| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "chrome/browser/extensions/extension_service.h" | 22 #include "chrome/browser/extensions/extension_service.h" |
| 23 #include "chrome/browser/extensions/updater/extension_downloader.h" | 23 #include "chrome/browser/extensions/updater/extension_downloader.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/common/pref_names.h" | 25 #include "chrome/common/pref_names.h" |
| 26 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
| 27 #include "content/public/browser/notification_details.h" | 27 #include "content/public/browser/notification_details.h" |
| 28 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
| 29 #include "content/public/browser/notification_source.h" | 29 #include "content/public/browser/notification_source.h" |
| 30 #include "crypto/sha2.h" | 30 #include "crypto/sha2.h" |
| 31 #include "extensions/browser/pending_extension_manager.h" | 31 #include "extensions/browser/pending_extension_manager.h" |
| 32 #include "extensions/browser/pref_names.h" |
| 32 #include "extensions/common/constants.h" | 33 #include "extensions/common/constants.h" |
| 33 #include "extensions/common/extension.h" | 34 #include "extensions/common/extension.h" |
| 34 #include "extensions/common/extension_set.h" | 35 #include "extensions/common/extension_set.h" |
| 35 #include "extensions/common/manifest.h" | 36 #include "extensions/common/manifest.h" |
| 36 | 37 |
| 37 using base::RandDouble; | 38 using base::RandDouble; |
| 38 using base::RandInt; | 39 using base::RandInt; |
| 39 using base::Time; | 40 using base::Time; |
| 40 using base::TimeDelta; | 41 using base::TimeDelta; |
| 41 using content::BrowserThread; | 42 using content::BrowserThread; |
| 42 using prefs::kLastExtensionsUpdateCheck; | |
| 43 using prefs::kNextExtensionsUpdateCheck; | |
| 44 | 43 |
| 45 typedef extensions::ExtensionDownloaderDelegate::Error Error; | 44 typedef extensions::ExtensionDownloaderDelegate::Error Error; |
| 46 typedef extensions::ExtensionDownloaderDelegate::PingResult PingResult; | 45 typedef extensions::ExtensionDownloaderDelegate::PingResult PingResult; |
| 47 | 46 |
| 48 namespace { | 47 namespace { |
| 49 | 48 |
| 50 // Wait at least 5 minutes after browser startup before we do any checks. If you | 49 // Wait at least 5 minutes after browser startup before we do any checks. If you |
| 51 // change this value, make sure to update comments where it is used. | 50 // change this value, make sure to update comments where it is used. |
| 52 const int kStartupWaitSeconds = 60 * 5; | 51 const int kStartupWaitSeconds = 60 * 5; |
| 53 | 52 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 157 |
| 159 // The overall goal here is to balance keeping clients up to date while | 158 // The overall goal here is to balance keeping clients up to date while |
| 160 // avoiding a thundering herd against update servers. | 159 // avoiding a thundering herd against update servers. |
| 161 TimeDelta ExtensionUpdater::DetermineFirstCheckDelay() { | 160 TimeDelta ExtensionUpdater::DetermineFirstCheckDelay() { |
| 162 DCHECK(alive_); | 161 DCHECK(alive_); |
| 163 // If someone's testing with a quick frequency, just allow it. | 162 // If someone's testing with a quick frequency, just allow it. |
| 164 if (frequency_seconds_ < kStartupWaitSeconds) | 163 if (frequency_seconds_ < kStartupWaitSeconds) |
| 165 return TimeDelta::FromSeconds(frequency_seconds_); | 164 return TimeDelta::FromSeconds(frequency_seconds_); |
| 166 | 165 |
| 167 // If we've never scheduled a check before, start at frequency_seconds_. | 166 // If we've never scheduled a check before, start at frequency_seconds_. |
| 168 if (!prefs_->HasPrefPath(kNextExtensionsUpdateCheck)) | 167 if (!prefs_->HasPrefPath(pref_names::kNextUpdateCheck)) |
| 169 return TimeDelta::FromSeconds(frequency_seconds_); | 168 return TimeDelta::FromSeconds(frequency_seconds_); |
| 170 | 169 |
| 171 // If it's been a long time since our last actual check, we want to do one | 170 // If it's been a long time since our last actual check, we want to do one |
| 172 // relatively soon. | 171 // relatively soon. |
| 173 Time now = Time::Now(); | 172 Time now = Time::Now(); |
| 174 Time last = Time::FromInternalValue(prefs_->GetInt64( | 173 Time last = Time::FromInternalValue(prefs_->GetInt64( |
| 175 kLastExtensionsUpdateCheck)); | 174 pref_names::kLastUpdateCheck)); |
| 176 int days = (now - last).InDays(); | 175 int days = (now - last).InDays(); |
| 177 if (days >= 30) { | 176 if (days >= 30) { |
| 178 // Wait 5-10 minutes. | 177 // Wait 5-10 minutes. |
| 179 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds, | 178 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds, |
| 180 kStartupWaitSeconds * 2)); | 179 kStartupWaitSeconds * 2)); |
| 181 } else if (days >= 14) { | 180 } else if (days >= 14) { |
| 182 // Wait 10-20 minutes. | 181 // Wait 10-20 minutes. |
| 183 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 2, | 182 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 2, |
| 184 kStartupWaitSeconds * 4)); | 183 kStartupWaitSeconds * 4)); |
| 185 } else if (days >= 3) { | 184 } else if (days >= 3) { |
| 186 // Wait 20-40 minutes. | 185 // Wait 20-40 minutes. |
| 187 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 4, | 186 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds * 4, |
| 188 kStartupWaitSeconds * 8)); | 187 kStartupWaitSeconds * 8)); |
| 189 } | 188 } |
| 190 | 189 |
| 191 // Read the persisted next check time, and use that if it isn't too soon. | 190 // Read the persisted next check time, and use that if it isn't too soon. |
| 192 // Otherwise pick something random. | 191 // Otherwise pick something random. |
| 193 Time saved_next = Time::FromInternalValue(prefs_->GetInt64( | 192 Time saved_next = Time::FromInternalValue(prefs_->GetInt64( |
| 194 kNextExtensionsUpdateCheck)); | 193 pref_names::kNextUpdateCheck)); |
| 195 Time earliest = now + TimeDelta::FromSeconds(kStartupWaitSeconds); | 194 Time earliest = now + TimeDelta::FromSeconds(kStartupWaitSeconds); |
| 196 if (saved_next >= earliest) { | 195 if (saved_next >= earliest) { |
| 197 return saved_next - now; | 196 return saved_next - now; |
| 198 } else { | 197 } else { |
| 199 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds, | 198 return TimeDelta::FromSeconds(RandInt(kStartupWaitSeconds, |
| 200 frequency_seconds_)); | 199 frequency_seconds_)); |
| 201 } | 200 } |
| 202 } | 201 } |
| 203 | 202 |
| 204 void ExtensionUpdater::Start() { | 203 void ExtensionUpdater::Start() { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 234 | 233 |
| 235 // Add +/- 10% random jitter. | 234 // Add +/- 10% random jitter. |
| 236 double delay_ms = target_delay.InMillisecondsF(); | 235 double delay_ms = target_delay.InMillisecondsF(); |
| 237 double jitter_factor = (RandDouble() * .2) - 0.1; | 236 double jitter_factor = (RandDouble() * .2) - 0.1; |
| 238 delay_ms += delay_ms * jitter_factor; | 237 delay_ms += delay_ms * jitter_factor; |
| 239 TimeDelta actual_delay = TimeDelta::FromMilliseconds( | 238 TimeDelta actual_delay = TimeDelta::FromMilliseconds( |
| 240 static_cast<int64>(delay_ms)); | 239 static_cast<int64>(delay_ms)); |
| 241 | 240 |
| 242 // Save the time of next check. | 241 // Save the time of next check. |
| 243 Time next = Time::Now() + actual_delay; | 242 Time next = Time::Now() + actual_delay; |
| 244 prefs_->SetInt64(kNextExtensionsUpdateCheck, next.ToInternalValue()); | 243 prefs_->SetInt64(pref_names::kNextUpdateCheck, next.ToInternalValue()); |
| 245 | 244 |
| 246 timer_.Start(FROM_HERE, actual_delay, this, &ExtensionUpdater::TimerFired); | 245 timer_.Start(FROM_HERE, actual_delay, this, &ExtensionUpdater::TimerFired); |
| 247 } | 246 } |
| 248 | 247 |
| 249 void ExtensionUpdater::TimerFired() { | 248 void ExtensionUpdater::TimerFired() { |
| 250 DCHECK(alive_); | 249 DCHECK(alive_); |
| 251 CheckNow(default_params_); | 250 CheckNow(default_params_); |
| 252 | 251 |
| 253 // If the user has overridden the update frequency, don't bother reporting | 252 // If the user has overridden the update frequency, don't bother reporting |
| 254 // this. | 253 // this. |
| 255 if (frequency_seconds_ == extensions::kDefaultUpdateFrequencySeconds) { | 254 if (frequency_seconds_ == extensions::kDefaultUpdateFrequencySeconds) { |
| 256 Time last = Time::FromInternalValue(prefs_->GetInt64( | 255 Time last = Time::FromInternalValue(prefs_->GetInt64( |
| 257 kLastExtensionsUpdateCheck)); | 256 pref_names::kLastUpdateCheck)); |
| 258 if (last.ToInternalValue() != 0) { | 257 if (last.ToInternalValue() != 0) { |
| 259 // Use counts rather than time so we can use minutes rather than millis. | 258 // Use counts rather than time so we can use minutes rather than millis. |
| 260 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.UpdateCheckGap", | 259 UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.UpdateCheckGap", |
| 261 (Time::Now() - last).InMinutes(), | 260 (Time::Now() - last).InMinutes(), |
| 262 TimeDelta::FromSeconds(kStartupWaitSeconds).InMinutes(), | 261 TimeDelta::FromSeconds(kStartupWaitSeconds).InMinutes(), |
| 263 TimeDelta::FromDays(40).InMinutes(), | 262 TimeDelta::FromDays(40).InMinutes(), |
| 264 50); // 50 buckets seems to be the default. | 263 50); // 50 buckets seems to be the default. |
| 265 } | 264 } |
| 266 } | 265 } |
| 267 | 266 |
| 268 // Save the last check time, and schedule the next check. | 267 // Save the last check time, and schedule the next check. |
| 269 int64 now = Time::Now().ToInternalValue(); | 268 int64 now = Time::Now().ToInternalValue(); |
| 270 prefs_->SetInt64(kLastExtensionsUpdateCheck, now); | 269 prefs_->SetInt64(pref_names::kLastUpdateCheck, now); |
| 271 ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_)); | 270 ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_)); |
| 272 } | 271 } |
| 273 | 272 |
| 274 void ExtensionUpdater::CheckSoon() { | 273 void ExtensionUpdater::CheckSoon() { |
| 275 DCHECK(alive_); | 274 DCHECK(alive_); |
| 276 if (will_check_soon_) | 275 if (will_check_soon_) |
| 277 return; | 276 return; |
| 278 if (BrowserThread::PostTask( | 277 if (BrowserThread::PostTask( |
| 279 BrowserThread::UI, FROM_HERE, | 278 BrowserThread::UI, FROM_HERE, |
| 280 base::Bind(&ExtensionUpdater::DoCheckSoon, | 279 base::Bind(&ExtensionUpdater::DoCheckSoon, |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 const InProgressCheck& request = requests_in_progress_[request_id]; | 634 const InProgressCheck& request = requests_in_progress_[request_id]; |
| 636 if (request.in_progress_ids_.empty()) { | 635 if (request.in_progress_ids_.empty()) { |
| 637 VLOG(2) << "Finished update check " << request_id; | 636 VLOG(2) << "Finished update check " << request_id; |
| 638 if (!request.callback.is_null()) | 637 if (!request.callback.is_null()) |
| 639 request.callback.Run(); | 638 request.callback.Run(); |
| 640 requests_in_progress_.erase(request_id); | 639 requests_in_progress_.erase(request_id); |
| 641 } | 640 } |
| 642 } | 641 } |
| 643 | 642 |
| 644 } // namespace extensions | 643 } // namespace extensions |
| OLD | NEW |