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.
4
5 #include "components/gcm_driver/fake_gcm_client.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/sys_byteorder.h"
13 #include "base/time/time.h"
14 #include "google_apis/gcm/base/encryptor.h"
15 #include "google_apis/gcm/engine/account_mapping.h"
16 #include "net/base/ip_endpoint.h"
17
18 namespace gcm {
19
FakeGCMClient(StartMode start_mode,const scoped_refptr<base::SequencedTaskRunner> & ui_thread,const scoped_refptr<base::SequencedTaskRunner> & io_thread)20 FakeGCMClient::FakeGCMClient(
21 StartMode start_mode,
22 const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
23 const scoped_refptr<base::SequencedTaskRunner>& io_thread)
24 : delegate_(NULL),
25 sequence_id_(0),
26 status_(UNINITIALIZED),
27 start_mode_(start_mode),
28 ui_thread_(ui_thread),
29 io_thread_(io_thread),
30 weak_ptr_factory_(this) {
31 }
32
~FakeGCMClient()33 FakeGCMClient::~FakeGCMClient() {
34 }
35
Initialize(const ChromeBuildInfo & chrome_build_info,const base::FilePath & store_path,const scoped_refptr<base::SequencedTaskRunner> & blocking_task_runner,const scoped_refptr<net::URLRequestContextGetter> & url_request_context_getter,scoped_ptr<Encryptor> encryptor,Delegate * delegate)36 void FakeGCMClient::Initialize(
37 const ChromeBuildInfo& chrome_build_info,
38 const base::FilePath& store_path,
39 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner,
40 const scoped_refptr<net::URLRequestContextGetter>&
41 url_request_context_getter,
42 scoped_ptr<Encryptor> encryptor,
43 Delegate* delegate) {
44 delegate_ = delegate;
45 }
46
Start()47 void FakeGCMClient::Start() {
48 DCHECK(io_thread_->RunsTasksOnCurrentThread());
49 DCHECK_NE(STARTED, status_);
50
51 if (start_mode_ == DELAY_START)
52 return;
53 DoLoading();
54 }
55
DoLoading()56 void FakeGCMClient::DoLoading() {
57 status_ = STARTED;
58 base::MessageLoop::current()->PostTask(
59 FROM_HERE,
60 base::Bind(&FakeGCMClient::CheckinFinished,
61 weak_ptr_factory_.GetWeakPtr()));
62 }
63
Stop()64 void FakeGCMClient::Stop() {
65 DCHECK(io_thread_->RunsTasksOnCurrentThread());
66 status_ = STOPPED;
67 delegate_->OnDisconnected();
68 }
69
CheckOut()70 void FakeGCMClient::CheckOut() {
71 DCHECK(io_thread_->RunsTasksOnCurrentThread());
72 status_ = CHECKED_OUT;
73 sequence_id_++;
74 }
75
Register(const std::string & app_id,const std::vector<std::string> & sender_ids)76 void FakeGCMClient::Register(const std::string& app_id,
77 const std::vector<std::string>& sender_ids) {
78 DCHECK(io_thread_->RunsTasksOnCurrentThread());
79
80 std::string registration_id = GetRegistrationIdFromSenderIds(sender_ids);
81 base::MessageLoop::current()->PostTask(
82 FROM_HERE,
83 base::Bind(&FakeGCMClient::RegisterFinished,
84 weak_ptr_factory_.GetWeakPtr(),
85 app_id,
86 registration_id));
87 }
88
Unregister(const std::string & app_id)89 void FakeGCMClient::Unregister(const std::string& app_id) {
90 DCHECK(io_thread_->RunsTasksOnCurrentThread());
91
92 base::MessageLoop::current()->PostTask(
93 FROM_HERE,
94 base::Bind(&FakeGCMClient::UnregisterFinished,
95 weak_ptr_factory_.GetWeakPtr(),
96 app_id));
97 }
98
Send(const std::string & app_id,const std::string & receiver_id,const OutgoingMessage & message)99 void FakeGCMClient::Send(const std::string& app_id,
100 const std::string& receiver_id,
101 const OutgoingMessage& message) {
102 DCHECK(io_thread_->RunsTasksOnCurrentThread());
103
104 base::MessageLoop::current()->PostTask(
105 FROM_HERE,
106 base::Bind(&FakeGCMClient::SendFinished,
107 weak_ptr_factory_.GetWeakPtr(),
108 app_id,
109 message));
110 }
111
SetRecording(bool recording)112 void FakeGCMClient::SetRecording(bool recording) {
113 }
114
ClearActivityLogs()115 void FakeGCMClient::ClearActivityLogs() {
116 }
117
GetStatistics() const118 GCMClient::GCMStatistics FakeGCMClient::GetStatistics() const {
119 return GCMClient::GCMStatistics();
120 }
121
SetAccountsForCheckin(const std::map<std::string,std::string> & account_tokens)122 void FakeGCMClient::SetAccountsForCheckin(
123 const std::map<std::string, std::string>& account_tokens) {
124 }
125
UpdateAccountMapping(const AccountMapping & account_mapping)126 void FakeGCMClient::UpdateAccountMapping(
127 const AccountMapping& account_mapping) {
128 }
129
RemoveAccountMapping(const std::string & account_id)130 void FakeGCMClient::RemoveAccountMapping(const std::string& account_id) {
131 }
132
PerformDelayedLoading()133 void FakeGCMClient::PerformDelayedLoading() {
134 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
135
136 io_thread_->PostTask(
137 FROM_HERE,
138 base::Bind(&FakeGCMClient::DoLoading, weak_ptr_factory_.GetWeakPtr()));
139 }
140
ReceiveMessage(const std::string & app_id,const IncomingMessage & message)141 void FakeGCMClient::ReceiveMessage(const std::string& app_id,
142 const IncomingMessage& message) {
143 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
144
145 io_thread_->PostTask(
146 FROM_HERE,
147 base::Bind(&FakeGCMClient::MessageReceived,
148 weak_ptr_factory_.GetWeakPtr(),
149 app_id,
150 message));
151 }
152
DeleteMessages(const std::string & app_id)153 void FakeGCMClient::DeleteMessages(const std::string& app_id) {
154 DCHECK(ui_thread_->RunsTasksOnCurrentThread());
155
156 io_thread_->PostTask(
157 FROM_HERE,
158 base::Bind(&FakeGCMClient::MessagesDeleted,
159 weak_ptr_factory_.GetWeakPtr(),
160 app_id));
161 }
162
GetRegistrationIdFromSenderIds(const std::vector<std::string> & sender_ids) const163 std::string FakeGCMClient::GetRegistrationIdFromSenderIds(
164 const std::vector<std::string>& sender_ids) const {
165 // GCMService normalizes the sender IDs by making them sorted.
166 std::vector<std::string> normalized_sender_ids = sender_ids;
167 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
168
169 // Simulate the registration_id by concaternating all sender IDs.
170 // Set registration_id to empty to denote an error if sender_ids contains a
171 // hint.
172 std::string registration_id;
173 if (sender_ids.size() != 1 ||
174 sender_ids[0].find("error") == std::string::npos) {
175 for (size_t i = 0; i < normalized_sender_ids.size(); ++i) {
176 if (i > 0)
177 registration_id += ",";
178 registration_id += normalized_sender_ids[i];
179 }
180 registration_id += base::IntToString(sequence_id_);
181 }
182 return registration_id;
183 }
184
CheckinFinished()185 void FakeGCMClient::CheckinFinished() {
186 delegate_->OnGCMReady(std::vector<AccountMapping>());
187 delegate_->OnConnected(net::IPEndPoint());
188 }
189
RegisterFinished(const std::string & app_id,const std::string & registrion_id)190 void FakeGCMClient::RegisterFinished(const std::string& app_id,
191 const std::string& registrion_id) {
192 delegate_->OnRegisterFinished(
193 app_id, registrion_id, registrion_id.empty() ? SERVER_ERROR : SUCCESS);
194 }
195
UnregisterFinished(const std::string & app_id)196 void FakeGCMClient::UnregisterFinished(const std::string& app_id) {
197 delegate_->OnUnregisterFinished(app_id, GCMClient::SUCCESS);
198 }
199
SendFinished(const std::string & app_id,const OutgoingMessage & message)200 void FakeGCMClient::SendFinished(const std::string& app_id,
201 const OutgoingMessage& message) {
202 delegate_->OnSendFinished(app_id, message.id, SUCCESS);
203
204 // Simulate send error if message id contains a hint.
205 if (message.id.find("error") != std::string::npos) {
206 SendErrorDetails send_error_details;
207 send_error_details.message_id = message.id;
208 send_error_details.result = NETWORK_ERROR;
209 send_error_details.additional_data = message.data;
210 base::MessageLoop::current()->PostDelayedTask(
211 FROM_HERE,
212 base::Bind(&FakeGCMClient::MessageSendError,
213 weak_ptr_factory_.GetWeakPtr(),
214 app_id,
215 send_error_details),
216 base::TimeDelta::FromMilliseconds(200));
217 } else if(message.id.find("ack") != std::string::npos) {
218 base::MessageLoop::current()->PostDelayedTask(
219 FROM_HERE,
220 base::Bind(&FakeGCMClient::SendAcknowledgement,
221 weak_ptr_factory_.GetWeakPtr(),
222 app_id,
223 message.id),
224 base::TimeDelta::FromMilliseconds(200));
225
226 }
227 }
228
MessageReceived(const std::string & app_id,const IncomingMessage & message)229 void FakeGCMClient::MessageReceived(const std::string& app_id,
230 const IncomingMessage& message) {
231 if (delegate_)
232 delegate_->OnMessageReceived(app_id, message);
233 }
234
MessagesDeleted(const std::string & app_id)235 void FakeGCMClient::MessagesDeleted(const std::string& app_id) {
236 if (delegate_)
237 delegate_->OnMessagesDeleted(app_id);
238 }
239
MessageSendError(const std::string & app_id,const GCMClient::SendErrorDetails & send_error_details)240 void FakeGCMClient::MessageSendError(
241 const std::string& app_id,
242 const GCMClient::SendErrorDetails& send_error_details) {
243 if (delegate_)
244 delegate_->OnMessageSendError(app_id, send_error_details);
245 }
246
SendAcknowledgement(const std::string & app_id,const std::string & message_id)247 void FakeGCMClient::SendAcknowledgement(const std::string& app_id,
248 const std::string& message_id) {
249 if (delegate_)
250 delegate_->OnSendAcknowledged(app_id, message_id);
251 }
252
253 } // namespace gcm
254