Home | History | Annotate | Download | only in listener
      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/xmpp_push_client.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/message_loop/message_loop_proxy.h"
      9 #include "jingle/notifier/base/notifier_options_util.h"
     10 #include "jingle/notifier/listener/push_client_observer.h"
     11 #include "jingle/notifier/listener/send_ping_task.h"
     12 #include "jingle/notifier/listener/push_notifications_send_update_task.h"
     13 
     14 namespace notifier {
     15 
     16 XmppPushClient::XmppPushClient(const NotifierOptions& notifier_options)
     17     : notifier_options_(notifier_options) {
     18   DCHECK(notifier_options_.request_context_getter->
     19          GetNetworkTaskRunner()->BelongsToCurrentThread());
     20 }
     21 
     22 XmppPushClient::~XmppPushClient() {
     23   DCHECK(thread_checker_.CalledOnValidThread());
     24 }
     25 
     26 void XmppPushClient::OnConnect(
     27     base::WeakPtr<buzz::XmppTaskParentInterface> base_task) {
     28   DCHECK(thread_checker_.CalledOnValidThread());
     29   base_task_ = base_task;
     30 
     31   if (!base_task_.get()) {
     32     NOTREACHED();
     33     return;
     34   }
     35 
     36   // Listen for notifications.
     37   {
     38     // Owned by |base_task_|.
     39     PushNotificationsListenTask* listener =
     40         new PushNotificationsListenTask(base_task_.get(), this);
     41     listener->Start();
     42   }
     43 
     44   // Send subscriptions.
     45   {
     46     // Owned by |base_task_|.
     47     PushNotificationsSubscribeTask* subscribe_task =
     48         new PushNotificationsSubscribeTask(
     49             base_task_.get(), subscriptions_, this);
     50     subscribe_task->Start();
     51   }
     52 
     53   std::vector<Notification> notifications_to_send;
     54   notifications_to_send.swap(pending_notifications_to_send_);
     55   for (std::vector<Notification>::const_iterator it =
     56            notifications_to_send.begin();
     57        it != notifications_to_send.end(); ++it) {
     58     DVLOG(1) << "Push: Sending pending notification " << it->ToString();
     59     SendNotification(*it);
     60   }
     61 }
     62 
     63 void XmppPushClient::OnTransientDisconnection() {
     64   DCHECK(thread_checker_.CalledOnValidThread());
     65   DVLOG(1) << "Push: Transient disconnection";
     66   base_task_.reset();
     67   FOR_EACH_OBSERVER(PushClientObserver, observers_,
     68                     OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
     69 }
     70 
     71 void XmppPushClient::OnCredentialsRejected() {
     72   DCHECK(thread_checker_.CalledOnValidThread());
     73   DVLOG(1) << "Push: Credentials rejected";
     74   base_task_.reset();
     75   FOR_EACH_OBSERVER(
     76       PushClientObserver, observers_,
     77       OnNotificationsDisabled(NOTIFICATION_CREDENTIALS_REJECTED));
     78 }
     79 
     80 void XmppPushClient::OnNotificationReceived(
     81     const Notification& notification) {
     82   DCHECK(thread_checker_.CalledOnValidThread());
     83   FOR_EACH_OBSERVER(PushClientObserver, observers_,
     84                     OnIncomingNotification(notification));
     85 }
     86 
     87 void XmppPushClient::OnPingResponseReceived() {
     88   DCHECK(thread_checker_.CalledOnValidThread());
     89   FOR_EACH_OBSERVER(PushClientObserver, observers_, OnPingResponse());
     90 }
     91 
     92 void XmppPushClient::OnSubscribed() {
     93   DCHECK(thread_checker_.CalledOnValidThread());
     94   FOR_EACH_OBSERVER(PushClientObserver, observers_,
     95                     OnNotificationsEnabled());
     96 }
     97 
     98 void XmppPushClient::OnSubscriptionError() {
     99   DCHECK(thread_checker_.CalledOnValidThread());
    100   FOR_EACH_OBSERVER(PushClientObserver, observers_,
    101                     OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
    102 }
    103 
    104 void XmppPushClient::AddObserver(PushClientObserver* observer) {
    105   DCHECK(thread_checker_.CalledOnValidThread());
    106   observers_.AddObserver(observer);
    107 }
    108 
    109 void XmppPushClient::RemoveObserver(PushClientObserver* observer) {
    110   DCHECK(thread_checker_.CalledOnValidThread());
    111   observers_.RemoveObserver(observer);
    112 }
    113 
    114 void XmppPushClient::UpdateSubscriptions(
    115     const SubscriptionList& subscriptions) {
    116   DCHECK(thread_checker_.CalledOnValidThread());
    117   subscriptions_ = subscriptions;
    118 }
    119 
    120 void XmppPushClient::UpdateCredentials(
    121       const std::string& email, const std::string& token) {
    122   DCHECK(thread_checker_.CalledOnValidThread());
    123   DVLOG(1) << "Push: Updating credentials for " << email;
    124   xmpp_settings_ = MakeXmppClientSettings(notifier_options_, email, token);
    125   if (login_.get()) {
    126     login_->UpdateXmppSettings(xmpp_settings_);
    127   } else {
    128     DVLOG(1) << "Push: Starting XMPP connection";
    129     base_task_.reset();
    130     login_.reset(new notifier::Login(this,
    131                                      xmpp_settings_,
    132                                      notifier_options_.request_context_getter,
    133                                      GetServerList(notifier_options_),
    134                                      notifier_options_.try_ssltcp_first,
    135                                      notifier_options_.auth_mechanism));
    136     login_->StartConnection();
    137   }
    138 }
    139 
    140 void XmppPushClient::SendNotification(const Notification& notification) {
    141   DCHECK(thread_checker_.CalledOnValidThread());
    142   if (!base_task_.get()) {
    143     // TODO(akalin): Figure out whether we really need to do this.
    144     DVLOG(1) << "Push: Cannot send notification "
    145              << notification.ToString() << "; sending later";
    146     pending_notifications_to_send_.push_back(notification);
    147     return;
    148   }
    149   // Owned by |base_task_|.
    150   PushNotificationsSendUpdateTask* task =
    151       new PushNotificationsSendUpdateTask(base_task_.get(), notification);
    152   task->Start();
    153 }
    154 
    155 void XmppPushClient::SendPing() {
    156   DCHECK(thread_checker_.CalledOnValidThread());
    157   if (!base_task_.get()) {
    158     DVLOG(1) << "Push: Cannot send ping";
    159     return;
    160   }
    161   // Owned by |base_task_|.
    162   SendPingTask* task = new SendPingTask(base_task_.get(), this);
    163   task->Start();
    164 }
    165 
    166 }  // namespace notifier
    167