Commit fd6836d5 authored by Iulian Moraru's avatar Iulian Moraru
Browse files

Backed out 10 changesets (bug 1528042) for causing build bustages on MediaDevices.cpp.

Backed out changeset 04d9fa0993ab (bug 1528042)
Backed out changeset a20768227ca6 (bug 1528042)
Backed out changeset 94066f37c5a0 (bug 1528042)
Backed out changeset cb2b433b47bd (bug 1528042)
Backed out changeset d0bfd185f0e7 (bug 1528042)
Backed out changeset 59b9147c85f0 (bug 1528042)
Backed out changeset e864d7f810b3 (bug 1528042)
Backed out changeset c0373264c89b (bug 1528042)
Backed out changeset cf689822deaf (bug 1528042)
Backed out changeset 0ac40a8f40a0 (bug 1528042)
parent f92a6be7
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -1321,15 +1321,11 @@ void Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
                                NavigatorUserMediaErrorCallback& aOnError,
                                CallerType aCallerType, ErrorResult& aRv) {
  MOZ_ASSERT(NS_IsMainThread());

  if (!mWindow || !mWindow->IsFullyActive()) {
    aRv.ThrowInvalidStateError("The document is not fully active.");
    return;
  }
  GetMediaDevices(aRv);
  if (aRv.Failed()) {
    return;
  }
  MOZ_ASSERT(mMediaDevices);
  if (Document* doc = mWindow->GetExtantDoc()) {
    if (!mWindow->IsSecureContext()) {
      doc->SetUseCounter(eUseCounter_custom_MozGetUserMediaInsec);
@@ -1343,7 +1339,7 @@ void Navigator::MozGetUserMedia(const MediaStreamConstraints& aConstraints,
                                  "audio and/or video is required"),
        __func__);
  } else {
    sp = mMediaDevices->GetUserMedia(mWindow, aConstraints, aCallerType);
    sp = MediaManager::Get()->GetUserMedia(mWindow, aConstraints, aCallerType);
  }
  RefPtr<NavigatorUserMediaSuccessCallback> onsuccess(&aOnSuccess);
  RefPtr<NavigatorUserMediaErrorCallback> onerror(&aOnError);
+62 −70
Original line number Diff line number Diff line
@@ -98,32 +98,7 @@ already_AddRefed<Promise> MediaDevices::GetUserMedia(
      }
    }
  }
  RefPtr<MediaDevices> self(this);
  GetUserMedia(owner, aConstraints, aCallerType)
      ->Then(
          GetCurrentSerialEventTarget(), __func__,
          [this, self, p](RefPtr<DOMMediaStream>&& aStream) {
            if (!GetWindowIfCurrent()) {
              return;  // Leave Promise pending after navigation by design.
            }
            p->MaybeResolve(std::move(aStream));
          },
          [this, self, p](const RefPtr<MediaMgrError>& error) {
            nsPIDOMWindowInner* window = GetWindowIfCurrent();
            if (!window) {
              return;  // Leave Promise pending after navigation by design.
            }
            error->Reject(p);
          });
  return p.forget();
}

