Chromium Code Reviews| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 -1, | 71 -1, |
| 72 | 72 |
| 73 // Don't use initial delay unless the last request was an error. | 73 // Don't use initial delay unless the last request was an error. |
| 74 false, | 74 false, |
| 75 }; | 75 }; |
| 76 | 76 |
| 77 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; | 77 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; |
| 78 const char kDefaultInstallSource[] = ""; | 78 const char kDefaultInstallSource[] = ""; |
| 79 | 79 |
| 80 #define RETRY_HISTOGRAM(name, retry_count, url) \ | 80 #define RETRY_HISTOGRAM(name, retry_count, url) \ |
| 81 if ((url).DomainIs("google.com")) \ | 81 if ((url).DomainIs("google.com")) { \ |
| 82 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 82 UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 83 "Extensions." name "RetryCountGoogleUrl", retry_count, 1, \ | 83 "Extensions." name "RetryCountGoogleUrl", retry_count, 1, \ |
| 84 kMaxRetries, kMaxRetries+1); \ | 84 kMaxRetries, kMaxRetries+1); \ |
| 85 else \ | 85 } else { \ |
| 86 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | 86 UMA_HISTOGRAM_CUSTOM_COUNTS( \ |
| 87 "Extensions." name "RetryCountOtherUrl", retry_count, 1, \ | 87 "Extensions." name "RetryCountOtherUrl", retry_count, 1, \ |
| 88 kMaxRetries, kMaxRetries+1) | 88 kMaxRetries, kMaxRetries+1); \ |
| 89 } | |
| 89 | 90 |
| 90 bool ShouldRetryRequest(const net::URLRequestStatus& status, | 91 bool ShouldRetryRequest(const net::URLRequestStatus& status, |
| 91 int response_code) { | 92 int response_code) { |
| 92 // Retry if the response code is a server error, or the request failed because | 93 // Retry if the response code is a server error, or the request failed because |
| 93 // of network errors as opposed to file errors. | 94 // of network errors as opposed to file errors. |
| 94 return (response_code >= 500 && status.is_success()) || | 95 return (response_code >= 500 && status.is_success()) || |
| 95 status.status() == net::URLRequestStatus::FAILED; | 96 status.status() == net::URLRequestStatus::FAILED; |
| 96 } | 97 } |
| 97 | 98 |
| 98 } // namespace | 99 } // namespace |
| 99 | 100 |
| 100 UpdateDetails::UpdateDetails(const std::string& id, const Version& version) | 101 UpdateDetails::UpdateDetails(const std::string& id, const Version& version) |
| 101 : id(id), version(version) {} | 102 : id(id), version(version) {} |
| 102 | 103 |
| 103 UpdateDetails::~UpdateDetails() {} | 104 UpdateDetails::~UpdateDetails() {} |
| 104 | 105 |
| 105 ExtensionDownloader::ExtensionFetch::ExtensionFetch() : url() {} | 106 ExtensionDownloader::ExtensionFetch::ExtensionFetch() : url() {} |
|
asargent_no_longer_on_chrome
2014/01/31 18:22:26
nit: make sure to initialize is_protected in this
Ken Rockot(use gerrit already)
2014/01/31 22:12:58
Done.
| |
| 106 | 107 |
| 107 ExtensionDownloader::ExtensionFetch::ExtensionFetch( | 108 ExtensionDownloader::ExtensionFetch::ExtensionFetch( |
| 108 const std::string& id, | 109 const std::string& id, |
| 109 const GURL& url, | 110 const GURL& url, |
| 110 const std::string& package_hash, | 111 const std::string& package_hash, |
| 111 const std::string& version, | 112 const std::string& version, |
| 112 const std::set<int>& request_ids) | 113 const std::set<int>& request_ids) |
| 113 : id(id), url(url), package_hash(package_hash), version(version), | 114 : id(id), url(url), package_hash(package_hash), version(version), |
| 114 request_ids(request_ids) {} | 115 request_ids(request_ids), is_protected(false) {} |
| 115 | 116 |
| 116 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} | 117 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} |
| 117 | 118 |
| 118 ExtensionDownloader::ExtensionDownloader( | 119 ExtensionDownloader::ExtensionDownloader( |
| 119 ExtensionDownloaderDelegate* delegate, | 120 ExtensionDownloaderDelegate* delegate, |
| 120 net::URLRequestContextGetter* request_context) | 121 net::URLRequestContextGetter* request_context) |
| 121 : delegate_(delegate), | 122 : delegate_(delegate), |
| 122 request_context_(request_context), | 123 request_context_(request_context), |
| 123 weak_ptr_factory_(this), | 124 weak_ptr_factory_(this), |
| 124 manifests_queue_(&kDefaultBackoffPolicy, | 125 manifests_queue_(&kDefaultBackoffPolicy, |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 650 scoped_ptr<ExtensionFetch> fetch_data, | 651 scoped_ptr<ExtensionFetch> fetch_data, |
| 651 const base::FilePath& crx_path, | 652 const base::FilePath& crx_path, |
| 652 bool file_ownership_passed) { | 653 bool file_ownership_passed) { |
| 653 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path, | 654 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path, |
| 654 file_ownership_passed, fetch_data->url, fetch_data->version, | 655 file_ownership_passed, fetch_data->url, fetch_data->version, |
| 655 ping_results_[fetch_data->id], fetch_data->request_ids); | 656 ping_results_[fetch_data->id], fetch_data->request_ids); |
| 656 ping_results_.erase(fetch_data->id); | 657 ping_results_.erase(fetch_data->id); |
| 657 } | 658 } |
| 658 | 659 |
| 659 void ExtensionDownloader::CreateExtensionFetcher() { | 660 void ExtensionDownloader::CreateExtensionFetcher() { |
| 661 const ExtensionFetch* fetch = extensions_queue_.active_request(); | |
| 662 int load_flags = net::LOAD_DISABLE_CACHE; | |
| 663 if (!fetch->is_protected) { | |
| 664 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES | | |
| 665 net::LOAD_DO_NOT_SAVE_COOKIES; | |
| 666 } | |
|
asargent_no_longer_on_chrome
2014/01/31 18:22:26
Perhaps we should also only send cookies on https
Ken Rockot(use gerrit already)
2014/01/31 22:12:58
Good catch. Done.
| |
| 660 extension_fetcher_.reset(net::URLFetcher::Create( | 667 extension_fetcher_.reset(net::URLFetcher::Create( |
| 661 kExtensionFetcherId, extensions_queue_.active_request()->url, | 668 kExtensionFetcherId, fetch->url, net::URLFetcher::GET, this)); |
| 662 net::URLFetcher::GET, this)); | |
| 663 extension_fetcher_->SetRequestContext(request_context_); | 669 extension_fetcher_->SetRequestContext(request_context_); |
| 664 extension_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 670 extension_fetcher_->SetLoadFlags(load_flags); |
| 665 net::LOAD_DO_NOT_SAVE_COOKIES | | |
| 666 net::LOAD_DISABLE_CACHE); | |
| 667 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 671 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
| 668 // Download CRX files to a temp file. The blacklist is small and will be | 672 // Download CRX files to a temp file. The blacklist is small and will be |
| 669 // processed in memory, so it is fetched into a string. | 673 // processed in memory, so it is fetched into a string. |
| 670 if (extensions_queue_.active_request()->id != kBlacklistAppID) { | 674 if (fetch->id != kBlacklistAppID) { |
| 671 extension_fetcher_->SaveResponseToTemporaryFile( | 675 extension_fetcher_->SaveResponseToTemporaryFile( |
| 672 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | 676 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); |
| 673 } | 677 } |
| 674 | 678 |
| 675 VLOG(2) << "Starting fetch of " << extensions_queue_.active_request()->url | 679 VLOG(2) << "Starting fetch of " << fetch->url << " for " << fetch->id; |
| 676 << " for " << extensions_queue_.active_request()->id; | |
| 677 | 680 |
| 678 extension_fetcher_->Start(); | 681 extension_fetcher_->Start(); |
| 679 } | 682 } |
| 680 | 683 |
| 681 void ExtensionDownloader::OnCRXFetchComplete( | 684 void ExtensionDownloader::OnCRXFetchComplete( |
| 682 const net::URLFetcher* source, | 685 const net::URLFetcher* source, |
| 683 const GURL& url, | 686 const GURL& url, |
| 684 const net::URLRequestStatus& status, | 687 const net::URLRequestStatus& status, |
| 685 int response_code, | 688 int response_code, |
| 686 const base::TimeDelta& backoff_delay) { | 689 const base::TimeDelta& backoff_delay) { |
| 687 const std::string& id = extensions_queue_.active_request()->id; | 690 const std::string& id = extensions_queue_.active_request()->id; |
| 688 if (status.status() == net::URLRequestStatus::SUCCESS && | 691 if (status.status() == net::URLRequestStatus::SUCCESS && |
| 689 (response_code == 200 || url.SchemeIsFile())) { | 692 (response_code == 200 || url.SchemeIsFile())) { |
| 690 RETRY_HISTOGRAM("CrxFetchSuccess", | 693 RETRY_HISTOGRAM("CrxFetchSuccess", |
| 691 extensions_queue_.active_request_failure_count(), url); | 694 extensions_queue_.active_request_failure_count(), url); |
| 692 base::FilePath crx_path; | 695 base::FilePath crx_path; |
| 693 // Take ownership of the file at |crx_path|. | 696 // Take ownership of the file at |crx_path|. |
| 694 CHECK(source->GetResponseAsFilePath(true, &crx_path)); | 697 CHECK(source->GetResponseAsFilePath(true, &crx_path)); |
| 695 scoped_ptr<ExtensionFetch> fetch_data = | 698 scoped_ptr<ExtensionFetch> fetch_data = |
| 696 extensions_queue_.reset_active_request(); | 699 extensions_queue_.reset_active_request(); |
| 697 if (extension_cache_) { | 700 if (extension_cache_) { |
| 698 const std::string& version = fetch_data->version; | 701 const std::string& version = fetch_data->version; |
| 699 extension_cache_->PutExtension(id, crx_path, version, | 702 extension_cache_->PutExtension(id, crx_path, version, |
| 700 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, | 703 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, |
| 701 weak_ptr_factory_.GetWeakPtr(), | 704 weak_ptr_factory_.GetWeakPtr(), |
| 702 base::Passed(&fetch_data))); | 705 base::Passed(&fetch_data))); |
| 703 } else { | 706 } else { |
| 704 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); | 707 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); |
| 705 } | 708 } |
| 709 } else if (status.status() == net::URLRequestStatus::SUCCESS && | |
| 710 (response_code == 401 || response_code == 403) && | |
| 711 !extensions_queue_.active_request()->is_protected) { | |
| 712 // On 401 or 403, requeue this fetch with cookies enabled. | |
| 713 extensions_queue_.active_request()->is_protected = true; | |
| 714 extensions_queue_.RetryRequest(backoff_delay); | |
| 706 } else { | 715 } else { |
| 707 const std::set<int>& request_ids = | 716 const std::set<int>& request_ids = |
| 708 extensions_queue_.active_request()->request_ids; | 717 extensions_queue_.active_request()->request_ids; |
| 709 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; | 718 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; |
| 710 | 719 |
| 711 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() | 720 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() |
| 712 << "' response code:" << response_code; | 721 << "' response code:" << response_code; |
| 713 if (ShouldRetryRequest(status, response_code) && | 722 if (ShouldRetryRequest(status, response_code) && |
| 714 extensions_queue_.active_request_failure_count() < kMaxRetries) { | 723 extensions_queue_.active_request_failure_count() < kMaxRetries) { |
| 715 extensions_queue_.RetryRequest(backoff_delay); | 724 extensions_queue_.RetryRequest(backoff_delay); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 746 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, | 755 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, |
| 747 const std::string& version) { | 756 const std::string& version) { |
| 748 UpdateDetails updateInfo(id, Version(version)); | 757 UpdateDetails updateInfo(id, Version(version)); |
| 749 content::NotificationService::current()->Notify( | 758 content::NotificationService::current()->Notify( |
| 750 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, | 759 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, |
| 751 content::NotificationService::AllBrowserContextsAndSources(), | 760 content::NotificationService::AllBrowserContextsAndSources(), |
| 752 content::Details<UpdateDetails>(&updateInfo)); | 761 content::Details<UpdateDetails>(&updateInfo)); |
| 753 } | 762 } |
| 754 | 763 |
| 755 } // namespace extensions | 764 } // namespace extensions |
| OLD | NEW |