Upstream version 8.37.180.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 <vector>
8
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"
16
17 namespace extensions {
18
19 namespace {
20
21 typedef std::vector<SharedModuleInfo::ImportInfo> ImportInfoVector;
22 typedef std::list<SharedModuleInfo::ImportInfo> ImportInfoList;
23
24 }  // namespace
25
26 SharedModuleService::SharedModuleService(content::BrowserContext* context)
27     : extension_registry_observer_(this), browser_context_(context) {
28   extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
29 }
30
31 SharedModuleService::~SharedModuleService() {
32 }
33
34 SharedModuleService::ImportStatus SharedModuleService::CheckImports(
35     const Extension* extension,
36     ImportInfoList* missing_modules,
37     ImportInfoList* outdated_modules) {
38   DCHECK(extension);
39   DCHECK(missing_modules && missing_modules->empty());
40   DCHECK(outdated_modules && outdated_modules->empty());
41
42   ImportStatus status = IMPORT_STATUS_OK;
43
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();
48        ++iter) {
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);
57       } else {
58         return IMPORT_STATUS_UNRECOVERABLE;
59       }
60     } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
61       return IMPORT_STATUS_UNRECOVERABLE;
62     } else if (!SharedModuleInfo::IsExportAllowedByWhitelist(imported_module,
63                                                              extension->id())) {
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;
70       } else {
71         return IMPORT_STATUS_UNRECOVERABLE;
72       }
73     }
74   }
75
76   return status;
77 }
78
79 SharedModuleService::ImportStatus SharedModuleService::SatisfyImports(
80     const Extension* extension) {
81   ImportInfoList missing_modules;
82   ImportInfoList outdated_modules;
83   ImportStatus status =
84       CheckImports(extension, &missing_modules, &outdated_modules);
85
86   ExtensionService* service =
87       ExtensionSystem::Get(browser_context_)->extension_service();
88
89   PendingExtensionManager* pending_extension_manager =
90       service->pending_extension_manager();
91   DCHECK(pending_extension_manager);
92
93   if (status == IMPORT_STATUS_UNSATISFIED) {
94     for (ImportInfoList::const_iterator iter = missing_modules.begin();
95          iter != missing_modules.end();
96          ++iter) {
97       pending_extension_manager->AddFromExtensionImport(
98           iter->extension_id,
99           extension_urls::GetWebstoreUpdateUrl(),
100           SharedModuleInfo::IsSharedModule);
101     }
102     service->CheckForUpdatesSoon();
103   }
104   return status;
105 }
106
107 scoped_ptr<ExtensionSet> SharedModuleService::GetDependentExtensions(
108     const Extension* extension) {
109   scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
110
111   if (SharedModuleInfo::IsSharedModule(extension)) {
112     ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
113     ExtensionService* service =
114         ExtensionSystem::Get(browser_context_)->extension_service();
115
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());
120
121     for (ExtensionSet::const_iterator iter = set_to_check.begin();
122          iter != set_to_check.end();
123          ++iter) {
124       if (SharedModuleInfo::ImportsExtensionById(iter->get(),
125                                                  extension->id())) {
126         dependents->Insert(*iter);
127       }
128     }
129   }
130   return dependents.PassAs<ExtensionSet>();
131 }
132
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))
138     return;
139
140   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
141   ExtensionService* service =
142       ExtensionSystem::Get(browser_context_)->extension_service();
143
144   const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension);
145   for (ImportInfoVector::const_iterator iter = imports.begin();
146        iter != imports.end();
147        ++iter) {
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.
158       }
159     }
160   }
161 }
162
163 }  // namespace extensions