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., | 
| 
 
dcheng
2016/05/13 03:42:55
These checks are kind of opaque. Why -10000, etc?
 
dcheng
2016/05/13 03:43:32
Oh I see, this is from the old Geolocation code. M
 
Sam McNally
2016/05/13 05:00:30
Done.
 
 | |
| 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 { | 
| 93 } | 95 } | 
| 94 | 96 | 
| 95 Geolocation::~Geolocation() | 97 Geolocation::~Geolocation() | 
| 96 { | 98 { | 
| 97 ASSERT(m_geolocationPermission != PermissionRequested); | 99 ASSERT(m_geolocationPermission != PermissionRequested); | 
| 98 } | 100 } | 
| 99 | 101 | 
| 100 DEFINE_TRACE(Geolocation) | 102 DEFINE_TRACE(Geolocation) | 
| 101 { | 103 { | 
| 102 visitor->trace(m_oneShots); | 104 visitor->trace(m_oneShots); | 
| 103 visitor->trace(m_watchers); | 105 visitor->trace(m_watchers); | 
| 104 visitor->trace(m_pendingForPermissionNotifiers); | 106 visitor->trace(m_pendingForPermissionNotifiers); | 
| 105 visitor->trace(m_lastPosition); | 107 visitor->trace(m_lastPosition); | 
| 106 visitor->trace(m_requestsAwaitingCachedPosition); | 108 ContextLifecycleObserver::trace(visitor); | 
| 107 ActiveDOMObject::trace(visitor); | 109 PageLifecycleObserver::trace(visitor); | 
| 108 } | 110 } | 
| 109 | 111 | 
| 110 Document* Geolocation::document() const | 112 Document* Geolocation::document() const | 
| 111 { | 113 { | 
| 112 return toDocument(getExecutionContext()); | 114 return toDocument(getExecutionContext()); | 
| 113 } | 115 } | 
| 114 | 116 | 
| 115 LocalFrame* Geolocation::frame() const | 117 LocalFrame* Geolocation::frame() const | 
| 116 { | 118 { | 
| 117 return document() ? document()->frame() : 0; | 119 return document() ? document()->frame() : 0; | 
| 118 } | 120 } | 
| 119 | 121 | 
| 120 void Geolocation::stop() | 122 void Geolocation::contextDestroyed() | 
| 121 { | 123 { | 
| 122 LocalFrame* frame = this->frame(); | 124 if (m_permissionService) | 
| 123 if (frame && m_geolocationPermission == PermissionRequested) | 125 m_permissionService.reset(); | 
| 
 
dcheng
2016/05/13 03:42:55
I think it's OK to just unconditionally call m_per
 
Sam McNally
2016/05/13 05:00:30
Done.
 
 | |
| 124 GeolocationController::from(frame)->cancelPermissionRequest(this); | |
| 125 | 126 | 
| 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(); | 127 cancelAllRequests(); | 
| 129 stopUpdating(); | 128 stopUpdating(); | 
| 129 m_geolocationPermission = PermissionDenied; | |
| 130 m_pendingForPermissionNotifiers.clear(); | 130 m_pendingForPermissionNotifiers.clear(); | 
| 131 } | 131 m_lastPosition = nullptr; | 
| 132 | 132 ContextLifecycleObserver::clearContext(); | 
| 133 Geoposition* Geolocation::lastPosition() | 133 PageLifecycleObserver::clearContext(); | 
| 
 
dcheng
2016/05/13 03:42:55
I guess that's an argument switching visibility ch
 
 | |
| 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 } | 134 } | 
| 143 | 135 | 
| 144 void Geolocation::recordOriginTypeAccess() const | 136 void Geolocation::recordOriginTypeAccess() const | 
| 145 { | 137 { | 
| 146 ASSERT(frame()); | 138 ASSERT(frame()); | 
| 147 | 139 | 
| 148 Document* document = this->document(); | 140 Document* document = this->document(); | 
| 149 ASSERT(document); | 141 ASSERT(document); | 
| 150 | 142 | 
| 151 // It is required by isSecureContext() but isn't | 143 // It is required by isSecureContext() but isn't | 
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 if (isDenied()) | 203 if (isDenied()) | 
| 212 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 204 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 
| 213 else if (haveSuitableCachedPosition(notifier->options())) | 205 else if (haveSuitableCachedPosition(notifier->options())) | 
| 214 notifier->setUseCachedPosition(); | 206 notifier->setUseCachedPosition(); | 
| 215 else if (!notifier->options().timeout()) | 207 else if (!notifier->options().timeout()) | 
| 216 notifier->startTimer(); | 208 notifier->startTimer(); | 
| 217 else if (!isAllowed()) { | 209 else if (!isAllowed()) { | 
| 218 // if we don't yet have permission, request for permission before callin g startUpdating() | 210 // if we don't yet have permission, request for permission before callin g startUpdating() | 
| 219 m_pendingForPermissionNotifiers.add(notifier); | 211 m_pendingForPermissionNotifiers.add(notifier); | 
| 220 requestPermission(); | 212 requestPermission(); | 
| 221 } else if (startUpdating(notifier)) | 213 } else { | 
| 214 startUpdating(notifier); | |
| 222 notifier->startTimer(); | 215 notifier->startTimer(); | 
| 223 else | 216 } | 
| 224 notifier->setFatalError(PositionError::create(PositionError::POSITION_UN AVAILABLE, failedToStartServiceErrorMessage)); | |
| 225 } | 217 } | 
| 226 | 218 | 
| 227 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) | 219 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) | 
| 228 { | 220 { | 
| 229 // This request has failed fatally. Remove it from our lists. | 221 // This request has failed fatally. Remove it from our lists. | 
| 230 m_oneShots.remove(notifier); | 222 m_oneShots.remove(notifier); | 
| 231 m_watchers.remove(notifier); | 223 m_watchers.remove(notifier); | 
| 232 | 224 | 
| 233 if (!hasListeners()) | 225 if (!hasListeners()) | 
| 234 stopUpdating(); | 226 stopUpdating(); | 
| 235 } | 227 } | 
| 236 | 228 | 
| 237 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) | 229 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) | 
| 238 { | 230 { | 
| 239 // This is called asynchronously, so the permissions could have been denied | 231 DCHECK(isAllowed()); | 
| 240 // since we last checked in startRequest. | 232 | 
| 241 if (isDenied()) { | 233 notifier->runSuccessCallback(m_lastPosition); | 
| 242 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 234 | 
| 243 return; | 235 // If this is a one-shot request, stop it. Otherwise, if the watch still | 
| 236 // exists, start the service to get updates. | |
| 237 if (m_oneShots.contains(notifier)) { | |
| 238 m_oneShots.remove(notifier); | |
| 239 } else if (m_watchers.contains(notifier)) { | |
| 240 if (notifier->options().timeout()) | |
| 241 startUpdating(notifier); | |
| 242 notifier->startTimer(); | |
| 244 } | 243 } | 
| 245 | 244 | 
| 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()) | 245 if (!hasListeners()) | 
| 281 stopUpdating(); | 246 stopUpdating(); | 
| 282 } | 247 } | 
| 283 | 248 | 
| 284 void Geolocation::requestTimedOut(GeoNotifier* notifier) | 249 void Geolocation::requestTimedOut(GeoNotifier* notifier) | 
| 285 { | 250 { | 
| 286 // If this is a one-shot request, stop it. | 251 // If this is a one-shot request, stop it. | 
| 287 m_oneShots.remove(notifier); | 252 m_oneShots.remove(notifier); | 
| 288 | 253 | 
| 289 if (!hasListeners()) | 254 if (!hasListeners()) | 
| 290 stopUpdating(); | 255 stopUpdating(); | 
| 291 } | 256 } | 
| 292 | 257 | 
| 293 bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) | 258 bool Geolocation::haveSuitableCachedPosition(const PositionOptions& options) | 
| 294 { | 259 { | 
| 295 Geoposition* cachedPosition = lastPosition(); | 260 if (!m_lastPosition) | 
| 296 if (!cachedPosition) | |
| 297 return false; | 261 return false; | 
| 262 DCHECK(isAllowed()); | |
| 298 if (!options.maximumAge()) | 263 if (!options.maximumAge()) | 
| 299 return false; | 264 return false; | 
| 300 DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime()) ; | 265 DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime()) ; | 
| 301 return cachedPosition->timestamp() > currentTimeMillis - options.maximumAge( ); | 266 return m_lastPosition->timestamp() > currentTimeMillis - options.maximumAge( ); | 
| 302 } | 267 } | 
| 303 | 268 | 
| 304 void Geolocation::clearWatch(int watchID) | 269 void Geolocation::clearWatch(int watchID) | 
| 305 { | 270 { | 
| 306 if (watchID <= 0) | 271 if (watchID <= 0) | 
| 307 return; | 272 return; | 
| 308 | 273 | 
| 309 if (GeoNotifier* notifier = m_watchers.find(watchID)) | 274 if (GeoNotifier* notifier = m_watchers.find(watchID)) | 
| 310 m_pendingForPermissionNotifiers.remove(notifier); | 275 m_pendingForPermissionNotifiers.remove(notifier); | 
| 311 m_watchers.remove(watchID); | 276 m_watchers.remove(watchID); | 
| 312 | 277 | 
| 313 if (!hasListeners()) | 278 if (!hasListeners()) | 
| 314 stopUpdating(); | 279 stopUpdating(); | 
| 315 } | 280 } | 
| 316 | 281 | 
| 317 void Geolocation::setIsAllowed(bool allowed) | 282 void Geolocation::onGeolocationPermissionUpdated(mojom::blink::PermissionStatus status) | 
| 318 { | 283 { | 
| 319 // This may be due to either a new position from the service, or a cached po sition. | 284 // This may be due to either a new position from the service, or a cached po sition. | 
| 320 m_geolocationPermission = allowed ? PermissionAllowed : PermissionDenied; | 285 m_geolocationPermission = status == mojom::blink::PermissionStatus::GRANTED ? PermissionAllowed : PermissionDenied; | 
| 286 m_permissionService.reset(); | |
| 321 | 287 | 
| 322 // Permission request was made during the startRequest process | 288 // While we iterate through the list, we need not worry about the list being modified as the permission | 
| 323 if (!m_pendingForPermissionNotifiers.isEmpty()) { | 289 // is already set to Yes/No and no new listeners will be added to the pendin g list. | 
| 324 handlePendingPermissionNotifiers(); | 290 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { | 
| 325 m_pendingForPermissionNotifiers.clear(); | 291 if (isAllowed()) { | 
| 326 return; | 292 // Start all pending notification requests as permission granted. | 
| 293 // The notifier is always ref'ed by m_oneShots or m_watchers. | |
| 294 startUpdating(notifier); | |
| 295 notifier->startTimer(); | |
| 296 } else { | |
| 297 notifier->setFatalError(PositionError::create(PositionError::PERMISS ION_DENIED, permissionDeniedErrorMessage)); | |
| 298 } | |
| 327 } | 299 } | 
| 328 | 300 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 } | 301 } | 
| 345 | 302 | 
| 346 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) | 303 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) | 
| 347 { | 304 { | 
| 348 for (GeoNotifier* notifier : notifiers) | 305 for (GeoNotifier* notifier : notifiers) | 
| 349 notifier->runErrorCallback(error); | 306 notifier->runErrorCallback(error); | 
| 350 } | 307 } | 
| 351 | 308 | 
| 352 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi on) | 309 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi on) | 
| 353 { | 310 { | 
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 void Geolocation::requestPermission() | 413 void Geolocation::requestPermission() | 
| 457 { | 414 { | 
| 458 if (m_geolocationPermission != PermissionUnknown) | 415 if (m_geolocationPermission != PermissionUnknown) | 
| 459 return; | 416 return; | 
| 460 | 417 | 
| 461 LocalFrame* frame = this->frame(); | 418 LocalFrame* frame = this->frame(); | 
| 462 if (!frame) | 419 if (!frame) | 
| 463 return; | 420 return; | 
| 464 | 421 | 
| 465 m_geolocationPermission = PermissionRequested; | 422 m_geolocationPermission = PermissionRequested; | 
| 423 frame->serviceRegistry()->connectToRemoteService( | |
| 424 mojo::GetProxy(&m_permissionService)); | |
| 425 m_permissionService.set_connection_error_handler(sameThreadBindForMojo(&Geol ocation::onPermissionConnectionError, this)); | |
| 466 | 426 | 
| 467 // Ask the embedder: it maintains the geolocation challenge policy itself. | 427 // Ask the embedder: it maintains the geolocation challenge policy itself. | 
| 468 GeolocationController::from(frame)->requestPermission(this); | 428 m_permissionService->RequestPermission( | 
| 429 mojom::blink::PermissionName::GEOLOCATION, | |
| 430 getExecutionContext()->getSecurityOrigin()->toString(), | |
| 431 sameThreadBindForMojo(&Geolocation::onGeolocationPermissionUpdated, this )); | |
| 469 } | 432 } | 
| 470 | 433 | 
| 471 void Geolocation::makeSuccessCallbacks() | 434 void Geolocation::makeSuccessCallbacks() | 
| 472 { | 435 { | 
| 473 ASSERT(lastPosition()); | 436 ASSERT(m_lastPosition); | 
| 474 ASSERT(isAllowed()); | 437 ASSERT(isAllowed()); | 
| 475 | 438 | 
| 476 GeoNotifierVector oneShotsCopy; | 439 GeoNotifierVector oneShotsCopy; | 
| 477 copyToVector(m_oneShots, oneShotsCopy); | 440 copyToVector(m_oneShots, oneShotsCopy); | 
| 478 | 441 | 
| 479 GeoNotifierVector watchersCopy; | 442 GeoNotifierVector watchersCopy; | 
| 480 m_watchers.getNotifiersVector(watchersCopy); | 443 m_watchers.getNotifiersVector(watchersCopy); | 
| 481 | 444 | 
| 482 // Clear the lists before we make the callbacks, to avoid clearing notifiers | 445 // 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 | 446 // added by calls to Geolocation methods from the callbacks, and to prevent | 
| 484 // further callbacks to these notifiers. | 447 // further callbacks to these notifiers. | 
| 485 m_oneShots.clear(); | 448 m_oneShots.clear(); | 
| 486 | 449 | 
| 487 // Also clear the set of notifiers waiting for a cached position. All the | 450 sendPosition(oneShotsCopy, m_lastPosition); | 
| 488 // oneshots and watchers will receive a position now, and if they happen to | 451 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 | 452 | 
| 495 if (!hasListeners()) | 453 if (!hasListeners()) | 
| 496 stopUpdating(); | 454 stopUpdating(); | 
| 497 } | 455 } | 
| 498 | 456 | 
| 499 void Geolocation::positionChanged() | 457 void Geolocation::positionChanged() | 
| 500 { | 458 { | 
| 501 ASSERT(isAllowed()); | 459 ASSERT(isAllowed()); | 
| 502 | 460 | 
| 503 // Stop all currently running timers. | 461 // Stop all currently running timers. | 
| 504 stopTimers(); | 462 stopTimers(); | 
| 505 | 463 | 
| 506 makeSuccessCallbacks(); | 464 makeSuccessCallbacks(); | 
| 507 } | 465 } | 
| 508 | 466 | 
| 509 void Geolocation::setError(GeolocationError* error) | 467 void Geolocation::startUpdating(GeoNotifier* notifier) | 
| 510 { | 468 { | 
| 511 handleError(createPositionError(error)); | 469 m_updating = true; | 
| 512 } | 470 if (notifier->options().enableHighAccuracy() && !m_enableHighAccuracy) { | 
| 513 | 471 m_enableHighAccuracy = true; | 
| 514 bool Geolocation::startUpdating(GeoNotifier* notifier) | 472 if (m_geolocationService) | 
| 515 { | 473 m_geolocationService->SetHighAccuracy(true); | 
| 516 LocalFrame* frame = this->frame(); | 474 } | 
| 517 if (!frame) | 475 updateGeolocationServiceConnection(); | 
| 518 return false; | |
| 519 | |
| 520 GeolocationController::from(frame)->addObserver(this, notifier->options().en ableHighAccuracy()); | |
| 521 return true; | |
| 522 } | 476 } | 
| 523 | 477 | 
| 524 void Geolocation::stopUpdating() | 478 void Geolocation::stopUpdating() | 
| 525 { | 479 { | 
| 526 LocalFrame* frame = this->frame(); | 480 m_updating = false; | 
| 527 if (!frame) | 481 updateGeolocationServiceConnection(); | 
| 482 m_enableHighAccuracy = false; | |
| 483 } | |
| 484 | |
| 485 void Geolocation::updateGeolocationServiceConnection() | |
| 486 { | |
| 487 if (!getExecutionContext() || !page() || !page()->isPageVisible() || !m_upda ting) { | |
| 488 m_geolocationService.reset(); | |
| 489 m_disconnectedGeolocationService = true; | |
| 490 return; | |
| 491 } | |
| 492 if (m_geolocationService) | |
| 528 return; | 493 return; | 
| 529 | 494 | 
| 530 GeolocationController::from(frame)->removeObserver(this); | 495 frame()->serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_geoloca tionService)); | 
| 496 m_geolocationService.set_connection_error_handler(sameThreadBindForMojo(&Geo location::onGeolocationConnectionError, this)); | |
| 497 if (m_enableHighAccuracy) | |
| 498 m_geolocationService->SetHighAccuracy(true); | |
| 499 queryNextPosition(); | |
| 531 } | 500 } | 
| 532 | 501 | 
| 533 void Geolocation::handlePendingPermissionNotifiers() | 502 void Geolocation::queryNextPosition() | 
| 534 { | 503 { | 
| 535 // While we iterate through the list, we need not worry about list being mod ified as the permission | 504 m_geolocationService->QueryNextPosition( | 
| 536 // is already set to Yes/No and no new listeners will be added to the pendin g list. | 505 sameThreadBindForMojo(&Geolocation::onPositionUpdated, this)); | 
| 537 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { | 506 } | 
| 538 if (isAllowed()) { | 507 | 
| 539 // start all pending notification requests as permission granted. | 508 void Geolocation::onPositionUpdated(mojom::blink::GeopositionPtr position) | 
| 540 // The notifier is always ref'ed by m_oneShots or m_watchers. | 509 { | 
| 541 if (startUpdating(notifier)) | 510 m_disconnectedGeolocationService = false; | 
| 542 notifier->startTimer(); | 511 if (position->valid) { | 
| 543 else | 512 m_lastPosition = createGeoposition(*position); | 
| 544 notifier->setFatalError(PositionError::create(PositionError::POS ITION_UNAVAILABLE, failedToStartServiceErrorMessage)); | 513 positionChanged(); | 
| 545 } else { | 514 } else { | 
| 546 notifier->setFatalError(PositionError::create(PositionError::PERMISS ION_DENIED, permissionDeniedErrorMessage)); | 515 handleError(createPositionError(position->error_code, position->error_me ssage)); | 
| 547 } | |
| 548 } | 516 } | 
| 517 if (!m_disconnectedGeolocationService) | |
| 518 queryNextPosition(); | |
| 519 } | |
| 520 | |
| 521 void Geolocation::pageVisibilityChanged() | |
| 522 { | |
| 523 updateGeolocationServiceConnection(); | |
| 524 } | |
| 525 | |
| 526 void Geolocation::onGeolocationConnectionError() | |
| 527 { | |
| 528 PositionError* error = PositionError::create(PositionError::POSITION_UNAVAIL ABLE, failedToStartServiceErrorMessage); | |
| 529 error->setIsFatal(true); | |
| 530 handleError(error); | |
| 531 } | |
| 532 | |
| 533 void Geolocation::onPermissionConnectionError() | |
| 534 { | |
| 535 onGeolocationPermissionUpdated(mojom::blink::PermissionStatus::DENIED); | |
| 549 } | 536 } | 
| 550 | 537 | 
| 551 } // namespace blink | 538 } // namespace blink | 
| OLD | NEW |