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
<GeofencingDispatcher
>>::Leaky
26 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
28 GeofencingDispatcher
* const kHasBeenDeleted
=
29 reinterpret_cast<GeofencingDispatcher
*>(0x1);
31 int CurrentWorkerId() {
32 return WorkerTaskRunner::Instance()->CurrentWorkerId();
37 GeofencingDispatcher::GeofencingDispatcher(ThreadSafeSender
* sender
)
38 : thread_safe_sender_(sender
) {
39 g_dispatcher_tls
.Pointer()->Set(this);
42 GeofencingDispatcher::~GeofencingDispatcher() {
43 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
46 bool GeofencingDispatcher::Send(IPC::Message
* msg
) {
47 return thread_safe_sender_
->Send(msg
);
50 void GeofencingDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
52 IPC_BEGIN_MESSAGE_MAP(GeofencingDispatcher
, msg
)
53 IPC_MESSAGE_HANDLER(GeofencingMsg_RegisterRegionComplete
,
54 OnRegisterRegionComplete
)
55 IPC_MESSAGE_HANDLER(GeofencingMsg_UnregisterRegionComplete
,
56 OnUnregisterRegionComplete
)
57 IPC_MESSAGE_HANDLER(GeofencingMsg_GetRegisteredRegionsComplete
,
58 OnGetRegisteredRegionsComplete
)
59 IPC_MESSAGE_UNHANDLED(handled
= false)
61 DCHECK(handled
) << "Unhandled message:" << msg
.type();
64 void GeofencingDispatcher::RegisterRegion(
65 const blink::WebString
& region_id
,
66 const blink::WebCircularGeofencingRegion
& region
,
67 blink::WebServiceWorkerRegistration
* service_worker_registration
,
68 blink::WebGeofencingCallbacks
* callbacks
) {
70 int request_id
= region_registration_requests_
.Add(callbacks
);
71 // TODO(mek): Immediately reject requests lacking a service worker
72 // registration, without bouncing through browser process.
73 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
74 if (service_worker_registration
) {
75 serviceworker_registration_id
=
76 static_cast<WebServiceWorkerRegistrationImpl
*>(
77 service_worker_registration
)->registration_id();
79 Send(new GeofencingHostMsg_RegisterRegion(CurrentWorkerId(),
83 serviceworker_registration_id
));
86 void GeofencingDispatcher::UnregisterRegion(
87 const blink::WebString
& region_id
,
88 blink::WebServiceWorkerRegistration
* service_worker_registration
,
89 blink::WebGeofencingCallbacks
* callbacks
) {
91 int request_id
= region_unregistration_requests_
.Add(callbacks
);
92 // TODO(mek): Immediately reject requests lacking a service worker
93 // registration, without bouncing through browser process.
94 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
95 if (service_worker_registration
) {
96 serviceworker_registration_id
=
97 static_cast<WebServiceWorkerRegistrationImpl
*>(
98 service_worker_registration
)->registration_id();
100 Send(new GeofencingHostMsg_UnregisterRegion(CurrentWorkerId(),
103 serviceworker_registration_id
));
106 void GeofencingDispatcher::GetRegisteredRegions(
107 blink::WebServiceWorkerRegistration
* service_worker_registration
,
108 blink::WebGeofencingRegionsCallbacks
* callbacks
) {
110 int request_id
= get_registered_regions_requests_
.Add(callbacks
);
111 // TODO(mek): Immediately reject requests lacking a service worker
112 // registration, without bouncing through browser process.
113 int64 serviceworker_registration_id
= kInvalidServiceWorkerRegistrationId
;
114 if (service_worker_registration
) {
115 serviceworker_registration_id
=
116 static_cast<WebServiceWorkerRegistrationImpl
*>(
117 service_worker_registration
)->registration_id();
119 Send(new GeofencingHostMsg_GetRegisteredRegions(
120 CurrentWorkerId(), request_id
, serviceworker_registration_id
));
123 void GeofencingDispatcher::SetMockProvider(bool service_available
) {
124 Send(new GeofencingHostMsg_SetMockProvider(
125 service_available
? GeofencingMockState::SERVICE_AVAILABLE
126 : GeofencingMockState::SERVICE_UNAVAILABLE
));
129 void GeofencingDispatcher::ClearMockProvider() {
130 Send(new GeofencingHostMsg_SetMockProvider(GeofencingMockState::NONE
));
133 void GeofencingDispatcher::SetMockPosition(double latitude
, double longitude
) {
134 Send(new GeofencingHostMsg_SetMockPosition(latitude
, longitude
));
137 GeofencingDispatcher
* GeofencingDispatcher::GetOrCreateThreadSpecificInstance(
138 ThreadSafeSender
* thread_safe_sender
) {
139 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
140 NOTREACHED() << "Re-instantiating TLS GeofencingDispatcher.";
141 g_dispatcher_tls
.Pointer()->Set(NULL
);
143 if (g_dispatcher_tls
.Pointer()->Get())
144 return 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 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(new 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(new 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 scoped_ptr
<blink::WebVector
<blink::WebGeofencingRegistration
>> result(
204 new blink::WebVector
<blink::WebGeofencingRegistration
>(regions
.size()));
206 for (GeofencingRegistrations::const_iterator it
= regions
.begin();
209 (*result
)[index
].id
= blink::WebString::fromUTF8(it
->first
);
210 (*result
)[index
].region
= it
->second
;
212 callbacks
->onSuccess(result
.release());
214 callbacks
->onError(new WebGeofencingError(
215 WebGeofencingError::ErrorTypeAbort
,
216 blink::WebString::fromUTF8(GeofencingStatusToString(status
))));
218 get_registered_regions_requests_
.Remove(request_id
);
221 void GeofencingDispatcher::OnWorkerRunLoopStopped() {
225 } // namespace content