blob: 199cb97f118f20644cbfab893570549d2956d060 [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"
[email protected]b52f8ca2013-11-28 08:25:2215#include "extensions/common/extension.h"
[email protected]a6483d22013-07-03 22:11:0016#include "url/gurl.h"
[email protected]b2907fd2011-03-25 16:43:3717
[email protected]631bb742011-11-02 11:29:3918using content::BrowserThread;
19
[email protected]b2907fd2011-03-25 16:43:3720namespace {
21
[email protected]b2907fd2011-03-25 16:43:3722// Install predicate used by AddFromExternalUpdateUrl().
[email protected]8f3bcbd2013-06-05 08:42:4023bool AlwaysInstall(const extensions::Extension* extension) {
[email protected]b2907fd2011-03-25 16:43:3724 return true;
25}
26
[email protected]c5e4a2222014-01-03 16:06:1327std::string GetVersionString(const Version& version) {
[email protected]4ec0f4b2012-12-07 09:41:4628 return version.IsValid() ? version.GetString() : "invalid";
29}
30
[email protected]b2907fd2011-03-25 16:43:3731} // namespace
32
[email protected]3f213ad2012-07-26 23:39:4133namespace extensions {
34
[email protected]b2907fd2011-03-25 16:43:3735PendingExtensionManager::PendingExtensionManager(
[email protected]46f3e102014-03-25 01:22:4536 content::BrowserContext* context)
[email protected]6c9bedf2014-05-21 03:55:5137 : context_(context) {}
[email protected]b2907fd2011-03-25 16:43:3738
39PendingExtensionManager::~PendingExtensionManager() {}
40
[email protected]51a3bf8b2012-06-08 22:53:0641const PendingExtensionInfo* PendingExtensionManager::GetById(
42 const std::string& id) const {
43 PendingExtensionList::const_iterator iter;
44 for (iter = pending_extension_list_.begin();
45 iter != pending_extension_list_.end();
46 ++iter) {
47 if (id == iter->id())
48 return &(*iter);
49 }
[email protected]b2907fd2011-03-25 16:43:3750
[email protected]51a3bf8b2012-06-08 22:53:0651 return NULL;
52}
53
54bool PendingExtensionManager::Remove(const std::string& id) {
55 PendingExtensionList::iterator iter;
56 for (iter = pending_extension_list_.begin();
57 iter != pending_extension_list_.end();
58 ++iter) {
59 if (id == iter->id()) {
60 pending_extension_list_.erase(iter);
61 return true;
62 }
[email protected]b2907fd2011-03-25 16:43:3763 }
64
65 return false;
66}
67
[email protected]b2907fd2011-03-25 16:43:3768bool PendingExtensionManager::IsIdPending(const std::string& id) const {
[email protected]870f5572013-12-19 12:30:1569 return GetById(id) != NULL;
[email protected]b2907fd2011-03-25 16:43:3770}
71
[email protected]9bd9a6862012-11-29 09:24:2272bool PendingExtensionManager::HasPendingExtensions() const {
73 return !pending_extension_list_.empty();
74}
75
[email protected]d31e19e2012-08-22 00:19:0476bool PendingExtensionManager::HasPendingExtensionFromSync() const {
77 PendingExtensionList::const_iterator iter;
78 for (iter = pending_extension_list_.begin();
79 iter != pending_extension_list_.end();
80 ++iter) {
81 if (iter->is_from_sync())
82 return true;
83 }
84
85 return false;
86}
87
[email protected]145a317b2011-04-12 16:03:4688bool PendingExtensionManager::AddFromSync(
[email protected]b2907fd2011-03-25 16:43:3789 const std::string& id,
90 const GURL& update_url,
91 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
[email protected]21db9ef2014-05-16 02:06:2792 bool install_silently,
93 bool remote_install) {
[email protected]b2907fd2011-03-25 16:43:3794 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
95
[email protected]6c9bedf2014-05-21 03:55:5196 if (ExtensionRegistry::Get(context_)->GetExtensionById(
97 id, ExtensionRegistry::EVERYTHING)) {
[email protected]145a317b2011-04-12 16:03:4698 LOG(ERROR) << "Trying to add pending extension " << id
99 << " which already exists";
100 return false;
[email protected]b2907fd2011-03-25 16:43:37101 }
102
[email protected]b873cd92012-02-09 21:51:48103 // Make sure we don't ever try to install the CWS app, because even though
104 // it is listed as a syncable app (because its values need to be synced) it
105 // should already be installed on every instance.
106 if (id == extension_misc::kWebStoreAppId) {
107 NOTREACHED();
108 return false;
109 }
110
[email protected]6c9bedf2014-05-21 03:55:51111 static const bool kIsFromSync = true;
112 static const Manifest::Location kSyncLocation = Manifest::INTERNAL;
113 static const bool kMarkAcknowledged = false;
[email protected]145a317b2011-04-12 16:03:46114
[email protected]d8fd0fd2014-03-24 13:16:06115 return AddExtensionImpl(id,
116 std::string(),
117 update_url,
118 Version(),
119 should_allow_install,
120 kIsFromSync,
121 install_silently,
122 kSyncLocation,
123 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;
142 static const bool kInstallSilently = true;
143 static const Manifest::Location kManifestLocation = Manifest::INTERNAL;
144 static const bool kMarkAcknowledged = false;
145 static const bool kRemoteInstall = false;
[email protected]9f4e4f082013-06-21 07:11:19146
[email protected]d8fd0fd2014-03-24 13:16:06147 return AddExtensionImpl(id,
148 std::string(),
149 update_url,
150 Version(),
151 should_allow_install,
152 kIsFromSync,
153 kInstallSilently,
154 kManifestLocation,
155 Extension::NO_FLAGS,
[email protected]21db9ef2014-05-16 02:06:27156 kMarkAcknowledged,
157 kRemoteInstall);
[email protected]9f4e4f082013-06-21 07:11:19158}
159
[email protected]9060d8b02012-01-13 02:14:30160bool PendingExtensionManager::AddFromExternalUpdateUrl(
[email protected]612a1cb12012-10-17 13:18:03161 const std::string& id,
[email protected]d8fd0fd2014-03-24 13:16:06162 const std::string& install_parameter,
[email protected]612a1cb12012-10-17 13:18:03163 const GURL& update_url,
[email protected]464213a2013-10-15 01:06:48164 Manifest::Location location,
165 int creation_flags,
166 bool mark_acknowledged) {
[email protected]b2907fd2011-03-25 16:43:37167 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168
[email protected]6c9bedf2014-05-21 03:55:51169 static const bool kIsFromSync = false;
170 static const bool kInstallSilently = true;
171 static const bool kRemoteInstall = false;
[email protected]b2907fd2011-03-25 16:43:37172
[email protected]6c9bedf2014-05-21 03:55:51173 const Extension* extension = ExtensionRegistry::Get(context_)
174 ->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
[email protected]d8fd0fd2014-03-24 13:16:06175 if (extension && location == Manifest::GetHigherPriorityLocation(
176 location, extension->location())) {
[email protected]8a87a5332011-08-11 17:54:59177 // If the new location has higher priority than the location of an existing
178 // extension, let the update process overwrite the existing extension.
179 } else {
[email protected]46f3e102014-03-25 01:22:45180 if (ExtensionPrefs::Get(context_)->IsExternalExtensionUninstalled(id))
[email protected]9060d8b02012-01-13 02:14:30181 return false;
182
[email protected]8a87a5332011-08-11 17:54:59183 if (extension) {
184 LOG(DFATAL) << "Trying to add extension " << id
185 << " by external update, but it is already installed.";
[email protected]9060d8b02012-01-13 02:14:30186 return false;
[email protected]8a87a5332011-08-11 17:54:59187 }
[email protected]b2907fd2011-03-25 16:43:37188 }
189
[email protected]d8fd0fd2014-03-24 13:16:06190 return AddExtensionImpl(id,
191 install_parameter,
192 update_url,
193 Version(),
194 &AlwaysInstall,
195 kIsFromSync,
196 kInstallSilently,
197 location,
198 creation_flags,
[email protected]21db9ef2014-05-16 02:06:27199 mark_acknowledged,
200 kRemoteInstall);
[email protected]b2907fd2011-03-25 16:43:37201}
202
203
[email protected]9060d8b02012-01-13 02:14:30204bool PendingExtensionManager::AddFromExternalFile(
[email protected]b2907fd2011-03-25 16:43:37205 const std::string& id,
[email protected]1d5e58b2013-01-31 08:41:40206 Manifest::Location install_source,
[email protected]c5e4a2222014-01-03 16:06:13207 const Version& version,
[email protected]464213a2013-10-15 01:06:48208 int creation_flags,
209 bool mark_acknowledged) {
[email protected]9060d8b02012-01-13 02:14:30210 // TODO(skerner): AddFromSync() checks to see if the extension is
211 // installed, but this method assumes that the caller already
212 // made sure it is not installed. Make all AddFrom*() methods
213 // consistent.
[email protected]6c9bedf2014-05-21 03:55:51214 const GURL& kUpdateUrl = GURL::EmptyGURL();
215 static const bool kIsFromSync = false;
216 static const bool kInstallSilently = true;
217 static const bool kRemoteInstall = false;
[email protected]b2907fd2011-03-25 16:43:37218
[email protected]d8fd0fd2014-03-24 13:16:06219 return AddExtensionImpl(id,
220 std::string(),
221 kUpdateUrl,
222 version,
223 &AlwaysInstall,
224 kIsFromSync,
225 kInstallSilently,
226 install_source,
227 creation_flags,
[email protected]21db9ef2014-05-16 02:06:27228 mark_acknowledged,
229 kRemoteInstall);
[email protected]9060d8b02012-01-13 02:14:30230}
231
232void PendingExtensionManager::GetPendingIdsForUpdateCheck(
[email protected]51a3bf8b2012-06-08 22:53:06233 std::list<std::string>* out_ids_for_update_check) const {
234 PendingExtensionList::const_iterator iter;
235 for (iter = pending_extension_list_.begin();
236 iter != pending_extension_list_.end();
[email protected]9060d8b02012-01-13 02:14:30237 ++iter) {
[email protected]1d5e58b2013-01-31 08:41:40238 Manifest::Location install_source = iter->install_source();
[email protected]9060d8b02012-01-13 02:14:30239
240 // Some install sources read a CRX from the filesystem. They can
241 // not be fetched from an update URL, so don't include them in the
242 // set of ids.
[email protected]1d5e58b2013-01-31 08:41:40243 if (install_source == Manifest::EXTERNAL_PREF ||
244 install_source == Manifest::EXTERNAL_REGISTRY)
[email protected]9060d8b02012-01-13 02:14:30245 continue;
246
[email protected]51a3bf8b2012-06-08 22:53:06247 out_ids_for_update_check->push_back(iter->id());
[email protected]9060d8b02012-01-13 02:14:30248 }
[email protected]b2907fd2011-03-25 16:43:37249}
250
[email protected]145a317b2011-04-12 16:03:46251bool PendingExtensionManager::AddExtensionImpl(
[email protected]9060d8b02012-01-13 02:14:30252 const std::string& id,
[email protected]d8fd0fd2014-03-24 13:16:06253 const std::string& install_parameter,
[email protected]9060d8b02012-01-13 02:14:30254 const GURL& update_url,
[email protected]c5e4a2222014-01-03 16:06:13255 const Version& version,
[email protected]b2907fd2011-03-25 16:43:37256 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
[email protected]9060d8b02012-01-13 02:14:30257 bool is_from_sync,
258 bool install_silently,
[email protected]464213a2013-10-15 01:06:48259 Manifest::Location install_source,
260 int creation_flags,
[email protected]21db9ef2014-05-16 02:06:27261 bool mark_acknowledged,
262 bool remote_install) {
[email protected]b2907fd2011-03-25 16:43:37263 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264
[email protected]4ec0f4b2012-12-07 09:41:46265 PendingExtensionInfo info(id,
[email protected]d8fd0fd2014-03-24 13:16:06266 install_parameter,
[email protected]4ec0f4b2012-12-07 09:41:46267 update_url,
268 version,
269 should_allow_install,
270 is_from_sync,
271 install_silently,
[email protected]464213a2013-10-15 01:06:48272 install_source,
273 creation_flags,
[email protected]21db9ef2014-05-16 02:06:27274 mark_acknowledged,
275 remote_install);
[email protected]4ec0f4b2012-12-07 09:41:46276
[email protected]51a3bf8b2012-06-08 22:53:06277 if (const PendingExtensionInfo* pending = GetById(id)) {
[email protected]145a317b2011-04-12 16:03:46278 // Bugs in this code will manifest as sporadic incorrect extension
279 // locations in situations where multiple install sources run at the
280 // same time. For example, on first login to a chrome os machine, an
[email protected]9060d8b02012-01-13 02:14:30281 // extension may be requested by sync and the default extension set.
[email protected]145a317b2011-04-12 16:03:46282 // The following logging will help diagnose such issues.
[email protected]b2907fd2011-03-25 16:43:37283 VLOG(1) << "Extension id " << id
284 << " was entered for update more than once."
[email protected]51a3bf8b2012-06-08 22:53:06285 << " old location: " << pending->install_source()
[email protected]4ec0f4b2012-12-07 09:41:46286 << " new location: " << install_source
287 << " old version: " << GetVersionString(pending->version())
288 << " new version: " << GetVersionString(version);
[email protected]145a317b2011-04-12 16:03:46289
[email protected]e3987852012-05-04 10:06:30290 // Never override an existing extension with an older version. Only
291 // extensions from local CRX files have a known version; extensions from an
292 // update URL will get the latest version.
[email protected]e3987852012-05-04 10:06:30293
[email protected]4ec0f4b2012-12-07 09:41:46294 // If |pending| has the same or higher precedence than |info| then don't
295 // install |info| over |pending|.
296 if (pending->CompareTo(info) >= 0)
[email protected]e3987852012-05-04 10:06:30297 return false;
[email protected]e3987852012-05-04 10:06:30298
299 VLOG(1) << "Overwrite existing record.";
[email protected]51a3bf8b2012-06-08 22:53:06300
301 std::replace(pending_extension_list_.begin(),
302 pending_extension_list_.end(),
303 *pending,
[email protected]4ec0f4b2012-12-07 09:41:46304 info);
[email protected]51a3bf8b2012-06-08 22:53:06305 } else {
[email protected]4ec0f4b2012-12-07 09:41:46306 pending_extension_list_.push_back(info);
[email protected]b2907fd2011-03-25 16:43:37307 }
308
[email protected]e3987852012-05-04 10:06:30309 return true;
[email protected]b2907fd2011-03-25 16:43:37310}
311
312void PendingExtensionManager::AddForTesting(
[email protected]b2907fd2011-03-25 16:43:37313 const PendingExtensionInfo& pending_extension_info) {
[email protected]51a3bf8b2012-06-08 22:53:06314 pending_extension_list_.push_back(pending_extension_info);
[email protected]b2907fd2011-03-25 16:43:37315}
[email protected]3f213ad2012-07-26 23:39:41316
317} // namespace extensions