// 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 "google_apis/gcm/engine/gcm_store_impl.h"

#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/threading/scoped_thread_priority.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.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/protocol/mcs.pb.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"

namespace gcm {

namespace {

// This enum is used in an UMA histogram (GCMLoadStatus enum defined in
// tools/metrics/histograms/histogram.xml). Hence the entries here shouldn't
// be deleted or re-ordered and new ones should be added to the end.
enum LoadStatus {
  LOADING_SUCCEEDED,
  RELOADING_OPEN_STORE,
  OPENING_STORE_FAILED,
  LOADING_DEVICE_CREDENTIALS_FAILED,
  LOADING_REGISTRATION_FAILED,
  LOADING_INCOMING_MESSAGES_FAILED,
  LOADING_OUTGOING_MESSAGES_FAILED,
  LOADING_LAST_CHECKIN_INFO_FAILED,
  LOADING_GSERVICE_SETTINGS_FAILED,
  LOADING_ACCOUNT_MAPPING_FAILED,
  LOADING_LAST_TOKEN_TIME_FAILED,
  LOADING_HEARTBEAT_INTERVALS_FAILED,
  LOADING_INSTANCE_ID_DATA_FAILED,
  STORE_DOES_NOT_EXIST,

  // NOTE: always keep this entry at the end. Add new status types only
  // immediately above this line. Make sure to update the corresponding
  // histogram enum accordingly.
  LOAD_STATUS_COUNT
};

// Limit to the number of outstanding messages per app.
const int kMessagesPerAppLimit = 20;

// ---- LevelDB keys. ----
// Key for this device's android id.
const char kDeviceAIDKey[] = "device_aid_key";
// Key for this device's android security token.
const char kDeviceTokenKey[] = "device_token_key";
// Lowest lexicographically ordered app ids.
// Used for prefixing app id.
const char kRegistrationKeyStart[] = "reg1-";
// Key guaranteed to be higher than all app ids.
// Used for limiting iteration.
const char kRegistrationKeyEnd[] = "reg2-";
// Lowest lexicographically ordered incoming message key.
// Used for prefixing messages.
const char kIncomingMsgKeyStart[] = "incoming1-";
// Key guaranteed to be higher than all incoming message keys.
// Used for limiting iteration.
const char kIncomingMsgKeyEnd[] = "incoming2-";
// Lowest lexicographically ordered outgoing message key.
// Used for prefixing outgoing messages.
const char kOutgoingMsgKeyStart[] = "outgoing1-";
// Key guaranteed to be higher than all outgoing message keys.
// Used for limiting iteration.
const char kOutgoingMsgKeyEnd[] = "outgoing2-";
// Lowest lexicographically ordered G-service settings key.
// Used for prefixing G-services settings.
const char kGServiceSettingKeyStart[] = "gservice1-";
// Key guaranteed to be higher than all G-services settings keys.
// Used for limiting iteration.
const char kGServiceSettingKeyEnd[] = "gservice2-";
// Key for digest of the last G-services settings update.
const char kGServiceSettingsDigestKey[] = "gservices_digest";
// Key used to indicate how many accounts were last checked in with this device.
const char kLastCheckinAccountsKey[] = "last_checkin_accounts_count";
// Key used to timestamp last checkin (marked with G services settings update).
const char kLastCheckinTimeKey[] = "last_checkin_time";
// Lowest lexicographically ordered account key.
// Used for prefixing account information.
const char kAccountKeyStart[] = "account1-";
// Key guaranteed to be higher than all account keys.
// Used for limiting iteration.
const char kAccountKeyEnd[] = "account2-";
// Lowest lexicographically ordered heartbeat key.
// Used for prefixing account information.
const char kHeartbeatKeyStart[] = "heartbeat1-";
// Key guaranteed to be higher than all heartbeat keys.
// Used for limiting iteration.
const char kHeartbeatKeyEnd[] = "heartbeat2-";
// Key used for last token fetch time.
const char kLastTokenFetchTimeKey[] = "last_token_fetch_time";
// Lowest lexicographically ordered app ids.
// Used for prefixing app id.
const char kInstanceIDKeyStart[] = "iid1-";
// Key guaranteed to be higher than all app ids.
// Used for limiting iteration.
const char kInstanceIDKeyEnd[] = "iid2-";

std::string MakeRegistrationKey(const std::string& app_id) {
  return kRegistrationKeyStart + app_id;
}

std::string ParseRegistrationKey(const std::string& key) {
  return key.substr(base::size(kRegistrationKeyStart) - 1);
}

std::string MakeIncomingKey(const std::string& persistent_id) {
  return kIncomingMsgKeyStart + persistent_id;
}

std::string MakeOutgoingKey(const std::string& persistent_id) {
  return kOutgoingMsgKeyStart + persistent_id;
}

std::string ParseOutgoingKey(const std::string& key) {
  return key.substr(base::size(kOutgoingMsgKeyStart) - 1);
}

std::string MakeGServiceSettingKey(const std::string& setting_name) {
  return kGServiceSettingKeyStart + setting_name;
}

std::string ParseGServiceSettingKey(const std::string& key) {
  return key.substr(base::size(kGServiceSettingKeyStart) - 1);
}

std::string MakeAccountKey(const std::string& account_id) {
  return kAccountKeyStart + account_id;
}

std::string ParseAccountKey(const std::string& key) {
  return key.substr(base::size(kAccountKeyStart) - 1);
}

std::string MakeHeartbeatKey(const std::string& scope) {
  return kHeartbeatKeyStart + scope;
}

std::string ParseHeartbeatKey(const std::string& key) {
  return key.substr(base::size(kHeartbeatKeyStart) - 1);
}

std::string MakeInstanceIDKey(const std::string& app_id) {
  return kInstanceIDKeyStart + app_id;
}

std::string ParseInstanceIDKey(const std::string& key) {
  return key.substr(base::size(kInstanceIDKeyStart) - 1);
}

// Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore
// outlive the slice.
// For example: MakeSlice(MakeOutgoingKey(x)) is invalid.
leveldb::Slice MakeSlice(const base::StringPiece& s) {
  return leveldb::Slice(s.begin(), s.size());
}

}  // namespace

class GCMStoreImpl::Backend
    : public base::RefCountedThreadSafe<GCMStoreImpl::Backend> {
 public:
  Backend(const base::FilePath& path,
          scoped_refptr<base::SequencedTaskRunner> foreground_runner,
          std::unique_ptr<Encryptor> encryptor);

  // Blocking implementations of GCMStoreImpl methods.
  void Load(StoreOpenMode open_mode, const LoadCallback& callback);
  void Close();
  void Destroy(const UpdateCallback& callback);
  void SetDeviceCredentials(uint64_t device_android_id,
                            uint64_t device_security_token,
                            const UpdateCallback& callback);
  void AddRegistration(const std::string& serialized_key,
                       const std::string& serialized_value,
                       const UpdateCallback& callback);
  void RemoveRegistration(const std::string& serialized_key,
                          const UpdateCallback& callback);
  void AddIncomingMessage(const std::string& persistent_id,
                          const UpdateCallback& callback);
  void RemoveIncomingMessages(const PersistentIdList& persistent_ids,
                              const UpdateCallback& callback);
  void AddOutgoingMessage(const std::string& persistent_id,
                          const MCSMessage& message,
                          const UpdateCallback& callback);
  void RemoveOutgoingMessages(
      const PersistentIdList& persistent_ids,
      const base::Callback<void(bool, const AppIdToMessageCountMap&)>
          callback);
  void AddUserSerialNumber(const std::string& username,
                           int64_t serial_number,
                           const UpdateCallback& callback);
  void RemoveUserSerialNumber(const std::string& username,
                              const UpdateCallback& callback);
  void SetLastCheckinInfo(const base::Time& time,
                          const std::set<std::string>& accounts,
                          const UpdateCallback& callback);
  void SetGServicesSettings(
      const std::map<std::string, std::string>& settings,
      const std::string& digest,
      const UpdateCallback& callback);
  void AddAccountMapping(const AccountMapping& account_mapping,
                         const UpdateCallback& callback);
  void RemoveAccountMapping(const std::string& account_id,
                            const UpdateCallback& callback);
  void SetLastTokenFetchTime(const base::Time& time,
                             const UpdateCallback& callback);
  void AddHeartbeatInterval(const std::string& scope,
                            int interval_ms,
                            const UpdateCallback& callback);
  void RemoveHeartbeatInterval(const std::string& scope,
                               const UpdateCallback& callback);
  void AddInstanceIDData(const std::string& app_id,
                         const std::string& instance_id_data,
                         const UpdateCallback& callback);
  void RemoveInstanceIDData(const std::string& app_id,
                            const UpdateCallback& callback);
  void SetValue(const std::string& key,
                const std::string& value,
                const UpdateCallback& callback);

 private:
  friend class base::RefCountedThreadSafe<Backend>;
  ~Backend();

  LoadStatus OpenStoreAndLoadData(StoreOpenMode open_mode, LoadResult* result);
  bool LoadDeviceCredentials(uint64_t* android_id, uint64_t* security_token);
  bool LoadRegistrations(std::map<std::string, std::string>* registrations);
  bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
  bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
  bool LoadLastCheckinInfo(base::Time* last_checkin_time,
                           std::set<std::string>* accounts);
  bool LoadGServicesSettings(std::map<std::string, std::string>* settings,
                             std::string* digest);
  bool LoadAccountMappingInfo(AccountMappings* account_mappings);
  bool LoadLastTokenFetchTime(base::Time* last_token_fetch_time);
  bool LoadHeartbeatIntervals(std::map<std::string, int>* heartbeat_intervals);
  bool LoadInstanceIDData(std::map<std::string, std::string>* instance_id_data);

  const base::FilePath path_;
  scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
  std::unique_ptr<Encryptor> encryptor_;

  std::unique_ptr<leveldb::DB> db_;
};

GCMStoreImpl::Backend::Backend(
    const base::FilePath& path,
    scoped_refptr<base::SequencedTaskRunner> foreground_task_runner,
    std::unique_ptr<Encryptor> encryptor)
    : path_(path),
      foreground_task_runner_(foreground_task_runner),
      encryptor_(std::move(encryptor)) {}

GCMStoreImpl::Backend::~Backend() {}

LoadStatus GCMStoreImpl::Backend::OpenStoreAndLoadData(StoreOpenMode open_mode,
                                                       LoadResult* result) {
  LoadStatus load_status;
  if (db_.get()) {
    LOG(ERROR) << "Attempting to reload open database.";
    return RELOADING_OPEN_STORE;
  }

  // Checks if the store exists or not. Opening a db with create_if_missing
  // not set will still create a new directory if the store does not exist.
  if (open_mode == DO_NOT_CREATE &&
      !leveldb_chrome::PossiblyValidDB(path_, leveldb::Env::Default())) {
    DVLOG(2) << "Database " << path_.value() << " does not exist";
    return STORE_DOES_NOT_EXIST;
  }

  leveldb_env::Options options;
  options.create_if_missing = open_mode == CREATE_IF_MISSING;
  options.paranoid_checks = true;
  leveldb::Status status =
      leveldb_env::OpenDB(options, path_.AsUTF8Unsafe(), &db_);
  UMA_HISTOGRAM_ENUMERATION("GCM.Database.Open",
                            leveldb_env::GetLevelDBStatusUMAValue(status),
                            leveldb_env::LEVELDB_STATUS_MAX);
  if (!status.ok()) {
    LOG(ERROR) << "Failed to open database " << path_.value() << ": "
               << status.ToString();
    return OPENING_STORE_FAILED;
  }

  if (!LoadDeviceCredentials(&result->device_android_id,
                             &result->device_security_token)) {
    return LOADING_DEVICE_CREDENTIALS_FAILED;
  }
  if (!LoadRegistrations(&result->registrations))
    return LOADING_REGISTRATION_FAILED;
  if (!LoadIncomingMessages(&result->incoming_messages))
    return LOADING_INCOMING_MESSAGES_FAILED;
  if (!LoadOutgoingMessages(&result->outgoing_messages))
    return LOADING_OUTGOING_MESSAGES_FAILED;
  if (!LoadLastCheckinInfo(&result->last_checkin_time,
                           &result->last_checkin_accounts)) {
    return LOADING_LAST_CHECKIN_INFO_FAILED;
  }
  if (!LoadGServicesSettings(&result->gservices_settings,
                             &result->gservices_digest)) {
    return load_status = LOADING_GSERVICE_SETTINGS_FAILED;
  }
  if (!LoadAccountMappingInfo(&result->account_mappings))
    return LOADING_ACCOUNT_MAPPING_FAILED;
  if (!LoadLastTokenFetchTime(&result->last_token_fetch_time))
    return LOADING_LAST_TOKEN_TIME_FAILED;
  if (!LoadHeartbeatIntervals(&result->heartbeat_intervals))
    return LOADING_HEARTBEAT_INTERVALS_FAILED;
  if (!LoadInstanceIDData(&result->instance_id_data))
    return LOADING_INSTANCE_ID_DATA_FAILED;

  return LOADING_SUCCEEDED;
}

void GCMStoreImpl::Backend::Load(StoreOpenMode open_mode,
                                 const LoadCallback& callback) {
  std::unique_ptr<LoadResult> result(new LoadResult());
  LoadStatus load_status = OpenStoreAndLoadData(open_mode, result.get());
  UMA_HISTOGRAM_ENUMERATION("GCM.LoadStatus", load_status, LOAD_STATUS_COUNT);
  if (load_status != LOADING_SUCCEEDED) {
    result->Reset();
    result->store_does_not_exist = (load_status == STORE_DOES_NOT_EXIST);
    foreground_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(callback, std::move(result)));
    return;
  }

