Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(294)

Side by Side Diff: chrome/browser/extensions/updater/extension_downloader.cc

Issue 434493002: OAuth2 support for Webstore downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 13 matching lines...) Expand all
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 "content/public/browser/browser_thread.h" 31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/browser/notification_details.h" 32 #include "content/public/browser/notification_details.h"
33 #include "content/public/browser/notification_service.h" 33 #include "content/public/browser/notification_service.h"
34 #include "extensions/browser/webstore_oauth2_token_provider.h"
34 #include "net/base/backoff_entry.h" 35 #include "net/base/backoff_entry.h"
35 #include "net/base/load_flags.h" 36 #include "net/base/load_flags.h"
36 #include "net/base/net_errors.h" 37 #include "net/base/net_errors.h"
38 #include "net/http/http_request_headers.h"
37 #include "net/url_request/url_fetcher.h" 39 #include "net/url_request/url_fetcher.h"
38 #include "net/url_request/url_request_context_getter.h" 40 #include "net/url_request/url_request_context_getter.h"
39 #include "net/url_request/url_request_status.h" 41 #include "net/url_request/url_request_status.h"
40 42
41 using base::Time; 43 using base::Time;
42 using base::TimeDelta; 44 using base::TimeDelta;
43 using content::BrowserThread; 45 using content::BrowserThread;
44 46
45 namespace extensions { 47 namespace extensions {
46 48
(...skipping 27 matching lines...) Expand all
74 false, 76 false,
75 }; 77 };
76 78
77 const char kAuthUserQueryKey[] = "authuser"; 79 const char kAuthUserQueryKey[] = "authuser";
78 80
79 const int kMaxAuthUserValue = 10; 81 const int kMaxAuthUserValue = 10;
80 82
81 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; 83 const char kNotFromWebstoreInstallSource[] = "notfromwebstore";
82 const char kDefaultInstallSource[] = ""; 84 const char kDefaultInstallSource[] = "";
83 85
84 #define RETRY_HISTOGRAM(name, retry_count, url) \ 86 const char kGoogleDotCom[] = "google.com";
85 if ((url).DomainIs("google.com")) { \ 87
86 UMA_HISTOGRAM_CUSTOM_COUNTS( \ 88 #define RETRY_HISTOGRAM(name, retry_count, url) \
87 "Extensions." name "RetryCountGoogleUrl", retry_count, 1, \ 89 if ((url).DomainIs(kGoogleDotCom)) { \
88 kMaxRetries, kMaxRetries+1); \ 90 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions." name "RetryCountGoogleUrl", \
89 } else { \ 91 retry_count, \
90 UMA_HISTOGRAM_CUSTOM_COUNTS( \ 92 1, \
91 "Extensions." name "RetryCountOtherUrl", retry_count, 1, \ 93 kMaxRetries, \
92 kMaxRetries, kMaxRetries+1); \ 94 kMaxRetries + 1); \
93 } 95 } else { \
96 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions." name "RetryCountOtherUrl", \
97 retry_count, \
98 1, \
99 kMaxRetries, \
100 kMaxRetries + 1); \
101 }
94 102
95 bool ShouldRetryRequest(const net::URLRequestStatus& status, 103 bool ShouldRetryRequest(const net::URLRequestStatus& status,
96 int response_code) { 104 int response_code) {
97 // Retry if the response code is a server error, or the request failed because 105 // Retry if the response code is a server error, or the request failed because
98 // of network errors as opposed to file errors. 106 // of network errors as opposed to file errors.
99 return ((response_code >= 500 && status.is_success()) || 107 return ((response_code >= 500 && status.is_success()) ||
100 status.status() == net::URLRequestStatus::FAILED); 108 status.status() == net::URLRequestStatus::FAILED);
101 } 109 }
102 110
103 bool ShouldRetryRequestWithCookies(const net::URLRequestStatus& status,
104 int response_code,
105 bool included_cookies) {
106 if (included_cookies)
107 return false;
108
109 if (status.status() == net::URLRequestStatus::CANCELED)
110 return true;
111
112 // Retry if a 401 or 403 is received.
113 return (status.status() == net::URLRequestStatus::SUCCESS &&
114 (response_code == 401 || response_code == 403));
115 }
116
117 bool ShouldRetryRequestWithNextUser(const net::URLRequestStatus& status,
118 int response_code,
119 bool included_cookies) {
120 // Retry if a 403 is received in response to a request including cookies.
121 // Note that receiving a 401 in response to a request which included cookies
122 // should indicate that the |authuser| index was out of bounds for the profile
123 // and therefore Chrome should NOT retry with another index.
124 return (status.status() == net::URLRequestStatus::SUCCESS &&
125 response_code == 403 && included_cookies);
126 }
127
128 // This parses and updates a URL query such that the value of the |authuser| 111 // This parses and updates a URL query such that the value of the |authuser|
129 // query parameter is incremented by 1. If parameter was not present in the URL, 112 // query parameter is incremented by 1. If parameter was not present in the URL,
130 // it will be added with a value of 1. All other query keys and values are 113 // it will be added with a value of 1. All other query keys and values are
131 // preserved as-is. Returns |false| if the user index exceeds a hard-coded 114 // preserved as-is. Returns |false| if the user index exceeds a hard-coded
132 // maximum. 115 // maximum.
133 bool IncrementAuthUserIndex(GURL* url) { 116 bool IncrementAuthUserIndex(GURL* url) {
134 int user_index = 0; 117 int user_index = 0;
135 std::string old_query = url->query(); 118 std::string old_query = url->query();
136 std::vector<std::string> new_query_parts; 119 std::vector<std::string> new_query_parts;
137 url::Component query(0, old_query.length()); 120 url::Component query(0, old_query.length());
(...skipping 21 matching lines...) Expand all
159 } 142 }
160 143
161 } // namespace 144 } // namespace
162 145
163 UpdateDetails::UpdateDetails(const std::string& id, const Version& version) 146 UpdateDetails::UpdateDetails(const std::string& id, const Version& version)
164 : id(id), version(version) {} 147 : id(id), version(version) {}
165 148
166 UpdateDetails::~UpdateDetails() {} 149 UpdateDetails::~UpdateDetails() {}
167 150
168 ExtensionDownloader::ExtensionFetch::ExtensionFetch() 151 ExtensionDownloader::ExtensionFetch::ExtensionFetch()
169 : url(), is_protected(false) {} 152 : url(), credentials(CREDENTIALS_NONE) {
153 }
170 154
171 ExtensionDownloader::ExtensionFetch::ExtensionFetch( 155 ExtensionDownloader::ExtensionFetch::ExtensionFetch(
172 const std::string& id, 156 const std::string& id,
173 const GURL& url, 157 const GURL& url,
174 const std::string& package_hash, 158 const std::string& package_hash,
175 const std::string& version, 159 const std::string& version,
176 const std::set<int>& request_ids) 160 const std::set<int>& request_ids)
177 : id(id), url(url), package_hash(package_hash), version(version), 161 : id(id),
178 request_ids(request_ids), is_protected(false) {} 162 url(url),
163 package_hash(package_hash),
164 version(version),
165 request_ids(request_ids),
166 credentials(CREDENTIALS_NONE) {
167 }
179 168
180 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} 169 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {}
181 170
182 ExtensionDownloader::ExtensionDownloader( 171 ExtensionDownloader::ExtensionDownloader(
183 ExtensionDownloaderDelegate* delegate, 172 ExtensionDownloaderDelegate* delegate,
184 net::URLRequestContextGetter* request_context) 173 net::URLRequestContextGetter* request_context,
174 IdentityProvider* webstore_identity_provider)
185 : delegate_(delegate), 175 : delegate_(delegate),
186 request_context_(request_context), 176 request_context_(request_context),
187 weak_ptr_factory_(this), 177 weak_ptr_factory_(this),
188 manifests_queue_(&kDefaultBackoffPolicy, 178 manifests_queue_(&kDefaultBackoffPolicy,
189 base::Bind(&ExtensionDownloader::CreateManifestFetcher, 179 base::Bind(&ExtensionDownloader::CreateManifestFetcher,
190 base::Unretained(this))), 180 base::Unretained(this))),
191 extensions_queue_(&kDefaultBackoffPolicy, 181 extensions_queue_(&kDefaultBackoffPolicy,
192 base::Bind(&ExtensionDownloader::CreateExtensionFetcher, 182 base::Bind(&ExtensionDownloader::CreateExtensionFetcher,
193 base::Unretained(this))), 183 base::Unretained(this))),
194 extension_cache_(NULL) { 184 extension_cache_(NULL) {
185 if (webstore_identity_provider) {
186 webstore_token_provider_.reset(
187 new WebstoreOAuth2TokenProvider(webstore_identity_provider));
188 }
195 DCHECK(delegate_); 189 DCHECK(delegate_);
196 DCHECK(request_context_); 190 DCHECK(request_context_);
197 } 191 }
198 192
199 ExtensionDownloader::~ExtensionDownloader() {} 193 ExtensionDownloader::~ExtensionDownloader() {}
200 194
201 bool ExtensionDownloader::AddExtension(const Extension& extension, 195 bool ExtensionDownloader::AddExtension(const Extension& extension,
202 int request_id) { 196 int request_id) {
203 // Skip extensions with empty update URLs converted from user 197 // Skip extensions with empty update URLs converted from user
204 // scripts. 198 // scripts.
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 if (extension_urls::IsWebstoreUpdateUrl(update_url) && 293 if (extension_urls::IsWebstoreUpdateUrl(update_url) &&
300 !update_url.SchemeIsSecure()) 294 !update_url.SchemeIsSecure())
301 update_url = extension_urls::GetWebstoreUpdateUrl(); 295 update_url = extension_urls::GetWebstoreUpdateUrl();
302 296
303 // Skip extensions with empty IDs. 297 // Skip extensions with empty IDs.
304 if (id.empty()) { 298 if (id.empty()) {
305 LOG(WARNING) << "Found extension with empty ID"; 299 LOG(WARNING) << "Found extension with empty ID";
306 return false; 300 return false;
307 } 301 }
308 302
309 if (update_url.DomainIs("google.com")) { 303 if (update_url.DomainIs(kGoogleDotCom)) {
310 url_stats_.google_url_count++; 304 url_stats_.google_url_count++;
311 } else if (update_url.is_empty()) { 305 } else if (update_url.is_empty()) {
312 url_stats_.no_url_count++; 306 url_stats_.no_url_count++;
313 // Fill in default update URL. 307 // Fill in default update URL.
314 update_url = extension_urls::GetWebstoreUpdateUrl(); 308 update_url = extension_urls::GetWebstoreUpdateUrl();
315 } else { 309 } else {
316 url_stats_.other_url_count++; 310 url_stats_.other_url_count++;
317 } 311 }
318 312
319 switch (extension_type) { 313 switch (extension_type) {
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 567 }
574 } 568 }
575 scoped_ptr<ExtensionFetch> fetch(new ExtensionFetch( 569 scoped_ptr<ExtensionFetch> fetch(new ExtensionFetch(
576 update->extension_id, crx_url, update->package_hash, 570 update->extension_id, crx_url, update->package_hash,
577 update->version, fetch_data.request_ids())); 571 update->version, fetch_data.request_ids()));
578 FetchUpdatedExtension(fetch.Pass()); 572 FetchUpdatedExtension(fetch.Pass());
579 } 573 }
580 574
581 // If the manifest response included a <daystart> element, we want to save 575 // If the manifest response included a <daystart> element, we want to save
582 // that value for any extensions which had sent a ping in the request. 576 // that value for any extensions which had sent a ping in the request.
583 if (fetch_data.base_url().DomainIs("google.com") && 577 if (fetch_data.base_url().DomainIs(kGoogleDotCom) &&
584 results->daystart_elapsed_seconds >= 0) { 578 results->daystart_elapsed_seconds >= 0) {
585 Time day_start = 579 Time day_start =
586 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); 580 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds);
587 581
588 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); 582 const std::set<std::string>& extension_ids = fetch_data.extension_ids();
589 std::set<std::string>::const_iterator i; 583 std::set<std::string>::const_iterator i;
590 for (i = extension_ids.begin(); i != extension_ids.end(); i++) { 584 for (i = extension_ids.begin(); i != extension_ids.end(); i++) {
591 const std::string& id = *i; 585 const std::string& id = *i;
592 ExtensionDownloaderDelegate::PingResult& result = ping_results_[id]; 586 ExtensionDownloaderDelegate::PingResult& result = ping_results_[id];
593 result.did_ping = fetch_data.DidPing(id, ManifestFetchData::ROLLCALL); 587 result.did_ping = fetch_data.DidPing(id, ManifestFetchData::ROLLCALL);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
715 const base::FilePath& crx_path, 709 const base::FilePath& crx_path,
716 bool file_ownership_passed) { 710 bool file_ownership_passed) {
717 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path, 711 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path,
718 file_ownership_passed, fetch_data->url, fetch_data->version, 712 file_ownership_passed, fetch_data->url, fetch_data->version,
719 ping_results_[fetch_data->id], fetch_data->request_ids); 713 ping_results_[fetch_data->id], fetch_data->request_ids);
720 ping_results_.erase(fetch_data->id); 714 ping_results_.erase(fetch_data->id);
721 } 715 }
722 716
723 void ExtensionDownloader::CreateExtensionFetcher() { 717 void ExtensionDownloader::CreateExtensionFetcher() {
724 const ExtensionFetch* fetch = extensions_queue_.active_request(); 718 const ExtensionFetch* fetch = extensions_queue_.active_request();
719 extension_fetcher_.reset(net::URLFetcher::Create(
720 kExtensionFetcherId, fetch->url, net::URLFetcher::GET, this));
721 extension_fetcher_->SetRequestContext(request_context_);
722 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3);
723
725 int load_flags = net::LOAD_DISABLE_CACHE; 724 int load_flags = net::LOAD_DISABLE_CACHE;
726 if (!fetch->is_protected || !fetch->url.SchemeIs("https")) { 725 bool is_secure = fetch->url.SchemeIsSecure();
726 if (fetch->credentials != ExtensionFetch::CREDENTIALS_COOKIES || !is_secure) {
727 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES | 727 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES |
728 net::LOAD_DO_NOT_SAVE_COOKIES; 728 net::LOAD_DO_NOT_SAVE_COOKIES;
729 } 729 }
730 extension_fetcher_.reset(net::URLFetcher::Create(
731 kExtensionFetcherId, fetch->url, net::URLFetcher::GET, this));
732 extension_fetcher_->SetRequestContext(request_context_);
733 extension_fetcher_->SetLoadFlags(load_flags); 730 extension_fetcher_->SetLoadFlags(load_flags);
734 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); 731
735 // Download CRX files to a temp file. The blacklist is small and will be 732 // Download CRX files to a temp file. The blacklist is small and will be
736 // processed in memory, so it is fetched into a string. 733 // processed in memory, so it is fetched into a string.
737 if (fetch->id != kBlacklistAppID) { 734 if (fetch->id != kBlacklistAppID) {
738 extension_fetcher_->SaveResponseToTemporaryFile( 735 extension_fetcher_->SaveResponseToTemporaryFile(
739 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 736 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
740 } 737 }
741 738
742 VLOG(2) << "Starting fetch of " << fetch->url << " for " << fetch->id; 739 // If we should use OAuth2, fetch a token first.
743 740 if (fetch->credentials == ExtensionFetch::CREDENTIALS_OAUTH2_TOKEN &&
744 extension_fetcher_->Start(); 741 is_secure && webstore_token_provider_) {
742 webstore_token_provider_->FetchToken(
743 base::Bind(&ExtensionDownloader::OnWebstoreOAuth2TokenReceived,
744 weak_ptr_factory_.GetWeakPtr()));
745 } else {
746 VLOG(2) << "Starting fetch of " << fetch->url << " for " << fetch->id;
747 extension_fetcher_->Start();
748 }
745 } 749 }
746 750
747 void ExtensionDownloader::OnCRXFetchComplete( 751 void ExtensionDownloader::OnCRXFetchComplete(
748 const net::URLFetcher* source, 752 const net::URLFetcher* source,
749 const GURL& url, 753 const GURL& url,
750 const net::URLRequestStatus& status, 754 const net::URLRequestStatus& status,
751 int response_code, 755 int response_code,
752 const base::TimeDelta& backoff_delay) { 756 const base::TimeDelta& backoff_delay) {
753 const std::string& id = extensions_queue_.active_request()->id; 757 ExtensionFetch& active_request = *extensions_queue_.active_request();
758 const std::string& id = active_request.id;
754 if (status.status() == net::URLRequestStatus::SUCCESS && 759 if (status.status() == net::URLRequestStatus::SUCCESS &&
755 (response_code == 200 || url.SchemeIsFile())) { 760 (response_code == 200 || url.SchemeIsFile())) {
756 RETRY_HISTOGRAM("CrxFetchSuccess", 761 RETRY_HISTOGRAM("CrxFetchSuccess",
757 extensions_queue_.active_request_failure_count(), url); 762 extensions_queue_.active_request_failure_count(), url);
758 base::FilePath crx_path; 763 base::FilePath crx_path;
759 // Take ownership of the file at |crx_path|. 764 // Take ownership of the file at |crx_path|.
760 CHECK(source->GetResponseAsFilePath(true, &crx_path)); 765 CHECK(source->GetResponseAsFilePath(true, &crx_path));
761 scoped_ptr<ExtensionFetch> fetch_data = 766 scoped_ptr<ExtensionFetch> fetch_data =
762 extensions_queue_.reset_active_request(); 767 extensions_queue_.reset_active_request();
763 if (extension_cache_) { 768 if (extension_cache_) {
764 const std::string& version = fetch_data->version; 769 const std::string& version = fetch_data->version;
765 extension_cache_->PutExtension(id, crx_path, version, 770 extension_cache_->PutExtension(id, crx_path, version,
766 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, 771 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished,
767 weak_ptr_factory_.GetWeakPtr(), 772 weak_ptr_factory_.GetWeakPtr(),
768 base::Passed(&fetch_data))); 773 base::Passed(&fetch_data)));
769 } else { 774 } else {
770 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); 775 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true);
771 } 776 }
772 } else if (ShouldRetryRequestWithCookies( 777 } else if (IterateFetchCredentialsAfterFailure(
773 status, 778 &active_request,
774 response_code, 779 status,
775 extensions_queue_.active_request()->is_protected)) { 780 response_code)) {
776 // Requeue the fetch with |is_protected| set, enabling cookies.
777 extensions_queue_.active_request()->is_protected = true;
778 extensions_queue_.RetryRequest(backoff_delay);
779 } else if (ShouldRetryRequestWithNextUser(
780 status,
781 response_code,
782 extensions_queue_.active_request()->is_protected) &&
783 IncrementAuthUserIndex(&extensions_queue_.active_request()->url)) {
784 extensions_queue_.RetryRequest(backoff_delay); 781 extensions_queue_.RetryRequest(backoff_delay);
785 } else { 782 } else {
786 const std::set<int>& request_ids = 783 const std::set<int>& request_ids = active_request.request_ids;
787 extensions_queue_.active_request()->request_ids;
788 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; 784 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id];
789 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() 785 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec()
790 << "' response code:" << response_code; 786 << "' response code:" << response_code;
791 if (ShouldRetryRequest(status, response_code) && 787 if (ShouldRetryRequest(status, response_code) &&
792 extensions_queue_.active_request_failure_count() < kMaxRetries) { 788 extensions_queue_.active_request_failure_count() < kMaxRetries) {
793 extensions_queue_.RetryRequest(backoff_delay); 789 extensions_queue_.RetryRequest(backoff_delay);
794 } else { 790 } else {
795 RETRY_HISTOGRAM("CrxFetchFailure", 791 RETRY_HISTOGRAM("CrxFetchFailure",
796 extensions_queue_.active_request_failure_count(), url); 792 extensions_queue_.active_request_failure_count(), url);
797 // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h) 793 // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h)
(...skipping 25 matching lines...) Expand all
823 819
824 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, 820 void ExtensionDownloader::NotifyUpdateFound(const std::string& id,
825 const std::string& version) { 821 const std::string& version) {
826 UpdateDetails updateInfo(id, Version(version)); 822 UpdateDetails updateInfo(id, Version(version));
827 content::NotificationService::current()->Notify( 823 content::NotificationService::current()->Notify(
828 extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND, 824 extensions::NOTIFICATION_EXTENSION_UPDATE_FOUND,
829 content::NotificationService::AllBrowserContextsAndSources(), 825 content::NotificationService::AllBrowserContextsAndSources(),
830 content::Details<UpdateDetails>(&updateInfo)); 826 content::Details<UpdateDetails>(&updateInfo));
831 } 827 }
832 828
829 bool ExtensionDownloader::IterateFetchCredentialsAfterFailure(
830 ExtensionFetch* fetch,
831 const net::URLRequestStatus& status,
832 int response_code) {
833 bool auth_failure = status.status() == net::URLRequestStatus::CANCELED ||
834 (status.status() == net::URLRequestStatus::SUCCESS &&
835 (response_code == 401 || response_code == 403));
836 if (!auth_failure) {
837 return false;
838 }
839 switch (fetch->credentials) {
840 case ExtensionFetch::CREDENTIALS_NONE:
841 if (fetch->url.DomainIs(kGoogleDotCom) && webstore_token_provider_) {
842 fetch->credentials = ExtensionFetch::CREDENTIALS_OAUTH2_TOKEN;
843 } else {
844 fetch->credentials = ExtensionFetch::CREDENTIALS_COOKIES;
845 }
846 break;
847 case ExtensionFetch::CREDENTIALS_OAUTH2_TOKEN:
848 fetch->credentials = ExtensionFetch::CREDENTIALS_COOKIES;
849 break;
850 case ExtensionFetch::CREDENTIALS_COOKIES:
851 if (response_code == 403) {
852 return IncrementAuthUserIndex(&fetch->url);
853 }
854 return false;
855 default:
856 NOTREACHED();
857 }
858 return true;
859 }
860
861 void ExtensionDownloader::OnWebstoreOAuth2TokenReceived(
862 bool success,
863 const std::string& token) {
864 // If for whatever reason the token fetch fails, the fetch will still be
865 // retried with no Authorization header; in such cases the download is
866 // probably going to fail again, but the fetcher will then fall back onto
867 // cookie-based authentication.
868 if (success) {
869 extension_fetcher_->AddExtraRequestHeader(
870 base::StringPrintf("%s:Bearer %s",
Roger Tawa OOO till Jul 10th 2014/08/07 01:35:15 nit: space between : and Bearer
Ken Rockot(use gerrit already) 2014/08/07 16:49:09 Done.
871 net::HttpRequestHeaders::kAuthorization,
872 token.c_str()));
873 }
874 extension_fetcher_->Start();
875 }
876
833 } // namespace extensions 877 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698