// Copyright 2014 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 "components/gcm_driver/gcm_client_impl.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/time/default_clock.h"
#include "base/timer/timer.h"
#include "components/crx_file/id_util.h"
#include "components/gcm_driver/crypto/gcm_decryption_result.h"
#include "components/gcm_driver/features.h"
#include "components/gcm_driver/gcm_account_mapper.h"
#include "components/gcm_driver/gcm_backoff_policy.h"
#include "google_apis/gcm/base/encryptor.h"
#include "google_apis/gcm/base/mcs_message.h"
#include "google_apis/gcm/base/mcs_util.h"
#include "google_apis/gcm/engine/checkin_request.h"
#include "google_apis/gcm/engine/connection_factory_impl.h"
#include "google_apis/gcm/engine/gcm_registration_request_handler.h"
#include "google_apis/gcm/engine/gcm_store_impl.h"
#include "google_apis/gcm/engine/gcm_unregistration_request_handler.h"
#include "google_apis/gcm/engine/instance_id_delete_token_request_handler.h"
#include "google_apis/gcm/engine/instance_id_get_token_request_handler.h"
#include "google_apis/gcm/monitoring/gcm_stats_recorder.h"
#include "google_apis/gcm/protocol/checkin.pb.h"
#include "google_apis/gcm/protocol/mcs.pb.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "url/gurl.h"

namespace gcm {

// It is okay to append to the enum if these states grow. DO NOT reorder,
// renumber or otherwise reuse existing values.
// Do not assign an explicit value to REGISTRATION_CACHE_STATUS_COUNT, as
// this lets the compiler keep it up to date.
enum class RegistrationCacheStatus {
  REGISTRATION_NOT_FOUND = 0,
  REGISTRATION_FOUND_AND_FRESH = 1,
  REGISTRATION_FOUND_BUT_STALE = 2,
  REGISTRATION_FOUND_BUT_SENDERS_DONT_MATCH = 3,
  // NOTE: always keep this entry at the end. Add new value only immediately
  // above this line. Make sure to update the corresponding histogram enum
  // accordingly.
  REGISTRATION_CACHE_STATUS_COUNT
};

namespace {

// Indicates a message type of the received message.
enum MessageType {
  UNKNOWN,           // Undetermined type.
  DATA_MESSAGE,      // Regular data message.
  DELETED_MESSAGES,  // Messages were deleted on the server.
  SEND_ERROR,        // Error sending a message.
};

enum ResetStoreError {
  DESTROYING_STORE_FAILED,
  INFINITE_STORE_RESET,
  // NOTE: always keep this entry at the end. Add new value only immediately
  // above this line. Make sure to update the corresponding histogram enum
  // accordingly.
  RESET_STORE_ERROR_COUNT
};

const int kMaxRegistrationRetries = 5;
const int kMaxUnregistrationRetries = 5;
const char kDeletedCountKey[] = "total_deleted";
const char kMessageTypeDataMessage[] = "gcm";
const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
const char kMessageTypeKey[] = "message_type";
const char kMessageTypeSendErrorKey[] = "send_error";
const char kSubtypeKey[] = "subtype";
const char kSendMessageFromValue[] = "gcm@chrome.com";
const int64_t kDefaultUserSerialNumber = 0LL;
const int kDestroyGCMStoreDelayMS = 5 * 60 * 1000;  // 5 minutes.

GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) {
  switch (status) {
    case MCSClient::QUEUED:
      return GCMClient::SUCCESS;
    case MCSClient::MESSAGE_TOO_LARGE:
      return GCMClient::INVALID_PARAMETER;
    case MCSClient::QUEUE_SIZE_LIMIT_REACHED:
    case MCSClient::APP_QUEUE_SIZE_LIMIT_REACHED:
    case MCSClient::NO_CONNECTION_ON_ZERO_TTL:
    case MCSClient::TTL_EXCEEDED:
      return GCMClient::NETWORK_ERROR;
    case MCSClient::SENT:
    case MCSClient::SEND_STATUS_COUNT:
      NOTREACHED();
      break;
  }
  return GCMClientImpl::UNKNOWN_ERROR;
}

void ToCheckinProtoVersion(
    const GCMClient::ChromeBuildInfo& chrome_build_info,
    checkin_proto::ChromeBuildProto* android_build_info) {
  checkin_proto::ChromeBuildProto_Platform platform =
      checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
  switch (chrome_build_info.platform) {
    case GCMClient::PLATFORM_WIN:
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN;
      break;
    case GCMClient::PLATFORM_MAC:
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC;
      break;
    case GCMClient::PLATFORM_LINUX:
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
      break;
    case GCMClient::PLATFORM_IOS:
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_IOS;
      break;
    case GCMClient::PLATFORM_ANDROID:
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_ANDROID;
      break;
    case GCMClient::PLATFORM_CROS:
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS;
      break;
    case GCMClient::PLATFORM_UNSPECIFIED:
      // For unknown platform, return as LINUX.
      platform = checkin_proto::ChromeBuildProto_Platform_PLATFORM_LINUX;
      break;
  }
  android_build_info->set_platform(platform);

  checkin_proto::ChromeBuildProto_Channel channel =
      checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN;
  switch (chrome_build_info.channel) {
    case GCMClient::CHANNEL_STABLE:
      channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_STABLE;
      break;
    case GCMClient::CHANNEL_BETA:
      channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_BETA;
      break;
    case GCMClient::CHANNEL_DEV:
      channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_DEV;
      break;
    case GCMClient::CHANNEL_CANARY:
      channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_CANARY;
      break;
    case GCMClient::CHANNEL_UNKNOWN:
      channel = checkin_proto::ChromeBuildProto_Channel_CHANNEL_UNKNOWN;
      break;
  }
  android_build_info->set_channel(channel);

  android_build_info->set_chrome_version(chrome_build_info.version);
}

MessageType DecodeMessageType(const std::string& value) {
  if (kMessageTypeDeletedMessagesKey == value)
    return DELETED_MESSAGES;
  if (kMessageTypeSendErrorKey == value)
    return SEND_ERROR;
  if (kMessageTypeDataMessage == value)
    return DATA_MESSAGE;
  return UNKNOWN;
}

int ConstructGCMVersion(const std::string& chrome_version) {
  // Major Chrome version is passed as GCM version.
  size_t pos = chrome_version.find('.');
  if (pos == std::string::npos) {
    NOTREACHED();
    return 0;
  }

  int gcm_version = 0;
  base::StringToInt(
      base::StringPiece(chrome_version.c_str(), pos), &gcm_version);
  return gcm_version;
}

std::string SerializeInstanceIDData(const std::string& instance_id,
                                    const std::string& extra_data) {
  DCHECK(!instance_id.empty() && !extra_data.empty());
  DCHECK(instance_id.find(',') == std::string::npos);
  return instance_id + "," + extra_data;
}

bool DeserializeInstanceIDData(const std::string& serialized_data,
                               std::string* instance_id,
                               std::string* extra_data) {
  DCHECK(instance_id && extra_data);
  std::size_t pos = serialized_data.find(',');
  if (pos == std::string::npos)
    return false;
  *instance_id = serialized_data.substr(0, pos);
  *extra_data = serialized_data.substr(pos + 1);
  return !instance_id->empty() && !extra_data->empty();
}

bool InstanceIDUsesSubtypeForAppId(const std::string& app_id) {
  // Always use subtypes with Instance ID, except for Chrome Apps/Extensions.
  return !crx_file::id_util::IdIsValid(app_id);
}

void RecordResetStoreErrorToUMA(ResetStoreError error) {
  UMA_HISTOGRAM_ENUMERATION("GCM.ResetStore", error, RESET_STORE_ERROR_COUNT);
}

}  // namespace

