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(¬ification.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