ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess( ScriptState* scriptState, Navigator& navigator, const String& keySystem, const HeapVector<MediaKeySystemConfiguration>& supportedConfigurations) { WTF_LOG(Media, "NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess()"); // From https://w3c.github.io/encrypted-media/#requestMediaKeySystemAccess // When this method is invoked, the user agent must run the following steps: // 1. If keySystem is an empty string, return a promise rejected with a // new DOMException whose name is InvalidAccessError. if (keySystem.isEmpty()) { return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create(InvalidAccessError, "The keySystem parameter is empty.")); } // 2. If supportedConfigurations was provided and is empty, return a // promise rejected with a new DOMException whose name is // InvalidAccessError. if (!supportedConfigurations.size()) { return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create(InvalidAccessError, "The supportedConfigurations parameter is empty.")); } // 3-4. 'May Document use powerful features?' check. ExecutionContext* executionContext = scriptState->executionContext(); String errorMessage; if (executionContext->isSecureContext(errorMessage)) { UseCounter::count(executionContext, UseCounter::EncryptedMediaSecureOrigin); } else { UseCounter::countDeprecation(executionContext, UseCounter::EncryptedMediaInsecureOrigin); // TODO(ddorwin): Implement the following: // Reject promise with a new DOMException whose name is NotSupportedError. } // 5. Let origin be the origin of document. // (Passed with the execution context in step 7.) // 6. Let promise be a new promise. Document* document = toDocument(executionContext); if (!document->page()) { return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create(InvalidStateError, "The context provided is not associated with a page.")); } MediaKeySystemAccessInitializer* initializer = new MediaKeySystemAccessInitializer(scriptState, keySystem, supportedConfigurations); ScriptPromise promise = initializer->promise(); // 7. Asynchronously determine support, and if allowed, create and // initialize the MediaKeySystemAccess object. MediaKeysController* controller = MediaKeysController::from(document->page()); WebEncryptedMediaClient* mediaClient = controller->encryptedMediaClient(executionContext); mediaClient->requestMediaKeySystemAccess(WebEncryptedMediaRequest(initializer)); // 8. Return promise. return promise; }
ScriptPromise USB::requestDevice(ScriptState* scriptState, const USBDeviceRequestOptions& options) { ExecutionContext* executionContext = scriptState->getExecutionContext(); UseCounter::count(executionContext, UseCounter::UsbRequestDevice); ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); if (!m_chooserService) { LocalFrame* frame = executionContext->isDocument() ? toDocument(executionContext)->frame() : nullptr; if (!frame) { resolver->reject(DOMException::create(NotSupportedError)); return promise; } frame->interfaceProvider()->getInterface(mojo::GetProxy(&m_chooserService)); m_chooserService.set_connection_error_handler( convertToBaseCallback(WTF::bind(&USB::onChooserServiceConnectionError, wrapWeakPersistent(this)))); } String errorMessage; if (!executionContext->isSecureContext(errorMessage)) { resolver->reject(DOMException::create(SecurityError, errorMessage)); } else if (!UserGestureIndicator::consumeUserGesture()) { resolver->reject(DOMException::create( SecurityError, "Must be handling a user gesture to show a permission request.")); } else { Vector<usb::DeviceFilterPtr> filters; if (options.hasFilters()) { filters.reserveCapacity(options.filters().size()); for (const auto& filter : options.filters()) filters.append(convertDeviceFilter(filter)); } m_chooserServiceRequests.add(resolver); m_chooserService->GetPermission( std::move(filters), convertToBaseCallback(WTF::bind( &USB::onGetPermission, wrapPersistent(this), wrapPersistent(resolver)))); } return promise; }
// https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetooth-requestdevice ScriptPromise Bluetooth::requestDevice(ScriptState* scriptState, const RequestDeviceOptions& options, ExceptionState& exceptionState) { ExecutionContext* context = scriptState->getExecutionContext(); // 1. If the incumbent settings object is not a secure context, reject promise // with a SecurityError and abort these steps. String errorMessage; if (!context->isSecureContext(errorMessage)) { return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create(SecurityError, errorMessage)); } // 2. If the algorithm is not allowed to show a popup, reject promise with a // SecurityError and abort these steps. if (!UserGestureIndicator::consumeUserGesture()) { return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create( SecurityError, "Must be handling a user gesture to show a permission request.")); } WebBluetooth* webbluetooth = BluetoothSupplement::fromScriptState(scriptState); if (!webbluetooth) return ScriptPromise::rejectWithDOMException( scriptState, DOMException::create(NotSupportedError)); // 3. In order to convert the arguments from service names and aliases to just // UUIDs, do the following substeps: WebRequestDeviceOptions webOptions; convertRequestDeviceOptions(options, webOptions, exceptionState); if (exceptionState.hadException()) return exceptionState.reject(scriptState); // Subsequent steps are handled in the browser process. ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); webbluetooth->requestDevice(webOptions, new RequestDeviceCallback(this, resolver)); return promise; }
ScriptPromise USB::getDevices(ScriptState* scriptState) { ExecutionContext* executionContext = scriptState->getExecutionContext(); UseCounter::count(executionContext, UseCounter::UsbGetDevices); ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); if (!m_deviceManager) { resolver->reject(DOMException::create(NotSupportedError)); } else { String errorMessage; if (!executionContext->isSecureContext(errorMessage)) { resolver->reject(DOMException::create(SecurityError, errorMessage)); } else { m_deviceManagerRequests.add(resolver); m_deviceManager->GetDevices( nullptr, convertToBaseCallback(WTF::bind(&USB::onGetDevices, wrapPersistent(this), wrapPersistent(resolver)))); } } return promise; }
ScriptPromise NavigatorVR::getVRDisplays(ScriptState* scriptState) { ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); Document* document = frame() ? frame()->document() : 0; if (!document || !controller()) { DOMException* exception = DOMException::create( InvalidStateError, "The object is no longer associated to a document."); resolver->reject(exception); return promise; } UseCounter::count(*document, UseCounter::VRGetDisplays); ExecutionContext* executionContext = scriptState->getExecutionContext(); String errorMessage; if (!executionContext->isSecureContext(errorMessage)) UseCounter::count(*document, UseCounter::VRGetDisplaysInsecureOrigin); controller()->getDisplays(resolver); return promise; }