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