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

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

Issue 2768573002: Send traffic-management headers from extension updater. (Closed)
Patch Set: Fix a compiler error in ChromeOS. Created 3 years, 9 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
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 "extensions/browser/updater/extension_downloader.h" 5 #include "extensions/browser/updater/extension_downloader.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/files/file_path.h" 13 #include "base/files/file_path.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/metrics/histogram_macros.h" 17 #include "base/metrics/histogram_macros.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_number_conversions.h"
20 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
22 #include "base/time/time.h" 22 #include "base/time/time.h"
23 #include "base/version.h" 23 #include "base/version.h"
24 #include "components/update_client/update_query_params.h"
24 #include "content/public/browser/browser_thread.h" 25 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/notification_details.h" 26 #include "content/public/browser/notification_details.h"
26 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
27 #include "extensions/browser/extensions_browser_client.h" 28 #include "extensions/browser/extensions_browser_client.h"
28 #include "extensions/browser/notification_types.h" 29 #include "extensions/browser/notification_types.h"
29 #include "extensions/browser/updater/extension_cache.h" 30 #include "extensions/browser/updater/extension_cache.h"
30 #include "extensions/browser/updater/extension_downloader_test_delegate.h" 31 #include "extensions/browser/updater/extension_downloader_test_delegate.h"
31 #include "extensions/browser/updater/request_queue_impl.h" 32 #include "extensions/browser/updater/request_queue_impl.h"
32 #include "extensions/browser/updater/safe_manifest_parser.h" 33 #include "extensions/browser/updater/safe_manifest_parser.h"
33 #include "extensions/common/extension_urls.h" 34 #include "extensions/common/extension_urls.h"
34 #include "extensions/common/manifest_url_handlers.h" 35 #include "extensions/common/manifest_url_handlers.h"
35 #include "google_apis/gaia/identity_provider.h" 36 #include "google_apis/gaia/identity_provider.h"
36 #include "net/base/backoff_entry.h" 37 #include "net/base/backoff_entry.h"
37 #include "net/base/load_flags.h" 38 #include "net/base/load_flags.h"
38 #include "net/base/net_errors.h" 39 #include "net/base/net_errors.h"
39 #include "net/http/http_request_headers.h" 40 #include "net/http/http_request_headers.h"
40 #include "net/http/http_status_code.h" 41 #include "net/http/http_status_code.h"
41 #include "net/url_request/url_fetcher.h" 42 #include "net/url_request/url_fetcher.h"
42 #include "net/url_request/url_request_context_getter.h" 43 #include "net/url_request/url_request_context_getter.h"
43 #include "net/url_request/url_request_status.h" 44 #include "net/url_request/url_request_status.h"
44 45
45 using base::Time; 46 using base::Time;
46 using base::TimeDelta; 47 using base::TimeDelta;
47 using content::BrowserThread; 48 using content::BrowserThread;
49 using update_client::UpdateQueryParams;
48 50
49 namespace extensions { 51 namespace extensions {
50 52
51 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist"; 53 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist";
52 54
53 namespace { 55 namespace {
54 56
55 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { 57 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
56 // Number of initial errors (in sequence) to ignore before applying 58 // Number of initial errors (in sequence) to ignore before applying
57 // exponential back-off rules. 59 // exponential back-off rules.
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 std::string new_query_string = base::JoinString(new_query_parts, "&"); 147 std::string new_query_string = base::JoinString(new_query_parts, "&");
146 url::Component new_query(0, new_query_string.size()); 148 url::Component new_query(0, new_query_string.size());
147 url::Replacements<char> replacements; 149 url::Replacements<char> replacements;
148 replacements.SetQuery(new_query_string.c_str(), new_query); 150 replacements.SetQuery(new_query_string.c_str(), new_query);
149 *url = url->ReplaceComponents(replacements); 151 *url = url->ReplaceComponents(replacements);
150 return true; 152 return true;
151 } 153 }
152 154
153 } // namespace 155 } // namespace
154 156
157 const char ExtensionDownloader::kUpdateInteractivityHeader[] =
158 "X-GoogleUpdate-Interactivity";
159 const char ExtensionDownloader::kUpdateAppIdHeader[] = "X-GoogleUpdate-AppId";
160 const char ExtensionDownloader::kUpdateUpdaterHeader[] =
161 "X-GoogleUpdate-Updater";
162
163 const char ExtensionDownloader::kUpdateInteractivityForeground[] = "fg";
164 const char ExtensionDownloader::kUpdateInteractivityBackground[] = "bg";
165
155 UpdateDetails::UpdateDetails(const std::string& id, 166 UpdateDetails::UpdateDetails(const std::string& id,
156 const base::Version& version) 167 const base::Version& version)
157 : id(id), version(version) {} 168 : id(id), version(version) {}
158 169
159 UpdateDetails::~UpdateDetails() { 170 UpdateDetails::~UpdateDetails() {
160 } 171 }
161 172
162 ExtensionDownloader::ExtensionFetch::ExtensionFetch() 173 ExtensionDownloader::ExtensionFetch::ExtensionFetch()
163 : url(), credentials(CREDENTIALS_NONE) { 174 : url(), credentials(CREDENTIALS_NONE) {
164 } 175 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 extension_cache_(NULL), 209 extension_cache_(NULL),
199 weak_ptr_factory_(this) { 210 weak_ptr_factory_(this) {
200 DCHECK(delegate_); 211 DCHECK(delegate_);
201 DCHECK(request_context_.get()); 212 DCHECK(request_context_.get());
202 } 213 }
203 214
204 ExtensionDownloader::~ExtensionDownloader() { 215 ExtensionDownloader::~ExtensionDownloader() {
205 } 216 }
206 217
207 bool ExtensionDownloader::AddExtension(const Extension& extension, 218 bool ExtensionDownloader::AddExtension(const Extension& extension,
208 int request_id) { 219 int request_id,
220 bool on_demand_update) {
209 // Skip extensions with empty update URLs converted from user 221 // Skip extensions with empty update URLs converted from user
210 // scripts. 222 // scripts.
211 if (extension.converted_from_user_script() && 223 if (extension.converted_from_user_script() &&
212 ManifestURL::GetUpdateURL(&extension).is_empty()) { 224 ManifestURL::GetUpdateURL(&extension).is_empty()) {
213 return false; 225 return false;
214 } 226 }
215 227
216 ExtraParams extra; 228 ExtraParams extra;
217 229
218 // If the extension updates itself from the gallery, ignore any update URL 230 // If the extension updates itself from the gallery, ignore any update URL
219 // data. At the moment there is no extra data that an extension can 231 // data. At the moment there is no extra data that an extension can
220 // communicate to the the gallery update servers. 232 // communicate to the the gallery update servers.
221 std::string update_url_data; 233 std::string update_url_data;
222 if (!ManifestURL::UpdatesFromGallery(&extension)) 234 if (!ManifestURL::UpdatesFromGallery(&extension))
223 extra.update_url_data = delegate_->GetUpdateUrlData(extension.id()); 235 extra.update_url_data = delegate_->GetUpdateUrlData(extension.id());
224 236
225 return AddExtensionData( 237 return AddExtensionData(extension.id(), *extension.version(),
226 extension.id(), *extension.version(), extension.GetType(), 238 extension.GetType(),
227 ManifestURL::GetUpdateURL(&extension), extra, request_id); 239 ManifestURL::GetUpdateURL(&extension), extra,
240 request_id, on_demand_update);
228 } 241 }
229 242
230 bool ExtensionDownloader::AddPendingExtension(const std::string& id, 243 bool ExtensionDownloader::AddPendingExtension(const std::string& id,
231 const GURL& update_url, 244 const GURL& update_url,
232 bool is_corrupt_reinstall, 245 bool is_corrupt_reinstall,
233 int request_id) { 246 int request_id,
247 bool on_demand_update) {
234 // Use a zero version to ensure that a pending extension will always 248 // Use a zero version to ensure that a pending extension will always
235 // be updated, and thus installed (assuming all extensions have 249 // be updated, and thus installed (assuming all extensions have
236 // non-zero versions). 250 // non-zero versions).
237 base::Version version("0.0.0.0"); 251 base::Version version("0.0.0.0");
238 DCHECK(version.IsValid()); 252 DCHECK(version.IsValid());
239 ExtraParams extra; 253 ExtraParams extra;
240 if (is_corrupt_reinstall) 254 if (is_corrupt_reinstall)
241 extra.is_corrupt_reinstall = true; 255 extra.is_corrupt_reinstall = true;
242 256
243 return AddExtensionData(id, version, Manifest::TYPE_UNKNOWN, update_url, 257 return AddExtensionData(id, version, Manifest::TYPE_UNKNOWN, update_url,
244 extra, request_id); 258 extra, request_id, on_demand_update);
245 } 259 }
246 260
247 void ExtensionDownloader::StartAllPending(ExtensionCache* cache) { 261 void ExtensionDownloader::StartAllPending(ExtensionCache* cache) {
248 if (cache) { 262 if (cache) {
249 extension_cache_ = cache; 263 extension_cache_ = cache;
250 extension_cache_->Start(base::Bind(&ExtensionDownloader::DoStartAllPending, 264 extension_cache_->Start(base::Bind(&ExtensionDownloader::DoStartAllPending,
251 weak_ptr_factory_.GetWeakPtr())); 265 weak_ptr_factory_.GetWeakPtr()));
252 } else { 266 } else {
253 DoStartAllPending(); 267 DoStartAllPending();
254 } 268 }
(...skipping 14 matching lines...) Expand all
269 } 283 }
270 284
271 void ExtensionDownloader::StartBlacklistUpdate( 285 void ExtensionDownloader::StartBlacklistUpdate(
272 const std::string& version, 286 const std::string& version,
273 const ManifestFetchData::PingData& ping_data, 287 const ManifestFetchData::PingData& ping_data,
274 int request_id) { 288 int request_id) {
275 // Note: it is very important that we use the https version of the update 289 // Note: it is very important that we use the https version of the update
276 // url here to avoid DNS hijacking of the blacklist, which is not validated 290 // url here to avoid DNS hijacking of the blacklist, which is not validated
277 // by a public key signature like .crx files are. 291 // by a public key signature like .crx files are.
278 std::unique_ptr<ManifestFetchData> blacklist_fetch(CreateManifestFetchData( 292 std::unique_ptr<ManifestFetchData> blacklist_fetch(CreateManifestFetchData(
279 extension_urls::GetWebstoreUpdateUrl(), request_id)); 293 extension_urls::GetWebstoreUpdateUrl(), request_id, false));
280 DCHECK(blacklist_fetch->base_url().SchemeIsCryptographic()); 294 DCHECK(blacklist_fetch->base_url().SchemeIsCryptographic());
281 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, 295 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data,
282 std::string(), kDefaultInstallSource); 296 std::string(), kDefaultInstallSource, false);
283 StartUpdateCheck(std::move(blacklist_fetch)); 297 StartUpdateCheck(std::move(blacklist_fetch));
284 } 298 }
285 299
286 void ExtensionDownloader::SetWebstoreIdentityProvider( 300 void ExtensionDownloader::SetWebstoreIdentityProvider(
287 std::unique_ptr<IdentityProvider> identity_provider) { 301 std::unique_ptr<IdentityProvider> identity_provider) {
288 identity_provider_.swap(identity_provider); 302 identity_provider_.swap(identity_provider);
289 } 303 }
290 304
291 // static 305 // static
292 void ExtensionDownloader::set_test_delegate( 306 void ExtensionDownloader::set_test_delegate(
293 ExtensionDownloaderTestDelegate* delegate) { 307 ExtensionDownloaderTestDelegate* delegate) {
294 g_test_delegate = delegate; 308 g_test_delegate = delegate;
295 } 309 }
296 310
297 bool ExtensionDownloader::AddExtensionData(const std::string& id, 311 bool ExtensionDownloader::AddExtensionData(const std::string& id,
298 const base::Version& version, 312 const base::Version& version,
299 Manifest::Type extension_type, 313 Manifest::Type extension_type,
300 const GURL& extension_update_url, 314 const GURL& extension_update_url,
301 const ExtraParams& extra, 315 const ExtraParams& extra,
302 int request_id) { 316 int request_id,
317 bool on_demand_update) {
303 GURL update_url(extension_update_url); 318 GURL update_url(extension_update_url);
304 // Skip extensions with non-empty invalid update URLs. 319 // Skip extensions with non-empty invalid update URLs.
305 if (!update_url.is_empty() && !update_url.is_valid()) { 320 if (!update_url.is_empty() && !update_url.is_valid()) {
306 DLOG(WARNING) << "Extension " << id << " has invalid update url " 321 DLOG(WARNING) << "Extension " << id << " has invalid update url "
307 << update_url; 322 << update_url;
308 return false; 323 return false;
309 } 324 }
310 325
311 // Make sure we use SSL for store-hosted extensions. 326 // Make sure we use SSL for store-hosted extensions.
312 if (extension_urls::IsWebstoreUpdateUrl(update_url) && 327 if (extension_urls::IsWebstoreUpdateUrl(update_url) &&
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
367 // Find or create a ManifestFetchData to add this extension to. 382 // Find or create a ManifestFetchData to add this extension to.
368 bool added = false; 383 bool added = false;
369 FetchMap::iterator existing_iter = 384 FetchMap::iterator existing_iter =
370 fetches_preparing_.find(std::make_pair(request_id, update_url)); 385 fetches_preparing_.find(std::make_pair(request_id, update_url));
371 if (existing_iter != fetches_preparing_.end() && 386 if (existing_iter != fetches_preparing_.end() &&
372 !existing_iter->second.empty()) { 387 !existing_iter->second.empty()) {
373 // Try to add to the ManifestFetchData at the end of the list. 388 // Try to add to the ManifestFetchData at the end of the list.
374 ManifestFetchData* existing_fetch = existing_iter->second.back().get(); 389 ManifestFetchData* existing_fetch = existing_iter->second.back().get();
375 if (existing_fetch->AddExtension(id, version.GetString(), 390 if (existing_fetch->AddExtension(id, version.GetString(),
376 optional_ping_data, extra.update_url_data, 391 optional_ping_data, extra.update_url_data,
377 install_source)) { 392 install_source, on_demand_update)) {
378 added = true; 393 added = true;
379 } 394 }
380 } 395 }
381 if (!added) { 396 if (!added) {
382 // Otherwise add a new element to the list, if the list doesn't exist or 397 // Otherwise add a new element to the list, if the list doesn't exist or
383 // if its last element is already full. 398 // if its last element is already full.
384 std::unique_ptr<ManifestFetchData> fetch( 399 std::unique_ptr<ManifestFetchData> fetch(
385 CreateManifestFetchData(update_url, request_id)); 400 CreateManifestFetchData(update_url, request_id, on_demand_update));
386 ManifestFetchData* fetch_ptr = fetch.get(); 401 ManifestFetchData* fetch_ptr = fetch.get();
387 fetches_preparing_[std::make_pair(request_id, update_url)].push_back( 402 fetches_preparing_[std::make_pair(request_id, update_url)].push_back(
388 std::move(fetch)); 403 std::move(fetch));
389 added = fetch_ptr->AddExtension(id, version.GetString(), optional_ping_data, 404 added = fetch_ptr->AddExtension(id, version.GetString(), optional_ping_data,
390 extra.update_url_data, install_source); 405 extra.update_url_data, install_source,
406 on_demand_update);
391 DCHECK(added); 407 DCHECK(added);
392 } 408 }
393 409
394 return true; 410 return true;
395 } 411 }
396 412
397 void ExtensionDownloader::ReportStats() const { 413 void ExtensionDownloader::ReportStats() const {
398 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension", 414 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension",
399 url_stats_.extension_count); 415 url_stats_.extension_count);
400 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme", 416 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme",
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 } else { 459 } else {
444 UMA_HISTOGRAM_COUNTS( 460 UMA_HISTOGRAM_COUNTS(
445 "Extensions.UpdateCheckUrlLength", 461 "Extensions.UpdateCheckUrlLength",
446 fetch_data->full_url().possibly_invalid_spec().length()); 462 fetch_data->full_url().possibly_invalid_spec().length());
447 463
448 manifests_queue_.ScheduleRequest(std::move(fetch_data)); 464 manifests_queue_.ScheduleRequest(std::move(fetch_data));
449 } 465 }
450 } 466 }
451 467
452 void ExtensionDownloader::CreateManifestFetcher() { 468 void ExtensionDownloader::CreateManifestFetcher() {
469 const ManifestFetchData* active_request = manifests_queue_.active_request();
470 std::vector<std::string> id_vector(active_request->extension_ids().begin(),
471 active_request->extension_ids().end());
472 std::string id_list = base::JoinString(id_vector, ",");
453 if (VLOG_IS_ON(2)) { 473 if (VLOG_IS_ON(2)) {
454 std::vector<std::string> id_vector( 474 VLOG(2) << "Fetching " << active_request->full_url() << " for " << id_list;
455 manifests_queue_.active_request()->extension_ids().begin(), 475 VLOG(2) << "Update interactivity: "
456 manifests_queue_.active_request()->extension_ids().end()); 476 << (active_request->on_demand_update() ? "fg" : "bg");
457 std::string id_list = base::JoinString(id_vector, ",");
458 VLOG(2) << "Fetching " << manifests_queue_.active_request()->full_url()
459 << " for " << id_list;
460 } 477 }
461 478
462 manifest_fetcher_ = net::URLFetcher::Create( 479 manifest_fetcher_ =
463 kManifestFetcherId, manifests_queue_.active_request()->full_url(), 480 net::URLFetcher::Create(kManifestFetcherId, active_request->full_url(),
464 net::URLFetcher::GET, this); 481 net::URLFetcher::GET, this);
465 manifest_fetcher_->SetRequestContext(request_context_.get()); 482 manifest_fetcher_->SetRequestContext(request_context_.get());
466 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 483 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
467 net::LOAD_DO_NOT_SAVE_COOKIES | 484 net::LOAD_DO_NOT_SAVE_COOKIES |
468 net::LOAD_DISABLE_CACHE); 485 net::LOAD_DISABLE_CACHE);
486
487 // Send traffic-management headers. http://crosbug.com/130602
488 manifest_fetcher_->AddExtraRequestHeader(base::StringPrintf(
489 "%s: %s", kUpdateInteractivityHeader,
490 active_request->on_demand_update() ? kUpdateInteractivityForeground
491 : kUpdateInteractivityBackground));
492 manifest_fetcher_->AddExtraRequestHeader(
493 base::StringPrintf("%s: %s", kUpdateAppIdHeader, id_list.c_str()));
494 manifest_fetcher_->AddExtraRequestHeader(base::StringPrintf(
495 "%s: %s-%s", kUpdateUpdaterHeader,
496 UpdateQueryParams::GetProdIdString(UpdateQueryParams::CRX),
497 UpdateQueryParams::GetProdVersion().c_str()));
498
469 // Update checks can be interrupted if a network change is detected; this is 499 // Update checks can be interrupted if a network change is detected; this is
470 // common for the retail mode AppPack on ChromeOS. Retrying once should be 500 // common for the retail mode AppPack on ChromeOS. Retrying once should be
471 // enough to recover in those cases; let the fetcher retry up to 3 times 501 // enough to recover in those cases; let the fetcher retry up to 3 times
472 // just in case. http://crosbug.com/130602 502 // just in case. http://crosbug.com/130602
473 manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); 503 manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3);
474 manifest_fetcher_->Start(); 504 manifest_fetcher_->Start();
475 } 505 }
476 506
477 void ExtensionDownloader::OnURLFetchComplete(const net::URLFetcher* source) { 507 void ExtensionDownloader::OnURLFetchComplete(const net::URLFetcher* source) {
478 VLOG(2) << source->GetResponseCode() << " " << source->GetURL(); 508 VLOG(2) << source->GetResponseCode() << " " << source->GetURL();
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
943 void ExtensionDownloader::OnGetTokenFailure( 973 void ExtensionDownloader::OnGetTokenFailure(
944 const OAuth2TokenService::Request* request, 974 const OAuth2TokenService::Request* request,
945 const GoogleServiceAuthError& error) { 975 const GoogleServiceAuthError& error) {
946 // If we fail to get an access token, kick the pending fetch and let it fall 976 // If we fail to get an access token, kick the pending fetch and let it fall
947 // back on cookies. 977 // back on cookies.
948 extension_fetcher_->Start(); 978 extension_fetcher_->Start();
949 } 979 }
950 980
951 ManifestFetchData* ExtensionDownloader::CreateManifestFetchData( 981 ManifestFetchData* ExtensionDownloader::CreateManifestFetchData(
952 const GURL& update_url, 982 const GURL& update_url,
953 int request_id) { 983 int request_id,
984 bool on_demand_update) {
954 ManifestFetchData::PingMode ping_mode = ManifestFetchData::NO_PING; 985 ManifestFetchData::PingMode ping_mode = ManifestFetchData::NO_PING;
955 if (update_url.DomainIs(ping_enabled_domain_.c_str())) 986 if (update_url.DomainIs(ping_enabled_domain_.c_str()))
956 ping_mode = ManifestFetchData::PING_WITH_ENABLED_STATE; 987 ping_mode = ManifestFetchData::PING_WITH_ENABLED_STATE;
957 return new ManifestFetchData( 988 return new ManifestFetchData(update_url, request_id, brand_code_,
958 update_url, request_id, brand_code_, manifest_query_params_, ping_mode); 989 manifest_query_params_, ping_mode,
990 on_demand_update);
959 } 991 }
960 992
961 } // namespace extensions 993 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698