1 // Copyright 2014 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 "chrome/browser/extensions/shared_module_service.h"
9 #include "base/version.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/pending_extension_manager.h"
12 #include "chrome/common/extensions/extension_constants.h"
13 #include "extensions/browser/extension_registry.h"
14 #include "extensions/browser/extension_system.h"
15 #include "extensions/common/extension.h"
17 namespace extensions {
21 typedef std::vector<SharedModuleInfo::ImportInfo> ImportInfoVector;
22 typedef std::list<SharedModuleInfo::ImportInfo> ImportInfoList;
26 SharedModuleService::SharedModuleService(content::BrowserContext* context)
27 : extension_registry_observer_(this), browser_context_(context) {
28 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
31 SharedModuleService::~SharedModuleService() {
34 SharedModuleService::ImportStatus SharedModuleService::CheckImports(
35 const Extension* extension,
36 ImportInfoList* missing_modules,
37 ImportInfoList* outdated_modules) {
39 DCHECK(missing_modules && missing_modules->empty());
40 DCHECK(outdated_modules && outdated_modules->empty());
42 ImportStatus status = IMPORT_STATUS_OK;
44 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
45 const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension);
46 for (ImportInfoVector::const_iterator iter = imports.begin();
47 iter != imports.end();
49 base::Version version_required(iter->minimum_version);
50 const Extension* imported_module =
51 registry->GetExtensionById(iter->extension_id,
52 ExtensionRegistry::EVERYTHING);
53 if (!imported_module) {
54 if (extension->from_webstore()) {
55 status = IMPORT_STATUS_UNSATISFIED;
56 missing_modules->push_back(*iter);
58 return IMPORT_STATUS_UNRECOVERABLE;
60 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
61 return IMPORT_STATUS_UNRECOVERABLE;
62 } else if (!SharedModuleInfo::IsExportAllowedByWhitelist(imported_module,
64 return IMPORT_STATUS_UNRECOVERABLE;
65 } else if (version_required.IsValid() &&
66 imported_module->version()->CompareTo(version_required) < 0) {
67 if (imported_module->from_webstore()) {
68 outdated_modules->push_back(*iter);
69 status = IMPORT_STATUS_UNSATISFIED;
71 return IMPORT_STATUS_UNRECOVERABLE;
79 SharedModuleService::ImportStatus SharedModuleService::SatisfyImports(
80 const Extension* extension) {
81 ImportInfoList missing_modules;
82 ImportInfoList outdated_modules;
84 CheckImports(extension, &missing_modules, &outdated_modules);
86 ExtensionService* service =
87 ExtensionSystem::Get(browser_context_)->extension_service();
89 PendingExtensionManager* pending_extension_manager =
90 service->pending_extension_manager();
91 DCHECK(pending_extension_manager);
93 if (status == IMPORT_STATUS_UNSATISFIED) {
94 for (ImportInfoList::const_iterator iter = missing_modules.begin();
95 iter != missing_modules.end();
97 pending_extension_manager->AddFromExtensionImport(
99 extension_urls::GetWebstoreUpdateUrl(),
100 SharedModuleInfo::IsSharedModule);
102 service->CheckForUpdatesSoon();
107 scoped_ptr<ExtensionSet> SharedModuleService::GetDependentExtensions(
108 const Extension* extension) {
109 scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
111 if (SharedModuleInfo::IsSharedModule(extension)) {
112 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
113 ExtensionService* service =
114 ExtensionSystem::Get(browser_context_)->extension_service();
116 ExtensionSet set_to_check;
117 set_to_check.InsertAll(registry->enabled_extensions());
118 set_to_check.InsertAll(registry->disabled_extensions());
119 set_to_check.InsertAll(*service->delayed_installs());
121 for (ExtensionSet::const_iterator iter = set_to_check.begin();
122 iter != set_to_check.end();
124 if (SharedModuleInfo::ImportsExtensionById(iter->get(),
126 dependents->Insert(*iter);
130 return dependents.PassAs<ExtensionSet>();
133 void SharedModuleService::OnExtensionUninstalled(
134 content::BrowserContext* browser_context,
135 const Extension* extension) {
136 // Uninstalls shared modules that were only referenced by |extension|.
137 if (!SharedModuleInfo::ImportsModules(extension))
140 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
141 ExtensionService* service =
142 ExtensionSystem::Get(browser_context_)->extension_service();
144 const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension);
145 for (ImportInfoVector::const_iterator iter = imports.begin();
146 iter != imports.end();
148 const Extension* imported_module =
149 registry->GetExtensionById(iter->extension_id,
150 ExtensionRegistry::EVERYTHING);
151 if (imported_module && imported_module->from_webstore()) {
152 scoped_ptr<ExtensionSet> dependents =
153 GetDependentExtensions(imported_module);
154 if (dependents->is_empty()) {
155 service->UninstallExtension(iter->extension_id,
156 true, // External uninstall.
157 NULL); // Ignore error.
163 } // namespace extensions