예제 #1
0
RefPtr<IDBOpenDBRequest> IDBFactory::openInternal(ScriptExecutionContext* context, const String& name, unsigned long long version, ExceptionCode& ec)
{
    if (name.isNull()) {
        ec = TypeError;
        return nullptr;
    }

    if (shouldThrowSecurityException(context)) {
        ec = SECURITY_ERR;
        return nullptr;
    }

    ASSERT(context->securityOrigin());
    ASSERT(context->topOrigin());
    IDBDatabaseIdentifier databaseIdentifier(name, *context->securityOrigin(), *context->topOrigin());
    if (!databaseIdentifier.isValid()) {
        ec = TypeError;
        return nullptr;
    }

    auto request = IDBOpenDBRequest::createOpenRequest(m_connectionToServer.get(), context, databaseIdentifier, version);
    m_connectionToServer->openDatabase(request.get());

    return adoptRef(&request.leakRef());
}
예제 #2
0
RefPtr<WebCore::IDBOpenDBRequest> IDBFactory::deleteDatabase(ScriptExecutionContext* context, const String& name, ExceptionCode& ec)
{
    LOG(IndexedDB, "IDBFactory::deleteDatabase");

    if (name.isNull()) {
        ec = TypeError;
        return nullptr;
    }
    
    if (shouldThrowSecurityException(context)) {
        ec = SECURITY_ERR;
        return nullptr;
    }

    ASSERT(context->securityOrigin());
    ASSERT(context->topOrigin());
    IDBDatabaseIdentifier databaseIdentifier(name, *context->securityOrigin(), *context->topOrigin());
    if (!databaseIdentifier.isValid()) {
        ec = TypeError;
        return nullptr;
    }

    auto request = IDBOpenDBRequest::createDeleteRequest(m_connectionToServer.get(), context, databaseIdentifier);
    m_connectionToServer->deleteDatabase(request.get());

    return adoptRef(&request.leakRef());
}
예제 #3
0
void UniqueIDBDatabase::handleOpenDatabaseOperations()
{
    ASSERT(isMainThread());
    LOG(IndexedDB, "(main) UniqueIDBDatabase::handleOpenDatabaseOperations");

    // If a version change transaction is currently in progress, no new connections can be opened right now.
    // We will try again later.
    if (m_versionChangeDatabaseConnection)
        return;

    auto operation = m_pendingOpenDatabaseOperations.takeFirst();

    // 3.3.1 Opening a database
    // If requested version is undefined, then let requested version be 1 if db was created in the previous step,
    // or the current version of db otherwise.
    uint64_t requestedVersion = operation->requestData().requestedVersion();
    if (!requestedVersion)
        requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1;

    // 3.3.1 Opening a database
    // If the database version higher than the requested version, abort these steps and return a VersionError.
    if (requestedVersion < m_databaseInfo->version()) {
        auto result = IDBResultData::error(operation->requestData().requestIdentifier(), IDBError(IDBExceptionCode::VersionError));
        operation->connection().didOpenDatabase(result);
        return;
    }

    Ref<UniqueIDBDatabaseConnection> connection = UniqueIDBDatabaseConnection::create(*this, operation->connection());
    UniqueIDBDatabaseConnection* rawConnection = &connection.get();
    m_server.registerDatabaseConnection(*rawConnection);

    if (requestedVersion == m_databaseInfo->version()) {
        addOpenDatabaseConnection(WTF::move(connection));

        auto result = IDBResultData::openDatabaseSuccess(operation->requestData().requestIdentifier(), *rawConnection);
        operation->connection().didOpenDatabase(result);
        return;
    }

    ASSERT(!m_versionChangeOperation);
    ASSERT(!m_versionChangeDatabaseConnection);

    m_versionChangeOperation = adoptRef(operation.leakRef());
    m_versionChangeDatabaseConnection = rawConnection;

    // 3.3.7 "versionchange" transaction steps
    // If there's no other open connections to this database, the version change process can begin immediately.
    if (!hasAnyOpenConnections()) {
        startVersionChangeTransaction();
        return;
    }

    // Otherwise we have to notify all those open connections and wait for them to close.
    notifyConnectionsOfVersionChange();
}
예제 #4
0
RefPtr<WebCore::IDBTransaction> IDBDatabase::transaction(const Vector<String>& objectStores, const String& modeString, ExceptionCodeWithMessage& ec)
{
    LOG(IndexedDB, "IDBDatabase::transaction");

    ASSERT(currentThread() == originThreadID());

    if (m_closePending) {
        ec.code = IDBDatabaseException::InvalidStateError;
        ec.message = ASCIILiteral("Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.");
        return nullptr;
    }

    if (objectStores.isEmpty()) {
        ec.code = IDBDatabaseException::InvalidAccessError;
        ec.message = ASCIILiteral("Failed to execute 'transaction' on 'IDBDatabase': The storeNames parameter was empty.");
        return nullptr;
    }

    IndexedDB::TransactionMode mode = IDBTransaction::stringToMode(modeString, ec.code);
    if (ec.code) {
        ec.message = makeString(ASCIILiteral("Failed to execute 'transaction' on 'IDBDatabase': The mode provided ('"), modeString, ASCIILiteral("') is not one of 'readonly' or 'readwrite'."));
        return nullptr;
    }

    if (mode != IndexedDB::TransactionMode::ReadOnly && mode != IndexedDB::TransactionMode::ReadWrite) {
        ec.code = TypeError;
        return nullptr;
    }

    if (m_versionChangeTransaction && !m_versionChangeTransaction->isFinishedOrFinishing()) {
        ec.code = IDBDatabaseException::InvalidStateError;
        ec.message = ASCIILiteral("Failed to execute 'transaction' on 'IDBDatabase': A version change transaction is running.");
        return nullptr;
    }

    for (auto& objectStoreName : objectStores) {
        if (m_info.hasObjectStore(objectStoreName))
            continue;
        ec.code = IDBDatabaseException::NotFoundError;
        ec.message = ASCIILiteral("Failed to execute 'transaction' on 'IDBDatabase': One of the specified object stores was not found.");
        return nullptr;
    }

    auto info = IDBTransactionInfo::clientTransaction(m_connectionProxy.get(), objectStores, mode);
    auto transaction = IDBTransaction::create(*this, info);

    LOG(IndexedDB, "IDBDatabase::transaction - Added active transaction %s", info.identifier().loggingString().utf8().data());

    m_activeTransactions.set(info.identifier(), &transaction.get());

    return adoptRef(&transaction.leakRef());
}
예제 #5
0
RefPtr<WebCore::IDBObjectStore> IDBTransaction::objectStore(const String& objectStoreName, ExceptionCode& ec)
{
    LOG(IndexedDB, "IDBTransaction::objectStore");

    if (objectStoreName.isEmpty()) {
        ec = NOT_FOUND_ERR;
        return nullptr;
    }

    if (isFinishedOrFinishing()) {
        ec = INVALID_STATE_ERR;
        return nullptr;
    }

    auto iterator = m_referencedObjectStores.find(objectStoreName);
    if (iterator != m_referencedObjectStores.end())
        return iterator->value;

    bool found = false;
    for (auto& objectStore : m_info.objectStores()) {
        if (objectStore == objectStoreName) {
            found = true;
            break;
        }
    }

    auto* info = m_database->info().infoForExistingObjectStore(objectStoreName);
    if (!info) {
        ec = NOT_FOUND_ERR;
        return nullptr;
    }

    // Version change transactions are scoped to every object store in the database.
    if (!found && !isVersionChange()) {
        ec = NOT_FOUND_ERR;
        return nullptr;
    }

    auto objectStore = IDBObjectStore::create(*info, *this);
    m_referencedObjectStores.set(objectStoreName, &objectStore.get());

    return adoptRef(&objectStore.leakRef());
}
예제 #6
0
RefPtr<WebCore::IDBTransaction> IDBDatabase::transaction(ScriptExecutionContext*, const Vector<String>& objectStores, const String& modeString, ExceptionCode& ec)
{
    LOG(IndexedDB, "IDBDatabase::transaction");

    if (m_closePending) {
        ec = INVALID_STATE_ERR;
        return nullptr;
    }

    if (objectStores.isEmpty()) {
        ec = INVALID_ACCESS_ERR;
        return nullptr;
    }

    IndexedDB::TransactionMode mode = IDBTransaction::stringToMode(modeString, ec);
    if (ec)
        return nullptr;

    if (mode != IndexedDB::TransactionMode::ReadOnly && mode != IndexedDB::TransactionMode::ReadWrite) {
        ec = TypeError;
        return nullptr;
    }

    if (m_versionChangeTransaction) {
        ec = INVALID_STATE_ERR;
        return nullptr;
    }

    for (auto& objectStoreName : objectStores) {
        if (m_info.hasObjectStore(objectStoreName))
            continue;
        ec = NOT_FOUND_ERR;
        return nullptr;
    }

    auto info = IDBTransactionInfo::clientTransaction(m_serverConnection.get(), objectStores, mode);
    auto transaction = IDBTransaction::create(*this, info);

    m_activeTransactions.set(info.identifier(), &transaction.get());

    return adoptRef(&transaction.leakRef());
}
예제 #7
0
RefPtr<WebCore::IDBObjectStore> IDBTransaction::objectStore(const String& objectStoreName, ExceptionCodeWithMessage& ec)
{
    LOG(IndexedDB, "IDBTransaction::objectStore");

    if (isFinishedOrFinishing()) {
        ec.code = IDBDatabaseException::InvalidStateError;
        ec.message = ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The transaction finished.");
        return nullptr;
    }

    auto iterator = m_referencedObjectStores.find(objectStoreName);
    if (iterator != m_referencedObjectStores.end())
        return iterator->value;

    bool found = false;
    for (auto& objectStore : m_info.objectStores()) {
        if (objectStore == objectStoreName) {
            found = true;
            break;
        }
    }

    auto* info = m_database->info().infoForExistingObjectStore(objectStoreName);
    if (!info) {
        ec.code = IDBDatabaseException::NotFoundError;
        ec.message = ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found.");
        return nullptr;
    }

    // Version change transactions are scoped to every object store in the database.
    if (!info || (!found && !isVersionChange())) {
        ec.code = IDBDatabaseException::NotFoundError;
        ec.message = ASCIILiteral("Failed to execute 'objectStore' on 'IDBTransaction': The specified object store was not found.");
        return nullptr;
    }

    auto objectStore = IDBObjectStore::create(*info, *this);
    m_referencedObjectStores.set(objectStoreName, &objectStore.get());

    return adoptRef(&objectStore.leakRef());
}