Home | History | Annotate | Download | only in gcm_driver
      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 
     14 GCMDriver::GCMDriver() {
     15 }
     16 
     17 GCMDriver::~GCMDriver() {
     18 }
     19 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    155 void GCMDriver::RemoveAppHandler(const std::string& app_id) {
    156   DCHECK(!app_id.empty());
    157   app_handlers_.erase(app_id);
    158 }
    159 
    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 
    175 bool GCMDriver::HasRegisterCallback(const std::string& app_id) {
    176   return register_callbacks_.find(app_id) != register_callbacks_.end();
    177 }
    178 
    179 void GCMDriver::ClearCallbacks() {
    180   register_callbacks_.clear();
    181   unregister_callbacks_.clear();
    182   send_callbacks_.clear();
    183 }
    184 
    185 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