summaryrefslogtreecommitdiffstats
path: root/WebCore/page/Geolocation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/page/Geolocation.cpp')
-rw-r--r--WebCore/page/Geolocation.cpp149
1 files changed, 132 insertions, 17 deletions
diff --git a/WebCore/page/Geolocation.cpp b/WebCore/page/Geolocation.cpp
index 5fbad47..f0578a8 100644
--- a/WebCore/page/Geolocation.cpp
+++ b/WebCore/page/Geolocation.cpp
@@ -39,10 +39,45 @@
#include "SQLValue.h"
#include <wtf/CurrentTime.h>
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+#include "Coordinates.h"
+#include "GeolocationController.h"
+#include "GeolocationError.h"
+#include "GeolocationPosition.h"
+#include "Geoposition.h"
+#include "PositionError.h"
+#endif
+
namespace WebCore {
static const char permissionDeniedErrorMessage[] = "User denied Geolocation";
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+
+static PassRefPtr<Geoposition> createGeoposition(GeolocationPosition* position)
+{
+ RefPtr<Coordinates> coordinates = Coordinates::create(position->latitude(), position->longitude(), position->canProvideAltitude(), position->altitude(),
+ position->accuracy(), position->canProvideAltitudeAccuracy(), position->altitudeAccuracy(),
+ position->canProvideHeading(), position->heading(), position->canProvideSpeed(), position->speed());
+ return Geoposition::create(coordinates.release(), position->timestamp());
+}
+
+static PassRefPtr<PositionError> createPositionError(GeolocationError* error)
+{
+ PositionError::ErrorCode code = PositionError::POSITION_UNAVAILABLE;
+ switch (error->code()) {
+ case GeolocationError::PermissionDenied:
+ code = PositionError::PERMISSION_DENIED;
+ break;
+ case GeolocationError::PositionUnavailable:
+ code = PositionError::POSITION_UNAVAILABLE;
+ break;
+ }
+
+ return PositionError::create(code, error->message());
+}
+#endif
+
Geolocation::GeoNotifier::GeoNotifier(Geolocation* geolocation, PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
: m_geolocation(geolocation)
, m_successCallback(successCallback)
@@ -305,7 +340,9 @@ String* CachedPositionManager::s_databaseFile = 0;
Geolocation::Geolocation(Frame* frame)
: EventListener(GeolocationEventListenerType)
, m_frame(frame)
+#if !ENABLE(CLIENT_BASED_GEOLOCATION)
, m_service(GeolocationService::create(this))
+#endif
, m_allowGeolocation(Unknown)
, m_shouldClearCache(false)
, m_cachedPositionManager(new CachedPositionManager)
@@ -327,7 +364,7 @@ Geolocation::~Geolocation()
void Geolocation::disconnectFrame()
{
- m_service->stopUpdating();
+ stopUpdating();
if (m_frame && m_frame->document())
m_frame->document()->setUsingGeolocation(false);
m_frame = 0;
@@ -335,6 +372,24 @@ void Geolocation::disconnectFrame()
delete m_cachedPositionManager;
}
+Geoposition* Geolocation::lastPosition()
+{
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+ if (!m_frame)
+ return 0;
+
+ Page* page = m_frame->page();
+ if (!page)
+ return 0;
+
+ m_lastPosition = createGeoposition(page->geolocationController()->lastPosition());
+#else
+ m_lastPosition = m_service->lastPosition();
+#endif
+
+ return m_lastPosition.get();
+}
+
void Geolocation::getCurrentPosition(PassRefPtr<PositionCallback> successCallback, PassRefPtr<PositionErrorCallback> errorCallback, PassRefPtr<PositionOptions> options)
{
RefPtr<GeoNotifier> notifier = startRequest(successCallback, errorCallback, options);
@@ -391,7 +446,7 @@ void Geolocation::fatalErrorOccurred(Geolocation::GeoNotifier* notifier)
m_watchers.remove(notifier);
if (!hasListeners())
- m_service->stopUpdating();
+ stopUpdating();
}
void Geolocation::requestTimedOut(GeoNotifier* notifier)
@@ -400,7 +455,7 @@ void Geolocation::requestTimedOut(GeoNotifier* notifier)
m_oneShots.remove(notifier);
if (!hasListeners())
- m_service->stopUpdating();
+ stopUpdating();
}
void Geolocation::requestReturnedCachedPosition(GeoNotifier* notifier)
@@ -408,11 +463,11 @@ void Geolocation::requestReturnedCachedPosition(GeoNotifier* notifier)
// If this is a one-shot request, stop it.
m_oneShots.remove(notifier);
if (!hasListeners())
- m_service->stopUpdating();
+ stopUpdating();
// Otherwise, if the watch still exists, start the service to get updates.
if (m_watchers.contains(notifier)) {
- if (notifier->hasZeroTimeout() || m_service->startUpdating(notifier->m_options.get()))
+ if (notifier->hasZeroTimeout() || startUpdating(notifier->m_options.get()))
notifier->startTimerIfNeeded();
else
notifier->setFatalError(PositionError::create(PositionError::POSITION_UNAVAILABLE, "Failed to start Geolocation service"));
@@ -436,7 +491,7 @@ void Geolocation::clearWatch(int watchId)
m_watchers.remove(watchId);
if (!hasListeners())
- m_service->stopUpdating();
+ stopUpdating();
}
void Geolocation::suspend()
@@ -497,7 +552,6 @@ void Geolocation::sendPosition(Vector<RefPtr<GeoNotifier> >& notifiers, Geoposit
RefPtr<GeoNotifier> notifier = *it;
ASSERT(notifier->m_successCallback);
- notifier->m_timer.stop();
notifier->m_successCallback->handleEvent(position);
}
}
@@ -554,7 +608,7 @@ void Geolocation::handleError(PositionError* error)
sendError(watchersCopy, error);
if (!hasListeners())
- m_service->stopUpdating();
+ stopUpdating();
}
void Geolocation::requestPermission()
@@ -575,12 +629,11 @@ void Geolocation::requestPermission()
page->chrome()->requestGeolocationPermissionForFrame(m_frame, this);
}
-void Geolocation::geolocationServicePositionChanged(GeolocationService* service)
+void Geolocation::positionChanged(PassRefPtr<Geoposition> newPosition)
{
- ASSERT_UNUSED(service, service == m_service);
- ASSERT(m_service->lastPosition());
+ m_currentPosition = newPosition;
- m_cachedPositionManager->setCachedPosition(m_service->lastPosition());
+ m_cachedPositionManager->setCachedPosition(m_currentPosition.get());
// Stop all currently running timers.
stopTimers();
@@ -599,7 +652,7 @@ void Geolocation::geolocationServicePositionChanged(GeolocationService* service)
void Geolocation::makeSuccessCallbacks()
{
- ASSERT(m_service->lastPosition());
+ ASSERT(m_currentPosition);
ASSERT(isAllowed());
Vector<RefPtr<GeoNotifier> > oneShotsCopy;
@@ -613,23 +666,85 @@ void Geolocation::makeSuccessCallbacks()
// further callbacks to these notifiers.
m_oneShots.clear();
- sendPosition(oneShotsCopy, m_service->lastPosition());
- sendPosition(watchersCopy, m_service->lastPosition());
+ sendPosition(oneShotsCopy, m_currentPosition.get());
+ sendPosition(watchersCopy, m_currentPosition.get());
if (!hasListeners())
- m_service->stopUpdating();
+ stopUpdating();
+}
+
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+
+void Geolocation::setPosition(GeolocationPosition* position)
+{
+ positionChanged(createGeoposition(position));
+}
+
+void Geolocation::setError(GeolocationError* error)
+{
+ RefPtr<PositionError> positionError = createPositionError(error);
+ handleError(positionError.get());
+}
+
+#else
+
+void Geolocation::geolocationServicePositionChanged(GeolocationService* service)
+{
+ ASSERT_UNUSED(service, service == m_service);
+ ASSERT(m_service->lastPosition());
+
+ positionChanged(m_service->lastPosition());
}
void Geolocation::geolocationServiceErrorOccurred(GeolocationService* service)
{
ASSERT(service->lastError());
-
+
// Note that we do not stop timers here. For one-shots, the request is
// cleared in handleError. For watchers, the spec requires that the timer is
// not cleared.
handleError(service->lastError());
}
+#endif
+
+bool Geolocation::startUpdating(PositionOptions* options)
+{
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+ // FIXME: Pass options to client.
+ UNUSED_PARAM(options);
+
+ if (!m_frame)
+ return false;
+
+ Page* page = m_frame->page();
+ if (!page)
+ return false;
+
+ page->geolocationController()->addObserver(this);
+ return true;
+#else
+ return m_service->startUpdating(options);
+#endif
+}
+
+void Geolocation::stopUpdating()
+{
+#if ENABLE(CLIENT_BASED_GEOLOCATION)
+ if (!m_frame)
+ return;
+
+ Page* page = m_frame->page();
+ if (!page)
+ return;
+
+ page->geolocationController()->removeObserver(this);
+#else
+ m_service->stopUpdating();
+#endif
+
+}
+
bool Geolocation::operator==(const EventListener& listener)
{
if (listener.type() != GeolocationEventListenerType)