Bug 874996 - Part 2 - Issue error events for geolocation provider errors. r=jdm

This commit is contained in:
Guilherme Gonçalves 2013-06-19 12:08:11 -07:00 committed by John Schoenick
parent 284ad48824
commit dc92302bb2
3 changed files with 85 additions and 33 deletions

View File

@ -313,6 +313,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocationRequest)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest)
NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest)
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeolocationRequest)
@ -320,21 +321,6 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest)
NS_IMPL_CYCLE_COLLECTION_3(nsGeolocationRequest, mCallback, mErrorCallback, mLocator)
void
nsGeolocationRequest::NotifyError(int16_t errorCode)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<PositionError> positionError = new PositionError(mLocator, errorCode);
if (!positionError) {
return;
}
positionError->NotifyCallback(mErrorCallback);
}
NS_IMETHODIMP
nsGeolocationRequest::Notify(nsITimer* aTimer)
{
@ -501,7 +487,7 @@ nsGeolocationRequest::SendLocation(nsIDOMGeoPosition* aPosition)
nsCOMPtr<nsIDOMGeoPositionCoords> coords;
aPosition->GetCoords(getter_AddRefs(coords));
if (coords) {
wrapped = new Position(mLocator, aPosition);
wrapped = new Position(ToSupports(mLocator), aPosition);
}
}
@ -545,11 +531,22 @@ nsGeolocationRequest::GetPrincipal()
return mLocator->GetPrincipal();
}
void
NS_IMETHODIMP
nsGeolocationRequest::Update(nsIDOMGeoPosition* aPosition)
{
nsCOMPtr<nsIRunnable> ev = new RequestSendLocationEvent(aPosition, this);
NS_DispatchToMainThread(ev);
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationRequest::NotifyError(uint16_t aErrorCode)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<PositionError> positionError = new PositionError(mLocator, aErrorCode);
positionError->NotifyCallback(mErrorCallback);
return NS_OK;
}
void
@ -777,6 +774,15 @@ nsGeolocationService::Update(nsIDOMGeoPosition *aSomewhere)
return NS_OK;
}
NS_IMETHODIMP
nsGeolocationService::NotifyError(uint16_t aErrorCode)
{
for (uint32_t i = 0; i < mGeolocators.Length(); i++) {
mGeolocators[i]->NotifyError(aErrorCode);
}
return NS_OK;
}
void
nsGeolocationService::SetCachedPosition(nsIDOMGeoPosition* aPosition)
@ -819,8 +825,15 @@ nsGeolocationService::StartDevice(nsIPrincipal *aPrincipal, bool aRequestPrivate
return NS_ERROR_FAILURE;
}
mProvider->Startup();
mProvider->Watch(this, aRequestPrivate);
nsresult rv;
if (NS_FAILED(rv = mProvider->Startup()) ||
NS_FAILED(rv = mProvider->Watch(this, aRequestPrivate))) {
NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE);
return rv;
}
obs->NotifyObservers(mProvider,
"geolocation-device-events",
NS_LITERAL_STRING("starting").get());
@ -946,6 +959,7 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Geolocation)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoGeolocation)
NS_INTERFACE_MAP_ENTRY(nsIDOMGeoGeolocation)
NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(Geolocation)
@ -1076,11 +1090,12 @@ Geolocation::RemoveRequest(nsGeolocationRequest* aRequest)
unused << requestWasKnown;
}
void
NS_IMETHODIMP
Geolocation::Update(nsIDOMGeoPosition *aSomewhere)
{
if (!WindowOwnerStillExists()) {
return Shutdown();
Shutdown();
return NS_OK;
}
for (uint32_t i = mPendingCallbacks.Length(); i > 0; i--) {
@ -1089,9 +1104,32 @@ Geolocation::Update(nsIDOMGeoPosition *aSomewhere)
}
// notify everyone that is watching
for (uint32_t i = 0; i< mWatchingCallbacks.Length(); i++) {
for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) {
mWatchingCallbacks[i]->Update(aSomewhere);
}
return NS_OK;
}
NS_IMETHODIMP
Geolocation::NotifyError(uint16_t aErrorCode)
{
if (!WindowOwnerStillExists()) {
Shutdown();
return NS_OK;
}
for (uint32_t i = mPendingCallbacks.Length(); i > 0; i--) {
mPendingCallbacks[i-1]->NotifyError(aErrorCode);
RemoveRequest(mPendingCallbacks[i-1]);
}
// notify everyone that is watching
for (uint32_t i = 0; i < mWatchingCallbacks.Length(); i++) {
mWatchingCallbacks[i]->NotifyError(aErrorCode);
}
return NS_OK;
}
void