  // |result->registrations| contains both GCM registrations and InstanceID
  // tokens. Count them separately.
  int gcm_registration_count = 0;
  int instance_id_token_count = 0;
  for (const auto& registration : result->registrations) {
    if (base::StartsWith(registration.first, "iid-",
                         base::CompareCase::SENSITIVE))
      instance_id_token_count++;
    else
      gcm_registration_count++;
  }

  // Only record histograms if GCM had already been set up for this device.
  if (result->device_android_id != 0 && result->device_security_token != 0) {
    int64_t file_size = 0;
    if (base::GetFileSize(path_, &file_size)) {
      UMA_HISTOGRAM_COUNTS_1M("GCM.StoreSizeKB",
                              static_cast<int>(file_size / 1024));
    }

    UMA_HISTOGRAM_COUNTS_1M("GCM.RestoredRegistrations",
                            gcm_registration_count);
    UMA_HISTOGRAM_COUNTS_1M("GCM.RestoredOutgoingMessages",
                            result->outgoing_messages.size());
    UMA_HISTOGRAM_COUNTS_1M("GCM.RestoredIncomingMessages",
                            result->incoming_messages.size());

    UMA_HISTOGRAM_COUNTS_1M("InstanceID.RestoredTokenCount",
                            instance_id_token_count);
    UMA_HISTOGRAM_COUNTS_1M("InstanceID.RestoredIDCount",
                            result->instance_id_data.size());
  }

