diff options
author | Steve Block <steveblock@google.com> | 2011-05-13 06:44:40 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-05-13 06:44:40 -0700 |
commit | 08014c20784f3db5df3a89b73cce46037b77eb59 (patch) | |
tree | 47749210d31e19e6e2f64036fa8fae2ad693476f /Source/WebCore/platform/android/GeolocationServiceAndroid.cpp | |
parent | 860220379e56aeb66424861ad602b07ee22b4055 (diff) | |
parent | 4c3661f7918f8b3f139f824efb7855bedccb4c94 (diff) | |
download | external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.zip external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.tar.gz external_webkit-08014c20784f3db5df3a89b73cce46037b77eb59.tar.bz2 |
Merge changes Ide388898,Ic49f367c,I1158a808,Iacb6ca5d,I2100dd3a,I5c1abe54,Ib0ef9902,I31dbc523,I570314b3
* changes:
Merge WebKit at r75315: Update WebKit version
Merge WebKit at r75315: Add FrameLoaderClient PageCache stubs
Merge WebKit at r75315: Stub out AXObjectCache::remove()
Merge WebKit at r75315: Fix ImageBuffer
Merge WebKit at r75315: Fix PluginData::initPlugins()
Merge WebKit at r75315: Fix conflicts
Merge WebKit at r75315: Fix Makefiles
Merge WebKit at r75315: Move Android-specific WebCore files to Source
Merge WebKit at r75315: Initial merge by git.
Diffstat (limited to 'Source/WebCore/platform/android/GeolocationServiceAndroid.cpp')
-rw-r--r-- | Source/WebCore/platform/android/GeolocationServiceAndroid.cpp | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp b/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp new file mode 100644 index 0000000..0f07722 --- /dev/null +++ b/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp @@ -0,0 +1,204 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "GeolocationServiceAndroid.h" + +#include "Geolocation.h" +#include "GeolocationServiceBridge.h" +#include "Geoposition.h" +#include "PositionError.h" +#include "PositionOptions.h" + +#if PLATFORM(ANDROID) +// Required for sim-eng build +#include <math.h> +#endif +#include <wtf/CurrentTime.h> + +using JSC::Bindings::getJNIEnv; +using namespace std; + +namespace WebCore { + +// GeolocationServiceAndroid is the Android implmentation of Geolocation +// service. Each object of this class owns an object of type +// GeolocationServiceBridge, which in turn owns a Java GeolocationService +// object. Therefore, there is a 1:1 mapping between Geolocation, +// GeolocationServiceAndroid, GeolocationServiceBridge and Java +// GeolocationService objects. In the case where multiple Geolocation objects +// exist simultaneously, the corresponsing Java GeolocationService objects all +// register with the platform location service. It is the platform service that +// handles making sure that updates are passed to all Geolocation objects. +GeolocationService* GeolocationServiceAndroid::create(GeolocationServiceClient* client) +{ + return new GeolocationServiceAndroid(client); +} + +GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceAndroid::create; + +GeolocationServiceAndroid::GeolocationServiceAndroid(GeolocationServiceClient* client) + : GeolocationService(client) + , m_timer(this, &GeolocationServiceAndroid::timerFired) + , m_javaBridge(0) +{ +} + +// ANDROID +// TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 +bool GeolocationServiceAndroid::startUpdating(PositionOptions* options, bool suspend) +{ + // ANDROID + // This is an ugly hack. A correct fix would require a change to WebCore, + // but this isn't worth the effort as we're in the process of switching to a + // client-based implementation. See https://bugs.webkit.org/show_bug.cgi?id=40373 + Frame* frame = reinterpret_cast<Geolocation*>(geolocationServiceClient())->frame(); + if (!frame) + return false; + + // This method is called every time a new watch or one-shot position request + // is started. If we already have a position or an error, call back + // immediately. + if (m_lastPosition || m_lastError) { + ASSERT(m_javaBridge); + m_timer.startOneShot(0); + } + + // Lazilly create the Java object. + bool haveJavaBridge = m_javaBridge; + if (!haveJavaBridge) + m_javaBridge.set(new GeolocationServiceBridge(this, frame)); + ASSERT(m_javaBridge); + + // On Android, high power == GPS. Set whether to use GPS before we start the + // implementation. + ASSERT(options); + if (options->enableHighAccuracy()) + m_javaBridge->setEnableGps(true); + + // We need only start the service when it's first created. + if (!haveJavaBridge) { + // If the browser is paused, don't start the service. It will be started + // when we get the call to resume. + // ANDROID + // TODO: Upstream to webkit.org. See https://bugs.webkit.org/show_bug.cgi?id=34082 + if (!suspend) + return m_javaBridge->start(); + } + + return true; +} + +void GeolocationServiceAndroid::stopUpdating() +{ + // Called when the Geolocation object has no watches or one shots in + // progress. This may be called repeatedly. + m_javaBridge.clear(); + // Reset last position and error to make sure that we always try to get a + // new position from the system service when a request is first made. + m_lastPosition = 0; + m_lastError = 0; + // remove the pending timer + if (m_timer.isActive()) + m_timer.stop(); +} + +void GeolocationServiceAndroid::suspend() +{ + if (m_javaBridge) + m_javaBridge->stop(); +} + +void GeolocationServiceAndroid::resume() +{ + if (m_javaBridge) + m_javaBridge->start(); +} + +// Note that there is no guarantee that subsequent calls to this method offer a +// more accurate or updated position. +void GeolocationServiceAndroid::newPositionAvailable(PassRefPtr<Geoposition> position) +{ + ASSERT(position); + if (!m_lastPosition + || isPositionMovement(m_lastPosition.get(), position.get()) + || isPositionMoreAccurate(m_lastPosition.get(), position.get()) + || isPositionMoreTimely(m_lastPosition.get(), position.get())) { + m_lastPosition = position; + // Remove the last error. + m_lastError = 0; + positionChanged(); + } +} + +void GeolocationServiceAndroid::newErrorAvailable(PassRefPtr<PositionError> error) +{ + ASSERT(error); + // We leave the last position + m_lastError = error; + errorOccurred(); +} + +void GeolocationServiceAndroid::timerFired(Timer<GeolocationServiceAndroid>* timer) +{ + ASSERT(&m_timer == timer); + ASSERT(m_lastPosition || m_lastError); + if (m_lastPosition) + positionChanged(); + else if (m_lastError) + errorOccurred(); +} + +bool GeolocationServiceAndroid::isPositionMovement(Geoposition* position1, Geoposition* position2) +{ + ASSERT(position1 && position2); + // For the small distances in which we are likely concerned, it's reasonable + // to approximate the distance between the two positions as the sum of the + // differences in latitude and longitude. + double delta = fabs(position1->coords()->latitude() - position2->coords()->latitude()) + + fabs(position1->coords()->longitude() - position2->coords()->longitude()); + // Approximate conversion from degrees of arc to metres. + delta *= 60 * 1852; + // The threshold is when the distance between the two positions exceeds the + // worse (larger) of the two accuracies. + int maxAccuracy = max(position1->coords()->accuracy(), position2->coords()->accuracy()); + return delta > maxAccuracy; +} + +bool GeolocationServiceAndroid::isPositionMoreAccurate(Geoposition* position1, Geoposition* position2) +{ + ASSERT(position1 && position2); + return position2->coords()->accuracy() < position1->coords()->accuracy(); +} + +bool GeolocationServiceAndroid::isPositionMoreTimely(Geoposition* position1, Geoposition* position2) +{ + ASSERT(position1 && position2); + DOMTimeStamp currentTime = convertSecondsToDOMTimeStamp(WTF::currentTime()); + DOMTimeStamp maximumAge = convertSecondsToDOMTimeStamp(10 * 60); // 10 minutes + return currentTime - position1->timestamp() > maximumAge; +} + +} // namespace WebCore |