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