Update mojo sdk to rev c02a28868825edfa57ab77947b8cb15e741c5598
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver.cc
blob4e17801f33539a8a781a0a444656b10e2f3dd7f6
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.
5 #include "components/gcm_driver/gcm_driver.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "components/gcm_driver/gcm_app_handler.h"
14 namespace gcm {
16 const size_t kMaxSenders = 100;
18 InstanceIDHandler::InstanceIDHandler() {
21 InstanceIDHandler::~InstanceIDHandler() {
24 void InstanceIDHandler::DeleteAllTokensForApp(
25 const std::string& app_id, const DeleteTokenCallback& callback) {
26 DeleteToken(app_id, "*", "*", callback);
29 GCMDriver::GCMDriver(
30 const base::FilePath& store_path,
31 const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner)
32 : weak_ptr_factory_(this) {
33 // The |blocking_task_runner| can be NULL for tests that do not need the
34 // encryption capabilities of the GCMDriver class.
35 if (blocking_task_runner)
36 encryption_provider_.Init(store_path, blocking_task_runner);
39 GCMDriver::~GCMDriver() {
42 void GCMDriver::Register(const std::string& app_id,
43 const std::vector<std::string>& sender_ids,
44 const RegisterCallback& callback) {
45 DCHECK(!app_id.empty());
46 DCHECK(!sender_ids.empty() && sender_ids.size() <= kMaxSenders);
47 DCHECK(!callback.is_null());
49 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
50 if (result != GCMClient::SUCCESS) {
51 callback.Run(std::string(), result);
52 return;
55 // If previous register operation is still in progress, bail out.
56 if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
57 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
58 return;
61 // Normalize the sender IDs by making them sorted.
62 std::vector<std::string> normalized_sender_ids = sender_ids;
63 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
65 register_callbacks_[app_id] = callback;
67 // If previous unregister operation is still in progress, wait until it
68 // finishes. We don't want to throw ASYNC_OPERATION_PENDING when the user
69 // uninstalls an app (ungistering) and then reinstalls the app again
70 // (registering).
71 std::map<std::string, UnregisterCallback>::iterator unregister_iter =
72 unregister_callbacks_.find(app_id);
73 if (unregister_iter != unregister_callbacks_.end()) {
74 // Replace the original unregister callback with an intermediate callback
75 // that will invoke the original unregister callback and trigger the pending
76 // registration after the unregistration finishes.
77 // Note that some parameters to RegisterAfterUnregister are specified here
78 // when the callback is created (base::Bind supports the partial binding
79 // of parameters).
80 unregister_iter->second = base::Bind(
81 &GCMDriver::RegisterAfterUnregister,
82 weak_ptr_factory_.GetWeakPtr(),
83 app_id,
84 normalized_sender_ids,
85 unregister_iter->second);
86 return;
89 RegisterImpl(app_id, normalized_sender_ids);
92 void GCMDriver::Unregister(const std::string& app_id,
93 const UnregisterCallback& callback) {
94 UnregisterInternal(app_id, nullptr /* sender_id */, callback);
97 void GCMDriver::UnregisterWithSenderId(
98 const std::string& app_id,
99 const std::string& sender_id,
100 const UnregisterCallback& callback) {
101 DCHECK(!sender_id.empty());
102 UnregisterInternal(app_id, &sender_id, callback);
105 void GCMDriver::UnregisterInternal(const std::string& app_id,
106 const std::string* sender_id,
107 const UnregisterCallback& callback) {
108 DCHECK(!app_id.empty());
109 DCHECK(!callback.is_null());
111 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
112 if (result != GCMClient::SUCCESS) {
113 callback.Run(result);
114 return;
117 // If previous un/register operation is still in progress, bail out.
118 if (register_callbacks_.find(app_id) != register_callbacks_.end() ||
119 unregister_callbacks_.find(app_id) != unregister_callbacks_.end()) {
120 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
121 return;
124 unregister_callbacks_[app_id] = callback;
126 if (sender_id)
127 UnregisterWithSenderIdImpl(app_id, *sender_id);
128 else
129 UnregisterImpl(app_id);
132 void GCMDriver::Send(const std::string& app_id,
133 const std::string& receiver_id,
134 const OutgoingMessage& message,
135 const SendCallback& callback) {
136 DCHECK(!app_id.empty());
137 DCHECK(!receiver_id.empty());
138 DCHECK(!callback.is_null());
140 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
141 if (result != GCMClient::SUCCESS) {
142 callback.Run(std::string(), result);
143 return;
146 // If the message with send ID is still in progress, bail out.
147 std::pair<std::string, std::string> key(app_id, message.id);
148 if (send_callbacks_.find(key) != send_callbacks_.end()) {
149 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
150 return;
153 send_callbacks_[key] = callback;
155 SendImpl(app_id, receiver_id, message);
158 void GCMDriver::GetPublicKey(
159 const std::string& app_id,
160 const GetPublicKeyCallback& callback) {
161 encryption_provider_.GetPublicKey(app_id, callback);
164 void GCMDriver::UnregisterWithSenderIdImpl(const std::string& app_id,
165 const std::string& sender_id) {
166 NOTREACHED();
169 void GCMDriver::RegisterFinished(const std::string& app_id,
170 const std::string& registration_id,
171 GCMClient::Result result) {
172 std::map<std::string, RegisterCallback>::iterator callback_iter =
173 register_callbacks_.find(app_id);
174 if (callback_iter == register_callbacks_.end()) {
175 // The callback could have been removed when the app is uninstalled.
176 return;
179 RegisterCallback callback = callback_iter->second;
180 register_callbacks_.erase(callback_iter);
181 callback.Run(registration_id, result);
184 void GCMDriver::UnregisterFinished(const std::string& app_id,
185 GCMClient::Result result) {
186 std::map<std::string, UnregisterCallback>::iterator callback_iter =
187 unregister_callbacks_.find(app_id);
188 if (callback_iter == unregister_callbacks_.end())
189 return;
191 UnregisterCallback callback = callback_iter->second;
192 unregister_callbacks_.erase(callback_iter);
193 callback.Run(result);
196 void GCMDriver::SendFinished(const std::string& app_id,
197 const std::string& message_id,
198 GCMClient::Result result) {
199 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
200 callback_iter = send_callbacks_.find(
201 std::pair<std::string, std::string>(app_id, message_id));
202 if (callback_iter == send_callbacks_.end()) {
203 // The callback could have been removed when the app is uninstalled.
204 return;
207 SendCallback callback = callback_iter->second;
208 send_callbacks_.erase(callback_iter);
209 callback.Run(message_id, result);
212 void GCMDriver::Shutdown() {
213 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
214 iter != app_handlers_.end(); ++iter) {
215 DVLOG(1) << "Calling ShutdownHandler for: " << iter->first;
216 iter->second->ShutdownHandler();
218 app_handlers_.clear();
221 void GCMDriver::AddAppHandler(const std::string& app_id,
222 GCMAppHandler* handler) {
223 DCHECK(!app_id.empty());
224 DCHECK(handler);
225 DCHECK_EQ(app_handlers_.count(app_id), 0u);
226 app_handlers_[app_id] = handler;
227 DVLOG(1) << "App handler added for: " << app_id;
230 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
231 DCHECK(!app_id.empty());
232 app_handlers_.erase(app_id);
233 DVLOG(1) << "App handler removed for: " << app_id;
236 GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
237 // Look for exact match.
238 GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
239 if (iter != app_handlers_.end())
240 return iter->second;
242 // Ask the handlers whether they know how to handle it.
243 for (iter = app_handlers_.begin(); iter != app_handlers_.end(); ++iter) {
244 if (iter->second->CanHandle(app_id))
245 return iter->second;
248 return &default_app_handler_;
251 bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
252 return register_callbacks_.find(app_id) != register_callbacks_.end();
255 void GCMDriver::ClearCallbacks() {
256 register_callbacks_.clear();
257 unregister_callbacks_.clear();
258 send_callbacks_.clear();
261 void GCMDriver::RegisterAfterUnregister(
262 const std::string& app_id,
263 const std::vector<std::string>& normalized_sender_ids,
264 const UnregisterCallback& unregister_callback,
265 GCMClient::Result result) {
266 // Invoke the original unregister callback.
267 unregister_callback.Run(result);
269 // Trigger the pending registration.
270 DCHECK(register_callbacks_.find(app_id) != register_callbacks_.end());
271 RegisterImpl(app_id, normalized_sender_ids);
274 } // namespace gcm