Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / extensions / plugin_manager.cc
blobe86fcb807d07239668a4a4361bb1edfd7f4dc92f
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/files/file_path.h"
6 #include "base/lazy_instance.h"
7 #include "base/path_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/extension_service.h"
10 #include "chrome/browser/extensions/plugin_manager.h"
11 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/common/chrome_paths.h"
14 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
15 #include "content/public/browser/plugin_service.h"
16 #include "content/public/common/pepper_plugin_info.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/common/extension.h"
19 #include "extensions/common/manifest_handlers/mime_types_handler.h"
20 #include "url/gurl.h"
22 #if !defined(DISABLE_NACL)
23 #include "components/nacl/common/nacl_constants.h"
24 #endif
26 using content::PluginService;
28 namespace extensions {
30 PluginManager::PluginManager(content::BrowserContext* context)
31 : profile_(Profile::FromBrowserContext(context)),
32 extension_registry_observer_(this) {
33 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
36 PluginManager::~PluginManager() {
39 static base::LazyInstance<BrowserContextKeyedAPIFactory<PluginManager> >
40 g_factory = LAZY_INSTANCE_INITIALIZER;
42 // static
43 BrowserContextKeyedAPIFactory<PluginManager>*
44 PluginManager::GetFactoryInstance() {
45 return g_factory.Pointer();
48 void PluginManager::OnExtensionLoaded(content::BrowserContext* browser_context,
49 const Extension* extension) {
50 bool plugins_or_nacl_changed = false;
51 if (PluginInfo::HasPlugins(extension)) {
52 const PluginInfo::PluginVector* plugins = PluginInfo::GetPlugins(extension);
53 CHECK(plugins);
54 plugins_or_nacl_changed = true;
55 for (PluginInfo::PluginVector::const_iterator plugin = plugins->begin();
56 plugin != plugins->end();
57 ++plugin) {
58 PluginService::GetInstance()->RefreshPlugins();
59 PluginService::GetInstance()->AddExtraPluginPath(plugin->path);
60 ChromePluginServiceFilter* filter =
61 ChromePluginServiceFilter::GetInstance();
62 if (plugin->is_public) {
63 filter->RestrictPluginToProfileAndOrigin(
64 plugin->path, profile_, GURL());
65 } else {
66 filter->RestrictPluginToProfileAndOrigin(
67 plugin->path, profile_, extension->url());
72 #if !defined(DISABLE_NACL)
73 const NaClModuleInfo::List* nacl_modules =
74 NaClModuleInfo::GetNaClModules(extension);
75 if (nacl_modules) {
76 plugins_or_nacl_changed = true;
77 for (NaClModuleInfo::List::const_iterator module = nacl_modules->begin();
78 module != nacl_modules->end();
79 ++module) {
80 RegisterNaClModule(*module);
82 UpdatePluginListWithNaClModules();
84 #endif
86 const MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
87 if (handler && handler->HasPlugin()) {
88 plugins_or_nacl_changed = true;
90 content::WebPluginInfo info;
91 info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
92 info.name = base::UTF8ToUTF16(extension->name());
93 info.path = handler->GetPluginPath();
95 for (std::set<std::string>::const_iterator mime_type =
96 handler->mime_type_set().begin();
97 mime_type != handler->mime_type_set().end(); ++mime_type) {
98 content::WebPluginMimeType mime_type_info;
99 mime_type_info.mime_type = *mime_type;
100 base::FilePath::StringType file_extension;
101 if (net::GetPreferredExtensionForMimeType(*mime_type, &file_extension)) {
102 mime_type_info.file_extensions.push_back(
103 base::FilePath(file_extension).AsUTF8Unsafe());
105 info.mime_types.push_back(mime_type_info);
108 PluginService::GetInstance()->RefreshPlugins();
109 PluginService::GetInstance()->RegisterInternalPlugin(info, true);
112 if (plugins_or_nacl_changed)
113 PluginService::GetInstance()->PurgePluginListCache(profile_, false);
116 void PluginManager::OnExtensionUnloaded(
117 content::BrowserContext* browser_context,
118 const Extension* extension,
119 UnloadedExtensionInfo::Reason reason) {
120 bool plugins_or_nacl_changed = false;
121 if (PluginInfo::HasPlugins(extension)) {
122 const PluginInfo::PluginVector* plugins = PluginInfo::GetPlugins(extension);
123 plugins_or_nacl_changed = true;
124 for (PluginInfo::PluginVector::const_iterator plugin = plugins->begin();
125 plugin != plugins->end();
126 ++plugin) {
127 PluginService::GetInstance()->ForcePluginShutdown(plugin->path);
128 PluginService::GetInstance()->RefreshPlugins();
129 PluginService::GetInstance()->RemoveExtraPluginPath(plugin->path);
130 ChromePluginServiceFilter::GetInstance()->UnrestrictPlugin(plugin->path);
134 #if !defined(DISABLE_NACL)
135 const NaClModuleInfo::List* nacl_modules =
136 NaClModuleInfo::GetNaClModules(extension);
137 if (nacl_modules) {
138 plugins_or_nacl_changed = true;
139 for (NaClModuleInfo::List::const_iterator module = nacl_modules->begin();
140 module != nacl_modules->end();
141 ++module) {
142 UnregisterNaClModule(*module);
144 UpdatePluginListWithNaClModules();
146 #endif
148 const MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
149 if (handler && handler->HasPlugin()) {
150 plugins_or_nacl_changed = true;
151 base::FilePath path = handler->GetPluginPath();
152 PluginService::GetInstance()->UnregisterInternalPlugin(path);
153 PluginService::GetInstance()->ForcePluginShutdown(path);
154 PluginService::GetInstance()->RefreshPlugins();
157 if (plugins_or_nacl_changed)
158 PluginService::GetInstance()->PurgePluginListCache(profile_, false);
161 #if !defined(DISABLE_NACL)
163 void PluginManager::RegisterNaClModule(const NaClModuleInfo& info) {
164 DCHECK(FindNaClModule(info.url) == nacl_module_list_.end());
165 nacl_module_list_.push_front(info);
168 void PluginManager::UnregisterNaClModule(const NaClModuleInfo& info) {
169 NaClModuleInfo::List::iterator iter = FindNaClModule(info.url);
170 DCHECK(iter != nacl_module_list_.end());
171 nacl_module_list_.erase(iter);
174 void PluginManager::UpdatePluginListWithNaClModules() {
175 // An extension has been added which has a nacl_module component, which means
176 // there is a MIME type that module wants to handle, so we need to add that
177 // MIME type to plugins which handle NaCl modules in order to allow the
178 // individual modules to handle these types.
179 base::FilePath path;
180 if (!PathService::Get(chrome::FILE_NACL_PLUGIN, &path))
181 return;
182 const content::PepperPluginInfo* pepper_info =
183 PluginService::GetInstance()->GetRegisteredPpapiPluginInfo(path);
184 if (!pepper_info)
185 return;
187 std::vector<content::WebPluginMimeType>::const_iterator mime_iter;
188 // Check each MIME type the plugins handle for the NaCl MIME type.
189 for (mime_iter = pepper_info->mime_types.begin();
190 mime_iter != pepper_info->mime_types.end(); ++mime_iter) {
191 if (mime_iter->mime_type == nacl::kNaClPluginMimeType) {
192 // This plugin handles "application/x-nacl".
194 PluginService::GetInstance()->UnregisterInternalPlugin(pepper_info->path);
196 content::WebPluginInfo info = pepper_info->ToWebPluginInfo();
198 for (NaClModuleInfo::List::const_iterator iter =
199 nacl_module_list_.begin();
200 iter != nacl_module_list_.end(); ++iter) {
201 // Add the MIME type specified in the extension to this NaCl plugin,
202 // With an extra "nacl" argument to specify the location of the NaCl
203 // manifest file.
204 content::WebPluginMimeType mime_type_info;
205 mime_type_info.mime_type = iter->mime_type;
206 mime_type_info.additional_param_names.push_back(
207 base::UTF8ToUTF16("nacl"));
208 mime_type_info.additional_param_values.push_back(
209 base::UTF8ToUTF16(iter->url.spec()));
210 info.mime_types.push_back(mime_type_info);
213 PluginService::GetInstance()->RefreshPlugins();
214 PluginService::GetInstance()->RegisterInternalPlugin(info, true);
215 // This plugin has been modified, no need to check the rest of its
216 // types, but continue checking other plugins.
217 break;
222 NaClModuleInfo::List::iterator PluginManager::FindNaClModule(const GURL& url) {
223 for (NaClModuleInfo::List::iterator iter = nacl_module_list_.begin();
224 iter != nacl_module_list_.end(); ++iter) {
225 if (iter->url == url)
226 return iter;
228 return nacl_module_list_.end();
231 #endif // !defined(DISABLE_NACL)
233 } // namespace extensions