| 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() |
| 107 : url(), is_protected(false) {} |
| 106 | 108 |
| 107 ExtensionDownloader::ExtensionFetch::ExtensionFetch( | 109 ExtensionDownloader::ExtensionFetch::ExtensionFetch( |
| 108 const std::string& id, | 110 const std::string& id, |
| 109 const GURL& url, | 111 const GURL& url, |
| 110 const std::string& package_hash, | 112 const std::string& package_hash, |
| 111 const std::string& version, | 113 const std::string& version, |
| 112 const std::set<int>& request_ids) | 114 const std::set<int>& request_ids) |
| 113 : id(id), url(url), package_hash(package_hash), version(version), | 115 : id(id), url(url), package_hash(package_hash), version(version), |
| 114 request_ids(request_ids) {} | 116 request_ids(request_ids), is_protected(false) {} |
| 115 | 117 |
| 116 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} | 118 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} |
| 117 | 119 |
| 118 ExtensionDownloader::ExtensionDownloader( | 120 ExtensionDownloader::ExtensionDownloader( |
| 119 ExtensionDownloaderDelegate* delegate, | 121 ExtensionDownloaderDelegate* delegate, |
| 120 net::URLRequestContextGetter* request_context) | 122 net::URLRequestContextGetter* request_context) |
| 121 : delegate_(delegate), | 123 : delegate_(delegate), |
| 122 request_context_(request_context), | 124 request_context_(request_context), |
| 123 weak_ptr_factory_(this), | 125 weak_ptr_factory_(this), |
| 124 manifests_queue_(&kDefaultBackoffPolicy, | 126 manifests_queue_(&kDefaultBackoffPolicy, |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 scoped_ptr<ExtensionFetch> fetch_data, | 652 scoped_ptr<ExtensionFetch> fetch_data, |
| 651 const base::FilePath& crx_path, | 653 const base::FilePath& crx_path, |
| 652 bool file_ownership_passed) { | 654 bool file_ownership_passed) { |
| 653 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path, | 655 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path, |
| 654 file_ownership_passed, fetch_data->url, fetch_data->version, | 656 file_ownership_passed, fetch_data->url, fetch_data->version, |
| 655 ping_results_[fetch_data->id], fetch_data->request_ids); | 657 ping_results_[fetch_data->id], fetch_data->request_ids); |
| 656 ping_results_.erase(fetch_data->id); | 658 ping_results_.erase(fetch_data->id); |
| 657 } | 659 } |
| 658 | 660 |
| 659 void ExtensionDownloader::CreateExtensionFetcher() { | 661 void ExtensionDownloader::CreateExtensionFetcher() { |
| 662 const ExtensionFetch* fetch = extensions_queue_.active_request(); |
| 663 int load_flags = net::LOAD_DISABLE_CACHE; |
| 664 if (!fetch->is_protected || !fetch->url.SchemeIs("https")) { |
| 665 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES | |
| 666 net::LOAD_DO_NOT_SAVE_COOKIES; |
| 667 } |
| 660 extension_fetcher_.reset(net::URLFetcher::Create( | 668 extension_fetcher_.reset(net::URLFetcher::Create( |
| 661 kExtensionFetcherId, extensions_queue_.active_request()->url, | 669 kExtensionFetcherId, fetch->url, net::URLFetcher::GET, this)); |
| 662 net::URLFetcher::GET, this)); | |
| 663 extension_fetcher_->SetRequestContext(request_context_); | 670 extension_fetcher_->SetRequestContext(request_context_); |
| 664 extension_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 671 extension_fetcher_->SetLoadFlags(load_flags); |
| 665 net::LOAD_DO_NOT_SAVE_COOKIES | | |
| 666 net::LOAD_DISABLE_CACHE); | |
| 667 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 672 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
| 668 // Download CRX files to a temp file. The blacklist is small and will be | 673 // 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. | 674 // processed in memory, so it is fetched into a string. |
| 670 if (extensions_queue_.active_request()->id != kBlacklistAppID) { | 675 if (fetch->id != kBlacklistAppID) { |
| 671 extension_fetcher_->SaveResponseToTemporaryFile( | 676 extension_fetcher_->SaveResponseToTemporaryFile( |
| 672 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | 677 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); |
| 673 } | 678 } |
| 674 | 679 |
| 675 VLOG(2) << "Starting fetch of " << extensions_queue_.active_request()->url | 680 VLOG(2) << "Starting fetch of " << fetch->url << " for " << fetch->id; |
| 676 << " for " << extensions_queue_.active_request()->id; | |
| 677 | 681 |
| 678 extension_fetcher_->Start(); | 682 extension_fetcher_->Start(); |
| 679 } | 683 } |
| 680 | 684 |
| 681 void ExtensionDownloader::OnCRXFetchComplete( | 685 void ExtensionDownloader::OnCRXFetchComplete( |
| 682 const net::URLFetcher* source, | 686 const net::URLFetcher* source, |
| 683 const GURL& url, | 687 const GURL& url, |
| 684 const net::URLRequestStatus& status, | 688 const net::URLRequestStatus& status, |
| 685 int response_code, | 689 int response_code, |
| 686 const base::TimeDelta& backoff_delay) { | 690 const base::TimeDelta& backoff_delay) { |
| 687 const std::string& id = extensions_queue_.active_request()->id; | 691 const std::string& id = extensions_queue_.active_request()->id; |
| 688 if (status.status() == net::URLRequestStatus::SUCCESS && | 692 if (status.status() == net::URLRequestStatus::SUCCESS && |
| 689 (response_code == 200 || url.SchemeIsFile())) { | 693 (response_code == 200 || url.SchemeIsFile())) { |
| 690 RETRY_HISTOGRAM("CrxFetchSuccess", | 694 RETRY_HISTOGRAM("CrxFetchSuccess", |
| 691 extensions_queue_.active_request_failure_count(), url); | 695 extensions_queue_.active_request_failure_count(), url); |
| 692 base::FilePath crx_path; | 696 base::FilePath crx_path; |
| 693 // Take ownership of the file at |crx_path|. | 697 // Take ownership of the file at |crx_path|. |
| 694 CHECK(source->GetResponseAsFilePath(true, &crx_path)); | 698 CHECK(source->GetResponseAsFilePath(true, &crx_path)); |
| 695 scoped_ptr<ExtensionFetch> fetch_data = | 699 scoped_ptr<ExtensionFetch> fetch_data = |
| 696 extensions_queue_.reset_active_request(); | 700 extensions_queue_.reset_active_request(); |
| 697 if (extension_cache_) { | 701 if (extension_cache_) { |
| 698 const std::string& version = fetch_data->version; | 702 const std::string& version = fetch_data->version; |
| 699 extension_cache_->PutExtension(id, crx_path, version, | 703 extension_cache_->PutExtension(id, crx_path, version, |
| 700 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, | 704 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, |
| 701 weak_ptr_factory_.GetWeakPtr(), | 705 weak_ptr_factory_.GetWeakPtr(), |
| 702 base::Passed(&fetch_data))); | 706 base::Passed(&fetch_data))); |
| 703 } else { | 707 } else { |
| 704 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); | 708 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); |
| 705 } | 709 } |
| 710 } else if (status.status() == net::URLRequestStatus::SUCCESS && |
| 711 (response_code == 401 || response_code == 403) && |
| 712 !extensions_queue_.active_request()->is_protected) { |
| 713 // On 401 or 403, requeue this fetch with cookies enabled. |
| 714 extensions_queue_.active_request()->is_protected = true; |
| 715 extensions_queue_.RetryRequest(backoff_delay); |
| 706 } else { | 716 } else { |
| 707 const std::set<int>& request_ids = | 717 const std::set<int>& request_ids = |
| 708 extensions_queue_.active_request()->request_ids; | 718 extensions_queue_.active_request()->request_ids; |
| 709 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; | 719 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; |
| 710 | 720 |
| 711 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() | 721 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() |
| 712 << "' response code:" << response_code; | 722 << "' response code:" << response_code; |
| 713 if (ShouldRetryRequest(status, response_code) && | 723 if (ShouldRetryRequest(status, response_code) && |
| 714 extensions_queue_.active_request_failure_count() < kMaxRetries) { | 724 extensions_queue_.active_request_failure_count() < kMaxRetries) { |
| 715 extensions_queue_.RetryRequest(backoff_delay); | 725 extensions_queue_.RetryRequest(backoff_delay); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 746 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, | 756 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, |
| 747 const std::string& version) { | 757 const std::string& version) { |
| 748 UpdateDetails updateInfo(id, Version(version)); | 758 UpdateDetails updateInfo(id, Version(version)); |
| 749 content::NotificationService::current()->Notify( | 759 content::NotificationService::current()->Notify( |
| 750 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, | 760 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, |
| 751 content::NotificationService::AllBrowserContextsAndSources(), | 761 content::NotificationService::AllBrowserContextsAndSources(), |
| 752 content::Details<UpdateDetails>(&updateInfo)); | 762 content::Details<UpdateDetails>(&updateInfo)); |
| 753 } | 763 } |
| 754 | 764 |
| 755 } // namespace extensions | 765 } // namespace extensions |
| OLD | NEW |