18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 Torch Mobile, Inc.
48a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block * Copyright 2010, The Android Open Source Project
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Geolocation.h"
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
31dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#if ENABLE(GEOLOCATION)
32dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Chrome.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Page.h"
36363d073b4eb761499b7bf1d6834b00e9551406e4Steve Block#if PLATFORM(ANDROID)
37930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block#include "PlatformBridge.h"
38363d073b4eb761499b7bf1d6834b00e9551406e4Steve Block#endif
399ca5793315e248418a353cc1443f3803ae0adfe6Steve Block#include <wtf/CurrentTime.h>
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
41370b559b082915acb99b185ed8c8e317fc654db6Steve Block#if ENABLE(CLIENT_BASED_GEOLOCATION)
42370b559b082915acb99b185ed8c8e317fc654db6Steve Block#include "Coordinates.h"
43370b559b082915acb99b185ed8c8e317fc654db6Steve Block#include "GeolocationController.h"
44370b559b082915acb99b185ed8c8e317fc654db6Steve Block#include "GeolocationError.h"
45370b559b082915acb99b185ed8c8e317fc654db6Steve Block#include "GeolocationPosition.h"
46370b559b082915acb99b185ed8c8e317fc654db6Steve Block#include "PositionError.h"
47370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
48370b559b082915acb99b185ed8c8e317fc654db6Steve Block
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
51466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Blockstatic const char permissionDeniedErrorMessage[] = "User denied Geolocation";
52159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Blockstatic const char failedToStartServiceErrorMessage[] = "Failed to start Geolocation service";
53f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickstatic const char framelessDocumentErrorMessage[] = "Geolocation cannot be used in frameless documents";
54f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
55f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickstatic const int firstAvailableWatchId = 1;
560c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block
57370b559b082915acb99b185ed8c8e317fc654db6Steve Block#if ENABLE(CLIENT_BASED_GEOLOCATION)
58370b559b082915acb99b185ed8c8e317fc654db6Steve Block
59370b559b082915acb99b185ed8c8e317fc654db6Steve Blockstatic PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position)
60370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
61db217ef7ffee230d812f9da02a02d7d7bc696a8dSteve Block    if (!position)
62db217ef7ffee230d812f9da02a02d7d7bc696a8dSteve Block        return 0;
63db217ef7ffee230d812f9da02a02d7d7bc696a8dSteve Block
64370b559b082915acb99b185ed8c8e317fc654db6Steve Block    RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(),
65370b559b082915acb99b185ed8c8e317fc654db6Steve Block                                                          position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(),
66370b559b082915acb99b185ed8c8e317fc654db6Steve Block                                                          position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed());
676b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    return Geoposition::create(coordinates.release(), convertSecondsToDOMTimeStamp(position->timestamp()));
68370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
69370b559b082915acb99b185ed8c8e317fc654db6Steve Block
70370b559b082915acb99b185ed8c8e317fc654db6Steve Blockstatic PassRefPtr<PositionError> createPositionError(GeolocationError* error)
71370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
72370b559b082915acb99b185ed8c8e317fc654db6Steve Block    PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE;
73370b559b082915acb99b185ed8c8e317fc654db6Steve Block    switch (error->code()) {
74370b559b082915acb99b185ed8c8e317fc654db6Steve Block    case GeolocationError::PermissionDenied:
75370b559b082915acb99b185ed8c8e317fc654db6Steve Block        code = PositionError::PERMISSION_DENIED;
76370b559b082915acb99b185ed8c8e317fc654db6Steve Block        break;
77370b559b082915acb99b185ed8c8e317fc654db6Steve Block    case GeolocationError::PositionUnavailable:
78370b559b082915acb99b185ed8c8e317fc654db6Steve Block        code = PositionError::POSITION_UNAVAILABLE;
79370b559b082915acb99b185ed8c8e317fc654db6Steve Block        break;
80370b559b082915acb99b185ed8c8e317fc654db6Steve Block    }
81370b559b082915acb99b185ed8c8e317fc654db6Steve Block
82370b559b082915acb99b185ed8c8e317fc654db6Steve Block    return PositionError::create(code, error->message());
83370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
84370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
85370b559b082915acb99b185ed8c8e317fc654db6Steve Block
860c97c982f069c9d9eee236d7f8461710d2e1d078Steve BlockGeolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
870c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    : m_geolocation(geolocation)
880c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    , m_successCallback(successCallback)
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_errorCallback(errorCallback)
905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_options(options)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_timer(this, &Geolocation::GeoNotifier::timerFired)
9295b5322fb41833173e2aa950c094b58ee83c1a16Steve Block    , m_useCachedPosition(false)
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
940c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    ASSERT(m_geolocation);
956453d21822fbf87a3fec6a6351a56933d2d9d730Steve Block    ASSERT(m_successCallback);
966453d21822fbf87a3fec6a6351a56933d2d9d730Steve Block    // If no options were supplied from JS, we should have created a default set
976453d21822fbf87a3fec6a6351a56933d2d9d730Steve Block    // of options in JSGeolocationCustom.cpp.
986453d21822fbf87a3fec6a6351a56933d2d9d730Steve Block    ASSERT(m_options);
995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1005f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1010c97c982f069c9d9eee236d7f8461710d2e1d078Steve Blockvoid Geolocation::GeoNotifier::setFatalError(PassRefPtr<PositionError> error)
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
103f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // If a fatal error has already been set, stick with it. This makes sure that
104f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // when permission is denied, this is the error reported, as required by the
105f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // spec.
106f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (m_fatalError)
107f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return;
108f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
1090c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    m_fatalError = error;
110f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // An existing timer may not have a zero timeout.
111f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    m_timer.stop();
1120c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    m_timer.startOneShot(0);
1135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
1145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
115a8d4462216d8e009ee5662660a0621b67c6e727fSteve Blockvoid Geolocation::GeoNotifier::setUseCachedPosition()
116bc2cb6973923b5560298950bd824d9627d6ed765Steve Block{
117a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block    m_useCachedPosition = true;
118bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    m_timer.startOneShot(0);
119bc2cb6973923b5560298950bd824d9627d6ed765Steve Block}
120bc2cb6973923b5560298950bd824d9627d6ed765Steve Block
121159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Blockbool Geolocation::GeoNotifier::hasZeroTimeout() const
122159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block{
123159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block    return m_options->hasTimeout() && m_options->timeout() == 0;
124159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block}
125159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block
126159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Blockvoid Geolocation::GeoNotifier::runSuccessCallback(Geoposition* position)
127a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block{
128a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block    m_successCallback->handleEvent(position);
129a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block}
130a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block
131802cd652fedb21e935bc514406bd7f5cc83de64dSteve Blockvoid Geolocation::GeoNotifier::startTimerIfNeeded()
1325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
133802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    if (m_options->hasTimeout())
1345f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_timer.startOneShot(m_options->timeout() / 1000.0);
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Geolocation::GeoNotifier::timerFired(Timer<GeoNotifier>*)
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_timer.stop();
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1411c58588a98d412c23d74caf92991904fddbc9d49Steve Block    // Protect this GeoNotifier object, since it
142643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // could be deleted by a call to clearWatch in a callback.
1431c58588a98d412c23d74caf92991904fddbc9d49Steve Block    RefPtr<GeoNotifier> protect(this);
1444cde69e96bdfa8e4abe06985ab19e407696539cfSteve Block
145f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Test for fatal error first. This is required for the case where the Frame is
146f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // disconnected and requests are cancelled.
1470c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    if (m_fatalError) {
148bc2cb6973923b5560298950bd824d9627d6ed765Steve Block        if (m_errorCallback)
1490c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block            m_errorCallback->handleEvent(m_fatalError.get());
1500c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block        // This will cause this notifier to be deleted.
1511c58588a98d412c23d74caf92991904fddbc9d49Steve Block        m_geolocation->fatalErrorOccurred(this);
1520c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block        return;
1530c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    }
1540c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block
155a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block    if (m_useCachedPosition) {
156a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block        // Clear the cached position flag in case this is a watch request, which
157c7d0c5294bbef1855c84c8072058813371f1af16Steve Block        // will continue to run.
158a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block        m_useCachedPosition = false;
159a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block        m_geolocation->requestUsesCachedPosition(this);
160bc2cb6973923b5560298950bd824d9627d6ed765Steve Block        return;
161bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    }
162bc2cb6973923b5560298950bd824d9627d6ed765Steve Block
163802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    if (m_errorCallback) {
164466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block        RefPtr<PositionError> error = PositionError::create(PositionError::TIMEOUT, "Timeout expired");
165802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block        m_errorCallback->handleEvent(error.get());
166802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    }
1671c58588a98d412c23d74caf92991904fddbc9d49Steve Block    m_geolocation->requestTimedOut(this);
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
170643ca7872b450ea4efacab6188849e5aac2ba161Steve Blockvoid Geolocation::Watchers::set(int id, PassRefPtr<GeoNotifier> prpNotifier)
171466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block{
172f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ASSERT(id > 0);
173643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    RefPtr<GeoNotifier> notifier = prpNotifier;
174643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
175643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_idToNotifierMap.set(id, notifier.get());
176643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    m_notifierToIdMap.set(notifier.release(), id);
177466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block}
178466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
179466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Blockvoid Geolocation::Watchers::remove(int id)
180466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block{
181f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ASSERT(id > 0);
182466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    IdToNotifierMap::iterator iter = m_idToNotifierMap.find(id);
183466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    if (iter == m_idToNotifierMap.end())
184466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block        return;
185466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_notifierToIdMap.remove(iter->second);
186466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_idToNotifierMap.remove(iter);
187466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block}
188466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
189466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Blockvoid Geolocation::Watchers::remove(GeoNotifier* notifier)
190466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block{
191466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    NotifierToIdMap::iterator iter = m_notifierToIdMap.find(notifier);
192466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    if (iter == m_notifierToIdMap.end())
193466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block        return;
194466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_idToNotifierMap.remove(iter->second);
195466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_notifierToIdMap.remove(iter);
196466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block}
197466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
19895e7487cbe7ec5c780e8af61f3cea2d90bb4459bSteve Blockbool Geolocation::Watchers::contains(GeoNotifier* notifier) const
19995e7487cbe7ec5c780e8af61f3cea2d90bb4459bSteve Block{
20095e7487cbe7ec5c780e8af61f3cea2d90bb4459bSteve Block    return m_notifierToIdMap.contains(notifier);
20195e7487cbe7ec5c780e8af61f3cea2d90bb4459bSteve Block}
20295e7487cbe7ec5c780e8af61f3cea2d90bb4459bSteve Block
203466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Blockvoid Geolocation::Watchers::clear()
204466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block{
205466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_idToNotifierMap.clear();
206466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_notifierToIdMap.clear();
207466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block}
208466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
209466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Blockbool Geolocation::Watchers::isEmpty() const
210466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block{
211466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    return m_idToNotifierMap.isEmpty();
212466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block}
213466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
2146b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid Geolocation::Watchers::getNotifiersVector(GeoNotifierVector& copy) const
215466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block{
216466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    copyValuesToVector(m_idToNotifierMap, copy);
217466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block}
218466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectGeolocation::Geolocation(Frame* frame)
220400e786798d320e3c9f4c9d82ea18ecc492a525aSteve Block    : m_frame(frame)
221370b559b082915acb99b185ed8c8e317fc654db6Steve Block#if !ENABLE(CLIENT_BASED_GEOLOCATION)
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_service(GeolocationService::create(this))
223370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
2248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_allowGeolocation(Unknown)
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_frame)
2278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_frame->document());
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame->document()->setUsingGeolocation(true);
2300c7394a4459ba850766d303b4307add7189cf5f3Steve Block}
2310c7394a4459ba850766d303b4307add7189cf5f3Steve Block
2320c7394a4459ba850766d303b4307add7189cf5f3Steve BlockGeolocation::~Geolocation()
2330c7394a4459ba850766d303b4307add7189cf5f3Steve Block{
2342bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(m_allowGeolocation != InProgress);
2352bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(!m_frame);
236400e786798d320e3c9f4c9d82ea18ecc492a525aSteve Block}
237400e786798d320e3c9f4c9d82ea18ecc492a525aSteve Block
2382bde8e466a4451c7319e3a072d118917957d6554Steve BlockPage* Geolocation::page() const
2392bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2402bde8e466a4451c7319e3a072d118917957d6554Steve Block    return m_frame ? m_frame->page() : 0;
2412bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2422bde8e466a4451c7319e3a072d118917957d6554Steve Block
2432bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid Geolocation::reset()
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2452bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = this->page();
2462bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (page && m_allowGeolocation == InProgress) {
247f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if ENABLE(CLIENT_BASED_GEOLOCATION)
2482bde8e466a4451c7319e3a072d118917957d6554Steve Block        page->geolocationController()->cancelPermissionRequest(this);
249f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
2502bde8e466a4451c7319e3a072d118917957d6554Steve Block        page->chrome()->cancelGeolocationPermissionRequestForFrame(m_frame, this);
251f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
2532bde8e466a4451c7319e3a072d118917957d6554Steve Block    // The frame may be moving to a new page and we want to get the permissions from the new page's client.
2542bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_allowGeolocation = Unknown;
255f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    cancelAllRequests();
2565af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke    stopUpdating();
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2582bde8e466a4451c7319e3a072d118917957d6554Steve Block
2592bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid Geolocation::disconnectFrame()
2602bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Once we are disconnected from the Frame, it is no longer possible to perform any operations.
2622bde8e466a4451c7319e3a072d118917957d6554Steve Block    reset();
263eebae91469b8f225fe78e97ce6dae26efcf6da43Steve Block    if (m_frame && m_frame->document())
264eebae91469b8f225fe78e97ce6dae26efcf6da43Steve Block        m_frame->document()->setUsingGeolocation(false);
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame = 0;
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268370b559b082915acb99b185ed8c8e317fc654db6Steve BlockGeoposition* Geolocation::lastPosition()
269370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
270370b559b082915acb99b185ed8c8e317fc654db6Steve Block#if ENABLE(CLIENT_BASED_GEOLOCATION)
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = this->page();
272370b559b082915acb99b185ed8c8e317fc654db6Steve Block    if (!page)
273370b559b082915acb99b185ed8c8e317fc654db6Steve Block        return 0;
274370b559b082915acb99b185ed8c8e317fc654db6Steve Block
275370b559b082915acb99b185ed8c8e317fc654db6Steve Block    m_lastPosition = createGeoposition(page->geolocationController()->lastPosition());
276370b559b082915acb99b185ed8c8e317fc654db6Steve Block#else
277370b559b082915acb99b185ed8c8e317fc654db6Steve Block    m_lastPosition = m_service->lastPosition();
278370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
279370b559b082915acb99b185ed8c8e317fc654db6Steve Block
280370b559b082915acb99b185ed8c8e317fc654db6Steve Block    return m_lastPosition.get();
281370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
282370b559b082915acb99b185ed8c8e317fc654db6Steve Block
2835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
285f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!m_frame)
286f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return;
287f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
288466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    RefPtr<GeoNotifier> notifier = startRequest(successCallback, errorCallback, options);
2894abe833d66929ee0f0363cf63dfe35ffe3d5a0a2Steve Block    ASSERT(notifier);
2903ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block
2913ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block    m_oneShots.add(notifier);
2923ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block}
2933ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block
2943ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Blockint Geolocation::watchPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
2953ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block{
296f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!m_frame)
297f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return 0;
298f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
299466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    RefPtr<GeoNotifier> notifier = startRequest(successCallback, errorCallback, options);
3004abe833d66929ee0f0363cf63dfe35ffe3d5a0a2Steve Block    ASSERT(notifier);
3013ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block
302f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    static int nextAvailableWatchId = firstAvailableWatchId;
303cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // In case of overflow, make sure the ID remains positive, but reuse the ID values.
304cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (nextAvailableWatchId < 1)
305cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        nextAvailableWatchId = 1;
306466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_watchers.set(nextAvailableWatchId, notifier.release());
307466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    return nextAvailableWatchId++;
3083ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block}
3093ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block
310466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve BlockPassRefPtr<Geolocation::GeoNotifier> Geolocation::startRequest(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
3113ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block{
3120c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    RefPtr<GeoNotifier> notifier = GeoNotifier::create(this, successCallback, errorCallback, options);
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3140c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    // Check whether permissions have already been denied. Note that if this is the case,
3150c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    // the permission state can not change again in the lifetime of this page.
316466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    if (isDenied())
3173ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block        notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
318159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block    else if (haveSuitableCachedPosition(notifier->m_options.get()))
319159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block        notifier->setUseCachedPosition();
320f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    else if (notifier->hasZeroTimeout())
321f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        notifier->startTimerIfNeeded();
322967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#if USE(PREEMPT_GEOLOCATION_PERMISSION)
323f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    else if (!isAllowed()) {
324f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        // if we don't yet have permission, request for permission before calling startUpdating()
325f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        m_pendingForPermissionNotifiers.add(notifier);
326f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        requestPermission();
327f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
328f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#endif
329f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    else if (startUpdating(notifier.get()))
330f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        notifier->startTimerIfNeeded();
331f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    else
332159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block        notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3343ae77a67311f7f1a6a072ccb81b5f502b09e4fb2Steve Block    return notifier.release();
3350c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block}
3360c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block
3370c97c982f069c9d9eee236d7f8461710d2e1d078Steve Blockvoid Geolocation::fatalErrorOccurred(Geolocation::GeoNotifier* notifier)
3380c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block{
3390c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    // This request has failed fatally. Remove it from our lists.
3400c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    m_oneShots.remove(notifier);
341466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_watchers.remove(notifier);
3420c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block
3430c97c982f069c9d9eee236d7f8461710d2e1d078Steve Block    if (!hasListeners())
344370b559b082915acb99b185ed8c8e317fc654db6Steve Block        stopUpdating();
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
347a8d4462216d8e009ee5662660a0621b67c6e727fSteve Blockvoid Geolocation::requestUsesCachedPosition(GeoNotifier* notifier)
348159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block{
349dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // This is called asynchronously, so the permissions could have been denied
350dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // since we last checked in startRequest.
351dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isDenied()) {
352dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
353dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
354dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
355dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
356dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_requestsAwaitingCachedPosition.add(notifier);
357dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
358dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // If permissions are allowed, make the callback
359dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (isAllowed()) {
360dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        makeCachedPositionCallbacks();
361dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
362dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
363dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
364dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // Request permissions, which may be synchronous or asynchronous.
365dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    requestPermission();
366dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
367dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
368dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid Geolocation::makeCachedPositionCallbacks()
369dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
370dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // All modifications to m_requestsAwaitingCachedPosition are done
371dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // asynchronously, so we don't need to worry about it being modified from
372dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // the callbacks.
373dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GeoNotifierSet::const_iterator end = m_requestsAwaitingCachedPosition.end();
374dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    for (GeoNotifierSet::const_iterator iter = m_requestsAwaitingCachedPosition.begin(); iter != end; ++iter) {
375dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        GeoNotifier* notifier = iter->get();
376f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        notifier->runSuccessCallback(m_positionCache.cachedPosition());
377dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
378dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // If this is a one-shot request, stop it. Otherwise, if the watch still
379dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        // exists, start the service to get updates.
380dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        if (m_oneShots.contains(notifier))
381dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            m_oneShots.remove(notifier);
382dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        else if (m_watchers.contains(notifier)) {
383dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            if (notifier->hasZeroTimeout() || startUpdating(notifier))
384dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                notifier->startTimerIfNeeded();
385dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            else
386dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
387dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        }
388dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    }
389dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
390dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_requestsAwaitingCachedPosition.clear();
391159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block
392159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block    if (!hasListeners())
393159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block        stopUpdating();
394159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block}
395159531f4ce4c04455cd544a7c0f7c1644a50ccbeSteve Block
396dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid Geolocation::requestTimedOut(GeoNotifier* notifier)
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
398dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // If this is a one-shot request, stop it.
399dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_oneShots.remove(notifier);
400dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!hasListeners())
402370b559b082915acb99b185ed8c8e317fc654db6Steve Block        stopUpdating();
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
405dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool Geolocation::haveSuitableCachedPosition(PositionOptions* options)
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
407f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_positionCache.cachedPosition())
408dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
409dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!options->hasMaximumAge())
410dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return true;
411dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!options->maximumAge())
412dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return false;
4136b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    DOMTimeStamp currentTimeMillis = convertSecondsToDOMTimeStamp(currentTime());
414f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_positionCache.cachedPosition()->timestamp() > currentTimeMillis - options->maximumAge();
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
417dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid Geolocation::clearWatch(int watchId)
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
419f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (watchId < firstAvailableWatchId)
420f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return;
421f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
422dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    m_watchers.remove(watchId);
423dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
424dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!hasListeners())
425dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        stopUpdating();
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4285fb15a120c24faef11e5952a791c5af38c54b07eSteve Blockvoid Geolocation::suspend()
4295fb15a120c24faef11e5952a791c5af38c54b07eSteve Block{
4305fb15a120c24faef11e5952a791c5af38c54b07eSteve Block#if !ENABLE(CLIENT_BASED_GEOLOCATION)
4315fb15a120c24faef11e5952a791c5af38c54b07eSteve Block    if (hasListeners())
4325fb15a120c24faef11e5952a791c5af38c54b07eSteve Block        m_service->suspend();
4335fb15a120c24faef11e5952a791c5af38c54b07eSteve Block#endif
4345fb15a120c24faef11e5952a791c5af38c54b07eSteve Block}
4355fb15a120c24faef11e5952a791c5af38c54b07eSteve Block
4365fb15a120c24faef11e5952a791c5af38c54b07eSteve Blockvoid Geolocation::resume()
4375fb15a120c24faef11e5952a791c5af38c54b07eSteve Block{
4385fb15a120c24faef11e5952a791c5af38c54b07eSteve Block#if !ENABLE(CLIENT_BASED_GEOLOCATION)
4395fb15a120c24faef11e5952a791c5af38c54b07eSteve Block    if (hasListeners())
4405fb15a120c24faef11e5952a791c5af38c54b07eSteve Block        m_service->resume();
4415fb15a120c24faef11e5952a791c5af38c54b07eSteve Block#endif
4425fb15a120c24faef11e5952a791c5af38c54b07eSteve Block}
4435fb15a120c24faef11e5952a791c5af38c54b07eSteve Block
4448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid Geolocation::setIsAllowed(bool allowed)
4458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
446bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    // This may be due to either a new position from the service, or a cached
447bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    // position.
4488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_allowGeolocation = allowed ? Yes : No;
44923c22a60ec108914d8df8cd80023582fbedfe978Steve Block
450967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#if USE(PREEMPT_GEOLOCATION_PERMISSION)
451f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // Permission request was made during the startRequest process
452f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    if (!m_pendingForPermissionNotifiers.isEmpty()) {
453f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        handlePendingPermissionNotifiers();
454f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        m_pendingForPermissionNotifiers.clear();
45523c22a60ec108914d8df8cd80023582fbedfe978Steve Block        return;
45623c22a60ec108914d8df8cd80023582fbedfe978Steve Block    }
45723c22a60ec108914d8df8cd80023582fbedfe978Steve Block#endif
458bc2cb6973923b5560298950bd824d9627d6ed765Steve Block
459bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    if (!isAllowed()) {
460466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block        RefPtr<PositionError> error = PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage);
4615343011d8c5e322c74a78385633354ca3db92343Steve Block        error->setIsFatal(true);
4628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        handleError(error.get());
463a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block        m_requestsAwaitingCachedPosition.clear();
464bc2cb6973923b5560298950bd824d9627d6ed765Steve Block        return;
4658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
466bc2cb6973923b5560298950bd824d9627d6ed765Steve Block
467bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    // If the service has a last position, use it to call back for all requests.
468bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    // If any of the requests are waiting for permission for a cached position,
469bc2cb6973923b5560298950bd824d9627d6ed765Steve Block    // the position from the service will be at least as fresh.
4708a03f7cd9e884b3db11bb5485b4d9f5095dc0bcaSteve Block    if (lastPosition())
471bc2cb6973923b5560298950bd824d9627d6ed765Steve Block        makeSuccessCallbacks();
472a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block    else
473a8d4462216d8e009ee5662660a0621b67c6e727fSteve Block        makeCachedPositionCallbacks();
4748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
4758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid Geolocation::sendError(GeoNotifierVector& notifiers, PositionError* error)
4770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
4786b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner     GeoNotifierVector::const_iterator end = notifiers.end();
4796b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner     for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
4800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch         RefPtr<GeoNotifier> notifier = *it;
4810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch         if (notifier->m_errorCallback)
4830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch             notifier->m_errorCallback->handleEvent(error);
4840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch     }
4850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
4860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4876b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid Geolocation::sendPosition(GeoNotifierVector& notifiers, Geoposition* position)
4880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
4896b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector::const_iterator end = notifiers.end();
4906b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RefPtr<GeoNotifier> notifier = *it;
4920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(notifier->m_successCallback);
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        notifier->m_successCallback->handleEvent(position);
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid Geolocation::stopTimer(GeoNotifierVector& notifiers)
4995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
5006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector::const_iterator end = notifiers.end();
5016b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
5025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RefPtr<GeoNotifier> notifier = *it;
503802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block        notifier->m_timer.stop();
5045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    }
5055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
5065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
507802cd652fedb21e935bc514406bd7f5cc83de64dSteve Blockvoid Geolocation::stopTimersForOneShots()
5085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
5096b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector copy;
5105f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    copyToVector(m_oneShots, copy);
5115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
512802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    stopTimer(copy);
5135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
5145f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
515802cd652fedb21e935bc514406bd7f5cc83de64dSteve Blockvoid Geolocation::stopTimersForWatchers()
5165f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
5176b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector copy;
518466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_watchers.getNotifiersVector(copy);
5195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
520802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    stopTimer(copy);
5215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
5225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
523802cd652fedb21e935bc514406bd7f5cc83de64dSteve Blockvoid Geolocation::stopTimers()
5245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
525802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    stopTimersForOneShots();
526802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    stopTimersForWatchers();
5275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
5285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
5296b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brennervoid Geolocation::cancelRequests(GeoNotifierVector& notifiers)
530f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
5316b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector::const_iterator end = notifiers.end();
5326b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it)
533f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        (*it)->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, framelessDocumentErrorMessage));
534f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
535f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
536f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid Geolocation::cancelAllRequests()
537f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
5386b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector copy;
539f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    copyToVector(m_oneShots, copy);
540f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    cancelRequests(copy);
541f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    m_watchers.getNotifiersVector(copy);
542f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    cancelRequests(copy);
543f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
544f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
5454576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid Geolocation::extractNotifiersWithCachedPosition(GeoNotifierVector& notifiers, GeoNotifierVector* cached)
5464576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{
5474576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    GeoNotifierVector nonCached;
5484576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    GeoNotifierVector::iterator end = notifiers.end();
5494576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    for (GeoNotifierVector::const_iterator it = notifiers.begin(); it != end; ++it) {
5504576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        GeoNotifier* notifier = it->get();
5514576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        if (notifier->m_useCachedPosition) {
5524576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            if (cached)
5534576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang                cached->append(notifier);
5544576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        } else
5554576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            nonCached.append(notifier);
5564576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
5574576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    notifiers.swap(nonCached);
5584576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang}
5594576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
5604576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wangvoid Geolocation::copyToSet(const GeoNotifierVector& src, GeoNotifierSet& dest)
5614576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang{
5624576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang     GeoNotifierVector::const_iterator end = src.end();
5634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang     for (GeoNotifierVector::const_iterator it = src.begin(); it != end; ++it) {
5644576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang         GeoNotifier* notifier = it->get();
5654576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang         dest.add(notifier);
5664576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang     }
5674576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang}
5684576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Geolocation::handleError(PositionError* error)
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(error);
572466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
5736b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector oneShotsCopy;
574e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block    copyToVector(m_oneShots, oneShotsCopy);
575e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block
5766b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector watchersCopy;
577466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_watchers.getNotifiersVector(watchersCopy);
578e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block
579e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block    // Clear the lists before we make the callbacks, to avoid clearing notifiers
580466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    // added by calls to Geolocation methods from the callbacks, and to prevent
581466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    // further callbacks to these notifiers.
5824576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    GeoNotifierVector oneShotsWithCachedPosition;
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_oneShots.clear();
5845343011d8c5e322c74a78385633354ca3db92343Steve Block    if (error->isFatal())
5855343011d8c5e322c74a78385633354ca3db92343Steve Block        m_watchers.clear();
5864576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    else {
5874576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        // Don't send non-fatal errors to notifiers due to receive a cached position.
5884576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        extractNotifiersWithCachedPosition(oneShotsCopy, &oneShotsWithCachedPosition);
5894576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        extractNotifiersWithCachedPosition(watchersCopy, 0);
5904576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    }
5910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
592e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block    sendError(oneShotsCopy, error);
593e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block    sendError(watchersCopy, error);
594e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block
5954576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // hasListeners() doesn't distinguish between notifiers due to receive a
5964576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // cached position and those requiring a fresh position. Perform the check
5974576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // before restoring the notifiers below.
5980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!hasListeners())
599370b559b082915acb99b185ed8c8e317fc654db6Steve Block        stopUpdating();
6004576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
6014576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // Maintain a reference to the cached notifiers until their timer fires.
6024576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    copyToSet(oneShotsWithCachedPosition, m_oneShots);
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid Geolocation::requestPermission()
6068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
6078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_allowGeolocation > Unknown)
6088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
6098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6102bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = this->page();
6118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!page)
6128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
6136c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
6140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_allowGeolocation = InProgress;
6150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
616f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Ask the embedder: it maintains the geolocation challenge policy itself.
617f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if ENABLE(CLIENT_BASED_GEOLOCATION)
618f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    page->geolocationController()->requestPermission(this);
619f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
6208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    page->chrome()->requestGeolocationPermissionForFrame(m_frame, this);
621f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
6228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
6238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6246c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenvoid Geolocation::positionChangedInternal()
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
626f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_positionCache.setCachedPosition(lastPosition());
62700bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block
628802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    // Stop all currently running timers.
629802cd652fedb21e935bc514406bd7f5cc83de64dSteve Block    stopTimers();
6306c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
63100bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block    if (!isAllowed()) {
63200bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block        // requestPermission() will ask the chrome for permission. This may be
63300bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block        // implemented synchronously or asynchronously. In both cases,
634466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block        // makeSuccessCallbacks() will be called if permission is granted, so
63500bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block        // there's nothing more to do here.
63600bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block        requestPermission();
6378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
63800bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block    }
63900bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block
64000bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block    makeSuccessCallbacks();
64100bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block}
64200bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block
64300bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Blockvoid Geolocation::makeSuccessCallbacks()
64400bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block{
645dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    ASSERT(lastPosition());
64600bd0fc337f03c8595ccae3a2d3d56c6d8e97cc9Steve Block    ASSERT(isAllowed());
647466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
6486b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector oneShotsCopy;
649e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block    copyToVector(m_oneShots, oneShotsCopy);
650466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
6516b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    GeoNotifierVector watchersCopy;
652466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    m_watchers.getNotifiersVector(watchersCopy);
653466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block
654e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block    // Clear the lists before we make the callbacks, to avoid clearing notifiers
655466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    // added by calls to Geolocation methods from the callbacks, and to prevent
656466006e4a13fd557d7b35c1fe0b7a38384e5ce2eSteve Block    // further callbacks to these notifiers.
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_oneShots.clear();
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
659dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    sendPosition(oneShotsCopy, lastPosition());
660dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    sendPosition(watchersCopy, lastPosition());
661e27fedc48d78b1c1b6e656fe42d64efd60056464Steve Block
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!hasListeners())
663370b559b082915acb99b185ed8c8e317fc654db6Steve Block        stopUpdating();
664370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
665370b559b082915acb99b185ed8c8e317fc654db6Steve Block
666370b559b082915acb99b185ed8c8e317fc654db6Steve Block#if ENABLE(CLIENT_BASED_GEOLOCATION)
667370b559b082915acb99b185ed8c8e317fc654db6Steve Block
6686c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenvoid Geolocation::positionChanged()
669370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
6706c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    positionChangedInternal();
671370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
672370b559b082915acb99b185ed8c8e317fc654db6Steve Block
673370b559b082915acb99b185ed8c8e317fc654db6Steve Blockvoid Geolocation::setError(GeolocationError* error)
674370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
675370b559b082915acb99b185ed8c8e317fc654db6Steve Block    RefPtr<PositionError> positionError = createPositionError(error);
676370b559b082915acb99b185ed8c8e317fc654db6Steve Block    handleError(positionError.get());
677370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
678370b559b082915acb99b185ed8c8e317fc654db6Steve Block
679370b559b082915acb99b185ed8c8e317fc654db6Steve Block#else
680370b559b082915acb99b185ed8c8e317fc654db6Steve Block
681370b559b082915acb99b185ed8c8e317fc654db6Steve Blockvoid Geolocation::geolocationServicePositionChanged(GeolocationService* service)
682370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
683370b559b082915acb99b185ed8c8e317fc654db6Steve Block    ASSERT_UNUSED(service, service == m_service);
684370b559b082915acb99b185ed8c8e317fc654db6Steve Block    ASSERT(m_service->lastPosition());
685370b559b082915acb99b185ed8c8e317fc654db6Steve Block
6866c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    positionChangedInternal();
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid Geolocation::geolocationServiceErrorOccurred(GeolocationService* service)
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(service->lastError());
692370b559b082915acb99b185ed8c8e317fc654db6Steve Block
693c7d0c5294bbef1855c84c8072058813371f1af16Steve Block    // Note that we do not stop timers here. For one-shots, the request is
694c7d0c5294bbef1855c84c8072058813371f1af16Steve Block    // cleared in handleError. For watchers, the spec requires that the timer is
695c7d0c5294bbef1855c84c8072058813371f1af16Steve Block    // not cleared.
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    handleError(service->lastError());
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
699370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
700370b559b082915acb99b185ed8c8e317fc654db6Steve Block
70123c22a60ec108914d8df8cd80023582fbedfe978Steve Blockbool Geolocation::startUpdating(GeoNotifier* notifier)
702370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
703967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch#if ENABLE(CLIENT_BASED_GEOLOCATION)
7042bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = this->page();
705370b559b082915acb99b185ed8c8e317fc654db6Steve Block    if (!page)
706370b559b082915acb99b185ed8c8e317fc654db6Steve Block        return false;
707370b559b082915acb99b185ed8c8e317fc654db6Steve Block
7080617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    page->geolocationController()->addObserver(this, notifier->m_options->enableHighAccuracy());
709370b559b082915acb99b185ed8c8e317fc654db6Steve Block    return true;
710370b559b082915acb99b185ed8c8e317fc654db6Steve Block#else
711930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block#if PLATFORM(ANDROID)
712930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block    // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082
713930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block    // Note that the correct fix is to use a 'paused' flag in WebCore, rather
714930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block    // than calling into PlatformBridge.
715b9362877ccf9e5f8027f12898166d56518bbedb6Steve Block    if (!m_frame)
716b9362877ccf9e5f8027f12898166d56518bbedb6Steve Block        return false;
717b9362877ccf9e5f8027f12898166d56518bbedb6Steve Block    FrameView* view = m_frame->view();
718b9362877ccf9e5f8027f12898166d56518bbedb6Steve Block    if (!view)
719b9362877ccf9e5f8027f12898166d56518bbedb6Steve Block        return false;
720b9362877ccf9e5f8027f12898166d56518bbedb6Steve Block    return m_service->startUpdating(notifier->m_options.get(), PlatformBridge::isWebViewPaused(view));
721930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block#else
722db42c078ffb0f6a679e3853cb4ebb39e09c1f815Steve Block    return m_service->startUpdating(notifier->m_options.get());
723370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
724930792dfdde9ad0fac3251ab70eb00d97f2fe88dSteve Block#endif
725370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
726370b559b082915acb99b185ed8c8e317fc654db6Steve Block
727370b559b082915acb99b185ed8c8e317fc654db6Steve Blockvoid Geolocation::stopUpdating()
728370b559b082915acb99b185ed8c8e317fc654db6Steve Block{
729370b559b082915acb99b185ed8c8e317fc654db6Steve Block#if ENABLE(CLIENT_BASED_GEOLOCATION)
7302bde8e466a4451c7319e3a072d118917957d6554Steve Block    Page* page = this->page();
731370b559b082915acb99b185ed8c8e317fc654db6Steve Block    if (!page)
732370b559b082915acb99b185ed8c8e317fc654db6Steve Block        return;
733370b559b082915acb99b185ed8c8e317fc654db6Steve Block
734370b559b082915acb99b185ed8c8e317fc654db6Steve Block    page->geolocationController()->removeObserver(this);
735370b559b082915acb99b185ed8c8e317fc654db6Steve Block#else
736370b559b082915acb99b185ed8c8e317fc654db6Steve Block    m_service->stopUpdating();
737370b559b082915acb99b185ed8c8e317fc654db6Steve Block#endif
738370b559b082915acb99b185ed8c8e317fc654db6Steve Block
739370b559b082915acb99b185ed8c8e317fc654db6Steve Block}
740370b559b082915acb99b185ed8c8e317fc654db6Steve Block
741f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#if USE(PREEMPT_GEOLOCATION_PERMISSION)
742f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickvoid Geolocation::handlePendingPermissionNotifiers()
743f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
744f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // While we iterate through the list, we need not worry about list being modified as the permission
745f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    // is already set to Yes/No and no new listeners will be added to the pending list
746f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    GeoNotifierSet::const_iterator end = m_pendingForPermissionNotifiers.end();
747f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    for (GeoNotifierSet::const_iterator iter = m_pendingForPermissionNotifiers.begin(); iter != end; ++iter) {
748f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        GeoNotifier* notifier = iter->get();
749f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
750f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        if (isAllowed()) {
751f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            // start all pending notification requests as permission granted.
752f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            // The notifier is always ref'ed by m_oneShots or m_watchers.
753e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block            if (startUpdating(notifier))
754e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block                notifier->startTimerIfNeeded();
755e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block            else
756e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block                notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, failedToStartServiceErrorMessage));
757f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        } else
758f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick            notifier->setFatalError(PositionError::create(PositionError::PERMISSION_DENIED, permissionDeniedErrorMessage));
759f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    }
760f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
761f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#endif
762f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
764dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
765dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#else
766dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
767dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blocknamespace WebCore {
768dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
769a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid Geolocation::clearWatch(int) {}
77021939df44de1705786c545cd1bf519d47250322dBen Murdoch
7712bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid Geolocation::reset() {}
7722bde8e466a4451c7319e3a072d118917957d6554Steve Block
773dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid Geolocation::disconnectFrame() {}
774dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
775dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGeolocation::Geolocation(Frame*) {}
776dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
777dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve BlockGeolocation::~Geolocation() {}
778dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
779dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid Geolocation::setIsAllowed(bool) {}
780dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
781dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
782dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
783dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif // ENABLE(GEOLOCATION)
784