Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver.cc
blob080ba526bdfb9efbd6668795368fb9ef3f1575e7
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 GCMDriver::GCMDriver() : weak_ptr_factory_(this) {
18 GCMDriver::~GCMDriver() {
21 void GCMDriver::Register(const std::string& app_id,
22 const std::vector<std::string>& sender_ids,
23 const RegisterCallback& callback) {
24 DCHECK(!app_id.empty());
25 DCHECK(!sender_ids.empty());
26 DCHECK(!callback.is_null());
28 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
29 if (result != GCMClient::SUCCESS) {
30 callback.Run(std::string(), result);
31 return;
34 // If previous register operation is still in progress, bail out.
35 if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
36 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
37 return;
40 // Normalize the sender IDs by making them sorted.
41 std::vector<std::string> normalized_sender_ids = sender_ids;
42 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
44 register_callbacks_[app_id] = callback;
46 // If previous unregister operation is still in progress, wait until it
47 // finishes. We don't want to throw ASYNC_OPERATION_PENDING when the user
48 // uninstalls an app (ungistering) and then reinstalls the app again
49 // (registering).
50 std::map<std::string, UnregisterCallback>::iterator unregister_iter =
51 unregister_callbacks_.find(app_id);
52 if (unregister_iter != unregister_callbacks_.end()) {
53 // Replace the original unregister callback with an intermediate callback
54 // that will invoke the original unregister callback and trigger the pending
55 // registration after the unregistration finishes.
56 // Note that some parameters to RegisterAfterUnregister are specified here
57 // when the callback is created (base::Bind supports the partial binding
58 // of parameters).
59 unregister_iter->second = base::Bind(
60 &GCMDriver::RegisterAfterUnregister,
61 weak_ptr_factory_.GetWeakPtr(),
62 app_id,
63 normalized_sender_ids,
64 unregister_iter->second);
65 return;
68 RegisterImpl(app_id, normalized_sender_ids);
71 void GCMDriver::Unregister(const std::string& app_id,
72 const UnregisterCallback& callback) {
73 UnregisterInternal(app_id, nullptr /* sender_id */, callback);
76 void GCMDriver::UnregisterWithSenderId(
77 const std::string& app_id,
78 const std::string& sender_id,
79 const UnregisterCallback& callback) {
80 DCHECK(!sender_id.empty());
81 UnregisterInternal(app_id, &sender_id, callback);
84 void GCMDriver::UnregisterInternal(const std::string& app_id,
85 const std::string* sender_id,
86 const UnregisterCallback& callback) {
87 DCHECK(!app_id.empty());
88 DCHECK(!callback.is_null());
90 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
91 if (result != GCMClient::SUCCESS) {
92 callback.Run(result);
93 return;
96 // If previous un/register operation is still in progress, bail out.
97 if (register_callbacks_.find(app_id) != register_callbacks_.end() ||
98 unregister_callbacks_.find(app_id) != unregister_callbacks_.end()) {
99 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
100 return;
103 unregister_callbacks_[app_id] = callback;
105 if (sender_id)
106 UnregisterWithSenderIdImpl(app_id, *sender_id);
107 else
108 UnregisterImpl(app_id);
111 void GCMDriver::Send(const std::string& app_id,
112 const std::string& receiver_id,
113 const GCMClient::OutgoingMessage& message,
114 const SendCallback& callback) {
115 DCHECK(!app_id.empty());
116 DCHECK(!receiver_id.empty());
117 DCHECK(!callback.is_null());
119 GCMClient::Result result = EnsureStarted(GCMClient::IMMEDIATE_START);
120 if (result != GCMClient::SUCCESS) {
121 callback.Run(std::string(), result);
122 return;
125 // If the message with send ID is still in progress, bail out.
126 std::pair<std::string, std::string> key(app_id, message.id);
127 if (send_callbacks_.find(key) != send_callbacks_.end()) {
128 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
129 return;
132 send_callbacks_[key] = callback;
134 SendImpl(app_id, receiver_id, message);
137 void GCMDriver::UnregisterWithSenderIdImpl(const std::string& app_id,
138 const std::string& sender_id) {
139 NOTREACHED();
142 void GCMDriver::RegisterFinished(const std::string& app_id,
143 const std::string& registration_id,
144 GCMClient::Result result) {
145 std::map<std::string, RegisterCallback>::iterator callback_iter =
146 register_callbacks_.find(app_id);
147 if (callback_iter == register_callbacks_.end()) {
148 // The callback could have been removed when the app is uninstalled.
149 return;
152 RegisterCallback callback = callback_iter->second;
153 register_callbacks_.erase(callback_iter);
154 callback.Run(registration_id, result);
157 void GCMDriver::UnregisterFinished(const std::string& app_id,
158 GCMClient::Result result) {
159 std::map<std::string, UnregisterCallback>::iterator callback_iter =
160 unregister_callbacks_.find(app_id);
161 if (callback_iter == unregister_callbacks_.end())
162 return;
164 UnregisterCallback callback = callback_iter->second;
165 unregister_callbacks_.erase(callback_iter);
166 callback.Run(result);
169 void GCMDriver::SendFinished(const std::string& app_id,
170 const std::string& message_id,
171 GCMClient::Result result) {
172 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
173 callback_iter = send_callbacks_.find(
174 std::pair<std::string, std::string>(app_id, message_id));
175 if (callback_iter == send_callbacks_.end()) {
176 // The callback could have been removed when the app is uninstalled.
177 return;
180 SendCallback callback = callback_iter->second;
181 send_callbacks_.erase(callback_iter);
182 callback.Run(message_id, result);
185 void GCMDriver::Shutdown() {
186 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
187 iter != app_handlers_.end(); ++iter) {
188 DVLOG(1) << "Calling ShutdownHandler for: " << iter->first;
189 iter->second->ShutdownHandler();
191 app_handlers_.clear();
194 void GCMDriver::AddAppHandler(const std::string& app_id,
195 GCMAppHandler* handler) {
196 DCHECK(!app_id.empty());
197 DCHECK(handler);
198 DCHECK_EQ(app_handlers_.count(app_id), 0u);
199 app_handlers_[app_id] = handler;
200 DVLOG(1) << "App handler added for: " << app_id;
203 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
204 DCHECK(!app_id.empty());
205 app_handlers_.erase(app_id);
206 DVLOG(1) << "App handler removed for: " << app_id;
209 GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
210 // Look for exact match.
211 GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
212 if (iter != app_handlers_.end())
213 return iter->second;
215 // Ask the handlers whether they know how to handle it.
216 for (iter = app_handlers_.begin(); iter != app_handlers_.end(); ++iter) {
217 if (iter->second->CanHandle(app_id))
218 return iter->second;
221 return &default_app_handler_;
224 bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
225 return register_callbacks_.find(app_id) != register_callbacks_.end();
228 void GCMDriver::ClearCallbacks() {
229 register_callbacks_.clear();
230 unregister_callbacks_.clear();
231 send_callbacks_.clear();
234 void GCMDriver::RegisterAfterUnregister(
235 const std::string& app_id,
236 const std::vector<std::string>& normalized_sender_ids,
237 const UnregisterCallback& unregister_callback,
238 GCMClient::Result result) {
239 // Invoke the original unregister callback.
240 unregister_callback.Run(result);
242 // Trigger the pending registration.
243 DCHECK(register_callbacks_.find(app_id) != register_callbacks_.end());
244 RegisterImpl(app_id, normalized_sender_ids);
247 } // namespace gcm