OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 "content/child/background_sync/background_sync_provider_thread_proxy.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/lazy_instance.h" | |
10 #include "base/location.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/single_thread_task_runner.h" | |
13 #include "base/threading/thread_local.h" | |
14 #include "content/child/background_sync/background_sync_provider.h" | |
15 | |
16 using base::LazyInstance; | |
17 using base::ThreadLocalPointer; | |
18 | |
19 namespace content { | |
20 | |
21 namespace { | |
22 | |
23 template <typename T> | |
24 struct WebCallbacksMatcher; | |
25 | |
26 template <typename Stype, typename Ttype> | |
27 struct WebCallbacksMatcher<blink::WebCallbacks<Stype, Ttype>> { | |
28 using S = Stype; | |
29 using T = Ttype; | |
30 using WebCallbacks = typename blink::WebCallbacks<S, T>; | |
31 }; | |
32 | |
33 // CallbackThreadAdapter<WebCallbacks<S, T>> is a wrapper for WebCallbacks<S, T> | |
34 // which switches to a specific thread before calling the wrapped callback's | |
35 // onSuccess or onError methods. | |
36 // | |
37 // Takes ownership of the WebCallbacks object which it wraps. | |
38 template <typename X> | |
39 class CallbackThreadAdapter : public WebCallbacksMatcher<X>::WebCallbacks { | |
40 using S = typename WebCallbacksMatcher<X>::S; | |
41 using T = typename WebCallbacksMatcher<X>::T; | |
42 using OnSuccessType = void (blink::WebCallbacks<S, T>::*)(S); | |
43 using OnErrorType = void (blink::WebCallbacks<S, T>::*)(T); | |
44 | |
45 public: | |
46 CallbackThreadAdapter(scoped_ptr<blink::WebCallbacks<S, T>> callbacks, | |
47 int worker_thread_id) | |
48 : worker_thread_id_(worker_thread_id) { | |
49 callbacks_.reset(callbacks.release()); | |
50 } | |
51 | |
52 virtual void onSuccess(S results) { | |
53 OnSuccessType on_success = &blink::WebCallbacks<S, T>::onSuccess; | |
54 // If the worker thread has been destroyed, then this task will be | |
55 // silently discarded. | |
56 WorkerTaskRunner::Instance()->PostTask( | |
57 worker_thread_id_, | |
58 base::Bind(on_success, base::Owned(callbacks_.release()), results)); | |
59 } | |
60 | |
61 virtual void onError(T error) { | |
62 OnErrorType on_error = &blink::WebCallbacks<S, T>::onError; | |
63 // If the worker thread has been destroyed, then this task will be | |
64 // silently discarded. | |
65 WorkerTaskRunner::Instance()->PostTask( | |
66 worker_thread_id_, | |
67 base::Bind(on_error, base::Owned(callbacks_.release()), error)); | |
68 } | |
69 | |
70 private: | |
71 scoped_ptr<blink::WebCallbacks<S, T>> callbacks_; | |
72 int worker_thread_id_; | |
73 }; | |
74 | |
75 LazyInstance<ThreadLocalPointer<BackgroundSyncProviderThreadProxy>>::Leaky | |
76 g_sync_provider_tls = LAZY_INSTANCE_INITIALIZER; | |
77 | |
78 void DuplicateRegistrationHandleCallbackOnSWThread( | |
79 const BackgroundSyncProviderThreadProxy:: | |
80 DuplicateRegistrationHandleCallback& callback, | |
81 BackgroundSyncError error, | |
82 SyncRegistrationPtr registration) { | |
83 callback.Run(error, registration.Pass()); | |
84 } | |
85 | |
86 void DuplicateRegistrationHandleCallbackOnMainThread( | |
87 int worker_thread_id, | |
88 const BackgroundSyncProviderThreadProxy:: | |
89 DuplicateRegistrationHandleCallback& callback, | |
90 BackgroundSyncError error, | |
91 SyncRegistrationPtr registration) { | |
92 WorkerTaskRunner::Instance()->PostTask( | |
93 worker_thread_id, | |
94 base::Bind(&DuplicateRegistrationHandleCallbackOnSWThread, callback, | |
95 error, base::Passed(registration.Pass()))); | |
96 } | |
97 | |
98 } // anonymous namespace | |
99 | |
100 // static | |
101 BackgroundSyncProviderThreadProxy* | |
102 BackgroundSyncProviderThreadProxy::GetThreadInstance( | |
103 base::SingleThreadTaskRunner* main_thread_task_runner, | |
104 BackgroundSyncProvider* sync_provider) { | |
105 if (g_sync_provider_tls.Pointer()->Get()) | |
106 return g_sync_provider_tls.Pointer()->Get(); | |
107 | |
108 if (!WorkerThread::GetCurrentId()) { | |
109 // This could happen if GetThreadInstance is called very late (say by a | |
110 // garbage collected SyncRegistration). | |
111 return nullptr; | |
112 } | |
113 | |
114 BackgroundSyncProviderThreadProxy* instance = | |
115 new BackgroundSyncProviderThreadProxy(main_thread_task_runner, | |
116 sync_provider); | |
117 WorkerThread::AddObserver(instance); | |
118 return instance; | |
119 } | |
120 | |
121 void BackgroundSyncProviderThreadProxy::registerBackgroundSync( | |
122 const blink::WebSyncRegistration* options, | |
123 blink::WebServiceWorkerRegistration* service_worker_registration, | |
124 bool requested_from_service_worker, | |
125 blink::WebSyncRegistrationCallbacks* callbacks) { | |
126 DCHECK(options); | |
127 DCHECK(service_worker_registration); | |
128 DCHECK(callbacks); | |
129 main_thread_task_runner_->PostTask( | |
130 FROM_HERE, | |
131 base::Bind( | |
132 &BackgroundSyncProvider::registerBackgroundSync, | |
133 base::Unretained(sync_provider_), options, | |
134 service_worker_registration, requested_from_service_worker, | |
135 new CallbackThreadAdapter<blink::WebSyncRegistrationCallbacks>( | |
136 make_scoped_ptr(callbacks), WorkerThread::GetCurrentId()))); | |
137 } | |
138 | |
139 void BackgroundSyncProviderThreadProxy::unregisterBackgroundSync( | |
140 int64_t handle_id, | |
141 blink::WebServiceWorkerRegistration* service_worker_registration, | |
142 blink::WebSyncUnregistrationCallbacks* callbacks) { | |
143 DCHECK(service_worker_registration); | |
144 DCHECK(callbacks); | |
145 main_thread_task_runner_->PostTask( | |
146 FROM_HERE, | |
147 base::Bind( | |
148 &BackgroundSyncProvider::unregisterBackgroundSync, | |
149 base::Unretained(sync_provider_), handle_id, | |
150 service_worker_registration, | |
151 new CallbackThreadAdapter<blink::WebSyncUnregistrationCallbacks>( | |
152 make_scoped_ptr(callbacks), WorkerThread::GetCurrentId()))); | |
153 } | |
154 | |
155 void BackgroundSyncProviderThreadProxy::getRegistration( | |
156 blink::WebSyncRegistration::Periodicity periodicity, | |
157 const blink::WebString& tag, | |
158 blink::WebServiceWorkerRegistration* service_worker_registration, | |
159 blink::WebSyncRegistrationCallbacks* callbacks) { | |
160 DCHECK(service_worker_registration); | |
161 DCHECK(callbacks); | |
162 main_thread_task_runner_->PostTask( | |
163 FROM_HERE, | |
164 base::Bind( | |
165 &BackgroundSyncProvider::getRegistration, | |
166 base::Unretained(sync_provider_), periodicity, | |
167 // We cast WebString to string16 before crossing threads | |
168 // for thread-safety. | |
169 static_cast<base::string16>(tag), service_worker_registration, | |
170 new CallbackThreadAdapter<blink::WebSyncRegistrationCallbacks>( | |
171 make_scoped_ptr(callbacks), WorkerThread::GetCurrentId()))); | |
172 } | |
173 | |
174 void BackgroundSyncProviderThreadProxy::getRegistrations( | |
175 blink::WebSyncRegistration::Periodicity periodicity, | |
176 blink::WebServiceWorkerRegistration* service_worker_registration, | |
177 blink::WebSyncGetRegistrationsCallbacks* callbacks) { | |
178 DCHECK(service_worker_registration); | |
179 DCHECK(callbacks); | |
180 main_thread_task_runner_->PostTask( | |
181 FROM_HERE, | |
182 base::Bind( | |
183 &BackgroundSyncProvider::getRegistrations, | |
184 base::Unretained(sync_provider_), periodicity, | |
185 service_worker_registration, | |
186 new CallbackThreadAdapter<blink::WebSyncGetRegistrationsCallbacks>( | |
187 make_scoped_ptr(callbacks), WorkerThread::GetCurrentId()))); | |
188 } | |
189 | |
190 void BackgroundSyncProviderThreadProxy::getPermissionStatus( | |
191 blink::WebSyncRegistration::Periodicity periodicity, | |
192 blink::WebServiceWorkerRegistration* service_worker_registration, | |
193 blink::WebSyncGetPermissionStatusCallbacks* callbacks) { | |
194 DCHECK(service_worker_registration); | |
195 DCHECK(callbacks); | |
196 main_thread_task_runner_->PostTask( | |
197 FROM_HERE, | |
198 base::Bind( | |
199 &BackgroundSyncProvider::getPermissionStatus, | |
200 base::Unretained(sync_provider_), periodicity, | |
201 service_worker_registration, | |
202 new CallbackThreadAdapter<blink::WebSyncGetPermissionStatusCallbacks>( | |
203 make_scoped_ptr(callbacks), WorkerThread::GetCurrentId()))); | |
204 } | |
205 | |
206 void BackgroundSyncProviderThreadProxy::releaseRegistration(int64_t handle_id) { | |
207 main_thread_task_runner_->PostTask( | |
208 FROM_HERE, base::Bind(&BackgroundSyncProvider::releaseRegistration, | |
209 base::Unretained(sync_provider_), handle_id)); | |
210 } | |
211 | |
212 void BackgroundSyncProviderThreadProxy::notifyWhenDone( | |
213 int64_t handle_id, | |
214 blink::WebSyncNotifyWhenDoneCallbacks* callbacks) { | |
215 DCHECK(callbacks); | |
216 | |
217 main_thread_task_runner_->PostTask( | |
218 FROM_HERE, | |
219 base::Bind( | |
220 &BackgroundSyncProvider::notifyWhenDone, | |
221 base::Unretained(sync_provider_), handle_id, | |
222 new CallbackThreadAdapter<blink::WebSyncNotifyWhenDoneCallbacks>( | |
223 make_scoped_ptr(callbacks), WorkerThread::GetCurrentId()))); | |
224 } | |
225 | |
226 void BackgroundSyncProviderThreadProxy::DuplicateRegistrationHandle( | |
227 int64_t handle_id, | |
228 const DuplicateRegistrationHandleCallback& callback) { | |
229 main_thread_task_runner_->PostTask( | |
230 FROM_HERE, | |
231 base::Bind(&BackgroundSyncProvider::DuplicateRegistrationHandle, | |
232 base::Unretained(sync_provider_), handle_id, | |
233 base::Bind(&DuplicateRegistrationHandleCallbackOnMainThread, | |
234 WorkerThread::GetCurrentId(), callback))); | |
235 } | |
236 | |
237 void BackgroundSyncProviderThreadProxy::WillStopCurrentWorkerThread() { | |
238 delete this; | |
239 } | |
240 | |
241 BackgroundSyncProviderThreadProxy::BackgroundSyncProviderThreadProxy( | |
242 base::SingleThreadTaskRunner* main_thread_task_runner, | |
243 BackgroundSyncProvider* sync_provider) | |
244 : main_thread_task_runner_(main_thread_task_runner), | |
245 sync_provider_(sync_provider) { | |
246 g_sync_provider_tls.Pointer()->Set(this); | |
247 } | |
248 | |
249 BackgroundSyncProviderThreadProxy::~BackgroundSyncProviderThreadProxy() { | |
250 g_sync_provider_tls.Pointer()->Set(nullptr); | |
251 } | |
252 | |
253 } // namespace content | |
OLD | NEW |