void RecordRegistrationRequestToUMA(gcm::RegistrationCacheStatus status) {
  UMA_HISTOGRAM_ENUMERATION(
      "GCM.RegistrationCacheStatus", status,
      RegistrationCacheStatus::REGISTRATION_CACHE_STATUS_COUNT);
}
GCMInternalsBuilder::GCMInternalsBuilder() {}
GCMInternalsBuilder::~GCMInternalsBuilder() {}

base::Clock* GCMInternalsBuilder::GetClock() {
  return base::DefaultClock::GetInstance();
}

std::unique_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient(
    const std::string& version,
    base::Clock* clock,
    ConnectionFactory* connection_factory,
    GCMStore* gcm_store,
    scoped_refptr<base::SequencedTaskRunner> io_task_runner,
    GCMStatsRecorder* recorder) {
  return std::unique_ptr<MCSClient>(
      new MCSClient(version, clock, connection_factory, gcm_store,
                    std::move(io_task_runner), recorder));
}

std::unique_ptr<ConnectionFactory> GCMInternalsBuilder::BuildConnectionFactory(
    const std::vector<GURL>& endpoints,
    const net::BackoffEntry::Policy& backoff_policy,
    base::RepeatingCallback<
        void(network::mojom::ProxyResolvingSocketFactoryRequest)>
        get_socket_factory_callback,
    scoped_refptr<base::SequencedTaskRunner> io_task_runner,
    GCMStatsRecorder* recorder,
    network::NetworkConnectionTracker* network_connection_tracker) {
  return std::make_unique<ConnectionFactoryImpl>(
      endpoints, backoff_policy, std::move(get_socket_factory_callback),
      std::move(io_task_runner), recorder, network_connection_tracker);
}

GCMClientImpl::CheckinInfo::CheckinInfo()
    : android_id(0), secret(0), accounts_set(false) {
}

GCMClientImpl::CheckinInfo::~CheckinInfo() {
}

void GCMClientImpl::CheckinInfo::SnapshotCheckinAccounts() {
  last_checkin_accounts.clear();
  for (auto iter = account_tokens.begin(); iter != account_tokens.end();
       ++iter) {
    last_checkin_accounts.insert(iter->first);
  }
}

void GCMClientImpl::CheckinInfo::Reset() {
  android_id = 0;
  secret = 0;
  accounts_set = false;
  account_tokens.clear();
  last_checkin_accounts.clear();
}

GCMClientImpl::GCMClientImpl(
    std::unique_ptr<GCMInternalsBuilder> internals_builder)
    : internals_builder_(std::move(internals_builder)),
      state_(UNINITIALIZED),
      delegate_(nullptr),
      start_mode_(DELAYED_START),
      clock_(internals_builder_->GetClock()),
      gcm_store_reset_(false),
      network_connection_tracker_(nullptr) {}

GCMClientImpl::~GCMClientImpl() {
}

void GCMClientImpl::Initialize(
    const ChromeBuildInfo& chrome_build_info,
    const base::FilePath& path,
    const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
    scoped_refptr<base::SequencedTaskRunner> io_task_runner,
    base::RepeatingCallback<
        void(network::mojom::ProxyResolvingSocketFactoryRequest)>
        get_socket_factory_callback,
    const scoped_refptr<network::SharedURLLoaderFactory>& url_loader_factory,
    network::NetworkConnectionTracker* network_connection_tracker,
    std::unique_ptr<Encryptor> encryptor,
    GCMClient::Delegate* delegate) {
  DCHECK_EQ(UNINITIALIZED, state_);
  DCHECK(delegate);
  DCHECK(io_task_runner);
  DCHECK(io_task_runner->RunsTasksInCurrentSequence());

  get_socket_factory_callback_ = std::move(get_socket_factory_callback);
  url_loader_factory_ = url_loader_factory;
  network_connection_tracker_ = network_connection_tracker;
  chrome_build_info_ = chrome_build_info;
  gcm_store_.reset(
      new GCMStoreImpl(path, blocking_task_runner, std::move(encryptor)));
  delegate_ = delegate;
  io_task_runner_ = std::move(io_task_runner);
  recorder_.SetDelegate(this);
  state_ = INITIALIZED;
}

void GCMClientImpl::Start(StartMode start_mode) {
  DCHECK_NE(UNINITIALIZED, state_);
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  if (state_ == LOADED) {
    // Start the GCM if not yet.
    if (start_mode == IMMEDIATE_START) {
      // Give up the scheduling to wipe out the store since now some one starts
      // to use GCM.
      destroying_gcm_store_ptr_factory_.InvalidateWeakPtrs();

      StartGCM();
    }
    return;
  }

  // The delay start behavior will be abandoned when Start has been called
  // once with IMMEDIATE_START behavior.
  if (start_mode == IMMEDIATE_START)
    start_mode_ = IMMEDIATE_START;

  // Bail out if the loading is not started or completed.
  if (state_ != INITIALIZED)
    return;

  // Once the loading is completed, the check-in will be initiated.
  // If we're in lazy start mode, don't create a new store since none is really
  // using GCM functionality yet.
  gcm_store_->Load(
      (start_mode == IMMEDIATE_START) ?
          GCMStore::CREATE_IF_MISSING :
          GCMStore::DO_NOT_CREATE,
      base::Bind(&GCMClientImpl::OnLoadCompleted,
                 weak_ptr_factory_.GetWeakPtr()));
  state_ = LOADING;
}

