blob: 1681770d52f38bcf069238cf88f24f7abf80bf0d [file] [log] [blame]
[email protected]a08ebea2011-02-13 17:50:201// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]a0421732011-02-23 03:55:405#include "content/browser/plugin_service.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]ceac9972011-01-13 01:51:147#include <vector>
8
[email protected]d48f1e0c2009-02-12 20:57:549#include "base/command_line.h"
[email protected]9c49ff02010-01-27 01:20:5510#include "base/path_service.h"
[email protected]d70539de2009-06-24 22:17:0611#include "base/string_util.h"
[email protected]34b99632011-01-01 01:01:0612#include "base/threading/thread.h"
[email protected]be1ce6a72010-08-03 14:35:2213#include "base/utf_string_conversions.h"
[email protected]cec1b8d2010-03-24 00:21:3414#include "base/values.h"
[email protected]44f9c952011-01-02 06:05:3915#include "base/synchronization/waitable_event.h"
initial.commit09911bf2008-07-26 23:55:2916#include "chrome/browser/browser_process.h"
17#include "chrome/browser/chrome_plugin_host.h"
[email protected]eaa7dd182010-12-14 11:09:0018#include "chrome/browser/extensions/extension_service.h"
[email protected]0a8b1e22010-07-02 09:31:1119#include "chrome/browser/plugin_updater.h"
[email protected]8ecad5e2010-12-02 21:18:3320#include "chrome/browser/profiles/profile.h"
initial.commit09911bf2008-07-26 23:55:2921#include "chrome/common/chrome_plugin_lib.h"
[email protected]9c49ff02010-01-27 01:20:5522#include "chrome/common/chrome_paths.h"
[email protected]d48f1e0c2009-02-12 20:57:5423#include "chrome/common/chrome_switches.h"
[email protected]2290cb862010-06-02 16:50:5824#include "chrome/common/default_plugin.h"
[email protected]5b1a0e22009-05-26 19:00:5825#include "chrome/common/extensions/extension.h"
[email protected]0b537a442011-03-04 00:43:1526#include "chrome/common/gpu_plugin.h"
initial.commit09911bf2008-07-26 23:55:2927#include "chrome/common/logging_chrome.h"
[email protected]894bb502009-05-21 22:39:5728#include "chrome/common/notification_type.h"
29#include "chrome/common/notification_service.h"
[email protected]4e0616e2010-05-28 14:55:5330#include "chrome/common/pepper_plugin_registry.h"
[email protected]4e59e812010-04-06 20:51:1631#include "chrome/common/plugin_messages.h"
[email protected]b547fd42009-04-23 23:16:2732#include "chrome/common/render_messages.h"
[email protected]a0421732011-02-23 03:55:4033#include "content/browser/browser_thread.h"
[email protected]a01efd22011-03-01 00:38:3234#include "content/browser/ppapi_plugin_process_host.h"
[email protected]a0421732011-02-23 03:55:4035#include "content/browser/renderer_host/render_process_host.h"
36#include "content/browser/renderer_host/render_view_host.h"
[email protected]191eb3f72010-12-21 06:27:5037#include "webkit/plugins/npapi/plugin_constants_win.h"
38#include "webkit/plugins/npapi/plugin_list.h"
39#include "webkit/plugins/npapi/webplugininfo.h"
40
[email protected]6fdd4182010-10-14 23:59:2641#if defined(OS_CHROMEOS)
42#include "chrome/browser/chromeos/plugin_selection_policy.h"
43#endif
initial.commit09911bf2008-07-26 23:55:2944
[email protected]a96ec6a2009-11-04 17:27:0845#if defined(OS_MACOSX)
46static void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0848
[email protected]d27893f62010-07-03 05:47:4249 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
[email protected]a96ec6a2009-11-04 17:27:0850 !iter.Done(); ++iter) {
51 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
52 plugin->OnAppActivation();
53 }
54}
55#endif
56
[email protected]634d23d2011-01-19 10:38:1957static void PurgePluginListCache(bool reload_pages) {
58 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
59 !it.IsAtEnd(); it.Advance()) {
60 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
61 }
62}
63
64#if defined(OS_LINUX)
65// Delegate class for monitoring directories.
66class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
67 virtual void OnFilePathChanged(const FilePath& path) {
68 VLOG(1) << "Watched path changed: " << path.value();
69 // Make the plugin list update itself
70 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
71 }
72 virtual void OnError() {
73 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
74 // stopping the watcher would be enough. Or possibly restart it.
75 NOTREACHED();
76 }
77};
78#endif
79
initial.commit09911bf2008-07-26 23:55:2980// static
[email protected]51549da2009-11-21 08:43:3981bool PluginService::enable_chrome_plugins_ = true;
82
83// static
[email protected]cec1b8d2010-03-24 00:21:3484void PluginService::InitGlobalInstance(Profile* profile) {
[email protected]f8b3ef82010-10-11 02:45:5285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]cec1b8d2010-03-24 00:21:3486
[email protected]24ff43d72011-03-01 13:28:5887 // We first group the plugins and then figure out which groups to
88 // enable or disable.
89 PluginUpdater::GetInstance()->UpdatePluginGroupsStateFromPrefs(profile);
[email protected]7bf795d92010-05-22 00:14:2890
[email protected]cec1b8d2010-03-24 00:21:3491 // Have Chrome plugins write their data to the profile directory.
92 GetInstance()->SetChromePluginDataDir(profile->GetPath());
93}
94
95// static
initial.commit09911bf2008-07-26 23:55:2996PluginService* PluginService::GetInstance() {
97 return Singleton<PluginService>::get();
98}
99
[email protected]51549da2009-11-21 08:43:39100// static
101void PluginService::EnableChromePlugins(bool enable) {
102 enable_chrome_plugins_ = enable;
103}
104
initial.commit09911bf2008-07-26 23:55:29105PluginService::PluginService()
106 : main_message_loop_(MessageLoop::current()),
initial.commit09911bf2008-07-26 23:55:29107 resource_dispatcher_host_(NULL),
[email protected]f77d87622010-07-30 17:43:17108 ui_locale_(g_browser_process->GetApplicationLocale()) {
[email protected]4e0616e2010-05-28 14:55:53109 RegisterPepperPlugins();
110
initial.commit09911bf2008-07-26 23:55:29111 // Have the NPAPI plugin list search for Chrome plugins as well.
112 ChromePluginLib::RegisterPluginsWithNPAPI();
[email protected]9a1c4262010-06-29 21:50:27113
114 // Load any specified on the command line as well.
[email protected]d48f1e0c2009-02-12 20:57:54115 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]c4e52f0d2009-11-06 19:55:16116 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28117 if (!path.empty())
[email protected]191eb3f72010-12-21 06:27:50118 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27119 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
120 if (!path.empty())
[email protected]191eb3f72010-12-21 06:27:50121 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]7bf795d92010-05-22 00:14:28122
[email protected]2290cb862010-06-02 16:50:58123 chrome::RegisterInternalDefaultPlugin();
124
[email protected]7bf795d92010-05-22 00:14:28125 // Register the internal Flash and PDF, if available.
126 if (!CommandLine::ForCurrentProcess()->HasSwitch(
127 switches::kDisableInternalFlash) &&
128 PathService::Get(chrome::FILE_FLASH_PLUGIN, &path)) {
[email protected]191eb3f72010-12-21 06:27:50129 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]35fa6a22009-08-15 00:04:01130 }
[email protected]d7ce4272010-03-27 01:06:01131
[email protected]6fdd4182010-10-14 23:59:26132#if defined(OS_CHROMEOS)
133 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy;
134 plugin_selection_policy_->StartInit();
135#endif
136
[email protected]0b537a442011-03-04 00:43:15137 chrome::RegisterInternalGPUPlugin();
138
[email protected]634d23d2011-01-19 10:38:19139 // Start watching for changes in the plugin list. This means watching
140 // for changes in the Windows registry keys and on both Windows and POSIX
141 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27142#if defined(OS_WIN)
143 hkcu_key_.Create(
[email protected]191eb3f72010-12-21 06:27:50144 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
[email protected]b547fd42009-04-23 23:16:27145 hklm_key_.Create(
[email protected]191eb3f72010-12-21 06:27:50146 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
[email protected]e06f4d52011-01-19 07:28:46147 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
[email protected]b547fd42009-04-23 23:16:27148 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
149 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
150 }
151
[email protected]e06f4d52011-01-19 07:28:46152 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
[email protected]b547fd42009-04-23 23:16:27153 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
154 hklm_watcher_.StartWatching(hklm_event_.get(), this);
155 }
[email protected]9c49ff02010-01-27 01:20:55156#elif defined(OS_POSIX) && !defined(OS_MACOSX)
157 // Also find plugins in a user-specific plugins dir,
158 // e.g. ~/.config/chromium/Plugins.
159 FilePath user_data_dir;
160 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
[email protected]191eb3f72010-12-21 06:27:50161 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(
[email protected]9c49ff02010-01-27 01:20:55162 user_data_dir.Append("Plugins"));
163 }
[email protected]b547fd42009-04-23 23:16:27164#endif
[email protected]634d23d2011-01-19 10:38:19165// The FilePathWatcher produces too many false positives on MacOS (access time
166// updates?) which will lead to enforcing updates of the plugins way too often.
167// On ChromeOS the user can't install plugins anyway and on Windows all
168// important plugins register themselves in the registry so no need to do that.
169#if defined(OS_LINUX)
170 file_watcher_delegate_ = new PluginDirWatcherDelegate();
171 // Get the list of all paths for registering the FilePathWatchers
172 // that will track and if needed reload the list of plugins on runtime.
173 std::vector<FilePath> plugin_dirs;
174 webkit::npapi::PluginList::Singleton()->GetPluginDirectories(
175 &plugin_dirs);
[email protected]894bb502009-05-21 22:39:57176
[email protected]634d23d2011-01-19 10:38:19177 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
178 FilePathWatcher* watcher = new FilePathWatcher();
179 // FilePathWatcher can not handle non-absolute paths under windows.
180 // We don't watch for file changes in windows now but if this should ever
181 // be extended to Windows these lines might save some time of debugging.
182#if defined(OS_WIN)
183 if (!plugin_dirs[i].IsAbsolute())
184 continue;
185#endif
186 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
187 BrowserThread::PostTask(
188 BrowserThread::FILE, FROM_HERE,
189 NewRunnableFunction(
190 &PluginService::RegisterFilePathWatcher,
191 watcher, plugin_dirs[i], file_watcher_delegate_));
192 file_watchers_.push_back(watcher);
193 }
194#endif
[email protected]ae09ca62009-08-21 19:46:46195 registrar_.Add(this, NotificationType::EXTENSION_LOADED,
[email protected]894bb502009-05-21 22:39:57196 NotificationService::AllSources());
197 registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
198 NotificationService::AllSources());
[email protected]a96ec6a2009-11-04 17:27:08199#if defined(OS_MACOSX)
200 // We need to know when the browser comes forward so we can bring modal plugin
201 // windows forward too.
202 registrar_.Add(this, NotificationType::APP_ACTIVATED,
203 NotificationService::AllSources());
204#endif
[email protected]5f101bbe2010-10-08 08:01:16205 registrar_.Add(this, NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
206 NotificationService::AllSources());
[email protected]c8f73ab2011-01-22 00:05:17207 registrar_.Add(this,
208 NotificationType::RENDERER_PROCESS_CLOSED,
209 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29210}
211
212PluginService::~PluginService() {
[email protected]b547fd42009-04-23 23:16:27213#if defined(OS_WIN)
214 // Release the events since they're owned by RegKey, not WaitableEvent.
215 hkcu_watcher_.StopWatching();
216 hklm_watcher_.StopWatching();
[email protected]c247cab2011-01-21 01:58:42217 if (hkcu_event_.get())
218 hkcu_event_->Release();
219 if (hklm_event_.get())
220 hklm_event_->Release();
[email protected]b547fd42009-04-23 23:16:27221#endif
initial.commit09911bf2008-07-26 23:55:29222}
223
initial.commit09911bf2008-07-26 23:55:29224void PluginService::LoadChromePlugins(
225 ResourceDispatcherHost* resource_dispatcher_host) {
[email protected]51549da2009-11-21 08:43:39226 if (!enable_chrome_plugins_)
227 return;
228
initial.commit09911bf2008-07-26 23:55:29229 resource_dispatcher_host_ = resource_dispatcher_host;
230 ChromePluginLib::LoadChromePlugins(GetCPBrowserFuncsForBrowser());
231}
232
[email protected]f7011fcb2009-01-28 21:54:32233void PluginService::SetChromePluginDataDir(const FilePath& data_dir) {
initial.commit09911bf2008-07-26 23:55:29234 chrome_plugin_data_dir_ = data_dir;
235}
236
[email protected]f7011fcb2009-01-28 21:54:32237const FilePath& PluginService::GetChromePluginDataDir() {
initial.commit09911bf2008-07-26 23:55:29238 return chrome_plugin_data_dir_;
239}
240
[email protected]f77d87622010-07-30 17:43:17241const std::string& PluginService::GetUILocale() {
initial.commit09911bf2008-07-26 23:55:29242 return ui_locale_;
243}
244
[email protected]a08ebea2011-02-13 17:50:20245PluginProcessHost* PluginService::FindNpapiPluginProcess(
[email protected]28ab7f92009-01-06 21:39:04246 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29248
[email protected]d27893f62010-07-03 05:47:42249 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
[email protected]a436d922009-02-13 23:16:42250 !iter.Done(); ++iter) {
251 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
252 if (plugin->info().path == plugin_path)
253 return plugin;
254 }
255
initial.commit09911bf2008-07-26 23:55:29256 return NULL;
257}
258
[email protected]a08ebea2011-02-13 17:50:20259PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess(
[email protected]610c0892009-09-08 19:46:18260 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29262
[email protected]a08ebea2011-02-13 17:50:20263 for (BrowserChildProcessHost::Iterator iter(
264 ChildProcessInfo::PPAPI_PLUGIN_PROCESS);
265 !iter.Done(); ++iter) {
266 PpapiPluginProcessHost* plugin =
267 static_cast<PpapiPluginProcessHost*>(*iter);
268 if (plugin->plugin_path() == plugin_path)
269 return plugin;
270 }
271
272 return NULL;
273}
274
275PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess(
276 const FilePath& plugin_path) {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
278
279 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29280 if (plugin_host)
281 return plugin_host;
282
[email protected]191eb3f72010-12-21 06:27:50283 webkit::npapi::WebPluginInfo info;
284 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath(
285 plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10286 return NULL;
287 }
288
initial.commit09911bf2008-07-26 23:55:29289 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40290 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
291 if (!new_host->Init(info, ui_locale_)) {
[email protected]a08ebea2011-02-13 17:50:20292 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29293 return NULL;
294 }
[email protected]8b8a554d2010-11-18 13:26:40295 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29296}
297
[email protected]a08ebea2011-02-13 17:50:20298PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess(
299 const FilePath& plugin_path) {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
301
302 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
303 if (plugin_host)
304 return plugin_host;
305
306 // Validate that the plugin is actually registered. There should generally
307 // be very few plugins so a brute-force search is fine.
308 PepperPluginInfo* info = NULL;
309 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
310 if (ppapi_plugins_[i].path == plugin_path) {
311 info = &ppapi_plugins_[i];
312 break;
313 }
314 }
315 if (!info)
316 return NULL;
317
318 // This plugin isn't loaded by any plugin process, so create a new process.
319 scoped_ptr<PpapiPluginProcessHost> new_host(new PpapiPluginProcessHost);
320 if (!new_host->Init(plugin_path)) {
321 NOTREACHED(); // Init is not expected to fail.
322 return NULL;
323 }
324 return new_host.release();
325}
326
327void PluginService::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17328 int render_process_id,
329 int render_view_id,
[email protected]610c0892009-09-08 19:46:18330 const GURL& url,
331 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39332 PluginProcessHost::Client* client) {
[email protected]6fdd4182010-10-14 23:59:26333 // The PluginList::GetFirstAllowedPluginInfo may need to load the
334 // plugins. Don't do it on the IO thread.
335 BrowserThread::PostTask(
336 BrowserThread::FILE, FROM_HERE,
337 NewRunnableMethod(
338 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin,
[email protected]c8f73ab2011-01-22 00:05:17339 render_process_id, render_view_id, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26340}
341
[email protected]a08ebea2011-02-13 17:50:20342void PluginService::OpenChannelToPpapiPlugin(
343 const FilePath& path,
344 PpapiPluginProcessHost::Client* client) {
345 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(path);
346 if (plugin_host)
347 plugin_host->OpenChannelToPlugin(client);
348 else // Send error.
349 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
350}
351
[email protected]6fdd4182010-10-14 23:59:26352void PluginService::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17353 int render_process_id,
354 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26355 const GURL& url,
356 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39357 PluginProcessHost::Client* client) {
[email protected]6fdd4182010-10-14 23:59:26358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]191eb3f72010-12-21 06:27:50359 webkit::npapi::WebPluginInfo info;
[email protected]c8f73ab2011-01-22 00:05:17360 bool found = GetFirstAllowedPluginInfo(
361 render_process_id, render_view_id, url, mime_type, &info, NULL);
[email protected]6fdd4182010-10-14 23:59:26362 FilePath plugin_path;
[email protected]b83ff222011-01-24 17:37:12363 if (found && webkit::npapi::IsPluginEnabled(info))
[email protected]6fdd4182010-10-14 23:59:26364 plugin_path = FilePath(info.path);
365
366 // Now we jump back to the IO thread to finish opening the channel.
367 BrowserThread::PostTask(
368 BrowserThread::IO, FROM_HERE,
369 NewRunnableMethod(
370 this, &PluginService::FinishOpenChannelToPlugin,
[email protected]46b69e42010-11-02 12:26:39371 plugin_path, client));
[email protected]6fdd4182010-10-14 23:59:26372}
373
374void PluginService::FinishOpenChannelToPlugin(
[email protected]6fdd4182010-10-14 23:59:26375 const FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39376 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08378
[email protected]a08ebea2011-02-13 17:50:20379 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
[email protected]46b69e42010-11-02 12:26:39380 if (plugin_host)
381 plugin_host->OpenChannelToPlugin(client);
382 else
383 client->OnError();
initial.commit09911bf2008-07-26 23:55:29384}
385
[email protected]6fdd4182010-10-14 23:59:26386bool PluginService::GetFirstAllowedPluginInfo(
[email protected]c8f73ab2011-01-22 00:05:17387 int render_process_id,
388 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26389 const GURL& url,
390 const std::string& mime_type,
[email protected]191eb3f72010-12-21 06:27:50391 webkit::npapi::WebPluginInfo* info,
[email protected]6fdd4182010-10-14 23:59:26392 std::string* actual_mime_type) {
393 // GetPluginInfoArray may need to load the plugins, so we need to be
394 // on the FILE thread.
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
396 bool allow_wildcard = true;
397#if defined(OS_CHROMEOS)
[email protected]191eb3f72010-12-21 06:27:50398 std::vector<webkit::npapi::WebPluginInfo> info_array;
[email protected]6fdd4182010-10-14 23:59:26399 std::vector<std::string> actual_mime_types;
[email protected]191eb3f72010-12-21 06:27:50400 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray(
[email protected]6fdd4182010-10-14 23:59:26401 url, mime_type, allow_wildcard, &info_array, &actual_mime_types);
402
403 // Now we filter by the plugin selection policy.
404 int allowed_index = plugin_selection_policy_->FindFirstAllowed(url,
405 info_array);
406 if (!info_array.empty() && allowed_index >= 0) {
407 *info = info_array[allowed_index];
408 if (actual_mime_type)
409 *actual_mime_type = actual_mime_types[allowed_index];
410 return true;
411 }
412 return false;
413#else
[email protected]c8f73ab2011-01-22 00:05:17414 {
[email protected]5c19e8b2011-01-22 00:18:47415 base::AutoLock auto_lock(overridden_plugins_lock_);
[email protected]c8f73ab2011-01-22 00:05:17416 for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
417 if (overridden_plugins_[i].render_process_id == render_process_id &&
418 overridden_plugins_[i].render_view_id == render_view_id &&
419 overridden_plugins_[i].url == url) {
[email protected]79f0fa752011-01-27 20:01:47420 if (actual_mime_type)
421 *actual_mime_type = mime_type;
[email protected]c8f73ab2011-01-22 00:05:17422 *info = overridden_plugins_[i].plugin;
423 return true;
424 }
425 }
426 }
[email protected]191eb3f72010-12-21 06:27:50427 return webkit::npapi::PluginList::Singleton()->GetPluginInfo(
[email protected]6fdd4182010-10-14 23:59:26428 url, mime_type, allow_wildcard, info, actual_mime_type);
429#endif
430}
431
[email protected]580522632009-08-17 21:55:55432void PluginService::OnWaitableEventSignaled(
433 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27434#if defined(OS_WIN)
435 if (waitable_event == hkcu_event_.get()) {
436 hkcu_key_.StartWatching();
437 } else {
438 hklm_key_.StartWatching();
439 }
440
[email protected]191eb3f72010-12-21 06:27:50441 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]b78e168b2009-09-21 22:05:45442 PurgePluginListCache(true);
[email protected]634d23d2011-01-19 10:38:19443#else
444 // This event should only get signaled on a Windows machine.
445 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53446#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27447}
[email protected]894bb502009-05-21 22:39:57448
[email protected]4e59e812010-04-06 20:51:16449static void ForceShutdownPlugin(const FilePath& plugin_path) {
450 PluginProcessHost* plugin =
[email protected]a08ebea2011-02-13 17:50:20451 PluginService::GetInstance()->FindNpapiPluginProcess(plugin_path);
[email protected]4e59e812010-04-06 20:51:16452 if (plugin)
453 plugin->ForceShutdown();
454}
455
[email protected]894bb502009-05-21 22:39:57456void PluginService::Observe(NotificationType type,
457 const NotificationSource& source,
458 const NotificationDetails& details) {
459 switch (type.value) {
[email protected]ae09ca62009-08-21 19:46:46460 case NotificationType::EXTENSION_LOADED: {
[email protected]9adb9692010-10-29 23:14:02461 const Extension* extension = Details<const Extension>(details).ptr();
[email protected]b78e168b2009-09-21 22:05:45462 bool plugins_changed = false;
[email protected]ee5e3792009-10-13 23:23:47463 for (size_t i = 0; i < extension->plugins().size(); ++i) {
[email protected]ae09ca62009-08-21 19:46:46464 const Extension::PluginInfo& plugin = extension->plugins()[i];
[email protected]191eb3f72010-12-21 06:27:50465 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
466 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(plugin.path);
[email protected]b78e168b2009-09-21 22:05:45467 plugins_changed = true;
[email protected]ae09ca62009-08-21 19:46:46468 if (!plugin.is_public)
469 private_plugins_[plugin.path] = extension->url();
[email protected]c533bb22009-06-03 19:06:11470 }
[email protected]b78e168b2009-09-21 22:05:45471 if (plugins_changed)
472 PurgePluginListCache(false);
[email protected]894bb502009-05-21 22:39:57473 break;
474 }
475
476 case NotificationType::EXTENSION_UNLOADED: {
[email protected]a9f39a312010-12-23 22:14:27477 const Extension* extension =
478 Details<UnloadedExtensionInfo>(details)->extension;
[email protected]b78e168b2009-09-21 22:05:45479 bool plugins_changed = false;
[email protected]ee5e3792009-10-13 23:23:47480 for (size_t i = 0; i < extension->plugins().size(); ++i) {
[email protected]b78e168b2009-09-21 22:05:45481 const Extension::PluginInfo& plugin = extension->plugins()[i];
[email protected]f8b3ef82010-10-11 02:45:52482 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
483 NewRunnableFunction(&ForceShutdownPlugin,
484 plugin.path));
[email protected]191eb3f72010-12-21 06:27:50485 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
486 webkit::npapi::PluginList::Singleton()->RemoveExtraPluginPath(
487 plugin.path);
[email protected]b78e168b2009-09-21 22:05:45488 plugins_changed = true;
489 if (!plugin.is_public)
490 private_plugins_.erase(plugin.path);
491 }
492 if (plugins_changed)
493 PurgePluginListCache(false);
[email protected]894bb502009-05-21 22:39:57494 break;
495 }
496
[email protected]a96ec6a2009-11-04 17:27:08497#if defined(OS_MACOSX)
498 case NotificationType::APP_ACTIVATED: {
[email protected]f8b3ef82010-10-11 02:45:52499 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
500 NewRunnableFunction(&NotifyPluginsOfActivation));
[email protected]a96ec6a2009-11-04 17:27:08501 break;
502 }
503#endif
504
[email protected]5f101bbe2010-10-08 08:01:16505 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: {
[email protected]b83ff222011-01-24 17:37:12506 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]5f101bbe2010-10-08 08:01:16507 PurgePluginListCache(false);
508 break;
509 }
[email protected]c8f73ab2011-01-22 00:05:17510 case NotificationType::RENDERER_PROCESS_CLOSED: {
511 int render_process_id = Source<RenderProcessHost>(source).ptr()->id();
512
[email protected]5c19e8b2011-01-22 00:18:47513 base::AutoLock auto_lock(overridden_plugins_lock_);
[email protected]c8f73ab2011-01-22 00:05:17514 for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
515 if (overridden_plugins_[i].render_process_id == render_process_id) {
516 overridden_plugins_.erase(overridden_plugins_.begin() + i);
517 break;
518 }
519 }
520 break;
521 }
[email protected]894bb502009-05-21 22:39:57522 default:
[email protected]634d23d2011-01-19 10:38:19523 NOTREACHED();
[email protected]894bb502009-05-21 22:39:57524 }
525}
[email protected]9dd9e8382009-06-05 18:23:21526
[email protected]7a13e792010-08-03 08:18:24527bool PluginService::PrivatePluginAllowedForURL(const FilePath& plugin_path,
528 const GURL& url) {
[email protected]9dd9e8382009-06-05 18:23:21529 if (url.is_empty())
530 return true; // Caller wants all plugins.
531
532 PrivatePluginMap::iterator it = private_plugins_.find(plugin_path);
533 if (it == private_plugins_.end())
534 return true; // This plugin is not private, so it's allowed everywhere.
535
536 // We do a dumb compare of scheme and host, rather than using the domain
537 // service, since we only care about this for extensions.
538 const GURL& required_url = it->second;
539 return (url.scheme() == required_url.scheme() &&
540 url.host() == required_url.host());
541}
[email protected]4e0616e2010-05-28 14:55:53542
[email protected]c8f73ab2011-01-22 00:05:17543void PluginService::OverridePluginForTab(OverriddenPlugin plugin) {
[email protected]5c19e8b2011-01-22 00:18:47544 base::AutoLock auto_lock(overridden_plugins_lock_);
[email protected]c8f73ab2011-01-22 00:05:17545 overridden_plugins_.push_back(plugin);
546}
547
[email protected]4e0616e2010-05-28 14:55:53548void PluginService::RegisterPepperPlugins() {
[email protected]a08ebea2011-02-13 17:50:20549 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
[email protected]fa28c1002011-03-03 19:57:36550
551 // Get the file path of the Native Client Plugin.
552 FilePath naclPath;
553 PathService::Get(chrome::FILE_NACL_PLUGIN, &naclPath);
554
[email protected]a08ebea2011-02-13 17:50:20555 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]b1420b192011-01-19 21:32:36556 webkit::npapi::WebPluginInfo info;
[email protected]a08ebea2011-02-13 17:50:20557 info.name = ppapi_plugins_[i].name.empty() ?
558 ppapi_plugins_[i].path.BaseName().LossyDisplayName() :
559 ASCIIToUTF16(ppapi_plugins_[i].name);
[email protected]f85d311a2011-03-08 00:42:07560 info.path = ppapi_plugins_[i].path;
[email protected]a505dfb2011-02-16 20:04:45561 info.version = ASCIIToUTF16(ppapi_plugins_[i].version);
[email protected]f85d311a2011-03-08 00:42:07562 info.desc = ASCIIToUTF16(ppapi_plugins_[i].description);
563 info.mime_types = ppapi_plugins_[i].mime_types;
[email protected]fa28c1002011-03-03 19:57:36564
565 webkit::npapi::WebPluginInfo::EnabledStates enabled_state =
566 webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED;
567
568 // Enable the Native Client Plugin based on the command line.
569 if (ppapi_plugins_[i].path == naclPath) {
570 bool nacl_enabled =
571 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl);
572 enabled_state = nacl_enabled ?
573 webkit::npapi::WebPluginInfo::USER_ENABLED_POLICY_UNMANAGED :
574 webkit::npapi::WebPluginInfo::USER_DISABLED_POLICY_UNMANAGED;
575 }
576 info.enabled = enabled_state;
[email protected]4e0616e2010-05-28 14:55:53577
[email protected]191eb3f72010-12-21 06:27:50578 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(info);
[email protected]4e0616e2010-05-28 14:55:53579 }
580}
[email protected]634d23d2011-01-19 10:38:19581
582#if defined(OS_LINUX)
583// static
584void PluginService::RegisterFilePathWatcher(
585 FilePathWatcher *watcher,
586 const FilePath& path,
587 FilePathWatcher::Delegate* delegate) {
588 bool result = watcher->Watch(path, delegate);
589 DCHECK(result);
590}
591#endif