Remove Instance ID and token data when an app with gcm permission is
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver.cc
blob82278172aab25e4f3fb97acf5516930310d7aeb0
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/logging.h"
11 #include "components/gcm_driver/gcm_app_handler.h"
13 namespace gcm {
15 namespace {
16 const size_t kMaxSenders = 100;
17 } // namespace
19 InstanceIDHandler::InstanceIDHandler() {
22 InstanceIDHandler::~InstanceIDHandler() {
25 void InstanceIDHandler::DeleteAllTokensForApp(
26 const std::string& app_id, const DeleteTokenCallback& callback) {
27 DeleteToken(app_id, "*", "*", callback);
30 GCMDriver::GCMDriver() : weak_ptr_factory_(this) {
33 GCMDriver::~GCMDriver() {
36 void GCMDriver::Register(const std::string& app_id,
37 const std::vector<std::string>& sender_ids,
38 const RegisterCallback& callback) {
39 DCHECK(!app_id.empty());
40 DCHECK(!sender_ids.empty() && sender_ids.size() <= kMaxSenders);
41 DCHECK(!callback.is_null());
43 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
44 if (result != GCMClient::SUCCESS) {
45 callback.Run(std::string(), result);
46 return;
49 // If previous register operation is still in progress, bail out.
50 if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
51 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
52 return;
55 // Normalize the sender IDs by making them sorted.
56 std::vector<std::string> normalized_sender_ids = sender_ids;
57 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
59 register_callbacks_[app_id] = callback;
61 // If previous unregister operation is still in progress, wait until it
62 // finishes. We don't want to throw ASYNC_OPERATION_PENDING when the user
63 // uninstalls an app (ungistering) and then reinstalls the app again
64 // (registering).
65 std::map<std::string, UnregisterCallback>::iterator unregister_iter =
66 unregister_callbacks_.find(app_id);
67 if (unregister_iter != unregister_callbacks_.end()) {
68 // Replace the original unregister callback with an intermediate callback
69 // that will invoke the original unregister callback and trigger the pending
70 // registration after the unregistration finishes.
71 // Note that some parameters to RegisterAfterUnregister are specified here
72 // when the callback is created (base::Bind supports the partial binding
73 // of parameters).
74 unregister_iter->second = base::Bind(
75 &GCMDriver::RegisterAfterUnregister,
76 weak_ptr_factory_.GetWeakPtr(),
77 app_id,
78 normalized_sender_ids,
79 unregister_iter->second);
80 return;
83 RegisterImpl(app_id, normalized_sender_ids);
86 void GCMDriver::Unregister(const std::string& app_id,
87 const UnregisterCallback& callback) {
88 UnregisterInternal(app_id, nullptr /* sender_id */, callback);
91 void GCMDriver::UnregisterWithSenderId(
92 const std::string& app_id,
93 const std::string& sender_id,
94 const UnregisterCallback& callback) {
95 DCHECK(!sender_id.empty());
96 UnregisterInternal(app_id, &sender_id, callback);
99 void GCMDriver::UnregisterInternal(const std::string& app_id,
100 const std::string* sender_id,
101 const UnregisterCallback& callback) {
102 DCHECK(!app_id.empty());
103 DCHECK(!callback.is_null());
105 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
106 if (result != GCMClient::SUCCESS) {
107 callback.Run(result);
108 return;
111 // If previous un/register operation is still in progress, bail out.
112 if (register_callbacks_.find(app_id) != register_callbacks_.end() ||
113 unregister_callbacks_.find(app_id) != unregister_callbacks_.end()) {
114 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
115 return;
118 unregister_callbacks_[app_id] = callback;
120 if (sender_id)
121 UnregisterWithSenderIdImpl(app_id, *sender_id);
122 else
123 UnregisterImpl(app_id);
126 void GCMDriver::Send(const std::string& app_id,
127 const std::string& receiver_id,
128 const GCMClient::OutgoingMessage& message,
129 const SendCallback& callback) {
130 DCHECK(!app_id.empty());
131 DCHECK(!receiver_id.empty());
132 DCHECK(!callback.is_null());
134 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
135 if (result != GCMClient::SUCCESS) {
136 callback.Run(std::string(), result);
137 return;
140 // If the message with send ID is still in progress, bail out.
141 std::pair<std::string, std::string> key(app_id, message.id);
142 if (send_callbacks_.find(key) != send_callbacks_.end()) {
143 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
144 return;
147 send_callbacks_[key] = callback;
149 SendImpl(app_id, receiver_id, message);
152 void GCMDriver::UnregisterWithSenderIdImpl(const std::string& app_id,
153 const std::string& sender_id) {
154 NOTREACHED();
157 void GCMDriver::RegisterFinished(const std::string& app_id,
158 const std::string& registration_id,
159 GCMClient::Result result) {
160 std::map<std::string, RegisterCallback>::iterator callback_iter =
161 register_callbacks_.find(app_id);
162 if (callback_iter == register_callbacks_.end()) {
163 // The callback could have been removed when the app is uninstalled.
164 return;
167 RegisterCallback callback = callback_iter->second;
168 register_callbacks_.erase(callback_iter);
169 callback.Run(registration_id, result);
172 void GCMDriver::UnregisterFinished(const std::string& app_id,
173 GCMClient::Result result) {
174 std::map<std::string, UnregisterCallback>::iterator callback_iter =
175 unregister_callbacks_.find(app_id);
176 if (callback_iter == unregister_callbacks_.end())
177 return;
179 UnregisterCallback callback = callback_iter->second;
180 unregister_callbacks_.erase(callback_iter);
181 callback.Run(result);
184 void GCMDriver::SendFinished(const std::string& app_id,
185 const std::string& message_id,
186 GCMClient::Result result) {
187 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
188 callback_iter = send_callbacks_.find(
189 std::pair<std::string, std::string>(app_id, message_id));
190 if (callback_iter == send_callbacks_.end()) {
191 // The callback could have been removed when the app is uninstalled.
192 return;
195 SendCallback callback = callback_iter->second;
196 send_callbacks_.erase(callback_iter);
197 callback.Run(message_id, result);
200 void GCMDriver::Shutdown() {
201 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
202 iter != app_handlers_.end(); ++iter) {
203 DVLOG(1) << "Calling ShutdownHandler for: " << iter->first;
204 iter->second->ShutdownHandler();
206 app_handlers_.clear();
209 void GCMDriver::AddAppHandler(const std::string& app_id,
210 GCMAppHandler* handler) {
211 DCHECK(!app_id.empty());
212 DCHECK(handler);
213 DCHECK_EQ(app_handlers_.count(app_id), 0u);
214 app_handlers_[app_id] = handler;
215 DVLOG(1) << "App handler added for: " << app_id;
218 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
219 DCHECK(!app_id.empty());
220 app_handlers_.erase(app_id);
221 DVLOG(1) << "App handler removed for: " << app_id;
224 GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
225 // Look for exact match.
226 GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
227 if (iter != app_handlers_.end())
228 return iter->second;
230 // Ask the handlers whether they know how to handle it.
231 for (iter = app_handlers_.begin(); iter != app_handlers_.end(); ++iter) {
232 if (iter->second->CanHandle(app_id))
233 return iter->second;
236 return &default_app_handler_;
239 bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
240 return register_callbacks_.find(app_id) != register_callbacks_.end();
243 void GCMDriver::ClearCallbacks() {
244 register_callbacks_.clear();
245 unregister_callbacks_.clear();
246 send_callbacks_.clear();
249 void GCMDriver::RegisterAfterUnregister(
250 const std::string& app_id,
251 const std::vector<std::string>& normalized_sender_ids,
252 const UnregisterCallback& unregister_callback,
253 GCMClient::Result result) {
254 // Invoke the original unregister callback.
255 unregister_callback.Run(result);
257 // Trigger the pending registration.
258 DCHECK(register_callbacks_.find(app_id) != register_callbacks_.end());
259 RegisterImpl(app_id, normalized_sender_ids);
262 } // namespace gcm