diff --git a/browser/base/content/test/general/browser_devices_get_user_media.js b/browser/base/content/test/general/browser_devices_get_user_media.js index 1ec3bdcae34..806e14bbd38 100644 --- a/browser/base/content/test/general/browser_devices_get_user_media.js +++ b/browser/base/content/test/general/browser_devices_get_user_media.js @@ -593,6 +593,9 @@ let gTests = [ yield promiseMessage(expectedMessage, gum); if (expectedMessage == "ok") { + expectObserverCalled("getUserMedia:request"); + yield promiseNoPopupNotification("webRTC-shareDevices"); + expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); // Check what's actually shared. @@ -687,6 +690,8 @@ let gTests = [ yield promiseMessage("ok", () => { content.wrappedJSObject.requestDevice(aRequestAudio, aRequestVideo); }); + expectObserverCalled("getUserMedia:request"); + expectObserverCalled("getUserMedia:response:allow"); expectObserverCalled("recording-device-events"); yield checkSharingUI(); diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm index f1eceece228..43dd0decd30 100644 --- a/browser/modules/webrtcUI.jsm +++ b/browser/modules/webrtcUI.jsm @@ -212,6 +212,38 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi if (aTopic != "showing") return false; + // DENY_ACTION is handled immediately by MediaManager, but handling + // of ALLOW_ACTION is delayed until the popupshowing event + // to avoid granting permissions automatically to background tabs. + if (aSecure) { + let perms = Services.perms; + + let micPerm = perms.testExactPermission(uri, "microphone"); + if (micPerm == perms.PROMPT_ACTION) + micPerm = perms.UNKNOWN_ACTION; + + let camPerm = perms.testExactPermission(uri, "camera"); + if (camPerm == perms.PROMPT_ACTION) + camPerm = perms.UNKNOWN_ACTION; + + // We don't check that permissions are set to ALLOW_ACTION in this + // test; only that they are set. This is because if audio is allowed + // and video is denied persistently, we don't want to show the prompt, + // and will grant audio access immediately. + if ((!audioDevices.length || micPerm) && (!videoDevices.length || camPerm)) { + // All permissions we were about to request are already persistently set. + let allowedDevices = Cc["@mozilla.org/supports-array;1"] + .createInstance(Ci.nsISupportsArray); + if (videoDevices.length && camPerm == perms.ALLOW_ACTION) + allowedDevices.AppendElement(videoDevices[0]); + if (audioDevices.length && micPerm == perms.ALLOW_ACTION) + allowedDevices.AppendElement(audioDevices[0]); + Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID); + this.remove(); + return true; + } + } + function listDevices(menupopup, devices) { while (menupopup.lastChild) menupopup.removeChild(menupopup.lastChild); diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 55eca714a11..f24ffbcdfbc 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -1498,14 +1498,6 @@ MediaManager::GetUserMedia(bool aPrivileged, rv = permManager->TestExactPermissionFromPrincipal( aWindow->GetExtantDoc()->NodePrincipal(), "microphone", &audioPerm); NS_ENSURE_SUCCESS(rv, rv); - if (audioPerm == nsIPermissionManager::PROMPT_ACTION) { - audioPerm = nsIPermissionManager::UNKNOWN_ACTION; - } - if (audioPerm == nsIPermissionManager::ALLOW_ACTION) { - if (!isHTTPS) { - audioPerm = nsIPermissionManager::UNKNOWN_ACTION; - } - } } uint32_t videoPerm = nsIPermissionManager::UNKNOWN_ACTION; @@ -1513,33 +1505,11 @@ MediaManager::GetUserMedia(bool aPrivileged, rv = permManager->TestExactPermissionFromPrincipal( aWindow->GetExtantDoc()->NodePrincipal(), "camera", &videoPerm); NS_ENSURE_SUCCESS(rv, rv); - if (videoPerm == nsIPermissionManager::PROMPT_ACTION) { - videoPerm = nsIPermissionManager::UNKNOWN_ACTION; - } - if (videoPerm == nsIPermissionManager::ALLOW_ACTION) { - if (!isHTTPS) { - videoPerm = nsIPermissionManager::UNKNOWN_ACTION; - } - } } - if ((!IsOn(c.mAudio) || audioPerm != nsIPermissionManager::UNKNOWN_ACTION) && - (!IsOn(c.mVideo) || videoPerm != nsIPermissionManager::UNKNOWN_ACTION)) { - // All permissions we were about to request already have a saved value. - if (IsOn(c.mAudio) && audioPerm == nsIPermissionManager::DENY_ACTION) { - c.mAudio.SetAsBoolean() = false; - runnable->SetContraints(c); - } - if (IsOn(c.mVideo) && videoPerm == nsIPermissionManager::DENY_ACTION) { - c.mVideo.SetAsBoolean() = false; - runnable->SetContraints(c); - } - - if (!IsOn(c.mAudio) && !IsOn(c.mVideo)) { - return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); - } - - return mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); + if ((!IsOn(c.mAudio) || audioPerm == nsIPermissionManager::DENY_ACTION) && + (!IsOn(c.mVideo) || videoPerm == nsIPermissionManager::DENY_ACTION)) { + return runnable->Denied(NS_LITERAL_STRING("PERMISSION_DENIED")); } // Ask for user permission, and dispatch runnable (or not) when a response