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
),
24 // TODO(jianli): support setting active state.
29 UserList::UserInfo::UserInfo(int64 serial_number
)
30 : serial_number(serial_number
),
35 UserList::UserInfo::UserInfo(GCMClient::Delegate
* delegate
,
36 const SetDelegateCallback
& callback
)
37 : serial_number(kInvalidSerialNumber
),
43 UserList::UserInfo::~UserInfo() {
46 UserList::UserList(GCMStore
* gcm_store
)
47 : initialized_(false),
48 next_serial_number_(kInvalidSerialNumber
),
49 gcm_store_(gcm_store
) {
52 UserList::~UserList() {
55 void UserList::Initialize(const GCMStore::SerialNumberMappings
& result
) {
56 DCHECK(!initialized_
);
57 DCHECK_GT(result
.next_serial_number
, 0);
60 next_serial_number_
= result
.next_serial_number
;
61 for (std::map
<std::string
, int64
>::const_iterator iter
=
62 result
.user_serial_numbers
.begin();
63 iter
!= result
.user_serial_numbers
.end();
65 SetSerialNumber(iter
->first
, iter
->second
);
68 for (UserInfoMap::iterator iter
= delegates_
.begin();
69 iter
!= delegates_
.end();
71 // Process only users with delegate and callback present.
72 if (iter
->second
.delegate
&& !iter
->second
.callback
.is_null()) {
73 if (iter
->second
.serial_number
== kInvalidSerialNumber
)
74 AssignSerialNumber(iter
->first
);
76 OnSerialNumberReady(iter
);
81 void UserList::SetDelegate(const std::string
& username
,
82 GCMClient::Delegate
* delegate
,
83 const SetDelegateCallback
& callback
) {
84 DCHECK(!username
.empty());
87 UserInfoMap::iterator iter
= delegates_
.find(username
);
88 if (iter
!= delegates_
.end()) {
90 DCHECK(!iter
->second
.delegate
);
91 iter
->second
.delegate
= delegate
;
92 iter
->second
.callback
= callback
;
96 UserInfoMap::value_type(username
, UserInfo(delegate
, callback
)));
100 UserInfoMap::iterator iter
= delegates_
.find(username
);
101 if (iter
->second
.serial_number
== kInvalidSerialNumber
)
102 AssignSerialNumber(iter
->first
);
104 OnSerialNumberReady(iter
);
108 void UserList::AssignSerialNumber(const std::string
& username
) {
109 DCHECK(initialized_
);
110 DCHECK_EQ(delegates_
.count(username
), 1UL);
111 DCHECK_EQ(delegates_
[username
].serial_number
, kInvalidSerialNumber
);
113 // Start by incrementing the |next_serial_number_| and persist it in the GCM
115 int64 serial_number
= next_serial_number_
++;
116 gcm_store_
->SetNextSerialNumber(
118 base::Bind(&UserList::IncrementSerialNumberCompleted
,
119 base::Unretained(this),
124 void UserList::IncrementSerialNumberCompleted(const std::string
& username
,
125 int64 user_serial_number
,
127 // TODO(fgorski): Introduce retry logic.
129 DCHECK(success
) << "Updating the next serial number failed.";
131 SetSerialNumber(username
, user_serial_number
);
132 gcm_store_
->AddUserSerialNumber(
135 base::Bind(&UserList::AssignSerialNumberCompleted
,
136 base::Unretained(this),
140 void UserList::AssignSerialNumberCompleted(const std::string
& username
,
142 // TODO(fgorski): Introduce retry logic.
144 DVLOG(1) << "It was not possible to persist username to serial number"
145 << " mapping for username: " << username
;
149 UserInfoMap::iterator iter
= delegates_
.find(username
);
150 DCHECK(iter
!= delegates_
.end());
151 OnSerialNumberReady(iter
);
154 void UserList::OnSerialNumberReady(const UserInfoMap::iterator
& iter
) {
155 base::MessageLoop::current()->PostTask(
157 base::Bind(iter
->second
.callback
,
159 iter
->second
.serial_number
));
160 iter
->second
.callback
.Reset();
163 void UserList::SetSerialNumber(const std::string
& username
,
164 int64 serial_number
) {
165 DCHECK(!username
.empty());
166 DCHECK_GT(serial_number
, 0L);
168 UserInfoMap::iterator iter
= delegates_
.find(username
);
169 if (iter
!= delegates_
.end()) {
170 DCHECK_EQ(iter
->second
.serial_number
, kInvalidSerialNumber
);
171 iter
->second
.serial_number
= serial_number
;
174 iter
, UserInfoMap::value_type(username
, UserInfo(serial_number
)));
178 GCMClient::Delegate
* UserList::GetDelegateBySerialNumber(int64 serial_number
)
180 for (UserInfoMap::const_iterator iter
= delegates_
.begin();
181 iter
!= delegates_
.end();
183 if (iter
->second
.serial_number
== serial_number
)
184 return iter
->second
.delegate
;
189 std::vector
<GCMClient::Delegate
*> UserList::GetAllDelegates() const {
190 std::vector
<GCMClient::Delegate
*> delegates
;
191 for (UserInfoMap::const_iterator iter
= delegates_
.begin();
192 iter
!= delegates_
.end(); ++iter
) {
193 if (iter
->second
.delegate
)
194 delegates
.push_back(iter
->second
.delegate
);
199 GCMClient::Delegate
* UserList::GetDelegateByUsername(
200 const std::string
& username
) const {
201 UserInfoMap::const_iterator iter
= delegates_
.find(username
);
202 return iter
!= delegates_
.end() ? iter
->second
.delegate
: NULL
;
205 int64
UserList::GetSerialNumberForUsername(const std::string
& username
) const {
206 UserInfoMap::const_iterator iter
= delegates_
.find(username
);
207 return iter
!= delegates_
.end() ? iter
->second
.serial_number
208 : kInvalidSerialNumber
;
211 std::vector
<int64
> UserList::GetAllActiveUserSerialNumbers() const {
212 std::vector
<int64
> user_serial_numbers
;
213 for (UserInfoMap::const_iterator iter
= delegates_
.begin();
214 iter
!= delegates_
.end(); ++iter
) {
215 if (iter
->second
.active
&&
216 iter
->second
.serial_number
!= kInvalidSerialNumber
)
217 user_serial_numbers
.push_back(iter
->second
.serial_number
);
219 return user_serial_numbers
;