14ee2ad04344446e610172a0e73949212923014dfSebastian Redl// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// Use of this source code is governed by a BSD-style license that can be 32cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor// found in the LICENSE file. 42cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 52cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "jingle/notifier/listener/xmpp_push_client.h" 62cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 72cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/logging.h" 82cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "base/message_loop/message_loop_proxy.h" 92cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "jingle/notifier/base/notifier_options_util.h" 10a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl#include "jingle/notifier/listener/push_client_observer.h" 112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "jingle/notifier/listener/send_ping_task.h" 122cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor#include "jingle/notifier/listener/push_notifications_send_update_task.h" 132cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 147faa2ec03a7ef120ac165bb45b6c70a8b20c9f1cSebastian Redlnamespace notifier { 150eca89e9890db4d8336ce762a5b359a1d58ca02bArgyrios Kyrtzidis 16e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas GregorXmppPushClient::XmppPushClient(const NotifierOptions& notifier_options) 17e737f5041a36d0befb39ffeed8d50ba15916d3daDouglas Gregor : notifier_options_(notifier_options) { 182cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(notifier_options_.request_context_getter-> 192cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor GetNetworkTaskRunner()->BelongsToCurrentThread()); 202cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 212a7fb27913999d132cf9e10e03dc5271faa2e9d3John McCall 2289eaf3af92c72c0c1aae807644e39cabc461d685Argyrios KyrtzidisXmppPushClient::~XmppPushClient() { 230b7489194f9f89fac39d57211c1e7953ae50251fDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 247a1fad38256eb4c5129359be85ba1ea1678eb5c9John McCall} 252cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 26a1ee0c548b8aa4aaf93d1917e304e3da13171a08John McCallvoid XmppPushClient::OnConnect( 276ab7cd853e9c15cf986a8a7c3db1f8d20e275409Sebastian Redl base::WeakPtr<buzz::XmppTaskParentInterface> base_task) { 287c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner DCHECK(thread_checker_.CalledOnValidThread()); 296a5a23f8e7fb65e028c8092bc1d1a1d9dfe2e9bcDouglas Gregor base_task_ = base_task; 307c5d24efcd2e505b5739f7def08dfe25ce59a1b2Chris Lattner 3183d63c78810556d26b62ac4cbae2eda6cdd2570cSteve Naroff if (!base_task_.get()) { 3214f79002e58556798e86168c63e48d533287eda5Douglas Gregor NOTREACHED(); 3310e286aa8d39fb51a21412850265d9dae74613eeChris Lattner return; 343251ceb90b3fec68e86d6dcfa58836e20a7205c3Douglas Gregor } 3514f79002e58556798e86168c63e48d533287eda5Douglas Gregor 36bd94500d3aa60092fb0f1e90f53fb0d03fa502a8Douglas Gregor // Listen for notifications. 372bec0410d268779f601bd509e0302a500af7ac6aDouglas Gregor { 38ab41e63821dc60ad144d0684df8d79a9eef86b75Douglas Gregor // Owned by |base_task_|. 390a0d2b179085a52c10402feebeb6db8b4d96a140Douglas Gregor PushNotificationsListenTask* listener = 4017fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor new PushNotificationsListenTask(base_task_.get(), this); 4117fc223395d51be582fc666bb6ea21bd1dff26dcDouglas Gregor listener->Start(); 422596e429a61602312bdd149786045b8a90cd2d10Daniel Dunbar } 432cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 44fbfd180495e7800975c6d9bdc6d24e706ef70e34Michael J. Spencer // Send subscriptions. 4514f79002e58556798e86168c63e48d533287eda5Douglas Gregor { 4603013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer // Owned by |base_task_|. 47f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor PushNotificationsSubscribeTask* subscribe_task = 483c304bd9ec2b4611572d4cbae9e1727bbecb5dc9Chris Lattner new PushNotificationsSubscribeTask( 49cfbf1c7536e016dc275139dd842d4a5f059a749fDouglas Gregor base_task_.get(), subscriptions_, this); 50f62d43d2afe1960755a1b5813cae1e5983bcac1bDouglas Gregor subscribe_task->Start(); 512cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 528538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl 532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor std::vector<Notification> notifications_to_send; 54ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl notifications_to_send.swap(pending_notifications_to_send_); 555f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (std::vector<Notification>::const_iterator it = 565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner notifications_to_send.begin(); 575f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner it != notifications_to_send.end(); ++it) { 586e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer DVLOG(1) << "Push: Sending pending notification " << it->ToString(); 59ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl SendNotification(*it); 606e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer } 616e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer} 625f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner 635f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid XmppPushClient::OnTransientDisconnection() { 646e089c687cc2b914c46859ab7e46fe4c3c6b0afbBenjamin Kramer DCHECK(thread_checker_.CalledOnValidThread()); 65ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl DVLOG(1) << "Push: Transient disconnection"; 66ade5000c8763f4bec41f452d7efa3a9b2a6d4712Sebastian Redl base_task_.reset(); 672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor FOR_EACH_OBSERVER(PushClientObserver, observers_, 682cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 692cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 7012b1c7615d4f9a2edc544be499f895f16ac100edChris Lattner 712cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid XmppPushClient::OnCredentialsRejected() { 723397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl DCHECK(thread_checker_.CalledOnValidThread()); 73a4232eb646d89e7d52424bb42eb87d9061f39e63Sebastian Redl DVLOG(1) << "Push: Credentials rejected"; 7489eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidis base_task_.reset(); 752cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor FOR_EACH_OBSERVER( 762cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor PushClientObserver, observers_, 772cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor OnNotificationsDisabled(NOTIFICATION_CREDENTIALS_REJECTED)); 788538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl} 792cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 8089eaf3af92c72c0c1aae807644e39cabc461d685Argyrios Kyrtzidisvoid XmppPushClient::OnNotificationReceived( 818538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl const Notification& notification) { 822cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 832cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor FOR_EACH_OBSERVER(PushClientObserver, observers_, 842cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor OnIncomingNotification(notification)); 852cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 862cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 872cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid XmppPushClient::OnPingResponseReceived() { 882cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 892cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor FOR_EACH_OBSERVER(PushClientObserver, observers_, OnPingResponse()); 902cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 912cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 922cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid XmppPushClient::OnSubscribed() { 933397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl DCHECK(thread_checker_.CalledOnValidThread()); 94b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie FOR_EACH_OBSERVER(PushClientObserver, observers_, 952cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor OnNotificationsEnabled()); 962cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 973397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 982cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid XmppPushClient::OnSubscriptionError() { 998538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl DCHECK(thread_checker_.CalledOnValidThread()); 1002cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor FOR_EACH_OBSERVER(PushClientObserver, observers_, 1012cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR)); 1023397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 1032cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1048538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid XmppPushClient::AddObserver(PushClientObserver* observer) { 1052cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 1062cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor observers_.AddObserver(observer); 1073397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1098538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid XmppPushClient::RemoveObserver(PushClientObserver* observer) { 1102cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 1112cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor observers_.RemoveObserver(observer); 1123397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 113df1550fc59b51681d37225934fe4e3acac321621Richard Smith 114df1550fc59b51681d37225934fe4e3acac321621Richard Smithvoid XmppPushClient::UpdateSubscriptions( 1158538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl const SubscriptionList& subscriptions) { 1162cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 1172cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor subscriptions_ = subscriptions; 1183397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} 119df1550fc59b51681d37225934fe4e3acac321621Richard Smith 1208538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redlvoid XmppPushClient::UpdateCredentials( 1212cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor const std::string& email, const std::string& token) { 1222cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 1233397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl DVLOG(1) << "Push: Updating credentials for " << email; 1241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump xmpp_settings_ = MakeXmppClientSettings(notifier_options_, email, token); 1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (login_.get()) { 1268538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl login_->UpdateXmppSettings(xmpp_settings_); 1272cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } else { 1282cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DVLOG(1) << "Push: Starting XMPP connection"; 1293397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl base_task_.reset(); 1302cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor login_.reset(new notifier::Login(this, 1312cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor xmpp_settings_, 1320953e767ff7817f97b3ab20896b229891eeff45bJohn McCall notifier_options_.request_context_getter, 1332cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor GetServerList(notifier_options_), 1342cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor notifier_options_.try_ssltcp_first, 1353397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl notifier_options_.auth_mechanism)); 1362cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor login_->StartConnection(); 1372cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1388538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl} 1392cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1402cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid XmppPushClient::SendNotification(const Notification& notification) { 1413397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl DCHECK(thread_checker_.CalledOnValidThread()); 1422cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor if (!base_task_.get()) { 1438538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl // TODO(akalin): Figure out whether we really need to do this. 1442cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DVLOG(1) << "Push: Cannot send notification " 1452cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor << notification.ToString() << "; sending later"; 1463397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl pending_notifications_to_send_.push_back(notification); 1472cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return; 1487e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor } 1497e7eb3da052a6d80ddf2377cab0384c798f73f75Douglas Gregor // Owned by |base_task_|. 150c9490c000f515c29f200a1215328d8ab9a0f3818Douglas Gregor PushNotificationsSendUpdateTask* task = 1518538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl new PushNotificationsSendUpdateTask(base_task_.get(), notification); 1522cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor task->Start(); 1532cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 1543397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl 1552cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregorvoid XmppPushClient::SendPing() { 1562cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor DCHECK(thread_checker_.CalledOnValidThread()); 157e86d78cf4754a6aef2cf9a33d847aa15338e276fBob Wilson if (!base_task_.get()) { 1588538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl DVLOG(1) << "Push: Cannot send ping"; 1592cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor return; 1602cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor } 1613397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl // Owned by |base_task_|. 1622cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor SendPingTask* task = new SendPingTask(base_task_.get(), this); 1638538e8d43a3a9bd439c987c0de37bcbf035dd391Sebastian Redl task->Start(); 1642cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor} 1652cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor 1663397c5570369f19b2d6c52e898f708d75ceede1fSebastian Redl} // namespace notifier 1672cf2634ffdb4f7c8d46cef3f8e60a55993f1c57aDouglas Gregor