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 DVLOG(1) << "Push notifications: Subscription stanza: " 47 << XmlElementToString(*iq_stanza.get()); 48 49 if (SendStanza(iq_stanza.get()) != buzz::XMPP_RETURN_OK) { 50 if (delegate_) 51 delegate_->OnSubscriptionError(); 52 return STATE_ERROR; 53 } 54 return STATE_RESPONSE; 55 } 56 57 int PushNotificationsSubscribeTask::ProcessResponse() { 58 DVLOG(1) << "Push notifications: Subscription response received."; 59 const buzz::XmlElement* stanza = NextStanza(); 60 if (stanza == NULL) { 61 return STATE_BLOCKED; 62 } 63 DVLOG(1) << "Push notifications: Subscription response: " 64 << XmlElementToString(*stanza); 65 // We've received a response to our subscription request. 66 if (stanza->HasAttr(buzz::QN_TYPE) && 67 stanza->Attr(buzz::QN_TYPE) == buzz::STR_RESULT) { 68 if (delegate_) 69 delegate_->OnSubscribed(); 70 return STATE_DONE; 71 } 72 // An error response was received. 73 if (delegate_) 74 delegate_->OnSubscriptionError(); 75 return STATE_ERROR; 76 } 77 78 buzz::XmlElement* PushNotificationsSubscribeTask::MakeSubscriptionMessage( 79 const SubscriptionList& subscriptions, 80 const buzz::Jid& jid, const std::string& task_id) { 81 DCHECK(jid.IsFull()); 82 const buzz::QName kQnSubscribe( 83 kPushNotificationsNamespace, "subscribe"); 84 85 // Create the subscription stanza using the notifications protocol. 86 // <iq from={full_jid} to={bare_jid} type="set" id={id}> 87 // <subscribe xmlns="google:push"> 88 // <item channel={channel_name} from={domain_name or bare_jid}/> 89 // <item channel={channel_name2} from={domain_name or bare_jid}/> 90 // <item channel={channel_name3} from={domain_name or bare_jid}/> 91 // </subscribe> 92 // </iq> 93 buzz::XmlElement* iq = MakeIq(buzz::STR_SET, jid.BareJid(), task_id); 94 buzz::XmlElement* subscribe = new buzz::XmlElement(kQnSubscribe, true); 95 iq->AddElement(subscribe); 96 97 for (SubscriptionList::const_iterator iter = 98 subscriptions.begin(); iter != subscriptions.end(); ++iter) { 99 buzz::XmlElement* item = new buzz::XmlElement( 100 buzz::QName(kPushNotificationsNamespace, "item")); 101 item->AddAttr(buzz::QName(buzz::STR_EMPTY, "channel"), 102 iter->channel.c_str()); 103 item->AddAttr(buzz::QN_FROM, iter->from.c_str()); 104 subscribe->AddElement(item); 105 } 106 return iq; 107 } 108 109 } // namespace notifier 110