shared_module_service.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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. 4 5#include "chrome/browser/extensions/shared_module_service.h" 6 7#include <set> 8#include <vector> 9 10#include "base/version.h" 11#include "chrome/browser/extensions/extension_service.h" 12#include "chrome/browser/extensions/pending_extension_manager.h" 13#include "chrome/common/extensions/extension_constants.h" 14#include "extensions/browser/extension_registry.h" 15#include "extensions/browser/extension_system.h" 16#include "extensions/browser/uninstall_reason.h" 17#include "extensions/common/extension.h" 18 19namespace extensions { 20 21namespace { 22 23typedef std::vector<SharedModuleInfo::ImportInfo> ImportInfoVector; 24typedef std::list<SharedModuleInfo::ImportInfo> ImportInfoList; 25 26} // namespace 27 28SharedModuleService::SharedModuleService(content::BrowserContext* context) 29 : extension_registry_observer_(this), browser_context_(context) { 30 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); 31} 32 33SharedModuleService::~SharedModuleService() { 34} 35 36SharedModuleService::ImportStatus SharedModuleService::CheckImports( 37 const Extension* extension, 38 ImportInfoList* missing_modules, 39 ImportInfoList* outdated_modules) { 40 DCHECK(extension); 41 DCHECK(missing_modules && missing_modules->empty()); 42 DCHECK(outdated_modules && outdated_modules->empty()); 43 44 ImportStatus status = IMPORT_STATUS_OK; 45 46 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); 47 const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension); 48 for (ImportInfoVector::const_iterator iter = imports.begin(); 49 iter != imports.end(); 50 ++iter) { 51 base::Version version_required(iter->minimum_version); 52 const Extension* imported_module = 53 registry->GetExtensionById(iter->extension_id, 54 ExtensionRegistry::EVERYTHING); 55 if (!imported_module) { 56 if (extension->from_webstore()) { 57 status = IMPORT_STATUS_UNSATISFIED; 58 missing_modules->push_back(*iter); 59 } else { 60 return IMPORT_STATUS_UNRECOVERABLE; 61 } 62 } else if (!SharedModuleInfo::IsSharedModule(imported_module)) { 63 return IMPORT_STATUS_UNRECOVERABLE; 64 } else if (!SharedModuleInfo::IsExportAllowedByWhitelist(imported_module, 65 extension->id())) { 66 return IMPORT_STATUS_UNRECOVERABLE; 67 } else if (version_required.IsValid() && 68 imported_module->version()->CompareTo(version_required) < 0) { 69 if (imported_module->from_webstore()) { 70 outdated_modules->push_back(*iter); 71 status = IMPORT_STATUS_UNSATISFIED; 72 } else { 73 return IMPORT_STATUS_UNRECOVERABLE; 74 } 75 } 76 } 77 78 return status; 79} 80 81SharedModuleService::ImportStatus SharedModuleService::SatisfyImports( 82 const Extension* extension) { 83 ImportInfoList missing_modules; 84 ImportInfoList outdated_modules; 85 ImportStatus status = 86 CheckImports(extension, &missing_modules, &outdated_modules); 87 88 ExtensionService* service = 89 ExtensionSystem::Get(browser_context_)->extension_service(); 90 91 PendingExtensionManager* pending_extension_manager = 92 service->pending_extension_manager(); 93 DCHECK(pending_extension_manager); 94 95 if (status == IMPORT_STATUS_UNSATISFIED) { 96 for (ImportInfoList::const_iterator iter = missing_modules.begin(); 97 iter != missing_modules.end(); 98 ++iter) { 99 pending_extension_manager->AddFromExtensionImport( 100 iter->extension_id, 101 extension_urls::GetWebstoreUpdateUrl(), 102 SharedModuleInfo::IsSharedModule); 103 } 104 service->CheckForUpdatesSoon(); 105 } 106 return status; 107} 108 109scoped_ptr<ExtensionSet> SharedModuleService::GetDependentExtensions( 110 const Extension* extension) { 111 scoped_ptr<ExtensionSet> dependents(new ExtensionSet()); 112 113 if (SharedModuleInfo::IsSharedModule(extension)) { 114 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); 115 ExtensionService* service = 116 ExtensionSystem::Get(browser_context_)->extension_service(); 117 118 ExtensionSet set_to_check; 119 set_to_check.InsertAll(registry->enabled_extensions()); 120 set_to_check.InsertAll(registry->disabled_extensions()); 121 set_to_check.InsertAll(*service->delayed_installs()); 122 123 for (ExtensionSet::const_iterator iter = set_to_check.begin(); 124 iter != set_to_check.end(); 125 ++iter) { 126 if (SharedModuleInfo::ImportsExtensionById(iter->get(), 127 extension->id())) { 128 dependents->Insert(*iter); 129 } 130 } 131 } 132 return dependents.PassAs<ExtensionSet>(); 133} 134 135void SharedModuleService::PruneSharedModules() { 136 ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); 137 ExtensionService* service = 138 ExtensionSystem::Get(browser_context_)->extension_service(); 139 140 ExtensionSet set_to_check; 141 set_to_check.InsertAll(registry->enabled_extensions()); 142 set_to_check.InsertAll(registry->disabled_extensions()); 143 set_to_check.InsertAll(*service->delayed_installs()); 144 145 std::vector<std::string> shared_modules; 146 std::set<std::string> used_shared_modules; 147 148 for (ExtensionSet::const_iterator iter = set_to_check.begin(); 149 iter != set_to_check.end(); 150 ++iter) { 151 if (SharedModuleInfo::IsSharedModule(iter->get())) 152 shared_modules.push_back(iter->get()->id()); 153 154 const ImportInfoVector& imports = SharedModuleInfo::GetImports(iter->get()); 155 for (ImportInfoVector::const_iterator imports_iter = imports.begin(); 156 imports_iter != imports.end(); 157 ++imports_iter) { 158 used_shared_modules.insert(imports_iter->extension_id); 159 } 160 } 161 162 std::vector<std::string>::const_iterator shared_modules_iter; 163 for (shared_modules_iter = shared_modules.begin(); 164 shared_modules_iter != shared_modules.end(); 165 shared_modules_iter++) { 166 if (used_shared_modules.count(*shared_modules_iter)) 167 continue; 168 service->UninstallExtension( 169 *shared_modules_iter, 170 extensions::UNINSTALL_REASON_ORPHANED_SHARED_MODULE, 171 base::Bind(&base::DoNothing), 172 NULL); // Ignore error. 173 } 174} 175 176void SharedModuleService::OnExtensionInstalled( 177 content::BrowserContext* browser_context, 178 const Extension* extension, 179 bool is_update) { 180 if (is_update) 181 PruneSharedModules(); 182} 183 184void SharedModuleService::OnExtensionUninstalled( 185 content::BrowserContext* browser_context, 186 const Extension* extension, 187 extensions::UninstallReason reason) { 188 PruneSharedModules(); 189} 190 191} // namespace extensions 192