blob: 64efebc1ec3dae955405bffba23033fb6d2a760c [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]2fccd3f2013-07-18 00:10:5211#include "base/message_loop/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]29e2fb42013-07-19 01:13:4723#include "content/common/plugin_list.h"
[email protected]38b592902011-04-16 02:08:4224#include "content/common/view_messages.h"
[email protected]c38831a12011-10-28 12:44:4925#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4426#include "content/public/browser/content_browser_client.h"
[email protected]31f376c2012-03-13 16:43:0927#include "content/public/browser/plugin_service_filter.h"
[email protected]ce967862012-02-09 22:47:0528#include "content/public/browser/resource_context.h"
[email protected]c08950d22011-10-13 22:20:2929#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1230#include "content/public/common/process_type.h"
[email protected]d7bd3e52013-07-21 04:29:2031#include "content/public/common/webplugininfo.h"
[email protected]fd8d8d6c2013-02-28 02:48:3332#include "webkit/plugins/plugin_constants.h"
[email protected]191eb3f72010-12-21 06:27:5033
[email protected]3b91edbe2012-09-27 22:49:2334#if defined(OS_WIN)
[email protected]29e2fb42013-07-19 01:13:4735#include "content/common/plugin_constants_win.h"
[email protected]9a60ccb2013-07-19 22:23:3636#include "ui/base/win/hwnd_util.h"
[email protected]3b91edbe2012-09-27 22:49:2337#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.
[email protected]6d057a0c2013-07-09 21:12:0769
70 // Can't load the plugins on the utility thread when in single process mode
[email protected]10212452013-07-16 20:10:5571 // since that requires GTK which can only be used on the main thread.
[email protected]6d057a0c2013-07-09 21:12:0772 if (RenderProcessHost::run_renderer_in_process())
73 return true;
74
[email protected]9a60ccb2013-07-19 22:23:3675 return !PluginService::GetInstance()->NPAPIPluginsSupported();
[email protected]1b517202012-12-19 17:16:1076#endif
77}
78
[email protected]49125952011-09-27 18:05:1579// Callback set on the PluginList to assert that plugin loading happens on the
80// correct thread.
[email protected]1b517202012-12-19 17:16:1081void WillLoadPluginsCallback(
[email protected]a33fa9d2012-05-16 14:47:4982 base::SequencedWorkerPool::SequenceToken token) {
[email protected]1b517202012-12-19 17:16:1083 if (LoadPluginListInProcess()) {
84 CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
85 token));
86 } else {
87 CHECK(false) << "Plugin loading should happen out-of-process.";
88 }
[email protected]a79912252012-05-16 11:52:1989}
[email protected]d33e7cc2011-09-23 01:43:5690
[email protected]a96ec6a2009-11-04 17:27:0891#if defined(OS_MACOSX)
[email protected]07b71c82013-01-08 19:07:3192void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0894
[email protected]4967f792012-01-20 22:14:4095 for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
96 iter->OnAppActivation();
[email protected]a96ec6a2009-11-04 17:27:0897}
[email protected]3b48dbc2012-01-06 16:34:1798#endif
[email protected]45a22e62011-10-12 09:48:0299
[email protected]07b71c82013-01-08 19:07:31100#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]2dec8ec2013-02-07 19:20:34101void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
[email protected]07b71c82013-01-08 19:07:31102 if (error) {
[email protected]634d23d2011-01-19 10:38:19103 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
104 // stopping the watcher would be enough. Or possibly restart it.
105 NOTREACHED();
[email protected]07b71c82013-01-08 19:07:31106 return;
[email protected]634d23d2011-01-19 10:38:19107 }
[email protected]07b71c82013-01-08 19:07:31108 VLOG(1) << "Watched path changed: " << path.value();
109 // Make the plugin list update itself
[email protected]29e2fb42013-07-19 01:13:47110 PluginList::Singleton()->RefreshPlugins();
[email protected]07b71c82013-01-08 19:07:31111 BrowserThread::PostTask(
112 BrowserThread::UI, FROM_HERE,
113 base::Bind(&PluginService::PurgePluginListCache,
114 static_cast<BrowserContext*>(NULL), false));
115}
[email protected]634d23d2011-01-19 10:38:19116#endif
117
[email protected]07b71c82013-01-08 19:07:31118} // namespace
119
[email protected]3a5180ae2011-12-21 02:39:38120// static
121PluginService* PluginService::GetInstance() {
[email protected]e67385f2011-12-21 06:00:56122 return PluginServiceImpl::GetInstance();
[email protected]3a5180ae2011-12-21 02:39:38123}
124
125void PluginService::PurgePluginListCache(BrowserContext* browser_context,
126 bool reload_pages) {
127 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
128 !it.IsAtEnd(); it.Advance()) {
129 RenderProcessHost* host = it.GetCurrentValue();
130 if (!browser_context || host->GetBrowserContext() == browser_context)
131 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
132 }
133}
134
initial.commit09911bf2008-07-26 23:55:29135// static
[email protected]e67385f2011-12-21 06:00:56136PluginServiceImpl* PluginServiceImpl::GetInstance() {
137 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29138}
139
[email protected]e67385f2011-12-21 06:00:56140PluginServiceImpl::PluginServiceImpl()
[email protected]8f3372122013-07-18 04:34:14141 : filter_(NULL) {
[email protected]fd8d8d6c2013-02-28 02:48:33142 // Collect the total number of browser processes (which create
143 // PluginServiceImpl objects, to be precise). The number is used to normalize
144 // the number of processes which start at least one NPAPI/PPAPI Flash process.
145 static bool counted = false;
146 if (!counted) {
147 counted = true;
148 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES,
149 FLASH_USAGE_ENUM_COUNT);
150 }
[email protected]ee066172011-11-10 23:20:05151}
152
[email protected]e67385f2011-12-21 06:00:56153PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05154#if defined(OS_WIN)
155 // Release the events since they're owned by RegKey, not WaitableEvent.
156 hkcu_watcher_.StopWatching();
157 hklm_watcher_.StopWatching();
[email protected]59383c782013-04-17 16:43:27158 if (hkcu_event_)
[email protected]ee066172011-11-10 23:20:05159 hkcu_event_->Release();
[email protected]59383c782013-04-17 16:43:27160 if (hklm_event_)
[email protected]ee066172011-11-10 23:20:05161 hklm_event_->Release();
162#endif
163 // Make sure no plugin channel requests have been leaked.
164 DCHECK(pending_plugin_clients_.empty());
165}
166
[email protected]e67385f2011-12-21 06:00:56167void PluginServiceImpl::Init() {
[email protected]a33fa9d2012-05-16 14:47:49168 plugin_list_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken();
[email protected]29e2fb42013-07-19 01:13:47169 PluginList::Singleton()->set_will_load_plugins_callback(
[email protected]1b517202012-12-19 17:16:10170 base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
[email protected]49125952011-09-27 18:05:15171
[email protected]4e0616e2010-05-28 14:55:53172 RegisterPepperPlugins();
173
[email protected]0f7d449e2013-01-23 15:12:35174 // The --site-per-process flag enables an out-of-process iframes
175 // prototype, which uses WebView for rendering. We need to register the MIME
176 // type we use with the plugin, so the renderer can instantiate it.
177 const CommandLine* command_line = CommandLine::ForCurrentProcess();
178 if (command_line->HasSwitch(switches::kSitePerProcess)) {
[email protected]d7bd3e52013-07-21 04:29:20179 WebPluginInfo webview_plugin(
[email protected]0f7d449e2013-01-23 15:12:35180 ASCIIToUTF16("WebView Tag"),
[email protected]007b3f82013-04-09 08:46:45181 base::FilePath(),
[email protected]0f7d449e2013-01-23 15:12:35182 ASCIIToUTF16("1.2.3.4"),
183 ASCIIToUTF16("Browser Plugin."));
[email protected]d7bd3e52013-07-21 04:29:20184 webview_plugin.type = WebPluginInfo::PLUGIN_TYPE_NPAPI;
185 WebPluginMimeType webview_plugin_mime_type;
[email protected]0f7d449e2013-01-23 15:12:35186 webview_plugin_mime_type.mime_type = "application/browser-plugin";
187 webview_plugin_mime_type.file_extensions.push_back("*");
188 webview_plugin.mime_types.push_back(webview_plugin_mime_type);
189 RegisterInternalPlugin(webview_plugin, true);
190 }
191
[email protected]9a1c4262010-06-29 21:50:27192 // Load any specified on the command line as well.
[email protected]2dec8ec2013-02-07 19:20:34193 base::FilePath path =
194 command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28195 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14196 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27197 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
198 if (!path.empty())
[email protected]29e2fb42013-07-19 01:13:47199 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]e87ce862013-06-12 17:30:48200
201 if (command_line->HasSwitch(switches::kDisablePluginsDiscovery))
[email protected]29e2fb42013-07-19 01:13:47202 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]dfba8762011-09-02 12:49:54203}
204
[email protected]e67385f2011-12-21 06:00:56205void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19206 // Start watching for changes in the plugin list. This means watching
207 // for changes in the Windows registry keys and on both Windows and POSIX
208 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27209#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19210 if (hkcu_key_.Create(HKEY_CURRENT_USER,
[email protected]29e2fb42013-07-19 01:13:47211 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19212 KEY_NOTIFY) == ERROR_SUCCESS) {
213 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
214 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
[email protected]329be052013-02-04 18:14:28215 base::WaitableEventWatcher::EventCallback callback =
216 base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
217 base::Unretained(this));
218 hkcu_watcher_.StartWatching(hkcu_event_.get(), callback);
[email protected]86ec4f6e2011-04-20 16:21:19219 }
[email protected]b547fd42009-04-23 23:16:27220 }
[email protected]86ec4f6e2011-04-20 16:21:19221 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
[email protected]29e2fb42013-07-19 01:13:47222 kRegistryMozillaPlugins,
[email protected]86ec4f6e2011-04-20 16:21:19223 KEY_NOTIFY) == ERROR_SUCCESS) {
224 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
225 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
[email protected]329be052013-02-04 18:14:28226 base::WaitableEventWatcher::EventCallback callback =
227 base::Bind(&PluginServiceImpl::OnWaitableEventSignaled,
228 base::Unretained(this));
229 hklm_watcher_.StartWatching(hklm_event_.get(), callback);
[email protected]86ec4f6e2011-04-20 16:21:19230 }
[email protected]b547fd42009-04-23 23:16:27231 }
[email protected]a33fa9d2012-05-16 14:47:49232#endif
[email protected]52348b22012-11-07 10:19:34233#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19234// On ChromeOS the user can't install plugins anyway and on Windows all
235// important plugins register themselves in the registry so no need to do that.
[email protected]07b71c82013-01-08 19:07:31236
[email protected]634d23d2011-01-19 10:38:19237 // Get the list of all paths for registering the FilePathWatchers
238 // that will track and if needed reload the list of plugins on runtime.
[email protected]2dec8ec2013-02-07 19:20:34239 std::vector<base::FilePath> plugin_dirs;
[email protected]29e2fb42013-07-19 01:13:47240 PluginList::Singleton()->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57241
[email protected]634d23d2011-01-19 10:38:19242 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19243 // FilePathWatcher can not handle non-absolute paths under windows.
244 // We don't watch for file changes in windows now but if this should ever
245 // be extended to Windows these lines might save some time of debugging.
246#if defined(OS_WIN)
247 if (!plugin_dirs[i].IsAbsolute())
248 continue;
249#endif
[email protected]493c8002011-04-14 16:56:01250 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19251 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
252 BrowserThread::PostTask(
253 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56254 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]07b71c82013-01-08 19:07:31255 plugin_dirs[i]));
[email protected]634d23d2011-01-19 10:38:19256 file_watchers_.push_back(watcher);
257 }
258#endif
initial.commit09911bf2008-07-26 23:55:29259}
260
[email protected]e67385f2011-12-21 06:00:56261PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34262 const base::FilePath& plugin_path) {
[email protected]4967f792012-01-20 22:14:40263 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
264 if (iter->info().path == plugin_path)
265 return *iter;
[email protected]a436d922009-02-13 23:16:42266 }
267
initial.commit09911bf2008-07-26 23:55:29268 return NULL;
269}
270
[email protected]e67385f2011-12-21 06:00:56271PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]2dec8ec2013-02-07 19:20:34272 const base::FilePath& plugin_path,
273 const base::FilePath& profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40274 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
[email protected]dd9a0952012-05-31 20:11:31275 if (iter->plugin_path() == plugin_path &&
276 iter->profile_data_directory() == profile_data_directory) {
[email protected]4967f792012-01-20 22:14:40277 return *iter;
[email protected]dd9a0952012-05-31 20:11:31278 }
[email protected]a08ebea2011-02-13 17:50:20279 }
[email protected]a08ebea2011-02-13 17:50:20280 return NULL;
281}
282
[email protected]e67385f2011-12-21 06:00:56283PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]2dec8ec2013-02-07 19:20:34284 const base::FilePath& broker_path) {
[email protected]4967f792012-01-20 22:14:40285 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
286 if (iter->plugin_path() == broker_path)
287 return *iter;
[email protected]eb415bf0e2011-04-14 02:45:42288 }
289
290 return NULL;
291}
292
[email protected]e67385f2011-12-21 06:00:56293PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54294 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34295 const base::FilePath& plugin_path) {
[email protected]a08ebea2011-02-13 17:50:20296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
297
[email protected]6be31d202013-02-01 18:20:54298 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
299 return NULL;
300
[email protected]a08ebea2011-02-13 17:50:20301 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29302 if (plugin_host)
303 return plugin_host;
304
[email protected]d7bd3e52013-07-21 04:29:20305 WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43306 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10307 return NULL;
308 }
309
[email protected]fd8d8d6c2013-02-28 02:48:33310 // Record when NPAPI Flash process is started for the first time.
311 static bool counted = false;
312 if (!counted && UTF16ToUTF8(info.name) == kFlashPluginName) {
313 counted = true;
314 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
315 START_NPAPI_FLASH_AT_LEAST_ONCE,
316 FLASH_USAGE_ENUM_COUNT);
317 }
318
initial.commit09911bf2008-07-26 23:55:29319 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40320 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
[email protected]99907362012-01-11 05:41:40321 if (!new_host->Init(info)) {
[email protected]a08ebea2011-02-13 17:50:20322 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29323 return NULL;
324 }
[email protected]8b8a554d2010-11-18 13:26:40325 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29326}
327
[email protected]e67385f2011-12-21 06:00:56328PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54329 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34330 const base::FilePath& plugin_path,
331 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14332 PpapiPluginProcessHost::PluginClient* client) {
[email protected]a08ebea2011-02-13 17:50:20333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
334
[email protected]6be31d202013-02-01 18:20:54335 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
336 return NULL;
337
[email protected]dd9a0952012-05-31 20:11:31338 PpapiPluginProcessHost* plugin_host =
339 FindPpapiPluginProcess(plugin_path, profile_data_directory);
[email protected]a08ebea2011-02-13 17:50:20340 if (plugin_host)
341 return plugin_host;
342
[email protected]eb415bf0e2011-04-14 02:45:42343 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19344 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]a08ebea2011-02-13 17:50:20345 if (!info)
346 return NULL;
347
[email protected]fd8d8d6c2013-02-28 02:48:33348 // Record when PPAPI Flash process is started for the first time.
349 static bool counted = false;
350 if (!counted && info->name == kFlashPluginName) {
351 counted = true;
352 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
353 START_PPAPI_FLASH_AT_LEAST_ONCE,
354 FLASH_USAGE_ENUM_COUNT);
355 }
356
[email protected]a08ebea2011-02-13 17:50:20357 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14358 return PpapiPluginProcessHost::CreatePluginHost(
[email protected]dd9a0952012-05-31 20:11:31359 *info, profile_data_directory,
[email protected]df02aca2012-02-09 21:03:20360 client->GetResourceContext()->GetHostResolver());
[email protected]a08ebea2011-02-13 17:50:20361}
362
[email protected]e67385f2011-12-21 06:00:56363PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]6be31d202013-02-01 18:20:54364 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34365 const base::FilePath& plugin_path) {
[email protected]eb415bf0e2011-04-14 02:45:42366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
367
[email protected]6be31d202013-02-01 18:20:54368 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
369 return NULL;
370
[email protected]a50432d2011-09-30 16:32:14371 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42372 if (plugin_host)
373 return plugin_host;
374
375 // Validate that the plugin is actually registered.
[email protected]130757672012-10-24 00:26:19376 PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42377 if (!info)
378 return NULL;
379
380 // TODO(ddorwin): Uncomment once out of process is supported.
381 // DCHECK(info->is_out_of_process);
382
383 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14384 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42385}
386
[email protected]e67385f2011-12-21 06:00:56387void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17388 int render_process_id,
389 int render_view_id,
[email protected]610c0892009-09-08 19:46:18390 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54391 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18392 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39393 PluginProcessHost::Client* client) {
[email protected]76b70f92011-11-21 19:31:14394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4befe7592011-09-14 22:49:09395 DCHECK(!ContainsKey(pending_plugin_clients_, client));
396 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43397
398 // Make sure plugins are loaded if necessary.
[email protected]209f2ae2012-03-13 01:28:08399 PluginServiceFilterParams params = {
[email protected]88ca4912011-10-12 14:00:43400 render_process_id,
401 render_view_id,
402 page_url,
[email protected]df02aca2012-02-09 21:03:20403 client->GetResourceContext()
[email protected]88ca4912011-10-12 14:00:43404 };
[email protected]e67385f2011-12-21 06:00:56405 GetPlugins(base::Bind(
406 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
407 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26408}
409
[email protected]e67385f2011-12-21 06:00:56410void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]6be31d202013-02-01 18:20:54411 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34412 const base::FilePath& plugin_path,
413 const base::FilePath& profile_data_directory,
[email protected]a50432d2011-09-30 16:32:14414 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09415 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
[email protected]6be31d202013-02-01 18:20:54416 render_process_id, plugin_path, profile_data_directory, client);
[email protected]1bf0fb22012-04-12 21:44:16417 if (plugin_host) {
[email protected]a08ebea2011-02-13 17:50:20418 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16419 } else {
420 // Send error.
[email protected]108fd342013-01-04 20:46:54421 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16422 }
[email protected]a08ebea2011-02-13 17:50:20423}
424
[email protected]e67385f2011-12-21 06:00:56425void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]6be31d202013-02-01 18:20:54426 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34427 const base::FilePath& path,
[email protected]a50432d2011-09-30 16:32:14428 PpapiPluginProcessHost::BrokerClient* client) {
[email protected]6be31d202013-02-01 18:20:54429 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
430 render_process_id, path);
[email protected]1bf0fb22012-04-12 21:44:16431 if (plugin_host) {
[email protected]a50432d2011-09-30 16:32:14432 plugin_host->OpenChannelToPlugin(client);
[email protected]1bf0fb22012-04-12 21:44:16433 } else {
434 // Send error.
[email protected]108fd342013-01-04 20:46:54435 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
[email protected]1bf0fb22012-04-12 21:44:16436 }
[email protected]eb415bf0e2011-04-14 02:45:42437}
438
[email protected]e67385f2011-12-21 06:00:56439void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09440 PluginProcessHost::Client* client) {
441 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
442 DCHECK(ContainsKey(pending_plugin_clients_, client));
443 pending_plugin_clients_.erase(client);
444}
445
[email protected]e67385f2011-12-21 06:00:56446void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]209f2ae2012-03-13 01:28:08447 const PluginServiceFilterParams& params,
[email protected]88ca4912011-10-12 14:00:43448 const GURL& url,
449 const std::string& mime_type,
450 PluginProcessHost::Client* client,
[email protected]d7bd3e52013-07-21 04:29:20451 const std::vector<WebPluginInfo>&) {
[email protected]88ca4912011-10-12 14:00:43452 GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
453 params.render_view_id, url, params.page_url, mime_type, client,
454 params.resource_context);
455}
456
[email protected]e67385f2011-12-21 06:00:56457void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17458 int render_process_id,
459 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26460 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54461 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26462 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59463 PluginProcessHost::Client* client,
[email protected]130757672012-10-24 00:26:19464 ResourceContext* resource_context) {
[email protected]d7bd3e52013-07-21 04:29:20465 WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54466 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27467 bool found = GetPluginInfo(
[email protected]df02aca2012-02-09 21:03:20468 render_process_id, render_view_id, resource_context,
[email protected]dfba8762011-09-02 12:49:54469 url, page_url, mime_type, allow_wildcard,
470 NULL, &info, NULL);
[email protected]2dec8ec2013-02-07 19:20:34471 base::FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28472 if (found)
[email protected]dfba8762011-09-02 12:49:54473 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26474
475 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56476 BrowserThread::PostTask(
477 BrowserThread::IO, FROM_HERE,
478 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]6be31d202013-02-01 18:20:54479 base::Unretained(this),
480 render_process_id,
481 plugin_path,
482 client));
[email protected]6fdd4182010-10-14 23:59:26483}
484
[email protected]e67385f2011-12-21 06:00:56485void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6be31d202013-02-01 18:20:54486 int render_process_id,
[email protected]2dec8ec2013-02-07 19:20:34487 const base::FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39488 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52489 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08490
[email protected]4befe7592011-09-14 22:49:09491 // Make sure it hasn't been canceled yet.
492 if (!ContainsKey(pending_plugin_clients_, client))
493 return;
494 pending_plugin_clients_.erase(client);
495
[email protected]6be31d202013-02-01 18:20:54496 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
497 render_process_id, plugin_path);
[email protected]4befe7592011-09-14 22:49:09498 if (plugin_host) {
499 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39500 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09501 } else {
[email protected]46b69e42010-11-02 12:26:39502 client->OnError();
[email protected]4befe7592011-09-14 22:49:09503 }
initial.commit09911bf2008-07-26 23:55:29504}
505
[email protected]e67385f2011-12-21 06:00:56506bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42507 const GURL& url,
508 const std::string& mime_type,
509 bool allow_wildcard,
[email protected]d7bd3e52013-07-21 04:29:20510 std::vector<WebPluginInfo>* plugins,
[email protected]51b63f62011-10-05 18:55:42511 std::vector<std::string>* actual_mime_types) {
512 bool use_stale = false;
[email protected]29e2fb42013-07-19 01:13:47513 PluginList::Singleton()->GetPluginInfoArray(
[email protected]9a60ccb2013-07-19 22:23:36514 url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(),
515 plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42516 return use_stale;
517}
518
[email protected]e67385f2011-12-21 06:00:56519bool PluginServiceImpl::GetPluginInfo(int render_process_id,
520 int render_view_id,
[email protected]130757672012-10-24 00:26:19521 ResourceContext* context,
[email protected]e67385f2011-12-21 06:00:56522 const GURL& url,
523 const GURL& page_url,
524 const std::string& mime_type,
525 bool allow_wildcard,
526 bool* is_stale,
[email protected]d7bd3e52013-07-21 04:29:20527 WebPluginInfo* info,
[email protected]e67385f2011-12-21 06:00:56528 std::string* actual_mime_type) {
[email protected]d7bd3e52013-07-21 04:29:20529 std::vector<WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28530 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43531 bool stale = GetPluginInfoArray(
532 url, mime_type, allow_wildcard, &plugins, &mime_types);
533 if (is_stale)
534 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54535
[email protected]68598072011-07-29 08:21:28536 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]05f511282013-02-05 15:02:50537 if (!filter_ || filter_->IsPluginAvailable(render_process_id,
538 render_view_id,
539 context,
540 url,
541 page_url,
542 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28543 *info = plugins[i];
544 if (actual_mime_type)
545 *actual_mime_type = mime_types[i];
546 return true;
547 }
548 }
549 return false;
[email protected]6fdd4182010-10-14 23:59:26550}
551
[email protected]2dec8ec2013-02-07 19:20:34552bool PluginServiceImpl::GetPluginInfoByPath(const base::FilePath& plugin_path,
[email protected]d7bd3e52013-07-21 04:29:20553 WebPluginInfo* info) {
554 std::vector<WebPluginInfo> plugins;
[email protected]29e2fb42013-07-19 01:13:47555 PluginList::Singleton()->GetPluginsNoRefresh(&plugins);
[email protected]88ca4912011-10-12 14:00:43556
[email protected]d7bd3e52013-07-21 04:29:20557 for (std::vector<WebPluginInfo>::iterator it = plugins.begin();
[email protected]88ca4912011-10-12 14:00:43558 it != plugins.end();
559 ++it) {
560 if (it->path == plugin_path) {
561 *info = *it;
562 return true;
563 }
564 }
565
566 return false;
567}
568
[email protected]2dec8ec2013-02-07 19:20:34569string16 PluginServiceImpl::GetPluginDisplayNameByPath(
570 const base::FilePath& path) {
[email protected]8be45842012-04-13 19:49:29571 string16 plugin_name = path.LossyDisplayName();
[email protected]d7bd3e52013-07-21 04:29:20572 WebPluginInfo info;
[email protected]8be45842012-04-13 19:49:29573 if (PluginService::GetInstance()->GetPluginInfoByPath(path, &info) &&
574 !info.name.empty()) {
575 plugin_name = info.name;
576#if defined(OS_MACOSX)
577 // Many plugins on the Mac have .plugin in the actual name, which looks
578 // terrible, so look for that and strip it off if present.
579 const std::string kPluginExtension = ".plugin";
580 if (EndsWith(plugin_name, ASCIIToUTF16(kPluginExtension), true))
581 plugin_name.erase(plugin_name.length() - kPluginExtension.length());
582#endif // OS_MACOSX
583 }
584 return plugin_name;
585}
586
[email protected]e67385f2011-12-21 06:00:56587void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
[email protected]49125952011-09-27 18:05:15588 scoped_refptr<base::MessageLoopProxy> target_loop(
[email protected]dd32b1272013-05-04 14:17:11589 base::MessageLoop::current()->message_loop_proxy());
[email protected]49125952011-09-27 18:05:15590
[email protected]1b517202012-12-19 17:16:10591 if (LoadPluginListInProcess()) {
592 BrowserThread::GetBlockingPool()->
593 PostSequencedWorkerTaskWithShutdownBehavior(
594 plugin_list_token_,
595 FROM_HERE,
596 base::Bind(&PluginServiceImpl::GetPluginsInternal,
597 base::Unretained(this),
598 target_loop, callback),
599 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
600 return;
601 }
602#if defined(OS_POSIX)
[email protected]d7bd3e52013-07-21 04:29:20603 std::vector<WebPluginInfo> cached_plugins;
[email protected]29e2fb42013-07-19 01:13:47604 if (PluginList::Singleton()->GetPluginsNoRefresh(&cached_plugins)) {
[email protected]49125952011-09-27 18:05:15605 // Can't assume the caller is reentrant.
606 target_loop->PostTask(FROM_HERE,
[email protected]00b25432012-04-07 04:21:37607 base::Bind(callback, cached_plugins));
[email protected]49125952011-09-27 18:05:15608 } else {
[email protected]4bb85b92011-11-05 02:53:29609 // If we switch back to loading plugins in process, then we need to make
610 // sure g_thread_init() gets called since plugins may call glib at load.
[email protected]fc72bb12013-06-02 21:13:46611 if (!plugin_loader_.get())
[email protected]d4af1e72011-10-21 17:45:43612 plugin_loader_ = new PluginLoaderPosix;
[email protected]49125952011-09-27 18:05:15613 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]d4af1e72011-10-21 17:45:43614 base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
615 target_loop, callback));
[email protected]49125952011-09-27 18:05:15616 }
[email protected]a33fa9d2012-05-16 14:47:49617#else
[email protected]1b517202012-12-19 17:16:10618 NOTREACHED();
[email protected]49125952011-09-27 18:05:15619#endif
[email protected]d33e7cc2011-09-23 01:43:56620}
621
[email protected]e67385f2011-12-21 06:00:56622void PluginServiceImpl::GetPluginsInternal(
[email protected]d33e7cc2011-09-23 01:43:56623 base::MessageLoopProxy* target_loop,
624 const PluginService::GetPluginsCallback& callback) {
[email protected]a33fa9d2012-05-16 14:47:49625 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
626 plugin_list_token_));
[email protected]d33e7cc2011-09-23 01:43:56627
[email protected]d7bd3e52013-07-21 04:29:20628 std::vector<WebPluginInfo> plugins;
[email protected]9a60ccb2013-07-19 22:23:36629 PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported());
[email protected]d33e7cc2011-09-23 01:43:56630
631 target_loop->PostTask(FROM_HERE,
[email protected]00b25432012-04-07 04:21:37632 base::Bind(callback, plugins));
[email protected]dfba8762011-09-02 12:49:54633}
634
[email protected]e67385f2011-12-21 06:00:56635void PluginServiceImpl::OnWaitableEventSignaled(
[email protected]580522632009-08-17 21:55:55636 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27637#if defined(OS_WIN)
[email protected]59383c782013-04-17 16:43:27638 if (waitable_event == hkcu_event_) {
[email protected]b547fd42009-04-23 23:16:27639 hkcu_key_.StartWatching();
640 } else {
641 hklm_key_.StartWatching();
642 }
643
[email protected]29e2fb42013-07-19 01:13:47644 PluginList::Singleton()->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02645 PurgePluginListCache(NULL, false);
[email protected]634d23d2011-01-19 10:38:19646#else
647 // This event should only get signaled on a Windows machine.
648 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53649#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27650}
[email protected]894bb502009-05-21 22:39:57651
[email protected]e67385f2011-12-21 06:00:56652void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]84396dbc2011-04-14 06:33:42653 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
[email protected]a08ebea2011-02-13 17:50:20654 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
655 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]c6f3dea2012-01-14 02:23:11656 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
[email protected]4e0616e2010-05-28 14:55:53657 }
658}
[email protected]634d23d2011-01-19 10:38:19659
[email protected]eb415bf0e2011-04-14 02:45:42660// There should generally be very few plugins so a brute-force search is fine.
[email protected]130757672012-10-24 00:26:19661PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]2dec8ec2013-02-07 19:20:34662 const base::FilePath& plugin_path) {
[email protected]130757672012-10-24 00:26:19663 PepperPluginInfo* info = NULL;
[email protected]eb415bf0e2011-04-14 02:45:42664 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
[email protected]6b14feb2011-08-16 11:22:56665 if (ppapi_plugins_[i].path == plugin_path) {
666 info = &ppapi_plugins_[i];
667 break;
668 }
[email protected]eb415bf0e2011-04-14 02:45:42669 }
[email protected]076117592011-08-17 03:16:41670 if (info)
671 return info;
672 // We did not find the plugin in our list. But wait! the plugin can also
673 // be a latecomer, as it happens with pepper flash. This information
674 // can be obtained from the PluginList singleton and we can use it to
675 // construct it and add it to the list. This same deal needs to be done
676 // in the renderer side in PepperPluginRegistry.
[email protected]d7bd3e52013-07-21 04:29:20677 WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43678 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41679 return NULL;
[email protected]130757672012-10-24 00:26:19680 PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41681 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
682 return NULL;
683 ppapi_plugins_.push_back(new_pepper_info);
684 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42685}
686
[email protected]52348b22012-11-07 10:19:34687#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
[email protected]634d23d2011-01-19 10:38:19688// static
[email protected]07b71c82013-01-08 19:07:31689void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
[email protected]2dec8ec2013-02-07 19:20:34690 const base::FilePath& path) {
[email protected]07b71c82013-01-08 19:07:31691 bool result = watcher->Watch(path, false,
692 base::Bind(&NotifyPluginDirChanged));
[email protected]634d23d2011-01-19 10:38:19693 DCHECK(result);
694}
695#endif
[email protected]f520b5b2011-11-08 02:42:14696
[email protected]130757672012-10-24 00:26:19697void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38698 filter_ = filter;
699}
700
[email protected]130757672012-10-24 00:26:19701PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38702 return filter_;
703}
704
[email protected]2dec8ec2013-02-07 19:20:34705void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
[email protected]b6a2f8de2012-01-31 17:28:49706 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
707 BrowserThread::PostTask(
708 BrowserThread::IO, FROM_HERE,
709 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
710 base::Unretained(this), plugin_path));
711 return;
712 }
713
714 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
715 if (plugin)
716 plugin->ForceShutdown();
717}
718
[email protected]47214d882012-02-29 06:28:48719static const unsigned int kMaxCrashesPerInterval = 3;
720static const unsigned int kCrashesInterval = 120;
721
[email protected]2dec8ec2013-02-07 19:20:34722void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
[email protected]47214d882012-02-29 06:28:48723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]2dec8ec2013-02-07 19:20:34724 std::map<base::FilePath, std::vector<base::Time> >::iterator i =
[email protected]47214d882012-02-29 06:28:48725 crash_times_.find(path);
726 if (i == crash_times_.end()) {
727 crash_times_[path] = std::vector<base::Time>();
728 i = crash_times_.find(path);
729 }
730 if (i->second.size() == kMaxCrashesPerInterval) {
731 i->second.erase(i->second.begin());
732 }
733 base::Time time = base::Time::Now();
734 i->second.push_back(time);
735}
736
[email protected]2dec8ec2013-02-07 19:20:34737bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) {
[email protected]47214d882012-02-29 06:28:48738 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]2dec8ec2013-02-07 19:20:34739 std::map<base::FilePath, std::vector<base::Time> >::const_iterator i =
[email protected]47214d882012-02-29 06:28:48740 crash_times_.find(path);
741 if (i == crash_times_.end()) {
742 return false;
743 }
744 if (i->second.size() != kMaxCrashesPerInterval) {
745 return false;
746 }
747 base::TimeDelta delta = base::Time::Now() - i->second[0];
[email protected]d8c70062013-04-24 00:22:34748 return delta.InSeconds() <= kCrashesInterval;
[email protected]47214d882012-02-29 06:28:48749}
750
[email protected]e67385f2011-12-21 06:00:56751void PluginServiceImpl::RefreshPlugins() {
[email protected]29e2fb42013-07-19 01:13:47752 PluginList::Singleton()->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14753}
754
[email protected]2dec8ec2013-02-07 19:20:34755void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
[email protected]9a60ccb2013-07-19 22:23:36756 if (!NPAPIPluginsSupported()) {
757 // TODO(jam): remove and just have CHECK once we're sure this doesn't get
758 // triggered.
759 DLOG(INFO) << "NPAPI plugins not supported";
760 return;
761 }
[email protected]29e2fb42013-07-19 01:13:47762 PluginList::Singleton()->AddExtraPluginPath(path);
[email protected]c6f3dea2012-01-14 02:23:11763}
764
[email protected]2dec8ec2013-02-07 19:20:34765void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47766 PluginList::Singleton()->RemoveExtraPluginPath(path);
[email protected]8f3372122013-07-18 04:34:14767}
768
769void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47770 PluginList::Singleton()->AddExtraPluginDir(path);
[email protected]8f3372122013-07-18 04:34:14771}
772
773void PluginServiceImpl::RegisterInternalPlugin(
[email protected]d7bd3e52013-07-21 04:29:20774 const WebPluginInfo& info,
[email protected]8f3372122013-07-18 04:34:14775 bool add_at_beginning) {
[email protected]9a60ccb2013-07-19 22:23:36776 if (!NPAPIPluginsSupported() &&
[email protected]d7bd3e52013-07-21 04:29:20777 info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
[email protected]9a60ccb2013-07-19 22:23:36778 DLOG(INFO) << "Don't register NPAPI plugins when they're not supported";
779 return;
780 }
[email protected]29e2fb42013-07-19 01:13:47781 PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
[email protected]f520b5b2011-11-08 02:42:14782}
783
[email protected]2dec8ec2013-02-07 19:20:34784void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
[email protected]29e2fb42013-07-19 01:13:47785 PluginList::Singleton()->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14786}
787
[email protected]8f3372122013-07-18 04:34:14788void PluginServiceImpl::GetInternalPlugins(
[email protected]d7bd3e52013-07-21 04:29:20789 std::vector<WebPluginInfo>* plugins) {
[email protected]29e2fb42013-07-19 01:13:47790 PluginList::Singleton()->GetInternalPlugins(plugins);
[email protected]8f3372122013-07-18 04:34:14791}
792
[email protected]9a60ccb2013-07-19 22:23:36793bool PluginServiceImpl::NPAPIPluginsSupported() {
794#if defined(OS_WIN) || defined(OS_MACOSX) || (defined(OS_LINUX) && !defined(USE_AURA))
795 return true;
796#else
797 return false;
798#endif
799}
800
[email protected]8f3372122013-07-18 04:34:14801void PluginServiceImpl::DisablePluginsDiscoveryForTesting() {
[email protected]29e2fb42013-07-19 01:13:47802 PluginList::Singleton()->DisablePluginsDiscovery();
[email protected]ee066172011-11-10 23:20:05803}
804
[email protected]5904cb42012-09-24 15:05:20805#if defined(OS_MACOSX)
806void PluginServiceImpl::AppActivated() {
807 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]07b71c82013-01-08 19:07:31808 base::Bind(&NotifyPluginsOfActivation));
[email protected]5904cb42012-09-24 15:05:20809}
[email protected]9a60ccb2013-07-19 22:23:36810#elif defined(OS_WIN)
811
812bool GetPluginPropertyFromWindow(
813 HWND window, const wchar_t* plugin_atom_property,
814 base::string16* plugin_property) {
815 ATOM plugin_atom = reinterpret_cast<ATOM>(
816 GetPropW(window, plugin_atom_property));
817 if (plugin_atom != 0) {
818 WCHAR plugin_property_local[MAX_PATH] = {0};
819 GlobalGetAtomNameW(plugin_atom,
820 plugin_property_local,
821 ARRAYSIZE(plugin_property_local));
822 *plugin_property = plugin_property_local;
823 return true;
824 }
825 return false;
826}
827
828bool PluginServiceImpl::GetPluginInfoFromWindow(
829 HWND window,
830 base::string16* plugin_name,
831 base::string16* plugin_version) {
832 if (!IsPluginWindow(window))
833 return false;
834
835 GetPluginPropertyFromWindow(
836 window, kPluginNameAtomProperty, plugin_name);
837 GetPluginPropertyFromWindow(
838 window, kPluginVersionAtomProperty, plugin_version);
839 return true;
840}
841
842bool PluginServiceImpl::IsPluginWindow(HWND window) {
843 return ui::GetClassName(window) == base::string16(kNativeWindowClassName);
844}
[email protected]5904cb42012-09-24 15:05:20845#endif
846
[email protected]130757672012-10-24 00:26:19847} // namespace content