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