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 "components/gcm_driver/fake_gcm_client.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 "base/timer/timer.h"
15 #include "google_apis/gcm/base/encryptor.h"
16 #include "google_apis/gcm/engine/account_mapping.h"
17 #include "net/base/ip_endpoint.h"
21 FakeGCMClient::FakeGCMClient(
22 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
23 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
26 start_mode_(DELAYED_START
),
27 start_mode_overridding_(RESPECT_START_MODE
),
28 ui_thread_(ui_thread
),
29 io_thread_(io_thread
),
30 weak_ptr_factory_(this) {
33 FakeGCMClient::~FakeGCMClient() {
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
,
47 void FakeGCMClient::Start(StartMode start_mode
) {
48 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
53 if (start_mode
== IMMEDIATE_START
)
54 start_mode_
= IMMEDIATE_START
;
55 if (start_mode_
== DELAYED_START
||
56 start_mode_overridding_
== FORCE_TO_ALWAYS_DELAY_START_GCM
) {
63 void FakeGCMClient::DoStart() {
65 base::MessageLoop::current()->PostTask(
67 base::Bind(&FakeGCMClient::Started
,
68 weak_ptr_factory_
.GetWeakPtr()));
71 void FakeGCMClient::Stop() {
72 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
74 delegate_
->OnDisconnected();
77 void FakeGCMClient::Register(
78 const linked_ptr
<RegistrationInfo
>& registration_info
) {
79 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
81 GCMRegistrationInfo
* gcm_registration_info
=
82 GCMRegistrationInfo::FromRegistrationInfo(registration_info
.get());
83 DCHECK(gcm_registration_info
);
85 std::string registration_id
= GetRegistrationIdFromSenderIds(
86 gcm_registration_info
->sender_ids
);
87 base::MessageLoop::current()->PostTask(
89 base::Bind(&FakeGCMClient::RegisterFinished
,
90 weak_ptr_factory_
.GetWeakPtr(),
95 void FakeGCMClient::Unregister(
96 const linked_ptr
<RegistrationInfo
>& registration_info
) {
97 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
99 base::MessageLoop::current()->PostTask(
101 base::Bind(&FakeGCMClient::UnregisterFinished
,
102 weak_ptr_factory_
.GetWeakPtr(),
106 void FakeGCMClient::Send(const std::string
& app_id
,
107 const std::string
& receiver_id
,
108 const OutgoingMessage
& message
) {
109 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
111 base::MessageLoop::current()->PostTask(
113 base::Bind(&FakeGCMClient::SendFinished
,
114 weak_ptr_factory_
.GetWeakPtr(),
119 void FakeGCMClient::SetRecording(bool recording
) {
122 void FakeGCMClient::ClearActivityLogs() {
125 GCMClient::GCMStatistics
FakeGCMClient::GetStatistics() const {
126 return GCMClient::GCMStatistics();
129 void FakeGCMClient::SetAccountTokens(
130 const std::vector
<AccountTokenInfo
>& account_tokens
) {
133 void FakeGCMClient::UpdateAccountMapping(
134 const AccountMapping
& account_mapping
) {
137 void FakeGCMClient::RemoveAccountMapping(const std::string
& account_id
) {
140 void FakeGCMClient::SetLastTokenFetchTime(const base::Time
& time
) {
143 void FakeGCMClient::UpdateHeartbeatTimer(scoped_ptr
<base::Timer
> timer
) {
146 void FakeGCMClient::AddInstanceIDData(const std::string
& app_id
,
147 const std::string
& instance_id
,
148 const std::string
& extra_data
) {
151 void FakeGCMClient::RemoveInstanceIDData(const std::string
& app_id
) {
154 void FakeGCMClient::GetInstanceIDData(const std::string
& app_id
,
155 std::string
* instance_id
,
156 std::string
* extra_data
) {
159 void FakeGCMClient::AddHeartbeatInterval(const std::string
& scope
,
163 void FakeGCMClient::RemoveHeartbeatInterval(const std::string
& scope
) {
166 void FakeGCMClient::PerformDelayedStart() {
167 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
169 io_thread_
->PostTask(
171 base::Bind(&FakeGCMClient::DoStart
, weak_ptr_factory_
.GetWeakPtr()));
174 void FakeGCMClient::ReceiveMessage(const std::string
& app_id
,
175 const IncomingMessage
& message
) {
176 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
178 io_thread_
->PostTask(
180 base::Bind(&FakeGCMClient::MessageReceived
,
181 weak_ptr_factory_
.GetWeakPtr(),
186 void FakeGCMClient::DeleteMessages(const std::string
& app_id
) {
187 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
189 io_thread_
->PostTask(
191 base::Bind(&FakeGCMClient::MessagesDeleted
,
192 weak_ptr_factory_
.GetWeakPtr(),
196 std::string
FakeGCMClient::GetRegistrationIdFromSenderIds(
197 const std::vector
<std::string
>& sender_ids
) const {
198 // GCMService normalizes the sender IDs by making them sorted.
199 std::vector
<std::string
> normalized_sender_ids
= sender_ids
;
200 std::sort(normalized_sender_ids
.begin(), normalized_sender_ids
.end());
202 // Simulate the registration_id by concaternating all sender IDs.
203 // Set registration_id to empty to denote an error if sender_ids contains a
205 std::string registration_id
;
206 if (sender_ids
.size() != 1 ||
207 sender_ids
[0].find("error") == std::string::npos
) {
208 for (size_t i
= 0; i
< normalized_sender_ids
.size(); ++i
) {
210 registration_id
+= ",";
211 registration_id
+= normalized_sender_ids
[i
];
214 return registration_id
;
217 void FakeGCMClient::Started() {
218 delegate_
->OnGCMReady(std::vector
<AccountMapping
>(), base::Time());
219 delegate_
->OnConnected(net::IPEndPoint());
222 void FakeGCMClient::RegisterFinished(
223 const linked_ptr
<RegistrationInfo
>& registration_info
,
224 const std::string
& registrion_id
) {
225 delegate_
->OnRegisterFinished(
228 registrion_id
.empty() ? SERVER_ERROR
: SUCCESS
);
231 void FakeGCMClient::UnregisterFinished(
232 const linked_ptr
<RegistrationInfo
>& registration_info
) {
233 delegate_
->OnUnregisterFinished(registration_info
, GCMClient::SUCCESS
);
236 void FakeGCMClient::SendFinished(const std::string
& app_id
,
237 const OutgoingMessage
& message
) {
238 delegate_
->OnSendFinished(app_id
, message
.id
, SUCCESS
);
240 // Simulate send error if message id contains a hint.
241 if (message
.id
.find("error") != std::string::npos
) {
242 SendErrorDetails send_error_details
;
243 send_error_details
.message_id
= message
.id
;
244 send_error_details
.result
= NETWORK_ERROR
;
245 send_error_details
.additional_data
= message
.data
;
246 base::MessageLoop::current()->PostDelayedTask(
248 base::Bind(&FakeGCMClient::MessageSendError
,
249 weak_ptr_factory_
.GetWeakPtr(),
252 base::TimeDelta::FromMilliseconds(200));
253 } else if(message
.id
.find("ack") != std::string::npos
) {
254 base::MessageLoop::current()->PostDelayedTask(
256 base::Bind(&FakeGCMClient::SendAcknowledgement
,
257 weak_ptr_factory_
.GetWeakPtr(),
260 base::TimeDelta::FromMilliseconds(200));
265 void FakeGCMClient::MessageReceived(const std::string
& app_id
,
266 const IncomingMessage
& message
) {
268 delegate_
->OnMessageReceived(app_id
, message
);
271 void FakeGCMClient::MessagesDeleted(const std::string
& app_id
) {
273 delegate_
->OnMessagesDeleted(app_id
);
276 void FakeGCMClient::MessageSendError(
277 const std::string
& app_id
,
278 const GCMClient::SendErrorDetails
& send_error_details
) {
280 delegate_
->OnMessageSendError(app_id
, send_error_details
);
283 void FakeGCMClient::SendAcknowledgement(const std::string
& app_id
,
284 const std::string
& message_id
) {
286 delegate_
->OnSendAcknowledged(app_id
, message_id
);