summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-25 03:50:19 +0000
committersanjeevr@chromium.org <sanjeevr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-25 03:50:19 +0000
commit015c203627350a3291fe471780a83ac53721f93b (patch)
treeaeb625014d6c1a55d975814b7abcf359d0d5fd74
parent176a07d221a18815b7afdb08cf38cf03bdc0b21f (diff)
downloadchromium_src-015c203627350a3291fe471780a83ac53721f93b.zip
chromium_src-015c203627350a3291fe471780a83ac53721f93b.tar.gz
chromium_src-015c203627350a3291fe471780a83ac53721f93b.tar.bz2
Added support for the new Google push notifications.
BUG=None TEST=Unit-tests, Cloud print proxy. Review URL: http://codereview.chromium.org/3493008 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60565 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--jingle/jingle.gyp7
-rw-r--r--jingle/notifier/listener/mediator_thread_impl.h17
-rw-r--r--jingle/notifier/listener/notification_constants.cc1
-rw-r--r--jingle/notifier/listener/notification_constants.h1
-rw-r--r--jingle/notifier/listener/push_notifications_listen_task.cc100
-rw-r--r--jingle/notifier/listener/push_notifications_listen_task.h57
-rw-r--r--jingle/notifier/listener/push_notifications_subscribe_task.cc111
-rw-r--r--jingle/notifier/listener/push_notifications_subscribe_task.h64
-rw-r--r--jingle/notifier/listener/push_notifications_subscribe_task_unittest.cc63
-rw-r--r--jingle/notifier/listener/push_notifications_thread.cc86
-rw-r--r--jingle/notifier/listener/push_notifications_thread.h63
11 files changed, 562 insertions, 8 deletions
diff --git a/jingle/jingle.gyp b/jingle/jingle.gyp
index b3c867e..01844b3 100644
--- a/jingle/jingle.gyp
+++ b/jingle/jingle.gyp
@@ -54,6 +54,12 @@
'notifier/listener/notification_constants.cc',
'notifier/listener/notification_constants.h',
'notifier/listener/notification_defines.h',
+ 'notifier/listener/push_notifications_listen_task.cc',
+ 'notifier/listener/push_notifications_listen_task.h',
+ 'notifier/listener/push_notifications_subscribe_task.cc',
+ 'notifier/listener/push_notifications_subscribe_task.h',
+ 'notifier/listener/push_notifications_thread.cc',
+ 'notifier/listener/push_notifications_thread.h',
'notifier/listener/send_update_task.cc',
'notifier/listener/send_update_task.h',
'notifier/listener/subscribe_task.cc',
@@ -95,6 +101,7 @@
'notifier/base/fake_ssl_client_socket_unittest.cc',
'notifier/base/xmpp_connection_unittest.cc',
'notifier/base/weak_xmpp_client_unittest.cc',
+ 'notifier/listener/push_notifications_subscribe_task_unittest.cc',
'notifier/listener/talk_mediator_unittest.cc',
'notifier/listener/send_update_task_unittest.cc',
'notifier/listener/subscribe_task_unittest.cc',
diff --git a/jingle/notifier/listener/mediator_thread_impl.h b/jingle/notifier/listener/mediator_thread_impl.h
index f329ee5..76d296d 100644
--- a/jingle/notifier/listener/mediator_thread_impl.h
+++ b/jingle/notifier/listener/mediator_thread_impl.h
@@ -81,6 +81,15 @@ class MediatorThreadImpl
virtual void OnDisconnect();
+ // These handle messages indicating an event happened in the outside
+ // world. These are all called from the worker thread. They are protected
+ // so they can be used by subclasses.
+ void OnIncomingNotification(
+ const IncomingNotificationData& notification_data);
+ void OnOutgoingNotification(bool success);
+ void OnConnect(base::WeakPtr<talk_base::Task> parent);
+ void OnSubscriptionStateChange(bool success);
+
Delegate* delegate_;
MessageLoop* parent_message_loop_;
base::WeakPtr<talk_base::Task> base_task_;
@@ -94,14 +103,6 @@ class MediatorThreadImpl
void DoSendNotification(
const OutgoingNotificationData& data);
- // These handle messages indicating an event happened in the outside
- // world. These are all called from the worker thread.
- void OnIncomingNotification(
- const IncomingNotificationData& notification_data);
- void OnOutgoingNotification(bool success);
- void OnConnect(base::WeakPtr<talk_base::Task> parent);
- void OnSubscriptionStateChange(bool success);
-
// Equivalents of the above functions called from the parent thread.
void OnIncomingNotificationOnParentThread(
const IncomingNotificationData& notification_data);
diff --git a/jingle/notifier/listener/notification_constants.cc b/jingle/notifier/listener/notification_constants.cc
index 11e9157..33d402e 100644
--- a/jingle/notifier/listener/notification_constants.cc
+++ b/jingle/notifier/listener/notification_constants.cc
@@ -7,5 +7,6 @@
namespace notifier {
const char kNotifierNamespace[] = "google:notifier";
+const char kPushNotificationsNamespace[] = "google:push";
} // namespace notifier
diff --git a/jingle/notifier/listener/notification_constants.h b/jingle/notifier/listener/notification_constants.h
index 04d9921..43d386f 100644
--- a/jingle/notifier/listener/notification_constants.h
+++ b/jingle/notifier/listener/notification_constants.h
@@ -8,6 +8,7 @@
namespace notifier {
extern const char kNotifierNamespace[];
+extern const char kPushNotificationsNamespace[];
} // namespace notifier
diff --git a/jingle/notifier/listener/push_notifications_listen_task.cc b/jingle/notifier/listener/push_notifications_listen_task.cc
new file mode 100644
index 0000000..20dc448
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_listen_task.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 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/push_notifications_listen_task.h"
+
+#include "base/base64.h"
+#include "base/logging.h"
+#include "jingle/notifier/listener/notification_constants.h"
+#include "jingle/notifier/listener/notification_defines.h"
+#include "jingle/notifier/listener/xml_element_util.h"
+#include "talk/base/task.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/xmppclient.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/xmppengine.h"
+
+namespace notifier {
+
+PushNotificationsListenTask::PushNotificationsListenTask(
+ Task* parent, Delegate* delegate)
+ : buzz::XmppTask(parent, buzz::XmppEngine::HL_TYPE),
+ delegate_(delegate) {
+ DCHECK(delegate_);
+}
+
+PushNotificationsListenTask::~PushNotificationsListenTask() {
+}
+
+int PushNotificationsListenTask::ProcessStart() {
+ LOG(INFO) << "Push notifications: Listener task started.";
+ return STATE_RESPONSE;
+}
+
+int PushNotificationsListenTask::ProcessResponse() {
+ LOG(INFO) << "Push notifications: Listener response received.";
+ const buzz::XmlElement* stanza = NextStanza();
+ if (stanza == NULL) {
+ return STATE_BLOCKED;
+ }
+ // The push notifications service does not need us to acknowledge receipt of
+ // the notification to the buzz server.
+
+ // TODO(sanjeevr): Write unittests to cover this.
+ // Extract the service URL and service-specific data from the stanza.
+ // Note that we treat the channel name as service URL.
+ // The response stanza has the following format.
+ // <message from=’someservice.google.com’ to={full_jid}>
+ // <push xmlns=’google:push’ channel={channel name}>
+ // <recipient to={bare_jid}>{base-64 encoded data}</recipient>
+ // <data>{base-64 data}</data>
+ // </push>
+ // </message>
+
+ const buzz::XmlElement* push_element =
+ stanza->FirstNamed(buzz::QName(kPushNotificationsNamespace, "push"));
+ if (push_element) {
+ IncomingNotificationData notification_data;
+ notification_data.service_url =
+ push_element->Attr(buzz::QName(buzz::STR_EMPTY, "channel"));
+ const buzz::XmlElement* data_element = push_element->FirstNamed(
+ buzz::QName(kPushNotificationsNamespace, "data"));
+ if (data_element) {
+ base::Base64Decode(data_element->BodyText(),
+ &notification_data.service_specific_data);
+ }
+ delegate_->OnNotificationReceived(notification_data);
+ } else {
+ LOG(WARNING) <<
+ "Push notifications: No push element found in response stanza";
+ }
+ return STATE_RESPONSE;
+}
+
+bool PushNotificationsListenTask::HandleStanza(const buzz::XmlElement* stanza) {
+ LOG(INFO) << "Push notifications: Stanza received: "
+ << XmlElementToString(*stanza);
+ if (IsValidNotification(stanza)) {
+ QueueStanza(stanza);
+ return true;
+ }
+ return false;
+}
+
+bool PushNotificationsListenTask::IsValidNotification(
+ const buzz::XmlElement* stanza) {
+ // An update notification has the following form.
+ // <message from=’someservice.google.com’ to={full_jid}>
+ // <push xmlns=’google:push’ channel={channel name}>
+ // <recipient to={bare_jid}>{base-64 encoded data}</recipient>
+ // <data>{base-64 data}</data>
+ // </push>
+ // </message>
+ return ((stanza->Name() == buzz::QN_MESSAGE) &&
+ (stanza->Attr(buzz::QN_TO) == GetClient()->jid().Str()));
+}
+
+} // namespace notifier
+
diff --git a/jingle/notifier/listener/push_notifications_listen_task.h b/jingle/notifier/listener/push_notifications_listen_task.h
new file mode 100644
index 0000000..341ddf1
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_listen_task.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2010 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.
+//
+// This class listens for notifications from the Google Push notifications
+// service, and signals when they arrive. It checks all incoming stanzas to
+// see if they look like notifications, and filters out those which are not
+// valid.
+//
+// The task is deleted automatically by the buzz::XmppClient. This occurs in the
+// destructor of TaskRunner, which is a superclass of buzz::XmppClient.
+
+#ifndef JINGLE_NOTIFIER_PUSH_NOTIFICATIONS_LISTENER_LISTEN_TASK_H_
+#define JINGLE_NOTIFIER_PUSH_NOTIFICATIONS_LISTENER_LISTEN_TASK_H_
+
+#include "talk/xmpp/xmpptask.h"
+
+namespace buzz {
+class XmlElement;
+}
+
+struct IncomingNotificationData;
+
+namespace notifier {
+
+class PushNotificationsListenTask : public buzz::XmppTask {
+ public:
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+ virtual void OnNotificationReceived(
+ const IncomingNotificationData& notification) = 0;
+ };
+
+ explicit PushNotificationsListenTask(Task* parent, Delegate* delegate);
+ virtual ~PushNotificationsListenTask();
+
+ // Overriden from buzz::XmppTask.
+ virtual int ProcessStart();
+ virtual int ProcessResponse();
+ virtual bool HandleStanza(const buzz::XmlElement* stanza);
+
+ private:
+ bool IsValidNotification(const buzz::XmlElement* stanza);
+
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(PushNotificationsListenTask);
+};
+
+typedef PushNotificationsListenTask::Delegate
+ PushNotificationsListenTaskDelegate;
+
+} // namespace notifier
+
+#endif // JINGLE_NOTIFIER_PUSH_NOTIFICATIONS_LISTENER_LISTEN_TASK_H_
+
diff --git a/jingle/notifier/listener/push_notifications_subscribe_task.cc b/jingle/notifier/listener/push_notifications_subscribe_task.cc
new file mode 100644
index 0000000..3601b5e
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_subscribe_task.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2010 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/push_notifications_subscribe_task.h"
+
+#include <string>
+
+#include "base/logging.h"
+#include "jingle/notifier/listener/notification_constants.h"
+#include "jingle/notifier/listener/xml_element_util.h"
+#include "talk/base/task.h"
+#include "talk/xmllite/qname.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/xmppclient.h"
+#include "talk/xmpp/constants.h"
+#include "talk/xmpp/xmppengine.h"
+
+namespace notifier {
+
+PushNotificationsSubscribeTask::PushNotificationsSubscribeTask(
+ TaskParent* parent,
+ const std::vector<PushSubscriptionInfo>& channels_list,
+ Delegate* delegate)
+ : XmppTask(parent, buzz::XmppEngine::HL_SINGLE),
+ channels_list_(channels_list), delegate_(delegate) {
+}
+
+PushNotificationsSubscribeTask::~PushNotificationsSubscribeTask() {
+}
+
+bool PushNotificationsSubscribeTask::HandleStanza(
+ const buzz::XmlElement* stanza) {
+ if (!MatchResponseIq(stanza, GetClient()->jid().BareJid(), task_id()))
+ return false;
+ QueueStanza(stanza);
+ return true;
+}
+
+int PushNotificationsSubscribeTask::ProcessStart() {
+ LOG(INFO) << "Push notifications: Subscription task started.";
+ scoped_ptr<buzz::XmlElement> iq_stanza(
+ MakeSubscriptionMessage(channels_list_, GetClient()->jid(),
+ task_id()));
+ std::string stanza_str = XmlElementToString(*iq_stanza.get());
+ LOG(INFO) << "Push notifications: Subscription stanza: "
+ << XmlElementToString(*iq_stanza.get());
+
+ if (SendStanza(iq_stanza.get()) != buzz::XMPP_RETURN_OK) {
+ if (delegate_)
+ delegate_->OnSubscriptionError();
+ return STATE_ERROR;
+ }
+ return STATE_RESPONSE;
+}
+
+int PushNotificationsSubscribeTask::ProcessResponse() {
+ LOG(INFO) << "Push notifications: Subscription response received.";
+ const buzz::XmlElement* stanza = NextStanza();
+ if (stanza == NULL) {
+ return STATE_BLOCKED;
+ }
+ std::string stanza_str = XmlElementToString(*stanza);
+ LOG(INFO) << "Push notifications: Subscription response: " <<
+ XmlElementToString(*stanza);
+ // We've receieved a response to our subscription request.
+ if (stanza->HasAttr(buzz::QN_TYPE) &&
+ stanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT) {
+ if (delegate_)
+ delegate_->OnSubscribed();
+ return STATE_DONE;
+ }
+ // An error response was received.
+ if (delegate_)
+ delegate_->OnSubscriptionError();
+ return STATE_ERROR;
+}
+
+buzz::XmlElement* PushNotificationsSubscribeTask::MakeSubscriptionMessage(
+ const std::vector<PushSubscriptionInfo>& channels_list,
+ const buzz::Jid& jid, const std::string& task_id) {
+ DCHECK(jid.IsFull());
+ static const buzz::QName kQnSubscribe(
+ kPushNotificationsNamespace, "subscribe");
+
+ // Create the subscription stanza using the notifications protocol.
+ // <iq from={full_jid} to={bare_jid} type=’set’ id={id}>
+ // <subscribe xmlns=’google:push’>
+ // <item channel={channel_name} from={domain_name or bare_jid}/>
+ // <item channel={channel_name2} from={domain_name or bare_jid}/>
+ // <item channel={channel_name3} from={domain_name or bare_jid}/>
+ // </subscribe>
+ // </iq>
+ buzz::XmlElement* iq = MakeIq(buzz::STR_SET, jid.BareJid(), task_id);
+ buzz::XmlElement* subscribe = new buzz::XmlElement(kQnSubscribe, true);
+ iq->AddElement(subscribe);
+
+ for (std::vector<PushSubscriptionInfo>::const_iterator iter =
+ channels_list.begin(); iter != channels_list.end(); ++iter) {
+ buzz::XmlElement* item = new buzz::XmlElement(
+ buzz::QName(kPushNotificationsNamespace, "item"));
+ item->AddAttr(buzz::QName(buzz::STR_EMPTY, "channel"),
+ iter->channel.c_str());
+ item->AddAttr(buzz::QN_FROM, iter->from.c_str());
+ subscribe->AddElement(item);
+ }
+ return iq;
+}
+
+} // namespace notifier
+
diff --git a/jingle/notifier/listener/push_notifications_subscribe_task.h b/jingle/notifier/listener/push_notifications_subscribe_task.h
new file mode 100644
index 0000000..5dbdb32
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_subscribe_task.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2010 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.
+//
+// This class handles subscribing to the new Google push notifications.
+
+#ifndef JINGLE_NOTIFIER_LISTENER_PUSH_NOTIFICATIONS_SUBSCRIBE_TASK_H_
+#define JINGLE_NOTIFIER_LISTENER_PUSH_NOTIFICATIONS_SUBSCRIBE_TASK_H_
+
+#include <string>
+#include <vector>
+
+#include "base/gtest_prod_util.h"
+#include "talk/xmllite/xmlelement.h"
+#include "talk/xmpp/xmpptask.h"
+
+namespace notifier {
+class PushNotificationsSubscribeTask : public buzz::XmppTask {
+ public:
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+ virtual void OnSubscribed() = 0;
+ virtual void OnSubscriptionError() = 0;
+ };
+
+ struct PushSubscriptionInfo {
+ std::string channel;
+ std::string from;
+ };
+
+ PushNotificationsSubscribeTask(TaskParent* parent,
+ const std::vector<PushSubscriptionInfo>& channels_list,
+ Delegate* delegate);
+ virtual ~PushNotificationsSubscribeTask();
+
+ // Overridden from XmppTask.
+ virtual int ProcessStart();
+ virtual int ProcessResponse();
+ virtual bool HandleStanza(const buzz::XmlElement* stanza);
+
+ private:
+ // Assembles an Xmpp stanza which can be sent to subscribe to notifications.
+ static buzz::XmlElement* MakeSubscriptionMessage(
+ const std::vector<PushSubscriptionInfo>& channels_list,
+ const buzz::Jid& jid, const std::string& task_id);
+
+ std::vector<PushSubscriptionInfo> channels_list_;
+ Delegate* delegate_;
+
+ FRIEND_TEST_ALL_PREFIXES(PushNotificationsSubscribeTaskTest,
+ MakeSubscriptionMessage);
+
+ DISALLOW_COPY_AND_ASSIGN(PushNotificationsSubscribeTask);
+};
+
+typedef PushNotificationsSubscribeTask::Delegate
+ PushNotificationsSubscribeTaskDelegate;
+
+
+} // namespace notifier
+
+#endif // JINGLE_NOTIFIER_LISTENER_PUSH_NOTIFICATIONS_SUBSCRIBE_TASK_H_
+
diff --git a/jingle/notifier/listener/push_notifications_subscribe_task_unittest.cc b/jingle/notifier/listener/push_notifications_subscribe_task_unittest.cc
new file mode 100644
index 0000000..752c762
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_subscribe_task_unittest.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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/push_notifications_subscribe_task.h"
+
+#include "base/scoped_ptr.h"
+#include "base/string_util.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 PushNotificationsSubscribeTaskTest : public testing::Test {
+ public:
+ PushNotificationsSubscribeTaskTest()
+ : jid_("to@jid.com/test123"), task_id_("taskid") {
+ EXPECT_NE(jid_.Str(), jid_.BareJid().Str());
+ }
+
+ protected:
+ const buzz::Jid jid_;
+ const std::string task_id_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PushNotificationsSubscribeTaskTest);
+};
+
+TEST_F(PushNotificationsSubscribeTaskTest, MakeSubscriptionMessage) {
+ std::vector<PushNotificationsSubscribeTask::PushSubscriptionInfo>
+ subscription_list;
+
+ PushNotificationsSubscribeTask::PushSubscriptionInfo subscription;
+ subscription.channel = "test_channel1";
+ subscription.from = "from.test.com";
+ subscription_list.push_back(subscription);
+ subscription.channel = "test_channel2";
+ subscription.from = "from.test2.com";
+ subscription_list.push_back(subscription);
+ scoped_ptr<buzz::XmlElement> message(
+ PushNotificationsSubscribeTask::MakeSubscriptionMessage(
+ subscription_list, jid_, task_id_));
+ std::string expected_xml_string =
+ StringPrintf(
+ "<cli:iq type=\"set\" to=\"%s\" id=\"%s\" "
+ "xmlns:cli=\"jabber:client\">"
+ "<subscribe xmlns=\"google:push\">"
+ "<item channel=\"test_channel1\" from=\"from.test.com\"/>"
+ "<item channel=\"test_channel2\" from=\"from.test2.com\"/>"
+ "</subscribe>"
+ "</cli:iq>",
+ jid_.BareJid().Str().c_str(), task_id_.c_str());
+
+ EXPECT_EQ(expected_xml_string, XmlElementToString(*message));
+}
+
+} // namespace notifier
+
diff --git a/jingle/notifier/listener/push_notifications_thread.cc b/jingle/notifier/listener/push_notifications_thread.cc
new file mode 100644
index 0000000..99a9847
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_thread.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2010 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/push_notifications_thread.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/task.h"
+#include "jingle/notifier/listener/notification_defines.h"
+#include "talk/xmpp/xmppclient.h"
+
+namespace notifier {
+
+PushNotificationsThread::PushNotificationsThread(
+ const NotifierOptions& notifier_options, const std::string& from)
+ : MediatorThreadImpl(notifier_options), from_(from) {
+}
+
+PushNotificationsThread::~PushNotificationsThread() {
+ DCHECK_EQ(MessageLoop::current(), parent_message_loop_);
+}
+
+void PushNotificationsThread::ListenForUpdates() {
+ DCHECK_EQ(MessageLoop::current(), parent_message_loop_);
+ worker_message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &PushNotificationsThread::ListenForPushNotifications));
+}
+
+void PushNotificationsThread::SubscribeForUpdates(
+ const std::vector<std::string>& subscribed_services_list) {
+ DCHECK_EQ(MessageLoop::current(), parent_message_loop_);
+ worker_message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this,
+ &PushNotificationsThread::SubscribeForPushNotifications,
+ subscribed_services_list));
+}
+
+void PushNotificationsThread::SendNotification(
+ const OutgoingNotificationData& data) {
+ DCHECK_EQ(MessageLoop::current(), parent_message_loop_);
+}
+
+void PushNotificationsThread::ListenForPushNotifications() {
+ DCHECK_EQ(MessageLoop::current(), worker_message_loop());
+ PushNotificationsListenTask* listener =
+ new PushNotificationsListenTask(base_task_, this);
+ listener->Start();
+}
+
+void PushNotificationsThread::SubscribeForPushNotifications(
+ const std::vector<std::string>& subscribed_services_list) {
+ std::vector<PushNotificationsSubscribeTask::PushSubscriptionInfo>
+ channels_list;
+ for (std::vector<std::string>::const_iterator iter =
+ subscribed_services_list.begin();
+ iter != subscribed_services_list.end(); iter++) {
+ PushNotificationsSubscribeTask::PushSubscriptionInfo subscription;
+ subscription.channel = *iter;
+ subscription.from = from_;
+ channels_list.push_back(subscription);
+ }
+ DCHECK_EQ(MessageLoop::current(), worker_message_loop());
+ PushNotificationsSubscribeTask* subscription =
+ new PushNotificationsSubscribeTask(base_task_, channels_list, this);
+ subscription->Start();
+}
+
+void PushNotificationsThread::OnSubscribed() {
+ OnSubscriptionStateChange(true);
+}
+
+void PushNotificationsThread::OnSubscriptionError() {
+ OnSubscriptionStateChange(false);
+}
+
+void PushNotificationsThread::OnNotificationReceived(
+ const IncomingNotificationData& notification) {
+ OnIncomingNotification(notification);
+}
+
+} // namespace notifier
+
diff --git a/jingle/notifier/listener/push_notifications_thread.h b/jingle/notifier/listener/push_notifications_thread.h
new file mode 100644
index 0000000..74af76b
--- /dev/null
+++ b/jingle/notifier/listener/push_notifications_thread.h
@@ -0,0 +1,63 @@
+// Copyright (c) 2010 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.
+//
+// An implementaion of MediatorThreadImpl to subscribe and listen for
+// notifications using the new Google Push notifications service.
+
+#ifndef JINGLE_NOTIFIER_LISTENER_PUSH_NOTIFICATIONS_THREAD_H_
+#define JINGLE_NOTIFIER_LISTENER_PUSH_NOTIFICATIONS_THREAD_H_
+
+#include <string>
+#include <vector>
+
+#include "jingle/notifier/listener/mediator_thread_impl.h"
+#include "jingle/notifier/listener/push_notifications_listen_task.h"
+#include "jingle/notifier/listener/push_notifications_subscribe_task.h"
+
+namespace notifier {
+
+class PushNotificationsThread
+ : public MediatorThreadImpl,
+ public PushNotificationsListenTaskDelegate,
+ public PushNotificationsSubscribeTaskDelegate {
+ public:
+ explicit PushNotificationsThread(
+ const NotifierOptions& notifier_options, const std::string& from);
+ virtual ~PushNotificationsThread();
+
+ // MediatorThreadImpl overrides.
+ virtual void ListenForUpdates();
+ // TODO(sanjeevr): Because we are using the MediatorThread interface which
+ // was designed for the old notifications scheme, this class is limited to
+ // subscribing to multiple channels from the same source (the |from| c'tor
+ // argument). We need to extend the interface to handle the new push
+ // notifications service.
+ virtual void SubscribeForUpdates(
+ const std::vector<std::string>& subscribed_services_list);
+ virtual void SendNotification(const OutgoingNotificationData& data);
+
+ // PushNotificationsListenTaskDelegate implementation.
+ virtual void OnNotificationReceived(
+ const IncomingNotificationData& notification);
+ // PushNotificationsSubscribeTaskDelegate implementation.
+ virtual void OnSubscribed();
+ virtual void OnSubscriptionError();
+
+ private:
+ // Helpers invoked on worker thread.
+ void ListenForPushNotifications();
+ void SubscribeForPushNotifications(
+ const std::vector<std::string>& subscribed_services_list);
+
+ std::string from_;
+
+ DISALLOW_COPY_AND_ASSIGN(PushNotificationsThread);
+};
+
+} // namespace notifier
+
+DISABLE_RUNNABLE_METHOD_REFCOUNT(notifier::PushNotificationsThread);
+
+#endif // JINGLE_NOTIFIER_LISTENER_PUSH_NOTIFICATIONS_THREAD_H_
+