Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / content / child / geofencing / geofencing_dispatcher.cc
blobae2f9e2c691be5d3132d9790fa1ba65f45876016
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;
21 namespace content {
23 namespace {
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 WorkerThread::GetCurrentId();
34 } // namespace
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) {
50 bool handled = true;
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)
59 IPC_END_MESSAGE_MAP()
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) {
68 DCHECK(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(),
79 request_id,
80 region_id.utf8(),
81 region,
82 serviceworker_registration_id));
85 void GeofencingDispatcher::UnregisterRegion(
86 const blink::WebString& region_id,
87 blink::WebServiceWorkerRegistration* service_worker_registration,
88 blink::WebGeofencingCallbacks* callbacks) {
89 DCHECK(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(),
100 request_id,
101 region_id.utf8(),
102 serviceworker_registration_id));
105 void GeofencingDispatcher::GetRegisteredRegions(
106 blink::WebServiceWorkerRegistration* service_worker_registration,
107 blink::WebGeofencingRegionsCallbacks* callbacks) {
108 DCHECK(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 (WorkerThread::GetCurrentId())
149 WorkerThread::AddObserver(dispatcher);
150 return dispatcher;
153 GeofencingDispatcher* GeofencingDispatcher::GetThreadSpecificInstance() {
154 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
155 return NULL;
156 return static_cast<GeofencingDispatcher*>(g_dispatcher_tls.Pointer()->Get());
159 void GeofencingDispatcher::OnRegisterRegionComplete(int thread_id,
160 int request_id,
161 GeofencingStatus status) {
162 blink::WebGeofencingCallbacks* callbacks =
163 region_registration_requests_.Lookup(request_id);
164 DCHECK(callbacks);
166 if (status == GEOFENCING_STATUS_OK) {
167 callbacks->onSuccess();
168 } else {
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,
177 int request_id,
178 GeofencingStatus status) {
179 blink::WebGeofencingCallbacks* callbacks =
180 region_unregistration_requests_.Lookup(request_id);
181 DCHECK(callbacks);
183 if (status == GEOFENCING_STATUS_OK) {
184 callbacks->onSuccess();
185 } else {
186 callbacks->onError(WebGeofencingError(
187 WebGeofencingError::ErrorTypeAbort,
188 blink::WebString::fromUTF8(GeofencingStatusToString(status))));
190 region_unregistration_requests_.Remove(request_id);
193 void GeofencingDispatcher::OnGetRegisteredRegionsComplete(
194 int thread_id,
195 int request_id,
196 GeofencingStatus status,
197 const GeofencingRegistrations& regions) {
198 blink::WebGeofencingRegionsCallbacks* callbacks =
199 get_registered_regions_requests_.Lookup(request_id);
200 DCHECK(callbacks);
202 if (status == GEOFENCING_STATUS_OK) {
203 blink::WebVector<blink::WebGeofencingRegistration> result(regions.size());
204 size_t index = 0;
205 for (GeofencingRegistrations::const_iterator it = regions.begin();
206 it != regions.end();
207 ++it, ++index) {
208 result[index].id = blink::WebString::fromUTF8(it->first);
209 result[index].region = it->second;
211 callbacks->onSuccess(result);
212 } else {
213 callbacks->onError(WebGeofencingError(
214 WebGeofencingError::ErrorTypeAbort,
215 blink::WebString::fromUTF8(GeofencingStatusToString(status))));
217 get_registered_regions_requests_.Remove(request_id);
220 void GeofencingDispatcher::WillStopCurrentWorkerThread() {
221 delete this;
224 } // namespace content