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