| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/geofencing/geofencing_manager.h" | 5 #include "content/browser/geofencing/geofencing_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/callback.h" | 9 #include "base/callback.h" |
| 10 #include "content/browser/geofencing/geofencing_service.h" | 10 #include "content/browser/geofencing/geofencing_service.h" |
| 11 #include "content/browser/geofencing/mock_geofencing_service.h" |
| 11 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 12 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
| 12 #include "content/public/browser/browser_context.h" | 13 #include "content/public/browser/browser_context.h" |
| 13 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
| 14 #include "content/public/browser/storage_partition.h" | 15 #include "content/public/browser/storage_partition.h" |
| 15 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h" | 16 #include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h" |
| 16 #include "third_party/WebKit/public/platform/WebGeofencingEventType.h" | 17 #include "third_party/WebKit/public/platform/WebGeofencingEventType.h" |
| 17 #include "url/gurl.h" | 18 #include "url/gurl.h" |
| 18 | 19 |
| 19 namespace content { | 20 namespace content { |
| 20 | 21 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 85 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 85 service_ = GeofencingServiceImpl::GetInstance(); | 86 service_ = GeofencingServiceImpl::GetInstance(); |
| 86 } | 87 } |
| 87 | 88 |
| 88 void GeofencingManager::ShutdownOnIO() { | 89 void GeofencingManager::ShutdownOnIO() { |
| 89 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 90 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 90 // Clean up all registrations with the |GeofencingService|. | 91 // Clean up all registrations with the |GeofencingService|. |
| 91 // TODO(mek): This will need to change to support geofence registrations that | 92 // TODO(mek): This will need to change to support geofence registrations that |
| 92 // outlive the browser, although removing the references to this | 93 // outlive the browser, although removing the references to this |
| 93 // |GeofencingManager| from the |GeofencingService| will still be needed. | 94 // |GeofencingManager| from the |GeofencingService| will still be needed. |
| 94 for (const auto& registration : registrations_by_id_) { | 95 for (const auto& service_worker : registrations_) { |
| 95 service_->UnregisterRegion(registration.first); | 96 GeofencingService* service = ServiceForServiceWorker(service_worker.first); |
| 97 for (const auto& registration : service_worker.second) |
| 98 service->UnregisterRegion(registration.second.geofencing_registration_id); |
| 96 } | 99 } |
| 97 } | 100 } |
| 98 | 101 |
| 99 void GeofencingManager::RegisterRegion( | 102 void GeofencingManager::RegisterRegion( |
| 100 int64 service_worker_registration_id, | 103 int64 service_worker_registration_id, |
| 101 const std::string& region_id, | 104 const std::string& region_id, |
| 102 const blink::WebCircularGeofencingRegion& region, | 105 const blink::WebCircularGeofencingRegion& region, |
| 103 const StatusCallback& callback) { | 106 const StatusCallback& callback) { |
| 104 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 107 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 105 | 108 |
| 106 // TODO(mek): Validate region_id and region. | 109 // TODO(mek): Validate region_id and region. |
| 107 | 110 |
| 108 // Look up service worker. In unit tests |service_worker_context_| might not | 111 // Look up service worker. In unit tests |service_worker_context_| might not |
| 109 // be set. | 112 // be set. |
| 110 GURL service_worker_origin; | 113 GURL service_worker_origin; |
| 111 if (service_worker_context_.get()) { | 114 if (service_worker_context_.get()) { |
| 112 ServiceWorkerRegistration* service_worker_registration = | 115 ServiceWorkerRegistration* service_worker_registration = |
| 113 service_worker_context_->context()->GetLiveRegistration( | 116 service_worker_context_->context()->GetLiveRegistration( |
| 114 service_worker_registration_id); | 117 service_worker_registration_id); |
| 115 if (!service_worker_registration) { | 118 if (!service_worker_registration) { |
| 116 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER); | 119 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER); |
| 117 return; | 120 return; |
| 118 } | 121 } |
| 119 | 122 |
| 120 service_worker_origin = service_worker_registration->pattern().GetOrigin(); | 123 service_worker_origin = service_worker_registration->pattern().GetOrigin(); |
| 121 } | 124 } |
| 122 | 125 |
| 123 if (!service_->IsServiceAvailable()) { | 126 GeofencingService* service = |
| 127 ServiceForServiceWorker(service_worker_registration_id); |
| 128 if (!service->IsServiceAvailable()) { |
| 124 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE); | 129 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE); |
| 125 return; | 130 return; |
| 126 } | 131 } |
| 127 | 132 |
| 128 if (FindRegistration(service_worker_registration_id, region_id)) { | 133 if (FindRegistration(service_worker_registration_id, region_id)) { |
| 129 // Already registered, return an error. | 134 // Already registered, return an error. |
| 130 // TODO(mek): Use a more specific error code. | 135 // TODO(mek): Use a more specific error code. |
| 131 callback.Run(GEOFENCING_STATUS_ERROR); | 136 callback.Run(GEOFENCING_STATUS_ERROR); |
| 132 return; | 137 return; |
| 133 } | 138 } |
| 134 | 139 |
| 135 AddRegistration(service_worker_registration_id, | 140 AddRegistration(service_worker_registration_id, service_worker_origin, |
| 136 service_worker_origin, | 141 region_id, region, callback, |
| 137 region_id, | 142 service->RegisterRegion(region, this)); |
| 138 region, | |
| 139 callback, | |
| 140 service_->RegisterRegion(region, this)); | |
| 141 } | 143 } |
| 142 | 144 |
| 143 void GeofencingManager::UnregisterRegion(int64 service_worker_registration_id, | 145 void GeofencingManager::UnregisterRegion(int64 service_worker_registration_id, |
| 144 const std::string& region_id, | 146 const std::string& region_id, |
| 145 const StatusCallback& callback) { | 147 const StatusCallback& callback) { |
| 146 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 148 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 147 | 149 |
| 148 // TODO(mek): Validate region_id. | 150 // TODO(mek): Validate region_id. |
| 149 | 151 |
| 150 // Look up service worker. In unit tests |service_worker_context_| might not | 152 // Look up service worker. In unit tests |service_worker_context_| might not |
| 151 // be set. | 153 // be set. |
| 152 if (service_worker_context_.get()) { | 154 if (service_worker_context_.get()) { |
| 153 ServiceWorkerRegistration* service_worker_registration = | 155 ServiceWorkerRegistration* service_worker_registration = |
| 154 service_worker_context_->context()->GetLiveRegistration( | 156 service_worker_context_->context()->GetLiveRegistration( |
| 155 service_worker_registration_id); | 157 service_worker_registration_id); |
| 156 if (!service_worker_registration) { | 158 if (!service_worker_registration) { |
| 157 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER); | 159 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER); |
| 158 return; | 160 return; |
| 159 } | 161 } |
| 160 } | 162 } |
| 161 | 163 |
| 162 if (!service_->IsServiceAvailable()) { | 164 GeofencingService* service = |
| 165 ServiceForServiceWorker(service_worker_registration_id); |
| 166 if (!service->IsServiceAvailable()) { |
| 163 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE); | 167 callback.Run(GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE); |
| 164 return; | 168 return; |
| 165 } | 169 } |
| 166 | 170 |
| 167 Registration* registration = | 171 Registration* registration = |
| 168 FindRegistration(service_worker_registration_id, region_id); | 172 FindRegistration(service_worker_registration_id, region_id); |
| 169 if (!registration) { | 173 if (!registration) { |
| 170 // Not registered, return an error. | 174 // Not registered, return an error. |
| 171 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED); | 175 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED); |
| 172 return; | 176 return; |
| 173 } | 177 } |
| 174 | 178 |
| 175 if (!registration->is_active()) { | 179 if (!registration->is_active()) { |
| 176 // Started registration, but not completed yet, error. | 180 // Started registration, but not completed yet, error. |
| 177 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED); | 181 callback.Run(GEOFENCING_STATUS_UNREGISTRATION_FAILED_NOT_REGISTERED); |
| 178 return; | 182 return; |
| 179 } | 183 } |
| 180 | 184 |
| 181 service_->UnregisterRegion(registration->geofencing_registration_id); | 185 service->UnregisterRegion(registration->geofencing_registration_id); |
| 182 ClearRegistration(registration); | 186 ClearRegistration(registration); |
| 183 callback.Run(GEOFENCING_STATUS_OK); | 187 callback.Run(GEOFENCING_STATUS_OK); |
| 184 } | 188 } |
| 185 | 189 |
| 186 GeofencingStatus GeofencingManager::GetRegisteredRegions( | 190 GeofencingStatus GeofencingManager::GetRegisteredRegions( |
| 187 int64 service_worker_registration_id, | 191 int64 service_worker_registration_id, |
| 188 std::map<std::string, blink::WebCircularGeofencingRegion>* result) { | 192 std::map<std::string, blink::WebCircularGeofencingRegion>* result) { |
| 189 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 193 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 190 CHECK(result); | 194 CHECK(result); |
| 191 | 195 |
| 192 // Look up service worker. In unit tests |service_worker_context_| might not | 196 // Look up service worker. In unit tests |service_worker_context_| might not |
| 193 // be set. | 197 // be set. |
| 194 if (service_worker_context_.get()) { | 198 if (service_worker_context_.get()) { |
| 195 ServiceWorkerRegistration* service_worker_registration = | 199 ServiceWorkerRegistration* service_worker_registration = |
| 196 service_worker_context_->context()->GetLiveRegistration( | 200 service_worker_context_->context()->GetLiveRegistration( |
| 197 service_worker_registration_id); | 201 service_worker_registration_id); |
| 198 if (!service_worker_registration) { | 202 if (!service_worker_registration) { |
| 199 return GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER; | 203 return GEOFENCING_STATUS_OPERATION_FAILED_NO_SERVICE_WORKER; |
| 200 } | 204 } |
| 201 } | 205 } |
| 202 | 206 |
| 203 if (!service_->IsServiceAvailable()) { | 207 GeofencingService* service = |
| 208 ServiceForServiceWorker(service_worker_registration_id); |
| 209 if (!service->IsServiceAvailable()) { |
| 204 return GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE; | 210 return GEOFENCING_STATUS_OPERATION_FAILED_SERVICE_NOT_AVAILABLE; |
| 205 } | 211 } |
| 206 | 212 |
| 207 // Populate result, filtering out inactive registrations. | 213 // Populate result, filtering out inactive registrations. |
| 208 result->clear(); | 214 result->clear(); |
| 209 ServiceWorkerRegistrationsMap::iterator registrations = | 215 ServiceWorkerRegistrationsMap::iterator registrations = |
| 210 registrations_.find(service_worker_registration_id); | 216 registrations_.find(service_worker_registration_id); |
| 211 if (registrations == registrations_.end()) | 217 if (registrations == registrations_.end()) |
| 212 return GEOFENCING_STATUS_OK; | 218 return GEOFENCING_STATUS_OK; |
| 213 for (const auto& registration : registrations->second) { | 219 for (const auto& registration : registrations->second) { |
| 214 if (registration.second.is_active()) | 220 if (registration.second.is_active()) |
| 215 (*result)[registration.first] = registration.second.region; | 221 (*result)[registration.first] = registration.second.region; |
| 216 } | 222 } |
| 217 return GEOFENCING_STATUS_OK; | 223 return GEOFENCING_STATUS_OK; |
| 218 } | 224 } |
| 219 | 225 |
| 226 void GeofencingManager::SetMockProvider(int64 service_worker_registration_id, |
| 227 GeofencingMockState mock_state) { |
| 228 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 229 // First erase all current registration for this service worker. |
| 230 CleanUpForServiceWorker(service_worker_registration_id); |
| 231 |
| 232 // Then set or reset the mock service for the service worker. |
| 233 if (mock_state == GeofencingMockState::NONE) { |
| 234 mock_services_.erase(service_worker_registration_id); |
| 235 } else { |
| 236 mock_services_[service_worker_registration_id] = |
| 237 make_linked_ptr(new MockGeofencingService( |
| 238 mock_state != GeofencingMockState::SERVICE_UNAVAILABLE)); |
| 239 } |
| 240 } |
| 241 |
| 242 void GeofencingManager::SetMockPosition(int64 service_worker_registration_id, |
| 243 double latitude, |
| 244 double longitude) { |
| 245 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 246 auto it = mock_services_.find(service_worker_registration_id); |
| 247 if (it == mock_services_.end()) |
| 248 return; |
| 249 it->second->SetMockPosition(latitude, longitude); |
| 250 } |
| 251 |
| 220 void GeofencingManager::RegistrationFinished(int64 geofencing_registration_id, | 252 void GeofencingManager::RegistrationFinished(int64 geofencing_registration_id, |
| 221 GeofencingStatus status) { | 253 GeofencingStatus status) { |
| 222 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 254 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 223 Registration* registration = FindRegistrationById(geofencing_registration_id); | 255 Registration* registration = FindRegistrationById(geofencing_registration_id); |
| 224 DCHECK(registration); | 256 DCHECK(registration); |
| 225 DCHECK(!registration->is_active()); | 257 DCHECK(!registration->is_active()); |
| 226 registration->registration_callback.Run(status); | 258 registration->registration_callback.Run(status); |
| 227 registration->registration_callback.Reset(); | 259 registration->registration_callback.Reset(); |
| 228 | 260 |
| 229 // If the registration wasn't succesful, remove it from our storage. | 261 // If the registration wasn't succesful, remove it from our storage. |
| 230 if (status != GEOFENCING_STATUS_OK) | 262 if (status != GEOFENCING_STATUS_OK) |
| 231 ClearRegistration(registration); | 263 ClearRegistration(registration); |
| 232 } | 264 } |
| 233 | 265 |
| 234 void GeofencingManager::RegionEntered(int64 geofencing_registration_id) { | 266 void GeofencingManager::RegionEntered(int64 geofencing_registration_id) { |
| 235 DispatchGeofencingEvent(blink::WebGeofencingEventTypeEnter, | 267 DispatchGeofencingEvent(blink::WebGeofencingEventTypeEnter, |
| 236 geofencing_registration_id); | 268 geofencing_registration_id); |
| 237 } | 269 } |
| 238 | 270 |
| 239 void GeofencingManager::RegionExited(int64 geofencing_registration_id) { | 271 void GeofencingManager::RegionExited(int64 geofencing_registration_id) { |
| 240 DispatchGeofencingEvent(blink::WebGeofencingEventTypeLeave, | 272 DispatchGeofencingEvent(blink::WebGeofencingEventTypeLeave, |
| 241 geofencing_registration_id); | 273 geofencing_registration_id); |
| 242 } | 274 } |
| 243 | 275 |
| 276 GeofencingService* GeofencingManager::ServiceForServiceWorker( |
| 277 int64 service_worker_registration_id) { |
| 278 auto it = mock_services_.find(service_worker_registration_id); |
| 279 if (it == mock_services_.end()) |
| 280 return service_; |
| 281 return it->second.get(); |
| 282 } |
| 283 |
| 244 GeofencingManager::Registration* GeofencingManager::FindRegistration( | 284 GeofencingManager::Registration* GeofencingManager::FindRegistration( |
| 245 int64 service_worker_registration_id, | 285 int64 service_worker_registration_id, |
| 246 const std::string& region_id) { | 286 const std::string& region_id) { |
| 247 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 287 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 248 ServiceWorkerRegistrationsMap::iterator registrations_iterator = | 288 ServiceWorkerRegistrationsMap::iterator registrations_iterator = |
| 249 registrations_.find(service_worker_registration_id); | 289 registrations_.find(service_worker_registration_id); |
| 250 if (registrations_iterator == registrations_.end()) | 290 if (registrations_iterator == registrations_.end()) |
| 251 return nullptr; | 291 return nullptr; |
| 252 RegionIdRegistrationMap::iterator registration = | 292 RegionIdRegistrationMap::iterator registration = |
| 253 registrations_iterator->second.find(region_id); | 293 registrations_iterator->second.find(region_id); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 333 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 294 registrations_by_id_.erase(registration->geofencing_registration_id); | 334 registrations_by_id_.erase(registration->geofencing_registration_id); |
| 295 ServiceWorkerRegistrationsMap::iterator registrations_iterator = | 335 ServiceWorkerRegistrationsMap::iterator registrations_iterator = |
| 296 registrations_.find(registration->service_worker_registration_id); | 336 registrations_.find(registration->service_worker_registration_id); |
| 297 DCHECK(registrations_iterator != registrations_.end()); | 337 DCHECK(registrations_iterator != registrations_.end()); |
| 298 registrations_iterator->second.erase(registration->region_id); | 338 registrations_iterator->second.erase(registration->region_id); |
| 299 if (registrations_iterator->second.empty()) | 339 if (registrations_iterator->second.empty()) |
| 300 registrations_.erase(registrations_iterator); | 340 registrations_.erase(registrations_iterator); |
| 301 } | 341 } |
| 302 | 342 |
| 343 void GeofencingManager::CleanUpForServiceWorker( |
| 344 int64 service_worker_registration_id) { |
| 345 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 346 ServiceWorkerRegistrationsMap::iterator registrations_iterator = |
| 347 registrations_.find(service_worker_registration_id); |
| 348 if (registrations_iterator == registrations_.end()) |
| 349 return; |
| 350 |
| 351 GeofencingService* service = |
| 352 ServiceForServiceWorker(service_worker_registration_id); |
| 353 for (auto it = registrations_iterator->second.begin(); |
| 354 !registrations_iterator->second.empty();) { |
| 355 int geofencing_registration_id = it->second.geofencing_registration_id; |
| 356 service->UnregisterRegion(geofencing_registration_id); |
| 357 registrations_by_id_.erase(geofencing_registration_id); |
| 358 auto old_it = it; |
| 359 ++it; |
| 360 registrations_iterator->second.erase(old_it); |
| 361 } |
| 362 } |
| 363 |
| 303 void GeofencingManager::DispatchGeofencingEvent( | 364 void GeofencingManager::DispatchGeofencingEvent( |
| 304 blink::WebGeofencingEventType event_type, | 365 blink::WebGeofencingEventType event_type, |
| 305 int64 geofencing_registration_id) { | 366 int64 geofencing_registration_id) { |
| 306 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 367 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 307 Registration* registration = FindRegistrationById(geofencing_registration_id); | 368 Registration* registration = FindRegistrationById(geofencing_registration_id); |
| 308 if (!registration || | 369 if (!registration || |
| 309 registration->service_worker_registration_id == | 370 registration->service_worker_registration_id == |
| 310 kInvalidServiceWorkerRegistrationId) { | 371 kInvalidServiceWorkerRegistrationId) { |
| 311 // TODO(mek): Log/track these failures. | 372 // TODO(mek): Log/track these failures. |
| 312 return; | 373 return; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 } | 423 } |
| 363 | 424 |
| 364 void GeofencingManager::DeliverGeofencingEventEnd( | 425 void GeofencingManager::DeliverGeofencingEventEnd( |
| 365 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration, | 426 const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration, |
| 366 ServiceWorkerStatusCode service_worker_status) { | 427 ServiceWorkerStatusCode service_worker_status) { |
| 367 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 428 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 368 // TODO(mek): log/check result. | 429 // TODO(mek): log/check result. |
| 369 } | 430 } |
| 370 | 431 |
| 371 } // namespace content | 432 } // namespace content |
| OLD | NEW |