| Index: google_apis/gcm/engine/user_list.cc
|
| diff --git a/google_apis/gcm/engine/user_list.cc b/google_apis/gcm/engine/user_list.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..829c66f34291fb5ef4d8dbb0ef5e2d7a076eea16
|
| --- /dev/null
|
| +++ b/google_apis/gcm/engine/user_list.cc
|
| @@ -0,0 +1,197 @@
|
| +// 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/user_list.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/files/file_path.h"
|
| +#include "base/location.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/message_loop/message_loop_proxy.h"
|
| +#include "base/sequenced_task_runner.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_piece.h"
|
| +#include "third_party/leveldatabase/src/include/leveldb/db.h"
|
| +
|
| +namespace gcm {
|
| +const int64 kInvalidSerialNumber = -1;
|
| +
|
| +UserList::UserInfo::UserInfo()
|
| + : serial_number(kInvalidSerialNumber),
|
| + delegate(NULL) {
|
| +}
|
| +
|
| +UserList::UserInfo::UserInfo(int64 serial_number)
|
| + : serial_number(serial_number),
|
| + delegate(NULL) {
|
| +}
|
| +
|
| +UserList::UserInfo::UserInfo(GCMClient::Delegate* delegate,
|
| + const SetDelegateCallback& callback)
|
| + : serial_number(kInvalidSerialNumber),
|
| + delegate(delegate),
|
| + callback(callback) {
|
| +}
|
| +
|
| +UserList::UserInfo::~UserInfo() {
|
| +}
|
| +
|
| +UserList::UserList(GCMStore* gcm_store)
|
| + : initialized_(false),
|
| + next_serial_number_(kInvalidSerialNumber),
|
| + gcm_store_(gcm_store) {
|
| +}
|
| +
|
| +UserList::~UserList() {
|
| +}
|
| +
|
| +void UserList::Initialize(const GCMStore::SerialNumberMappings& result) {
|
| + DCHECK(!initialized_);
|
| + DCHECK_GT(result.next_serial_number, 0);
|
| +
|
| + initialized_ = true;
|
| + next_serial_number_ = result.next_serial_number;
|
| + for (std::map<std::string, int64>::const_iterator iter =
|
| + result.user_serial_numbers.begin();
|
| + iter != result.user_serial_numbers.end();
|
| + ++iter) {
|
| + SetSerialNumber(iter->first, iter->second);
|
| + }
|
| +
|
| + for (UserInfoMap::iterator iter = delegates_.begin();
|
| + iter != delegates_.end();
|
| + ++iter) {
|
| + // Process only users with delegate and callback present.
|
| + if (iter->second.delegate && !iter->second.callback.is_null()) {
|
| + if (iter->second.serial_number == kInvalidSerialNumber)
|
| + AssignSerialNumber(iter->first);
|
| + else
|
| + OnSerialNumberReady(iter);
|
| + }
|
| + }
|
| +}
|
| +
|
| +void UserList::SetDelegate(const std::string& username,
|
| + GCMClient::Delegate* delegate,
|
| + const SetDelegateCallback& callback) {
|
| + DCHECK(!username.empty());
|
| + DCHECK(delegate);
|
| +
|
| + UserInfoMap::iterator iter = delegates_.find(username);
|
| + if (iter != delegates_.end()) {
|
| + DCHECK(initialized_);
|
| + DCHECK(!iter->second.delegate);
|
| + iter->second.delegate = delegate;
|
| + iter->second.callback = callback;
|
| + } else {
|
| + delegates_.insert(
|
| + iter,
|
| + UserInfoMap::value_type(username, UserInfo(delegate, callback)));
|
| + }
|
| +
|
| + if (initialized_) {
|
| + UserInfoMap::iterator iter = delegates_.find(username);
|
| + if (iter->second.serial_number == kInvalidSerialNumber)
|
| + AssignSerialNumber(iter->first);
|
| + else
|
| + OnSerialNumberReady(iter);
|
| + }
|
| +}
|
| +
|
| +void UserList::AssignSerialNumber(const std::string& username) {
|
| + DCHECK(initialized_);
|
| + DCHECK_EQ(delegates_.count(username), 1UL);
|
| + DCHECK_EQ(delegates_[username].serial_number, kInvalidSerialNumber);
|
| +
|
| + // Start by incrementing the |next_serial_number_| and persist it in the GCM
|
| + // store.
|
| + int64 serial_number = next_serial_number_++;
|
| + gcm_store_->SetNextSerialNumber(
|
| + serial_number,
|
| + base::Bind(&UserList::IncrementSerialNumberCompleted,
|
| + base::Unretained(this),
|
| + username,
|
| + serial_number));
|
| +}
|
| +
|
| +void UserList::IncrementSerialNumberCompleted(const std::string& username,
|
| + int64 user_serial_number,
|
| + bool success) {
|
| + // TODO(fgorski): Introduce retry logic.
|
| + if (!success)
|
| + DCHECK(success) << "Updating the next serial number failed.";
|
| +
|
| + SetSerialNumber(username, user_serial_number);
|
| + gcm_store_->AddUserSerialNumber(
|
| + username,
|
| + user_serial_number,
|
| + base::Bind(&UserList::AssignSerialNumberCompleted,
|
| + base::Unretained(this),
|
| + username));
|
| +}
|
| +
|
| +void UserList::AssignSerialNumberCompleted(const std::string& username,
|
| + bool success) {
|
| + // TODO(fgorski): Introduce retry logic.
|
| + if (!success) {
|
| + DVLOG(1) << "It was not possible to persist username to serial number"
|
| + << " mapping for username: " << username;
|
| + return;
|
| + }
|
| +
|
| + UserInfoMap::iterator iter = delegates_.find(username);
|
| + DCHECK(iter != delegates_.end());
|
| + OnSerialNumberReady(iter);
|
| +}
|
| +
|
| +void UserList::OnSerialNumberReady(const UserInfoMap::iterator& iter) {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(iter->second.callback,
|
| + iter->first,
|
| + iter->second.serial_number));
|
| + iter->second.callback.Reset();
|
| +}
|
| +
|
| +void UserList::SetSerialNumber(const std::string& username,
|
| + int64 serial_number) {
|
| + DCHECK(!username.empty());
|
| + DCHECK_GT(serial_number, 0L);
|
| +
|
| + UserInfoMap::iterator iter = delegates_.find(username);
|
| + if (iter != delegates_.end()) {
|
| + DCHECK_EQ(iter->second.serial_number, kInvalidSerialNumber);
|
| + iter->second.serial_number = serial_number;
|
| + } else {
|
| + delegates_.insert(
|
| + iter, UserInfoMap::value_type(username, UserInfo(serial_number)));
|
| + }
|
| +}
|
| +
|
| +GCMClient::Delegate* UserList::GetDelegateBySerialNumber(int64 serial_number)
|
| + const {
|
| + for (UserInfoMap::const_iterator iter = delegates_.begin();
|
| + iter != delegates_.end();
|
| + ++iter) {
|
| + if (iter->second.serial_number == serial_number)
|
| + return iter->second.delegate;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +GCMClient::Delegate* UserList::GetDelegateByUsername(
|
| + const std::string& username) const {
|
| + UserInfoMap::const_iterator iter = delegates_.find(username);
|
| + return iter != delegates_.end() ? iter->second.delegate : NULL;
|
| +}
|
| +
|
| +int64 UserList::GetSerialNumberForUsername(const std::string& username) const {
|
| + UserInfoMap::const_iterator iter = delegates_.find(username);
|
| + return iter != delegates_.end() ? iter->second.serial_number
|
| + : kInvalidSerialNumber;
|
| +}
|
| +
|
| +} // namespace gcm
|
|
|