Home | History | Annotate | Download | only in listener
      1 // Copyright (c) 2011 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 "jingle/notifier/listener/push_notifications_listen_task.h"
      6 
      7 #include "base/base64.h"
      8 #include "base/logging.h"
      9 #include "jingle/notifier/listener/notification_constants.h"
     10 #include "jingle/notifier/listener/notification_defines.h"
     11 #include "jingle/notifier/listener/xml_element_util.h"
     12 #include "talk/base/task.h"
     13 #include "talk/xmllite/qname.h"
     14 #include "talk/xmllite/xmlelement.h"
     15 #include "talk/xmpp/xmppclient.h"
     16 #include "talk/xmpp/constants.h"
     17 #include "talk/xmpp/xmppengine.h"
     18 
     19 namespace notifier {
     20 
     21 PushNotificationsListenTask::Delegate::~Delegate() {
     22 }
     23 
     24 PushNotificationsListenTask::PushNotificationsListenTask(
     25     buzz::XmppTaskParentInterface* parent, Delegate* delegate)
     26         : buzz::XmppTask(parent, buzz::XmppEngine::HL_TYPE),
     27           delegate_(delegate) {
     28   DCHECK(delegate_);
     29 }
     30 
     31 PushNotificationsListenTask::~PushNotificationsListenTask() {
     32 }
     33 
     34 int PushNotificationsListenTask::ProcessStart() {
     35   return STATE_RESPONSE;
     36 }
     37 
     38 int PushNotificationsListenTask::ProcessResponse() {
     39   const buzz::XmlElement* stanza = NextStanza();
     40   if (stanza == NULL) {
     41     return STATE_BLOCKED;
     42   }
     43 
     44   DVLOG(1) << "Received stanza " << XmlElementToString(*stanza);
     45 
     46   // The push notifications service does not need us to acknowledge receipt of
     47   // the notification to the buzz server.
     48 
     49   // TODO(sanjeevr): Write unittests to cover this.
     50   // Extract the service URL and service-specific data from the stanza.
     51   // Note that we treat the channel name as service URL.
     52   // The response stanza has the following format.
     53   // <message from="{url or bare jid}" to={full jid}>
     54   //  <push xmlns="google:push" channel={channel name}>
     55   //    <recipient to={bare jid}>{base-64 encoded data}</recipient>
     56   //    <data>{base-64 encoded data}</data>
     57   //  </push>
     58   // </message>
     59 
     60   const buzz::QName kQnPush(kPushNotificationsNamespace, "push");
     61   const buzz::QName kQnChannel(buzz::STR_EMPTY, "channel");
     62   const buzz::QName kQnData(kPushNotificationsNamespace, "data");
     63 
     64   const buzz::XmlElement* push_element = stanza->FirstNamed(kQnPush);
     65   if (push_element) {
     66     Notification notification;
     67     notification.channel = push_element->Attr(kQnChannel);
     68     const buzz::XmlElement* data_element = push_element->FirstNamed(kQnData);
     69     if (data_element) {
     70       const std::string& base64_encoded_data = data_element->BodyText();
     71       if (!base::Base64Decode(base64_encoded_data, &notification.data)) {
     72         LOG(WARNING) << "Could not base64-decode " << base64_encoded_data;
     73       }
     74     } else {
     75       LOG(WARNING) << "No data element found in push element "
     76                    << XmlElementToString(*push_element);
     77     }
     78     DVLOG(1) << "Received notification " << notification.ToString();
     79     delegate_->OnNotificationReceived(notification);
     80   } else {
     81     LOG(WARNING) << "No push element found in stanza "
     82                  << XmlElementToString(*stanza);
     83   }
     84   return STATE_RESPONSE;
     85 }
     86 
     87 bool PushNotificationsListenTask::HandleStanza(const buzz::XmlElement* stanza) {
     88   if (IsValidNotification(stanza)) {
     89     QueueStanza(stanza);
     90     return true;
     91   }
     92   return false;
     93 }
     94 
     95 bool PushNotificationsListenTask::IsValidNotification(
     96     const buzz::XmlElement* stanza) {
     97   // We don't do much validation here, just check if the stanza is a message
     98   // stanza.
     99   return (stanza->Name() == buzz::QN_MESSAGE);
    100 }
    101 
    102 }  // namespace notifier
    103