blob: 703235e2b08ae6fd7583dfed7ea0b9110972bfea [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]7b3ee8b2011-04-01 18:48:1910#include "base/compiler_specific.h"
[email protected]9c49ff02010-01-27 01:20:5511#include "base/path_service.h"
[email protected]d70539de2009-06-24 22:17:0612#include "base/string_util.h"
[email protected]7f070d42011-03-09 20:25:3213#include "base/synchronization/waitable_event.h"
[email protected]34b99632011-01-01 01:01:0614#include "base/threading/thread.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]cec1b8d2010-03-24 00:21:3416#include "base/values.h"
initial.commit09911bf2008-07-26 23:55:2917#include "chrome/browser/browser_process.h"
[email protected]0a8b1e22010-07-02 09:31:1118#include "chrome/browser/plugin_updater.h"
[email protected]8ecad5e2010-12-02 21:18:3319#include "chrome/browser/profiles/profile.h"
[email protected]9c49ff02010-01-27 01:20:5520#include "chrome/common/chrome_paths.h"
[email protected]d48f1e0c2009-02-12 20:57:5421#include "chrome/common/chrome_switches.h"
[email protected]2290cb862010-06-02 16:50:5822#include "chrome/common/default_plugin.h"
initial.commit09911bf2008-07-26 23:55:2923#include "chrome/common/logging_chrome.h"
[email protected]4e0616e2010-05-28 14:55:5324#include "chrome/common/pepper_plugin_registry.h"
[email protected]b547fd42009-04-23 23:16:2725#include "chrome/common/render_messages.h"
[email protected]a0421732011-02-23 03:55:4026#include "content/browser/browser_thread.h"
[email protected]a01efd22011-03-01 00:38:3227#include "content/browser/ppapi_plugin_process_host.h"
[email protected]a0421732011-02-23 03:55:4028#include "content/browser/renderer_host/render_process_host.h"
29#include "content/browser/renderer_host/render_view_host.h"
[email protected]7f070d42011-03-09 20:25:3230#include "content/common/notification_service.h"
31#include "content/common/notification_type.h"
[email protected]105303e2011-03-14 22:16:1032#include "content/common/plugin_messages.h"
[email protected]38b592902011-04-16 02:08:4233#include "content/common/view_messages.h"
[email protected]191eb3f72010-12-21 06:27:5034#include "webkit/plugins/npapi/plugin_constants_win.h"
35#include "webkit/plugins/npapi/plugin_list.h"
36#include "webkit/plugins/npapi/webplugininfo.h"
37
[email protected]6fdd4182010-10-14 23:59:2638#if defined(OS_CHROMEOS)
39#include "chrome/browser/chromeos/plugin_selection_policy.h"
40#endif
initial.commit09911bf2008-07-26 23:55:2941
[email protected]493c8002011-04-14 16:56:0142#if defined(OS_LINUX)
43using ::base::files::FilePathWatcher;
44#endif
45
[email protected]a96ec6a2009-11-04 17:27:0846#if defined(OS_MACOSX)
47static void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0849
[email protected]d27893f62010-07-03 05:47:4250 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
[email protected]a96ec6a2009-11-04 17:27:0851 !iter.Done(); ++iter) {
52 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
53 plugin->OnAppActivation();
54 }
55}
56#endif
57
[email protected]634d23d2011-01-19 10:38:1958#if defined(OS_LINUX)
59// Delegate class for monitoring directories.
60class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
[email protected]7b3ee8b2011-04-01 18:48:1961 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:1962 VLOG(1) << "Watched path changed: " << path.value();
63 // Make the plugin list update itself
64 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
65 }
[email protected]7b3ee8b2011-04-01 18:48:1966 virtual void OnFilePathError(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:1967 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
68 // stopping the watcher would be enough. Or possibly restart it.
69 NOTREACHED();
70 }
71};
72#endif
73
initial.commit09911bf2008-07-26 23:55:2974// static
[email protected]cec1b8d2010-03-24 00:21:3475void PluginService::InitGlobalInstance(Profile* profile) {
[email protected]f8b3ef82010-10-11 02:45:5276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]cec1b8d2010-03-24 00:21:3477
[email protected]24ff43d72011-03-01 13:28:5878 // We first group the plugins and then figure out which groups to
79 // enable or disable.
80 PluginUpdater::GetInstance()->UpdatePluginGroupsStateFromPrefs(profile);
[email protected]cec1b8d2010-03-24 00:21:3481}
82
83// static
initial.commit09911bf2008-07-26 23:55:2984PluginService* PluginService::GetInstance() {
85 return Singleton<PluginService>::get();
86}
87
88PluginService::PluginService()
89 : main_message_loop_(MessageLoop::current()),
[email protected]f77d87622010-07-30 17:43:1790 ui_locale_(g_browser_process->GetApplicationLocale()) {
[email protected]4e0616e2010-05-28 14:55:5391 RegisterPepperPlugins();
92
[email protected]9a1c4262010-06-29 21:50:2793 // Load any specified on the command line as well.
[email protected]d48f1e0c2009-02-12 20:57:5494 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]c4e52f0d2009-11-06 19:55:1695 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:2896 if (!path.empty())
[email protected]191eb3f72010-12-21 06:27:5097 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:2798 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
99 if (!path.empty())
[email protected]191eb3f72010-12-21 06:27:50100 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]7bf795d92010-05-22 00:14:28101
[email protected]2290cb862010-06-02 16:50:58102 chrome::RegisterInternalDefaultPlugin();
103
[email protected]7bf795d92010-05-22 00:14:28104 // Register the internal Flash and PDF, if available.
105 if (!CommandLine::ForCurrentProcess()->HasSwitch(
106 switches::kDisableInternalFlash) &&
107 PathService::Get(chrome::FILE_FLASH_PLUGIN, &path)) {
[email protected]191eb3f72010-12-21 06:27:50108 webkit::npapi::PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]35fa6a22009-08-15 00:04:01109 }
[email protected]d7ce4272010-03-27 01:06:01110
[email protected]6fdd4182010-10-14 23:59:26111#if defined(OS_CHROMEOS)
112 plugin_selection_policy_ = new chromeos::PluginSelectionPolicy;
113 plugin_selection_policy_->StartInit();
114#endif
115
[email protected]634d23d2011-01-19 10:38:19116 // Start watching for changes in the plugin list. This means watching
117 // for changes in the Windows registry keys and on both Windows and POSIX
118 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27119#if defined(OS_WIN)
120 hkcu_key_.Create(
[email protected]191eb3f72010-12-21 06:27:50121 HKEY_CURRENT_USER, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
[email protected]b547fd42009-04-23 23:16:27122 hklm_key_.Create(
[email protected]191eb3f72010-12-21 06:27:50123 HKEY_LOCAL_MACHINE, webkit::npapi::kRegistryMozillaPlugins, KEY_NOTIFY);
[email protected]e06f4d52011-01-19 07:28:46124 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
[email protected]b547fd42009-04-23 23:16:27125 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
126 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
127 }
128
[email protected]e06f4d52011-01-19 07:28:46129 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
[email protected]b547fd42009-04-23 23:16:27130 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
131 hklm_watcher_.StartWatching(hklm_event_.get(), this);
132 }
[email protected]9c49ff02010-01-27 01:20:55133#elif defined(OS_POSIX) && !defined(OS_MACOSX)
134 // Also find plugins in a user-specific plugins dir,
135 // e.g. ~/.config/chromium/Plugins.
136 FilePath user_data_dir;
137 if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
[email protected]191eb3f72010-12-21 06:27:50138 webkit::npapi::PluginList::Singleton()->AddExtraPluginDir(
[email protected]9c49ff02010-01-27 01:20:55139 user_data_dir.Append("Plugins"));
140 }
[email protected]b547fd42009-04-23 23:16:27141#endif
[email protected]634d23d2011-01-19 10:38:19142// The FilePathWatcher produces too many false positives on MacOS (access time
143// updates?) which will lead to enforcing updates of the plugins way too often.
144// On ChromeOS the user can't install plugins anyway and on Windows all
145// important plugins register themselves in the registry so no need to do that.
146#if defined(OS_LINUX)
147 file_watcher_delegate_ = new PluginDirWatcherDelegate();
148 // Get the list of all paths for registering the FilePathWatchers
149 // that will track and if needed reload the list of plugins on runtime.
150 std::vector<FilePath> plugin_dirs;
151 webkit::npapi::PluginList::Singleton()->GetPluginDirectories(
152 &plugin_dirs);
[email protected]894bb502009-05-21 22:39:57153
[email protected]634d23d2011-01-19 10:38:19154 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19155 // FilePathWatcher can not handle non-absolute paths under windows.
156 // We don't watch for file changes in windows now but if this should ever
157 // be extended to Windows these lines might save some time of debugging.
158#if defined(OS_WIN)
159 if (!plugin_dirs[i].IsAbsolute())
160 continue;
161#endif
[email protected]493c8002011-04-14 16:56:01162 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19163 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
164 BrowserThread::PostTask(
165 BrowserThread::FILE, FROM_HERE,
166 NewRunnableFunction(
167 &PluginService::RegisterFilePathWatcher,
168 watcher, plugin_dirs[i], file_watcher_delegate_));
169 file_watchers_.push_back(watcher);
170 }
171#endif
[email protected]a96ec6a2009-11-04 17:27:08172#if defined(OS_MACOSX)
173 // We need to know when the browser comes forward so we can bring modal plugin
174 // windows forward too.
175 registrar_.Add(this, NotificationType::APP_ACTIVATED,
176 NotificationService::AllSources());
177#endif
[email protected]5f101bbe2010-10-08 08:01:16178 registrar_.Add(this, NotificationType::PLUGIN_ENABLE_STATUS_CHANGED,
179 NotificationService::AllSources());
[email protected]c8f73ab2011-01-22 00:05:17180 registrar_.Add(this,
181 NotificationType::RENDERER_PROCESS_CLOSED,
182 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29183}
184
185PluginService::~PluginService() {
[email protected]b547fd42009-04-23 23:16:27186#if defined(OS_WIN)
187 // Release the events since they're owned by RegKey, not WaitableEvent.
188 hkcu_watcher_.StopWatching();
189 hklm_watcher_.StopWatching();
[email protected]c247cab2011-01-21 01:58:42190 if (hkcu_event_.get())
191 hkcu_event_->Release();
192 if (hklm_event_.get())
193 hklm_event_->Release();
[email protected]b547fd42009-04-23 23:16:27194#endif
initial.commit09911bf2008-07-26 23:55:29195}
196
[email protected]f77d87622010-07-30 17:43:17197const std::string& PluginService::GetUILocale() {
initial.commit09911bf2008-07-26 23:55:29198 return ui_locale_;
199}
200
[email protected]a08ebea2011-02-13 17:50:20201PluginProcessHost* PluginService::FindNpapiPluginProcess(
[email protected]28ab7f92009-01-06 21:39:04202 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29204
[email protected]d27893f62010-07-03 05:47:42205 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
[email protected]a436d922009-02-13 23:16:42206 !iter.Done(); ++iter) {
207 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
208 if (plugin->info().path == plugin_path)
209 return plugin;
210 }
211
initial.commit09911bf2008-07-26 23:55:29212 return NULL;
213}
214
[email protected]a08ebea2011-02-13 17:50:20215PpapiPluginProcessHost* PluginService::FindPpapiPluginProcess(
[email protected]610c0892009-09-08 19:46:18216 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29218
[email protected]a08ebea2011-02-13 17:50:20219 for (BrowserChildProcessHost::Iterator iter(
220 ChildProcessInfo::PPAPI_PLUGIN_PROCESS);
221 !iter.Done(); ++iter) {
222 PpapiPluginProcessHost* plugin =
223 static_cast<PpapiPluginProcessHost*>(*iter);
224 if (plugin->plugin_path() == plugin_path)
225 return plugin;
226 }
227
228 return NULL;
229}
230
[email protected]eb415bf0e2011-04-14 02:45:42231PpapiBrokerProcessHost* PluginService::FindPpapiBrokerProcess(
232 const FilePath& broker_path) {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
234
235 for (BrowserChildProcessHost::Iterator iter(
236 ChildProcessInfo::PPAPI_BROKER_PROCESS);
237 !iter.Done(); ++iter) {
238 PpapiBrokerProcessHost* broker =
239 static_cast<PpapiBrokerProcessHost*>(*iter);
240 if (broker->broker_path() == broker_path)
241 return broker;
242 }
243
244 return NULL;
245}
246
[email protected]a08ebea2011-02-13 17:50:20247PluginProcessHost* PluginService::FindOrStartNpapiPluginProcess(
248 const FilePath& plugin_path) {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
250
251 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29252 if (plugin_host)
253 return plugin_host;
254
[email protected]191eb3f72010-12-21 06:27:50255 webkit::npapi::WebPluginInfo info;
256 if (!webkit::npapi::PluginList::Singleton()->GetPluginInfoByPath(
257 plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10258 return NULL;
259 }
260
initial.commit09911bf2008-07-26 23:55:29261 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40262 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
263 if (!new_host->Init(info, ui_locale_)) {
[email protected]a08ebea2011-02-13 17:50:20264 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29265 return NULL;
266 }
[email protected]8b8a554d2010-11-18 13:26:40267 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29268}
269
[email protected]a08ebea2011-02-13 17:50:20270PpapiPluginProcessHost* PluginService::FindOrStartPpapiPluginProcess(
271 const FilePath& plugin_path) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
273
274 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
275 if (plugin_host)
276 return plugin_host;
277
[email protected]eb415bf0e2011-04-14 02:45:42278 // Validate that the plugin is actually registered.
279 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]a08ebea2011-02-13 17:50:20280 if (!info)
281 return NULL;
282
283 // This plugin isn't loaded by any plugin process, so create a new process.
284 scoped_ptr<PpapiPluginProcessHost> new_host(new PpapiPluginProcessHost);
[email protected]277a1112011-03-19 06:03:56285 if (!new_host->Init(*info)) {
[email protected]a08ebea2011-02-13 17:50:20286 NOTREACHED(); // Init is not expected to fail.
287 return NULL;
288 }
289 return new_host.release();
290}
291
[email protected]eb415bf0e2011-04-14 02:45:42292PpapiBrokerProcessHost* PluginService::FindOrStartPpapiBrokerProcess(
293 const FilePath& plugin_path) {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
295
296 PpapiBrokerProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
297 if (plugin_host)
298 return plugin_host;
299
300 // Validate that the plugin is actually registered.
301 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
302 if (!info)
303 return NULL;
304
305 // TODO(ddorwin): Uncomment once out of process is supported.
306 // DCHECK(info->is_out_of_process);
307
308 // This broker isn't loaded by any broker process, so create a new process.
309 scoped_ptr<PpapiBrokerProcessHost> new_host(
310 new PpapiBrokerProcessHost);
311 if (!new_host->Init(*info)) {
312 NOTREACHED(); // Init is not expected to fail.
313 return NULL;
314 }
315 return new_host.release();
316}
317
[email protected]a08ebea2011-02-13 17:50:20318void PluginService::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17319 int render_process_id,
320 int render_view_id,
[email protected]610c0892009-09-08 19:46:18321 const GURL& url,
322 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39323 PluginProcessHost::Client* client) {
[email protected]6fdd4182010-10-14 23:59:26324 // The PluginList::GetFirstAllowedPluginInfo may need to load the
325 // plugins. Don't do it on the IO thread.
326 BrowserThread::PostTask(
327 BrowserThread::FILE, FROM_HERE,
328 NewRunnableMethod(
329 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin,
[email protected]c8f73ab2011-01-22 00:05:17330 render_process_id, render_view_id, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26331}
332
[email protected]a08ebea2011-02-13 17:50:20333void PluginService::OpenChannelToPpapiPlugin(
334 const FilePath& path,
335 PpapiPluginProcessHost::Client* client) {
336 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(path);
337 if (plugin_host)
338 plugin_host->OpenChannelToPlugin(client);
339 else // Send error.
340 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
341}
342
[email protected]eb415bf0e2011-04-14 02:45:42343void PluginService::OpenChannelToPpapiBroker(
344 const FilePath& path,
345 PpapiBrokerProcessHost::Client* client) {
346 PpapiBrokerProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
347 if (plugin_host)
348 plugin_host->OpenChannelToPpapiBroker(client);
349 else // Send error.
350 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
351}
352
[email protected]6fdd4182010-10-14 23:59:26353void PluginService::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17354 int render_process_id,
355 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26356 const GURL& url,
357 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39358 PluginProcessHost::Client* client) {
[email protected]6fdd4182010-10-14 23:59:26359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]191eb3f72010-12-21 06:27:50360 webkit::npapi::WebPluginInfo info;
[email protected]c8f73ab2011-01-22 00:05:17361 bool found = GetFirstAllowedPluginInfo(
362 render_process_id, render_view_id, url, mime_type, &info, NULL);
[email protected]6fdd4182010-10-14 23:59:26363 FilePath plugin_path;
[email protected]b83ff222011-01-24 17:37:12364 if (found && webkit::npapi::IsPluginEnabled(info))
[email protected]6fdd4182010-10-14 23:59:26365 plugin_path = FilePath(info.path);
366
367 // Now we jump back to the IO thread to finish opening the channel.
368 BrowserThread::PostTask(
369 BrowserThread::IO, FROM_HERE,
370 NewRunnableMethod(
371 this, &PluginService::FinishOpenChannelToPlugin,
[email protected]46b69e42010-11-02 12:26:39372 plugin_path, client));
[email protected]6fdd4182010-10-14 23:59:26373}
374
375void PluginService::FinishOpenChannelToPlugin(
[email protected]6fdd4182010-10-14 23:59:26376 const FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39377 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08379
[email protected]a08ebea2011-02-13 17:50:20380 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
[email protected]46b69e42010-11-02 12:26:39381 if (plugin_host)
382 plugin_host->OpenChannelToPlugin(client);
383 else
384 client->OnError();
initial.commit09911bf2008-07-26 23:55:29385}
386
[email protected]6fdd4182010-10-14 23:59:26387bool PluginService::GetFirstAllowedPluginInfo(
[email protected]c8f73ab2011-01-22 00:05:17388 int render_process_id,
389 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26390 const GURL& url,
391 const std::string& mime_type,
[email protected]191eb3f72010-12-21 06:27:50392 webkit::npapi::WebPluginInfo* info,
[email protected]6fdd4182010-10-14 23:59:26393 std::string* actual_mime_type) {
394 // GetPluginInfoArray may need to load the plugins, so we need to be
395 // on the FILE thread.
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
397 bool allow_wildcard = true;
398#if defined(OS_CHROMEOS)
[email protected]191eb3f72010-12-21 06:27:50399 std::vector<webkit::npapi::WebPluginInfo> info_array;
[email protected]6fdd4182010-10-14 23:59:26400 std::vector<std::string> actual_mime_types;
[email protected]191eb3f72010-12-21 06:27:50401 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray(
[email protected]6fdd4182010-10-14 23:59:26402 url, mime_type, allow_wildcard, &info_array, &actual_mime_types);
403
404 // Now we filter by the plugin selection policy.
405 int allowed_index = plugin_selection_policy_->FindFirstAllowed(url,
406 info_array);
407 if (!info_array.empty() && allowed_index >= 0) {
408 *info = info_array[allowed_index];
409 if (actual_mime_type)
410 *actual_mime_type = actual_mime_types[allowed_index];
411 return true;
412 }
413 return false;
414#else
[email protected]c8f73ab2011-01-22 00:05:17415 {
[email protected]5c19e8b2011-01-22 00:18:47416 base::AutoLock auto_lock(overridden_plugins_lock_);
[email protected]c8f73ab2011-01-22 00:05:17417 for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
418 if (overridden_plugins_[i].render_process_id == render_process_id &&
419 overridden_plugins_[i].render_view_id == render_view_id &&
420 overridden_plugins_[i].url == url) {
[email protected]79f0fa752011-01-27 20:01:47421 if (actual_mime_type)
422 *actual_mime_type = mime_type;
[email protected]c8f73ab2011-01-22 00:05:17423 *info = overridden_plugins_[i].plugin;
424 return true;
425 }
426 }
427 }
[email protected]191eb3f72010-12-21 06:27:50428 return webkit::npapi::PluginList::Singleton()->GetPluginInfo(
[email protected]6fdd4182010-10-14 23:59:26429 url, mime_type, allow_wildcard, info, actual_mime_type);
430#endif
431}
432
[email protected]580522632009-08-17 21:55:55433void PluginService::OnWaitableEventSignaled(
434 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27435#if defined(OS_WIN)
436 if (waitable_event == hkcu_event_.get()) {
437 hkcu_key_.StartWatching();
438 } else {
439 hklm_key_.StartWatching();
440 }
441
[email protected]191eb3f72010-12-21 06:27:50442 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]b78e168b2009-09-21 22:05:45443 PurgePluginListCache(true);
[email protected]634d23d2011-01-19 10:38:19444#else
445 // This event should only get signaled on a Windows machine.
446 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53447#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27448}
[email protected]894bb502009-05-21 22:39:57449
450void PluginService::Observe(NotificationType type,
451 const NotificationSource& source,
452 const NotificationDetails& details) {
453 switch (type.value) {
[email protected]a96ec6a2009-11-04 17:27:08454#if defined(OS_MACOSX)
455 case NotificationType::APP_ACTIVATED: {
[email protected]f8b3ef82010-10-11 02:45:52456 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
457 NewRunnableFunction(&NotifyPluginsOfActivation));
[email protected]a96ec6a2009-11-04 17:27:08458 break;
459 }
460#endif
461
[email protected]5f101bbe2010-10-08 08:01:16462 case NotificationType::PLUGIN_ENABLE_STATUS_CHANGED: {
[email protected]b83ff222011-01-24 17:37:12463 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]5f101bbe2010-10-08 08:01:16464 PurgePluginListCache(false);
465 break;
466 }
[email protected]c8f73ab2011-01-22 00:05:17467 case NotificationType::RENDERER_PROCESS_CLOSED: {
468 int render_process_id = Source<RenderProcessHost>(source).ptr()->id();
469
[email protected]5c19e8b2011-01-22 00:18:47470 base::AutoLock auto_lock(overridden_plugins_lock_);
[email protected]c8f73ab2011-01-22 00:05:17471 for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
472 if (overridden_plugins_[i].render_process_id == render_process_id) {
473 overridden_plugins_.erase(overridden_plugins_.begin() + i);
474 break;
475 }
476 }
477 break;
478 }
[email protected]894bb502009-05-21 22:39:57479 default:
[email protected]634d23d2011-01-19 10:38:19480 NOTREACHED();
[email protected]894bb502009-05-21 22:39:57481 }
482}
[email protected]9dd9e8382009-06-05 18:23:21483
[email protected]bd5174d2011-03-11 01:02:56484void PluginService::OverridePluginForTab(const OverriddenPlugin& plugin) {
[email protected]5c19e8b2011-01-22 00:18:47485 base::AutoLock auto_lock(overridden_plugins_lock_);
[email protected]c8f73ab2011-01-22 00:05:17486 overridden_plugins_.push_back(plugin);
487}
488
[email protected]2de307592011-04-05 21:16:58489void PluginService::PurgePluginListCache(bool reload_pages) {
490 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
491 !it.IsAtEnd(); it.Advance()) {
492 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
493 }
494}
495
496void PluginService::RestrictPluginToUrl(const FilePath& plugin_path,
497 const GURL& url) {
498 base::AutoLock auto_lock(restricted_plugin_lock_);
499 if (url.is_empty()) {
500 restricted_plugin_.erase(plugin_path);
501 } else {
502 restricted_plugin_[plugin_path] = url;
503 }
504}
505
506bool PluginService::PluginAllowedForURL(const FilePath& plugin_path,
507 const GURL& url) {
508 if (url.is_empty())
509 return true; // Caller wants all plugins.
510
511 base::AutoLock auto_lock(restricted_plugin_lock_);
512
513 RestrictedPluginMap::iterator it = restricted_plugin_.find(plugin_path);
514 if (it == restricted_plugin_.end())
515 return true; // This plugin is not restricted, so it's allowed everywhere.
516
517 const GURL& required_url = it->second;
518 return (url.scheme() == required_url.scheme() &&
519 url.host() == required_url.host());
520}
521
[email protected]4e0616e2010-05-28 14:55:53522void PluginService::RegisterPepperPlugins() {
[email protected]84396dbc2011-04-14 06:33:42523 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
[email protected]a08ebea2011-02-13 17:50:20524 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
525 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]84396dbc2011-04-14 06:33:42526 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(
527 ppapi_plugins_[i].ToWebPluginInfo());
[email protected]4e0616e2010-05-28 14:55:53528 }
529}
[email protected]634d23d2011-01-19 10:38:19530
[email protected]eb415bf0e2011-04-14 02:45:42531// There should generally be very few plugins so a brute-force search is fine.
532PepperPluginInfo* PluginService::GetRegisteredPpapiPluginInfo(
533 const FilePath& plugin_path) {
534 PepperPluginInfo* info = NULL;
535 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
536 if (ppapi_plugins_[i].path == plugin_path) {
537 info = &ppapi_plugins_[i];
538 break;
539 }
540 }
541 return info;
542}
543
[email protected]634d23d2011-01-19 10:38:19544#if defined(OS_LINUX)
545// static
546void PluginService::RegisterFilePathWatcher(
547 FilePathWatcher *watcher,
548 const FilePath& path,
549 FilePathWatcher::Delegate* delegate) {
[email protected]7b3ee8b2011-04-01 18:48:19550 bool result = watcher->Watch(path, delegate);
[email protected]634d23d2011-01-19 10:38:19551 DCHECK(result);
552}
553#endif