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