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 "jingle/notifier/listener/push_notifications_subscribe_task.h" 6 7 #include <string> 8 9 #include "base/logging.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "jingle/notifier/listener/notification_constants.h" 12 #include "jingle/notifier/listener/xml_element_util.h" 13 #include "talk/base/task.h" 14 #include "talk/xmllite/qname.h" 15 #include "talk/xmllite/xmlelement.h" 16 #include "talk/xmpp/xmppclient.h" 17 #include "talk/xmpp/constants.h" 18 #include "talk/xmpp/xmppengine.h" 19 20 namespace notifier { 21 22 PushNotificationsSubscribeTask::PushNotificationsSubscribeTask( 23 buzz::XmppTaskParentInterface* parent, 24 const SubscriptionList& subscriptions, 25 Delegate* delegate) 26 : XmppTask(parent, buzz::XmppEngine::HL_SINGLE), 27 subscriptions_(subscriptions), delegate_(delegate) { 28 } 29 30 PushNotificationsSubscribeTask::~PushNotificationsSubscribeTask() { 31 } 32 33 bool PushNotificationsSubscribeTask::HandleStanza( 34 const buzz::XmlElement* stanza) { 35 if (!MatchResponseIq(stanza, GetClient()->jid().BareJid(), task_id())) 36 return false; 37 QueueStanza(stanza); 38 return true; 39 } 40 41 int PushNotificationsSubscribeTask::ProcessStart() { 42 DVLOG(1) << "Push notifications: Subscription task started."; 43 scoped_ptr<buzz::XmlElement> iq_stanza( 44 MakeSubscriptionMessage(subscriptions_, GetClient()->jid(), 45 task_id())); 46 std::string stanza_str = XmlElementToString(*iq_stanza.get()); 47 DVLOG(1) << "Push notifications: Subscription stanza: " 48 << XmlElementToString(*iq_stanza.get()); 49 50 if (SendStanza(iq_stanza.get()) != buzz::XMPP_RETURN_OK) { 51 if (delegate_) 52 delegate_->OnSubscriptionError(); 53 return STATE_ERROR; 54 } 55 return STATE_RESPONSE; 56 } 57 58 int PushNotificationsSubscribeTask::ProcessResponse() { 59 DVLOG(1) << "Push notifications: Subscription response received."; 60 const buzz::XmlElement* stanza = NextStanza(); 61 if (stanza == NULL) { 62 return STATE_BLOCKED; 63 } 64 std::string stanza_str = XmlElementToString(*stanza); 65 DVLOG(1) << "Push notifications: Subscription response: " 66 << XmlElementToString(*stanza); 67 // We've receieved a response to our subscription request. 68 if (stanza->HasAttr(buzz::QN_TYPE) && 69 stanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT) { 70 if (delegate_) 71 delegate_->OnSubscribed(); 72 return STATE_DONE; 73 } 74 // An error response was received. 75 if (delegate_) 76 delegate_->OnSubscriptionError(); 77 return STATE_ERROR; 78 } 79 80 buzz::XmlElement* PushNotificationsSubscribeTask::MakeSubscriptionMessage( 81 const SubscriptionList& subscriptions, 82 const buzz::Jid& jid, const std::string& task_id) { 83 DCHECK(jid.IsFull()); 84 const buzz::QName kQnSubscribe( 85 kPushNotificationsNamespace, "subscribe"); 86 87 // Create the subscription stanza using the notifications protocol. 88 // <iq from={full_jid} to={bare_jid} type="set" id={id}> 89 // <subscribe xmlns="google:push"> 90 // <item channel={channel_name} from={domain_name or bare_jid}/> 91 // <item channel={channel_name2} from={domain_name or bare_jid}/> 92 // <item channel={channel_name3} from={domain_name or bare_jid}/> 93 // </subscribe> 94 // </iq> 95 buzz::XmlElement* iq = MakeIq(buzz::STR_SET, jid.BareJid(), task_id); 96 buzz::XmlElement* subscribe = new buzz::XmlElement(kQnSubscribe, true); 97 iq->AddElement(subscribe); 98 99 for (SubscriptionList::const_iterator iter = 100 subscriptions.begin(); iter != subscriptions.end(); ++iter) { 101 buzz::XmlElement* item = new buzz::XmlElement( 102 buzz::QName(kPushNotificationsNamespace, "item")); 103 item->AddAttr(buzz::QName(buzz::STR_EMPTY, "channel"), 104 iter->channel.c_str()); 105 item->AddAttr(buzz::QN_FROM, iter->from.c_str()); 106 subscribe->AddElement(item); 107 } 108 return iq; 109 } 110 111 } // namespace notifier 112