Bug 1487204 - Add platform support for calling authorizationStatusForMediaType and requestAccessForMediaType from JS r=spohl
Add a new interface nsIOSPermissionRequest for querying the staus of access permissions for audio/video media capture and requesting access to audio/video capture devices. Provides an implementation for macOS 10.14 and a default implementation (nsOSPermissionRequestBase) for earlier macOS versions and other platforms. The default implementation always returns status indicating access is allowed. Differential Revision: https://phabricator.services.mozilla.com/D4601
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
#include "nsURILoader.h"
|
#include "nsURILoader.h"
|
||||||
#include "nsDocLoader.h"
|
#include "nsDocLoader.h"
|
||||||
#include "nsOSHelperAppService.h"
|
#include "nsOSHelperAppService.h"
|
||||||
|
#include "nsOSPermissionRequest.h"
|
||||||
#include "nsExternalProtocolHandler.h"
|
#include "nsExternalProtocolHandler.h"
|
||||||
#include "nsPrefetchService.h"
|
#include "nsPrefetchService.h"
|
||||||
#include "nsOfflineCacheUpdate.h"
|
#include "nsOfflineCacheUpdate.h"
|
||||||
@@ -91,6 +92,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsExternalURLHandlerService)
|
|||||||
#endif
|
#endif
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ContentHandlerService, Init)
|
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ContentHandlerService, Init)
|
||||||
|
|
||||||
|
// OS access permissions
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsOSPermissionRequest)
|
||||||
|
|
||||||
// session history
|
// session history
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHEntry)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSHEntry)
|
||||||
|
|
||||||
@@ -106,6 +110,7 @@ NS_DEFINE_NAMED_CID(NS_PREFETCHSERVICE_CID);
|
|||||||
NS_DEFINE_NAMED_CID(NS_OFFLINECACHEUPDATESERVICE_CID);
|
NS_DEFINE_NAMED_CID(NS_OFFLINECACHEUPDATESERVICE_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_OFFLINECACHEUPDATE_CID);
|
NS_DEFINE_NAMED_CID(NS_OFFLINECACHEUPDATE_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_LOCALHANDLERAPP_CID);
|
NS_DEFINE_NAMED_CID(NS_LOCALHANDLERAPP_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(NS_OSPERMISSIONREQUEST_CID);
|
||||||
#ifdef MOZ_ENABLE_DBUS
|
#ifdef MOZ_ENABLE_DBUS
|
||||||
NS_DEFINE_NAMED_CID(NS_DBUSHANDLERAPP_CID);
|
NS_DEFINE_NAMED_CID(NS_DBUSHANDLERAPP_CID);
|
||||||
#endif
|
#endif
|
||||||
@@ -125,6 +130,7 @@ const mozilla::Module::CIDEntry kDocShellCIDs[] = {
|
|||||||
{ &kNS_URI_LOADER_CID, false, nullptr, nsURILoaderConstructor },
|
{ &kNS_URI_LOADER_CID, false, nullptr, nsURILoaderConstructor },
|
||||||
{ &kNS_DOCUMENTLOADER_SERVICE_CID, false, nullptr, nsDocLoaderConstructor },
|
{ &kNS_DOCUMENTLOADER_SERVICE_CID, false, nullptr, nsDocLoaderConstructor },
|
||||||
{ &kNS_EXTERNALHELPERAPPSERVICE_CID, false, nullptr, nsOSHelperAppServiceConstructor },
|
{ &kNS_EXTERNALHELPERAPPSERVICE_CID, false, nullptr, nsOSHelperAppServiceConstructor },
|
||||||
|
{ &kNS_OSPERMISSIONREQUEST_CID, false, nullptr, nsOSPermissionRequestConstructor },
|
||||||
{ &kNS_CONTENTHANDLERSERVICE_CID, false, nullptr, ContentHandlerServiceConstructor,
|
{ &kNS_CONTENTHANDLERSERVICE_CID, false, nullptr, ContentHandlerServiceConstructor,
|
||||||
mozilla::Module::CONTENT_PROCESS_ONLY },
|
mozilla::Module::CONTENT_PROCESS_ONLY },
|
||||||
{ &kNS_EXTERNALPROTOCOLHANDLER_CID, false, nullptr, nsExternalProtocolHandlerConstructor },
|
{ &kNS_EXTERNALPROTOCOLHANDLER_CID, false, nullptr, nsExternalProtocolHandlerConstructor },
|
||||||
@@ -197,6 +203,7 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = {
|
|||||||
{ NS_SHENTRY_CONTRACTID, &kNS_SHENTRY_CID },
|
{ NS_SHENTRY_CONTRACTID, &kNS_SHENTRY_CID },
|
||||||
{ NS_LOADCONTEXT_CONTRACTID, &kNS_LOADCONTEXT_CID },
|
{ NS_LOADCONTEXT_CONTRACTID, &kNS_LOADCONTEXT_CID },
|
||||||
{ NS_PRIVATELOADCONTEXT_CONTRACTID, &kNS_PRIVATELOADCONTEXT_CID },
|
{ NS_PRIVATELOADCONTEXT_CONTRACTID, &kNS_PRIVATELOADCONTEXT_CID },
|
||||||
|
{ NS_OSPERMISSIONREQUEST_CONTRACTID, &kNS_OSPERMISSIONREQUEST_CID, mozilla::Module::MAIN_PROCESS_ONLY },
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,14 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
SOURCES += ['CoreLocationLocationProvider.mm']
|
SOURCES += [
|
||||||
|
'CoreLocationLocationProvider.mm',
|
||||||
|
'nsOSPermissionRequest.mm',
|
||||||
|
]
|
||||||
|
|
||||||
|
EXPORTS += [
|
||||||
|
'nsOSPermissionRequest.h',
|
||||||
|
]
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
|
||||||
|
|||||||
30
dom/system/mac/nsOSPermissionRequest.h
Normal file
30
dom/system/mac/nsOSPermissionRequest.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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 nsOSPermissionRequest_h__
|
||||||
|
#define nsOSPermissionRequest_h__
|
||||||
|
|
||||||
|
#include "nsOSPermissionRequestBase.h"
|
||||||
|
|
||||||
|
class nsOSPermissionRequest : public nsOSPermissionRequestBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsOSPermissionRequest() {};
|
||||||
|
|
||||||
|
NS_IMETHOD GetAudioCapturePermissionState(uint16_t* aAudio) override;
|
||||||
|
|
||||||
|
NS_IMETHOD GetVideoCapturePermissionState(uint16_t* aVideo) override;
|
||||||
|
|
||||||
|
NS_IMETHOD RequestVideoCapturePermission(JSContext* aCx,
|
||||||
|
mozilla::dom::Promise** aPromiseOut)
|
||||||
|
override;
|
||||||
|
|
||||||
|
NS_IMETHOD RequestAudioCapturePermission(JSContext* aCx,
|
||||||
|
mozilla::dom::Promise** aPromiseOut)
|
||||||
|
override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
77
dom/system/mac/nsOSPermissionRequest.mm
Normal file
77
dom/system/mac/nsOSPermissionRequest.mm
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "nsOSPermissionRequest.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
#include "nsCocoaFeatures.h"
|
||||||
|
#include "nsCocoaUtils.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
|
||||||
|
using mozilla::dom::Promise;
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequest::GetAudioCapturePermissionState(uint16_t* aAudio)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aAudio);
|
||||||
|
|
||||||
|
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||||
|
return nsOSPermissionRequestBase::GetAudioCapturePermissionState(aAudio);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsCocoaUtils::GetAudioCapturePermissionState(*aAudio);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequest::GetVideoCapturePermissionState(uint16_t* aVideo)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aVideo);
|
||||||
|
|
||||||
|
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||||
|
return nsOSPermissionRequestBase::GetVideoCapturePermissionState(aVideo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsCocoaUtils::GetVideoCapturePermissionState(*aVideo);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequest::RequestVideoCapturePermission(JSContext* aCx,
|
||||||
|
Promise** aPromiseOut)
|
||||||
|
{
|
||||||
|
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||||
|
return nsOSPermissionRequestBase::RequestVideoCapturePermission(aCx, aPromiseOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Promise> promiseHandle;
|
||||||
|
nsresult rv = GetPromise(aCx, promiseHandle);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = nsCocoaUtils::RequestVideoCapturePermission(promiseHandle);
|
||||||
|
promiseHandle.forget(aPromiseOut);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequest::RequestAudioCapturePermission(JSContext* aCx,
|
||||||
|
Promise** aPromiseOut)
|
||||||
|
{
|
||||||
|
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||||
|
return nsOSPermissionRequestBase::RequestAudioCapturePermission(aCx, aPromiseOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Promise> promiseHandle;
|
||||||
|
nsresult rv = GetPromise(aCx, promiseHandle);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = nsCocoaUtils::RequestAudioCapturePermission(promiseHandle);
|
||||||
|
promiseHandle.forget(aPromiseOut);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
@@ -20,6 +20,9 @@ with Files("windows/*LocationProvider*"):
|
|||||||
with Files("mac/*LocationProvider*"):
|
with Files("mac/*LocationProvider*"):
|
||||||
BUG_COMPONENT = ("Core", "Geolocation")
|
BUG_COMPONENT = ("Core", "Geolocation")
|
||||||
|
|
||||||
|
with Files("mac/*OSPermissionRequest*"):
|
||||||
|
BUG_COMPONENT = ("Firefox", "Device Permissions")
|
||||||
|
|
||||||
with Files("linux/*LocationProvider*"):
|
with Files("linux/*LocationProvider*"):
|
||||||
BUG_COMPONENT = ("Core", "Geolocation")
|
BUG_COMPONENT = ("Core", "Geolocation")
|
||||||
|
|
||||||
@@ -49,14 +52,21 @@ elif toolkit == 'android':
|
|||||||
elif toolkit == 'gtk3':
|
elif toolkit == 'gtk3':
|
||||||
DIRS += ['linux']
|
DIRS += ['linux']
|
||||||
|
|
||||||
|
if toolkit != 'cocoa':
|
||||||
|
EXPORTS += [
|
||||||
|
'nsOSPermissionRequest.h',
|
||||||
|
]
|
||||||
|
|
||||||
XPIDL_SOURCES += [
|
XPIDL_SOURCES += [
|
||||||
'nsIOSFileConstantsService.idl',
|
'nsIOSFileConstantsService.idl',
|
||||||
|
'nsIOSPermissionRequest.idl',
|
||||||
]
|
]
|
||||||
|
|
||||||
XPIDL_MODULE = 'dom_system'
|
XPIDL_MODULE = 'dom_system'
|
||||||
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'nsDeviceSensors.h',
|
'nsDeviceSensors.h',
|
||||||
|
'nsOSPermissionRequestBase.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
@@ -65,6 +75,7 @@ EXPORTS.mozilla += [
|
|||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'nsDeviceSensors.cpp',
|
'nsDeviceSensors.cpp',
|
||||||
|
'nsOSPermissionRequestBase.cpp',
|
||||||
'OSFileConstants.cpp',
|
'OSFileConstants.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
55
dom/system/nsIOSPermissionRequest.idl
Normal file
55
dom/system/nsIOSPermissionRequest.idl
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||||
|
/* vim: set ts=2 et sw=2 tw=40: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
|
[scriptable, uuid(95790842-75a0-430d-98bf-f5ce3788ea6d)]
|
||||||
|
interface nsIOSPermissionRequest: nsISupports
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The permission state is not known. As an example, on macOS
|
||||||
|
* this is used to indicate the user has not been prompted to
|
||||||
|
* authorize or deny access and there is no policy in place to
|
||||||
|
* deny access.
|
||||||
|
*/
|
||||||
|
const uint16_t PERMISSION_STATE_NOTDETERMINED = 0;
|
||||||
|
|
||||||
|
/* A policy prevents the application from accessing the resource */
|
||||||
|
const uint16_t PERMISSION_STATE_RESTRICTED = 1;
|
||||||
|
|
||||||
|
/* Access to the resource is denied */
|
||||||
|
const uint16_t PERMISSION_STATE_DENIED = 2;
|
||||||
|
|
||||||
|
/* Access to the resource is allowed */
|
||||||
|
const uint16_t PERMISSION_STATE_AUTHORIZED = 3;
|
||||||
|
|
||||||
|
/* Get the permission state for both audio and video capture */
|
||||||
|
void getMediaCapturePermissionState(out uint16_t aVideo,
|
||||||
|
out uint16_t aAudio);
|
||||||
|
|
||||||
|
/* Get the permission state for audio capture */
|
||||||
|
void getAudioCapturePermissionState(out uint16_t aAudio);
|
||||||
|
|
||||||
|
/* Get the permission state for video capture */
|
||||||
|
void getVideoCapturePermissionState(out uint16_t aVideo);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request permission to access video capture devices. Returns a
|
||||||
|
* promise that resolves with |true| after the browser has been
|
||||||
|
* granted permission to capture video. If capture access is denied,
|
||||||
|
* the promise is resolved with |false|. The promise is rejected if
|
||||||
|
* an error occurs.
|
||||||
|
*/
|
||||||
|
[implicit_jscontext, must_use]
|
||||||
|
Promise requestVideoCapturePermission();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request permission to access audio capture devices. Returns a
|
||||||
|
* promise with the same semantics as |requestVideoCapturePermission|.
|
||||||
|
*/
|
||||||
|
[implicit_jscontext, must_use]
|
||||||
|
Promise requestAudioCapturePermission();
|
||||||
|
};
|
||||||
20
dom/system/nsOSPermissionRequest.h
Normal file
20
dom/system/nsOSPermissionRequest.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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 nsOSPermissionRequest_h__
|
||||||
|
#define nsOSPermissionRequest_h__
|
||||||
|
|
||||||
|
#include "nsOSPermissionRequestBase.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default implementation of nsOSPermissionRequestBase used on platforms
|
||||||
|
* that don't have a platform-specific version.
|
||||||
|
*/
|
||||||
|
class nsOSPermissionRequest : public nsOSPermissionRequestBase
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* nsOSPermissionRequest_h__ */
|
||||||
93
dom/system/nsOSPermissionRequestBase.cpp
Normal file
93
dom/system/nsOSPermissionRequestBase.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "nsOSPermissionRequestBase.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
|
||||||
|
using mozilla::dom::Promise;
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(
|
||||||
|
nsOSPermissionRequestBase,
|
||||||
|
nsIOSPermissionRequest,
|
||||||
|
nsISupportsWeakReference)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequestBase::GetMediaCapturePermissionState(uint16_t* aCamera,
|
||||||
|
uint16_t* aMicrophone)
|
||||||
|
{
|
||||||
|
nsresult rv = GetVideoCapturePermissionState(aCamera);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
return GetAudioCapturePermissionState(aMicrophone);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequestBase::GetAudioCapturePermissionState(uint16_t* aAudio)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aAudio);
|
||||||
|
*aAudio = PERMISSION_STATE_AUTHORIZED;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequestBase::GetVideoCapturePermissionState(uint16_t* aVideo)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aVideo);
|
||||||
|
*aVideo = PERMISSION_STATE_AUTHORIZED;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsOSPermissionRequestBase::GetPromise(JSContext* aCx,
|
||||||
|
RefPtr<Promise>& aPromiseOut)
|
||||||
|
{
|
||||||
|
nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx);
|
||||||
|
if (NS_WARN_IF(!globalObject)) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorResult result;
|
||||||
|
aPromiseOut = Promise::Create(globalObject, result);
|
||||||
|
if (NS_WARN_IF(result.Failed())) {
|
||||||
|
return result.StealNSResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequestBase::RequestVideoCapturePermission(JSContext* aCx,
|
||||||
|
Promise** aPromiseOut)
|
||||||
|
{
|
||||||
|
RefPtr<Promise> promiseHandle;
|
||||||
|
nsresult rv = GetPromise(aCx, promiseHandle);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
promiseHandle->MaybeResolve(true /* access authorized */);
|
||||||
|
promiseHandle.forget(aPromiseOut);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsOSPermissionRequestBase::RequestAudioCapturePermission(JSContext* aCx,
|
||||||
|
Promise** aPromiseOut)
|
||||||
|
{
|
||||||
|
RefPtr<Promise> promiseHandle;
|
||||||
|
nsresult rv = GetPromise(aCx, promiseHandle);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
promiseHandle->MaybeResolve(true /* access authorized */);
|
||||||
|
promiseHandle.forget(aPromiseOut);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
48
dom/system/nsOSPermissionRequestBase.h
Normal file
48
dom/system/nsOSPermissionRequestBase.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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 nsOSPermissionRequestBase_h__
|
||||||
|
#define nsOSPermissionRequestBase_h__
|
||||||
|
|
||||||
|
#include "nsIOSPermissionRequest.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
|
||||||
|
#define NS_OSPERMISSIONREQUEST_CID \
|
||||||
|
{ 0x95790842, 0x75a0, 0x430d, \
|
||||||
|
{ 0x98, 0xbf, 0xf5, 0xce, 0x37, 0x88, 0xea, 0x6d } }
|
||||||
|
#define NS_OSPERMISSIONREQUEST_CONTRACTID \
|
||||||
|
"@mozilla.org/ospermissionrequest;1"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
class Promise;
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
using mozilla::dom::Promise;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The base implementation of nsIOSPermissionRequest to be subclassed on
|
||||||
|
* platforms that require permission requests for access to resources such
|
||||||
|
* as media captures devices. This implementation always returns results
|
||||||
|
* indicating access is permitted.
|
||||||
|
*/
|
||||||
|
class nsOSPermissionRequestBase
|
||||||
|
: public nsIOSPermissionRequest,
|
||||||
|
public nsSupportsWeakReference
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIOSPERMISSIONREQUEST
|
||||||
|
|
||||||
|
nsOSPermissionRequestBase() {};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nsresult GetPromise(JSContext* aCx, RefPtr<Promise>& aPromiseOut);
|
||||||
|
virtual ~nsOSPermissionRequestBase() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "nsObjCExceptions.h"
|
#include "nsObjCExceptions.h"
|
||||||
|
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
|
#include "mozilla/StaticPtr.h"
|
||||||
|
|
||||||
// Declare the backingScaleFactor method that we want to call
|
// Declare the backingScaleFactor method that we want to call
|
||||||
// on NSView/Window/Screen objects, if they recognize it.
|
// on NSView/Window/Screen objects, if they recognize it.
|
||||||
@@ -38,8 +39,14 @@ class TimeStamp;
|
|||||||
namespace gfx {
|
namespace gfx {
|
||||||
class SourceSurface;
|
class SourceSurface;
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
namespace dom {
|
||||||
|
class Promise;
|
||||||
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
using mozilla::StaticAutoPtr;
|
||||||
|
using mozilla::StaticMutex;
|
||||||
|
|
||||||
// Used to retain a Cocoa object for the remainder of a method's execution.
|
// Used to retain a Cocoa object for the remainder of a method's execution.
|
||||||
class nsAutoRetainCocoaObject {
|
class nsAutoRetainCocoaObject {
|
||||||
public:
|
public:
|
||||||
@@ -102,11 +109,18 @@ struct KeyBindingsCommand
|
|||||||
|
|
||||||
@end // NativeKeyBindingsRecorder
|
@end // NativeKeyBindingsRecorder
|
||||||
|
|
||||||
|
#if !defined(MAC_OS_X_VERSION_10_14) || \
|
||||||
|
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_14
|
||||||
|
typedef NSString* AVMediaType;
|
||||||
|
#endif
|
||||||
|
|
||||||
class nsCocoaUtils
|
class nsCocoaUtils
|
||||||
{
|
{
|
||||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||||
typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
|
typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
|
||||||
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
|
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
|
||||||
|
typedef mozilla::dom::Promise Promise;
|
||||||
|
typedef StaticAutoPtr<nsTArray<RefPtr<Promise>>> PromiseArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -396,6 +410,84 @@ public:
|
|||||||
* If aEventTime is 0, this returns current timestamp.
|
* If aEventTime is 0, this returns current timestamp.
|
||||||
*/
|
*/
|
||||||
static mozilla::TimeStamp GetEventTimeStamp(NSTimeInterval aEventTime);
|
static mozilla::TimeStamp GetEventTimeStamp(NSTimeInterval aEventTime);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current video capture permission status.
|
||||||
|
* Returns NS_ERROR_NOT_IMPLEMENTED on 10.13 and earlier macOS versions.
|
||||||
|
*/
|
||||||
|
static nsresult GetVideoCapturePermissionState(uint16_t& aPermissionState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current audio capture permission status.
|
||||||
|
* Returns NS_ERROR_NOT_IMPLEMENTED on 10.13 and earlier macOS versions.
|
||||||
|
*/
|
||||||
|
static nsresult GetAudioCapturePermissionState(uint16_t& aPermissionState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request video capture permission from the OS. Caller must be running
|
||||||
|
* on the main thread and the promise will be resolved on the main thread.
|
||||||
|
* Returns NS_ERROR_NOT_IMPLEMENTED on 10.13 and earlier macOS versions.
|
||||||
|
*/
|
||||||
|
static nsresult RequestVideoCapturePermission(RefPtr<Promise>& aPromise);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request audio capture permission from the OS. Caller must be running
|
||||||
|
* on the main thread and the promise will be resolved on the main thread.
|
||||||
|
* Returns NS_ERROR_NOT_IMPLEMENTED on 10.13 and earlier macOS versions.
|
||||||
|
*/
|
||||||
|
static nsresult RequestAudioCapturePermission(RefPtr<Promise>& aPromise);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Completion handlers used as an argument to the macOS API to
|
||||||
|
* request media capture permission. These are called asynchronously
|
||||||
|
* on an arbitrary dispatch queue.
|
||||||
|
*/
|
||||||
|
static void (^AudioCompletionHandler)(BOOL);
|
||||||
|
static void (^VideoCompletionHandler)(BOOL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called from the audio and video completion handlers in order to
|
||||||
|
* dispatch the handling back to the main thread.
|
||||||
|
*/
|
||||||
|
static void ResolveAudioCapturePromises(bool aGranted);
|
||||||
|
static void ResolveVideoCapturePromises(bool aGranted);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main implementation for Request{Audio,Video}CapturePermission.
|
||||||
|
* @param aType the AVMediaType to request capture permission for
|
||||||
|
* @param aPromise the Promise to resolve when capture permission
|
||||||
|
* is either allowed or denied
|
||||||
|
* @param aPromiseList the array of promises to save |aPromise| in
|
||||||
|
* @param aHandler the block function (either ResolveAudioCapturePromises
|
||||||
|
* or ResolveVideoCapturePromises) to be used as
|
||||||
|
* the requestAccessForMediaType callback.
|
||||||
|
*/
|
||||||
|
static nsresult RequestCapturePermission(NSString* aType,
|
||||||
|
RefPtr<Promise>& aPromise,
|
||||||
|
PromiseArray& aPromiseList,
|
||||||
|
void (^aHandler)(BOOL granted));
|
||||||
|
/**
|
||||||
|
* Resolves the pending promises that are waiting for a response
|
||||||
|
* to a request video or audio capture permission.
|
||||||
|
*/
|
||||||
|
static void ResolveMediaCapturePromises(bool aGranted,
|
||||||
|
PromiseArray& aPromiseList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of promises waiting to be resolved due to a video capture request.
|
||||||
|
*/
|
||||||
|
static PromiseArray sVideoCapturePromises;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of promises waiting to be resolved due to an audio capture request.
|
||||||
|
*/
|
||||||
|
static PromiseArray sAudioCapturePromises;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock protecting |sVideoCapturePromises| and |sAudioCapturePromises|.
|
||||||
|
*/
|
||||||
|
static StaticMutex sMediaCaptureMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsCocoaUtils_h_
|
#endif // nsCocoaUtils_h_
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
@@ -16,6 +18,8 @@
|
|||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIInterfaceRequestorUtils.h"
|
#include "nsIInterfaceRequestorUtils.h"
|
||||||
#include "nsIAppShellService.h"
|
#include "nsIAppShellService.h"
|
||||||
|
#include "nsIOSPermissionRequest.h"
|
||||||
|
#include "nsIRunnable.h"
|
||||||
#include "nsIXULWindow.h"
|
#include "nsIXULWindow.h"
|
||||||
#include "nsIBaseWindow.h"
|
#include "nsIBaseWindow.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
@@ -23,14 +27,19 @@
|
|||||||
#include "nsToolkit.h"
|
#include "nsToolkit.h"
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "SVGImageContext.h"
|
#include "SVGImageContext.h"
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/MiscEvents.h"
|
#include "mozilla/MiscEvents.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/TextEvents.h"
|
#include "mozilla/TextEvents.h"
|
||||||
|
#include "mozilla/StaticMutex.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::widget;
|
using namespace mozilla::widget;
|
||||||
|
|
||||||
|
using mozilla::dom::Promise;
|
||||||
using mozilla::gfx::BackendType;
|
using mozilla::gfx::BackendType;
|
||||||
using mozilla::gfx::DataSourceSurface;
|
using mozilla::gfx::DataSourceSurface;
|
||||||
using mozilla::gfx::DrawTarget;
|
using mozilla::gfx::DrawTarget;
|
||||||
@@ -44,6 +53,21 @@ using mozilla::gfx::SourceSurface;
|
|||||||
using mozilla::image::ImageRegion;
|
using mozilla::image::ImageRegion;
|
||||||
using std::ceil;
|
using std::ceil;
|
||||||
|
|
||||||
|
LazyLogModule gCocoaUtilsLog("nsCocoaUtils");
|
||||||
|
#undef LOG
|
||||||
|
#define LOG(...) MOZ_LOG(gCocoaUtilsLog, LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each audio and video capture request, we hold an owning reference
|
||||||
|
* to a promise to be resolved when the request's async callback is invoked.
|
||||||
|
* sVideoCapturePromises and sAudioCapturePromises are arrays of video and
|
||||||
|
* audio promises waiting for to be resolved. Each array is protected by a
|
||||||
|
* mutex.
|
||||||
|
*/
|
||||||
|
nsCocoaUtils::PromiseArray nsCocoaUtils::sVideoCapturePromises;
|
||||||
|
nsCocoaUtils::PromiseArray nsCocoaUtils::sAudioCapturePromises;
|
||||||
|
StaticMutex nsCocoaUtils::sMediaCaptureMutex;
|
||||||
|
|
||||||
static float
|
static float
|
||||||
MenuBarScreenHeight()
|
MenuBarScreenHeight()
|
||||||
{
|
{
|
||||||
@@ -1123,3 +1147,259 @@ nsCocoaUtils::GetEventTimeStamp(NSTimeInterval aEventTime)
|
|||||||
BaseTimeDurationPlatformUtils::TicksFromMilliseconds(aEventTime * 1000.0);
|
BaseTimeDurationPlatformUtils::TicksFromMilliseconds(aEventTime * 1000.0);
|
||||||
return TimeStamp::FromSystemTime(tick);
|
return TimeStamp::FromSystemTime(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AVAuthorizationStatus is not needed unless we are running on 10.14.
|
||||||
|
// However, on pre-10.14 SDK's, AVAuthorizationStatus and its enum values
|
||||||
|
// are both defined and prohibited from use by compile-time checks. We
|
||||||
|
// define a copy of AVAuthorizationStatus to allow compilation on pre-10.14
|
||||||
|
// SDK's. The enum values must match what is defined in the 10.14 SDK.
|
||||||
|
// We use ASSERTS for 10.14 SDK builds to check the enum values match.
|
||||||
|
enum GeckoAVAuthorizationStatus {
|
||||||
|
GeckoAVAuthorizationStatusNotDetermined = 0,
|
||||||
|
GeckoAVAuthorizationStatusRestricted = 1,
|
||||||
|
GeckoAVAuthorizationStatusDenied = 2,
|
||||||
|
GeckoAVAuthorizationStatusAuthorized = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(MAC_OS_X_VERSION_10_14) || \
|
||||||
|
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_14
|
||||||
|
// Define authorizationStatusForMediaType: as returning
|
||||||
|
// GeckoAVAuthorizationStatus instead of AVAuthorizationStatus to allow
|
||||||
|
// compilation on pre-10.14 SDK's.
|
||||||
|
@interface AVCaptureDevice(GeckoAVAuthorizationStatus)
|
||||||
|
+ (GeckoAVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface AVCaptureDevice(WithCompletionHandler)
|
||||||
|
+ (void)requestAccessForMediaType:(AVMediaType)mediaType completionHandler:(void (^)(BOOL granted))handler;
|
||||||
|
@end
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char*
|
||||||
|
AVMediaTypeToString(AVMediaType aType)
|
||||||
|
{
|
||||||
|
if (aType == AVMediaTypeVideo) {
|
||||||
|
return "video";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aType == AVMediaTypeAudio) {
|
||||||
|
return "audio";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unexpected type";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
LogAuthorizationStatus(AVMediaType aType, int aState)
|
||||||
|
{
|
||||||
|
const char* stateString;
|
||||||
|
|
||||||
|
switch (aState) {
|
||||||
|
case GeckoAVAuthorizationStatusAuthorized:
|
||||||
|
stateString = "AVAuthorizationStatusAuthorized";
|
||||||
|
break;
|
||||||
|
case GeckoAVAuthorizationStatusDenied:
|
||||||
|
stateString = "AVAuthorizationStatusDenied";
|
||||||
|
break;
|
||||||
|
case GeckoAVAuthorizationStatusNotDetermined:
|
||||||
|
stateString = "AVAuthorizationStatusNotDetermined";
|
||||||
|
break;
|
||||||
|
case GeckoAVAuthorizationStatusRestricted:
|
||||||
|
stateString = "AVAuthorizationStatusRestricted";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
stateString = "Invalid state";
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG("%s authorization status: %s\n", AVMediaTypeToString(aType), stateString);
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsresult
|
||||||
|
GetPermissionState(AVMediaType aMediaType, uint16_t& aState)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aMediaType == AVMediaTypeVideo || aMediaType == AVMediaTypeAudio);
|
||||||
|
|
||||||
|
// Only attempt to check authorization status on 10.14+.
|
||||||
|
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeckoAVAuthorizationStatus authStatus =
|
||||||
|
[AVCaptureDevice authorizationStatusForMediaType:aMediaType];
|
||||||
|
LogAuthorizationStatus(aMediaType, authStatus);
|
||||||
|
|
||||||
|
// Convert GeckoAVAuthorizationStatus to nsIOSPermissionRequest const
|
||||||
|
switch (authStatus) {
|
||||||
|
case GeckoAVAuthorizationStatusAuthorized:
|
||||||
|
aState = nsIOSPermissionRequest::PERMISSION_STATE_AUTHORIZED;
|
||||||
|
return NS_OK;
|
||||||
|
case GeckoAVAuthorizationStatusDenied:
|
||||||
|
aState = nsIOSPermissionRequest::PERMISSION_STATE_DENIED;
|
||||||
|
return NS_OK;
|
||||||
|
case GeckoAVAuthorizationStatusNotDetermined:
|
||||||
|
aState = nsIOSPermissionRequest::PERMISSION_STATE_NOTDETERMINED;
|
||||||
|
return NS_OK;
|
||||||
|
case GeckoAVAuthorizationStatusRestricted:
|
||||||
|
aState = nsIOSPermissionRequest::PERMISSION_STATE_RESTRICTED;
|
||||||
|
return NS_OK;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT(false, "Invalid authorization status");
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsCocoaUtils::GetVideoCapturePermissionState(uint16_t& aPermissionState)
|
||||||
|
{
|
||||||
|
return GetPermissionState(AVMediaTypeVideo, aPermissionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsCocoaUtils::GetAudioCapturePermissionState(uint16_t& aPermissionState)
|
||||||
|
{
|
||||||
|
return GetPermissionState(AVMediaTypeAudio, aPermissionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsCocoaUtils::RequestVideoCapturePermission(RefPtr<Promise>& aPromise)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
return nsCocoaUtils::RequestCapturePermission(AVMediaTypeVideo,
|
||||||
|
aPromise,
|
||||||
|
sVideoCapturePromises,
|
||||||
|
VideoCompletionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsCocoaUtils::RequestAudioCapturePermission(RefPtr<Promise>& aPromise)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
return nsCocoaUtils::RequestCapturePermission(AVMediaTypeAudio,
|
||||||
|
aPromise,
|
||||||
|
sAudioCapturePromises,
|
||||||
|
AudioCompletionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Stores |aPromise| on |aPromiseList| and starts an asynchronous media
|
||||||
|
// capture request for the given media type |aType|. If we are already
|
||||||
|
// waiting for a capture request for this media type, don't start a new
|
||||||
|
// request. |aHandler| is invoked on an arbitrary dispatch queue when the
|
||||||
|
// request completes and must resolve any waiting Promises on the main
|
||||||
|
// thread.
|
||||||
|
//
|
||||||
|
nsresult
|
||||||
|
nsCocoaUtils::RequestCapturePermission(AVMediaType aType,
|
||||||
|
RefPtr<Promise>& aPromise,
|
||||||
|
PromiseArray& aPromiseList,
|
||||||
|
void (^aHandler)(BOOL granted))
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aType == AVMediaTypeVideo || aType == AVMediaTypeAudio);
|
||||||
|
#if defined(MAC_OS_X_VERSION_10_14)
|
||||||
|
// Ensure our enum constants match. We can only do this when
|
||||||
|
// compiling on 10.14+ because AVAuthorizationStatus is
|
||||||
|
// prohibited by preprocessor checks on earlier OS versions.
|
||||||
|
MOZ_ASSERT((int)GeckoAVAuthorizationStatusNotDetermined ==
|
||||||
|
(int)AVAuthorizationStatusNotDetermined);
|
||||||
|
MOZ_ASSERT((int)GeckoAVAuthorizationStatusRestricted ==
|
||||||
|
(int)AVAuthorizationStatusRestricted);
|
||||||
|
MOZ_ASSERT((int)GeckoAVAuthorizationStatusDenied ==
|
||||||
|
(int)AVAuthorizationStatusDenied);
|
||||||
|
MOZ_ASSERT((int)GeckoAVAuthorizationStatusAuthorized ==
|
||||||
|
(int)AVAuthorizationStatusAuthorized);
|
||||||
|
#endif
|
||||||
|
LOG("RequestCapturePermission(%s)", AVMediaTypeToString(aType));
|
||||||
|
|
||||||
|
// Only attempt to request authorization on 10.14+.
|
||||||
|
if (!nsCocoaFeatures::OnMojaveOrLater()) {
|
||||||
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
sMediaCaptureMutex.Lock();
|
||||||
|
|
||||||
|
// Initialize our list of promises on first invocation
|
||||||
|
if (aPromiseList == nullptr) {
|
||||||
|
aPromiseList = new nsTArray<RefPtr<Promise>>;
|
||||||
|
ClearOnShutdown(&aPromiseList);
|
||||||
|
}
|
||||||
|
|
||||||
|
aPromiseList->AppendElement(aPromise);
|
||||||
|
size_t nPromises = aPromiseList->Length();
|
||||||
|
|
||||||
|
sMediaCaptureMutex.Unlock();
|
||||||
|
|
||||||
|
LOG("RequestCapturePermission(%s): %ld promise(s) unresolved",
|
||||||
|
AVMediaTypeToString(aType), nPromises);
|
||||||
|
|
||||||
|
// If we had one or more more existing promises waiting to be resolved
|
||||||
|
// by the completion handler, we don't need to start another request.
|
||||||
|
if (nPromises > 1) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the request
|
||||||
|
[AVCaptureDevice requestAccessForMediaType:aType completionHandler:aHandler];
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Audio capture request completion handler. Called from an arbitrary
|
||||||
|
// dispatch queue.
|
||||||
|
//
|
||||||
|
void (^nsCocoaUtils::AudioCompletionHandler)(BOOL) = ^void (BOOL granted)
|
||||||
|
{
|
||||||
|
nsCocoaUtils::ResolveAudioCapturePromises(granted);
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// Video capture request completion handler. Called from an arbitrary
|
||||||
|
// dispatch queue.
|
||||||
|
//
|
||||||
|
void (^nsCocoaUtils::VideoCompletionHandler)(BOOL) = ^void (BOOL granted)
|
||||||
|
{
|
||||||
|
nsCocoaUtils::ResolveVideoCapturePromises(granted);
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
nsCocoaUtils::ResolveMediaCapturePromises(bool aGranted,
|
||||||
|
PromiseArray& aPromiseList)
|
||||||
|
{
|
||||||
|
StaticMutexAutoLock lock(sMediaCaptureMutex);
|
||||||
|
|
||||||
|
// Remove each promise from the list and resolve it.
|
||||||
|
while (aPromiseList->Length() > 0) {
|
||||||
|
RefPtr<Promise> promise = aPromiseList->LastElement();
|
||||||
|
aPromiseList->RemoveLastElement();
|
||||||
|
|
||||||
|
// Resolve on main thread
|
||||||
|
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||||
|
"ResolveMediaAccessPromise",
|
||||||
|
[aGranted, aPromise = std::move(promise)]() {
|
||||||
|
aPromise->MaybeResolve(aGranted);
|
||||||
|
}));
|
||||||
|
NS_DispatchToMainThread(runnable.forget());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsCocoaUtils::ResolveAudioCapturePromises(bool aGranted)
|
||||||
|
{
|
||||||
|
// Resolve on main thread
|
||||||
|
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||||
|
"ResolveAudioCapturePromise", [aGranted]() {
|
||||||
|
ResolveMediaCapturePromises(aGranted, sAudioCapturePromises);
|
||||||
|
}));
|
||||||
|
NS_DispatchToMainThread(runnable.forget());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsCocoaUtils::ResolveVideoCapturePromises(bool aGranted)
|
||||||
|
{
|
||||||
|
// Resolve on main thread
|
||||||
|
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
|
||||||
|
"ResolveVideoCapturePromise", [aGranted]() {
|
||||||
|
ResolveMediaCapturePromises(aGranted, sVideoCapturePromises);
|
||||||
|
}));
|
||||||
|
NS_DispatchToMainThread(runnable.forget());
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user