push_client_channel.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/notifier/push_client_channel.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google/cacheinvalidation/client_gateway.pb.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/listener/push_client.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace syncer {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kBotJid[] = "tango@bot.talk.google.com";
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kChannelName[] = "tango_raw";
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushClientChannel::PushClientChannel(
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<notifier::PushClient> push_client)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : push_client_(push_client.Pass()),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notifications_enabled_(false),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scheduling_hash_(0) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->AddObserver(this);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier::Subscription subscription;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subscription.channel = kChannelName;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subscription.from = "";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier::SubscriptionList subscriptions;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subscriptions.push_back(subscription);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->UpdateSubscriptions(subscriptions);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PushClientChannel::~PushClientChannel() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->RemoveObserver(this);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&network_status_receivers_);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::UpdateCredentials(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& email, const std::string& token) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->UpdateCredentials(email, token);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::SendMessage(const std::string& outgoing_message) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->SendNotification(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EncodeMessage(outgoing_message, service_context_, scheduling_hash_));
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::SetMessageReceiver(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::MessageCallback* incoming_receiver) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incoming_receiver_.reset(incoming_receiver);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::AddNetworkStatusReceiver(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::NetworkStatusCallback* network_status_receiver) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_status_receiver->Run(notifications_enabled_);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  network_status_receivers_.push_back(network_status_receiver);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::SetSystemResources(
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    invalidation::SystemResources* resources) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::OnNotificationsEnabled() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (NetworkStatusReceiverList::const_iterator it =
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           network_status_receivers_.begin();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != network_status_receivers_.end(); ++it) {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->Run(true);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::OnNotificationsDisabled(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notifier::NotificationsDisabledReason reason) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (NetworkStatusReceiverList::const_iterator it =
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           network_status_receivers_.begin();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != network_status_receivers_.end(); ++it) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)->Run(false);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PushClientChannel::OnIncomingNotification(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const notifier::Notification& notification) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!incoming_receiver_.get()) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "No receiver for incoming notification";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string message;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!DecodeMessage(notification,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     &message, &service_context_, &scheduling_hash_)) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "Could not parse ClientGatewayMessage from: "
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << notification.ToString();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  incoming_receiver_->Run(message);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& PushClientChannel::GetServiceContextForTest() const {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return service_context_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 PushClientChannel::GetSchedulingHashForTest() const {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return scheduling_hash_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)notifier::Notification PushClientChannel::EncodeMessageForTest(
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& message, const std::string& service_context,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 scheduling_hash) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return EncodeMessage(message, service_context, scheduling_hash);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PushClientChannel::DecodeMessageForTest(
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const notifier::Notification& notification,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* message,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* service_context,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64* scheduling_hash) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DecodeMessage(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notification, message, service_context, scheduling_hash);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)notifier::Notification PushClientChannel::EncodeMessage(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& message, const std::string& service_context,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 scheduling_hash) {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipc::invalidation::ClientGatewayMessage envelope;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  envelope.set_is_client_to_server(true);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service_context.empty()) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    envelope.set_service_context(service_context);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    envelope.set_rpc_scheduling_hash(scheduling_hash);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  envelope.set_network_message(message);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier::Recipient recipient;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recipient.to = kBotJid;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier::Notification notification;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification.channel = kChannelName;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification.recipients.push_back(recipient);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  envelope.SerializeToString(&notification.data);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return notification;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool PushClientChannel::DecodeMessage(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const notifier::Notification& notification,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* message,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* service_context,
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64* scheduling_hash) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipc::invalidation::ClientGatewayMessage envelope;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!envelope.ParseFromString(notification.data)) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *message = envelope.network_message();
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (envelope.has_service_context()) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *service_context = envelope.service_context();
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (envelope.has_rpc_scheduling_hash()) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *scheduling_hash = envelope.rpc_scheduling_hash();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace syncer
160