void GCMClientImpl::OnLoadCompleted(
    std::unique_ptr<GCMStore::LoadResult> result) {
  DCHECK_EQ(LOADING, state_);
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  if (!result->success) {
    if (result->store_does_not_exist) {
      if (start_mode_ == IMMEDIATE_START) {
        // An immediate start was requested during the delayed start that just
        // completed. Perform it now.
        gcm_store_->Load(GCMStore::CREATE_IF_MISSING,
                         base::Bind(&GCMClientImpl::OnLoadCompleted,
                                    weak_ptr_factory_.GetWeakPtr()));
      } else {
        // In the case that the store does not exist, set |state_| back to
        // INITIALIZED such that store loading could be triggered again when
        // Start() is called with IMMEDIATE_START.
        state_ = INITIALIZED;
      }
    } else {
      // Otherwise, destroy the store to try again.
      ResetStore();
    }
    return;
  }
  gcm_store_reset_ = false;

  device_checkin_info_.android_id = result->device_android_id;
  device_checkin_info_.secret = result->device_security_token;
  device_checkin_info_.last_checkin_accounts = result->last_checkin_accounts;
  // A case where there were previously no accounts reported with checkin is
  // considered to be the same as when the list of accounts is empty. It enables
  // scheduling a periodic checkin for devices with no signed in users
  // immediately after restart, while keeping |accounts_set == false| delays the
  // checkin until the list of accounts is set explicitly.
  if (result->last_checkin_accounts.size() == 0)
    device_checkin_info_.accounts_set = true;
  last_checkin_time_ = result->last_checkin_time;
  gservices_settings_.UpdateFromLoadResult(*result);

  for (auto iter = result->registrations.begin();
       iter != result->registrations.end();
       ++iter) {
    std::string registration_id;
    scoped_refptr<RegistrationInfo> registration =
        RegistrationInfo::BuildFromString(iter->first, iter->second,
                                          &registration_id);
    // TODO(jianli): Add UMA to track the error case.
    if (registration)
      registrations_.emplace(std::move(registration), registration_id);
  }

  for (auto iter = result->instance_id_data.begin();
       iter != result->instance_id_data.end();
       ++iter) {
    std::string instance_id;
    std::string extra_data;
    if (DeserializeInstanceIDData(iter->second, &instance_id, &extra_data))
      instance_id_data_[iter->first] = std::make_pair(instance_id, extra_data);
  }

  load_result_ = std::move(result);
  state_ = LOADED;

  // Don't initiate the GCM connection when GCM is in delayed start mode and
  // not any standalone app has registered GCM yet.
  if (start_mode_ == DELAYED_START && !HasStandaloneRegisteredApp()) {
    // If no standalone app is using GCM and the device ID is present, schedule
    // to have the store wiped out.
    if (device_checkin_info_.android_id) {
      io_task_runner_->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&GCMClientImpl::DestroyStoreWhenNotNeeded,
                         destroying_gcm_store_ptr_factory_.GetWeakPtr()),
          base::TimeDelta::FromMilliseconds(kDestroyGCMStoreDelayMS));
    }

    return;
  }

  StartGCM();
}

void GCMClientImpl::StartGCM() {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  // Taking over the value of account_mappings before passing the ownership of
  // load result to InitializeMCSClient.
  std::vector<AccountMapping> account_mappings;
  account_mappings.swap(load_result_->account_mappings);
  base::Time last_token_fetch_time = load_result_->last_token_fetch_time;

  InitializeMCSClient();

  if (device_checkin_info_.IsValid()) {
    SchedulePeriodicCheckin();
    OnReady(account_mappings, last_token_fetch_time);
    return;
  }

  state_ = INITIAL_DEVICE_CHECKIN;
  device_checkin_info_.Reset();
  StartCheckin();
}

void GCMClientImpl::InitializeMCSClient() {
  DCHECK(network_connection_tracker_);
  std::vector<GURL> endpoints;
  endpoints.push_back(gservices_settings_.GetMCSMainEndpoint());
  GURL fallback_endpoint = gservices_settings_.GetMCSFallbackEndpoint();
  if (fallback_endpoint.is_valid())
    endpoints.push_back(fallback_endpoint);
  connection_factory_ = internals_builder_->BuildConnectionFactory(
      endpoints, GetGCMBackoffPolicy(), get_socket_factory_callback_,
      io_task_runner_, &recorder_, network_connection_tracker_);
  connection_factory_->SetConnectionListener(this);
  mcs_client_ = internals_builder_->BuildMCSClient(
      chrome_build_info_.version, clock_, connection_factory_.get(),
      gcm_store_.get(), io_task_runner_, &recorder_);

  mcs_client_->Initialize(
      base::Bind(&GCMClientImpl::OnMCSError, weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&GCMClientImpl::OnMessageReceivedFromMCS,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&GCMClientImpl::OnMessageSentToMCS,
                 weak_ptr_factory_.GetWeakPtr()),
      std::move(load_result_));
}

void GCMClientImpl::OnFirstTimeDeviceCheckinCompleted(
    const CheckinInfo& checkin_info) {
  DCHECK(!device_checkin_info_.IsValid());

  device_checkin_info_.android_id = checkin_info.android_id;
  device_checkin_info_.secret = checkin_info.secret;
  // If accounts were not set by now, we can consider them set (to empty list)
  // to make sure periodic checkins get scheduled after initial checkin.
  device_checkin_info_.accounts_set = true;
  gcm_store_->SetDeviceCredentials(
      checkin_info.android_id, checkin_info.secret,
      base::Bind(&GCMClientImpl::SetDeviceCredentialsCallback,
                 weak_ptr_factory_.GetWeakPtr()));

  OnReady(std::vector<AccountMapping>(), base::Time());
}

void GCMClientImpl::OnReady(const std::vector<AccountMapping>& account_mappings,
                            const base::Time& last_token_fetch_time) {
  state_ = READY;
  StartMCSLogin();

  delegate_->OnGCMReady(account_mappings, last_token_fetch_time);
}

void GCMClientImpl::StartMCSLogin() {
  DCHECK_EQ(READY, state_);
  DCHECK(device_checkin_info_.IsValid());
  mcs_client_->Login(device_checkin_info_.android_id,
                     device_checkin_info_.secret);
}

