Chromium Code Reviews| 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...) Expand all 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 ASSERT_NOT_REACHED(); | |
|
Marijn Kruisselbrink
2016/05/06 20:12:15
ASSERT_NOT_REACHED() is deprecated in favor of NOT
Sam McNally
2016/05/10 10:06:08
Done.
| |
| 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(); | 87 geolocation->suspendIfNeeded(); |
| 86 return geolocation; | 88 return geolocation; |
| 87 } | 89 } |
| 88 | 90 |
| 89 Geolocation::Geolocation(ExecutionContext* context) | 91 Geolocation::Geolocation(ExecutionContext* context) |
| 90 : ActiveDOMObject(context) | 92 : ActiveDOMObject(context) |
| 93 , PageLifecycleObserver(document()->page()) | |
| 91 , m_geolocationPermission(PermissionUnknown) | 94 , m_geolocationPermission(PermissionUnknown) |
| 92 { | 95 { |
| 96 ThreadState::current()->registerPreFinalizer(this); | |
| 93 } | 97 } |
| 94 | 98 |
| 95 Geolocation::~Geolocation() | 99 Geolocation::~Geolocation() |
| 96 { | 100 { |
| 97 ASSERT(m_geolocationPermission != PermissionRequested); | 101 ASSERT(m_geolocationPermission != PermissionRequested); |
| 98 } | 102 } |
| 99 | 103 |
| 100 DEFINE_TRACE(Geolocation) | 104 DEFINE_TRACE(Geolocation) |
| 101 { | 105 { |
| 102 visitor->trace(m_oneShots); | 106 visitor->trace(m_oneShots); |
| 103 visitor->trace(m_watchers); | 107 visitor->trace(m_watchers); |
| 104 visitor->trace(m_pendingForPermissionNotifiers); | 108 visitor->trace(m_pendingForPermissionNotifiers); |
| 105 visitor->trace(m_lastPosition); | 109 visitor->trace(m_lastPosition); |
| 106 visitor->trace(m_requestsAwaitingCachedPosition); | |
| 107 ActiveDOMObject::trace(visitor); | 110 ActiveDOMObject::trace(visitor); |
| 111 PageLifecycleObserver::trace(visitor); | |
| 108 } | 112 } |
| 109 | 113 |
| 110 Document* Geolocation::document() const | 114 Document* Geolocation::document() const |
| 111 { | 115 { |
| 112 return toDocument(getExecutionContext()); | 116 return toDocument(getExecutionContext()); |
| 113 } | 117 } |
| 114 | 118 |
| 115 LocalFrame* Geolocation::frame() const | 119 LocalFrame* Geolocation::frame() const |
| 116 { | 120 { |
| 117 return document() ? document()->frame() : 0; | 121 return document() ? document()->frame() : 0; |
| 118 } | 122 } |
| 119 | 123 |
| 120 void Geolocation::stop() | 124 void Geolocation::stop() |
|
Michael van Ouwerkerk
2016/05/09 17:22:31
I think this should also stop observing Page: "Pag
Sam McNally
2016/05/10 10:06:08
Done.
dcheng
2016/05/10 23:55:29
I don't think a swept Page should be doing any vis
Michael van Ouwerkerk
2016/05/11 12:38:30
The issue seems to be that while ContextLifecycleO
| |
| 121 { | 125 { |
| 122 LocalFrame* frame = this->frame(); | 126 if (m_permissionService) |
| 123 if (frame && m_geolocationPermission == PermissionRequested) | 127 m_permissionService.reset(); |
| 124 GeolocationController::from(frame)->cancelPermissionRequest(this); | |
| 125 | 128 |
| 126 // The frame may be moving to a new page and we want to get the permissions from the new page's client. | 129 // The frame may be moving to a new page and we want to get the permissions from the new page's permission service. |
|
Michael van Ouwerkerk
2016/05/09 17:22:31
I think there's more that has changed than just Ge
dcheng
2016/05/09 18:22:29
I don't understand this comment. What does it mean
Sam McNally
2016/05/10 10:06:08
I didn't think that Geolocation objects would be r
| |
| 127 m_geolocationPermission = PermissionUnknown; | 130 m_geolocationPermission = PermissionUnknown; |
| 128 cancelAllRequests(); | 131 cancelAllRequests(); |
| 129 stopUpdating(); | 132 stopUpdating(); |
| 130 m_pendingForPermissionNotifiers.clear(); | 133 m_pendingForPermissionNotifiers.clear(); |
| 131 } | 134 m_lastPosition = nullptr; |
| 132 | |
| 133 Geoposition* Geolocation::lastPosition() | |
| 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 if (isDenied()) | 196 if (isDenied()) |
| 204 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 197 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); |
| 205 else if (haveSuitableCachedPosition(notifier->options())) | 198 else if (haveSuitableCachedPosition(notifier->options())) |
| 206 notifier->setUseCachedPosition(); | 199 notifier->setUseCachedPosition(); |
| 207 else if (!notifier->options().timeout()) | 200 else if (!notifier->options().timeout()) |
| 208 notifier->startTimer(); | 201 notifier->startTimer(); |
| 209 else if (!isAllowed()) { | 202 else if (!isAllowed()) { |
| 210 // if we don't yet have permission, request for permission before callin g startUpdating() | 203 // if we don't yet have permission, request for permission before callin g startUpdating() |
| 211 m_pendingForPermissionNotifiers.add(notifier); | 204 m_pendingForPermissionNotifiers.add(notifier); |
| 212 requestPermission(); | 205 requestPermission(); |
| 213 } else if (startUpdating(notifier)) | 206 } else { |
| 207 startUpdating(notifier); | |
| 214 notifier->startTimer(); | 208 notifier->startTimer(); |
| 215 else | 209 } |
| 216 notifier->setFatalError(PositionError::create(PositionError::POSITION_UN AVAILABLE, failedToStartServiceErrorMessage)); | |
| 217 } | 210 } |
| 218 | 211 |
| 219 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) | 212 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) |
| 220 { | 213 { |
| 221 // This request has failed fatally. Remove it from our lists. | 214 // This request has failed fatally. Remove it from our lists. |
| 222 m_oneShots.remove(notifier); | 215 m_oneShots.remove(notifier); |
| 223 m_watchers.remove(notifier); | 216 m_watchers.remove(notifier); |
| 224 | 217 |
| 225 if (!hasListeners()) | 218 if (!hasListeners()) |
| 226 stopUpdating(); | 219 stopUpdating(); |
| 227 } | 220 } |
| 228 | 221 |
| 229 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) | 222 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) |
| 230 { | 223 { |
| 231 // This is called asynchronously, so the permissions could have been denied | 224 DCHECK(isAllowed()); |
| 232 // since we last checked in startRequest. | 225 |
| 233 if (isDenied()) { | 226 notifier->runSuccessCallback(m_lastPosition); |
| 234 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 227 |
| 235 return; | 228 // If this is a one-shot request, stop it. Otherwise, if the watch still |
| 229 // exists, start the service to get updates. | |
| 230 if (m_oneShots.contains(notifier)) { | |
| 231 m_oneShots.remove(notifier); | |
| 232 } else if (m_watchers.contains(notifier)) { | |
| 233 if (notifier->options().timeout()) | |
| 234 startUpdating(notifier); | |
| 235 notifier->startTimer(); | |
| 236 } | 236 } |
| 237 | 237 |
| 238 m_requestsAwaitingCachedPosition.add(notifier); | |
| 239 | |
| 240 // If permissions are allowed, make the callback | |
| 241 if (isAllowed()) { | |
| 242 makeCachedPositionCallbacks(); | |
| 243 return; | |
| 244 } | |
| 245 | |
| 246 // Request permissions, which may be synchronous or asynchronous. | |
| 247 requestPermission(); | |
| 248 } | |
| 249 | |
| 250 void Geolocation::makeCachedPositionCallbacks() | |
| 251 { | |
| 252 // All modifications to m_requestsAwaitingCachedPosition are done | |
| 253 // asynchronously, so we don't need to worry about it being modified from | |
| 254 // the callbacks. | |
| 255 for (GeoNotifier* notifier : m_requestsAwaitingCachedPosition) { | |
| 256 notifier->runSuccessCallback(lastPosition()); | |
| 257 | |
| 258 // If this is a one-shot request, stop it. Otherwise, if the watch still | |
| 259 // exists, start the service to get updates. | |
| 260 if (m_oneShots.contains(notifier)) | |
| 261 m_oneShots.remove(notifier); | |
| 262 else if (m_watchers.contains(notifier)) { | |
| 263 if (!notifier->options().timeout() || startUpdating(notifier)) | |
| 264 notifier->startTimer(); | |
| 265 else | |
| 266 notifier->setFatalError(PositionError::create(PositionError::POS ITION_UNAVAILABLE, failedToStartServiceErrorMessage)); | |
| 267 } | |
| 268 } | |
| 269 | |
| 270 m_requestsAwaitingCachedPosition.clear(); | |
| 271 | |
| 272 if (!hasListeners()) | 238 if (!hasListeners()) |
| 273 stopUpdating(); | 239 stopUpdating(); |
| 274 } | 240 } |
| 275 | 241 |
| 276 void Geolocation::requestTimedOut(GeoNotifier* notifier) | 242 void Geolocation::requestTimedOut(GeoNotifier* notifier) |
| 277 { | 243 { |
| 278 // If this is a one-shot request, stop it. | 244 // If this is a one-shot request, stop it. |
| 279 m_oneShots.remove(notifier); | 245 m_oneShots.remove(notifier); |
| 280 | 246 |
| 281 if (!hasListeners()) | 247 if (!hasListeners()) |
| 282 stopUpdating(); | 248 stopUpdating(); |
| 283 } | 249 } |
| 284 | 250 |
| 285 bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) | 251 bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) |
| 286 { | 252 { |
| 287 Geoposition* cachedPosition = lastPosition(); | 253 if (!m_lastPosition) |
| 288 if (!cachedPosition) | |
| 289 return false; | 254 return false; |
| 255 DCHECK(isAllowed()); | |
| 290 if (!options.maximumAge()) | 256 if (!options.maximumAge()) |
| 291 return false; | 257 return false; |
| 292 DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime()) ; | 258 DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime()) ; |
| 293 return cachedPosition->timestamp() > currentTimeMillis - options.maximumAge( ); | 259 return m_lastPosition->timestamp() > currentTimeMillis - options.maximumAge( ); |
| 294 } | 260 } |
| 295 | 261 |
| 296 void Geolocation::clearWatch(int watchID) | 262 void Geolocation::clearWatch(int watchID) |
| 297 { | 263 { |
| 298 if (watchID <= 0) | 264 if (watchID <= 0) |
| 299 return; | 265 return; |
| 300 | 266 |
| 301 if (GeoNotifier* notifier = m_watchers.find(watchID)) | 267 if (GeoNotifier* notifier = m_watchers.find(watchID)) |
| 302 m_pendingForPermissionNotifiers.remove(notifier); | 268 m_pendingForPermissionNotifiers.remove(notifier); |
| 303 m_watchers.remove(watchID); | 269 m_watchers.remove(watchID); |
| 304 | 270 |
| 305 if (!hasListeners()) | 271 if (!hasListeners()) |
| 306 stopUpdating(); | 272 stopUpdating(); |
| 307 } | 273 } |
| 308 | 274 |
| 309 void Geolocation::setIsAllowed(bool allowed) | 275 void Geolocation::onGeolocationPermissionUpdated(mojom::blink::PermissionStatus status) |
| 310 { | 276 { |
| 311 // This may be due to either a new position from the service, or a cached po sition. | 277 // This may be due to either a new position from the service, or a cached po sition. |
| 312 m_geolocationPermission = allowed ? PermissionAllowed : PermissionDenied; | 278 m_geolocationPermission = status == mojom::blink::PermissionStatus::GRANTED ? PermissionAllowed : PermissionDenied; |
| 279 m_permissionService.reset(); | |
| 313 | 280 |
| 314 // Permission request was made during the startRequest process | 281 // While we iterate through the list, we need not worry about the list being modified as the permission |
| 315 if (!m_pendingForPermissionNotifiers.isEmpty()) { | 282 // is already set to Yes/No and no new listeners will be added to the pendin g list. |
| 316 handlePendingPermissionNotifiers(); | 283 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { |
| 317 m_pendingForPermissionNotifiers.clear(); | 284 if (isAllowed()) { |
| 318 return; | 285 // Start all pending notification requests as permission granted. |
| 286 // The notifier is always ref'ed by m_oneShots or m_watchers. | |
| 287 startUpdating(notifier); | |
| 288 notifier->startTimer(); | |
| 289 } else { | |
| 290 notifier->setFatalError(PositionError::create(PositionError::PERMISS ION_DENIED, permissionDeniedErrorMessage)); | |
| 291 } | |
| 319 } | 292 } |
| 320 | 293 m_pendingForPermissionNotifiers.clear(); |
| 321 if (!isAllowed()) { | |
| 322 PositionError* error = PositionError::create(PositionError::PERMISSION_D ENIED, permissionDeniedErrorMessage); | |
| 323 error->setIsFatal(true); | |
| 324 handleError(error); | |
| 325 m_requestsAwaitingCachedPosition.clear(); | |
| 326 return; | |
| 327 } | |
| 328 | |
| 329 // If the service has a last position, use it to call back for all requests. | |
| 330 // If any of the requests are waiting for permission for a cached position, | |
| 331 // the position from the service will be at least as fresh. | |
| 332 if (lastPosition()) | |
| 333 makeSuccessCallbacks(); | |
| 334 else | |
| 335 makeCachedPositionCallbacks(); | |
| 336 } | 294 } |
| 337 | 295 |
| 338 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) | 296 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) |
| 339 { | 297 { |
| 340 for (GeoNotifier* notifier : notifiers) | 298 for (GeoNotifier* notifier : notifiers) |
| 341 notifier->runErrorCallback(error); | 299 notifier->runErrorCallback(error); |
| 342 } | 300 } |
| 343 | 301 |
| 344 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi on) | 302 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi on) |
| 345 { | 303 { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 void Geolocation::requestPermission() | 406 void Geolocation::requestPermission() |
| 449 { | 407 { |
| 450 if (m_geolocationPermission != PermissionUnknown) | 408 if (m_geolocationPermission != PermissionUnknown) |
| 451 return; | 409 return; |
| 452 | 410 |
| 453 LocalFrame* frame = this->frame(); | 411 LocalFrame* frame = this->frame(); |
| 454 if (!frame) | 412 if (!frame) |
| 455 return; | 413 return; |
| 456 | 414 |
| 457 m_geolocationPermission = PermissionRequested; | 415 m_geolocationPermission = PermissionRequested; |
| 416 frame->serviceRegistry()->connectToRemoteService( | |
| 417 mojo::GetProxy(&m_permissionService)); | |
| 418 m_permissionService.set_connection_error_handler(sameThreadBindForMojo(&Geol ocation::onPermissionConnectionError, this)); | |
| 458 | 419 |
| 459 // Ask the embedder: it maintains the geolocation challenge policy itself. | 420 // Ask the embedder: it maintains the geolocation challenge policy itself. |
| 460 GeolocationController::from(frame)->requestPermission(this); | 421 m_permissionService->RequestPermission( |
| 422 mojom::blink::PermissionName::GEOLOCATION, | |
| 423 getExecutionContext()->getSecurityOrigin()->toString(), | |
| 424 sameThreadBindForMojo(&Geolocation::onGeolocationPermissionUpdated, this )); | |
| 461 } | 425 } |
| 462 | 426 |
| 463 void Geolocation::makeSuccessCallbacks() | 427 void Geolocation::makeSuccessCallbacks() |
| 464 { | 428 { |
| 465 ASSERT(lastPosition()); | 429 ASSERT(m_lastPosition); |
| 466 ASSERT(isAllowed()); | 430 ASSERT(isAllowed()); |
| 467 | 431 |
| 468 GeoNotifierVector oneShotsCopy; | 432 GeoNotifierVector oneShotsCopy; |
| 469 copyToVector(m_oneShots, oneShotsCopy); | 433 copyToVector(m_oneShots, oneShotsCopy); |
| 470 | 434 |
| 471 GeoNotifierVector watchersCopy; | 435 GeoNotifierVector watchersCopy; |
| 472 m_watchers.getNotifiersVector(watchersCopy); | 436 m_watchers.getNotifiersVector(watchersCopy); |
| 473 | 437 |
| 474 // Clear the lists before we make the callbacks, to avoid clearing notifiers | 438 // Clear the lists before we make the callbacks, to avoid clearing notifiers |
| 475 // added by calls to Geolocation methods from the callbacks, and to prevent | 439 // added by calls to Geolocation methods from the callbacks, and to prevent |
| 476 // further callbacks to these notifiers. | 440 // further callbacks to these notifiers. |
| 477 m_oneShots.clear(); | 441 m_oneShots.clear(); |
| 478 | 442 |
| 479 // Also clear the set of notifiers waiting for a cached position. All the | 443 sendPosition(oneShotsCopy, m_lastPosition); |
| 480 // oneshots and watchers will receive a position now, and if they happen to | 444 sendPosition(watchersCopy, m_lastPosition); |
| 481 // be lingering in that set, avoid this bug: http://crbug.com/311876 . | |
| 482 m_requestsAwaitingCachedPosition.clear(); | |
| 483 | |
| 484 sendPosition(oneShotsCopy, lastPosition()); | |
| 485 sendPosition(watchersCopy, lastPosition()); | |
| 486 | 445 |
| 487 if (!hasListeners()) | 446 if (!hasListeners()) |
| 488 stopUpdating(); | 447 stopUpdating(); |
| 489 } | 448 } |
| 490 | 449 |
| 491 void Geolocation::positionChanged() | 450 void Geolocation::positionChanged() |
| 492 { | 451 { |
| 493 ASSERT(isAllowed()); | 452 ASSERT(isAllowed()); |
| 494 | 453 |
| 495 // Stop all currently running timers. | 454 // Stop all currently running timers. |
| 496 stopTimers(); | 455 stopTimers(); |
| 497 | 456 |
| 498 makeSuccessCallbacks(); | 457 makeSuccessCallbacks(); |
| 499 } | 458 } |
| 500 | 459 |
| 501 void Geolocation::setError(GeolocationError* error) | 460 void Geolocation::startUpdating(GeoNotifier* notifier) |
| 502 { | 461 { |
| 503 handleError(createPositionError(error)); | 462 // This may be called multiple times, though stopUpdating() is called only |
|
Michael van Ouwerkerk
2016/05/09 17:22:31
There are many calls to stopUpdating(). What did y
Sam McNally
2016/05/10 10:06:08
It was copy-pasted from GeolocationController and
| |
| 504 } | 463 // once. |
| 505 | 464 m_updating = true; |
| 506 bool Geolocation::startUpdating(GeoNotifier* notifier) | 465 if (notifier->options().enableHighAccuracy() && !m_enableHighAccuracy) { |
| 507 { | 466 m_enableHighAccuracy = true; |
| 508 LocalFrame* frame = this->frame(); | 467 if (m_geolocationService) |
| 509 if (!frame) | 468 m_geolocationService->SetHighAccuracy(true); |
| 510 return false; | 469 } |
| 511 | 470 updateGeolocationServiceConnection(); |
| 512 GeolocationController::from(frame)->addObserver(this, notifier->options().en ableHighAccuracy()); | |
| 513 return true; | |
| 514 } | 471 } |
| 515 | 472 |
| 516 void Geolocation::stopUpdating() | 473 void Geolocation::stopUpdating() |
| 517 { | 474 { |
| 518 LocalFrame* frame = this->frame(); | 475 m_updating = false; |
| 519 if (!frame) | 476 updateGeolocationServiceConnection(); |
| 477 m_enableHighAccuracy = false; | |
| 478 } | |
| 479 | |
| 480 void Geolocation::updateGeolocationServiceConnection() | |
| 481 { | |
| 482 if (!page() || !page()->isPageVisible() || !m_updating) { | |
|
Michael van Ouwerkerk
2016/05/09 17:22:31
This should also check that getExecutionContext()
Sam McNally
2016/05/10 10:06:08
Done.
| |
| 483 m_geolocationService.reset(); | |
| 484 m_disconnectedGeolocationService = true; | |
| 485 return; | |
| 486 } | |
| 487 if (m_geolocationService) | |
| 520 return; | 488 return; |
| 521 | 489 |
| 522 GeolocationController::from(frame)->removeObserver(this); | 490 frame()->serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_geoloca tionService)); |
| 491 m_geolocationService.set_connection_error_handler(sameThreadBindForMojo(&Geo location::onGeolocationConnectionError, this)); | |
| 492 if (m_enableHighAccuracy) | |
| 493 m_geolocationService->SetHighAccuracy(true); | |
| 494 queryNextPosition(); | |
| 523 } | 495 } |
| 524 | 496 |
| 525 void Geolocation::handlePendingPermissionNotifiers() | 497 void Geolocation::queryNextPosition() |
| 526 { | 498 { |
| 527 // While we iterate through the list, we need not worry about list being mod ified as the permission | 499 m_geolocationService->QueryNextPosition( |
| 528 // is already set to Yes/No and no new listeners will be added to the pendin g list. | 500 sameThreadBindForMojo(&Geolocation::onPositionUpdated, this)); |
| 529 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { | 501 } |
| 530 if (isAllowed()) { | 502 |
| 531 // start all pending notification requests as permission granted. | 503 void Geolocation::onPositionUpdated(mojom::blink::GeopositionPtr position) |
| 532 // The notifier is always ref'ed by m_oneShots or m_watchers. | 504 { |
| 533 if (startUpdating(notifier)) | 505 m_disconnectedGeolocationService = false; |
| 534 notifier->startTimer(); | 506 if (position->valid) { |
| 535 else | 507 m_lastPosition = createGeoposition(*position); |
| 536 notifier->setFatalError(PositionError::create(PositionError::POS ITION_UNAVAILABLE, failedToStartServiceErrorMessage)); | 508 positionChanged(); |
| 537 } else { | 509 } else { |
| 538 notifier->setFatalError(PositionError::create(PositionError::PERMISS ION_DENIED, permissionDeniedErrorMessage)); | 510 handleError(createPositionError(position->error_code, position->error_me ssage)); |
| 539 } | |
| 540 } | 511 } |
| 512 if (!m_disconnectedGeolocationService) | |
| 513 queryNextPosition(); | |
| 514 } | |
| 515 | |
| 516 void Geolocation::pageVisibilityChanged() | |
| 517 { | |
| 518 updateGeolocationServiceConnection(); | |
| 519 } | |
| 520 | |
| 521 void Geolocation::onGeolocationConnectionError() | |
| 522 { | |
| 523 PositionError* error = PositionError::create(PositionError::POSITION_UNAVAIL ABLE, failedToStartServiceErrorMessage); | |
| 524 error->setIsFatal(true); | |
| 525 handleError(error); | |
| 526 } | |
| 527 | |
| 528 void Geolocation::onPermissionConnectionError() | |
| 529 { | |
| 530 onGeolocationPermissionUpdated(mojom::blink::PermissionStatus::DENIED); | |
| 541 } | 531 } |
| 542 | 532 |
| 543 } // namespace blink | 533 } // namespace blink |
| OLD | NEW |