Bug 993495: Update MediaManager UI r=jesup,florian,smaug
authorRandell Jesup <rjesup@jesup.org>
Wed, 16 Apr 2014 02:22:19 -0400
changeset 197250 b11545d51a15683ea88e955673d664d4b5251f51
parent 197249 547ffcbeb07a694162f6c7850887cf301c196175
child 197251 090ed8ff3c8e67890ec4fc7840089c3f6e2ea89a
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, florian, smaug
bugs993495
milestone31.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 993495: Update MediaManager UI r=jesup,florian,smaug
browser/base/content/test/general/browser_devices_get_user_media.js
browser/modules/webrtcUI.jsm
dom/media/GetUserMediaRequest.cpp
dom/media/GetUserMediaRequest.h
dom/media/MediaManager.cpp
dom/webidl/GetUserMediaRequest.webidl
--- a/browser/base/content/test/general/browser_devices_get_user_media.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media.js
@@ -766,17 +766,17 @@ function test() {
       }
     }).then(finish, ex => {
      ok(false, "Unexpected Exception: " + ex);
      finish();
     });
   }, 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";
 }
 
 
 function wait(time) {
   let deferred = Promise.defer();
   setTimeout(deferred.resolve, time);
   return deferred.promise;
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -61,23 +61,24 @@ 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 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
       // and allow the user to plug in a device, instead of immediately failing.
       denyRequest(aSubject.callID, error);
     },
     aSubject.innerWindowID);
 }
@@ -86,17 +87,17 @@ 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(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevices) {
+function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevices, aSecure) {
   let audioDevices = [];
   let videoDevices = [];
   for (let device of aDevices) {
     device = device.QueryInterface(Ci.nsIMediaDevice);
     switch (device.type) {
       case "audio":
         if (aAudioRequested)
           audioDevices.push(device);
@@ -138,31 +139,34 @@ function prompt(aContentWindow, aCallID,
     callback: function() {}
   };
 
   let secondaryActions = [
     {
       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);
       }
     },
     {
       label: stringBundle.getString("getUserMedia.denyRequest.label"),
       accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
       callback: function () {
         denyRequest(aCallID);
       }
     },
     {
       label: stringBundle.getString("getUserMedia.never.label"),
       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);
         if (videoDevices.length)
           perms.add(uri, "camera", perms.DENY_ACTION);
       }
     }
   ];
--- a/dom/media/GetUserMediaRequest.cpp
+++ b/dom/media/GetUserMediaRequest.cpp
@@ -11,21 +11,23 @@
 #include "nsCxPusher.h"
 
 namespace mozilla {
 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();
 }
 
 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)
@@ -54,16 +56,21 @@ uint64_t GetUserMediaRequest::WindowID()
   return mOuterWindowID;
 }
 
 uint64_t GetUserMediaRequest::InnerWindowID()
 {
   return mInnerWindowID;
 }
 
+bool GetUserMediaRequest::IsSecure()
+{
+  return mIsSecure;
+}
+
 void
 GetUserMediaRequest::GetConstraints(MediaStreamConstraintsInternal &result)
 {
   result = *mConstraints;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/GetUserMediaRequest.h
+++ b/dom/media/GetUserMediaRequest.h
@@ -16,33 +16,36 @@ namespace mozilla {
 namespace dom {
 class MediaStreamConstraintsInternal;
 
 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
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(GetUserMediaRequest)
 
   virtual JSObject* WrapObject(JSContext* cx)
     MOZ_OVERRIDE;
   nsISupports* GetParentObject();
 
   uint64_t WindowID();
   uint64_t InnerWindowID();
+  bool IsSecure();
   void GetCallID(nsString& retval);
   void GetConstraints(MediaStreamConstraintsInternal &result);
 
 private:
   uint64_t mInnerWindowID, mOuterWindowID;
   const nsString mCallID;
   nsAutoPtr<MediaStreamConstraintsInternal> mConstraints;
+  bool mIsSecure;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // GetUserMediaRequest_h__
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1454,43 +1454,60 @@ MediaManager::GetUserMedia(JSContext* aC
     return NS_OK;
   }
 #endif
   // XXX No full support for picture in Desktop yet (needs proper UI)
   if (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<nsIPermissionManager> permManager =
       do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     uint32_t audioPerm = nsIPermissionManager::UNKNOWN_ACTION;
     if (IsOn(c.mAudio)) {
       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;
     if (IsOn(c.mVideo)) {
       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) && (!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;
         runnable->SetContraints(c);
       }
       if (IsOn(c.mVideo) && videoPerm == nsIPermissionManager::DENY_ACTION) {
         c.mVideo.SetAsBoolean() = false;
         runnable->SetContraints(c);
@@ -1528,17 +1545,17 @@ MediaManager::GetUserMedia(JSContext* aC
       array = new nsTArray<nsString>();
       array->AppendElement(callID);
       mCallIds.Put(windowID, array);
     } else {
       array->AppendElement(callID);
     }
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
     nsRefPtr<GetUserMediaRequest> req = new GetUserMediaRequest(aWindow,
-                                                                callID, c);
+                                                                callID, c, isHTTPS);
     obs->NotifyObservers(req, "getUserMedia:request", nullptr);
   }
 
   return NS_OK;
 }
 
 nsresult
 MediaManager::GetUserMediaDevices(nsPIDOMWindow* aWindow,
--- a/dom/webidl/GetUserMediaRequest.webidl
+++ b/dom/webidl/GetUserMediaRequest.webidl
@@ -7,9 +7,10 @@
  */
 
 [NoInterfaceObject]
 interface GetUserMediaRequest {
   readonly attribute unsigned long long windowID;
   readonly attribute unsigned long long innerWindowID;
   readonly attribute DOMString callID;
   MediaStreamConstraintsInternal getConstraints();
+  readonly attribute boolean isSecure;
 };