  DVLOG(1) << "Succeeded in loading "
           << gcm_registration_count << " GCM registrations, "
           << result->incoming_messages.size()
           << " unacknowledged incoming messages "
           << result->outgoing_messages.size()
           << " unacknowledged outgoing messages, "
           << result->instance_id_data.size() << " Instance IDs, "
           << instance_id_token_count << " InstanceID tokens.";
  result->success = true;
  foreground_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(callback, std::move(result)));
  return;
}

void GCMStoreImpl::Backend::Close() {
  DVLOG(1) << "Closing GCM store.";
  db_.reset();
}

void GCMStoreImpl::Backend::Destroy(const UpdateCallback& callback) {
  DVLOG(1) << "Destroying GCM store.";
  db_.reset();
  const leveldb::Status s =
      leveldb::DestroyDB(path_.AsUTF8Unsafe(), leveldb_env::Options());
  if (s.ok()) {
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, true));
    return;
  }
  LOG(ERROR) << "Destroy failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, false));
}

void GCMStoreImpl::Backend::SetDeviceCredentials(
    uint64_t device_android_id,
    uint64_t device_security_token,
    const UpdateCallback& callback) {
  DVLOG(1) << "Saving device credentials with AID " << device_android_id;
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  std::string encrypted_token;
  encryptor_->EncryptString(base::NumberToString(device_security_token),
                            &encrypted_token);
  std::string android_id_str = base::NumberToString(device_android_id);
  leveldb::Status s =
      db_->Put(write_options,
               MakeSlice(kDeviceAIDKey),
               MakeSlice(android_id_str));
  if (s.ok()) {
    s = db_->Put(
        write_options, MakeSlice(kDeviceTokenKey), MakeSlice(encrypted_token));
  }
  if (s.ok()) {
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, true));
    return;
  }
  LOG(ERROR) << "LevelDB put failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, false));
}

