зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1709474 send selectAudioOutput requests to app r=jib
Differential Revision: https://phabricator.services.mozilla.com/D108385
This commit is contained in:
Родитель
bd3b9693bd
Коммит
fd16b4ad67
|
@ -305,8 +305,29 @@ already_AddRefed<Promise> MediaDevices::SelectAudioOutput(
|
|||
"selectAudioOutput requires transient user activation.");
|
||||
return p.forget();
|
||||
}
|
||||
aRv.ThrowNotSupportedError("Under implementation");
|
||||
return nullptr;
|
||||
RefPtr<MediaDevices> self(this);
|
||||
MediaManager::Get()
|
||||
->SelectAudioOutput(owner, aOptions, aCallerType)
|
||||
->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[this, self, p](RefPtr<MediaDevice> aDevice) {
|
||||
nsPIDOMWindowInner* window = GetWindowIfCurrent();
|
||||
if (!window) {
|
||||
return; // Leave Promise pending after navigation by design.
|
||||
}
|
||||
MOZ_ASSERT(aDevice->mKind == dom::MediaDeviceKind::Audiooutput);
|
||||
p->MaybeResolve(
|
||||
MakeRefPtr<MediaDeviceInfo>(aDevice->mID, aDevice->mKind,
|
||||
aDevice->mName, aDevice->mGroupID));
|
||||
},
|
||||
[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();
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MediaDevices, DOMEventTargetHelper)
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "mozilla/dom/GetUserMediaRequestBinding.h"
|
||||
#include "mozilla/dom/MediaDeviceInfo.h"
|
||||
#include "mozilla/dom/MediaDevices.h"
|
||||
#include "mozilla/dom/MediaDevicesBinding.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
@ -3164,6 +3165,88 @@ RefPtr<MediaManager::DeviceSetPromise> MediaManager::EnumerateDevices(
|
|||
});
|
||||
}
|
||||
|
||||
RefPtr<MediaManager::DevicePromise> MediaManager::SelectAudioOutput(
|
||||
nsPIDOMWindowInner* aWindow, const dom::AudioOutputOptions& aOptions,
|
||||
CallerType aCallerType) {
|
||||
bool isHandlingUserInput = UserActivation::IsHandlingUserInput();
|
||||
nsCOMPtr<nsIPrincipal> principal =
|
||||
nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
|
||||
if (NS_WARN_IF(!principal)) {
|
||||
return DevicePromise::CreateAndReject(
|
||||
MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
|
||||
__func__);
|
||||
}
|
||||
// Disallow access to null principal.
|
||||
if (principal->GetIsNullPrincipal()) {
|
||||
return DevicePromise::CreateAndReject(
|
||||
MakeRefPtr<MediaMgrError>(MediaMgrError::Name::NotAllowedError),
|
||||
__func__);
|
||||
}
|
||||
ipc::PrincipalInfo principalInfo;
|
||||
nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return DevicePromise::CreateAndReject(
|
||||
MakeRefPtr<MediaMgrError>(MediaMgrError::Name::SecurityError),
|
||||
__func__);
|
||||
}
|
||||
uint64_t windowID = aWindow->WindowID();
|
||||
auto devices = MakeRefPtr<MediaDeviceSetRefCnt>();
|
||||
return EnumerateDevicesImpl(aWindow, MediaSourceEnum::Other,
|
||||
MediaSourceEnum::Other, MediaSinkEnum::Speaker,
|
||||
DeviceEnumerationType::Normal,
|
||||
DeviceEnumerationType::Normal, true, devices)
|
||||
->Then(
|
||||
GetCurrentSerialEventTarget(), __func__,
|
||||
[self = RefPtr<MediaManager>(this), windowID, devices, aOptions,
|
||||
aCallerType, isHandlingUserInput, principalInfo](bool) mutable {
|
||||
// Ensure that the window is still good.
|
||||
RefPtr<nsPIDOMWindowInner> window =
|
||||
nsGlobalWindowInner::GetInnerWindowWithId(windowID);
|
||||
if (!window) {
|
||||
LOG("SelectAudioOutput: bad window (%" PRIu64
|
||||
") in post enumeration success callback!",
|
||||
windowID);
|
||||
return DevicePromise::CreateAndReject(
|
||||
MakeRefPtr<MediaMgrError>(MediaMgrError::Name::AbortError),
|
||||
__func__);
|
||||
}
|
||||
MozPromiseHolder<DevicePromise> holder;
|
||||
RefPtr<DevicePromise> p = holder.Ensure(__func__);
|
||||
auto task = MakeRefPtr<SelectAudioOutputTask>(
|
||||
std::move(holder), windowID, aCallerType, principalInfo);
|
||||
nsString callID;
|
||||
nsresult rv = GenerateUUID(callID);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
size_t taskCount =
|
||||
self->AddTaskAndGetCount(windowID, callID, std::move(task));
|
||||
bool askPermission =
|
||||
!Preferences::GetBool("media.navigator.permission.disabled") ||
|
||||
Preferences::GetBool("media.navigator.permission.force");
|
||||
if (!askPermission) {
|
||||
self->NotifyAllowed(callID, *devices);
|
||||
} else {
|
||||
MOZ_ASSERT(window->IsSecureContext());
|
||||
auto req = MakeRefPtr<GetUserMediaRequest>(
|
||||
window, callID, std::move(devices), aOptions, true,
|
||||
isHandlingUserInput);
|
||||
if (taskCount > 1) {
|
||||
// there is at least 1 pending gUM request
|
||||
self->mPendingGUMRequest.AppendElement(req.forget());
|
||||
} else {
|
||||
nsCOMPtr<nsIObserverService> obs =
|
||||
services::GetObserverService();
|
||||
obs->NotifyObservers(req, "getUserMedia:request", nullptr);
|
||||
}
|
||||
}
|
||||
return p;
|
||||
},
|
||||
[](RefPtr<MediaMgrError> aError) {
|
||||
LOG("SelectAudioOutput: EnumerateDevicesImpl "
|
||||
"failure callback called!");
|
||||
return DevicePromise::CreateAndReject(std::move(aError), __func__);
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<AudioDeviceInfo> CopyWithNullDeviceId(AudioDeviceInfo* aDeviceInfo) {
|
||||
MOZ_ASSERT(aDeviceInfo->Preferred());
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace mozilla {
|
|||
class TaskQueue;
|
||||
class MediaTimer;
|
||||
namespace dom {
|
||||
struct AudioOutputOptions;
|
||||
struct MediaStreamConstraints;
|
||||
struct MediaTrackConstraints;
|
||||
struct MediaTrackConstraintSet;
|
||||
|
@ -238,6 +239,9 @@ class MediaManager final : public nsIMediaManagerService,
|
|||
nsresult EnumerateDevices(nsPIDOMWindowInner* aWindow,
|
||||
dom::Promise& aPromise);
|
||||
|
||||
RefPtr<DevicePromise> SelectAudioOutput(
|
||||
nsPIDOMWindowInner* aWindow, const dom::AudioOutputOptions& aOptions,
|
||||
dom::CallerType aCallerType);
|
||||
// Get the sink that corresponds to the given device id.
|
||||
// It is resposible to check if an application is
|
||||
// authorized to play audio through the requested device.
|
||||
|
|
Загрузка…
Ссылка в новой задаче