Bug 949907 - GetUserMediaDevices cleanup + untie GetUserMediaRequest obj from DOM. r=jesup, a=abillings
authorJan-Ivar Bruaroey <jib@mozilla.com>
Fri, 14 Feb 2014 11:32:58 -0800
changeset 170827 f988a03ddc6d7f092549af14e69d6f5efa15e699
parent 170826 38792cacf700d37f2b9994531aabce6002c34bcd
child 170828 9af4a3b686292f0dc44df7314d423733db485fd9
push id173
push userryanvm@gmail.com
push dateFri, 28 Feb 2014 23:32:02 +0000
reviewersjesup, abillings
bugs949907
milestone28.0
Bug 949907 - GetUserMediaDevices cleanup + untie GetUserMediaRequest obj from DOM. r=jesup, a=abillings
browser/modules/webrtcUI.jsm
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/media/GetUserMediaRequest.cpp
dom/media/GetUserMediaRequest.h
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/MediaPermissionGonk.cpp
dom/webidl/GetUserMediaRequest.webidl
dom/webidl/Navigator.webidl
mobile/android/chrome/content/WebrtcUI.js
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -61,41 +61,42 @@ function getBrowserForWindow(aContentWin
   return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIWebNavigation)
                        .QueryInterface(Ci.nsIDocShell)
                        .chromeEventHandler;
 }
 
 function handleRequest(aSubject, aTopic, aData) {
   let constraints = aSubject.getConstraints();
+  let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID);
 
-  Services.wm.getMostRecentWindow(null).navigator.mozGetUserMediaDevices(
+  contentWindow.navigator.mozGetUserMediaDevices(
     constraints,
     function (devices) {
-      prompt(aSubject.windowID, aSubject.callID, constraints.audio,
+      prompt(contentWindow, aSubject.callID, constraints.audio,
              constraints.video || constraints.picture, devices);
     },
     function (error) {
       // bug 827146 -- In the future, the UI should catch NO_DEVICES_FOUND
       // and allow the user to plug in a device, instead of immediately failing.
       denyRequest(aSubject.callID, error);
-    }
-  );
+    },
+    aSubject.innerWindowID);
 }
 
 function denyRequest(aCallID, aError) {
   let msg = null;
   if (aError) {
     msg = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
     msg.data = aError;
   }
   Services.obs.notifyObservers(msg, "getUserMedia:response:deny", aCallID);
 }
 
