Bug 1372073 - Spoof navigator.mediaDevices.enumerateDevices. draft
authorChung-Sheng Fu <cfu@mozilla.com>
Mon, 18 Sep 2017 09:52:06 +0800
changeset 679877 99f477e10e293716ae60aa63d2a52d45a024b823
parent 679629 25aad10380b10b6efa50c2b4d97245f078d870a0
child 679878 663656d4c3a88e0baa9f872cbbc49cf1237d1f2b
push id84329
push userbmo:cfu@mozilla.com
push dateFri, 13 Oct 2017 06:08:14 +0000
bugs1372073
milestone58.0a1
Bug 1372073 - Spoof navigator.mediaDevices.enumerateDevices. MozReview-Commit-ID: HubfB6M4UM0
dom/media/MediaDevices.cpp
dom/media/MediaDevices.h
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/webidl/MediaDevices.webidl
--- a/dom/media/MediaDevices.cpp
+++ b/dom/media/MediaDevices.cpp
@@ -192,27 +192,27 @@ MediaDevices::GetUserMedia(const MediaSt
 
   aRv = MediaManager::Get()->GetUserMedia(window, aConstraints,
                                           resolver, rejecter,
 					  aCallerType);
   return p.forget();
 }
 
 already_AddRefed<Promise>
-MediaDevices::EnumerateDevices(ErrorResult &aRv)
+MediaDevices::EnumerateDevices(CallerType aCallerType, ErrorResult &aRv)
 {
   nsPIDOMWindowInner* window = GetOwner();
   nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(window);
   RefPtr<Promise> p = Promise::Create(go, aRv);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
   RefPtr<EnumDevResolver> resolver = new EnumDevResolver(p, window->WindowID());
   RefPtr<GumRejecter> rejecter = new GumRejecter(p);
 
-  aRv = MediaManager::Get()->EnumerateDevices(window, resolver, rejecter);
+  aRv = MediaManager::Get()->EnumerateDevices(window, resolver, rejecter, aCallerType);
   return p.forget();
 }
 
 NS_IMPL_ADDREF_INHERITED(MediaDevices, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(MediaDevices, DOMEventTargetHelper)
 NS_INTERFACE_MAP_BEGIN(MediaDevices)
   NS_INTERFACE_MAP_ENTRY(MediaDevices)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
--- a/dom/media/MediaDevices.h
+++ b/dom/media/MediaDevices.h
@@ -38,17 +38,17 @@ public:
   // No code needed, as MediaTrackSupportedConstraints members default to true.
   void GetSupportedConstraints(MediaTrackSupportedConstraints& aResult) {};
 
   already_AddRefed<Promise>
   GetUserMedia(const MediaStreamConstraints& aConstraints,
 	       CallerType aCallerType, ErrorResult &aRv);
 
   already_AddRefed<Promise>
-  EnumerateDevices(ErrorResult &aRv);
+  EnumerateDevices(CallerType aCallerType, ErrorResult &aRv);
 
   virtual void OnDeviceChange() override;
 
   mozilla::dom::EventHandlerNonNull* GetOndevicechange();
 
   void SetOndevicechange(mozilla::dom::EventHandlerNonNull* aCallback);
 
   NS_IMETHOD AddEventListener(const nsAString& aType,
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -2753,17 +2753,18 @@ MediaManager::EnumerateDevicesImpl(uint6
     });
   });
   return pledge.forget();
 }
 
 nsresult
 MediaManager::EnumerateDevices(nsPIDOMWindowInner* aWindow,
                                nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
-                               nsIDOMGetUserMediaErrorCallback* aOnFailure)
+                               nsIDOMGetUserMediaErrorCallback* aOnFailure,
+                               dom::CallerType aCallerType)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE(!sInShutdown, NS_ERROR_FAILURE);
   nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure(aOnFailure);
   uint64_t windowId = aWindow->WindowID();
 
   nsIPrincipal* principal = aWindow->GetExtantDoc()->NodePrincipal();
@@ -2780,17 +2781,18 @@ MediaManager::EnumerateDevices(nsPIDOMWi
     AddWindowID(windowId, windowListener);
   }
 
   // Create an inactive SourceListener to act as a placeholder, so the
   // window listener doesn't clean itself up until we're done.
   RefPtr<SourceListener> sourceListener = new SourceListener();
   windowListener->Register(sourceListener);
 
-  bool fake = Preferences::GetBool("media.navigator.streams.fake");
+  bool fake = Preferences::GetBool("media.navigator.streams.fake") ||
+              nsContentUtils::ResistFingerprinting(aCallerType);
 
   RefPtr<PledgeSourceSet> p = EnumerateDevicesImpl(windowId,
                                                    MediaSourceEnum::Camera,
                                                    MediaSourceEnum::Microphone,
                                                    fake);
   p->Then([onSuccess, windowListener, sourceListener](SourceSet*& aDevices) mutable {
     UniquePtr<SourceSet> devices(aDevices); // grab result
     DebugOnly<bool> rv = windowListener->Remove(sourceListener);
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -252,17 +252,18 @@ public:
                                const dom::MediaStreamConstraints& aConstraints,
                                nsIGetUserMediaDevicesSuccessCallback* onSuccess,
                                nsIDOMGetUserMediaErrorCallback* onError,
                                uint64_t aInnerWindowID = 0,
                                const nsAString& aCallID = nsString());
 
   nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow,
                             nsIGetUserMediaDevicesSuccessCallback* aOnSuccess,
-                            nsIDOMGetUserMediaErrorCallback* aOnFailure);
+                            nsIDOMGetUserMediaErrorCallback* aOnFailure,
+                            dom::CallerType aCallerType);
 
   nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow, dom::Promise& aPromise);
   void OnNavigation(uint64_t aWindowID);
   bool IsActivelyCapturingOrHasAPermission(uint64_t aWindowId);
 
   MediaEnginePrefs mPrefs;
 
   typedef nsTArray<RefPtr<MediaDevice>> SourceSet;
--- a/dom/webidl/MediaDevices.webidl
+++ b/dom/webidl/MediaDevices.webidl
@@ -11,14 +11,14 @@
  */
 
 [Func="Navigator::HasUserMediaSupport"]
 interface MediaDevices : EventTarget {
   [Pref="media.ondevicechange.enabled"]
   attribute EventHandler ondevicechange;
   MediaTrackSupportedConstraints getSupportedConstraints();
 
-  [Throws]
+  [Throws, NeedsCallerType]
   Promise<sequence<MediaDeviceInfo>> enumerateDevices();
 
   [Throws, NeedsCallerType]
   Promise<MediaStream> getUserMedia(optional MediaStreamConstraints constraints);
 };