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/install_tracker.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/common/extension.h"
18 namespace extensions
{
22 typedef std::vector
<SharedModuleInfo::ImportInfo
> ImportInfoVector
;
23 typedef std::list
<SharedModuleInfo::ImportInfo
> ImportInfoList
;
27 SharedModuleService::SharedModuleService(content::BrowserContext
* context
)
28 : context_(context
), observing_(false) {
29 InstallTracker::Get(context_
)->AddObserver(this);
32 SharedModuleService::~SharedModuleService() {
34 InstallTracker::Get(context_
)->RemoveObserver(this);
37 SharedModuleService::ImportStatus
SharedModuleService::CheckImports(
38 const extensions::Extension
* extension
,
39 ImportInfoList
* missing_modules
,
40 ImportInfoList
* outdated_modules
) {
42 DCHECK(missing_modules
&& missing_modules
->empty());
43 DCHECK(outdated_modules
&& outdated_modules
->empty());
45 ImportStatus status
= IMPORT_STATUS_OK
;
47 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context_
);
48 const ImportInfoVector
& imports
= SharedModuleInfo::GetImports(extension
);
49 for (ImportInfoVector::const_iterator iter
= imports
.begin();
50 iter
!= imports
.end();
52 base::Version
version_required(iter
->minimum_version
);
53 const Extension
* imported_module
=
54 registry
->GetExtensionById(iter
->extension_id
,
55 ExtensionRegistry::EVERYTHING
);
56 if (!imported_module
) {
57 if (extension
->from_webstore()) {
58 status
= IMPORT_STATUS_UNSATISFIED
;
59 missing_modules
->push_back(*iter
);
61 return IMPORT_STATUS_UNRECOVERABLE
;
63 } else if (!SharedModuleInfo::IsSharedModule(imported_module
)) {
64 return IMPORT_STATUS_UNRECOVERABLE
;
65 } else if (!SharedModuleInfo::IsExportAllowedByWhitelist(imported_module
,
67 return IMPORT_STATUS_UNRECOVERABLE
;
68 } else if (version_required
.IsValid() &&
69 imported_module
->version()->CompareTo(version_required
) < 0) {
70 if (imported_module
->from_webstore()) {
71 outdated_modules
->push_back(*iter
);
72 status
= IMPORT_STATUS_UNSATISFIED
;
74 return IMPORT_STATUS_UNRECOVERABLE
;
82 SharedModuleService::ImportStatus
SharedModuleService::SatisfyImports(
83 const Extension
* extension
) {
84 ImportInfoList missing_modules
;
85 ImportInfoList outdated_modules
;
87 CheckImports(extension
, &missing_modules
, &outdated_modules
);
89 ExtensionService
* service
=
90 ExtensionSystem::Get(context_
)->extension_service();
92 PendingExtensionManager
* pending_extension_manager
=
93 service
->pending_extension_manager();
94 DCHECK(pending_extension_manager
);
96 if (status
== IMPORT_STATUS_UNSATISFIED
) {
97 for (ImportInfoList::const_iterator iter
= missing_modules
.begin();
98 iter
!= missing_modules
.end();
100 pending_extension_manager
->AddFromExtensionImport(
102 extension_urls::GetWebstoreUpdateUrl(),
103 SharedModuleInfo::IsSharedModule
);
105 service
->CheckForUpdatesSoon();
110 scoped_ptr
<const ExtensionSet
> SharedModuleService::GetDependentExtensions(
111 const Extension
* extension
) {
112 scoped_ptr
<ExtensionSet
> dependents(new ExtensionSet());
114 if (SharedModuleInfo::IsSharedModule(extension
)) {
115 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context_
);
116 ExtensionService
* service
=
117 ExtensionSystem::Get(context_
)->extension_service();
119 ExtensionSet set_to_check
;
120 set_to_check
.InsertAll(registry
->enabled_extensions());
121 set_to_check
.InsertAll(registry
->disabled_extensions());
122 set_to_check
.InsertAll(*service
->delayed_installs());
124 for (ExtensionSet::const_iterator iter
= set_to_check
.begin();
125 iter
!= set_to_check
.end();
127 if (SharedModuleInfo::ImportsExtensionById(iter
->get(),
129 dependents
->Insert(*iter
);
133 return dependents
.PassAs
<const ExtensionSet
>();
136 void SharedModuleService::PruneSharedModulesOnUninstall(
137 const Extension
* extension
) {
138 if (!SharedModuleInfo::ImportsModules(extension
))
141 ExtensionRegistry
* registry
= ExtensionRegistry::Get(context_
);
142 ExtensionService
* service
=
143 ExtensionSystem::Get(context_
)->extension_service();
145 const ImportInfoVector
& imports
= SharedModuleInfo::GetImports(extension
);
146 for (ImportInfoVector::const_iterator iter
= imports
.begin();
147 iter
!= imports
.end();
149 const Extension
* imported_module
=
150 registry
->GetExtensionById(iter
->extension_id
,
151 ExtensionRegistry::EVERYTHING
);
152 if (imported_module
&& imported_module
->from_webstore()) {
153 scoped_ptr
<const ExtensionSet
> dependents
=
154 GetDependentExtensions(imported_module
);
155 if (dependents
->is_empty()) {
156 service
->UninstallExtension(iter
->extension_id
,
157 true, // External uninstall.
158 NULL
); // Ignore error.
164 void SharedModuleService::OnExtensionUninstalled(const Extension
* extension
) {
165 PruneSharedModulesOnUninstall(extension
);
168 void SharedModuleService::OnShutdown() {
169 InstallTracker::Get(context_
)->RemoveObserver(this);
173 } // namespace extensions