| OLD | NEW | 
|---|
|  | (Empty) | 
| 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/copresence/handlers/gcm_handler_impl.h" |  | 
| 6 |  | 
| 7 #include "base/base64.h" |  | 
| 8 #include "base/bind.h" |  | 
| 9 #include "base/logging.h" |  | 
| 10 #include "base/strings/string_util.h" |  | 
| 11 #include "components/copresence/handlers/directive_handler.h" |  | 
| 12 #include "components/copresence/proto/push_message.pb.h" |  | 
| 13 #include "components/gcm_driver/gcm_driver.h" |  | 
| 14 |  | 
| 15 using gcm::GCMClient; |  | 
| 16 |  | 
| 17 namespace { |  | 
| 18 |  | 
| 19 // TODO(ckehoe): Move this to a common library. |  | 
| 20 bool Base64Decode(std::string data, std::string* out) { |  | 
| 21   // Convert from URL-safe. |  | 
| 22   base::ReplaceChars(data, "-", "+", &data); |  | 
| 23   base::ReplaceChars(data, "_", "/", &data); |  | 
| 24 |  | 
| 25   // Add padding if needed. |  | 
| 26   while (data.size() % 4) |  | 
| 27     data.push_back('='); |  | 
| 28 |  | 
| 29   // Decode. |  | 
| 30   return base::Base64Decode(data, out); |  | 
| 31 } |  | 
| 32 |  | 
| 33 }  // namespace |  | 
| 34 |  | 
| 35 namespace copresence { |  | 
| 36 |  | 
| 37 const char GCMHandlerImpl::kCopresenceAppId[] = |  | 
| 38     "com.google.android.gms.location.copresence"; |  | 
| 39 const char GCMHandlerImpl::kCopresenceSenderId[] = "745476177629"; |  | 
| 40 const char GCMHandlerImpl::kGcmMessageKey[] = "PUSH_MESSAGE"; |  | 
| 41 |  | 
| 42 |  | 
| 43 // Public functions. |  | 
| 44 |  | 
| 45 GCMHandlerImpl::GCMHandlerImpl(gcm::GCMDriver* gcm_driver, |  | 
| 46                                DirectiveHandler* directive_handler, |  | 
| 47                                const MessagesCallback& new_messages_callback) |  | 
| 48     : driver_(gcm_driver), |  | 
| 49       directive_handler_(directive_handler), |  | 
| 50       new_messages_callback_(new_messages_callback), |  | 
| 51       registration_callback_(base::Bind(&GCMHandlerImpl::RegistrationComplete, |  | 
| 52                                         base::Unretained(this))) { |  | 
| 53   DCHECK(driver_); |  | 
| 54   DCHECK(directive_handler_); |  | 
| 55 |  | 
| 56   driver_->AddAppHandler(kCopresenceAppId, this); |  | 
| 57   driver_->Register(kCopresenceAppId, |  | 
| 58                     std::vector<std::string>(1, kCopresenceSenderId), |  | 
| 59                     registration_callback_.callback()); |  | 
| 60 } |  | 
| 61 |  | 
| 62 GCMHandlerImpl::~GCMHandlerImpl() { |  | 
| 63   if (driver_) |  | 
| 64     driver_->RemoveAppHandler(kCopresenceAppId); |  | 
| 65 } |  | 
| 66 |  | 
| 67 void GCMHandlerImpl::GetGcmId(const RegistrationCallback& callback) { |  | 
| 68   if (gcm_id_.empty()) { |  | 
| 69     pending_id_requests_.push_back(callback); |  | 
| 70   } else { |  | 
| 71     callback.Run(gcm_id_); |  | 
| 72   } |  | 
| 73 } |  | 
| 74 |  | 
| 75 void GCMHandlerImpl::ShutdownHandler() { |  | 
| 76   // The GCMDriver is going away. Make sure we don't try to contact it. |  | 
| 77   driver_ = nullptr; |  | 
| 78 } |  | 
| 79 |  | 
| 80 void GCMHandlerImpl::OnMessage(const std::string& app_id, |  | 
| 81                                const gcm::IncomingMessage& message) { |  | 
| 82   DCHECK_EQ(kCopresenceAppId, app_id); |  | 
| 83   DVLOG(2) << "Incoming GCM message"; |  | 
| 84 |  | 
| 85   const auto& content = message.data.find(kGcmMessageKey); |  | 
| 86   if (content == message.data.end()) { |  | 
| 87     LOG(ERROR) << "GCM message missing data key"; |  | 
| 88     return; |  | 
| 89   } |  | 
| 90 |  | 
| 91   std::string serialized_message; |  | 
| 92   if (!Base64Decode(content->second, &serialized_message)) { |  | 
| 93     LOG(ERROR) << "Couldn't decode GCM message"; |  | 
| 94     return; |  | 
| 95   } |  | 
| 96 |  | 
| 97   PushMessage push_message; |  | 
| 98   if (!push_message.ParseFromString(serialized_message)) { |  | 
| 99     LOG(ERROR) << "GCM message contained invalid proto"; |  | 
| 100     return; |  | 
| 101   } |  | 
| 102 |  | 
| 103   if (push_message.type() != PushMessage::REPORT) { |  | 
| 104     DVLOG(2) << "Discarding non-report GCM message"; |  | 
| 105     return; |  | 
| 106   } |  | 
| 107 |  | 
| 108   DVLOG(3) << "Processing " << push_message.report().directive_size() |  | 
| 109            << " directive(s) from GCM message"; |  | 
| 110   for (const Directive& directive : push_message.report().directive()) { |  | 
| 111     // TODO(ckehoe): Use a callback here so GCMHandler |  | 
| 112     // is decoupled from DirectiveHandler. |  | 
| 113     directive_handler_->AddDirective(directive); |  | 
| 114   } |  | 
| 115 |  | 
| 116   new_messages_callback_.Run(push_message.report().subscribed_message()); |  | 
| 117 } |  | 
| 118 |  | 
| 119 void GCMHandlerImpl::OnMessagesDeleted(const std::string& app_id) { |  | 
| 120   DCHECK_EQ(kCopresenceAppId, app_id); |  | 
| 121   DVLOG(2) << "GCM message overflow reported"; |  | 
| 122 } |  | 
| 123 |  | 
| 124 void GCMHandlerImpl::OnSendError( |  | 
| 125     const std::string& /* app_id */, |  | 
| 126     const GCMClient::SendErrorDetails& /* send_error_details */) { |  | 
| 127   NOTREACHED() << "Copresence clients should not be sending GCM messages"; |  | 
| 128 } |  | 
| 129 |  | 
| 130 void GCMHandlerImpl::OnSendAcknowledged(const std::string& /* app_id */, |  | 
| 131                                         const std::string& /* message_id */) { |  | 
| 132   NOTREACHED() << "Copresence clients should not be sending GCM messages"; |  | 
| 133 } |  | 
| 134 |  | 
| 135 bool GCMHandlerImpl::CanHandle(const std::string& app_id) const { |  | 
| 136   return app_id == kCopresenceAppId; |  | 
| 137 } |  | 
| 138 |  | 
| 139 |  | 
| 140 // Private functions. |  | 
| 141 |  | 
| 142 void GCMHandlerImpl::RegistrationComplete(const std::string& registration_id, |  | 
| 143                                           GCMClient::Result result) { |  | 
| 144   if (result == GCMClient::SUCCESS) { |  | 
| 145     DVLOG(2) << "GCM registration successful. ID: " << registration_id; |  | 
| 146     gcm_id_ = registration_id; |  | 
| 147   } else { |  | 
| 148     LOG(ERROR) << "GCM registration failed with error " << result; |  | 
| 149   } |  | 
| 150 |  | 
| 151   for (const RegistrationCallback& callback : pending_id_requests_) { |  | 
| 152     callback.Run(result == GCMClient::SUCCESS ? |  | 
| 153         registration_id : std::string()); |  | 
| 154   } |  | 
| 155   pending_id_requests_.clear(); |  | 
| 156 } |  | 
| 157 |  | 
| 158 }  // namespace copresence |  | 
| OLD | NEW | 
|---|