blob: ee7759b10229fd1c1c3b6b28818bcef4deae38ab [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
pwnallcbd73192016-08-22 18:59:1728std::string GetVersionString(const base::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,
mamir0128d5a2016-07-15 20:55:48123 Extension::NO_FLAGS,
[email protected]21db9ef2014-05-16 02:06:27124 kMarkAcknowledged,
125 remote_install);
[email protected]b2907fd2011-03-25 16:43:37126}
127
[email protected]9f4e4f082013-06-21 07:11:19128bool PendingExtensionManager::AddFromExtensionImport(
129 const std::string& id,
130 const GURL& update_url,
131 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install) {
132 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
133
[email protected]6c9bedf2014-05-21 03:55:51134 if (ExtensionRegistry::Get(context_)->GetExtensionById(
135 id, ExtensionRegistry::EVERYTHING)) {
[email protected]9f4e4f082013-06-21 07:11:19136 LOG(ERROR) << "Trying to add pending extension " << id
137 << " which already exists";
138 return false;
139 }
140
[email protected]6c9bedf2014-05-21 03:55:51141 static const bool kIsFromSync = false;
[email protected]6c9bedf2014-05-21 03:55:51142 static const Manifest::Location kManifestLocation = Manifest::INTERNAL;
143 static const bool kMarkAcknowledged = false;
144 static const bool kRemoteInstall = false;
[email protected]9f4e4f082013-06-21 07:11:19145
[email protected]d8fd0fd2014-03-24 13:16:06146 return AddExtensionImpl(id,
147 std::string(),
148 update_url,
pwnallcbd73192016-08-22 18:59:17149 base::Version(),
[email protected]d8fd0fd2014-03-24 13:16:06150 should_allow_install,
151 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06152 kManifestLocation,
mamir0128d5a2016-07-15 20:55:48153 Extension::NO_FLAGS,
[email protected]21db9ef2014-05-16 02:06:27154 kMarkAcknowledged,
155 kRemoteInstall);
[email protected]9f4e4f082013-06-21 07:11:19156}
157
[email protected]9060d8b02012-01-13 02:14:30158bool PendingExtensionManager::AddFromExternalUpdateUrl(
[email protected]612a1cb12012-10-17 13:18:03159 const std::string& id,
[email protected]d8fd0fd2014-03-24 13:16:06160 const std::string& install_parameter,
[email protected]612a1cb12012-10-17 13:18:03161 const GURL& update_url,
[email protected]464213a2013-10-15 01:06:48162 Manifest::Location location,
163 int creation_flags,
164 bool mark_acknowledged) {
[email protected]b2907fd2011-03-25 16:43:37165 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
166
[email protected]6c9bedf2014-05-21 03:55:51167 static const bool kIsFromSync = false;
[email protected]6c9bedf2014-05-21 03:55:51168 static const bool kRemoteInstall = false;
[email protected]b2907fd2011-03-25 16:43:37169
[email protected]6c9bedf2014-05-21 03:55:51170 const Extension* extension = ExtensionRegistry::Get(context_)
171 ->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
[email protected]d8fd0fd2014-03-24 13:16:06172 if (extension && location == Manifest::GetHigherPriorityLocation(
173 location, extension->location())) {
[email protected]8a87a5332011-08-11 17:54:59174 // If the new location has higher priority than the location of an existing
175 // extension, let the update process overwrite the existing extension.
176 } else {
[email protected]46f3e102014-03-25 01:22:45177 if (ExtensionPrefs::Get(context_)->IsExternalExtensionUninstalled(id))
[email protected]9060d8b02012-01-13 02:14:30178 return false;
179
[email protected]8a87a5332011-08-11 17:54:59180 if (extension) {
181 LOG(DFATAL) << "Trying to add extension " << id
182 << " by external update, but it is already installed.";
[email protected]9060d8b02012-01-13 02:14:30183 return false;
[email protected]8a87a5332011-08-11 17:54:59184 }
[email protected]b2907fd2011-03-25 16:43:37185 }
186
[email protected]d8fd0fd2014-03-24 13:16:06187 return AddExtensionImpl(id,
188 install_parameter,
189 update_url,
pwnallcbd73192016-08-22 18:59:17190 base::Version(),
[email protected]d8fd0fd2014-03-24 13:16:06191 &AlwaysInstall,
192 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06193 location,
mamir0128d5a2016-07-15 20:55:48194 creation_flags,
[email protected]21db9ef2014-05-16 02:06:27195 mark_acknowledged,
196 kRemoteInstall);
[email protected]b2907fd2011-03-25 16:43:37197}
198
thakis37be69c2015-08-19 03:26:57199
[email protected]9060d8b02012-01-13 02:14:30200bool PendingExtensionManager::AddFromExternalFile(
[email protected]b2907fd2011-03-25 16:43:37201 const std::string& id,
[email protected]1d5e58b2013-01-31 08:41:40202 Manifest::Location install_source,
pwnallcbd73192016-08-22 18:59:17203 const base::Version& version,
[email protected]464213a2013-10-15 01:06:48204 int creation_flags,
205 bool mark_acknowledged) {
[email protected]9060d8b02012-01-13 02:14:30206 // TODO(skerner): AddFromSync() checks to see if the extension is
207 // installed, but this method assumes that the caller already
208 // made sure it is not installed. Make all AddFrom*() methods
209 // consistent.
[email protected]6c9bedf2014-05-21 03:55:51210 const GURL& kUpdateUrl = GURL::EmptyGURL();
211 static const bool kIsFromSync = false;
[email protected]6c9bedf2014-05-21 03:55:51212 static const bool kRemoteInstall = false;
[email protected]b2907fd2011-03-25 16:43:37213
[email protected]d8fd0fd2014-03-24 13:16:06214 return AddExtensionImpl(id,
215 std::string(),
216 kUpdateUrl,
217 version,
218 &AlwaysInstall,
219 kIsFromSync,
[email protected]d8fd0fd2014-03-24 13:16:06220 install_source,
mamir0128d5a2016-07-15 20:55:48221 creation_flags,
[email protected]21db9ef2014-05-16 02:06:27222 mark_acknowledged,
223 kRemoteInstall);
[email protected]9060d8b02012-01-13 02:14:30224}
225
226void PendingExtensionManager::GetPendingIdsForUpdateCheck(
[email protected]51a3bf8b2012-06-08 22:53:06227 std::list<std::string>* out_ids_for_update_check) const {
228 PendingExtensionList::const_iterator iter;
229 for (iter = pending_extension_list_.begin();
230 iter != pending_extension_list_.end();
[email protected]9060d8b02012-01-13 02:14:30231 ++iter) {
[email protected]1d5e58b2013-01-31 08:41:40232 Manifest::Location install_source = iter->install_source();
[email protected]9060d8b02012-01-13 02:14:30233
234 // Some install sources read a CRX from the filesystem. They can
235 // not be fetched from an update URL, so don't include them in the
236 // set of ids.
[email protected]1d5e58b2013-01-31 08:41:40237 if (install_source == Manifest::EXTERNAL_PREF ||
binjin52eb40412015-08-18 06:29:30238 install_source == Manifest::EXTERNAL_REGISTRY ||
239 install_source == Manifest::EXTERNAL_POLICY) {
[email protected]9060d8b02012-01-13 02:14:30240 continue;
binjin52eb40412015-08-18 06:29:30241 }
[email protected]9060d8b02012-01-13 02:14:30242
[email protected]51a3bf8b2012-06-08 22:53:06243 out_ids_for_update_check->push_back(iter->id());
[email protected]9060d8b02012-01-13 02:14:30244 }
[email protected]b2907fd2011-03-25 16:43:37245}
246
[email protected]145a317b2011-04-12 16:03:46247bool PendingExtensionManager::AddExtensionImpl(
[email protected]9060d8b02012-01-13 02:14:30248 const std::string& id,
[email protected]d8fd0fd2014-03-24 13:16:06249 const std::string& install_parameter,
[email protected]9060d8b02012-01-13 02:14:30250 const GURL& update_url,
pwnallcbd73192016-08-22 18:59:17251 const base::Version& version,
[email protected]b2907fd2011-03-25 16:43:37252 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
[email protected]9060d8b02012-01-13 02:14:30253 bool is_from_sync,
[email protected]464213a2013-10-15 01:06:48254 Manifest::Location install_source,
mamir0128d5a2016-07-15 20:55:48255 int creation_flags,
[email protected]21db9ef2014-05-16 02:06:27256 bool mark_acknowledged,
257 bool remote_install) {
[email protected]b2907fd2011-03-25 16:43:37258 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
259
[email protected]4ec0f4b2012-12-07 09:41:46260 PendingExtensionInfo info(id,
[email protected]d8fd0fd2014-03-24 13:16:06261 install_parameter,
[email protected]4ec0f4b2012-12-07 09:41:46262 update_url,
263 version,
264 should_allow_install,
265 is_from_sync,
[email protected]464213a2013-10-15 01:06:48266 install_source,
mamir0128d5a2016-07-15 20:55:48267 creation_flags,
[email protected]21db9ef2014-05-16 02:06:27268 mark_acknowledged,
269 remote_install);
[email protected]4ec0f4b2012-12-07 09:41:46270
[email protected]51a3bf8b2012-06-08 22:53:06271 if (const PendingExtensionInfo* pending = GetById(id)) {
[email protected]145a317b2011-04-12 16:03:46272 // Bugs in this code will manifest as sporadic incorrect extension
273 // locations in situations where multiple install sources run at the
274 // same time. For example, on first login to a chrome os machine, an
[email protected]9060d8b02012-01-13 02:14:30275 // extension may be requested by sync and the default extension set.
[email protected]145a317b2011-04-12 16:03:46276 // The following logging will help diagnose such issues.
[email protected]b2907fd2011-03-25 16:43:37277 VLOG(1) << "Extension id " << id
278 << " was entered for update more than once."
[email protected]51a3bf8b2012-06-08 22:53:06279 << " old location: " << pending->install_source()
[email protected]4ec0f4b2012-12-07 09:41:46280 << " new location: " << install_source
281 << " old version: " << GetVersionString(pending->version())
282 << " new version: " << GetVersionString(version);
[email protected]145a317b2011-04-12 16:03:46283
[email protected]e3987852012-05-04 10:06:30284 // Never override an existing extension with an older version. Only
285 // extensions from local CRX files have a known version; extensions from an
286 // update URL will get the latest version.
[email protected]e3987852012-05-04 10:06:30287
[email protected]4ec0f4b2012-12-07 09:41:46288 // If |pending| has the same or higher precedence than |info| then don't
289 // install |info| over |pending|.
290 if (pending->CompareTo(info) >= 0)
[email protected]e3987852012-05-04 10:06:30291 return false;
[email protected]e3987852012-05-04 10:06:30292
293 VLOG(1) << "Overwrite existing record.";
[email protected]51a3bf8b2012-06-08 22:53:06294
295 std::replace(pending_extension_list_.begin(),
296 pending_extension_list_.end(),
297 *pending,
[email protected]4ec0f4b2012-12-07 09:41:46298 info);
[email protected]51a3bf8b2012-06-08 22:53:06299 } else {
[email protected]4ec0f4b2012-12-07 09:41:46300 pending_extension_list_.push_back(info);
[email protected]b2907fd2011-03-25 16:43:37301 }
302
[email protected]e3987852012-05-04 10:06:30303 return true;
[email protected]b2907fd2011-03-25 16:43:37304}
305
306void PendingExtensionManager::AddForTesting(
[email protected]b2907fd2011-03-25 16:43:37307 const PendingExtensionInfo& pending_extension_info) {
[email protected]51a3bf8b2012-06-08 22:53:06308 pending_extension_list_.push_back(pending_extension_info);
[email protected]b2907fd2011-03-25 16:43:37309}
[email protected]3f213ad2012-07-26 23:39:41310
311} // namespace extensions