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