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