dom/media/MediaDevices.h
author Marian-Vasile Laza <mlaza@mozilla.com>
Tue, 30 Nov 2021 23:30:59 +0200
changeset 600683 15c1262d6e8f4524fa63dcc9cc2572038ffb3a92
parent 595402 3e347b20ef3618773cfdd2746195aaba8fe9e556
permissions -rw-r--r--
Backed out 6 changesets (bug 1715892, bug 1719735) for causing bc test failures. CLOSED TREE Backed out changeset 196952bd8c9c (bug 1715892) Backed out changeset 9105fe01c025 (bug 1715892) Backed out changeset 4c15d1a24ccd (bug 1715892) Backed out changeset 2c328b84285f (bug 1715892) Backed out changeset 8fcdcdf44b62 (bug 1719735) Backed out changeset c48f398e301f (bug 1719735)

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_dom_MediaDevices_h
#define mozilla_dom_MediaDevices_h

#include "MediaEventSource.h"
#include "js/RootingAPI.h"
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/DOMEventTargetHelper.h"
#include "mozilla/UseCounter.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsCOMPtr.h"
#include "nsID.h"
#include "nsISupports.h"
#include "nsITimer.h"
#include "nsTHashSet.h"

class AudioDeviceInfo;

namespace mozilla {

template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
class MozPromise;

namespace dom {

class Promise;
struct MediaStreamConstraints;
struct DisplayMediaStreamConstraints;
struct MediaTrackSupportedConstraints;
struct AudioOutputOptions;

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

  explicit MediaDevices(nsPIDOMWindowInner* aWindow);

  NS_DECL_ISUPPORTS_INHERITED
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaDevices, DOMEventTargetHelper)

  JSObject* WrapObject(JSContext* cx,
                       JS::Handle<JSObject*> aGivenProto) override;

  // 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);

  already_AddRefed<Promise> GetDisplayMedia(
      const DisplayMediaStreamConstraints& aConstraints, CallerType aCallerType,
      ErrorResult& aRv);

  already_AddRefed<Promise> SelectAudioOutput(
      const AudioOutputOptions& aOptions, CallerType aCallerType,
      ErrorResult& aRv);

  // Get the sink that corresponds to the given device id.
  // The returned promise will be resolved with the device
  // information if the aDeviceId matches a device that would be exposed by
  // enumerateDevices().
  // The promise will be rejected with NS_ERROR_NOT_AVAILABLE if aDeviceId
  // does not match any exposed device.
  RefPtr<SinkInfoPromise> GetSinkDevice(const nsString& aDeviceId);

  // Called when MediaManager encountered a change in its device lists.
  void OnDeviceChange();

  void SetupDeviceChangeListener();

  mozilla::dom::EventHandlerNonNull* GetOndevicechange();
  void SetOndevicechange(mozilla::dom::EventHandlerNonNull* aCallback);

  void EventListenerAdded(nsAtom* aType) override;
  using DOMEventTargetHelper::EventListenerAdded;

  void BackgroundStateChanged() { MaybeResumeDeviceExposure(); }
  void WindowResumed() { MaybeResumeDeviceExposure(); }
  void BrowserWindowBecameActive() { MaybeResumeDeviceExposure(); }

 private:
  class GumResolver;
  class EnumDevResolver;
  class GumRejecter;

  virtual ~MediaDevices();
  void MaybeResumeDeviceExposure();
  void ResumeEnumerateDevices(RefPtr<Promise> aPromise);

  nsTHashSet<nsString> mExplicitlyGrantedAudioOutputIds;
  nsTArray<RefPtr<Promise>> mPendingEnumerateDevicesPromises;
  nsCOMPtr<nsITimer> mFuzzTimer;

  // Connect/Disconnect on main thread only
  MediaEventListener mDeviceChangeListener;
  bool mIsDeviceChangeListenerSetUp = false;
  bool mCanExposeMicrophoneInfo = false;

  void RecordAccessTelemetry(const UseCounter counter) const;
};

}  // namespace dom
}  // namespace mozilla

#endif  // mozilla_dom_MediaDevices_h