blob: cfe9f99eaf68a04e4b6e6573e0886fa469ed37a1 [file] [log] [blame]
[email protected]df84c532014-04-25 15:36:541// 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
[email protected]8d41e5a2014-05-28 03:18:495#include "components/gcm_driver/gcm_driver.h"
[email protected]df84c532014-04-25 15:36:546
[email protected]c27c10792014-06-05 15:27:237#include <algorithm>
8
[email protected]df84c532014-04-25 15:36:549#include "base/logging.h"
[email protected]446f73c22014-05-14 20:47:1810#include "components/gcm_driver/gcm_app_handler.h"
[email protected]df84c532014-04-25 15:36:5411
12namespace gcm {
13
[email protected]21b77652014-05-31 01:21:0914GCMDriver::GCMDriver() {
[email protected]9d7e5c02014-05-21 03:09:0315}
16
17GCMDriver::~GCMDriver() {
18}
19
[email protected]c27c10792014-06-05 15:27:2320void GCMDriver::Register(const std::string& app_id,
21 const std::vector<std::string>& sender_ids,
22 const RegisterCallback& callback) {
23 DCHECK(!app_id.empty());
24 DCHECK(!sender_ids.empty());
25 DCHECK(!callback.is_null());
26
27 GCMClient::Result result = EnsureStarted();
28 if (result != GCMClient::SUCCESS) {
29 callback.Run(std::string(), result);
30 return;
31 }
32
33 // If previous un/register operation is still in progress, bail out.
34 if (IsAsyncOperationPending(app_id)) {
35 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
36 return;
37 }
38
39 // Normalize the sender IDs by making them sorted.
40 std::vector<std::string> normalized_sender_ids = sender_ids;
41 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
42
43 register_callbacks_[app_id] = callback;
44
45 RegisterImpl(app_id, normalized_sender_ids);
46}
47
48void GCMDriver::Unregister(const std::string& app_id,
49 const UnregisterCallback& callback) {
50 DCHECK(!app_id.empty());
51 DCHECK(!callback.is_null());
52
53 GCMClient::Result result = EnsureStarted();
54 if (result != GCMClient::SUCCESS) {
55 callback.Run(result);
56 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
[email protected]9d7e5c02014-05-21 03:09:03139void GCMDriver::Shutdown() {
[email protected]df84c532014-04-25 15:36:54140 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
141 iter != app_handlers_.end(); ++iter) {
142 iter->second->ShutdownHandler();
143 }
144 app_handlers_.clear();
[email protected]df84c532014-04-25 15:36:54145}
146
[email protected]530f2162014-05-15 01:05:04147void GCMDriver::AddAppHandler(const std::string& app_id,
148 GCMAppHandler* handler) {
[email protected]df84c532014-04-25 15:36:54149 DCHECK(!app_id.empty());
150 DCHECK(handler);
[email protected]b7176262014-06-18 15:26:29151 DCHECK_EQ(app_handlers_.count(app_id), 0u);
[email protected]df84c532014-04-25 15:36:54152 app_handlers_[app_id] = handler;
153}
154
[email protected]530f2162014-05-15 01:05:04155void GCMDriver::RemoveAppHandler(const std::string& app_id) {
[email protected]df84c532014-04-25 15:36:54156 DCHECK(!app_id.empty());
[email protected]df84c532014-04-25 15:36:54157 app_handlers_.erase(app_id);
[email protected]df84c532014-04-25 15:36:54158}
159
[email protected]530f2162014-05-15 01:05:04160GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
[email protected]b7176262014-06-18 15:26:29161 // Look for exact match.
[email protected]21b77652014-05-31 01:21:09162 GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
[email protected]b7176262014-06-18 15:26:29163 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_;
[email protected]df84c532014-04-25 15:36:54173}
174
[email protected]c27c10792014-06-05 15:27:23175bool 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
[email protected]df84c532014-04-25 15:36:54190} // namespace gcm