[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 5 | #include "chrome/browser/extensions/pending_extension_manager.h" |
| 6 | |
[email protected] | d31e19e | 2012-08-22 00:19:04 | [diff] [blame] | 7 | #include <algorithm> |
| 8 | |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 9 | #include "base/logging.h" |
[email protected] | 7286e3fc | 2011-07-19 22:13:24 | [diff] [blame] | 10 | #include "base/stl_util.h" |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 11 | #include "base/version.h" |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 12 | #include "chrome/browser/extensions/extension_service.h" |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 13 | #include "chrome/browser/extensions/pending_extension_info.h" |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 14 | #include "chrome/common/extensions/extension.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 15 | #include "content/public/browser/browser_thread.h" |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 16 | |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 17 | using content::BrowserThread; |
| 18 | |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 19 | namespace { |
| 20 | |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 21 | // Install predicate used by AddFromExternalUpdateUrl(). |
[email protected] | 3f213ad | 2012-07-26 23:39:41 | [diff] [blame] | 22 | bool AlwaysInstall(const extensions::Extension& extension) { |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 23 | return true; |
| 24 | } |
| 25 | |
| 26 | } // namespace |
| 27 | |
[email protected] | 3f213ad | 2012-07-26 23:39:41 | [diff] [blame] | 28 | namespace extensions { |
| 29 | |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 30 | PendingExtensionManager::PendingExtensionManager( |
[email protected] | 2859946f | 2011-04-04 18:18:06 | [diff] [blame] | 31 | const ExtensionServiceInterface& service) |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 32 | : service_(service) { |
| 33 | } |
| 34 | |
| 35 | PendingExtensionManager::~PendingExtensionManager() {} |
| 36 | |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 37 | const 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] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 46 | |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 47 | return NULL; |
| 48 | } |
| 49 | |
| 50 | bool 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] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | return false; |
| 62 | } |
| 63 | |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 64 | bool PendingExtensionManager::IsIdPending(const std::string& id) const { |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 65 | 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] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 74 | } |
| 75 | |
[email protected] | 9bd9a686 | 2012-11-29 09:24:22 | [diff] [blame^] | 76 | bool PendingExtensionManager::HasPendingExtensions() const { |
| 77 | return !pending_extension_list_.empty(); |
| 78 | } |
| 79 | |
[email protected] | d31e19e | 2012-08-22 00:19:04 | [diff] [blame] | 80 | bool 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] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 92 | bool PendingExtensionManager::AddFromSync( |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 93 | const std::string& id, |
| 94 | const GURL& update_url, |
| 95 | PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install, |
[email protected] | 6cc7dbae | 2011-04-29 21:18:33 | [diff] [blame] | 96 | bool install_silently) { |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 97 | CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 98 | |
[email protected] | 8001df2 | 2011-04-28 19:59:47 | [diff] [blame] | 99 | if (service_.GetInstalledExtension(id)) { |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 100 | LOG(ERROR) << "Trying to add pending extension " << id |
| 101 | << " which already exists"; |
| 102 | return false; |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 103 | } |
| 104 | |
[email protected] | b873cd9 | 2012-02-09 21:51:48 | [diff] [blame] | 105 | // 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] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 113 | const bool kIsFromSync = true; |
| 114 | const Extension::Location kSyncLocation = Extension::INTERNAL; |
| 115 | |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 116 | return AddExtensionImpl(id, update_url, Version(), should_allow_install, |
[email protected] | 6cc7dbae | 2011-04-29 21:18:33 | [diff] [blame] | 117 | kIsFromSync, install_silently, kSyncLocation); |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 118 | } |
| 119 | |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 120 | bool PendingExtensionManager::AddFromExternalUpdateUrl( |
[email protected] | 612a1cb1 | 2012-10-17 13:18:03 | [diff] [blame] | 121 | const std::string& id, |
| 122 | const GURL& update_url, |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 123 | Extension::Location location) { |
| 124 | CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 125 | |
| 126 | const bool kIsFromSync = false; |
| 127 | const bool kInstallSilently = true; |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 128 | |
[email protected] | 8a87a533 | 2011-08-11 17:54:59 | [diff] [blame] | 129 | 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] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 136 | if (service_.IsExternalExtensionUninstalled(id)) |
| 137 | return false; |
| 138 | |
[email protected] | 8a87a533 | 2011-08-11 17:54:59 | [diff] [blame] | 139 | if (extension) { |
| 140 | LOG(DFATAL) << "Trying to add extension " << id |
| 141 | << " by external update, but it is already installed."; |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 142 | return false; |
[email protected] | 8a87a533 | 2011-08-11 17:54:59 | [diff] [blame] | 143 | } |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 144 | } |
| 145 | |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 146 | return AddExtensionImpl(id, update_url, Version(), &AlwaysInstall, |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 147 | kIsFromSync, kInstallSilently, |
| 148 | location); |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 152 | bool PendingExtensionManager::AddFromExternalFile( |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 153 | const std::string& id, |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 154 | Extension::Location install_source, |
| 155 | const Version& version) { |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 156 | // 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] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 160 | GURL kUpdateUrl = GURL(); |
| 161 | bool kIsFromSync = false; |
| 162 | bool kInstallSilently = true; |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 163 | |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 164 | return AddExtensionImpl( |
| 165 | id, |
| 166 | kUpdateUrl, |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 167 | version, |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 168 | &AlwaysInstall, |
| 169 | kIsFromSync, |
| 170 | kInstallSilently, |
| 171 | install_source); |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 172 | } |
| 173 | |
| 174 | void PendingExtensionManager::GetPendingIdsForUpdateCheck( |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 175 | 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] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 179 | ++iter) { |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 180 | Extension::Location install_source = iter->install_source(); |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 181 | |
| 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] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 189 | out_ids_for_update_check->push_back(iter->id()); |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 190 | } |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 191 | } |
| 192 | |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 193 | bool PendingExtensionManager::AddExtensionImpl( |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 194 | const std::string& id, |
| 195 | const GURL& update_url, |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 196 | const Version& version, |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 197 | PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install, |
[email protected] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 198 | bool is_from_sync, |
| 199 | bool install_silently, |
[email protected] | 6cc7dbae | 2011-04-29 21:18:33 | [diff] [blame] | 200 | Extension::Location install_source) { |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 201 | CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 202 | |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 203 | if (const PendingExtensionInfo* pending = GetById(id)) { |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 204 | // 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] | 9060d8b0 | 2012-01-13 02:14:30 | [diff] [blame] | 207 | // extension may be requested by sync and the default extension set. |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 208 | // The following logging will help diagnose such issues. |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 209 | VLOG(1) << "Extension id " << id |
| 210 | << " was entered for update more than once." |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 211 | << " old location: " << pending->install_source() |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 212 | << " new location: " << install_source; |
| 213 | |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 214 | // 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] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 218 | pending->version().IsValid() && |
| 219 | pending->version().CompareTo(version) == 1) { |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 220 | VLOG(1) << "Keep existing record (has a newer version)."; |
| 221 | return false; |
| 222 | } |
| 223 | |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 224 | Extension::Location higher_priority_location = |
| 225 | Extension::GetHigherPriorityLocation( |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 226 | install_source, pending->install_source()); |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 227 | |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 228 | if (higher_priority_location != install_source) { |
| 229 | VLOG(1) << "Keep existing record (has a higher priority location)."; |
| 230 | return false; |
[email protected] | 145a317b | 2011-04-12 16:03:46 | [diff] [blame] | 231 | } |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 232 | |
| 233 | VLOG(1) << "Overwrite existing record."; |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 234 | |
| 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] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 254 | } |
| 255 | |
[email protected] | e398785 | 2012-05-04 10:06:30 | [diff] [blame] | 256 | return true; |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | void PendingExtensionManager::AddForTesting( |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 260 | const PendingExtensionInfo& pending_extension_info) { |
[email protected] | 51a3bf8b | 2012-06-08 22:53:06 | [diff] [blame] | 261 | pending_extension_list_.push_back(pending_extension_info); |
[email protected] | b2907fd | 2011-03-25 16:43:37 | [diff] [blame] | 262 | } |
[email protected] | 3f213ad | 2012-07-26 23:39:41 | [diff] [blame] | 263 | |
| 264 | } // namespace extensions |