void GCMStoreImpl::Backend::AddRegistration(
    const std::string& serialized_key,
    const std::string& serialized_value,
    const UpdateCallback& callback) {
  DVLOG(1) << "Saving registration info for app: " << serialized_key;
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  const leveldb::Status status = db_->Put(
      write_options,
      MakeSlice(MakeRegistrationKey(serialized_key)),
      MakeSlice(serialized_value));
  if (!status.ok())
    LOG(ERROR) << "LevelDB put failed: " << status.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, status.ok()));
}

void GCMStoreImpl::Backend::RemoveRegistration(
    const std::string& serialized_key,
    const UpdateCallback& callback) {
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  leveldb::Status status = db_->Delete(
      write_options, MakeSlice(MakeRegistrationKey(serialized_key)));
  if (!status.ok())
    LOG(ERROR) << "LevelDB remove failed: " << status.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, status.ok()));
}

void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id,
                                               const UpdateCallback& callback) {
  DVLOG(1) << "Saving incoming message with id " << persistent_id;
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  std::string key = MakeIncomingKey(persistent_id);
  const leveldb::Status s = db_->Put(write_options,
                                     MakeSlice(key),
                                     MakeSlice(persistent_id));
  if (s.ok()) {
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, true));
    return;
  }
  LOG(ERROR) << "LevelDB put failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, false));
}

void GCMStoreImpl::Backend::RemoveIncomingMessages(
    const PersistentIdList& persistent_ids,
    const UpdateCallback& callback) {
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  leveldb::Status s;
  for (PersistentIdList::const_iterator iter = persistent_ids.begin();
       iter != persistent_ids.end();
       ++iter) {
    DVLOG(1) << "Removing incoming message with id " << *iter;
    std::string key = MakeIncomingKey(*iter);
    s = db_->Delete(write_options, MakeSlice(key));
    if (!s.ok())
      break;
  }
  if (s.ok()) {
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, true));
    return;
  }
  LOG(ERROR) << "LevelDB remove failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, false));
}

void GCMStoreImpl::Backend::AddOutgoingMessage(const std::string& persistent_id,
                                               const MCSMessage& message,
                                               const UpdateCallback& callback) {
  DVLOG(1) << "Saving outgoing message with id " << persistent_id;
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  std::string data =
      static_cast<char>(message.tag()) + message.SerializeAsString();
  std::string key = MakeOutgoingKey(persistent_id);
  const leveldb::Status s = db_->Put(write_options,
                                     MakeSlice(key),
                                     MakeSlice(data));
  if (s.ok()) {
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, true));
    return;
  }
  LOG(ERROR) << "LevelDB put failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, false));
}

void GCMStoreImpl::Backend::RemoveOutgoingMessages(
    const PersistentIdList& persistent_ids,
    const base::Callback<void(bool, const AppIdToMessageCountMap&)>
        callback) {
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(callback, false, AppIdToMessageCountMap()));
    return;
  }
  leveldb::ReadOptions read_options;
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  AppIdToMessageCountMap removed_message_counts;

  leveldb::Status s;
  for (PersistentIdList::const_iterator iter = persistent_ids.begin();
       iter != persistent_ids.end();
       ++iter) {
    DVLOG(1) << "Removing outgoing message with id " << *iter;
    std::string outgoing_message;
    std::string key = MakeOutgoingKey(*iter);
    s = db_->Get(read_options,
                 MakeSlice(key),
                 &outgoing_message);
    if (!s.ok())
      break;
    mcs_proto::DataMessageStanza data_message;
    // Skip the initial tag byte and parse the rest to extract the message.
    if (data_message.ParseFromString(outgoing_message.substr(1))) {
      DCHECK(!data_message.category().empty());
      if (removed_message_counts.count(data_message.category()) != 0)
        removed_message_counts[data_message.category()]++;
      else
        removed_message_counts[data_message.category()] = 1;
    }
    DVLOG(1) << "Removing outgoing message with id " << *iter;
    s = db_->Delete(write_options, MakeSlice(key));
    if (!s.ok())
      break;
  }
  if (s.ok()) {
    foreground_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(callback, true, removed_message_counts));
    return;
  }
  LOG(ERROR) << "LevelDB remove failed: " << s.ToString();
  foreground_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(callback, false, AppIdToMessageCountMap()));
}

void GCMStoreImpl::Backend::SetLastCheckinInfo(
    const base::Time& time,
    const std::set<std::string>& accounts,
    const UpdateCallback& callback) {
  leveldb::WriteBatch write_batch;

  int64_t last_checkin_time_internal = time.ToInternalValue();
  write_batch.Put(MakeSlice(kLastCheckinTimeKey),
                  MakeSlice(base::NumberToString(last_checkin_time_internal)));

  std::string serialized_accounts;
  for (std::set<std::string>::iterator iter = accounts.begin();
       iter != accounts.end();
       ++iter) {
    serialized_accounts += *iter;
    serialized_accounts += ",";
  }
  if (!serialized_accounts.empty())
    serialized_accounts.erase(serialized_accounts.length() - 1);

  write_batch.Put(MakeSlice(kLastCheckinAccountsKey),
                  MakeSlice(serialized_accounts));

  leveldb::WriteOptions write_options;
  write_options.sync = true;
  const leveldb::Status s = db_->Write(write_options, &write_batch);

  if (!s.ok())
    LOG(ERROR) << "LevelDB set last checkin info failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::AddInstanceIDData(const std::string& app_id,
                                     const std::string& instance_id_data,
                                     const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::AddInstanceIDData,
                                backend_, app_id, instance_id_data, callback));
}

