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

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

Issue 279453002: Support multiple sign-in for extension updates. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/location.h" 12 #include "base/location.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/scoped_handle.h" 14 #include "base/memory/scoped_handle.h"
15 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
16 #include "base/metrics/sparse_histogram.h" 16 #include "base/metrics/sparse_histogram.h"
17 #include "base/platform_file.h" 17 #include "base/platform_file.h"
18 #include "base/stl_util.h" 18 #include "base/stl_util.h"
19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
20 #include "base/time/time.h" 22 #include "base/time/time.h"
21 #include "base/version.h" 23 #include "base/version.h"
22 #include "chrome/browser/chrome_notification_types.h" 24 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/extensions/updater/extension_cache.h" 25 #include "chrome/browser/extensions/updater/extension_cache.h"
24 #include "chrome/browser/extensions/updater/request_queue_impl.h" 26 #include "chrome/browser/extensions/updater/request_queue_impl.h"
25 #include "chrome/browser/extensions/updater/safe_manifest_parser.h" 27 #include "chrome/browser/extensions/updater/safe_manifest_parser.h"
26 #include "chrome/browser/metrics/metrics_service.h" 28 #include "chrome/browser/metrics/metrics_service.h"
27 #include "chrome/common/chrome_switches.h" 29 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/chrome_version_info.h" 30 #include "chrome/common/chrome_version_info.h"
29 #include "chrome/common/extensions/extension_constants.h" 31 #include "chrome/common/extensions/extension_constants.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 -1, 69 -1,
68 70
69 // Time to keep an entry from being discarded even when it 71 // Time to keep an entry from being discarded even when it
70 // has no significant state, -1 to never discard. 72 // has no significant state, -1 to never discard.
71 -1, 73 -1,
72 74
73 // Don't use initial delay unless the last request was an error. 75 // Don't use initial delay unless the last request was an error.
74 false, 76 false,
75 }; 77 };
76 78
79 const char kAuthUserQueryKey[] = "authuser";
80
81 const int kMaxAuthUserValue = 10;
82
77 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; 83 const char kNotFromWebstoreInstallSource[] = "notfromwebstore";
78 const char kDefaultInstallSource[] = ""; 84 const char kDefaultInstallSource[] = "";
79 85
80 #define RETRY_HISTOGRAM(name, retry_count, url) \ 86 #define RETRY_HISTOGRAM(name, retry_count, url) \
81 if ((url).DomainIs("google.com")) { \ 87 if ((url).DomainIs("google.com")) { \
82 UMA_HISTOGRAM_CUSTOM_COUNTS( \ 88 UMA_HISTOGRAM_CUSTOM_COUNTS( \
83 "Extensions." name "RetryCountGoogleUrl", retry_count, 1, \ 89 "Extensions." name "RetryCountGoogleUrl", retry_count, 1, \
84 kMaxRetries, kMaxRetries+1); \ 90 kMaxRetries, kMaxRetries+1); \
85 } else { \ 91 } else { \
86 UMA_HISTOGRAM_CUSTOM_COUNTS( \ 92 UMA_HISTOGRAM_CUSTOM_COUNTS( \
87 "Extensions." name "RetryCountOtherUrl", retry_count, 1, \ 93 "Extensions." name "RetryCountOtherUrl", retry_count, 1, \
88 kMaxRetries, kMaxRetries+1); \ 94 kMaxRetries, kMaxRetries+1); \
89 } 95 }
90 96
91 bool ShouldRetryRequest(const net::URLRequestStatus& status, 97 bool ShouldRetryRequest(const net::URLRequestStatus& status,
92 int response_code) { 98 int response_code) {
93 // Retry if the response code is a server error, or the request failed because 99 // Retry if the response code is a server error, or the request failed because
94 // of network errors as opposed to file errors. 100 // of network errors as opposed to file errors.
95 return (response_code >= 500 && status.is_success()) || 101 return (response_code >= 500 && status.is_success()) ||
96 status.status() == net::URLRequestStatus::FAILED; 102 status.status() == net::URLRequestStatus::FAILED;
97 } 103 }
98 104
105 bool ShouldRetryRequestWithCookies(
106 const net::URLRequestStatus& status,
107 int response_code,
108 bool included_cookies) {
109 if (included_cookies)
110 return false;
111
112 if (status.status() == net::URLRequestStatus::CANCELED)
113 return true;
114
115 // Retry if a 401 or 403 is received.
116 return status.status() == net::URLRequestStatus::SUCCESS &&
117 (response_code == 401 || response_code == 403);
asargent_no_longer_on_chrome 2014/05/08 04:27:11 optional: if you add parentheses around the entire
Ken Rockot(use gerrit already) 2014/05/08 05:23:09 Done.
118 }
119
120 bool ShouldRetryRequestWithNextUser(
121 const net::URLRequestStatus& status,
122 int response_code,
123 bool included_cookies) {
124 // Retry if a 403 is received in response to a request including cookies.
125 // Note that receiving a 401 in response to a request which included cookies
126 // should indicate that the |authuser| index was out of bounds for the profile
127 // and therefore Chrome should NOT retry with another index.
128 return status.status() == net::URLRequestStatus::SUCCESS &&
129 response_code == 403 && included_cookies;
asargent_no_longer_on_chrome 2014/05/08 04:27:11 same here
Ken Rockot(use gerrit already) 2014/05/08 05:23:09 Done.
130 }
131
132 // This parses and updates a URL query such that the value of the |authuser|
133 // query parameter is incremented by 1. If parameter was not present in the URL,
134 // it will be added with a value of 1. All other query keys and values are
135 // preserved as-is. Returns |false| if the user index exceeds a hard-coded
136 // maximum.
137 bool IncrementAuthUserIndex(GURL* url) {
138 int user_index = 0;
139 std::string old_query = url->query();
140 std::vector<std::string> new_query_parts;
141 url::Component query(0, old_query.length());
142 url::Component key, value;
143 while (url::ExtractQueryKeyValue(
144 old_query.c_str(), &query, &key, &value)) {
145 std::string key_string = old_query.substr(key.begin, key.len);
146 std::string value_string = old_query.substr(value.begin, value.len);
147 if (key_string == kAuthUserQueryKey) {
148 base::StringToInt(value_string, &user_index);
149 } else {
150 new_query_parts.push_back(
151 base::StringPrintf("%s=%s",
152 key_string.c_str(),
153 value_string.c_str()));
154 }
155 }
156 if (user_index >= kMaxAuthUserValue)
157 return false;
158 new_query_parts.push_back(
159 base::StringPrintf("%s=%d", kAuthUserQueryKey, user_index + 1));
160 std::string new_query = "?" + JoinString(new_query_parts, '&');
161 *url = url->Resolve(new_query);
asargent_no_longer_on_chrome 2014/05/08 04:27:11 Hmm, I assume you've actually run this and it work
Ken Rockot(use gerrit already) 2014/05/08 05:23:09 Yeah, using Resolve is OK in this case, but I actu
162 return true;
163 }
164
99 } // namespace 165 } // namespace
100 166
101 UpdateDetails::UpdateDetails(const std::string& id, const Version& version) 167 UpdateDetails::UpdateDetails(const std::string& id, const Version& version)
102 : id(id), version(version) {} 168 : id(id), version(version) {}
103 169
104 UpdateDetails::~UpdateDetails() {} 170 UpdateDetails::~UpdateDetails() {}
105 171
106 ExtensionDownloader::ExtensionFetch::ExtensionFetch() 172 ExtensionDownloader::ExtensionFetch::ExtensionFetch()
107 : url(), is_protected(false) {} 173 : url(), is_protected(false) {}
108 174
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 extensions_queue_.reset_active_request(); 766 extensions_queue_.reset_active_request();
701 if (extension_cache_) { 767 if (extension_cache_) {
702 const std::string& version = fetch_data->version; 768 const std::string& version = fetch_data->version;
703 extension_cache_->PutExtension(id, crx_path, version, 769 extension_cache_->PutExtension(id, crx_path, version,
704 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, 770 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished,
705 weak_ptr_factory_.GetWeakPtr(), 771 weak_ptr_factory_.GetWeakPtr(),
706 base::Passed(&fetch_data))); 772 base::Passed(&fetch_data)));
707 } else { 773 } else {
708 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); 774 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true);
709 } 775 }
710 } else if (status.status() == net::URLRequestStatus::SUCCESS && 776 } else if (ShouldRetryRequestWithCookies(
711 (response_code == 401 || response_code == 403) && 777 status,
712 !extensions_queue_.active_request()->is_protected) { 778 response_code,
713 // On 401 or 403, requeue this fetch with cookies enabled. 779 extensions_queue_.active_request()->is_protected)) {
780 // Requeue the fetch with |is_protected| set, enabling cookies.
714 extensions_queue_.active_request()->is_protected = true; 781 extensions_queue_.active_request()->is_protected = true;
715 extensions_queue_.RetryRequest(backoff_delay); 782 extensions_queue_.RetryRequest(backoff_delay);
783 } else if (ShouldRetryRequestWithNextUser(
784 status,
785 response_code,
786 extensions_queue_.active_request()->is_protected) &&
787 IncrementAuthUserIndex(&extensions_queue_.active_request()->url)) {
788 extensions_queue_.RetryRequest(backoff_delay);
716 } else { 789 } else {
717 const std::set<int>& request_ids = 790 const std::set<int>& request_ids =
718 extensions_queue_.active_request()->request_ids; 791 extensions_queue_.active_request()->request_ids;
719 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; 792 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id];
720
721 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() 793 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec()
722 << "' response code:" << response_code; 794 << "' response code:" << response_code;
723 if (ShouldRetryRequest(status, response_code) && 795 if (ShouldRetryRequest(status, response_code) &&
724 extensions_queue_.active_request_failure_count() < kMaxRetries) { 796 extensions_queue_.active_request_failure_count() < kMaxRetries) {
725 extensions_queue_.RetryRequest(backoff_delay); 797 extensions_queue_.RetryRequest(backoff_delay);
726 } else { 798 } else {
727 RETRY_HISTOGRAM("CrxFetchFailure", 799 RETRY_HISTOGRAM("CrxFetchFailure",
728 extensions_queue_.active_request_failure_count(), url); 800 extensions_queue_.active_request_failure_count(), url);
729 // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h) 801 // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h)
730 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.CrxFetchError", -status.error()); 802 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.CrxFetchError", -status.error());
(...skipping 25 matching lines...) Expand all
756 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, 828 void ExtensionDownloader::NotifyUpdateFound(const std::string& id,
757 const std::string& version) { 829 const std::string& version) {
758 UpdateDetails updateInfo(id, Version(version)); 830 UpdateDetails updateInfo(id, Version(version));
759 content::NotificationService::current()->Notify( 831 content::NotificationService::current()->Notify(
760 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, 832 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND,
761 content::NotificationService::AllBrowserContextsAndSources(), 833 content::NotificationService::AllBrowserContextsAndSources(),
762 content::Details<UpdateDetails>(&updateInfo)); 834 content::Details<UpdateDetails>(&updateInfo));
763 } 835 }
764 836
765 } // namespace extensions 837 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698