| OLD | NEW | 
|---|
| 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 "base/bind.h" | 7 #include "base/bind.h" | 
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" | 
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" | 
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 92   if (LoadPluginListInProcess()) { | 92   if (LoadPluginListInProcess()) { | 
| 93     CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( | 93     CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( | 
| 94         token)); | 94         token)); | 
| 95   } else { | 95   } else { | 
| 96     CHECK(false) << "Plugin loading should happen out-of-process."; | 96     CHECK(false) << "Plugin loading should happen out-of-process."; | 
| 97   } | 97   } | 
| 98 } | 98 } | 
| 99 | 99 | 
| 100 #if defined(OS_MACOSX) | 100 #if defined(OS_MACOSX) | 
| 101 void NotifyPluginsOfActivation() { | 101 void NotifyPluginsOfActivation() { | 
| 102   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 102   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 103 | 103 | 
| 104   for (PluginProcessHostIterator iter; !iter.Done(); ++iter) | 104   for (PluginProcessHostIterator iter; !iter.Done(); ++iter) | 
| 105     iter->OnAppActivation(); | 105     iter->OnAppActivation(); | 
| 106 } | 106 } | 
| 107 #endif | 107 #endif | 
| 108 | 108 | 
| 109 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) | 109 #if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) | 
| 110 void NotifyPluginDirChanged(const base::FilePath& path, bool error) { | 110 void NotifyPluginDirChanged(const base::FilePath& path, bool error) { | 
| 111   if (error) { | 111   if (error) { | 
| 112     // TODO(pastarmovj): Add some sensible error handling. Maybe silently | 112     // TODO(pastarmovj): Add some sensible error handling. Maybe silently | 
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 270     if (iter->plugin_path() == broker_path) | 270     if (iter->plugin_path() == broker_path) | 
| 271       return *iter; | 271       return *iter; | 
| 272   } | 272   } | 
| 273 | 273 | 
| 274   return NULL; | 274   return NULL; | 
| 275 } | 275 } | 
| 276 | 276 | 
| 277 PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess( | 277 PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess( | 
| 278     int render_process_id, | 278     int render_process_id, | 
| 279     const base::FilePath& plugin_path) { | 279     const base::FilePath& plugin_path) { | 
| 280   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 280   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 281 | 281 | 
| 282   if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) | 282   if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) | 
| 283     return NULL; | 283     return NULL; | 
| 284 | 284 | 
| 285   PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); | 285   PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); | 
| 286   if (plugin_host) | 286   if (plugin_host) | 
| 287     return plugin_host; | 287     return plugin_host; | 
| 288 | 288 | 
| 289   WebPluginInfo info; | 289   WebPluginInfo info; | 
| 290   if (!GetPluginInfoByPath(plugin_path, &info)) { | 290   if (!GetPluginInfoByPath(plugin_path, &info)) { | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 311     NOTREACHED();  // Init is not expected to fail. | 311     NOTREACHED();  // Init is not expected to fail. | 
| 312     return NULL; | 312     return NULL; | 
| 313   } | 313   } | 
| 314   return new_host.release(); | 314   return new_host.release(); | 
| 315 } | 315 } | 
| 316 | 316 | 
| 317 PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( | 317 PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( | 
| 318     int render_process_id, | 318     int render_process_id, | 
| 319     const base::FilePath& plugin_path, | 319     const base::FilePath& plugin_path, | 
| 320     const base::FilePath& profile_data_directory) { | 320     const base::FilePath& profile_data_directory) { | 
| 321   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 321   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 322 | 322 | 
| 323   if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) { | 323   if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) { | 
| 324     VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII(); | 324     VLOG(1) << "Unable to load ppapi plugin: " << plugin_path.MaybeAsASCII(); | 
| 325     return NULL; | 325     return NULL; | 
| 326   } | 326   } | 
| 327 | 327 | 
| 328   PpapiPluginProcessHost* plugin_host = | 328   PpapiPluginProcessHost* plugin_host = | 
| 329       FindPpapiPluginProcess(plugin_path, profile_data_directory); | 329       FindPpapiPluginProcess(plugin_path, profile_data_directory); | 
| 330   if (plugin_host) | 330   if (plugin_host) | 
| 331     return plugin_host; | 331     return plugin_host; | 
| (...skipping 22 matching lines...) Expand all  Loading... | 
| 354     VLOG(1) << "Unable to create ppapi plugin process for: " | 354     VLOG(1) << "Unable to create ppapi plugin process for: " | 
| 355             << plugin_path.MaybeAsASCII(); | 355             << plugin_path.MaybeAsASCII(); | 
| 356   } | 356   } | 
| 357 | 357 | 
| 358   return plugin_host; | 358   return plugin_host; | 
| 359 } | 359 } | 
| 360 | 360 | 
| 361 PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess( | 361 PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess( | 
| 362     int render_process_id, | 362     int render_process_id, | 
| 363     const base::FilePath& plugin_path) { | 363     const base::FilePath& plugin_path) { | 
| 364   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 364   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 365 | 365 | 
| 366   if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) | 366   if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) | 
| 367     return NULL; | 367     return NULL; | 
| 368 | 368 | 
| 369   PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path); | 369   PpapiPluginProcessHost* plugin_host = FindPpapiBrokerProcess(plugin_path); | 
| 370   if (plugin_host) | 370   if (plugin_host) | 
| 371     return plugin_host; | 371     return plugin_host; | 
| 372 | 372 | 
| 373   // Validate that the plugin is actually registered. | 373   // Validate that the plugin is actually registered. | 
| 374   PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path); | 374   PepperPluginInfo* info = GetRegisteredPpapiPluginInfo(plugin_path); | 
| 375   if (!info) | 375   if (!info) | 
| 376     return NULL; | 376     return NULL; | 
| 377 | 377 | 
| 378   // TODO(ddorwin): Uncomment once out of process is supported. | 378   // TODO(ddorwin): Uncomment once out of process is supported. | 
| 379   // DCHECK(info->is_out_of_process); | 379   // DCHECK(info->is_out_of_process); | 
| 380 | 380 | 
| 381   // This broker isn't loaded by any broker process, so create a new process. | 381   // This broker isn't loaded by any broker process, so create a new process. | 
| 382   return PpapiPluginProcessHost::CreateBrokerHost(*info); | 382   return PpapiPluginProcessHost::CreateBrokerHost(*info); | 
| 383 } | 383 } | 
| 384 | 384 | 
| 385 void PluginServiceImpl::OpenChannelToNpapiPlugin( | 385 void PluginServiceImpl::OpenChannelToNpapiPlugin( | 
| 386     int render_process_id, | 386     int render_process_id, | 
| 387     int render_frame_id, | 387     int render_frame_id, | 
| 388     const GURL& url, | 388     const GURL& url, | 
| 389     const GURL& page_url, | 389     const GURL& page_url, | 
| 390     const std::string& mime_type, | 390     const std::string& mime_type, | 
| 391     PluginProcessHost::Client* client) { | 391     PluginProcessHost::Client* client) { | 
| 392   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 392   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 393   DCHECK(!ContainsKey(pending_plugin_clients_, client)); | 393   DCHECK(!ContainsKey(pending_plugin_clients_, client)); | 
| 394   pending_plugin_clients_.insert(client); | 394   pending_plugin_clients_.insert(client); | 
| 395 | 395 | 
| 396   // Make sure plugins are loaded if necessary. | 396   // Make sure plugins are loaded if necessary. | 
| 397   PluginServiceFilterParams params = { | 397   PluginServiceFilterParams params = { | 
| 398     render_process_id, | 398     render_process_id, | 
| 399     render_frame_id, | 399     render_frame_id, | 
| 400     page_url, | 400     page_url, | 
| 401     client->GetResourceContext() | 401     client->GetResourceContext() | 
| 402   }; | 402   }; | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 429   if (plugin_host) { | 429   if (plugin_host) { | 
| 430     plugin_host->OpenChannelToPlugin(client); | 430     plugin_host->OpenChannelToPlugin(client); | 
| 431   } else { | 431   } else { | 
| 432     // Send error. | 432     // Send error. | 
| 433     client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0); | 433     client->OnPpapiChannelOpened(IPC::ChannelHandle(), base::kNullProcessId, 0); | 
| 434   } | 434   } | 
| 435 } | 435 } | 
| 436 | 436 | 
| 437 void PluginServiceImpl::CancelOpenChannelToNpapiPlugin( | 437 void PluginServiceImpl::CancelOpenChannelToNpapiPlugin( | 
| 438     PluginProcessHost::Client* client) { | 438     PluginProcessHost::Client* client) { | 
| 439   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 439   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 440   DCHECK(ContainsKey(pending_plugin_clients_, client)); | 440   DCHECK(ContainsKey(pending_plugin_clients_, client)); | 
| 441   pending_plugin_clients_.erase(client); | 441   pending_plugin_clients_.erase(client); | 
| 442 } | 442 } | 
| 443 | 443 | 
| 444 void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin( | 444 void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin( | 
| 445     const PluginServiceFilterParams& params, | 445     const PluginServiceFilterParams& params, | 
| 446     const GURL& url, | 446     const GURL& url, | 
| 447     const std::string& mime_type, | 447     const std::string& mime_type, | 
| 448     PluginProcessHost::Client* client, | 448     PluginProcessHost::Client* client, | 
| 449     const std::vector<WebPluginInfo>&) { | 449     const std::vector<WebPluginInfo>&) { | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 477                  base::Unretained(this), | 477                  base::Unretained(this), | 
| 478                  render_process_id, | 478                  render_process_id, | 
| 479                  plugin_path, | 479                  plugin_path, | 
| 480                  client)); | 480                  client)); | 
| 481 } | 481 } | 
| 482 | 482 | 
| 483 void PluginServiceImpl::FinishOpenChannelToPlugin( | 483 void PluginServiceImpl::FinishOpenChannelToPlugin( | 
| 484     int render_process_id, | 484     int render_process_id, | 
| 485     const base::FilePath& plugin_path, | 485     const base::FilePath& plugin_path, | 
| 486     PluginProcessHost::Client* client) { | 486     PluginProcessHost::Client* client) { | 
| 487   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 487   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 488 | 488 | 
| 489   // Make sure it hasn't been canceled yet. | 489   // Make sure it hasn't been canceled yet. | 
| 490   if (!ContainsKey(pending_plugin_clients_, client)) | 490   if (!ContainsKey(pending_plugin_clients_, client)) | 
| 491     return; | 491     return; | 
| 492   pending_plugin_clients_.erase(client); | 492   pending_plugin_clients_.erase(client); | 
| 493 | 493 | 
| 494   PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess( | 494   PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess( | 
| 495       render_process_id, plugin_path); | 495       render_process_id, plugin_path); | 
| 496   if (plugin_host) { | 496   if (plugin_host) { | 
| 497     client->OnFoundPluginProcessHost(plugin_host); | 497     client->OnFoundPluginProcessHost(plugin_host); | 
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 616   PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported()); | 616   PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported()); | 
| 617 | 617 | 
| 618   target_loop->PostTask(FROM_HERE, | 618   target_loop->PostTask(FROM_HERE, | 
| 619       base::Bind(callback, plugins)); | 619       base::Bind(callback, plugins)); | 
| 620 } | 620 } | 
| 621 | 621 | 
| 622 #if defined(OS_POSIX) | 622 #if defined(OS_POSIX) | 
| 623 void PluginServiceImpl::GetPluginsOnIOThread( | 623 void PluginServiceImpl::GetPluginsOnIOThread( | 
| 624     base::MessageLoopProxy* target_loop, | 624     base::MessageLoopProxy* target_loop, | 
| 625     const GetPluginsCallback& callback) { | 625     const GetPluginsCallback& callback) { | 
| 626   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 626   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 627 | 627 | 
| 628   // If we switch back to loading plugins in process, then we need to make | 628   // If we switch back to loading plugins in process, then we need to make | 
| 629   // sure g_thread_init() gets called since plugins may call glib at load. | 629   // sure g_thread_init() gets called since plugins may call glib at load. | 
| 630 | 630 | 
| 631   if (!plugin_loader_.get()) | 631   if (!plugin_loader_.get()) | 
| 632     plugin_loader_ = new PluginLoaderPosix; | 632     plugin_loader_ = new PluginLoaderPosix; | 
| 633 | 633 | 
| 634   plugin_loader_->GetPlugins( | 634   plugin_loader_->GetPlugins( | 
| 635       base::Bind(&ForwardCallback, make_scoped_refptr(target_loop), callback)); | 635       base::Bind(&ForwardCallback, make_scoped_refptr(target_loop), callback)); | 
| 636 } | 636 } | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 710 | 710 | 
| 711   PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path); | 711   PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path); | 
| 712   if (plugin) | 712   if (plugin) | 
| 713     plugin->ForceShutdown(); | 713     plugin->ForceShutdown(); | 
| 714 } | 714 } | 
| 715 | 715 | 
| 716 static const unsigned int kMaxCrashesPerInterval = 3; | 716 static const unsigned int kMaxCrashesPerInterval = 3; | 
| 717 static const unsigned int kCrashesInterval = 120; | 717 static const unsigned int kCrashesInterval = 120; | 
| 718 | 718 | 
| 719 void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) { | 719 void PluginServiceImpl::RegisterPluginCrash(const base::FilePath& path) { | 
| 720   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 720   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 721   std::map<base::FilePath, std::vector<base::Time> >::iterator i = | 721   std::map<base::FilePath, std::vector<base::Time> >::iterator i = | 
| 722       crash_times_.find(path); | 722       crash_times_.find(path); | 
| 723   if (i == crash_times_.end()) { | 723   if (i == crash_times_.end()) { | 
| 724     crash_times_[path] = std::vector<base::Time>(); | 724     crash_times_[path] = std::vector<base::Time>(); | 
| 725     i = crash_times_.find(path); | 725     i = crash_times_.find(path); | 
| 726   } | 726   } | 
| 727   if (i->second.size() == kMaxCrashesPerInterval) { | 727   if (i->second.size() == kMaxCrashesPerInterval) { | 
| 728     i->second.erase(i->second.begin()); | 728     i->second.erase(i->second.begin()); | 
| 729   } | 729   } | 
| 730   base::Time time = base::Time::Now(); | 730   base::Time time = base::Time::Now(); | 
| 731   i->second.push_back(time); | 731   i->second.push_back(time); | 
| 732 } | 732 } | 
| 733 | 733 | 
| 734 bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) { | 734 bool PluginServiceImpl::IsPluginUnstable(const base::FilePath& path) { | 
| 735   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 735   DCHECK_CURRENTLY_ON(BrowserThread::IO); | 
| 736   std::map<base::FilePath, std::vector<base::Time> >::const_iterator i = | 736   std::map<base::FilePath, std::vector<base::Time> >::const_iterator i = | 
| 737       crash_times_.find(path); | 737       crash_times_.find(path); | 
| 738   if (i == crash_times_.end()) { | 738   if (i == crash_times_.end()) { | 
| 739     return false; | 739     return false; | 
| 740   } | 740   } | 
| 741   if (i->second.size() != kMaxCrashesPerInterval) { | 741   if (i->second.size() != kMaxCrashesPerInterval) { | 
| 742     return false; | 742     return false; | 
| 743   } | 743   } | 
| 744   base::TimeDelta delta = base::Time::Now() - i->second[0]; | 744   base::TimeDelta delta = base::Time::Now() - i->second[0]; | 
| 745   return delta.InSeconds() <= kCrashesInterval; | 745   return delta.InSeconds() <= kCrashesInterval; | 
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 864 #endif | 864 #endif | 
| 865 | 865 | 
| 866 bool PluginServiceImpl::PpapiDevChannelSupported( | 866 bool PluginServiceImpl::PpapiDevChannelSupported( | 
| 867     BrowserContext* browser_context, | 867     BrowserContext* browser_context, | 
| 868     const GURL& document_url) { | 868     const GURL& document_url) { | 
| 869   return content::GetContentClient()->browser()-> | 869   return content::GetContentClient()->browser()-> | 
| 870       IsPluginAllowedToUseDevChannelAPIs(browser_context, document_url); | 870       IsPluginAllowedToUseDevChannelAPIs(browser_context, document_url); | 
| 871 } | 871 } | 
| 872 | 872 | 
| 873 }  // namespace content | 873 }  // namespace content | 
| OLD | NEW | 
|---|