void GCMStoreImpl::RemoveInstanceIDData(const std::string& app_id,
                                        const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::RemoveInstanceIDData,
                                backend_, app_id, callback));
}

void GCMStoreImpl::Backend::SetGServicesSettings(
    const std::map<std::string, std::string>& settings,
    const std::string& settings_digest,
    const UpdateCallback& callback) {
  leveldb::WriteBatch write_batch;

  // Remove all existing settings.
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;
  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kGServiceSettingKeyStart));
       iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd;
       iter->Next()) {
    write_batch.Delete(iter->key());
  }

  // Add the new settings.
  for (std::map<std::string, std::string>::const_iterator iter =
           settings.begin();
       iter != settings.end(); ++iter) {
    write_batch.Put(MakeSlice(MakeGServiceSettingKey(iter->first)),
                    MakeSlice(iter->second));
  }

  // Update the settings digest.
  write_batch.Put(MakeSlice(kGServiceSettingsDigestKey),
                  MakeSlice(settings_digest));

  // Write it all in a batch.
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  leveldb::Status s = db_->Write(write_options, &write_batch);
  if (!s.ok())
    LOG(ERROR) << "LevelDB GService Settings update failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::Backend::AddAccountMapping(
    const AccountMapping& account_mapping,
    const UpdateCallback& callback) {
  DVLOG(1) << "Saving account info for account with email: "
           << account_mapping.email;
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  std::string data = account_mapping.SerializeAsString();
  std::string key = MakeAccountKey(account_mapping.account_id);
  const leveldb::Status s =
      db_->Put(write_options, MakeSlice(key), MakeSlice(data));
  if (!s.ok())
    LOG(ERROR) << "LevelDB adding account mapping failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::Backend::RemoveAccountMapping(
    const std::string& account_id,
    const UpdateCallback& callback) {
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  leveldb::Status s =
      db_->Delete(write_options, MakeSlice(MakeAccountKey(account_id)));

  if (!s.ok())
    LOG(ERROR) << "LevelDB removal of account mapping failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::Backend::SetLastTokenFetchTime(
    const base::Time& time,
    const UpdateCallback& callback) {
  DVLOG(1) << "Setting last token fetching time.";
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  const leveldb::Status s =
      db_->Put(write_options, MakeSlice(kLastTokenFetchTimeKey),
               MakeSlice(base::NumberToString(time.ToInternalValue())));

  if (!s.ok())
    LOG(ERROR) << "LevelDB setting last token fetching time: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::Backend::AddHeartbeatInterval(
    const std::string& scope,
    int interval_ms,
    const UpdateCallback& callback) {
  DVLOG(1) << "Saving a heartbeat interval: scope: " << scope
           << " interval: " << interval_ms << "ms.";
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  std::string data = base::NumberToString(interval_ms);
  std::string key = MakeHeartbeatKey(scope);
  const leveldb::Status s =
      db_->Put(write_options, MakeSlice(key), MakeSlice(data));
  if (!s.ok())
    LOG(ERROR) << "LevelDB adding heartbeat interval failed: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::Backend::RemoveHeartbeatInterval(
    const std::string& scope,
    const UpdateCallback& callback) {
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  leveldb::Status s =
      db_->Delete(write_options, MakeSlice(MakeHeartbeatKey(scope)));

  if (!s.ok()) {
    LOG(ERROR) << "LevelDB removal of heartbeat interval failed: "
               << s.ToString();
  }
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

void GCMStoreImpl::Backend::AddInstanceIDData(
    const std::string& app_id,
    const std::string& instance_id_data,
    const UpdateCallback& callback) {
  DVLOG(1) << "Adding Instance ID data.";
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  std::string key = MakeInstanceIDKey(app_id);
  const leveldb::Status status = db_->Put(write_options,
                                          MakeSlice(key),
                                          MakeSlice(instance_id_data));
  if (!status.ok())
    LOG(ERROR) << "LevelDB put failed: " << status.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, status.ok()));
}

void GCMStoreImpl::Backend::RemoveInstanceIDData(
    const std::string& app_id,
    const UpdateCallback& callback) {
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }
  leveldb::WriteOptions write_options;
  write_options.sync = true;

  leveldb::Status status =
      db_->Delete(write_options, MakeSlice(MakeInstanceIDKey(app_id)));
  if (!status.ok())
    LOG(ERROR) << "LevelDB remove failed: " << status.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, status.ok()));
}

void GCMStoreImpl::Backend::SetValue(const std::string& key,
                                     const std::string& value,
                                     const UpdateCallback& callback) {
  DVLOG(1) << "Injecting a value to GCM Store for testing. Key: "
           << key << ", Value: " << value;
  if (!db_.get()) {
    LOG(ERROR) << "GCMStore db doesn't exist.";
    foreground_task_runner_->PostTask(FROM_HERE,
                                      base::BindOnce(callback, false));
    return;
  }

  leveldb::WriteOptions write_options;
  write_options.sync = true;

  const leveldb::Status s =
      db_->Put(write_options, MakeSlice(key), MakeSlice(value));

  if (!s.ok())
    LOG(ERROR) << "LevelDB had problems injecting a value: " << s.ToString();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::BindOnce(callback, s.ok()));
}

bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64_t* android_id,
                                                  uint64_t* security_token) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::string result;
  leveldb::Status s = db_->Get(read_options, MakeSlice(kDeviceAIDKey), &result);
  if (s.ok()) {
    if (!base::StringToUint64(result, android_id)) {
      LOG(ERROR) << "Failed to restore device id.";
      return false;
    }
    result.clear();
    s = db_->Get(read_options, MakeSlice(kDeviceTokenKey), &result);
  }
  if (s.ok()) {
    // Mitigate the issues caused by loading DLLs on a background thread
    // (http://crbug/973868).
    base::ScopedThreadMayLoadLibraryOnBackgroundThread priority_boost(
        FROM_HERE);

    std::string decrypted_token;
    encryptor_->DecryptString(result, &decrypted_token);
    if (!base::StringToUint64(decrypted_token, security_token)) {
      LOG(ERROR) << "Failed to restore security token.";
      return false;
    }
    return true;
  }

  if (s.IsNotFound()) {
    DVLOG(1) << "No credentials found.";
    return true;
  }

  LOG(ERROR) << "Error reading credentials from store.";
  return false;
}

bool GCMStoreImpl::Backend::LoadRegistrations(
    std::map<std::string, std::string>* registrations) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kRegistrationKeyStart));
       iter->Valid() && iter->key().ToString() < kRegistrationKeyEnd;
       iter->Next()) {
    leveldb::Slice s = iter->value();
    if (s.size() <= 1) {
      LOG(ERROR) << "Error reading registration with key " << s.ToString();
      return false;
    }
    std::string app_id = ParseRegistrationKey(iter->key().ToString());
    DVLOG(1) << "Found registration with app id " << app_id;
    (*registrations)[app_id] = iter->value().ToString();
  }

  return true;
}

bool GCMStoreImpl::Backend::LoadIncomingMessages(
    std::vector<std::string>* incoming_messages) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kIncomingMsgKeyStart));
       iter->Valid() && iter->key().ToString() < kIncomingMsgKeyEnd;
       iter->Next()) {
    leveldb::Slice s = iter->value();
    if (s.empty()) {
      LOG(ERROR) << "Error reading incoming message with key "
                 << iter->key().ToString();
      return false;
    }
    DVLOG(1) << "Found incoming message with id " << s.ToString();
    incoming_messages->push_back(s.ToString());
  }

  return true;
}

bool GCMStoreImpl::Backend::LoadOutgoingMessages(
    OutgoingMessageMap* outgoing_messages) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kOutgoingMsgKeyStart));
       iter->Valid() && iter->key().ToString() < kOutgoingMsgKeyEnd;
       iter->Next()) {
    leveldb::Slice s = iter->value();
    if (s.size() <= 1) {
      LOG(ERROR) << "Error reading incoming message with key " << s.ToString();
      return false;
    }
    uint8_t tag = iter->value().data()[0];
    std::string id = ParseOutgoingKey(iter->key().ToString());
    std::unique_ptr<google::protobuf::MessageLite> message(
        BuildProtobufFromTag(tag));
    if (!message.get() ||
        !message->ParseFromString(iter->value().ToString().substr(1))) {
      LOG(ERROR) << "Failed to parse outgoing message with id " << id
                 << " and tag " << tag;
      return false;
    }
    DVLOG(1) << "Found outgoing message with id " << id << " of type "
             << base::NumberToString(tag);
    (*outgoing_messages)[id] = std::move(message);
  }

  return true;
}

bool GCMStoreImpl::Backend::LoadLastCheckinInfo(
    base::Time* last_checkin_time,
    std::set<std::string>* accounts) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::string result;
  leveldb::Status s = db_->Get(read_options,
                               MakeSlice(kLastCheckinTimeKey),
                               &result);
  int64_t time_internal = 0LL;
  if (s.ok() && !base::StringToInt64(result, &time_internal)) {
    LOG(ERROR) << "Failed to restore last checkin time. Using default = 0.";
    time_internal = 0LL;
  }

  // In case we cannot read last checkin time, we default it to 0, as we don't
  // want that situation to cause the whole load to fail.
  *last_checkin_time = base::Time::FromInternalValue(time_internal);

  accounts->clear();
  s = db_->Get(read_options, MakeSlice(kLastCheckinAccountsKey), &result);
  if (!s.ok())
    DVLOG(1) << "No accounts where stored during last run.";

  base::StringTokenizer t(result, ",");
  while (t.GetNext())
    accounts->insert(t.token());

  return true;
}

bool GCMStoreImpl::Backend::LoadGServicesSettings(
    std::map<std::string, std::string>* settings,
    std::string* digest) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  // Load all of the GServices settings.
  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kGServiceSettingKeyStart));
       iter->Valid() && iter->key().ToString() < kGServiceSettingKeyEnd;
       iter->Next()) {
    std::string value = iter->value().ToString();
    if (value.empty()) {
      LOG(ERROR) << "Error reading GService Settings " << value;
      return false;
    }
    std::string id = ParseGServiceSettingKey(iter->key().ToString());
    (*settings)[id] = value;
    DVLOG(1) << "Found G Service setting with key: " << id
             << ", and value: " << value;
  }

  // Load the settings digest. It's ok if it is empty.
  db_->Get(read_options, MakeSlice(kGServiceSettingsDigestKey), digest);

  return true;
}

