OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/gcm_driver/gcm_channel_status_syncer.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/location.h" | |
9 #include "base/logging.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/prefs/pref_registry_simple.h" | |
12 #include "base/prefs/pref_service.h" | |
13 #include "base/rand_util.h" | |
14 #include "components/gcm_driver/gcm_channel_status_request.h" | |
15 #include "components/gcm_driver/gcm_driver.h" | |
16 | |
17 namespace gcm { | |
18 | |
19 namespace { | |
20 | |
21 // The GCM channel's enabled state. | |
22 const char kGCMChannelStatus[] = "gcm.channel_status"; | |
23 | |
24 // The GCM channel's polling interval (in seconds). | |
25 const char kGCMChannelPollIntervalSeconds[] = "gcm.poll_interval"; | |
26 | |
27 // Last time when checking with the GCM channel status server is done. | |
28 const char kGCMChannelLastCheckTime[] = "gcm.check_time"; | |
29 | |
30 // A small delay to avoid sending request at browser startup time for first-time | |
31 // request. | |
32 const int kFirstTimeDelaySeconds = 1 * 60; // 1 minute. | |
33 | |
34 // The fuzzing variation added to the polling delay. | |
35 const int kGCMChannelRequestTimeJitterSeconds = 15 * 60; // 15 minues. | |
36 | |
37 } // namespace | |
38 | |
39 // static | |
40 void GCMChannelStatusSyncer::RegisterPrefs(PrefRegistrySimple* registry) { | |
41 registry->RegisterBooleanPref(kGCMChannelStatus, true); | |
42 registry->RegisterIntegerPref( | |
43 kGCMChannelPollIntervalSeconds, | |
44 GCMChannelStatusRequest::default_poll_interval_seconds()); | |
45 registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0); | |
46 } | |
47 | |
48 // static | |
49 void GCMChannelStatusSyncer::RegisterProfilePrefs( | |
50 user_prefs::PrefRegistrySyncable* registry) { | |
51 registry->RegisterBooleanPref( | |
52 kGCMChannelStatus, | |
53 true, | |
54 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
55 registry->RegisterIntegerPref( | |
56 kGCMChannelPollIntervalSeconds, | |
57 GCMChannelStatusRequest::default_poll_interval_seconds(), | |
58 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
59 registry->RegisterInt64Pref( | |
60 kGCMChannelLastCheckTime, | |
61 0, | |
62 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
63 } | |
64 | |
65 // static | |
66 int GCMChannelStatusSyncer::first_time_delay_seconds() { | |
67 return kFirstTimeDelaySeconds; | |
68 } | |
69 | |
70 GCMChannelStatusSyncer::GCMChannelStatusSyncer( | |
71 GCMDriver* driver, | |
72 PrefService* prefs, | |
73 scoped_refptr<net::URLRequestContextGetter> request_context) | |
74 : driver_(driver), | |
75 prefs_(prefs), | |
76 request_context_(request_context), | |
77 gcm_enabled_(true), | |
78 poll_interval_seconds_( | |
79 GCMChannelStatusRequest::default_poll_interval_seconds()), | |
80 delay_removed_for_testing_(false), | |
81 weak_ptr_factory_(this) { | |
82 gcm_enabled_ = prefs_->GetBoolean(kGCMChannelStatus); | |
83 poll_interval_seconds_ = prefs_->GetInteger(kGCMChannelPollIntervalSeconds); | |
84 if (poll_interval_seconds_ < | |
85 GCMChannelStatusRequest::min_poll_interval_seconds()) { | |
86 poll_interval_seconds_ = | |
87 GCMChannelStatusRequest::min_poll_interval_seconds(); | |
88 } | |
89 last_check_time_ = base::Time::FromInternalValue( | |
90 prefs_->GetInt64(kGCMChannelLastCheckTime)); | |
91 } | |
92 | |
93 GCMChannelStatusSyncer::~GCMChannelStatusSyncer() { | |
94 } | |
95 | |
96 void GCMChannelStatusSyncer::EnsureStarted() { | |
97 // Bail out if already started. | |
98 if (request_) | |
99 return; | |
100 | |
101 ScheduleRequest(); | |
102 } | |
103 | |
104 void GCMChannelStatusSyncer::Stop() { | |
105 request_.reset(); | |
106 weak_ptr_factory_.InvalidateWeakPtrs(); | |
107 } | |
108 | |
109 void GCMChannelStatusSyncer::OnRequestCompleted(bool enabled, | |
110 int poll_interval_seconds) { | |
111 DCHECK(request_); | |
112 request_.reset(); | |
113 | |
114 // Persist the current time as the last request complete time. | |
115 last_check_time_ = base::Time::Now(); | |
fgorski
2014/09/11 18:24:35
injected clock is typically more useful for testin
jianli
2014/09/11 21:04:30
Agreed. For now, testing with real clock seems to
| |
116 prefs_->SetInt64(kGCMChannelLastCheckTime, | |
117 last_check_time_.ToInternalValue()); | |
118 | |
119 if (gcm_enabled_ != enabled) { | |
120 gcm_enabled_ = enabled; | |
121 prefs_->SetBoolean(kGCMChannelStatus, enabled); | |
122 if (gcm_enabled_) | |
123 driver_->Enable(); | |
124 else | |
125 driver_->Disable(); | |
126 } | |
127 | |
128 if (poll_interval_seconds_ != poll_interval_seconds) { | |
129 poll_interval_seconds_ = poll_interval_seconds; | |
fgorski
2014/09/11 18:24:35
this code should check for min poll interval.
try
jianli
2014/09/11 21:04:30
OnRequestCompleted is called with min value enforc
| |
130 prefs_->SetInteger(kGCMChannelPollIntervalSeconds, poll_interval_seconds_); | |
131 } | |
132 | |
133 ScheduleRequest(); | |
134 } | |
135 | |
136 void GCMChannelStatusSyncer::ScheduleRequest() { | |
137 current_request_delay_interval_ = GetRequestDelayInterval(); | |
138 base::MessageLoop::current()->PostDelayedTask( | |
139 FROM_HERE, | |
140 base::Bind(&GCMChannelStatusSyncer::StartRequest, | |
141 weak_ptr_factory_.GetWeakPtr()), | |
142 current_request_delay_interval_); | |
143 } | |
144 | |
145 void GCMChannelStatusSyncer::StartRequest() { | |
146 DCHECK(!request_); | |
147 | |
148 request_.reset(new GCMChannelStatusRequest( | |
149 request_context_, | |
150 base::Bind(&GCMChannelStatusSyncer::OnRequestCompleted, | |
151 weak_ptr_factory_.GetWeakPtr()))); | |
152 request_->Start(); | |
153 } | |
154 | |
155 base::TimeDelta GCMChannelStatusSyncer::GetRequestDelayInterval() const { | |
156 // No delay during testing. | |
157 if (delay_removed_for_testing_) | |
158 return base::TimeDelta(); | |
159 | |
160 // Make sure that checking with server occurs at polling interval, regardless | |
161 // whether the browser restarts. | |
162 int delay_seconds = static_cast<int>(poll_interval_seconds_ - | |
163 (base::Time::Now() - last_check_time_).InSeconds()); | |
164 if (delay_seconds < 0) | |
165 delay_seconds = 0; | |
166 | |
167 if (last_check_time_.is_null()) { | |
168 // For the first-time request, add a small delay to avoid sending request at | |
169 // browser startup time. | |
170 DCHECK(!delay_seconds); | |
171 delay_seconds = kFirstTimeDelaySeconds; | |
172 } else { | |
173 // Otherwise, add a fuzzing variation to the delay. | |
174 delay_seconds += base::RandInt(0, kGCMChannelRequestTimeJitterSeconds); | |
175 } | |
176 | |
177 return base::TimeDelta::FromSeconds(delay_seconds); | |
178 } | |
179 | |
180 } // namespace gcm | |
OLD | NEW |