1 // Copyright 2014 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 "content/child/push_messaging/push_provider.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h"
10 #include "base/threading/thread_local.h"
11 #include "content/child/push_messaging/push_dispatcher.h"
12 #include "content/child/service_worker/web_service_worker_registration_impl.h"
13 #include "content/child/thread_safe_sender.h"
14 #include "content/child/worker_task_runner.h"
15 #include "content/common/push_messaging_messages.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/platform/modules/push_messaging/WebPushRegistration.h"
22 int CurrentWorkerId() {
23 return WorkerTaskRunner::Instance()->CurrentWorkerId();
26 // Returns the id of the given |service_worker_registration|, which
27 // is only available on the implementation of the interface.
28 int64
GetServiceWorkerRegistrationId(
29 blink::WebServiceWorkerRegistration
* service_worker_registration
) {
30 return static_cast<WebServiceWorkerRegistrationImpl
*>(
31 service_worker_registration
)->registration_id();
36 static base::LazyInstance
<base::ThreadLocalPointer
<PushProvider
>>::Leaky
37 g_push_provider_tls
= LAZY_INSTANCE_INITIALIZER
;
39 PushProvider::PushProvider(ThreadSafeSender
* thread_safe_sender
,
40 PushDispatcher
* push_dispatcher
)
41 : thread_safe_sender_(thread_safe_sender
),
42 push_dispatcher_(push_dispatcher
) {
43 g_push_provider_tls
.Pointer()->Set(this);
46 PushProvider::~PushProvider() {
47 g_push_provider_tls
.Pointer()->Set(nullptr);
50 PushProvider
* PushProvider::ThreadSpecificInstance(
51 ThreadSafeSender
* thread_safe_sender
,
52 PushDispatcher
* push_dispatcher
) {
53 if (g_push_provider_tls
.Pointer()->Get())
54 return g_push_provider_tls
.Pointer()->Get();
56 PushProvider
* provider
=
57 new PushProvider(thread_safe_sender
, push_dispatcher
);
58 if (CurrentWorkerId())
59 WorkerTaskRunner::Instance()->AddStopObserver(provider
);
63 void PushProvider::OnWorkerRunLoopStopped() {
67 void PushProvider::registerPushMessaging(
68 blink::WebServiceWorkerRegistration
* service_worker_registration
,
69 blink::WebPushRegistrationCallbacks
* callbacks
) {
70 DCHECK(service_worker_registration
);
72 int request_id
= push_dispatcher_
->GenerateRequestId(CurrentWorkerId());
73 registration_callbacks_
.AddWithID(callbacks
, request_id
);
74 int64 service_worker_registration_id
=
75 GetServiceWorkerRegistrationId(service_worker_registration
);
76 thread_safe_sender_
->Send(new PushMessagingHostMsg_RegisterFromWorker(
77 request_id
, service_worker_registration_id
));
80 void PushProvider::unregister(
81 blink::WebServiceWorkerRegistration
* service_worker_registration
,
82 blink::WebPushUnregisterCallbacks
* callbacks
) {
83 DCHECK(service_worker_registration
);
86 int request_id
= push_dispatcher_
->GenerateRequestId(CurrentWorkerId());
87 unregister_callbacks_
.AddWithID(callbacks
, request_id
);
89 int64 service_worker_registration_id
=
90 GetServiceWorkerRegistrationId(service_worker_registration
);
91 thread_safe_sender_
->Send(new PushMessagingHostMsg_Unregister(
92 request_id
, service_worker_registration_id
));
95 void PushProvider::getRegistration(
96 blink::WebServiceWorkerRegistration
* service_worker_registration
,
97 blink::WebPushRegistrationCallbacks
* callbacks
) {
98 DCHECK(service_worker_registration
);
100 int request_id
= push_dispatcher_
->GenerateRequestId(CurrentWorkerId());
101 registration_callbacks_
.AddWithID(callbacks
, request_id
);
102 int64 service_worker_registration_id
=
103 GetServiceWorkerRegistrationId(service_worker_registration
);
104 thread_safe_sender_
->Send(new PushMessagingHostMsg_GetRegistration(
105 request_id
, service_worker_registration_id
));
108 void PushProvider::getPermissionStatus(
109 blink::WebServiceWorkerRegistration
* service_worker_registration
,
110 blink::WebPushPermissionStatusCallbacks
* callbacks
) {
111 DCHECK(service_worker_registration
);
113 int request_id
= push_dispatcher_
->GenerateRequestId(CurrentWorkerId());
114 permission_status_callbacks_
.AddWithID(callbacks
, request_id
);
115 int64 service_worker_registration_id
=
116 GetServiceWorkerRegistrationId(service_worker_registration
);
117 thread_safe_sender_
->Send(new PushMessagingHostMsg_GetPermissionStatus(
118 request_id
, service_worker_registration_id
));
121 bool PushProvider::OnMessageReceived(const IPC::Message
& message
) {
123 IPC_BEGIN_MESSAGE_MAP(PushProvider
, message
)
124 IPC_MESSAGE_HANDLER(PushMessagingMsg_RegisterFromWorkerSuccess
,
125 OnRegisterFromWorkerSuccess
);
126 IPC_MESSAGE_HANDLER(PushMessagingMsg_RegisterFromWorkerError
,
127 OnRegisterFromWorkerError
);
128 IPC_MESSAGE_HANDLER(PushMessagingMsg_UnregisterSuccess
,
129 OnUnregisterSuccess
);
130 IPC_MESSAGE_HANDLER(PushMessagingMsg_UnregisterError
,
132 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetRegistrationSuccess
,
133 OnGetRegistrationSuccess
);
134 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetRegistrationError
,
135 OnGetRegistrationError
);
136 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusSuccess
,
137 OnGetPermissionStatusSuccess
);
138 IPC_MESSAGE_HANDLER(PushMessagingMsg_GetPermissionStatusError
,
139 OnGetPermissionStatusError
);
140 IPC_MESSAGE_UNHANDLED(handled
= false)
141 IPC_END_MESSAGE_MAP()
146 void PushProvider::OnRegisterFromWorkerSuccess(
148 const GURL
& endpoint
,
149 const std::string
& registration_id
) {
150 blink::WebPushRegistrationCallbacks
* callbacks
=
151 registration_callbacks_
.Lookup(request_id
);
155 scoped_ptr
<blink::WebPushRegistration
> registration(
156 new blink::WebPushRegistration(
157 blink::WebString::fromUTF8(endpoint
.spec()),
158 blink::WebString::fromUTF8(registration_id
)));
159 callbacks
->onSuccess(registration
.release());
161 registration_callbacks_
.Remove(request_id
);
164 void PushProvider::OnRegisterFromWorkerError(int request_id
,
165 PushRegistrationStatus status
) {
166 blink::WebPushRegistrationCallbacks
* callbacks
=
167 registration_callbacks_
.Lookup(request_id
);
171 scoped_ptr
<blink::WebPushError
> error(new blink::WebPushError(
172 blink::WebPushError::ErrorTypeAbort
,
173 blink::WebString::fromUTF8(PushRegistrationStatusToString(status
))));
174 callbacks
->onError(error
.release());
176 registration_callbacks_
.Remove(request_id
);
179 void PushProvider::OnUnregisterSuccess(int request_id
, bool did_unregister
) {
180 blink::WebPushUnregisterCallbacks
* callbacks
=
181 unregister_callbacks_
.Lookup(request_id
);
185 callbacks
->onSuccess(&did_unregister
);
187 unregister_callbacks_
.Remove(request_id
);
190 void PushProvider::OnUnregisterError(
192 blink::WebPushError::ErrorType error_type
,
193 const std::string
& error_message
) {
194 blink::WebPushUnregisterCallbacks
* callbacks
=
195 unregister_callbacks_
.Lookup(request_id
);
199 scoped_ptr
<blink::WebPushError
> error(new blink::WebPushError(
200 error_type
, blink::WebString::fromUTF8(error_message
)));
201 callbacks
->onError(error
.release());
203 unregister_callbacks_
.Remove(request_id
);
206 void PushProvider::OnGetRegistrationSuccess(
208 const GURL
& endpoint
,
209 const std::string
& registration_id
) {
210 blink::WebPushRegistrationCallbacks
* callbacks
=
211 registration_callbacks_
.Lookup(request_id
);
215 scoped_ptr
<blink::WebPushRegistration
> registration(
216 new blink::WebPushRegistration(
217 blink::WebString::fromUTF8(endpoint
.spec()),
218 blink::WebString::fromUTF8(registration_id
)));
219 callbacks
->onSuccess(registration
.release());
221 registration_callbacks_
.Remove(request_id
);
224 void PushProvider::OnGetRegistrationError(
226 PushGetRegistrationStatus status
) {
227 blink::WebPushRegistrationCallbacks
* callbacks
=
228 registration_callbacks_
.Lookup(request_id
);
232 // We are only expecting an error if we can't find a registration.
233 callbacks
->onSuccess(nullptr);
235 registration_callbacks_
.Remove(request_id
);
238 void PushProvider::OnGetPermissionStatusSuccess(
240 blink::WebPushPermissionStatus status
) {
241 blink::WebPushPermissionStatusCallbacks
* callbacks
=
242 permission_status_callbacks_
.Lookup(request_id
);
246 callbacks
->onSuccess(&status
);
248 permission_status_callbacks_
.Remove(request_id
);
251 void PushProvider::OnGetPermissionStatusError(int request_id
) {
252 blink::WebPushPermissionStatusCallbacks
* callbacks
=
253 permission_status_callbacks_
.Lookup(request_id
);
257 callbacks
->onError();
259 permission_status_callbacks_
.Remove(request_id
);
262 } // namespace content