-function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices) {
+function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevices) {
   let audioDevices = [];
   let videoDevices = [];
   for (let device of aDevices) {
     device = device.QueryInterface(Ci.nsIMediaDevice);
     switch (device.type) {
       case "audio":
         if (aAudioRequested)
           audioDevices.push(device);
@@ -114,19 +115,18 @@ function prompt(aWindowID, aCallID, aAud
     requestType = "Microphone";
   else if (videoDevices.length)
     requestType = "Camera";
   else {
     denyRequest(aCallID, "NO_DEVICES_FOUND");
     return;
   }
 
-  let contentWindow = Services.wm.getOuterWindowWithId(aWindowID);
-  let host = contentWindow.document.documentURIObject.host;
-  let browser = getBrowserForWindow(contentWindow);
+  let host = aContentWindow.document.documentURIObject.host;
+  let browser = getBrowserForWindow(aContentWindow);
   let chromeDoc = browser.ownerDocument;
   let chromeWin = chromeDoc.defaultView;
   let stringBundle = chromeWin.gNavigatorBundle;
   let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
                                                 [ host ]);
 
   function listDevices(menupopup, devices) {
     while (menupopup.lastChild)
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1003,16 +1003,17 @@ Navigator::MozGetUserMedia(JSContext* aC
   aRv = manager->GetUserMedia(aCx, privileged, mWindow, aConstraints,
                               onsuccess, onerror);
 }
 
 void
 Navigator::MozGetUserMediaDevices(const MediaStreamConstraintsInternal& aConstraints,
                                   MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
                                   NavigatorUserMediaErrorCallback& aOnError,
+                                  uint64_t aInnerWindowID,
                                   ErrorResult& aRv)
 {
   CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
                        nsIGetUserMediaDevicesSuccessCallback> holder1(&aOnSuccess);
   nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onsuccess =
     holder1.ToXPCOMCallback();
 
   CallbackObjectHolder<NavigatorUserMediaErrorCallback,
@@ -1021,17 +1022,18 @@ Navigator::MozGetUserMediaDevices(const 
 
   if (!mWindow || !mWindow->GetOuterWindow() ||
       mWindow->GetOuterWindow()->GetCurrentInnerWindow() != mWindow) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
   MediaManager* manager = MediaManager::Get();
-  aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror);
+  aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
+                                     aInnerWindowID);
 }
 #endif
 
 DesktopNotificationCenter*
 Navigator::GetMozNotification(ErrorResult& aRv)
 {
   if (mNotification) {
     return mNotification;
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -225,16 +225,17 @@ public:
   void MozGetUserMedia(JSContext* aCx,
                        const MediaStreamConstraints& aConstraints,
                        NavigatorUserMediaSuccessCallback& aOnSuccess,
                        NavigatorUserMediaErrorCallback& aOnError,
                        ErrorResult& aRv);
   void MozGetUserMediaDevices(const MediaStreamConstraintsInternal& aConstraints,
                               MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
                               NavigatorUserMediaErrorCallback& aOnError,
+                              uint64_t aInnerWindowID,
                               ErrorResult& aRv);
 #endif // MOZ_MEDIA_NAVIGATOR
   bool DoNewResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
                     JS::Handle<jsid> aId, JS::MutableHandle<JS::Value> aValue);
   void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
                            ErrorResult& aRv);
 
   // WebIDL helper methods
--- a/dom/media/GetUserMediaRequest.cpp
+++ b/dom/media/GetUserMediaRequest.cpp
@@ -12,51 +12,56 @@
 
 namespace mozilla {
 namespace dom {
 
 GetUserMediaRequest::GetUserMediaRequest(
     nsPIDOMWindow* aInnerWindow,
     const nsAString& aCallID,
     const MediaStreamConstraintsInternal& aConstraints)
-  : mInnerWindow(aInnerWindow)
-  , mWindowID(aInnerWindow->GetOuterWindow()->WindowID())
+  : mInnerWindowID(aInnerWindow->WindowID())
+  , mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID())
   , mCallID(aCallID)
   , mConstraints(aConstraints)
 {
   SetIsDOMBinding();
 }
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(GetUserMediaRequest, mInnerWindow)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(GetUserMediaRequest)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(GetUserMediaRequest)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(GetUserMediaRequest)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(GetUserMediaRequest)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 JSObject*
 GetUserMediaRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
 {
   return GetUserMediaRequestBinding::Wrap(aCx, aScope, this);
 }
 
 nsISupports* GetUserMediaRequest::GetParentObject()
 {
-  return mInnerWindow;
+  return nullptr;
 }
 
 void GetUserMediaRequest::GetCallID(nsString& retval)
 {
   retval = mCallID;
 }
 
 uint64_t GetUserMediaRequest::WindowID()
 {
-  return mWindowID;
+  return mOuterWindowID;
+}
+
+uint64_t GetUserMediaRequest::InnerWindowID()
+{
+  return mInnerWindowID;
 }
 
 void
 GetUserMediaRequest::GetConstraints(MediaStreamConstraintsInternal &result)
 {
   result = mConstraints;
 }
 
--- a/dom/media/GetUserMediaRequest.h
+++ b/dom/media/GetUserMediaRequest.h
@@ -15,34 +15,35 @@
 
 namespace mozilla {
 namespace dom {
 class MediaStreamConstraintsInternal;
 
 class GetUserMediaRequest : public nsISupports, public nsWrapperCache
 {
 public:
-  GetUserMediaRequest(nsPIDOMWindow* aInnerWindow, const nsAString& aCallID,
+  GetUserMediaRequest(nsPIDOMWindow* aInnerWindow,
+                      const nsAString& aCallID,
                       const MediaStreamConstraintsInternal& aConstraints);
   virtual ~GetUserMediaRequest() {};
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(GetUserMediaRequest)
 
   virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
     MOZ_OVERRIDE;
   nsISupports* GetParentObject();
 
   uint64_t WindowID();
+  uint64_t InnerWindowID();
   void GetCallID(nsString& retval);
   void GetConstraints(MediaStreamConstraintsInternal &result);
 
 private:
-  nsCOMPtr<nsPIDOMWindow> mInnerWindow;
-  uint64_t mWindowID;
+  uint64_t mInnerWindowID, mOuterWindowID;
   const nsString mCallID;
   MediaStreamConstraintsInternal mConstraints;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // GetUserMediaRequest_h__
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -219,31 +219,39 @@ private:
  * Invoke the GetUserMediaDevices success callback. Wrapped in a runnable
  * so that it may be called on the main thread. The error callback is also
  * passed so it can be released correctly.
  */
 class DeviceSuccessCallbackRunnable: public nsRunnable
 {
 public:
   DeviceSuccessCallbackRunnable(
+    uint64_t aWindowID,
     already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
     nsTArray<nsCOMPtr<nsIMediaDevice> >* aDevices)
     : mSuccess(aSuccess)
     , mError(aError)
-    , mDevices(aDevices) {}
+    , mDevices(aDevices)
+    , mWindowID(aWindowID)
+    , mManager(MediaManager::GetInstance()) {}
 
   NS_IMETHOD
   Run()
   {
     NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
     nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> success(mSuccess);
     nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
 
+    // Only run if window is still on our active list.
+    if (!mManager->IsWindowStillActive(mWindowID)) {
+      return NS_OK;
+    }
+
     nsCOMPtr<nsIWritableVariant> devices =
       do_CreateInstance("@mozilla.org/variant;1");
 
     int32_t len = mDevices->Length();
     if (len == 0) {
       // XXX
       // We should in the future return an empty array, and dynamically add
       // devices to the dropdowns if things are hotplugged while the
@@ -267,16 +275,18 @@ public:
     success->OnSuccess(devices);
     return NS_OK;
   }
 
 private:
   already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   nsAutoPtr<nsTArray<nsCOMPtr<nsIMediaDevice> > > mDevices;
+  uint64_t mWindowID;
+  nsRefPtr<MediaManager> mManager;
 };
 
 // Handle removing GetUserMediaCallbackMediaStreamListener from main thread
 class GetUserMediaListenerRemove: public nsRunnable
 {
 public:
   GetUserMediaListenerRemove(uint64_t aWindowID,
     GetUserMediaCallbackMediaStreamListener *aListener)
@@ -1058,27 +1068,29 @@ public:
 
     ScopedDeletePtr<SourceSet> final (GetSources(backend, mConstraints.mVideom,
                                           &MediaEngine::EnumerateVideoDevices));
     {
       ScopedDeletePtr<SourceSet> s (GetSources(backend, mConstraints.mAudiom,
                                         &MediaEngine::EnumerateAudioDevices));
       final->MoveElementsFrom(*s);
     }
-    NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mSuccess, mError,
+    NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
+                                                              mSuccess, mError,
                                                               final.forget()));
     return NS_OK;
   }
 
 private:
   MediaStreamConstraintsInternal mConstraints;
   already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   nsRefPtr<MediaManager> mManager;
   uint64_t mWindowId;
+  const nsString mCallId;
 };
 
 MediaManager::MediaManager()
   : mMediaThread(nullptr)
   , mMutex("mozilla::MediaManager")
   , mBackend(nullptr) {
   mPrefs.mWidth  = MediaEngine::DEFAULT_VIDEO_WIDTH;
   mPrefs.mHeight = MediaEngine::DEFAULT_VIDEO_HEIGHT;
@@ -1426,28 +1438,30 @@ MediaManager::GetUserMedia(JSContext* aC
 
   return NS_OK;
 }
 
 nsresult
 MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
   const MediaStreamConstraintsInternal& aConstraints,
   nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
-  nsIDOMGetUserMediaErrorCallback* aOnError)
+  nsIDOMGetUserMediaErrorCallback* aOnError,
+  uint64_t aInnerWindowID)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   NS_ENSURE_TRUE(aOnError, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError);
 
   nsCOMPtr<nsIRunnable> gUMDRunnable = new GetUserMediaDevicesRunnable(
-    aConstraints, onSuccess.forget(), onError.forget(), aWindow->WindowID()
+    aConstraints, onSuccess.forget(), onError.forget(),
+    (aInnerWindowID ? aInnerWindowID : aWindow->WindowID())
   );
 
   nsCOMPtr<nsIThread> deviceThread;
   nsresult rv = NS_NewThread(getter_AddRefs(deviceThread));
   NS_ENSURE_SUCCESS(rv, rv);
 
 
   deviceThread->Dispatch(gUMDRunnable, NS_DISPATCH_NORMAL);
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -489,17 +489,18 @@ public:
     nsPIDOMWindow* aWindow,
     const dom::MediaStreamConstraints& aRawConstraints,
     nsIDOMGetUserMediaSuccessCallback* onSuccess,
     nsIDOMGetUserMediaErrorCallback* onError);
 
   nsresult GetUserMediaDevices(nsPIDOMWindow* aWindow,
     const dom::MediaStreamConstraintsInternal& aConstraints,
     nsIGetUserMediaDevicesSuccessCallback* onSuccess,
-    nsIDOMGetUserMediaErrorCallback* onError);
+    nsIDOMGetUserMediaErrorCallback* onError,
+    uint64_t aInnerWindowID = 0);
   void OnNavigation(uint64_t aWindowID);
 
   MediaEnginePrefs mPrefs;
 
 private:
   WindowTable *GetActiveWindows() {
     NS_ASSERTION(NS_IsMainThread(), "Only access windowlist on main thread");
     return &mActiveWindows;
--- a/dom/media/MediaPermissionGonk.cpp
+++ b/dom/media/MediaPermissionGonk.cpp
@@ -120,17 +120,18 @@ MediaPermissionRequest::MediaPermissionR
 }
 
 // nsIContentPermissionRequest methods
 NS_IMETHODIMP
 MediaPermissionRequest::GetPrincipal(nsIPrincipal **aRequestingPrincipal)
 {
   NS_ENSURE_ARG_POINTER(aRequestingPrincipal);
 
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mRequest->GetParentObject());
+  nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
+      (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
   NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   NS_ADDREF(*aRequestingPrincipal = doc->NodePrincipal());
   return NS_OK;
 }
@@ -152,17 +153,18 @@ MediaPermissionRequest::GetAccess(nsACSt
   aAccess = "unused";
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaPermissionRequest::GetWindow(nsIDOMWindow** aRequestingWindow)
 {
   NS_ENSURE_ARG_POINTER(aRequestingWindow);
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mRequest->GetParentObject());
+  nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
+      (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
   window.forget(aRequestingWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaPermissionRequest::GetElement(nsIDOMElement** aRequestingElement)
 {
   NS_ENSURE_ARG_POINTER(aRequestingElement);
@@ -186,17 +188,18 @@ MediaPermissionRequest::Allow()
   mRequest->GetCallID(callID);
   NotifyPermissionAllow(callID, mDevices);
   return NS_OK;
 }
 
 already_AddRefed<nsPIDOMWindow>
 MediaPermissionRequest::GetOwner()
 {
-  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mRequest->GetParentObject());
+  nsCOMPtr<nsPIDOMWindow> window = static_cast<nsPIDOMWindow*>
+      (nsGlobalWindow::GetInnerWindowWithId(mRequest->InnerWindowID()));
   return window.forget();
 }
 
 //PCOMContentPermissionRequestChild
 bool
 MediaPermissionRequest::Recv__delete__(const bool& allow)
 {
   if (allow) {
@@ -401,17 +404,18 @@ MediaPermissionManager::Observe(nsISuppo
 
 // Handle GetUserMediaRequest, query available media device first.
 nsresult
 MediaPermissionManager::HandleRequest(nsRefPtr<dom::GetUserMediaRequest> &req)
 {
   nsString callID;
   req->GetCallID(callID);
 
-  nsCOMPtr<nsPIDOMWindow> innerWindow = do_QueryInterface(req->GetParentObject());
+  nsCOMPtr<nsPIDOMWindow> innerWindow = static_cast<nsPIDOMWindow*>
+      (nsGlobalWindow::GetInnerWindowWithId(req->InnerWindowID()));
   if (!innerWindow) {
     MOZ_ASSERT(false, "No inner window");
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess =
       new MediaDeviceSuccessCallback(req);
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError =
--- a/dom/webidl/GetUserMediaRequest.webidl
+++ b/dom/webidl/GetUserMediaRequest.webidl
@@ -4,11 +4,12 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * This is an internal IDL file
  */
 
 [NoInterfaceObject]
 interface GetUserMediaRequest {
   readonly attribute unsigned long long windowID;
+  readonly attribute unsigned long long innerWindowID;
   readonly attribute DOMString callID;
   MediaStreamConstraintsInternal getConstraints();
 };
--- a/dom/webidl/Navigator.webidl
+++ b/dom/webidl/Navigator.webidl
@@ -332,11 +332,15 @@ partial interface Navigator {
 };
 
 // nsINavigatorUserMedia
 callback MozGetUserMediaDevicesSuccessCallback = void (nsIVariant? devices);
 partial interface Navigator {
   [Throws, ChromeOnly]
   void mozGetUserMediaDevices(MediaStreamConstraintsInternal constraints,
                               MozGetUserMediaDevicesSuccessCallback onsuccess,
-                              NavigatorUserMediaErrorCallback onerror);
+                              NavigatorUserMediaErrorCallback onerror,
+                              // The originating innerWindowID is needed to
+                              // avoid calling the callbacks if the window has
+                              // navigated away. It is optional only as legacy.
+                              optional unsigned long long innerWindowID = 0);
 };
 #endif // MOZ_MEDIA_NAVIGATOR
--- a/mobile/android/chrome/content/WebrtcUI.js
+++ b/mobile/android/chrome/content/WebrtcUI.js
@@ -69,27 +69,28 @@ var WebrtcUI = {
         this._notificationId = Notifications.create(notificationOptions);
       if (count > 1)
         msg.count = count;
     }
   },
 
   handleRequest: function handleRequest(aSubject, aTopic, aData) {
     let constraints = aSubject.getConstraints();
+    let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID);
 
-    Services.wm.getMostRecentWindow(null).navigator.mozGetUserMediaDevices(
+    contentWindow.navigator.mozGetUserMediaDevices(
       constraints,
       function (devices) {
-        WebrtcUI.prompt(aSubject.windowID, aSubject.callID, constraints.audio,
+        WebrtcUI.prompt(contentWindow, aSubject.callID, constraints.audio,
                         constraints.video, devices);
       },
       function (error) {
         Cu.reportError(error);
-      }
-    );
+      },
+      aSubject.innerWindowID);
   },
 
   getDeviceButtons: function(audioDevices, videoDevices, aCallID) {
     return [{
       label: Strings.browser.GetStringFromName("getUserMedia.denyRequest.label"),
       callback: function() {
         Services.obs.notifyObservers(null, "getUserMedia:response:deny", aCallID);
       }
@@ -148,17 +149,18 @@ var WebrtcUI = {
           label: Strings.browser.GetStringFromName("getUserMedia." + aType + ".prompt"),
           values: list
         });
 
       }
     }
   },
 
-  prompt: function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices) {
+  prompt: function prompt(aContentWindow, aCallID, aAudioRequested,
+                          aVideoRequested, aDevices) {
     let audioDevices = [];
     let videoDevices = [];
     for (let device of aDevices) {
       device = device.QueryInterface(Ci.nsIMediaDevice);
       switch (device.type) {
       case "audio":
         if (aAudioRequested)
           audioDevices.push(device);
@@ -175,18 +177,17 @@ var WebrtcUI = {
       requestType = "CameraAndMicrophone";
     else if (audioDevices.length)
       requestType = "Microphone";
     else if (videoDevices.length)
       requestType = "Camera";
     else
       return;
 
-    let contentWindow = Services.wm.getOuterWindowWithId(aWindowID);
-    let host = contentWindow.document.documentURIObject.host;
+    let host = aContentWindow.document.documentURIObject.host;
     let requestor = BrowserApp.manifest ? "'" + BrowserApp.manifest.name  + "'" : host;
     let message = Strings.browser.formatStringFromName("getUserMedia.share" + requestType + ".message", [ requestor ], 1);
 
     let options = { inputs: [] };
     // if the users only option would be to select "No Audio" or "No Video"
     // i.e. we're only showing audio or only video and there is only one device for that type
     // don't bother showing a menulist to select from
     var extraItems = null;