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; |
76 break; | 73 break; |
74 default: | |
Michael van Ouwerkerk
2016/05/04 13:52:16
Doesn't clang fail the build when a switch fails t
Sam McNally
2016/05/05 11:50:24
Done.
| |
75 ASSERT_NOT_REACHED(); | |
77 } | 76 } |
77 return PositionError::create(errorCode, error); | |
78 } | |
78 | 79 |
79 return PositionError::create(code, error->message()); | 80 } // namespace |
80 } | |
81 | 81 |
82 Geolocation* Geolocation::create(ExecutionContext* context) | 82 Geolocation* Geolocation::create(ExecutionContext* context) |
83 { | 83 { |
84 Geolocation* geolocation = new Geolocation(context); | 84 Geolocation* geolocation = new Geolocation(context); |
85 geolocation->suspendIfNeeded(); | 85 geolocation->suspendIfNeeded(); |
86 return geolocation; | 86 return geolocation; |
87 } | 87 } |
88 | 88 |
89 Geolocation::Geolocation(ExecutionContext* context) | 89 Geolocation::Geolocation(ExecutionContext* context) |
90 : ActiveDOMObject(context) | 90 : ActiveDOMObject(context) |
91 , PageLifecycleObserver(document()->page()) | |
91 , m_geolocationPermission(PermissionUnknown) | 92 , m_geolocationPermission(PermissionUnknown) |
92 { | 93 { |
93 } | 94 } |
94 | 95 |
95 Geolocation::~Geolocation() | 96 Geolocation::~Geolocation() |
96 { | 97 { |
97 ASSERT(m_geolocationPermission != PermissionRequested); | 98 ASSERT(m_geolocationPermission != PermissionRequested); |
98 } | 99 } |
99 | 100 |
100 DEFINE_TRACE(Geolocation) | 101 DEFINE_TRACE(Geolocation) |
101 { | 102 { |
102 visitor->trace(m_oneShots); | 103 visitor->trace(m_oneShots); |
103 visitor->trace(m_watchers); | 104 visitor->trace(m_watchers); |
104 visitor->trace(m_pendingForPermissionNotifiers); | 105 visitor->trace(m_pendingForPermissionNotifiers); |
105 visitor->trace(m_lastPosition); | 106 visitor->trace(m_lastPosition); |
106 visitor->trace(m_requestsAwaitingCachedPosition); | |
107 ActiveDOMObject::trace(visitor); | 107 ActiveDOMObject::trace(visitor); |
108 PageLifecycleObserver::trace(visitor); | |
108 } | 109 } |
109 | 110 |
110 Document* Geolocation::document() const | 111 Document* Geolocation::document() const |
111 { | 112 { |
112 return toDocument(getExecutionContext()); | 113 return toDocument(getExecutionContext()); |
113 } | 114 } |
114 | 115 |
115 LocalFrame* Geolocation::frame() const | 116 LocalFrame* Geolocation::frame() const |
116 { | 117 { |
117 return document() ? document()->frame() : 0; | 118 return document() ? document()->frame() : 0; |
118 } | 119 } |
119 | 120 |
120 void Geolocation::stop() | 121 void Geolocation::stop() |
121 { | 122 { |
122 LocalFrame* frame = this->frame(); | 123 if (m_permissionService) |
Michael van Ouwerkerk
2016/05/04 13:52:16
Why not also stop m_geolocationService?
Sam McNally
2016/05/05 11:50:24
stopUpdating() stops it.
| |
123 if (frame && m_geolocationPermission == PermissionRequested) | 124 m_permissionService.reset(); |
124 GeolocationController::from(frame)->cancelPermissionRequest(this); | |
125 | 125 |
126 // The frame may be moving to a new page and we want to get the permissions from the new page's client. | 126 // The frame may be moving to a new page and we want to get the permissions from the new page's client. |
Michael van Ouwerkerk
2016/05/04 13:52:16
Please update this comment, there is no client any
Sam McNally
2016/05/05 11:50:24
Done.
| |
127 m_geolocationPermission = PermissionUnknown; | 127 m_geolocationPermission = PermissionUnknown; |
128 cancelAllRequests(); | 128 cancelAllRequests(); |
129 stopUpdating(); | 129 stopUpdating(); |
130 m_pendingForPermissionNotifiers.clear(); | 130 m_pendingForPermissionNotifiers.clear(); |
131 m_lastPosition = nullptr; | |
131 } | 132 } |
132 | 133 |
133 Geoposition* Geolocation::lastPosition() | 134 Geoposition* Geolocation::lastPosition() |
Michael van Ouwerkerk
2016/05/04 13:52:16
This can be in the header now, or removed entirely
Sam McNally
2016/05/05 11:50:24
Done.
| |
134 { | 135 { |
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; | 136 return m_lastPosition; |
142 } | 137 } |
143 | 138 |
144 void Geolocation::recordOriginTypeAccess() const | 139 void Geolocation::recordOriginTypeAccess() const |
145 { | 140 { |
146 ASSERT(frame()); | 141 ASSERT(frame()); |
147 | 142 |
148 Document* document = this->document(); | 143 Document* document = this->document(); |
149 ASSERT(document); | 144 ASSERT(document); |
150 | 145 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 String errorMessage; | 190 String errorMessage; |
196 if (!frame()->settings()->allowGeolocationOnInsecureOrigins() && !getExecuti onContext()->isSecureContext(errorMessage)) { | 191 if (!frame()->settings()->allowGeolocationOnInsecureOrigins() && !getExecuti onContext()->isSecureContext(errorMessage)) { |
197 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, errorMessage)); | 192 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, errorMessage)); |
198 return; | 193 return; |
199 } | 194 } |
200 | 195 |
201 // Check whether permissions have already been denied. Note that if this is the case, | 196 // Check whether permissions have already been denied. Note that if this is the case, |
202 // the permission state can not change again in the lifetime of this page. | 197 // the permission state can not change again in the lifetime of this page. |
203 if (isDenied()) | 198 if (isDenied()) |
204 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 199 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); |
205 else if (haveSuitableCachedPosition(notifier->options())) | 200 else if (isAllowed() && haveSuitableCachedPosition(notifier->options())) |
Michael van Ouwerkerk
2016/05/04 13:52:16
Why add the isAllowed call? Is it for readability?
Sam McNally
2016/05/05 11:50:24
It was for readability. Removed it and added a DCH
| |
206 notifier->setUseCachedPosition(); | 201 notifier->setUseCachedPosition(); |
207 else if (!notifier->options().timeout()) | 202 else if (!notifier->options().timeout()) |
208 notifier->startTimer(); | 203 notifier->startTimer(); |
209 else if (!isAllowed()) { | 204 else if (!isAllowed()) { |
210 // if we don't yet have permission, request for permission before callin g startUpdating() | 205 // if we don't yet have permission, request for permission before callin g startUpdating() |
211 m_pendingForPermissionNotifiers.add(notifier); | 206 m_pendingForPermissionNotifiers.add(notifier); |
212 requestPermission(); | 207 requestPermission(); |
213 } else if (startUpdating(notifier)) | 208 } else { |
209 startUpdating(notifier); | |
214 notifier->startTimer(); | 210 notifier->startTimer(); |
215 else | 211 } |
216 notifier->setFatalError(PositionError::create(PositionError::POSITION_UN AVAILABLE, failedToStartServiceErrorMessage)); | |
217 } | 212 } |
218 | 213 |
219 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) | 214 void Geolocation::fatalErrorOccurred(GeoNotifier* notifier) |
220 { | 215 { |
221 // This request has failed fatally. Remove it from our lists. | 216 // This request has failed fatally. Remove it from our lists. |
222 m_oneShots.remove(notifier); | 217 m_oneShots.remove(notifier); |
223 m_watchers.remove(notifier); | 218 m_watchers.remove(notifier); |
224 | 219 |
225 if (!hasListeners()) | 220 if (!hasListeners()) |
226 stopUpdating(); | 221 stopUpdating(); |
227 } | 222 } |
228 | 223 |
229 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) | 224 void Geolocation::requestUsesCachedPosition(GeoNotifier* notifier) |
230 { | 225 { |
231 // This is called asynchronously, so the permissions could have been denied | 226 DCHECK(isAllowed()); |
Michael van Ouwerkerk
2016/05/04 13:52:16
This DCHECK is not equivalent to the isDenied() br
Sam McNally
2016/05/05 11:50:23
This should never be reached unless permission has
| |
232 // since we last checked in startRequest. | 227 |
233 if (isDenied()) { | 228 notifier->runSuccessCallback(lastPosition()); |
234 notifier->setFatalError(PositionError::create(PositionError::PERMISSION_ DENIED, permissionDeniedErrorMessage)); | 229 |
235 return; | 230 // If this is a one-shot request, stop it. Otherwise, if the watch still |
231 // exists, start the service to get updates. | |
232 if (m_oneShots.contains(notifier)) { | |
233 m_oneShots.remove(notifier); | |
234 } else if (m_watchers.contains(notifier)) { | |
235 if (notifier->options().timeout()) | |
236 startUpdating(notifier); | |
237 notifier->startTimer(); | |
236 } | 238 } |
237 | 239 |
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()) | 240 if (!hasListeners()) |
273 stopUpdating(); | 241 stopUpdating(); |
274 } | 242 } |
275 | 243 |
276 void Geolocation::requestTimedOut(GeoNotifier* notifier) | 244 void Geolocation::requestTimedOut(GeoNotifier* notifier) |
277 { | 245 { |
278 // If this is a one-shot request, stop it. | 246 // If this is a one-shot request, stop it. |
279 m_oneShots.remove(notifier); | 247 m_oneShots.remove(notifier); |
280 | 248 |
281 if (!hasListeners()) | 249 if (!hasListeners()) |
(...skipping 17 matching lines...) Expand all Loading... | |
299 return; | 267 return; |
300 | 268 |
301 if (GeoNotifier* notifier = m_watchers.find(watchID)) | 269 if (GeoNotifier* notifier = m_watchers.find(watchID)) |
302 m_pendingForPermissionNotifiers.remove(notifier); | 270 m_pendingForPermissionNotifiers.remove(notifier); |
303 m_watchers.remove(watchID); | 271 m_watchers.remove(watchID); |
304 | 272 |
305 if (!hasListeners()) | 273 if (!hasListeners()) |
306 stopUpdating(); | 274 stopUpdating(); |
307 } | 275 } |
308 | 276 |
309 void Geolocation::setIsAllowed(bool allowed) | 277 void Geolocation::onGeolocationPermissionUpdated(mojom::blink::PermissionStatus status) |
310 { | 278 { |
311 // This may be due to either a new position from the service, or a cached po sition. | 279 // This may be due to either a new position from the service, or a cached po sition. |
312 m_geolocationPermission = allowed ? PermissionAllowed : PermissionDenied; | 280 m_geolocationPermission = status == mojom::blink::PermissionStatus::GRANTED ? PermissionAllowed : PermissionDenied; |
281 m_permissionService.reset(); | |
313 | 282 |
314 // Permission request was made during the startRequest process | 283 // While we iterate through the list, we need not worry about list being mod ified as the permission |
Michael van Ouwerkerk
2016/05/04 13:52:16
s/list/the list/
Sam McNally
2016/05/05 11:50:24
Done.
| |
315 if (!m_pendingForPermissionNotifiers.isEmpty()) { | 284 // is already set to Yes/No and no new listeners will be added to the pendin g list. |
316 handlePendingPermissionNotifiers(); | 285 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { |
317 m_pendingForPermissionNotifiers.clear(); | 286 if (isAllowed()) { |
318 return; | 287 // start all pending notification requests as permission granted. |
Michael van Ouwerkerk
2016/05/04 13:52:16
nit: s/start/Start/
Sam McNally
2016/05/05 11:50:24
Done.
| |
288 // The notifier is always ref'ed by m_oneShots or m_watchers. | |
289 startUpdating(notifier); | |
290 notifier->startTimer(); | |
291 } else { | |
292 notifier->setFatalError(PositionError::create(PositionError::PERMISS ION_DENIED, permissionDeniedErrorMessage)); | |
293 } | |
319 } | 294 } |
320 | 295 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 } | 296 } |
337 | 297 |
338 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) | 298 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) |
339 { | 299 { |
340 for (GeoNotifier* notifier : notifiers) | 300 for (GeoNotifier* notifier : notifiers) |
341 notifier->runErrorCallback(error); | 301 notifier->runErrorCallback(error); |
342 } | 302 } |
343 | 303 |
344 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi on) | 304 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi on) |
345 { | 305 { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 void Geolocation::requestPermission() | 408 void Geolocation::requestPermission() |
449 { | 409 { |
450 if (m_geolocationPermission != PermissionUnknown) | 410 if (m_geolocationPermission != PermissionUnknown) |
451 return; | 411 return; |
452 | 412 |
453 LocalFrame* frame = this->frame(); | 413 LocalFrame* frame = this->frame(); |
454 if (!frame) | 414 if (!frame) |
455 return; | 415 return; |
456 | 416 |
457 m_geolocationPermission = PermissionRequested; | 417 m_geolocationPermission = PermissionRequested; |
418 frame->serviceRegistry()->connectToRemoteService( | |
419 mojo::GetProxy(&m_permissionService)); | |
420 m_permissionService.set_connection_error_handler(sameThreadBindForMojo(&Geol ocation::onPermissionConnectionError, this)); | |
Michael van Ouwerkerk
2016/05/04 13:52:16
Under what circumstances does this get called?
Sam McNally
2016/05/05 11:50:23
Normally, this would only happen if the browser do
| |
458 | 421 |
459 // Ask the embedder: it maintains the geolocation challenge policy itself. | 422 // Ask the embedder: it maintains the geolocation challenge policy itself. |
460 GeolocationController::from(frame)->requestPermission(this); | 423 m_permissionService->RequestPermission( |
424 mojom::blink::PermissionName::GEOLOCATION, | |
425 getExecutionContext()->getSecurityOrigin()->toString(), | |
426 sameThreadBindForMojo(&Geolocation::onGeolocationPermissionUpdated, this )); | |
461 } | 427 } |
462 | 428 |
463 void Geolocation::makeSuccessCallbacks() | 429 void Geolocation::makeSuccessCallbacks() |
464 { | 430 { |
465 ASSERT(lastPosition()); | 431 ASSERT(lastPosition()); |
466 ASSERT(isAllowed()); | 432 ASSERT(isAllowed()); |
467 | 433 |
468 GeoNotifierVector oneShotsCopy; | 434 GeoNotifierVector oneShotsCopy; |
469 copyToVector(m_oneShots, oneShotsCopy); | 435 copyToVector(m_oneShots, oneShotsCopy); |
470 | 436 |
471 GeoNotifierVector watchersCopy; | 437 GeoNotifierVector watchersCopy; |
472 m_watchers.getNotifiersVector(watchersCopy); | 438 m_watchers.getNotifiersVector(watchersCopy); |
473 | 439 |
474 // Clear the lists before we make the callbacks, to avoid clearing notifiers | 440 // 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 | 441 // added by calls to Geolocation methods from the callbacks, and to prevent |
476 // further callbacks to these notifiers. | 442 // further callbacks to these notifiers. |
477 m_oneShots.clear(); | 443 m_oneShots.clear(); |
478 | 444 |
479 // Also clear the set of notifiers waiting for a cached position. All the | |
480 // oneshots and watchers will receive a position now, and if they happen to | |
481 // be lingering in that set, avoid this bug: http://crbug.com/311876 . | |
482 m_requestsAwaitingCachedPosition.clear(); | |
483 | |
484 sendPosition(oneShotsCopy, lastPosition()); | 445 sendPosition(oneShotsCopy, lastPosition()); |
485 sendPosition(watchersCopy, lastPosition()); | 446 sendPosition(watchersCopy, lastPosition()); |
486 | 447 |
487 if (!hasListeners()) | 448 if (!hasListeners()) |
488 stopUpdating(); | 449 stopUpdating(); |
489 } | 450 } |
490 | 451 |
491 void Geolocation::positionChanged() | 452 void Geolocation::positionChanged() |
492 { | 453 { |
493 ASSERT(isAllowed()); | 454 ASSERT(isAllowed()); |
494 | 455 |
495 // Stop all currently running timers. | 456 // Stop all currently running timers. |
496 stopTimers(); | 457 stopTimers(); |
497 | 458 |
498 makeSuccessCallbacks(); | 459 makeSuccessCallbacks(); |
499 } | 460 } |
500 | 461 |
501 void Geolocation::setError(GeolocationError* error) | 462 void Geolocation::startUpdating(GeoNotifier* notifier) |
502 { | 463 { |
503 handleError(createPositionError(error)); | 464 // This may be called multiple times, though stopUpdating() is called only |
504 } | 465 // once. |
505 | 466 m_updating = true; |
506 bool Geolocation::startUpdating(GeoNotifier* notifier) | 467 if (notifier->options().enableHighAccuracy() && !m_enableHighAccuracy) { |
507 { | 468 m_enableHighAccuracy = true; |
508 LocalFrame* frame = this->frame(); | 469 if (m_geolocationService) |
509 if (!frame) | 470 m_geolocationService->SetHighAccuracy(true); |
510 return false; | 471 } |
511 | 472 updateGeolocationServiceConnection(); |
512 GeolocationController::from(frame)->addObserver(this, notifier->options().en ableHighAccuracy()); | |
513 return true; | |
514 } | 473 } |
515 | 474 |
516 void Geolocation::stopUpdating() | 475 void Geolocation::stopUpdating() |
517 { | 476 { |
518 LocalFrame* frame = this->frame(); | 477 m_updating = false; |
519 if (!frame) | 478 updateGeolocationServiceConnection(); |
479 m_enableHighAccuracy = false; | |
480 } | |
481 | |
482 void Geolocation::updateGeolocationServiceConnection() | |
483 { | |
484 if (!page() || page()->visibilityState() != PageVisibilityStateVisible || !m _updating) { | |
Michael van Ouwerkerk
2016/05/04 13:52:16
nit: use page()->isPageVisible()
Sam McNally
2016/05/05 11:50:24
Done.
| |
485 m_geolocationService.reset(); | |
486 m_queryInProgress = false; | |
487 return; | |
488 } | |
489 if (m_geolocationService) | |
520 return; | 490 return; |
521 | 491 |
522 GeolocationController::from(frame)->removeObserver(this); | 492 frame()->serviceRegistry()->connectToRemoteService(mojo::GetProxy(&m_geoloca tionService)); |
493 m_geolocationService.set_connection_error_handler(sameThreadBindForMojo(&Geo location::onGeolocationConnectionError, this)); | |
494 if (m_enableHighAccuracy) | |
495 m_geolocationService->SetHighAccuracy(true); | |
496 queryNextPosition(); | |
523 } | 497 } |
524 | 498 |
525 void Geolocation::handlePendingPermissionNotifiers() | 499 void Geolocation::queryNextPosition() |
526 { | 500 { |
527 // While we iterate through the list, we need not worry about list being mod ified as the permission | 501 if (m_queryInProgress) |
528 // is already set to Yes/No and no new listeners will be added to the pendin g list. | 502 return; |
529 for (GeoNotifier* notifier : m_pendingForPermissionNotifiers) { | 503 |
530 if (isAllowed()) { | 504 m_queryInProgress = true; |
531 // start all pending notification requests as permission granted. | 505 m_geolocationService->QueryNextPosition( |
532 // The notifier is always ref'ed by m_oneShots or m_watchers. | 506 sameThreadBindForMojo(&Geolocation::onPositionUpdated, this)); |
533 if (startUpdating(notifier)) | 507 } |
534 notifier->startTimer(); | 508 |
535 else | 509 void Geolocation::onPositionUpdated(mojom::blink::GeopositionPtr position) |
536 notifier->setFatalError(PositionError::create(PositionError::POS ITION_UNAVAILABLE, failedToStartServiceErrorMessage)); | 510 { |
537 } else { | 511 m_queryInProgress = false; |
538 notifier->setFatalError(PositionError::create(PositionError::PERMISS ION_DENIED, permissionDeniedErrorMessage)); | 512 if (position->valid) { |
539 } | 513 m_lastPosition = createGeoposition(*position); |
514 positionChanged(); | |
515 } else { | |
516 handleError(createPositionError(position->error_code, position->error_me ssage)); | |
540 } | 517 } |
518 if (m_geolocationService) | |
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); | |
541 } | 537 } |
542 | 538 |
543 } // namespace blink | 539 } // namespace blink |
OLD | NEW |