fake_gcm_client.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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
15namespace gcm {
16
17FakeGCMClient::FakeGCMClient(
18    StartMode start_mode,
19    const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
20    const scoped_refptr<base::SequencedTaskRunner>& io_thread)
21    : delegate_(NULL),
22      status_(UNINITIALIZED),
23      start_mode_(start_mode),
24      ui_thread_(ui_thread),
25      io_thread_(io_thread),
26      weak_ptr_factory_(this) {
27}
28
29FakeGCMClient::~FakeGCMClient() {
30}
31
32void FakeGCMClient::Initialize(
33    const ChromeBuildInfo& chrome_build_info,
34    const base::FilePath& store_path,
35    const std::vector<std::string>& account_ids,
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}
65
66void FakeGCMClient::CheckOut() {
67  DCHECK(io_thread_->RunsTasksOnCurrentThread());
68  status_ = CHECKED_OUT;
69}
70
71void FakeGCMClient::Register(const std::string& app_id,
72                             const std::vector<std::string>& sender_ids) {
73  DCHECK(io_thread_->RunsTasksOnCurrentThread());
74
75  std::string registration_id = GetRegistrationIdFromSenderIds(sender_ids);
76  base::MessageLoop::current()->PostTask(
77      FROM_HERE,
78      base::Bind(&FakeGCMClient::RegisterFinished,
79                 weak_ptr_factory_.GetWeakPtr(),
80                 app_id,
81                 registration_id));
82}
83
84void FakeGCMClient::Unregister(const std::string& app_id) {
85  DCHECK(io_thread_->RunsTasksOnCurrentThread());
86
87  base::MessageLoop::current()->PostTask(
88      FROM_HERE,
89      base::Bind(&FakeGCMClient::UnregisterFinished,
90                 weak_ptr_factory_.GetWeakPtr(),
91                 app_id));
92}
93
94void FakeGCMClient::Send(const std::string& app_id,
95                         const std::string& receiver_id,
96                         const OutgoingMessage& message) {
97  DCHECK(io_thread_->RunsTasksOnCurrentThread());
98
99  base::MessageLoop::current()->PostTask(
100      FROM_HERE,
101      base::Bind(&FakeGCMClient::SendFinished,
102                 weak_ptr_factory_.GetWeakPtr(),
103                 app_id,
104                 message));
105}
106
107void FakeGCMClient::SetRecording(bool recording) {
108}
109
110void FakeGCMClient::ClearActivityLogs() {
111}
112
113GCMClient::GCMStatistics FakeGCMClient::GetStatistics() const {
114  return GCMClient::GCMStatistics();
115}
116
117void FakeGCMClient::PerformDelayedLoading() {
118  DCHECK(ui_thread_->RunsTasksOnCurrentThread());
119
120  io_thread_->PostTask(
121      FROM_HERE,
122      base::Bind(&FakeGCMClient::DoLoading, weak_ptr_factory_.GetWeakPtr()));
123}
124
125void FakeGCMClient::ReceiveMessage(const std::string& app_id,
126                                   const IncomingMessage& message) {
127  DCHECK(ui_thread_->RunsTasksOnCurrentThread());
128
129  io_thread_->PostTask(
130      FROM_HERE,
131      base::Bind(&FakeGCMClient::MessageReceived,
132                 weak_ptr_factory_.GetWeakPtr(),
133                 app_id,
134                 message));
135}
136
137void FakeGCMClient::DeleteMessages(const std::string& app_id) {
138  DCHECK(ui_thread_->RunsTasksOnCurrentThread());
139
140  io_thread_->PostTask(
141      FROM_HERE,
142      base::Bind(&FakeGCMClient::MessagesDeleted,
143                 weak_ptr_factory_.GetWeakPtr(),
144                 app_id));
145}
146
147// static
148std::string FakeGCMClient::GetRegistrationIdFromSenderIds(
149    const std::vector<std::string>& sender_ids) {
150  // GCMService normalizes the sender IDs by making them sorted.
151  std::vector<std::string> normalized_sender_ids = sender_ids;
152  std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
153
154  // Simulate the registration_id by concaternating all sender IDs.
155  // Set registration_id to empty to denote an error if sender_ids contains a
156  // hint.
157  std::string registration_id;
158  if (sender_ids.size() != 1 ||
159      sender_ids[0].find("error") == std::string::npos) {
160    for (size_t i = 0; i < normalized_sender_ids.size(); ++i) {
161      if (i > 0)
162        registration_id += ",";
163      registration_id += normalized_sender_ids[i];
164    }
165  }
166  return registration_id;
167}
168
169void FakeGCMClient::CheckinFinished() {
170  delegate_->OnGCMReady();
171}
172
173void FakeGCMClient::RegisterFinished(const std::string& app_id,
174                                     const std::string& registrion_id) {
175  delegate_->OnRegisterFinished(
176      app_id, registrion_id, registrion_id.empty() ? SERVER_ERROR : SUCCESS);
177}
178
179void FakeGCMClient::UnregisterFinished(const std::string& app_id) {
180  delegate_->OnUnregisterFinished(app_id, GCMClient::SUCCESS);
181}
182
183void FakeGCMClient::SendFinished(const std::string& app_id,
184                                 const OutgoingMessage& message) {
185  delegate_->OnSendFinished(app_id, message.id, SUCCESS);
186
187  // Simulate send error if message id contains a hint.
188  if (message.id.find("error") != std::string::npos) {
189    SendErrorDetails send_error_details;
190    send_error_details.message_id = message.id;
191    send_error_details.result = NETWORK_ERROR;
192    send_error_details.additional_data = message.data;
193    base::MessageLoop::current()->PostDelayedTask(
194        FROM_HERE,
195        base::Bind(&FakeGCMClient::MessageSendError,
196                   weak_ptr_factory_.GetWeakPtr(),
197                   app_id,
198                   send_error_details),
199        base::TimeDelta::FromMilliseconds(200));
200  }
201}
202
203void FakeGCMClient::MessageReceived(const std::string& app_id,
204                                    const IncomingMessage& message) {
205  if (delegate_)
206    delegate_->OnMessageReceived(app_id, message);
207}
208
209void FakeGCMClient::MessagesDeleted(const std::string& app_id) {
210  if (delegate_)
211    delegate_->OnMessagesDeleted(app_id);
212}
213
214void FakeGCMClient::MessageSendError(
215    const std::string& app_id,
216    const GCMClient::SendErrorDetails& send_error_details) {
217  if (delegate_)
218    delegate_->OnMessageSendError(app_id, send_error_details);
219}
220
221}  // namespace gcm
222