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

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

Issue 7387010: Add PluginServiceFilter interface. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Move PluginFilter into content:: Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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.h" 5 #include "content/browser/plugin_service.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/file_path.h"
11 #include "base/path_service.h" 12 #include "base/path_service.h"
12 #include "base/string_util.h" 13 #include "base/string_util.h"
13 #include "base/synchronization/waitable_event.h" 14 #include "base/synchronization/waitable_event.h"
14 #include "base/threading/thread.h" 15 #include "base/threading/thread.h"
15 #include "base/utf_string_conversions.h" 16 #include "base/utf_string_conversions.h"
16 #include "base/values.h" 17 #include "base/values.h"
17 #include "content/browser/browser_thread.h" 18 #include "content/browser/browser_thread.h"
18 #include "content/browser/content_browser_client.h" 19 #include "content/browser/content_browser_client.h"
20 #include "content/browser/plugin_filter.h"
19 #include "content/browser/ppapi_plugin_process_host.h" 21 #include "content/browser/ppapi_plugin_process_host.h"
20 #include "content/browser/renderer_host/render_process_host.h" 22 #include "content/browser/renderer_host/render_process_host.h"
21 #include "content/browser/renderer_host/render_view_host.h" 23 #include "content/browser/renderer_host/render_view_host.h"
22 #include "content/browser/resource_context.h" 24 #include "content/browser/resource_context.h"
23 #include "content/common/content_notification_types.h" 25 #include "content/common/content_notification_types.h"
24 #include "content/common/content_switches.h" 26 #include "content/common/content_switches.h"
25 #include "content/common/notification_service.h" 27 #include "content/common/notification_service.h"
26 #include "content/common/pepper_plugin_registry.h" 28 #include "content/common/pepper_plugin_registry.h"
27 #include "content/common/plugin_messages.h" 29 #include "content/common/plugin_messages.h"
28 #include "content/common/view_messages.h" 30 #include "content/common/view_messages.h"
29 #include "webkit/plugins/npapi/plugin_constants_win.h" 31 #include "webkit/plugins/npapi/plugin_constants_win.h"
30 #include "webkit/plugins/npapi/plugin_list.h" 32 #include "webkit/plugins/npapi/plugin_list.h"
31 #include "webkit/plugins/npapi/webplugininfo.h" 33 #include "webkit/plugins/npapi/webplugininfo.h"
32 34
33 #if defined(OS_POSIX) && !defined(OS_MACOSX) 35 #if defined(OS_POSIX) && !defined(OS_MACOSX)
34 using ::base::files::FilePathWatcher; 36 using ::base::files::FilePathWatcher;
35 #endif 37 #endif
36 38
39 using content::PluginFilter;
40
37 #if defined(OS_MACOSX) 41 #if defined(OS_MACOSX)
38 static void NotifyPluginsOfActivation() { 42 static void NotifyPluginsOfActivation() {
39 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
40 44
41 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS); 45 for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::PLUGIN_PROCESS);
42 !iter.Done(); ++iter) { 46 !iter.Done(); ++iter) {
43 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter); 47 PluginProcessHost* plugin = static_cast<PluginProcessHost*>(*iter);
44 plugin->OnAppActivation(); 48 plugin->OnAppActivation();
45 } 49 }
46 } 50 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 FilePathWatcher* watcher = new FilePathWatcher(); 131 FilePathWatcher* watcher = new FilePathWatcher();
128 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value(); 132 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
129 BrowserThread::PostTask( 133 BrowserThread::PostTask(
130 BrowserThread::FILE, FROM_HERE, 134 BrowserThread::FILE, FROM_HERE,
131 NewRunnableFunction( 135 NewRunnableFunction(
132 &PluginService::RegisterFilePathWatcher, 136 &PluginService::RegisterFilePathWatcher,
133 watcher, plugin_dirs[i], file_watcher_delegate_)); 137 watcher, plugin_dirs[i], file_watcher_delegate_));
134 file_watchers_.push_back(watcher); 138 file_watchers_.push_back(watcher);
135 } 139 }
136 #endif 140 #endif
137 registrar_.Add(this, content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED,
138 NotificationService::AllSources());
139 registrar_.Add(this,
140 content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
141 NotificationService::AllSources());
142 } 141 }
143 142
144 PluginService::~PluginService() { 143 PluginService::~PluginService() {
145 #if defined(OS_WIN) 144 #if defined(OS_WIN)
146 // Release the events since they're owned by RegKey, not WaitableEvent. 145 // Release the events since they're owned by RegKey, not WaitableEvent.
147 hkcu_watcher_.StopWatching(); 146 hkcu_watcher_.StopWatching();
148 hklm_watcher_.StopWatching(); 147 hklm_watcher_.StopWatching();
149 if (hkcu_event_.get()) 148 if (hkcu_event_.get())
150 hkcu_event_->Release(); 149 hkcu_event_->Release();
151 if (hklm_event_.get()) 150 if (hklm_event_.get())
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 NOTREACHED(); // Init is not expected to fail. 272 NOTREACHED(); // Init is not expected to fail.
274 return NULL; 273 return NULL;
275 } 274 }
276 return new_host.release(); 275 return new_host.release();
277 } 276 }
278 277
279 void PluginService::OpenChannelToNpapiPlugin( 278 void PluginService::OpenChannelToNpapiPlugin(
280 int render_process_id, 279 int render_process_id,
281 int render_view_id, 280 int render_view_id,
282 const GURL& url, 281 const GURL& url,
282 const GURL& page_url,
283 const std::string& mime_type, 283 const std::string& mime_type,
284 PluginProcessHost::Client* client) { 284 PluginProcessHost::Client* client) {
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
286 PluginFilter* filter =
287 content::GetContentClient()->browser()->CreatePluginFilter(
288 render_process_id, render_view_id, *client->GetResourceContext(),
289 url, page_url);
285 // The PluginList::GetPluginInfo may need to load the plugins. Don't do it on 290 // The PluginList::GetPluginInfo may need to load the plugins. Don't do it on
286 // the IO thread. 291 // the IO thread.
287 BrowserThread::PostTask( 292 BrowserThread::PostTask(
288 BrowserThread::FILE, FROM_HERE, 293 BrowserThread::FILE, FROM_HERE,
289 NewRunnableMethod( 294 NewRunnableMethod(
290 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, 295 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin,
291 render_process_id, render_view_id, url, mime_type, client)); 296 url, mime_type, filter, client));
292 } 297 }
293 298
294 void PluginService::OpenChannelToPpapiPlugin( 299 void PluginService::OpenChannelToPpapiPlugin(
295 const FilePath& path, 300 const FilePath& path,
296 PpapiPluginProcessHost::Client* client) { 301 PpapiPluginProcessHost::Client* client) {
297 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess( 302 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
298 path, client); 303 path, client);
299 if (plugin_host) 304 if (plugin_host)
300 plugin_host->OpenChannelToPlugin(client); 305 plugin_host->OpenChannelToPlugin(client);
301 else // Send error. 306 else // Send error.
302 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); 307 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
303 } 308 }
304 309
305 void PluginService::OpenChannelToPpapiBroker( 310 void PluginService::OpenChannelToPpapiBroker(
306 const FilePath& path, 311 const FilePath& path,
307 PpapiBrokerProcessHost::Client* client) { 312 PpapiBrokerProcessHost::Client* client) {
308 PpapiBrokerProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path); 313 PpapiBrokerProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
309 if (plugin_host) 314 if (plugin_host)
310 plugin_host->OpenChannelToPpapiBroker(client); 315 plugin_host->OpenChannelToPpapiBroker(client);
311 else // Send error. 316 else // Send error.
312 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); 317 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
313 } 318 }
314 319
315 void PluginService::GetAllowedPluginForOpenChannelToPlugin( 320 void PluginService::GetAllowedPluginForOpenChannelToPlugin(
316 int render_process_id,
317 int render_view_id,
318 const GURL& url, 321 const GURL& url,
319 const std::string& mime_type, 322 const std::string& mime_type,
323 PluginFilter* filter,
320 PluginProcessHost::Client* client) { 324 PluginProcessHost::Client* client) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
322 webkit::npapi::WebPluginInfo info; 326 webkit::npapi::WebPluginInfo info;
323 bool found = GetPluginInfo( 327 bool allow_wildcard = true;
324 render_process_id, render_view_id, url, mime_type, &info, NULL); 328 bool found = GetPluginInfo(url, mime_type, allow_wildcard, filter,
329 NULL, &info, NULL);
325 FilePath plugin_path; 330 FilePath plugin_path;
326 if (found) 331 if (found)
327 plugin_path = FilePath(info.path); 332 plugin_path = info.path;
328 333
329 // Now we jump back to the IO thread to finish opening the channel. 334 // Now we jump back to the IO thread to finish opening the channel.
330 BrowserThread::PostTask( 335 BrowserThread::PostTask(
331 BrowserThread::IO, FROM_HERE, 336 BrowserThread::IO, FROM_HERE,
332 NewRunnableMethod( 337 NewRunnableMethod(
333 this, &PluginService::FinishOpenChannelToPlugin, 338 this, &PluginService::FinishOpenChannelToPlugin,
334 plugin_path, client)); 339 plugin_path, client));
335 } 340 }
336 341
337 void PluginService::FinishOpenChannelToPlugin( 342 void PluginService::FinishOpenChannelToPlugin(
338 const FilePath& plugin_path, 343 const FilePath& plugin_path,
339 PluginProcessHost::Client* client) { 344 PluginProcessHost::Client* client) {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 345 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
341 346
342 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path); 347 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
343 if (plugin_host) 348 if (plugin_host)
344 plugin_host->OpenChannelToPlugin(client); 349 plugin_host->OpenChannelToPlugin(client);
345 else 350 else
346 client->OnError(); 351 client->OnError();
347 } 352 }
348 353
349 bool PluginService::GetPluginInfo(int render_process_id, 354 bool PluginService::GetPluginInfo(
350 int render_view_id, 355 const GURL& url,
351 const GURL& url, 356 const std::string& mime_type,
352 const std::string& mime_type, 357 bool allow_wildcard,
353 webkit::npapi::WebPluginInfo* info, 358 PluginFilter* filter,
354 std::string* actual_mime_type) { 359 bool* use_stale,
360 webkit::npapi::WebPluginInfo* info,
361 std::string* actual_mime_type) {
362 scoped_ptr<PluginFilter> owned_filter(filter);
363 webkit::npapi::PluginList* plugin_list =
364 webkit::npapi::PluginList::Singleton();
355 // GetPluginInfoArray may need to load the plugins, so we need to be 365 // GetPluginInfoArray may need to load the plugins, so we need to be
356 // on the FILE thread. 366 // on the FILE thread.
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 367 DCHECK(use_stale || BrowserThread::CurrentlyOn(BrowserThread::FILE));
358 {
359 base::AutoLock auto_lock(overridden_plugins_lock_);
360 for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
361 if (overridden_plugins_[i].render_process_id == render_process_id &&
362 overridden_plugins_[i].render_view_id == render_view_id &&
363 overridden_plugins_[i].url == url) {
364 if (actual_mime_type)
365 *actual_mime_type = mime_type;
366 *info = overridden_plugins_[i].plugin;
367 return true;
368 }
369 }
370 }
371 bool allow_wildcard = true;
372 std::vector<webkit::npapi::WebPluginInfo> plugins; 368 std::vector<webkit::npapi::WebPluginInfo> plugins;
373 std::vector<std::string> mime_types; 369 std::vector<std::string> mime_types;
374 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( 370 plugin_list->GetPluginInfoArray(
375 url, mime_type, allow_wildcard, NULL, &plugins, &mime_types); 371 url, mime_type, allow_wildcard, use_stale, &plugins, &mime_types);
376 for (size_t i = 0; i < plugins.size(); ++i) { 372 for (size_t i = 0; i < plugins.size(); ++i) {
377 if (webkit::npapi::IsPluginEnabled(plugins[i])) { 373 if (filter->ShouldUsePlugin(&plugins[i])) {
378 *info = plugins[i]; 374 *info = plugins[i];
379 if (actual_mime_type) 375 if (actual_mime_type)
380 *actual_mime_type = mime_types[i]; 376 *actual_mime_type = mime_types[i];
381 return true; 377 return true;
382 } 378 }
383 } 379 }
384 return false; 380 return false;
385 } 381 }
386 382
383 void PluginService::GetPlugins(
384 PluginFilter* filter,
385 std::vector<webkit::npapi::WebPluginInfo>* plugins) {
386 scoped_ptr<PluginFilter> owned_filter(filter);
387 webkit::npapi::PluginList* plugin_list =
388 webkit::npapi::PluginList::Singleton();
389 // GetPluginInfoArray may need to load the plugins, so we need to be
390 // on the FILE thread.
391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
392 std::vector<webkit::npapi::WebPluginInfo> all_plugins;
393 plugin_list->GetPlugins(&all_plugins);
394 for (size_t i = 0; i < all_plugins.size(); ++i) {
395 if (filter->ShouldUsePlugin(&all_plugins[i]))
396 plugins->push_back(all_plugins[i]);
397 }
398 }
399
387 void PluginService::OnWaitableEventSignaled( 400 void PluginService::OnWaitableEventSignaled(
388 base::WaitableEvent* waitable_event) { 401 base::WaitableEvent* waitable_event) {
389 #if defined(OS_WIN) 402 #if defined(OS_WIN)
390 if (waitable_event == hkcu_event_.get()) { 403 if (waitable_event == hkcu_event_.get()) {
391 hkcu_key_.StartWatching(); 404 hkcu_key_.StartWatching();
392 } else { 405 } else {
393 hklm_key_.StartWatching(); 406 hklm_key_.StartWatching();
394 } 407 }
395 408
396 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); 409 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
397 PurgePluginListCache(true); 410 PurgePluginListCache(true);
398 #else 411 #else
399 // This event should only get signaled on a Windows machine. 412 // This event should only get signaled on a Windows machine.
400 NOTREACHED(); 413 NOTREACHED();
401 #endif // defined(OS_WIN) 414 #endif // defined(OS_WIN)
402 } 415 }
403 416
404 void PluginService::Observe(int type, 417 void PluginService::Observe(int type,
405 const NotificationSource& source, 418 const NotificationSource& source,
406 const NotificationDetails& details) { 419 const NotificationDetails& details) {
407 switch (type) {
408 #if defined(OS_MACOSX) 420 #if defined(OS_MACOSX)
409 case content::NOTIFICATION_APP_ACTIVATED: { 421 if (type == content::NOTIFICATION_APP_ACTIVATED) {
410 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 422 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
411 NewRunnableFunction(&NotifyPluginsOfActivation)); 423 NewRunnableFunction(&NotifyPluginsOfActivation));
412 break; 424 return;
413 } 425 }
414 #endif 426 #endif
415 427 NOTREACHED();
416 case content::NOTIFICATION_PLUGIN_ENABLE_STATUS_CHANGED: {
417 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
418 PurgePluginListCache(false);
419 break;
420 }
421 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
422 int render_process_id = Source<RenderProcessHost>(source).ptr()->id();
423
424 base::AutoLock auto_lock(overridden_plugins_lock_);
425 for (size_t i = 0; i < overridden_plugins_.size(); ++i) {
426 if (overridden_plugins_[i].render_process_id == render_process_id) {
427 overridden_plugins_.erase(overridden_plugins_.begin() + i);
428 break;
429 }
430 }
431 break;
432 }
433 default:
434 NOTREACHED();
435 }
436 }
437
438 void PluginService::OverridePluginForTab(const OverriddenPlugin& plugin) {
439 base::AutoLock auto_lock(overridden_plugins_lock_);
440 overridden_plugins_.push_back(plugin);
441 } 428 }
442 429
443 void PluginService::PurgePluginListCache(bool reload_pages) { 430 void PluginService::PurgePluginListCache(bool reload_pages) {
444 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); 431 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
445 !it.IsAtEnd(); it.Advance()) { 432 !it.IsAtEnd(); it.Advance()) {
446 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages)); 433 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
447 } 434 }
448 } 435 }
449 436
450 void PluginService::RestrictPluginToUrl(const FilePath& plugin_path,
451 const GURL& url) {
452 base::AutoLock auto_lock(restricted_plugin_lock_);
453 if (url.is_empty()) {
454 restricted_plugin_.erase(plugin_path);
455 } else {
456 restricted_plugin_[plugin_path] = url;
457 }
458 }
459
460 bool PluginService::PluginAllowedForURL(const FilePath& plugin_path,
461 const GURL& url) {
462 if (url.is_empty())
463 return true; // Caller wants all plugins.
464
465 base::AutoLock auto_lock(restricted_plugin_lock_);
466
467 RestrictedPluginMap::iterator it = restricted_plugin_.find(plugin_path);
468 if (it == restricted_plugin_.end())
469 return true; // This plugin is not restricted, so it's allowed everywhere.
470
471 const GURL& required_url = it->second;
472 return (url.scheme() == required_url.scheme() &&
473 url.host() == required_url.host());
474 }
475
476 void PluginService::RegisterPepperPlugins() { 437 void PluginService::RegisterPepperPlugins() {
477 // TODO(abarth): It seems like the PepperPluginRegistry should do this work. 438 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
478 PepperPluginRegistry::ComputeList(&ppapi_plugins_); 439 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
479 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { 440 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
480 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin( 441 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(
481 ppapi_plugins_[i].ToWebPluginInfo()); 442 ppapi_plugins_[i].ToWebPluginInfo());
482 } 443 }
483 } 444 }
484 445
485 // There should generally be very few plugins so a brute-force search is fine. 446 // There should generally be very few plugins so a brute-force search is fine.
(...skipping 12 matching lines...) Expand all
498 #if defined(OS_POSIX) && !defined(OS_MACOSX) 459 #if defined(OS_POSIX) && !defined(OS_MACOSX)
499 // static 460 // static
500 void PluginService::RegisterFilePathWatcher( 461 void PluginService::RegisterFilePathWatcher(
501 FilePathWatcher *watcher, 462 FilePathWatcher *watcher,
502 const FilePath& path, 463 const FilePath& path,
503 FilePathWatcher::Delegate* delegate) { 464 FilePathWatcher::Delegate* delegate) {
504 bool result = watcher->Watch(path, delegate); 465 bool result = watcher->Watch(path, delegate);
505 DCHECK(result); 466 DCHECK(result);
506 } 467 }
507 #endif 468 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698