Home | History | Annotate | Download | only in notifier
      1 // Copyright (c) 2012 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 "sync/notifier/push_client_channel.h"
      6 
      7 #include "base/stl_util.h"
      8 #include "google/cacheinvalidation/client_gateway.pb.h"
      9 #include "jingle/notifier/listener/push_client.h"
     10 
     11 namespace syncer {
     12 
     13 namespace {
     14 
     15 const char kBotJid[] = "tango (at) bot.talk.google.com";
     16 const char kChannelName[] = "tango_raw";
     17 
     18 }  // namespace
     19 
     20 PushClientChannel::PushClientChannel(
     21     scoped_ptr<notifier::PushClient> push_client)
     22     : push_client_(push_client.Pass()),
     23       notifications_enabled_(false),
     24       scheduling_hash_(0) {
     25   push_client_->AddObserver(this);
     26   notifier::Subscription subscription;
     27   subscription.channel = kChannelName;
     28   subscription.from = "";
     29   notifier::SubscriptionList subscriptions;
     30   subscriptions.push_back(subscription);
     31   push_client_->UpdateSubscriptions(subscriptions);
     32 }
     33 
     34 PushClientChannel::~PushClientChannel() {
     35   push_client_->RemoveObserver(this);
     36   STLDeleteElements(&network_status_receivers_);
     37 }
     38 
     39 void PushClientChannel::UpdateCredentials(
     40     const std::string& email, const std::string& token) {
     41   push_client_->UpdateCredentials(email, token);
     42 }
     43 
     44 void PushClientChannel::SendMessage(const std::string& outgoing_message) {
     45   push_client_->SendNotification(
     46       EncodeMessage(outgoing_message, service_context_, scheduling_hash_));
     47 }
     48 
     49 void PushClientChannel::SetMessageReceiver(
     50     invalidation::MessageCallback* incoming_receiver) {
     51   incoming_receiver_.reset(incoming_receiver);
     52 }
     53 
     54 void PushClientChannel::AddNetworkStatusReceiver(
     55     invalidation::NetworkStatusCallback* network_status_receiver) {
     56   network_status_receiver->Run(notifications_enabled_);
     57   network_status_receivers_.push_back(network_status_receiver);
     58 }
     59 
     60 void PushClientChannel::SetSystemResources(
     61     invalidation::SystemResources* resources) {
     62   // Do nothing.
     63 }
     64 
     65 void PushClientChannel::OnNotificationsEnabled() {
     66   for (NetworkStatusReceiverList::const_iterator it =
     67            network_status_receivers_.begin();
     68        it != network_status_receivers_.end(); ++it) {
     69     (*it)->Run(true);
     70   }
     71 }
     72 
     73 void PushClientChannel::OnNotificationsDisabled(
     74     notifier::NotificationsDisabledReason reason) {
     75   for (NetworkStatusReceiverList::const_iterator it =
     76            network_status_receivers_.begin();
     77        it != network_status_receivers_.end(); ++it) {
     78     (*it)->Run(false);
     79   }
     80 }
     81 
     82 void PushClientChannel::OnIncomingNotification(
     83     const notifier::Notification& notification) {
     84   if (!incoming_receiver_) {
     85     DLOG(ERROR) << "No receiver for incoming notification";
     86     return;
     87   }
     88   std::string message;
     89   if (!DecodeMessage(notification,
     90                      &message, &service_context_, &scheduling_hash_)) {
     91     DLOG(ERROR) << "Could not parse ClientGatewayMessage from: "
     92                 << notification.ToString();
     93   }
     94   incoming_receiver_->Run(message);
     95 }
     96 
     97 const std::string& PushClientChannel::GetServiceContextForTest() const {
     98   return service_context_;
     99 }
    100 
    101 int64 PushClientChannel::GetSchedulingHashForTest() const {
    102   return scheduling_hash_;
    103 }
    104 
    105 notifier::Notification PushClientChannel::EncodeMessageForTest(
    106     const std::string& message, const std::string& service_context,
    107     int64 scheduling_hash) {
    108   return EncodeMessage(message, service_context, scheduling_hash);
    109 }
    110 
    111 bool PushClientChannel::DecodeMessageForTest(
    112     const notifier::Notification& notification,
    113     std::string* message,
    114     std::string* service_context,
    115     int64* scheduling_hash) {
    116   return DecodeMessage(
    117       notification, message, service_context, scheduling_hash);
    118 }
    119 
    120 notifier::Notification PushClientChannel::EncodeMessage(
    121     const std::string& message, const std::string& service_context,
    122     int64 scheduling_hash) {
    123   ipc::invalidation::ClientGatewayMessage envelope;
    124   envelope.set_is_client_to_server(true);
    125   if (!service_context.empty()) {
    126     envelope.set_service_context(service_context);
    127     envelope.set_rpc_scheduling_hash(scheduling_hash);
    128   }
    129   envelope.set_network_message(message);
    130 
    131   notifier::Recipient recipient;
    132   recipient.to = kBotJid;
    133   notifier::Notification notification;
    134   notification.channel = kChannelName;
    135   notification.recipients.push_back(recipient);
    136   envelope.SerializeToString(&notification.data);
    137   return notification;
    138 }
    139 
    140 bool PushClientChannel::DecodeMessage(
    141     const notifier::Notification& notification,
    142     std::string* message,
    143     std::string* service_context,
    144     int64* scheduling_hash) {
    145   ipc::invalidation::ClientGatewayMessage envelope;
    146   if (!envelope.ParseFromString(notification.data)) {
    147     return false;
    148   }
    149   *message = envelope.network_message();
    150   if (envelope.has_service_context()) {
    151     *service_context = envelope.service_context();
    152   }
    153   if (envelope.has_rpc_scheduling_hash()) {
    154     *scheduling_hash = envelope.rpc_scheduling_hash();
    155   }
    156   return true;
    157 }
    158 
    159 }  // namespace syncer
    160