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 |