Chromium Code Reviews| 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 "google_apis/gcm/engine/heartbeat_manager.h" | 5 #include "google_apis/gcm/engine/heartbeat_manager.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/power_monitor/power_monitor.h" | |
| 9 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| 10 #include "base/timer/timer.h" | 11 #include "base/timer/timer.h" |
| 11 #include "google_apis/gcm/protocol/mcs.pb.h" | 12 #include "google_apis/gcm/protocol/mcs.pb.h" |
| 12 #include "net/base/network_change_notifier.h" | 13 #include "net/base/network_change_notifier.h" |
| 13 | 14 |
| 14 namespace gcm { | 15 namespace gcm { |
| 15 | 16 |
| 16 namespace { | 17 namespace { |
| 17 // The default heartbeat when on a mobile or unknown network . | 18 // The default heartbeat when on a mobile or unknown network . |
| 18 const int64 kCellHeartbeatDefaultMs = 1000 * 60 * 28; // 28 minutes. | 19 const int64 kCellHeartbeatDefaultMs = 1000 * 60 * 28; // 28 minutes. |
| 19 // The default heartbeat when on WiFi (also used for ethernet). | 20 // The default heartbeat when on WiFi (also used for ethernet). |
| 20 const int64 kWifiHeartbeatDefaultMs = 1000 * 60 * 15; // 15 minutes. | 21 const int64 kWifiHeartbeatDefaultMs = 1000 * 60 * 15; // 15 minutes. |
| 21 // The default heartbeat ack interval. | 22 // The default heartbeat ack interval. |
| 22 const int64 kHeartbeatAckDefaultMs = 1000 * 60 * 1; // 1 minute. | 23 const int64 kHeartbeatAckDefaultMs = 1000 * 60 * 1; // 1 minute. |
| 24 | |
| 25 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 23 // The period at which to check if the heartbeat time has passed. Used to | 26 // The period at which to check if the heartbeat time has passed. Used to |
| 24 // protect against platforms where the timer is delayed by the system being | 27 // protect against platforms where the timer is delayed by the system being |
| 25 // suspended. | 28 // suspended. Only needed on linux because the other OSes provide a standard |
| 29 // way to be notified of system suspend and resume events. | |
| 26 const int kHeartbeatMissedCheckMs = 1000 * 60 * 5; // 5 minutes. | 30 const int kHeartbeatMissedCheckMs = 1000 * 60 * 5; // 5 minutes. |
| 31 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 32 | |
| 27 } // namespace | 33 } // namespace |
| 28 | 34 |
| 29 HeartbeatManager::HeartbeatManager() | 35 HeartbeatManager::HeartbeatManager() |
| 30 : waiting_for_ack_(false), | 36 : waiting_for_ack_(false), |
| 31 heartbeat_interval_ms_(0), | 37 heartbeat_interval_ms_(0), |
| 32 server_interval_ms_(0), | 38 server_interval_ms_(0), |
| 33 heartbeat_timer_(new base::Timer(true /* retain_user_task */, | 39 heartbeat_timer_(new base::Timer(true /* retain_user_task */, |
| 34 false /* is_repeating */)), | 40 false /* is_repeating */)), |
| 35 weak_ptr_factory_(this) {} | 41 weak_ptr_factory_(this) { |
| 42 // Listen for system suspend and resume events. | |
| 43 base::PowerMonitor* monitor = base::PowerMonitor::Get(); | |
| 44 if (monitor) | |
| 45 monitor->AddObserver(this); | |
| 46 } | |
| 36 | 47 |
| 37 HeartbeatManager::~HeartbeatManager() {} | 48 HeartbeatManager::~HeartbeatManager() { |
| 49 // Stop listening for system suspend and resume events. | |
| 50 base::PowerMonitor* monitor = base::PowerMonitor::Get(); | |
| 51 if (monitor) | |
| 52 monitor->RemoveObserver(this); | |
| 53 } | |
| 38 | 54 |
| 39 void HeartbeatManager::Start( | 55 void HeartbeatManager::Start( |
| 40 const base::Closure& send_heartbeat_callback, | 56 const base::Closure& send_heartbeat_callback, |
| 41 const base::Closure& trigger_reconnect_callback) { | 57 const base::Closure& trigger_reconnect_callback) { |
| 42 DCHECK(!send_heartbeat_callback.is_null()); | 58 DCHECK(!send_heartbeat_callback.is_null()); |
| 43 DCHECK(!trigger_reconnect_callback.is_null()); | 59 DCHECK(!trigger_reconnect_callback.is_null()); |
| 44 send_heartbeat_callback_ = send_heartbeat_callback; | 60 send_heartbeat_callback_ = send_heartbeat_callback; |
| 45 trigger_reconnect_callback_ = trigger_reconnect_callback; | 61 trigger_reconnect_callback_ = trigger_reconnect_callback; |
| 46 | 62 |
| 47 // Kicks off the timer. | 63 // Kicks off the timer. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 heartbeat_timer_->desired_run_time() - base::TimeTicks::Now(); | 105 heartbeat_timer_->desired_run_time() - base::TimeTicks::Now(); |
| 90 base::Closure timer_task(heartbeat_timer_->user_task()); | 106 base::Closure timer_task(heartbeat_timer_->user_task()); |
| 91 | 107 |
| 92 heartbeat_timer_->Stop(); | 108 heartbeat_timer_->Stop(); |
| 93 heartbeat_timer_ = timer.Pass(); | 109 heartbeat_timer_ = timer.Pass(); |
| 94 | 110 |
| 95 if (was_running) | 111 if (was_running) |
| 96 heartbeat_timer_->Start(FROM_HERE, remaining_delay, timer_task); | 112 heartbeat_timer_->Start(FROM_HERE, remaining_delay, timer_task); |
| 97 } | 113 } |
| 98 | 114 |
| 115 void HeartbeatManager::OnResume() { | |
| 116 CheckForMissedHeartbeat(); | |
|
Nicolas Zea
2015/03/09 18:42:51
On Linux, will this just never be called?
Chirantan Ekbote
2015/03/09 19:23:59
Yup, that's correct.
| |
| 117 } | |
| 118 | |
| 99 void HeartbeatManager::OnHeartbeatTriggered() { | 119 void HeartbeatManager::OnHeartbeatTriggered() { |
| 100 // Reset the weak pointers used for heartbeat checks. | 120 // Reset the weak pointers used for heartbeat checks. |
| 101 weak_ptr_factory_.InvalidateWeakPtrs(); | 121 weak_ptr_factory_.InvalidateWeakPtrs(); |
| 102 | 122 |
| 103 if (waiting_for_ack_) { | 123 if (waiting_for_ack_) { |
| 104 LOG(WARNING) << "Lost connection to MCS, reconnecting."; | 124 LOG(WARNING) << "Lost connection to MCS, reconnecting."; |
| 105 Stop(); | 125 Stop(); |
| 106 trigger_reconnect_callback_.Run(); | 126 trigger_reconnect_callback_.Run(); |
| 107 return; | 127 return; |
| 108 } | 128 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 137 | 157 |
| 138 heartbeat_expected_time_ = | 158 heartbeat_expected_time_ = |
| 139 base::Time::Now() + | 159 base::Time::Now() + |
| 140 base::TimeDelta::FromMilliseconds(heartbeat_interval_ms_); | 160 base::TimeDelta::FromMilliseconds(heartbeat_interval_ms_); |
| 141 heartbeat_timer_->Start(FROM_HERE, | 161 heartbeat_timer_->Start(FROM_HERE, |
| 142 base::TimeDelta::FromMilliseconds( | 162 base::TimeDelta::FromMilliseconds( |
| 143 heartbeat_interval_ms_), | 163 heartbeat_interval_ms_), |
| 144 base::Bind(&HeartbeatManager::OnHeartbeatTriggered, | 164 base::Bind(&HeartbeatManager::OnHeartbeatTriggered, |
| 145 weak_ptr_factory_.GetWeakPtr())); | 165 weak_ptr_factory_.GetWeakPtr())); |
| 146 | 166 |
| 147 // TODO(zea): Polling is not a particularly good way to detect the missed | 167 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) |
| 148 // heartbeat. Ideally we should be listening to wake-from-suspend events, | 168 // Windows, Mac, Android, iOS, and Chrome OS all provide a way to be notified |
| 149 // although that would require platform-specific implementations. | 169 // when the system is suspending or resuming. The only one that does not is |
| 170 // Linux so we need to poll to check for missed heartbeats. | |
| 150 base::MessageLoop::current()->PostDelayedTask( | 171 base::MessageLoop::current()->PostDelayedTask( |
| 151 FROM_HERE, | 172 FROM_HERE, |
| 152 base::Bind(&HeartbeatManager::CheckForMissedHeartbeat, | 173 base::Bind(&HeartbeatManager::CheckForMissedHeartbeat, |
| 153 weak_ptr_factory_.GetWeakPtr()), | 174 weak_ptr_factory_.GetWeakPtr()), |
| 154 base::TimeDelta::FromMilliseconds(kHeartbeatMissedCheckMs)); | 175 base::TimeDelta::FromMilliseconds(kHeartbeatMissedCheckMs)); |
| 176 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 155 } | 177 } |
| 156 | 178 |
| 157 void HeartbeatManager::CheckForMissedHeartbeat() { | 179 void HeartbeatManager::CheckForMissedHeartbeat() { |
| 158 // If there's no heartbeat pending, return without doing anything. | 180 // If there's no heartbeat pending, return without doing anything. |
| 159 if (heartbeat_expected_time_.is_null()) | 181 if (heartbeat_expected_time_.is_null()) |
| 160 return; | 182 return; |
| 161 | 183 |
| 162 // If the heartbeat has been missed, manually trigger it. | 184 // If the heartbeat has been missed, manually trigger it. |
| 163 if (base::Time::Now() > heartbeat_expected_time_) { | 185 if (base::Time::Now() > heartbeat_expected_time_) { |
| 164 UMA_HISTOGRAM_LONG_TIMES("GCM.HeartbeatMissedDelta", | 186 UMA_HISTOGRAM_LONG_TIMES("GCM.HeartbeatMissedDelta", |
| 165 base::Time::Now() - heartbeat_expected_time_); | 187 base::Time::Now() - heartbeat_expected_time_); |
| 166 OnHeartbeatTriggered(); | 188 OnHeartbeatTriggered(); |
| 167 return; | 189 return; |
| 168 } | 190 } |
| 169 | 191 |
| 192 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 170 // Otherwise check again later. | 193 // Otherwise check again later. |
| 171 base::MessageLoop::current()->PostDelayedTask( | 194 base::MessageLoop::current()->PostDelayedTask( |
| 172 FROM_HERE, | 195 FROM_HERE, |
| 173 base::Bind(&HeartbeatManager::CheckForMissedHeartbeat, | 196 base::Bind(&HeartbeatManager::CheckForMissedHeartbeat, |
| 174 weak_ptr_factory_.GetWeakPtr()), | 197 weak_ptr_factory_.GetWeakPtr()), |
| 175 base::TimeDelta::FromMilliseconds(kHeartbeatMissedCheckMs)); | 198 base::TimeDelta::FromMilliseconds(kHeartbeatMissedCheckMs)); |
| 199 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS) | |
| 176 } | 200 } |
| 177 | 201 |
| 178 } // namespace gcm | 202 } // namespace gcm |
| OLD | NEW |