Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(482)

Side by Side Diff: content/browser/plugin_service_impl.cc

Issue 1862513003: Remove NPAPI from browser and utility (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/plugin_service_impl.h" 5 #include "content/browser/plugin_service_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 16 matching lines...) Expand all
27 #include "content/common/view_messages.h" 27 #include "content/common/view_messages.h"
28 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/content_browser_client.h" 29 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/plugin_service_filter.h" 30 #include "content/public/browser/plugin_service_filter.h"
31 #include "content/public/browser/resource_context.h" 31 #include "content/public/browser/resource_context.h"
32 #include "content/public/common/content_constants.h" 32 #include "content/public/common/content_constants.h"
33 #include "content/public/common/content_switches.h" 33 #include "content/public/common/content_switches.h"
34 #include "content/public/common/process_type.h" 34 #include "content/public/common/process_type.h"
35 #include "content/public/common/webplugininfo.h" 35 #include "content/public/common/webplugininfo.h"
36 36
37 #if defined(OS_WIN)
38 #include "content/common/plugin_constants_win.h"
39 #include "ui/gfx/win/hwnd_util.h"
40 #endif
41
42 #if defined(OS_POSIX)
43 #include "content/browser/plugin_loader_posix.h"
44 #endif
45
46 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
47 using ::base::FilePathWatcher;
48 #endif
49
50 namespace content { 37 namespace content {
51 namespace { 38 namespace {
52 39
53 // This enum is used to collect Flash usage data. 40 // This enum is used to collect Flash usage data.
54 enum FlashUsage { 41 enum FlashUsage {
55 // Number of browser processes that have started at least one NPAPI Flash
56 // process during their lifetime.
57 START_NPAPI_FLASH_AT_LEAST_ONCE,
58 // Number of browser processes that have started at least one PPAPI Flash 42 // Number of browser processes that have started at least one PPAPI Flash
59 // process during their lifetime. 43 // process during their lifetime.
60 START_PPAPI_FLASH_AT_LEAST_ONCE, 44 START_PPAPI_FLASH_AT_LEAST_ONCE = 1,
61 // Total number of browser processes. 45 // Total number of browser processes.
62 TOTAL_BROWSER_PROCESSES, 46 TOTAL_BROWSER_PROCESSES,
63 FLASH_USAGE_ENUM_COUNT 47 FLASH_USAGE_ENUM_COUNT
64 }; 48 };
65 49
66 enum NPAPIPluginStatus {
67 // Platform does not support NPAPI.
68 NPAPI_STATUS_UNSUPPORTED,
69 // Platform supports NPAPI and NPAPI is disabled.
70 NPAPI_STATUS_DISABLED,
71 // Platform supports NPAPI and NPAPI is enabled.
72 NPAPI_STATUS_ENABLED,
73 NPAPI_STATUS_ENUM_COUNT
74 };
75
76 bool LoadPluginListInProcess() {
77 #if defined(OS_WIN)
78 return true;
79 #else
80 // If on POSIX, we don't want to load the list of NPAPI plugins in-process as
81 // that causes instability.
82
83 // Can't load the plugins on the utility thread when in single process mode
84 // since that requires GTK which can only be used on the main thread.
85 if (RenderProcessHost::run_renderer_in_process())
86 return true;
87
88 return !PluginService::GetInstance()->NPAPIPluginsSupported();
89 #endif
90 }
91
92 // Callback set on the PluginList to assert that plugin loading happens on the 50 // Callback set on the PluginList to assert that plugin loading happens on the
93 // correct thread. 51 // correct thread.
94 void WillLoadPluginsCallback( 52 void WillLoadPluginsCallback(
95 base::SequencedWorkerPool::SequenceToken token) { 53 base::SequencedWorkerPool::SequenceToken token) {
96 if (LoadPluginListInProcess()) { 54 CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
97 CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( 55 token));
98 token));
99 } else {
100 CHECK(false) << "Plugin loading should happen out-of-process.";
101 }
102 } 56 }
103 57
104 #if defined(OS_MACOSX)
105 void NotifyPluginsOfActivation() {
106 DCHECK_CURRENTLY_ON(BrowserThread::IO);
107
108 for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
109 iter->OnAppActivation();
110 }
111 #endif
112
113 #if defined(OS_POSIX)
114 #if !defined(OS_OPENBSD) && !defined(OS_ANDROID)
115 void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
116 if (error) {
117 // TODO(pastarmovj): Add some sensible error handling. Maybe silently
118 // stopping the watcher would be enough. Or possibly restart it.
119 NOTREACHED();
120 return;
121 }
122 VLOG(1) << "Watched path changed: " << path.value();
123 // Make the plugin list update itself
124 PluginList::Singleton()->RefreshPlugins();
125 BrowserThread::PostTask(
126 BrowserThread::UI, FROM_HERE,
127 base::Bind(&PluginService::PurgePluginListCache,
128 static_cast<BrowserContext*>(NULL), false));
129 }
130 #endif // !defined(OS_OPENBSD) && !defined(OS_ANDROID)
131
132 void ForwardCallback(base::SingleThreadTaskRunner* target_task_runner,
133 const PluginService::GetPluginsCallback& callback,
134 const std::vector<WebPluginInfo>& plugins) {
135 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
136 }
137 #endif // defined(OS_POSIX)
138
139 } // namespace 58 } // namespace
140 59
141 // static 60 // static
142 PluginService* PluginService::GetInstance() { 61 PluginService* PluginService::GetInstance() {
143 return PluginServiceImpl::GetInstance(); 62 return PluginServiceImpl::GetInstance();
144 } 63 }
145 64
146 void PluginService::PurgePluginListCache(BrowserContext* browser_context, 65 void PluginService::PurgePluginListCache(BrowserContext* browser_context,
147 bool reload_pages) { 66 bool reload_pages) {
148 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); 67 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
149 !it.IsAtEnd(); it.Advance()) { 68 !it.IsAtEnd(); it.Advance()) {
150 RenderProcessHost* host = it.GetCurrentValue(); 69 RenderProcessHost* host = it.GetCurrentValue();
151 if (!browser_context || host->GetBrowserContext() == browser_context) 70 if (!browser_context || host->GetBrowserContext() == browser_context)
152 host->Send(new ViewMsg_PurgePluginListCache(reload_pages)); 71 host->Send(new ViewMsg_PurgePluginListCache(reload_pages));
153 } 72 }
154 } 73 }
155 74
156 // static 75 // static
157 PluginServiceImpl* PluginServiceImpl::GetInstance() { 76 PluginServiceImpl* PluginServiceImpl::GetInstance() {
158 return base::Singleton<PluginServiceImpl>::get(); 77 return base::Singleton<PluginServiceImpl>::get();
159 } 78 }
160 79
161 PluginServiceImpl::PluginServiceImpl() 80 PluginServiceImpl::PluginServiceImpl()
162 : npapi_plugins_enabled_(false), filter_(NULL) { 81 : filter_(NULL) {
163 // Collect the total number of browser processes (which create 82 // Collect the total number of browser processes (which create
164 // PluginServiceImpl objects, to be precise). The number is used to normalize 83 // PluginServiceImpl objects, to be precise). The number is used to normalize
165 // the number of processes which start at least one NPAPI/PPAPI Flash process. 84 // the number of processes which start at least one NPAPI/PPAPI Flash process.
166 static bool counted = false; 85 static bool counted = false;
167 if (!counted) { 86 if (!counted) {
168 counted = true; 87 counted = true;
169 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES, 88 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", TOTAL_BROWSER_PROCESSES,
170 FLASH_USAGE_ENUM_COUNT); 89 FLASH_USAGE_ENUM_COUNT);
171 } 90 }
172 } 91 }
173 92
174 PluginServiceImpl::~PluginServiceImpl() { 93 PluginServiceImpl::~PluginServiceImpl() {
175 // Make sure no plugin channel requests have been leaked.
176 DCHECK(pending_plugin_clients_.empty());
177 } 94 }
178 95
179 void PluginServiceImpl::Init() { 96 void PluginServiceImpl::Init() {
180 plugin_list_token_ = base::SequencedWorkerPool::GetSequenceToken(); 97 plugin_list_token_ = base::SequencedWorkerPool::GetSequenceToken();
181 PluginList::Singleton()->set_will_load_plugins_callback( 98 PluginList::Singleton()->set_will_load_plugins_callback(
182 base::Bind(&WillLoadPluginsCallback, plugin_list_token_)); 99 base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
183 100
184 RegisterPepperPlugins(); 101 RegisterPepperPlugins();
185
186 // Load any specified on the command line as well.
187 const base::CommandLine* command_line =
188 base::CommandLine::ForCurrentProcess();
189 base::FilePath path =
190 command_line->GetSwitchValuePath(switches::kLoadPlugin);
191 if (!path.empty())
192 AddExtraPluginPath(path);
193 path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
194 if (!path.empty())
195 PluginList::Singleton()->AddExtraPluginDir(path);
196
197 if (command_line->HasSwitch(switches::kDisablePluginsDiscovery))
198 PluginList::Singleton()->DisablePluginsDiscovery();
199 }
200
201 void PluginServiceImpl::StartWatchingPlugins() {
202 // 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.
205 #if defined(OS_WIN)
206 if (hkcu_key_.Create(HKEY_CURRENT_USER,
207 kRegistryMozillaPlugins,
208 KEY_NOTIFY) == ERROR_SUCCESS) {
209 base::win::RegKey::ChangeCallback callback =
210 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
211 base::Unretained(&hkcu_key_));
212 hkcu_key_.StartWatching(callback);
213 }
214 if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
215 kRegistryMozillaPlugins,
216 KEY_NOTIFY) == ERROR_SUCCESS) {
217 base::win::RegKey::ChangeCallback callback =
218 base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
219 base::Unretained(&hklm_key_));
220 hklm_key_.StartWatching(callback);
221 }
222 #endif
223 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
224 // On ChromeOS the user can't install plugins anyway and on Windows all
225 // important plugins register themselves in the registry so no need to do that.
226
227 // Get the list of all paths for registering the FilePathWatchers
228 // that will track and if needed reload the list of plugins on runtime.
229 std::vector<base::FilePath> plugin_dirs;
230 PluginList::Singleton()->GetPluginDirectories(&plugin_dirs);
231
232 for (size_t i = 0; i < plugin_dirs.size(); ++i) {
233 // FilePathWatcher can not handle non-absolute paths under windows.
234 // We don't watch for file changes in windows now but if this should ever
235 // be extended to Windows these lines might save some time of debugging.
236 #if defined(OS_WIN)
237 if (!plugin_dirs[i].IsAbsolute())
238 continue;
239 #endif
240 FilePathWatcher* watcher = new FilePathWatcher();
241 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
242 BrowserThread::PostTask(
243 BrowserThread::FILE, FROM_HERE,
244 base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
245 plugin_dirs[i]));
246 file_watchers_.push_back(watcher);
247 }
248 #endif
249 }
250
251 PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
252 const base::FilePath& plugin_path) {
253 for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
254 if (iter->info().path == plugin_path)
255 return *iter;
256 }
257
258 return NULL;
259 } 102 }
260 103
261 PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess( 104 PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
262 const base::FilePath& plugin_path, 105 const base::FilePath& plugin_path,
263 const base::FilePath& profile_data_directory) { 106 const base::FilePath& profile_data_directory) {
264 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) { 107 for (PpapiPluginProcessHostIterator iter; !iter.Done(); ++iter) {
265 if (iter->plugin_path() == plugin_path && 108 if (iter->plugin_path() == plugin_path &&
266 iter->profile_data_directory() == profile_data_directory) { 109 iter->profile_data_directory() == profile_data_directory) {
267 return *iter; 110 return *iter;
268 } 111 }
269 } 112 }
270 return NULL; 113 return NULL;
271 } 114 }
272 115
273 PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess( 116 PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
274 const base::FilePath& broker_path) { 117 const base::FilePath& broker_path) {
275 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) { 118 for (PpapiBrokerProcessHostIterator iter; !iter.Done(); ++iter) {
276 if (iter->plugin_path() == broker_path) 119 if (iter->plugin_path() == broker_path)
277 return *iter; 120 return *iter;
278 } 121 }
279 122
280 return NULL; 123 return NULL;
281 } 124 }
282 125
283 PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
284 int render_process_id,
285 const base::FilePath& plugin_path) {
286 DCHECK_CURRENTLY_ON(BrowserThread::IO);
287
288 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
289 return NULL;
290
291 PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
292 if (plugin_host)
293 return plugin_host;
294
295 WebPluginInfo info;
296 if (!GetPluginInfoByPath(plugin_path, &info)) {
297 return NULL;
298 }
299
300 // Record when NPAPI Flash process is started for the first time.
301 static bool counted = false;
302 if (!counted && base::UTF16ToUTF8(info.name) == kFlashPluginName) {
303 counted = true;
304 UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
305 START_NPAPI_FLASH_AT_LEAST_ONCE,
306 FLASH_USAGE_ENUM_COUNT);
307 }
308 #if defined(OS_CHROMEOS)
309 // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now
310 // we still want Plugin.FlashUsage recorded if we end up here.
311 LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS.";
312 return NULL;
313 #endif
314 // This plugin isn't loaded by any plugin process, so create a new process.
315 scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
316 if (!new_host->Init(info)) {
317 NOTREACHED(); // Init is not expected to fail.
318 return NULL;
319 }
320 return new_host.release();
321 }
322
323 PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( 126 PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
324 int render_process_id, 127 int render_process_id,
325 const base::FilePath& plugin_path, 128 const base::FilePath& plugin_path,
326 const base::FilePath& profile_data_directory) { 129 const base::FilePath& profile_data_directory) {
327 DCHECK_CURRENTLY_ON(BrowserThread::IO); 130 DCHECK_CURRENTLY_ON(BrowserThread::IO);
328 131
329 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) { 132 if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) {
330 VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII(); 133 VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII();
331 return NULL; 134 return NULL;
332 } 135 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 if (!info) 184 if (!info)
382 return NULL; 185 return NULL;
383 186
384 // TODO(ddorwin): Uncomment once out of process is supported. 187 // TODO(ddorwin): Uncomment once out of process is supported.
385 // DCHECK(info->is_out_of_process); 188 // DCHECK(info->is_out_of_process);
386 189
387 // This broker isn't loaded by any broker process, so create a new process. 190 // This broker isn't loaded by any broker process, so create a new process.
388 return PpapiPluginProcessHost::CreateBrokerHost(*info); 191 return PpapiPluginProcessHost::CreateBrokerHost(*info);
389 } 192 }
390 193
391 void PluginServiceImpl::OpenChannelToNpapiPlugin(
392 int render_process_id,
393 int render_frame_id,
394 const GURL& url,
395 const GURL& page_url,
396 const std::string& mime_type,
397 PluginProcessHost::Client* client) {
398 DCHECK_CURRENTLY_ON(BrowserThread::IO);
399 DCHECK(!ContainsKey(pending_plugin_clients_, client));
400 pending_plugin_clients_.insert(client);
401
402 // Make sure plugins are loaded if necessary.
403 PluginServiceFilterParams params = {
404 render_process_id,
405 render_frame_id,
406 page_url,
407 client->GetResourceContext()
408 };
409 GetPlugins(base::Bind(
410 &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
411 base::Unretained(this), params, url, mime_type, client));
412 }
413
414 void PluginServiceImpl::OpenChannelToPpapiPlugin( 194 void PluginServiceImpl::OpenChannelToPpapiPlugin(
415 int render_process_id, 195 int render_process_id,
416 const base::FilePath& plugin_path, 196 const base::FilePath& plugin_path,
417 const base::FilePath& profile_data_directory, 197 const base::FilePath& profile_data_directory,
418 PpapiPluginProcessHost::PluginClient* client) { 198 PpapiPluginProcessHost::PluginClient* client) {
419 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess( 199 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
420 render_process_id, plugin_path, profile_data_directory); 200 render_process_id, plugin_path, profile_data_directory);
421 if (plugin_host) { 201 if (plugin_host) {
422 plugin_host->OpenChannelToPlugin(client); 202 plugin_host->OpenChannelToPlugin(client);
423 } else { 203 } else {
424 // Send error. 204 // Send error.
425 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0); 205 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
426 } 206 }
427 } 207 }
428 208
429 void PluginServiceImpl::OpenChannelToPpapiBroker( 209 void PluginServiceImpl::OpenChannelToPpapiBroker(
430 int render_process_id, 210 int render_process_id,
431 const base::FilePath& path, 211 const base::FilePath& path,
432 PpapiPluginProcessHost::BrokerClient* client) { 212 PpapiPluginProcessHost::BrokerClient* client) {
433 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess( 213 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(
434 render_process_id, path); 214 render_process_id, path);
435 if (plugin_host) { 215 if (plugin_host) {
436 plugin_host->OpenChannelToPlugin(client); 216 plugin_host->OpenChannelToPlugin(client);
437 } else { 217 } else {
438 // Send error. 218 // Send error.
439 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0); 219 client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0);
440 } 220 }
441 } 221 }
442 222
443 void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
444 PluginProcessHost::Client* client) {
445 DCHECK_CURRENTLY_ON(BrowserThread::IO);
446 DCHECK(ContainsKey(pending_plugin_clients_, client));
447 pending_plugin_clients_.erase(client);
448 }
449
450 void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
451 const PluginServiceFilterParams& params,
452 const GURL& url,
453 const std::string& mime_type,
454 PluginProcessHost::Client* client,
455 const std::vector<WebPluginInfo>&) {
456 GetAllowedPluginForOpenChannelToPlugin(
457 params.render_process_id, params.render_frame_id, url, params.page_url,
458 mime_type, client, params.resource_context);
459 }
460
461 void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
462 int render_process_id,
463 int render_frame_id,
464 const GURL& url,
465 const GURL& page_url,
466 const std::string& mime_type,
467 PluginProcessHost::Client* client,
468 ResourceContext* resource_context) {
469 WebPluginInfo info;
470 bool allow_wildcard = true;
471 bool found = GetPluginInfo(
472 render_process_id, render_frame_id, resource_context,
473 url, page_url, mime_type, allow_wildcard,
474 NULL, &info, NULL);
475 base::FilePath plugin_path;
476 if (found)
477 plugin_path = info.path;
478
479 // Now we jump back to the IO thread to finish opening the channel.
480 BrowserThread::PostTask(
481 BrowserThread::IO, FROM_HERE,
482 base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
483 base::Unretained(this),
484 render_process_id,
485 plugin_path,
486 client));
487 if (filter_) {
488 DCHECK_EQ(WebPluginInfo::PLUGIN_TYPE_NPAPI, info.type);
489 filter_->NPAPIPluginLoaded(render_process_id, render_frame_id, mime_type,
490 info);
491 }
492 }
493
494 void PluginServiceImpl::FinishOpenChannelToPlugin(
495 int render_process_id,
496 const base::FilePath& plugin_path,
497 PluginProcessHost::Client* client) {
498 DCHECK_CURRENTLY_ON(BrowserThread::IO);
499
500 // Make sure it hasn't been canceled yet.
501 if (!ContainsKey(pending_plugin_clients_, client))
502 return;
503 pending_plugin_clients_.erase(client);
504
505 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
506 render_process_id, plugin_path);
507 if (plugin_host) {
508 client->OnFoundPluginProcessHost(plugin_host);
509 plugin_host->OpenChannelToPlugin(client);
510 } else {
511 client->OnError();
512 }
513 }
514
515 bool PluginServiceImpl::GetPluginInfoArray( 223 bool PluginServiceImpl::GetPluginInfoArray(
516 const GURL& url, 224 const GURL& url,
517 const std::string& mime_type, 225 const std::string& mime_type,
518 bool allow_wildcard, 226 bool allow_wildcard,
519 std::vector<WebPluginInfo>* plugins, 227 std::vector<WebPluginInfo>* plugins,
520 std::vector<std::string>* actual_mime_types) { 228 std::vector<std::string>* actual_mime_types) {
521 bool use_stale = false; 229 bool use_stale = false;
522 PluginList::Singleton()->GetPluginInfoArray( 230 PluginList::Singleton()->GetPluginInfoArray(
523 url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(), 231 url, mime_type, allow_wildcard, &use_stale, plugins, actual_mime_types);
524 plugins, actual_mime_types);
525 return use_stale; 232 return use_stale;
526 } 233 }
527 234
528 bool PluginServiceImpl::GetPluginInfo(int render_process_id, 235 bool PluginServiceImpl::GetPluginInfo(int render_process_id,
529 int render_frame_id, 236 int render_frame_id,
530 ResourceContext* context, 237 ResourceContext* context,
531 const GURL& url, 238 const GURL& url,
532 const GURL& page_url, 239 const GURL& page_url,
533 const std::string& mime_type, 240 const std::string& mime_type,
534 bool allow_wildcard, 241 bool allow_wildcard,
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 plugin_name.erase(plugin_name.length() - kPluginExtension.length()); 298 plugin_name.erase(plugin_name.length() - kPluginExtension.length());
592 #endif // OS_MACOSX 299 #endif // OS_MACOSX
593 } 300 }
594 return plugin_name; 301 return plugin_name;
595 } 302 }
596 303
597 void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) { 304 void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
598 scoped_refptr<base::SingleThreadTaskRunner> target_task_runner( 305 scoped_refptr<base::SingleThreadTaskRunner> target_task_runner(
599 base::ThreadTaskRunnerHandle::Get()); 306 base::ThreadTaskRunnerHandle::Get());
600 307
601 if (LoadPluginListInProcess()) { 308 BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
602 BrowserThread::GetBlockingPool() 309 plugin_list_token_, FROM_HERE,
603 ->PostSequencedWorkerTaskWithShutdownBehavior( 310 base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this),
604 plugin_list_token_, FROM_HERE, 311 base::RetainedRef(target_task_runner), callback),
605 base::Bind(&PluginServiceImpl::GetPluginsInternal, 312 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
606 base::Unretained(this),
607 base::RetainedRef(target_task_runner), callback),
608 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
609 return;
610 }
611 #if defined(OS_POSIX)
612 BrowserThread::PostTask(
613 BrowserThread::IO, FROM_HERE,
614 base::Bind(&PluginServiceImpl::GetPluginsOnIOThread,
615 base::Unretained(this), base::RetainedRef(target_task_runner),
616 callback));
617 #else
618 NOTREACHED();
619 #endif
620 } 313 }
621 314
622 void PluginServiceImpl::GetPluginsInternal( 315 void PluginServiceImpl::GetPluginsInternal(
623 base::SingleThreadTaskRunner* target_task_runner, 316 base::SingleThreadTaskRunner* target_task_runner,
624 const PluginService::GetPluginsCallback& callback) { 317 const PluginService::GetPluginsCallback& callback) {
625 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( 318 DCHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
626 plugin_list_token_)); 319 plugin_list_token_));
627 320
628 std::vector<WebPluginInfo> plugins; 321 std::vector<WebPluginInfo> plugins;
629 PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported()); 322 PluginList::Singleton()->GetPlugins(&plugins);
630 323
631 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins)); 324 target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
632 } 325 }
633 326
634 #if defined(OS_POSIX)
635 void PluginServiceImpl::GetPluginsOnIOThread(
636 base::SingleThreadTaskRunner* target_task_runner,
637 const GetPluginsCallback& callback) {
638 DCHECK_CURRENTLY_ON(BrowserThread::IO);
639
640 // If we switch back to loading plugins in process, then we need to make
641 // sure g_thread_init() gets called since plugins may call glib at load.
642
643 if (!plugin_loader_.get())
644 plugin_loader_ = new PluginLoaderPosix;
645
646 plugin_loader_->GetPlugins(base::Bind(
647 &ForwardCallback, base::RetainedRef(target_task_runner), callback));
648 }
649 #endif
650
651 #if defined(OS_WIN)
652 void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) {
653 key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged,
654 base::Unretained(this),
655 base::Unretained(key)));
656
657 PluginList::Singleton()->RefreshPlugins();
658 PurgePluginListCache(NULL, false);
659 }
660 #endif // defined(OS_WIN)
661
662 void PluginServiceImpl::RegisterPepperPlugins() { 327 void PluginServiceImpl::RegisterPepperPlugins() {
663 ComputePepperPluginList(&ppapi_plugins_); 328 ComputePepperPluginList(&ppapi_plugins_);
664 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { 329 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
665 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true); 330 RegisterInternalPlugin(ppapi_plugins_[i].ToWebPluginInfo(), true);
666 } 331 }
667 } 332 }
668 333
669 // There should generally be very few plugins so a brute-force search is fine. 334 // There should generally be very few plugins so a brute-force search is fine.
670 PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo( 335 PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
671 const base::FilePath& plugin_path) { 336 const base::FilePath& plugin_path) {
(...skipping 14 matching lines...) Expand all
686 WebPluginInfo webplugin_info; 351 WebPluginInfo webplugin_info;
687 if (!GetPluginInfoByPath(plugin_path, &webplugin_info)) 352 if (!GetPluginInfoByPath(plugin_path, &webplugin_info))
688 return NULL; 353 return NULL;
689 PepperPluginInfo new_pepper_info; 354 PepperPluginInfo new_pepper_info;
690 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info)) 355 if (!MakePepperPluginInfo(webplugin_info, &new_pepper_info))
691 return NULL; 356 return NULL;
692 ppapi_plugins_.push_back(new_pepper_info); 357 ppapi_plugins_.push_back(new_pepper_info);
693 return &ppapi_plugins_[ppapi_plugins_.size() - 1]; 358 return &ppapi_plugins_[ppapi_plugins_.size() - 1];
694 } 359 }
695 360
696 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
697 // static
698 void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
699 const base::FilePath& path) {
700 bool result = watcher->Watch(path, false,
701 base::Bind(&NotifyPluginDirChanged));
702 DCHECK(result);
703 }
704 #endif
705
706 void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) { 361 void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
707 filter_ = filter; 362 filter_ = filter;
708 } 363 }
709 364
710 PluginServiceFilter* PluginServiceImpl::GetFilter() { 365 PluginServiceFilter* PluginServiceImpl::GetFilter() {
711 return filter_; 366 return filter_;
712 } 367 }
713 368
714 void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
715 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
716 BrowserThread::PostTask(
717 BrowserThread::IO, FROM_HERE,
718 base::Bind(&PluginServiceImpl::ForcePluginShutdown,
719 base::Unretained(this), plugin_path));
720 return;
721 }
722
723 PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
724 if (plugin)
725 plugin->ForceShutdown();
726 }
727
728 static const unsigned int kMaxCrashesPerInterval = 3; 369 static const unsigned int kMaxCrashesPerInterval = 3;
729 static const unsigned int kCrashesInterval = 120; 370 static const unsigned int kCrashesInterval = 120;
730 371
731 void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) { 372 void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) {
732 DCHECK_CURRENTLY_ON(BrowserThread::IO); 373 DCHECK_CURRENTLY_ON(BrowserThread::IO);
733 std::map<base::FilePath, std::vector<base::Time> >::iterator i = 374 std::map<base::FilePath, std::vector<base::Time> >::iterator i =
734 crash_times_.find(path); 375 crash_times_.find(path);
735 if (i == crash_times_.end()) { 376 if (i == crash_times_.end()) {
736 crash_times_[path] = std::vector<base::Time>(); 377 crash_times_[path] = std::vector<base::Time>();
737 i = crash_times_.find(path); 378 i = crash_times_.find(path);
(...skipping 16 matching lines...) Expand all
754 return false; 395 return false;
755 } 396 }
756 base::TimeDelta delta = base::Time::Now() - i->second[0]; 397 base::TimeDelta delta = base::Time::Now() - i->second[0];
757 return delta.InSeconds() <= kCrashesInterval; 398 return delta.InSeconds() <= kCrashesInterval;
758 } 399 }
759 400
760 void PluginServiceImpl::RefreshPlugins() { 401 void PluginServiceImpl::RefreshPlugins() {
761 PluginList::Singleton()->RefreshPlugins(); 402 PluginList::Singleton()->RefreshPlugins();
762 } 403 }
763 404
764 void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
765 if (!NPAPIPluginsSupported()) {
766 // TODO(jam): remove and just have CHECK once we're sure this doesn't get
767 // triggered.
768 DVLOG(0) << "NPAPI plugins not supported";
769 return;
770 }
771 PluginList::Singleton()->AddExtraPluginPath(path);
772 }
773
774 void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
775 PluginList::Singleton()->RemoveExtraPluginPath(path);
776 }
777
778 void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
779 PluginList::Singleton()->AddExtraPluginDir(path);
780 }
781
782 void PluginServiceImpl::RegisterInternalPlugin( 405 void PluginServiceImpl::RegisterInternalPlugin(
783 const WebPluginInfo& info, 406 const WebPluginInfo& info,
784 bool add_at_beginning) { 407 bool add_at_beginning) {
785 // Internal plugins should never be NPAPI.
786 CHECK_NE(info.type, WebPluginInfo::PLUGIN_TYPE_NPAPI);
787 if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
788 DVLOG(0) << "Don't register NPAPI plugins when they're not supported";
789 return;
790 }
791 PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning); 408 PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
792 } 409 }
793 410
794 void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) { 411 void PluginServiceImpl::UnregisterInternalPlugin(const base::FilePath& path) {
795 PluginList::Singleton()->UnregisterInternalPlugin(path); 412 PluginList::Singleton()->UnregisterInternalPlugin(path);
796 } 413 }
797 414
798 void PluginServiceImpl::GetInternalPlugins( 415 void PluginServiceImpl::GetInternalPlugins(
799 std::vector<WebPluginInfo>* plugins) { 416 std::vector<WebPluginInfo>* plugins) {
800 PluginList::Singleton()->GetInternalPlugins(plugins); 417 PluginList::Singleton()->GetInternalPlugins(plugins);
801 } 418 }
802 419
803 bool PluginServiceImpl::NPAPIPluginsSupported() {
804 #if defined(OS_WIN) || defined(OS_MACOSX)
805 npapi_plugins_enabled_ = GetContentClient()->browser()->IsNPAPIEnabled();
806 #if defined(OS_WIN)
807 // NPAPI plugins don't play well with Win32k renderer lockdown.
808 if (npapi_plugins_enabled_)
809 DisableWin32kRendererLockdown();
810 #endif
811 NPAPIPluginStatus status =
812 npapi_plugins_enabled_ ? NPAPI_STATUS_ENABLED : NPAPI_STATUS_DISABLED;
813 #else
814 NPAPIPluginStatus status = NPAPI_STATUS_UNSUPPORTED;
815 #endif
816 UMA_HISTOGRAM_ENUMERATION("Plugin.NPAPIStatus", status,
817 NPAPI_STATUS_ENUM_COUNT);
818
819 return npapi_plugins_enabled_;
820 }
821
822 void PluginServiceImpl::DisablePluginsDiscoveryForTesting() {
823 PluginList::Singleton()->DisablePluginsDiscovery();
824 }
825
826 #if defined(OS_MACOSX)
827 void PluginServiceImpl::AppActivated() {
828 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
829 base::Bind(&NotifyPluginsOfActivation));
830 }
831 #endif
832
833 bool PluginServiceImpl::PpapiDevChannelSupported( 420 bool PluginServiceImpl::PpapiDevChannelSupported(
834 BrowserContext* browser_context, 421 BrowserContext* browser_context,
835 const GURL& document_url) { 422 const GURL& document_url) {
836 return GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs( 423 return GetContentClient()->browser()->IsPluginAllowedToUseDevChannelAPIs(
837 browser_context, document_url); 424 browser_context, document_url);
838 } 425 }
839 426
840 } // namespace content 427 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/plugin_service_impl.h ('k') | content/browser/renderer_host/render_process_host_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698