gcm_driver.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
1e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver// Copyright 2014 The Chromium Authors. All rights reserved.
2e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver// Use of this source code is governed by a BSD-style license that can be
3e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver// found in the LICENSE file.
4e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
5e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver#include "components/gcm_driver/gcm_driver.h"
6e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
7e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver#include <algorithm>
8e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
9e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver#include "base/logging.h"
10e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver#include "components/gcm_driver/gcm_app_handler.h"
11e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
12e80efa670f1027fdf3882a298216a460199e38d0Ben Gruvernamespace gcm {
13e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
14e80efa670f1027fdf3882a298216a460199e38d0Ben GruverGCMDriver::GCMDriver() {
15e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver}
16e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
17e80efa670f1027fdf3882a298216a460199e38d0Ben GruverGCMDriver::~GCMDriver() {
18e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver}
19e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
20e80efa670f1027fdf3882a298216a460199e38d0Ben Gruvervoid GCMDriver::Register(const std::string& app_id,
21e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver                         const std::vector<std::string>& sender_ids,
22e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver                         const RegisterCallback& callback) {
23e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  DCHECK(!app_id.empty());
24e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  DCHECK(!sender_ids.empty());
25e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  DCHECK(!callback.is_null());
26e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
27e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  GCMClient::Result result = EnsureStarted();
28e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  if (result != GCMClient::SUCCESS) {
29e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver    callback.Run(std::string(), result);
30e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver    return;
31e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  }
32e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
33e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  // If previous un/register operation is still in progress, bail out.
34e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  if (IsAsyncOperationPending(app_id)) {
35e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver    callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
36e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver    return;
37e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  }
38e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
39e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  // Normalize the sender IDs by making them sorted.
40e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  std::vector<std::string> normalized_sender_ids = sender_ids;
41e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
42e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
43e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  register_callbacks_[app_id] = callback;
44e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
45e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  RegisterImpl(app_id, normalized_sender_ids);
46e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver}
47e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
48e80efa670f1027fdf3882a298216a460199e38d0Ben Gruvervoid GCMDriver::Unregister(const std::string& app_id,
49e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver                           const UnregisterCallback& callback) {
50e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  DCHECK(!app_id.empty());
51e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  DCHECK(!callback.is_null());
52e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver
53e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  GCMClient::Result result = EnsureStarted();
54e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver  if (result != GCMClient::SUCCESS) {
55e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver    callback.Run(result);
56e80efa670f1027fdf3882a298216a460199e38d0Ben Gruver    return;
57  }
58
59  // If previous un/register operation is still in progress, bail out.
60  if (IsAsyncOperationPending(app_id)) {
61    callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
62    return;
63  }
64
65  unregister_callbacks_[app_id] = callback;
66
67  UnregisterImpl(app_id);
68}
69
70void GCMDriver::Send(const std::string& app_id,
71                     const std::string& receiver_id,
72                     const GCMClient::OutgoingMessage& message,
73                     const SendCallback& callback) {
74  DCHECK(!app_id.empty());
75  DCHECK(!receiver_id.empty());
76  DCHECK(!callback.is_null());
77
78  GCMClient::Result result = EnsureStarted();
79  if (result != GCMClient::SUCCESS) {
80    callback.Run(std::string(), result);
81    return;
82  }
83
84  // If the message with send ID is still in progress, bail out.
85  std::pair<std::string, std::string> key(app_id, message.id);
86  if (send_callbacks_.find(key) != send_callbacks_.end()) {
87    callback.Run(message.id, GCMClient::INVALID_PARAMETER);
88    return;
89  }
90
91  send_callbacks_[key] = callback;
92
93  SendImpl(app_id, receiver_id, message);
94}
95
96void GCMDriver::RegisterFinished(const std::string& app_id,
97                                 const std::string& registration_id,
98                                 GCMClient::Result result) {
99  std::map<std::string, RegisterCallback>::iterator callback_iter =
100      register_callbacks_.find(app_id);
101  if (callback_iter == register_callbacks_.end()) {
102    // The callback could have been removed when the app is uninstalled.
103    return;
104  }
105
106  RegisterCallback callback = callback_iter->second;
107  register_callbacks_.erase(callback_iter);
108  callback.Run(registration_id, result);
109}
110
111void GCMDriver::UnregisterFinished(const std::string& app_id,
112                                   GCMClient::Result result) {
113  std::map<std::string, UnregisterCallback>::iterator callback_iter =
114      unregister_callbacks_.find(app_id);
115  if (callback_iter == unregister_callbacks_.end())
116    return;
117
118  UnregisterCallback callback = callback_iter->second;
119  unregister_callbacks_.erase(callback_iter);
120  callback.Run(result);
121}
122
123void GCMDriver::SendFinished(const std::string& app_id,
124                             const std::string& message_id,
125                             GCMClient::Result result) {
126  std::map<std::pair<std::string, std::string>, SendCallback>::iterator
127      callback_iter = send_callbacks_.find(
128          std::pair<std::string, std::string>(app_id, message_id));
129  if (callback_iter == send_callbacks_.end()) {
130    // The callback could have been removed when the app is uninstalled.
131    return;
132  }
133
134  SendCallback callback = callback_iter->second;
135  send_callbacks_.erase(callback_iter);
136  callback.Run(message_id, result);
137}
138
139void GCMDriver::Shutdown() {
140  for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
141       iter != app_handlers_.end(); ++iter) {
142    iter->second->ShutdownHandler();
143  }
144  app_handlers_.clear();
145}
146
147void GCMDriver::AddAppHandler(const std::string& app_id,
148                              GCMAppHandler* handler) {
149  DCHECK(!app_id.empty());
150  DCHECK(handler);
151  DCHECK_EQ(app_handlers_.count(app_id), 0u);
152  app_handlers_[app_id] = handler;
153}
154
155void GCMDriver::RemoveAppHandler(const std::string& app_id) {
156  DCHECK(!app_id.empty());
157  app_handlers_.erase(app_id);
158}
159
160GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
161  // Look for exact match.
162  GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
163  if (iter != app_handlers_.end())
164    return iter->second;
165
166  // Ask the handlers whether they know how to handle it.
167  for (iter = app_handlers_.begin(); iter != app_handlers_.end(); ++iter) {
168    if (iter->second->CanHandle(app_id))
169      return iter->second;
170  }
171
172  return &default_app_handler_;
173}
174
175bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
176  return register_callbacks_.find(app_id) != register_callbacks_.end();
177}
178
179void GCMDriver::ClearCallbacks() {
180  register_callbacks_.clear();
181  unregister_callbacks_.clear();
182  send_callbacks_.clear();
183}
184
185bool GCMDriver::IsAsyncOperationPending(const std::string& app_id) const {
186  return register_callbacks_.find(app_id) != register_callbacks_.end() ||
187         unregister_callbacks_.find(app_id) != unregister_callbacks_.end();
188}
189
190}  // namespace gcm
191