| 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 "chrome/browser/extensions/component_loader.h" | 5 #include "chrome/browser/extensions/component_loader.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 return !base::CommandLine::ForCurrentProcess()->HasSwitch( | 104 return !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 105 chromeos::switches::kGuestSession) && | 105 chromeos::switches::kGuestSession) && |
| 106 user_manager::UserManager::IsInitialized() && | 106 user_manager::UserManager::IsInitialized() && |
| 107 user_manager::UserManager::Get()->IsUserLoggedIn(); | 107 user_manager::UserManager::Get()->IsUserLoggedIn(); |
| 108 } | 108 } |
| 109 #endif // defined(OS_CHROMEOS) | 109 #endif // defined(OS_CHROMEOS) |
| 110 | 110 |
| 111 } // namespace | 111 } // namespace |
| 112 | 112 |
| 113 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo( | 113 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo( |
| 114 const base::DictionaryValue* manifest, const base::FilePath& directory) | 114 std::unique_ptr<base::DictionaryValue> manifest_param, |
| 115 : manifest(manifest), | 115 const base::FilePath& directory) |
| 116 root_directory(directory) { | 116 : manifest(std::move(manifest_param)), root_directory(directory) { |
| 117 if (!root_directory.IsAbsolute()) { | 117 if (!root_directory.IsAbsolute()) { |
| 118 CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory)); | 118 CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory)); |
| 119 root_directory = root_directory.Append(directory); | 119 root_directory = root_directory.Append(directory); |
| 120 } | 120 } |
| 121 extension_id = GenerateId(manifest, root_directory); | 121 extension_id = GenerateId(manifest.get(), root_directory); |
| 122 } | 122 } |
| 123 | 123 |
| 124 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo( |
| 125 ComponentExtensionInfo&& other) |
| 126 : manifest(std::move(other.manifest)), |
| 127 root_directory(std::move(other.root_directory)), |
| 128 extension_id(std::move(other.extension_id)) {} |
| 129 |
| 130 ComponentLoader::ComponentExtensionInfo& |
| 131 ComponentLoader::ComponentExtensionInfo::operator=( |
| 132 ComponentExtensionInfo&& other) { |
| 133 manifest = std::move(other.manifest); |
| 134 root_directory = std::move(other.root_directory); |
| 135 extension_id = std::move(other.extension_id); |
| 136 return *this; |
| 137 } |
| 138 |
| 139 ComponentLoader::ComponentExtensionInfo::~ComponentExtensionInfo() {} |
| 140 |
| 124 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service, | 141 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service, |
| 125 PrefService* profile_prefs, | 142 PrefService* profile_prefs, |
| 126 PrefService* local_state, | 143 PrefService* local_state, |
| 127 Profile* profile) | 144 Profile* profile) |
| 128 : profile_prefs_(profile_prefs), | 145 : profile_prefs_(profile_prefs), |
| 129 local_state_(local_state), | 146 local_state_(local_state), |
| 130 profile_(profile), | 147 profile_(profile), |
| 131 extension_service_(extension_service), | 148 extension_service_(extension_service), |
| 132 ignore_whitelist_for_testing_(false), | 149 ignore_whitelist_for_testing_(false), |
| 133 weak_factory_(this) {} | 150 weak_factory_(this) {} |
| 134 | 151 |
| 135 ComponentLoader::~ComponentLoader() { | 152 ComponentLoader::~ComponentLoader() { |
| 136 ClearAllRegistered(); | |
| 137 } | 153 } |
| 138 | 154 |
| 139 void ComponentLoader::LoadAll() { | 155 void ComponentLoader::LoadAll() { |
| 140 TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll"); | 156 TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll"); |
| 141 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime"); | 157 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime"); |
| 142 | 158 |
| 143 for (RegisteredComponentExtensions::iterator it = | 159 for (const auto& component_extension : component_extensions_) |
| 144 component_extensions_.begin(); | 160 Load(component_extension); |
| 145 it != component_extensions_.end(); ++it) { | |
| 146 Load(*it); | |
| 147 } | |
| 148 } | 161 } |
| 149 | 162 |
| 150 base::DictionaryValue* ComponentLoader::ParseManifest( | 163 std::unique_ptr<base::DictionaryValue> ComponentLoader::ParseManifest( |
| 151 base::StringPiece manifest_contents) const { | 164 base::StringPiece manifest_contents) const { |
| 152 JSONStringValueDeserializer deserializer(manifest_contents); | 165 JSONStringValueDeserializer deserializer(manifest_contents); |
| 153 std::unique_ptr<base::Value> manifest = deserializer.Deserialize(NULL, NULL); | 166 std::unique_ptr<base::Value> manifest = deserializer.Deserialize(NULL, NULL); |
| 154 | 167 |
| 155 if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) { | 168 if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) { |
| 156 LOG(ERROR) << "Failed to parse extension manifest."; | 169 LOG(ERROR) << "Failed to parse extension manifest."; |
| 157 return NULL; | 170 return std::unique_ptr<base::DictionaryValue>(); |
| 158 } | 171 } |
| 159 // Transfer ownership to the caller. | 172 return base::DictionaryValue::From(std::move(manifest)); |
| 160 return static_cast<base::DictionaryValue*>(manifest.release()); | |
| 161 } | |
| 162 | |
| 163 void ComponentLoader::ClearAllRegistered() { | |
| 164 for (RegisteredComponentExtensions::iterator it = | |
| 165 component_extensions_.begin(); | |
| 166 it != component_extensions_.end(); ++it) { | |
| 167 delete it->manifest; | |
| 168 } | |
| 169 | |
| 170 component_extensions_.clear(); | |
| 171 } | |
| 172 | |
| 173 std::string ComponentLoader::GetExtensionID( | |
| 174 int manifest_resource_id, | |
| 175 const base::FilePath& root_directory) { | |
| 176 base::DictionaryValue* manifest = | |
| 177 ParseManifest(ResourceBundle::GetSharedInstance().GetRawDataResource( | |
| 178 manifest_resource_id)); | |
| 179 if (!manifest) | |
| 180 return std::string(); | |
| 181 | |
| 182 ComponentExtensionInfo info(manifest, root_directory); | |
| 183 return info.extension_id; | |
| 184 } | 173 } |
| 185 | 174 |
| 186 std::string ComponentLoader::Add(int manifest_resource_id, | 175 std::string ComponentLoader::Add(int manifest_resource_id, |
| 187 const base::FilePath& root_directory) { | 176 const base::FilePath& root_directory) { |
| 188 if (!ignore_whitelist_for_testing_ && | 177 if (!ignore_whitelist_for_testing_ && |
| 189 !IsComponentExtensionWhitelisted(manifest_resource_id)) | 178 !IsComponentExtensionWhitelisted(manifest_resource_id)) |
| 190 return std::string(); | 179 return std::string(); |
| 191 | 180 |
| 192 base::StringPiece manifest_contents = | 181 base::StringPiece manifest_contents = |
| 193 ResourceBundle::GetSharedInstance().GetRawDataResource( | 182 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 194 manifest_resource_id); | 183 manifest_resource_id); |
| 195 return Add(manifest_contents, root_directory, true); | 184 return Add(manifest_contents, root_directory, true); |
| 196 } | 185 } |
| 197 | 186 |
| 198 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, | 187 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, |
| 199 const base::FilePath& root_directory) { | 188 const base::FilePath& root_directory) { |
| 200 return Add(manifest_contents, root_directory, false); | 189 return Add(manifest_contents, root_directory, false); |
| 201 } | 190 } |
| 202 | 191 |
| 203 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, | 192 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, |
| 204 const base::FilePath& root_directory, | 193 const base::FilePath& root_directory, |
| 205 bool skip_whitelist) { | 194 bool skip_whitelist) { |
| 206 // The Value is kept for the lifetime of the ComponentLoader. This is | 195 // The Value is kept for the lifetime of the ComponentLoader. This is |
| 207 // required in case LoadAll() is called again. | 196 // required in case LoadAll() is called again. |
| 208 base::DictionaryValue* manifest = ParseManifest(manifest_contents); | 197 std::unique_ptr<base::DictionaryValue> manifest = |
| 198 ParseManifest(manifest_contents); |
| 209 if (manifest) | 199 if (manifest) |
| 210 return Add(manifest, root_directory, skip_whitelist); | 200 return Add(std::move(manifest), root_directory, skip_whitelist); |
| 211 return std::string(); | 201 return std::string(); |
| 212 } | 202 } |
| 213 | 203 |
| 214 std::string ComponentLoader::Add(const base::DictionaryValue* parsed_manifest, | 204 std::string ComponentLoader::Add( |
| 215 const base::FilePath& root_directory, | 205 std::unique_ptr<base::DictionaryValue> parsed_manifest, |
| 216 bool skip_whitelist) { | 206 const base::FilePath& root_directory, |
| 217 ComponentExtensionInfo info(parsed_manifest, root_directory); | 207 bool skip_whitelist) { |
| 208 ComponentExtensionInfo info(std::move(parsed_manifest), root_directory); |
| 218 if (!ignore_whitelist_for_testing_ && | 209 if (!ignore_whitelist_for_testing_ && |
| 219 !skip_whitelist && | 210 !skip_whitelist && |
| 220 !IsComponentExtensionWhitelisted(info.extension_id)) | 211 !IsComponentExtensionWhitelisted(info.extension_id)) |
| 221 return std::string(); | 212 return std::string(); |
| 222 | 213 |
| 223 component_extensions_.push_back(info); | 214 component_extensions_.push_back(std::move(info)); |
| 215 ComponentExtensionInfo& added_info = component_extensions_.back(); |
| 224 if (extension_service_->is_ready()) | 216 if (extension_service_->is_ready()) |
| 225 Load(info); | 217 Load(added_info); |
| 226 return info.extension_id; | 218 return added_info.extension_id; |
| 227 } | 219 } |
| 228 | 220 |
| 229 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) { | 221 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) { |
| 230 base::FilePath absolute_path = base::MakeAbsoluteFilePath(path); | 222 base::FilePath absolute_path = base::MakeAbsoluteFilePath(path); |
| 231 std::string error; | 223 std::string error; |
| 232 std::unique_ptr<base::DictionaryValue> manifest( | 224 std::unique_ptr<base::DictionaryValue> manifest( |
| 233 file_util::LoadManifest(absolute_path, &error)); | 225 file_util::LoadManifest(absolute_path, &error)); |
| 234 if (!manifest) { | 226 if (!manifest) { |
| 235 LOG(ERROR) << "Could not load extension from '" << | 227 LOG(ERROR) << "Could not load extension from '" << |
| 236 absolute_path.value() << "'. " << error; | 228 absolute_path.value() << "'. " << error; |
| 237 return std::string(); | 229 return std::string(); |
| 238 } | 230 } |
| 239 Remove(GenerateId(manifest.get(), absolute_path)); | 231 Remove(GenerateId(manifest.get(), absolute_path)); |
| 240 | 232 |
| 241 // We don't check component extensions loaded by path because this is only | 233 // We don't check component extensions loaded by path because this is only |
| 242 // used by developers for testing. | 234 // used by developers for testing. |
| 243 return Add(manifest.release(), absolute_path, true); | 235 return Add(std::move(manifest), absolute_path, true); |
| 244 } | 236 } |
| 245 | 237 |
| 246 void ComponentLoader::Reload(const std::string& extension_id) { | 238 void ComponentLoader::Reload(const std::string& extension_id) { |
| 247 for (RegisteredComponentExtensions::iterator it = | 239 for (const auto& component_extension : component_extensions_) { |
| 248 component_extensions_.begin(); it != component_extensions_.end(); | 240 if (component_extension.extension_id == extension_id) { |
| 249 ++it) { | 241 Load(component_extension); |
| 250 if (it->extension_id == extension_id) { | |
| 251 Load(*it); | |
| 252 break; | 242 break; |
| 253 } | 243 } |
| 254 } | 244 } |
| 255 } | 245 } |
| 256 | 246 |
| 257 void ComponentLoader::Load(const ComponentExtensionInfo& info) { | 247 void ComponentLoader::Load(const ComponentExtensionInfo& info) { |
| 258 std::string error; | 248 std::string error; |
| 259 scoped_refptr<const Extension> extension(CreateExtension(info, &error)); | 249 scoped_refptr<const Extension> extension(CreateExtension(info, &error)); |
| 260 if (!extension.get()) { | 250 if (!extension.get()) { |
| 261 LOG(ERROR) << error; | 251 LOG(ERROR) << error; |
| 262 return; | 252 return; |
| 263 } | 253 } |
| 264 | 254 |
| 265 CHECK_EQ(info.extension_id, extension->id()) << extension->name(); | 255 CHECK_EQ(info.extension_id, extension->id()) << extension->name(); |
| 266 extension_service_->AddComponentExtension(extension.get()); | 256 extension_service_->AddComponentExtension(extension.get()); |
| 267 } | 257 } |
| 268 | 258 |
| 269 void ComponentLoader::Remove(const base::FilePath& root_directory) { | 259 void ComponentLoader::Remove(const base::FilePath& root_directory) { |
| 270 // Find the ComponentExtensionInfo for the extension. | 260 // Find the ComponentExtensionInfo for the extension. |
| 271 RegisteredComponentExtensions::iterator it = component_extensions_.begin(); | 261 for (const auto& component_extension : component_extensions_) { |
| 272 for (; it != component_extensions_.end(); ++it) { | 262 if (component_extension.root_directory == root_directory) { |
| 273 if (it->root_directory == root_directory) { | 263 Remove(GenerateId(component_extension.manifest.get(), root_directory)); |
| 274 Remove(GenerateId(it->manifest, root_directory)); | |
| 275 break; | 264 break; |
| 276 } | 265 } |
| 277 } | 266 } |
| 278 } | 267 } |
| 279 | 268 |
| 280 void ComponentLoader::Remove(const std::string& id) { | 269 void ComponentLoader::Remove(const std::string& id) { |
| 281 RegisteredComponentExtensions::iterator it = component_extensions_.begin(); | 270 for (RegisteredComponentExtensions::iterator it = |
| 282 for (; it != component_extensions_.end(); ++it) { | 271 component_extensions_.begin(); |
| 272 it != component_extensions_.end(); ++it) { |
| 283 if (it->extension_id == id) { | 273 if (it->extension_id == id) { |
| 284 UnloadComponent(&(*it)); | 274 UnloadComponent(&(*it)); |
| 285 it = component_extensions_.erase(it); | 275 component_extensions_.erase(it); |
| 286 break; | 276 break; |
| 287 } | 277 } |
| 288 } | 278 } |
| 289 } | 279 } |
| 290 | 280 |
| 291 bool ComponentLoader::Exists(const std::string& id) const { | 281 bool ComponentLoader::Exists(const std::string& id) const { |
| 292 RegisteredComponentExtensions::const_iterator it = | 282 for (const auto& component_extension : component_extensions_) { |
| 293 component_extensions_.begin(); | 283 if (component_extension.extension_id == id) |
| 294 for (; it != component_extensions_.end(); ++it) | |
| 295 if (it->extension_id == id) | |
| 296 return true; | 284 return true; |
| 285 } |
| 297 return false; | 286 return false; |
| 298 } | 287 } |
| 299 | 288 |
| 300 void ComponentLoader::AddFileManagerExtension() { | 289 void ComponentLoader::AddFileManagerExtension() { |
| 301 #if defined(OS_CHROMEOS) | 290 #if defined(OS_CHROMEOS) |
| 302 AddWithNameAndDescription( | 291 AddWithNameAndDescription( |
| 303 IDR_FILEMANAGER_MANIFEST, | 292 IDR_FILEMANAGER_MANIFEST, |
| 304 base::FilePath(FILE_PATH_LITERAL("file_manager")), | 293 base::FilePath(FILE_PATH_LITERAL("file_manager")), |
| 305 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_NAME), | 294 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_NAME), |
| 306 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_DESCRIPTION)); | 295 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_DESCRIPTION)); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 if (!ignore_whitelist_for_testing_ && | 382 if (!ignore_whitelist_for_testing_ && |
| 394 !IsComponentExtensionWhitelisted(manifest_resource_id)) | 383 !IsComponentExtensionWhitelisted(manifest_resource_id)) |
| 395 return; | 384 return; |
| 396 | 385 |
| 397 base::StringPiece manifest_contents = | 386 base::StringPiece manifest_contents = |
| 398 ResourceBundle::GetSharedInstance().GetRawDataResource( | 387 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 399 manifest_resource_id); | 388 manifest_resource_id); |
| 400 | 389 |
| 401 // The Value is kept for the lifetime of the ComponentLoader. This is | 390 // The Value is kept for the lifetime of the ComponentLoader. This is |
| 402 // required in case LoadAll() is called again. | 391 // required in case LoadAll() is called again. |
| 403 base::DictionaryValue* manifest = ParseManifest(manifest_contents); | 392 std::unique_ptr<base::DictionaryValue> manifest = |
| 393 ParseManifest(manifest_contents); |
| 404 | 394 |
| 405 if (manifest) { | 395 if (manifest) { |
| 406 manifest->SetString(manifest_keys::kName, name_string); | 396 manifest->SetString(manifest_keys::kName, name_string); |
| 407 manifest->SetString(manifest_keys::kDescription, description_string); | 397 manifest->SetString(manifest_keys::kDescription, description_string); |
| 408 Add(manifest, root_directory, true); | 398 Add(std::move(manifest), root_directory, true); |
| 409 } | 399 } |
| 410 } | 400 } |
| 411 | 401 |
| 412 void ComponentLoader::AddChromeApp() { | 402 void ComponentLoader::AddChromeApp() { |
| 413 #if BUILDFLAG(ENABLE_APP_LIST) | 403 #if BUILDFLAG(ENABLE_APP_LIST) |
| 414 AddWithNameAndDescription( | 404 AddWithNameAndDescription( |
| 415 IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")), | 405 IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")), |
| 416 l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME), | 406 l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME), |
| 417 l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION)); | 407 l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION)); |
| 418 #endif | 408 #endif |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 (command_line->HasSwitch(switches::kTestType) || | 621 (command_line->HasSwitch(switches::kTestType) || |
| 632 command_line->HasSwitch( | 622 command_line->HasSwitch( |
| 633 switches::kDisableComponentExtensionsWithBackgroundPages))) { | 623 switches::kDisableComponentExtensionsWithBackgroundPages))) { |
| 634 return; | 624 return; |
| 635 } | 625 } |
| 636 | 626 |
| 637 AddHangoutServicesExtension(); | 627 AddHangoutServicesExtension(); |
| 638 } | 628 } |
| 639 | 629 |
| 640 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) { | 630 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) { |
| 641 delete component->manifest; | |
| 642 if (extension_service_->is_ready()) { | 631 if (extension_service_->is_ready()) { |
| 643 extension_service_-> | 632 extension_service_-> |
| 644 RemoveComponentExtension(component->extension_id); | 633 RemoveComponentExtension(component->extension_id); |
| 645 } | 634 } |
| 646 } | 635 } |
| 647 | 636 |
| 648 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) { | 637 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) { |
| 649 #if defined(OS_CHROMEOS) | 638 #if defined(OS_CHROMEOS) |
| 650 if (!IsNormalSession()) { | 639 if (!IsNormalSession()) { |
| 651 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for | 640 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 } | 674 } |
| 686 | 675 |
| 687 void ComponentLoader::FinishAddComponentFromDir( | 676 void ComponentLoader::FinishAddComponentFromDir( |
| 688 const base::FilePath& root_directory, | 677 const base::FilePath& root_directory, |
| 689 const char* extension_id, | 678 const char* extension_id, |
| 690 const base::Closure& done_cb, | 679 const base::Closure& done_cb, |
| 691 std::unique_ptr<base::DictionaryValue> manifest) { | 680 std::unique_ptr<base::DictionaryValue> manifest) { |
| 692 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 681 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 693 if (!manifest) | 682 if (!manifest) |
| 694 return; // Error already logged. | 683 return; // Error already logged. |
| 695 std::string actual_extension_id = Add( | 684 std::string actual_extension_id = |
| 696 manifest.release(), | 685 Add(std::move(manifest), root_directory, false); |
| 697 root_directory, | |
| 698 false); | |
| 699 CHECK_EQ(extension_id, actual_extension_id); | 686 CHECK_EQ(extension_id, actual_extension_id); |
| 700 if (!done_cb.is_null()) | 687 if (!done_cb.is_null()) |
| 701 done_cb.Run(); | 688 done_cb.Run(); |
| 702 } | 689 } |
| 703 #endif | 690 #endif |
| 704 | 691 |
| 705 } // namespace extensions | 692 } // namespace extensions |
| OLD | NEW |