Bug 949907 - GetUserMediaDevices cleanup + untie GetUserMediaRequest obj from DOM. r=jesup

This commit is contained in:
Jan-Ivar Bruaroey 2014-02-14 11:32:58 -08:00
parent e4ee73c4f6
commit f3c6621dae
11 changed files with 69 additions and 36 deletions

View File

@ -66,19 +66,20 @@ function getBrowserForWindow(aContentWindow) {
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) {
@ -90,7 +91,7 @@ function denyRequest(aCallID, 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) {
@ -119,9 +120,8 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
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;

View File

@ -1022,6 +1022,7 @@ void
Navigator::MozGetUserMediaDevices(const MediaStreamConstraintsInternal& aConstraints,
MozGetUserMediaDevicesSuccessCallback& aOnSuccess,
NavigatorUserMediaErrorCallback& aOnError,
uint64_t aInnerWindowID,
ErrorResult& aRv)
{
CallbackObjectHolder<MozGetUserMediaDevicesSuccessCallback,
@ -1040,7 +1041,8 @@ Navigator::MozGetUserMediaDevices(const MediaStreamConstraintsInternal& aConstra
}
MediaManager* manager = MediaManager::Get();
aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror);
aRv = manager->GetUserMediaDevices(mWindow, aConstraints, onsuccess, onerror,
aInnerWindowID);
}
#endif

View File

@ -230,6 +230,7 @@ public:
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,

View File

@ -17,15 +17,15 @@ 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)
@ -41,7 +41,7 @@ GetUserMediaRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
nsISupports* GetUserMediaRequest::GetParentObject()
{
return mInnerWindow;
return nullptr;
}
void GetUserMediaRequest::GetCallID(nsString& retval)
@ -51,7 +51,12 @@ void GetUserMediaRequest::GetCallID(nsString& retval)
uint64_t GetUserMediaRequest::WindowID()
{
return mWindowID;
return mOuterWindowID;
}
uint64_t GetUserMediaRequest::InnerWindowID()
{
return mInnerWindowID;
}
void

View File

@ -20,7 +20,8 @@ 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() {};
@ -32,12 +33,12 @@ public:
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;
};

View File

@ -225,12 +225,15 @@ 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()
@ -240,6 +243,11 @@ public:
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");
@ -273,6 +281,8 @@ 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
@ -1076,7 +1086,8 @@ public:
mLoopbackAudioDevice));
final->MoveElementsFrom(*s);
}
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mSuccess, mError,
NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mWindowId,
mSuccess, mError,
final.forget()));
return NS_OK;
}
@ -1087,6 +1098,7 @@ private:
already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
nsRefPtr<MediaManager> mManager;
uint64_t mWindowId;
const nsString mCallId;
// Audio & Video loopback devices to be used based on
// the preference settings. This is currently used for
// automated media tests only.
@ -1449,7 +1461,8 @@ 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");
@ -1474,9 +1487,9 @@ MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
#endif
nsCOMPtr<nsIRunnable> gUMDRunnable = new GetUserMediaDevicesRunnable(
aConstraints, onSuccess.forget(), onError.forget(), aWindow->WindowID(),
loopbackAudioDevice, loopbackVideoDevice
);
aConstraints, onSuccess.forget(), onError.forget(),
(aInnerWindowID ? aInnerWindowID : aWindow->WindowID()),
loopbackAudioDevice, loopbackVideoDevice);
nsCOMPtr<nsIThread> deviceThread;
rv = NS_NewThread(getter_AddRefs(deviceThread));

View File

@ -494,7 +494,8 @@ public:
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;

View File

@ -173,7 +173,8 @@ 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();
@ -187,7 +188,8 @@ 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;
}
@ -221,7 +223,8 @@ MediaPermissionRequest::Allow()
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();
}
@ -434,7 +437,8 @@ 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;

View File

@ -9,6 +9,7 @@
[NoInterfaceObject]
interface GetUserMediaRequest {
readonly attribute unsigned long long windowID;
readonly attribute unsigned long long innerWindowID;
readonly attribute DOMString callID;
MediaStreamConstraintsInternal getConstraints();
};

View File

@ -340,6 +340,10 @@ 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

View File

@ -74,17 +74,18 @@ var WebrtcUI = {
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) {
@ -153,7 +154,8 @@ var WebrtcUI = {
}
},
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) {
@ -180,8 +182,7 @@ var WebrtcUI = {
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);