Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / jingle / notifier / listener / non_blocking_push_client.cc
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/non_blocking_push_client.h"
6
7 #include "base/bind.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"
12
13 namespace notifier {
14
15 // All methods are called on the delegate thread unless specified
16 // otherwise.
17 class NonBlockingPushClient::Core
18     : public base::RefCountedThreadSafe<NonBlockingPushClient::Core>,
19       public PushClientObserver {
20  public:
21   // Called on the parent thread.
22   explicit Core(
23       const scoped_refptr<base::SingleThreadTaskRunner>&
24           delegate_task_runner,
25       const base::WeakPtr<NonBlockingPushClient>& parent_push_client);
26
27   // Must be called after being created.
28   //
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);
34
35   // Must be called before being destroyed.
36   void DestroyOnDelegateThread();
37
38   void UpdateSubscriptions(const SubscriptionList& subscriptions);
39   void UpdateCredentials(const std::string& email, const std::string& token);
40   void SendNotification(const Notification& data);
41   void SendPing();
42
43   void OnNotificationsEnabled() override;
44   void OnNotificationsDisabled(NotificationsDisabledReason reason) override;
45   void OnIncomingNotification(const Notification& notification) override;
46   void OnPingResponse() override;
47
48  private:
49   friend class base::RefCountedThreadSafe<NonBlockingPushClient::Core>;
50
51   // Called on either the parent thread or the delegate thread.
52   ~Core() override;
53
54   const scoped_refptr<base::SingleThreadTaskRunner> parent_task_runner_;
55   const scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
56
57   const base::WeakPtr<NonBlockingPushClient> parent_push_client_;
58   scoped_ptr<PushClient> delegate_push_client_;
59
60   DISALLOW_COPY_AND_ASSIGN(Core);
61 };
62
63 NonBlockingPushClient::Core::Core(
64     const scoped_refptr<base::SingleThreadTaskRunner>& delegate_task_runner,
65     const base::WeakPtr<NonBlockingPushClient>& parent_push_client)
66     : parent_task_runner_(base::MessageLoopProxy::current()),
67       delegate_task_runner_(delegate_task_runner),
68       parent_push_client_(parent_push_client) {}
69
70 NonBlockingPushClient::Core::~Core() {
71   DCHECK(parent_task_runner_->BelongsToCurrentThread() ||
72          delegate_task_runner_->BelongsToCurrentThread());
73   DCHECK(!delegate_push_client_.get());
74 }
75
76 void NonBlockingPushClient::Core::CreateOnDelegateThread(
77     const CreateBlockingPushClientCallback&
78         create_blocking_push_client_callback) {
79   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
80   DCHECK(!delegate_push_client_.get());
81   delegate_push_client_ = create_blocking_push_client_callback.Run();
82   delegate_push_client_->AddObserver(this);
83 }
84
85 void NonBlockingPushClient::Core::DestroyOnDelegateThread() {
86   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
87   DCHECK(delegate_push_client_.get());
88   delegate_push_client_->RemoveObserver(this);
89   delegate_push_client_.reset();
90 }
91
92 void NonBlockingPushClient::Core::UpdateSubscriptions(
93     const SubscriptionList& subscriptions) {
94   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
95   DCHECK(delegate_push_client_.get());
96   delegate_push_client_->UpdateSubscriptions(subscriptions);
97 }
98
99 void NonBlockingPushClient::Core::UpdateCredentials(
100       const std::string& email, const std::string& token) {
101   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
102   DCHECK(delegate_push_client_.get());
103   delegate_push_client_->UpdateCredentials(email, token);
104 }
105
106 void NonBlockingPushClient::Core::SendNotification(
107     const Notification& notification) {
108   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
109   DCHECK(delegate_push_client_.get());
110   delegate_push_client_->SendNotification(notification);
111 }
112
113 void NonBlockingPushClient::Core::SendPing() {
114   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
115   DCHECK(delegate_push_client_.get());
116   delegate_push_client_->SendPing();
117 }
118
119 void NonBlockingPushClient::Core::OnNotificationsEnabled() {
120   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
121   parent_task_runner_->PostTask(
122       FROM_HERE,
123       base::Bind(&NonBlockingPushClient::OnNotificationsEnabled,
124                  parent_push_client_));
125 }
126
127 void NonBlockingPushClient::Core::OnNotificationsDisabled(
128     NotificationsDisabledReason reason) {
129   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
130   parent_task_runner_->PostTask(
131       FROM_HERE,
132       base::Bind(&NonBlockingPushClient::OnNotificationsDisabled,
133                  parent_push_client_, reason));
134 }
135
136 void NonBlockingPushClient::Core::OnIncomingNotification(
137     const Notification& notification) {
138   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
139   parent_task_runner_->PostTask(
140       FROM_HERE,
141       base::Bind(&NonBlockingPushClient::OnIncomingNotification,
142                  parent_push_client_, notification));
143 }
144
145 void NonBlockingPushClient::Core::OnPingResponse() {
146   DCHECK(delegate_task_runner_->BelongsToCurrentThread());
147   parent_task_runner_->PostTask(
148       FROM_HERE,
149       base::Bind(&NonBlockingPushClient::OnPingResponse,
150                  parent_push_client_));
151 }
152
153 NonBlockingPushClient::NonBlockingPushClient(
154     const scoped_refptr<base::SingleThreadTaskRunner>& delegate_task_runner,
155     const CreateBlockingPushClientCallback&
156         create_blocking_push_client_callback)
157     : delegate_task_runner_(delegate_task_runner),
158       weak_ptr_factory_(this) {
159   core_ = new Core(delegate_task_runner_, weak_ptr_factory_.GetWeakPtr());
160   delegate_task_runner_->PostTask(
161       FROM_HERE,
162       base::Bind(&NonBlockingPushClient::Core::CreateOnDelegateThread,
163                  core_.get(), create_blocking_push_client_callback));
164 }
165
166 NonBlockingPushClient::~NonBlockingPushClient() {
167   DCHECK(thread_checker_.CalledOnValidThread());
168   delegate_task_runner_->PostTask(
169       FROM_HERE,
170       base::Bind(&NonBlockingPushClient::Core::DestroyOnDelegateThread,
171                  core_.get()));
172 }
173
174 void NonBlockingPushClient::AddObserver(PushClientObserver* observer) {
175   DCHECK(thread_checker_.CalledOnValidThread());
176   observers_.AddObserver(observer);
177 }
178
179 void NonBlockingPushClient::RemoveObserver(PushClientObserver* observer) {
180   DCHECK(thread_checker_.CalledOnValidThread());
181   observers_.RemoveObserver(observer);
182 }
183
184 void NonBlockingPushClient::UpdateSubscriptions(
185     const SubscriptionList& subscriptions) {
186   DCHECK(thread_checker_.CalledOnValidThread());
187   delegate_task_runner_->PostTask(
188       FROM_HERE,
189       base::Bind(&NonBlockingPushClient::Core::UpdateSubscriptions,
190                  core_.get(), subscriptions));
191 }
192
193 void NonBlockingPushClient::UpdateCredentials(
194     const std::string& email, const std::string& token) {
195   DCHECK(thread_checker_.CalledOnValidThread());
196   delegate_task_runner_->PostTask(
197       FROM_HERE,
198       base::Bind(&NonBlockingPushClient::Core::UpdateCredentials,
199                  core_.get(), email, token));
200 }
201
202 void NonBlockingPushClient::SendNotification(
203     const Notification& notification) {
204   DCHECK(thread_checker_.CalledOnValidThread());
205   delegate_task_runner_->PostTask(
206       FROM_HERE,
207       base::Bind(&NonBlockingPushClient::Core::SendNotification, core_.get(),
208                  notification));
209 }
210
211 void NonBlockingPushClient::SendPing() {
212   DCHECK(thread_checker_.CalledOnValidThread());
213   delegate_task_runner_->PostTask(
214       FROM_HERE,
215       base::Bind(&NonBlockingPushClient::Core::SendPing, core_.get()));
216 }
217
218 void NonBlockingPushClient::OnNotificationsEnabled() {
219   DCHECK(thread_checker_.CalledOnValidThread());
220   FOR_EACH_OBSERVER(PushClientObserver, observers_,
221                     OnNotificationsEnabled());
222 }
223
224 void NonBlockingPushClient::OnNotificationsDisabled(
225     NotificationsDisabledReason reason) {
226   DCHECK(thread_checker_.CalledOnValidThread());
227   FOR_EACH_OBSERVER(PushClientObserver, observers_,
228                     OnNotificationsDisabled(reason));
229 }
230
231 void NonBlockingPushClient::OnIncomingNotification(
232     const Notification& notification) {
233   DCHECK(thread_checker_.CalledOnValidThread());
234   FOR_EACH_OBSERVER(PushClientObserver, observers_,
235                     OnIncomingNotification(notification));
236 }
237
238 void NonBlockingPushClient::OnPingResponse() {
239   DCHECK(thread_checker_.CalledOnValidThread());
240   FOR_EACH_OBSERVER(PushClientObserver, observers_, OnPingResponse());
241 }
242
243 }  // namespace notifier