mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 850442 - Part 3 - Convert callbacks, Geolocation and Position. r=bz
This commit is contained in:
parent
13bec84c07
commit
bc55011071
@ -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
|
||||
|
@ -348,6 +348,11 @@ DOMInterfaces = {
|
||||
'workers': True,
|
||||
},
|
||||
|
||||
'Geolocation': {
|
||||
'nativeType': 'mozilla::dom::nsGeolocation',
|
||||
'headerFile': 'nsGeolocation.h'
|
||||
},
|
||||
|
||||
'UndoManager': [
|
||||
{
|
||||
'implicitJSContext' : [ 'undo', 'redo', 'transact' ]
|
||||
|
@ -12,7 +12,6 @@ XPIDL_SOURCES += [
|
||||
'nsIDOMGeoPositionError.idl',
|
||||
'nsIDOMGeoPositionErrorCallback.idl',
|
||||
'nsIDOMNavigatorGeolocation.idl',
|
||||
'nsIGeolocation.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'dom_geolocation'
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
};
|
@ -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;
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ public:
|
||||
|
||||
uint64_t Timestamp() const;
|
||||
|
||||
nsIDOMGeoPosition* GetWrappedGeoPosition() { return mGeoPosition; }
|
||||
|
||||
private:
|
||||
nsRefPtr<Coordinates> mCoordinates;
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 \
|
||||
|
81
dom/tests/mochitest/geolocation/test_cachedPosition.html
Normal file
81
dom/tests/mochitest/geolocation/test_cachedPosition.html
Normal 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>
|
||||
|
@ -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);
|
||||
|
||||
|
36
dom/webidl/Geolocation.webidl
Normal file
36
dom/webidl/Geolocation.webidl
Normal 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);
|
@ -72,6 +72,7 @@ webidl_files = \
|
||||
FormData.webidl \
|
||||
Function.webidl \
|
||||
GainNode.webidl \
|
||||
Geolocation.webidl \
|
||||
HTMLAnchorElement.webidl \
|
||||
HTMLAppletElement.webidl \
|
||||
HTMLAreaElement.webidl \
|
||||
|
@ -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",
|
||||
|
@ -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":"",
|
||||
|
Loading…
Reference in New Issue
Block a user