Home | History | Annotate | Download | only in invalidation
      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/invalidation/push_client_channel.h"
      6 
      7 #include "base/stl_util.h"
      8 #include "components/invalidation/notifier_reason_util.h"
      9 #include "google/cacheinvalidation/client_gateway.pb.h"
     10 #include "google/cacheinvalidation/types.pb.h"
     11 #include "jingle/notifier/listener/push_client.h"
     12 
     13 namespace syncer {
     14 
     15 namespace {
     16 
     17 const char kBotJid[] = "tango (at) bot.talk.google.com";
     18 const char kChannelName[] = "tango_raw";
     19 
     20 }  // namespace
     21 
     22 PushClientChannel::PushClientChannel(
     23     scoped_ptr<notifier::PushClient> push_client)
     24     : push_client_(push_client.Pass()),
     25       scheduling_hash_(0),
     26       sent_messages_count_(0) {
     27   push_client_->AddObserver(this);
     28   notifier::Subscription subscription;
     29   subscription.channel = kChannelName;
     30   subscription.from = "";
     31   notifier::SubscriptionList subscriptions;
     32   subscriptions.push_back(subscription);
     33   push_client_->UpdateSubscriptions(subscriptions);
     34 }
     35 
     36 PushClientChannel::~PushClientChannel() {
     37   push_client_->RemoveObserver(this);
     38 }
     39 
     40 void PushClientChannel::UpdateCredentials(
     41     const std::string& email, const std::string& token) {
     42   push_client_->UpdateCredentials(email, token);
     43 }
     44 
     45 int PushClientChannel::GetInvalidationClientType() {
     46 #if defined(OS_IOS)
     47   return ipc::invalidation::ClientType::CHROME_SYNC_IOS;
     48 #else
     49   return ipc::invalidation::ClientType::CHROME_SYNC;
     50 #endif
     51 }
     52 
     53 void PushClientChannel::RequestDetailedStatus(
     54     base::Callback<void(const base::DictionaryValue&)> callback) {
     55   callback.Run(*CollectDebugData());
     56 }
     57 
     58 void PushClientChannel::SendMessage(const std::string& message) {
     59   std::string encoded_message;
     60   EncodeMessage(&encoded_message, message, service_context_, scheduling_hash_);
     61 
     62   notifier::Recipient recipient;
     63   recipient.to = kBotJid;
     64   notifier::Notification notification;
     65   notification.channel = kChannelName;
     66   notification.recipients.push_back(recipient);
     67   notification.data = encoded_message;
     68   push_client_->SendNotification(notification);
     69   sent_messages_count_++;
     70 }
     71 
     72 void PushClientChannel::OnNotificationsEnabled() {
     73   NotifyNetworkStatusChange(true);
     74   NotifyChannelStateChange(INVALIDATIONS_ENABLED);
     75 }
     76 
     77 void PushClientChannel::OnNotificationsDisabled(
     78     notifier::NotificationsDisabledReason reason) {
     79   NotifyNetworkStatusChange(false);
     80   NotifyChannelStateChange(FromNotifierReason(reason));
     81 }
     82 
     83 void PushClientChannel::OnIncomingNotification(
     84     const notifier::Notification& notification) {
     85   std::string message;
     86   std::string service_context;
     87   int64 scheduling_hash;
     88   if (!DecodeMessage(
     89            notification.data, &message, &service_context, &scheduling_hash)) {
     90     DLOG(ERROR) << "Could not parse ClientGatewayMessage";
     91     return;
     92   }
     93   if (DeliverIncomingMessage(message)) {
     94     service_context_ = service_context;
     95     scheduling_hash_ = scheduling_hash;
     96   }
     97 }
     98 
     99 const std::string& PushClientChannel::GetServiceContextForTest() const {
    100   return service_context_;
    101 }
    102 
    103 int64 PushClientChannel::GetSchedulingHashForTest() const {
    104   return scheduling_hash_;
    105 }
    106 
    107 std::string PushClientChannel::EncodeMessageForTest(
    108     const std::string& message,
    109     const std::string& service_context,
    110     int64 scheduling_hash) {
    111   std::string encoded_message;
    112   EncodeMessage(&encoded_message, message, service_context, scheduling_hash);
    113   return encoded_message;
    114 }
    115 
    116 bool PushClientChannel::DecodeMessageForTest(const std::string& data,
    117                                              std::string* message,
    118                                              std::string* service_context,
    119                                              int64* scheduling_hash) {
    120   return DecodeMessage(data, message, service_context, scheduling_hash);
    121 }
    122 
    123 void PushClientChannel::EncodeMessage(std::string* encoded_message,
    124                                       const std::string& message,
    125                                       const std::string& service_context,
    126                                       int64 scheduling_hash) {
    127   ipc::invalidation::ClientGatewayMessage envelope;
    128   envelope.set_is_client_to_server(true);
    129   if (!service_context.empty()) {
    130     envelope.set_service_context(service_context);
    131     envelope.set_rpc_scheduling_hash(scheduling_hash);
    132   }
    133   envelope.set_network_message(message);
    134   envelope.SerializeToString(encoded_message);
    135 }
    136 
    137 bool PushClientChannel::DecodeMessage(const std::string& data,
    138                                       std::string* message,
    139                                       std::string* service_context,
    140                                       int64* scheduling_hash) {
    141   ipc::invalidation::ClientGatewayMessage envelope;
    142   if (!envelope.ParseFromString(data)) {
    143     return false;
    144   }
    145   *message = envelope.network_message();
    146   if (envelope.has_service_context()) {
    147     *service_context = envelope.service_context();
    148   }
    149   if (envelope.has_rpc_scheduling_hash()) {
    150     *scheduling_hash = envelope.rpc_scheduling_hash();
    151   }
    152   return true;
    153 }
    154 
    155 scoped_ptr<base::DictionaryValue> PushClientChannel::CollectDebugData() const {
    156   scoped_ptr<base::DictionaryValue> status(new base::DictionaryValue);
    157   status->SetString("PushClientChannel.NetworkChannel", "Push Client");
    158   status->SetInteger("PushClientChannel.SentMessages", sent_messages_count_);
    159   status->SetInteger("PushClientChannel.ReceivedMessages",
    160                      SyncNetworkChannel::GetReceivedMessagesCount());
    161   return status.Pass();
    162 }
    163 
    164 }  // namespace syncer
    165