Bug 731875 - Geolocation doorhanger might cause a zombie compartment, GeoPositionOptions part, r=dougt
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 16 Apr 2012 22:08:48 +0300
changeset 91754 686e5bcf747ba2fc7b5e4babb791114ac734c5e3
parent 91753 14084207e9d112e399e553d16cf4aa21ff2c1e91
child 91755 b56db6eab47c0192cfc80b3baf328e494c394354
push id22474
push useropettay@mozilla.com
push dateMon, 16 Apr 2012 19:23:30 +0000
treeherdermozilla-central@686e5bcf747b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdougt
bugs731875
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 731875 - Geolocation doorhanger might cause a zombie compartment, GeoPositionOptions part, r=dougt
dom/interfaces/geolocation/Makefile.in
dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
dom/interfaces/geolocation/nsIDOMGeoPositionOptions.idl
dom/ipc/ContentParent.cpp
dom/src/geolocation/nsGeolocation.cpp
dom/src/geolocation/nsGeolocation.h
dom/system/unix/MaemoLocationProvider.h
js/xpconnect/src/dictionary_helper_gen.conf
--- a/dom/interfaces/geolocation/Makefile.in
+++ b/dom/interfaces/geolocation/Makefile.in
@@ -48,13 +48,12 @@ GRE_MODULE     = 1
 
 XPIDLSRCS =                                    \
             nsIDOMGeoGeolocation.idl           \
             nsIDOMGeoPosition.idl              \
             nsIDOMGeoPositionCoords.idl        \
             nsIDOMGeoPositionCallback.idl      \
             nsIDOMGeoPositionError.idl         \
             nsIDOMGeoPositionErrorCallback.idl \
-            nsIDOMGeoPositionOptions.idl       \
             nsIDOMNavigatorGeolocation.idl     \
             $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
+++ b/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
@@ -36,21 +36,32 @@
 
 #include "domstubs.idl"
 
 interface nsIDOMGeoPosition;
 interface nsIDOMGeoPositionOptions;
 interface nsIDOMGeoPositionCallback;
 interface nsIDOMGeoPositionErrorCallback;
 
-[scriptable, uuid(37687DAF-B85F-4E4D-8881-85A0AD24CF78)]
+dictionary GeoPositionOptions
+{
+  boolean enableHighAccuracy;
+  long timeout;
+  long maximumAge;
+};
+
+[scriptable, uuid(b9a301f7-285b-4be9-b739-fb869019c77a)]
 interface nsIDOMGeoGeolocation : nsISupports
 {
+  [implicit_jscontext]
   void getCurrentPosition(in nsIDOMGeoPositionCallback successCallback,
                           [optional] in nsIDOMGeoPositionErrorCallback errorCallback,
-                          [optional] in nsIDOMGeoPositionOptions options);
+                          /* GeoPositionOptions */
+                          [optional] in jsval options);
 
+  [implicit_jscontext]
   long watchPosition(in nsIDOMGeoPositionCallback successCallback,
                      [optional] in nsIDOMGeoPositionErrorCallback errorCallback,
-                     [optional] in nsIDOMGeoPositionOptions options);
+                     /* GeoPositionOptions */
+                     [optional] in jsval options);
 
   void clearWatch(in long watchId);
 };
