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

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

Powered by Google App Engine
This is Rietveld 408576698