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/location.h"
9 #include "base/logging.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/sys_byteorder.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "base/timer/timer.h"
17 #include "google_apis/gcm/base/encryptor.h"
18 #include "google_apis/gcm/engine/account_mapping.h"
19 #include "net/base/ip_endpoint.h"
24 std::string
FakeGCMClient::GenerateGCMRegistrationID(
25 const std::vector
<std::string
>& sender_ids
) {
26 // GCMService normalizes the sender IDs by making them sorted.
27 std::vector
<std::string
> normalized_sender_ids
= sender_ids
;
28 std::sort(normalized_sender_ids
.begin(), normalized_sender_ids
.end());
30 // Simulate the registration_id by concaternating all sender IDs.
31 // Set registration_id to empty to denote an error if sender_ids contains a
33 std::string registration_id
;
34 if (sender_ids
.size() != 1 ||
35 sender_ids
[0].find("error") == std::string::npos
) {
36 for (size_t i
= 0; i
< normalized_sender_ids
.size(); ++i
) {
38 registration_id
+= ",";
39 registration_id
+= normalized_sender_ids
[i
];
42 return registration_id
;
46 std::string
FakeGCMClient::GenerateInstanceIDToken(
47 const std::string
& authorized_entity
, const std::string
& scope
) {
48 if (authorized_entity
.find("error") != std::string::npos
)
50 std::string
token(authorized_entity
);
56 FakeGCMClient::FakeGCMClient(
57 const scoped_refptr
<base::SequencedTaskRunner
>& ui_thread
,
58 const scoped_refptr
<base::SequencedTaskRunner
>& io_thread
)
61 start_mode_(DELAYED_START
),
62 start_mode_overridding_(RESPECT_START_MODE
),
63 ui_thread_(ui_thread
),
64 io_thread_(io_thread
),
65 weak_ptr_factory_(this) {
68 FakeGCMClient::~FakeGCMClient() {
71 void FakeGCMClient::Initialize(
72 const ChromeBuildInfo
& chrome_build_info
,
73 const base::FilePath
& store_path
,
74 const scoped_refptr
<base::SequencedTaskRunner
>& blocking_task_runner
,
75 const scoped_refptr
<net::URLRequestContextGetter
>&
76 url_request_context_getter
,
77 scoped_ptr
<Encryptor
> encryptor
,
82 void FakeGCMClient::Start(StartMode start_mode
) {
83 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
88 if (start_mode
== IMMEDIATE_START
)
89 start_mode_
= IMMEDIATE_START
;
90 if (start_mode_
== DELAYED_START
||
91 start_mode_overridding_
== FORCE_TO_ALWAYS_DELAY_START_GCM
) {
98 void FakeGCMClient::DoStart() {
100 base::ThreadTaskRunnerHandle::Get()->PostTask(
102 base::Bind(&FakeGCMClient::Started
, weak_ptr_factory_
.GetWeakPtr()));
105 void FakeGCMClient::Stop() {
106 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
108 delegate_
->OnDisconnected();
111 void FakeGCMClient::Register(
112 const linked_ptr
<RegistrationInfo
>& registration_info
) {
113 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
115 std::string registration_id
;
117 GCMRegistrationInfo
* gcm_registration_info
=
118 GCMRegistrationInfo::FromRegistrationInfo(registration_info
.get());
119 if (gcm_registration_info
) {
120 registration_id
= GenerateGCMRegistrationID(
121 gcm_registration_info
->sender_ids
);
124 InstanceIDTokenInfo
* instance_id_token_info
=
125 InstanceIDTokenInfo::FromRegistrationInfo(registration_info
.get());
126 if (instance_id_token_info
) {
127 registration_id
= GenerateInstanceIDToken(
128 instance_id_token_info
->authorized_entity
,
129 instance_id_token_info
->scope
);
132 base::ThreadTaskRunnerHandle::Get()->PostTask(
133 FROM_HERE
, base::Bind(&FakeGCMClient::RegisterFinished
,
134 weak_ptr_factory_
.GetWeakPtr(), registration_info
,
138 void FakeGCMClient::Unregister(
139 const linked_ptr
<RegistrationInfo
>& registration_info
) {
140 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
142 base::ThreadTaskRunnerHandle::Get()->PostTask(
143 FROM_HERE
, base::Bind(&FakeGCMClient::UnregisterFinished
,
144 weak_ptr_factory_
.GetWeakPtr(), registration_info
));
147 void FakeGCMClient::Send(const std::string
& app_id
,
148 const std::string
& receiver_id
,
149 const OutgoingMessage
& message
) {
150 DCHECK(io_thread_
->RunsTasksOnCurrentThread());
152 base::ThreadTaskRunnerHandle::Get()->PostTask(
153 FROM_HERE
, base::Bind(&FakeGCMClient::SendFinished
,
154 weak_ptr_factory_
.GetWeakPtr(), app_id
, message
));
157 void FakeGCMClient::SetRecording(bool recording
) {
160 void FakeGCMClient::ClearActivityLogs() {
163 GCMClient::GCMStatistics
FakeGCMClient::GetStatistics() const {
164 return GCMClient::GCMStatistics();
167 void FakeGCMClient::SetAccountTokens(
168 const std::vector
<AccountTokenInfo
>& account_tokens
) {
171 void FakeGCMClient::UpdateAccountMapping(
172 const AccountMapping
& account_mapping
) {
175 void FakeGCMClient::RemoveAccountMapping(const std::string
& account_id
) {
178 void FakeGCMClient::SetLastTokenFetchTime(const base::Time
& time
) {
181 void FakeGCMClient::UpdateHeartbeatTimer(scoped_ptr
<base::Timer
> timer
) {
184 void FakeGCMClient::AddInstanceIDData(const std::string
& app_id
,
185 const std::string
& instance_id
,
186 const std::string
& extra_data
) {
187 instance_id_data_
[app_id
] = make_pair(instance_id
, extra_data
);
190 void FakeGCMClient::RemoveInstanceIDData(const std::string
& app_id
) {
191 instance_id_data_
.erase(app_id
);
194 void FakeGCMClient::GetInstanceIDData(const std::string
& app_id
,
195 std::string
* instance_id
,
196 std::string
* extra_data
) {
197 auto iter
= instance_id_data_
.find(app_id
);
198 if (iter
== instance_id_data_
.end()) {
199 instance_id
->clear();
204 *instance_id
= iter
->second
.first
;
205 *extra_data
= iter
->second
.second
;
208 void FakeGCMClient::AddHeartbeatInterval(const std::string
& scope
,
212 void FakeGCMClient::RemoveHeartbeatInterval(const std::string
& scope
) {
215 void FakeGCMClient::PerformDelayedStart() {
216 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
218 io_thread_
->PostTask(
220 base::Bind(&FakeGCMClient::DoStart
, weak_ptr_factory_
.GetWeakPtr()));
223 void FakeGCMClient::ReceiveMessage(const std::string
& app_id
,
224 const IncomingMessage
& message
) {
225 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
227 io_thread_
->PostTask(
229 base::Bind(&FakeGCMClient::MessageReceived
,
230 weak_ptr_factory_
.GetWeakPtr(),
235 void FakeGCMClient::DeleteMessages(const std::string
& app_id
) {
236 DCHECK(ui_thread_
->RunsTasksOnCurrentThread());
238 io_thread_
->PostTask(
240 base::Bind(&FakeGCMClient::MessagesDeleted
,
241 weak_ptr_factory_
.GetWeakPtr(),
245 void FakeGCMClient::Started() {
246 delegate_
->OnGCMReady(std::vector
<AccountMapping
>(), base::Time());
247 delegate_
->OnConnected(net::IPEndPoint());
250 void FakeGCMClient::RegisterFinished(
251 const linked_ptr
<RegistrationInfo
>& registration_info
,
252 const std::string
& registrion_id
) {
253 delegate_
->OnRegisterFinished(
256 registrion_id
.empty() ? SERVER_ERROR
: SUCCESS
);
259 void FakeGCMClient::UnregisterFinished(
260 const linked_ptr
<RegistrationInfo
>& registration_info
) {
261 delegate_
->OnUnregisterFinished(registration_info
, GCMClient::SUCCESS
);
264 void FakeGCMClient::SendFinished(const std::string
& app_id
,
265 const OutgoingMessage
& message
) {
266 delegate_
->OnSendFinished(app_id
, message
.id
, SUCCESS
);
268 // Simulate send error if message id contains a hint.
269 if (message
.id
.find("error") != std::string::npos
) {
270 SendErrorDetails send_error_details
;
271 send_error_details
.message_id
= message
.id
;
272 send_error_details
.result
= NETWORK_ERROR
;
273 send_error_details
.additional_data
= message
.data
;
274 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
276 base::Bind(&FakeGCMClient::MessageSendError
,
277 weak_ptr_factory_
.GetWeakPtr(), app_id
, send_error_details
),
278 base::TimeDelta::FromMilliseconds(200));
279 } else if(message
.id
.find("ack") != std::string::npos
) {
280 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
282 base::Bind(&FakeGCMClient::SendAcknowledgement
,
283 weak_ptr_factory_
.GetWeakPtr(), app_id
, message
.id
),
284 base::TimeDelta::FromMilliseconds(200));
288 void FakeGCMClient::MessageReceived(const std::string
& app_id
,
289 const IncomingMessage
& message
) {
291 delegate_
->OnMessageReceived(app_id
, message
);
294 void FakeGCMClient::MessagesDeleted(const std::string
& app_id
) {
296 delegate_
->OnMessagesDeleted(app_id
);
299 void FakeGCMClient::MessageSendError(
300 const std::string
& app_id
,
301 const GCMClient::SendErrorDetails
& send_error_details
) {
303 delegate_
->OnMessageSendError(app_id
, send_error_details
);
306 void FakeGCMClient::SendAcknowledgement(const std::string
& app_id
,
307 const std::string
& message_id
) {
309 delegate_
->OnSendAcknowledged(app_id
, message_id
);