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. |
11 * 2. Redistributions in binary form must reproduce the above copyright | 11 * 2. Redistributions in binary form must reproduce the above copyright |
12 * notice, this list of conditions and the following disclaimer in the | 12 * notice, this list of conditions and the following disclaimer in the |
13 * documentation and/or other materials provided with the distribution. | 13 * documentation and/or other materials provided with the distribution. |
14 * | 14 * |
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
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 "config.h" | 28 #include "config.h" |
29 #include "modules/geolocation/Geolocation.h" | 29 #include "modules/geolocation/Geolocation.h" |
30 | 30 |
31 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
32 #include "core/page/Frame.h" | 32 #include "core/page/Frame.h" |
33 #include "core/page/Page.h" | 33 #include "core/page/Page.h" |
34 #include "modules/geolocation/Geoposition.h" | 34 #include "modules/geolocation/Geoposition.h" |
35 #include "wtf/CurrentTime.h" | 35 #include "wtf/CurrentTime.h" |
36 | 36 |
37 #include "modules/geolocation/Coordinates.h" | 37 #include "modules/geolocation/Coordinates.h" |
38 #include "modules/geolocation/GeolocationController.h" | 38 #include "modules/geolocation/GeolocationController.h" |
39 #include "modules/geolocation/GeolocationError.h" | 39 #include "modules/geolocation/GeolocationError.h" |
40 #include "modules/geolocation/GeolocationPosition.h" | 40 #include "modules/geolocation/GeolocationPosition.h" |
41 #include "modules/geolocation/PositionError.h" | 41 #include "modules/geolocation/PositionError.h" |
42 | 42 |
43 namespace WebCore { | 43 namespace WebCore { |
44 | 44 |
45 static const char permissionDeniedErrorMessage[] = "User denied Geolocation"; | 45 static const char permissionDeniedErrorMessage[] = "User denied Geolocation"; |
46 static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocat
ion service"; | 46 static const char failedToStartServiceErrorMessage[] = "Failed to start Geolocat
ion service"; |
47 static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used
in frameless documents"; | 47 static const char framelessDocumentErrorMessage[] = "Geolocation cannot be used
in frameless documents"; |
48 | 48 |
49 static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position) | 49 static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position) |
50 { | 50 { |
51 if (!position) | 51 if (!position) |
52 return 0; | 52 return 0; |
53 | 53 |
54 RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(),
position->longitude(), position->canProvideAltitude(), position->altitude(), | 54 RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(),
position->longitude(), position->canProvideAltitude(), position->altitude(), |
55 position->accuracy(),
position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(), | 55 position->accuracy(),
position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(), |
56 position->canProvideHe
ading(), position->heading(), position->canProvideSpeed(), position->speed()); | 56 position->canProvideHe
ading(), position->heading(), position->canProvideSpeed(), position->speed()); |
57 return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeSta
mp(position->timestamp())); | 57 return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeSta
mp(position->timestamp())); |
58 } | 58 } |
59 | 59 |
60 static PassRefPtr<PositionError> createPositionError(GeolocationError* error) | 60 static PassRefPtr<PositionError> createPositionError(GeolocationError* error) |
61 { | 61 { |
62 PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE; | 62 PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE; |
63 switch (error->code()) { | 63 switch (error->code()) { |
64 case GeolocationError::PermissionDenied: | 64 case GeolocationError::PermissionDenied: |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 417 } |
418 | 418 |
419 void Geolocation::clearWatch(int watchID) | 419 void Geolocation::clearWatch(int watchID) |
420 { | 420 { |
421 if (watchID <= 0) | 421 if (watchID <= 0) |
422 return; | 422 return; |
423 | 423 |
424 if (GeoNotifier* notifier = m_watchers.find(watchID)) | 424 if (GeoNotifier* notifier = m_watchers.find(watchID)) |
425 m_pendingForPermissionNotifiers.remove(notifier); | 425 m_pendingForPermissionNotifiers.remove(notifier); |
426 m_watchers.remove(watchID); | 426 m_watchers.remove(watchID); |
427 | 427 |
428 if (!hasListeners()) | 428 if (!hasListeners()) |
429 stopUpdating(); | 429 stopUpdating(); |
430 } | 430 } |
431 | 431 |
432 void Geolocation::setIsAllowed(bool allowed) | 432 void Geolocation::setIsAllowed(bool allowed) |
433 { | 433 { |
434 // Protect the Geolocation object from garbage collection during a callback. | 434 // Protect the Geolocation object from garbage collection during a callback. |
435 RefPtr<Geolocation> protect(this); | 435 RefPtr<Geolocation> protect(this); |
436 | 436 |
437 // This may be due to either a new position from the service, or a cached | 437 // This may be due to either a new position from the service, or a cached |
438 // position. | 438 // position. |
439 m_allowGeolocation = allowed ? Yes : No; | 439 m_allowGeolocation = allowed ? Yes : No; |
440 | 440 |
441 // Permission request was made during the startRequest process | 441 // Permission request was made during the startRequest process |
442 if (!m_pendingForPermissionNotifiers.isEmpty()) { | 442 if (!m_pendingForPermissionNotifiers.isEmpty()) { |
443 handlePendingPermissionNotifiers(); | 443 handlePendingPermissionNotifiers(); |
444 m_pendingForPermissionNotifiers.clear(); | 444 m_pendingForPermissionNotifiers.clear(); |
445 return; | 445 return; |
446 } | 446 } |
447 | 447 |
448 if (!isAllowed()) { | 448 if (!isAllowed()) { |
449 RefPtr<PositionError> error = PositionError::create(PositionError::PERMI
SSION_DENIED, ASCIILiteral(permissionDeniedErrorMessage)); | 449 RefPtr<PositionError> error = PositionError::create(PositionError::PERMI
SSION_DENIED, ASCIILiteral(permissionDeniedErrorMessage)); |
450 error->setIsFatal(true); | 450 error->setIsFatal(true); |
451 handleError(error.get()); | 451 handleError(error.get()); |
452 m_requestsAwaitingCachedPosition.clear(); | 452 m_requestsAwaitingCachedPosition.clear(); |
453 return; | 453 return; |
454 } | 454 } |
455 | 455 |
456 // If the service has a last position, use it to call back for all requests. | 456 // If the service has a last position, use it to call back for all requests. |
457 // If any of the requests are waiting for permission for a cached position, | 457 // If any of the requests are waiting for permission for a cached position, |
458 // the position from the service will be at least as fresh. | 458 // the position from the service will be at least as fresh. |
459 if (lastPosition()) | 459 if (lastPosition()) |
460 makeSuccessCallbacks(); | 460 makeSuccessCallbacks(); |
461 else | 461 else |
462 makeCachedPositionCallbacks(); | 462 makeCachedPositionCallbacks(); |
463 } | 463 } |
464 | 464 |
465 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) | 465 void Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error) |
466 { | 466 { |
467 GeoNotifierVector::const_iterator end = notifiers.end(); | 467 GeoNotifierVector::const_iterator end = notifiers.end(); |
468 for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; +
+it) { | 468 for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; +
+it) { |
469 RefPtr<GeoNotifier> notifier = *it; | 469 RefPtr<GeoNotifier> notifier = *it; |
470 | 470 |
471 notifier->runErrorCallback(error); | 471 notifier->runErrorCallback(error); |
472 } | 472 } |
473 } | 473 } |
474 | 474 |
475 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi
on) | 475 void Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* positi
on) |
476 { | 476 { |
477 GeoNotifierVector::const_iterator end = notifiers.end(); | 477 GeoNotifierVector::const_iterator end = notifiers.end(); |
478 for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++
it) | 478 for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++
it) |
479 (*it)->runSuccessCallback(position); | 479 (*it)->runSuccessCallback(position); |
480 } | 480 } |
481 | 481 |
482 void Geolocation::stopTimer(GeoNotifierVector& notifiers) | 482 void Geolocation::stopTimer(GeoNotifierVector& notifiers) |
483 { | 483 { |
484 GeoNotifierVector::const_iterator end = notifiers.end(); | 484 GeoNotifierVector::const_iterator end = notifiers.end(); |
485 for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++
it) | 485 for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++
it) |
486 (*it)->stopTimer(); | 486 (*it)->stopTimer(); |
487 } | 487 } |
488 | 488 |
489 void Geolocation::stopTimersForOneShots() | 489 void Geolocation::stopTimersForOneShots() |
490 { | 490 { |
491 GeoNotifierVector copy; | 491 GeoNotifierVector copy; |
492 copyToVector(m_oneShots, copy); | 492 copyToVector(m_oneShots, copy); |
493 | 493 |
494 stopTimer(copy); | 494 stopTimer(copy); |
495 } | 495 } |
496 | 496 |
497 void Geolocation::stopTimersForWatchers() | 497 void Geolocation::stopTimersForWatchers() |
498 { | 498 { |
499 GeoNotifierVector copy; | 499 GeoNotifierVector copy; |
500 m_watchers.getNotifiersVector(copy); | 500 m_watchers.getNotifiersVector(copy); |
501 | 501 |
502 stopTimer(copy); | 502 stopTimer(copy); |
503 } | 503 } |
504 | 504 |
505 void Geolocation::stopTimers() | 505 void Geolocation::stopTimers() |
506 { | 506 { |
507 stopTimersForOneShots(); | 507 stopTimersForOneShots(); |
508 stopTimersForWatchers(); | 508 stopTimersForWatchers(); |
509 } | 509 } |
510 | 510 |
511 void Geolocation::cancelRequests(GeoNotifierVector& notifiers) | 511 void Geolocation::cancelRequests(GeoNotifierVector& notifiers) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
544 GeoNotifierVector::const_iterator end = src.end(); | 544 GeoNotifierVector::const_iterator end = src.end(); |
545 for (GeoNotifierVector::const_iterator it = src.begin(); it != end; ++it) { | 545 for (GeoNotifierVector::const_iterator it = src.begin(); it != end; ++it) { |
546 GeoNotifier* notifier = it->get(); | 546 GeoNotifier* notifier = it->get(); |
547 dest.add(notifier); | 547 dest.add(notifier); |
548 } | 548 } |
549 } | 549 } |
550 | 550 |
551 void Geolocation::handleError(PositionError* error) | 551 void Geolocation::handleError(PositionError* error) |
552 { | 552 { |
553 ASSERT(error); | 553 ASSERT(error); |
554 | 554 |
555 GeoNotifierVector oneShotsCopy; | 555 GeoNotifierVector oneShotsCopy; |
556 copyToVector(m_oneShots, oneShotsCopy); | 556 copyToVector(m_oneShots, oneShotsCopy); |
557 | 557 |
558 GeoNotifierVector watchersCopy; | 558 GeoNotifierVector watchersCopy; |
559 m_watchers.getNotifiersVector(watchersCopy); | 559 m_watchers.getNotifiersVector(watchersCopy); |
560 | 560 |
561 // Clear the lists before we make the callbacks, to avoid clearing notifiers | 561 // Clear the lists before we make the callbacks, to avoid clearing notifiers |
562 // added by calls to Geolocation methods from the callbacks, and to prevent | 562 // added by calls to Geolocation methods from the callbacks, and to prevent |
563 // further callbacks to these notifiers. | 563 // further callbacks to these notifiers. |
564 GeoNotifierVector oneShotsWithCachedPosition; | 564 GeoNotifierVector oneShotsWithCachedPosition; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 m_allowGeolocation = InProgress; | 596 m_allowGeolocation = InProgress; |
597 | 597 |
598 // Ask the embedder: it maintains the geolocation challenge policy itself. | 598 // Ask the embedder: it maintains the geolocation challenge policy itself. |
599 GeolocationController::from(page)->requestPermission(this); | 599 GeolocationController::from(page)->requestPermission(this); |
600 } | 600 } |
601 | 601 |
602 void Geolocation::makeSuccessCallbacks() | 602 void Geolocation::makeSuccessCallbacks() |
603 { | 603 { |
604 ASSERT(lastPosition()); | 604 ASSERT(lastPosition()); |
605 ASSERT(isAllowed()); | 605 ASSERT(isAllowed()); |
606 | 606 |
607 GeoNotifierVector oneShotsCopy; | 607 GeoNotifierVector oneShotsCopy; |
608 copyToVector(m_oneShots, oneShotsCopy); | 608 copyToVector(m_oneShots, oneShotsCopy); |
609 | 609 |
610 GeoNotifierVector watchersCopy; | 610 GeoNotifierVector watchersCopy; |
611 m_watchers.getNotifiersVector(watchersCopy); | 611 m_watchers.getNotifiersVector(watchersCopy); |
612 | 612 |
613 // Clear the lists before we make the callbacks, to avoid clearing notifiers | 613 // Clear the lists before we make the callbacks, to avoid clearing notifiers |
614 // added by calls to Geolocation methods from the callbacks, and to prevent | 614 // added by calls to Geolocation methods from the callbacks, and to prevent |
615 // further callbacks to these notifiers. | 615 // further callbacks to these notifiers. |
616 m_oneShots.clear(); | 616 m_oneShots.clear(); |
617 | 617 |
618 sendPosition(oneShotsCopy, lastPosition()); | 618 sendPosition(oneShotsCopy, lastPosition()); |
619 sendPosition(watchersCopy, lastPosition()); | 619 sendPosition(watchersCopy, lastPosition()); |
620 | 620 |
621 if (!hasListeners()) | 621 if (!hasListeners()) |
622 stopUpdating(); | 622 stopUpdating(); |
(...skipping 29 matching lines...) Expand all Loading... |
652 { | 652 { |
653 Page* page = this->page(); | 653 Page* page = this->page(); |
654 if (!page) | 654 if (!page) |
655 return; | 655 return; |
656 | 656 |
657 GeolocationController::from(page)->removeObserver(this); | 657 GeolocationController::from(page)->removeObserver(this); |
658 } | 658 } |
659 | 659 |
660 void Geolocation::handlePendingPermissionNotifiers() | 660 void Geolocation::handlePendingPermissionNotifiers() |
661 { | 661 { |
662 // While we iterate through the list, we need not worry about list being mod
ified as the permission | 662 // While we iterate through the list, we need not worry about list being mod
ified as the permission |
663 // is already set to Yes/No and no new listeners will be added to the pendin
g list | 663 // is already set to Yes/No and no new listeners will be added to the pendin
g list |
664 GeoNotifierSet::const_iterator end = m_pendingForPermissionNotifiers.end(); | 664 GeoNotifierSet::const_iterator end = m_pendingForPermissionNotifiers.end(); |
665 for (GeoNotifierSet::const_iterator iter = m_pendingForPermissionNotifiers.b
egin(); iter != end; ++iter) { | 665 for (GeoNotifierSet::const_iterator iter = m_pendingForPermissionNotifiers.b
egin(); iter != end; ++iter) { |
666 GeoNotifier* notifier = iter->get(); | 666 GeoNotifier* notifier = iter->get(); |
667 | 667 |
668 if (isAllowed()) { | 668 if (isAllowed()) { |
669 // start all pending notification requests as permission granted. | 669 // start all pending notification requests as permission granted. |
670 // The notifier is always ref'ed by m_oneShots or m_watchers. | 670 // The notifier is always ref'ed by m_oneShots or m_watchers. |
671 if (startUpdating(notifier)) | 671 if (startUpdating(notifier)) |
672 notifier->startTimerIfNeeded(); | 672 notifier->startTimerIfNeeded(); |
673 else | 673 else |
674 notifier->setFatalError(PositionError::create(PositionError::POS
ITION_UNAVAILABLE, ASCIILiteral(failedToStartServiceErrorMessage))); | 674 notifier->setFatalError(PositionError::create(PositionError::POS
ITION_UNAVAILABLE, ASCIILiteral(failedToStartServiceErrorMessage))); |
675 } else | 675 } else |
676 notifier->setFatalError(PositionError::create(PositionError::PERMISS
ION_DENIED, ASCIILiteral(permissionDeniedErrorMessage))); | 676 notifier->setFatalError(PositionError::create(PositionError::PERMISS
ION_DENIED, ASCIILiteral(permissionDeniedErrorMessage))); |
677 } | 677 } |
678 } | 678 } |
679 | 679 |
680 } // namespace WebCore | 680 } // namespace WebCore |
OLD | NEW |