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 |