void GCMClientImpl::DestroyStoreWhenNotNeeded() {
  if (state_ != LOADED || start_mode_ != DELAYED_START)
    return;

  gcm_store_->Destroy(base::Bind(&GCMClientImpl::DestroyStoreCallback,
                      weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::ResetStore() {
  // If already being reset, don't do it again. We want to prevent from
  // resetting and loading from the store again and again.
  if (gcm_store_reset_) {
    RecordResetStoreErrorToUMA(INFINITE_STORE_RESET);
    state_ = UNINITIALIZED;
    return;
  }
  gcm_store_reset_ = true;

  // Destroy the GCM store to start over.
  gcm_store_->Destroy(base::Bind(&GCMClientImpl::ResetStoreCallback,
                      weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::SetAccountTokens(
    const std::vector<AccountTokenInfo>& account_tokens) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  device_checkin_info_.account_tokens.clear();
  for (auto iter = account_tokens.begin(); iter != account_tokens.end();
       ++iter) {
    device_checkin_info_.account_tokens[iter->email] = iter->access_token;
  }

  bool accounts_set_before = device_checkin_info_.accounts_set;
  device_checkin_info_.accounts_set = true;

  DVLOG(1) << "Set account called with: " << account_tokens.size()
           << " accounts.";

  if (state_ != READY && state_ != INITIAL_DEVICE_CHECKIN)
    return;

  bool account_removed = false;
  for (auto iter = device_checkin_info_.last_checkin_accounts.begin();
       iter != device_checkin_info_.last_checkin_accounts.end(); ++iter) {
    if (device_checkin_info_.account_tokens.find(*iter) ==
            device_checkin_info_.account_tokens.end()) {
      account_removed = true;
    }
  }

  // Checkin will be forced when any of the accounts was removed during the
  // current Chrome session or if there has been an account removed between the
  // restarts of Chrome. If there is a checkin in progress, it will be canceled.
  // We only force checkin when user signs out. When there is a new account
  // signed in, the periodic checkin will take care of adding the association in
  // reasonable time.
  if (account_removed) {
    DVLOG(1) << "Detected that account has been removed. Forcing checkin.";
    checkin_request_.reset();
    StartCheckin();
  } else if (!accounts_set_before) {
    SchedulePeriodicCheckin();
    DVLOG(1) << "Accounts set for the first time. Scheduled periodic checkin.";
  }
}

void GCMClientImpl::UpdateAccountMapping(
    const AccountMapping& account_mapping) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  gcm_store_->AddAccountMapping(account_mapping,
                                base::Bind(&GCMClientImpl::DefaultStoreCallback,
                                           weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::RemoveAccountMapping(const CoreAccountId& account_id) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  gcm_store_->RemoveAccountMapping(
      account_id,
      base::Bind(&GCMClientImpl::DefaultStoreCallback,
                 weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::SetLastTokenFetchTime(const base::Time& time) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  gcm_store_->SetLastTokenFetchTime(
      time,
      base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
                 weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::UpdateHeartbeatTimer(
    std::unique_ptr<base::RetainingOneShotTimer> timer) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  DCHECK(mcs_client_);
  mcs_client_->UpdateHeartbeatTimer(std::move(timer));
}

void GCMClientImpl::AddInstanceIDData(const std::string& app_id,
                                      const std::string& instance_id,
                                      const std::string& extra_data) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  instance_id_data_[app_id] = std::make_pair(instance_id, extra_data);
  gcm_store_->AddInstanceIDData(
      app_id,
      SerializeInstanceIDData(instance_id, extra_data),
      base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
                 weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  instance_id_data_.erase(app_id);
  gcm_store_->RemoveInstanceIDData(
      app_id,
      base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
                 weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::GetInstanceIDData(const std::string& app_id,
                                      std::string* instance_id,
                                      std::string* extra_data) {
  DCHECK(instance_id && extra_data);

  auto iter = instance_id_data_.find(app_id);
  if (iter == instance_id_data_.end())
    return;
  *instance_id = iter->second.first;
  *extra_data = iter->second.second;
}

void GCMClientImpl::AddHeartbeatInterval(const std::string& scope,
                                         int interval_ms) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  DCHECK(mcs_client_);
  mcs_client_->AddHeartbeatInterval(scope, interval_ms);
}

void GCMClientImpl::RemoveHeartbeatInterval(const std::string& scope) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  DCHECK(mcs_client_);
  mcs_client_->RemoveHeartbeatInterval(scope);
}

void GCMClientImpl::StartCheckin() {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  // Make sure no checkin is in progress.
  if (checkin_request_)
    return;

  checkin_proto::ChromeBuildProto chrome_build_proto;
  ToCheckinProtoVersion(chrome_build_info_, &chrome_build_proto);
  CheckinRequest::RequestInfo request_info(device_checkin_info_.android_id,
                                           device_checkin_info_.secret,
                                           device_checkin_info_.account_tokens,
                                           gservices_settings_.digest(),
                                           chrome_build_proto);
  checkin_request_.reset(new CheckinRequest(
      gservices_settings_.GetCheckinURL(), request_info, GetGCMBackoffPolicy(),
      base::Bind(&GCMClientImpl::OnCheckinCompleted,
                 weak_ptr_factory_.GetWeakPtr()),
      url_loader_factory_, io_task_runner_, &recorder_));
  // Taking a snapshot of the accounts count here, as there might be an asynch
  // update of the account tokens while checkin is in progress.
  device_checkin_info_.SnapshotCheckinAccounts();
  checkin_request_->Start();
}

void GCMClientImpl::OnCheckinCompleted(
    net::HttpStatusCode response_code,
    const checkin_proto::AndroidCheckinResponse& checkin_response) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  checkin_request_.reset();

  if (response_code == net::HTTP_UNAUTHORIZED ||
      response_code == net::HTTP_BAD_REQUEST) {
    LOG(ERROR) << "Checkin rejected. Resetting GCM Store.";
    ResetStore();
    return;
  }

  DCHECK(checkin_response.has_android_id());
  DCHECK(checkin_response.has_security_token());
  CheckinInfo checkin_info;
  checkin_info.android_id = checkin_response.android_id();
  checkin_info.secret = checkin_response.security_token();

  if (state_ == INITIAL_DEVICE_CHECKIN) {
    OnFirstTimeDeviceCheckinCompleted(checkin_info);
  } else {
    // checkin_info is not expected to change after a periodic checkin as it
    // would invalidate the registration IDs.
    DCHECK_EQ(READY, state_);
    DCHECK_EQ(device_checkin_info_.android_id, checkin_info.android_id);
    DCHECK_EQ(device_checkin_info_.secret, checkin_info.secret);
  }

  if (device_checkin_info_.IsValid()) {
    // First update G-services settings, as something might have changed.
    if (gservices_settings_.UpdateFromCheckinResponse(checkin_response)) {
      gcm_store_->SetGServicesSettings(
          gservices_settings_.settings_map(),
          gservices_settings_.digest(),
          base::Bind(&GCMClientImpl::SetGServicesSettingsCallback,
                     weak_ptr_factory_.GetWeakPtr()));
    }

    last_checkin_time_ = clock_->Now();
    gcm_store_->SetLastCheckinInfo(
        last_checkin_time_,
        device_checkin_info_.last_checkin_accounts,
        base::Bind(&GCMClientImpl::SetLastCheckinInfoCallback,
                   weak_ptr_factory_.GetWeakPtr()));
    SchedulePeriodicCheckin();
  }
}

void GCMClientImpl::SetGServicesSettingsCallback(bool success) {
  DCHECK(success);
}

void GCMClientImpl::SchedulePeriodicCheckin() {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  // Make sure no checkin is in progress.
  if (checkin_request_.get() || !device_checkin_info_.accounts_set)
    return;

  // There should be only one periodic checkin pending at a time. Removing
  // pending periodic checkin to schedule a new one.
  periodic_checkin_ptr_factory_.InvalidateWeakPtrs();

  base::TimeDelta time_to_next_checkin = GetTimeToNextCheckin();
  if (time_to_next_checkin < base::TimeDelta())
    time_to_next_checkin = base::TimeDelta();

  io_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&GCMClientImpl::StartCheckin,
                     periodic_checkin_ptr_factory_.GetWeakPtr()),
      time_to_next_checkin);
}

base::TimeDelta GCMClientImpl::GetTimeToNextCheckin() const {
  return last_checkin_time_ + gservices_settings_.GetCheckinInterval() -
         clock_->Now();
}

void GCMClientImpl::SetLastCheckinInfoCallback(bool success) {
  // TODO(fgorski): This is one of the signals that store needs a rebuild.
  DCHECK(success);
}

void GCMClientImpl::SetDeviceCredentialsCallback(bool success) {
  // TODO(fgorski): This is one of the signals that store needs a rebuild.
  DCHECK(success);
}

void GCMClientImpl::UpdateRegistrationCallback(bool success) {
  // TODO(fgorski): This is one of the signals that store needs a rebuild.
  DCHECK(success);
}

void GCMClientImpl::DefaultStoreCallback(bool success) {
  DCHECK(success);
}

void GCMClientImpl::IgnoreWriteResultCallback(bool success) {
  // TODO(fgorski): Ignoring the write result for now to make sure
  // sync_intergration_tests are not broken.
}

void GCMClientImpl::DestroyStoreCallback(bool success) {
  ResetCache();

  if (!success) {
    LOG(ERROR) << "Failed to destroy GCM store";
    RecordResetStoreErrorToUMA(DESTROYING_STORE_FAILED);
    state_ = UNINITIALIZED;
    return;
  }

  state_ = INITIALIZED;
}

void GCMClientImpl::ResetStoreCallback(bool success) {
  // Even an incomplete reset may invalidate registrations, and this might be
  // the only opportunity to notify the delegate. For example a partial reset
  // that deletes the "CURRENT" file will cause GCMStoreImpl to consider the DB
  // to no longer exist, in which case the next load will simply create a new
  // store rather than resetting it.
  delegate_->OnStoreReset();

  if (!success) {
    LOG(ERROR) << "Failed to reset GCM store";
    RecordResetStoreErrorToUMA(DESTROYING_STORE_FAILED);
    state_ = UNINITIALIZED;
    return;
  }

  state_ = INITIALIZED;
  Start(start_mode_);
}

void GCMClientImpl::Stop() {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  // TODO(fgorski): Perhaps we should make a distinction between a Stop and a
  // Shutdown.
  DVLOG(1) << "Stopping the GCM Client";
  ResetCache();
  state_ = INITIALIZED;
  gcm_store_->Close();
}

void GCMClientImpl::ResetCache() {
  weak_ptr_factory_.InvalidateWeakPtrs();
  periodic_checkin_ptr_factory_.InvalidateWeakPtrs();
  device_checkin_info_.Reset();
  connection_factory_.reset();
  delegate_->OnDisconnected();
  mcs_client_.reset();
  checkin_request_.reset();
  // Delete all of the pending registration and unregistration requests.
  pending_registration_requests_.clear();
  pending_unregistration_requests_.clear();
}

void GCMClientImpl::Register(
    scoped_refptr<RegistrationInfo> registration_info) {
  DCHECK_EQ(state_, READY);
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  // Registrations should never pass as an app_id the special category used
  // internally when registering with a subtype. See security note in
  // GCMClientImpl::HandleIncomingMessage.
  CHECK_NE(registration_info->app_id,
           chrome_build_info_.product_category_for_subtypes);

  // Find and use the cached registration ID.
  RegistrationInfoMap::const_iterator registrations_iter =
      registrations_.find(registration_info);
  if (registrations_iter != registrations_.end()) {
    bool matched = true;

    // For GCM registration, we also match the sender IDs since multiple
    // registrations are not supported.
    const GCMRegistrationInfo* gcm_registration_info =
        GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
    if (gcm_registration_info) {
      const GCMRegistrationInfo* cached_gcm_registration_info =
          GCMRegistrationInfo::FromRegistrationInfo(
              registrations_iter->first.get());
      DCHECK(cached_gcm_registration_info);
      if (gcm_registration_info->sender_ids !=
          cached_gcm_registration_info->sender_ids) {
        matched = false;
        // Senders IDs don't match existing registration.
        RecordRegistrationRequestToUMA(
            RegistrationCacheStatus::REGISTRATION_FOUND_BUT_SENDERS_DONT_MATCH);
      }
    }

    if (matched) {
      // Skip registration if token is fresh.
      base::TimeDelta token_invalidation_period =
          features::GetTokenInvalidationInterval();
      base::TimeDelta time_since_last_validation =
          clock_->Now() - registrations_iter->first->last_validated;
      if (token_invalidation_period.is_zero() ||
          time_since_last_validation < token_invalidation_period) {
        // Token is fresh, or token invalidation is disabled.
        // Use cached registration.
        delegate_->OnRegisterFinished(registration_info,
                                      registrations_iter->second, SUCCESS);
        RecordRegistrationRequestToUMA(
            RegistrationCacheStatus::REGISTRATION_FOUND_AND_FRESH);
        return;
      } else {
        // Token is stale.
        RecordRegistrationRequestToUMA(
            RegistrationCacheStatus::REGISTRATION_FOUND_BUT_STALE);
      }
    }
  } else {
    // New Registration request (no existing registration)
    RecordRegistrationRequestToUMA(
        RegistrationCacheStatus::REGISTRATION_NOT_FOUND);
  }

  std::unique_ptr<RegistrationRequest::CustomRequestHandler> request_handler;
  std::string source_to_record;

  const GCMRegistrationInfo* gcm_registration_info =
      GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
  if (gcm_registration_info) {
    std::string senders;
    for (auto iter = gcm_registration_info->sender_ids.begin();
         iter != gcm_registration_info->sender_ids.end();
         ++iter) {
      if (!senders.empty())
        senders.append(",");
      senders.append(*iter);
    }
    UMA_HISTOGRAM_COUNTS_1M("GCM.RegistrationSenderIdCount",
                            gcm_registration_info->sender_ids.size());

    request_handler.reset(new GCMRegistrationRequestHandler(senders));
    source_to_record = senders;
  }

  const InstanceIDTokenInfo* instance_id_token_info =
      InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
  if (instance_id_token_info) {
    auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
    DCHECK(instance_id_iter != instance_id_data_.end());

    request_handler.reset(new InstanceIDGetTokenRequestHandler(
          instance_id_iter->second.first,
          instance_id_token_info->authorized_entity,
          instance_id_token_info->scope,
          ConstructGCMVersion(chrome_build_info_.version),
          instance_id_token_info->options));
    source_to_record = instance_id_token_info->authorized_entity + "/" +
                       instance_id_token_info->scope;
  }

  bool use_subtype = instance_id_token_info &&
                     InstanceIDUsesSubtypeForAppId(registration_info->app_id);
  std::string category = use_subtype
                             ? chrome_build_info_.product_category_for_subtypes
                             : registration_info->app_id;
  std::string subtype = use_subtype ? registration_info->app_id : std::string();
  RegistrationRequest::RequestInfo request_info(device_checkin_info_.android_id,
                                                device_checkin_info_.secret,
                                                category, subtype);

  std::unique_ptr<RegistrationRequest> registration_request(
      new RegistrationRequest(
          gservices_settings_.GetRegistrationURL(), request_info,
          std::move(request_handler), GetGCMBackoffPolicy(),
          base::Bind(&GCMClientImpl::OnRegisterCompleted,
                     weak_ptr_factory_.GetWeakPtr(), registration_info),
          kMaxRegistrationRetries, url_loader_factory_, io_task_runner_,
          &recorder_, source_to_record));
  registration_request->Start();
  pending_registration_requests_.insert(
      std::make_pair(registration_info, std::move(registration_request)));
}

void GCMClientImpl::OnRegisterCompleted(
    scoped_refptr<RegistrationInfo> registration_info,
    RegistrationRequest::Status status,
    const std::string& registration_id) {
  DCHECK(delegate_);

  Result result;
  PendingRegistrationRequests::const_iterator iter =
      pending_registration_requests_.find(registration_info);
  if (iter == pending_registration_requests_.end()) {
    result = UNKNOWN_ERROR;
  } else if (status == RegistrationRequest::INVALID_SENDER) {
    result = INVALID_PARAMETER;
  } else if (registration_id.empty()) {
    // All other errors are currently treated as SERVER_ERROR (including
    // REACHED_MAX_RETRIES due to the device being offline!).
    result = SERVER_ERROR;
  } else {
    result = SUCCESS;
  }

  if (result == SUCCESS) {
    // Cache it.
    // Note that the existing cached record has to be removed first because
    // otherwise the key value in registrations_ will not be updated. For GCM
    // registrations, the key consists of pair of app_id and sender_ids though
    // only app_id is used in the key comparison.
    registrations_.erase(registration_info);
    registration_info->last_validated = clock_->Now();
    registrations_[registration_info] = registration_id;

    // Save it in the persistent store.
    gcm_store_->AddRegistration(
        registration_info->GetSerializedKey(),
        registration_info->GetSerializedValue(registration_id),
        base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
                   weak_ptr_factory_.GetWeakPtr()));
  }

  delegate_->OnRegisterFinished(
      registration_info,
      result == SUCCESS ? registration_id : std::string(),
      result);

  if (iter != pending_registration_requests_.end())
    pending_registration_requests_.erase(iter);
}

bool GCMClientImpl::ValidateRegistration(
    scoped_refptr<RegistrationInfo> registration_info,
    const std::string& registration_id) {
  DCHECK_EQ(state_, READY);
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  // Must have a cached registration.
  RegistrationInfoMap::const_iterator registrations_iter =
      registrations_.find(registration_info);
  if (registrations_iter == registrations_.end())
    return false;

  // Cached registration ID must match.
  const std::string& cached_registration_id = registrations_iter->second;
  if (registration_id != cached_registration_id)
    return false;

  // For GCM registration, we also match the sender IDs since multiple
  // registrations are not supported.
  const GCMRegistrationInfo* gcm_registration_info =
      GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
  if (gcm_registration_info) {
    const GCMRegistrationInfo* cached_gcm_registration_info =
        GCMRegistrationInfo::FromRegistrationInfo(
            registrations_iter->first.get());
    DCHECK(cached_gcm_registration_info);
    if (gcm_registration_info->sender_ids !=
        cached_gcm_registration_info->sender_ids) {
      return false;
    }
  }

  return true;
}

void GCMClientImpl::Unregister(
    scoped_refptr<RegistrationInfo> registration_info) {
  DCHECK_EQ(state_, READY);
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  std::unique_ptr<UnregistrationRequest::CustomRequestHandler> request_handler;
  std::string source_to_record;

  const GCMRegistrationInfo* gcm_registration_info =
      GCMRegistrationInfo::FromRegistrationInfo(registration_info.get());
  if (gcm_registration_info) {
    request_handler.reset(
        new GCMUnregistrationRequestHandler(registration_info->app_id));
  }

  const InstanceIDTokenInfo* instance_id_token_info =
      InstanceIDTokenInfo::FromRegistrationInfo(registration_info.get());
  if (instance_id_token_info) {
    auto instance_id_iter = instance_id_data_.find(registration_info->app_id);
    if (instance_id_iter == instance_id_data_.end()) {
      // This should not be reached since we should not delete tokens when
      // an InstanceID has not been created yet.
      NOTREACHED();
      return;
    }

    request_handler.reset(new InstanceIDDeleteTokenRequestHandler(
        instance_id_iter->second.first,
        instance_id_token_info->authorized_entity,
        instance_id_token_info->scope,
        ConstructGCMVersion(chrome_build_info_.version)));
    source_to_record = instance_id_token_info->authorized_entity + "/" +
                       instance_id_token_info->scope;
  }

  // Remove the registration/token(s) from the cache and the store.
  // TODO(jianli): Remove it only when the request is successful.
  if (instance_id_token_info &&
      instance_id_token_info->authorized_entity == "*" &&
      instance_id_token_info->scope == "*") {
    // If authorized_entity and scope are '*', find and remove all associated
    // tokens.
    bool token_found = false;
    for (auto iter = registrations_.begin();
          iter != registrations_.end();) {
      InstanceIDTokenInfo* cached_instance_id_token_info =
          InstanceIDTokenInfo::FromRegistrationInfo(iter->first.get());
      if (cached_instance_id_token_info &&
          cached_instance_id_token_info->app_id == registration_info->app_id) {
        token_found = true;
        gcm_store_->RemoveRegistration(
            cached_instance_id_token_info->GetSerializedKey(),
            base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
                        weak_ptr_factory_.GetWeakPtr()));
        registrations_.erase(iter++);
      } else {
        ++iter;
      }
    }

    // If no token is found for the Instance ID, don't need to unregister
    // since the Instance ID is not sent to the server yet.
    if (!token_found) {
      OnUnregisterCompleted(registration_info,
                            UnregistrationRequest::SUCCESS);
      return;
    }
  } else {
    auto iter = registrations_.find(registration_info);
    if (iter == registrations_.end()) {
      delegate_->OnUnregisterFinished(registration_info, INVALID_PARAMETER);
      return;
    }
    registrations_.erase(iter);

    gcm_store_->RemoveRegistration(
      registration_info->GetSerializedKey(),
      base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
                  weak_ptr_factory_.GetWeakPtr()));
  }

  bool use_subtype = instance_id_token_info &&
                     InstanceIDUsesSubtypeForAppId(registration_info->app_id);
  std::string category = use_subtype
                             ? chrome_build_info_.product_category_for_subtypes
                             : registration_info->app_id;
  std::string subtype = use_subtype ? registration_info->app_id : std::string();
  UnregistrationRequest::RequestInfo request_info(
      device_checkin_info_.android_id, device_checkin_info_.secret, category,
      subtype);

  std::unique_ptr<UnregistrationRequest> unregistration_request(
      new UnregistrationRequest(
          gservices_settings_.GetRegistrationURL(), request_info,
          std::move(request_handler), GetGCMBackoffPolicy(),
          base::Bind(&GCMClientImpl::OnUnregisterCompleted,
                     weak_ptr_factory_.GetWeakPtr(), registration_info),
          kMaxUnregistrationRetries, url_loader_factory_, io_task_runner_,
          &recorder_, source_to_record));
  unregistration_request->Start();
  pending_unregistration_requests_.insert(
      std::make_pair(registration_info, std::move(unregistration_request)));
}

void GCMClientImpl::OnUnregisterCompleted(
    scoped_refptr<RegistrationInfo> registration_info,
    UnregistrationRequest::Status status) {
  DVLOG(1) << "Unregister completed for app: " << registration_info->app_id
           << " with " << (status ? "success." : "failure.");

  Result result;
  switch (status) {
    case UnregistrationRequest::SUCCESS:
      result = SUCCESS;
      break;
    case UnregistrationRequest::INVALID_PARAMETERS:
      result = INVALID_PARAMETER;
      break;
    default:
      // All other errors are currently treated as SERVER_ERROR (including
      // REACHED_MAX_RETRIES due to the device being offline!).
      result = SERVER_ERROR;
      break;
  }
  delegate_->OnUnregisterFinished(registration_info, result);

  pending_unregistration_requests_.erase(registration_info);
}

void GCMClientImpl::OnGCMStoreDestroyed(bool success) {
  DLOG_IF(ERROR, !success) << "GCM store failed to be destroyed!";
  UMA_HISTOGRAM_BOOLEAN("GCM.StoreDestroySucceeded", success);
}

void GCMClientImpl::Send(const std::string& app_id,
                         const std::string& receiver_id,
                         const OutgoingMessage& message) {
  DCHECK_EQ(state_, READY);
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());

  mcs_proto::DataMessageStanza stanza;
  stanza.set_ttl(message.time_to_live);
  stanza.set_sent(clock_->Now().ToInternalValue() /
                  base::Time::kMicrosecondsPerSecond);
  stanza.set_id(message.id);
  stanza.set_from(kSendMessageFromValue);
  stanza.set_to(receiver_id);
  stanza.set_category(app_id);

  for (auto iter = message.data.begin(); iter != message.data.end(); ++iter) {
    mcs_proto::AppData* app_data = stanza.add_app_data();
    app_data->set_key(iter->first);
    app_data->set_value(iter->second);
  }

  MCSMessage mcs_message(stanza);
  DVLOG(1) << "MCS message size: " << mcs_message.size();
  mcs_client_->SendMessage(mcs_message);
}

std::string GCMClientImpl::GetStateString() const {
  switch(state_) {
    case GCMClientImpl::UNINITIALIZED:
      return "UNINITIALIZED";
    case GCMClientImpl::INITIALIZED:
      return "INITIALIZED";
    case GCMClientImpl::LOADING:
      return "LOADING";
    case GCMClientImpl::LOADED:
      return "LOADED";
    case GCMClientImpl::INITIAL_DEVICE_CHECKIN:
      return "INITIAL_DEVICE_CHECKIN";
    case GCMClientImpl::READY:
      return "READY";
  }
  NOTREACHED();
  return std::string();
}

void GCMClientImpl::RecordDecryptionFailure(const std::string& app_id,
                                            GCMDecryptionResult result) {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  recorder_.RecordDecryptionFailure(app_id, result);
}

void GCMClientImpl::SetRecording(bool recording) {
  recorder_.set_is_recording(recording);
}

void GCMClientImpl::ClearActivityLogs() {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  recorder_.Clear();
}

GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const {
  DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
  GCMClient::GCMStatistics stats;
  stats.gcm_client_created = true;
  stats.is_recording = recorder_.is_recording();
  stats.gcm_client_state = GetStateString();
  stats.connection_client_created = mcs_client_ != nullptr;
  stats.last_checkin = last_checkin_time_;
  stats.next_checkin =
      last_checkin_time_ + gservices_settings_.GetCheckinInterval();
  if (connection_factory_)
    stats.connection_state = connection_factory_->GetConnectionStateString();
  if (mcs_client_) {
    stats.send_queue_size = mcs_client_->GetSendQueueSize();
    stats.resend_queue_size = mcs_client_->GetResendQueueSize();
  }
  if (device_checkin_info_.android_id > 0)
    stats.android_id = device_checkin_info_.android_id;
  if (device_checkin_info_.secret > 0)
    stats.android_secret = device_checkin_info_.secret;

  recorder_.CollectActivities(&stats.recorded_activities);

  for (auto it = registrations_.begin(); it != registrations_.end(); ++it) {
    stats.registered_app_ids.push_back(it->first->app_id);
  }
  return stats;
}

void GCMClientImpl::OnActivityRecorded() {
  delegate_->OnActivityRecorded();
}

void GCMClientImpl::OnConnected(const GURL& current_server,
                                const net::IPEndPoint& ip_endpoint) {
  // TODO(gcm): expose current server in debug page.
  delegate_->OnActivityRecorded();
  delegate_->OnConnected(ip_endpoint);
}

void GCMClientImpl::OnDisconnected() {
  delegate_->OnActivityRecorded();
  delegate_->OnDisconnected();
}

void GCMClientImpl::OnMessageReceivedFromMCS(const gcm::MCSMessage& message) {
  switch (message.tag()) {
    case kLoginResponseTag:
      DVLOG(1) << "Login response received by GCM Client. Ignoring.";
      return;
    case kDataMessageStanzaTag:
      DVLOG(1) << "A downstream message received. Processing...";
      HandleIncomingMessage(message);
      return;
    default:
      NOTREACHED() << "Message with unexpected tag received by GCMClient";
      return;
  }
}

void GCMClientImpl::OnMessageSentToMCS(int64_t user_serial_number,
                                       const std::string& app_id,
                                       const std::string& message_id,
                                       MCSClient::MessageSendStatus status) {
  DCHECK_EQ(user_serial_number, kDefaultUserSerialNumber);
  DCHECK(delegate_);

  // TTL_EXCEEDED is singled out here, because it can happen long time after the
  // message was sent. That is why it comes as |OnMessageSendError| event rather
  // than |OnSendFinished|. SendErrorDetails.additional_data is left empty.
  // All other errors will be raised immediately, through asynchronous callback.
  // It is expected that TTL_EXCEEDED will be issued for a message that was
  // previously issued |OnSendFinished| with status SUCCESS.
  // TODO(jianli): Consider adding UMA for this status.
  if (status == MCSClient::TTL_EXCEEDED) {
    SendErrorDetails send_error_details;
    send_error_details.message_id = message_id;
    send_error_details.result = GCMClient::TTL_EXCEEDED;
    delegate_->OnMessageSendError(app_id, send_error_details);
  } else if (status == MCSClient::SENT) {
    delegate_->OnSendAcknowledged(app_id, message_id);
  } else {
    delegate_->OnSendFinished(app_id, message_id, ToGCMClientResult(status));
  }
}

void GCMClientImpl::OnMCSError() {
  // TODO(fgorski): For now it replaces the initialization method. Long term it
  // should have an error or status passed in.
}

void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) {
  DCHECK(delegate_);

  const mcs_proto::DataMessageStanza& data_message_stanza =
      reinterpret_cast<const mcs_proto::DataMessageStanza&>(
          message.GetProtobuf());
  DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber);

  // Copy all the data from the stanza to a MessageData object. When present,
  // keys like kSubtypeKey or kMessageTypeKey will be filtered out later.
  MessageData message_data;
  for (int i = 0; i < data_message_stanza.app_data_size(); ++i) {
    std::string key = data_message_stanza.app_data(i).key();
    message_data[key] = data_message_stanza.app_data(i).value();
  }

  std::string subtype;
  auto subtype_iter = message_data.find(kSubtypeKey);
  if (subtype_iter != message_data.end()) {
    subtype = subtype_iter->second;
    message_data.erase(subtype_iter);
  }

  // SECURITY NOTE: Subtypes received from GCM *cannot* be trusted for
  // registrations without a subtype (as the sender can pass any subtype they
  // want). They can however be trusted for registrations that are known to have
  // a subtype (as GCM overwrites anything passed by the sender).
  //
  // So a given Chrome profile always passes a fixed string called
  // |product_category_for_subtypes| (of the form "com.chrome.macosx") as the
  // category when registering with a subtype, and incoming subtypes are only
  // trusted for that category.
  //
  // TODO(johnme): Remove this check if GCM starts sending the subtype in a
  // field that's guaranteed to be trusted (b/18198485).
  //
  // (On Android, all registrations made by Chrome on behalf of third-party
  // apps/extensions/websites have always had a subtype, so such a check is not
  // necessary - or possible, since category is fixed to the true package name).
  bool subtype_is_trusted = data_message_stanza.category() ==
                            chrome_build_info_.product_category_for_subtypes;
  bool use_subtype = subtype_is_trusted && !subtype.empty();
  std::string app_id = use_subtype ? subtype : data_message_stanza.category();

  MessageType message_type = DATA_MESSAGE;
  auto type_iter = message_data.find(kMessageTypeKey);
  if (type_iter != message_data.end()) {
    message_type = DecodeMessageType(type_iter->second);
    message_data.erase(type_iter);
  }

  switch (message_type) {
    case DATA_MESSAGE:
      HandleIncomingDataMessage(app_id, use_subtype, data_message_stanza,
                                message_data);
      break;
    case DELETED_MESSAGES:
      HandleIncomingDeletedMessages(app_id, data_message_stanza, message_data);
      break;
    case SEND_ERROR:
      HandleIncomingSendError(app_id, data_message_stanza, message_data);
      break;
    case UNKNOWN:
      DVLOG(1) << "Unknown message_type received. Message ignored. "
               << "App ID: " << app_id << ".";
      break;
  }
}

