// 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/threading/thread_task_runner_handle.h"
#include "base/time/default_clock.h"
#include "base/timer/timer.h"
#include "components/crx_file/id_util.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 "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
#include "url/gurl.h"

namespace gcm {

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 OutgoingMessageTTLCategory {
  TTL_ZERO,
  TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE,
  TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR,
  TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY,
  TTL_LESS_THAN_OR_EQUAL_TO_ONE_WEEK,
  TTL_MORE_THAN_ONE_WEEK,
  TTL_MAXIMUM,
  // NOTE: always keep this entry at the end. Add new TTL category only
  // immediately above this line. Make sure to update the corresponding
  // histogram enum accordingly.
  TTL_CATEGORY_COUNT
};

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 char kGCMScope[] = "GCM";
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 kSendErrorMessageIdKey[] = "google.message_id";
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_UNKNOWN:
      // 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 RecordOutgoingMessageToUMA(const gcm::OutgoingMessage& message) {
  OutgoingMessageTTLCategory ttl_category;
  if (message.time_to_live == 0)
    ttl_category = TTL_ZERO;
  else if (message.time_to_live <= 60 )
    ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_MINUTE;
  else if (message.time_to_live <= 60 * 60)
    ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_HOUR;
  else if (message.time_to_live <= 24 * 60 * 60)
    ttl_category = TTL_LESS_THAN_OR_EQUAL_TO_ONE_DAY;
  else
    ttl_category = TTL_MAXIMUM;

  UMA_HISTOGRAM_ENUMERATION("GCM.OutgoingMessageTTL",
                            ttl_category,
                            TTL_CATEGORY_COUNT);
}

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

}  // namespace

GCMInternalsBuilder::GCMInternalsBuilder() {}
GCMInternalsBuilder::~GCMInternalsBuilder() {}

std::unique_ptr<base::Clock> GCMInternalsBuilder::BuildClock() {
  return base::WrapUnique<base::Clock>(new base::DefaultClock());
}

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

std::unique_ptr<ConnectionFactory> GCMInternalsBuilder::BuildConnectionFactory(
    const std::vector<GURL>& endpoints,
    const net::BackoffEntry::Policy& backoff_policy,
    net::HttpNetworkSession* gcm_network_session,
    net::HttpNetworkSession* http_network_session,
    GCMStatsRecorder* recorder) {
  return base::WrapUnique<ConnectionFactory>(
      new ConnectionFactoryImpl(endpoints, backoff_policy, gcm_network_session,
                                http_network_session, nullptr, recorder));
}

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

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

void GCMClientImpl::CheckinInfo::SnapshotCheckinAccounts() {
  last_checkin_accounts.clear();
  for (std::map<std::string, std::string>::iterator 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_(NULL),
      start_mode_(DELAYED_START),
      clock_(internals_builder_->BuildClock()),
      gcm_store_reset_(false),
      url_request_context_getter_(NULL),
      periodic_checkin_ptr_factory_(this),
      destroying_gcm_store_ptr_factory_(this),
      weak_ptr_factory_(this) {}

GCMClientImpl::~GCMClientImpl() {
}

void GCMClientImpl::Initialize(
    const ChromeBuildInfo& chrome_build_info,
    const base::FilePath& path,
    const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
    const scoped_refptr<net::URLRequestContextGetter>&
        url_request_context_getter,
    std::unique_ptr<Encryptor> encryptor,
    GCMClient::Delegate* delegate) {
  DCHECK_EQ(UNINITIALIZED, state_);
  DCHECK(url_request_context_getter.get());
  DCHECK(delegate);

  url_request_context_getter_ = url_request_context_getter;
  const net::HttpNetworkSession::Params* network_session_params =
      url_request_context_getter_->GetURLRequestContext()->
          GetNetworkSessionParams();
  DCHECK(network_session_params);
  const net::HttpNetworkSession::Context* network_session_context =
      url_request_context_getter_->GetURLRequestContext()
          ->GetNetworkSessionContext();
  network_session_.reset(new net::HttpNetworkSession(*network_session_params,
                                                     *network_session_context));

  chrome_build_info_ = chrome_build_info;

  gcm_store_.reset(
      new GCMStoreImpl(path, blocking_task_runner, std::move(encryptor)));

  delegate_ = delegate;

  recorder_.SetDelegate(this);

  state_ = INITIALIZED;
}

void GCMClientImpl::Start(StartMode start_mode) {
  DCHECK_NE(UNINITIALIZED, state_);

  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_);

  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;
    std::unique_ptr<RegistrationInfo> registration =
        RegistrationInfo::BuildFromString(iter->first, iter->second,
                                          &registration_id);
    // TODO(jianli): Add UMA to track the error case.
    if (registration.get())
      registrations_[make_linked_ptr(registration.release())] = 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) {
      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
          FROM_HERE, base::Bind(&GCMClientImpl::DestroyStoreWhenNotNeeded,
                                destroying_gcm_store_ptr_factory_.GetWeakPtr()),
          base::TimeDelta::FromMilliseconds(kDestroyGCMStoreDelayMS));
    }

    return;
  }

  StartGCM();
}

