• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "components/gcm_driver/gcm_driver.h"
6 
7 #include <algorithm>
8 
9 #include "base/logging.h"
10 #include "components/gcm_driver/gcm_app_handler.h"
11 
12 namespace gcm {
13 
GCMDriver()14 GCMDriver::GCMDriver() {
15 }
16 
~GCMDriver()17 GCMDriver::~GCMDriver() {
18 }
19 
Register(const std::string & app_id,const std::vector<std::string> & sender_ids,const RegisterCallback & callback)20 void 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 
Unregister(const std::string & app_id,const UnregisterCallback & callback)48 void 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 
Send(const std::string & app_id,const std::string & receiver_id,const GCMClient::OutgoingMessage & message,const SendCallback & callback)70 void 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 
RegisterFinished(const std::string & app_id,const std::string & registration_id,GCMClient::Result result)96 void 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 
UnregisterFinished(const std::string & app_id,GCMClient::Result result)111 void 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 
SendFinished(const std::string & app_id,const std::string & message_id,GCMClient::Result result)123 void 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 
Shutdown()139 void 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 
AddAppHandler(const std::string & app_id,GCMAppHandler * handler)147 void 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 
RemoveAppHandler(const std::string & app_id)155 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
156   DCHECK(!app_id.empty());
157   app_handlers_.erase(app_id);
158 }
159 
GetAppHandler(const std::string & app_id)160 GCMAppHandler* 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 
HasRegisterCallback(const std::string & app_id)175 bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
176   return register_callbacks_.find(app_id) != register_callbacks_.end();
177 }
178 
ClearCallbacks()179 void GCMDriver::ClearCallbacks() {
180   register_callbacks_.clear();
181   unregister_callbacks_.clear();
182   send_callbacks_.clear();
183 }
184 
IsAsyncOperationPending(const std::string & app_id) const185 bool 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