Bug 850442 - Part 3 - Convert callbacks, Geolocation and Position. r=bz

This commit is contained in:
Guilherme Gonçalves 2013-04-12 11:46:36 -07:00 committed by John Schoenick
parent 13bec84c07
commit bc55011071
16 changed files with 376 additions and 179 deletions

View File

@ -31,10 +31,15 @@
class nsPluginArray;
class nsMimeTypeArray;
class nsGeolocation;
class nsPIDOMWindow;
class nsIDOMMozConnection;
namespace mozilla {
namespace dom {
class nsGeolocation;
}
}
#ifdef MOZ_MEDIA_NAVIGATOR
#include "nsIDOMNavigatorUserMedia.h"
#endif

View File

@ -348,6 +348,11 @@ DOMInterfaces = {
'workers': True,
},
'Geolocation': {
'nativeType': 'mozilla::dom::nsGeolocation',
'headerFile': 'nsGeolocation.h'
},
'UndoManager': [
{
'implicitJSContext' : [ 'undo', 'redo', 'transact' ]

View File

@ -12,7 +12,6 @@ XPIDL_SOURCES += [
'nsIDOMGeoPositionError.idl',
'nsIDOMGeoPositionErrorCallback.idl',
'nsIDOMNavigatorGeolocation.idl',
'nsIGeolocation.idl',
]
XPIDL_MODULE = 'dom_geolocation'

View File

@ -4,11 +4,13 @@
#include "domstubs.idl"
interface nsIDOMGeoPosition;
interface nsIDOMGeoPositionOptions;
interface nsIDOMGeoPositionCallback;
interface nsIDOMGeoPositionErrorCallback;
%{C++
#include "DictionaryHelpers.h"
%}
dictionary GeoPositionOptions
{
boolean enableHighAccuracy;
@ -16,20 +18,16 @@ dictionary GeoPositionOptions
long maximumAge;
};
[scriptable, uuid(b9a301f7-285b-4be9-b739-fb869019c77a)]
[ptr] native NamespacedGeoPositionOptions(mozilla::idl::GeoPositionOptions);
[scriptable, builtinclass, uuid(1bc7d103-c7ae-4467-881c-21a8dfa17938)]
interface nsIDOMGeoGeolocation : nsISupports
{
[implicit_jscontext]
void getCurrentPosition(in nsIDOMGeoPositionCallback successCallback,
[optional] in nsIDOMGeoPositionErrorCallback errorCallback,
/* GeoPositionOptions */
[optional] in jsval options);
[implicit_jscontext]
long watchPosition(in nsIDOMGeoPositionCallback successCallback,
[optional] in nsIDOMGeoPositionErrorCallback errorCallback,
/* GeoPositionOptions */
[optional] in jsval options);
int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
in nsIDOMGeoPositionErrorCallback errorCallback,
in NamespacedGeoPositionOptions options);
void getCurrentPosition(in nsIDOMGeoPositionCallback callback,
in nsIDOMGeoPositionErrorCallback errorCallback,
in NamespacedGeoPositionOptions options);
void clearWatch(in long watchId);
};

View File

@ -1,29 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "domstubs.idl"
interface nsIDOMGeoPositionCallback;
interface nsIDOMGeoPositionErrorCallback;
[ptr] native GeoPositionOptions(mozilla::idl::GeoPositionOptions);
%{C++
namespace mozilla {
namespace idl {
class GeoPositionOptions;
}
}
%}
[scriptable, builtinclass, uuid(d8e6449f-92c8-4c6a-aa9f-fef70157ec29)]
interface nsIGeolocation : nsISupports
{
// Versions of the DOM APIs that don't require JS option values
int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
in nsIDOMGeoPositionErrorCallback errorCallback,
in GeoPositionOptions options);
void getCurrentPosition(in nsIDOMGeoPositionCallback callback,
in nsIDOMGeoPositionErrorCallback errorCallback,
in GeoPositionOptions options);
};

View File

