Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / shared_module_service.cc
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 "extensions/browser/extension_registry.h"
14 #include "extensions/browser/extension_system.h"
15 #include "extensions/browser/uninstall_reason.h"
16 #include "extensions/common/extension.h"
17 #include "extensions/common/extension_urls.h"
18
19 namespace extensions {
20
21 namespace {
22
23 typedef std::vector<SharedModuleInfo::ImportInfo> ImportInfoVector;
24 typedef std::list<SharedModuleInfo::ImportInfo> ImportInfoList;
25
26 }  // namespace
27
28 SharedModuleService::SharedModuleService(content::BrowserContext* context)
29     : extension_registry_observer_(this), browser_context_(context) {
30   extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
31 }
32
33 SharedModuleService::~SharedModuleService() {
34 }
35
36 SharedModuleService::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   // TODO(crbug.com/420147): Code like this lives in CrxInstaller and
47   // UnpackedInstaller.  If a change is made here that is important to enforce
48   // at install time, those locations need to be updated.
49   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
50   const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension);
51   for (ImportInfoVector::const_iterator iter = imports.begin();
52        iter != imports.end();
53        ++iter) {
54     base::Version version_required(iter->minimum_version);
55     const Extension* imported_module =
56         registry->GetExtensionById(iter->extension_id,
57                                    ExtensionRegistry::EVERYTHING);
58     if (!imported_module) {
59       if (extension->from_webstore()) {
60         status = IMPORT_STATUS_UNSATISFIED;
61         missing_modules->push_back(*iter);
62       } else {
63         return IMPORT_STATUS_UNRECOVERABLE;
64       }
65     } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
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
81 SharedModuleService::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
109 scoped_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.Pass();
133 }
134
135 void 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
176 void SharedModuleService::OnExtensionInstalled(
177     content::BrowserContext* browser_context,
178     const Extension* extension,
179     bool is_update) {
180   if (is_update)
181     PruneSharedModules();
182 }
183
184 void SharedModuleService::OnExtensionUninstalled(
185     content::BrowserContext* browser_context,
186     const Extension* extension,
187     extensions::UninstallReason reason) {
188   PruneSharedModules();
189 }
190
191 }  // namespace extensions