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 void GeofencingDispatcher::SetMockProvider(bool service_available
) {
125 Send(new GeofencingHostMsg_SetMockProvider(
126 service_available
? GeofencingMockState::SERVICE_AVAILABLE
127 : GeofencingMockState::SERVICE_UNAVAILABLE
));
130 void GeofencingDispatcher::ClearMockProvider() {
131 Send(new GeofencingHostMsg_SetMockProvider(GeofencingMockState::NONE
));
134 void GeofencingDispatcher::SetMockPosition(double latitude
, double longitude
) {
135 Send(new GeofencingHostMsg_SetMockPosition(latitude
, longitude
));
138 GeofencingDispatcher
* GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
139 ThreadSafeSender
* thread_safe_sender
) {
140 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
141 NOTREACHED() << "Re-instantiating TLS GeofencingDispatcher.";
142 g_dispatcher_tls
.Pointer()->Set(NULL
);
144 if (g_dispatcher_tls
.Pointer()->Get())
145 return g_dispatcher_tls
.Pointer()->Get();
147 GeofencingDispatcher
* dispatcher
=
148 new GeofencingDispatcher(thread_safe_sender
);
149 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
150 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
154 GeofencingDispatcher
* GeofencingDispatcher::GetThreadSpecificInstance() {
155 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
)
157 return g_dispatcher_tls
.Pointer()->Get();
160 void GeofencingDispatcher::OnRegisterRegionComplete(int thread_id
,
162 GeofencingStatus status
) {
163 blink::WebGeofencingCallbacks
* callbacks
=
164 region_registration_requests_
.Lookup(request_id
);
167 if (status
== GEOFENCING_STATUS_OK
) {
168 callbacks
->onSuccess();
170 callbacks
->onError(new WebGeofencingError(
171 WebGeofencingError::ErrorTypeAbort
,
172 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
174 region_registration_requests_
.Remove(request_id
);
177 void GeofencingDispatcher::OnUnregisterRegionComplete(int thread_id
,
179 GeofencingStatus status
) {
180 blink::WebGeofencingCallbacks
* callbacks
=
181 region_unregistration_requests_
.Lookup(request_id
);
184 if (status
== GEOFENCING_STATUS_OK
) {
185 callbacks
->onSuccess();
187 callbacks
->onError(new WebGeofencingError(
188 WebGeofencingError::ErrorTypeAbort
,
189 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
191 region_unregistration_requests_
.Remove(request_id
);
194 void GeofencingDispatcher::OnGetRegisteredRegionsComplete(
197 GeofencingStatus status
,
198 const GeofencingRegistrations
& regions
) {
199 blink::WebGeofencingRegionsCallbacks
* callbacks
=
200 get_registered_regions_requests_
.Lookup(request_id
);
203 if (status
== GEOFENCING_STATUS_OK
) {
204 scoped_ptr
<blink::WebVector
<blink::WebGeofencingRegistration
>> result(
205 new blink::WebVector
<blink::WebGeofencingRegistration
>(regions
.size()));
207 for (GeofencingRegistrations::const_iterator it
= regions
.begin();
210 (*result
)[index
].id
= blink::WebString::fromUTF8(it
->first
);
211 (*result
)[index
].region
= it
->second
;
213 callbacks
->onSuccess(result
.release());
215 callbacks
->onError(new WebGeofencingError(
216 WebGeofencingError::ErrorTypeAbort
,
217 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
219 get_registered_regions_requests_
.Remove(request_id
);
222 void GeofencingDispatcher::OnWorkerRunLoopStopped() {
226 } // namespace content