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