Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: content/browser/geofencing/geofencing_manager.cc

Issue 1972733002: Delete geofencing implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mark histogram suffix as obsolete Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "content/browser/geofencing/geofencing_manager.h"
6
7 #include <algorithm>
8
9 #include "base/callback.h"
10 #include "content/browser/geofencing/geofencing_service.h"
11 #include "content/browser/geofencing/mock_geofencing_service.h"
12 #include "content/browser/service_worker/service_worker_context_wrapper.h"
13 #include "content/common/geofencing_messages.h"
14 #include "content/common/service_worker/service_worker_messages.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/storage_partition.h"
18 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
19 #include "third_party/WebKit/public/platform/WebGeofencingEventType.h"
20 #include "url/gurl.h"
21
22 namespace content {
23
24 struct GeofencingManager::Registration {
25 Registration(int64_t service_worker_registration_id,
26 const GURL& service_worker_origin,
27 const std::string& region_id,
28 const blink::WebCircularGeofencingRegion& region,
29 const StatusCallback& callback,
30 int64_t geofencing_registration_id);
31 int64_t service_worker_registration_id;
32 GURL service_worker_origin;
33 std::string region_id;
34 blink::WebCircularGeofencingRegion region;
35
36 // Registration ID as returned by the |GeofencingService|.
37 int64_t geofencing_registration_id;
38
39 // Callback to call when registration is completed. This field is reset when
40 // registration is complete.
41 StatusCallback registration_callback;
42
43 // Returns true if registration has been completed, and thus should be
44 // included in calls to GetRegisteredRegions.
45 bool is_active() const { return registration_callback.is_null(); }
46 };
47
48 GeofencingManager::Registration::Registration(
49 int64_t service_worker_registration_id,
50 const GURL& service_worker_origin,
51 const std::string& region_id,
52 const blink::WebCircularGeofencingRegion& region,
53 const GeofencingManager::StatusCallback& callback,
54 int64_t geofencing_registration_id)
55 : service_worker_registration_id(service_worker_registration_id),
56 service_worker_origin(service_worker_origin),
57 region_id(region_id),
58 region(region),
59 geofencing_registration_id(geofencing_registration_id),
60 registration_callback(callback) {}
61
62 GeofencingManager::GeofencingManager(
63 const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
64 : service_(nullptr), service_worker_context_(service_worker_context) {
65 DCHECK_CURRENTLY_ON(BrowserThread::UI);
66 }
67
68 GeofencingManager::~GeofencingManager() {
69 }
70
71 void GeofencingManager::Init() {
72 DCHECK_CURRENTLY_ON(BrowserThread::UI);
73 BrowserThread::PostTask(BrowserThread::IO,
74 FROM_HERE,
75 base::Bind(&GeofencingManager::InitOnIO, this));
76 }
77
78 void GeofencingManager::Shutdown() {
79 DCHECK_CURRENTLY_ON(BrowserThread::UI);
80 BrowserThread::PostTask(BrowserThread::IO,
81 FROM_HERE,
82 base::Bind(&GeofencingManager::ShutdownOnIO, this));
83 }
84
85 void GeofencingManager::InitOnIO() {
86 DCHECK_CURRENTLY_ON(BrowserThread::IO);
87 service_worker_context_->AddObserver(this);
88 if (!service_)
89 service_ = GeofencingServiceImpl::GetInstance();
90 }
91
92 void GeofencingManager::ShutdownOnIO() {
93 DCHECK_CURRENTLY_ON(BrowserThread::IO);
94 service_worker_context_->RemoveObserver(this);
95 // Clean up all registrations with the |GeofencingService|.
96 // TODO(mek): This will need to change to support geofence registrations that
97 // outlive the browser, although removing the references to this
98 // |GeofencingManager| from the |GeofencingService| will still be needed.
99 for (const auto& registration : registrations_by_id_)
100 service_->UnregisterRegion(registration.first);
101 }
102
103 void GeofencingManager::RegisterRegion(
104 int64_t service_worker_registration_id,
105 const std::string& region_id,
106 const blink::WebCircularGeofencingRegion& region,
107 const StatusCallback& callback) {
108 DCHECK_CURRENTLY_ON(BrowserThread::IO);
109
110 // TODO(mek): Validate region_id and region.
111
112 // Look up service worker.
113 ServiceWorkerRegistration* service_worker_registration =
114 service_worker_context_->GetLiveRegistration(
115 service_worker_registration_id);
116 if (!service_worker_registration) {
117 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER);
118 return;
119 }
120
121 GURL service_worker_origin =
122 service_worker_registration->pattern().GetOrigin();
123
124 if (!service_->IsServiceAvailable()) {
125 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
126 return;
127 }
128
129 if (FindRegistration(service_worker_registration_id, region_id)) {
130 // Already registered, return an error.
131 // TODO(mek): Use a more specific error code.
132 callback.Run(GEOFENCING_STATUS_ERROR);
133 return;
134 }
135
136 AddRegistration(service_worker_registration_id, service_worker_origin,
137 region_id, region, callback,
138 service_->RegisterRegion(region, this));
139 }
140
141 void GeofencingManager::UnregisterRegion(int64_t service_worker_registration_id,
142 const std::string& region_id,
143 const StatusCallback& callback) {
144 DCHECK_CURRENTLY_ON(BrowserThread::IO);
145
146 // TODO(mek): Validate region_id.
147
148 // Look up service worker.
149 ServiceWorkerRegistration* service_worker_registration =
150 service_worker_context_->GetLiveRegistration(
151 service_worker_registration_id);
152 if (!service_worker_registration) {
153 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER);
154 return;
155 }
156
157 if (!service_->IsServiceAvailable()) {
158 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE);
159 return;
160 }
161
162 Registration* registration =
163 FindRegistration(service_worker_registration_id, region_id);
164 if (!registration) {
165 // Not registered, return an error.
166 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED);
167 return;
168 }
169
170 if (!registration->is_active()) {
171 // Started registration, but not completed yet, error.
172 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED);
173 return;
174 }
175
176 service_->UnregisterRegion(registration->geofencing_registration_id);
177 ClearRegistration(registration);
178 callback.Run(GEOFENCING_STATUS_OK);
179 }
180
181 GeofencingStatus GeofencingManager::GetRegisteredRegions(
182 int64_t service_worker_registration_id,
183 std::map<std::string, blink::WebCircularGeofencingRegion>* result) {
184 DCHECK_CURRENTLY_ON(BrowserThread::IO);
185 CHECK(result);
186
187 // Look up service worker.
188 ServiceWorkerRegistration* service_worker_registration =
189 service_worker_context_->GetLiveRegistration(
190 service_worker_registration_id);
191 if (!service_worker_registration) {
192 return GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER;
193 }
194
195 if (!service_->IsServiceAvailable()) {
196 return GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE;
197 }
198
199 // Populate result, filtering out inactive registrations.
200 result->clear();
201 ServiceWorkerRegistrationsMap::iterator registrations =
202 registrations_.find(service_worker_registration_id);
203 if (registrations == registrations_.end())
204 return GEOFENCING_STATUS_OK;
205 for (const auto& registration : registrations->second) {
206 if (registration.second.is_active())
207 (*result)[registration.first] = registration.second.region;
208 }
209 return GEOFENCING_STATUS_OK;
210 }
211
212 void GeofencingManager::SetMockProvider(GeofencingMockState mock_state) {
213 DCHECK_CURRENTLY_ON(BrowserThread::IO);
214
215 // TODO(mek): It would be nice if enabling the mock geofencing service
216 // wouldn't completely delete all existing registrations but instead just
217 // somehow keep them around but inactive.
218 // For now mocking is only used in layout tests, so just clearing all
219 // registrations works good enough.
220 for (const auto& registration : registrations_by_id_)
221 service_->UnregisterRegion(registration.first);
222 registrations_by_id_.clear();
223 registrations_.clear();
224
225 // Then set or reset the mock service for the service worker.
226 if (mock_state == GeofencingMockState::NONE) {
227 service_ = GeofencingServiceImpl::GetInstance();
228 mock_service_.reset();
229 } else {
230 mock_service_.reset(new MockGeofencingService(
231 mock_state != GeofencingMockState::SERVICE_UNAVAILABLE));
232 service_ = mock_service_.get();
233 }
234 }
235
236 void GeofencingManager::SetMockPosition(double latitude, double longitude) {
237 DCHECK_CURRENTLY_ON(BrowserThread::IO);
238 if (!mock_service_)
239 return;
240 mock_service_->SetMockPosition(latitude, longitude);
241 }
242
243 void GeofencingManager::OnRegistrationDeleted(
244 int64_t service_worker_registration_id,
245 const GURL& pattern) {
246 DCHECK_CURRENTLY_ON(BrowserThread::IO);
247 CleanUpForServiceWorker(service_worker_registration_id);
248 }
249
250 void GeofencingManager::RegistrationFinished(int64_t geofencing_registration_id,
251 GeofencingStatus status) {
252 DCHECK_CURRENTLY_ON(BrowserThread::IO);
253 Registration* registration = FindRegistrationById(geofencing_registration_id);
254 DCHECK(registration);
255 DCHECK(!registration->is_active());
256 registration->registration_callback.Run(status);
257 registration->registration_callback.Reset();
258
259 // If the registration wasn't succesful, remove it from our storage.
260 if (status != GEOFENCING_STATUS_OK)
261 ClearRegistration(registration);
262 }
263
264 void GeofencingManager::RegionEntered(int64_t geofencing_registration_id) {
265 DispatchGeofencingEvent(blink::WebGeofencingEventTypeEnter,
266 geofencing_registration_id);
267 }
268
269 void GeofencingManager::RegionExited(int64_t geofencing_registration_id) {
270 DispatchGeofencingEvent(blink::WebGeofencingEventTypeLeave,
271 geofencing_registration_id);
272 }
273
274 GeofencingManager::Registration* GeofencingManager::FindRegistration(
275 int64_t service_worker_registration_id,
276 const std::string& region_id) {
277 DCHECK_CURRENTLY_ON(BrowserThread::IO);
278 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
279 registrations_.find(service_worker_registration_id);
280 if (registrations_iterator == registrations_.end())
281 return nullptr;
282 RegionIdRegistrationMap::iterator registration =
283 registrations_iterator->second.find(region_id);
284 if (registration == registrations_iterator->second.end())
285 return nullptr;
286 return &registration->second;
287 }
288
289 GeofencingManager::Registration* GeofencingManager::FindRegistrationById(
290 int64_t geofencing_registration_id) {
291 DCHECK_CURRENTLY_ON(BrowserThread::IO);
292 RegistrationIdRegistrationMap::iterator registration_iterator =
293 registrations_by_id_.find(geofencing_registration_id);
294 if (registration_iterator == registrations_by_id_.end())
295 return nullptr;
296 return &registration_iterator->second->second;
297 }
298
299 GeofencingManager::Registration& GeofencingManager::AddRegistration(
300 int64_t service_worker_registration_id,
301 const GURL& service_worker_origin,
302 const std::string& region_id,
303 const blink::WebCircularGeofencingRegion& region,
304 const StatusCallback& callback,
305 int64_t geofencing_registration_id) {
306 DCHECK_CURRENTLY_ON(BrowserThread::IO);
307 DCHECK(!FindRegistration(service_worker_registration_id, region_id));
308 RegionIdRegistrationMap::iterator registration =
309 registrations_[service_worker_registration_id]
310 .insert(std::make_pair(region_id,
311 Registration(service_worker_registration_id,
312 service_worker_origin,
313 region_id,
314 region,
315 callback,
316 geofencing_registration_id)))
317 .first;
318 registrations_by_id_[geofencing_registration_id] = registration;
319 return registration->second;
320 }
321
322 void GeofencingManager::ClearRegistration(Registration* registration) {
323 DCHECK_CURRENTLY_ON(BrowserThread::IO);
324 registrations_by_id_.erase(registration->geofencing_registration_id);
325 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
326 registrations_.find(registration->service_worker_registration_id);
327 DCHECK(registrations_iterator != registrations_.end());
328 registrations_iterator->second.erase(registration->region_id);
329 if (registrations_iterator->second.empty())
330 registrations_.erase(registrations_iterator);
331 }
332
333 void GeofencingManager::CleanUpForServiceWorker(
334 int64_t service_worker_registration_id) {
335 DCHECK_CURRENTLY_ON(BrowserThread::IO);
336 ServiceWorkerRegistrationsMap::iterator registrations_iterator =
337 registrations_.find(service_worker_registration_id);
338 if (registrations_iterator == registrations_.end())
339 return;
340
341 for (const auto& registration : registrations_iterator->second) {
342 int geofencing_registration_id =
343 registration.second.geofencing_registration_id;
344 service_->UnregisterRegion(geofencing_registration_id);
345 registrations_by_id_.erase(geofencing_registration_id);
346 }
347 registrations_.erase(service_worker_registration_id);
348 }
349
350 void GeofencingManager::DispatchGeofencingEvent(
351 blink::WebGeofencingEventType event_type,
352 int64_t geofencing_registration_id) {
353 DCHECK_CURRENTLY_ON(BrowserThread::IO);
354 Registration* registration = FindRegistrationById(geofencing_registration_id);
355 if (!registration ||
356 registration->service_worker_registration_id ==
357 kInvalidServiceWorkerRegistrationId) {
358 // TODO(mek): Log/track these failures.
359 return;
360 }
361
362 service_worker_context_->FindReadyRegistrationForId(
363 registration->service_worker_registration_id,
364 registration->service_worker_origin,
365 base::Bind(&GeofencingManager::DeliverGeofencingEvent,
366 this,
367 event_type,
368 geofencing_registration_id));
369 }
370
371 void GeofencingManager::DeliverGeofencingEvent(
372 blink::WebGeofencingEventType event_type,
373 int64_t geofencing_registration_id,
374 ServiceWorkerStatusCode service_worker_status,
375 const scoped_refptr<ServiceWorkerRegistration>&
376 service_worker_registration) {
377 DCHECK_CURRENTLY_ON(BrowserThread::IO);
378 Registration* registration = FindRegistrationById(geofencing_registration_id);
379 if (!registration) {
380 // Geofence got unregistered in the meantime, no longer need to deliver
381 // event.
382 return;
383 }
384
385 if (service_worker_status != SERVICE_WORKER_OK) {
386 // TODO(mek): SW no longer exists, somehow handle this.
387 return;
388 }
389
390 ServiceWorkerVersion* active_version =
391 service_worker_registration->active_version();
392 DCHECK(active_version);
393
394 // Hold on to the service worker registration in the callback to keep it alive
395 // until the callback dies. Otherwise the registration could be released when
396 // this method returns - before the event is delivered to the service worker.
397 active_version->RunAfterStartWorker(
398 ServiceWorkerMetrics::EventType::GEOFENCING,
399 base::Bind(&GeofencingManager::DeliverEventToRunningWorker, this,
400 service_worker_registration, event_type,
401 registration->region_id, registration->region,
402 make_scoped_refptr(active_version)),
403 base::Bind(&GeofencingManager::OnEventError, this));
404 }
405
406 void GeofencingManager::DeliverEventToRunningWorker(
407 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
408 blink::WebGeofencingEventType event_type,
409 const std::string& region_id,
410 const blink::WebCircularGeofencingRegion& region,
411 const scoped_refptr<ServiceWorkerVersion>& worker) {
412 int request_id =
413 worker->StartRequest(ServiceWorkerMetrics::EventType::GEOFENCING,
414 base::Bind(&GeofencingManager::OnEventError, this));
415
416 worker->DispatchEvent<ServiceWorkerHostMsg_GeofencingEventFinished>(
417 request_id, ServiceWorkerMsg_GeofencingEvent(request_id, event_type,
418 region_id, region),
419 base::Bind(&GeofencingManager::OnEventResponse, this, worker,
420 service_worker_registration));
421 }
422
423 void GeofencingManager::OnEventResponse(
424 const scoped_refptr<ServiceWorkerVersion>& worker,
425 const scoped_refptr<ServiceWorkerRegistration>& registration,
426 int request_id,
427 blink::WebServiceWorkerEventResult result) {
428 bool finish_result = worker->FinishRequest(
429 request_id, result == blink::WebServiceWorkerEventResultCompleted);
430 DCHECK(finish_result)
431 << "No messages should be passed to handler if request had "
432 "already finished";
433 // TODO(mek): log/check result.
434 }
435
436 void GeofencingManager::OnEventError(
437 ServiceWorkerStatusCode service_worker_status) {
438 DCHECK_CURRENTLY_ON(BrowserThread::IO);
439 // TODO(mek): log/check errors.
440 }
441
442 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/geofencing/geofencing_manager.h ('k') | content/browser/geofencing/geofencing_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698