summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/android/GeolocationServiceAndroid.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-13 06:44:40 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-05-13 06:44:40 -0700
commit08014c20784f3db5df3a89b73cce46037b77eb59 (patch)
tree47749210d31e19e6e2f64036fa8fae2ad693476f /Source/WebCore/platform/android/GeolocationServiceAndroid.cpp
parent860220379e56aeb66424861ad602b07ee22b4055 (diff)
parent4c3661f7918f8b3f139f824efb7855bedccb4c94 (diff)
downloadexternal_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.cpp204
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