diff options
Diffstat (limited to 'chromium/content/browser/plugin_service_impl.cc')
-rw-r--r-- | chromium/content/browser/plugin_service_impl.cc | 473 |
1 files changed, 11 insertions, 462 deletions
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc index 700d30428c7..c81e19b6b23 100644 --- a/chromium/content/browser/plugin_service_impl.cc +++ b/chromium/content/browser/plugin_service_impl.cc @@ -34,108 +34,27 @@ #include "content/public/common/process_type.h" #include "content/public/common/webplugininfo.h" -#if defined(OS_WIN) -#include "content/common/plugin_constants_win.h" -#include "ui/gfx/win/hwnd_util.h" -#endif - -#if defined(OS_POSIX) -#include "content/browser/plugin_loader_posix.h" -#endif - -#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) -using ::base::FilePathWatcher; -#endif - namespace content { namespace { // This enum is used to collect Flash usage data. enum FlashUsage { - // Number of browser processes that have started at least one NPAPI Flash - // process during their lifetime. - START_NPAPI_FLASH_AT_LEAST_ONCE, // Number of browser processes that have started at least one PPAPI Flash // process during their lifetime. - START_PPAPI_FLASH_AT_LEAST_ONCE, + START_PPAPI_FLASH_AT_LEAST_ONCE = 1, // Total number of browser processes. TOTAL_BROWSER_PROCESSES, FLASH_USAGE_ENUM_COUNT }; -enum NPAPIPluginStatus { - // Platform does not support NPAPI. - NPAPI_STATUS_UNSUPPORTED, - // Platform supports NPAPI and NPAPI is disabled. - NPAPI_STATUS_DISABLED, - // Platform supports NPAPI and NPAPI is enabled. - NPAPI_STATUS_ENABLED, - NPAPI_STATUS_ENUM_COUNT -}; - -bool LoadPluginListInProcess() { -#if defined(OS_WIN) - return true; -#else - // If on POSIX, we don't want to load the list of NPAPI plugins in-process as - // that causes instability. - - // Can't load the plugins on the utility thread when in single process mode - // since that requires GTK which can only be used on the main thread. - if (RenderProcessHost::run_renderer_in_process()) - return true; - - return !PluginService::GetInstance()->NPAPIPluginsSupported(); -#endif -} - // Callback set on the PluginList to assert that plugin loading happens on the // correct thread. void WillLoadPluginsCallback( base::SequencedWorkerPool::SequenceToken token) { - if (LoadPluginListInProcess()) { - CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( - token)); - } else { - CHECK(false) << "Plugin loading should happen out-of-process."; - } + CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread( + token)); } -#if defined(OS_MACOSX) -void NotifyPluginsOfActivation() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - for (PluginProcessHostIterator iter; !iter.Done(); ++iter) - iter->OnAppActivation(); -} -#endif - -#if defined(OS_POSIX) -#if !defined(OS_OPENBSD) && !defined(OS_ANDROID) -void NotifyPluginDirChanged(const base::FilePath& path, bool error) { - if (error) { - // TODO(pastarmovj): Add some sensible error handling. Maybe silently - // stopping the watcher would be enough. Or possibly restart it. - NOTREACHED(); - return; - } - VLOG(1) << "Watched path changed: " << path.value(); - // Make the plugin list update itself - PluginList::Singleton()->RefreshPlugins(); - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&PluginService::PurgePluginListCache, - static_cast<BrowserContext*>(NULL), false)); -} -#endif // !defined(OS_OPENBSD) && !defined(OS_ANDROID) - -void ForwardCallback(base::SingleThreadTaskRunner* target_task_runner, - const PluginService::GetPluginsCallback& callback, - const std::vector<WebPluginInfo>& plugins) { - target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins)); -} -#endif // defined(OS_POSIX) - } // namespace // static @@ -159,7 +78,7 @@ PluginServiceImpl* PluginServiceImpl::GetInstance() { } PluginServiceImpl::PluginServiceImpl() - : npapi_plugins_enabled_(false), filter_(NULL) { + : filter_(NULL) { // Collect the total number of browser processes (which create // PluginServiceImpl objects, to be precise). The number is used to normalize // the number of processes which start at least one NPAPI/PPAPI Flash process. @@ -172,8 +91,6 @@ PluginServiceImpl::PluginServiceImpl() } PluginServiceImpl::~PluginServiceImpl() { - // Make sure no plugin channel requests have been leaked. - DCHECK(pending_plugin_clients_.empty()); } void PluginServiceImpl::Init() { @@ -182,80 +99,6 @@ void PluginServiceImpl::Init() { base::Bind(&WillLoadPluginsCallback, plugin_list_token_)); RegisterPepperPlugins(); - - // Load any specified on the command line as well. - const base::CommandLine* command_line = - base::CommandLine::ForCurrentProcess(); - base::FilePath path = - command_line->GetSwitchValuePath(switches::kLoadPlugin); - if (!path.empty()) - AddExtraPluginPath(path); - path = command_line->GetSwitchValuePath(switches::kExtraPluginDir); - if (!path.empty()) - PluginList::Singleton()->AddExtraPluginDir(path); - - if (command_line->HasSwitch(switches::kDisablePluginsDiscovery)) - PluginList::Singleton()->DisablePluginsDiscovery(); -} - -void PluginServiceImpl::StartWatchingPlugins() { - // Start watching for changes in the plugin list. This means watching - // for changes in the Windows registry keys and on both Windows and POSIX - // watch for changes in the paths that are expected to contain plugins. -#if defined(OS_WIN) - if (hkcu_key_.Create(HKEY_CURRENT_USER, - kRegistryMozillaPlugins, - KEY_NOTIFY) == ERROR_SUCCESS) { - base::win::RegKey::ChangeCallback callback = - base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this), - base::Unretained(&hkcu_key_)); - hkcu_key_.StartWatching(callback); - } - if (hklm_key_.Create(HKEY_LOCAL_MACHINE, - kRegistryMozillaPlugins, - KEY_NOTIFY) == ERROR_SUCCESS) { - base::win::RegKey::ChangeCallback callback = - base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this), - base::Unretained(&hklm_key_)); - hklm_key_.StartWatching(callback); - } -#endif -#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) -// On ChromeOS the user can't install plugins anyway and on Windows all -// important plugins register themselves in the registry so no need to do that. - - // Get the list of all paths for registering the FilePathWatchers - // that will track and if needed reload the list of plugins on runtime. - std::vector<base::FilePath> plugin_dirs; - PluginList::Singleton()->GetPluginDirectories(&plugin_dirs); - - for (size_t i = 0; i < plugin_dirs.size(); ++i) { - // FilePathWatcher can not handle non-absolute paths under windows. - // We don't watch for file changes in windows now but if this should ever - // be extended to Windows these lines might save some time of debugging. -#if defined(OS_WIN) - if (!plugin_dirs[i].IsAbsolute()) - continue; -#endif - FilePathWatcher* watcher = new FilePathWatcher(); - VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value(); - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher, - plugin_dirs[i])); - file_watchers_.push_back(watcher); - } -#endif -} - -PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess( - const base::FilePath& plugin_path) { - for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { - if (iter->info().path == plugin_path) - return *iter; - } - - return NULL; } PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess( @@ -280,46 +123,6 @@ PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess( return NULL; } -PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess( - int render_process_id, - const base::FilePath& plugin_path) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path)) - return NULL; - - PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path); - if (plugin_host) - return plugin_host; - - WebPluginInfo info; - if (!GetPluginInfoByPath(plugin_path, &info)) { - return NULL; - } - - // Record when NPAPI Flash process is started for the first time. - static bool counted = false; - if (!counted && base::UTF16ToUTF8(info.name) == kFlashPluginName) { - counted = true; - UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage", - START_NPAPI_FLASH_AT_LEAST_ONCE, - FLASH_USAGE_ENUM_COUNT); - } -#if defined(OS_CHROMEOS) - // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now - // we still want Plugin.FlashUsage recorded if we end up here. - LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS."; - return NULL; -#endif - // This plugin isn't loaded by any plugin process, so create a new process. - scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost()); - if (!new_host->Init(info)) { - NOTREACHED(); // Init is not expected to fail. - return NULL; - } - return new_host.release(); -} - PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess( int render_process_id, const base::FilePath& plugin_path, @@ -388,29 +191,6 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess( return PpapiPluginProcessHost::CreateBrokerHost(*info); } -void PluginServiceImpl::OpenChannelToNpapiPlugin( - int render_process_id, - int render_frame_id, - const GURL& url, - const GURL& page_url, - const std::string& mime_type, - PluginProcessHost::Client* client) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!ContainsKey(pending_plugin_clients_, client)); - pending_plugin_clients_.insert(client); - - // Make sure plugins are loaded if necessary. - PluginServiceFilterParams params = { - render_process_id, - render_frame_id, - page_url, - client->GetResourceContext() - }; - GetPlugins(base::Bind( - &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin, - base::Unretained(this), params, url, mime_type, client)); -} - void PluginServiceImpl::OpenChannelToPpapiPlugin( int render_process_id, const base::FilePath& plugin_path, @@ -440,78 +220,6 @@ void PluginServiceImpl::OpenChannelToPpapiBroker( } } -void PluginServiceImpl::CancelOpenChannelToNpapiPlugin( - PluginProcessHost::Client* client) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(ContainsKey(pending_plugin_clients_, client)); - pending_plugin_clients_.erase(client); -} - -void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin( - const PluginServiceFilterParams& params, - const GURL& url, - const std::string& mime_type, - PluginProcessHost::Client* client, - const std::vector<WebPluginInfo>&) { - GetAllowedPluginForOpenChannelToPlugin( - params.render_process_id, params.render_frame_id, url, params.page_url, - mime_type, client, params.resource_context); -} - -void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin( - int render_process_id, - int render_frame_id, - const GURL& url, - const GURL& page_url, - const std::string& mime_type, - PluginProcessHost::Client* client, - ResourceContext* resource_context) { - WebPluginInfo info; - bool allow_wildcard = true; - bool found = GetPluginInfo( - render_process_id, render_frame_id, resource_context, - url, page_url, mime_type, allow_wildcard, - NULL, &info, NULL); - base::FilePath plugin_path; - if (found) - plugin_path = info.path; - - // Now we jump back to the IO thread to finish opening the channel. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin, - base::Unretained(this), - render_process_id, - plugin_path, - client)); - if (filter_) { - DCHECK_EQ(WebPluginInfo::PLUGIN_TYPE_NPAPI, info.type); - filter_->NPAPIPluginLoaded(render_process_id, render_frame_id, mime_type, - info); - } -} - -void PluginServiceImpl::FinishOpenChannelToPlugin( - int render_process_id, - const base::FilePath& plugin_path, - PluginProcessHost::Client* client) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // Make sure it hasn't been canceled yet. - if (!ContainsKey(pending_plugin_clients_, client)) - return; - pending_plugin_clients_.erase(client); - - PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess( - render_process_id, plugin_path); - if (plugin_host) { - client->OnFoundPluginProcessHost(plugin_host); - plugin_host->OpenChannelToPlugin(client); - } else { - client->OnError(); - } -} - bool PluginServiceImpl::GetPluginInfoArray( const GURL& url, const std::string& mime_type, @@ -520,8 +228,7 @@ bool PluginServiceImpl::GetPluginInfoArray( std::vector<std::string>* actual_mime_types) { bool use_stale = false; PluginList::Singleton()->GetPluginInfoArray( - url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(), - plugins, actual_mime_types); + url, mime_type, allow_wildcard, &use_stale, plugins, actual_mime_types); return use_stale; } @@ -598,23 +305,11 @@ void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) { scoped_refptr<base::SingleThreadTaskRunner> target_task_runner( base::ThreadTaskRunnerHandle::Get()); - if (LoadPluginListInProcess()) { - BrowserThread::GetBlockingPool() - ->PostSequencedWorkerTaskWithShutdownBehavior( - plugin_list_token_, FROM_HERE, - base::Bind(&PluginServiceImpl::GetPluginsInternal, - base::Unretained(this), target_task_runner, callback), - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); - return; - } -#if defined(OS_POSIX) - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&PluginServiceImpl::GetPluginsOnIOThread, - base::Unretained(this), target_task_runner, callback)); -#else - NOTREACHED(); -#endif + BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior( + plugin_list_token_, FROM_HERE, + base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this), + base::RetainedRef(target_task_runner), callback), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); } void PluginServiceImpl::GetPluginsInternal( @@ -624,39 +319,11 @@ void PluginServiceImpl::GetPluginsInternal( plugin_list_token_)); std::vector<WebPluginInfo> plugins; - PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported()); + PluginList::Singleton()->GetPlugins(&plugins); target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins)); } -#if defined(OS_POSIX) -void PluginServiceImpl::GetPluginsOnIOThread( - base::SingleThreadTaskRunner* target_task_runner, - const GetPluginsCallback& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - // If we switch back to loading plugins in process, then we need to make - // sure g_thread_init() gets called since plugins may call glib at load. - - if (!plugin_loader_.get()) - plugin_loader_ = new PluginLoaderPosix; - - plugin_loader_->GetPlugins(base::Bind( - &ForwardCallback, make_scoped_refptr(target_task_runner), callback)); -} -#endif - -#if defined(OS_WIN) -void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) { - key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged, - base::Unretained(this), - base::Unretained(key))); - - PluginList::Singleton()->RefreshPlugins(); - PurgePluginListCache(NULL, false); -} -#endif // defined(OS_WIN) - void PluginServiceImpl::RegisterPepperPlugins() { ComputePepperPluginList(&ppapi_plugins_); for (size_t i = 0; i < ppapi_plugins_.size(); ++i) { @@ -691,16 +358,6 @@ PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo( return &ppapi_plugins_[ppapi_plugins_.size() - 1]; } -#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID) -// static -void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher, - const base::FilePath& path) { - bool result = watcher->Watch(path, false, - base::Bind(&NotifyPluginDirChanged)); - DCHECK(result); -} -#endif - void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) { filter_ = filter; } @@ -709,20 +366,6 @@ PluginServiceFilter* PluginServiceImpl::GetFilter() { return filter_; } -void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) { - if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - base::Bind(&PluginServiceImpl::ForcePluginShutdown, - base::Unretained(this), plugin_path)); - return; - } - - PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path); - if (plugin) - plugin->ForceShutdown(); -} - static const unsigned int kMaxCrashesPerInterval = 3; static const unsigned int kCrashesInterval = 120; @@ -759,33 +402,9 @@ void PluginServiceImpl::RefreshPlugins() { PluginList::Singleton()->RefreshPlugins(); } -void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) { - if (!NPAPIPluginsSupported()) { - // TODO(jam): remove and just have CHECK once we're sure this doesn't get - // triggered. - DVLOG(0) << "NPAPI plugins not supported"; - return; - } - PluginList::Singleton()->AddExtraPluginPath(path); -} - -void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) { - PluginList::Singleton()->RemoveExtraPluginPath(path); -} - -void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) { - PluginList::Singleton()->AddExtraPluginDir(path); -} - void PluginServiceImpl::RegisterInternalPlugin( const WebPluginInfo& info, bool add_at_beginning) { - // Internal plugins should never be NPAPI. - CHECK_NE(info.type, WebPluginInfo::PLUGIN_TYPE_NPAPI); - if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) { - DVLOG(0) << "Don't register NPAPI plugins when they're not supported"; - return; - } PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning); } @@ -798,76 +417,6 @@ void PluginServiceImpl::GetInternalPlugins( PluginList::Singleton()->GetInternalPlugins(plugins); } -bool PluginServiceImpl::NPAPIPluginsSupported() { -#if defined(OS_WIN) || defined(OS_MACOSX) - npapi_plugins_enabled_ = GetContentClient()->browser()->IsNPAPIEnabled(); -#if defined(OS_WIN) - // NPAPI plugins don't play well with Win32k renderer lockdown. - if (npapi_plugins_enabled_) - DisableWin32kRendererLockdown(); -#endif - NPAPIPluginStatus status = - npapi_plugins_enabled_ ? NPAPI_STATUS_ENABLED : NPAPI_STATUS_DISABLED; -#else - NPAPIPluginStatus status = NPAPI_STATUS_UNSUPPORTED; -#endif - UMA_HISTOGRAM_ENUMERATION("Plugin.NPAPIStatus", status, - NPAPI_STATUS_ENUM_COUNT); - - return npapi_plugins_enabled_; -} - -void PluginServiceImpl::DisablePluginsDiscoveryForTesting() { - PluginList::Singleton()->DisablePluginsDiscovery(); -} - -#if defined(OS_MACOSX) -void PluginServiceImpl::AppActivated() { - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, - base::Bind(&NotifyPluginsOfActivation)); -} -#elif defined(OS_WIN) - -bool GetPluginPropertyFromWindow( - HWND window, const wchar_t* plugin_atom_property, - base::string16* plugin_property) { - ATOM plugin_atom = static_cast<ATOM>( - reinterpret_cast<uintptr_t>(GetPropW(window, plugin_atom_property))); - if (plugin_atom != 0) { - WCHAR plugin_property_local[MAX_PATH] = {0}; - GlobalGetAtomNameW(plugin_atom, - plugin_property_local, - ARRAYSIZE(plugin_property_local)); - *plugin_property = plugin_property_local; - return true; - } - return false; -} - -bool PluginServiceImpl::GetPluginInfoFromWindow( - HWND window, - base::string16* plugin_name, - base::string16* plugin_version) { - if (!IsPluginWindow(window)) - return false; - - - DWORD process_id = 0; - GetWindowThreadProcessId(window, &process_id); - WebPluginInfo info; - if (!PluginProcessHost::GetWebPluginInfoFromPluginPid(process_id, &info)) - return false; - - *plugin_name = info.name; - *plugin_version = info.version; - return true; -} - -bool PluginServiceImpl::IsPluginWindow(HWND window) { - return gfx::GetClassName(window) == base::string16(kNativeWindowClassName); -} -#endif - bool PluginServiceImpl::PpapiDevChannelSupported( BrowserContext* browser_context, const GURL& document_url) { |