Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: jingle/notifier/listener/push_client.cc

Issue 10413014: [Sync] Turn notifier::PushClient into an interface (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync to head Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « jingle/notifier/listener/push_client.h ('k') | jingle/notifier/listener/push_client_observer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "jingle/notifier/listener/push_client.h" 5 #include "jingle/notifier/listener/push_client.h"
6 6
7 #include <cstddef>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/compiler_specific.h" 10 #include "base/single_thread_task_runner.h"
9 #include "base/location.h" 11 #include "jingle/notifier/listener/non_blocking_push_client.h"
10 #include "base/logging.h" 12 #include "jingle/notifier/listener/xmpp_push_client.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/observer_list_threadsafe.h"
13 #include "jingle/notifier/base/notifier_options_util.h"
14 #include "jingle/notifier/communicator/login.h"
15 #include "jingle/notifier/listener/push_notifications_listen_task.h"
16 #include "jingle/notifier/listener/push_notifications_send_update_task.h"
17 #include "jingle/notifier/listener/push_notifications_subscribe_task.h"
18 #include "talk/xmpp/xmppclientsettings.h"
19 13
20 namespace notifier { 14 namespace notifier {
21 15
22 PushClient::Observer::~Observer() {} 16 PushClient::~PushClient() {}
23 17
24 // All member functions except for the constructor, destructor, and 18 namespace {
25 // {Add,Remove}Observer() must be called on the IO thread (as taken from
26 // |notifier_options|).
27 class PushClient::Core
28 : public base::RefCountedThreadSafe<PushClient::Core>,
29 public LoginDelegate,
30 public PushNotificationsListenTaskDelegate,
31 public PushNotificationsSubscribeTaskDelegate {
32 public:
33 // Called on the parent thread.
34 explicit Core(const NotifierOptions& notifier_options);
35 19
36 // Must be called before being destroyed. 20 scoped_ptr<PushClient> CreateXmppPushClient(
37 void DestroyOnIOThread(); 21 const NotifierOptions& notifier_options) {
38 22 return scoped_ptr<PushClient>(new XmppPushClient(notifier_options));
39 // Login::Delegate implementation.
40 virtual void OnConnect(
41 base::WeakPtr<buzz::XmppTaskParentInterface> base_task) OVERRIDE;
42 virtual void OnDisconnect();
43
44 // PushNotificationsListenTaskDelegate implementation.
45 virtual void OnNotificationReceived(
46 const Notification& notification) OVERRIDE;
47
48 // PushNotificationsSubscribeTaskDelegate implementation.
49 virtual void OnSubscribed() OVERRIDE;
50 virtual void OnSubscriptionError() OVERRIDE;
51
52 // Called on the parent thread.
53 void AddObserver(Observer* observer);
54 void RemoveObserver(Observer* observer);
55
56 void UpdateSubscriptions(const SubscriptionList& subscriptions);
57 void UpdateCredentials(const std::string& email, const std::string& token);
58 void SendNotification(const Notification& data);
59
60 // Any notifications sent after this is called will be reflected,
61 // i.e. will be treated as an incoming notification also.
62 void ReflectSentNotificationsForTest();
63
64 private:
65 friend class base::RefCountedThreadSafe<PushClient::Core>;
66
67 // Called on either the parent thread or the I/O thread.
68 virtual ~Core();
69
70 const NotifierOptions notifier_options_;
71 const scoped_refptr<base::MessageLoopProxy> parent_message_loop_proxy_;
72 const scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
73 const scoped_refptr<ObserverListThreadSafe<Observer> > observers_;
74
75 // XMPP connection settings.
76 SubscriptionList subscriptions_;
77 buzz::XmppClientSettings xmpp_settings_;
78
79 // Must be created/used/destroyed only on the IO thread.
80 scoped_ptr<notifier::Login> login_;
81
82 // The XMPP connection.
83 base::WeakPtr<buzz::XmppTaskParentInterface> base_task_;
84
85 std::vector<Notification> pending_notifications_to_send_;
86
87 bool reflect_sent_notifications_for_test_;
88
89 DISALLOW_COPY_AND_ASSIGN(Core);
90 };
91
92 PushClient::Core::Core(const NotifierOptions& notifier_options)
93 : notifier_options_(notifier_options),
94 parent_message_loop_proxy_(base::MessageLoopProxy::current()),
95 io_message_loop_proxy_(
96 notifier_options_.request_context_getter->GetIOMessageLoopProxy()),
97 observers_(new ObserverListThreadSafe<Observer>()),
98 reflect_sent_notifications_for_test_(false) {}
99
100 PushClient::Core::~Core() {
101 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread() ||
102 io_message_loop_proxy_->BelongsToCurrentThread());
103 DCHECK(!login_.get());
104 DCHECK(!base_task_.get());
105 observers_->AssertEmpty();
106 } 23 }
107 24
108 void PushClient::Core::DestroyOnIOThread() { 25 } // namespace
109 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
110 login_.reset();
111 base_task_.reset();
112 }
113 26
114 void PushClient::Core::OnConnect( 27 scoped_ptr<PushClient> PushClient::CreateDefault(
115 base::WeakPtr<buzz::XmppTaskParentInterface> base_task) { 28 const NotifierOptions& notifier_options) {
116 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread()); 29 return scoped_ptr<PushClient>(new NonBlockingPushClient(
117 base_task_ = base_task; 30 notifier_options.request_context_getter->GetIOMessageLoopProxy(),
118 31 base::Bind(&CreateXmppPushClient, notifier_options)));
119 if (!base_task_.get()) {
120 NOTREACHED();
121 return;
122 }
123
124 // Listen for notifications.
125 {
126 // Owned by |base_task_|.
127 PushNotificationsListenTask* listener =
128 new PushNotificationsListenTask(base_task_, this);
129 listener->Start();
130 }
131
132 // Send subscriptions.
133 {
134 // Owned by |base_task_|.
135 PushNotificationsSubscribeTask* subscribe_task =
136 new PushNotificationsSubscribeTask(base_task_, subscriptions_, this);
137 subscribe_task->Start();
138 }
139
140 std::vector<Notification> notifications_to_send;
141 notifications_to_send.swap(pending_notifications_to_send_);
142 for (std::vector<Notification>::const_iterator it =
143 notifications_to_send.begin();
144 it != notifications_to_send.end(); ++it) {
145 DVLOG(1) << "Push: Sending pending notification " << it->ToString();
146 SendNotification(*it);
147 }
148 }
149
150 void PushClient::Core::OnDisconnect() {
151 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
152 base_task_.reset();
153 observers_->Notify(&Observer::OnNotificationStateChange, false);
154 }
155
156 void PushClient::Core::OnNotificationReceived(
157 const Notification& notification) {
158 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
159 observers_->Notify(&Observer::OnIncomingNotification, notification);
160 }
161
162 void PushClient::Core::OnSubscribed() {
163 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
164 observers_->Notify(&Observer::OnNotificationStateChange, true);
165 }
166
167 void PushClient::Core::OnSubscriptionError() {
168 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
169 observers_->Notify(&Observer::OnNotificationStateChange, false);
170 }
171
172 void PushClient::Core::AddObserver(Observer* observer) {
173 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
174 observers_->AddObserver(observer);
175 }
176
177 void PushClient::Core::RemoveObserver(Observer* observer) {
178 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
179 observers_->RemoveObserver(observer);
180 }
181
182 void PushClient::Core::UpdateSubscriptions(
183 const SubscriptionList& subscriptions) {
184 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
185 subscriptions_ = subscriptions;
186 }
187
188 void PushClient::Core::UpdateCredentials(
189 const std::string& email, const std::string& token) {
190 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
191 DVLOG(1) << "Push: Updating credentials for " << email;
192 xmpp_settings_ = MakeXmppClientSettings(notifier_options_, email, token);
193 if (login_.get()) {
194 login_->UpdateXmppSettings(xmpp_settings_);
195 } else {
196 DVLOG(1) << "Push: Starting XMPP connection";
197 base_task_.reset();
198 login_.reset(new notifier::Login(this,
199 xmpp_settings_,
200 notifier_options_.request_context_getter,
201 GetServerList(notifier_options_),
202 notifier_options_.try_ssltcp_first,
203 notifier_options_.auth_mechanism));
204 login_->StartConnection();
205 }
206 }
207
208 void PushClient::Core::SendNotification(const Notification& notification) {
209 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
210 if (!base_task_.get()) {
211 DVLOG(1) << "Push: Cannot send notification "
212 << notification.ToString() << "; sending later";
213 pending_notifications_to_send_.push_back(notification);
214 return;
215 }
216 // Owned by |base_task_|.
217 PushNotificationsSendUpdateTask* task =
218 new PushNotificationsSendUpdateTask(base_task_, notification);
219 task->Start();
220
221 if (reflect_sent_notifications_for_test_) {
222 OnNotificationReceived(notification);
223 }
224 }
225
226 void PushClient::Core::ReflectSentNotificationsForTest() {
227 DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
228 reflect_sent_notifications_for_test_ = true;
229 }
230
231 PushClient::PushClient(const NotifierOptions& notifier_options)
232 : core_(new Core(notifier_options)),
233 parent_message_loop_proxy_(base::MessageLoopProxy::current()),
234 io_message_loop_proxy_(
235 notifier_options.request_context_getter->GetIOMessageLoopProxy()) {
236 }
237
238 PushClient::~PushClient() {
239 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
240 io_message_loop_proxy_->PostTask(
241 FROM_HERE,
242 base::Bind(&PushClient::Core::DestroyOnIOThread, core_.get()));
243 }
244
245 void PushClient::AddObserver(Observer* observer) {
246 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
247 core_->AddObserver(observer);
248 }
249
250 void PushClient::RemoveObserver(Observer* observer) {
251 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
252 core_->RemoveObserver(observer);
253 }
254
255 void PushClient::UpdateSubscriptions(const SubscriptionList& subscriptions) {
256 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
257 io_message_loop_proxy_->PostTask(
258 FROM_HERE,
259 base::Bind(&PushClient::Core::UpdateSubscriptions,
260 core_.get(), subscriptions));
261 }
262
263 void PushClient::UpdateCredentials(
264 const std::string& email, const std::string& token) {
265 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
266 io_message_loop_proxy_->PostTask(
267 FROM_HERE,
268 base::Bind(&PushClient::Core::UpdateCredentials,
269 core_.get(), email, token));
270 }
271
272 void PushClient::SendNotification(const Notification& notification) {
273 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
274 io_message_loop_proxy_->PostTask(
275 FROM_HERE,
276 base::Bind(&PushClient::Core::SendNotification, core_.get(),
277 notification));
278 }
279
280 void PushClient::SimulateOnNotificationReceivedForTest(
281 const Notification& notification) {
282 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
283 io_message_loop_proxy_->PostTask(
284 FROM_HERE,
285 base::Bind(&PushClient::Core::OnNotificationReceived,
286 core_.get(), notification));
287 }
288
289 void PushClient::SimulateConnectAndSubscribeForTest(
290 base::WeakPtr<buzz::XmppTaskParentInterface> base_task) {
291 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
292 io_message_loop_proxy_->PostTask(
293 FROM_HERE,
294 base::Bind(&PushClient::Core::OnConnect, core_.get(), base_task));
295 io_message_loop_proxy_->PostTask(
296 FROM_HERE,
297 base::Bind(&PushClient::Core::OnSubscribed, core_.get()));
298 }
299
300 void PushClient::SimulateDisconnectForTest() {
301 DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread());
302 io_message_loop_proxy_->PostTask(
303 FROM_HERE,
304 base::Bind(&PushClient::Core::OnDisconnect, core_.get()));
305 }
306
307 void PushClient::SimulateSubscriptionErrorForTest() {
308 io_message_loop_proxy_->PostTask(
309 FROM_HERE,
310 base::Bind(&PushClient::Core::OnSubscriptionError, core_.get()));
311 }
312
313 void PushClient::ReflectSentNotificationsForTest() {
314 io_message_loop_proxy_->PostTask(
315 FROM_HERE,
316 base::Bind(&PushClient::Core::ReflectSentNotificationsForTest,
317 core_.get()));
318 } 32 }
319 33
320 } // namespace notifier 34 } // namespace notifier
OLDNEW
« no previous file with comments | « jingle/notifier/listener/push_client.h ('k') | jingle/notifier/listener/push_client_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698