OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All Rights Reserved. | 2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All Rights Reserved. |
3 * Copyright (C) 2009 Torch Mobile, Inc. | 3 * Copyright (C) 2009 Torch Mobile, Inc. |
4 * Copyright 2010, The Android Open Source Project | 4 * Copyright 2010, The Android Open Source Project |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 14 matching lines...) Loading... |
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 */ | 26 */ |
27 | 27 |
28 #include "modules/geolocation/Geolocation.h" | 28 #include "modules/geolocation/Geolocation.h" |
29 | 29 |
30 #include "core/dom/Document.h" | 30 #include "core/dom/Document.h" |
31 #include "core/frame/Deprecation.h" | 31 #include "core/frame/Deprecation.h" |
32 #include "core/frame/OriginsUsingFeatures.h" | 32 #include "core/frame/OriginsUsingFeatures.h" |
33 #include "core/frame/Settings.h" | 33 #include "core/frame/Settings.h" |
34 #include "modules/geolocation/Coordinates.h" | 34 #include "modules/geolocation/Coordinates.h" |
35 #include "modules/geolocation/GeolocationController.h" | |
36 #include "modules/geolocation/GeolocationError.h" | 35 #include "modules/geolocation/GeolocationError.h" |
37 #include "modules/geolocation/GeolocationPosition.h" | 36 #include "platform/mojo/MojoHelper.h" |
38 #include "platform/weborigin/SecurityOrigin.h" | 37 #include "public/platform/ServiceRegistry.h" |
39 #include "wtf/CurrentTime.h" | 38 #include "wtf/CurrentTime.h" |
40 | 39 |
41 namespace blink { | 40 namespace blink { |
| 41 namespace { |
42 | 42 |
43 static const char permissionDeniedErrorMessage[] = "User denied Geolocation"; | 43 static const char permissionDeniedErrorMessage[] = "User denied Geolocation"; |
44 static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocat
ion service"; | 44 static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocat
ion service"; |
45 static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used
in frameless documents"; | 45 static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used
in frameless documents"; |
46 | 46 |
47 static Geoposition* createGeoposition(GeolocationPosition* position) | 47 static Geoposition* createGeoposition(const mojom::blink::Geoposition& position) |
48 { | 48 { |
49 if (!position) | |
50 return nullptr; | |
51 | |
52 Coordinates* coordinates = Coordinates::create( | 49 Coordinates* coordinates = Coordinates::create( |
53 position->latitude(), | 50 position.latitude, |
54 position->longitude(), | 51 position.longitude, |
55 position->canProvideAltitude(), | 52 position.altitude > -10000., |
56 position->altitude(), | 53 position.altitude, |
57 position->accuracy(), | 54 position.accuracy, |
58 position->canProvideAltitudeAccuracy(), | 55 position.altitude_accuracy >= 0., |
59 position->altitudeAccuracy(), | 56 position.altitude_accuracy, |
60 position->canProvideHeading(), | 57 position.heading >= 0. && position.heading <= 360., |
61 position->heading(), | 58 position.heading, |
62 position->canProvideSpeed(), | 59 position.speed >= 0., |
63 position->speed()); | 60 position.speed); |
64 return Geoposition::create(coordinates, convertSecondsToDOMTimeStamp(positio
n->timestamp())); | 61 return Geoposition::create(coordinates, convertSecondsToDOMTimeStamp(positio
n.timestamp)); |
65 } | 62 } |
66 | 63 |
67 static PositionError* createPositionError(GeolocationError* error) | 64 static PositionError* createPositionError(mojom::blink::Geoposition::ErrorCode m
ojomErrorCode, const String& error) |
68 { | 65 { |
69 PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE; | 66 PositionError::ErrorCode errorCode = PositionError::POSITION_UNAVAILABLE; |
70 switch (error->code()) { | 67 switch (mojomErrorCode) { |
71 case GeolocationError::PermissionDenied: | 68 case mojom::blink::Geoposition::ErrorCode::PERMISSION_DENIED: |
72 code = PositionError::PERMISSION_DENIED; | 69 errorCode = PositionError::PERMISSION_DENIED; |
73 break; | 70 break; |
74 case GeolocationError::PositionUnavailable: | 71 case mojom::blink::Geoposition::ErrorCode::POSITION_UNAVAILABLE: |
75 code = PositionError::POSITION_UNAVAILABLE; | 72 errorCode = PositionError::POSITION_UNAVAILABLE; |
| 73 break; |
| 74 case mojom::blink::Geoposition::ErrorCode::NONE: |
| 75 case mojom::blink::Geoposition::ErrorCode::TIMEOUT: |
| 76 NOTREACHED(); |
76 break; | 77 break; |
77 } | 78 } |
| 79 return PositionError::create(errorCode, error); |
| 80 } |
78 | 81 |
79 return PositionError::create(code, error->message()); | 82 } // namespace |
80 } | |
81 | 83 |
82 Geolocation* Geolocation::create(ExecutionContext* context) | 84 Geolocation* Geolocation::create(ExecutionContext* context) |
83 { | 85 { |
84 Geolocation* geolocation = new Geolocation(context); | 86 Geolocation* geolocation = new Geolocation(context); |
85 geolocation->suspendIfNeeded(); | |
86 return geolocation; | 87 return geolocation; |
87 } | 88 } |
88 | 89 |
89 Geolocation::Geolocation(ExecutionContext* context) | 90 Geolocation::Geolocation(ExecutionContext* context) |
90 : ActiveDOMObject(context) | 91 : ContextLifecycleObserver(context) |
| 92 , PageLifecycleObserver(document()->page()) |
91 , m_geolocationPermission(PermissionUnknown) | 93 , m_geolocationPermission(PermissionUnknown) |
92 { | 94 { |
| 95 ThreadState::current()->registerPreFinalizer(this); |
93 } | 96 } |
94 | 97 |
95 Geolocation::~Geolocation() | 98 Geolocation::~Geolocation() |
96 { | 99 { |
97 ASSERT(m_geolocationPermission != PermissionRequested); | 100 ASSERT(m_geolocationPermission != PermissionRequested); |
98 } | 101 } |
99 | 102 |
100 DEFINE_TRACE(Geolocation) | 103 DEFINE_TRACE(Geolocation) |
101 { | 104 { |
102 visitor->trace(m_oneShots); | 105 visitor->trace(m_oneShots); |
103 visitor->trace(m_watchers); | 106 visitor->trace(m_watchers); |
104 visitor->trace(m_pendingForPermissionNotifiers); | 107 visitor->trace(m_pendingForPermissionNotifiers); |
105 visitor->trace(m_lastPosition); | 108 visitor->trace(m_lastPosition); |
106 visitor->trace(m_requestsAwaitingCachedPosition); | 109 ContextLifecycleObserver::trace(visitor); |
107 ActiveDOMObject::trace(visitor); | 110 PageLifecycleObserver::trace(visitor); |
108 } | 111 } |
109 | 112 |
110 Document* Geolocation::document() const | 113 Document* Geolocation::document() const |
111 { | 114 { |
112 return toDocument(getExecutionContext()); | 115 return toDocument(getExecutionContext()); |
113 } | 116 } |
114 | 117 |
115 LocalFrame* Geolocation::frame() const | 118 LocalFrame* Geolocation::frame() const |
116 { | 119 { |
117 return document() ? document()->frame() : 0; | 120 return document() ? document()->frame() : 0; |
118 } | 121 } |
119 | 122 |
120 void Geolocation::stop() | 123 void Geolocation::contextDestroyed() |
121 { | 124 { |
122 LocalFrame* frame = this->frame(); | 125 if (m_permissionService) |
123 if (frame && m_geolocationPermission == PermissionRequested) | 126 m_permissionService.reset(); |
124 GeolocationController::from(frame)->cancelPermissionRequest(this); | |
125 | 127 |
126 // The frame may be moving to a new page and we want to get the permissions
from the new page's client. | |
127 m_geolocationPermission = PermissionUnknown; | |
128 cancelAllRequests(); | 128 cancelAllRequests(); |
129 stopUpdating(); | 129 stopUpdating(); |
| 130 m_geolocationPermission = PermissionDenied; |
130 m_pendingForPermissionNotifiers.clear(); | 131 m_pendingForPermissionNotifiers.clear(); |
131 } | 132 m_lastPosition = nullptr; |
132 | 133 ContextLifecycleObserver::clearContext(); |
133 Geoposition* Geolocation::lastPosition() | 134 PageLifecycleObserver::clearContext(); |
134 { | |
135 LocalFrame* frame = this->frame(); | |
136 if (!frame) | |
137 return 0; | |
138 | |
139 m_lastPosition = createGeoposition(GeolocationController::from(frame)->lastP
osition()); | |
140 | |
141 return m_lastPosition; | |
142 } | 135 } |
143 | 136 |
144 void Geolocation::recordOriginTypeAccess() const | 137 void Geolocation::recordOriginTypeAccess() const |
145 { | 138 { |
146 ASSERT(frame()); | 139 ASSERT(frame()); |
147 | 140 |
148 Document* document = this->document(); | 141 Document* document = this->document(); |
149 ASSERT(document); | 142 ASSERT(document); |
150 | 143 |
151 // It is required by isSecureContext() but isn't | 144 // It is required by isSecureContext() but isn't |
(...skipping 59 matching lines...) Loading... |
211 if (isDenied()) | 204 if (isDenied()) |
212 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_
DENIED, permissionDeniedErrorMessage)); | 205 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_
DENIED, permissionDeniedErrorMessage)); |
213 else if (haveSuitableCachedPosition(notifier->options())) | 206 else if (haveSuitableCachedPosition(notifier->options())) |
214 notifier->setUseCachedPosition(); | 207 notifier->setUseCachedPosition(); |
215 else if (!notifier->options().timeout()) | 208 else if (!notifier->options().timeout()) |
216 notifier->startTimer(); | 209 notifier->startTimer(); |
217 else if (!isAllowed()) { | 210 else if (!isAllowed()) { |
218 // if we don't yet have permission, request for permission before callin
g startUpdating() | 211 // if we don't yet have permission, request for permission before callin
g startUpdating() |
219 m_pendingForPermissionNotifiers.add(notifier); | 212 m_pendingForPermissionNotifiers.add(notifier); |
220 requestPermission(); | 213 requestPermission(); |
221 } else if (startUpdating(notifier)) | 214 } else { |
| 215 startUpdating(notifier); |
222 notifier->startTimer(); | 216 notifier->startTimer(); |
223 else | 217 } |
224 notifier->setFatalError(PositionError::create(PositionError::POSITION_UN
AVAILABLE, failedToStartServiceErrorMessage)); | |
225 } | 218 } |
226 | 219 |
227 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) | 220 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) |
228 { | 221 { |
229 // This request has failed fatally. Remove it from our lists. | 222 // This request has failed fatally. Remove it from our lists. |
230 m_oneShots.remove(notifier); | 223 m_oneShots.remove(notifier); |
231 m_watchers.remove(notifier); | 224 m_watchers.remove(notifier); |
232 | 225 |
233 if (!hasListeners()) | 226 if (!hasListeners()) |
234 stopUpdating(); | 227 stopUpdating(); |
235 } | 228 } |
236 | 229 |
237 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) | 230 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) |
238 { | 231 { |
239 // This is called asynchronously, so the permissions could have been denied | 232 DCHECK(isAllowed()); |
240 // since we last checked in startRequest. | 233 |
241 if (isDenied()) { | 234 notifier->runSuccessCallback(m_lastPosition); |
242 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_
DENIED, permissionDeniedErrorMessage)); | 235 |
243 return; | 236 // If this is a one-shot request, stop it. Otherwise, if the watch still |
| 237 // exists, start the service to get updates. |
| 238 if (m_oneShots.contains(notifier)) { |
| 239 m_oneShots.remove(notifier); |
| 240 } else if (m_watchers.contains(notifier)) { |
| 241 if (notifier->options().timeout()) |
| 242 startUpdating(notifier); |
| 243 notifier->startTimer(); |
244 } | 244 } |
245 | 245 |
246 m_requestsAwaitingCachedPosition.add(notifier); | |
247 | |
248 // If permissions are allowed, make the callback | |
249 if (isAllowed()) { | |
250 makeCachedPositionCallbacks(); | |
251 return; | |
252 } | |
253 | |
254 // Request permissions, which may be synchronous or asynchronous. | |
255 requestPermission(); | |
256 } | |
257 | |
258 void Geolocation::makeCachedPositionCallbacks() | |
259 { | |
260 // All modifications to m_requestsAwaitingCachedPosition are done | |
261 // asynchronously, so we don't need to worry about it being modified from | |
262 // the callbacks. | |
263 for (GeoNotifier* notifier : m_requestsAwaitingCachedPosition) { | |
264 notifier->runSuccessCallback(lastPosition()); | |
265 | |
266 // If this is a one-shot request, stop it. Otherwise, if the watch still | |
267 // exists, start the service to get updates. | |
268 if (m_oneShots.contains(notifier)) | |
269 m_oneShots.remove(notifier); | |
270 else if (m_watchers.contains(notifier)) { | |
271 if (!notifier->options().timeout() || startUpdating(notifier)) | |
272 notifier->startTimer(); | |
273 else | |
274 notifier->setFatalError(PositionError::create(PositionError::POS
ITION_UNAVAILABLE, failedToStartServiceErrorMessage)); | |
275 } | |
276 } | |
277 | |
278 m_requestsAwaitingCachedPosition.clear(); | |
279 | |
280 if (!hasListeners()) | 246 if (!hasListeners()) |
281 stopUpdating(); | 247 stopUpdating(); |
282 } | 248 } |
283 | 249 |
284 void Geolocation::requestTimedOut(GeoNotifier* notifier) | 250 void Geolocation::requestTimedOut(GeoNotifier* notifier) |
285 { | 251 { |
286 // If this is a one-shot request, stop it. | 252 // If this is a one-shot request, stop it. |
287 m_oneShots.remove(notifier); | 253 m_oneShots.remove(notifier); |
288 | 254 |
289 if (!hasListeners()) | 255 if (!hasListeners()) |
290 stopUpdating(); | 256 stopUpdating(); |
291 } | 257 } |
292 | 258 |
293 bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) | 259 bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) |
294 { | 260 { |
295 Geoposition* cachedPosition = lastPosition(); | 261 if (!m_lastPosition) |
296 if (!cachedPosition) | |
297 return false; | 262 return false; |
| 263 DCHECK(isAllowed()); |
298 if (!options.maximumAge()) | 264 if (!options.maximumAge()) |
299 return false; | 265 return false; |
300 DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime())
; | 266 DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime())
; |
301 return cachedPosition->timestamp() > currentTimeMillis - options.maximumAge(
); | 267 return m_lastPosition->timestamp() > currentTimeMillis - options.maximumAge(
); |
302 } | 268 } |
303 | 269 |
304 void Geolocation::clearWatch(int watchID) | 270 void Geolocation::clearWatch(int watchID) |
305 { | 271 { |
306 if (watchID <= 0) | 272 if (watchID <= 0) |
307 return; | 273 return; |
308 | 274 |
309 if (GeoNotifier* notifier = m_watchers.find(watchID)) | 275 if (GeoNotifier* notifier = m_watchers.find(watchID)) |
310 m_pendingForPermissionNotifiers.remove(notifier); | 276 m_pendingForPermissionNotifiers.remove(notifier); |
311 m_watchers.remove(watchID); | 277 m_watchers.remove(watchID); |
312 | 278 |
313 if (!hasListeners()) | 279 if (!hasListeners()) |
314 stopUpdating(); | 280 stopUpdating(); |
315 } | 281 } |
316 | 282 |
317 void Geolocation::setIsAllowed(bool allowed) | 283 void Geolocation::onGeolocationPermissionUpdated(mojom::blink::PermissionStatus
status) |
318 { | 284 { |
319 // This may be due to either a new position from the service, or a cached po
sition. | 285 // This may be due to either a new position from the service, or a cached po
sition. |
320 m_geolocationPermission = allowed ? PermissionAllowed : PermissionDenied; | 286 m_geolocationPermission = status == mojom::blink::PermissionStatus::GRANTED
? PermissionAllowed : PermissionDenied; |
| 287 m_permissionService.reset(); |
321 | 288 |
322 // Permission request was made during the startRequest process | 289 // While we iterate through the list, we need not worry about the list being
modified as the permission |
323 if (!m_pendingForPermissionNotifiers.isEmpty()) { | 290 // is already set to Yes/No and no new listeners will be added to the pendin
g list. |
324 handlePendingPermissionNotifiers(); | 291 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { |
325 m_pendingForPermissionNotifiers.clear(); | 292 if (isAllowed()) { |
326 return; | 293 // Start all pending notification requests as permission granted. |
| 294 // The notifier is always ref'ed by m_oneShots or m_watchers. |
| 295 startUpdating(notifier); |
| 296 notifier->startTimer(); |
| 297 } else { |
| 298 notifier->setFatalError(PositionError::create(PositionError::PERMISS
ION_DENIED, permissionDeniedErrorMessage)); |
| 299 } |
327 } | 300 } |
328 | 301 m_pendingForPermissionNotifiers.clear(); |
329 if (!isAllowed()) { | |
330 PositionError* error = PositionError::create(PositionError::PERMISSION_D
ENIED, permissionDeniedErrorMessage); | |
331 error->setIsFatal(true); | |
332 handleError(error); | |
333 m_requestsAwaitingCachedPosition.clear(); | |
334 return; | |
335 } | |
336 | |
337 // If the service has a last position, use it to call back for all requests. | |
338 // If any of the requests are waiting for permission for a cached position, | |
339 // the position from the service will be at least as fresh. | |
340 if (lastPosition()) | |
341 makeSuccessCallbacks(); | |
342 else | |
343 makeCachedPositionCallbacks(); | |
344 } | 302 } |
345 | 303 |
346 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) | 304 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) |
347 { | 305 { |
348 for (GeoNotifier* notifier : notifiers) | 306 for (GeoNotifier* notifier : notifiers) |
349 notifier->runErrorCallback(error); | 307 notifier->runErrorCallback(error); |
350 } | 308 } |
351 | 309 |
352 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi
on) | 310 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi
on) |
353 { | 311 { |
(...skipping 102 matching lines...) Loading... |
456 void Geolocation::requestPermission() | 414 void Geolocation::requestPermission() |
457 { | 415 { |
458 if (m_geolocationPermission != PermissionUnknown) | 416 if (m_geolocationPermission != PermissionUnknown) |
459 return; | 417 return; |
460 | 418 |
461 LocalFrame* frame = this->frame(); | 419 LocalFrame* frame = this->frame(); |
462 if (!frame) | 420 if (!frame) |
463 return; | 421 return; |
464 | 422 |
465 m_geolocationPermission = PermissionRequested; | 423 m_geolocationPermission = PermissionRequested; |
| 424 frame->serviceRegistry()->connectToRemoteService( |
| 425 mojo::GetProxy(&m_permissionService)); |
| 426 m_permissionService.set_connection_error_handler(sameThreadBindForMojo(&Geol
ocation::onPermissionConnectionError, this)); |
466 | 427 |
467 // Ask the embedder: it maintains the geolocation challenge policy itself. | 428 // Ask the embedder: it maintains the geolocation challenge policy itself. |
468 GeolocationController::from(frame)->requestPermission(this); | 429 m_permissionService->RequestPermission( |
| 430 mojom::blink::PermissionName::GEOLOCATION, |
| 431 getExecutionContext()->getSecurityOrigin()->toString(), |
| 432 sameThreadBindForMojo(&Geolocation::onGeolocationPermissionUpdated, this
)); |
469 } | 433 } |
470 | 434 |
471 void Geolocation::makeSuccessCallbacks() | 435 void Geolocation::makeSuccessCallbacks() |
472 { | 436 { |
473 ASSERT(lastPosition()); | 437 ASSERT(m_lastPosition); |
474 ASSERT(isAllowed()); | 438 ASSERT(isAllowed()); |
475 | 439 |
476 GeoNotifierVector oneShotsCopy; | 440 GeoNotifierVector oneShotsCopy; |
477 copyToVector(m_oneShots, oneShotsCopy); | 441 copyToVector(m_oneShots, oneShotsCopy); |
478 | 442 |
479 GeoNotifierVector watchersCopy; | 443 GeoNotifierVector watchersCopy; |
480 m_watchers.getNotifiersVector(watchersCopy); | 444 m_watchers.getNotifiersVector(watchersCopy); |
481 | 445 |
482 // Clear the lists before we make the callbacks, to avoid clearing notifiers | 446 // Clear the lists before we make the callbacks, to avoid clearing notifiers |
483 // added by calls to Geolocation methods from the callbacks, and to prevent | 447 // added by calls to Geolocation methods from the callbacks, and to prevent |
484 // further callbacks to these notifiers. | 448 // further callbacks to these notifiers. |
485 m_oneShots.clear(); | 449 m_oneShots.clear(); |
486 | 450 |
487 // Also clear the set of notifiers waiting for a cached position. All the | 451 sendPosition(oneShotsCopy, m_lastPosition); |
488 // oneshots and watchers will receive a position now, and if they happen to | 452 sendPosition(watchersCopy, m_lastPosition); |
489 // be lingering in that set, avoid this bug: http://crbug.com/311876 . | |
490 m_requestsAwaitingCachedPosition.clear(); | |
491 | |
492 sendPosition(oneShotsCopy, lastPosition()); | |
493 sendPosition(watchersCopy, lastPosition()); | |
494 | 453 |
495 if (!hasListeners()) | 454 if (!hasListeners()) |
496 stopUpdating(); | 455 stopUpdating(); |
497 } | 456 } |
498 | 457 |
499 void Geolocation::positionChanged() | 458 void Geolocation::positionChanged() |
500 { | 459 { |
501 ASSERT(isAllowed()); | 460 ASSERT(isAllowed()); |
502 | 461 |
503 // Stop all currently running timers. | 462 // Stop all currently running timers. |
504 stopTimers(); | 463 stopTimers(); |
505 | 464 |
506 makeSuccessCallbacks(); | 465 makeSuccessCallbacks(); |
507 } | 466 } |
508 | 467 |
509 void Geolocation::setError(GeolocationError* error) | 468 void Geolocation::startUpdating(GeoNotifier* notifier) |
510 { | 469 { |
511 handleError(createPositionError(error)); | 470 m_updating = true; |
512 } | 471 if (notifier->options().enableHighAccuracy() && !m_enableHighAccuracy) { |
513 | 472 m_enableHighAccuracy = true; |
514 bool Geolocation::startUpdating(GeoNotifier* notifier) | 473 if (m_geolocationService) |
515 { | 474 m_geolocationService->SetHighAccuracy(true); |
516 LocalFrame* frame = this->frame(); | 475 } |
517 if (!frame) | 476 updateGeolocationServiceConnection(); |
518 return false; | |
519 | |
520 GeolocationController::from(frame)->addObserver(this, notifier->options().en
ableHighAccuracy()); | |
521 return true; | |
522 } | 477 } |
523 | 478 |
524 void Geolocation::stopUpdating() | 479 void Geolocation::stopUpdating() |
525 { | 480 { |
526 LocalFrame* frame = this->frame(); | 481 m_updating = false; |
527 if (!frame) | 482 updateGeolocationServiceConnection(); |
| 483 m_enableHighAccuracy = false; |
| 484 } |
| 485 |
| 486 void Geolocation::updateGeolocationServiceConnection() |
| 487 { |
| 488 if (!getExecutionContext() || !page() || !page()->isPageVisible() || !m_upda
ting) { |
| 489 m_geolocationService.reset(); |
| 490 m_disconnectedGeolocationService = true; |
| 491 return; |
| 492 } |
| 493 if (m_geolocationService) |
528 return; | 494 return; |
529 | 495 |
530 GeolocationController::from(frame)->removeObserver(this); | 496 frame()->serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_geoloca
tionService)); |
| 497 m_geolocationService.set_connection_error_handler(sameThreadBindForMojo(&Geo
location::onGeolocationConnectionError, this)); |
| 498 if (m_enableHighAccuracy) |
| 499 m_geolocationService->SetHighAccuracy(true); |
| 500 queryNextPosition(); |
531 } | 501 } |
532 | 502 |
533 void Geolocation::handlePendingPermissionNotifiers() | 503 void Geolocation::queryNextPosition() |
534 { | 504 { |
535 // While we iterate through the list, we need not worry about list being mod
ified as the permission | 505 m_geolocationService->QueryNextPosition( |
536 // is already set to Yes/No and no new listeners will be added to the pendin
g list. | 506 sameThreadBindForMojo(&Geolocation::onPositionUpdated, this)); |
537 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { | 507 } |
538 if (isAllowed()) { | 508 |
539 // start all pending notification requests as permission granted. | 509 void Geolocation::onPositionUpdated(mojom::blink::GeopositionPtr position) |
540 // The notifier is always ref'ed by m_oneShots or m_watchers. | 510 { |
541 if (startUpdating(notifier)) | 511 m_disconnectedGeolocationService = false; |
542 notifier->startTimer(); | 512 if (position->valid) { |
543 else | 513 m_lastPosition = createGeoposition(*position); |
544 notifier->setFatalError(PositionError::create(PositionError::POS
ITION_UNAVAILABLE, failedToStartServiceErrorMessage)); | 514 positionChanged(); |
545 } else { | 515 } else { |
546 notifier->setFatalError(PositionError::create(PositionError::PERMISS
ION_DENIED, permissionDeniedErrorMessage)); | 516 handleError(createPositionError(position->error_code, position->error_me
ssage)); |
547 } | |
548 } | 517 } |
| 518 if (!m_disconnectedGeolocationService) |
| 519 queryNextPosition(); |
| 520 } |
| 521 |
| 522 void Geolocation::pageVisibilityChanged() |
| 523 { |
| 524 updateGeolocationServiceConnection(); |
| 525 } |
| 526 |
| 527 void Geolocation::onGeolocationConnectionError() |
| 528 { |
| 529 PositionError* error = PositionError::create(PositionError::POSITION_UNAVAIL
ABLE, failedToStartServiceErrorMessage); |
| 530 error->setIsFatal(true); |
| 531 handleError(error); |
| 532 } |
| 533 |
| 534 void Geolocation::onPermissionConnectionError() |
| 535 { |
| 536 onGeolocationPermissionUpdated(mojom::blink::PermissionStatus::DENIED); |
549 } | 537 } |
550 | 538 |
551 } // namespace blink | 539 } // namespace blink |
OLD | NEW |