ScriptPromise Permissions::request(ScriptState* scriptState, const Vector<Dictionary>& rawPermissions)
{
    WebPermissionClient* client = getClient(scriptState->executionContext());
    if (!client)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "In its current state, the global scope can't query permissions."));

    TrackExceptionState exceptionState;
    OwnPtr<WebVector<WebPermissionType>> permissions = adoptPtr(new WebVector<WebPermissionType>(rawPermissions.size()));

    for (size_t i = 0; i < rawPermissions.size(); ++i) {
        const Dictionary& rawPermission = rawPermissions[i];
        PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState);

        if (exceptionState.hadException())
            return ScriptPromise::reject(scriptState, v8::Exception::TypeError(v8String(scriptState->isolate(), exceptionState.message())));

        permissions->operator[](i) = getPermissionType(scriptState, rawPermission, permission, exceptionState);
    }

    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
    ScriptPromise promise = resolver->promise();

    // We need to do this is a separate loop because we can't create the Resolver and Promise untile we are clear of all parsing/type errors.
    for (size_t i = 0; i < rawPermissions.size(); ++i) {
        if (handleNotSupportedPermission(scriptState, rawPermissions[i], resolver, (*permissions)[i], exceptionState))
            return promise;
    }

    client->requestPermissions(*permissions, KURL(KURL(), scriptState->executionContext()->securityOrigin()->toString()), new PermissionsCallback(resolver, permissions.release()));
    return promise;
}
ScriptPromise Permissions::requestAll(ScriptState* scriptState, const Vector<Dictionary>& rawPermissions)
{
    WebPermissionClient* client = getClient(scriptState->getExecutionContext());
    if (!client)
        return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(InvalidStateError, "In its current state, the global scope can't request permissions."));

    ExceptionState exceptionState(ExceptionState::GetterContext,  "request", "Permissions", scriptState->context()->Global(), scriptState->isolate());
    OwnPtr<Vector<WebPermissionType>> internalPermissions = adoptPtr(new Vector<WebPermissionType>());
    OwnPtr<Vector<int>> callerIndexToInternalIndex = adoptPtr(new Vector<int>(rawPermissions.size()));
    for (size_t i = 0; i < rawPermissions.size(); ++i) {
        const Dictionary& rawPermission = rawPermissions[i];

        Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermission, exceptionState);
        if (exceptionState.hadException())
            return exceptionState.reject(scriptState);

        // Only append permissions to the vector that is passed to the client if it is not already
        // in the vector (i.e. do not duplicate permisison types).
        int internalIndex;
        auto it = internalPermissions->find(type.get());
        if (it == kNotFound) {
            internalIndex = internalPermissions->size();
            internalPermissions->append(type.get());
        } else {
            internalIndex = it;
        }
        callerIndexToInternalIndex->operator[](i) = internalIndex;
    }

    ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
    ScriptPromise promise = resolver->promise();

    WebVector<WebPermissionType> internalWebPermissions = *internalPermissions;
    client->requestPermissions(internalWebPermissions, KURL(KURL(), scriptState->getExecutionContext()->getSecurityOrigin()->toString()),
        new PermissionsCallback(resolver, internalPermissions.release(), callerIndexToInternalIndex.release()));
    return promise;
}