bool GCMStoreImpl::Backend::LoadAccountMappingInfo(
    AccountMappings* account_mappings) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kAccountKeyStart));
       iter->Valid() && iter->key().ToString() < kAccountKeyEnd;
       iter->Next()) {
    AccountMapping account_mapping;
    account_mapping.account_id = ParseAccountKey(iter->key().ToString());
    if (!account_mapping.ParseFromString(iter->value().ToString())) {
      DVLOG(1) << "Failed to parse account info with ID: "
               << account_mapping.account_id;
      return false;
    }
    DVLOG(1) << "Found account mapping with ID: " << account_mapping.account_id;
    account_mappings->push_back(account_mapping);
  }

  return true;
}

bool GCMStoreImpl::Backend::LoadLastTokenFetchTime(
    base::Time* last_token_fetch_time) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::string result;
  leveldb::Status s =
      db_->Get(read_options, MakeSlice(kLastTokenFetchTimeKey), &result);
  int64_t time_internal = 0LL;
  if (s.ok() && !base::StringToInt64(result, &time_internal)) {
    LOG(ERROR) <<
        "Failed to restore last token fetching time. Using default = 0.";
    time_internal = 0LL;
  }

  // In case we cannot read last token fetching time, we default it to 0.
  *last_token_fetch_time = base::Time::FromInternalValue(time_internal);

  return true;
}

bool GCMStoreImpl::Backend::LoadHeartbeatIntervals(
    std::map<std::string, int>* heartbeat_intervals) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kHeartbeatKeyStart));
       iter->Valid() && iter->key().ToString() < kHeartbeatKeyEnd;
       iter->Next()) {
    std::string scope = ParseHeartbeatKey(iter->key().ToString());
    int interval_ms;
    if (!base::StringToInt(iter->value().ToString(), &interval_ms)) {
      DVLOG(1) << "Failed to parse heartbeat interval info with scope: "
               << scope;
      return false;
    }
    DVLOG(1) << "Found heartbeat interval with scope: " << scope
             << " interval: " << interval_ms << "ms.";
    (*heartbeat_intervals)[scope] = interval_ms;
  }

  return true;
}

bool GCMStoreImpl::Backend::LoadInstanceIDData(
    std::map<std::string, std::string>* instance_id_data) {
  leveldb::ReadOptions read_options;
  read_options.verify_checksums = true;

  std::unique_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
  for (iter->Seek(MakeSlice(kInstanceIDKeyStart));
       iter->Valid() && iter->key().ToString() < kInstanceIDKeyEnd;
       iter->Next()) {
    leveldb::Slice s = iter->value();
    if (s.size() <= 1) {
      LOG(ERROR) << "Error reading IID data with key " << s.ToString();
      return false;
    }
    std::string app_id = ParseInstanceIDKey(iter->key().ToString());
    DVLOG(1) << "Found IID data with app id " << app_id;
    (*instance_id_data)[app_id] = s.ToString();
  }

  return true;
}

GCMStoreImpl::GCMStoreImpl(
    const base::FilePath& path,
    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner,
    std::unique_ptr<Encryptor> encryptor)
    : backend_(new Backend(path,
                           base::ThreadTaskRunnerHandle::Get(),
                           std::move(encryptor))),
      blocking_task_runner_(blocking_task_runner),
      weak_ptr_factory_(this) {}

GCMStoreImpl::~GCMStoreImpl() {}

void GCMStoreImpl::Load(StoreOpenMode open_mode, const LoadCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&GCMStoreImpl::Backend::Load, backend_, open_mode,
                     base::Bind(&GCMStoreImpl::LoadContinuation,
                                weak_ptr_factory_.GetWeakPtr(), callback)));
}

void GCMStoreImpl::Close() {
  weak_ptr_factory_.InvalidateWeakPtrs();
  app_message_counts_.clear();
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::Close, backend_));
}

void GCMStoreImpl::Destroy(const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&GCMStoreImpl::Backend::Destroy, backend_, callback));
}

void GCMStoreImpl::SetDeviceCredentials(uint64_t device_android_id,
                                        uint64_t device_security_token,
                                        const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&GCMStoreImpl::Backend::SetDeviceCredentials, backend_,
                     device_android_id, device_security_token, callback));
}

void GCMStoreImpl::AddRegistration(
    const std::string& serialized_key,
    const std::string& serialized_value,
    const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&GCMStoreImpl::Backend::AddRegistration, backend_,
                     serialized_key, serialized_value, callback));
}

void GCMStoreImpl::RemoveRegistration(const std::string& app_id,
                                          const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::RemoveRegistration,
                                backend_, app_id, callback));
}

void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id,
                                      const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::AddIncomingMessage,
                                backend_, persistent_id, callback));
}

void GCMStoreImpl::RemoveIncomingMessage(const std::string& persistent_id,
                                         const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(&GCMStoreImpl::Backend::RemoveIncomingMessages, backend_,
                     PersistentIdList(1, persistent_id), callback));
}

void GCMStoreImpl::RemoveIncomingMessages(
    const PersistentIdList& persistent_ids,
    const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::RemoveIncomingMessages,
                                backend_, persistent_ids, callback));
}

