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/common/geofencing_messages.h"
14 #include "content/common/service_worker/service_worker_types.h"
15 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
16 #include "third_party/WebKit/public/platform/WebGeofencingError.h"
17 #include "third_party/WebKit/public/platform/WebGeofencingRegistration.h"
19 using blink::WebGeofencingError
;
25 base::LazyInstance
<base::ThreadLocalPointer
<void>>::Leaky g_dispatcher_tls
=
26 LAZY_INSTANCE_INITIALIZER
;
28 void* const kHasBeenDeleted
= reinterpret_cast<void*>(0x1);
30 int CurrentWorkerId() {
31 return WorkerTaskRunner::Instance()->CurrentWorkerId();
36 GeofencingDispatcher::GeofencingDispatcher(ThreadSafeSender
* sender
)
37 : thread_safe_sender_(sender
) {
38 g_dispatcher_tls
.Pointer()->Set(static_cast<void*>(this));
41 GeofencingDispatcher::~GeofencingDispatcher() {
42 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
45 bool GeofencingDispatcher::Send(IPC::Message
* msg
) {
46 return thread_safe_sender_
->Send(msg
);
49 void GeofencingDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
51 IPC_BEGIN_MESSAGE_MAP(GeofencingDispatcher
, msg
)
52 IPC_MESSAGE_HANDLER(GeofencingMsg_RegisterRegionComplete
,
53 OnRegisterRegionComplete
)
54 IPC_MESSAGE_HANDLER(GeofencingMsg_UnregisterRegionComplete
,
55 OnUnregisterRegionComplete
)
56 IPC_MESSAGE_HANDLER(GeofencingMsg_GetRegisteredRegionsComplete
,
57 OnGetRegisteredRegionsComplete
)
58 IPC_MESSAGE_UNHANDLED(handled
= false)
60 DCHECK(handled
) << "Unhandled message:" << msg
.type();
63 void GeofencingDispatcher::RegisterRegion(
64 const blink::WebString
& region_id
,
65 const blink::WebCircularGeofencingRegion
& region
,
66 blink::WebServiceWorkerRegistration
* service_worker_registration
,
67 blink::WebGeofencingCallbacks
* callbacks
) {
69 int request_id
= region_registration_requests_
.Add(callbacks
);
70 // TODO(mek): Immediately reject requests lacking a service worker
71 // registration, without bouncing through browser process.
72 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
73 if (service_worker_registration
) {
74 serviceworker_registration_id
=
75 static_cast<WebServiceWorkerRegistrationImpl
*>(
76 service_worker_registration
)->registration_id();
78 Send(new GeofencingHostMsg_RegisterRegion(CurrentWorkerId(),
82 serviceworker_registration_id
));
85 void GeofencingDispatcher::UnregisterRegion(
86 const blink::WebString
& region_id
,
87 blink::WebServiceWorkerRegistration
* service_worker_registration
,
88 blink::WebGeofencingCallbacks
* callbacks
) {
90 int request_id
= region_unregistration_requests_
.Add(callbacks
);
91 // TODO(mek): Immediately reject requests lacking a service worker
92 // registration, without bouncing through browser process.
93 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
94 if (service_worker_registration
) {
95 serviceworker_registration_id
=
96 static_cast<WebServiceWorkerRegistrationImpl
*>(
97 service_worker_registration
)->registration_id();
99 Send(new GeofencingHostMsg_UnregisterRegion(CurrentWorkerId(),
102 serviceworker_registration_id
));
105 void GeofencingDispatcher::GetRegisteredRegions(
106 blink::WebServiceWorkerRegistration
* service_worker_registration
,
107 blink::WebGeofencingRegionsCallbacks
* callbacks
) {
109 int request_id
= get_registered_regions_requests_
.Add(callbacks
);
110 // TODO(mek): Immediately reject requests lacking a service worker
111 // registration, without bouncing through browser process.
112 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
113 if (service_worker_registration
) {
114 serviceworker_registration_id
=
115 static_cast<WebServiceWorkerRegistrationImpl
*>(
116 service_worker_registration
)->registration_id();
118 Send(new GeofencingHostMsg_GetRegisteredRegions(
119 CurrentWorkerId(), request_id
, serviceworker_registration_id
));
122 void GeofencingDispatcher::SetMockProvider(bool service_available
) {
123 Send(new GeofencingHostMsg_SetMockProvider(
124 service_available
? GeofencingMockState::SERVICE_AVAILABLE
125 : GeofencingMockState::SERVICE_UNAVAILABLE
));
128 void GeofencingDispatcher::ClearMockProvider() {
129 Send(new GeofencingHostMsg_SetMockProvider(GeofencingMockState::NONE
));
132 void GeofencingDispatcher::SetMockPosition(double latitude
, double longitude
) {
133 Send(new GeofencingHostMsg_SetMockPosition(latitude
, longitude
));
136 GeofencingDispatcher
* GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
137 ThreadSafeSender
* thread_safe_sender
) {
138 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
139 NOTREACHED() << "Re-instantiating TLS GeofencingDispatcher.";
140 g_dispatcher_tls
.Pointer()->Set(NULL
);
142 if (g_dispatcher_tls
.Pointer()->Get())
143 return static_cast<GeofencingDispatcher
*>(
144 g_dispatcher_tls
.Pointer()->Get());
146 GeofencingDispatcher
* dispatcher
=
147 new GeofencingDispatcher(thread_safe_sender
);
148 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
149 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
153 GeofencingDispatcher
* GeofencingDispatcher::GetThreadSpecificInstance() {
154 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
156 return static_cast<GeofencingDispatcher
*>(g_dispatcher_tls
.Pointer()->Get());
159 void GeofencingDispatcher::OnRegisterRegionComplete(int thread_id
,
161 GeofencingStatus status
) {
162 blink::WebGeofencingCallbacks
* callbacks
=
163 region_registration_requests_
.Lookup(request_id
);
166 if (status
== GEOFENCING_STATUS_OK
) {
167 callbacks
->onSuccess();
169 callbacks
->onError(WebGeofencingError(
170 WebGeofencingError::ErrorTypeAbort
,
171 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
173 region_registration_requests_
.Remove(request_id
);
176 void GeofencingDispatcher::OnUnregisterRegionComplete(int thread_id
,
178 GeofencingStatus status
) {
179 blink::WebGeofencingCallbacks
* callbacks
=
180 region_unregistration_requests_
.Lookup(request_id
);
183 if (status
== GEOFENCING_STATUS_OK
) {
184 callbacks
->onSuccess();
186 callbacks
->onError(WebGeofencingError(
187 WebGeofencingError::ErrorTypeAbort
,
188 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
190 region_unregistration_requests_
.Remove(request_id
);
193 void GeofencingDispatcher::OnGetRegisteredRegionsComplete(
196 GeofencingStatus status
,
197 const GeofencingRegistrations
& regions
) {
198 blink::WebGeofencingRegionsCallbacks
* callbacks
=
199 get_registered_regions_requests_
.Lookup(request_id
);
202 if (status
== GEOFENCING_STATUS_OK
) {
203 blink::WebVector
<blink::WebGeofencingRegistration
> result(regions
.size());
205 for (GeofencingRegistrations::const_iterator it
= regions
.begin();
208 result
[index
].id
= blink::WebString::fromUTF8(it
->first
);
209 result
[index
].region
= it
->second
;
211 callbacks
->onSuccess(result
);
213 callbacks
->onError(WebGeofencingError(
214 WebGeofencingError::ErrorTypeAbort
,
215 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
217 get_registered_regions_requests_
.Remove(request_id
);
220 void GeofencingDispatcher::OnWorkerRunLoopStopped() {
224 } // namespace content