blob: b86b0eb38f3cb2f321568ffcb6ac65b4b7481f9d [file] [log] [blame]
[email protected]9060d8b02012-01-13 02:14:301// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b2907fd2011-03-25 16:43:372// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]51a3bf8b2012-06-08 22:53:065#include "chrome/browser/extensions/pending_extension_manager.h"
6
[email protected]d31e19e2012-08-22 00:19:047#include <algorithm>
8
[email protected]b2907fd2011-03-25 16:43:379#include "base/logging.h"
[email protected]7286e3fc2011-07-19 22:13:2410#include "base/stl_util.h"
[email protected]e3987852012-05-04 10:06:3011#include "base/version.h"
[email protected]b2907fd2011-03-25 16:43:3712#include "chrome/browser/extensions/extension_service.h"
[email protected]51a3bf8b2012-06-08 22:53:0613#include "chrome/browser/extensions/pending_extension_info.h"
[email protected]145a317b2011-04-12 16:03:4614#include "chrome/common/extensions/extension.h"
[email protected]c38831a12011-10-28 12:44:4915#include "content/public/browser/browser_thread.h"
[email protected]b2907fd2011-03-25 16:43:3716
[email protected]631bb742011-11-02 11:29:3917using content::BrowserThread;
18
[email protected]b2907fd2011-03-25 16:43:3719namespace {
20
[email protected]b2907fd2011-03-25 16:43:3721// Install predicate used by AddFromExternalUpdateUrl().
[email protected]3f213ad2012-07-26 23:39:4122bool AlwaysInstall(const extensions::Extension& extension) {
[email protected]b2907fd2011-03-25 16:43:3723 return true;
24}
25
26} // namespace
27
[email protected]3f213ad2012-07-26 23:39:4128namespace extensions {
29
[email protected]b2907fd2011-03-25 16:43:3730PendingExtensionManager::PendingExtensionManager(
[email protected]2859946f2011-04-04 18:18:0631 const ExtensionServiceInterface& service)
[email protected]b2907fd2011-03-25 16:43:3732 : service_(service) {
33}
34
35PendingExtensionManager::~PendingExtensionManager() {}
36
[email protected]51a3bf8b2012-06-08 22:53:0637const PendingExtensionInfo* PendingExtensionManager::GetById(
38 const std::string& id) const {
39 PendingExtensionList::const_iterator iter;
40 for (iter = pending_extension_list_.begin();
41 iter != pending_extension_list_.end();
42 ++iter) {
43 if (id == iter->id())
44 return &(*iter);
45 }
[email protected]b2907fd2011-03-25 16:43:3746
[email protected]51a3bf8b2012-06-08 22:53:0647 return NULL;
48}
49
50bool PendingExtensionManager::Remove(const std::string& id) {
51 PendingExtensionList::iterator iter;
52 for (iter = pending_extension_list_.begin();
53 iter != pending_extension_list_.end();
54 ++iter) {
55 if (id == iter->id()) {
56 pending_extension_list_.erase(iter);
57 return true;
58 }
[email protected]b2907fd2011-03-25 16:43:3759 }
60
61 return false;
62}
63
[email protected]b2907fd2011-03-25 16:43:3764bool PendingExtensionManager::IsIdPending(const std::string& id) const {
[email protected]51a3bf8b2012-06-08 22:53:0665 PendingExtensionList::const_iterator iter;
66 for (iter = pending_extension_list_.begin();
67 iter != pending_extension_list_.end();
68 ++iter) {
69 if (id == iter->id())
70 return true;
71 }
72
73 return false;
[email protected]b2907fd2011-03-25 16:43:3774}
75
[email protected]9bd9a6862012-11-29 09:24:2276bool PendingExtensionManager::HasPendingExtensions() const {
77 return !pending_extension_list_.empty();
78}
79
[email protected]d31e19e2012-08-22 00:19:0480bool PendingExtensionManager::HasPendingExtensionFromSync() const {
81 PendingExtensionList::const_iterator iter;
82 for (iter = pending_extension_list_.begin();
83 iter != pending_extension_list_.end();
84 ++iter) {
85 if (iter->is_from_sync())
86 return true;
87 }
88
89 return false;
90}
91
[email protected]145a317b2011-04-12 16:03:4692bool PendingExtensionManager::AddFromSync(
[email protected]b2907fd2011-03-25 16:43:3793 const std::string& id,
94 const GURL& update_url,
95 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
[email protected]6cc7dbae2011-04-29 21:18:3396 bool install_silently) {
[email protected]b2907fd2011-03-25 16:43:3797 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
98
[email protected]8001df22011-04-28 19:59:4799 if (service_.GetInstalledExtension(id)) {
[email protected]145a317b2011-04-12 16:03:46100 LOG(ERROR) << "Trying to add pending extension " << id
101 << " which already exists";
102 return false;
[email protected]b2907fd2011-03-25 16:43:37103 }
104
[email protected]b873cd92012-02-09 21:51:48105 // Make sure we don't ever try to install the CWS app, because even though
106 // it is listed as a syncable app (because its values need to be synced) it
107 // should already be installed on every instance.
108 if (id == extension_misc::kWebStoreAppId) {
109 NOTREACHED();
110 return false;
111 }
112
[email protected]145a317b2011-04-12 16:03:46113 const bool kIsFromSync = true;
114 const Extension::Location kSyncLocation = Extension::INTERNAL;
115
[email protected]e3987852012-05-04 10:06:30116 return AddExtensionImpl(id, update_url, Version(), should_allow_install,
[email protected]6cc7dbae2011-04-29 21:18:33117 kIsFromSync, install_silently, kSyncLocation);
[email protected]b2907fd2011-03-25 16:43:37118}
119
[email protected]9060d8b02012-01-13 02:14:30120bool PendingExtensionManager::AddFromExternalUpdateUrl(
[email protected]612a1cb12012-10-17 13:18:03121 const std::string& id,
122 const GURL& update_url,
[email protected]b2907fd2011-03-25 16:43:37123 Extension::Location location) {
124 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
125
126 const bool kIsFromSync = false;
127 const bool kInstallSilently = true;
[email protected]b2907fd2011-03-25 16:43:37128
[email protected]8a87a5332011-08-11 17:54:59129 const Extension* extension = service_.GetInstalledExtension(id);
130 if (extension &&
131 location == Extension::GetHigherPriorityLocation(location,
132 extension->location())) {
133 // If the new location has higher priority than the location of an existing
134 // extension, let the update process overwrite the existing extension.
135 } else {
[email protected]9060d8b02012-01-13 02:14:30136 if (service_.IsExternalExtensionUninstalled(id))
137 return false;
138
[email protected]8a87a5332011-08-11 17:54:59139 if (extension) {
140 LOG(DFATAL) << "Trying to add extension " << id
141 << " by external update, but it is already installed.";
[email protected]9060d8b02012-01-13 02:14:30142 return false;
[email protected]8a87a5332011-08-11 17:54:59143 }
[email protected]b2907fd2011-03-25 16:43:37144 }
145
[email protected]e3987852012-05-04 10:06:30146 return AddExtensionImpl(id, update_url, Version(), &AlwaysInstall,
[email protected]9060d8b02012-01-13 02:14:30147 kIsFromSync, kInstallSilently,
148 location);
[email protected]b2907fd2011-03-25 16:43:37149}
150
151
[email protected]9060d8b02012-01-13 02:14:30152bool PendingExtensionManager::AddFromExternalFile(
[email protected]b2907fd2011-03-25 16:43:37153 const std::string& id,
[email protected]e3987852012-05-04 10:06:30154 Extension::Location install_source,
155 const Version& version) {
[email protected]9060d8b02012-01-13 02:14:30156 // TODO(skerner): AddFromSync() checks to see if the extension is
157 // installed, but this method assumes that the caller already
158 // made sure it is not installed. Make all AddFrom*() methods
159 // consistent.
[email protected]b2907fd2011-03-25 16:43:37160 GURL kUpdateUrl = GURL();
161 bool kIsFromSync = false;
162 bool kInstallSilently = true;
[email protected]b2907fd2011-03-25 16:43:37163
[email protected]9060d8b02012-01-13 02:14:30164 return AddExtensionImpl(
165 id,
166 kUpdateUrl,
[email protected]e3987852012-05-04 10:06:30167 version,
[email protected]9060d8b02012-01-13 02:14:30168 &AlwaysInstall,
169 kIsFromSync,
170 kInstallSilently,
171 install_source);
[email protected]9060d8b02012-01-13 02:14:30172}
173
174void PendingExtensionManager::GetPendingIdsForUpdateCheck(
[email protected]51a3bf8b2012-06-08 22:53:06175 std::list<std::string>* out_ids_for_update_check) const {
176 PendingExtensionList::const_iterator iter;
177 for (iter = pending_extension_list_.begin();
178 iter != pending_extension_list_.end();
[email protected]9060d8b02012-01-13 02:14:30179 ++iter) {
[email protected]51a3bf8b2012-06-08 22:53:06180 Extension::Location install_source = iter->install_source();
[email protected]9060d8b02012-01-13 02:14:30181
182 // Some install sources read a CRX from the filesystem. They can
183 // not be fetched from an update URL, so don't include them in the
184 // set of ids.
185 if (install_source == Extension::EXTERNAL_PREF ||
186 install_source == Extension::EXTERNAL_REGISTRY)
187 continue;
188
[email protected]51a3bf8b2012-06-08 22:53:06189 out_ids_for_update_check->push_back(iter->id());
[email protected]9060d8b02012-01-13 02:14:30190 }
[email protected]b2907fd2011-03-25 16:43:37191}
192
[email protected]145a317b2011-04-12 16:03:46193bool PendingExtensionManager::AddExtensionImpl(
[email protected]9060d8b02012-01-13 02:14:30194 const std::string& id,
195 const GURL& update_url,
[email protected]e3987852012-05-04 10:06:30196 const Version& version,
[email protected]b2907fd2011-03-25 16:43:37197 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
[email protected]9060d8b02012-01-13 02:14:30198 bool is_from_sync,
199 bool install_silently,
[email protected]6cc7dbae2011-04-29 21:18:33200 Extension::Location install_source) {
[email protected]b2907fd2011-03-25 16:43:37201 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202
[email protected]51a3bf8b2012-06-08 22:53:06203 if (const PendingExtensionInfo* pending = GetById(id)) {
[email protected]145a317b2011-04-12 16:03:46204 // Bugs in this code will manifest as sporadic incorrect extension
205 // locations in situations where multiple install sources run at the
206 // same time. For example, on first login to a chrome os machine, an
[email protected]9060d8b02012-01-13 02:14:30207 // extension may be requested by sync and the default extension set.
[email protected]145a317b2011-04-12 16:03:46208 // The following logging will help diagnose such issues.
[email protected]b2907fd2011-03-25 16:43:37209 VLOG(1) << "Extension id " << id
210 << " was entered for update more than once."
[email protected]51a3bf8b2012-06-08 22:53:06211 << " old location: " << pending->install_source()
[email protected]145a317b2011-04-12 16:03:46212 << " new location: " << install_source;
213
[email protected]e3987852012-05-04 10:06:30214 // Never override an existing extension with an older version. Only
215 // extensions from local CRX files have a known version; extensions from an
216 // update URL will get the latest version.
217 if (version.IsValid() &&
[email protected]51a3bf8b2012-06-08 22:53:06218 pending->version().IsValid() &&
219 pending->version().CompareTo(version) == 1) {
[email protected]e3987852012-05-04 10:06:30220 VLOG(1) << "Keep existing record (has a newer version).";
221 return false;
222 }
223
[email protected]145a317b2011-04-12 16:03:46224 Extension::Location higher_priority_location =
225 Extension::GetHigherPriorityLocation(
[email protected]51a3bf8b2012-06-08 22:53:06226 install_source, pending->install_source());
[email protected]145a317b2011-04-12 16:03:46227
[email protected]e3987852012-05-04 10:06:30228 if (higher_priority_location != install_source) {
229 VLOG(1) << "Keep existing record (has a higher priority location).";
230 return false;
[email protected]145a317b2011-04-12 16:03:46231 }
[email protected]e3987852012-05-04 10:06:30232
233 VLOG(1) << "Overwrite existing record.";
[email protected]51a3bf8b2012-06-08 22:53:06234
235 std::replace(pending_extension_list_.begin(),
236 pending_extension_list_.end(),
237 *pending,
238 PendingExtensionInfo(id,
239 update_url,
240 version,
241 should_allow_install,
242 is_from_sync,
243 install_silently,
244 install_source));
245 } else {
246 pending_extension_list_.push_back(
247 PendingExtensionInfo(id,
248 update_url,
249 version,
250 should_allow_install,
251 is_from_sync,
252 install_silently,
253 install_source));
[email protected]b2907fd2011-03-25 16:43:37254 }
255
[email protected]e3987852012-05-04 10:06:30256 return true;
[email protected]b2907fd2011-03-25 16:43:37257}
258
259void PendingExtensionManager::AddForTesting(
[email protected]b2907fd2011-03-25 16:43:37260 const PendingExtensionInfo& pending_extension_info) {
[email protected]51a3bf8b2012-06-08 22:53:06261 pending_extension_list_.push_back(pending_extension_info);
[email protected]b2907fd2011-03-25 16:43:37262}
[email protected]3f213ad2012-07-26 23:39:41263
264} // namespace extensions