| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/updater/extension_downloader.h" | 5 #include "chrome/browser/extensions/updater/extension_downloader.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "base/version.h" | 21 #include "base/version.h" |
| 22 #include "chrome/browser/chrome_notification_types.h" | 22 #include "chrome/browser/chrome_notification_types.h" |
| 23 #include "chrome/browser/extensions/updater/extension_cache.h" | 23 #include "chrome/browser/extensions/updater/extension_cache.h" |
| 24 #include "chrome/browser/extensions/updater/request_queue_impl.h" | 24 #include "chrome/browser/extensions/updater/request_queue_impl.h" |
| 25 #include "chrome/browser/extensions/updater/safe_manifest_parser.h" | 25 #include "chrome/browser/extensions/updater/safe_manifest_parser.h" |
| 26 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" | 26 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" |
| 27 #include "chrome/common/chrome_switches.h" | 27 #include "chrome/common/chrome_switches.h" |
| 28 #include "chrome/common/chrome_version_info.h" | 28 #include "chrome/common/chrome_version_info.h" |
| 29 #include "chrome/common/extensions/extension_constants.h" | 29 #include "chrome/common/extensions/extension_constants.h" |
| 30 #include "chrome/common/extensions/manifest_url_handler.h" | 30 #include "chrome/common/extensions/manifest_url_handler.h" |
| 31 #include "components/omaha_query_params/omaha_query_params.h" | |
| 32 #include "content/public/browser/browser_thread.h" | 31 #include "content/public/browser/browser_thread.h" |
| 33 #include "content/public/browser/notification_details.h" | 32 #include "content/public/browser/notification_details.h" |
| 34 #include "content/public/browser/notification_service.h" | 33 #include "content/public/browser/notification_service.h" |
| 35 #include "google_apis/gaia/identity_provider.h" | 34 #include "google_apis/gaia/identity_provider.h" |
| 36 #include "net/base/backoff_entry.h" | 35 #include "net/base/backoff_entry.h" |
| 37 #include "net/base/load_flags.h" | 36 #include "net/base/load_flags.h" |
| 38 #include "net/base/net_errors.h" | 37 #include "net/base/net_errors.h" |
| 39 #include "net/http/http_request_headers.h" | 38 #include "net/http/http_request_headers.h" |
| 40 #include "net/http/http_status_code.h" | 39 #include "net/http/http_status_code.h" |
| 41 #include "net/url_request/url_fetcher.h" | 40 #include "net/url_request/url_fetcher.h" |
| 42 #include "net/url_request/url_request_context_getter.h" | 41 #include "net/url_request/url_request_context_getter.h" |
| 43 #include "net/url_request/url_request_status.h" | 42 #include "net/url_request/url_request_status.h" |
| 44 | 43 |
| 45 using base::Time; | 44 using base::Time; |
| 46 using base::TimeDelta; | 45 using base::TimeDelta; |
| 47 using content::BrowserThread; | 46 using content::BrowserThread; |
| 48 using omaha_query_params::OmahaQueryParams; | |
| 49 | 47 |
| 50 namespace extensions { | 48 namespace extensions { |
| 51 | 49 |
| 52 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist"; | 50 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist"; |
| 53 | 51 |
| 54 namespace { | 52 namespace { |
| 55 | 53 |
| 56 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { | 54 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { |
| 57 // Number of initial errors (in sequence) to ignore before applying | 55 // Number of initial errors (in sequence) to ignore before applying |
| 58 // exponential back-off rules. | 56 // exponential back-off rules. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 79 false, | 77 false, |
| 80 }; | 78 }; |
| 81 | 79 |
| 82 const char kAuthUserQueryKey[] = "authuser"; | 80 const char kAuthUserQueryKey[] = "authuser"; |
| 83 | 81 |
| 84 const int kMaxAuthUserValue = 10; | 82 const int kMaxAuthUserValue = 10; |
| 85 const int kMaxOAuth2Attempts = 3; | 83 const int kMaxOAuth2Attempts = 3; |
| 86 | 84 |
| 87 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; | 85 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; |
| 88 const char kDefaultInstallSource[] = ""; | 86 const char kDefaultInstallSource[] = ""; |
| 89 const char kWrongMultiCrxInstallSource[] = "wrong_multi_crx"; | |
| 90 | 87 |
| 91 const char kGoogleDotCom[] = "google.com"; | 88 const char kGoogleDotCom[] = "google.com"; |
| 92 const char kTokenServiceConsumerId[] = "extension_downloader"; | 89 const char kTokenServiceConsumerId[] = "extension_downloader"; |
| 93 const char kWebstoreOAuth2Scope[] = | 90 const char kWebstoreOAuth2Scope[] = |
| 94 "https://www.googleapis.com/auth/chromewebstore.readonly"; | 91 "https://www.googleapis.com/auth/chromewebstore.readonly"; |
| 95 | 92 |
| 96 #define RETRY_HISTOGRAM(name, retry_count, url) \ | 93 #define RETRY_HISTOGRAM(name, retry_count, url) \ |
| 97 if ((url).DomainIs(kGoogleDotCom)) { \ | 94 if ((url).DomainIs(kGoogleDotCom)) { \ |
| 98 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions." name "RetryCountGoogleUrl", \ | 95 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions." name "RetryCountGoogleUrl", \ |
| 99 retry_count, \ | 96 retry_count, \ |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 return false; | 203 return false; |
| 207 } | 204 } |
| 208 | 205 |
| 209 // If the extension updates itself from the gallery, ignore any update URL | 206 // If the extension updates itself from the gallery, ignore any update URL |
| 210 // data. At the moment there is no extra data that an extension can | 207 // data. At the moment there is no extra data that an extension can |
| 211 // communicate to the the gallery update servers. | 208 // communicate to the the gallery update servers. |
| 212 std::string update_url_data; | 209 std::string update_url_data; |
| 213 if (!ManifestURL::UpdatesFromGallery(&extension)) | 210 if (!ManifestURL::UpdatesFromGallery(&extension)) |
| 214 update_url_data = delegate_->GetUpdateUrlData(extension.id()); | 211 update_url_data = delegate_->GetUpdateUrlData(extension.id()); |
| 215 | 212 |
| 216 // If the browser's native architecture has changed since this extension was | 213 return AddExtensionData(extension.id(), *extension.version(), |
| 217 // installed, we need to force an update. | |
| 218 bool force_update = false; | |
| 219 std::string install_source; | |
| 220 if (extension.HasPlatformSpecificResources() && | |
| 221 !extension.HasResourcesForPlatform(OmahaQueryParams::GetNaclArch())) { | |
| 222 force_update = true; | |
| 223 install_source = kWrongMultiCrxInstallSource; | |
| 224 } | |
| 225 | |
| 226 return AddExtensionData(extension.id(), | |
| 227 *extension.version(), | |
| 228 extension.GetType(), | 214 extension.GetType(), |
| 229 ManifestURL::GetUpdateURL(&extension), | 215 ManifestURL::GetUpdateURL(&extension), |
| 230 update_url_data, | 216 update_url_data, request_id); |
| 231 request_id, | |
| 232 force_update, | |
| 233 install_source); | |
| 234 } | 217 } |
| 235 | 218 |
| 236 bool ExtensionDownloader::AddPendingExtension(const std::string& id, | 219 bool ExtensionDownloader::AddPendingExtension(const std::string& id, |
| 237 const GURL& update_url, | 220 const GURL& update_url, |
| 238 int request_id) { | 221 int request_id) { |
| 239 // Use a zero version to ensure that a pending extension will always | 222 // Use a zero version to ensure that a pending extension will always |
| 240 // be updated, and thus installed (assuming all extensions have | 223 // be updated, and thus installed (assuming all extensions have |
| 241 // non-zero versions). | 224 // non-zero versions). |
| 242 Version version("0.0.0.0"); | 225 Version version("0.0.0.0"); |
| 243 DCHECK(version.IsValid()); | 226 DCHECK(version.IsValid()); |
| 244 | 227 |
| 245 return AddExtensionData(id, | 228 return AddExtensionData(id, |
| 246 version, | 229 version, |
| 247 Manifest::TYPE_UNKNOWN, | 230 Manifest::TYPE_UNKNOWN, |
| 248 update_url, | 231 update_url, |
| 249 std::string(), | 232 std::string(), |
| 250 request_id, | 233 request_id); |
| 251 false, | |
| 252 std::string()); | |
| 253 } | 234 } |
| 254 | 235 |
| 255 void ExtensionDownloader::StartAllPending(ExtensionCache* cache) { | 236 void ExtensionDownloader::StartAllPending(ExtensionCache* cache) { |
| 256 if (cache) { | 237 if (cache) { |
| 257 extension_cache_ = cache; | 238 extension_cache_ = cache; |
| 258 extension_cache_->Start(base::Bind( | 239 extension_cache_->Start(base::Bind( |
| 259 &ExtensionDownloader::DoStartAllPending, | 240 &ExtensionDownloader::DoStartAllPending, |
| 260 weak_ptr_factory_.GetWeakPtr())); | 241 weak_ptr_factory_.GetWeakPtr())); |
| 261 } else { | 242 } else { |
| 262 DoStartAllPending(); | 243 DoStartAllPending(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 285 // url here to avoid DNS hijacking of the blacklist, which is not validated | 266 // url here to avoid DNS hijacking of the blacklist, which is not validated |
| 286 // by a public key signature like .crx files are. | 267 // by a public key signature like .crx files are. |
| 287 scoped_ptr<ManifestFetchData> blacklist_fetch( | 268 scoped_ptr<ManifestFetchData> blacklist_fetch( |
| 288 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl(), | 269 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl(), |
| 289 request_id)); | 270 request_id)); |
| 290 DCHECK(blacklist_fetch->base_url().SchemeIsSecure()); | 271 DCHECK(blacklist_fetch->base_url().SchemeIsSecure()); |
| 291 blacklist_fetch->AddExtension(kBlacklistAppID, | 272 blacklist_fetch->AddExtension(kBlacklistAppID, |
| 292 version, | 273 version, |
| 293 &ping_data, | 274 &ping_data, |
| 294 std::string(), | 275 std::string(), |
| 295 kDefaultInstallSource, | 276 kDefaultInstallSource); |
| 296 false); | |
| 297 StartUpdateCheck(blacklist_fetch.Pass()); | 277 StartUpdateCheck(blacklist_fetch.Pass()); |
| 298 } | 278 } |
| 299 | 279 |
| 300 void ExtensionDownloader::SetWebstoreIdentityProvider( | 280 void ExtensionDownloader::SetWebstoreIdentityProvider( |
| 301 scoped_ptr<IdentityProvider> identity_provider) { | 281 scoped_ptr<IdentityProvider> identity_provider) { |
| 302 identity_provider_.swap(identity_provider); | 282 identity_provider_.swap(identity_provider); |
| 303 } | 283 } |
| 304 | 284 |
| 305 bool ExtensionDownloader::AddExtensionData( | 285 bool ExtensionDownloader::AddExtensionData(const std::string& id, |
| 306 const std::string& id, | 286 const Version& version, |
| 307 const Version& version, | 287 Manifest::Type extension_type, |
| 308 Manifest::Type extension_type, | 288 const GURL& extension_update_url, |
| 309 const GURL& extension_update_url, | 289 const std::string& update_url_data, |
| 310 const std::string& update_url_data, | 290 int request_id) { |
| 311 int request_id, | |
| 312 bool force_update, | |
| 313 const std::string& install_source_override) { | |
| 314 GURL update_url(extension_update_url); | 291 GURL update_url(extension_update_url); |
| 315 // Skip extensions with non-empty invalid update URLs. | 292 // Skip extensions with non-empty invalid update URLs. |
| 316 if (!update_url.is_empty() && !update_url.is_valid()) { | 293 if (!update_url.is_empty() && !update_url.is_valid()) { |
| 317 LOG(WARNING) << "Extension " << id << " has invalid update url " | 294 LOG(WARNING) << "Extension " << id << " has invalid update url " |
| 318 << update_url; | 295 << update_url; |
| 319 return false; | 296 return false; |
| 320 } | 297 } |
| 321 | 298 |
| 322 // Make sure we use SSL for store-hosted extensions. | 299 // Make sure we use SSL for store-hosted extensions. |
| 323 if (extension_urls::IsWebstoreUpdateUrl(update_url) && | 300 if (extension_urls::IsWebstoreUpdateUrl(update_url) && |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 ChromeMetricsServiceAccessor::IsMetricsReportingEnabled()) { | 346 ChromeMetricsServiceAccessor::IsMetricsReportingEnabled()) { |
| 370 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); | 347 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); |
| 371 } | 348 } |
| 372 | 349 |
| 373 for (size_t i = 0; i < update_urls.size(); ++i) { | 350 for (size_t i = 0; i < update_urls.size(); ++i) { |
| 374 DCHECK(!update_urls[i].is_empty()); | 351 DCHECK(!update_urls[i].is_empty()); |
| 375 DCHECK(update_urls[i].is_valid()); | 352 DCHECK(update_urls[i].is_valid()); |
| 376 | 353 |
| 377 std::string install_source = i == 0 ? | 354 std::string install_source = i == 0 ? |
| 378 kDefaultInstallSource : kNotFromWebstoreInstallSource; | 355 kDefaultInstallSource : kNotFromWebstoreInstallSource; |
| 379 if (!install_source_override.empty()) { | |
| 380 install_source = install_source_override; | |
| 381 } | |
| 382 | 356 |
| 383 ManifestFetchData::PingData ping_data; | 357 ManifestFetchData::PingData ping_data; |
| 384 ManifestFetchData::PingData* optional_ping_data = NULL; | 358 ManifestFetchData::PingData* optional_ping_data = NULL; |
| 385 if (delegate_->GetPingDataForExtension(id, &ping_data)) | 359 if (delegate_->GetPingDataForExtension(id, &ping_data)) |
| 386 optional_ping_data = &ping_data; | 360 optional_ping_data = &ping_data; |
| 387 | 361 |
| 388 // Find or create a ManifestFetchData to add this extension to. | 362 // Find or create a ManifestFetchData to add this extension to. |
| 389 bool added = false; | 363 bool added = false; |
| 390 FetchMap::iterator existing_iter = fetches_preparing_.find( | 364 FetchMap::iterator existing_iter = fetches_preparing_.find( |
| 391 std::make_pair(request_id, update_urls[i])); | 365 std::make_pair(request_id, update_urls[i])); |
| 392 if (existing_iter != fetches_preparing_.end() && | 366 if (existing_iter != fetches_preparing_.end() && |
| 393 !existing_iter->second.empty()) { | 367 !existing_iter->second.empty()) { |
| 394 // Try to add to the ManifestFetchData at the end of the list. | 368 // Try to add to the ManifestFetchData at the end of the list. |
| 395 ManifestFetchData* existing_fetch = existing_iter->second.back().get(); | 369 ManifestFetchData* existing_fetch = existing_iter->second.back().get(); |
| 396 if (existing_fetch->AddExtension(id, version.GetString(), | 370 if (existing_fetch->AddExtension(id, version.GetString(), |
| 397 optional_ping_data, update_url_data, | 371 optional_ping_data, update_url_data, |
| 398 install_source, | 372 install_source)) { |
| 399 force_update)) { | |
| 400 added = true; | 373 added = true; |
| 401 } | 374 } |
| 402 } | 375 } |
| 403 if (!added) { | 376 if (!added) { |
| 404 // Otherwise add a new element to the list, if the list doesn't exist or | 377 // Otherwise add a new element to the list, if the list doesn't exist or |
| 405 // if its last element is already full. | 378 // if its last element is already full. |
| 406 linked_ptr<ManifestFetchData> fetch( | 379 linked_ptr<ManifestFetchData> fetch( |
| 407 new ManifestFetchData(update_urls[i], request_id)); | 380 new ManifestFetchData(update_urls[i], request_id)); |
| 408 fetches_preparing_[std::make_pair(request_id, update_urls[i])]. | 381 fetches_preparing_[std::make_pair(request_id, update_urls[i])]. |
| 409 push_back(fetch); | 382 push_back(fetch); |
| 410 added = fetch->AddExtension(id, version.GetString(), | 383 added = fetch->AddExtension(id, version.GetString(), |
| 411 optional_ping_data, | 384 optional_ping_data, |
| 412 update_url_data, | 385 update_url_data, |
| 413 install_source, | 386 install_source); |
| 414 force_update); | |
| 415 DCHECK(added); | 387 DCHECK(added); |
| 416 } | 388 } |
| 417 } | 389 } |
| 418 | 390 |
| 419 return true; | 391 return true; |
| 420 } | 392 } |
| 421 | 393 |
| 422 void ExtensionDownloader::ReportStats() const { | 394 void ExtensionDownloader::ReportStats() const { |
| 423 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension", | 395 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension", |
| 424 url_stats_.extension_count); | 396 url_stats_.extension_count); |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 // version is the same or older than what's already installed, | 632 // version is the same or older than what's already installed, |
| 661 // we don't want it. | 633 // we don't want it. |
| 662 std::string version; | 634 std::string version; |
| 663 if (!delegate_->GetExtensionExistingVersion(id, &version)) { | 635 if (!delegate_->GetExtensionExistingVersion(id, &version)) { |
| 664 VLOG(2) << id << " is not installed"; | 636 VLOG(2) << id << " is not installed"; |
| 665 continue; | 637 continue; |
| 666 } | 638 } |
| 667 | 639 |
| 668 VLOG(2) << id << " is at '" << version << "'"; | 640 VLOG(2) << id << " is at '" << version << "'"; |
| 669 | 641 |
| 670 // We should skip the version check if update was forced. | 642 Version existing_version(version); |
| 671 if (!fetch_data.DidForceUpdate(id)) { | 643 Version update_version(update->version); |
| 672 Version existing_version(version); | 644 |
| 673 Version update_version(update->version); | 645 if (!update_version.IsValid() || |
| 674 if (!update_version.IsValid() || | 646 update_version.CompareTo(existing_version) <= 0) { |
| 675 update_version.CompareTo(existing_version) <= 0) { | 647 continue; |
| 676 continue; | |
| 677 } | |
| 678 } | 648 } |
| 679 } | 649 } |
| 680 | 650 |
| 681 // If the update specifies a browser minimum version, do we qualify? | 651 // If the update specifies a browser minimum version, do we qualify? |
| 682 if (update->browser_min_version.length() > 0) { | 652 if (update->browser_min_version.length() > 0) { |
| 683 // First determine the browser version if we haven't already. | 653 // First determine the browser version if we haven't already. |
| 684 if (!browser_version.IsValid()) { | 654 if (!browser_version.IsValid()) { |
| 685 chrome::VersionInfo version_info; | 655 chrome::VersionInfo version_info; |
| 686 if (version_info.is_valid()) | 656 if (version_info.is_valid()) |
| 687 browser_version = Version(version_info.Version()); | 657 browser_version = Version(version_info.Version()); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 | 922 |
| 953 void ExtensionDownloader::OnGetTokenFailure( | 923 void ExtensionDownloader::OnGetTokenFailure( |
| 954 const OAuth2TokenService::Request* request, | 924 const OAuth2TokenService::Request* request, |
| 955 const GoogleServiceAuthError& error) { | 925 const GoogleServiceAuthError& error) { |
| 956 // If we fail to get an access token, kick the pending fetch and let it fall | 926 // If we fail to get an access token, kick the pending fetch and let it fall |
| 957 // back on cookies. | 927 // back on cookies. |
| 958 extension_fetcher_->Start(); | 928 extension_fetcher_->Start(); |
| 959 } | 929 } |
| 960 | 930 |
| 961 } // namespace extensions | 931 } // namespace extensions |
| OLD | NEW |