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 cf90a5b3b929..051a887acf8c 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 @@ -771,7 +771,7 @@ function test() { }, true); let rootDir = getRootDirectory(gTestPath) rootDir = rootDir.replace("chrome://mochitests/content/", - "http://127.0.0.1:8888/"); + "https://example.com/"); content.location = rootDir + "get_user_media.html"; } diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm index 06705f851a29..4ef39eadd6b8 100644 --- a/browser/modules/webrtcUI.jsm +++ b/browser/modules/webrtcUI.jsm @@ -66,13 +66,14 @@ function getBrowserForWindow(aContentWindow) { function handleRequest(aSubject, aTopic, aData) { let constraints = aSubject.getConstraints(); + let secure = aSubject.isSecure; let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID); contentWindow.navigator.mozGetUserMediaDevices( constraints, function (devices) { prompt(contentWindow, aSubject.callID, constraints.audio, - constraints.video || constraints.picture, devices); + constraints.video || constraints.picture, devices, secure); }, function (error) { // bug 827146 -- In the future, the UI should catch NO_DEVICES_FOUND @@ -91,7 +92,7 @@ function denyRequest(aCallID, aError) { Services.obs.notifyObservers(msg, "getUserMedia:response:deny", aCallID); } -function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevices) { +function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevices, aSecure) { let audioDevices = []; let videoDevices = []; for (let device of aDevices) { @@ -143,7 +144,8 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi label: stringBundle.getString("getUserMedia.always.label"), accessKey: stringBundle.getString("getUserMedia.always.accesskey"), callback: function () { - mainAction.callback(true); + // don't save unless secure load! + mainAction.callback(aSecure); } }, { @@ -158,6 +160,8 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi accessKey: stringBundle.getString("getUserMedia.never.accesskey"), callback: function () { denyRequest(aCallID); + // Let someone save "Never" for http sites so that they can be stopped from + // bothering you with doorhangers let perms = Services.perms; if (audioDevices.length) perms.add(uri, "microphone", perms.DENY_ACTION); diff --git a/dom/media/GetUserMediaRequest.cpp b/dom/media/GetUserMediaRequest.cpp index 2500946c35eb..c0c320240513 100644 --- a/dom/media/GetUserMediaRequest.cpp +++ b/dom/media/GetUserMediaRequest.cpp @@ -16,11 +16,13 @@ namespace dom { GetUserMediaRequest::GetUserMediaRequest( nsPIDOMWindow* aInnerWindow, const nsAString& aCallID, - const MediaStreamConstraintsInternal& aConstraints) + const MediaStreamConstraintsInternal& aConstraints, + bool aIsSecure) : mInnerWindowID(aInnerWindow->WindowID()) , mOuterWindowID(aInnerWindow->GetOuterWindow()->WindowID()) , mCallID(aCallID) , mConstraints(new MediaStreamConstraintsInternal(aConstraints)) + , mIsSecure(aIsSecure) { SetIsDOMBinding(); } @@ -59,6 +61,11 @@ uint64_t GetUserMediaRequest::InnerWindowID() return mInnerWindowID; } +bool GetUserMediaRequest::IsSecure() +{ + return mIsSecure; +} + void GetUserMediaRequest::GetConstraints(MediaStreamConstraintsInternal &result) { diff --git a/dom/media/GetUserMediaRequest.h b/dom/media/GetUserMediaRequest.h index 4932a3234f19..0393fe51bbdc 100644 --- a/dom/media/GetUserMediaRequest.h +++ b/dom/media/GetUserMediaRequest.h @@ -21,7 +21,8 @@ class GetUserMediaRequest : public nsISupports, public nsWrapperCache public: GetUserMediaRequest(nsPIDOMWindow* aInnerWindow, const nsAString& aCallID, - const MediaStreamConstraintsInternal& aConstraints); + const MediaStreamConstraintsInternal& aConstraints, + bool aIsSecure); virtual ~GetUserMediaRequest() {}; NS_DECL_CYCLE_COLLECTING_ISUPPORTS @@ -33,6 +34,7 @@ public: uint64_t WindowID(); uint64_t InnerWindowID(); + bool IsSecure(); void GetCallID(nsString& retval); void GetConstraints(MediaStreamConstraintsInternal &result); @@ -40,6 +42,7 @@ private: uint64_t mInnerWindowID, mOuterWindowID; const nsString mCallID; nsAutoPtr mConstraints; + bool mIsSecure; }; } // namespace dom diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index aac8bc6fb855..86374d147ffa 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -1459,6 +1459,12 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, (c.mFake && !Preferences::GetBool("media.navigator.permission.fake"))) { mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL); } else { + bool isHTTPS = false; + nsIURI* docURI = aWindow->GetDocumentURI(); + if (docURI) { + docURI->SchemeIs("https", &isHTTPS); + } + // Check if this site has persistent permissions. nsresult rv; nsCOMPtr permManager = @@ -1473,6 +1479,11 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, 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; @@ -1483,9 +1494,15 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, 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) && (!IsOn(c.mVideo) || videoPerm)) { + 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; @@ -1533,7 +1550,7 @@ MediaManager::GetUserMedia(JSContext* aCx, bool aPrivileged, } nsCOMPtr obs = services::GetObserverService(); nsRefPtr req = new GetUserMediaRequest(aWindow, - callID, c); + callID, c, isHTTPS); obs->NotifyObservers(req, "getUserMedia:request", nullptr); } diff --git a/dom/webidl/GetUserMediaRequest.webidl b/dom/webidl/GetUserMediaRequest.webidl index 0d3b49a5991d..0fb6ad40dcec 100644 --- a/dom/webidl/GetUserMediaRequest.webidl +++ b/dom/webidl/GetUserMediaRequest.webidl @@ -12,4 +12,5 @@ interface GetUserMediaRequest { readonly attribute unsigned long long innerWindowID; readonly attribute DOMString callID; MediaStreamConstraintsInternal getConstraints(); + readonly attribute boolean isSecure; };