Beispiel #1
0
void CryptoAlgorithmRSASSA_PKCS1_v1_5::exportKey(SubtleCrypto::KeyFormat format, Ref<CryptoKey>&& key, KeyDataCallback&& callback, ExceptionCallback&& exceptionCallback)
{
    const auto& rsaKey = downcast<CryptoKeyRSA>(key.get());

    if (!rsaKey.keySizeInBits()) {
        exceptionCallback(OperationError);
        return;
    }

    KeyData result;
    switch (format) {
    case SubtleCrypto::KeyFormat::Jwk: {
        JsonWebKey jwk = rsaKey.exportJwk();
        switch (rsaKey.hashAlgorithmIdentifier()) {
        case CryptoAlgorithmIdentifier::SHA_1:
            jwk.alg = String(ALG1);
            break;
        case CryptoAlgorithmIdentifier::SHA_224:
            jwk.alg = String(ALG224);
            break;
        case CryptoAlgorithmIdentifier::SHA_256:
            jwk.alg = String(ALG256);
            break;
        case CryptoAlgorithmIdentifier::SHA_384:
            jwk.alg = String(ALG384);
            break;
        case CryptoAlgorithmIdentifier::SHA_512:
            jwk.alg = String(ALG512);
            break;
        default:
            ASSERT_NOT_REACHED();
        }
        result = WTFMove(jwk);
        break;
    }
    case SubtleCrypto::KeyFormat::Spki: {
        auto spki = rsaKey.exportSpki();
        if (spki.hasException()) {
            exceptionCallback(spki.releaseException().code());
            return;
        }
        result = spki.releaseReturnValue();
        break;
    }
    case SubtleCrypto::KeyFormat::Pkcs8: {
        auto pkcs8 = rsaKey.exportPkcs8();
        if (pkcs8.hasException()) {
            exceptionCallback(pkcs8.releaseException().code());
            return;
        }
        result = pkcs8.releaseReturnValue();
        break;
    }
    default:
        exceptionCallback(NOT_SUPPORTED_ERR);
        return;
    }

    callback(format, WTFMove(result));
}
Beispiel #2
0
ExceptionOr<void> MessagePort::postMessage(JSC::ExecState& state, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer)
{
    Vector<RefPtr<MessagePort>> ports;
    auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
    if (message.hasException())
        return message.releaseException();

    if (!isEntangled())
        return { };
    ASSERT(m_scriptExecutionContext);

    std::unique_ptr<MessagePortChannelArray> channels;
    // Make sure we aren't connected to any of the passed-in ports.
    if (!ports.isEmpty()) {
        for (auto& dataPort : ports) {
            if (dataPort == this || m_entangledChannel->isConnectedTo(dataPort.get()))
                return Exception { DATA_CLONE_ERR };
        }
        auto disentangleResult = MessagePort::disentanglePorts(WTFMove(ports));
        if (disentangleResult.hasException())
            return disentangleResult.releaseException();
        channels = disentangleResult.releaseReturnValue();
    }
    m_entangledChannel->postMessageToRemote(message.releaseReturnValue(), WTFMove(channels));
    return { };
}
Beispiel #3
0
ExceptionOr<void> Worker::postMessage(JSC::ExecState& state, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer)
{
    Vector<RefPtr<MessagePort>> ports;
    auto message = SerializedScriptValue::create(state, messageValue, WTFMove(transfer), ports);
    if (message.hasException())
        return message.releaseException();

    // Disentangle the port in preparation for sending it to the remote context.
    auto channels = MessagePort::disentanglePorts(WTFMove(ports));
    if (channels.hasException())
        return channels.releaseException();
    m_contextProxy.postMessageToWorkerGlobalScope(message.releaseReturnValue(), channels.releaseReturnValue());
    return { };
}
Beispiel #4
0
ExceptionOr<Ref<Database>> DatabaseManager::tryToOpenDatabaseBackend(DatabaseContext& backendContext, const String& name, const String& expectedVersion, const String& displayName, unsigned estimatedSize, bool setVersionInNewDatabase,
    OpenAttempt attempt)
{
    ExceptionOr<void> preflightResult;
    switch (attempt) {
    case FirstTryToOpenDatabase:
        preflightResult = DatabaseTracker::singleton().canEstablishDatabase(backendContext, name, estimatedSize);
        break;
    case RetryOpenDatabase:
        preflightResult = DatabaseTracker::singleton().retryCanEstablishDatabase(backendContext, name, estimatedSize);
        break;
    }
    if (preflightResult.hasException())
        return preflightResult.releaseException();

    auto database = adoptRef(*new Database(backendContext, name, expectedVersion, displayName, estimatedSize));

    auto openResult = database->openAndVerifyVersion(setVersionInNewDatabase);
    if (openResult.hasException())
        return openResult.releaseException();

    // FIXME: What guarantees backendContext.securityOrigin() is non-null?
    DatabaseTracker::singleton().setDatabaseDetails(backendContext.securityOrigin(), name, displayName, estimatedSize);
    return WTFMove(database);
}
Beispiel #5
0
bool JSStorage::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult)
{
    VM& vm = state->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // Only perform the custom put if the object doesn't have a native property by this name.
    // Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check
    // the native property slots manually.
    PropertySlot slot { this, PropertySlot::InternalMethodType::GetOwnProperty };

    JSValue prototype = this->getPrototypeDirect();
    if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot))
        return false;

    if (propertyName.isSymbol())
        return false;

    String stringValue = value.toWTFString(state);
    RETURN_IF_EXCEPTION(scope, true);

    auto setItemResult = wrapped().setItem(propertyNameToString(propertyName), stringValue);
    if (setItemResult.hasException()) {
        propagateException(*state, scope, setItemResult.releaseException());
        return true;
    }

    putResult = true;
    return true;
}
Beispiel #6
0
ExceptionOr<String> FileReaderSync::startLoadingString(ScriptExecutionContext& scriptExecutionContext, FileReaderLoader& loader, Blob& blob)
{
    auto result = startLoading(scriptExecutionContext, loader, blob);
    if (result.hasException())
        return result.releaseException();
    return loader.stringResult();
}
Beispiel #7
0
ExceptionOr<Ref<Worker>> Worker::create(ScriptExecutionContext& context, const String& url, JSC::RuntimeFlags runtimeFlags)
{
    ASSERT(isMainThread());

    // We don't currently support nested workers, so workers can only be created from documents.
    ASSERT_WITH_SECURITY_IMPLICATION(context.isDocument());

    auto worker = adoptRef(*new Worker(context, runtimeFlags));

    worker->suspendIfNeeded();

    bool shouldBypassMainWorldContentSecurityPolicy = context.shouldBypassMainWorldContentSecurityPolicy();
    auto scriptURL = worker->resolveURL(url, shouldBypassMainWorldContentSecurityPolicy);
    if (scriptURL.hasException())
        return scriptURL.releaseException();

    worker->m_shouldBypassMainWorldContentSecurityPolicy = shouldBypassMainWorldContentSecurityPolicy;

    // The worker context does not exist while loading, so we must ensure that the worker object is not collected, nor are its event listeners.
    worker->setPendingActivity(worker.ptr());

    worker->m_scriptLoader = WorkerScriptLoader::create();
    auto contentSecurityPolicyEnforcement = shouldBypassMainWorldContentSecurityPolicy ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceChildSrcDirective;
    worker->m_scriptLoader->loadAsynchronously(&context, scriptURL.releaseReturnValue(), FetchOptions::Mode::SameOrigin, contentSecurityPolicyEnforcement, worker->m_identifier, worker.ptr());
    return WTFMove(worker);
}
Beispiel #8
0
ExceptionOr<Ref<Database>> DatabaseManager::openDatabase(ScriptExecutionContext& context, const String& name, const String& expectedVersion, const String& displayName, unsigned estimatedSize, RefPtr<DatabaseCallback>&& creationCallback)
{
    ScriptController::initializeThreading();

    bool setVersionInNewDatabase = !creationCallback;
    auto openResult = openDatabaseBackend(context, name, expectedVersion, displayName, estimatedSize, setVersionInNewDatabase);
    if (openResult.hasException())
        return openResult.releaseException();

    RefPtr<Database> database = openResult.releaseReturnValue();

    auto databaseContext = this->databaseContext(context);
    databaseContext->setHasOpenDatabases();
    InspectorInstrumentation::didOpenDatabase(&context, database.copyRef(), context.securityOrigin()->host(), name, expectedVersion);

    if (database->isNew() && creationCallback.get()) {
        LOG(StorageAPI, "Scheduling DatabaseCreationCallbackTask for database %p\n", database.get());
        database->setHasPendingCreationEvent(true);
        database->m_scriptExecutionContext->postTask([creationCallback, database] (ScriptExecutionContext&) {
            creationCallback->handleEvent(database.get());
            database->setHasPendingCreationEvent(false);
        });
    }

    return database.releaseNonNull();
}
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;
}
Beispiel #10
0
ExceptionOr<RefPtr<ArrayBuffer>> FileReaderSync::readAsArrayBuffer(ScriptExecutionContext& scriptExecutionContext, Blob& blob)
{
    FileReaderLoader loader(FileReaderLoader::ReadAsArrayBuffer, 0);
    auto result = startLoading(scriptExecutionContext, loader, blob);
    if (result.hasException())
        return result.releaseException();
    return loader.arrayBufferResult();
}
Beispiel #11
0
ExceptionOr<Ref<WebKitCSSMatrix>> WebKitCSSMatrix::create(const String& string)
{
    auto result = adoptRef(*new WebKitCSSMatrix);
    auto setMatrixValueResult = result->setMatrixValue(string);
    if (setMatrixValueResult.hasException())
        return setMatrixValueResult.releaseException();
    return WTFMove(result);
}
Beispiel #12
0
ExceptionOr<void> Worker::postMessage(RefPtr<SerializedScriptValue>&& message, Vector<RefPtr<MessagePort>>&& ports)
{
    // Disentangle the port in preparation for sending it to the remote context.
    auto channels = MessagePort::disentanglePorts(WTFMove(ports));
    if (channels.hasException())
        return channels.releaseException();
    m_contextProxy->postMessageToWorkerGlobalScope(WTFMove(message), channels.releaseReturnValue());
    return { };
}
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;
}
Beispiel #14
0
ExceptionOr<void> ShadowRoot::setInnerHTML(const String& markup)
{
    if (isOrphan())
        return Exception { INVALID_ACCESS_ERR };
    auto fragment = createFragmentForInnerOuterHTML(*host(), markup, AllowScriptingContent);
    if (fragment.hasException())
        return fragment.releaseException();
    return replaceChildrenWithFragment(*this, fragment.releaseReturnValue());
}
Beispiel #15
0
ExceptionOr<void> SVGLengthValue::convertToSpecifiedUnits(unsigned short type, const SVGLengthContext& context)
{
    if (type == LengthTypeUnknown || type > LengthTypePC)
        return Exception { NOT_SUPPORTED_ERR };

    auto valueInUserUnits = valueForBindings(context);
    if (valueInUserUnits.hasException())
        return valueInUserUnits.releaseException();

    auto originalUnitAndType = m_unit;
    m_unit = storeUnit(extractMode(m_unit), static_cast<SVGLengthType>(type));
    auto result = setValue(valueInUserUnits.releaseReturnValue(), context);
    if (result.hasException()) {
        m_unit = originalUnitAndType;
        return result.releaseException();
    }

    return { };
}
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;
}
Beispiel #17
0
ExceptionOr<void> SVGLengthValue::setValue(float value, const SVGLengthContext& context)
{
    // 100% = 100.0 instead of 1.0 for historical reasons, this could eventually be changed
    if (extractType(m_unit) == LengthTypePercentage)
        value = value / 100;

    auto convertedValue = context.convertValueFromUserUnits(value, extractMode(m_unit), extractType(m_unit));
    if (convertedValue.hasException())
        return convertedValue.releaseException();
    m_valueInSpecifiedUnits = convertedValue.releaseReturnValue();
    return { };
}
ExceptionOr<void> PaymentHandler::canCreateSession(Document& document)
{
#if ENABLE(APPLE_PAY)
    auto result = PaymentSession::canCreateSession(document);
    if (result.hasException())
        return Exception { SecurityError, result.releaseException().releaseMessage() };
#else
    UNUSED_PARAM(document);
#endif

    return { };
}
Beispiel #19
0
ExceptionOr<RefPtr<RTCConfiguration>> RTCConfiguration::create(const Dictionary& configuration)
{
    if (configuration.isUndefinedOrNull())
        return nullptr;

    auto result = adoptRef(*new RTCConfiguration);
    auto initializeResult = result->initialize(configuration);
    if (initializeResult.hasException())
        return initializeResult.releaseException();

    return RefPtr<RTCConfiguration> { WTFMove(result) };
}
Beispiel #20
0
ExceptionOr<void> RTCConfiguration::initialize(const Dictionary& configuration)
{
    ArrayValue iceServers;
    bool ok = configuration.get("iceServers", iceServers);
    if (!ok || iceServers.isUndefinedOrNull())
        return Exception { TYPE_MISMATCH_ERR };

    size_t numberOfServers;
    ok = iceServers.length(numberOfServers);
    if (!ok)
        return Exception { TYPE_MISMATCH_ERR };
    if (!numberOfServers)
        return Exception { INVALID_ACCESS_ERR };

    for (size_t i = 0; i < numberOfServers; ++i) {
        Dictionary iceServerDict;
        ok = iceServers.get(i, iceServerDict);
        if (!ok)
            return Exception { TYPE_MISMATCH_ERR };

        auto server = parseIceServer(iceServerDict);
        if (server.hasException())
            return server.releaseException();

        m_iceServers.append(server.releaseReturnValue());
    }

    String iceTransportPolicy;
    if (configuration.get("iceTransportPolicy", iceTransportPolicy)) {
        if (iceTransportPolicy == "relay")
            m_iceTransportPolicy = IceTransportPolicy::Relay;
        else if (iceTransportPolicy == "all")
            m_iceTransportPolicy = IceTransportPolicy::All;
        else
            return Exception { TypeError };
    }

    String bundlePolicy;
    if (configuration.get("bundlePolicy", bundlePolicy)) {
        if (bundlePolicy == "balanced")
            m_bundlePolicy = BundlePolicy::Balanced;
        else if (bundlePolicy == "max-compat")
            m_bundlePolicy = BundlePolicy::MaxCompat;
        else if (bundlePolicy == "max-bundle")
            m_bundlePolicy = BundlePolicy::MaxBundle;
        else
            return Exception { TypeError };
    }

    return { };
}
void DOMFileSystem::getFile(ScriptExecutionContext& context, FileSystemFileEntry& fileEntry, GetFileCallback&& completionCallback)
{
    auto virtualPath = fileEntry.virtualPath();
    auto fullPath = evaluatePath(virtualPath);
    m_workQueue->dispatch([context = makeRef(context), fullPath = crossThreadCopy(fullPath), virtualPath = crossThreadCopy(virtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
        auto validatedVirtualPath = validatePathIsExpectedType(fullPath, WTFMove(virtualPath), FileMetadata::Type::File);
        callOnMainThread([context = WTFMove(context), fullPath = crossThreadCopy(fullPath), validatedVirtualPath = crossThreadCopy(validatedVirtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
            if (validatedVirtualPath.hasException())
                completionCallback(validatedVirtualPath.releaseException());
            else
                completionCallback(File::create(fullPath));
        });
    });
}
Beispiel #22
0
void JSStorage::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
    VM& vm = state->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    auto& thisObject = *jsCast<JSStorage*>(object);
    auto lengthResult = thisObject.wrapped().length();
    if (lengthResult.hasException()) {
        propagateException(*state, scope, lengthResult.releaseException());
        return;
    }
    unsigned length = lengthResult.releaseReturnValue();
    for (unsigned i = 0; i < length; ++i) {
        auto keyResult = thisObject.wrapped().key(i);
        if (keyResult.hasException()) {
            propagateException(*state, scope, lengthResult.releaseException());
            return;
        }
        propertyNames.add(Identifier::fromString(state, keyResult.releaseReturnValue()));
    }
        
    Base::getOwnPropertyNames(&thisObject, state, propertyNames, mode);
}
static gboolean webkit_dom_html_embed_element_dispatch_event(WebKitDOMEventTarget* target, WebKitDOMEvent* event, GError** error)
{
    WebCore::Event* coreEvent = WebKit::core(event);
    if (!coreEvent)
        return false;
    WebCore::HTMLEmbedElement* coreTarget = static_cast<WebCore::HTMLEmbedElement*>(WEBKIT_DOM_OBJECT(target)->coreObject);

    auto result = coreTarget->dispatchEventForBindings(*coreEvent);
    if (result.hasException()) {
        WebCore::ExceptionCodeDescription description(result.releaseException().code());
        g_set_error_literal(error, g_quark_from_string("WEBKIT_DOM"), description.code, description.name);
        return false;
    }
    return result.releaseReturnValue();
}
Beispiel #24
0
ExceptionOr<int> CSSStyleSheet::addRule(const String& selector, const String& style, std::optional<unsigned> index)
{
    StringBuilder text;
    text.append(selector);
    text.appendLiteral(" { ");
    text.append(style);
    if (!style.isEmpty())
        text.append(' ');
    text.append('}');
    auto insertRuleResult = insertRule(text.toString(), index.value_or(length()));
    if (insertRuleResult.hasException())
        return insertRuleResult.releaseException();
    
    // As per Microsoft documentation, always return -1.
    return -1;
}
bool JSTestNamedDeleterThrowingException::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
{
    auto& thisObject = *jsCast<JSTestNamedDeleterThrowingException*>(cell);
    auto& impl = thisObject.wrapped();
    if (isVisibleNamedProperty<OverrideBuiltins::No>(*state, thisObject, propertyName)) {
        auto result = impl.deleteNamedProperty(propertyNameToString(propertyName));
        if (result.hasException()) {
            auto throwScope = DECLARE_THROW_SCOPE(state->vm());
            propagateException(*state, throwScope, result.releaseException());
            return true;
        }

        return result.releaseReturnValue();
    }
    return JSObject::deleteProperty(cell, state, propertyName);
}
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;
}
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;
}
Beispiel #28
0
ExceptionOr<Ref<FontFace>> FontFace::create(JSC::ExecState& state, Document& document, const String& family, JSC::JSValue source, const Descriptors& descriptors)
{
    auto result = adoptRef(*new FontFace(document.fontSelector()));

    bool dataRequiresAsynchronousLoading = true;

    auto setFamilyResult = result->setFamily(family);
    if (setFamilyResult.hasException())
        return setFamilyResult.releaseException();

    if (source.isString()) {
        auto value = FontFace::parseString(source.getString(&state), CSSPropertySrc);
        if (!is<CSSValueList>(value.get()))
            return Exception { SYNTAX_ERR };
        CSSFontFace::appendSources(result->backing(), downcast<CSSValueList>(*value), &document, false);
    } else if (auto arrayBufferView = toUnsharedArrayBufferView(source))
        dataRequiresAsynchronousLoading = populateFontFaceWithArrayBuffer(result->backing(), arrayBufferView.releaseNonNull());
    else if (auto arrayBuffer = toUnsharedArrayBuffer(source)) {
        auto arrayBufferView = JSC::Uint8Array::create(arrayBuffer, 0, arrayBuffer->byteLength());
        dataRequiresAsynchronousLoading = populateFontFaceWithArrayBuffer(result->backing(), arrayBufferView.releaseNonNull());
    }

    // These ternaries match the default strings inside the FontFaceDescriptors dictionary inside FontFace.idl.
    auto setStyleResult = result->setStyle(descriptors.style.isEmpty() ? ASCIILiteral("normal") : descriptors.style);
    if (setStyleResult.hasException())
        return setStyleResult.releaseException();
    auto setWeightResult = result->setWeight(descriptors.weight.isEmpty() ? ASCIILiteral("normal") : descriptors.weight);
    if (setWeightResult.hasException())
        return setWeightResult.releaseException();
    auto setStretchResult = result->setStretch(descriptors.stretch.isEmpty() ? ASCIILiteral("normal") : descriptors.stretch);
    if (setStretchResult.hasException())
        return setStretchResult.releaseException();
    auto setUnicodeRangeResult = result->setUnicodeRange(descriptors.unicodeRange.isEmpty() ? ASCIILiteral("U+0-10FFFF") : descriptors.unicodeRange);
    if (setUnicodeRangeResult.hasException())
        return setUnicodeRangeResult.releaseException();
    auto setVariantResult = result->setVariant(descriptors.variant.isEmpty() ? ASCIILiteral("normal") : descriptors.variant);
    if (setVariantResult.hasException())
        return setVariantResult.releaseException();
    auto setFeatureSettingsResult = result->setFeatureSettings(descriptors.featureSettings.isEmpty() ? ASCIILiteral("normal") : descriptors.featureSettings);
    if (setFeatureSettingsResult.hasException())
        return setFeatureSettingsResult.releaseException();

    if (!dataRequiresAsynchronousLoading) {
        result->backing().load();
        ASSERT(result->backing().status() == CSSFontFace::Status::Success);
    }

    return WTFMove(result);
}
void DOMFileSystem::getParent(ScriptExecutionContext& context, FileSystemEntry& entry, GetParentCallback&& completionCallback)
{
    ASSERT(&entry.filesystem() == this);

    auto virtualPath = resolveRelativeVirtualPath(entry.virtualPath(), "..");
    ASSERT(virtualPath[0] == '/');
    auto fullPath = evaluatePath(virtualPath);
    m_workQueue->dispatch([this, context = makeRef(context), fullPath = crossThreadCopy(fullPath), virtualPath = crossThreadCopy(virtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
        auto validatedVirtualPath = validatePathIsExpectedType(fullPath, WTFMove(virtualPath), FileMetadata::Type::Directory);
        callOnMainThread([this, context = WTFMove(context), validatedVirtualPath = crossThreadCopy(validatedVirtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
            if (validatedVirtualPath.hasException())
                completionCallback(validatedVirtualPath.releaseException());
            else
                completionCallback(FileSystemDirectoryEntry::create(context, *this, validatedVirtualPath.releaseReturnValue()));
        });
    });
}
void CryptoAlgorithmRSA_OAEP::platformDecrypt(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& key, Vector<uint8_t>&& cipherText, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
{
    context.ref();
    workQueue.dispatch([parameters = WTFMove(parameters), key = WTFMove(key), cipherText = WTFMove(cipherText), callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback), &context]() mutable {
        auto& rsaParameters = downcast<CryptoAlgorithmRsaOaepParams>(*parameters);
        auto& rsaKey = downcast<CryptoKeyRSA>(key.get());
        auto result = decryptRSA_OAEP(rsaKey.hashAlgorithmIdentifier(), rsaParameters.labelVector(), rsaKey.platformKey(), rsaKey.keySizeInBits(), cipherText.data(), cipherText.size());
        if (result.hasException()) {
            context.postTask([exceptionCallback = WTFMove(exceptionCallback), ec = result.releaseException().code()](ScriptExecutionContext& context) {
                exceptionCallback(ec);
                context.deref();
            });
            return;
        }
        context.postTask([callback = WTFMove(callback), result = result.releaseReturnValue()](ScriptExecutionContext& context) {
            callback(result);
            context.deref();
        });
    });
}