@ -84,7 +84,6 @@
#include "StructuredCloneUtils.h"
#include "TabParent.h"
#include "URIUtils.h"
#include "nsGeolocation.h"
#ifdef ANDROID
# include "gfxAndroidPlatform.h"
@ -2370,7 +2369,7 @@ ContentParent::RecvFilePathUpdateNotify(const nsString& aType, const nsString& a
static int32_t
AddGeolocationListener(nsIDOMGeoPositionCallback* watcher, bool highAccuracy)
{
nsCOMPtr<nsIGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
if (!geo) {
return -1;
}

View File

@ -97,6 +97,8 @@ public:
uint64_t Timestamp() const;
nsIDOMGeoPosition* GetWrappedGeoPosition() { return mGeoPosition; }
private:
nsRefPtr<Coordinates> mCoordinates;
nsCOMPtr<nsISupports> mParent;

View File

@ -46,6 +46,7 @@
#include <math.h>
#include <algorithm>
#include <limits>
#ifdef MOZ_MAEMO_LIBLOCATION
#include "MaemoLocationProvider.h"
@ -77,6 +78,19 @@ using mozilla::unused; // <snicker>
using namespace mozilla;
using namespace mozilla::dom;
static mozilla::idl::GeoPositionOptions*
GeoPositionOptionsFromPositionOptions(const PositionOptions& aOptions)
{
nsAutoPtr<mozilla::idl::GeoPositionOptions> geoOptions(
new mozilla::idl::GeoPositionOptions());
geoOptions->enableHighAccuracy = aOptions.mEnableHighAccuracy;
geoOptions->maximumAge = aOptions.mMaximumAge;
geoOptions->timeout = aOptions.mTimeout;
return geoOptions.forget();
}
class GeolocationSettingsCallback : public nsISettingsServiceCallback
{
public:
@ -174,16 +188,18 @@ public:
// event should remove the request from it. If we ever
// have to do more, then we can change this around.
RequestSendLocationEvent(nsIDOMGeoPosition* aPosition,
bool aCachePosition,
nsGeolocationRequest* aRequest,
nsGeolocation* aLocator)
: mPosition(aPosition),
mCachePosition(aCachePosition),
mRequest(aRequest),
mLocator(aLocator)
{
}
NS_IMETHOD Run() {
mRequest->SendLocation(mPosition);
mRequest->SendLocation(mPosition, mCachePosition);
if (mLocator) {
mLocator->RemoveRequest(mRequest);
}
@ -191,7 +207,8 @@ public:
}
private:
nsCOMPtr<nsIDOMGeoPosition> mPosition;
nsCOMPtr<nsIDOMGeoPosition> mPosition;
bool mCachePosition;
nsRefPtr<nsGeolocationRequest> mRequest;
nsRefPtr<nsGeolocation> mLocator;
@ -262,12 +279,8 @@ PositionError::WrapObject(JSContext* aCx, JSObject* aScope)
}
void
PositionError::NotifyCallback(nsIDOMGeoPositionErrorCallback* aCallback)
PositionError::NotifyCallback(const GeoPositionErrorCallback& aCallback)
{
if (!aCallback) {
return;
}
// Ensure that the proper context is on the stack (bug 452762)
nsCOMPtr<nsIJSContextStack> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
if (!stack || NS_FAILED(stack->Push(nullptr))) {
@ -275,7 +288,19 @@ PositionError::NotifyCallback(nsIDOMGeoPositionErrorCallback* aCallback)
}
nsAutoMicroTask mt;
aCallback->HandleEvent(this);
if (aCallback.HasWebIDLCallback()) {
PositionErrorCallback* callback = aCallback.GetWebIDLCallback();
if (callback) {
ErrorResult err;
callback->Call(*this, err);
}
} else {
nsIDOMGeoPositionErrorCallback* callback = aCallback.GetXPCOMCallback();
if (callback) {
callback->HandleEvent(this);
}
}
// remove the stack
JSContext* cx;
@ -286,8 +311,8 @@ PositionError::NotifyCallback(nsIDOMGeoPositionErrorCallback* aCallback)
////////////////////////////////////////////////////
nsGeolocationRequest::nsGeolocationRequest(nsGeolocation* aLocator,
nsIDOMGeoPositionCallback* aCallback,
nsIDOMGeoPositionErrorCallback* aErrorCallback,
const GeoPositionCallback& aCallback,
const GeoPositionErrorCallback& aErrorCallback,
mozilla::idl::GeoPositionOptions* aOptions,
bool aWatchPositionRequest,
int32_t aWatchId)
@ -307,23 +332,6 @@ nsGeolocationRequest::~nsGeolocationRequest()
{
}
static mozilla::idl::GeoPositionOptions*
OptionsFromJSOptions(JSContext* aCx, const JS::Value& aOptions, nsresult* aRv)
{
*aRv = NS_OK;
nsAutoPtr<mozilla::idl::GeoPositionOptions> options(nullptr);
if (aCx && !JSVAL_IS_VOID(aOptions) && !JSVAL_IS_NULL(aOptions)) {
options = new mozilla::idl::GeoPositionOptions();
nsresult rv = options->Init(aCx, &aOptions);
if (NS_FAILED(rv)) {
*aRv = rv;
return nullptr;
}
}
return options.forget();
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocationRequest)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
@ -472,9 +480,10 @@ nsGeolocationRequest::Allow()
// okay, we can return a cached position
mAllowed = true;
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(lastPosition,
this,
mIsWatchPositionRequest ? nullptr : mLocator);
nsCOMPtr<nsIRunnable> ev =
new RequestSendLocationEvent(
lastPosition, true, this, mIsWatchPositionRequest ? nullptr : mLocator);
NS_DispatchToMainThread(ev);
}
@ -517,7 +526,7 @@ nsGeolocationRequest::MarkCleared()
}
void
nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition, bool aCachePosition)
{
if (mCleared || !mAllowed) {
return;
@ -528,17 +537,24 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
mTimeoutTimer = nullptr;
}
// we should not pass null back to the DOM.
if (!aPosition) {
nsRefPtr<Position> wrapped, cachedWrapper = mLocator->GetCachedPosition();
if (cachedWrapper && aPosition == cachedWrapper->GetWrappedGeoPosition()) {
wrapped = cachedWrapper;
} else if (aPosition) {
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
aPosition->GetCoords(getter_AddRefs(coords));
if (coords) {
wrapped = new Position(mLocator, aPosition);
}
}
if (!wrapped) {
NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
return;
}
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
aPosition->GetCoords(getter_AddRefs(coords));
if (!coords) {
NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
return;
if (aCachePosition) {
mLocator->SetCachedPosition(wrapped);
}
// Ensure that the proper context is on the stack (bug 452762)
@ -548,7 +564,18 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
}
nsAutoMicroTask mt;
mCallback->HandleEvent(aPosition);
if (mCallback.HasWebIDLCallback()) {
ErrorResult err;
PositionCallback* callback = mCallback.GetWebIDLCallback();
MOZ_ASSERT(callback);
callback->Call(*wrapped, err);
} else {
nsIDOMGeoPositionCallback* callback = mCallback.GetXPCOMCallback();
MOZ_ASSERT(callback);
callback->HandleEvent(aPosition);
}
// remove the stack
JSContext* cx;
@ -585,8 +612,9 @@ nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition, bool aIsBetter)
if (mIsFirstUpdate || aIsBetter) {
mIsFirstUpdate = false;
ev = new RequestSendLocationEvent(aPosition,
aIsBetter,
this,
mIsWatchPositionRequest ? nullptr : mLocator);
mIsWatchPositionRequest ? nullptr : mLocator);
} else {
ev = new RequestRestartTimerEvent(this);
}
@ -602,8 +630,6 @@ nsGeolocationRequest::Shutdown()
mTimeoutTimer = nullptr;
}
mCleared = true;
mCallback = nullptr;
mErrorCallback = nullptr;
// This should happen last, to ensure that this request isn't taken into consideration
// when deciding whether existing requests still require high accuracy.
@ -1129,9 +1155,9 @@ nsGeolocationService::RemoveLocator(nsGeolocation* aLocator)
DOMCI_DATA(GeoGeolocation, nsGeolocation)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocation)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoGeolocation)
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoGeolocation)
NS_INTERFACE_MAP_ENTRY(nsIGeolocation)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(GeoGeolocation)
NS_INTERFACE_MAP_END
@ -1139,22 +1165,28 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeolocation)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocation)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGeolocation)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedPosition)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
tmp->mPendingRequests.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingCallbacks)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWatchingCallbacks)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGeolocation)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedPosition)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
for (uint32_t i = 0; i < tmp->mPendingRequests.Length(); ++i)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingRequests[i].request)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingCallbacks)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWatchingCallbacks)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsGeolocation)
nsGeolocation::nsGeolocation()
: mLastWatchId(0)
{
SetIsDOMBinding();
}
nsGeolocation::~nsGeolocation()
@ -1220,6 +1252,12 @@ nsGeolocation::Shutdown()
mPrincipal = nullptr;
}
nsIDOMWindow*
nsGeolocation::GetParentObject() const {
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mOwner);
return window.get();
}
bool
nsGeolocation::HasActiveCallbacks()
{
@ -1285,26 +1323,56 @@ nsGeolocation::Update(nsIDOMGeoPosition *aSomewhere, bool aIsBetter)
}
}
NS_IMETHODIMP
nsGeolocation::GetCurrentPosition(nsIDOMGeoPositionCallback *callback,
nsIDOMGeoPositionErrorCallback *errorCallback,
const JS::Value& jsoptions,
JSContext* cx)
void
nsGeolocation::SetCachedPosition(Position* aPosition)
{
nsresult rv;
nsAutoPtr<mozilla::idl::GeoPositionOptions> options(
OptionsFromJSOptions(cx, jsoptions, &rv));
NS_ENSURE_SUCCESS(rv, rv);
return GetCurrentPosition(callback, errorCallback, options.forget());
mCachedPosition = aPosition;
}
Position*
nsGeolocation::GetCachedPosition()
{
return mCachedPosition;
}
void
nsGeolocation::GetCurrentPosition(PositionCallback& aCallback,
PositionErrorCallback* aErrorCallback,
const PositionOptions& aOptions,
ErrorResult& aRv)
{
GeoPositionCallback successCallback(&aCallback);
GeoPositionErrorCallback errorCallback(aErrorCallback);
nsresult rv =
GetCurrentPosition(successCallback, errorCallback,
GeoPositionOptionsFromPositionOptions(aOptions));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
return;
}
NS_IMETHODIMP
nsGeolocation::GetCurrentPosition(nsIDOMGeoPositionCallback *callback,
nsIDOMGeoPositionErrorCallback *errorCallback,
nsGeolocation::GetCurrentPosition(nsIDOMGeoPositionCallback* aCallback,
nsIDOMGeoPositionErrorCallback* aErrorCallback,
mozilla::idl::GeoPositionOptions* aOptions)
{
NS_ENSURE_ARG_POINTER(aCallback);
GeoPositionCallback successCallback(aCallback);
GeoPositionErrorCallback errorCallback(aErrorCallback);
return GetCurrentPosition(successCallback, errorCallback, aOptions);
}
nsresult
nsGeolocation::GetCurrentPosition(GeoPositionCallback& callback,
GeoPositionErrorCallback& errorCallback,
mozilla::idl::GeoPositionOptions *options)
{
NS_ENSURE_ARG_POINTER(callback);
if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
return NS_ERROR_NOT_AVAILABLE;
}
@ -1357,41 +1425,60 @@ nsGeolocation::GetCurrentPositionReady(nsGeolocationRequest* aRequest)
return NS_OK;
}
NS_IMETHODIMP
nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *callback,
nsIDOMGeoPositionErrorCallback *errorCallback,
const JS::Value& jsoptions,
JSContext* cx,
int32_t *_retval)
int32_t
nsGeolocation::WatchPosition(PositionCallback& aCallback,
PositionErrorCallback* aErrorCallback,
const PositionOptions& aOptions,
ErrorResult& aRv)
{
nsresult rv;
nsAutoPtr<mozilla::idl::GeoPositionOptions> options(
OptionsFromJSOptions(cx, jsoptions, &rv));
NS_ENSURE_SUCCESS(rv, rv);
return WatchPosition(callback, errorCallback, options.forget(), _retval);
int32_t ret;
GeoPositionCallback successCallback(&aCallback);
GeoPositionErrorCallback errorCallback(aErrorCallback);
nsresult rv =
WatchPosition(successCallback, errorCallback,
GeoPositionOptionsFromPositionOptions(aOptions), &ret);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
return ret;
}
NS_IMETHODIMP
nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *callback,
nsIDOMGeoPositionErrorCallback *errorCallback,
mozilla::idl::GeoPositionOptions *options,
int32_t *_retval)
nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
nsIDOMGeoPositionErrorCallback *aErrorCallback,
mozilla::idl::GeoPositionOptions *aOptions,
int32_t* aRv)
{
NS_ENSURE_ARG_POINTER(callback);
NS_ENSURE_ARG_POINTER(aCallback);
GeoPositionCallback successCallback(aCallback);
GeoPositionErrorCallback errorCallback(aErrorCallback);
return WatchPosition(successCallback, errorCallback, aOptions, aRv);
}
nsresult
nsGeolocation::WatchPosition(GeoPositionCallback& aCallback,
GeoPositionErrorCallback& aErrorCallback,
mozilla::idl::GeoPositionOptions* aOptions,
int32_t* aRv)
{
if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
return NS_ERROR_NOT_AVAILABLE;
}
// The watch ID:
*_retval = mLastWatchId++;
*aRv = mLastWatchId++;
nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this,
callback,
errorCallback,
options,
aCallback,
aErrorCallback,
aOptions,
true,
*_retval);
*aRv);
if (!sGeoEnabled) {
nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
@ -1540,3 +1627,9 @@ nsGeolocation::RegisterRequestWithPrompt(nsGeolocationRequest* request)
NS_DispatchToMainThread(ev);
return true;
}
JSObject*
nsGeolocation::WrapObject(JSContext *aCtx, JSObject *aScope)
{
return mozilla::dom::GeolocationBinding::Wrap(aCtx, aScope, this);
}

