1c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// found in the LICENSE file.
4c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
5c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/shared_module_service.h"
6c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <set>
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <vector>
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/version.h"
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/extension_service.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/pending_extension_manager.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/browser/extension_registry.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/browser/extension_system.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/uninstall_reason.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/extension.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/common/extension_urls.h"
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace extensions {
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochnamespace {
22c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
23c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochtypedef std::vector<SharedModuleInfo::ImportInfo> ImportInfoVector;
24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochtypedef std::list<SharedModuleInfo::ImportInfo> ImportInfoList;
25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSharedModuleService::SharedModuleService(content::BrowserContext* context)
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : extension_registry_observer_(this), browser_context_(context) {
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
33c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSharedModuleService::~SharedModuleService() {
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSharedModuleService::ImportStatus SharedModuleService::CheckImports(
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const Extension* extension,
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ImportInfoList* missing_modules,
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ImportInfoList* outdated_modules) {
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(extension);
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(missing_modules && missing_modules->empty());
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(outdated_modules && outdated_modules->empty());
43c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ImportStatus status = IMPORT_STATUS_OK;
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const ImportInfoVector& imports = SharedModuleInfo::GetImports(extension);
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (ImportInfoVector::const_iterator iter = imports.begin();
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       iter != imports.end();
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       ++iter) {
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    base::Version version_required(iter->minimum_version);
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const Extension* imported_module =
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        registry->GetExtensionById(iter->extension_id,
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                   ExtensionRegistry::EVERYTHING);
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!imported_module) {
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (extension->from_webstore()) {
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        status = IMPORT_STATUS_UNSATISFIED;
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        missing_modules->push_back(*iter);
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      } else {
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return IMPORT_STATUS_UNRECOVERABLE;
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    } else if (!SharedModuleInfo::IsSharedModule(imported_module)) {
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return IMPORT_STATUS_UNRECOVERABLE;
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    } else if (version_required.IsValid() &&
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               imported_module->version()->CompareTo(version_required) < 0) {
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (imported_module->from_webstore()) {
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        outdated_modules->push_back(*iter);
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        status = IMPORT_STATUS_UNSATISFIED;
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      } else {
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        return IMPORT_STATUS_UNRECOVERABLE;
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return status;
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochSharedModuleService::ImportStatus SharedModuleService::SatisfyImports(
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const Extension* extension) {
80c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ImportInfoList missing_modules;
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ImportInfoList outdated_modules;
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ImportStatus status =
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CheckImports(extension, &missing_modules, &outdated_modules);
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ExtensionService* service =
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ExtensionSystem::Get(browser_context_)->extension_service();
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PendingExtensionManager* pending_extension_manager =
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      service->pending_extension_manager();
90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(pending_extension_manager);
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (status == IMPORT_STATUS_UNSATISFIED) {
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (ImportInfoList::const_iterator iter = missing_modules.begin();
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         iter != missing_modules.end();
95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         ++iter) {
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      pending_extension_manager->AddFromExtensionImport(
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          iter->extension_id,
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          extension_urls::GetWebstoreUpdateUrl(),
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          SharedModuleInfo::IsSharedModule);
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    service->CheckForUpdatesSoon();
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return status;
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)scoped_ptr<ExtensionSet> SharedModuleService::GetDependentExtensions(
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const Extension* extension) {
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  scoped_ptr<ExtensionSet> dependents(new ExtensionSet());
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (SharedModuleInfo::IsSharedModule(extension)) {
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ExtensionService* service =
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ExtensionSystem::Get(browser_context_)->extension_service();
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ExtensionSet set_to_check;
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    set_to_check.InsertAll(registry->enabled_extensions());
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    set_to_check.InsertAll(registry->disabled_extensions());
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    set_to_check.InsertAll(*service->delayed_installs());
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    for (ExtensionSet::const_iterator iter = set_to_check.begin();
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         iter != set_to_check.end();
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch         ++iter) {
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (SharedModuleInfo::ImportsExtensionById(iter->get(),
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                                 extension->id())) {
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        dependents->Insert(*iter);
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return dependents.PassAs<ExtensionSet>();
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SharedModuleService::PruneSharedModules() {
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ExtensionService* service =
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      ExtensionSystem::Get(browser_context_)->extension_service();
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ExtensionSet set_to_check;
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  set_to_check.InsertAll(registry->enabled_extensions());
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  set_to_check.InsertAll(registry->disabled_extensions());
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  set_to_check.InsertAll(*service->delayed_installs());
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<std::string> shared_modules;
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::set<std::string> used_shared_modules;
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (ExtensionSet::const_iterator iter = set_to_check.begin();
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       iter != set_to_check.end();
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch       ++iter) {
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (SharedModuleInfo::IsSharedModule(iter->get()))
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      shared_modules.push_back(iter->get()->id());
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const ImportInfoVector& imports = SharedModuleInfo::GetImports(iter->get());
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (ImportInfoVector::const_iterator imports_iter = imports.begin();
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         imports_iter != imports.end();
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch         ++imports_iter) {
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      used_shared_modules.insert(imports_iter->extension_id);
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::vector<std::string>::const_iterator shared_modules_iter;
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (shared_modules_iter = shared_modules.begin();
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       shared_modules_iter != shared_modules.end();
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       shared_modules_iter++) {
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (used_shared_modules.count(*shared_modules_iter))
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      continue;
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    service->UninstallExtension(
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        *shared_modules_iter,
1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        extensions::UNINSTALL_REASON_ORPHANED_SHARED_MODULE,
1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        base::Bind(&base::DoNothing),
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        NULL);  // Ignore error.
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SharedModuleService::OnExtensionInstalled(
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const Extension* extension,
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    bool is_update) {
177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (is_update)
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    PruneSharedModules();
179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
181116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SharedModuleService::OnExtensionUninstalled(
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    content::BrowserContext* browser_context,
1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const Extension* extension,
1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    extensions::UninstallReason reason) {
185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PruneSharedModules();
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}  // namespace extensions
189