bool GCMStoreImpl::AddOutgoingMessage(const std::string& persistent_id,
                                      const MCSMessage& message,
                                      const UpdateCallback& callback) {
  DCHECK_EQ(message.tag(), kDataMessageStanzaTag);
  std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>(
                           &message.GetProtobuf())->category();
  DCHECK(!app_id.empty());
  if (app_message_counts_.count(app_id) == 0)
    app_message_counts_[app_id] = 0;
  if (app_message_counts_[app_id] < kMessagesPerAppLimit) {
    app_message_counts_[app_id]++;

    blocking_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(
            &GCMStoreImpl::Backend::AddOutgoingMessage, backend_, persistent_id,
            message,
            base::Bind(&GCMStoreImpl::AddOutgoingMessageContinuation,
                       weak_ptr_factory_.GetWeakPtr(), callback, app_id)));
    return true;
  }
  return false;
}

void GCMStoreImpl::OverwriteOutgoingMessage(const std::string& persistent_id,
                                            const MCSMessage& message,
                                            const UpdateCallback& callback) {
  DCHECK_EQ(message.tag(), kDataMessageStanzaTag);
  std::string app_id = reinterpret_cast<const mcs_proto::DataMessageStanza*>(
                           &message.GetProtobuf())->category();
  DCHECK(!app_id.empty());
  // There should already be pending messages for this app.
  DCHECK(app_message_counts_.count(app_id));
  // TODO(zea): consider verifying the specific message already exists.
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::AddOutgoingMessage,
                                backend_, persistent_id, message, callback));
}

void GCMStoreImpl::RemoveOutgoingMessage(const std::string& persistent_id,
                                         const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &GCMStoreImpl::Backend::RemoveOutgoingMessages, backend_,
          PersistentIdList(1, persistent_id),
          base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation,
                     weak_ptr_factory_.GetWeakPtr(), callback)));
}

void GCMStoreImpl::RemoveOutgoingMessages(
    const PersistentIdList& persistent_ids,
    const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          &GCMStoreImpl::Backend::RemoveOutgoingMessages, backend_,
          persistent_ids,
          base::Bind(&GCMStoreImpl::RemoveOutgoingMessagesContinuation,
                     weak_ptr_factory_.GetWeakPtr(), callback)));
}

void GCMStoreImpl::SetLastCheckinInfo(const base::Time& time,
                                      const std::set<std::string>& accounts,
                                      const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::SetLastCheckinInfo,
                                backend_, time, accounts, callback));
}

void GCMStoreImpl::SetGServicesSettings(
    const std::map<std::string, std::string>& settings,
    const std::string& digest,
    const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::SetGServicesSettings,
                                backend_, settings, digest, callback));
}

void GCMStoreImpl::AddAccountMapping(const AccountMapping& account_mapping,
                                     const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::AddAccountMapping,
                                backend_, account_mapping, callback));
}

void GCMStoreImpl::RemoveAccountMapping(const std::string& account_id,
                                        const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::RemoveAccountMapping,
                                backend_, account_id, callback));
}

void GCMStoreImpl::SetLastTokenFetchTime(const base::Time& time,
                                         const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::SetLastTokenFetchTime,
                                backend_, time, callback));
}

void GCMStoreImpl::AddHeartbeatInterval(const std::string& scope,
                                        int interval_ms,
                                        const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::AddHeartbeatInterval,
                                backend_, scope, interval_ms, callback));
}

void GCMStoreImpl::RemoveHeartbeatInterval(const std::string& scope,
                                           const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::RemoveHeartbeatInterval,
                                backend_, scope, callback));
}

void GCMStoreImpl::SetValueForTesting(const std::string& key,
                                      const std::string& value,
                                      const UpdateCallback& callback) {
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&GCMStoreImpl::Backend::SetValue, backend_, key,
                                value, callback));
}

void GCMStoreImpl::LoadContinuation(const LoadCallback& callback,
                                    std::unique_ptr<LoadResult> result) {
  if (!result->success) {
    callback.Run(std::move(result));
    return;
  }
  int num_throttled_apps = 0;
  for (OutgoingMessageMap::const_iterator
           iter = result->outgoing_messages.begin();
       iter != result->outgoing_messages.end(); ++iter) {
    const mcs_proto::DataMessageStanza* data_message =
        reinterpret_cast<mcs_proto::DataMessageStanza*>(iter->second.get());
    DCHECK(!data_message->category().empty());
    if (app_message_counts_.count(data_message->category()) == 0)
      app_message_counts_[data_message->category()] = 1;
    else
      app_message_counts_[data_message->category()]++;
    if (app_message_counts_[data_message->category()] == kMessagesPerAppLimit)
      num_throttled_apps++;
  }
  UMA_HISTOGRAM_COUNTS_1M("GCM.NumThrottledApps", num_throttled_apps);
  callback.Run(std::move(result));
}

void GCMStoreImpl::AddOutgoingMessageContinuation(
    const UpdateCallback& callback,
    const std::string& app_id,
    bool success) {
  if (!success) {
    DCHECK(app_message_counts_[app_id] > 0);
    app_message_counts_[app_id]--;
  }
  callback.Run(success);
}

void GCMStoreImpl::RemoveOutgoingMessagesContinuation(
    const UpdateCallback& callback,
    bool success,
    const AppIdToMessageCountMap& removed_message_counts) {
  if (!success) {
    callback.Run(false);
    return;
  }
  for (AppIdToMessageCountMap::const_iterator iter =
           removed_message_counts.begin();
       iter != removed_message_counts.end(); ++iter) {
    DCHECK_NE(app_message_counts_.count(iter->first), 0U);
    app_message_counts_[iter->first] -= iter->second;
    DCHECK_GE(app_message_counts_[iter->first], 0);
  }
  callback.Run(true);
}

}  // namespace gcm
