| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/gcm_driver/gcm_channel_status_syncer.h" | 5 #include "components/gcm_driver/gcm_channel_status_syncer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" |
| 8 #include "base/location.h" | 9 #include "base/location.h" |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 11 #include "base/prefs/pref_registry_simple.h" | 12 #include "base/prefs/pref_registry_simple.h" |
| 12 #include "base/prefs/pref_service.h" | 13 #include "base/prefs/pref_service.h" |
| 13 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 15 #include "base/strings/string_number_conversions.h" |
| 14 #include "components/gcm_driver/gcm_channel_status_request.h" | 16 #include "components/gcm_driver/gcm_channel_status_request.h" |
| 15 #include "components/gcm_driver/gcm_driver.h" | 17 #include "components/gcm_driver/gcm_driver.h" |
| 16 #include "components/pref_registry/pref_registry_syncable.h" | 18 #include "components/pref_registry/pref_registry_syncable.h" |
| 17 | 19 |
| 18 namespace gcm { | 20 namespace gcm { |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 // The GCM channel's enabled state. | 24 // The GCM channel's enabled state. |
| 23 const char kGCMChannelStatus[] = "gcm.channel_status"; | 25 const char kGCMChannelStatus[] = "gcm.channel_status"; |
| 24 | 26 |
| 25 // The GCM channel's polling interval (in seconds). | 27 // The GCM channel's polling interval (in seconds). |
| 26 const char kGCMChannelPollIntervalSeconds[] = "gcm.poll_interval"; | 28 const char kGCMChannelPollIntervalSeconds[] = "gcm.poll_interval"; |
| 27 | 29 |
| 28 // Last time when checking with the GCM channel status server is done. | 30 // Last time when checking with the GCM channel status server is done. |
| 29 const char kGCMChannelLastCheckTime[] = "gcm.check_time"; | 31 const char kGCMChannelLastCheckTime[] = "gcm.check_time"; |
| 30 | 32 |
| 31 // A small delay to avoid sending request at browser startup time for first-time | 33 // A small delay to avoid sending request at browser startup time for first-time |
| 32 // request. | 34 // request. |
| 33 const int kFirstTimeDelaySeconds = 1 * 60; // 1 minute. | 35 const int kFirstTimeDelaySeconds = 1 * 60; // 1 minute. |
| 34 | 36 |
| 35 // The fuzzing variation added to the polling delay. | 37 // The fuzzing variation added to the polling delay. |
| 36 const int kGCMChannelRequestTimeJitterSeconds = 15 * 60; // 15 minues. | 38 const int kGCMChannelRequestTimeJitterSeconds = 15 * 60; // 15 minues. |
| 37 | 39 |
| 40 // The minimum poll interval that can be overridden to. |
| 41 const int kMinCustomPollIntervalMinutes = 2; |
| 42 |
| 43 // Custom poll interval could not be used more than the limit below. |
| 44 const int kMaxNumberToUseCustomPollInterval = 10; |
| 45 |
| 38 } // namespace | 46 } // namespace |
| 39 | 47 |
| 48 namespace switches { |
| 49 |
| 50 // Override the default poll interval for testing purpose. |
| 51 const char kCustomPollIntervalMinutes[] = "gcm-channel-poll-interval"; |
| 52 |
| 53 } // namepsace switches |
| 54 |
| 40 // static | 55 // static |
| 41 void GCMChannelStatusSyncer::RegisterPrefs(PrefRegistrySimple* registry) { | 56 void GCMChannelStatusSyncer::RegisterPrefs(PrefRegistrySimple* registry) { |
| 42 registry->RegisterBooleanPref(kGCMChannelStatus, true); | 57 registry->RegisterBooleanPref(kGCMChannelStatus, true); |
| 43 registry->RegisterIntegerPref( | 58 registry->RegisterIntegerPref( |
| 44 kGCMChannelPollIntervalSeconds, | 59 kGCMChannelPollIntervalSeconds, |
| 45 GCMChannelStatusRequest::default_poll_interval_seconds()); | 60 GCMChannelStatusRequest::default_poll_interval_seconds()); |
| 46 registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0); | 61 registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0); |
| 47 } | 62 } |
| 48 | 63 |
| 49 // static | 64 // static |
| (...skipping 22 matching lines...) Expand all Loading... |
| 72 GCMDriver* driver, | 87 GCMDriver* driver, |
| 73 PrefService* prefs, | 88 PrefService* prefs, |
| 74 const std::string& channel_status_request_url, | 89 const std::string& channel_status_request_url, |
| 75 const std::string& user_agent, | 90 const std::string& user_agent, |
| 76 const scoped_refptr<net::URLRequestContextGetter>& request_context) | 91 const scoped_refptr<net::URLRequestContextGetter>& request_context) |
| 77 : driver_(driver), | 92 : driver_(driver), |
| 78 prefs_(prefs), | 93 prefs_(prefs), |
| 79 channel_status_request_url_(channel_status_request_url), | 94 channel_status_request_url_(channel_status_request_url), |
| 80 user_agent_(user_agent), | 95 user_agent_(user_agent), |
| 81 request_context_(request_context), | 96 request_context_(request_context), |
| 97 started_(false), |
| 82 gcm_enabled_(true), | 98 gcm_enabled_(true), |
| 83 poll_interval_seconds_( | 99 poll_interval_seconds_( |
| 84 GCMChannelStatusRequest::default_poll_interval_seconds()), | 100 GCMChannelStatusRequest::default_poll_interval_seconds()), |
| 101 custom_poll_interval_use_count_(0), |
| 85 delay_removed_for_testing_(false), | 102 delay_removed_for_testing_(false), |
| 86 weak_ptr_factory_(this) { | 103 weak_ptr_factory_(this) { |
| 87 gcm_enabled_ = prefs_->GetBoolean(kGCMChannelStatus); | 104 gcm_enabled_ = prefs_->GetBoolean(kGCMChannelStatus); |
| 88 poll_interval_seconds_ = prefs_->GetInteger(kGCMChannelPollIntervalSeconds); | 105 poll_interval_seconds_ = prefs_->GetInteger(kGCMChannelPollIntervalSeconds); |
| 89 if (poll_interval_seconds_ < | 106 if (poll_interval_seconds_ < |
| 90 GCMChannelStatusRequest::min_poll_interval_seconds()) { | 107 GCMChannelStatusRequest::min_poll_interval_seconds()) { |
| 91 poll_interval_seconds_ = | 108 poll_interval_seconds_ = |
| 92 GCMChannelStatusRequest::min_poll_interval_seconds(); | 109 GCMChannelStatusRequest::min_poll_interval_seconds(); |
| 93 } | 110 } |
| 111 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 112 switches::kCustomPollIntervalMinutes)) { |
| 113 std::string value(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 114 switches::kCustomPollIntervalMinutes)); |
| 115 int minutes = 0; |
| 116 if (base::StringToInt(value, &minutes)) { |
| 117 DCHECK_GE(minutes, kMinCustomPollIntervalMinutes); |
| 118 if (minutes >= kMinCustomPollIntervalMinutes) { |
| 119 poll_interval_seconds_ = minutes * 60; |
| 120 custom_poll_interval_use_count_ = kMaxNumberToUseCustomPollInterval; |
| 121 } |
| 122 } |
| 123 } |
| 94 last_check_time_ = base::Time::FromInternalValue( | 124 last_check_time_ = base::Time::FromInternalValue( |
| 95 prefs_->GetInt64(kGCMChannelLastCheckTime)); | 125 prefs_->GetInt64(kGCMChannelLastCheckTime)); |
| 96 } | 126 } |
| 97 | 127 |
| 98 GCMChannelStatusSyncer::~GCMChannelStatusSyncer() { | 128 GCMChannelStatusSyncer::~GCMChannelStatusSyncer() { |
| 99 } | 129 } |
| 100 | 130 |
| 101 void GCMChannelStatusSyncer::EnsureStarted() { | 131 void GCMChannelStatusSyncer::EnsureStarted() { |
| 102 // Bail out if the request is already scheduled or started. | 132 // Bail out if the request is already scheduled or started. |
| 103 if (weak_ptr_factory_.HasWeakPtrs() || request_) | 133 if (started_) |
| 104 return; | 134 return; |
| 135 started_ = true; |
| 105 | 136 |
| 106 ScheduleRequest(); | 137 ScheduleRequest(); |
| 107 } | 138 } |
| 108 | 139 |
| 109 void GCMChannelStatusSyncer::Stop() { | 140 void GCMChannelStatusSyncer::Stop() { |
| 141 started_ = false; |
| 110 request_.reset(); | 142 request_.reset(); |
| 111 weak_ptr_factory_.InvalidateWeakPtrs(); | 143 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 112 } | 144 } |
| 113 | 145 |
| 114 void GCMChannelStatusSyncer::OnRequestCompleted(bool enabled, | 146 void GCMChannelStatusSyncer::OnRequestCompleted(bool update_received, |
| 147 bool enabled, |
| 115 int poll_interval_seconds) { | 148 int poll_interval_seconds) { |
| 116 DCHECK(request_); | 149 DCHECK(request_); |
| 117 request_.reset(); | 150 request_.reset(); |
| 118 | 151 |
| 119 // Persist the current time as the last request complete time. | 152 // Persist the current time as the last request complete time. |
| 120 last_check_time_ = base::Time::Now(); | 153 last_check_time_ = base::Time::Now(); |
| 121 prefs_->SetInt64(kGCMChannelLastCheckTime, | 154 prefs_->SetInt64(kGCMChannelLastCheckTime, |
| 122 last_check_time_.ToInternalValue()); | 155 last_check_time_.ToInternalValue()); |
| 123 | 156 |
| 124 if (gcm_enabled_ != enabled) { | 157 if (update_received) { |
| 125 gcm_enabled_ = enabled; | 158 if (gcm_enabled_ != enabled) { |
| 126 prefs_->SetBoolean(kGCMChannelStatus, enabled); | 159 gcm_enabled_ = enabled; |
| 127 if (gcm_enabled_) | 160 prefs_->SetBoolean(kGCMChannelStatus, enabled); |
| 128 driver_->Enable(); | 161 if (gcm_enabled_) |
| 129 else | 162 driver_->Enable(); |
| 130 driver_->Disable(); | 163 else |
| 164 driver_->Disable(); |
| 165 } |
| 166 |
| 167 // Skip updating poll interval if the custom one is still in effect. |
| 168 if (!custom_poll_interval_use_count_) { |
| 169 DCHECK_GE(poll_interval_seconds, |
| 170 GCMChannelStatusRequest::min_poll_interval_seconds()); |
| 171 if (poll_interval_seconds_ != poll_interval_seconds) { |
| 172 poll_interval_seconds_ = poll_interval_seconds; |
| 173 prefs_->SetInteger(kGCMChannelPollIntervalSeconds, |
| 174 poll_interval_seconds_); |
| 175 } |
| 176 } |
| 131 } | 177 } |
| 132 | 178 |
| 133 DCHECK_GE(poll_interval_seconds, | 179 // Do not schedule next request if syncer is stopped. |
| 134 GCMChannelStatusRequest::min_poll_interval_seconds()); | 180 if (started_) |
| 135 if (poll_interval_seconds_ != poll_interval_seconds) { | 181 ScheduleRequest(); |
| 136 poll_interval_seconds_ = poll_interval_seconds; | |
| 137 prefs_->SetInteger(kGCMChannelPollIntervalSeconds, poll_interval_seconds_); | |
| 138 } | |
| 139 | |
| 140 ScheduleRequest(); | |
| 141 } | 182 } |
| 142 | 183 |
| 143 void GCMChannelStatusSyncer::ScheduleRequest() { | 184 void GCMChannelStatusSyncer::ScheduleRequest() { |
| 144 current_request_delay_interval_ = GetRequestDelayInterval(); | 185 current_request_delay_interval_ = GetRequestDelayInterval(); |
| 145 base::MessageLoop::current()->PostDelayedTask( | 186 base::MessageLoop::current()->PostDelayedTask( |
| 146 FROM_HERE, | 187 FROM_HERE, |
| 147 base::Bind(&GCMChannelStatusSyncer::StartRequest, | 188 base::Bind(&GCMChannelStatusSyncer::StartRequest, |
| 148 weak_ptr_factory_.GetWeakPtr()), | 189 weak_ptr_factory_.GetWeakPtr()), |
| 149 current_request_delay_interval_); | 190 current_request_delay_interval_); |
| 191 |
| 192 if (custom_poll_interval_use_count_) |
| 193 custom_poll_interval_use_count_--; |
| 150 } | 194 } |
| 151 | 195 |
| 152 void GCMChannelStatusSyncer::StartRequest() { | 196 void GCMChannelStatusSyncer::StartRequest() { |
| 153 DCHECK(!request_); | 197 DCHECK(!request_); |
| 154 | 198 |
| 155 request_.reset(new GCMChannelStatusRequest( | 199 request_.reset(new GCMChannelStatusRequest( |
| 156 request_context_, | 200 request_context_, |
| 157 channel_status_request_url_, | 201 channel_status_request_url_, |
| 158 user_agent_, | 202 user_agent_, |
| 159 base::Bind(&GCMChannelStatusSyncer::OnRequestCompleted, | 203 base::Bind(&GCMChannelStatusSyncer::OnRequestCompleted, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 173 if (delay_seconds < 0) | 217 if (delay_seconds < 0) |
| 174 delay_seconds = 0; | 218 delay_seconds = 0; |
| 175 | 219 |
| 176 if (last_check_time_.is_null()) { | 220 if (last_check_time_.is_null()) { |
| 177 // For the first-time request, add a small delay to avoid sending request at | 221 // For the first-time request, add a small delay to avoid sending request at |
| 178 // browser startup time. | 222 // browser startup time. |
| 179 DCHECK(!delay_seconds); | 223 DCHECK(!delay_seconds); |
| 180 delay_seconds = kFirstTimeDelaySeconds; | 224 delay_seconds = kFirstTimeDelaySeconds; |
| 181 } else { | 225 } else { |
| 182 // Otherwise, add a fuzzing variation to the delay. | 226 // Otherwise, add a fuzzing variation to the delay. |
| 183 delay_seconds += base::RandInt(0, kGCMChannelRequestTimeJitterSeconds); | 227 // The fuzzing variation is off when the custom interval is used. |
| 228 if (!custom_poll_interval_use_count_) |
| 229 delay_seconds += base::RandInt(0, kGCMChannelRequestTimeJitterSeconds); |
| 184 } | 230 } |
| 185 | 231 |
| 186 return base::TimeDelta::FromSeconds(delay_seconds); | 232 return base::TimeDelta::FromSeconds(delay_seconds); |
| 187 } | 233 } |
| 188 | 234 |
| 189 } // namespace gcm | 235 } // namespace gcm |
| OLD | NEW |