push_client_channel.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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
11namespace syncer {
12
13namespace {
14
15const char kBotJid[] = "tango@bot.talk.google.com";
16const char kChannelName[] = "tango_raw";
17
18}  // namespace
19
20PushClientChannel::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
34PushClientChannel::~PushClientChannel() {
35  push_client_->RemoveObserver(this);
36  STLDeleteElements(&network_status_receivers_);
37}
38
39void PushClientChannel::UpdateCredentials(
40    const std::string& email, const std::string& token) {
41  push_client_->UpdateCredentials(email, token);
42}
43
44void PushClientChannel::SendMessage(const std::string& outgoing_message) {
45  push_client_->SendNotification(
46      EncodeMessage(outgoing_message, service_context_, scheduling_hash_));
47}
48
49void PushClientChannel::SetMessageReceiver(
50    invalidation::MessageCallback* incoming_receiver) {
51  incoming_receiver_.reset(incoming_receiver);
52}
53
54void 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
60void PushClientChannel::SetSystemResources(
61    invalidation::SystemResources* resources) {
62  // Do nothing.
63}
64
65void 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
73void 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
82void PushClientChannel::OnIncomingNotification(
83    const notifier::Notification& notification) {
84  if (!incoming_receiver_.get()) {
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
97const std::string& PushClientChannel::GetServiceContextForTest() const {
98  return service_context_;
99}
100
101int64 PushClientChannel::GetSchedulingHashForTest() const {
102  return scheduling_hash_;
103}
104
105notifier::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
111bool 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
120notifier::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
140bool 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