| 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 "extensions/browser/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/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 15 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 44 using base::TimeDelta; | 44 using base::TimeDelta; |
| 45 using content::BrowserThread; | 45 using content::BrowserThread; |
| 46 | 46 |
| 47 namespace extensions { | 47 namespace extensions { |
| 48 | 48 |
| 49 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist"; | 49 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist"; |
| 50 | 50 |
| 51 namespace { | 51 namespace { |
| 52 | 52 |
| 53 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { | 53 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { |
| 54 // Number of initial errors (in sequence) to ignore before applying | 54 // Number of initial errors (in sequence) to ignore before applying |
| 55 // exponential back-off rules. | 55 // exponential back-off rules. |
| 56 0, | 56 0, |
| 57 | 57 |
| 58 // Initial delay for exponential back-off in ms. | 58 // Initial delay for exponential back-off in ms. |
| 59 2000, | 59 2000, |
| 60 | 60 |
| 61 // Factor by which the waiting time will be multiplied. | 61 // Factor by which the waiting time will be multiplied. |
| 62 2, | 62 2, |
| 63 | 63 |
| 64 // Fuzzing percentage. ex: 10% will spread requests randomly | 64 // Fuzzing percentage. ex: 10% will spread requests randomly |
| 65 // between 90%-100% of the calculated time. | 65 // between 90%-100% of the calculated time. |
| 66 0.1, | 66 0.1, |
| 67 | 67 |
| 68 // Maximum amount of time we are willing to delay our request in ms. | 68 // Maximum amount of time we are willing to delay our request in ms. |
| 69 -1, | 69 -1, |
| 70 | 70 |
| 71 // Time to keep an entry from being discarded even when it | 71 // Time to keep an entry from being discarded even when it |
| 72 // has no significant state, -1 to never discard. | 72 // has no significant state, -1 to never discard. |
| 73 -1, | 73 -1, |
| 74 | 74 |
| 75 // 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. |
| 76 false, | 76 false, |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 const char kAuthUserQueryKey[] = "authuser"; | 79 const char kAuthUserQueryKey[] = "authuser"; |
| 80 | 80 |
| 81 const int kMaxAuthUserValue = 10; | 81 const int kMaxAuthUserValue = 10; |
| 82 const int kMaxOAuth2Attempts = 3; | 82 const int kMaxOAuth2Attempts = 3; |
| 83 | 83 |
| 84 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; | 84 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; |
| 85 const char kDefaultInstallSource[] = ""; | 85 const char kDefaultInstallSource[] = ""; |
| 86 | 86 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 url::Component new_query(0, new_query_string.size()); | 141 url::Component new_query(0, new_query_string.size()); |
| 142 url::Replacements<char> replacements; | 142 url::Replacements<char> replacements; |
| 143 replacements.SetQuery(new_query_string.c_str(), new_query); | 143 replacements.SetQuery(new_query_string.c_str(), new_query); |
| 144 *url = url->ReplaceComponents(replacements); | 144 *url = url->ReplaceComponents(replacements); |
| 145 return true; | 145 return true; |
| 146 } | 146 } |
| 147 | 147 |
| 148 } // namespace | 148 } // namespace |
| 149 | 149 |
| 150 UpdateDetails::UpdateDetails(const std::string& id, const Version& version) | 150 UpdateDetails::UpdateDetails(const std::string& id, const Version& version) |
| 151 : id(id), version(version) {} | 151 : id(id), version(version) { |
| 152 } |
| 152 | 153 |
| 153 UpdateDetails::~UpdateDetails() {} | 154 UpdateDetails::~UpdateDetails() { |
| 155 } |
| 154 | 156 |
| 155 ExtensionDownloader::ExtensionFetch::ExtensionFetch() | 157 ExtensionDownloader::ExtensionFetch::ExtensionFetch() |
| 156 : url(), credentials(CREDENTIALS_NONE) { | 158 : url(), credentials(CREDENTIALS_NONE) { |
| 157 } | 159 } |
| 158 | 160 |
| 159 ExtensionDownloader::ExtensionFetch::ExtensionFetch( | 161 ExtensionDownloader::ExtensionFetch::ExtensionFetch( |
| 160 const std::string& id, | 162 const std::string& id, |
| 161 const GURL& url, | 163 const GURL& url, |
| 162 const std::string& package_hash, | 164 const std::string& package_hash, |
| 163 const std::string& version, | 165 const std::string& version, |
| 164 const std::set<int>& request_ids) | 166 const std::set<int>& request_ids) |
| 165 : id(id), | 167 : id(id), |
| 166 url(url), | 168 url(url), |
| 167 package_hash(package_hash), | 169 package_hash(package_hash), |
| 168 version(version), | 170 version(version), |
| 169 request_ids(request_ids), | 171 request_ids(request_ids), |
| 170 credentials(CREDENTIALS_NONE), | 172 credentials(CREDENTIALS_NONE), |
| 171 oauth2_attempt_count(0) { | 173 oauth2_attempt_count(0) { |
| 172 } | 174 } |
| 173 | 175 |
| 174 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} | 176 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() { |
| 177 } |
| 175 | 178 |
| 176 ExtensionDownloader::ExtensionDownloader( | 179 ExtensionDownloader::ExtensionDownloader( |
| 177 ExtensionDownloaderDelegate* delegate, | 180 ExtensionDownloaderDelegate* delegate, |
| 178 net::URLRequestContextGetter* request_context) | 181 net::URLRequestContextGetter* request_context) |
| 179 : OAuth2TokenService::Consumer(kTokenServiceConsumerId), | 182 : OAuth2TokenService::Consumer(kTokenServiceConsumerId), |
| 180 delegate_(delegate), | 183 delegate_(delegate), |
| 181 request_context_(request_context), | 184 request_context_(request_context), |
| 182 manifests_queue_(&kDefaultBackoffPolicy, | 185 manifests_queue_(&kDefaultBackoffPolicy, |
| 183 base::Bind(&ExtensionDownloader::CreateManifestFetcher, | 186 base::Bind(&ExtensionDownloader::CreateManifestFetcher, |
| 184 base::Unretained(this))), | 187 base::Unretained(this))), |
| 185 extensions_queue_(&kDefaultBackoffPolicy, | 188 extensions_queue_(&kDefaultBackoffPolicy, |
| 186 base::Bind(&ExtensionDownloader::CreateExtensionFetcher, | 189 base::Bind(&ExtensionDownloader::CreateExtensionFetcher, |
| 187 base::Unretained(this))), | 190 base::Unretained(this))), |
| 188 extension_cache_(NULL), | 191 extension_cache_(NULL), |
| 189 enable_extra_update_metrics_(false), | 192 enable_extra_update_metrics_(false), |
| 190 weak_ptr_factory_(this) { | 193 weak_ptr_factory_(this) { |
| 191 DCHECK(delegate_); | 194 DCHECK(delegate_); |
| 192 DCHECK(request_context_.get()); | 195 DCHECK(request_context_.get()); |
| 193 } | 196 } |
| 194 | 197 |
| 195 ExtensionDownloader::~ExtensionDownloader() {} | 198 ExtensionDownloader::~ExtensionDownloader() { |
| 199 } |
| 196 | 200 |
| 197 bool ExtensionDownloader::AddExtension(const Extension& extension, | 201 bool ExtensionDownloader::AddExtension(const Extension& extension, |
| 198 int request_id) { | 202 int request_id) { |
| 199 // Skip extensions with empty update URLs converted from user | 203 // Skip extensions with empty update URLs converted from user |
| 200 // scripts. | 204 // scripts. |
| 201 if (extension.converted_from_user_script() && | 205 if (extension.converted_from_user_script() && |
| 202 ManifestURL::GetUpdateURL(&extension).is_empty()) { | 206 ManifestURL::GetUpdateURL(&extension).is_empty()) { |
| 203 return false; | 207 return false; |
| 204 } | 208 } |
| 205 | 209 |
| 206 // If the extension updates itself from the gallery, ignore any update URL | 210 // If the extension updates itself from the gallery, ignore any update URL |
| 207 // data. At the moment there is no extra data that an extension can | 211 // data. At the moment there is no extra data that an extension can |
| 208 // communicate to the the gallery update servers. | 212 // communicate to the the gallery update servers. |
| 209 std::string update_url_data; | 213 std::string update_url_data; |
| 210 if (!ManifestURL::UpdatesFromGallery(&extension)) | 214 if (!ManifestURL::UpdatesFromGallery(&extension)) |
| 211 update_url_data = delegate_->GetUpdateUrlData(extension.id()); | 215 update_url_data = delegate_->GetUpdateUrlData(extension.id()); |
| 212 | 216 |
| 213 std::string install_source; | 217 std::string install_source; |
| 214 bool force_update = delegate_->ShouldForceUpdate(extension.id(), | 218 bool force_update = |
| 215 &install_source); | 219 delegate_->ShouldForceUpdate(extension.id(), &install_source); |
| 216 return AddExtensionData(extension.id(), | 220 return AddExtensionData(extension.id(), |
| 217 *extension.version(), | 221 *extension.version(), |
| 218 extension.GetType(), | 222 extension.GetType(), |
| 219 ManifestURL::GetUpdateURL(&extension), | 223 ManifestURL::GetUpdateURL(&extension), |
| 220 update_url_data, | 224 update_url_data, |
| 221 request_id, | 225 request_id, |
| 222 force_update, | 226 force_update, |
| 223 install_source); | 227 install_source); |
| 224 } | 228 } |
| 225 | 229 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 238 update_url, | 242 update_url, |
| 239 std::string(), | 243 std::string(), |
| 240 request_id, | 244 request_id, |
| 241 false, | 245 false, |
| 242 std::string()); | 246 std::string()); |
| 243 } | 247 } |
| 244 | 248 |
| 245 void ExtensionDownloader::StartAllPending(ExtensionCache* cache) { | 249 void ExtensionDownloader::StartAllPending(ExtensionCache* cache) { |
| 246 if (cache) { | 250 if (cache) { |
| 247 extension_cache_ = cache; | 251 extension_cache_ = cache; |
| 248 extension_cache_->Start(base::Bind( | 252 extension_cache_->Start(base::Bind(&ExtensionDownloader::DoStartAllPending, |
| 249 &ExtensionDownloader::DoStartAllPending, | 253 weak_ptr_factory_.GetWeakPtr())); |
| 250 weak_ptr_factory_.GetWeakPtr())); | |
| 251 } else { | 254 } else { |
| 252 DoStartAllPending(); | 255 DoStartAllPending(); |
| 253 } | 256 } |
| 254 } | 257 } |
| 255 | 258 |
| 256 void ExtensionDownloader::DoStartAllPending() { | 259 void ExtensionDownloader::DoStartAllPending() { |
| 257 ReportStats(); | 260 ReportStats(); |
| 258 url_stats_ = URLStats(); | 261 url_stats_ = URLStats(); |
| 259 | 262 |
| 260 for (FetchMap::iterator it = fetches_preparing_.begin(); | 263 for (FetchMap::iterator it = fetches_preparing_.begin(); |
| 261 it != fetches_preparing_.end(); ++it) { | 264 it != fetches_preparing_.end(); |
| 262 std::vector<linked_ptr<ManifestFetchData> >& list = it->second; | 265 ++it) { |
| 266 std::vector<linked_ptr<ManifestFetchData>>& list = it->second; |
| 263 for (size_t i = 0; i < list.size(); ++i) { | 267 for (size_t i = 0; i < list.size(); ++i) { |
| 264 StartUpdateCheck(scoped_ptr<ManifestFetchData>(list[i].release())); | 268 StartUpdateCheck(scoped_ptr<ManifestFetchData>(list[i].release())); |
| 265 } | 269 } |
| 266 } | 270 } |
| 267 fetches_preparing_.clear(); | 271 fetches_preparing_.clear(); |
| 268 } | 272 } |
| 269 | 273 |
| 270 void ExtensionDownloader::StartBlacklistUpdate( | 274 void ExtensionDownloader::StartBlacklistUpdate( |
| 271 const std::string& version, | 275 const std::string& version, |
| 272 const ManifestFetchData::PingData& ping_data, | 276 const ManifestFetchData::PingData& ping_data, |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 // webstore update URL. | 360 // webstore update URL. |
| 357 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && | 361 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && |
| 358 enable_extra_update_metrics_) { | 362 enable_extra_update_metrics_) { |
| 359 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); | 363 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); |
| 360 } | 364 } |
| 361 | 365 |
| 362 for (size_t i = 0; i < update_urls.size(); ++i) { | 366 for (size_t i = 0; i < update_urls.size(); ++i) { |
| 363 DCHECK(!update_urls[i].is_empty()); | 367 DCHECK(!update_urls[i].is_empty()); |
| 364 DCHECK(update_urls[i].is_valid()); | 368 DCHECK(update_urls[i].is_valid()); |
| 365 | 369 |
| 366 std::string install_source = i == 0 ? | 370 std::string install_source = |
| 367 kDefaultInstallSource : kNotFromWebstoreInstallSource; | 371 i == 0 ? kDefaultInstallSource : kNotFromWebstoreInstallSource; |
| 368 if (!install_source_override.empty()) { | 372 if (!install_source_override.empty()) { |
| 369 install_source = install_source_override; | 373 install_source = install_source_override; |
| 370 } | 374 } |
| 371 | 375 |
| 372 ManifestFetchData::PingData ping_data; | 376 ManifestFetchData::PingData ping_data; |
| 373 ManifestFetchData::PingData* optional_ping_data = NULL; | 377 ManifestFetchData::PingData* optional_ping_data = NULL; |
| 374 if (delegate_->GetPingDataForExtension(id, &ping_data)) | 378 if (delegate_->GetPingDataForExtension(id, &ping_data)) |
| 375 optional_ping_data = &ping_data; | 379 optional_ping_data = &ping_data; |
| 376 | 380 |
| 377 // Find or create a ManifestFetchData to add this extension to. | 381 // Find or create a ManifestFetchData to add this extension to. |
| 378 bool added = false; | 382 bool added = false; |
| 379 FetchMap::iterator existing_iter = fetches_preparing_.find( | 383 FetchMap::iterator existing_iter = |
| 380 std::make_pair(request_id, update_urls[i])); | 384 fetches_preparing_.find(std::make_pair(request_id, update_urls[i])); |
| 381 if (existing_iter != fetches_preparing_.end() && | 385 if (existing_iter != fetches_preparing_.end() && |
| 382 !existing_iter->second.empty()) { | 386 !existing_iter->second.empty()) { |
| 383 // Try to add to the ManifestFetchData at the end of the list. | 387 // Try to add to the ManifestFetchData at the end of the list. |
| 384 ManifestFetchData* existing_fetch = existing_iter->second.back().get(); | 388 ManifestFetchData* existing_fetch = existing_iter->second.back().get(); |
| 385 if (existing_fetch->AddExtension(id, version.GetString(), | 389 if (existing_fetch->AddExtension(id, |
| 386 optional_ping_data, update_url_data, | 390 version.GetString(), |
| 391 optional_ping_data, |
| 392 update_url_data, |
| 387 install_source, | 393 install_source, |
| 388 force_update)) { | 394 force_update)) { |
| 389 added = true; | 395 added = true; |
| 390 } | 396 } |
| 391 } | 397 } |
| 392 if (!added) { | 398 if (!added) { |
| 393 // Otherwise add a new element to the list, if the list doesn't exist or | 399 // Otherwise add a new element to the list, if the list doesn't exist or |
| 394 // if its last element is already full. | 400 // if its last element is already full. |
| 395 linked_ptr<ManifestFetchData> fetch( | 401 linked_ptr<ManifestFetchData> fetch( |
| 396 CreateManifestFetchData(update_urls[i], request_id)); | 402 CreateManifestFetchData(update_urls[i], request_id)); |
| 397 fetches_preparing_[std::make_pair(request_id, update_urls[i])]. | 403 fetches_preparing_[std::make_pair(request_id, update_urls[i])].push_back( |
| 398 push_back(fetch); | 404 fetch); |
| 399 added = fetch->AddExtension(id, version.GetString(), | 405 added = fetch->AddExtension(id, |
| 406 version.GetString(), |
| 400 optional_ping_data, | 407 optional_ping_data, |
| 401 update_url_data, | 408 update_url_data, |
| 402 install_source, | 409 install_source, |
| 403 force_update); | 410 force_update); |
| 404 DCHECK(added); | 411 DCHECK(added); |
| 405 } | 412 } |
| 406 } | 413 } |
| 407 | 414 |
| 408 return true; | 415 return true; |
| 409 } | 416 } |
| 410 | 417 |
| 411 void ExtensionDownloader::ReportStats() const { | 418 void ExtensionDownloader::ReportStats() const { |
| 412 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension", | 419 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension", |
| 413 url_stats_.extension_count); | 420 url_stats_.extension_count); |
| 414 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme", | 421 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme", |
| 415 url_stats_.theme_count); | 422 url_stats_.theme_count); |
| 416 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckApp", | 423 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckApp", url_stats_.app_count); |
| 417 url_stats_.app_count); | |
| 418 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckPackagedApp", | 424 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckPackagedApp", |
| 419 url_stats_.platform_app_count); | 425 url_stats_.platform_app_count); |
| 420 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckPending", | 426 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckPending", |
| 421 url_stats_.pending_count); | 427 url_stats_.pending_count); |
| 422 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl", | 428 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl", |
| 423 url_stats_.google_url_count); | 429 url_stats_.google_url_count); |
| 424 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl", | 430 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl", |
| 425 url_stats_.other_url_count); | 431 url_stats_.other_url_count); |
| 426 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl", | 432 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl", |
| 427 url_stats_.no_url_count); | 433 url_stats_.no_url_count); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 443 // This url is already scheduled to be fetched. | 449 // This url is already scheduled to be fetched. |
| 444 i->Merge(*fetch_data); | 450 i->Merge(*fetch_data); |
| 445 return; | 451 return; |
| 446 } | 452 } |
| 447 } | 453 } |
| 448 | 454 |
| 449 if (manifests_queue_.active_request() && | 455 if (manifests_queue_.active_request() && |
| 450 manifests_queue_.active_request()->full_url() == fetch_data->full_url()) { | 456 manifests_queue_.active_request()->full_url() == fetch_data->full_url()) { |
| 451 manifests_queue_.active_request()->Merge(*fetch_data); | 457 manifests_queue_.active_request()->Merge(*fetch_data); |
| 452 } else { | 458 } else { |
| 453 UMA_HISTOGRAM_COUNTS("Extensions.UpdateCheckUrlLength", | 459 UMA_HISTOGRAM_COUNTS( |
| 460 "Extensions.UpdateCheckUrlLength", |
| 454 fetch_data->full_url().possibly_invalid_spec().length()); | 461 fetch_data->full_url().possibly_invalid_spec().length()); |
| 455 | 462 |
| 456 manifests_queue_.ScheduleRequest(fetch_data.Pass()); | 463 manifests_queue_.ScheduleRequest(fetch_data.Pass()); |
| 457 } | 464 } |
| 458 } | 465 } |
| 459 | 466 |
| 460 void ExtensionDownloader::CreateManifestFetcher() { | 467 void ExtensionDownloader::CreateManifestFetcher() { |
| 461 if (VLOG_IS_ON(2)) { | 468 if (VLOG_IS_ON(2)) { |
| 462 std::vector<std::string> id_vector( | 469 std::vector<std::string> id_vector( |
| 463 manifests_queue_.active_request()->extension_ids().begin(), | 470 manifests_queue_.active_request()->extension_ids().begin(), |
| 464 manifests_queue_.active_request()->extension_ids().end()); | 471 manifests_queue_.active_request()->extension_ids().end()); |
| 465 std::string id_list = JoinString(id_vector, ','); | 472 std::string id_list = JoinString(id_vector, ','); |
| 466 VLOG(2) << "Fetching " << manifests_queue_.active_request()->full_url() | 473 VLOG(2) << "Fetching " << manifests_queue_.active_request()->full_url() |
| 467 << " for " << id_list; | 474 << " for " << id_list; |
| 468 } | 475 } |
| 469 | 476 |
| 470 manifest_fetcher_.reset(net::URLFetcher::Create( | 477 manifest_fetcher_.reset( |
| 471 kManifestFetcherId, manifests_queue_.active_request()->full_url(), | 478 net::URLFetcher::Create(kManifestFetcherId, |
| 472 net::URLFetcher::GET, this)); | 479 manifests_queue_.active_request()->full_url(), |
| 480 net::URLFetcher::GET, |
| 481 this)); |
| 473 manifest_fetcher_->SetRequestContext(request_context_.get()); | 482 manifest_fetcher_->SetRequestContext(request_context_.get()); |
| 474 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 483 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 475 net::LOAD_DO_NOT_SAVE_COOKIES | | 484 net::LOAD_DO_NOT_SAVE_COOKIES | |
| 476 net::LOAD_DISABLE_CACHE); | 485 net::LOAD_DISABLE_CACHE); |
| 477 // Update checks can be interrupted if a network change is detected; this is | 486 // Update checks can be interrupted if a network change is detected; this is |
| 478 // common for the retail mode AppPack on ChromeOS. Retrying once should be | 487 // common for the retail mode AppPack on ChromeOS. Retrying once should be |
| 479 // enough to recover in those cases; let the fetcher retry up to 3 times | 488 // enough to recover in those cases; let the fetcher retry up to 3 times |
| 480 // just in case. http://crosbug.com/130602 | 489 // just in case. http://crosbug.com/130602 |
| 481 manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 490 manifest_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
| 482 manifest_fetcher_->Start(); | 491 manifest_fetcher_->Start(); |
| 483 } | 492 } |
| 484 | 493 |
| 485 void ExtensionDownloader::OnURLFetchComplete( | 494 void ExtensionDownloader::OnURLFetchComplete(const net::URLFetcher* source) { |
| 486 const net::URLFetcher* source) { | |
| 487 // TODO(vadimt): Remove ScopedProfile below once crbug.com/422577 is fixed. | 495 // TODO(vadimt): Remove ScopedProfile below once crbug.com/422577 is fixed. |
| 488 tracked_objects::ScopedProfile tracking_profile( | 496 tracked_objects::ScopedProfile tracking_profile( |
| 489 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 497 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 490 "422577 ExtensionDownloader::OnURLFetchComplete")); | 498 "422577 ExtensionDownloader::OnURLFetchComplete")); |
| 491 | 499 |
| 492 VLOG(2) << source->GetResponseCode() << " " << source->GetURL(); | 500 VLOG(2) << source->GetResponseCode() << " " << source->GetURL(); |
| 493 | 501 |
| 494 if (source == manifest_fetcher_.get()) { | 502 if (source == manifest_fetcher_.get()) { |
| 495 std::string data; | 503 std::string data; |
| 496 source->GetResponseAsString(&data); | 504 source->GetResponseAsString(&data); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 514 const GURL& url, | 522 const GURL& url, |
| 515 const net::URLRequestStatus& status, | 523 const net::URLRequestStatus& status, |
| 516 int response_code, | 524 int response_code, |
| 517 const base::TimeDelta& backoff_delay, | 525 const base::TimeDelta& backoff_delay, |
| 518 const std::string& data) { | 526 const std::string& data) { |
| 519 // We want to try parsing the manifest, and if it indicates updates are | 527 // We want to try parsing the manifest, and if it indicates updates are |
| 520 // available, we want to fire off requests to fetch those updates. | 528 // available, we want to fire off requests to fetch those updates. |
| 521 if (status.status() == net::URLRequestStatus::SUCCESS && | 529 if (status.status() == net::URLRequestStatus::SUCCESS && |
| 522 (response_code == 200 || (url.SchemeIsFile() && data.length() > 0))) { | 530 (response_code == 200 || (url.SchemeIsFile() && data.length() > 0))) { |
| 523 RETRY_HISTOGRAM("ManifestFetchSuccess", | 531 RETRY_HISTOGRAM("ManifestFetchSuccess", |
| 524 manifests_queue_.active_request_failure_count(), url); | 532 manifests_queue_.active_request_failure_count(), |
| 533 url); |
| 525 VLOG(2) << "beginning manifest parse for " << url; | 534 VLOG(2) << "beginning manifest parse for " << url; |
| 526 scoped_refptr<SafeManifestParser> safe_parser( | 535 scoped_refptr<SafeManifestParser> safe_parser(new SafeManifestParser( |
| 527 new SafeManifestParser( | 536 data, |
| 528 data, | 537 manifests_queue_.reset_active_request().release(), |
| 529 manifests_queue_.reset_active_request().release(), | 538 base::Bind(&ExtensionDownloader::HandleManifestResults, |
| 530 base::Bind(&ExtensionDownloader::HandleManifestResults, | 539 weak_ptr_factory_.GetWeakPtr()))); |
| 531 weak_ptr_factory_.GetWeakPtr()))); | |
| 532 safe_parser->Start(); | 540 safe_parser->Start(); |
| 533 } else { | 541 } else { |
| 534 VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec() | 542 VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec() |
| 535 << "' response code:" << response_code; | 543 << "' response code:" << response_code; |
| 536 if (ShouldRetryRequest(status, response_code) && | 544 if (ShouldRetryRequest(status, response_code) && |
| 537 manifests_queue_.active_request_failure_count() < kMaxRetries) { | 545 manifests_queue_.active_request_failure_count() < kMaxRetries) { |
| 538 manifests_queue_.RetryRequest(backoff_delay); | 546 manifests_queue_.RetryRequest(backoff_delay); |
| 539 } else { | 547 } else { |
| 540 RETRY_HISTOGRAM("ManifestFetchFailure", | 548 RETRY_HISTOGRAM("ManifestFetchFailure", |
| 541 manifests_queue_.active_request_failure_count(), url); | 549 manifests_queue_.active_request_failure_count(), |
| 550 url); |
| 542 NotifyExtensionsDownloadFailed( | 551 NotifyExtensionsDownloadFailed( |
| 543 manifests_queue_.active_request()->extension_ids(), | 552 manifests_queue_.active_request()->extension_ids(), |
| 544 manifests_queue_.active_request()->request_ids(), | 553 manifests_queue_.active_request()->request_ids(), |
| 545 ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED); | 554 ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED); |
| 546 } | 555 } |
| 547 } | 556 } |
| 548 manifest_fetcher_.reset(); | 557 manifest_fetcher_.reset(); |
| 549 manifests_queue_.reset_active_request(); | 558 manifests_queue_.reset_active_request(); |
| 550 | 559 |
| 551 // If we have any pending manifest requests, fire off the next one. | 560 // If we have any pending manifest requests, fire off the next one. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 586 | 595 |
| 587 // Force https (crbug.com/129587). | 596 // Force https (crbug.com/129587). |
| 588 if (!crx_url.SchemeIsSecure()) { | 597 if (!crx_url.SchemeIsSecure()) { |
| 589 url::Replacements<char> replacements; | 598 url::Replacements<char> replacements; |
| 590 std::string scheme("https"); | 599 std::string scheme("https"); |
| 591 replacements.SetScheme(scheme.c_str(), | 600 replacements.SetScheme(scheme.c_str(), |
| 592 url::Component(0, scheme.size())); | 601 url::Component(0, scheme.size())); |
| 593 crx_url = crx_url.ReplaceComponents(replacements); | 602 crx_url = crx_url.ReplaceComponents(replacements); |
| 594 } | 603 } |
| 595 } | 604 } |
| 596 scoped_ptr<ExtensionFetch> fetch(new ExtensionFetch( | 605 scoped_ptr<ExtensionFetch> fetch( |
| 597 update->extension_id, crx_url, update->package_hash, | 606 new ExtensionFetch(update->extension_id, |
| 598 update->version, fetch_data.request_ids())); | 607 crx_url, |
| 608 update->package_hash, |
| 609 update->version, |
| 610 fetch_data.request_ids())); |
| 599 FetchUpdatedExtension(fetch.Pass()); | 611 FetchUpdatedExtension(fetch.Pass()); |
| 600 } | 612 } |
| 601 | 613 |
| 602 // If the manifest response included a <daystart> element, we want to save | 614 // If the manifest response included a <daystart> element, we want to save |
| 603 // that value for any extensions which had sent a ping in the request. | 615 // that value for any extensions which had sent a ping in the request. |
| 604 if (fetch_data.base_url().DomainIs(kGoogleDotCom) && | 616 if (fetch_data.base_url().DomainIs(kGoogleDotCom) && |
| 605 results->daystart_elapsed_seconds >= 0) { | 617 results->daystart_elapsed_seconds >= 0) { |
| 606 Time day_start = | 618 Time day_start = |
| 607 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); | 619 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); |
| 608 | 620 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 632 | 644 |
| 633 if (!fetch_data.Includes(id)) { | 645 if (!fetch_data.Includes(id)) { |
| 634 VLOG(2) << "Ignoring " << id << " from this manifest"; | 646 VLOG(2) << "Ignoring " << id << " from this manifest"; |
| 635 continue; | 647 continue; |
| 636 } | 648 } |
| 637 | 649 |
| 638 if (VLOG_IS_ON(2)) { | 650 if (VLOG_IS_ON(2)) { |
| 639 if (update->version.empty()) | 651 if (update->version.empty()) |
| 640 VLOG(2) << "manifest indicates " << id << " has no update"; | 652 VLOG(2) << "manifest indicates " << id << " has no update"; |
| 641 else | 653 else |
| 642 VLOG(2) << "manifest indicates " << id | 654 VLOG(2) << "manifest indicates " << id << " latest version is '" |
| 643 << " latest version is '" << update->version << "'"; | 655 << update->version << "'"; |
| 644 } | 656 } |
| 645 | 657 |
| 646 if (!delegate_->IsExtensionPending(id)) { | 658 if (!delegate_->IsExtensionPending(id)) { |
| 647 // If we're not installing pending extension, and the update | 659 // If we're not installing pending extension, and the update |
| 648 // version is the same or older than what's already installed, | 660 // version is the same or older than what's already installed, |
| 649 // we don't want it. | 661 // we don't want it. |
| 650 std::string version; | 662 std::string version; |
| 651 if (!delegate_->GetExtensionExistingVersion(id, &version)) { | 663 if (!delegate_->GetExtensionExistingVersion(id, &version)) { |
| 652 VLOG(2) << id << " is not installed"; | 664 VLOG(2) << id << " is not installed"; |
| 653 continue; | 665 continue; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 675 LOG(WARNING) << "Updated version of extension " << id | 687 LOG(WARNING) << "Updated version of extension " << id |
| 676 << " available, but requires chrome version " | 688 << " available, but requires chrome version " |
| 677 << update->browser_min_version; | 689 << update->browser_min_version; |
| 678 continue; | 690 continue; |
| 679 } | 691 } |
| 680 VLOG(2) << "will try to update " << id; | 692 VLOG(2) << "will try to update " << id; |
| 681 result->push_back(i); | 693 result->push_back(i); |
| 682 } | 694 } |
| 683 } | 695 } |
| 684 | 696 |
| 685 // Begins (or queues up) download of an updated extension. | 697 // Begins (or queues up) download of an updated extension. |
| 686 void ExtensionDownloader::FetchUpdatedExtension( | 698 void ExtensionDownloader::FetchUpdatedExtension( |
| 687 scoped_ptr<ExtensionFetch> fetch_data) { | 699 scoped_ptr<ExtensionFetch> fetch_data) { |
| 688 if (!fetch_data->url.is_valid()) { | 700 if (!fetch_data->url.is_valid()) { |
| 689 // TODO(asargent): This can sometimes be invalid. See crbug.com/130881. | 701 // TODO(asargent): This can sometimes be invalid. See crbug.com/130881. |
| 690 LOG(ERROR) << "Invalid URL: '" << fetch_data->url.possibly_invalid_spec() | 702 LOG(ERROR) << "Invalid URL: '" << fetch_data->url.possibly_invalid_spec() |
| 691 << "' for extension " << fetch_data->id; | 703 << "' for extension " << fetch_data->id; |
| 692 return; | 704 return; |
| 693 } | 705 } |
| 694 | 706 |
| 695 for (RequestQueue<ExtensionFetch>::iterator iter = | 707 for (RequestQueue<ExtensionFetch>::iterator iter = extensions_queue_.begin(); |
| 696 extensions_queue_.begin(); | 708 iter != extensions_queue_.end(); |
| 697 iter != extensions_queue_.end(); ++iter) { | 709 ++iter) { |
| 698 if (iter->id == fetch_data->id || iter->url == fetch_data->url) { | 710 if (iter->id == fetch_data->id || iter->url == fetch_data->url) { |
| 699 iter->request_ids.insert(fetch_data->request_ids.begin(), | 711 iter->request_ids.insert(fetch_data->request_ids.begin(), |
| 700 fetch_data->request_ids.end()); | 712 fetch_data->request_ids.end()); |
| 701 return; // already scheduled | 713 return; // already scheduled |
| 702 } | 714 } |
| 703 } | 715 } |
| 704 | 716 |
| 705 if (extensions_queue_.active_request() && | 717 if (extensions_queue_.active_request() && |
| 706 extensions_queue_.active_request()->url == fetch_data->url) { | 718 extensions_queue_.active_request()->url == fetch_data->url) { |
| 707 extensions_queue_.active_request()->request_ids.insert( | 719 extensions_queue_.active_request()->request_ids.insert( |
| (...skipping 10 matching lines...) Expand all Loading... |
| 718 } else { | 730 } else { |
| 719 extensions_queue_.ScheduleRequest(fetch_data.Pass()); | 731 extensions_queue_.ScheduleRequest(fetch_data.Pass()); |
| 720 } | 732 } |
| 721 } | 733 } |
| 722 } | 734 } |
| 723 | 735 |
| 724 void ExtensionDownloader::NotifyDelegateDownloadFinished( | 736 void ExtensionDownloader::NotifyDelegateDownloadFinished( |
| 725 scoped_ptr<ExtensionFetch> fetch_data, | 737 scoped_ptr<ExtensionFetch> fetch_data, |
| 726 const base::FilePath& crx_path, | 738 const base::FilePath& crx_path, |
| 727 bool file_ownership_passed) { | 739 bool file_ownership_passed) { |
| 728 delegate_->OnExtensionDownloadFinished(fetch_data->id, crx_path, | 740 delegate_->OnExtensionDownloadFinished(fetch_data->id, |
| 729 file_ownership_passed, fetch_data->url, fetch_data->version, | 741 crx_path, |
| 730 ping_results_[fetch_data->id], fetch_data->request_ids); | 742 file_ownership_passed, |
| 743 fetch_data->url, |
| 744 fetch_data->version, |
| 745 ping_results_[fetch_data->id], |
| 746 fetch_data->request_ids); |
| 731 ping_results_.erase(fetch_data->id); | 747 ping_results_.erase(fetch_data->id); |
| 732 } | 748 } |
| 733 | 749 |
| 734 void ExtensionDownloader::CreateExtensionFetcher() { | 750 void ExtensionDownloader::CreateExtensionFetcher() { |
| 735 const ExtensionFetch* fetch = extensions_queue_.active_request(); | 751 const ExtensionFetch* fetch = extensions_queue_.active_request(); |
| 736 extension_fetcher_.reset(net::URLFetcher::Create( | 752 extension_fetcher_.reset(net::URLFetcher::Create( |
| 737 kExtensionFetcherId, fetch->url, net::URLFetcher::GET, this)); | 753 kExtensionFetcherId, fetch->url, net::URLFetcher::GET, this)); |
| 738 extension_fetcher_->SetRequestContext(request_context_.get()); | 754 extension_fetcher_->SetRequestContext(request_context_.get()); |
| 739 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 755 extension_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
| 740 | 756 |
| 741 int load_flags = net::LOAD_DISABLE_CACHE; | 757 int load_flags = net::LOAD_DISABLE_CACHE; |
| 742 bool is_secure = fetch->url.SchemeIsSecure(); | 758 bool is_secure = fetch->url.SchemeIsSecure(); |
| 743 if (fetch->credentials != ExtensionFetch::CREDENTIALS_COOKIES || !is_secure) { | 759 if (fetch->credentials != ExtensionFetch::CREDENTIALS_COOKIES || !is_secure) { |
| 744 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES | | 760 load_flags |= net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES; |
| 745 net::LOAD_DO_NOT_SAVE_COOKIES; | |
| 746 } | 761 } |
| 747 extension_fetcher_->SetLoadFlags(load_flags); | 762 extension_fetcher_->SetLoadFlags(load_flags); |
| 748 | 763 |
| 749 // Download CRX files to a temp file. The blacklist is small and will be | 764 // Download CRX files to a temp file. The blacklist is small and will be |
| 750 // processed in memory, so it is fetched into a string. | 765 // processed in memory, so it is fetched into a string. |
| 751 if (fetch->id != kBlacklistAppID) { | 766 if (fetch->id != kBlacklistAppID) { |
| 752 extension_fetcher_->SaveResponseToTemporaryFile( | 767 extension_fetcher_->SaveResponseToTemporaryFile( |
| 753 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | 768 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); |
| 754 } | 769 } |
| 755 | 770 |
| 756 if (fetch->credentials == ExtensionFetch::CREDENTIALS_OAUTH2_TOKEN && | 771 if (fetch->credentials == ExtensionFetch::CREDENTIALS_OAUTH2_TOKEN && |
| 757 is_secure) { | 772 is_secure) { |
| 758 if (access_token_.empty()) { | 773 if (access_token_.empty()) { |
| 759 // We should try OAuth2, but we have no token cached. This | 774 // We should try OAuth2, but we have no token cached. This |
| 760 // ExtensionFetcher will be started once the token fetch is complete, | 775 // ExtensionFetcher will be started once the token fetch is complete, |
| 761 // in either OnTokenFetchSuccess or OnTokenFetchFailure. | 776 // in either OnTokenFetchSuccess or OnTokenFetchFailure. |
| 762 DCHECK(identity_provider_.get()); | 777 DCHECK(identity_provider_.get()); |
| 763 OAuth2TokenService::ScopeSet webstore_scopes; | 778 OAuth2TokenService::ScopeSet webstore_scopes; |
| 764 webstore_scopes.insert(kWebstoreOAuth2Scope); | 779 webstore_scopes.insert(kWebstoreOAuth2Scope); |
| 765 access_token_request_ = | 780 access_token_request_ = |
| 766 identity_provider_->GetTokenService()->StartRequest( | 781 identity_provider_->GetTokenService()->StartRequest( |
| 767 identity_provider_->GetActiveAccountId(), | 782 identity_provider_->GetActiveAccountId(), webstore_scopes, this); |
| 768 webstore_scopes, | |
| 769 this); | |
| 770 return; | 783 return; |
| 771 } | 784 } |
| 772 extension_fetcher_->AddExtraRequestHeader( | 785 extension_fetcher_->AddExtraRequestHeader( |
| 773 base::StringPrintf("%s: Bearer %s", | 786 base::StringPrintf("%s: Bearer %s", |
| 774 net::HttpRequestHeaders::kAuthorization, | 787 net::HttpRequestHeaders::kAuthorization, |
| 775 access_token_.c_str())); | 788 access_token_.c_str())); |
| 776 } | 789 } |
| 777 | 790 |
| 778 VLOG(2) << "Starting fetch of " << fetch->url << " for " << fetch->id; | 791 VLOG(2) << "Starting fetch of " << fetch->url << " for " << fetch->id; |
| 779 extension_fetcher_->Start(); | 792 extension_fetcher_->Start(); |
| 780 } | 793 } |
| 781 | 794 |
| 782 void ExtensionDownloader::OnCRXFetchComplete( | 795 void ExtensionDownloader::OnCRXFetchComplete( |
| 783 const net::URLFetcher* source, | 796 const net::URLFetcher* source, |
| 784 const GURL& url, | 797 const GURL& url, |
| 785 const net::URLRequestStatus& status, | 798 const net::URLRequestStatus& status, |
| 786 int response_code, | 799 int response_code, |
| 787 const base::TimeDelta& backoff_delay) { | 800 const base::TimeDelta& backoff_delay) { |
| 788 ExtensionFetch& active_request = *extensions_queue_.active_request(); | 801 ExtensionFetch& active_request = *extensions_queue_.active_request(); |
| 789 const std::string& id = active_request.id; | 802 const std::string& id = active_request.id; |
| 790 if (status.status() == net::URLRequestStatus::SUCCESS && | 803 if (status.status() == net::URLRequestStatus::SUCCESS && |
| 791 (response_code == 200 || url.SchemeIsFile())) { | 804 (response_code == 200 || url.SchemeIsFile())) { |
| 792 RETRY_HISTOGRAM("CrxFetchSuccess", | 805 RETRY_HISTOGRAM("CrxFetchSuccess", |
| 793 extensions_queue_.active_request_failure_count(), url); | 806 extensions_queue_.active_request_failure_count(), |
| 807 url); |
| 794 base::FilePath crx_path; | 808 base::FilePath crx_path; |
| 795 // Take ownership of the file at |crx_path|. | 809 // Take ownership of the file at |crx_path|. |
| 796 CHECK(source->GetResponseAsFilePath(true, &crx_path)); | 810 CHECK(source->GetResponseAsFilePath(true, &crx_path)); |
| 797 scoped_ptr<ExtensionFetch> fetch_data = | 811 scoped_ptr<ExtensionFetch> fetch_data = |
| 798 extensions_queue_.reset_active_request(); | 812 extensions_queue_.reset_active_request(); |
| 799 if (extension_cache_) { | 813 if (extension_cache_) { |
| 800 const std::string& version = fetch_data->version; | 814 const std::string& version = fetch_data->version; |
| 801 extension_cache_->PutExtension(id, crx_path, version, | 815 extension_cache_->PutExtension( |
| 816 id, |
| 817 crx_path, |
| 818 version, |
| 802 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, | 819 base::Bind(&ExtensionDownloader::NotifyDelegateDownloadFinished, |
| 803 weak_ptr_factory_.GetWeakPtr(), | 820 weak_ptr_factory_.GetWeakPtr(), |
| 804 base::Passed(&fetch_data))); | 821 base::Passed(&fetch_data))); |
| 805 } else { | 822 } else { |
| 806 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); | 823 NotifyDelegateDownloadFinished(fetch_data.Pass(), crx_path, true); |
| 807 } | 824 } |
| 808 } else if (IterateFetchCredentialsAfterFailure( | 825 } else if (IterateFetchCredentialsAfterFailure( |
| 809 &active_request, | 826 &active_request, status, response_code)) { |
| 810 status, | |
| 811 response_code)) { | |
| 812 extensions_queue_.RetryRequest(backoff_delay); | 827 extensions_queue_.RetryRequest(backoff_delay); |
| 813 } else { | 828 } else { |
| 814 const std::set<int>& request_ids = active_request.request_ids; | 829 const std::set<int>& request_ids = active_request.request_ids; |
| 815 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; | 830 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; |
| 816 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() | 831 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() |
| 817 << "' response code:" << response_code; | 832 << "' response code:" << response_code; |
| 818 if (ShouldRetryRequest(status, response_code) && | 833 if (ShouldRetryRequest(status, response_code) && |
| 819 extensions_queue_.active_request_failure_count() < kMaxRetries) { | 834 extensions_queue_.active_request_failure_count() < kMaxRetries) { |
| 820 extensions_queue_.RetryRequest(backoff_delay); | 835 extensions_queue_.RetryRequest(backoff_delay); |
| 821 } else { | 836 } else { |
| 822 RETRY_HISTOGRAM("CrxFetchFailure", | 837 RETRY_HISTOGRAM("CrxFetchFailure", |
| 823 extensions_queue_.active_request_failure_count(), url); | 838 extensions_queue_.active_request_failure_count(), |
| 839 url); |
| 824 // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h) | 840 // status.error() is 0 (net::OK) or negative. (See net/base/net_errors.h) |
| 825 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.CrxFetchError", -status.error()); | 841 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.CrxFetchError", -status.error()); |
| 826 delegate_->OnExtensionDownloadFailed( | 842 delegate_->OnExtensionDownloadFailed( |
| 827 id, ExtensionDownloaderDelegate::CRX_FETCH_FAILED, ping, request_ids); | 843 id, ExtensionDownloaderDelegate::CRX_FETCH_FAILED, ping, request_ids); |
| 828 } | 844 } |
| 829 ping_results_.erase(id); | 845 ping_results_.erase(id); |
| 830 extensions_queue_.reset_active_request(); | 846 extensions_queue_.reset_active_request(); |
| 831 } | 847 } |
| 832 | 848 |
| 833 extension_fetcher_.reset(); | 849 extension_fetcher_.reset(); |
| 834 | 850 |
| 835 // If there are any pending downloads left, start the next one. | 851 // If there are any pending downloads left, start the next one. |
| 836 extensions_queue_.StartNextRequest(); | 852 extensions_queue_.StartNextRequest(); |
| 837 } | 853 } |
| 838 | 854 |
| 839 void ExtensionDownloader::NotifyExtensionsDownloadFailed( | 855 void ExtensionDownloader::NotifyExtensionsDownloadFailed( |
| 840 const std::set<std::string>& extension_ids, | 856 const std::set<std::string>& extension_ids, |
| 841 const std::set<int>& request_ids, | 857 const std::set<int>& request_ids, |
| 842 ExtensionDownloaderDelegate::Error error) { | 858 ExtensionDownloaderDelegate::Error error) { |
| 843 for (std::set<std::string>::const_iterator it = extension_ids.begin(); | 859 for (std::set<std::string>::const_iterator it = extension_ids.begin(); |
| 844 it != extension_ids.end(); ++it) { | 860 it != extension_ids.end(); |
| 861 ++it) { |
| 845 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[*it]; | 862 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[*it]; |
| 846 delegate_->OnExtensionDownloadFailed(*it, error, ping, request_ids); | 863 delegate_->OnExtensionDownloadFailed(*it, error, ping, request_ids); |
| 847 ping_results_.erase(*it); | 864 ping_results_.erase(*it); |
| 848 } | 865 } |
| 849 } | 866 } |
| 850 | 867 |
| 851 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, | 868 void ExtensionDownloader::NotifyUpdateFound(const std::string& id, |
| 852 const std::string& version) { | 869 const std::string& version) { |
| 853 UpdateDetails updateInfo(id, Version(version)); | 870 UpdateDetails updateInfo(id, Version(version)); |
| 854 content::NotificationService::current()->Notify( | 871 content::NotificationService::current()->Notify( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 identity_provider_->GetTokenService()->InvalidateToken( | 907 identity_provider_->GetTokenService()->InvalidateToken( |
| 891 identity_provider_->GetActiveAccountId(), | 908 identity_provider_->GetActiveAccountId(), |
| 892 webstore_scopes, | 909 webstore_scopes, |
| 893 access_token_); | 910 access_token_); |
| 894 access_token_.clear(); | 911 access_token_.clear(); |
| 895 return true; | 912 return true; |
| 896 } | 913 } |
| 897 // Either there is no Gaia identity available, the active identity | 914 // Either there is no Gaia identity available, the active identity |
| 898 // doesn't have access to this resource, or the server keeps returning | 915 // doesn't have access to this resource, or the server keeps returning |
| 899 // 401s and we've retried too many times. Fall back on cookies. | 916 // 401s and we've retried too many times. Fall back on cookies. |
| 900 if (access_token_.empty() || | 917 if (access_token_.empty() || response_code == net::HTTP_FORBIDDEN || |
| 901 response_code == net::HTTP_FORBIDDEN || | |
| 902 fetch->oauth2_attempt_count > kMaxOAuth2Attempts) { | 918 fetch->oauth2_attempt_count > kMaxOAuth2Attempts) { |
| 903 fetch->credentials = ExtensionFetch::CREDENTIALS_COOKIES; | 919 fetch->credentials = ExtensionFetch::CREDENTIALS_COOKIES; |
| 904 return true; | 920 return true; |
| 905 } | 921 } |
| 906 // Something else is wrong. Time to give up. | 922 // Something else is wrong. Time to give up. |
| 907 return false; | 923 return false; |
| 908 case ExtensionFetch::CREDENTIALS_COOKIES: | 924 case ExtensionFetch::CREDENTIALS_COOKIES: |
| 909 if (response_code == net::HTTP_FORBIDDEN) { | 925 if (response_code == net::HTTP_FORBIDDEN) { |
| 910 // Try the next session identity, up to some maximum. | 926 // Try the next session identity, up to some maximum. |
| 911 return IncrementAuthUserIndex(&fetch->url); | 927 return IncrementAuthUserIndex(&fetch->url); |
| 912 } | 928 } |
| 913 return false; | 929 return false; |
| 914 default: | 930 default: |
| 915 NOTREACHED(); | 931 NOTREACHED(); |
| 916 } | 932 } |
| 917 NOTREACHED(); | 933 NOTREACHED(); |
| 918 return false; | 934 return false; |
| 919 } | 935 } |
| 920 | 936 |
| 921 void ExtensionDownloader::OnGetTokenSuccess( | 937 void ExtensionDownloader::OnGetTokenSuccess( |
| 922 const OAuth2TokenService::Request* request, | 938 const OAuth2TokenService::Request* request, |
| 923 const std::string& access_token, | 939 const std::string& access_token, |
| 924 const base::Time& expiration_time) { | 940 const base::Time& expiration_time) { |
| 925 access_token_ = access_token; | 941 access_token_ = access_token; |
| 926 extension_fetcher_->AddExtraRequestHeader( | 942 extension_fetcher_->AddExtraRequestHeader( |
| 927 base::StringPrintf("%s: Bearer %s", | 943 base::StringPrintf("%s: Bearer %s", |
| 928 net::HttpRequestHeaders::kAuthorization, | 944 net::HttpRequestHeaders::kAuthorization, |
| 929 access_token_.c_str())); | 945 access_token_.c_str())); |
| 930 extension_fetcher_->Start(); | 946 extension_fetcher_->Start(); |
| 931 } | 947 } |
| 932 | 948 |
| 933 void ExtensionDownloader::OnGetTokenFailure( | 949 void ExtensionDownloader::OnGetTokenFailure( |
| 934 const OAuth2TokenService::Request* request, | 950 const OAuth2TokenService::Request* request, |
| 935 const GoogleServiceAuthError& error) { | 951 const GoogleServiceAuthError& error) { |
| 936 // If we fail to get an access token, kick the pending fetch and let it fall | 952 // If we fail to get an access token, kick the pending fetch and let it fall |
| 937 // back on cookies. | 953 // back on cookies. |
| 938 extension_fetcher_->Start(); | 954 extension_fetcher_->Start(); |
| 939 } | 955 } |
| 940 | 956 |
| 941 ManifestFetchData* ExtensionDownloader::CreateManifestFetchData( | 957 ManifestFetchData* ExtensionDownloader::CreateManifestFetchData( |
| 942 const GURL& update_url, | 958 const GURL& update_url, |
| 943 int request_id) { | 959 int request_id) { |
| 944 ManifestFetchData::PingMode ping_mode = ManifestFetchData::NO_PING; | 960 ManifestFetchData::PingMode ping_mode = ManifestFetchData::NO_PING; |
| 945 if (update_url.DomainIs(ping_enabled_domain_.c_str())) { | 961 if (update_url.DomainIs(ping_enabled_domain_.c_str())) { |
| 946 if (enable_extra_update_metrics_) { | 962 if (enable_extra_update_metrics_) { |
| 947 ping_mode = ManifestFetchData::PING_WITH_METRICS; | 963 ping_mode = ManifestFetchData::PING_WITH_METRICS; |
| 948 } else { | 964 } else { |
| 949 ping_mode = ManifestFetchData::PING; | 965 ping_mode = ManifestFetchData::PING; |
| 950 } | 966 } |
| 951 } | 967 } |
| 952 return new ManifestFetchData( | 968 return new ManifestFetchData( |
| 953 update_url, request_id, brand_code_, manifest_query_params_, ping_mode); | 969 update_url, request_id, brand_code_, manifest_query_params_, ping_mode); |
| 954 } | 970 } |
| 955 | 971 |
| 956 } // namespace extensions | 972 } // namespace extensions |
| OLD | NEW |