Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / components / gcm_driver / gcm_driver.cc
blobdb0362408a9a3587aaa769987ee42eb80797715a
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/logging.h"
10 #include "base/metrics/field_trial.h"
11 #include "components/gcm_driver/gcm_app_handler.h"
13 namespace gcm {
15 namespace {
16 const char kGCMFieldTrialName[] = "GCM";
17 const char kGCMFieldTrialEnabledGroupName[] = "Enabled";
18 } // namespace
20 // static
21 bool GCMDriver::IsAllowedForAllUsers() {
22 std::string group_name =
23 base::FieldTrialList::FindFullName(kGCMFieldTrialName);
24 return group_name == kGCMFieldTrialEnabledGroupName;
27 GCMDriver::GCMDriver() : weak_ptr_factory_(this) {
30 GCMDriver::~GCMDriver() {
33 void GCMDriver::Register(const std::string& app_id,
34 const std::vector<std::string>& sender_ids,
35 const RegisterCallback& callback) {
36 DCHECK(!app_id.empty());
37 DCHECK(!sender_ids.empty());
38 DCHECK(!callback.is_null());
40 GCMClient::Result result = EnsureStarted();
41 if (result != GCMClient::SUCCESS) {
42 callback.Run(std::string(), result);
43 return;
46 // If previous register operation is still in progress, bail out.
47 if (register_callbacks_.find(app_id) != register_callbacks_.end()) {
48 callback.Run(std::string(), GCMClient::ASYNC_OPERATION_PENDING);
49 return;
52 // Normalize the sender IDs by making them sorted.
53 std::vector<std::string> normalized_sender_ids = sender_ids;
54 std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
56 register_callbacks_[app_id] = callback;
58 // If previous unregister operation is still in progress, wait until it
59 // finishes. We don't want to throw ASYNC_OPERATION_PENDING when the user
60 // uninstalls an app (ungistering) and then reinstalls the app again
61 // (registering).
62 std::map<std::string, UnregisterCallback>::iterator unregister_iter =
63 unregister_callbacks_.find(app_id);
64 if (unregister_iter != unregister_callbacks_.end()) {
65 // Replace the original unregister callback with an intermediate callback
66 // that will invoke the original unregister callback and trigger the pending
67 // registration after the unregistration finishes.
68 // Note that some parameters to RegisterAfterUnregister are specified here
69 // when the callback is created (base::Bind supports the partial binding
70 // of parameters).
71 unregister_iter->second = base::Bind(
72 &GCMDriver::RegisterAfterUnregister,
73 weak_ptr_factory_.GetWeakPtr(),
74 app_id,
75 normalized_sender_ids,
76 unregister_iter->second);
77 return;
80 RegisterImpl(app_id, normalized_sender_ids);
83 void GCMDriver::Unregister(const std::string& app_id,
84 const UnregisterCallback& callback) {
85 DCHECK(!app_id.empty());
86 DCHECK(!callback.is_null());
88 GCMClient::Result result = EnsureStarted();
89 if (result != GCMClient::SUCCESS) {
90 callback.Run(result);
91 return;
94 // If previous un/register operation is still in progress, bail out.
95 if (register_callbacks_.find(app_id) != register_callbacks_.end() ||
96 unregister_callbacks_.find(app_id) != unregister_callbacks_.end()) {
97 callback.Run(GCMClient::ASYNC_OPERATION_PENDING);
98 return;
101 unregister_callbacks_[app_id] = callback;
103 UnregisterImpl(app_id);
106 void GCMDriver::Send(const std::string& app_id,
107 const std::string& receiver_id,
108 const GCMClient::OutgoingMessage& message,
109 const SendCallback& callback) {
110 DCHECK(!app_id.empty());
111 DCHECK(!receiver_id.empty());
112 DCHECK(!callback.is_null());
114 GCMClient::Result result = EnsureStarted();
115 if (result != GCMClient::SUCCESS) {
116 callback.Run(std::string(), result);
117 return;
120 // If the message with send ID is still in progress, bail out.
121 std::pair<std::string, std::string> key(app_id, message.id);
122 if (send_callbacks_.find(key) != send_callbacks_.end()) {
123 callback.Run(message.id, GCMClient::INVALID_PARAMETER);
124 return;
127 send_callbacks_[key] = callback;
129 SendImpl(app_id, receiver_id, message);
132 void GCMDriver::RegisterFinished(const std::string& app_id,
133 const std::string& registration_id,
134 GCMClient::Result result) {
135 std::map<std::string, RegisterCallback>::iterator callback_iter =
136 register_callbacks_.find(app_id);
137 if (callback_iter == register_callbacks_.end()) {
138 // The callback could have been removed when the app is uninstalled.
139 return;
142 RegisterCallback callback = callback_iter->second;
143 register_callbacks_.erase(callback_iter);
144 callback.Run(registration_id, result);
147 void GCMDriver::UnregisterFinished(const std::string& app_id,
148 GCMClient::Result result) {
149 std::map<std::string, UnregisterCallback>::iterator callback_iter =
150 unregister_callbacks_.find(app_id);
151 if (callback_iter == unregister_callbacks_.end())
152 return;
154 UnregisterCallback callback = callback_iter->second;
155 unregister_callbacks_.erase(callback_iter);
156 callback.Run(result);
159 void GCMDriver::SendFinished(const std::string& app_id,
160 const std::string& message_id,
161 GCMClient::Result result) {
162 std::map<std::pair<std::string, std::string>, SendCallback>::iterator
163 callback_iter = send_callbacks_.find(
164 std::pair<std::string, std::string>(app_id, message_id));
165 if (callback_iter == send_callbacks_.end()) {
166 // The callback could have been removed when the app is uninstalled.
167 return;
170 SendCallback callback = callback_iter->second;
171 send_callbacks_.erase(callback_iter);
172 callback.Run(message_id, result);
175 void GCMDriver::Shutdown() {
176 for (GCMAppHandlerMap::const_iterator iter = app_handlers_.begin();
177 iter != app_handlers_.end(); ++iter) {
178 DVLOG(1) << "Calling ShutdownHandler for: " << iter->first;
179 iter->second->ShutdownHandler();
181 app_handlers_.clear();
184 void GCMDriver::AddAppHandler(const std::string& app_id,
185 GCMAppHandler* handler) {
186 DCHECK(!app_id.empty());
187 DCHECK(handler);
188 DCHECK_EQ(app_handlers_.count(app_id), 0u);
189 app_handlers_[app_id] = handler;
190 DVLOG(1) << "App handler added for: " << app_id;
193 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
194 DCHECK(!app_id.empty());
195 app_handlers_.erase(app_id);
196 DVLOG(1) << "App handler removed for: " << app_id;
199 GCMAppHandler* GCMDriver::GetAppHandler(const std::string& app_id) {
200 // Look for exact match.
201 GCMAppHandlerMap::const_iterator iter = app_handlers_.find(app_id);
202 if (iter != app_handlers_.end())
203 return iter->second;
205 // Ask the handlers whether they know how to handle it.
206 for (iter = app_handlers_.begin(); iter != app_handlers_.end(); ++iter) {
207 if (iter->second->CanHandle(app_id))
208 return iter->second;
211 return &default_app_handler_;
214 bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
215 return register_callbacks_.find(app_id) != register_callbacks_.end();
218 void GCMDriver::ClearCallbacks() {
219 register_callbacks_.clear();
220 unregister_callbacks_.clear();
221 send_callbacks_.clear();
224 void GCMDriver::RegisterAfterUnregister(
225 const std::string& app_id,
226 const std::vector<std::string>& normalized_sender_ids,
227 const UnregisterCallback& unregister_callback,
228 GCMClient::Result result) {
229 // Invoke the original unregister callback.
230 unregister_callback.Run(result);
232 // Trigger the pending registration.
233 DCHECK(register_callbacks_.find(app_id) != register_callbacks_.end());
234 RegisterImpl(app_id, normalized_sender_ids);
237 } // namespace gcm