| Index: google_apis/gcm/engine/heartbeat_manager.cc
|
| diff --git a/google_apis/gcm/engine/heartbeat_manager.cc b/google_apis/gcm/engine/heartbeat_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e17ea8e77961311247cc3eb76c99690889a213a7
|
| --- /dev/null
|
| +++ b/google_apis/gcm/engine/heartbeat_manager.cc
|
| @@ -0,0 +1,119 @@
|
| +// Copyright 2013 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "google_apis/gcm/engine/heartbeat_manager.h"
|
| +
|
| +#include "google_apis/gcm/protocol/mcs.pb.h"
|
| +#include "net/base/network_change_notifier.h"
|
| +
|
| +namespace gcm {
|
| +
|
| +namespace {
|
| +// The default heartbeat when on a mobile or unknown network .
|
| +const int64 kCellHeartbeatDefaultMs = 1000 * 60 * 28; // 28 minutes.
|
| +// The default heartbeat when on WiFi (also used for ethernet).
|
| +const int64 kWifiHeartbeatDefaultMs = 1000 * 60 * 15; // 15 minutes.
|
| +// The default heartbeat ack interval.
|
| +const int64 kHeartbeatAckDefaultMs = 1000 * 60 * 1; // 1 minute.
|
| +} // namespace
|
| +
|
| +HeartbeatManager::HeartbeatManager()
|
| + : waiting_for_ack_(false),
|
| + heartbeat_interval_ms_(0),
|
| + server_interval_ms_(0),
|
| + heartbeat_timer_(true /* retain user task */,
|
| + false /* not repeating */),
|
| + weak_ptr_factory_(this) {}
|
| +
|
| +HeartbeatManager::~HeartbeatManager() {}
|
| +
|
| +void HeartbeatManager::Start(
|
| + const base::Closure& send_heartbeat_callback,
|
| + const base::Closure& trigger_reconnect_callback) {
|
| + DCHECK(!send_heartbeat_callback.is_null());
|
| + DCHECK(!trigger_reconnect_callback.is_null());
|
| + send_heartbeat_callback_ = send_heartbeat_callback;
|
| + trigger_reconnect_callback_ = trigger_reconnect_callback;
|
| +
|
| + // Kicks off the timer.
|
| + waiting_for_ack_ = false;
|
| + RestartTimer();
|
| +}
|
| +
|
| +void HeartbeatManager::Stop() {
|
| + heartbeat_timer_.Stop();
|
| + waiting_for_ack_ = false;
|
| +}
|
| +
|
| +void HeartbeatManager::OnHeartbeatAcked() {
|
| + if (!heartbeat_timer_.IsRunning())
|
| + return;
|
| +
|
| + DCHECK(!send_heartbeat_callback_.is_null());
|
| + DCHECK(!trigger_reconnect_callback_.is_null());
|
| + waiting_for_ack_ = false;
|
| + RestartTimer();
|
| +}
|
| +
|
| +void HeartbeatManager::UpdateHeartbeatConfig(
|
| + const mcs_proto::HeartbeatConfig& config) {
|
| + if (!config.IsInitialized() ||
|
| + !config.has_interval_ms() ||
|
| + config.interval_ms() <= 0) {
|
| + return;
|
| + }
|
| + DVLOG(1) << "Updating heartbeat interval to " << config.interval_ms();
|
| + server_interval_ms_ = config.interval_ms();
|
| +}
|
| +
|
| +base::TimeTicks HeartbeatManager::GetNextHeartbeatTime() const {
|
| + if (heartbeat_timer_.IsRunning())
|
| + return heartbeat_timer_.desired_run_time();
|
| + else
|
| + return base::TimeTicks();
|
| +}
|
| +
|
| +void HeartbeatManager::OnHeartbeatTriggered() {
|
| + if (waiting_for_ack_) {
|
| + LOG(WARNING) << "Lost connection to MCS, reconnecting.";
|
| + Stop();
|
| + trigger_reconnect_callback_.Run();
|
| + return;
|
| + }
|
| +
|
| + waiting_for_ack_ = true;
|
| + RestartTimer();
|
| + send_heartbeat_callback_.Run();
|
| +}
|
| +
|
| +void HeartbeatManager::RestartTimer() {
|
| + if (!waiting_for_ack_) {
|
| + // Recalculate the timer interval based network type.
|
| + if (server_interval_ms_ != 0) {
|
| + // If a server interval is set, it overrides any local one.
|
| + heartbeat_interval_ms_ = server_interval_ms_;
|
| + } else if (net::NetworkChangeNotifier::GetConnectionType() ==
|
| + net::NetworkChangeNotifier::CONNECTION_WIFI ||
|
| + net::NetworkChangeNotifier::GetConnectionType() ==
|
| + net::NetworkChangeNotifier::CONNECTION_ETHERNET) {
|
| + heartbeat_interval_ms_ = kWifiHeartbeatDefaultMs;
|
| + } else {
|
| + // For unknown connections, use the longer cellular heartbeat interval.
|
| + heartbeat_interval_ms_ = kCellHeartbeatDefaultMs;
|
| + }
|
| + DVLOG(1) << "Sending next heartbeat in "
|
| + << heartbeat_interval_ms_ << " ms.";
|
| + } else {
|
| + heartbeat_interval_ms_ = kHeartbeatAckDefaultMs;
|
| + DVLOG(1) << "Resetting timer for ack with "
|
| + << heartbeat_interval_ms_ << " ms interval.";
|
| + }
|
| + heartbeat_timer_.Start(FROM_HERE,
|
| + base::TimeDelta::FromMilliseconds(
|
| + heartbeat_interval_ms_),
|
| + base::Bind(&HeartbeatManager::OnHeartbeatTriggered,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +} // namespace gcm
|
|
|