Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This class responds to requests from renderers for the list of plugins, and
      6 // also a proxy object for plugin instances.
      7 
      8 #ifndef CONTENT_BROWSER_PLUGIN_SERVICE_IMPL_H_
      9 #define CONTENT_BROWSER_PLUGIN_SERVICE_IMPL_H_
     10 
     11 #if !defined(ENABLE_PLUGINS)
     12 #error "Plugins should be enabled"
     13 #endif
     14 
     15 #include <map>
     16 #include <set>
     17 #include <vector>
     18 
     19 #include "base/basictypes.h"
     20 #include "base/compiler_specific.h"
     21 #include "base/memory/scoped_vector.h"
     22 #include "base/memory/singleton.h"
     23 #include "base/synchronization/waitable_event_watcher.h"
     24 #include "base/threading/sequenced_worker_pool.h"
     25 #include "base/time/time.h"
     26 #include "build/build_config.h"
     27 #include "content/browser/plugin_process_host.h"
     28 #include "content/browser/ppapi_plugin_process_host.h"
     29 #include "content/common/content_export.h"
     30 #include "content/public/browser/plugin_service.h"
     31 #include "content/public/common/pepper_plugin_info.h"
     32 #include "ipc/ipc_channel_handle.h"
     33 #include "url/gurl.h"
     34 
     35 #if defined(OS_WIN)
     36 #include "base/memory/scoped_ptr.h"
     37 #include "base/win/registry.h"
     38 #endif
     39 
     40 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
     41 #include "base/files/file_path_watcher.h"
     42 #endif
     43 
     44 namespace base {
     45 class MessageLoopProxy;
     46 }
     47 
     48 namespace content {
     49 class BrowserContext;
     50 class PluginDirWatcherDelegate;
     51 class PluginLoaderPosix;
     52 class PluginServiceFilter;
     53 class ResourceContext;
     54 struct PepperPluginInfo;
     55 
     56 // base::Bind() has limited arity, and the filter-related methods tend to
     57 // surpass that limit.
     58 struct PluginServiceFilterParams {
     59   int render_process_id;
     60   int render_frame_id;
     61   GURL page_url;
     62   ResourceContext* resource_context;
     63 };
     64 
     65 class CONTENT_EXPORT PluginServiceImpl
     66     : NON_EXPORTED_BASE(public PluginService) {
     67  public:
     68   // Returns the PluginServiceImpl singleton.
     69   static PluginServiceImpl* GetInstance();
     70 
     71   // PluginService implementation:
     72   virtual void Init() OVERRIDE;
     73   virtual void StartWatchingPlugins() OVERRIDE;
     74   virtual bool GetPluginInfoArray(
     75       const GURL& url,
     76       const std::string& mime_type,
     77       bool allow_wildcard,
     78       std::vector<WebPluginInfo>* info,
     79       std::vector<std::string>* actual_mime_types) OVERRIDE;
     80   virtual bool GetPluginInfo(int render_process_id,
     81                              int render_frame_id,
     82                              ResourceContext* context,
     83                              const GURL& url,
     84                              const GURL& page_url,
     85                              const std::string& mime_type,
     86                              bool allow_wildcard,
     87                              bool* is_stale,
     88                              WebPluginInfo* info,
     89                              std::string* actual_mime_type) OVERRIDE;
     90   virtual bool GetPluginInfoByPath(const base::FilePath& plugin_path,
     91                                    WebPluginInfo* info) OVERRIDE;
     92   virtual base::string16 GetPluginDisplayNameByPath(
     93       const base::FilePath& path) OVERRIDE;
     94   virtual void GetPlugins(const GetPluginsCallback& callback) OVERRIDE;
     95   virtual PepperPluginInfo* GetRegisteredPpapiPluginInfo(
     96       const base::FilePath& plugin_path) OVERRIDE;
     97   virtual void SetFilter(PluginServiceFilter* filter) OVERRIDE;
     98   virtual PluginServiceFilter* GetFilter() OVERRIDE;
     99   virtual void ForcePluginShutdown(const base::FilePath& plugin_path) OVERRIDE;
    100   virtual bool IsPluginUnstable(const base::FilePath& plugin_path) OVERRIDE;
    101   virtual void RefreshPlugins() OVERRIDE;
    102   virtual void AddExtraPluginPath(const base::FilePath& path) OVERRIDE;
    103   virtual void RemoveExtraPluginPath(const base::FilePath& path) OVERRIDE;
    104   virtual void AddExtraPluginDir(const base::FilePath& path) OVERRIDE;
    105   virtual void RegisterInternalPlugin(
    106       const WebPluginInfo& info, bool add_at_beginning) OVERRIDE;
    107   virtual void UnregisterInternalPlugin(const base::FilePath& path) OVERRIDE;
    108   virtual void GetInternalPlugins(
    109       std::vector<WebPluginInfo>* plugins) OVERRIDE;
    110   virtual bool NPAPIPluginsSupported() OVERRIDE;
    111   virtual void DisablePluginsDiscoveryForTesting() OVERRIDE;
    112 #if defined(OS_MACOSX)
    113   virtual void AppActivated() OVERRIDE;
    114 #elif defined(OS_WIN)
    115   virtual bool GetPluginInfoFromWindow(HWND window,
    116                                        base::string16* plugin_name,
    117                                        base::string16* plugin_version) OVERRIDE;
    118 
    119   // Returns true iff the given HWND is a plugin.
    120   bool IsPluginWindow(HWND window);
    121 #endif
    122   virtual bool PpapiDevChannelSupported(BrowserContext* browser_context,
    123                                         const GURL& document_url) OVERRIDE;
    124 
    125   // Returns the plugin process host corresponding to the plugin process that
    126   // has been started by this service. This will start a process to host the
    127   // 'plugin_path' if needed. If the process fails to start, the return value
    128   // is NULL. Must be called on the IO thread.
    129   PluginProcessHost* FindOrStartNpapiPluginProcess(
    130       int render_process_id, const base::FilePath& plugin_path);
    131   PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
    132       int render_process_id,
    133       const base::FilePath& plugin_path,
    134       const base::FilePath& profile_data_directory);
    135   PpapiPluginProcessHost* FindOrStartPpapiBrokerProcess(
    136       int render_process_id, const base::FilePath& plugin_path);
    137 
    138   // Opens a channel to a plugin process for the given mime type, starting
    139   // a new plugin process if necessary.  This must be called on the IO thread
    140   // or else a deadlock can occur.
    141   void OpenChannelToNpapiPlugin(int render_process_id,
    142                                 int render_frame_id,
    143                                 const GURL& url,
    144                                 const GURL& page_url,
    145                                 const std::string& mime_type,
    146                                 PluginProcessHost::Client* client);
    147   void OpenChannelToPpapiPlugin(int render_process_id,
    148                                 const base::FilePath& plugin_path,
    149                                 const base::FilePath& profile_data_directory,
    150                                 PpapiPluginProcessHost::PluginClient* client);
    151   void OpenChannelToPpapiBroker(int render_process_id,
    152                                 const base::FilePath& path,
    153                                 PpapiPluginProcessHost::BrokerClient* client);
    154 
    155   // Cancels opening a channel to a NPAPI plugin.
    156   void CancelOpenChannelToNpapiPlugin(PluginProcessHost::Client* client);
    157 
    158   // Used to monitor plug-in stability.
    159   void RegisterPluginCrash(const base::FilePath& plugin_path);
    160 
    161  private:
    162   friend struct DefaultSingletonTraits<PluginServiceImpl>;
    163 
    164   // Creates the PluginServiceImpl object, but doesn't actually build the plugin
    165   // list yet.  It's generated lazily.
    166   PluginServiceImpl();
    167   virtual ~PluginServiceImpl();
    168 
    169   void OnWaitableEventSignaled(base::WaitableEvent* waitable_event);
    170 
    171   // Returns the plugin process host corresponding to the plugin process that
    172   // has been started by this service. Returns NULL if no process has been
    173   // started.
    174   PluginProcessHost* FindNpapiPluginProcess(const base::FilePath& plugin_path);
    175   PpapiPluginProcessHost* FindPpapiPluginProcess(
    176       const base::FilePath& plugin_path,
    177       const base::FilePath& profile_data_directory);
    178   PpapiPluginProcessHost* FindPpapiBrokerProcess(
    179       const base::FilePath& broker_path);
    180 
    181   void RegisterPepperPlugins();
    182 
    183   // Run on the blocking pool to load the plugins synchronously.
    184   void GetPluginsInternal(base::MessageLoopProxy* target_loop,
    185                           const GetPluginsCallback& callback);
    186 
    187 #if defined(OS_POSIX)
    188   void GetPluginsOnIOThread(
    189       base::MessageLoopProxy* target_loop,
    190       const GetPluginsCallback& callback);
    191 #endif
    192 
    193   // Binding directly to GetAllowedPluginForOpenChannelToPlugin() isn't possible
    194   // because more arity is needed <http://crbug.com/98542>. This just forwards.
    195   void ForwardGetAllowedPluginForOpenChannelToPlugin(
    196       const PluginServiceFilterParams& params,
    197       const GURL& url,
    198       const std::string& mime_type,
    199       PluginProcessHost::Client* client,
    200       const std::vector<WebPluginInfo>&);
    201   // Helper so we can do the plugin lookup on the FILE thread.
    202   void GetAllowedPluginForOpenChannelToPlugin(
    203       int render_process_id,
    204       int render_frame_id,
    205       const GURL& url,
    206       const GURL& page_url,
    207       const std::string& mime_type,
    208       PluginProcessHost::Client* client,
    209       ResourceContext* resource_context);
    210 
    211   // Helper so we can finish opening the channel after looking up the
    212   // plugin.
    213   void FinishOpenChannelToPlugin(int render_process_id,
    214                                  const base::FilePath& plugin_path,
    215                                  PluginProcessHost::Client* client);
    216 
    217 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
    218   // Registers a new FilePathWatcher for a given path.
    219   static void RegisterFilePathWatcher(base::FilePathWatcher* watcher,
    220                                       const base::FilePath& path);
    221 #endif
    222 
    223 #if defined(OS_WIN)
    224   // Registry keys for getting notifications when new plugins are installed.
    225   base::win::RegKey hkcu_key_;
    226   base::win::RegKey hklm_key_;
    227   scoped_ptr<base::WaitableEvent> hkcu_event_;
    228   scoped_ptr<base::WaitableEvent> hklm_event_;
    229   base::WaitableEventWatcher hkcu_watcher_;
    230   base::WaitableEventWatcher hklm_watcher_;
    231 #endif
    232 
    233 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
    234   ScopedVector<base::FilePathWatcher> file_watchers_;
    235 #endif
    236 
    237   std::vector<PepperPluginInfo> ppapi_plugins_;
    238 
    239   // Weak pointer; outlives us.
    240   PluginServiceFilter* filter_;
    241 
    242   std::set<PluginProcessHost::Client*> pending_plugin_clients_;
    243 
    244   // Used to sequentialize loading plug-ins from disk.
    245   base::SequencedWorkerPool::SequenceToken plugin_list_token_;
    246 
    247 #if defined(OS_POSIX)
    248   scoped_refptr<PluginLoaderPosix> plugin_loader_;
    249 #endif
    250 
    251   // Used to detect if a given plug-in is crashing over and over.
    252   std::map<base::FilePath, std::vector<base::Time> > crash_times_;
    253 
    254   DISALLOW_COPY_AND_ASSIGN(PluginServiceImpl);
    255 };
    256 
    257 }  // namespace content
    258 
    259 #endif  // CONTENT_BROWSER_PLUGIN_SERVICE_IMPL_H_
    260