Modern IDB: Reimplement Web Inspector code that was tied to Legacy IDB.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Apr 2016 18:47:20 +0000 (18:47 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Apr 2016 18:47:20 +0000 (18:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=154686

Reviewed by Alex Christensen.

No new tests (Inspector folks will have to write them if they're possible).

* inspector/InspectorIndexedDBAgent.cpp: Reimplement missing functionality mostly with code that was
  removed in http://trac.webkit.org/changeset/197131/trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@200202 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorIndexedDBAgent.cpp

index f8b8aed..0a1e204 100644 (file)
@@ -1,3 +1,15 @@
+2016-04-28  Brady Eidson  <beidson@apple.com>
+
+        Modern IDB: Reimplement Web Inspector code that was tied to Legacy IDB.
+        https://bugs.webkit.org/show_bug.cgi?id=154686
+
+        Reviewed by Alex Christensen.
+
+        No new tests (Inspector folks will have to write them if they're possible).
+
+        * inspector/InspectorIndexedDBAgent.cpp: Reimplement missing functionality mostly with code that was 
+          removed in http://trac.webkit.org/changeset/197131/trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp
+
 2016-04-28  Daniel Bates  <dabates@apple.com>
 
         Fix the Apple Internal OS X build
index 569327a..af00cd6 100644 (file)
@@ -96,7 +96,7 @@ public:
         : m_context(context) { }
     virtual ~ExecutableWithDatabase() { };
     void start(IDBFactory*, SecurityOrigin*, const String& databaseName);
-    virtual void execute() = 0;
+    virtual void execute(IDBDatabase&) = 0;
     virtual RequestCallback& requestCallback() = 0;
     ScriptExecutionContext* context() { return m_context; };
 private:
@@ -135,9 +135,8 @@ public:
             return;
         }
 
-        // FIXME (webkit.org/b/154686) - Reimplement this.
-        m_executableWithDatabase->requestCallback().sendFailure("Modern IDB is not supported yet");
-        return;
+        m_executableWithDatabase->execute(*databaseResult);
+        databaseResult->close();
     }
 
 private:
@@ -165,6 +164,67 @@ void ExecutableWithDatabase::start(IDBFactory* idbFactory, SecurityOrigin*, cons
     idbOpenDBRequest->addEventListener(eventNames().successEvent, WTFMove(callback), false);
 }
 
+
+static RefPtr<KeyPath> keyPathFromIDBKeyPath(const IDBKeyPath& idbKeyPath)
+{
+    RefPtr<KeyPath> keyPath;
+    switch (idbKeyPath.type()) {
+    case IndexedDB::KeyPathType::Null:
+        keyPath = KeyPath::create()
+            .setType(KeyPath::Type::Null)
+            .release();
+        break;
+    case IndexedDB::KeyPathType::String:
+        keyPath = KeyPath::create()
+            .setType(KeyPath::Type::String)
+            .release();
+        keyPath->setString(idbKeyPath.string());
+
+        break;
+    case IndexedDB::KeyPathType::Array: {
+        auto array = Inspector::Protocol::Array<String>::create();
+        for (auto& string : idbKeyPath.array())
+            array->addItem(string);
+        keyPath = KeyPath::create()
+            .setType(KeyPath::Type::Array)
+            .release();
+        keyPath->setArray(WTFMove(array));
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    return keyPath;
+}
+
+static RefPtr<IDBTransaction> transactionForDatabase(ScriptExecutionContext* scriptExecutionContext, IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IDBTransaction::modeReadOnly())
+{
+    ExceptionCodeWithMessage ec;
+    RefPtr<IDBTransaction> idbTransaction = idbDatabase->transaction(scriptExecutionContext, objectStoreName, mode, ec);
+    if (ec.code)
+        return nullptr;
+    return idbTransaction;
+}
+
+static RefPtr<IDBObjectStore> objectStoreForTransaction(IDBTransaction* idbTransaction, const String& objectStoreName)
+{
+    ExceptionCodeWithMessage ec;
+    RefPtr<IDBObjectStore> idbObjectStore = idbTransaction->objectStore(objectStoreName, ec);
+    if (ec.code)
+        return nullptr;
+    return idbObjectStore;
+}
+
+static RefPtr<IDBIndex> indexForObjectStore(IDBObjectStore* idbObjectStore, const String& indexName)
+{
+    ExceptionCodeWithMessage ec;
+    RefPtr<IDBIndex> idbIndex = idbObjectStore->index(indexName, ec);
+    if (ec.code)
+        return nullptr;
+    return idbIndex;
+}
+
 class DatabaseLoader : public ExecutableWithDatabase {
 public:
     static Ref<DatabaseLoader> create(ScriptExecutionContext* context, Ref<RequestDatabaseCallback>&& requestCallback)
@@ -174,12 +234,48 @@ public:
 
     virtual ~DatabaseLoader() { }
 
-    void execute() override
+    void execute(IDBDatabase& database) override
     {
         if (!requestCallback().isActive())
             return;
-
-        // FIXME (webkit.org/b/154686) - Reimplement this.
+    
+        auto& databaseInfo = database.info();
+        auto objectStores = Inspector::Protocol::Array<Inspector::Protocol::IndexedDB::ObjectStore>::create();
+        auto objectStoreNames = databaseInfo.objectStoreNames();
+        for (auto& name : objectStoreNames) {
+            auto* objectStoreInfo = databaseInfo.infoForExistingObjectStore(name);
+            if (!objectStoreInfo)
+                continue;
+
+            auto indexes = Inspector::Protocol::Array<Inspector::Protocol::IndexedDB::ObjectStoreIndex>::create();
+    
+            for (auto& indexInfo : objectStoreInfo->indexMap().values()) {
+                Ref<ObjectStoreIndex> objectStoreIndex = ObjectStoreIndex::create()
+                    .setName(indexInfo.name())
+                    .setKeyPath(keyPathFromIDBKeyPath(indexInfo.keyPath()))
+                    .setUnique(indexInfo.unique())
+                    .setMultiEntry(indexInfo.multiEntry())
+                    .release();
+                indexes->addItem(WTFMove(objectStoreIndex));
+            }
+    
+            Ref<ObjectStore> objectStore = ObjectStore::create()
+                .setName(objectStoreInfo->name())
+                .setKeyPath(keyPathFromIDBKeyPath(objectStoreInfo->keyPath()))
+                .setAutoIncrement(objectStoreInfo->autoIncrement())
+                .setIndexes(WTFMove(indexes))
+                .release();
+        
+            objectStores->addItem(WTFMove(objectStore));
+        }
+    
+        Ref<DatabaseWithObjectStores> result = DatabaseWithObjectStores::create()
+            .setName(databaseInfo.name())
+            .setVersion(databaseInfo.version())
+            .setObjectStores(WTFMove(objectStores))
+            .release();
+        
+        m_requestCallback->sendSuccess(WTFMove(result));
     }
 
     RequestCallback& requestCallback() override { return m_requestCallback.get(); }
@@ -372,12 +468,42 @@ public:
 
     virtual ~DataLoader() { }
 
-    void execute() override
+    void execute(IDBDatabase& database) override
     {
         if (!requestCallback().isActive())
             return;
+        RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), &database, m_objectStoreName);
+        if (!idbTransaction) {
+            m_requestCallback->sendFailure("Could not get transaction");
+            return;
+        }
+        RefPtr<IDBObjectStore> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
+        if (!idbObjectStore) {
+            m_requestCallback->sendFailure("Could not get object store");
+            return;
+        }
+
+        Ref<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_injectedScript, m_requestCallback.copyRef(), 0, m_pageSize);
+
+        ExceptionCodeWithMessage ec;
+        RefPtr<IDBRequest> idbRequest;
+        if (!m_indexName.isEmpty()) {
+            RefPtr<IDBIndex> idbIndex = indexForObjectStore(idbObjectStore.get(), m_indexName);
+            if (!idbIndex) {
+                m_requestCallback->sendFailure("Could not get index");
+                return;
+            }
+
+            idbRequest = idbIndex->openCursor(*context(), m_idbKeyRange.get(), IDBCursor::directionNext(), ec);
+        } else
+            idbRequest = idbObjectStore->openCursor(*context(), m_idbKeyRange.get(), IDBCursor::directionNext(), ec);
+
+        if (!idbRequest) {
+            m_requestCallback->sendFailure("Could not open cursor to populate database data");
+            return;
+        }
 
-        // FIXME (webkit.org/b/154686) - Reimplement this.
+        idbRequest->addEventListener(eventNames().successEvent, WTFMove(openCursorCallback), false);
     }
 
     RequestCallback& requestCallback() override { return m_requestCallback.get(); }
@@ -560,7 +686,6 @@ private:
     Ref<ClearObjectStoreCallback> m_requestCallback;
 };
 
-
 class ClearObjectStore : public ExecutableWithDatabase {
 public:
     static Ref<ClearObjectStore> create(ScriptExecutionContext* context, const String& objectStoreName, Ref<ClearObjectStoreCallback>&& requestCallback)
@@ -575,12 +700,30 @@ public:
     {
     }
 
-    void execute() override
+    void execute(IDBDatabase& database) override
     {
         if (!requestCallback().isActive())
             return;
 
-        // FIXME (webkit.org/b/154686) - Reimplement this.
+        RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), &database, m_objectStoreName);
+        if (!idbTransaction) {
+            m_requestCallback->sendFailure("Could not get transaction");
+            return;
+        }
+        RefPtr<IDBObjectStore> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
+        if (!idbObjectStore) {
+            m_requestCallback->sendFailure("Could not get object store");
+            return;
+        }
+
+        ExceptionCodeWithMessage ec;
+        RefPtr<IDBRequest> idbRequest = idbObjectStore->clear(*context(), ec);
+        ASSERT(!ec.code);
+        if (ec.code) {
+            m_requestCallback->sendFailure(String::format("Could not clear object store '%s': %d", m_objectStoreName.utf8().data(), ec.code));
+            return;
+        }
+        idbTransaction->addEventListener(eventNames().completeEvent, ClearObjectStoreListener::create(m_requestCallback.copyRef()), false);
     }
 
     RequestCallback& requestCallback() override { return m_requestCallback.get(); }