Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / child / geofencing / geofencing_dispatcher.cc
blob37ba161aa289fa8ec44174beae43bfdf59e2f29c
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<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();
35 } // namespace
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) {
51 bool handled = true;
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)
60 IPC_END_MESSAGE_MAP()
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) {
69 DCHECK(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(),
80 request_id,
81 region_id.utf8(),
82 region,
83 serviceworker_registration_id));
86 void GeofencingDispatcher::UnregisterRegion(
87 const blink::WebString& region_id,
88 blink::WebServiceWorkerRegistration* service_worker_registration,
89 blink::WebGeofencingCallbacks* callbacks) {
90 DCHECK(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(),
101 request_id,
102 region_id.utf8(),
103 serviceworker_registration_id));
106 void GeofencingDispatcher::GetRegisteredRegions(
107 blink::WebServiceWorkerRegistration* service_worker_registration,
108 blink::WebGeofencingRegionsCallbacks* callbacks) {
109 DCHECK(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);
150 return dispatcher;
153 GeofencingDispatcher* GeofencingDispatcher::GetThreadSpecificInstance() {
154 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted)
155 return NULL;
156 return 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(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,
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(new 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 scoped_ptr<blink::WebVector<blink::WebGeofencingRegistration>> result(
204 new blink::WebVector<blink::WebGeofencingRegistration>(regions.size()));
205 size_t index = 0;
206 for (GeofencingRegistrations::const_iterator it = regions.begin();
207 it != regions.end();
208 ++it, ++index) {
209 (*result)[index].id = blink::WebString::fromUTF8(it->first);
210 (*result)[index].region = it->second;
212 callbacks->onSuccess(result.release());
213 } else {
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() {
222 delete this;
225 } // namespace content