View File

@ -21,14 +21,16 @@
#include "nsWeakPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsGeoPosition.h"
#include "nsIDOMGeoGeolocation.h"
#include "nsIDOMGeoPosition.h"
#include "nsIDOMGeoPositionError.h"
#include "nsIDOMGeoPositionCallback.h"
#include "nsIDOMGeoPositionErrorCallback.h"
#include "nsIDOMNavigatorGeolocation.h"
#include "nsIGeolocation.h"
#include "mozilla/dom/GeolocationBinding.h"
#include "mozilla/dom/PositionErrorBinding.h"
#include "mozilla/dom/CallbackObject.h"
#include "nsPIDOMWindow.h"
@ -39,7 +41,14 @@
#include "mozilla/Attributes.h"
class nsGeolocationService;
namespace mozilla {
namespace dom {
class nsGeolocation;
typedef CallbackObjectHolder<PositionCallback, nsIDOMGeoPositionCallback> GeoPositionCallback;
typedef CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallback> GeoPositionErrorCallback;
}
}
class nsGeolocationRequest
: public nsIContentPermissionRequest
@ -53,9 +62,9 @@ class nsGeolocationRequest
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
nsGeolocationRequest(nsGeolocation* locator,
nsIDOMGeoPositionCallback* callback,
nsIDOMGeoPositionErrorCallback* errorCallback,
nsGeolocationRequest(mozilla::dom::nsGeolocation* locator,
const mozilla::dom::GeoPositionCallback& callback,
const mozilla::dom::GeoPositionErrorCallback& errorCallback,
mozilla::idl::GeoPositionOptions* aOptions,
bool watchPositionRequest = false,
int32_t watchId = 0);
@ -65,7 +74,7 @@ class nsGeolocationRequest
// isBetter: the accuracy is as good or better than the previous position.
bool Update(nsIDOMGeoPosition* aPosition, bool aIsBetter);
void SendLocation(nsIDOMGeoPosition* location);
void SendLocation(nsIDOMGeoPosition* location, bool aCachePosition);
void MarkCleared();
bool WantsHighAccuracy() {return mOptions && mOptions->enableHighAccuracy;}
bool IsActive() {return !mCleared;}
@ -88,11 +97,11 @@ class nsGeolocationRequest
bool mIsWatchPositionRequest;
nsCOMPtr<nsITimer> mTimeoutTimer;
nsCOMPtr<nsIDOMGeoPositionCallback> mCallback;
nsCOMPtr<nsIDOMGeoPositionErrorCallback> mErrorCallback;
mozilla::dom::GeoPositionCallback mCallback;
mozilla::dom::GeoPositionErrorCallback mErrorCallback;
nsAutoPtr<mozilla::idl::GeoPositionOptions> mOptions;
nsRefPtr<nsGeolocation> mLocator;
nsRefPtr<mozilla::dom::nsGeolocation> mLocator;
int32_t mWatchId;
};
@ -121,8 +130,8 @@ public:
void HandleMozsettingValue(const bool aValue);
// Management of the nsGeolocation objects
void AddLocator(nsGeolocation* locator);
void RemoveLocator(nsGeolocation* locator);
void AddLocator(mozilla::dom::nsGeolocation* locator);
void RemoveLocator(mozilla::dom::nsGeolocation* locator);
void SetCachedPosition(nsIDOMGeoPosition* aPosition);
nsIDOMGeoPosition* GetCachedPosition();
@ -156,7 +165,7 @@ private:
// mGeolocators are not owned here. Their constructor
// adds them to this list, and their destructor removes
// them from this list.
nsTArray<nsGeolocation*> mGeolocators;
nsTArray<mozilla::dom::nsGeolocation*> mGeolocators;
// This is the last geo position that we have seen.
nsCOMPtr<nsIDOMGeoPosition> mLastPosition;
@ -165,28 +174,38 @@ private:
bool mHigherAccuracy;
};
namespace mozilla {
namespace dom {
/**
* Can return a geolocation info
*/
class nsGeolocation MOZ_FINAL : public nsIDOMGeoGeolocation,
public nsIGeolocation
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIDOMGEOGEOLOCATION
NS_DECL_NSIGEOLOCATION
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsGeolocation)
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocation, nsIDOMGeoGeolocation)
NS_DECL_NSIDOMGEOGEOLOCATION
nsGeolocation();
nsresult Init(nsIDOMWindow* contentDom=nullptr);
nsIDOMWindow* GetParentObject() const;
virtual JSObject* WrapObject(JSContext *aCtx, JSObject *aScope) MOZ_OVERRIDE;
int32_t WatchPosition(PositionCallback& aCallback, PositionErrorCallback* aErrorCallback, const PositionOptions& aOptions, ErrorResult& aRv);
void GetCurrentPosition(PositionCallback& aCallback, PositionErrorCallback* aErrorCallback, const PositionOptions& aOptions, ErrorResult& aRv);
// Called by the geolocation device to notify that a location has changed.
void Update(nsIDOMGeoPosition* aPosition, bool aIsBetter);
void SetCachedPosition(Position* aPosition);
Position* GetCachedPosition();
// Returns true if any of the callbacks are repeating
bool HasActiveCallbacks();
@ -215,6 +234,9 @@ private:
~nsGeolocation();
nsresult GetCurrentPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, mozilla::idl::GeoPositionOptions* aOptions);
nsresult WatchPosition(GeoPositionCallback& aCallback, GeoPositionErrorCallback& aErrorCallback, mozilla::idl::GeoPositionOptions* aOptions, int32_t* aRv);
bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
// Methods for the service when it's ready to process requests:
@ -238,6 +260,9 @@ private:
// owning back pointer.
nsRefPtr<nsGeolocationService> mService;
// cached Position wrapper
nsRefPtr<Position> mCachedPosition;
// Watch ID
uint32_t mLastWatchId;
@ -255,9 +280,6 @@ private:
nsTArray<PendingRequest> mPendingRequests;
};
namespace mozilla {
namespace dom {
class PositionError MOZ_FINAL : public nsIDOMGeoPositionError,
public nsWrapperCache
{
@ -281,7 +303,7 @@ public:
aRetVal.Truncate();
}
void NotifyCallback(nsIDOMGeoPositionErrorCallback* callback);
void NotifyCallback(const GeoPositionErrorCallback& callback);
private:
~PositionError();
int16_t mCode;

View File

@ -13,6 +13,7 @@ include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES = \
test_allowCurrent.html \
test_allowWatch.html \
test_cachedPosition.html \
test_cancelCurrent.html \
test_cancelWatch.html \
test_clearWatch.html \

View File

@ -0,0 +1,81 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=850442
-->
<head>
<title>Test for getCurrentPosition </title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="geolocation_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=850442">Mozilla Bug 850442</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
resume_geolocationProvider();
force_prompt(true);
function done() {
reset_prompt();
resume_geolocationProvider();
SimpleTest.finish();
}
function errorCallback(err) {
ok(false, "error callback should not have been called");
done();
}
function testCachedPosition() {
var cached = null;
navigator.geolocation.getCurrentPosition(function(pos) {
// get cached position
cached = pos;
navigator.geolocation.getCurrentPosition(function(pos) {
// force use of cached position, make sure
// it's equal to what we have
is(pos, cached, "position should be equal to cached position");
resume_geolocationProvider();
navigator.geolocation.getCurrentPosition(function(pos) {
// force new position, can't be the one we have
isnot(pos, cached, "new position should be different from the cached");
done();
}, errorCallback, {maximumAge: 0});
}, errorCallback, {maximumAge: 21600000});
}, errorCallback, {maximumAge: 21600000});
}
// ensure we have a position in cache,
// and stop receiving new positions once we do so the
// cache doesn't change
var watchID;
watchID = navigator.geolocation.watchPosition(
function(pos) {
info("Stopping geolocation provider");
stop_geolocationProvider();
}, function(err) {
is(err.code, err.TIMEOUT, "got TIMEOUT for watchPosition");
// no new positions in a while,
// the cache should be stable now.
navigator.geolocation.clearWatch(watchID);
testCachedPosition();
}, {maximumAge: 0, timeout: 1000}
);
</script>
</pre>
</body>
</html>

View File

@ -24,87 +24,69 @@ force_prompt(true)
/** Test for Bug 452566 **/
const NOT_ENOUGH_ARGS = 2153185281;
ok(navigator.geolocation, "Should have geolocation");
var exception = null;
try {
navigator.geolocation.getCurrentPosition();
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(exception, "Should have got an exception");
exception = null;
try {
navigator.geolocation.getCurrentPosition(function() {});
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(!exception, exception);
exception = null;
try {
navigator.geolocation.getCurrentPosition(function() {}, function() {});
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(!exception, exception);
exception = null;
try {
navigator.geolocation.getCurrentPosition(function() {}, function() {}, {});
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(!exception, exception);
exception = null;
try {
navigator.geolocation.watchPosition();
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(exception, "Should have got an exception");
exception = null;
try {
navigator.geolocation.watchPosition(function() {});
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(!exception, exception);
exception = null;
try {
navigator.geolocation.watchPosition(function() {}, function() {});
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(!exception, exception);
exception = null;
try {
navigator.geolocation.watchPosition(function() {}, function() {}, {});
} catch(ex) {
if (ex.result == NOT_ENOUGH_ARGS) {
exception = ex;
}
} catch(ex if ex instanceof TypeError) {
exception = ex;
}
ok(!exception, exception);

View File

@ -0,0 +1,36 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.w3.org/TR/geolocation-API
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
dictionary PositionOptions {
boolean enableHighAccuracy = false;
long timeout = 0x7fffffff;
long maximumAge = 30000; /* non-conformant, should be 0 */
};
[NoInterfaceObject]
interface Geolocation {
[Throws]
void getCurrentPosition(PositionCallback successCallback,
optional PositionErrorCallback? errorCallback = null,
optional PositionOptions options);
[Throws]
long watchPosition(PositionCallback successCallback,
optional PositionErrorCallback? errorCallback = null,
optional PositionOptions options);
void clearWatch(long watchId);
};
callback PositionCallback = void (Position position);
callback PositionErrorCallback = void (PositionError positionError);

View File

@ -72,6 +72,7 @@ webidl_files = \
FormData.webidl \
Function.webidl \
GainNode.webidl \
Geolocation.webidl \
HTMLAnchorElement.webidl \
HTMLAppletElement.webidl \
HTMLAreaElement.webidl \

View File

@ -196,6 +196,7 @@
"dom/tests/mochitest/general/test_windowProperties.html": "",
"dom/tests/mochitest/geolocation/test_allowCurrent.html": "TIMED_OUT",
"dom/tests/mochitest/geolocation/test_allowWatch.html": "TIMED_OUT",
"dom/tests/mochitest/geolocation/test_cachedPosition.html": "TIMED_OUT",
"dom/tests/mochitest/geolocation/test_clearWatch.html": "TIMED_OUT",
"dom/tests/mochitest/geolocation/test_manyCurrentConcurrent.html": "TIMED_OUT",
"dom/tests/mochitest/geolocation/test_manyCurrentSerial.html": "TIMED_OUT",

View File

@ -379,6 +379,7 @@
"dom/tests/mochitest/general/test_interfaces.html":"",
"dom/tests/mochitest/geolocation/test_allowCurrent.html":"",
"dom/tests/mochitest/geolocation/test_allowWatch.html":"",
"dom/tests/mochitest/geolocation/test_cachedPosition.html":"",
"dom/tests/mochitest/geolocation/test_cancelCurrent.html":"",
"dom/tests/mochitest/geolocation/test_cancelWatch.html":"",
"dom/tests/mochitest/geolocation/test_clearWatch.html":"",