示例#1
0
RefPtr<IDBObjectStore> LegacyTransaction::objectStore(const String& name, ExceptionCode& ec)
{
    if (m_state == Finished) {
        ec = IDBDatabaseException::InvalidStateError;
        return 0;
    }

    IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
    if (it != m_objectStoreMap.end())
        return it->value;

    if (!isVersionChange() && !m_objectStoreNames.contains(name)) {
        ec = IDBDatabaseException::NotFoundError;
        return 0;
    }

    int64_t objectStoreId = m_database->findObjectStoreId(name);
    if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
        ASSERT(isVersionChange());
        ec = IDBDatabaseException::NotFoundError;
        return 0;
    }

    const IDBDatabaseMetadata& metadata = m_database->metadata();

    RefPtr<LegacyObjectStore> objectStore = LegacyObjectStore::create(metadata.objectStores.get(objectStoreId), this);
    objectStoreCreated(name, objectStore);
    return objectStore.release();
}
IDBObjectStore* IDBTransaction::objectStore(const String& name, ExceptionState& exceptionState)
{
    if (m_state == Finished) {
        exceptionState.throwDOMException(InvalidStateError, IDBDatabase::transactionFinishedErrorMessage);
        return nullptr;
    }

    IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
    if (it != m_objectStoreMap.end())
        return it->value;

    if (!isVersionChange() && !m_objectStoreNames.contains(name)) {
        exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjectStoreErrorMessage);
        return nullptr;
    }

    int64_t objectStoreId = m_database->findObjectStoreId(name);
    if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
        ASSERT(isVersionChange());
        exceptionState.throwDOMException(NotFoundError, IDBDatabase::noSuchObjectStoreErrorMessage);
        return nullptr;
    }

    const IDBDatabaseMetadata& metadata = m_database->metadata();

    IDBObjectStore* objectStore = IDBObjectStore::create(metadata.objectStores.get(objectStoreId), this);
    objectStoreCreated(name, objectStore);
    return objectStore;
}
示例#3
0
void IDBTransaction::revertDatabaseMetadata() {
  DCHECK_NE(m_state, Active);
  if (!isVersionChange())
    return;

  // Mark stores created by this transaction as deleted.
  for (auto& objectStore : m_objectStoreMap.values()) {
    const int64_t objectStoreId = objectStore->id();
    if (!objectStore->isNewlyCreated()) {
      DCHECK(m_oldStoreMetadata.contains(objectStore));
      continue;
    }

    DCHECK(!m_oldStoreMetadata.contains(objectStore));
    m_database->revertObjectStoreCreation(objectStoreId);
    objectStore->markDeleted();
  }

  for (auto& it : m_oldStoreMetadata) {
    IDBObjectStore* objectStore = it.key;
    RefPtr<IDBObjectStoreMetadata> oldMetadata = it.value;

    m_database->revertObjectStoreMetadata(oldMetadata);
    objectStore->revertMetadata(oldMetadata);
  }
  for (auto& index : m_deletedIndexes)
    index->objectStore()->revertDeletedIndexMetadata(*index);
  for (auto& oldMedata : m_deletedObjectStores)
    m_database->revertObjectStoreMetadata(std::move(oldMedata));

  // We only need to revert the database's own metadata because we have reverted
  // the metadata for the database's object stores above.
  m_database->setDatabaseMetadata(m_oldDatabaseMetadata);
}
示例#4
0
DispatchEventResult IDBTransaction::dispatchEventInternal(Event* event) {
  IDB_TRACE("IDBTransaction::dispatchEvent");
  if (!getExecutionContext()) {
    m_state = Finished;
    return DispatchEventResult::CanceledBeforeDispatch;
  }
  DCHECK_NE(m_state, Finished);
  DCHECK(m_hasPendingActivity);
  DCHECK(getExecutionContext());
  DCHECK_EQ(event->target(), this);
  m_state = Finished;

  HeapVector<Member<EventTarget>> targets;
  targets.append(this);
  targets.append(db());

  // FIXME: When we allow custom event dispatching, this will probably need to
  // change.
  DCHECK(event->type() == EventTypeNames::complete ||
         event->type() == EventTypeNames::abort);
  DispatchEventResult dispatchResult =
      IDBEventDispatcher::dispatch(event, targets);
  // FIXME: Try to construct a test where |this| outlives openDBRequest and we
  // get a crash.
  if (m_openDBRequest) {
    DCHECK(isVersionChange());
    m_openDBRequest->transactionDidFinishAndDispatch();
  }
  m_hasPendingActivity = false;
  return dispatchResult;
}
示例#5
0
void IDBTransaction::onAbort(DOMException* error) {
  IDB_TRACE("IDBTransaction::onAbort");
  if (!getExecutionContext()) {
    finished();
    return;
  }

  DCHECK_NE(m_state, Finished);
  if (m_state != Finishing) {
    // Abort was not triggered by front-end.
    DCHECK(error);
    setError(error);

    abortOutstandingRequests();
    revertDatabaseMetadata();

    m_state = Finishing;
  }

  if (isVersionChange())
    m_database->close();

  // Enqueue events before notifying database, as database may close which
  // enqueues more events and order matters.
  enqueueEvent(Event::createBubble(EventTypeNames::abort));
  finished();
}
示例#6
0
void IDBTransaction::finished() {
#if DCHECK_IS_ON()
  DCHECK(!m_finishCalled);
  m_finishCalled = true;
#endif  // DCHECK_IS_ON()

  m_database->transactionFinished(this);

  // Remove references to the IDBObjectStore and IDBIndex instances held by
  // this transaction, so Oilpan can garbage-collect the instances that aren't
  // used by JavaScript.

  for (auto& it : m_objectStoreMap) {
    IDBObjectStore* objectStore = it.value;
    if (!isVersionChange() || objectStore->isNewlyCreated()) {
      DCHECK(!m_oldStoreMetadata.contains(objectStore));
      objectStore->clearIndexCache();
    } else {
      // We'll call clearIndexCache() on this store in the loop below.
      DCHECK(m_oldStoreMetadata.contains(objectStore));
    }
  }
  m_objectStoreMap.clear();

  for (auto& it : m_oldStoreMetadata) {
    IDBObjectStore* objectStore = it.key;
    objectStore->clearIndexCache();
  }
  m_oldStoreMetadata.clear();

  m_deletedIndexes.clear();
  m_deletedObjectStores.clear();
}
示例#7
0
void IDBTransaction::deleteIndexOnServer(TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const String& indexName)
{
    LOG(IndexedDB, "IDBTransaction::deleteIndexOnServer");
    ASSERT(isVersionChange());

    serverConnection().deleteIndex(operation, objectStoreIdentifier, indexName);
}
示例#8
0
IDBError MemoryIDBBackingStore::renameIndex(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t indexIdentifier, const String& newName)
{
    LOG(IndexedDB, "MemoryIDBBackingStore::renameIndex");

    ASSERT(m_databaseInfo);
    auto* objectStoreInfo = m_databaseInfo->infoForExistingObjectStore(objectStoreIdentifier);
    if (!objectStoreInfo)
        return { IDBDatabaseException::ConstraintError };

    auto* indexInfo = objectStoreInfo->infoForExistingIndex(indexIdentifier);
    if (!indexInfo)
        return { IDBDatabaseException::ConstraintError };

    auto transaction = m_transactions.get(transactionIdentifier);
    ASSERT(transaction);
    ASSERT(transaction->isVersionChange());

    auto objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier);
    ASSERT(objectStore);
    if (!objectStore)
        return { IDBDatabaseException::ConstraintError };

    auto* index = objectStore->indexForIdentifier(indexIdentifier);
    ASSERT(index);
    if (!index)
        return { IDBDatabaseException::ConstraintError };

    String oldName = index->info().name();
    objectStore->renameIndex(*index, newName);
    transaction->indexRenamed(*index, oldName);

    indexInfo->rename(newName);

    return { };
}
示例#9
0
bool IDBTransaction::dispatchEvent(PassRefPtr<Event> event)
{
    IDB_TRACE("IDBTransaction::dispatchEvent");
    ASSERT(m_state != Finished);
    ASSERT(m_hasPendingActivity);
    ASSERT(scriptExecutionContext());
    ASSERT(event->target() == this);
    m_state = Finished;

    // Break reference cycles.
    for (IDBObjectStoreMap::iterator it = m_objectStoreMap.begin(); it != m_objectStoreMap.end(); ++it)
        it->value->transactionFinished();
    m_objectStoreMap.clear();
    for (IDBObjectStoreSet::iterator it = m_deletedObjectStores.begin(); it != m_deletedObjectStores.end(); ++it)
        (*it)->transactionFinished();
    m_deletedObjectStores.clear();

    Vector<RefPtr<EventTarget> > targets;
    targets.append(this);
    targets.append(db());

    // FIXME: When we allow custom event dispatching, this will probably need to change.
    ASSERT(event->type() == eventNames().completeEvent || event->type() == eventNames().abortEvent);
    bool returnValue = IDBEventDispatcher::dispatch(event.get(), targets);
    // FIXME: Try to construct a test where |this| outlives openDBRequest and we
    // get a crash.
    if (m_openDBRequest) {
        ASSERT(isVersionChange());
        m_openDBRequest->transactionDidFinishAndDispatch();
    }
    m_hasPendingActivity = false;
    return returnValue;
}
示例#10
0
bool IDBTransaction::dispatchEvent(Event& event)
{
    LOG(IndexedDB, "IDBTransaction::dispatchEvent");

    ASSERT(scriptExecutionContext());
    ASSERT(!m_contextStopped);
    ASSERT(event.target() == this);
    ASSERT(event.type() == eventNames().completeEvent || event.type() == eventNames().abortEvent);

    Vector<RefPtr<EventTarget>> targets;
    targets.append(this);
    targets.append(db());

    bool result = IDBEventDispatcher::dispatch(event, targets);

    if (isVersionChange()) {
        ASSERT(m_openDBRequest);
        m_openDBRequest->versionChangeTransactionDidFinish();

        if (event.type() == eventNames().completeEvent) {
            if (m_database->isClosingOrClosed())
                m_openDBRequest->fireErrorAfterVersionChangeCompletion();
            else
                m_openDBRequest->fireSuccessAfterVersionChangeCommit();
        }

        m_openDBRequest = nullptr;
    }

    return result;
}
void IDBTransaction::objectStoreCreated(const String& name, IDBObjectStore* objectStore)
{
    ASSERT(m_state != Finished);
    m_objectStoreMap.set(name, objectStore);
    if (isVersionChange())
        m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
}
示例#12
0
void IDBTransaction::deleteObjectStoreOnServer(TransactionOperation& operation, const String& objectStoreName)
{
    LOG(IndexedDB, "IDBTransaction::deleteObjectStoreOnServer");
    ASSERT(isVersionChange());

    serverConnection().deleteObjectStore(operation, objectStoreName);
}
示例#13
0
bool LegacyTransaction::dispatchEvent(Event& event)
{
    LOG(StorageAPI, "LegacyTransaction::dispatchEvent");
    ASSERT(m_state != Finished);
    ASSERT(m_hasPendingActivity);
    ASSERT(scriptExecutionContext());
    ASSERT(event.target() == this);
    m_state = Finished;

    // Break reference cycles.
    for (auto& objectStore : m_objectStoreMap)
        objectStore.value->transactionFinished();
    m_objectStoreMap.clear();
    for (auto& objectStore : m_deletedObjectStores)
        objectStore->transactionFinished();
    m_deletedObjectStores.clear();

    Vector<RefPtr<EventTarget>> targets;
    targets.append(this);
    targets.append(db());

    // FIXME: When we allow custom event dispatching, this will probably need to change.
    ASSERT(event.type() == eventNames().completeEvent || event.type() == eventNames().abortEvent);
    bool returnValue = IDBEventDispatcher::dispatch(event, targets);
    // FIXME: Try to construct a test where |this| outlives openDBRequest and we
    // get a crash.
    if (m_openDBRequest) {
        ASSERT(isVersionChange());
        m_openDBRequest->transactionDidFinishAndDispatch();
    }
    m_hasPendingActivity = false;
    return returnValue;
}
示例#14
0
void LegacyTransaction::onAbort(PassRefPtr<IDBDatabaseError> prpError)
{
    LOG(StorageAPI, "LegacyTransaction::onAbort");
    RefPtr<IDBDatabaseError> error = prpError;
    ASSERT(m_state != Finished);

    if (m_state != Finishing) {
        ASSERT(error.get());
        setError(DOMError::create(error->name()), error->message());

        // Abort was not triggered by front-end, so outstanding requests must
        // be aborted now.
        while (!m_requestList.isEmpty()) {
            RefPtr<LegacyRequest> request = *m_requestList.begin();
            m_requestList.remove(request);
            request->abort();
        }
        m_state = Finishing;
    }

    if (isVersionChange()) {
        for (auto& objectStore : m_objectStoreCleanupMap)
            objectStore.key->setMetadata(objectStore.value);
        m_database->setMetadata(m_previousMetadata);
        m_database->close();
    }
    m_objectStoreCleanupMap.clear();
    closeOpenCursors();

    // Enqueue events before notifying database, as database may close which enqueues more events and order matters.
    enqueueEvent(Event::create(eventNames().abortEvent, true, false));
    m_database->transactionFinished(this);
}
示例#15
0
void IDBTransaction::createIndexOnServer(TransactionOperation& operation, const IDBIndexInfo& info)
{
    LOG(IndexedDB, "IDBTransaction::createIndexOnServer");

    ASSERT(isVersionChange());

    m_database->serverConnection().createIndex(operation, info);
}
示例#16
0
void LegacyTransaction::objectStoreCreated(const String& name, PassRefPtr<LegacyObjectStore> prpObjectStore)
{
    ASSERT(m_state != Finished);
    RefPtr<LegacyObjectStore> objectStore = prpObjectStore;
    m_objectStoreMap.set(name, objectStore);
    if (isVersionChange())
        m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
}
示例#17
0
IDBObjectStore* IDBTransaction::objectStore(const String& name,
                                            ExceptionState& exceptionState) {
  if (isFinished()) {
    exceptionState.throwDOMException(
        InvalidStateError, IDBDatabase::transactionFinishedErrorMessage);
    return nullptr;
  }

  IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
  if (it != m_objectStoreMap.end())
    return it->value;

  if (!isVersionChange() && !m_scope.contains(name)) {
    exceptionState.throwDOMException(
        NotFoundError, IDBDatabase::noSuchObjectStoreErrorMessage);
    return nullptr;
  }

  int64_t objectStoreId = m_database->findObjectStoreId(name);
  if (objectStoreId == IDBObjectStoreMetadata::InvalidId) {
    DCHECK(isVersionChange());
    exceptionState.throwDOMException(
        NotFoundError, IDBDatabase::noSuchObjectStoreErrorMessage);
    return nullptr;
  }

  DCHECK(m_database->metadata().objectStores.contains(objectStoreId));
  RefPtr<IDBObjectStoreMetadata> objectStoreMetadata =
      m_database->metadata().objectStores.get(objectStoreId);
  DCHECK(objectStoreMetadata.get());

  IDBObjectStore* objectStore =
      IDBObjectStore::create(std::move(objectStoreMetadata), this);
  DCHECK(!m_objectStoreMap.contains(name));
  m_objectStoreMap.set(name, objectStore);

  if (isVersionChange()) {
    DCHECK(!objectStore->isNewlyCreated())
        << "Object store IDs are not assigned sequentially";
    RefPtr<IDBObjectStoreMetadata> backupMetadata =
        objectStore->metadata().createCopy();
    m_oldStoreMetadata.set(objectStore, std::move(backupMetadata));
  }
  return objectStore;
}
void MemoryBackingStoreTransaction::addNewIndex(MemoryIndex& index)
{
    LOG(IndexedDB, "MemoryBackingStoreTransaction::addNewIndex()");

    ASSERT(isVersionChange());
    m_versionChangeAddedIndexes.add(&index);

    addExistingIndex(index);
}
示例#19
0
void IDBTransaction::deleteIndex(uint64_t objectStoreIdentifier, const String& indexName)
{
    LOG(IndexedDB, "IDBTransaction::deleteIndex");

    ASSERT(isVersionChange());

    auto operation = createTransactionOperation(*this, &IDBTransaction::didDeleteIndexOnServer, &IDBTransaction::deleteIndexOnServer, objectStoreIdentifier, indexName);
    scheduleOperation(WTFMove(operation));
}
void MemoryBackingStoreTransaction::addNewObjectStore(MemoryObjectStore& objectStore)
{
    LOG(IndexedDB, "MemoryBackingStoreTransaction::addNewObjectStore()");

    ASSERT(isVersionChange());
    m_versionChangeAddedObjectStores.add(&objectStore);

    addExistingObjectStore(objectStore);
}
示例#21
0
std::unique_ptr<IDBIndex> IDBTransaction::createIndex(IDBObjectStore& objectStore, const IDBIndexInfo& info)
{
    LOG(IndexedDB, "IDBTransaction::createIndex");
    ASSERT(isVersionChange());

    auto operation = createTransactionOperation(*this, &IDBTransaction::didCreateIndexOnServer, &IDBTransaction::createIndexOnServer, info);
    scheduleOperation(WTFMove(operation));

    return std::make_unique<IDBIndex>(info, objectStore);
}
示例#22
0
void IDBTransaction::notifyDidAbort(const IDBError& error)
{
    m_database->didAbortTransaction(*this);
    m_idbError = error;
    fireOnAbort();

    if (isVersionChange()) {
        ASSERT(m_openDBRequest);
        m_openDBRequest->fireErrorAfterVersionChangeCompletion();
    }
}
示例#23
0
void IDBServer::deleteIndex(const IDBRequestData& requestData, uint64_t objectStoreIdentifier, const String& indexName)
{
    LOG(IndexedDB, "IDBServer::deleteIndex");

    auto transaction = m_transactions.get(requestData.transactionIdentifier());
    if (!transaction)
        return;

    ASSERT(transaction->isVersionChange());
    transaction->deleteIndex(requestData, objectStoreIdentifier, indexName);
}
示例#24
0
DOMStringList* IDBTransaction::objectStoreNames() const {
  if (isVersionChange())
    return m_database->objectStoreNames();

  DOMStringList* objectStoreNames =
      DOMStringList::create(DOMStringList::IndexedDB);
  for (const String& objectStoreName : m_scope)
    objectStoreNames->append(objectStoreName);
  objectStoreNames->sort();
  return objectStoreNames;
}
示例#25
0
void IDBServer::createIndex(const IDBRequestData& requestData, const IDBIndexInfo& info)
{
    LOG(IndexedDB, "IDBServer::createIndex");

    auto transaction = m_transactions.get(requestData.transactionIdentifier());
    if (!transaction)
        return;

    ASSERT(transaction->isVersionChange());
    transaction->createIndex(requestData, info);
}
void MemoryBackingStoreTransaction::addNewObjectStore(MemoryObjectStore& objectStore)
{
    LOG(IndexedDB, "MemoryBackingStoreTransaction::addNewObjectStore()");

    ASSERT(isVersionChange());

    ASSERT(!m_objectStores.contains(&objectStore));
    m_objectStores.add(&objectStore);
    m_versionChangeAddedObjectStores.add(&objectStore);

    objectStore.writeTransactionStarted(*this);
}
示例#27
0
void IDBTransaction::deleteObjectStore(const String& objectStoreName)
{
    LOG(IndexedDB, "IDBTransaction::deleteObjectStore");

    ASSERT(isVersionChange());

    if (auto objectStore = m_referencedObjectStores.take(objectStoreName))
        objectStore->markAsDeleted();

    auto operation = createTransactionOperation(*this, &IDBTransaction::didDeleteObjectStoreOnServer, &IDBTransaction::deleteObjectStoreOnServer, objectStoreName);
    scheduleOperation(WTFMove(operation));
}
Ref<IDBIndex> IDBTransaction::createIndex(IDBObjectStore& objectStore, const IDBIndexInfo& info)
{
    LOG(IndexedDB, "IDBTransaction::createIndex");
    ASSERT(isVersionChange());

    Ref<IDBIndex> index = IDBIndex::create(info, objectStore);

    auto operation = createTransactionOperation(*this, &IDBTransaction::didCreateIndexOnServer, &IDBTransaction::createIndexOnServer, info);
    scheduleOperation(WTF::move(operation));

    return WTF::move(index);
}
void IDBTransaction::objectStoreDeleted(const String& name)
{
    ASSERT(m_state != Finished);
    ASSERT(isVersionChange());
    IDBObjectStoreMap::iterator it = m_objectStoreMap.find(name);
    if (it != m_objectStoreMap.end()) {
        IDBObjectStore* objectStore = it->value;
        m_objectStoreMap.remove(name);
        objectStore->markDeleted();
        m_objectStoreCleanupMap.set(objectStore, objectStore->metadata());
        m_deletedObjectStores.add(objectStore);
    }
}
示例#30
0
Ref<IDBObjectStore> IDBTransaction::createObjectStore(const IDBObjectStoreInfo& info)
{
    LOG(IndexedDB, "IDBTransaction::createObjectStore");
    ASSERT(isVersionChange());

    Ref<IDBObjectStore> objectStore = IDBObjectStore::create(info, *this);
    m_referencedObjectStores.set(info.name(), &objectStore.get());

    auto operation = createTransactionOperation(*this, &IDBTransaction::didCreateObjectStoreOnServer, &IDBTransaction::createObjectStoreOnServer, info);
    scheduleOperation(WTFMove(operation));

    return objectStore;
}