blob: 601bc3af29518ef814643e2bb78e7794c4d50abd [file] [log] [blame]
[email protected]f3d3b382014-03-14 21:19:281// Copyright 2014 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]f3d3b382014-03-14 21:19:285#include "chrome/browser/extensions/pending_extension_manager.h"
[email protected]51a3bf8b2012-06-08 22:53:066
[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]e3987852012-05-04 10:06:3010#include "base/version.h"
[email protected]6c9bedf2014-05-21 03:55:5111#include "chrome/common/extensions/extension_constants.h"
[email protected]c38831a12011-10-28 12:44:4912#include "content/public/browser/browser_thread.h"
[email protected]46f3e102014-03-25 01:22:4513#include "extensions/browser/extension_prefs.h"
[email protected]6c9bedf2014-05-21 03:55:5114#include "extensions/browser/extension_registry.h"
hanxia3182da2014-09-02 22:51:1915#include "extensions/common/constants.h"
[email protected]b52f8ca2013-11-28 08:25:2216#include "extensions/common/extension.h"
[email protected]a6483d22013-07-03 22:11:0017#include "url/gurl.h"
[email protected]b2907fd2011-03-25 16:43:3718
[email protected]631bb742011-11-02 11:29:3919using content::BrowserThread;
20
[email protected]b2907fd2011-03-25 16:43:3721namespace {
22
[email protected]b2907fd2011-03-25 16:43:3723// Install predicate used by AddFromExternalUpdateUrl().
[email protected]8f3bcbd2013-06-05 08:42:4024bool AlwaysInstall(const extensions::Extension* extension) {
[email protected]b2907fd2011-03-25 16:43:3725 return true;
26}
27
thakis37be69c2015-08-19 03:26:5728std::string GetVersionString(const Version& version) {
[email protected]4ec0f4b2012-12-07 09:41:4629 return version.IsValid() ? version.GetString() : "invalid";
30}
31
[email protected]b2907fd2011-03-25 16:43:3732} // namespace
33
[email protected]3f213ad2012-07-26 23:39:4134namespace extensions {
35
[email protected]b2907fd2011-03-25 16:43:3736PendingExtensionManager::PendingExtensionManager(
[email protected]46f3e102014-03-25 01:22:4537 content::BrowserContext* context)
[email protected]6c9bedf2014-05-21 03:55:5138 : context_(context) {}
[email protected]b2907fd2011-03-25 16:43:3739
40PendingExtensionManager::~PendingExtensionManager() {}
41
[email protected]51a3bf8b2012-06-08 22:53:0642const PendingExtensionInfo* PendingExtensionManager::GetById(
43 const std::string& id) const {
44 PendingExtensionList::const_iterator iter;
45 for (iter = pending_extension_list_.begin();
46 iter != pending_extension_list_.end();
47 ++iter) {
48 if (id == iter->id())
49 return &(*iter);
50 }
[email protected]b2907fd2011-03-25 16:43:3751
[email protected]51a3bf8b2012-06-08 22:53:0652 return NULL;
53}
54
55bool PendingExtensionManager::Remove(const std::string& id) {
56 PendingExtensionList::iterator iter;
57 for (iter = pending_extension_list_.begin();
58 iter != pending_extension_list_.end();
59 ++iter) {
60 if (id == iter->id()) {
61 pending_extension_list_.erase(iter);
62 return true;
63 }
[email protected]b2907fd2011-03-25 16:43:3764 }
65
66 return false;
67}
68
[email protected]b2907fd2011-03-25 16:43:3769bool PendingExtensionManager::IsIdPending(const std::string& id) const {
[email protected]870f5572013-12-19 12:30:1570 return GetById(id) != NULL;
[email protected]b2907fd2011-03-25 16:43:3771}
72
[email protected]9bd9a6862012-11-29 09:24:2273bool PendingExtensionManager::HasPendingExtensions() const {
74 return !pending_extension_list_.empty();
75}
76
[email protected]d31e19e2012-08-22 00:19:0477bool PendingExtensionManager::HasPendingExtensionFromSync() const {
78 PendingExtensionList::const_iterator iter;
79 for (iter = pending_extension_list_.begin();
80 iter != pending_extension_list_.end();
81 ++iter) {
82 if (iter->is_from_sync())
83 return true;
84 }
85
86 return false;
87}
88
[email protected]145a317b2011-04-12 16:03:4689bool PendingExtensionManager::AddFromSync(
[email protected]b2907fd2011-03-25 16:43:3790 const std::string& id,
91 const GURL& update_url,
treibe960e282015-09-11 10:38:0892 const base::Version& version,
[email protected]b2907fd2011-03-25 16:43:3793 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
mamir192d7882016-06-22 17:10:1694 bool remote_install) {
[email protected]b2907fd2011-03-25 16:43:3795 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
96
[email protected]6c9bedf2014-05-21 03:55:5197 if (ExtensionRegistry::Get(context_)->GetExtensionById(
98 id, ExtensionRegistry::EVERYTHING)) {
[email protected]145a317b2011-04-12 16:03:4699 LOG(ERROR) << "Trying to add pending extension " << id
100 << " which already exists";
101 return false;
[email protected]b2907fd2011-03-25 16:43:37102 }
103
[email protected]b873cd92012-02-09 21:51:48104 // Make sure we don't ever try to install the CWS app, because even though
105 // it is listed as a syncable app (because its values need to be synced) it
106 // should already be installed on every instance.
hanxia3182da2014-09-02 22:51:19107 if (id == extensions::kWebStoreAppId) {
[email protected]b873cd92012-02-09 21:51:48108 NOTREACHED();
109 return false;
110 }
111
[email protected]6c9bedf2014-05-21 03:55:51112 static const bool kIsFromSync = true;
113 static const Manifest::Location kSyncLocation = Manifest::INTERNAL;
114 static const bool kMarkAcknowledged = false;
[email protected]145a317b2011-04-12 16:03:46115
[email protected]d8fd0fd2014-03-24 13:16:06116 return AddExtensionImpl(id,
117 std::string(),
118 update_url,
treibe960e282015-09-11 10:38:08119 version,
[email protected]d8fd0fd2014-03-24 13:16:06120 should_allow_install,
121 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06122 kSyncLocation,
[email protected]21db9ef2014-05-16 02:06:27123 kMarkAcknowledged,
124 remote_install);
[email protected]b2907fd2011-03-25 16:43:37125}
126
[email protected]9f4e4f082013-06-21 07:11:19127bool PendingExtensionManager::AddFromExtensionImport(
128 const std::string& id,
129 const GURL& update_url,
130 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install) {
131 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
132
[email protected]6c9bedf2014-05-21 03:55:51133 if (ExtensionRegistry::Get(context_)->GetExtensionById(
134 id, ExtensionRegistry::EVERYTHING)) {
[email protected]9f4e4f082013-06-21 07:11:19135 LOG(ERROR) << "Trying to add pending extension " << id
136 << " which already exists";
137 return false;
138 }
139
[email protected]6c9bedf2014-05-21 03:55:51140 static const bool kIsFromSync = false;
[email protected]6c9bedf2014-05-21 03:55:51141 static const Manifest::Location kManifestLocation = Manifest::INTERNAL;
142 static const bool kMarkAcknowledged = false;
143 static const bool kRemoteInstall = false;
[email protected]9f4e4f082013-06-21 07:11:19144
[email protected]d8fd0fd2014-03-24 13:16:06145 return AddExtensionImpl(id,
146 std::string(),
147 update_url,
thakis37be69c2015-08-19 03:26:57148 Version(),
[email protected]d8fd0fd2014-03-24 13:16:06149 should_allow_install,
150 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06151 kManifestLocation,
[email protected]21db9ef2014-05-16 02:06:27152 kMarkAcknowledged,
153 kRemoteInstall);
[email protected]9f4e4f082013-06-21 07:11:19154}
155
[email protected]9060d8b02012-01-13 02:14:30156bool PendingExtensionManager::AddFromExternalUpdateUrl(
[email protected]612a1cb12012-10-17 13:18:03157 const std::string& id,
[email protected]d8fd0fd2014-03-24 13:16:06158 const std::string& install_parameter,
[email protected]612a1cb12012-10-17 13:18:03159 const GURL& update_url,
[email protected]464213a2013-10-15 01:06:48160 Manifest::Location location,
161 int creation_flags,
162 bool mark_acknowledged) {
[email protected]b2907fd2011-03-25 16:43:37163 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164
[email protected]6c9bedf2014-05-21 03:55:51165 static const bool kIsFromSync = false;
[email protected]6c9bedf2014-05-21 03:55:51166 static const bool kRemoteInstall = false;
[email protected]b2907fd2011-03-25 16:43:37167
[email protected]6c9bedf2014-05-21 03:55:51168 const Extension* extension = ExtensionRegistry::Get(context_)
169 ->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
[email protected]d8fd0fd2014-03-24 13:16:06170 if (extension && location == Manifest::GetHigherPriorityLocation(
171 location, extension->location())) {
[email protected]8a87a5332011-08-11 17:54:59172 // If the new location has higher priority than the location of an existing
173 // extension, let the update process overwrite the existing extension.
174 } else {
[email protected]46f3e102014-03-25 01:22:45175 if (ExtensionPrefs::Get(context_)->IsExternalExtensionUninstalled(id))
[email protected]9060d8b02012-01-13 02:14:30176 return false;
177
[email protected]8a87a5332011-08-11 17:54:59178 if (extension) {
179 LOG(DFATAL) << "Trying to add extension " << id
180 << " by external update, but it is already installed.";
[email protected]9060d8b02012-01-13 02:14:30181 return false;
[email protected]8a87a5332011-08-11 17:54:59182 }
[email protected]b2907fd2011-03-25 16:43:37183 }
184
[email protected]d8fd0fd2014-03-24 13:16:06185 return AddExtensionImpl(id,
186 install_parameter,
187 update_url,
thakis37be69c2015-08-19 03:26:57188 Version(),
[email protected]d8fd0fd2014-03-24 13:16:06189 &AlwaysInstall,
190 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06191 location,
[email protected]21db9ef2014-05-16 02:06:27192 mark_acknowledged,
193 kRemoteInstall);
[email protected]b2907fd2011-03-25 16:43:37194}
195
thakis37be69c2015-08-19 03:26:57196
[email protected]9060d8b02012-01-13 02:14:30197bool PendingExtensionManager::AddFromExternalFile(
[email protected]b2907fd2011-03-25 16:43:37198 const std::string& id,
[email protected]1d5e58b2013-01-31 08:41:40199 Manifest::Location install_source,
thakis37be69c2015-08-19 03:26:57200 const Version& version,
[email protected]464213a2013-10-15 01:06:48201 int creation_flags,
202 bool mark_acknowledged) {
[email protected]9060d8b02012-01-13 02:14:30203 // TODO(skerner): AddFromSync() checks to see if the extension is
204 // installed, but this method assumes that the caller already
205 // made sure it is not installed. Make all AddFrom*() methods
206 // consistent.
[email protected]6c9bedf2014-05-21 03:55:51207 const GURL& kUpdateUrl = GURL::EmptyGURL();
208 static const bool kIsFromSync = false;
[email protected]6c9bedf2014-05-21 03:55:51209 static const bool kRemoteInstall = false;
[email protected]b2907fd2011-03-25 16:43:37210
[email protected]d8fd0fd2014-03-24 13:16:06211 return AddExtensionImpl(id,
212 std::string(),
213 kUpdateUrl,
214 version,
215 &AlwaysInstall,
216 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06217 install_source,
[email protected]21db9ef2014-05-16 02:06:27218 mark_acknowledged,
219 kRemoteInstall);
[email protected]9060d8b02012-01-13 02:14:30220}
221
222void PendingExtensionManager::GetPendingIdsForUpdateCheck(
[email protected]51a3bf8b2012-06-08 22:53:06223 std::list<std::string>* out_ids_for_update_check) const {
224 PendingExtensionList::const_iterator iter;
225 for (iter = pending_extension_list_.begin();
226 iter != pending_extension_list_.end();
[email protected]9060d8b02012-01-13 02:14:30227 ++iter) {
[email protected]1d5e58b2013-01-31 08:41:40228 Manifest::Location install_source = iter->install_source();
[email protected]9060d8b02012-01-13 02:14:30229
230 // Some install sources read a CRX from the filesystem. They can
231 // not be fetched from an update URL, so don't include them in the
232 // set of ids.
[email protected]1d5e58b2013-01-31 08:41:40233 if (install_source == Manifest::EXTERNAL_PREF ||
binjin52eb40412015-08-18 06:29:30234 install_source == Manifest::EXTERNAL_REGISTRY ||
235 install_source == Manifest::EXTERNAL_POLICY) {
[email protected]9060d8b02012-01-13 02:14:30236 continue;
binjin52eb40412015-08-18 06:29:30237 }
[email protected]9060d8b02012-01-13 02:14:30238
[email protected]51a3bf8b2012-06-08 22:53:06239 out_ids_for_update_check->push_back(iter->id());
[email protected]9060d8b02012-01-13 02:14:30240 }
[email protected]b2907fd2011-03-25 16:43:37241}
242
[email protected]145a317b2011-04-12 16:03:46243bool PendingExtensionManager::AddExtensionImpl(
[email protected]9060d8b02012-01-13 02:14:30244 const std::string& id,
[email protected]d8fd0fd2014-03-24 13:16:06245 const std::string& install_parameter,
[email protected]9060d8b02012-01-13 02:14:30246 const GURL& update_url,
thakis37be69c2015-08-19 03:26:57247 const Version& version,
[email protected]b2907fd2011-03-25 16:43:37248 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
[email protected]9060d8b02012-01-13 02:14:30249 bool is_from_sync,
[email protected]464213a2013-10-15 01:06:48250 Manifest::Location install_source,
[email protected]21db9ef2014-05-16 02:06:27251 bool mark_acknowledged,
252 bool remote_install) {
[email protected]b2907fd2011-03-25 16:43:37253 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254
[email protected]4ec0f4b2012-12-07 09:41:46255 PendingExtensionInfo info(id,
[email protected]d8fd0fd2014-03-24 13:16:06256 install_parameter,
[email protected]4ec0f4b2012-12-07 09:41:46257 update_url,
258 version,
259 should_allow_install,
260 is_from_sync,
[email protected]464213a2013-10-15 01:06:48261 install_source,
[email protected]21db9ef2014-05-16 02:06:27262 mark_acknowledged,
263 remote_install);
[email protected]4ec0f4b2012-12-07 09:41:46264
[email protected]51a3bf8b2012-06-08 22:53:06265 if (const PendingExtensionInfo* pending = GetById(id)) {
[email protected]145a317b2011-04-12 16:03:46266 // Bugs in this code will manifest as sporadic incorrect extension
267 // locations in situations where multiple install sources run at the
268 // same time. For example, on first login to a chrome os machine, an
[email protected]9060d8b02012-01-13 02:14:30269 // extension may be requested by sync and the default extension set.
[email protected]145a317b2011-04-12 16:03:46270 // The following logging will help diagnose such issues.
[email protected]b2907fd2011-03-25 16:43:37271 VLOG(1) << "Extension id " << id
272 << " was entered for update more than once."
[email protected]51a3bf8b2012-06-08 22:53:06273 << " old location: " << pending->install_source()
[email protected]4ec0f4b2012-12-07 09:41:46274 << " new location: " << install_source
275 << " old version: " << GetVersionString(pending->version())
276 << " new version: " << GetVersionString(version);
[email protected]145a317b2011-04-12 16:03:46277
[email protected]e3987852012-05-04 10:06:30278 // Never override an existing extension with an older version. Only
279 // extensions from local CRX files have a known version; extensions from an
280 // update URL will get the latest version.
[email protected]e3987852012-05-04 10:06:30281
[email protected]4ec0f4b2012-12-07 09:41:46282 // If |pending| has the same or higher precedence than |info| then don't
283 // install |info| over |pending|.
284 if (pending->CompareTo(info) >= 0)
[email protected]e3987852012-05-04 10:06:30285 return false;
[email protected]e3987852012-05-04 10:06:30286
287 VLOG(1) << "Overwrite existing record.";
[email protected]51a3bf8b2012-06-08 22:53:06288
289 std::replace(pending_extension_list_.begin(),
290 pending_extension_list_.end(),
291 *pending,
[email protected]4ec0f4b2012-12-07 09:41:46292 info);
[email protected]51a3bf8b2012-06-08 22:53:06293 } else {
[email protected]4ec0f4b2012-12-07 09:41:46294 pending_extension_list_.push_back(info);
[email protected]b2907fd2011-03-25 16:43:37295 }
296
[email protected]e3987852012-05-04 10:06:30297 return true;
[email protected]b2907fd2011-03-25 16:43:37298}
299
300void PendingExtensionManager::AddForTesting(
[email protected]b2907fd2011-03-25 16:43:37301 const PendingExtensionInfo& pending_extension_info) {
[email protected]51a3bf8b2012-06-08 22:53:06302 pending_extension_list_.push_back(pending_extension_info);
[email protected]b2907fd2011-03-25 16:43:37303}
[email protected]3f213ad2012-07-26 23:39:41304
305} // namespace extensions