void GCMClientImpl::HandleIncomingDataMessage(
    const std::string& app_id,
    bool was_subtype,
    const mcs_proto::DataMessageStanza& data_message_stanza,
    MessageData& message_data) {
  UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceived", true);

  bool has_collapse_key =
      data_message_stanza.has_token() && !data_message_stanza.token().empty();
  UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceivedHasCollapseKey",
                        has_collapse_key);

  recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(),
                                      data_message_stanza.ByteSize(),
                                      GCMStatsRecorder::DATA_MESSAGE);

  IncomingMessage incoming_message;
  incoming_message.sender_id = data_message_stanza.from();
  incoming_message.message_id = data_message_stanza.persistent_id();
  if (data_message_stanza.has_token())
    incoming_message.collapse_key = data_message_stanza.token();
  incoming_message.data = message_data;
  incoming_message.raw_data = data_message_stanza.raw_data();

  delegate_->OnMessageReceived(app_id, incoming_message);
}

void GCMClientImpl::HandleIncomingDeletedMessages(
    const std::string& app_id,
    const mcs_proto::DataMessageStanza& data_message_stanza,
    MessageData& message_data) {
  int deleted_count = 0;
  auto count_iter = message_data.find(kDeletedCountKey);
  if (count_iter != message_data.end()) {
    if (!base::StringToInt(count_iter->second, &deleted_count))
      deleted_count = 0;
  }
  UMA_HISTOGRAM_COUNTS_1000("GCM.DeletedMessagesReceived", deleted_count);

  recorder_.RecordDataMessageReceived(app_id, data_message_stanza.from(),
                                      data_message_stanza.ByteSize(),
                                      GCMStatsRecorder::DELETED_MESSAGES);
  delegate_->OnMessagesDeleted(app_id);
}

void GCMClientImpl::HandleIncomingSendError(
    const std::string& app_id,
    const mcs_proto::DataMessageStanza& data_message_stanza,
    MessageData& message_data) {
  SendErrorDetails send_error_details;
  send_error_details.additional_data = message_data;
  send_error_details.result = SERVER_ERROR;
  send_error_details.message_id = data_message_stanza.persistent_id();

  recorder_.RecordIncomingSendError(app_id, data_message_stanza.to(),
                                    data_message_stanza.id());
  delegate_->OnMessageSendError(app_id, send_error_details);
}

bool GCMClientImpl::HasStandaloneRegisteredApp() const {
  if (registrations_.empty())
    return false;
  // Note that account mapper is not counted as a standalone app since it is
  // automatically started when other app uses GCM.
  return registrations_.size() > 1 ||
         !ExistsGCMRegistrationInMap(registrations_, kGCMAccountMapperAppId);
}

}  // namespace gcm
