Bug 1497141 - FeaturePolicy: camera, r=jib
authorAndrea Marchesini <amarchesini@mozilla.com>
Wed, 10 Oct 2018 16:54:17 +0200
changeset 499009 7757f7200917569e8630fb021ecb06d2425e20ed
parent 499008 41506b1cb3857f99ffdf9dcb7291adb066265172
child 499010 a3f04193768a01d9dbbfa499e208e37717a4347e
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjib
bugs1497141
milestone64.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 1497141 - FeaturePolicy: camera, r=jib
dom/media/MediaManager.cpp
dom/security/featurepolicy/FeaturePolicyUtils.cpp
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -39,16 +39,17 @@
 #include "mozilla/MozPromise.h"
 #include "mozilla/NullPrincipal.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Types.h"
 #include "mozilla/PeerIdentity.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/FeaturePolicyUtils.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/MediaStreamBinding.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/GetUserMediaRequestBinding.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/MediaDevices.h"
 #include "mozilla/Base64.h"
 #include "mozilla/ipc/BackgroundChild.h"
@@ -2680,16 +2681,21 @@ MediaManager::GetUserMedia(nsPIDOMWindow
   }
 
   nsCOMPtr<nsIPrincipal> principal =
     nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
   if (NS_WARN_IF(!principal)) {
     return NS_ERROR_FAILURE;
   }
 
+  nsIDocument* doc = aWindow->GetExtantDoc();
+  if (NS_WARN_IF(!doc)) {
+    return NS_ERROR_FAILURE;
+  }
+
   // This principal needs to be sent to different threads and so via IPC.
   // For this reason it's better to convert it to PrincipalInfo right now.
   ipc::PrincipalInfo principalInfo;
   rv = PrincipalToPrincipalInfo(principal, &principalInfo);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -2882,23 +2888,29 @@ MediaManager::GetUserMedia(nsPIDOMWindow
         rv = permManager->TestExactPermissionFromPrincipal(
           principal, "microphone", &audioPerm);
         NS_ENSURE_SUCCESS(rv, rv);
       }
     }
 
     uint32_t videoPerm = nsIPermissionManager::UNKNOWN_ACTION;
     if (IsOn(c.mVideo)) {
-      if (videoType == MediaSourceEnum::Camera &&
-          Preferences::GetBool("media.getusermedia.camera.deny", false)) {
-        videoPerm = nsIPermissionManager::DENY_ACTION;
+      if (videoType == MediaSourceEnum::Camera) {
+        if (Preferences::GetBool("media.getusermedia.camera.deny", false) ||
+            !dom::FeaturePolicyUtils::IsFeatureAllowed(doc,
+                                                       NS_LITERAL_STRING("camera"))) {
+          videoPerm = nsIPermissionManager::DENY_ACTION;
+        } else {
+          rv = permManager->TestExactPermissionFromPrincipal(
+            principal, "camera", &videoPerm);
+          NS_ENSURE_SUCCESS(rv, rv);
+        }
       } else {
         rv = permManager->TestExactPermissionFromPrincipal(
-          principal, videoType == MediaSourceEnum::Camera ? "camera" : "screen",
-          &videoPerm);
+          principal, "screen", &videoPerm);
         NS_ENSURE_SUCCESS(rv, rv);
       }
     }
 
     if ((!IsOn(c.mAudio) && !IsOn(c.mVideo)) ||
         (IsOn(c.mAudio) && audioPerm == nsIPermissionManager::DENY_ACTION) ||
         (IsOn(c.mVideo) && videoPerm == nsIPermissionManager::DENY_ACTION)) {
       RefPtr<MediaStreamError> error =
@@ -4123,35 +4135,51 @@ MediaManager::IsActivelyCapturingOrHasAP
   }
 
   // Or are persistent permissions (audio or video) granted?
 
   auto* window = nsGlobalWindowInner::GetInnerWindowWithId(aWindowId);
   if (NS_WARN_IF(!window) || NS_WARN_IF(!window->GetPrincipal())) {
     return false;
   }
+
+  nsIDocument* doc = window->GetExtantDoc();
+  if (NS_WARN_IF(!doc)) {
+    return false;
+  }
+
+  nsIPrincipal* principal = window->GetPrincipal();
+  if (NS_WARN_IF(!principal)) {
+    return false;
+  }
+
   // Check if this site has persistent permissions.
   nsresult rv;
   nsCOMPtr<nsIPermissionManager> mgr =
     do_GetService(NS_PERMISSIONMANAGER_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false; // no permission manager no permissions!
   }
 
   uint32_t audio = nsIPermissionManager::UNKNOWN_ACTION;
   uint32_t video = nsIPermissionManager::UNKNOWN_ACTION;
   {
-    auto* principal = window->GetPrincipal();
     rv = mgr->TestExactPermissionFromPrincipal(principal, "microphone", &audio);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return false;
     }
-    rv = mgr->TestExactPermissionFromPrincipal(principal, "camera", &video);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return false;
+
+    if (!dom::FeaturePolicyUtils::IsFeatureAllowed(doc,
+                                                   NS_LITERAL_STRING("camera"))) {
+      video = nsIPermissionManager::DENY_ACTION;
+    } else {
+      rv = mgr->TestExactPermissionFromPrincipal(principal, "camera", &video);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return false;
+      }
     }
   }
   return audio == nsIPermissionManager::ALLOW_ACTION ||
          video == nsIPermissionManager::ALLOW_ACTION;
 }
 
 SourceListener::SourceListener()
   : mStopped(false)
--- a/dom/security/featurepolicy/FeaturePolicyUtils.cpp
+++ b/dom/security/featurepolicy/FeaturePolicyUtils.cpp
@@ -21,17 +21,16 @@ struct FeatureMap {
 };
 
 /*
  * IMPORTANT: Do not change this list without review from a DOM peer _AND_ a
  * DOM Security peer!
  */
 static FeatureMap sSupportedFeatures[] = {
   { "autoplay", FeatureMap::eAll },
-  // TODO: not supported yet!!!
   { "camera", FeatureMap::eAll  },
   { "encrypted-media", FeatureMap::eAll  },
   { "fullscreen", FeatureMap::eAll  },
   { "geolocation", FeatureMap::eAll  },
   // TODO: not supported yet!!!
   { "microphone", FeatureMap::eAll  },
   { "midi", FeatureMap::eAll  },
   { "payment", FeatureMap::eAll  },