RefPtr<MediaDevices::StreamPromise> MediaDevices::GetUserMedia(
    nsPIDOMWindowInner* aWindow, const MediaStreamConstraints& aConstraints,
    CallerType aCallerType) {
  MOZ_ASSERT(NS_IsMainThread());
  bool haveFake = aConstraints.mFake.WasPassed() && aConstraints.mFake.Value();
  const OwningBooleanOrMediaTrackConstraints& video = aConstraints.mVideo;
  const OwningBooleanOrMediaTrackConstraints& audio = aConstraints.mAudio;
  bool isMicrophone =
      !haveFake &&
@@ -135,26 +110,32 @@ RefPtr<MediaDevices::StreamPromise> MediaDevices::GetUserMedia(
      (video.IsBoolean()
           ? video.GetAsBoolean()
           : !video.GetAsMediaTrackConstraints().mMediaSource.WasPassed());

  RefPtr<MediaDevices> self(this);
  return MediaManager::Get()
      ->GetUserMedia(aWindow, aConstraints, aCallerType)
  MediaManager::Get()
      ->GetUserMedia(owner, aConstraints, aCallerType)
      ->Then(
          GetCurrentSerialEventTarget(), __func__,
          [this, self, isMicrophone,
          [this, self, p, isMicrophone,
           isCamera](RefPtr<DOMMediaStream>&& aStream) {
            if (!GetWindowIfCurrent()) {
              return;  // Leave Promise pending after navigation by design.
            }
            if (isMicrophone) {
              mCanExposeMicrophoneInfo = true;
            }
            if (isCamera) {
              mCanExposeCameraInfo = true;
            }
            return StreamPromise::CreateAndResolve(std::move(aStream),
                                                   __func__);
            p->MaybeResolve(std::move(aStream));
          },
          [](RefPtr<MediaMgrError>&& aError) {
            return StreamPromise::CreateAndReject(std::move(aError), __func__);
          [this, self, p](const RefPtr<MediaMgrError>& error) {
            nsPIDOMWindowInner* window = GetWindowIfCurrent();
            if (!window) {
              return;  // Leave Promise pending after navigation by design.
            }
            error->Reject(p);
          });
  return p.forget();
}

already_AddRefed<Promise> MediaDevices::EnumerateDevices(ErrorResult& aRv) {
@@ -257,7 +238,6 @@ RefPtr<MediaDeviceSetRefCnt> MediaDevices::FilterExposedDevices(
    // they are exposed only when explicitly and individually allowed by the
    // user.
  }
  bool legacy = StaticPrefs::media_devices_enumerate_legacy_enabled();
  bool outputIsDefault = true;  // First output is the default.
  bool haveDefaultOutput = false;
  nsTHashSet<nsString> exposedMicrophoneGroupIds;
@@ -270,17 +250,13 @@ RefPtr<MediaDeviceSetRefCnt> MediaDevices::FilterExposedDevices(
        if (mCanExposeMicrophoneInfo) {
          exposedMicrophoneGroupIds.Insert(device->mRawGroupID);
        }
        if (!mCanExposeMicrophoneInfo && !legacy) {
          dropMics = true;
        }
        // Reducing to one mic or cam device when not mCanExposeMicrophoneInfo
        // or not mCanExposeCameraInfo is bug 1528042.
        break;
      case MediaDeviceKind::Videoinput:
        if (dropCams) {
          continue;
        }
        if (!mCanExposeCameraInfo && !legacy) {
          dropCams = true;
        }
        break;
      case MediaDeviceKind::Audiooutput:
        if (dropSpeakers ||
@@ -325,23 +301,6 @@ RefPtr<MediaDeviceSetRefCnt> MediaDevices::FilterExposedDevices(
  return exposed;
}

bool MediaDevices::CanExposeInfo(MediaDeviceKind aKind) const {
  switch (aKind) {
    case MediaDeviceKind::Audioinput:
      return mCanExposeMicrophoneInfo;
    case MediaDeviceKind::Videoinput:
      return mCanExposeCameraInfo;
    case MediaDeviceKind::Audiooutput:
      // Assumes caller has used FilterExposedDevices()
      return true;
    case MediaDeviceKind::EndGuard_:
      MOZ_ASSERT_UNREACHABLE("unexpected MediaDeviceKind");
      return false;
      // Avoid `default:` so that `-Wswitch` catches missing enumerators at
      // compile time.
  }
};

bool MediaDevices::ShouldQueueDeviceChange(
    const MediaDeviceSet& aExposedDevices) const {
  if (!mLastPhysicalDevices) {  // SetupDeviceChangeListener not complete
@@ -358,6 +317,22 @@ bool MediaDevices::ShouldQueueDeviceChange(
  // exposed by enumerateDevices() (but multiple devices are currently exposed
  // - bug 1528042).  "devicechange" events are not queued when the number
  // of such devices changes but remains non-zero.
  auto CanExposeNonZeroChanges = [this](MediaDeviceKind aKind) {
    switch (aKind) {
      case MediaDeviceKind::Audioinput:
        return mCanExposeMicrophoneInfo;
      case MediaDeviceKind::Videoinput:
        return mCanExposeCameraInfo;
      case MediaDeviceKind::Audiooutput:
        return true;
      case MediaDeviceKind::EndGuard_:
        break;
        // Avoid `default:` so that `-Wswitch` catches missing enumerators at
        // compile time.
    }
    MOZ_ASSERT_UNREACHABLE("unexpected MediaDeviceKind");
    return false;
  };
  while (exposed < exposedEnd && last < lastEnd) {
    // First determine whether there is at least one device of the same kind
    // in both `aExposedDevices` and `lastExposedDevices`.
@@ -369,7 +344,7 @@ bool MediaDevices::ShouldQueueDeviceChange(
      return true;
    }
    // `exposed` and `last` have matching kind.
    if (CanExposeInfo(kind)) {
    if (CanExposeNonZeroChanges(kind)) {
      // Queue "devicechange" if there has been any change in devices of this
      // exposed kind.  ID and kind uniquely identify a device.
      if ((*exposed)->mRawID != (*last)->mRawID) {
@@ -424,16 +399,37 @@ void MediaDevices::ResumeEnumerateDevices(

void MediaDevices::ResolveEnumerateDevicesPromise(
    Promise* aPromise, const LocalMediaDeviceSet& aDevices) const {
  nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
  auto windowId = window->WindowID();
  nsTArray<RefPtr<MediaDeviceInfo>> infos;
  bool legacy = StaticPrefs::media_devices_enumerate_legacy_enabled();

  bool allowLabel =
      aDevices.Length() == 0 ||
      MediaManager::Get()->IsActivelyCapturingOrHasAPermission(windowId);
  for (const RefPtr<LocalMediaDevice>& device : aDevices) {
    bool exposeInfo = CanExposeInfo(device->Kind()) || legacy;
    bool exposeLabel = legacy ? DeviceInformationCanBeExposed() : exposeInfo;
    infos.AppendElement(MakeRefPtr<MediaDeviceInfo>(
        exposeInfo ? device->mID : u""_ns, device->Kind(),
        exposeLabel ? device->mName : u""_ns,
        exposeInfo ? device->mGroupID : u""_ns));
    nsString label;
    MOZ_ASSERT(device->Kind() < MediaDeviceKind::EndGuard_);
    switch (device->Kind()) {
      case MediaDeviceKind::Audioinput:
      case MediaDeviceKind::Videoinput:
        // Include name only if page currently has a gUM stream
        // active or persistent permissions (audio or video) have
        // been granted.  See bug 1528042 for using
        // mCanExposeMicrophoneInfo.
        if (allowLabel || Preferences::GetBool(
                              "media.navigator.permission.disabled", false)) {
          label = device->mName;
        }
        break;
      case MediaDeviceKind::Audiooutput:
        label = device->mName;
        break;
      case MediaDeviceKind::EndGuard_:
        break;
        // Avoid `default:` so that `-Wswitch` catches missing
        // enumerators at compile time.
    }
    infos.AppendElement(MakeRefPtr<MediaDeviceInfo>(device->mID, device->Kind(),
                                                    label, device->mGroupID));
  }
  aPromise->MaybeResolve(std::move(infos));
}
@@ -788,10 +784,6 @@ void MediaDevices::EventListenerAdded(nsAtom* aType) {
  SetupDeviceChangeListener();
}

bool MediaDevices::DeviceInformationCanBeExposed() const {
  return mCanExposeCameraInfo || mCanExposeMicrophoneInfo;
}

JSObject* MediaDevices::WrapObject(JSContext* aCx,
                                   JS::Handle<JSObject*> aGivenProto) {
  return MediaDevices_Binding::Wrap(aCx, this, aGivenProto);
+0 −12
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/UseCounter.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/MediaDeviceInfoBinding.h"
#include "nsCOMPtr.h"
#include "nsID.h"
#include "nsISupports.h"
@@ -24,7 +23,6 @@ namespace mozilla {
class LocalMediaDevice;
class MediaDevice;
class MediaMgrError;
class DOMMediaStream;
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
class MozPromise;

@@ -43,8 +41,6 @@ struct AudioOutputOptions;

class MediaDevices final : public DOMEventTargetHelper {
 public:
  using StreamPromise =
      MozPromise<RefPtr<DOMMediaStream>, RefPtr<MediaMgrError>, true>;
  using SinkInfoPromise = MozPromise<RefPtr<AudioDeviceInfo>, nsresult, true>;

  explicit MediaDevices(nsPIDOMWindowInner* aWindow);
@@ -62,10 +58,6 @@ class MediaDevices final : public DOMEventTargetHelper {
      const MediaStreamConstraints& aConstraints, CallerType aCallerType,
      ErrorResult& aRv);

  RefPtr<StreamPromise> GetUserMedia(nsPIDOMWindowInner* aWindow,
                                     const MediaStreamConstraints& aConstraints,
                                     CallerType aCallerType);

  already_AddRefed<Promise> EnumerateDevices(ErrorResult& aRv);

  already_AddRefed<Promise> GetDisplayMedia(
@@ -111,14 +103,10 @@ class MediaDevices final : public DOMEventTargetHelper {
      RefPtr<const MediaDeviceSetRefCnt> aExposedDevices) const;
  RefPtr<MediaDeviceSetRefCnt> FilterExposedDevices(
      const MediaDeviceSet& aDevices) const;
  bool CanExposeInfo(MediaDeviceKind aKind) const;
  bool ShouldQueueDeviceChange(const MediaDeviceSet& aExposedDevices) const;
  void ResolveEnumerateDevicesPromise(
      Promise* aPromise, const LocalMediaDeviceSet& aDevices) const;

  // See https://www.w3.org/TR/mediacapture-streams/#device-information-exposure
  bool DeviceInformationCanBeExposed() const;

  nsTHashSet<nsString> mExplicitlyGrantedAudioOutputRawIds;
  nsTArray<RefPtr<Promise>> mPendingEnumerateDevicesPromises;
  // Set only once, if and when required.
+9 −11
Original line number Diff line number Diff line
@@ -1869,8 +1869,15 @@ RefPtr<MediaManager::DeviceSetPromise> MediaManager::EnumerateRawDevices(
        Maybe<MediaDeviceSet> speakers;
        RefPtr devices = new MediaDeviceSetRefCnt();

        // Enumerate microphones first, then cameras, then speakers, since the
        // enumerateDevices() algorithm expects them listed in that order.
        if (hasVideo) {
          videoBackend = hasFakeCams ? fakeBackend : realBackend;
          MediaDeviceSet videos;
          LOG("EnumerateRawDevices Task: Getting video sources with %s backend",
              videoBackend == fakeBackend ? "fake" : "real");
          GetMediaDevices(videoBackend, aVideoInputType, videos,
                          videoLoopDev.get());
          devices->AppendElements(videos);
        }
        if (hasAudio) {
          audioBackend = hasFakeMics ? fakeBackend : realBackend;
          MediaDeviceSet audios;
@@ -1885,15 +1892,6 @@ RefPtr<MediaManager::DeviceSetPromise> MediaManager::EnumerateRawDevices(
          }
          devices->AppendElements(audios);
        }
        if (hasVideo) {
          videoBackend = hasFakeCams ? fakeBackend : realBackend;
          MediaDeviceSet videos;
          LOG("EnumerateRawDevices Task: Getting video sources with %s backend",
              videoBackend == fakeBackend ? "fake" : "real");
          GetMediaDevices(videoBackend, aVideoInputType, videos,
                          videoLoopDev.get());
          devices->AppendElements(videos);
        }
        if (hasAudioOutput) {
          MediaDeviceSet outputs;
          MOZ_ASSERT(realBackend);
+16 −38
Original line number Diff line number Diff line
@@ -175,9 +175,9 @@ function addLoadEvent() {}

/* import-globals-from /testing/mochitest/tests/SimpleTest/SimpleTest.js */
/* import-globals-from head.js */
const scriptsReady = Promise.all(
var scriptsReady = Promise.all(
  ["/tests/SimpleTest/SimpleTest.js", "head.js"].map(script => {
    const el = document.createElement("script");
    var el = document.createElement("script");
    el.src = script;
    document.head.appendChild(el);
    return new Promise(r => (el.onload = r));
@@ -189,12 +189,7 @@ function createHTML(options) {
}

async function runTest(testFunction) {
  await Promise.all([
    scriptsReady,
    SpecialPowers.pushPrefEnv({
      set: [["media.navigator.permission.fake", true]],
    }),
  ]);
  await scriptsReady;
  await runTestWhenReady(async (...args) => {
    await testFunction(...args);
    await noGum();
@@ -203,39 +198,22 @@ async function runTest(testFunction) {

// noGum - Helper to detect whether active guM tracks still exist.
//
// Note it relies on the permissions system to detect active tracks, so it won't
// catch getUserMedia use while media.navigator.permission.disabled is true
// (which is common in automation), UNLESS we set
// media.navigator.permission.fake to true also, like runTest() does above.
// It relies on the fact that, by spec, device labels from enumerateDevices are
// only visible during active gum calls. They're also visible when persistent
// permissions are granted, so turn off media.navigator.permission.disabled
// (which is normally on otherwise in our tests). Lastly, we must turn on
// media.navigator.permission.fake otherwise fake devices don't count as active.
async function noGum() {
  await pushPrefs(
    ["media.navigator.permission.disabled", false],
    ["media.navigator.permission.fake", true]
  );
  if (!navigator.mediaDevices) {
    // No mediaDevices, then gUM cannot have been called either.
    return;
  }
  const mediaManagerService = Cc[
    "@mozilla.org/mediaManagerService;1"
  ].getService(Ci.nsIMediaManagerService);

  const hasCamera = {};
  const hasMicrophone = {};
  mediaManagerService.mediaCaptureWindowState(
    window,
    hasCamera,
    hasMicrophone,
    {},
    {},
    {},
    {},
    false
  );
  is(
    hasCamera.value,
    mediaManagerService.STATE_NOCAPTURE,
    "Test must leave no active camera gUM tracks behind."
  );
  is(
    hasMicrophone.value,
    mediaManagerService.STATE_NOCAPTURE,
    "Test must leave no active microphone gUM tracks behind."
  );
  const [device] = await navigator.mediaDevices.enumerateDevices();
  if (device) {
    is(device.label, "", "Test must leave no active gUM streams behind.");
  }
}
Loading