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

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: review 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"
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 FilePathWatcher* watcher = new FilePathWatcher(); 129 FilePathWatcher* watcher = new FilePathWatcher();
128 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value(); 130 VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
129 BrowserThread::PostTask( 131 BrowserThread::PostTask(
130 BrowserThread::FILE, FROM_HERE, 132 BrowserThread::FILE, FROM_HERE,
131 NewRunnableFunction( 133 NewRunnableFunction(
132 &PluginService::RegisterFilePathWatcher, 134 &PluginService::RegisterFilePathWatcher,
133 watcher, plugin_dirs[i], file_watcher_delegate_)); 135 watcher, plugin_dirs[i], file_watcher_delegate_));
134 file_watchers_.push_back(watcher); 136 file_watchers_.push_back(watcher);
135 } 137 }
136 #endif 138 #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 } 139 }
143 140
144 PluginService::~PluginService() { 141 PluginService::~PluginService() {
145 #if defined(OS_WIN) 142 #if defined(OS_WIN)
146 // Release the events since they're owned by RegKey, not WaitableEvent. 143 // Release the events since they're owned by RegKey, not WaitableEvent.
147 hkcu_watcher_.StopWatching(); 144 hkcu_watcher_.StopWatching();
148 hklm_watcher_.StopWatching(); 145 hklm_watcher_.StopWatching();
149 if (hkcu_event_.get()) 146 if (hkcu_event_.get())
150 hkcu_event_->Release(); 147 hkcu_event_->Release();
151 if (hklm_event_.get()) 148 if (hklm_event_.get())
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 NOTREACHED(); // Init is not expected to fail. 270 NOTREACHED(); // Init is not expected to fail.
274 return NULL; 271 return NULL;
275 } 272 }
276 return new_host.release(); 273 return new_host.release();
277 } 274 }
278 275
279 void PluginService::OpenChannelToNpapiPlugin( 276 void PluginService::OpenChannelToNpapiPlugin(
280 int render_process_id, 277 int render_process_id,
281 int render_view_id, 278 int render_view_id,
282 const GURL& url, 279 const GURL& url,
280 const GURL& page_url,
283 const std::string& mime_type, 281 const std::string& mime_type,
284 PluginProcessHost::Client* client) { 282 PluginProcessHost::Client* client) {
283 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
284 PluginFilter* filter =
285 content::GetContentClient()->browser()->CreatePluginFilter(
286 render_process_id, render_view_id, *client->GetResourceContext(),
287 url, page_url);
285 // The PluginList::GetPluginInfo may need to load the plugins. Don't do it on 288 // The PluginList::GetPluginInfo may need to load the plugins. Don't do it on
286 // the IO thread. 289 // the IO thread.
287 BrowserThread::PostTask( 290 BrowserThread::PostTask(
288 BrowserThread::FILE, FROM_HERE, 291 BrowserThread::FILE, FROM_HERE,
289 NewRunnableMethod( 292 NewRunnableMethod(
290 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin, 293 this, &PluginService::GetAllowedPluginForOpenChannelToPlugin,
291 render_process_id, render_view_id, url, mime_type, client)); 294 url, mime_type, filter, client));
292 } 295 }
293 296
294 void PluginService::OpenChannelToPpapiPlugin( 297 void PluginService::OpenChannelToPpapiPlugin(
295 const FilePath& path, 298 const FilePath& path,
296 PpapiPluginProcessHost::Client* client) { 299 PpapiPluginProcessHost::Client* client) {
297 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess( 300 PpapiPluginProcessHost* plugin_host = FindOrStartPpapiPluginProcess(
298 path, client); 301 path, client);
299 if (plugin_host) 302 if (plugin_host)
300 plugin_host->OpenChannelToPlugin(client); 303 plugin_host->OpenChannelToPlugin(client);
301 else // Send error. 304 else // Send error.
302 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); 305 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
303 } 306 }
304 307
305 void PluginService::OpenChannelToPpapiBroker( 308 void PluginService::OpenChannelToPpapiBroker(
306 const FilePath& path, 309 const FilePath& path,
307 PpapiBrokerProcessHost::Client* client) { 310 PpapiBrokerProcessHost::Client* client) {
308 PpapiBrokerProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path); 311 PpapiBrokerProcessHost* plugin_host = FindOrStartPpapiBrokerProcess(path);
309 if (plugin_host) 312 if (plugin_host)
310 plugin_host->OpenChannelToPpapiBroker(client); 313 plugin_host->OpenChannelToPpapiBroker(client);
311 else // Send error. 314 else // Send error.
312 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle()); 315 client->OnChannelOpened(base::kNullProcessHandle, IPC::ChannelHandle());
313 } 316 }
314 317
315 void PluginService::GetAllowedPluginForOpenChannelToPlugin( 318 void PluginService::GetAllowedPluginForOpenChannelToPlugin(
316 int render_process_id,
317 int render_view_id,
318 const GURL& url, 319 const GURL& url,
319 const std::string& mime_type, 320 const std::string& mime_type,
321 PluginFilter* filter,
320 PluginProcessHost::Client* client) { 322 PluginProcessHost::Client* client) {
321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
322 webkit::npapi::WebPluginInfo info; 324 webkit::npapi::WebPluginInfo info;
323 bool found = GetPluginInfo( 325 bool allow_wildcard = true;
324 render_process_id, render_view_id, url, mime_type, &info, NULL); 326 bool found = GetPluginInfo(url, mime_type, allow_wildcard, filter,
327 NULL, &info, NULL);
325 FilePath plugin_path; 328 FilePath plugin_path;
326 if (found) 329 if (found)
327 plugin_path = FilePath(info.path); 330 plugin_path = info.path;
328 331
329 // Now we jump back to the IO thread to finish opening the channel. 332 // Now we jump back to the IO thread to finish opening the channel.
330 BrowserThread::PostTask( 333 BrowserThread::PostTask(
331 BrowserThread::IO, FROM_HERE, 334 BrowserThread::IO, FROM_HERE,
332 NewRunnableMethod( 335 NewRunnableMethod(
333 this, &PluginService::FinishOpenChannelToPlugin, 336 this, &PluginService::FinishOpenChannelToPlugin,
334 plugin_path, client)); 337 plugin_path, client));
335 } 338 }
336 339
337 void PluginService::FinishOpenChannelToPlugin( 340 void PluginService::FinishOpenChannelToPlugin(
338 const FilePath& plugin_path, 341 const FilePath& plugin_path,
339 PluginProcessHost::Client* client) { 342 PluginProcessHost::Client* client) {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
341 344
342 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path); 345 PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(plugin_path);
343 if (plugin_host) 346 if (plugin_host)
344 plugin_host->OpenChannelToPlugin(client); 347 plugin_host->OpenChannelToPlugin(client);
345 else 348 else
346 client->OnError(); 349 client->OnError();
347 } 350 }
348 351
349 bool PluginService::GetPluginInfo(int render_process_id, 352 bool PluginService::GetPluginInfo(
350 int render_view_id, 353 const GURL& url,
351 const GURL& url, 354 const std::string& mime_type,
352 const std::string& mime_type, 355 bool allow_wildcard,
353 webkit::npapi::WebPluginInfo* info, 356 PluginFilter* filter,
354 std::string* actual_mime_type) { 357 bool* use_stale,
358 webkit::npapi::WebPluginInfo* info,
359 std::string* actual_mime_type) {
360 scoped_ptr<PluginFilter> owned_filter(filter);
361 webkit::npapi::PluginList* plugin_list =
362 webkit::npapi::PluginList::Singleton();
355 // GetPluginInfoArray may need to load the plugins, so we need to be 363 // GetPluginInfoArray may need to load the plugins, so we need to be
356 // on the FILE thread. 364 // on the FILE thread.
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 365 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; 366 std::vector<webkit::npapi::WebPluginInfo> plugins;
373 std::vector<std::string> mime_types; 367 std::vector<std::string> mime_types;
374 webkit::npapi::PluginList::Singleton()->GetPluginInfoArray( 368 plugin_list->GetPluginInfoArray(
375 url, mime_type, allow_wildcard, NULL, &plugins, &mime_types); 369 url, mime_type, allow_wildcard, use_stale, &plugins, &mime_types);
376 for (size_t i = 0; i < plugins.size(); ++i) { 370 for (size_t i = 0; i < plugins.size(); ++i) {
377 if (webkit::npapi::IsPluginEnabled(plugins[i])) { 371 if (filter->ShouldUsePlugin(&plugins[i])) {
378 *info = plugins[i]; 372 *info = plugins[i];
379 if (actual_mime_type) 373 if (actual_mime_type)
380 *actual_mime_type = mime_types[i]; 374 *actual_mime_type = mime_types[i];
381 return true; 375 return true;
382 } 376 }
383 } 377 }
384 return false; 378 return false;
385 } 379 }
386 380
381 void PluginService::GetPlugins(
382 PluginFilter* filter,
383 std::vector<webkit::npapi::WebPluginInfo>* plugins) {
384 scoped_ptr<PluginFilter> owned_filter(filter);
385 webkit::npapi::PluginList* plugin_list =
386 webkit::npapi::PluginList::Singleton();
387 // GetPluginInfoArray may need to load the plugins, so we need to be
388 // on the FILE thread.
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
390 std::vector<webkit::npapi::WebPluginInfo> all_plugins;
391 plugin_list->GetPlugins(&all_plugins);
392 for (size_t i = 0; i < all_plugins.size(); ++i) {
393 if (filter->ShouldUsePlugin(&all_plugins[i]))
394 plugins->push_back(all_plugins[i]);
395 }
396 }
397
387 void PluginService::OnWaitableEventSignaled( 398 void PluginService::OnWaitableEventSignaled(
388 base::WaitableEvent* waitable_event) { 399 base::WaitableEvent* waitable_event) {
389 #if defined(OS_WIN) 400 #if defined(OS_WIN)
390 if (waitable_event == hkcu_event_.get()) { 401 if (waitable_event == hkcu_event_.get()) {
391 hkcu_key_.StartWatching(); 402 hkcu_key_.StartWatching();
392 } else { 403 } else {
393 hklm_key_.StartWatching(); 404 hklm_key_.StartWatching();
394 } 405 }
395 406
396 webkit::npapi::PluginList::Singleton()->RefreshPlugins(); 407 webkit::npapi::PluginList::Singleton()->RefreshPlugins();
397 PurgePluginListCache(true); 408 PurgePluginListCache(true);
398 #else 409 #else
399 // This event should only get signaled on a Windows machine. 410 // This event should only get signaled on a Windows machine.
400 NOTREACHED(); 411 NOTREACHED();
401 #endif // defined(OS_WIN) 412 #endif // defined(OS_WIN)
402 } 413 }
403 414
404 void PluginService::Observe(int type, 415 void PluginService::Observe(int type,
405 const NotificationSource& source, 416 const NotificationSource& source,
406 const NotificationDetails& details) { 417 const NotificationDetails& details) {
407 switch (type) {
408 #if defined(OS_MACOSX) 418 #if defined(OS_MACOSX)
409 case content::NOTIFICATION_APP_ACTIVATED: { 419 if (type == content::NOTIFICATION_APP_ACTIVATED) {
410 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 420 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
411 NewRunnableFunction(&NotifyPluginsOfActivation)); 421 NewRunnableFunction(&NotifyPluginsOfActivation));
412 break; 422 return;
413 } 423 }
414 #endif 424 #endif
415 425 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 } 426 }
442 427
443 void PluginService::PurgePluginListCache(bool reload_pages) { 428 void PluginService::PurgePluginListCache(bool reload_pages) {
444 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator(); 429 for (RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
445 !it.IsAtEnd(); it.Advance()) { 430 !it.IsAtEnd(); it.Advance()) {
446 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages)); 431 it.GetCurrentValue()->Send(new ViewMsg_PurgePluginListCache(reload_pages));
447 } 432 }
448 } 433 }
449 434
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() { 435 void PluginService::RegisterPepperPlugins() {
477 // TODO(abarth): It seems like the PepperPluginRegistry should do this work. 436 // TODO(abarth): It seems like the PepperPluginRegistry should do this work.
478 PepperPluginRegistry::ComputeList(&ppapi_plugins_); 437 PepperPluginRegistry::ComputeList(&ppapi_plugins_);
479 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { 438 for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
480 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin( 439 webkit::npapi::PluginList::Singleton()->RegisterInternalPlugin(
481 ppapi_plugins_[i].ToWebPluginInfo()); 440 ppapi_plugins_[i].ToWebPluginInfo());
482 } 441 }
483 } 442 }
484 443
485 // There should generally be very few plugins so a brute-force search is fine. 444 // 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) 457 #if defined(OS_POSIX) && !defined(OS_MACOSX)
499 // static 458 // static
500 void PluginService::RegisterFilePathWatcher( 459 void PluginService::RegisterFilePathWatcher(
501 FilePathWatcher *watcher, 460 FilePathWatcher *watcher,
502 const FilePath& path, 461 const FilePath& path,
503 FilePathWatcher::Delegate* delegate) { 462 FilePathWatcher::Delegate* delegate) {
504 bool result = watcher->Watch(path, delegate); 463 bool result = watcher->Watch(path, delegate);
505 DCHECK(result); 464 DCHECK(result);
506 } 465 }
507 #endif 466 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698