fake_gcm_client.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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
16namespace gcm {
17
18FakeGCMClient::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
30FakeGCMClient::~FakeGCMClient() {
31}
32
33void 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
44void 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
53void 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
61void FakeGCMClient::Stop() {
62  DCHECK(io_thread_->RunsTasksOnCurrentThread());
63  status_ = STOPPED;
64  delegate_->OnDisconnected();
65}
66
67void FakeGCMClient::CheckOut() {
68  DCHECK(io_thread_->RunsTasksOnCurrentThread());
69  status_ = CHECKED_OUT;
70}
71
72void 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
85void 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
95void 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
108void FakeGCMClient::SetRecording(bool recording) {
109}
110
111void FakeGCMClient::ClearActivityLogs() {
112}
113
114GCMClient::GCMStatistics FakeGCMClient::GetStatistics() const {
115  return GCMClient::GCMStatistics();
116}
117
118void FakeGCMClient::SetAccountsForCheckin(
119    const std::map<std::string, std::string>& account_tokens) {
120}
121
122void FakeGCMClient::UpdateAccountMapping(
123    const AccountMapping& account_mapping) {
124}
125
126void FakeGCMClient::RemoveAccountMapping(const std::string& account_id) {
127}
128
129void FakeGCMClient::PerformDelayedLoading() {
130  DCHECK(ui_thread_->RunsTasksOnCurrentThread());
131
132  io_thread_->PostTask(
133      FROM_HERE,
134      base::Bind(&FakeGCMClient::DoLoading, weak_ptr_factory_.GetWeakPtr()));
135}
136
137void FakeGCMClient::ReceiveMessage(const std::string& app_id,
138                                   const IncomingMessage& message) {
139  DCHECK(ui_thread_->RunsTasksOnCurrentThread());
140
141  io_thread_->PostTask(
142      FROM_HERE,
143      base::Bind(&FakeGCMClient::MessageReceived,
144                 weak_ptr_factory_.GetWeakPtr(),
145                 app_id,
146                 message));
147}
148
149void FakeGCMClient::DeleteMessages(const std::string& app_id) {
150  DCHECK(ui_thread_->RunsTasksOnCurrentThread());
151
152  io_thread_->PostTask(
153      FROM_HERE,
154      base::Bind(&FakeGCMClient::MessagesDeleted,
155                 weak_ptr_factory_.GetWeakPtr(),
156                 app_id));
157}
158
159// static
160std::string FakeGCMClient::GetRegistrationIdFromSenderIds(
161    const std::vector<std::string>& sender_ids) {
162  // GCMService normalizes the sender IDs by making them sorted.
163  std::vector<std::string> normalized_sender_ids = sender_ids;
164  std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
165
166  // Simulate the registration_id by concaternating all sender IDs.
167  // Set registration_id to empty to denote an error if sender_ids contains a
168  // hint.
169  std::string registration_id;
170  if (sender_ids.size() != 1 ||
171      sender_ids[0].find("error") == std::string::npos) {
172    for (size_t i = 0; i < normalized_sender_ids.size(); ++i) {
173      if (i > 0)
174        registration_id += ",";
175      registration_id += normalized_sender_ids[i];
176    }
177  }
178  return registration_id;
179}
180
181void FakeGCMClient::CheckinFinished() {
182  delegate_->OnGCMReady();
183  delegate_->OnConnected(net::IPEndPoint());
184}
185
186void FakeGCMClient::RegisterFinished(const std::string& app_id,
187                                     const std::string& registrion_id) {
188  delegate_->OnRegisterFinished(
189      app_id, registrion_id, registrion_id.empty() ? SERVER_ERROR : SUCCESS);
190}
191
192void FakeGCMClient::UnregisterFinished(const std::string& app_id) {
193  delegate_->OnUnregisterFinished(app_id, GCMClient::SUCCESS);
194}
195
196void FakeGCMClient::SendFinished(const std::string& app_id,
197                                 const OutgoingMessage& message) {
198  delegate_->OnSendFinished(app_id, message.id, SUCCESS);
199
200  // Simulate send error if message id contains a hint.
201  if (message.id.find("error") != std::string::npos) {
202    SendErrorDetails send_error_details;
203    send_error_details.message_id = message.id;
204    send_error_details.result = NETWORK_ERROR;
205    send_error_details.additional_data = message.data;
206    base::MessageLoop::current()->PostDelayedTask(
207        FROM_HERE,
208        base::Bind(&FakeGCMClient::MessageSendError,
209                   weak_ptr_factory_.GetWeakPtr(),
210                   app_id,
211                   send_error_details),
212        base::TimeDelta::FromMilliseconds(200));
213  } else if(message.id.find("ack") != std::string::npos) {
214    base::MessageLoop::current()->PostDelayedTask(
215        FROM_HERE,
216        base::Bind(&FakeGCMClient::SendAcknowledgement,
217                   weak_ptr_factory_.GetWeakPtr(),
218                   app_id,
219                   message.id),
220        base::TimeDelta::FromMilliseconds(200));
221
222  }
223}
224
225void FakeGCMClient::MessageReceived(const std::string& app_id,
226                                    const IncomingMessage& message) {
227  if (delegate_)
228    delegate_->OnMessageReceived(app_id, message);
229}
230
231void FakeGCMClient::MessagesDeleted(const std::string& app_id) {
232  if (delegate_)
233    delegate_->OnMessagesDeleted(app_id);
234}
235
236void FakeGCMClient::MessageSendError(
237    const std::string& app_id,
238    const GCMClient::SendErrorDetails& send_error_details) {
239  if (delegate_)
240    delegate_->OnMessageSendError(app_id, send_error_details);
241}
242
243void FakeGCMClient::SendAcknowledgement(const std::string& app_id,
244                                        const std::string& message_id) {
245  if (delegate_)
246    delegate_->OnSendAcknowledged(app_id, message_id);
247}
248
249}  // namespace gcm
250