blob: 7ad30e576868c63cbe77596a1de72a9080b13075 [file] [log] [blame]
[email protected]3b48dbc2012-01-06 16:34:171// Copyright (c) 2012 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]e67385f2011-12-21 06:00:565#include "content/browser/plugin_service_impl.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]d33e7cc2011-09-23 01:43:567#include "base/bind.h"
[email protected]d48f1e0c2009-02-12 20:57:548#include "base/command_line.h"
[email protected]7b3ee8b2011-04-01 18:48:199#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5210#include "base/files/file_path.h"
[email protected]d33e7cc2011-09-23 01:43:5611#include "base/message_loop.h"
[email protected]7ccb7072013-06-10 20:56:2812#include "base/message_loop/message_loop_proxy.h"
[email protected]fd8d8d6c2013-02-28 02:48:3313#include "base/metrics/histogram.h"
[email protected]9c49ff02010-01-27 01:20:5514#include "base/path_service.h"
[email protected]348fbaac2013-06-11 06:31:5115#include "base/strings/string_util.h"
[email protected]74ebfb12013-06-07 20:48:0016#include "base/strings/utf_string_conversions.h"
[email protected]7f070d42011-03-09 20:25:3217#include "base/synchronization/waitable_event.h"
[email protected]34b99632011-01-01 01:01:0618#include "base/threading/thread.h"
[email protected]a01efd22011-03-01 00:38:3219#include "content/browser/ppapi_plugin_process_host.h"
[email protected]f3b1a082011-11-18 00:34:3020#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]b3c41c0b2012-03-06 15:48:3221#include "content/browser/renderer_host/render_view_host_impl.h"
[email protected]cebc3dc2011-04-18 17:15:0022#include "content/common/pepper_plugin_registry.h"
[email protected]38b592902011-04-16 02:08:4223#include "content/common/view_messages.h"
[email protected]c38831a12011-10-28 12:44:4924#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4425#include "content/public/browser/content_browser_client.h"
[email protected]31f376c2012-03-13 16:43:0926#include "content/public/browser/plugin_service_filter.h"
[email protected]ce967862012-02-09 22:47:0527#include "content/public/browser/resource_context.h"
[email protected]c08950d22011-10-13 22:20:2928#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1229#include "content/public/common/process_type.h"
[email protected]191eb3f72010-12-21 06:27:5030#include "webkit/plugins/npapi/plugin_list.h"
[email protected]1b517202012-12-19 17:16:1031#include "webkit/plugins/npapi/plugin_utils.h"
[email protected]fd8d8d6c2013-02-28 02:48:3332#include "webkit/plugins/plugin_constants.h"
[email protected]91d9f3d2011-08-14 05:24:4433#include "webkit/plugins/webplugininfo.h"
[email protected]191eb3f72010-12-21 06:27:5034
[email protected]3b91edbe2012-09-27 22:49:2335#if defined(OS_WIN)
36#include "webkit/plugins/npapi/plugin_constants_win.h"
37#endif
38
39#if defined(OS_POSIX)
40#include "content/browser/plugin_loader_posix.h"
41#endif
42
[email protected]52348b22012-11-07 10:19:3443#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]6665571f2013-01-15 07:59:5244using ::base::FilePathWatcher;
[email protected]493c8002011-04-14 16:56:0145#endif
46
[email protected]130757672012-10-24 00:26:1947namespace content {
[email protected]d33e7cc2011-09-23 01:43:5648namespace {
49
[email protected]fd8d8d6c2013-02-28 02:48:3350// This enum is used to collect Flash usage data.
51enum FlashUsage {
52 // Number of browser processes that have started at least one NPAPI Flash
53 // process during their lifetime.
54 START_NPAPI_FLASH_AT_LEAST_ONCE,
55 // Number of browser processes that have started at least one PPAPI Flash
56 // process during their lifetime.
57 START_PPAPI_FLASH_AT_LEAST_ONCE,
58 // Total number of browser processes.
59 TOTAL_BROWSER_PROCESSES,
60 FLASH_USAGE_ENUM_COUNT
61};
62
[email protected]1b517202012-12-19 17:16:1063bool LoadPluginListInProcess() {
64#if defined(OS_WIN)
65 return true;
66#else
67 // If on POSIX, we don't want to load the list of NPAPI plugins in-process as
68 // that causes instability.
69 return !webkit::npapi::NPAPIPluginsSupported();
70#endif
71}
72
[email protected]49125952011-09-27 18:05:1573// Callback set on the PluginList to assert that plugin loading happens on the
74// correct thread.
[email protected]1b517202012-12-19 17:16:1075void WillLoadPluginsCallback(
[email protected]a33fa9d2012-05-16 14:47:4976 base::SequencedWorkerPool::SequenceToken token) {
[email protected]1b517202012-12-19 17:16:1077 if (LoadPluginListInProcess()) {
78 CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
79 token));
80 } else {
81 CHECK(false) << "Plugin loading should happen out-of-process.";
82 }
[email protected]a79912252012-05-16 11:52:1983}
[email protected]d33e7cc2011-09-23 01:43:5684
[email protected]a96ec6a2009-11-04 17:27:0885#if defined(OS_MACOSX)
[email protected]07b71c82013-01-08 19:07:3186void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5287 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0888
[email protected]4967f792012-01-20 22:14:4089 for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
90 iter->OnAppActivation();
[email protected]a96ec6a2009-11-04 17:27:0891}
[email protected]3b48dbc2012-01-06 16:34:1792#endif
[email protected]45a22e62011-10-12 09:48:0293
[email protected]07b71c82013-01-08 19:07:3194#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]2dec8ec2013-02-07 19:20:3495void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
[email protected]07b71c82013-01-08 19:07:3196 if (error) {
[email protected]634d23d2011-01-19 10:38:1997 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
98 // stopping the watcher would be enough. Or possibly restart it.
99 NOTREACHED();
[email protected]07b71c82013-01-08 19:07:31100 return;
[email protected]634d23d2011-01-19 10:38:19101 }
[email protected]07b71c82013-01-08 19:07:31102 VLOG(1) << "Watched path changed: " << path.value();
103 // Make the plugin list update itself
104 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
105 BrowserThread::PostTask(
106 BrowserThread::UI, FROM_HERE,
107 base::Bind(&PluginService::PurgePluginListCache,
108 static_cast<BrowserContext*>(NULL), false));
109}
[email protected]634d23d2011-01-19 10:38:19110#endif
111
[email protected]07b71c82013-01-08 19:07:31112} // namespace
113
[email protected]3a5180ae2011-12-21 02:39:38114// static
115PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56116 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38117}
118
119void PluginService::PurgePluginListCache(BrowserContext* browser_context,
120 bool reload_pages) {
121 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
122 !it.IsAtEnd(); it.Advance()) {
123 RenderProcessHost* host = it.GetCurrentValue();
124 if (!browser_context || host->GetBrowserContext() == browser_context)
125 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
126 }
127}
128
initial.commit09911bf2008-07-26 23:55:29129// static
[email protected]e67385f2011-12-21 06:00:56130PluginServiceImpl* PluginServiceImpl::GetInstance() {
131 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29132}
133
[email protected]e67385f2011-12-21 06:00:56134PluginServiceImpl::PluginServiceImpl()
[email protected]99907362012-01-11 05:41:40135 : plugin_list_(NULL), filter_(NULL) {
[email protected]fd8d8d6c2013-02-28 02:48:33136 // Collect the total number of browser processes (which create
137 // PluginServiceImpl objects, to be precise). The number is used to normalize
138 // the number of processes which start at least one NPAPI/PPAPI Flash process.
139 static bool counted = false;
140 if (!counted) {
141 counted = true;
142 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES,
143 FLASH_USAGE_ENUM_COUNT);
144 }
[email protected]ee066172011-11-10 23:20:05145}
146
[email protected]e67385f2011-12-21 06:00:56147PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05148#if defined(OS_WIN)
149 // Release the events since they're owned by RegKey, not WaitableEvent.
150 hkcu_watcher_.StopWatching();
151 hklm_watcher_.StopWatching();
[email protected]59383c782013-04-17 16:43:27152 if (hkcu_event_)
[email protected]ee066172011-11-10 23:20:05153 hkcu_event_->Release();
[email protected]59383c782013-04-17 16:43:27154 if (hklm_event_)
[email protected]ee066172011-11-10 23:20:05155 hklm_event_->Release();
156#endif
157 // Make sure no plugin channel requests have been leaked.
158 DCHECK(pending_plugin_clients_.empty());
159}
160
[email protected]e67385f2011-12-21 06:00:56161void PluginServiceImpl::Init() {
[email protected]ee066172011-11-10 23:20:05162 if (!plugin_list_)
163 plugin_list_ = webkit::npapi::PluginList::Singleton();
164
[email protected]a33fa9d2012-05-16 14:47:49165 plugin_list_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
[email protected]3a5180ae2011-12-21 02:39:38166 plugin_list_->set_will_load_plugins_callback(
[email protected]1b517202012-12-19 17:16:10167 base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
[email protected]49125952011-09-27 18:05:15168
[email protected]4e0616e2010-05-28 14:55:53169 RegisterPepperPlugins();
170
[email protected]0f7d449e2013-01-23 15:12:35171 // The --site-per-process flag enables an out-of-process iframes
172 // prototype, which uses WebView for rendering. We need to register the MIME
173 // type we use with the plugin, so the renderer can instantiate it.
174 const CommandLine* command_line = CommandLine::ForCurrentProcess();
175 if (command_line->HasSwitch(switches::kSitePerProcess)) {
176 webkit::WebPluginInfo webview_plugin(
177 ASCIIToUTF16("WebView Tag"),
[email protected]007b3f82013-04-09 08:46:45178 base::FilePath(),
[email protected]0f7d449e2013-01-23 15:12:35179 ASCIIToUTF16("1.2.3.4"),
180 ASCIIToUTF16("Browser Plugin."));
181 webview_plugin.type = webkit::WebPluginInfo::PLUGIN_TYPE_NPAPI;
182 webkit::WebPluginMimeType webview_plugin_mime_type;
183 webview_plugin_mime_type.mime_type = "application/browser-plugin";
184 webview_plugin_mime_type.file_extensions.push_back("*");
185 webview_plugin.mime_types.push_back(webview_plugin_mime_type);
186 RegisterInternalPlugin(webview_plugin, true);
187 }
188
[email protected]130757672012-10-24 00:26:19189 GetContentClient()->AddNPAPIPlugins(plugin_list_);
[email protected]f520b5b2011-11-08 02:42:14190
[email protected]9a1c4262010-06-29 21:50:27191 // Load any specified on the command line as well.
[email protected]2dec8ec2013-02-07 19:20:34192 base::FilePath path =
193 command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28194 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14195 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27196 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
197 if (!path.empty())
[email protected]3a5180ae2011-12-21 02:39:38198 plugin_list_->AddExtraPluginDir(path);
[email protected]dfba8762011-09-02 12:49:54199}
200
[email protected]e67385f2011-12-21 06:00:56201void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19202 // Start watching for changes in the plugin list. This means watching
203 // for changes in the Windows registry keys and on both Windows and POSIX
204 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27205#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19206 if (hkcu_key_.Create(HKEY_CURRENT_USER,
207 webkit::npapi::kRegistryMozillaPlugins,
208 KEY_NOTIFY) == ERROR_SUCCESS) {
209 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
210 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
[email protected]329be052013-02-04 18:14:28211 base::WaitableEventWatcher::EventCallback callback =
212 base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
213 base::Unretained(this));
214 hkcu_watcher_.StartWatching(hkcu_event_.get(), callback);
[email protected]86ec4f6e2011-04-20 16:21:19215 }
[email protected]b547fd42009-04-23 23:16:27216 }
[email protected]86ec4f6e2011-04-20 16:21:19217 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
218 webkit::npapi::kRegistryMozillaPlugins,
219 KEY_NOTIFY) == ERROR_SUCCESS) {
220 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
221 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
[email protected]329be052013-02-04 18:14:28222 base::WaitableEventWatcher::EventCallback callback =
223 base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
224 base::Unretained(this));
225 hklm_watcher_.StartWatching(hklm_event_.get(), callback);
[email protected]86ec4f6e2011-04-20 16:21:19226 }
[email protected]b547fd42009-04-23 23:16:27227 }
[email protected]a33fa9d2012-05-16 14:47:49228#endif
[email protected]52348b22012-11-07 10:19:34229#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19230// On ChromeOS the user can't install plugins anyway and on Windows all
231// important plugins register themselves in the registry so no need to do that.
[email protected]07b71c82013-01-08 19:07:31232
[email protected]634d23d2011-01-19 10:38:19233 // Get the list of all paths for registering the FilePathWatchers
234 // that will track and if needed reload the list of plugins on runtime.
[email protected]2dec8ec2013-02-07 19:20:34235 std::vector<base::FilePath> plugin_dirs;
[email protected]3a5180ae2011-12-21 02:39:38236 plugin_list_->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57237
[email protected]634d23d2011-01-19 10:38:19238 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19239 // FilePathWatcher can not handle non-absolute paths under windows.
240 // We don't watch for file changes in windows now but if this should ever
241 // be extended to Windows these lines might save some time of debugging.
242#if defined(OS_WIN)
243 if (!plugin_dirs[i].IsAbsolute())
244 continue;
245#endif
[email protected]493c8002011-04-14 16:56:01246 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19247 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
248 BrowserThread::PostTask(
249 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56250 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]07b71c82013-01-08 19:07:31251 plugin_dirs[i]));
[email protected]634d23d2011-01-19 10:38:19252 file_watchers_.push_back(watcher);
253 }
254#endif
initial.commit09911bf2008-07-26 23:55:29255}
256
[email protected]e67385f2011-12-21 06:00:56257PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34258 const base::FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40259 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
260 if (iter->info().path == plugin_path)
261 return *iter;
[email protected]a436d922009-02-13 23:16:42262 }
263
initial.commit09911bf2008-07-26 23:55:29264 return NULL;
265}
266
[email protected]e67385f2011-12-21 06:00:56267PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34268 const base::FilePath& plugin_path,
269 const base::FilePath& profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40270 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]dd9a0952012-05-31 20:11:31271 if (iter->plugin_path() == plugin_path &&
272 iter->profile_data_directory() == profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40273 return *iter;
[email protected]dd9a0952012-05-31 20:11:31274 }
[email protected]a08ebea2011-02-13 17:50:20275 }
[email protected]a08ebea2011-02-13 17:50:20276 return NULL;
277}
278
[email protected]e67385f2011-12-21 06:00:56279PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]2dec8ec2013-02-07 19:20:34280 const base::FilePath& broker_path) {
[email protected]4967f792012-01-20 22:14:40281 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
282 if (iter->plugin_path() == broker_path)
283 return *iter;
[email protected]eb415bf0e2011-04-14 02:45:42284 }
285
286 return NULL;
287}
288
[email protected]e67385f2011-12-21 06:00:56289PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54290 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34291 const base::FilePath& plugin_path) {
[email protected]a08ebea2011-02-13 17:50:20292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
293
[email protected]6be31d202013-02-01 18:20:54294 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
295 return NULL;
296
[email protected]a08ebea2011-02-13 17:50:20297 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29298 if (plugin_host)
299 return plugin_host;
300
[email protected]91d9f3d2011-08-14 05:24:44301 webkit::WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43302 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10303 return NULL;
304 }
305
[email protected]fd8d8d6c2013-02-28 02:48:33306 // Record when NPAPI Flash process is started for the first time.
307 static bool counted = false;
308 if (!counted && UTF16ToUTF8(info.name) == kFlashPluginName) {
309 counted = true;
310 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
311 START_NPAPI_FLASH_AT_LEAST_ONCE,
312 FLASH_USAGE_ENUM_COUNT);
313 }
314
initial.commit09911bf2008-07-26 23:55:29315 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40316 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
[email protected]99907362012-01-11 05:41:40317 if (!new_host->Init(info)) {
[email protected]a08ebea2011-02-13 17:50:20318 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29319 return NULL;
320 }
[email protected]8b8a554d2010-11-18 13:26:40321 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29322}
323
[email protected]e67385f2011-12-21 06:00:56324PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54325 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34326 const base::FilePath& plugin_path,
327 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14328 PpapiPluginProcessHost::PluginClient* client) {
[email protected]a08ebea2011-02-13 17:50:20329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
330
[email protected]6be31d202013-02-01 18:20:54331 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
332 return NULL;
333
[email protected]dd9a0952012-05-31 20:11:31334 PpapiPluginProcessHost* plugin_host =
335 FindPpapiPluginProcess(plugin_path, profile_data_directory);
[email protected]a08ebea2011-02-13 17:50:20336 if (plugin_host)
337 return plugin_host;
338
[email protected]eb415bf0e2011-04-14 02:45:42339 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19340 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]a08ebea2011-02-13 17:50:20341 if (!info)
342 return NULL;
343
[email protected]fd8d8d6c2013-02-28 02:48:33344 // Record when PPAPI Flash process is started for the first time.
345 static bool counted = false;
346 if (!counted && info->name == kFlashPluginName) {
347 counted = true;
348 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
349 START_PPAPI_FLASH_AT_LEAST_ONCE,
350 FLASH_USAGE_ENUM_COUNT);
351 }
352
[email protected]a08ebea2011-02-13 17:50:20353 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14354 return PpapiPluginProcessHost::CreatePluginHost(
[email protected]dd9a0952012-05-31 20:11:31355 *info, profile_data_directory,
[email protected]df02aca2012-02-09 21:03:20356 client->GetResourceContext()->GetHostResolver());
[email protected]a08ebea2011-02-13 17:50:20357}
358
[email protected]e67385f2011-12-21 06:00:56359PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]6be31d202013-02-01 18:20:54360 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34361 const base::FilePath& plugin_path) {
[email protected]eb415bf0e2011-04-14 02:45:42362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
363
[email protected]6be31d202013-02-01 18:20:54364 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
365 return NULL;
366
[email protected]a50432d2011-09-30 16:32:14367 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42368 if (plugin_host)
369 return plugin_host;
370
371 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19372 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42373 if (!info)
374 return NULL;
375
376 // TODO(ddorwin): Uncomment once out of process is supported.
377 // DCHECK(info->is_out_of_process);
378
379 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14380 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42381}
382
[email protected]e67385f2011-12-21 06:00:56383void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17384 int render_process_id,
385 int render_view_id,
[email protected]610c0892009-09-08 19:46:18386 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54387 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18388 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39389 PluginProcessHost::Client* client) {
[email protected]76b70f92011-11-21 19:31:14390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4befe7592011-09-14 22:49:09391 DCHECK(!ContainsKey(pending_plugin_clients_, client));
392 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43393
394 // Make sure plugins are loaded if necessary.
[email protected]209f2ae2012-03-13 01:28:08395 PluginServiceFilterParams params = {
[email protected]88ca4912011-10-12 14:00:43396 render_process_id,
397 render_view_id,
398 page_url,
[email protected]df02aca2012-02-09 21:03:20399 client->GetResourceContext()
[email protected]88ca4912011-10-12 14:00:43400 };
[email protected]e67385f2011-12-21 06:00:56401 GetPlugins(base::Bind(
402 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
403 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26404}
405
[email protected]e67385f2011-12-21 06:00:56406void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]6be31d202013-02-01 18:20:54407 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34408 const base::FilePath& plugin_path,
409 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14410 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09411 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54412 render_process_id, plugin_path, profile_data_directory, client);
[email protected]1bf0fb22012-04-12 21:44:16413 if (plugin_host) {
[email protected]a08ebea2011-02-13 17:50:20414 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16415 } else {
416 // Send error.
[email protected]108fd342013-01-04 20:46:54417 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16418 }
[email protected]a08ebea2011-02-13 17:50:20419}
420
[email protected]e67385f2011-12-21 06:00:56421void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]6be31d202013-02-01 18:20:54422 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34423 const base::FilePath& path,
[email protected]a50432d2011-09-30 16:32:14424 PpapiPluginProcessHost::BrokerClient* client) {
[email protected]6be31d202013-02-01 18:20:54425 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
426 render_process_id, path);
[email protected]1bf0fb22012-04-12 21:44:16427 if (plugin_host) {
[email protected]a50432d2011-09-30 16:32:14428 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16429 } else {
430 // Send error.
[email protected]108fd342013-01-04 20:46:54431 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16432 }
[email protected]eb415bf0e2011-04-14 02:45:42433}
434
[email protected]e67385f2011-12-21 06:00:56435void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09436 PluginProcessHost::Client* client) {
437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
438 DCHECK(ContainsKey(pending_plugin_clients_, client));
439 pending_plugin_clients_.erase(client);
440}
441
[email protected]e67385f2011-12-21 06:00:56442void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]209f2ae2012-03-13 01:28:08443 const PluginServiceFilterParams& params,
[email protected]88ca4912011-10-12 14:00:43444 const GURL& url,
445 const std::string& mime_type,
446 PluginProcessHost::Client* client,
447 const std::vector<webkit::WebPluginInfo>&) {
448 GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
449 params.render_view_id, url, params.page_url, mime_type, client,
450 params.resource_context);
451}
452
[email protected]e67385f2011-12-21 06:00:56453void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17454 int render_process_id,
455 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26456 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54457 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26458 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59459 PluginProcessHost::Client* client,
[email protected]130757672012-10-24 00:26:19460 ResourceContext* resource_context) {
[email protected]91d9f3d2011-08-14 05:24:44461 webkit::WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54462 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27463 bool found = GetPluginInfo(
[email protected]df02aca2012-02-09 21:03:20464 render_process_id, render_view_id, resource_context,
[email protected]dfba8762011-09-02 12:49:54465 url, page_url, mime_type, allow_wildcard,
466 NULL, &info, NULL);
[email protected]2dec8ec2013-02-07 19:20:34467 base::FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28468 if (found)
[email protected]dfba8762011-09-02 12:49:54469 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26470
471 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56472 BrowserThread::PostTask(
473 BrowserThread::IO, FROM_HERE,
474 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]6be31d202013-02-01 18:20:54475 base::Unretained(this),
476 render_process_id,
477 plugin_path,
478 client));
[email protected]6fdd4182010-10-14 23:59:26479}
480
[email protected]e67385f2011-12-21 06:00:56481void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6be31d202013-02-01 18:20:54482 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34483 const base::FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39484 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08486
[email protected]4befe7592011-09-14 22:49:09487 // Make sure it hasn't been canceled yet.
488 if (!ContainsKey(pending_plugin_clients_, client))
489 return;
490 pending_plugin_clients_.erase(client);
491
[email protected]6be31d202013-02-01 18:20:54492 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
493 render_process_id, plugin_path);
[email protected]4befe7592011-09-14 22:49:09494 if (plugin_host) {
495 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39496 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09497 } else {
[email protected]46b69e42010-11-02 12:26:39498 client->OnError();
[email protected]4befe7592011-09-14 22:49:09499 }
initial.commit09911bf2008-07-26 23:55:29500}
501
[email protected]e67385f2011-12-21 06:00:56502bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42503 const GURL& url,
504 const std::string& mime_type,
505 bool allow_wildcard,
506 std::vector<webkit::WebPluginInfo>* plugins,
507 std::vector<std::string>* actual_mime_types) {
508 bool use_stale = false;
[email protected]3a5180ae2011-12-21 02:39:38509 plugin_list_->GetPluginInfoArray(url, mime_type, allow_wildcard,
510 &use_stale, plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42511 return use_stale;
512}
513
[email protected]e67385f2011-12-21 06:00:56514bool PluginServiceImpl::GetPluginInfo(int render_process_id,
515 int render_view_id,
[email protected]130757672012-10-24 00:26:19516 ResourceContext* context,
[email protected]e67385f2011-12-21 06:00:56517 const GURL& url,
518 const GURL& page_url,
519 const std::string& mime_type,
520 bool allow_wildcard,
521 bool* is_stale,
522 webkit::WebPluginInfo* info,
523 std::string* actual_mime_type) {
[email protected]91d9f3d2011-08-14 05:24:44524 std::vector<webkit::WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28525 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43526 bool stale = GetPluginInfoArray(
527 url, mime_type, allow_wildcard, &plugins, &mime_types);
528 if (is_stale)
529 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54530
[email protected]68598072011-07-29 08:21:28531 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]05f511282013-02-05 15:02:50532 if (!filter_ || filter_->IsPluginAvailable(render_process_id,
533 render_view_id,
534 context,
535 url,
536 page_url,
537 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28538 *info = plugins[i];
539 if (actual_mime_type)
540 *actual_mime_type = mime_types[i];
541 return true;
542 }
543 }
544 return false;
[email protected]6fdd4182010-10-14 23:59:26545}
546
[email protected]2dec8ec2013-02-07 19:20:34547bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
[email protected]e67385f2011-12-21 06:00:56548 webkit::WebPluginInfo* info) {
[email protected]88ca4912011-10-12 14:00:43549 std::vector<webkit::WebPluginInfo> plugins;
[email protected]480c7cc2012-06-29 17:38:44550 plugin_list_->GetPluginsNoRefresh(&plugins);
[email protected]88ca4912011-10-12 14:00:43551
552 for (std::vector<webkit::WebPluginInfo>::iterator it = plugins.begin();
553 it != plugins.end();
554 ++it) {
555 if (it->path == plugin_path) {
556 *info = *it;
557 return true;
558 }
559 }
560
561 return false;
562}
563
[email protected]2dec8ec2013-02-07 19:20:34564string16 PluginServiceImpl::GetPluginDisplayNameByPath(
565 const base::FilePath& path) {
[email protected]8be45842012-04-13 19:49:29566 string16 plugin_name = path.LossyDisplayName();
567 webkit::WebPluginInfo info;
568 if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
569 !info.name.empty()) {
570 plugin_name = info.name;
571#if defined(OS_MACOSX)
572 // Many plugins on the Mac have .plugin in the actual name, which looks
573 // terrible, so look for that and strip it off if present.
574 const std::string kPluginExtension = ".plugin";
575 if (EndsWith(plugin_name, ASCIIToUTF16(kPluginExtension), true))
576 plugin_name.erase(plugin_name.length() - kPluginExtension.length());
577#endif // OS_MACOSX
578 }
579 return plugin_name;
580}
581
[email protected]e67385f2011-12-21 06:00:56582void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
[email protected]49125952011-09-27 18:05:15583 scoped_refptr<base::MessageLoopProxy> target_loop(
[email protected]dd32b1272013-05-04 14:17:11584 base::MessageLoop::current()->message_loop_proxy());
[email protected]49125952011-09-27 18:05:15585
[email protected]1b517202012-12-19 17:16:10586 if (LoadPluginListInProcess()) {
587 BrowserThread::GetBlockingPool()->
588 PostSequencedWorkerTaskWithShutdownBehavior(
589 plugin_list_token_,
590 FROM_HERE,
591 base::Bind(&PluginServiceImpl::GetPluginsInternal,
592 base::Unretained(this),
593 target_loop, callback),
594 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
595 return;
596 }
597#if defined(OS_POSIX)
[email protected]49125952011-09-27 18:05:15598 std::vector<webkit::WebPluginInfo> cached_plugins;
[email protected]480c7cc2012-06-29 17:38:44599 if (plugin_list_->GetPluginsNoRefresh(&cached_plugins)) {
[email protected]49125952011-09-27 18:05:15600 // Can't assume the caller is reentrant.
601 target_loop->PostTask(FROM_HERE,
[email protected]00b25432012-04-07 04:21:37602 base::Bind(callback, cached_plugins));
[email protected]49125952011-09-27 18:05:15603 } else {
[email protected]4bb85b92011-11-05 02:53:29604 // If we switch back to loading plugins in process, then we need to make
605 // sure g_thread_init() gets called since plugins may call glib at load.
[email protected]fc72bb12013-06-02 21:13:46606 if (!plugin_loader_.get())
[email protected]d4af1e72011-10-21 17:45:43607 plugin_loader_ = new PluginLoaderPosix;
[email protected]49125952011-09-27 18:05:15608 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]d4af1e72011-10-21 17:45:43609 base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
610 target_loop, callback));
[email protected]49125952011-09-27 18:05:15611 }
[email protected]a33fa9d2012-05-16 14:47:49612#else
[email protected]1b517202012-12-19 17:16:10613 NOTREACHED();
[email protected]49125952011-09-27 18:05:15614#endif
[email protected]d33e7cc2011-09-23 01:43:56615}
616
[email protected]e67385f2011-12-21 06:00:56617void PluginServiceImpl::GetPluginsInternal(
[email protected]d33e7cc2011-09-23 01:43:56618 base::MessageLoopProxy* target_loop,
619 const PluginService::GetPluginsCallback& callback) {
[email protected]a33fa9d2012-05-16 14:47:49620 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
621 plugin_list_token_));
[email protected]d33e7cc2011-09-23 01:43:56622
623 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38624 plugin_list_->GetPlugins(&plugins);
[email protected]d33e7cc2011-09-23 01:43:56625
626 target_loop->PostTask(FROM_HERE,
[email protected]00b25432012-04-07 04:21:37627 base::Bind(callback, plugins));
[email protected]dfba8762011-09-02 12:49:54628}
629
[email protected]e67385f2011-12-21 06:00:56630void PluginServiceImpl::OnWaitableEventSignaled(
[email protected]580522632009-08-17 21:55:55631 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27632#if defined(OS_WIN)
[email protected]59383c782013-04-17 16:43:27633 if (waitable_event == hkcu_event_) {
[email protected]b547fd42009-04-23 23:16:27634 hkcu_key_.StartWatching();
635 } else {
636 hklm_key_.StartWatching();
637 }
638
[email protected]3a5180ae2011-12-21 02:39:38639 plugin_list_->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02640 PurgePluginListCache(NULL, false);
[email protected]634d23d2011-01-19 10:38:19641#else
642 // This event should only get signaled on a Windows machine.
643 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53644#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27645}
[email protected]894bb502009-05-21 22:39:57646
[email protected]e67385f2011-12-21 06:00:56647void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]84396dbc2011-04-14 06:33:42648 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
[email protected]a08ebea2011-02-13 17:50:20649 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
650 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]c6f3dea2012-01-14 02:23:11651 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
[email protected]4e0616e2010-05-28 14:55:53652 }
653}
[email protected]634d23d2011-01-19 10:38:19654
[email protected]eb415bf0e2011-04-14 02:45:42655// There should generally be very few plugins so a brute-force search is fine.
[email protected]130757672012-10-24 00:26:19656PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]2dec8ec2013-02-07 19:20:34657 const base::FilePath& plugin_path) {
[email protected]130757672012-10-24 00:26:19658 PepperPluginInfo* info = NULL;
[email protected]eb415bf0e2011-04-14 02:45:42659 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
[email protected]6b14feb2011-08-16 11:22:56660 if (ppapi_plugins_[i].path == plugin_path) {
661 info = &ppapi_plugins_[i];
662 break;
663 }
[email protected]eb415bf0e2011-04-14 02:45:42664 }
[email protected]076117592011-08-17 03:16:41665 if (info)
666 return info;
667 // We did not find the plugin in our list. But wait! the plugin can also
668 // be a latecomer, as it happens with pepper flash. This information
669 // can be obtained from the PluginList singleton and we can use it to
670 // construct it and add it to the list. This same deal needs to be done
671 // in the renderer side in PepperPluginRegistry.
672 webkit::WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43673 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41674 return NULL;
[email protected]130757672012-10-24 00:26:19675 PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41676 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
677 return NULL;
678 ppapi_plugins_.push_back(new_pepper_info);
679 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42680}
681
[email protected]52348b22012-11-07 10:19:34682#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19683// static
[email protected]07b71c82013-01-08 19:07:31684void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
[email protected]2dec8ec2013-02-07 19:20:34685 const base::FilePath& path) {
[email protected]07b71c82013-01-08 19:07:31686 bool result = watcher->Watch(path, false,
687 base::Bind(&NotifyPluginDirChanged));
[email protected]634d23d2011-01-19 10:38:19688 DCHECK(result);
689}
690#endif
[email protected]f520b5b2011-11-08 02:42:14691
[email protected]130757672012-10-24 00:26:19692void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38693 filter_ = filter;
694}
695
[email protected]130757672012-10-24 00:26:19696PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38697 return filter_;
698}
699
[email protected]2dec8ec2013-02-07 19:20:34700void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
[email protected]b6a2f8de2012-01-31 17:28:49701 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
702 BrowserThread::PostTask(
703 BrowserThread::IO, FROM_HERE,
704 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
705 base::Unretained(this), plugin_path));
706 return;
707 }
708
709 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
710 if (plugin)
711 plugin->ForceShutdown();
712}
713
[email protected]47214d882012-02-29 06:28:48714static const unsigned int kMaxCrashesPerInterval = 3;
715static const unsigned int kCrashesInterval = 120;
716
[email protected]2dec8ec2013-02-07 19:20:34717void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
[email protected]47214d882012-02-29 06:28:48718 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]2dec8ec2013-02-07 19:20:34719 std::map<base::FilePath, std::vector<base::Time> >::iterator i =
[email protected]47214d882012-02-29 06:28:48720 crash_times_.find(path);
721 if (i == crash_times_.end()) {
722 crash_times_[path] = std::vector<base::Time>();
723 i = crash_times_.find(path);
724 }
725 if (i->second.size() == kMaxCrashesPerInterval) {
726 i->second.erase(i->second.begin());
727 }
728 base::Time time = base::Time::Now();
729 i->second.push_back(time);
730}
731
[email protected]2dec8ec2013-02-07 19:20:34732bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
[email protected]47214d882012-02-29 06:28:48733 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]2dec8ec2013-02-07 19:20:34734 std::map<base::FilePath, std::vector<base::Time> >::const_iterator i =
[email protected]47214d882012-02-29 06:28:48735 crash_times_.find(path);
736 if (i == crash_times_.end()) {
737 return false;
738 }
739 if (i->second.size() != kMaxCrashesPerInterval) {
740 return false;
741 }
742 base::TimeDelta delta = base::Time::Now() - i->second[0];
[email protected]d8c70062013-04-24 00:22:34743 return delta.InSeconds() <= kCrashesInterval;
[email protected]47214d882012-02-29 06:28:48744}
745
[email protected]e67385f2011-12-21 06:00:56746void PluginServiceImpl::RefreshPlugins() {
[email protected]3a5180ae2011-12-21 02:39:38747 plugin_list_->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14748}
749
[email protected]2dec8ec2013-02-07 19:20:34750void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38751 plugin_list_->AddExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14752}
753
[email protected]2dec8ec2013-02-07 19:20:34754void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
[email protected]c6f3dea2012-01-14 02:23:11755 plugin_list_->AddExtraPluginDir(path);
756}
757
[email protected]2dec8ec2013-02-07 19:20:34758void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38759 plugin_list_->RemoveExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14760}
761
[email protected]2dec8ec2013-02-07 19:20:34762void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38763 plugin_list_->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14764}
765
[email protected]e67385f2011-12-21 06:00:56766void PluginServiceImpl::SetPluginListForTesting(
[email protected]ee066172011-11-10 23:20:05767 webkit::npapi::PluginList* plugin_list) {
768 plugin_list_ = plugin_list;
769}
770
[email protected]5904cb42012-09-24 15:05:20771#if defined(OS_MACOSX)
772void PluginServiceImpl::AppActivated() {
773 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]07b71c82013-01-08 19:07:31774 base::Bind(&NotifyPluginsOfActivation));
[email protected]5904cb42012-09-24 15:05:20775}
776#endif
777
[email protected]e67385f2011-12-21 06:00:56778void PluginServiceImpl::RegisterInternalPlugin(
[email protected]c6f3dea2012-01-14 02:23:11779 const webkit::WebPluginInfo& info,
780 bool add_at_beginning) {
781 plugin_list_->RegisterInternalPlugin(info, add_at_beginning);
[email protected]f520b5b2011-11-08 02:42:14782}
783
[email protected]57aece22012-10-10 22:10:27784void PluginServiceImpl::GetInternalPlugins(
785 std::vector<webkit::WebPluginInfo>* plugins) {
786 plugin_list_->GetInternalPlugins(plugins);
787}
788
[email protected]e67385f2011-12-21 06:00:56789webkit::npapi::PluginList* PluginServiceImpl::GetPluginList() {
[email protected]3a5180ae2011-12-21 02:39:38790 return plugin_list_;
[email protected]f520b5b2011-11-08 02:42:14791}
[email protected]130757672012-10-24 00:26:19792
793} // namespace content