deleted file mode 100644
--- a/dom/interfaces/geolocation/nsIDOMGeoPositionOptions.idl
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Geolocation.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Doug Turner <dougt@meer.net>  (Original Author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-
-#include "domstubs.idl"
-
-[scriptable, uuid(453B72DE-EA90-4F09-AE16-C2E7EE0DDDC4)]
-interface nsIDOMGeoPositionOptions : nsISupports
-{
-  attribute boolean enableHighAccuracy;
-  attribute long timeout;
-  attribute long maximumAge;
-};
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1167,17 +1167,18 @@ ContentParent::RecvAsyncMessage(const ns
 bool
 ContentParent::RecvAddGeolocationListener()
 {
   if (mGeolocationWatchID == -1) {
     nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
     if (!geo) {
       return true;
     }
-    geo->WatchPosition(this, nsnull, nsnull, &mGeolocationWatchID);
+    jsval dummy = JSVAL_VOID;
+    geo->WatchPosition(this, nsnull, dummy, nsnull, &mGeolocationWatchID);
   }
   return true;
 }
 
 bool
 ContentParent::RecvRemoveGeolocationListener()
 {
   if (mGeolocationWatchID != -1) {
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -237,49 +237,51 @@ nsDOMGeoPositionError::NotifyCallback(ns
 }
 ////////////////////////////////////////////////////
 // nsGeolocationRequest
 ////////////////////////////////////////////////////
 
 nsGeolocationRequest::nsGeolocationRequest(nsGeolocation* aLocator,
                                            nsIDOMGeoPositionCallback* aCallback,
                                            nsIDOMGeoPositionErrorCallback* aErrorCallback,
-                                           nsIDOMGeoPositionOptions* aOptions,
                                            bool aWatchPositionRequest)
   : mAllowed(false),
     mCleared(false),
     mIsWatchPositionRequest(aWatchPositionRequest),
     mCallback(aCallback),
     mErrorCallback(aErrorCallback),
-    mOptions(aOptions),
     mLocator(aLocator)
 {
 }
 
 nsGeolocationRequest::~nsGeolocationRequest()
 {
 }
 
 nsresult
-nsGeolocationRequest::Init()
+nsGeolocationRequest::Init(JSContext* aCx, const jsval& aOptions)
 {
-  // This method is called before the user has given permission for this request.
+  if (aCx && !JSVAL_IS_VOID(aOptions) && !JSVAL_IS_NULL(aOptions)) {
+    mOptions = new mozilla::dom::GeoPositionOptions();
+    nsresult rv = mOptions->Init(aCx, &aOptions);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
   return NS_OK;
 }
 
 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_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGeolocationRequest)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest)
 
-NS_IMPL_CYCLE_COLLECTION_4(nsGeolocationRequest, mCallback, mErrorCallback, mOptions, mLocator)
+NS_IMPL_CYCLE_COLLECTION_3(nsGeolocationRequest, mCallback, mErrorCallback, mLocator)
 
 
 void
 nsGeolocationRequest::NotifyError(PRInt16 errorCode)
 {
   nsRefPtr<nsDOMGeoPositionError> positionError = new nsDOMGeoPositionError(errorCode);
   if (!positionError)
     return;
@@ -373,26 +375,21 @@ nsGeolocationRequest::Allow()
   //
   // either:
   // a) the user has specified a maximumAge which allows us to return a cached value,
   // -or-
   // b) the cached position time is some reasonable value to return to the user (<30s)
   
   PRUint32 maximumAge = 30 * PR_MSEC_PER_SEC;
   if (mOptions) {
-    PRInt32 tempAge;
-    nsresult rv = mOptions->GetMaximumAge(&tempAge);
-    if (NS_SUCCEEDED(rv)) {
-      if (tempAge >= 0)
-        maximumAge = tempAge;
+    if (mOptions->maximumAge >= 0) {
+      maximumAge = mOptions->maximumAge;
     }
-    bool highAccuracy;
-    rv = mOptions->GetEnableHighAccuracy(&highAccuracy);
-    if (NS_SUCCEEDED(rv) && highAccuracy) {
-	geoService->SetHigherAccuracy(true);
+    if (mOptions->enableHighAccuracy) {
+      geoService->SetHigherAccuracy(true);
     }
   }
 
   if (lastPosition && maximumAge > 0 &&
       ( PRTime(PR_Now() / PR_USEC_PER_MSEC) - maximumAge <=
         PRTime(cachedPositionTime) )) {
     // okay, we can return a cached position
     mAllowed = true;
@@ -412,17 +409,17 @@ nsGeolocationRequest::Allow()
 void
 nsGeolocationRequest::SetTimeoutTimer()
 {
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
     mTimeoutTimer = nsnull;
   }
   PRInt32 timeout;
-  if (mOptions && NS_SUCCEEDED(mOptions->GetTimeout(&timeout)) && timeout != 0) {
+  if (mOptions && (timeout = mOptions->timeout) != 0) {
 
     if (timeout < 0)
       timeout = 0;
     else if (timeout < 10)
       timeout = 10;
 
     mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
     mTimeoutTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
@@ -482,24 +479,21 @@ nsGeolocationRequest::Update(nsIDOMGeoPo
                                    mIsWatchPositionRequest ? nsnull : mLocator);
   NS_DispatchToMainThread(ev);
   return true;
 }
 
 void
 nsGeolocationRequest::Shutdown()
 {
-  if (mOptions) {
-      bool highAccuracy;
-      nsresult rv = mOptions->GetEnableHighAccuracy(&highAccuracy);
-      if (NS_SUCCEEDED(rv) && highAccuracy) {
-	  nsRefPtr<nsGeolocationService> geoService = nsGeolocationService::GetInstance();
-	  if (geoService)
-	      geoService->SetHigherAccuracy(false);
-      }
+  if (mOptions && mOptions->enableHighAccuracy) {
+    nsRefPtr<nsGeolocationService> geoService = nsGeolocationService::GetInstance();
+    if (geoService) {
+      geoService->SetHigherAccuracy(false);
+    }
   }
 
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
     mTimeoutTimer = nsnull;
   }
   mCleared = true;
   mCallback = nsnull;
@@ -936,36 +930,36 @@ nsGeolocation::Update(nsIDOMGeoPosition 
   for (PRUint32 i = 0; i< mWatchingCallbacks.Length(); i++) {
     mWatchingCallbacks[i]->Update(aSomewhere);
   }
 }
 
 NS_IMETHODIMP
 nsGeolocation::GetCurrentPosition(nsIDOMGeoPositionCallback *callback,
                                   nsIDOMGeoPositionErrorCallback *errorCallback,
-                                  nsIDOMGeoPositionOptions *options)
+                                  const jsval& options,
+                                  JSContext* cx)
 {
   NS_ENSURE_ARG_POINTER(callback);
 
   if (!sGeoEnabled)
     return NS_ERROR_NOT_AVAILABLE;
 
   if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
     return NS_ERROR_NOT_AVAILABLE;
 
   nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this,
 								    callback,
 								    errorCallback,
-								    options,
 								    false);
   if (!request)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  if (NS_FAILED(request->Init()))
-    return NS_ERROR_FAILURE; // this as OKAY.  not sure why we wouldn't throw. xxx dft
+  nsresult rv = request->Init(cx, options);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (mOwner) {
     if (!RegisterRequestWithPrompt(request))
       return NS_ERROR_NOT_AVAILABLE;
     
     mPendingCallbacks.AppendElement(request);
     return NS_OK;
   }
@@ -979,38 +973,38 @@ nsGeolocation::GetCurrentPosition(nsIDOM
   NS_DispatchToMainThread(ev);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsGeolocation::WatchPosition(nsIDOMGeoPositionCallback *callback,
                              nsIDOMGeoPositionErrorCallback *errorCallback,
-                             nsIDOMGeoPositionOptions *options,
+                             const jsval& options,
+                             JSContext* cx,
                              PRInt32 *_retval NS_OUTPARAM)
 {
 
   NS_ENSURE_ARG_POINTER(callback);
 
   if (!sGeoEnabled)
     return NS_ERROR_NOT_AVAILABLE;
 
   if (mPendingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW)
     return NS_ERROR_NOT_AVAILABLE;
 
   nsRefPtr<nsGeolocationRequest> request = new nsGeolocationRequest(this,
 								    callback,
 								    errorCallback,
-								    options,
 								    true);
   if (!request)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  if (NS_FAILED(request->Init()))
-    return NS_ERROR_FAILURE; // this as OKAY.  not sure why we wouldn't throw. xxx dft
+  nsresult rv = request->Init(cx, options);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (mOwner) {
     if (!RegisterRequestWithPrompt(request))
       return NS_ERROR_NOT_AVAILABLE;
 
     // need to hand back an index/reference.
     mWatchingCallbacks.AppendElement(request);
     *_retval = mWatchingCallbacks.Length() - 1;
--- a/dom/src/geolocation/nsGeolocation.h
+++ b/dom/src/geolocation/nsGeolocation.h
@@ -52,24 +52,23 @@
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionError.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIDOMGeoPositionErrorCallback.h"
-#include "nsIDOMGeoPositionOptions.h"
 #include "nsIDOMNavigatorGeolocation.h"
 
 #include "nsPIDOMWindow.h"
 
 #include "nsIGeolocationProvider.h"
 #include "nsIContentPermissionPrompt.h"
-
+#include "DictionaryHelpers.h"
 #include "PCOMContentPermissionRequestChild.h"
 
 class nsGeolocationService;
 class nsGeolocation;
 
 class nsGeolocationRequest
  : public nsIContentPermissionRequest
  , public nsITimerCallback
@@ -80,19 +79,18 @@ class nsGeolocationRequest
   NS_DECL_NSICONTENTPERMISSIONREQUEST
   NS_DECL_NSITIMERCALLBACK
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest)
 
   nsGeolocationRequest(nsGeolocation* locator,
                        nsIDOMGeoPositionCallback* callback,
                        nsIDOMGeoPositionErrorCallback* errorCallback,
-                       nsIDOMGeoPositionOptions* options,
                        bool watchPositionRequest = false);
-  nsresult Init();
+  nsresult Init(JSContext* aCx, const jsval& aOptions);
   void Shutdown();
 
   // Called by the geolocation device to notify that a location has changed.
   bool Update(nsIDOMGeoPosition* aPosition);
 
   void SendLocation(nsIDOMGeoPosition* location);
   void MarkCleared();
   bool IsActive() {return !mCleared;}
@@ -109,17 +107,17 @@ class nsGeolocationRequest
   void NotifyError(PRInt16 errorCode);
   bool mAllowed;
   bool mCleared;
   bool mIsWatchPositionRequest;
 
   nsCOMPtr<nsITimer> mTimeoutTimer;
   nsCOMPtr<nsIDOMGeoPositionCallback> mCallback;
   nsCOMPtr<nsIDOMGeoPositionErrorCallback> mErrorCallback;
-  nsCOMPtr<nsIDOMGeoPositionOptions> mOptions;
+  nsAutoPtr<mozilla::dom::GeoPositionOptions> mOptions;
 
   nsRefPtr<nsGeolocation> mLocator;
 };
 
 /**
  * Singleton that manages the geolocation provider
  */
 class nsGeolocationService : public nsIGeolocationUpdate, public nsIObserver
--- a/dom/system/unix/MaemoLocationProvider.h
+++ b/dom/system/unix/MaemoLocationProvider.h
@@ -47,17 +47,16 @@
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionError.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIDOMGeoPositionErrorCallback.h"
-#include "nsIDOMGeoPositionOptions.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "nsIDOMGeoPositionCoords.h"
 
 #include "nsPIDOMWindow.h"
 
 #include "nsIGeolocationProvider.h"
 
 
--- a/js/xpconnect/src/dictionary_helper_gen.conf
+++ b/js/xpconnect/src/dictionary_helper_gen.conf
@@ -8,17 +8,18 @@ dictionaries = [
      [ 'CloseEventInit', 'nsIDOMCloseEvent.idl' ],
      [ 'UIEventInit', 'nsIDOMUIEvent.idl' ],
      [ 'MouseEventInit', 'nsIDOMMouseEvent.idl' ],
      [ 'IDBObjectStoreParameters', 'nsIIDBDatabase.idl' ],
      [ 'IDBIndexParameters', 'nsIIDBObjectStore.idl' ],
      [ 'StorageEventInit', 'nsIDOMStorageEvent.idl' ],
      [ 'BlobPropertyBag', 'nsIDOMFile.idl' ],
      [ 'MutationObserverInit', 'nsIDOMMutationObserver.idl' ],
-     [ 'SettingsEventInit', 'nsIDOMSettingsManager.idl' ]
+     [ 'SettingsEventInit', 'nsIDOMSettingsManager.idl' ],
+     [ 'GeoPositionOptions', 'nsIDOMGeoGeolocation.idl']
    ]
 
 # include file names
 special_includes = [
     'nsContentUtils.h',
     'XPCQuickStubs.h'
   ]