1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "google_apis/gcm/engine/user_list.h"
8 #include "base/files/file_path.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/sequenced_task_runner.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_piece.h"
17 #include "third_party/leveldatabase/src/include/leveldb/db.h"
20 const int64 kInvalidSerialNumber = -1;
22 UserList::UserInfo::UserInfo()
23 : serial_number(kInvalidSerialNumber),
27 UserList::UserInfo::UserInfo(int64 serial_number)
28 : serial_number(serial_number),
32 UserList::UserInfo::UserInfo(GCMClient::Delegate* delegate,
33 const SetDelegateCallback& callback)
34 : serial_number(kInvalidSerialNumber),
39 UserList::UserInfo::~UserInfo() {
42 UserList::UserList(GCMStore* gcm_store)
43 : initialized_(false),
44 next_serial_number_(kInvalidSerialNumber),
45 gcm_store_(gcm_store) {
48 UserList::~UserList() {
51 void UserList::Initialize(const GCMStore::SerialNumberMappings& result) {
52 DCHECK(!initialized_);
53 DCHECK_GT(result.next_serial_number, 0);
56 next_serial_number_ = result.next_serial_number;
57 for (std::map<std::string, int64>::const_iterator iter =
58 result.user_serial_numbers.begin();
59 iter != result.user_serial_numbers.end();
61 SetSerialNumber(iter->first, iter->second);
64 for (UserInfoMap::iterator iter = delegates_.begin();
65 iter != delegates_.end();
67 // Process only users with delegate and callback present.
68 if (iter->second.delegate && !iter->second.callback.is_null()) {
69 if (iter->second.serial_number == kInvalidSerialNumber)
70 AssignSerialNumber(iter->first);
72 OnSerialNumberReady(iter);
77 void UserList::SetDelegate(const std::string& username,
78 GCMClient::Delegate* delegate,
79 const SetDelegateCallback& callback) {
80 DCHECK(!username.empty());
83 UserInfoMap::iterator iter = delegates_.find(username);
84 if (iter != delegates_.end()) {
86 DCHECK(!iter->second.delegate);
87 iter->second.delegate = delegate;
88 iter->second.callback = callback;
92 UserInfoMap::value_type(username, UserInfo(delegate, callback)));
96 UserInfoMap::iterator iter = delegates_.find(username);
97 if (iter->second.serial_number == kInvalidSerialNumber)
98 AssignSerialNumber(iter->first);
100 OnSerialNumberReady(iter);
104 void UserList::AssignSerialNumber(const std::string& username) {
105 DCHECK(initialized_);
106 DCHECK_EQ(delegates_.count(username), 1UL);
107 DCHECK_EQ(delegates_[username].serial_number, kInvalidSerialNumber);
109 // Start by incrementing the |next_serial_number_| and persist it in the GCM
111 int64 serial_number = next_serial_number_++;
112 gcm_store_->SetNextSerialNumber(
114 base::Bind(&UserList::IncrementSerialNumberCompleted,
115 base::Unretained(this),
120 void UserList::IncrementSerialNumberCompleted(const std::string& username,
121 int64 user_serial_number,
123 // TODO(fgorski): Introduce retry logic.
125 DCHECK(success) << "Updating the next serial number failed.";
127 SetSerialNumber(username, user_serial_number);
128 gcm_store_->AddUserSerialNumber(
131 base::Bind(&UserList::AssignSerialNumberCompleted,
132 base::Unretained(this),
136 void UserList::AssignSerialNumberCompleted(const std::string& username,
138 // TODO(fgorski): Introduce retry logic.
140 DVLOG(1) << "It was not possible to persist username to serial number"
141 << " mapping for username: " << username;
145 UserInfoMap::iterator iter = delegates_.find(username);
146 DCHECK(iter != delegates_.end());
147 OnSerialNumberReady(iter);
150 void UserList::OnSerialNumberReady(const UserInfoMap::iterator& iter) {
151 base::MessageLoop::current()->PostTask(
153 base::Bind(iter->second.callback,
155 iter->second.serial_number));
156 iter->second.callback.Reset();
159 void UserList::SetSerialNumber(const std::string& username,
160 int64 serial_number) {
161 DCHECK(!username.empty());
162 DCHECK_GT(serial_number, 0L);
164 UserInfoMap::iterator iter = delegates_.find(username);
165 if (iter != delegates_.end()) {
166 DCHECK_EQ(iter->second.serial_number, kInvalidSerialNumber);
167 iter->second.serial_number = serial_number;
170 iter, UserInfoMap::value_type(username, UserInfo(serial_number)));
174 GCMClient::Delegate* UserList::GetDelegateBySerialNumber(int64 serial_number)
176 for (UserInfoMap::const_iterator iter = delegates_.begin();
177 iter != delegates_.end();
179 if (iter->second.serial_number == serial_number)
180 return iter->second.delegate;
185 GCMClient::Delegate* UserList::GetDelegateByUsername(
186 const std::string& username) const {
187 UserInfoMap::const_iterator iter = delegates_.find(username);
188 return iter != delegates_.end() ? iter->second.delegate : NULL;
191 int64 UserList::GetSerialNumberForUsername(const std::string& username) const {
192 UserInfoMap::const_iterator iter = delegates_.find(username);
193 return iter != delegates_.end() ? iter->second.serial_number
194 : kInvalidSerialNumber;