Home | History | Annotate | Download | only in geolocation
      1 /*
      2  * Copyright (C) 2009 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
     14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
     17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     23  * THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "modules/geolocation/GeolocationController.h"
     28 
     29 #include "core/inspector/InspectorInstrumentation.h"
     30 #include "modules/geolocation/GeolocationClient.h"
     31 #include "modules/geolocation/GeolocationError.h"
     32 #include "modules/geolocation/GeolocationPosition.h"
     33 
     34 namespace WebCore {
     35 
     36 GeolocationController::GeolocationController(Page* page, GeolocationClient* client)
     37     : PageLifecycleObserver(page)
     38     , m_client(client)
     39     , m_isClientUpdating(false)
     40 {
     41 }
     42 
     43 void GeolocationController::startUpdatingIfNeeded()
     44 {
     45     if (m_isClientUpdating)
     46         return;
     47     m_isClientUpdating = true;
     48     m_client->startUpdating();
     49 }
     50 
     51 void GeolocationController::stopUpdatingIfNeeded()
     52 {
     53     if (!m_isClientUpdating)
     54         return;
     55     m_isClientUpdating = false;
     56     m_client->stopUpdating();
     57 }
     58 
     59 GeolocationController::~GeolocationController()
     60 {
     61     ASSERT(m_observers.isEmpty());
     62 
     63     if (m_client)
     64         m_client->geolocationDestroyed();
     65 }
     66 
     67 PassOwnPtr<GeolocationController> GeolocationController::create(Page* page, GeolocationClient* client)
     68 {
     69     return adoptPtr(new GeolocationController(page, client));
     70 }
     71 
     72 void GeolocationController::addObserver(Geolocation* observer, bool enableHighAccuracy)
     73 {
     74     // This may be called multiple times with the same observer, though removeObserver()
     75     // is called only once with each.
     76     bool wasEmpty = m_observers.isEmpty();
     77     m_observers.add(observer);
     78     if (enableHighAccuracy)
     79         m_highAccuracyObservers.add(observer);
     80 
     81     if (m_client) {
     82         if (enableHighAccuracy)
     83             m_client->setEnableHighAccuracy(true);
     84         if (wasEmpty && page() && page()->visibilityState() == PageVisibilityStateVisible)
     85             startUpdatingIfNeeded();
     86     }
     87 }
     88 
     89 void GeolocationController::removeObserver(Geolocation* observer)
     90 {
     91     if (!m_observers.contains(observer))
     92         return;
     93 
     94     m_observers.remove(observer);
     95     m_highAccuracyObservers.remove(observer);
     96 
     97     if (m_client) {
     98         if (m_observers.isEmpty())
     99             stopUpdatingIfNeeded();
    100         else if (m_highAccuracyObservers.isEmpty())
    101             m_client->setEnableHighAccuracy(false);
    102     }
    103 }
    104 
    105 void GeolocationController::requestPermission(Geolocation* geolocation)
    106 {
    107     if (m_client)
    108         m_client->requestPermission(geolocation);
    109 }
    110 
    111 void GeolocationController::cancelPermissionRequest(Geolocation* geolocation)
    112 {
    113     if (m_client)
    114         m_client->cancelPermissionRequest(geolocation);
    115 }
    116 
    117 void GeolocationController::positionChanged(GeolocationPosition* position)
    118 {
    119     position = InspectorInstrumentation::overrideGeolocationPosition(page(), position);
    120     if (!position) {
    121         errorOccurred(GeolocationError::create(GeolocationError::PositionUnavailable, "PositionUnavailable").get());
    122         return;
    123     }
    124     m_lastPosition = position;
    125     Vector<RefPtr<Geolocation> > observersVector;
    126     copyToVector(m_observers, observersVector);
    127     for (size_t i = 0; i < observersVector.size(); ++i)
    128         observersVector[i]->positionChanged();
    129 }
    130 
    131 void GeolocationController::errorOccurred(GeolocationError* error)
    132 {
    133     Vector<RefPtr<Geolocation> > observersVector;
    134     copyToVector(m_observers, observersVector);
    135     for (size_t i = 0; i < observersVector.size(); ++i)
    136         observersVector[i]->setError(error);
    137 }
    138 
    139 GeolocationPosition* GeolocationController::lastPosition()
    140 {
    141     if (m_lastPosition.get())
    142         return m_lastPosition.get();
    143 
    144     if (!m_client)
    145         return 0;
    146 
    147     return m_client->lastPosition();
    148 }
    149 
    150 void GeolocationController::pageVisibilityChanged()
    151 {
    152     if (m_observers.isEmpty() || !m_client)
    153         return;
    154 
    155     if (page() && page()->visibilityState() == PageVisibilityStateVisible)
    156         startUpdatingIfNeeded();
    157     else
    158         stopUpdatingIfNeeded();
    159 }
    160 
    161 const char* GeolocationController::supplementName()
    162 {
    163     return "GeolocationController";
    164 }
    165 
    166 void provideGeolocationTo(Page* page, GeolocationClient* client)
    167 {
    168     Supplement<Page>::provideTo(page, GeolocationController::supplementName(), GeolocationController::create(page, client));
    169 }
    170 
    171 } // namespace WebCore
    172