ScriptPromise ServiceWorkerContainer::registerServiceWorker(ScriptState* scriptState, const String& url, const Dictionary& dictionary) { RegistrationOptionList options(dictionary); ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); ScriptPromise promise = resolver->promise(); if (!m_provider) { resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available")); return promise; } ExecutionContext* executionContext = scriptState->executionContext(); RefPtr<SecurityOrigin> documentOrigin = executionContext->securityOrigin(); KURL patternURL = executionContext->completeURL(options.scope); patternURL.removeFragmentIdentifier(); if (!documentOrigin->canRequest(patternURL)) { resolver->reject(DOMException::create(SecurityError, "Can only register for patterns in the document's origin.")); return promise; } KURL scriptURL = executionContext->completeURL(url); scriptURL.removeFragmentIdentifier(); if (!documentOrigin->canRequest(scriptURL)) { resolver->reject(DOMException::create(SecurityError, "Script must be in document's origin.")); return promise; } m_provider->registerServiceWorker(patternURL, scriptURL, new CallbackPromiseAdapter<ServiceWorker, ServiceWorkerError>(resolver)); return promise; }
JSValue JSWebKitSubtleCrypto::wrapKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2)); if (!key) return throwTypeError(&state, scope); if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'")); throwNotSupportedError(state, scope); return jsUndefined(); } auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto exportSuccessCallback = [keyFormat, algorithm, parameters, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable { auto encryptSuccessCallback = [wrapper](const Vector<uint8_t>& encryptedData) mutable { fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), encryptedData.data(), encryptedData.size()); }; auto encryptFailureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = algorithm->encryptForWrapKey(*parameters, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTFMove(encryptSuccessCallback), WTFMove(encryptFailureCallback)); if (result.hasException()) { // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions. wrapper->reject(); // FIXME: This should reject with an Exception. } }; auto exportFailureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; WebCore::exportKey(state, keyFormat, *key, WTFMove(exportSuccessCallback), WTFMove(exportFailureCallback)); return promise; }
ScriptPromise FontFaceSet::load(ScriptState* scriptState, const String& fontString, const String& text) { if (!inActiveDocumentContext()) return ScriptPromise(); Font font; if (!resolveFontStyle(fontString, font)) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); resolver->reject(DOMException::create(SyntaxError, "Could not resolve '" + fontString + "' as a font.")); return promise; } FontFaceCache* fontFaceCache = document()->styleEngine()->fontSelector()->fontFaceCache(); FontFaceArray faces; for (const FontFamily* f = &font.fontDescription().family(); f; f = f->next()) { CSSSegmentedFontFace* segmentedFontFace = fontFaceCache->get(font.fontDescription(), f->family()); if (segmentedFontFace) segmentedFontFace->match(nullToSpace(text), faces); } RefPtr<LoadFontPromiseResolver> resolver = LoadFontPromiseResolver::create(faces, scriptState); ScriptPromise promise = resolver->promise(); resolver->loadFonts(executionContext()); // After this, resolver->promise() may return null. return promise; }
JSValue JSWebKitSubtleCrypto::digest(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 2) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForDigest(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = algorithm->digest(*parameters, data, WTFMove(successCallback), WTFMove(failureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
JSValue JSWebKitSubtleCrypto::exportKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 2) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable { fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size()); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; WebCore::exportKey(state, keyFormat, *key, WTFMove(successCallback), WTFMove(failureCallback)); RETURN_IF_EXCEPTION(scope, JSValue()); return promise; }
ScriptPromise Presentation::joinSession(ScriptState* state, const String& senderId, const String& presentationId) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(state); ScriptPromise promise = resolver->promise(); resolver->reject(DOMException::create(NotSupportedError, "The method is not supported yet.")); return promise; }
void ScriptModuleLoader::notifyFinished(CachedModuleScriptLoader& loader, RefPtr<DeferredPromise> promise) { // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script if (!m_loaders.remove(&loader)) return; loader.clearClient(); auto& cachedScript = *loader.cachedScript(); bool failed = false; if (cachedScript.resourceError().isAccessControl()) { promise->reject(TypeError, ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy.")); return; } if (cachedScript.errorOccurred()) failed = true; else if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(cachedScript.response().mimeType())) { // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script // The result of extracting a MIME type from response's header list (ignoring parameters) is not a JavaScript MIME type. // For historical reasons, fetching a classic script does not include MIME type checking. In contrast, module scripts will fail to load if they are not of a correct MIME type. promise->reject(TypeError, makeString("'", cachedScript.response().mimeType(), "' is not a valid JavaScript MIME type.")); return; } auto* frame = m_document.frame(); if (!frame) return; if (failed) { // Reject a promise to propagate the error back all the way through module promise chains to the script element. promise->reject(frame->script().moduleLoaderAlreadyReportedErrorSymbol()); return; } if (cachedScript.wasCanceled()) { promise->reject(frame->script().moduleLoaderFetchingIsCanceledSymbol()); return; } m_requestURLToResponseURLMap.add(cachedScript.url(), cachedScript.response().url()); // FIXME: Let's wrap around ScriptSourceCode to propagate it directly through the module pipeline. promise->resolve<IDLDOMString>(ScriptSourceCode(&cachedScript, JSC::SourceProviderSourceType::Module).source().toString()); }
void LoadFontPromiseResolver::notifyError(FontFace* fontFace) { m_numLoading--; if (!m_errorOccured) { m_errorOccured = true; m_resolver->reject(fontFace->error()); } }
JSValue JSWebKitSubtleCrypto::verify(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(0)); ASSERT(scope.exception() || algorithm); if (!algorithm) return jsUndefined(); auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(&state, algorithm->identifier(), state.uncheckedArgument(0)); ASSERT(scope.exception() || parameters); if (!parameters) return jsUndefined(); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); if (!key->allows(CryptoKeyUsageVerify)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); setDOMException(&state, NOT_SUPPORTED_ERR); return jsUndefined(); } CryptoOperationData signature; auto success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(2), signature); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); CryptoOperationData data; success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(3), data); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](bool result) mutable { wrapper->resolve(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(nullptr); }; auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
ScriptPromise ScriptPromise::reject(ScriptState* scriptState, v8::Handle<v8::Value> value) { if (value.IsEmpty()) return ScriptPromise(); RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); resolver->reject(value); return promise; }
ScriptPromise Cache::ready(ScriptState* scriptState) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); // FIXME: Implement. notImplemented(); resolver->reject(DOMError::create(NotSupportedError)); return promise; }
ScriptPromise InstallEvent::reloadAll(ExecutionContext* context) { // FIXME: implement. notImplemented(); // For now this just returns a promise which is already rejected. ScriptPromise promise = ScriptPromise::createPending(context); RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, context); resolver->reject(ScriptValue::createNull()); return promise; }
static ScriptPromise fulfillImageBitmap(ScriptState* scriptState, PassRefPtrWillBeRawPtr<ImageBitmap> imageBitmap) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); if (imageBitmap) { resolver->resolve(imageBitmap); } else { resolver->reject(ScriptValue(scriptState, v8::Null(scriptState->isolate()))); } return promise; }
JSValue JSWebKitSubtleCrypto::generateKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 1) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(0)); ASSERT(scope.exception() || algorithm); if (!algorithm) return jsUndefined(); auto parameters = JSCryptoAlgorithmDictionary::createParametersForGenerateKey(&state, algorithm->identifier(), state.uncheckedArgument(0)); ASSERT(scope.exception() || parameters); if (!parameters) return jsUndefined(); bool extractable = false; if (state.argumentCount() >= 2) { extractable = state.uncheckedArgument(1).toBoolean(&state); RETURN_IF_EXCEPTION(scope, JSValue()); } CryptoKeyUsageBitmap keyUsages = 0; if (state.argumentCount() >= 3) { auto success = cryptoKeyUsagesFromJSValue(state, state.argument(2), keyUsages); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); } RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](CryptoKey* key, CryptoKeyPair* keyPair) mutable { ASSERT(key || keyPair); ASSERT(!key || !keyPair); if (key) wrapper->resolve(key); else wrapper->resolve(keyPair); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(nullptr); }; auto result = algorithm->generateKey(*parameters, extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback), *scriptExecutionContextFromExecState(&state)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
ScriptPromise InstallEvent::reloadAll(ScriptState* scriptState) { // FIXME: implement. notImplemented(); // For now this just returns a promise which is already rejected. RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); ScriptPromise promise = resolver->promise(); resolver->reject(ScriptValue(scriptState, v8::Null(scriptState->isolate()))); return promise; }
ScriptPromise NavigatorServiceWorker::unregisterServiceWorker(ScriptExecutionContext* scriptExecutionContext, const String& pattern, ExceptionState& es) { ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); FrameLoaderClient* client = m_navigator->frame()->loader()->client(); WebKit::WebServiceWorkerRegistry* peer = client->serviceWorkerRegistry(); RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptExecutionContext); if (peer) peer->unregisterServiceWorker(pattern, new CallbackPromiseAdapter(resolver)); else resolver->reject(PassRefPtr<ServiceWorker>(0)); return resolver->promise(); }
ScriptPromise ScreenOrientation::lock(ScriptState* state, const AtomicString& lockString) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(state); ScriptPromise promise = resolver->promise(); Document* document = m_frame ? m_frame->document() : 0; if (!document || !controller()) { RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(InvalidStateError, "The object is no longer associated to a document."); resolver->reject(exception); return promise; } if (document->isSandboxed(SandboxOrientationLock)) { RefPtrWillBeRawPtr<DOMException> exception = DOMException::create(SecurityError, "The document is sandboxed and lacks the 'allow-orientation-lock' flag."); resolver->reject(exception); return promise; } controller()->lock(stringToOrientationLock(lockString), new LockOrientationCallback(resolver)); return promise; }
ScriptPromise ServiceWorkerContainer::unregisterServiceWorker(ScriptState* scriptState, const String& pattern) { ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); RefPtr<ScriptPromiseResolverWithContext> resolver = ScriptPromiseResolverWithContext::create(scriptState); ScriptPromise promise = resolver->promise(); if (!m_provider) { resolver->reject(DOMException::create(InvalidStateError, "No associated provider is available")); return promise; } RefPtr<SecurityOrigin> documentOrigin = scriptState->executionContext()->securityOrigin(); KURL patternURL = scriptState->executionContext()->completeURL(pattern); patternURL.removeFragmentIdentifier(); if (!pattern.isEmpty() && !documentOrigin->canRequest(patternURL)) { resolver->reject(DOMException::create(SecurityError, "Can only unregister for patterns in the document's origin.")); return promise; } m_provider->unregisterServiceWorker(patternURL, new CallbackPromiseAdapter<UndefinedValue, ServiceWorkerError>(resolver)); return promise; }
ScriptPromise StorageQuota::requestPersistentQuota(ExecutionContext* executionContext, unsigned long long newQuota) { ASSERT(executionContext); StorageQuotaClient* client = StorageQuotaClient::from(executionContext); if (!client) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(executionContext); resolver->reject(DOMError::create(NotSupportedError)); return resolver->promise(); } return client->requestPersistentQuota(executionContext, newQuota); }
ScriptPromise NavigatorServiceWorker::registerServiceWorker(ScriptExecutionContext* scriptExecutionContext, const String& pattern, const String& scriptSrc, ExceptionState& es) { ASSERT(RuntimeEnabledFeatures::serviceWorkerEnabled()); FrameLoaderClient* client = m_navigator->frame()->loader()->client(); // WTF? Surely there's a better way to resolve a url? KURL scriptUrl = m_navigator->frame()->document()->completeURL(scriptSrc); WebKit::WebServiceWorkerRegistry* peer = client->serviceWorkerRegistry(); RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptExecutionContext); if (peer) peer->registerServiceWorker(pattern, scriptUrl, new CallbackPromiseAdapter(resolver)); else resolver->reject(PassRefPtr<ServiceWorker>(0)); // call here? return resolver->promise(); }
JSValue JSWebKitSubtleCrypto::importKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 3) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoAlgorithm> algorithm; RefPtr<CryptoAlgorithmParametersDeprecated> parameters; if (!state.uncheckedArgument(2).isNull()) { algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(2)); RETURN_IF_EXCEPTION(scope, { }); parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, algorithm->identifier(), state.uncheckedArgument(2)); RETURN_IF_EXCEPTION(scope, { }); } bool extractable = state.argument(3).toBoolean(&state); RETURN_IF_EXCEPTION(scope, JSValue()); CryptoKeyUsageBitmap keyUsages = 0; if (state.argumentCount() >= 5) { keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(4)); RETURN_IF_EXCEPTION(scope, { }); } RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](CryptoKey& result) mutable { wrapper->resolve<IDLInterface<CryptoKey>>(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback)); RETURN_IF_EXCEPTION(scope, JSValue()); return promise; }
JSValue JSWebKitSubtleCrypto::generateKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 1) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForGenerateKey(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); bool extractable = state.argument(1).toBoolean(&state); RETURN_IF_EXCEPTION(scope, { }); CryptoKeyUsageBitmap keyUsages = 0; if (state.argumentCount() >= 3) { keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(2)); RETURN_IF_EXCEPTION(scope, { }); } RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](KeyOrKeyPair&& keyOrKeyPair) mutable { WTF::switchOn(keyOrKeyPair, [&wrapper] (RefPtr<CryptoKey>& key) { wrapper->resolve<IDLInterface<CryptoKey>>(*key); }, [&wrapper] (CryptoKeyPair& keyPair) { wrapper->resolve<IDLDictionary<CryptoKeyPair>>(keyPair); } ); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = algorithm->generateKey(*parameters, extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback), *scriptExecutionContextFromExecState(&state)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
JSValue JSWebKitSubtleCrypto::verify(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 4) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(state, scope, algorithm->identifier(), state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1)); if (!key) return throwTypeError(&state, scope); if (!key->allows(CryptoKeyUsageVerify)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'")); throwNotSupportedError(state, scope); return jsUndefined(); } auto signature = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2)); RETURN_IF_EXCEPTION(scope, { }); auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](bool result) mutable { wrapper->resolve<IDLBoolean>(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }
TEST_F(ScriptPromiseTest, rejectThen) { RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); ScriptPromise promise = resolver->promise(); String onFulfilled, onRejected; resolver->reject("hello"); promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); ASSERT_FALSE(promise.isEmpty()); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ(String(), onRejected); isolate()->RunMicrotasks(); EXPECT_EQ(String(), onFulfilled); EXPECT_EQ("hello", onRejected); }
ScriptPromise StorageQuota::queryInfo(ExecutionContext* executionContext, String type) { ASSERT(executionContext); ScriptPromise promise = ScriptPromise::createPending(executionContext); RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(promise, executionContext); SecurityOrigin* securityOrigin = executionContext->securityOrigin(); if (securityOrigin->isUnique()) { resolver->reject(DOMError::create(NotSupportedError)); return promise; } KURL storagePartition = KURL(KURL(), securityOrigin->toString()); blink::Platform::current()->queryStorageUsageAndQuota(storagePartition, stringToStorageQuotaType(type), WebStorageQuotaCallbacksImpl::createLeakedPtr(resolver, executionContext)); return promise; }
ScriptPromise StorageQuotaClientImpl::requestPersistentQuota(ExecutionContext* executionContext, unsigned long long newQuotaInBytes) { ASSERT(executionContext); RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(executionContext); ScriptPromise promise = resolver->promise(); if (executionContext->isDocument()) { Document* document = toDocument(executionContext); WebFrameImpl* webFrame = WebFrameImpl::fromFrame(document->frame()); OwnPtr<StorageQuotaCallbacks> callbacks = StorageQuotaCallbacksImpl::create(resolver, executionContext); webFrame->client()->requestStorageQuota(webFrame, WebStorageQuotaTypePersistent, newQuotaInBytes, callbacks.release()); } else { // Requesting quota in Worker is not supported. resolver->reject(DOMError::create(NotSupportedError)); } return promise; }
JSValue JSWebKitSubtleCrypto::importKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 3) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); CryptoKeyFormat keyFormat; auto success = cryptoKeyFormatFromJSValue(state, state.argument(0), keyFormat); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); CryptoOperationData data; success = cryptoOperationDataFromJSValue(&state, state.uncheckedArgument(1), data); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); RefPtr<CryptoAlgorithm> algorithm; RefPtr<CryptoAlgorithmParametersDeprecated> parameters; if (!state.uncheckedArgument(2).isNull()) { algorithm = createAlgorithmFromJSValue(state, state.uncheckedArgument(2)); ASSERT(scope.exception() || algorithm); if (!algorithm) return jsUndefined(); parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(&state, algorithm->identifier(), state.uncheckedArgument(2)); ASSERT(scope.exception() || parameters); if (!parameters) return jsUndefined(); } bool extractable = false; if (state.argumentCount() >= 4) { extractable = state.uncheckedArgument(3).toBoolean(&state); RETURN_IF_EXCEPTION(scope, JSValue()); } CryptoKeyUsageBitmap keyUsages = 0; if (state.argumentCount() >= 5) { auto success = cryptoKeyUsagesFromJSValue(state, state.argument(4), keyUsages); ASSERT(scope.exception() || success); if (!success) return jsUndefined(); } RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); auto successCallback = [wrapper](CryptoKey& result) mutable { wrapper->resolve(result); }; auto failureCallback = [wrapper]() mutable { wrapper->reject(nullptr); }; WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback)); RETURN_IF_EXCEPTION(scope, JSValue()); return promise; }
JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state) { VM& vm = state.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (state.argumentCount() < 5) return throwException(&state, scope, createNotEnoughArgumentsError(&state)); auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0)); RETURN_IF_EXCEPTION(scope, { }); auto wrappedKeyData = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2)); if (!unwrappingKey) return throwTypeError(&state, scope); if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) { wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'")); throwNotSupportedError(state, scope); return jsUndefined(); } auto unwrapAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); auto unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, unwrapAlgorithm->identifier(), state.uncheckedArgument(3)); RETURN_IF_EXCEPTION(scope, { }); RefPtr<CryptoAlgorithm> unwrappedKeyAlgorithm; RefPtr<CryptoAlgorithmParametersDeprecated> unwrappedKeyAlgorithmParameters; if (!state.uncheckedArgument(4).isNull()) { unwrappedKeyAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(4)); RETURN_IF_EXCEPTION(scope, { }); unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, unwrappedKeyAlgorithm->identifier(), state.uncheckedArgument(4)); RETURN_IF_EXCEPTION(scope, { }); } bool extractable = state.argument(5).toBoolean(&state); RETURN_IF_EXCEPTION(scope, { }); CryptoKeyUsageBitmap keyUsages = 0; if (state.argumentCount() >= 7) { keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(6)); RETURN_IF_EXCEPTION(scope, { }); } RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow()); auto promise = wrapper->promise(); Strong<JSDOMGlobalObject> domGlobalObject(state.vm(), globalObject()); auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable { auto importSuccessCallback = [wrapper](CryptoKey& key) mutable { wrapper->resolve<IDLInterface<CryptoKey>>(key); }; auto importFailureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; VM& vm = domGlobalObject->vm(); auto scope = DECLARE_CATCH_SCOPE(vm); ExecState& state = *domGlobalObject->globalExec(); WebCore::importKey(state, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, WTFMove(importSuccessCallback), WTFMove(importFailureCallback)); if (UNLIKELY(scope.exception())) { // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions. scope.clearException(); wrapper->reject(); // FIXME: This should reject with an Exception. } }; auto decryptFailureCallback = [wrapper]() mutable { wrapper->reject(); // FIXME: This should reject with an Exception. }; auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback)); if (result.hasException()) { propagateException(state, scope, result.releaseException()); return { }; } return promise; }