diff options
author | gene@chromium.org <gene@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 19:59:41 +0000 |
---|---|---|
committer | gene@chromium.org <gene@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 19:59:41 +0000 |
commit | 05861d65af900b604d9e99e4eebb61deb45de1cd (patch) | |
tree | 172427792ac96feea1189b762287b0af74b7cea9 /jingle | |
parent | fc992beca7a034a8e6437faf73377d375ac2e44a (diff) | |
download | chromium_src-05861d65af900b604d9e99e4eebb61deb45de1cd.zip chromium_src-05861d65af900b604d9e99e4eebb61deb45de1cd.tar.gz chromium_src-05861d65af900b604d9e99e4eebb61deb45de1cd.tar.bz2 |
Adding XMPP ping functionality to CloudPrint. XMPP ping and timeout is controlled thorugh Service State file.
BUG=157735
Review URL: https://chromiumcodereview.appspot.com/11232048
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164385 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'jingle')
18 files changed, 281 insertions, 7 deletions
diff --git a/jingle/jingle.gyp b/jingle/jingle.gyp index b1270b6..95a99ae 100644 --- a/jingle/jingle.gyp +++ b/jingle/jingle.gyp @@ -95,6 +95,8 @@ 'notifier/listener/push_notifications_send_update_task.h', 'notifier/listener/push_notifications_subscribe_task.cc', 'notifier/listener/push_notifications_subscribe_task.h', + 'notifier/listener/send_ping_task.cc', + 'notifier/listener/send_ping_task.h', 'notifier/listener/xml_element_util.cc', 'notifier/listener/xml_element_util.h', 'notifier/listener/xmpp_push_client.cc', @@ -179,6 +181,7 @@ 'notifier/listener/push_client_unittest.cc', 'notifier/listener/push_notifications_send_update_task_unittest.cc', 'notifier/listener/push_notifications_subscribe_task_unittest.cc', + 'notifier/listener/send_ping_task_unittest.cc', 'notifier/listener/xml_element_util_unittest.cc', 'notifier/listener/xmpp_push_client_unittest.cc', 'run_all_unittests.cc', diff --git a/jingle/notifier/listener/fake_push_client.cc b/jingle/notifier/listener/fake_push_client.cc index 0565c3c..1106c93 100644 --- a/jingle/notifier/listener/fake_push_client.cc +++ b/jingle/notifier/listener/fake_push_client.cc @@ -8,7 +8,7 @@ namespace notifier { -FakePushClient::FakePushClient() {} +FakePushClient::FakePushClient() : sent_pings_(0) {} FakePushClient::~FakePushClient() {} @@ -35,6 +35,10 @@ void FakePushClient::SendNotification(const Notification& notification) { sent_notifications_.push_back(notification); } +void FakePushClient::SendPing() { + sent_pings_++; +} + void FakePushClient::EnableNotifications() { FOR_EACH_OBSERVER(PushClientObserver, observers_, OnNotificationsEnabled()); @@ -68,5 +72,9 @@ const std::vector<Notification>& FakePushClient::sent_notifications() const { return sent_notifications_; } +int FakePushClient::sent_pings() const { + return sent_pings_; +} + } // namespace notifier diff --git a/jingle/notifier/listener/fake_push_client.h b/jingle/notifier/listener/fake_push_client.h index 90e086c..2c1340d 100644 --- a/jingle/notifier/listener/fake_push_client.h +++ b/jingle/notifier/listener/fake_push_client.h @@ -29,6 +29,7 @@ class FakePushClient : public PushClient { virtual void UpdateCredentials( const std::string& email, const std::string& token) OVERRIDE; virtual void SendNotification(const Notification& notification) OVERRIDE; + virtual void SendPing() OVERRIDE; // Triggers OnNotificationsEnabled on all observers. void EnableNotifications(); @@ -43,6 +44,7 @@ class FakePushClient : public PushClient { const std::string& email() const; const std::string& token() const; const std::vector<Notification>& sent_notifications() const; + int sent_pings() const; private: ObserverList<PushClientObserver> observers_; @@ -50,6 +52,7 @@ class FakePushClient : public PushClient { std::string email_; std::string token_; std::vector<Notification> sent_notifications_; + int sent_pings_; DISALLOW_COPY_AND_ASSIGN(FakePushClient); }; diff --git a/jingle/notifier/listener/non_blocking_push_client.cc b/jingle/notifier/listener/non_blocking_push_client.cc index 5765d37..c42561e 100644 --- a/jingle/notifier/listener/non_blocking_push_client.cc +++ b/jingle/notifier/listener/non_blocking_push_client.cc @@ -38,12 +38,14 @@ class NonBlockingPushClient::Core void UpdateSubscriptions(const SubscriptionList& subscriptions); void UpdateCredentials(const std::string& email, const std::string& token); void SendNotification(const Notification& data); + void SendPing(); virtual void OnNotificationsEnabled() OVERRIDE; virtual void OnNotificationsDisabled( NotificationsDisabledReason reason) OVERRIDE; virtual void OnIncomingNotification( const Notification& notification) OVERRIDE; + virtual void OnPingResponse() OVERRIDE; private: friend class base::RefCountedThreadSafe<NonBlockingPushClient::Core>; @@ -110,6 +112,12 @@ void NonBlockingPushClient::Core::SendNotification( delegate_push_client_->SendNotification(notification); } +void NonBlockingPushClient::Core::SendPing() { + DCHECK(delegate_task_runner_->BelongsToCurrentThread()); + DCHECK(delegate_push_client_.get()); + delegate_push_client_->SendPing(); +} + void NonBlockingPushClient::Core::OnNotificationsEnabled() { DCHECK(delegate_task_runner_->BelongsToCurrentThread()); parent_task_runner_->PostTask( @@ -136,6 +144,14 @@ void NonBlockingPushClient::Core::OnIncomingNotification( parent_push_client_, notification)); } +void NonBlockingPushClient::Core::OnPingResponse() { + DCHECK(delegate_task_runner_->BelongsToCurrentThread()); + parent_task_runner_->PostTask( + FROM_HERE, + base::Bind(&NonBlockingPushClient::OnPingResponse, + parent_push_client_)); +} + NonBlockingPushClient::NonBlockingPushClient( const scoped_refptr<base::SingleThreadTaskRunner>& delegate_task_runner, const CreateBlockingPushClientCallback& @@ -195,6 +211,13 @@ void NonBlockingPushClient::SendNotification( notification)); } +void NonBlockingPushClient::SendPing() { + DCHECK(thread_checker_.CalledOnValidThread()); + delegate_task_runner_->PostTask( + FROM_HERE, + base::Bind(&NonBlockingPushClient::Core::SendPing, core_.get())); +} + void NonBlockingPushClient::OnNotificationsEnabled() { DCHECK(thread_checker_.CalledOnValidThread()); FOR_EACH_OBSERVER(PushClientObserver, observers_, @@ -215,4 +238,9 @@ void NonBlockingPushClient::OnIncomingNotification( OnIncomingNotification(notification)); } +void NonBlockingPushClient::OnPingResponse() { + DCHECK(thread_checker_.CalledOnValidThread()); + FOR_EACH_OBSERVER(PushClientObserver, observers_, OnPingResponse()); +} + } // namespace notifier diff --git a/jingle/notifier/listener/non_blocking_push_client.h b/jingle/notifier/listener/non_blocking_push_client.h index 434f5f4..f5c6bc4 100644 --- a/jingle/notifier/listener/non_blocking_push_client.h +++ b/jingle/notifier/listener/non_blocking_push_client.h @@ -49,6 +49,7 @@ class NonBlockingPushClient : public PushClient { virtual void UpdateCredentials( const std::string& email, const std::string& token) OVERRIDE; virtual void SendNotification(const Notification& notification) OVERRIDE; + virtual void SendPing() OVERRIDE; private: class Core; @@ -56,6 +57,7 @@ class NonBlockingPushClient : public PushClient { void OnNotificationsEnabled(); void OnNotificationsDisabled(NotificationsDisabledReason reason); void OnIncomingNotification(const Notification& notification); + void OnPingResponse(); base::ThreadChecker thread_checker_; base::WeakPtrFactory<NonBlockingPushClient> weak_ptr_factory_; diff --git a/jingle/notifier/listener/non_blocking_push_client_unittest.cc b/jingle/notifier/listener/non_blocking_push_client_unittest.cc index f9e0282..8908910 100644 --- a/jingle/notifier/listener/non_blocking_push_client_unittest.cc +++ b/jingle/notifier/listener/non_blocking_push_client_unittest.cc @@ -112,6 +112,14 @@ TEST_F(NonBlockingPushClientTest, SendNotification) { fake_push_client_->sent_notifications()[0].Equals(notification)); } +// Make sure SendPing() gets delegated properly. +TEST_F(NonBlockingPushClientTest, SendPing) { + push_client_->SendPing(); + EXPECT_EQ(0, fake_push_client_->sent_pings()); + message_loop_.RunAllPending(); + ASSERT_EQ(1, fake_push_client_->sent_pings()); +} + // Make sure notification state changes get propagated back to the // parent. TEST_F(NonBlockingPushClientTest, NotificationStateChange) { diff --git a/jingle/notifier/listener/push_client.h b/jingle/notifier/listener/push_client.h index f80f422..fd67337 100644 --- a/jingle/notifier/listener/push_client.h +++ b/jingle/notifier/listener/push_client.h @@ -50,6 +50,9 @@ class PushClient { // Sends a notification (with no reliability guarantees). virtual void SendNotification(const Notification& notification) = 0; + + // Sends a ping (with no reliability guarantees). + virtual void SendPing() = 0; }; } // namespace notifier diff --git a/jingle/notifier/listener/push_client_observer.cc b/jingle/notifier/listener/push_client_observer.cc index 04a877b..a958eea 100644 --- a/jingle/notifier/listener/push_client_observer.cc +++ b/jingle/notifier/listener/push_client_observer.cc @@ -8,4 +8,6 @@ namespace notifier { PushClientObserver::~PushClientObserver() {} +void PushClientObserver::OnPingResponse() {} + } // namespace notifier diff --git a/jingle/notifier/listener/push_client_observer.h b/jingle/notifier/listener/push_client_observer.h index d51deb2..d153ff0 100644 --- a/jingle/notifier/listener/push_client_observer.h +++ b/jingle/notifier/listener/push_client_observer.h @@ -39,6 +39,10 @@ class PushClientObserver { // Called when a notification is received. The details of the // notification are in |notification|. virtual void OnIncomingNotification(const Notification& notification) = 0; + + // Called when a ping response is received. Default implementation does + // nothing. + virtual void OnPingResponse(); }; } // namespace notifier diff --git a/jingle/notifier/listener/push_notifications_listen_task.cc b/jingle/notifier/listener/push_notifications_listen_task.cc index ad1da9f..2e6b2ca 100644 --- a/jingle/notifier/listener/push_notifications_listen_task.cc +++ b/jingle/notifier/listener/push_notifications_listen_task.cc @@ -18,6 +18,9 @@ namespace notifier { +PushNotificationsListenTask::Delegate::~Delegate() { +} + PushNotificationsListenTask::PushNotificationsListenTask( buzz::XmppTaskParentInterface* parent, Delegate* delegate) : buzz::XmppTask(parent, buzz::XmppEngine::HL_TYPE), diff --git a/jingle/notifier/listener/push_notifications_listen_task.h b/jingle/notifier/listener/push_notifications_listen_task.h index daf48d9..62d408b 100644 --- a/jingle/notifier/listener/push_notifications_listen_task.h +++ b/jingle/notifier/listener/push_notifications_listen_task.h @@ -31,7 +31,7 @@ class PushNotificationsListenTask : public buzz::XmppTask { virtual void OnNotificationReceived(const Notification& notification) = 0; protected: - virtual ~Delegate() {} + virtual ~Delegate(); }; PushNotificationsListenTask(buzz::XmppTaskParentInterface* parent, diff --git a/jingle/notifier/listener/push_notifications_send_update_task.cc b/jingle/notifier/listener/push_notifications_send_update_task.cc index 50ec15e..4e0c127 100644 --- a/jingle/notifier/listener/push_notifications_send_update_task.cc +++ b/jingle/notifier/listener/push_notifications_send_update_task.cc @@ -32,7 +32,7 @@ int PushNotificationsSendUpdateTask::ProcessStart() { DVLOG(1) << "Sending notification " << notification_.ToString() << " as stanza " << XmlElementToString(*stanza); if (SendStanza(stanza.get()) != buzz::XMPP_RETURN_OK) { - LOG(WARNING) << "Could not send stanza " << XmlElementToString(*stanza); + DLOG(WARNING) << "Could not send stanza " << XmlElementToString(*stanza); } return STATE_DONE; } @@ -72,8 +72,8 @@ buzz::XmlElement* PushNotificationsSendUpdateTask::MakeUpdateMessage( if (!recipient.user_specific_data.empty()) { std::string base64_data; if (!base::Base64Encode(recipient.user_specific_data, &base64_data)) { - LOG(WARNING) << "Could not encode data " - << recipient.user_specific_data; + DLOG(WARNING) << "Could not encode data " + << recipient.user_specific_data; } else { recipient_element->SetBodyText(base64_data); } @@ -83,7 +83,7 @@ buzz::XmlElement* PushNotificationsSendUpdateTask::MakeUpdateMessage( buzz::XmlElement* data = new buzz::XmlElement(kQnData, true); std::string base64_data; if (!base::Base64Encode(notification.data, &base64_data)) { - LOG(WARNING) << "Could not encode data " << notification.data; + DLOG(WARNING) << "Could not encode data " << notification.data; } data->SetBodyText(base64_data); push->AddElement(data); diff --git a/jingle/notifier/listener/send_ping_task.cc b/jingle/notifier/listener/send_ping_task.cc new file mode 100644 index 0000000..90b7196 --- /dev/null +++ b/jingle/notifier/listener/send_ping_task.cc @@ -0,0 +1,80 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "jingle/notifier/listener/send_ping_task.h" + +#include <string> + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "jingle/notifier/listener/xml_element_util.h" +#include "talk/xmllite/qname.h" +#include "talk/xmllite/xmlelement.h" +#include "talk/xmpp/constants.h" +#include "talk/xmpp/jid.h" +#include "talk/xmpp/xmppclient.h" + +namespace notifier { + +SendPingTask::Delegate::~Delegate() { +} + +SendPingTask::SendPingTask(buzz::XmppTaskParentInterface* parent, + Delegate* delegate) + : XmppTask(parent, buzz::XmppEngine::HL_SINGLE), delegate_(delegate) { +} + +SendPingTask::~SendPingTask() { +} + +int SendPingTask::ProcessStart() { + ping_task_id_ = task_id(); + scoped_ptr<buzz::XmlElement> stanza(MakePingStanza(ping_task_id_)); + DVLOG(1) << "Sending ping stanza " << XmlElementToString(*stanza); + if (SendStanza(stanza.get()) != buzz::XMPP_RETURN_OK) { + DLOG(WARNING) << "Could not send stanza " << XmlElementToString(*stanza); + return STATE_ERROR; + } + return STATE_RESPONSE; +} + +int SendPingTask::ProcessResponse() { + const buzz::XmlElement* stanza = NextStanza(); + if (stanza == NULL) { + return STATE_BLOCKED; + } + + DVLOG(1) << "Received stanza " << XmlElementToString(*stanza); + + std::string type = stanza->Attr(buzz::QN_TYPE); + if (type != buzz::STR_RESULT) { + DLOG(WARNING) << "No type=\"result\" attribute found in stanza " + << XmlElementToString(*stanza); + return STATE_ERROR; + } + + delegate_->OnPingResponseReceived(); + return STATE_DONE; +} + +bool SendPingTask::HandleStanza(const buzz::XmlElement* stanza) { + // MatchResponseIq() matches the given Jid with the "from" field of the given + // stanza, which in this case should be the empty string + // (signifying the server). + if (MatchResponseIq(stanza, buzz::Jid(buzz::STR_EMPTY), ping_task_id_)) { + QueueStanza(stanza); + return true; + } + return false; +} + +buzz::XmlElement* SendPingTask::MakePingStanza(const std::string& task_id) { + buzz::XmlElement* stanza = MakeIq(buzz::STR_GET, + buzz::Jid(buzz::STR_EMPTY), + task_id); + stanza->AddElement(new buzz::XmlElement(buzz::QN_PING)); + return stanza; +} + +} // namespace notifier diff --git a/jingle/notifier/listener/send_ping_task.h b/jingle/notifier/listener/send_ping_task.h new file mode 100644 index 0000000..9cd8b22 --- /dev/null +++ b/jingle/notifier/listener/send_ping_task.h @@ -0,0 +1,54 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Methods for sending the update stanza to notify peers via xmpp. + +#ifndef JINGLE_NOTIFIER_LISTENER_SEND_PING_TASK_H_ +#define JINGLE_NOTIFIER_LISTENER_SEND_PING_TASK_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" +#include "talk/xmpp/xmpptask.h" + +namespace buzz { +class XmlElement; +} // namespace + +namespace notifier { + +class SendPingTask : public buzz::XmppTask { + public: + class Delegate { + public: + virtual void OnPingResponseReceived() = 0; + + protected: + virtual ~Delegate(); + }; + + SendPingTask(buzz::XmppTaskParentInterface* parent, Delegate* delegate); + virtual ~SendPingTask(); + + // Overridden from buzz::XmppTask. + virtual int ProcessStart() OVERRIDE; + virtual int ProcessResponse() OVERRIDE; + virtual bool HandleStanza(const buzz::XmlElement* stanza) OVERRIDE; + + private: + static buzz::XmlElement* MakePingStanza(const std::string& task_id); + + FRIEND_TEST_ALL_PREFIXES(SendPingTaskTest, MakePingStanza); + + std::string ping_task_id_; + Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(SendPingTask); +}; + +typedef SendPingTask::Delegate SendPingTaskDelegate; + +} // namespace notifier + +#endif // JINGLE_NOTIFIER_LISTENER_SEND_PING_TASK_H_ diff --git a/jingle/notifier/listener/send_ping_task_unittest.cc b/jingle/notifier/listener/send_ping_task_unittest.cc new file mode 100644 index 0000000..1a2dd4b --- /dev/null +++ b/jingle/notifier/listener/send_ping_task_unittest.cc @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "jingle/notifier/listener/send_ping_task.h" + +#include "base/base64.h" +#include "base/memory/scoped_ptr.h" +#include "jingle/notifier/listener/xml_element_util.h" +#include "talk/xmpp/jid.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace buzz { +class XmlElement; +} + +namespace notifier { + +class SendPingTaskTest : public testing::Test { + public: + SendPingTaskTest() {} + + private: + DISALLOW_COPY_AND_ASSIGN(SendPingTaskTest); +}; + +TEST_F(SendPingTaskTest, MakePingStanza) { + std::string task_id = "42"; + + scoped_ptr<buzz::XmlElement> message(SendPingTask::MakePingStanza(task_id)); + + std::string expected_xml_string("<cli:iq type=\"get\" id=\""); + expected_xml_string += task_id; + expected_xml_string += + "\" xmlns:cli=\"jabber:client\">" + "<ping:ping xmlns:ping=\"urn:xmpp:ping\"/></cli:iq>"; + + EXPECT_EQ(expected_xml_string, XmlElementToString(*message)); +} + +} // namespace notifier diff --git a/jingle/notifier/listener/xmpp_push_client.cc b/jingle/notifier/listener/xmpp_push_client.cc index 9b4811e..76ee4ee 100644 --- a/jingle/notifier/listener/xmpp_push_client.cc +++ b/jingle/notifier/listener/xmpp_push_client.cc @@ -8,6 +8,7 @@ #include "base/message_loop_proxy.h" #include "jingle/notifier/base/notifier_options_util.h" #include "jingle/notifier/listener/push_client_observer.h" +#include "jingle/notifier/listener/send_ping_task.h" #include "jingle/notifier/listener/push_notifications_send_update_task.h" namespace notifier { @@ -80,6 +81,11 @@ void XmppPushClient::OnNotificationReceived( OnIncomingNotification(notification)); } +void XmppPushClient::OnPingResponseReceived() { + DCHECK(thread_checker_.CalledOnValidThread()); + FOR_EACH_OBSERVER(PushClientObserver, observers_, OnPingResponse()); +} + void XmppPushClient::OnSubscribed() { DCHECK(thread_checker_.CalledOnValidThread()); FOR_EACH_OBSERVER(PushClientObserver, observers_, @@ -143,4 +149,15 @@ void XmppPushClient::SendNotification(const Notification& notification) { task->Start(); } +void XmppPushClient::SendPing() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!base_task_.get()) { + DVLOG(1) << "Push: Cannot send ping"; + return; + } + // Owned by |base_task_|. + SendPingTask* task = new SendPingTask(base_task_, this); + task->Start(); +} + } // namespace notifier diff --git a/jingle/notifier/listener/xmpp_push_client.h b/jingle/notifier/listener/xmpp_push_client.h index 64725d8..08a1811 100644 --- a/jingle/notifier/listener/xmpp_push_client.h +++ b/jingle/notifier/listener/xmpp_push_client.h @@ -21,6 +21,7 @@ #include "jingle/notifier/listener/push_client.h" #include "jingle/notifier/listener/push_notifications_listen_task.h" #include "jingle/notifier/listener/push_notifications_subscribe_task.h" +#include "jingle/notifier/listener/send_ping_task.h" #include "talk/xmpp/xmppclientsettings.h" namespace buzz { @@ -36,7 +37,8 @@ class XmppPushClient : public PushClient, public Login::Delegate, public PushNotificationsListenTaskDelegate, - public PushNotificationsSubscribeTaskDelegate { + public PushNotificationsSubscribeTaskDelegate, + public SendPingTaskDelegate { public: explicit XmppPushClient(const NotifierOptions& notifier_options); virtual ~XmppPushClient(); @@ -49,6 +51,7 @@ class XmppPushClient : virtual void UpdateCredentials( const std::string& email, const std::string& token) OVERRIDE; virtual void SendNotification(const Notification& notification) OVERRIDE; + virtual void SendPing() OVERRIDE; // Login::Delegate implementation. virtual void OnConnect( @@ -64,6 +67,9 @@ class XmppPushClient : virtual void OnSubscribed() OVERRIDE; virtual void OnSubscriptionError() OVERRIDE; + // SendPingTaskDelegate implementation. + virtual void OnPingResponseReceived() OVERRIDE; + private: base::ThreadChecker thread_checker_; const NotifierOptions notifier_options_; diff --git a/jingle/notifier/listener/xmpp_push_client_unittest.cc b/jingle/notifier/listener/xmpp_push_client_unittest.cc index 3487479..3beb488 100644 --- a/jingle/notifier/listener/xmpp_push_client_unittest.cc +++ b/jingle/notifier/listener/xmpp_push_client_unittest.cc @@ -27,6 +27,7 @@ class MockObserver : public PushClientObserver { MOCK_METHOD0(OnNotificationsEnabled, void()); MOCK_METHOD1(OnNotificationsDisabled, void(NotificationsDisabledReason)); MOCK_METHOD1(OnIncomingNotification, void(const Notification&)); + MOCK_METHOD0(OnPingResponse, void()); }; class XmppPushClientTest : public testing::Test { @@ -110,6 +111,17 @@ TEST_F(XmppPushClientTest, SendNotification) { xmpp_push_client_->SendNotification(Notification()); } +// Make sure nothing blows up when the XMPP push client sends a ping. +// +// TODO(akalin): Figure out how to test that the ping was actually sent. +TEST_F(XmppPushClientTest, SendPing) { + EXPECT_CALL(mock_observer_, OnNotificationsEnabled()); + + xmpp_push_client_->OnConnect(fake_base_task_.AsWeakPtr()); + xmpp_push_client_->OnSubscribed(); + xmpp_push_client_->SendPing(); +} + // Make sure nothing blows up when the XMPP push client sends a // notification when disconnected, and the client connects. // |