void GCMClientImpl::StartGCM() {
  // 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() {
  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(),
      network_session_.get(),
      url_request_context_getter_->GetURLRequestContext()
          ->http_transaction_factory()
          ->GetSession(),
      &recorder_);
  connection_factory_->SetConnectionListener(this);
  mcs_client_ = internals_builder_->BuildMCSClient(
      chrome_build_info_.version, clock_.get(), connection_factory_.get(),
      gcm_store_.get(), &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) {
  device_checkin_info_.account_tokens.clear();
  for (std::vector<AccountTokenInfo>::const_iterator 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 (std::set<std::string>::iterator 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) {
  gcm_store_->AddAccountMapping(account_mapping,
                                base::Bind(&GCMClientImpl::DefaultStoreCallback,
                                           weak_ptr_factory_.GetWeakPtr()));
}

void GCMClientImpl::RemoveAccountMapping(const std::string& account_id) {
  gcm_store_->RemoveAccountMapping(
      account_id,
      base::Bind(&GCMClientImpl::DefaultStoreCallback,
                 weak_ptr_factory_.GetWeakPtr()));
}

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

void GCMClientImpl::UpdateHeartbeatTimer(std::unique_ptr<base::Timer> timer) {
  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) {
  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) {
  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(mcs_client_);
  mcs_client_->AddHeartbeatInterval(scope, interval_ms);
}

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

void GCMClientImpl::StartCheckin() {
  // Make sure no checkin is in progress.
  if (checkin_request_.get())
    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_request_context_getter_.get(),
                         &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) {
  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() {
  // 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();

  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, base::Bind(&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() {
  // 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(
    const linked_ptr<RegistrationInfo>& registration_info) {
  DCHECK_EQ(state_, READY);

  // 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;
      }
    }

    if (matched) {
      delegate_->OnRegisterFinished(
          registration_info, registrations_iter->second, SUCCESS);
      return;
    }
  }

  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("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_request_context_getter_, &recorder_,
          source_to_record));
  registration_request->Start();
  pending_registration_requests_.insert(
      std::make_pair(registration_info, std::move(registration_request)));
}

void GCMClientImpl::OnRegisterCompleted(
    const linked_ptr<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 comparison.
    registrations_.erase(registration_info);
    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(
    const linked_ptr<RegistrationInfo>& registration_info,
    const std::string& registration_id) {
  DCHECK_EQ(state_, READY);

  // 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(
    const linked_ptr<RegistrationInfo>& registration_info) {
  DCHECK_EQ(state_, READY);

  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_request_context_getter_, &recorder_,
          source_to_record));
  unregistration_request->Start();
  pending_unregistration_requests_.insert(
      std::make_pair(registration_info, std::move(unregistration_request)));
}

void GCMClientImpl::OnUnregisterCompleted(
    const linked_ptr<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);

  RecordOutgoingMessageToUMA(message);

  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 (MessageData::const_iterator 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,
    GCMEncryptionProvider::DecryptionResult result) {
  recorder_.RecordDecryptionFailure(app_id, result);
}

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

void GCMClientImpl::ClearActivityLogs() {
  recorder_.Clear();
}

GCMClient::GCMStatistics GCMClientImpl::GetStatistics() const {
  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_.get() != NULL;
  stats.last_checkin = last_checkin_time_;
  stats.next_checkin =
      last_checkin_time_ + gservices_settings_.GetCheckinInterval();
  if (connection_factory_.get())
    stats.connection_state = connection_factory_->GetConnectionStateString();
  if (mcs_client_.get()) {
    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;
  recorder_.CollectActivities(&stats.recorded_activities);

  for (RegistrationInfoMap::const_iterator 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, kMessageTypeKey or kSendErrorMessageIdKey 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;
  MessageData::iterator 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) {
  std::string sender = data_message_stanza.from();

  // Drop the message when the app is not registered for the sender of the
  // message.
  bool registered = false;

  // First, find among all GCM registrations.
  std::unique_ptr<GCMRegistrationInfo> gcm_registration(
      new GCMRegistrationInfo);
  gcm_registration->app_id = app_id;
  auto gcm_registration_iter = registrations_.find(
      make_linked_ptr<RegistrationInfo>(gcm_registration.release()));
  if (gcm_registration_iter != registrations_.end()) {
    GCMRegistrationInfo* cached_gcm_registration =
        GCMRegistrationInfo::FromRegistrationInfo(
            gcm_registration_iter->first.get());
    if (cached_gcm_registration &&
        std::find(cached_gcm_registration->sender_ids.begin(),
                  cached_gcm_registration->sender_ids.end(),
                  sender) != cached_gcm_registration->sender_ids.end()) {
      if (was_subtype)
        DLOG(ERROR) << "GCM message for non-IID " << app_id << " used subtype";
      else
        registered = true;
    }
  }

  // Then, find among all InstanceID registrations.
  if (!registered) {
    std::unique_ptr<InstanceIDTokenInfo> instance_id_token(
        new InstanceIDTokenInfo);
    instance_id_token->app_id = app_id;
    instance_id_token->authorized_entity = sender;
    instance_id_token->scope = kGCMScope;
    auto instance_id_token_iter = registrations_.find(
        make_linked_ptr<RegistrationInfo>(instance_id_token.release()));
    if (instance_id_token_iter != registrations_.end()) {
      if (was_subtype != InstanceIDUsesSubtypeForAppId(app_id)) {
        DLOG(ERROR) << "GCM message for " << app_id
                    << " incorrectly had was_subtype = " << was_subtype;
      } else {
        registered = true;
      }
    }
  }

  UMA_HISTOGRAM_BOOLEAN("GCM.DataMessageReceivedHasRegisteredApp", registered);
  if (registered) {
    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, sender,
      data_message_stanza.ByteSize(), registered,
      GCMStatsRecorder::DATA_MESSAGE);
  if (!registered)
    return;

  IncomingMessage incoming_message;
  incoming_message.sender_id = data_message_stanza.from();
  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;
  MessageData::iterator 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(),
                                      true /* to_registered_app */,
                                      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;

  MessageData::iterator iter =
      send_error_details.additional_data.find(kSendErrorMessageIdKey);
  if (iter != send_error_details.additional_data.end()) {
    send_error_details.message_id = iter->second;
    send_error_details.additional_data.erase(iter);
  }

  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
