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.
5 #include "jingle/notifier/listener/non_blocking_push_client.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "jingle/notifier/listener/push_client_observer.h"
15 // All methods are called on the delegate thread unless specified
17 class NonBlockingPushClient::Core
18 : public base::RefCountedThreadSafe<NonBlockingPushClient::Core>,
19 public PushClientObserver {
21 // Called on the parent thread.
23 const scoped_refptr<base::SingleThreadTaskRunner>&
25 const base::WeakPtr<NonBlockingPushClient>& parent_push_client);
27 // Must be called after being created.
29 // This is separated out from the constructor since posting tasks
30 // from the constructor is dangerous.
31 void CreateOnDelegateThread(
32 const CreateBlockingPushClientCallback&
33 create_blocking_push_client_callback);
35 // Must be called before being destroyed.
36 void DestroyOnDelegateThread();
38 void UpdateSubscriptions(const SubscriptionList& subscriptions);
39 void UpdateCredentials(const std::string& email, const std::string& token);
40 void SendNotification(const Notification& data);
43 virtual void OnNotificationsEnabled() OVERRIDE;
44 virtual void OnNotificationsDisabled(
45 NotificationsDisabledReason reason) OVERRIDE;
46 virtual void OnIncomingNotification(
47 const Notification& notification) OVERRIDE;
48 virtual void OnPingResponse() OVERRIDE;
51 friend class base::RefCountedThreadSafe<NonBlockingPushClient::Core>;
53 // Called on either the parent thread or the delegate thread.
56 const scoped_refptr<base::SingleThreadTaskRunner> parent_task_runner_;
57 const scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
59 const base::WeakPtr<NonBlockingPushClient> parent_push_client_;
60 scoped_ptr<PushClient> delegate_push_client_;
62 DISALLOW_COPY_AND_ASSIGN(Core);
65 NonBlockingPushClient::Core::Core(
66 const scoped_refptr<base::SingleThreadTaskRunner>& delegate_task_runner,
67 const base::WeakPtr<NonBlockingPushClient>& parent_push_client)
68 : parent_task_runner_(base::MessageLoopProxy::current()),
69 delegate_task_runner_(delegate_task_runner),
70 parent_push_client_(parent_push_client) {}
72 NonBlockingPushClient::Core::~Core() {
73 DCHECK(parent_task_runner_->BelongsToCurrentThread() ||
74 delegate_task_runner_->BelongsToCurrentThread());
75 DCHECK(!delegate_push_client_.get());
78 void NonBlockingPushClient::Core::CreateOnDelegateThread(
79 const CreateBlockingPushClientCallback&
80 create_blocking_push_client_callback) {
81 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
82 DCHECK(!delegate_push_client_.get());
83 delegate_push_client_ = create_blocking_push_client_callback.Run();
84 delegate_push_client_->AddObserver(this);
87 void NonBlockingPushClient::Core::DestroyOnDelegateThread() {
88 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
89 DCHECK(delegate_push_client_.get());
90 delegate_push_client_->RemoveObserver(this);
91 delegate_push_client_.reset();
94 void NonBlockingPushClient::Core::UpdateSubscriptions(
95 const SubscriptionList& subscriptions) {
96 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
97 DCHECK(delegate_push_client_.get());
98 delegate_push_client_->UpdateSubscriptions(subscriptions);
101 void NonBlockingPushClient::Core::UpdateCredentials(
102 const std::string& email, const std::string& token) {
103 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
104 DCHECK(delegate_push_client_.get());
105 delegate_push_client_->UpdateCredentials(email, token);
108 void NonBlockingPushClient::Core::SendNotification(
109 const Notification& notification) {
110 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
111 DCHECK(delegate_push_client_.get());
112 delegate_push_client_->SendNotification(notification);
115 void NonBlockingPushClient::Core::SendPing() {
116 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
117 DCHECK(delegate_push_client_.get());
118 delegate_push_client_->SendPing();
121 void NonBlockingPushClient::Core::OnNotificationsEnabled() {
122 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
123 parent_task_runner_->PostTask(
125 base::Bind(&NonBlockingPushClient::OnNotificationsEnabled,
126 parent_push_client_));
129 void NonBlockingPushClient::Core::OnNotificationsDisabled(
130 NotificationsDisabledReason reason) {
131 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
132 parent_task_runner_->PostTask(
134 base::Bind(&NonBlockingPushClient::OnNotificationsDisabled,
135 parent_push_client_, reason));
138 void NonBlockingPushClient::Core::OnIncomingNotification(
139 const Notification& notification) {
140 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
141 parent_task_runner_->PostTask(
143 base::Bind(&NonBlockingPushClient::OnIncomingNotification,
144 parent_push_client_, notification));
147 void NonBlockingPushClient::Core::OnPingResponse() {
148 DCHECK(delegate_task_runner_->BelongsToCurrentThread());
149 parent_task_runner_->PostTask(
151 base::Bind(&NonBlockingPushClient::OnPingResponse,
152 parent_push_client_));
155 NonBlockingPushClient::NonBlockingPushClient(
156 const scoped_refptr<base::SingleThreadTaskRunner>& delegate_task_runner,
157 const CreateBlockingPushClientCallback&
158 create_blocking_push_client_callback)
159 : weak_ptr_factory_(this),
160 delegate_task_runner_(delegate_task_runner),
161 core_(new Core(delegate_task_runner_,
162 weak_ptr_factory_.GetWeakPtr())) {
163 delegate_task_runner_->PostTask(
165 base::Bind(&NonBlockingPushClient::Core::CreateOnDelegateThread,
166 core_.get(), create_blocking_push_client_callback));
169 NonBlockingPushClient::~NonBlockingPushClient() {
170 DCHECK(thread_checker_.CalledOnValidThread());
171 delegate_task_runner_->PostTask(
173 base::Bind(&NonBlockingPushClient::Core::DestroyOnDelegateThread,
177 void NonBlockingPushClient::AddObserver(PushClientObserver* observer) {
178 DCHECK(thread_checker_.CalledOnValidThread());
179 observers_.AddObserver(observer);
182 void NonBlockingPushClient::RemoveObserver(PushClientObserver* observer) {
183 DCHECK(thread_checker_.CalledOnValidThread());
184 observers_.RemoveObserver(observer);
187 void NonBlockingPushClient::UpdateSubscriptions(
188 const SubscriptionList& subscriptions) {
189 DCHECK(thread_checker_.CalledOnValidThread());
190 delegate_task_runner_->PostTask(
192 base::Bind(&NonBlockingPushClient::Core::UpdateSubscriptions,
193 core_.get(), subscriptions));
196 void NonBlockingPushClient::UpdateCredentials(
197 const std::string& email, const std::string& token) {
198 DCHECK(thread_checker_.CalledOnValidThread());
199 delegate_task_runner_->PostTask(
201 base::Bind(&NonBlockingPushClient::Core::UpdateCredentials,
202 core_.get(), email, token));
205 void NonBlockingPushClient::SendNotification(
206 const Notification& notification) {
207 DCHECK(thread_checker_.CalledOnValidThread());
208 delegate_task_runner_->PostTask(
210 base::Bind(&NonBlockingPushClient::Core::SendNotification, core_.get(),
214 void NonBlockingPushClient::SendPing() {
215 DCHECK(thread_checker_.CalledOnValidThread());
216 delegate_task_runner_->PostTask(
218 base::Bind(&NonBlockingPushClient::Core::SendPing, core_.get()));
221 void NonBlockingPushClient::OnNotificationsEnabled() {
222 DCHECK(thread_checker_.CalledOnValidThread());
223 FOR_EACH_OBSERVER(PushClientObserver, observers_,
224 OnNotificationsEnabled());
227 void NonBlockingPushClient::OnNotificationsDisabled(
228 NotificationsDisabledReason reason) {
229 DCHECK(thread_checker_.CalledOnValidThread());
230 FOR_EACH_OBSERVER(PushClientObserver, observers_,
231 OnNotificationsDisabled(reason));
234 void NonBlockingPushClient::OnIncomingNotification(
235 const Notification& notification) {
236 DCHECK(thread_checker_.CalledOnValidThread());
237 FOR_EACH_OBSERVER(PushClientObserver, observers_,
238 OnIncomingNotification(notification));
241 void NonBlockingPushClient::OnPingResponse() {
242 DCHECK(thread_checker_.CalledOnValidThread());
243 FOR_EACH_OBSERVER(PushClientObserver, observers_, OnPingResponse());
246 } // namespace notifier