View File

@ -54,12 +54,14 @@ typedef CallbackObjectHolder<PositionErrorCallback, nsIDOMGeoPositionErrorCallba
class nsGeolocationRequest
: public nsIContentPermissionRequest
, public nsITimerCallback
, public nsIGeolocationUpdate
, public PCOMContentPermissionRequestChild
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSICONTENTPERMISSIONREQUEST
NS_DECL_NSITIMERCALLBACK
NS_DECL_NSIGEOLOCATIONUPDATE
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
@ -71,9 +73,6 @@ class nsGeolocationRequest
int32_t watchId = 0);
void Shutdown();
// Called by the geolocation device to notify that a location has changed.
void Update(nsIDOMGeoPosition* aPosition);
void SendLocation(nsIDOMGeoPosition* location);
bool WantsHighAccuracy() {return mOptions && mOptions->enableHighAccuracy;}
void SetTimeoutTimer();
@ -87,8 +86,6 @@ class nsGeolocationRequest
bool IsWatch() { return mIsWatchPositionRequest; }
int32_t WatchId() { return mWatchId; }
private:
void NotifyError(int16_t errorCode);
bool mIsWatchPositionRequest;
nsCOMPtr<nsITimer> mTimeoutTimer;
@ -176,13 +173,15 @@ namespace dom {
* Can return a geolocation info
*/
class Geolocation MOZ_FINAL : public nsIDOMGeoGeolocation,
public nsWrapperCache
public nsIGeolocationUpdate,
public nsWrapperCache
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Geolocation)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Geolocation, nsIDOMGeoGeolocation)
NS_DECL_NSIGEOLOCATIONUPDATE
NS_DECL_NSIDOMGEOGEOLOCATION
Geolocation();
@ -196,9 +195,6 @@ public:
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);
void SetCachedPosition(Position* aPosition);
Position* GetCachedPosition();
@ -312,6 +308,12 @@ private:
};
}
inline nsISupports*
ToSupports(dom::Geolocation* aGeolocation)
{
return ToSupports(static_cast<nsIDOMGeoGeolocation*>(aGeolocation));
}
}
#endif /* nsGeoLocation_h */

View File

@ -17,7 +17,7 @@ interface nsIGeolocationPrompt;
* Interface provides a way for a geolocation provider to
* notify the system that a new location is available.
*/
[scriptable, uuid(B89D7227-9F04-4236-A582-25A3F2779D72)]
[scriptable, uuid(f00ff730-acff-4e8c-9991-0d4c84ba0e10)]
interface nsIGeolocationUpdate : nsISupports {
/**
@ -26,6 +26,18 @@ interface nsIGeolocationUpdate : nsISupports {
* This must be called on the main thread
*/
void update(in nsIDOMGeoPosition position);
/**
* Notify the geolocation service of an error.
* This must be called on the main thread.
* The parameter refers to one of the constants in the
* nsIDOMGeoPositionError interface.
* Use this to report spurious errors coming from the
* provider; for errors occurring inside the methods in
* the nsIGeolocationProvider interface, just use the return
* value.
*/
void notifyError(in unsigned short error);
};