| 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_updater.h" | 5 #include "chrome/browser/extensions/updater/extension_updater.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 // Wait at least 5 minutes after browser startup before we do any checks. If you | 53 // Wait at least 5 minutes after browser startup before we do any checks. If you |
| 54 // change this value, make sure to update comments where it is used. | 54 // change this value, make sure to update comments where it is used. |
| 55 const int kStartupWaitSeconds = 60 * 5; | 55 const int kStartupWaitSeconds = 60 * 5; |
| 56 | 56 |
| 57 // For sanity checking on update frequency - enforced in release mode only. | 57 // For sanity checking on update frequency - enforced in release mode only. |
| 58 #if defined(NDEBUG) | 58 #if defined(NDEBUG) |
| 59 const int kMinUpdateFrequencySeconds = 30; | 59 const int kMinUpdateFrequencySeconds = 30; |
| 60 #endif | 60 #endif |
| 61 const int kMaxUpdateFrequencySeconds = 60 * 60 * 24 * 7; // 7 days | 61 const int kMaxUpdateFrequencySeconds = 60 * 60 * 24 * 7; // 7 days |
| 62 | 62 |
| 63 // Require at least 5 seconds between consecutive non-succesful extension update |
| 64 // checks. |
| 65 const int kMinUpdateThrottleTime = 5; |
| 66 |
| 63 // When we've computed a days value, we want to make sure we don't send a | 67 // When we've computed a days value, we want to make sure we don't send a |
| 64 // negative value (due to the system clock being set backwards, etc.), since -1 | 68 // negative value (due to the system clock being set backwards, etc.), since -1 |
| 65 // is a special sentinel value that means "never pinged", and other negative | 69 // is a special sentinel value that means "never pinged", and other negative |
| 66 // values don't make sense. | 70 // values don't make sense. |
| 67 int SanitizeDays(int days) { | 71 int SanitizeDays(int days) { |
| 68 if (days < 0) | 72 if (days < 0) |
| 69 return 0; | 73 return 0; |
| 70 return days; | 74 return days; |
| 71 } | 75 } |
| 72 | 76 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 ExtensionUpdater::FetchedCRXFile::~FetchedCRXFile() {} | 122 ExtensionUpdater::FetchedCRXFile::~FetchedCRXFile() {} |
| 119 | 123 |
| 120 ExtensionUpdater::InProgressCheck::InProgressCheck() | 124 ExtensionUpdater::InProgressCheck::InProgressCheck() |
| 121 : install_immediately(false) {} | 125 : install_immediately(false) {} |
| 122 | 126 |
| 123 ExtensionUpdater::InProgressCheck::InProgressCheck( | 127 ExtensionUpdater::InProgressCheck::InProgressCheck( |
| 124 const InProgressCheck& other) = default; | 128 const InProgressCheck& other) = default; |
| 125 | 129 |
| 126 ExtensionUpdater::InProgressCheck::~InProgressCheck() {} | 130 ExtensionUpdater::InProgressCheck::~InProgressCheck() {} |
| 127 | 131 |
| 132 struct ExtensionUpdater::ThrottleInfo { |
| 133 ThrottleInfo() |
| 134 : in_progress(true), |
| 135 throttle_delay(kMinUpdateThrottleTime), |
| 136 check_start(Time::Now()) {} |
| 137 |
| 138 bool in_progress; |
| 139 int throttle_delay; |
| 140 Time check_start; |
| 141 }; |
| 142 |
| 128 ExtensionUpdater::ExtensionUpdater( | 143 ExtensionUpdater::ExtensionUpdater( |
| 129 ExtensionServiceInterface* service, | 144 ExtensionServiceInterface* service, |
| 130 ExtensionPrefs* extension_prefs, | 145 ExtensionPrefs* extension_prefs, |
| 131 PrefService* prefs, | 146 PrefService* prefs, |
| 132 Profile* profile, | 147 Profile* profile, |
| 133 int frequency_seconds, | 148 int frequency_seconds, |
| 134 ExtensionCache* cache, | 149 ExtensionCache* cache, |
| 135 const ExtensionDownloader::Factory& downloader_factory) | 150 const ExtensionDownloader::Factory& downloader_factory) |
| 136 : alive_(false), | 151 : alive_(false), |
| 137 service_(service), | 152 service_(service), |
| 138 downloader_factory_(downloader_factory), | 153 downloader_factory_(downloader_factory), |
| 139 frequency_seconds_(frequency_seconds), | 154 frequency_seconds_(frequency_seconds), |
| 140 will_check_soon_(false), | 155 will_check_soon_(false), |
| 141 extension_prefs_(extension_prefs), | 156 extension_prefs_(extension_prefs), |
| 142 prefs_(prefs), | 157 prefs_(prefs), |
| 143 profile_(profile), | 158 profile_(profile), |
| 144 next_request_id_(0), | 159 next_request_id_(0), |
| 160 extension_registry_observer_(this), |
| 145 crx_install_is_running_(false), | 161 crx_install_is_running_(false), |
| 146 extension_cache_(cache), | 162 extension_cache_(cache), |
| 147 weak_ptr_factory_(this) { | 163 weak_ptr_factory_(this) { |
| 148 DCHECK_GE(frequency_seconds_, 5); | 164 DCHECK_GE(frequency_seconds_, 5); |
| 149 DCHECK_LE(frequency_seconds_, kMaxUpdateFrequencySeconds); | 165 DCHECK_LE(frequency_seconds_, kMaxUpdateFrequencySeconds); |
| 150 #if defined(NDEBUG) | 166 #if defined(NDEBUG) |
| 151 // In Release mode we enforce that update checks don't happen too often. | 167 // In Release mode we enforce that update checks don't happen too often. |
| 152 frequency_seconds_ = std::max(frequency_seconds_, kMinUpdateFrequencySeconds); | 168 frequency_seconds_ = std::max(frequency_seconds_, kMinUpdateFrequencySeconds); |
| 153 #endif | 169 #endif |
| 154 frequency_seconds_ = std::min(frequency_seconds_, kMaxUpdateFrequencySeconds); | 170 frequency_seconds_ = std::min(frequency_seconds_, kMaxUpdateFrequencySeconds); |
| 171 |
| 172 extension_registry_observer_.Add(ExtensionRegistry::Get(profile)); |
| 155 } | 173 } |
| 156 | 174 |
| 157 ExtensionUpdater::~ExtensionUpdater() { | 175 ExtensionUpdater::~ExtensionUpdater() { |
| 158 Stop(); | 176 Stop(); |
| 159 } | 177 } |
| 160 | 178 |
| 161 void ExtensionUpdater::EnsureDownloaderCreated() { | 179 void ExtensionUpdater::EnsureDownloaderCreated() { |
| 162 if (!downloader_.get()) { | 180 if (!downloader_.get()) { |
| 163 downloader_ = downloader_factory_.Run(this); | 181 downloader_ = downloader_factory_.Run(this); |
| 164 } | 182 } |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 bool noChecks = request.in_progress_ids_.empty(); | 415 bool noChecks = request.in_progress_ids_.empty(); |
| 398 | 416 |
| 399 // StartAllPending() will call OnExtensionDownloadFailed or | 417 // StartAllPending() will call OnExtensionDownloadFailed or |
| 400 // OnExtensionDownloadFinished for each extension that was checked. | 418 // OnExtensionDownloadFinished for each extension that was checked. |
| 401 downloader_->StartAllPending(extension_cache_); | 419 downloader_->StartAllPending(extension_cache_); |
| 402 | 420 |
| 403 if (noChecks) | 421 if (noChecks) |
| 404 NotifyIfFinished(request_id); | 422 NotifyIfFinished(request_id); |
| 405 } | 423 } |
| 406 | 424 |
| 407 void ExtensionUpdater::CheckExtensionSoon(const std::string& extension_id, | 425 bool ExtensionUpdater::CheckExtensionSoon(const std::string& extension_id, |
| 408 const FinishedCallback& callback) { | 426 const FinishedCallback& callback) { |
| 427 bool have_throttle_info = ContainsKey(throttle_info_, extension_id); |
| 428 ThrottleInfo& info = throttle_info_[extension_id]; |
| 429 if (have_throttle_info) { |
| 430 // We already had a ThrottleInfo object for this extension, check if the |
| 431 // update check request should be allowed. |
| 432 |
| 433 // If another check is in progress, don't start a new check. |
| 434 if (info.in_progress) |
| 435 return false; |
| 436 |
| 437 Time now = Time::Now(); |
| 438 Time last = info.check_start; |
| 439 // If somehow time moved back, we don't want to infinitely keep throttling. |
| 440 if (now < last) { |
| 441 last = now; |
| 442 info.check_start = now; |
| 443 } |
| 444 Time earliest = last + TimeDelta::FromSeconds(info.throttle_delay); |
| 445 // If check is too soon, throttle. |
| 446 if (now < earliest) |
| 447 return false; |
| 448 |
| 449 // TODO(mek): Somehow increase time between allowing checks when checks |
| 450 // are repeatedly throttled and don't result in updates being installed. |
| 451 |
| 452 // It's okay to start a check, update values. |
| 453 info.check_start = now; |
| 454 info.in_progress = true; |
| 455 } |
| 456 |
| 409 CheckParams params; | 457 CheckParams params; |
| 410 params.ids.push_back(extension_id); | 458 params.ids.push_back(extension_id); |
| 411 params.callback = callback; | 459 params.callback = base::Bind(&ExtensionUpdater::ExtensionCheckFinished, |
| 460 weak_ptr_factory_.GetWeakPtr(), |
| 461 extension_id, callback); |
| 412 CheckNow(params); | 462 CheckNow(params); |
| 463 return true; |
| 464 } |
| 465 |
| 466 void ExtensionUpdater::ExtensionCheckFinished( |
| 467 const std::string& extension_id, |
| 468 const FinishedCallback& callback) { |
| 469 std::map<std::string, ThrottleInfo>::iterator it = |
| 470 throttle_info_.find(extension_id); |
| 471 if (it != throttle_info_.end()) { |
| 472 it->second.in_progress = false; |
| 473 } |
| 474 callback.Run(); |
| 413 } | 475 } |
| 414 | 476 |
| 415 void ExtensionUpdater::OnExtensionDownloadFailed( | 477 void ExtensionUpdater::OnExtensionDownloadFailed( |
| 416 const std::string& id, | 478 const std::string& id, |
| 417 Error error, | 479 Error error, |
| 418 const PingResult& ping, | 480 const PingResult& ping, |
| 419 const std::set<int>& request_ids) { | 481 const std::set<int>& request_ids) { |
| 420 DCHECK(alive_); | 482 DCHECK(alive_); |
| 421 UpdatePingData(id, ping); | 483 UpdatePingData(id, ping); |
| 422 bool install_immediately = false; | 484 bool install_immediately = false; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 } | 652 } |
| 591 if (!crx_file.callback.is_null()) { | 653 if (!crx_file.callback.is_null()) { |
| 592 crx_file.callback.Run(false); | 654 crx_file.callback.Run(false); |
| 593 } | 655 } |
| 594 } | 656 } |
| 595 | 657 |
| 596 // If any files are available to update, start one. | 658 // If any files are available to update, start one. |
| 597 MaybeInstallCRXFile(); | 659 MaybeInstallCRXFile(); |
| 598 } | 660 } |
| 599 | 661 |
| 662 void ExtensionUpdater::OnExtensionWillBeInstalled( |
| 663 content::BrowserContext* browser_context, |
| 664 const Extension* extension, |
| 665 bool is_update, |
| 666 const std::string& old_name) { |
| 667 throttle_info_.erase(extension->id()); |
| 668 } |
| 669 |
| 600 void ExtensionUpdater::NotifyStarted() { | 670 void ExtensionUpdater::NotifyStarted() { |
| 601 content::NotificationService::current()->Notify( | 671 content::NotificationService::current()->Notify( |
| 602 extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED, | 672 extensions::NOTIFICATION_EXTENSION_UPDATING_STARTED, |
| 603 content::Source<Profile>(profile_), | 673 content::Source<Profile>(profile_), |
| 604 content::NotificationService::NoDetails()); | 674 content::NotificationService::NoDetails()); |
| 605 } | 675 } |
| 606 | 676 |
| 607 void ExtensionUpdater::NotifyIfFinished(int request_id) { | 677 void ExtensionUpdater::NotifyIfFinished(int request_id) { |
| 608 DCHECK(ContainsKey(requests_in_progress_, request_id)); | 678 DCHECK(ContainsKey(requests_in_progress_, request_id)); |
| 609 const InProgressCheck& request = requests_in_progress_[request_id]; | 679 const InProgressCheck& request = requests_in_progress_[request_id]; |
| 610 if (request.in_progress_ids_.empty()) { | 680 if (request.in_progress_ids_.empty()) { |
| 611 VLOG(2) << "Finished update check " << request_id; | 681 VLOG(2) << "Finished update check " << request_id; |
| 612 if (!request.callback.is_null()) | 682 if (!request.callback.is_null()) |
| 613 request.callback.Run(); | 683 request.callback.Run(); |
| 614 requests_in_progress_.erase(request_id); | 684 requests_in_progress_.erase(request_id); |
| 615 } | 685 } |
| 616 } | 686 } |
| 617 | 687 |
| 618 } // namespace extensions | 688 } // namespace extensions |
| OLD | NEW |