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