12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/api/plugins/plugins_handler.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h" 116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "chrome/grit/generated_resources.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/error_utils.h" 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/manifest.h" 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "extensions/common/manifest_handlers/permissions_parser.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "extensions/common/permissions/api_permission_set.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/metro.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)namespace keys = manifest_keys; 273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct PluginManifestData : Extension::ManifestData { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Optional list of NPAPI plugins and associated properties for an extension. 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PluginInfo::PluginVector plugins; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginInfo::PluginInfo(const base::FilePath& plugin_path, bool plugin_is_public) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : path(plugin_path), is_public(plugin_is_public) { 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginInfo::~PluginInfo() { 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const PluginInfo::PluginVector* PluginInfo::GetPlugins( 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PluginManifestData* data = static_cast<PluginManifestData*>( 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->GetManifestData(keys::kPlugins)); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return data ? &data->plugins : NULL; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PluginInfo::HasPlugins(const Extension* extension) { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PluginManifestData* data = static_cast<PluginManifestData*>( 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->GetManifestData(keys::kPlugins)); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return data && !data->plugins.empty() ? true : false; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginsHandler::PluginsHandler() { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PluginsHandler::~PluginsHandler() { 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<std::string> PluginsHandler::Keys() const { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SingleKey(keys::kPlugins); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool PluginsHandler::Parse(Extension* extension, base::string16* error) { 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* list_value = NULL; 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!extension->manifest()->GetList(keys::kPlugins, &list_value)) { 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(manifest_errors::kInvalidPlugins); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<PluginManifestData> plugins_data(new PluginManifestData); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < list_value->GetSize(); ++i) { 797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* plugin_value = NULL; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!list_value->GetDictionary(i, &plugin_value)) { 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *error = base::ASCIIToUTF16(manifest_errors::kInvalidPlugins); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get plugins[i].path. 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string path_str; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!plugin_value->GetString(keys::kPluginsPath, &path_str)) { 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) manifest_errors::kInvalidPluginsPath, base::IntToString(i)); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Get plugins[i].content (optional). 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_public = false; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (plugin_value->HasKey(keys::kPluginsPublic)) { 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!plugin_value->GetBoolean(keys::kPluginsPublic, &is_public)) { 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = ErrorUtils::FormatErrorMessageUTF16( 97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) manifest_errors::kInvalidPluginsPublic, 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::IntToString(i)); 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We don't allow extensions to load NPAPI plugins on Chrome OS, or under 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Windows 8 Metro mode, but still parse the entries to display consistent 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // error messages. If the extension actually requires the plugins then 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // LoadRequirements will prevent it loading. 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_WIN) 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (base::win::IsMetroProcess()) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(OS_WIN). 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) plugins_data->plugins.push_back(PluginInfo( 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->path().Append(base::FilePath::FromUTF8Unsafe(path_str)), 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_public)); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!plugins_data->plugins.empty()) { 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extension->SetManifestData(keys::kPlugins, plugins_data.release()); 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PermissionsParser::AddAPIPermission(extension, APIPermission::kPlugin); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool PluginsHandler::Validate(const Extension* extension, 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string* error, 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<InstallWarning>* warnings) const { 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Validate claimed plugin paths. 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (extensions::PluginInfo::HasPlugins(extension)) { 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::PluginInfo::PluginVector* plugins = 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::PluginInfo::GetPlugins(extension); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(plugins); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::vector<extensions::PluginInfo>::const_iterator plugin = 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) plugins->begin(); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) plugin != plugins->end(); ++plugin) { 1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(plugin->path)) { 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *error = l10n_util::GetStringFUTF8( 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IDS_EXTENSION_LOAD_PLUGIN_PATH_FAILED, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) plugin->path.LossyDisplayName()); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace extensions 150