blob: fd1f0bd25797a3faddcc8b99e7a1f81abd43a7d7 [file] [log] [blame]
[email protected]a08ebea2011-02-13 17:50:201// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]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]dfba8762011-09-02 12:49:5410#include "base/file_path.h"
[email protected]d33e7cc2011-09-23 01:43:5611#include "base/message_loop.h"
12#include "base/message_loop_proxy.h"
[email protected]9c49ff02010-01-27 01:20:5513#include "base/path_service.h"
[email protected]d70539de2009-06-24 22:17:0614#include "base/string_util.h"
[email protected]7f070d42011-03-09 20:25:3215#include "base/synchronization/waitable_event.h"
[email protected]34b99632011-01-01 01:01:0616#include "base/threading/thread.h"
[email protected]be1ce6a72010-08-03 14:35:2217#include "base/utf_string_conversions.h"
[email protected]cec1b8d2010-03-24 00:21:3418#include "base/values.h"
[email protected]6be08ae2011-10-18 02:23:2319#include "content/browser/plugin_loader_posix.h"
[email protected]dfba8762011-09-02 12:49:5420#include "content/browser/plugin_service_filter.h"
[email protected]a01efd22011-03-01 00:38:3221#include "content/browser/ppapi_plugin_process_host.h"
[email protected]f3b1a082011-11-18 00:34:3022#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]a0421732011-02-23 03:55:4023#include "content/browser/renderer_host/render_view_host.h"
[email protected]d259a8e2011-05-18 22:31:0924#include "content/browser/resource_context.h"
[email protected]49125952011-09-27 18:05:1525#include "content/browser/utility_process_host.h"
[email protected]cebc3dc2011-04-18 17:15:0026#include "content/common/pepper_plugin_registry.h"
[email protected]105303e2011-03-14 22:16:1027#include "content/common/plugin_messages.h"
[email protected]49125952011-09-27 18:05:1528#include "content/common/utility_messages.h"
[email protected]38b592902011-04-16 02:08:4229#include "content/common/view_messages.h"
[email protected]c38831a12011-10-28 12:44:4930#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4431#include "content/public/browser/content_browser_client.h"
[email protected]c38831a12011-10-28 12:44:4932#include "content/public/browser/notification_service.h"
[email protected]0d6e9bd2011-10-18 04:29:1633#include "content/public/browser/notification_types.h"
[email protected]c08950d22011-10-13 22:20:2934#include "content/public/common/content_switches.h"
[email protected]bd5d6cf2011-12-01 00:39:1235#include "content/public/common/process_type.h"
[email protected]191eb3f72010-12-21 06:27:5036#include "webkit/plugins/npapi/plugin_constants_win.h"
[email protected]d33e7cc2011-09-23 01:43:5637#include "webkit/plugins/npapi/plugin_group.h"
[email protected]191eb3f72010-12-21 06:27:5038#include "webkit/plugins/npapi/plugin_list.h"
[email protected]91d9f3d2011-08-14 05:24:4439#include "webkit/plugins/webplugininfo.h"
[email protected]191eb3f72010-12-21 06:27:5040
[email protected]e60c0232011-11-11 19:56:3541#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
[email protected]493c8002011-04-14 16:56:0142using ::base::files::FilePathWatcher;
43#endif
44
[email protected]631bb742011-11-02 11:29:3945using content::BrowserThread;
[email protected]e67385f2011-12-21 06:00:5646using content::PluginService;
[email protected]dfba8762011-09-02 12:49:5447using content::PluginServiceFilter;
48
[email protected]d33e7cc2011-09-23 01:43:5649namespace {
50
51// Helper function that merely runs the callback with the result. Called on the
52// thread on which the original GetPlugins() call was made.
53static void RunGetPluginsCallback(
54 const PluginService::GetPluginsCallback& callback,
55 const std::vector<webkit::WebPluginInfo>& result) {
56 callback.Run(result);
57}
58
59// A callback for GetPlugins() that then gets the freshly loaded plugin groups
60// and runs the callback for GetPluginGroups().
61static void GetPluginsForGroupsCallback(
62 const PluginService::GetPluginGroupsCallback& callback,
63 const std::vector<webkit::WebPluginInfo>& plugins) {
64 std::vector<webkit::npapi::PluginGroup> groups;
65 webkit::npapi::PluginList::Singleton()->GetPluginGroups(false, &groups);
66 callback.Run(groups);
67}
68
[email protected]49125952011-09-27 18:05:1569// Callback set on the PluginList to assert that plugin loading happens on the
70// correct thread.
71void WillLoadPluginsCallback() {
[email protected]6a0dc7a2011-11-02 14:37:0772#if defined(OS_WIN)
[email protected]88ca4912011-10-12 14:00:4373 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]49125952011-09-27 18:05:1574#else
[email protected]88ca4912011-10-12 14:00:4375 CHECK(false) << "Plugin loading should happen out-of-process.";
[email protected]49125952011-09-27 18:05:1576#endif
77}
78
[email protected]d33e7cc2011-09-23 01:43:5679} // namespace
80
[email protected]a96ec6a2009-11-04 17:27:0881#if defined(OS_MACOSX)
82static void NotifyPluginsOfActivation() {
[email protected]f8b3ef82010-10-11 02:45:5283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]a96ec6a2009-11-04 17:27:0884
[email protected]bd5d6cf2011-12-01 00:39:1285 for (BrowserChildProcessHost::Iterator iter(
86 content::PROCESS_TYPE_PLUGIN);
[email protected]a96ec6a2009-11-04 17:27:0887 !iter.Done(); ++iter) {
88 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
89 plugin->OnAppActivation();
90 }
91}
[email protected]e60c0232011-11-11 19:56:3592#elif defined(OS_POSIX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:1993// Delegate class for monitoring directories.
94class PluginDirWatcherDelegate : public FilePathWatcher::Delegate {
[email protected]7b3ee8b2011-04-01 18:48:1995 virtual void OnFilePathChanged(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:1996 VLOG(1) << "Watched path changed: " << path.value();
97 // Make the plugin list update itself
98 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
[email protected]ee6fcb22011-10-22 01:27:0699 BrowserThread::PostTask(
100 BrowserThread::UI, FROM_HERE,
[email protected]3a5180ae2011-12-21 02:39:38101 base::Bind(&content::PluginService::PurgePluginListCache,
[email protected]ee6fcb22011-10-22 01:27:06102 static_cast<content::BrowserContext*>(NULL), false));
[email protected]634d23d2011-01-19 10:38:19103 }
[email protected]45a22e62011-10-12 09:48:02104
[email protected]7b3ee8b2011-04-01 18:48:19105 virtual void OnFilePathError(const FilePath& path) OVERRIDE {
[email protected]634d23d2011-01-19 10:38:19106 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
107 // stopping the watcher would be enough. Or possibly restart it.
108 NOTREACHED();
109 }
110};
111#endif
112
[email protected]3a5180ae2011-12-21 02:39:38113namespace content {
114// 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
129} // namespace content
130
initial.commit09911bf2008-07-26 23:55:29131// static
[email protected]e67385f2011-12-21 06:00:56132PluginServiceImpl* PluginServiceImpl::GetInstance() {
133 return Singleton<PluginServiceImpl>::get();
initial.commit09911bf2008-07-26 23:55:29134}
135
[email protected]e67385f2011-12-21 06:00:56136PluginServiceImpl::PluginServiceImpl()
[email protected]ee066172011-11-10 23:20:05137 : plugin_list_(NULL),
138 ui_locale_(
[email protected]dfba8762011-09-02 12:49:54139 content::GetContentClient()->browser()->GetApplicationLocale()),
140 filter_(NULL) {
[email protected]ee066172011-11-10 23:20:05141}
142
[email protected]e67385f2011-12-21 06:00:56143PluginServiceImpl::~PluginServiceImpl() {
[email protected]ee066172011-11-10 23:20:05144#if defined(OS_WIN)
145 // Release the events since they're owned by RegKey, not WaitableEvent.
146 hkcu_watcher_.StopWatching();
147 hklm_watcher_.StopWatching();
148 if (hkcu_event_.get())
149 hkcu_event_->Release();
150 if (hklm_event_.get())
151 hklm_event_->Release();
152#endif
153 // Make sure no plugin channel requests have been leaked.
154 DCHECK(pending_plugin_clients_.empty());
155}
156
[email protected]e67385f2011-12-21 06:00:56157void PluginServiceImpl::Init() {
[email protected]ee066172011-11-10 23:20:05158 if (!plugin_list_)
159 plugin_list_ = webkit::npapi::PluginList::Singleton();
160
[email protected]3a5180ae2011-12-21 02:39:38161 plugin_list_->set_will_load_plugins_callback(
[email protected]49125952011-09-27 18:05:15162 base::Bind(&WillLoadPluginsCallback));
163
[email protected]4e0616e2010-05-28 14:55:53164 RegisterPepperPlugins();
165
[email protected]3a5180ae2011-12-21 02:39:38166 content::GetContentClient()->AddNPAPIPlugins(plugin_list_);
[email protected]f520b5b2011-11-08 02:42:14167
[email protected]9a1c4262010-06-29 21:50:27168 // Load any specified on the command line as well.
[email protected]d48f1e0c2009-02-12 20:57:54169 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]c4e52f0d2009-11-06 19:55:16170 FilePath path = command_line->GetSwitchValuePath(switches::kLoadPlugin);
[email protected]7bf795d92010-05-22 00:14:28171 if (!path.empty())
[email protected]f520b5b2011-11-08 02:42:14172 AddExtraPluginPath(path);
[email protected]9a1c4262010-06-29 21:50:27173 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
174 if (!path.empty())
[email protected]3a5180ae2011-12-21 02:39:38175 plugin_list_->AddExtraPluginDir(path);
[email protected]7bf795d92010-05-22 00:14:28176
[email protected]dfba8762011-09-02 12:49:54177#if defined(OS_MACOSX)
178 // We need to know when the browser comes forward so we can bring modal plugin
179 // windows forward too.
180 registrar_.Add(this, content::NOTIFICATION_APP_ACTIVATED,
[email protected]ad50def52011-10-19 23:17:07181 content::NotificationService::AllSources());
[email protected]dfba8762011-09-02 12:49:54182#endif
183}
184
[email protected]e67385f2011-12-21 06:00:56185void PluginServiceImpl::StartWatchingPlugins() {
[email protected]634d23d2011-01-19 10:38:19186 // Start watching for changes in the plugin list. This means watching
187 // for changes in the Windows registry keys and on both Windows and POSIX
188 // watch for changes in the paths that are expected to contain plugins.
[email protected]b547fd42009-04-23 23:16:27189#if defined(OS_WIN)
[email protected]86ec4f6e2011-04-20 16:21:19190 if (hkcu_key_.Create(HKEY_CURRENT_USER,
191 webkit::npapi::kRegistryMozillaPlugins,
192 KEY_NOTIFY) == ERROR_SUCCESS) {
193 if (hkcu_key_.StartWatching() == ERROR_SUCCESS) {
194 hkcu_event_.reset(new base::WaitableEvent(hkcu_key_.watch_event()));
195 hkcu_watcher_.StartWatching(hkcu_event_.get(), this);
196 }
[email protected]b547fd42009-04-23 23:16:27197 }
[email protected]86ec4f6e2011-04-20 16:21:19198 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
199 webkit::npapi::kRegistryMozillaPlugins,
200 KEY_NOTIFY) == ERROR_SUCCESS) {
201 if (hklm_key_.StartWatching() == ERROR_SUCCESS) {
202 hklm_event_.reset(new base::WaitableEvent(hklm_key_.watch_event()));
203 hklm_watcher_.StartWatching(hklm_event_.get(), this);
204 }
[email protected]b547fd42009-04-23 23:16:27205 }
[email protected]e60c0232011-11-11 19:56:35206#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:19207// The FilePathWatcher produces too many false positives on MacOS (access time
208// updates?) which will lead to enforcing updates of the plugins way too often.
209// On ChromeOS the user can't install plugins anyway and on Windows all
210// important plugins register themselves in the registry so no need to do that.
[email protected]634d23d2011-01-19 10:38:19211 file_watcher_delegate_ = new PluginDirWatcherDelegate();
212 // Get the list of all paths for registering the FilePathWatchers
213 // that will track and if needed reload the list of plugins on runtime.
214 std::vector<FilePath> plugin_dirs;
[email protected]3a5180ae2011-12-21 02:39:38215 plugin_list_->GetPluginDirectories(&plugin_dirs);
[email protected]894bb502009-05-21 22:39:57216
[email protected]634d23d2011-01-19 10:38:19217 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
[email protected]634d23d2011-01-19 10:38:19218 // FilePathWatcher can not handle non-absolute paths under windows.
219 // We don't watch for file changes in windows now but if this should ever
220 // be extended to Windows these lines might save some time of debugging.
221#if defined(OS_WIN)
222 if (!plugin_dirs[i].IsAbsolute())
223 continue;
224#endif
[email protected]493c8002011-04-14 16:56:01225 FilePathWatcher* watcher = new FilePathWatcher();
[email protected]634d23d2011-01-19 10:38:19226 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
227 BrowserThread::PostTask(
228 BrowserThread::FILE, FROM_HERE,
[email protected]e67385f2011-12-21 06:00:56229 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
[email protected]81050512011-12-19 19:32:51230 plugin_dirs[i], file_watcher_delegate_));
[email protected]634d23d2011-01-19 10:38:19231 file_watchers_.push_back(watcher);
232 }
233#endif
initial.commit09911bf2008-07-26 23:55:29234}
235
[email protected]e67385f2011-12-21 06:00:56236const std::string& PluginServiceImpl::GetUILocale() {
initial.commit09911bf2008-07-26 23:55:29237 return ui_locale_;
238}
239
[email protected]e67385f2011-12-21 06:00:56240PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
[email protected]28ab7f92009-01-06 21:39:04241 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29243
[email protected]bd5d6cf2011-12-01 00:39:12244 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_PLUGIN);
[email protected]a436d922009-02-13 23:16:42245 !iter.Done(); ++iter) {
246 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
247 if (plugin->info().path == plugin_path)
248 return plugin;
249 }
250
initial.commit09911bf2008-07-26 23:55:29251 return NULL;
252}
253
[email protected]e67385f2011-12-21 06:00:56254PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
[email protected]610c0892009-09-08 19:46:18255 const FilePath& plugin_path) {
[email protected]f8b3ef82010-10-11 02:45:52256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
initial.commit09911bf2008-07-26 23:55:29257
[email protected]a08ebea2011-02-13 17:50:20258 for (BrowserChildProcessHost::Iterator iter(
[email protected]bd5d6cf2011-12-01 00:39:12259 content::PROCESS_TYPE_PPAPI_PLUGIN);
[email protected]a08ebea2011-02-13 17:50:20260 !iter.Done(); ++iter) {
261 PpapiPluginProcessHost* plugin =
262 static_cast<PpapiPluginProcessHost*>(*iter);
263 if (plugin->plugin_path() == plugin_path)
264 return plugin;
265 }
266
267 return NULL;
268}
269
[email protected]e67385f2011-12-21 06:00:56270PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
[email protected]eb415bf0e2011-04-14 02:45:42271 const FilePath& broker_path) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
273
274 for (BrowserChildProcessHost::Iterator iter(
[email protected]bd5d6cf2011-12-01 00:39:12275 content::PROCESS_TYPE_PPAPI_BROKER);
[email protected]eb415bf0e2011-04-14 02:45:42276 !iter.Done(); ++iter) {
[email protected]a50432d2011-09-30 16:32:14277 PpapiPluginProcessHost* broker =
278 static_cast<PpapiPluginProcessHost*>(*iter);
279 if (broker->plugin_path() == broker_path)
[email protected]eb415bf0e2011-04-14 02:45:42280 return broker;
281 }
282
283 return NULL;
284}
285
[email protected]e67385f2011-12-21 06:00:56286PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
[email protected]a08ebea2011-02-13 17:50:20287 const FilePath& plugin_path) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
289
290 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
initial.commit09911bf2008-07-26 23:55:29291 if (plugin_host)
292 return plugin_host;
293
[email protected]91d9f3d2011-08-14 05:24:44294 webkit::WebPluginInfo info;
[email protected]88ca4912011-10-12 14:00:43295 if (!GetPluginInfoByPath(plugin_path, &info)) {
[email protected]a27a9382009-02-11 23:55:10296 return NULL;
297 }
298
initial.commit09911bf2008-07-26 23:55:29299 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]8b8a554d2010-11-18 13:26:40300 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
301 if (!new_host->Init(info, ui_locale_)) {
[email protected]a08ebea2011-02-13 17:50:20302 NOTREACHED(); // Init is not expected to fail.
initial.commit09911bf2008-07-26 23:55:29303 return NULL;
304 }
[email protected]8b8a554d2010-11-18 13:26:40305 return new_host.release();
initial.commit09911bf2008-07-26 23:55:29306}
307
[email protected]e67385f2011-12-21 06:00:56308PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
[email protected]d259a8e2011-05-18 22:31:09309 const FilePath& plugin_path,
[email protected]a50432d2011-09-30 16:32:14310 PpapiPluginProcessHost::PluginClient* client) {
[email protected]a08ebea2011-02-13 17:50:20311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
312
313 PpapiPluginProcessHost* plugin_host = FindPpapiPluginProcess(plugin_path);
314 if (plugin_host)
315 return plugin_host;
316
[email protected]eb415bf0e2011-04-14 02:45:42317 // Validate that the plugin is actually registered.
[email protected]738a7212011-10-21 17:33:52318 content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]a08ebea2011-02-13 17:50:20319 if (!info)
320 return NULL;
321
322 // This plugin isn't loaded by any plugin process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14323 return PpapiPluginProcessHost::CreatePluginHost(
324 *info,
325 client->GetResourceContext()->host_resolver());
[email protected]a08ebea2011-02-13 17:50:20326}
327
[email protected]e67385f2011-12-21 06:00:56328PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
[email protected]eb415bf0e2011-04-14 02:45:42329 const FilePath& plugin_path) {
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
331
[email protected]a50432d2011-09-30 16:32:14332 PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42333 if (plugin_host)
334 return plugin_host;
335
336 // Validate that the plugin is actually registered.
[email protected]738a7212011-10-21 17:33:52337 content::PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path);
[email protected]eb415bf0e2011-04-14 02:45:42338 if (!info)
339 return NULL;
340
341 // TODO(ddorwin): Uncomment once out of process is supported.
342 // DCHECK(info->is_out_of_process);
343
344 // This broker isn't loaded by any broker process, so create a new process.
[email protected]a50432d2011-09-30 16:32:14345 return PpapiPluginProcessHost::CreateBrokerHost(*info);
[email protected]eb415bf0e2011-04-14 02:45:42346}
347
[email protected]e67385f2011-12-21 06:00:56348void PluginServiceImpl::OpenChannelToNpapiPlugin(
[email protected]c8f73ab2011-01-22 00:05:17349 int render_process_id,
350 int render_view_id,
[email protected]610c0892009-09-08 19:46:18351 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54352 const GURL& page_url,
[email protected]610c0892009-09-08 19:46:18353 const std::string& mime_type,
[email protected]46b69e42010-11-02 12:26:39354 PluginProcessHost::Client* client) {
[email protected]76b70f92011-11-21 19:31:14355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]4befe7592011-09-14 22:49:09356 DCHECK(!ContainsKey(pending_plugin_clients_, client));
357 pending_plugin_clients_.insert(client);
[email protected]88ca4912011-10-12 14:00:43358
359 // Make sure plugins are loaded if necessary.
360 content::PluginServiceFilterParams params = {
361 render_process_id,
362 render_view_id,
363 page_url,
364 &client->GetResourceContext()
365 };
[email protected]e67385f2011-12-21 06:00:56366 GetPlugins(base::Bind(
367 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
368 base::Unretained(this), params, url, mime_type, client));
[email protected]6fdd4182010-10-14 23:59:26369}
370
[email protected]e67385f2011-12-21 06:00:56371void PluginServiceImpl::OpenChannelToPpapiPlugin(
[email protected]a08ebea2011-02-13 17:50:20372 const FilePath& path,
[email protected]a50432d2011-09-30 16:32:14373 PpapiPluginProcessHost::PluginClient* client) {
[email protected]d259a8e2011-05-18 22:31:09374 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
375 path, client);
[email protected]a08ebea2011-02-13 17:50:20376 if (plugin_host)
377 plugin_host->OpenChannelToPlugin(client);
378 else // Send error.
379 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
380}
381
[email protected]e67385f2011-12-21 06:00:56382void PluginServiceImpl::OpenChannelToPpapiBroker(
[email protected]eb415bf0e2011-04-14 02:45:42383 const FilePath& path,
[email protected]a50432d2011-09-30 16:32:14384 PpapiPluginProcessHost::BrokerClient* client) {
385 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
[email protected]eb415bf0e2011-04-14 02:45:42386 if (plugin_host)
[email protected]a50432d2011-09-30 16:32:14387 plugin_host->OpenChannelToPlugin(client);
[email protected]eb415bf0e2011-04-14 02:45:42388 else // Send error.
389 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
390}
391
[email protected]e67385f2011-12-21 06:00:56392void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
[email protected]4befe7592011-09-14 22:49:09393 PluginProcessHost::Client* client) {
394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
395 DCHECK(ContainsKey(pending_plugin_clients_, client));
396 pending_plugin_clients_.erase(client);
397}
398
[email protected]e67385f2011-12-21 06:00:56399void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
[email protected]88ca4912011-10-12 14:00:43400 const content::PluginServiceFilterParams& params,
401 const GURL& url,
402 const std::string& mime_type,
403 PluginProcessHost::Client* client,
404 const std::vector<webkit::WebPluginInfo>&) {
405 GetAllowedPluginForOpenChannelToPlugin(params.render_process_id,
406 params.render_view_id, url, params.page_url, mime_type, client,
407 params.resource_context);
408}
409
[email protected]e67385f2011-12-21 06:00:56410void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
[email protected]c8f73ab2011-01-22 00:05:17411 int render_process_id,
412 int render_view_id,
[email protected]6fdd4182010-10-14 23:59:26413 const GURL& url,
[email protected]dfba8762011-09-02 12:49:54414 const GURL& page_url,
[email protected]6fdd4182010-10-14 23:59:26415 const std::string& mime_type,
[email protected]87c4be42011-09-16 01:10:59416 PluginProcessHost::Client* client,
417 const content::ResourceContext* resource_context) {
[email protected]91d9f3d2011-08-14 05:24:44418 webkit::WebPluginInfo info;
[email protected]dfba8762011-09-02 12:49:54419 bool allow_wildcard = true;
[email protected]11e1c182011-05-17 20:26:27420 bool found = GetPluginInfo(
[email protected]87c4be42011-09-16 01:10:59421 render_process_id, render_view_id, *resource_context,
[email protected]dfba8762011-09-02 12:49:54422 url, page_url, mime_type, allow_wildcard,
423 NULL, &info, NULL);
[email protected]6fdd4182010-10-14 23:59:26424 FilePath plugin_path;
[email protected]68598072011-07-29 08:21:28425 if (found)
[email protected]dfba8762011-09-02 12:49:54426 plugin_path = info.path;
[email protected]6fdd4182010-10-14 23:59:26427
428 // Now we jump back to the IO thread to finish opening the channel.
[email protected]e67385f2011-12-21 06:00:56429 BrowserThread::PostTask(
430 BrowserThread::IO, FROM_HERE,
431 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
[email protected]88ca4912011-10-12 14:00:43432 base::Unretained(this), plugin_path, client));
[email protected]6fdd4182010-10-14 23:59:26433}
434
[email protected]e67385f2011-12-21 06:00:56435void PluginServiceImpl::FinishOpenChannelToPlugin(
[email protected]6fdd4182010-10-14 23:59:26436 const FilePath& plugin_path,
[email protected]46b69e42010-11-02 12:26:39437 PluginProcessHost::Client* client) {
[email protected]f8b3ef82010-10-11 02:45:52438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20a793e2010-10-12 06:50:08439
[email protected]4befe7592011-09-14 22:49:09440 // Make sure it hasn't been canceled yet.
441 if (!ContainsKey(pending_plugin_clients_, client))
442 return;
443 pending_plugin_clients_.erase(client);
444
[email protected]a08ebea2011-02-13 17:50:20445 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
[email protected]4befe7592011-09-14 22:49:09446 if (plugin_host) {
447 client->OnFoundPluginProcessHost(plugin_host);
[email protected]46b69e42010-11-02 12:26:39448 plugin_host->OpenChannelToPlugin(client);
[email protected]4befe7592011-09-14 22:49:09449 } else {
[email protected]46b69e42010-11-02 12:26:39450 client->OnError();
[email protected]4befe7592011-09-14 22:49:09451 }
initial.commit09911bf2008-07-26 23:55:29452}
453
[email protected]e67385f2011-12-21 06:00:56454bool PluginServiceImpl::GetPluginInfoArray(
[email protected]51b63f62011-10-05 18:55:42455 const GURL& url,
456 const std::string& mime_type,
457 bool allow_wildcard,
458 std::vector<webkit::WebPluginInfo>* plugins,
459 std::vector<std::string>* actual_mime_types) {
460 bool use_stale = false;
[email protected]3a5180ae2011-12-21 02:39:38461 plugin_list_->GetPluginInfoArray(url, mime_type, allow_wildcard,
462 &use_stale, plugins, actual_mime_types);
[email protected]51b63f62011-10-05 18:55:42463 return use_stale;
464}
465
[email protected]e67385f2011-12-21 06:00:56466bool PluginServiceImpl::GetPluginInfo(int render_process_id,
467 int render_view_id,
468 const content::ResourceContext& context,
469 const GURL& url,
470 const GURL& page_url,
471 const std::string& mime_type,
472 bool allow_wildcard,
473 bool* is_stale,
474 webkit::WebPluginInfo* info,
475 std::string* actual_mime_type) {
[email protected]91d9f3d2011-08-14 05:24:44476 std::vector<webkit::WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28477 std::vector<std::string> mime_types;
[email protected]88ca4912011-10-12 14:00:43478 bool stale = GetPluginInfoArray(
479 url, mime_type, allow_wildcard, &plugins, &mime_types);
480 if (is_stale)
481 *is_stale = stale;
[email protected]dfba8762011-09-02 12:49:54482 if (plugins.size() > 1 &&
483 plugins.back().path ==
484 FilePath(webkit::npapi::kDefaultPluginLibraryName)) {
485 // If there is at least one plug-in handling the required MIME type (apart
486 // from the default plug-in), we don't need the default plug-in.
487 plugins.pop_back();
488 }
489
[email protected]68598072011-07-29 08:21:28490 for (size_t i = 0; i < plugins.size(); ++i) {
[email protected]dfba8762011-09-02 12:49:54491 if (!filter_ || filter_->ShouldUsePlugin(render_process_id,
492 render_view_id,
493 &context,
494 url,
495 page_url,
496 &plugins[i])) {
[email protected]68598072011-07-29 08:21:28497 *info = plugins[i];
498 if (actual_mime_type)
499 *actual_mime_type = mime_types[i];
500 return true;
501 }
502 }
503 return false;
[email protected]6fdd4182010-10-14 23:59:26504}
505
[email protected]e67385f2011-12-21 06:00:56506bool PluginServiceImpl::GetPluginInfoByPath(const FilePath& plugin_path,
507 webkit::WebPluginInfo* info) {
[email protected]88ca4912011-10-12 14:00:43508 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38509 plugin_list_->GetPluginsIfNoRefreshNeeded(&plugins);
[email protected]88ca4912011-10-12 14:00:43510
511 for (std::vector<webkit::WebPluginInfo>::iterator it = plugins.begin();
512 it != plugins.end();
513 ++it) {
514 if (it->path == plugin_path) {
515 *info = *it;
516 return true;
517 }
518 }
519
520 return false;
521}
522
[email protected]e67385f2011-12-21 06:00:56523void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
[email protected]49125952011-09-27 18:05:15524 scoped_refptr<base::MessageLoopProxy> target_loop(
525 MessageLoop::current()->message_loop_proxy());
526
[email protected]6a0dc7a2011-11-02 14:37:07527#if defined(OS_WIN)
[email protected]e67385f2011-12-21 06:00:56528 BrowserThread::PostTask(
529 BrowserThread::FILE, FROM_HERE,
530 base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this),
[email protected]49125952011-09-27 18:05:15531 target_loop, callback));
532#else
533 std::vector<webkit::WebPluginInfo> cached_plugins;
[email protected]3a5180ae2011-12-21 02:39:38534 if (plugin_list_->GetPluginsIfNoRefreshNeeded(&cached_plugins)) {
[email protected]49125952011-09-27 18:05:15535 // Can't assume the caller is reentrant.
536 target_loop->PostTask(FROM_HERE,
537 base::Bind(&RunGetPluginsCallback, callback, cached_plugins));
538 } else {
[email protected]4bb85b92011-11-05 02:53:29539 // If we switch back to loading plugins in process, then we need to make
540 // sure g_thread_init() gets called since plugins may call glib at load.
[email protected]d4af1e72011-10-21 17:45:43541 if (!plugin_loader_.get())
542 plugin_loader_ = new PluginLoaderPosix;
[email protected]49125952011-09-27 18:05:15543 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]d4af1e72011-10-21 17:45:43544 base::Bind(&PluginLoaderPosix::LoadPlugins, plugin_loader_,
545 target_loop, callback));
[email protected]49125952011-09-27 18:05:15546 }
547#endif
[email protected]d33e7cc2011-09-23 01:43:56548}
549
[email protected]e67385f2011-12-21 06:00:56550void PluginServiceImpl::GetPluginGroups(
551 const GetPluginGroupsCallback& callback) {
[email protected]d33e7cc2011-09-23 01:43:56552 GetPlugins(base::Bind(&GetPluginsForGroupsCallback, callback));
553}
554
[email protected]e67385f2011-12-21 06:00:56555void PluginServiceImpl::GetPluginsInternal(
[email protected]d33e7cc2011-09-23 01:43:56556 base::MessageLoopProxy* target_loop,
557 const PluginService::GetPluginsCallback& callback) {
558 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
559
560 std::vector<webkit::WebPluginInfo> plugins;
[email protected]3a5180ae2011-12-21 02:39:38561 plugin_list_->GetPlugins(&plugins);
[email protected]d33e7cc2011-09-23 01:43:56562
563 target_loop->PostTask(FROM_HERE,
564 base::Bind(&RunGetPluginsCallback, callback, plugins));
[email protected]dfba8762011-09-02 12:49:54565}
566
[email protected]e67385f2011-12-21 06:00:56567void PluginServiceImpl::OnWaitableEventSignaled(
[email protected]580522632009-08-17 21:55:55568 base::WaitableEvent* waitable_event) {
[email protected]b547fd42009-04-23 23:16:27569#if defined(OS_WIN)
570 if (waitable_event == hkcu_event_.get()) {
571 hkcu_key_.StartWatching();
572 } else {
573 hklm_key_.StartWatching();
574 }
575
[email protected]3a5180ae2011-12-21 02:39:38576 plugin_list_->RefreshPlugins();
[email protected]45a22e62011-10-12 09:48:02577 PurgePluginListCache(NULL, false);
[email protected]634d23d2011-01-19 10:38:19578#else
579 // This event should only get signaled on a Windows machine.
580 NOTREACHED();
[email protected]9de09f82009-08-17 20:13:53581#endif // defined(OS_WIN)
[email protected]b547fd42009-04-23 23:16:27582}
[email protected]894bb502009-05-21 22:39:57583
[email protected]e67385f2011-12-21 06:00:56584void PluginServiceImpl::Observe(int type,
585 const content::NotificationSource& source,
586 const content::NotificationDetails& details) {
[email protected]a96ec6a2009-11-04 17:27:08587#if defined(OS_MACOSX)
[email protected]dfba8762011-09-02 12:49:54588 if (type == content::NOTIFICATION_APP_ACTIVATED) {
589 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]81050512011-12-19 19:32:51590 base::Bind(&NotifyPluginsOfActivation));
[email protected]dfba8762011-09-02 12:49:54591 return;
[email protected]894bb502009-05-21 22:39:57592 }
[email protected]dfba8762011-09-02 12:49:54593#endif
594 NOTREACHED();
[email protected]c8f73ab2011-01-22 00:05:17595}
596
[email protected]e67385f2011-12-21 06:00:56597void PluginServiceImpl::RegisterPepperPlugins() {
[email protected]84396dbc2011-04-14 06:33:42598 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
[email protected]a08ebea2011-02-13 17:50:20599 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
600 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
[email protected]f520b5b2011-11-08 02:42:14601 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo());
[email protected]4e0616e2010-05-28 14:55:53602 }
603}
[email protected]634d23d2011-01-19 10:38:19604
[email protected]eb415bf0e2011-04-14 02:45:42605// There should generally be very few plugins so a brute-force search is fine.
[email protected]e67385f2011-12-21 06:00:56606content::PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
[email protected]eb415bf0e2011-04-14 02:45:42607 const FilePath& plugin_path) {
[email protected]738a7212011-10-21 17:33:52608 content::PepperPluginInfo* info = NULL;
[email protected]eb415bf0e2011-04-14 02:45:42609 for (size_t i = 0; i < ppapi_plugins_.size(); i++) {
[email protected]6b14feb2011-08-16 11:22:56610 if (ppapi_plugins_[i].path == plugin_path) {
611 info = &ppapi_plugins_[i];
612 break;
613 }
[email protected]eb415bf0e2011-04-14 02:45:42614 }
[email protected]076117592011-08-17 03:16:41615 if (info)
616 return info;
617 // We did not find the plugin in our list. But wait! the plugin can also
618 // be a latecomer, as it happens with pepper flash. This information
619 // can be obtained from the PluginList singleton and we can use it to
620 // construct it and add it to the list. This same deal needs to be done
621 // in the renderer side in PepperPluginRegistry.
622 webkit::WebPluginInfo webplugin_info;
[email protected]88ca4912011-10-12 14:00:43623 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
[email protected]076117592011-08-17 03:16:41624 return NULL;
[email protected]738a7212011-10-21 17:33:52625 content::PepperPluginInfo new_pepper_info;
[email protected]076117592011-08-17 03:16:41626 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
627 return NULL;
628 ppapi_plugins_.push_back(new_pepper_info);
629 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
[email protected]eb415bf0e2011-04-14 02:45:42630}
631
[email protected]e60c0232011-11-11 19:56:35632#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
[email protected]634d23d2011-01-19 10:38:19633// static
[email protected]e67385f2011-12-21 06:00:56634void PluginServiceImpl::RegisterFilePathWatcher(
[email protected]634d23d2011-01-19 10:38:19635 FilePathWatcher *watcher,
636 const FilePath& path,
637 FilePathWatcher::Delegate* delegate) {
[email protected]7b3ee8b2011-04-01 18:48:19638 bool result = watcher->Watch(path, delegate);
[email protected]634d23d2011-01-19 10:38:19639 DCHECK(result);
640}
641#endif
[email protected]f520b5b2011-11-08 02:42:14642
[email protected]e67385f2011-12-21 06:00:56643void PluginServiceImpl::SetFilter(content::PluginServiceFilter* filter) {
[email protected]3a5180ae2011-12-21 02:39:38644 filter_ = filter;
645}
646
[email protected]e67385f2011-12-21 06:00:56647content::PluginServiceFilter* PluginServiceImpl::GetFilter() {
[email protected]3a5180ae2011-12-21 02:39:38648 return filter_;
649}
650
[email protected]e67385f2011-12-21 06:00:56651void PluginServiceImpl::RefreshPlugins() {
[email protected]3a5180ae2011-12-21 02:39:38652 plugin_list_->RefreshPlugins();
[email protected]f520b5b2011-11-08 02:42:14653}
654
[email protected]e67385f2011-12-21 06:00:56655void PluginServiceImpl::AddExtraPluginPath(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38656 plugin_list_->AddExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14657}
658
[email protected]e67385f2011-12-21 06:00:56659void PluginServiceImpl::RemoveExtraPluginPath(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38660 plugin_list_->RemoveExtraPluginPath(path);
[email protected]f520b5b2011-11-08 02:42:14661}
662
[email protected]e67385f2011-12-21 06:00:56663void PluginServiceImpl::UnregisterInternalPlugin(const FilePath& path) {
[email protected]3a5180ae2011-12-21 02:39:38664 plugin_list_->UnregisterInternalPlugin(path);
[email protected]f520b5b2011-11-08 02:42:14665}
666
[email protected]e67385f2011-12-21 06:00:56667void PluginServiceImpl::SetPluginListForTesting(
[email protected]ee066172011-11-10 23:20:05668 webkit::npapi::PluginList* plugin_list) {
669 plugin_list_ = plugin_list;
670}
671
[email protected]e67385f2011-12-21 06:00:56672void PluginServiceImpl::RegisterInternalPlugin(
673 const webkit::WebPluginInfo& info) {
[email protected]3a5180ae2011-12-21 02:39:38674 plugin_list_->RegisterInternalPlugin(info);
[email protected]f520b5b2011-11-08 02:42:14675}
676
[email protected]e67385f2011-12-21 06:00:56677string16 PluginServiceImpl::GetPluginGroupName(const std::string& plugin_name) {
[email protected]3a5180ae2011-12-21 02:39:38678 return plugin_list_->GetPluginGroupName(plugin_name);
679}
680
[email protected]e67385f2011-12-21 06:00:56681webkit::npapi::PluginList* PluginServiceImpl::GetPluginList() {
[email protected]3a5180ae2011-12-21 02:39:38682 return plugin_list_;
[email protected]f520b5b2011-11-08 02:42:14683}