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/geofencing/geofencing_dispatcher.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/child/service_worker/web_service_worker_registration_impl.h"
12 #include "content/child/thread_safe_sender.h"
13 #include "content/child/worker_thread_task_runner.h"
14 #include "content/common/geofencing_messages.h"
15 #include "content/common/service_worker/service_worker_types.h"
16 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
17 #include "third_party/WebKit/public/platform/WebGeofencingError.h"
18 #include "third_party/WebKit/public/platform/WebGeofencingRegistration.h"
20 using blink::WebGeofencingError
;
26 base::LazyInstance
<base::ThreadLocalPointer
<GeofencingDispatcher
>>::Leaky
27 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
29 GeofencingDispatcher
* const kHasBeenDeleted
=
30 reinterpret_cast<GeofencingDispatcher
*>(0x1);
32 int CurrentWorkerId() {
33 return WorkerTaskRunner::Instance()->CurrentWorkerId();
38 GeofencingDispatcher::GeofencingDispatcher(ThreadSafeSender
* sender
)
39 : thread_safe_sender_(sender
) {
40 g_dispatcher_tls
.Pointer()->Set(this);
43 GeofencingDispatcher::~GeofencingDispatcher() {
44 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
47 bool GeofencingDispatcher::Send(IPC::Message
* msg
) {
48 return thread_safe_sender_
->Send(msg
);
51 void GeofencingDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
53 IPC_BEGIN_MESSAGE_MAP(GeofencingDispatcher
, msg
)
54 IPC_MESSAGE_HANDLER(GeofencingMsg_RegisterRegionComplete
,
55 OnRegisterRegionComplete
)
56 IPC_MESSAGE_HANDLER(GeofencingMsg_UnregisterRegionComplete
,
57 OnUnregisterRegionComplete
)
58 IPC_MESSAGE_HANDLER(GeofencingMsg_GetRegisteredRegionsComplete
,
59 OnGetRegisteredRegionsComplete
)
60 IPC_MESSAGE_UNHANDLED(handled
= false)
62 DCHECK(handled
) << "Unhandled message:" << msg
.type();
65 void GeofencingDispatcher::RegisterRegion(
66 const blink::WebString
& region_id
,
67 const blink::WebCircularGeofencingRegion
& region
,
68 blink::WebServiceWorkerRegistration
* service_worker_registration
,
69 blink::WebGeofencingCallbacks
* callbacks
) {
71 int request_id
= region_registration_requests_
.Add(callbacks
);
72 // TODO(mek): Immediately reject requests lacking a service worker
73 // registration, without bouncing through browser process.
74 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
75 if (service_worker_registration
) {
76 serviceworker_registration_id
=
77 static_cast<WebServiceWorkerRegistrationImpl
*>(
78 service_worker_registration
)->registration_id();
80 Send(new GeofencingHostMsg_RegisterRegion(CurrentWorkerId(),
84 serviceworker_registration_id
));
87 void GeofencingDispatcher::UnregisterRegion(
88 const blink::WebString
& region_id
,
89 blink::WebServiceWorkerRegistration
* service_worker_registration
,
90 blink::WebGeofencingCallbacks
* callbacks
) {
92 int request_id
= region_unregistration_requests_
.Add(callbacks
);
93 // TODO(mek): Immediately reject requests lacking a service worker
94 // registration, without bouncing through browser process.
95 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
96 if (service_worker_registration
) {
97 serviceworker_registration_id
=
98 static_cast<WebServiceWorkerRegistrationImpl
*>(
99 service_worker_registration
)->registration_id();
101 Send(new GeofencingHostMsg_UnregisterRegion(CurrentWorkerId(),
104 serviceworker_registration_id
));
107 void GeofencingDispatcher::GetRegisteredRegions(
108 blink::WebServiceWorkerRegistration
* service_worker_registration
,
109 blink::WebGeofencingRegionsCallbacks
* callbacks
) {
111 int request_id
= get_registered_regions_requests_
.Add(callbacks
);
112 // TODO(mek): Immediately reject requests lacking a service worker
113 // registration, without bouncing through browser process.
114 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
115 if (service_worker_registration
) {
116 serviceworker_registration_id
=
117 static_cast<WebServiceWorkerRegistrationImpl
*>(
118 service_worker_registration
)->registration_id();
120 Send(new GeofencingHostMsg_GetRegisteredRegions(
121 CurrentWorkerId(), request_id
, serviceworker_registration_id
));
124 GeofencingDispatcher
* GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
125 ThreadSafeSender
* thread_safe_sender
) {
126 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
127 NOTREACHED() << "Re-instantiating TLS GeofencingDispatcher.";
128 g_dispatcher_tls
.Pointer()->Set(NULL
);
130 if (g_dispatcher_tls
.Pointer()->Get())
131 return g_dispatcher_tls
.Pointer()->Get();
133 GeofencingDispatcher
* dispatcher
=
134 new GeofencingDispatcher(thread_safe_sender
);
135 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
136 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
140 GeofencingDispatcher
* GeofencingDispatcher::GetThreadSpecificInstance() {
141 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
143 return g_dispatcher_tls
.Pointer()->Get();
146 void GeofencingDispatcher::OnRegisterRegionComplete(int thread_id
,
148 GeofencingStatus status
) {
149 blink::WebGeofencingCallbacks
* callbacks
=
150 region_registration_requests_
.Lookup(request_id
);
155 if (status
== GEOFENCING_STATUS_OK
) {
156 callbacks
->onSuccess();
158 callbacks
->onError(new WebGeofencingError(
159 WebGeofencingError::ErrorTypeAbort
,
160 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
162 region_registration_requests_
.Remove(request_id
);
165 void GeofencingDispatcher::OnUnregisterRegionComplete(int thread_id
,
167 GeofencingStatus status
) {
168 blink::WebGeofencingCallbacks
* callbacks
=
169 region_unregistration_requests_
.Lookup(request_id
);
174 if (status
== GEOFENCING_STATUS_OK
) {
175 callbacks
->onSuccess();
177 callbacks
->onError(new WebGeofencingError(
178 WebGeofencingError::ErrorTypeAbort
,
179 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
181 region_unregistration_requests_
.Remove(request_id
);
184 void GeofencingDispatcher::OnGetRegisteredRegionsComplete(
187 GeofencingStatus status
,
188 const GeofencingRegistrations
& regions
) {
189 blink::WebGeofencingRegionsCallbacks
* callbacks
=
190 get_registered_regions_requests_
.Lookup(request_id
);
195 if (status
== GEOFENCING_STATUS_OK
) {
196 scoped_ptr
<blink::WebVector
<blink::WebGeofencingRegistration
>> result(
197 new blink::WebVector
<blink::WebGeofencingRegistration
>(regions
.size()));
199 for (GeofencingRegistrations::const_iterator it
= regions
.begin();
202 (*result
)[index
].id
= blink::WebString::fromUTF8(it
->first
);
203 (*result
)[index
].region
= it
->second
;
205 callbacks
->onSuccess(result
.release());
207 callbacks
->onError(new WebGeofencingError(
208 WebGeofencingError::ErrorTypeAbort
,
209 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
211 get_registered_regions_requests_
.Remove(request_id
);
214 void GeofencingDispatcher::OnWorkerRunLoopStopped() {
218 } // namespace content