plugin_manager.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_path.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/lazy_instance.h" 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/path_service.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/extensions/plugin_manager.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/plugins/chrome_plugin_service_filter.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/chrome_paths.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/api/plugins/plugins_handler.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_details.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/notification_source.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/plugin_service.h" 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/common/pepper_plugin_info.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using content::PluginService; 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static const char* kNaClPluginMimeType = "application/x-nacl"; 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace extensions { 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PluginManager::PluginManager(content::BrowserContext* context) 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : profile_(Profile::FromBrowserContext(context)) { 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) registrar_.Add(this, 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_LOADED, 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::Source<Profile>(profile_)); 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) registrar_.Add(this, 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) chrome::NOTIFICATION_EXTENSION_UNLOADED, 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) content::Source<Profile>(profile_)); 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PluginManager::~PluginManager() { 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static base::LazyInstance<BrowserContextKeyedAPIFactory<PluginManager> > 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) g_factory = LAZY_INSTANCE_INITIALIZER; 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)BrowserContextKeyedAPIFactory<PluginManager>* 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)PluginManager::GetFactoryInstance() { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return g_factory.Pointer(); 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PluginManager::Observe(int type, 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationSource& source, 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationDetails& details) { 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Extension* extension = 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::Details<const Extension>(details).ptr(); 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool plugins_or_nacl_changed = false; 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (PluginInfo::HasPlugins(extension)) { 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const PluginInfo::PluginVector* plugins = 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginInfo::GetPlugins(extension); 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(plugins); 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugins_or_nacl_changed = true; 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (PluginInfo::PluginVector::const_iterator plugin = plugins->begin(); 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugin != plugins->end(); ++plugin) { 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->RefreshPlugins(); 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->AddExtraPluginPath(plugin->path); 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChromePluginServiceFilter* filter = 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChromePluginServiceFilter::GetInstance(); 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (plugin->is_public) { 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) filter->RestrictPluginToProfileAndOrigin( 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugin->path, profile_, GURL()); 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) filter->RestrictPluginToProfileAndOrigin( 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugin->path, profile_, extension->url()); 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const NaClModuleInfo::List* nacl_modules = 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClModuleInfo::GetNaClModules(extension); 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (nacl_modules) { 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugins_or_nacl_changed = true; 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (NaClModuleInfo::List::const_iterator module = nacl_modules->begin(); 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) module != nacl_modules->end(); ++module) { 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) RegisterNaClModule(*module); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UpdatePluginListWithNaClModules(); 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (plugins_or_nacl_changed) 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->PurgePluginListCache(profile_, false); 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Extension* extension = 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::Details<UnloadedExtensionInfo>(details)->extension; 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool plugins_or_nacl_changed = false; 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (PluginInfo::HasPlugins(extension)) { 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const PluginInfo::PluginVector* plugins = 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginInfo::GetPlugins(extension); 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugins_or_nacl_changed = true; 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (PluginInfo::PluginVector::const_iterator plugin = plugins->begin(); 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugin != plugins->end(); ++plugin) { 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->ForcePluginShutdown(plugin->path); 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->RefreshPlugins(); 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->RemoveExtraPluginPath(plugin->path); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ChromePluginServiceFilter::GetInstance()->UnrestrictPlugin( 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugin->path); 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const NaClModuleInfo::List* nacl_modules = 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClModuleInfo::GetNaClModules(extension); 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (nacl_modules) { 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) plugins_or_nacl_changed = true; 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (NaClModuleInfo::List::const_iterator module = nacl_modules->begin(); 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) module != nacl_modules->end(); ++module) { 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UnregisterNaClModule(*module); 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UpdatePluginListWithNaClModules(); 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (plugins_or_nacl_changed) 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->PurgePluginListCache(profile_, false); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NOTREACHED(); 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PluginManager::RegisterNaClModule(const NaClModuleInfo& info) { 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(FindNaClModule(info.url) == nacl_module_list_.end()); 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) nacl_module_list_.push_front(info); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PluginManager::UnregisterNaClModule(const NaClModuleInfo& info) { 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) NaClModuleInfo::List::iterator iter = FindNaClModule(info.url); 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(iter != nacl_module_list_.end()); 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) nacl_module_list_.erase(iter); 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PluginManager::UpdatePluginListWithNaClModules() { 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // An extension has been added which has a nacl_module component, which means 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // there is a MIME type that module wants to handle, so we need to add that 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // MIME type to plugins which handle NaCl modules in order to allow the 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // individual modules to handle these types. 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FilePath path; 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!PathService::Get(chrome::FILE_NACL_PLUGIN, &path)) 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::PepperPluginInfo* pepper_info = 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(path); 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!pepper_info) 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch std::vector<content::WebPluginMimeType>::const_iterator mime_iter; 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Check each MIME type the plugins handle for the NaCl MIME type. 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (mime_iter = pepper_info->mime_types.begin(); 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mime_iter != pepper_info->mime_types.end(); ++mime_iter) { 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (mime_iter->mime_type == kNaClPluginMimeType) { 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This plugin handles "application/x-nacl". 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->UnregisterInternalPlugin(pepper_info->path); 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch content::WebPluginInfo info = pepper_info->ToWebPluginInfo(); 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (NaClModuleInfo::List::const_iterator iter = 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) nacl_module_list_.begin(); 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) iter != nacl_module_list_.end(); ++iter) { 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Add the MIME type specified in the extension to this NaCl plugin, 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // With an extra "nacl" argument to specify the location of the NaCl 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // manifest file. 172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch content::WebPluginMimeType mime_type_info; 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mime_type_info.mime_type = iter->mime_type; 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) mime_type_info.additional_param_names.push_back( 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16("nacl")); 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) mime_type_info.additional_param_values.push_back( 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(iter->url.spec())); 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) info.mime_types.push_back(mime_type_info); 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->RefreshPlugins(); 182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) PluginService::GetInstance()->RegisterInternalPlugin(info, true); 183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This plugin has been modified, no need to check the rest of its 184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // types, but continue checking other plugins. 185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)NaClModuleInfo::List::iterator PluginManager::FindNaClModule(const GURL& url) { 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (NaClModuleInfo::List::iterator iter = nacl_module_list_.begin(); 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) iter != nacl_module_list_.end(); ++iter) { 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (iter->url == url) 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return iter; 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return nacl_module_list_.end(); 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace extensions 200