Introduce an extension parameter which is used to customize the extension. It's avail...
[chromium-blink-merge.git] / chrome / browser / extensions / pending_extension_manager.cc
blob425143b2626153948b883a9207eee41d26ac8be8
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/pending_extension_manager.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "base/version.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "extensions/common/extension.h"
14 #include "url/gurl.h"
16 using content::BrowserThread;
18 namespace {
20 // Install predicate used by AddFromExternalUpdateUrl().
21 bool AlwaysInstall(const extensions::Extension* extension) {
22 return true;
25 std::string GetVersionString(const Version& version) {
26 return version.IsValid() ? version.GetString() : "invalid";
29 } // namespace
31 namespace extensions {
33 PendingExtensionManager::PendingExtensionManager(
34 const ExtensionServiceInterface& service)
35 : service_(service) {
38 PendingExtensionManager::~PendingExtensionManager() {}
40 const PendingExtensionInfo* PendingExtensionManager::GetById(
41 const std::string& id) const {
42 PendingExtensionList::const_iterator iter;
43 for (iter = pending_extension_list_.begin();
44 iter != pending_extension_list_.end();
45 ++iter) {
46 if (id == iter->id())
47 return &(*iter);
50 return NULL;
53 bool PendingExtensionManager::Remove(const std::string& id) {
54 PendingExtensionList::iterator iter;
55 for (iter = pending_extension_list_.begin();
56 iter != pending_extension_list_.end();
57 ++iter) {
58 if (id == iter->id()) {
59 pending_extension_list_.erase(iter);
60 return true;
64 return false;
67 bool PendingExtensionManager::IsIdPending(const std::string& id) const {
68 return GetById(id) != NULL;
71 bool PendingExtensionManager::HasPendingExtensions() const {
72 return !pending_extension_list_.empty();
75 bool PendingExtensionManager::HasPendingExtensionFromSync() const {
76 PendingExtensionList::const_iterator iter;
77 for (iter = pending_extension_list_.begin();
78 iter != pending_extension_list_.end();
79 ++iter) {
80 if (iter->is_from_sync())
81 return true;
84 return false;
87 bool PendingExtensionManager::AddFromSync(
88 const std::string& id,
89 const GURL& update_url,
90 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
91 bool install_silently) {
92 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94 if (service_.GetInstalledExtension(id)) {
95 LOG(ERROR) << "Trying to add pending extension " << id
96 << " which already exists";
97 return false;
100 // Make sure we don't ever try to install the CWS app, because even though
101 // it is listed as a syncable app (because its values need to be synced) it
102 // should already be installed on every instance.
103 if (id == extension_misc::kWebStoreAppId) {
104 NOTREACHED();
105 return false;
108 const bool kIsFromSync = true;
109 const Manifest::Location kSyncLocation = Manifest::INTERNAL;
110 const bool kMarkAcknowledged = false;
112 return AddExtensionImpl(id,
113 std::string(),
114 update_url,
115 Version(),
116 should_allow_install,
117 kIsFromSync,
118 install_silently,
119 kSyncLocation,
120 Extension::NO_FLAGS,
121 kMarkAcknowledged);
124 bool PendingExtensionManager::AddFromExtensionImport(
125 const std::string& id,
126 const GURL& update_url,
127 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install) {
128 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
130 if (service_.GetInstalledExtension(id)) {
131 LOG(ERROR) << "Trying to add pending extension " << id
132 << " which already exists";
133 return false;
136 const bool kIsFromSync = false;
137 const bool kInstallSilently = true;
138 const Manifest::Location kManifestLocation = Manifest::INTERNAL;
139 const bool kMarkAcknowledged = false;
141 return AddExtensionImpl(id,
142 std::string(),
143 update_url,
144 Version(),
145 should_allow_install,
146 kIsFromSync,
147 kInstallSilently,
148 kManifestLocation,
149 Extension::NO_FLAGS,
150 kMarkAcknowledged);
153 bool PendingExtensionManager::AddFromExternalUpdateUrl(
154 const std::string& id,
155 const std::string& install_parameter,
156 const GURL& update_url,
157 Manifest::Location location,
158 int creation_flags,
159 bool mark_acknowledged) {
160 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
162 const bool kIsFromSync = false;
163 const bool kInstallSilently = true;
165 const Extension* extension = service_.GetInstalledExtension(id);
166 if (extension && location == Manifest::GetHigherPriorityLocation(
167 location, extension->location())) {
168 // If the new location has higher priority than the location of an existing
169 // extension, let the update process overwrite the existing extension.
170 } else {
171 if (service_.IsExternalExtensionUninstalled(id))
172 return false;
174 if (extension) {
175 LOG(DFATAL) << "Trying to add extension " << id
176 << " by external update, but it is already installed.";
177 return false;
181 return AddExtensionImpl(id,
182 install_parameter,
183 update_url,
184 Version(),
185 &AlwaysInstall,
186 kIsFromSync,
187 kInstallSilently,
188 location,
189 creation_flags,
190 mark_acknowledged);
194 bool PendingExtensionManager::AddFromExternalFile(
195 const std::string& id,
196 Manifest::Location install_source,
197 const Version& version,
198 int creation_flags,
199 bool mark_acknowledged) {
200 // TODO(skerner): AddFromSync() checks to see if the extension is
201 // installed, but this method assumes that the caller already
202 // made sure it is not installed. Make all AddFrom*() methods
203 // consistent.
204 GURL kUpdateUrl = GURL();
205 bool kIsFromSync = false;
206 bool kInstallSilently = true;
208 return AddExtensionImpl(id,
209 std::string(),
210 kUpdateUrl,
211 version,
212 &AlwaysInstall,
213 kIsFromSync,
214 kInstallSilently,
215 install_source,
216 creation_flags,
217 mark_acknowledged);
220 void PendingExtensionManager::GetPendingIdsForUpdateCheck(
221 std::list<std::string>* out_ids_for_update_check) const {
222 PendingExtensionList::const_iterator iter;
223 for (iter = pending_extension_list_.begin();
224 iter != pending_extension_list_.end();
225 ++iter) {
226 Manifest::Location install_source = iter->install_source();
228 // Some install sources read a CRX from the filesystem. They can
229 // not be fetched from an update URL, so don't include them in the
230 // set of ids.
231 if (install_source == Manifest::EXTERNAL_PREF ||
232 install_source == Manifest::EXTERNAL_REGISTRY)
233 continue;
235 out_ids_for_update_check->push_back(iter->id());
239 bool PendingExtensionManager::AddExtensionImpl(
240 const std::string& id,
241 const std::string& install_parameter,
242 const GURL& update_url,
243 const Version& version,
244 PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
245 bool is_from_sync,
246 bool install_silently,
247 Manifest::Location install_source,
248 int creation_flags,
249 bool mark_acknowledged) {
250 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
252 PendingExtensionInfo info(id,
253 install_parameter,
254 update_url,
255 version,
256 should_allow_install,
257 is_from_sync,
258 install_silently,
259 install_source,
260 creation_flags,
261 mark_acknowledged);
263 if (const PendingExtensionInfo* pending = GetById(id)) {
264 // Bugs in this code will manifest as sporadic incorrect extension
265 // locations in situations where multiple install sources run at the
266 // same time. For example, on first login to a chrome os machine, an
267 // extension may be requested by sync and the default extension set.
268 // The following logging will help diagnose such issues.
269 VLOG(1) << "Extension id " << id
270 << " was entered for update more than once."
271 << " old location: " << pending->install_source()
272 << " new location: " << install_source
273 << " old version: " << GetVersionString(pending->version())
274 << " new version: " << GetVersionString(version);
276 // Never override an existing extension with an older version. Only
277 // extensions from local CRX files have a known version; extensions from an
278 // update URL will get the latest version.
280 // If |pending| has the same or higher precedence than |info| then don't
281 // install |info| over |pending|.
282 if (pending->CompareTo(info) >= 0)
283 return false;
285 VLOG(1) << "Overwrite existing record.";
287 std::replace(pending_extension_list_.begin(),
288 pending_extension_list_.end(),
289 *pending,
290 info);
291 } else {
292 pending_extension_list_.push_back(info);
295 return true;
298 void PendingExtensionManager::AddForTesting(
299 const PendingExtensionInfo& pending_extension_info) {
300 pending_extension_list_.push_back(pending_extension_info);
303 } // namespace extensions