Title: [146218] trunk
Revision
146218
Author
alecfl...@chromium.org
Date
2013-03-19 10:29:15 -0700 (Tue, 19 Mar 2013)

Log Message

Inspector: IndexedDB clear button and menu item
https://bugs.webkit.org/show_bug.cgi?id=112066

Reviewed by Vsevolod Vlasov.

Source/WebCore:

Adds a button that can clear the contents of an objectStore from
the IDBDataView, and a context menu from the ResourcesPanel that
can do the same.

This also disables the Refresh button from the IDBDataView, so there
is at least some visual feedback that the refresh button is working.

Tests: http/tests/inspector/indexeddb/database-data.html

* inspector/Inspector.json: New API clearObjectStore.
* inspector/InspectorIndexedDBAgent.cpp: Implementation of clearObjectStore
(WebCore):
(ClearObjectStoreListener): Calls the original closure after the objectStore is cleared.
(ClearObjectStore): Initiates the clear operation after the DB opens.
* inspector/front-end/IndexedDBModel.js: Exposes clearObjectStore to the Model API.
(WebInspector.IDBDataView): Add clear button and enable/disable clear and refresh buttons appropriately.
* inspector/front-end/ResourcesPanel.js: Add a menu item and refresh the displayed data after the clear.
* inspector/front-end/inspector.css: Add a style to show the right button for clear.

LayoutTests:

Add extra methods to test clearing the database after populating it.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (146217 => 146218)


--- trunk/LayoutTests/ChangeLog	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/LayoutTests/ChangeLog	2013-03-19 17:29:15 UTC (rev 146218)
@@ -1,3 +1,12 @@
+2013-03-19  Alec Flett  <alecfl...@chromium.org>
+
+        Inspector: IndexedDB clear button and menu item
+        https://bugs.webkit.org/show_bug.cgi?id=112066
+
+        Reviewed by Vsevolod Vlasov.
+
+        Add extra methods to test clearing the database after populating it.
+
 2013-03-19  Simon Fraser  <simon.fra...@apple.com>
 
         [Mac] Flaky crash in SliderThumbElement::defaultEventHandler on fast/forms/range/slider-delete-while-dragging-thumb.html

Modified: trunk/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt (146217 => 146218)


--- trunk/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt	2013-03-19 17:29:15 UTC (rev 146218)
@@ -61,4 +61,7 @@
     Key = value_01, primaryKey = key_01, value = {"key":"key_01","value":"value_01"}
     Key = value_02, primaryKey = key_02, value = {"key":"key_02","value":"value_02"}
     hasMore = true
+Cleared data from objectStore
+Dumping values, fromIndex = false, skipCount = 0, pageSize = 10, idbKeyRange = null
+    hasMore = false
 

Modified: trunk/LayoutTests/http/tests/inspector/indexeddb/database-data.html (146217 => 146218)


--- trunk/LayoutTests/http/tests/inspector/indexeddb/database-data.html	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/LayoutTests/http/tests/inspector/indexeddb/database-data.html	2013-03-19 17:29:15 UTC (rev 146218)
@@ -179,12 +179,30 @@
 
         function step2()
         {
-            clearDatabase();
+            runClearTests();
         }
     }
 
-    function clearDatabase()
+    function runClearTests()
     {
+        indexedDBModel.clearObjectStore(databaseId, objectStoreName, step1);
+        InspectorTest.addResult("Cleared data from objectStore");
+
+        function step1() {
+            indexedDBModel.addEventListener(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, step2);
+            indexedDBModel.refreshDatabase(databaseId);
+        }
+        function step2() {
+            indexedDBModel.removeEventListener(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, step2);
+            loadValuesAndDump(false, null, 0, 10, step3);
+        }
+
+        function step3() {
+            deleteDatabase();
+        }
+    }
+
+    function deleteDatabase() {
         InspectorTest.deleteObjectStoreIndex(mainFrameId, databaseName, objectStoreName, indexName, step2);
 
         function step2()

Modified: trunk/Source/WebCore/ChangeLog (146217 => 146218)


--- trunk/Source/WebCore/ChangeLog	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/ChangeLog	2013-03-19 17:29:15 UTC (rev 146218)
@@ -1,3 +1,29 @@
+2013-03-19  Alec Flett  <alecfl...@chromium.org>
+
+        Inspector: IndexedDB clear button and menu item
+        https://bugs.webkit.org/show_bug.cgi?id=112066
+
+        Reviewed by Vsevolod Vlasov.
+
+        Adds a button that can clear the contents of an objectStore from
+        the IDBDataView, and a context menu from the ResourcesPanel that
+        can do the same.
+
+        This also disables the Refresh button from the IDBDataView, so there
+        is at least some visual feedback that the refresh button is working.
+
+        Tests: http/tests/inspector/indexeddb/database-data.html
+
+        * inspector/Inspector.json: New API clearObjectStore.
+        * inspector/InspectorIndexedDBAgent.cpp: Implementation of clearObjectStore
+        (WebCore):
+        (ClearObjectStoreListener): Calls the original closure after the objectStore is cleared.
+        (ClearObjectStore): Initiates the clear operation after the DB opens.
+        * inspector/front-end/IndexedDBModel.js: Exposes clearObjectStore to the Model API.
+        (WebInspector.IDBDataView): Add clear button and enable/disable clear and refresh buttons appropriately.
+        * inspector/front-end/ResourcesPanel.js: Add a menu item and refresh the displayed data after the clear.
+        * inspector/front-end/inspector.css: Add a style to show the right button for clear.
+
 2013-03-19  Nate Chapin  <jap...@chromium.org>
 
         Merge MainResourceLoader::responseReceived into DocumentLoader

Modified: trunk/Source/WebCore/English.lproj/localizedStrings.js (146217 => 146218)


--- trunk/Source/WebCore/English.lproj/localizedStrings.js	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/English.lproj/localizedStrings.js	2013-03-19 17:29:15 UTC (rev 146218)
@@ -111,6 +111,7 @@
 localizedStrings["Clear console"] = "Clear console";
 localizedStrings["Clear audit results."] = "Clear audit results.";
 localizedStrings["Clear console log."] = "Clear console log.";
+localizedStrings["Clear object store"] = "Clear object store";
 localizedStrings["Clear"] = "Clear";
 localizedStrings["Click to open a colorpicker. Shift-click to change color format"] = "Click to open a colorpicker. Shift-click to change color format";
 localizedStrings["Closure"] = "Closure";

Modified: trunk/Source/WebCore/inspector/Inspector.json (146217 => 146218)


--- trunk/Source/WebCore/inspector/Inspector.json	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/Inspector.json	2013-03-19 17:29:15 UTC (rev 146218)
@@ -1412,6 +1412,18 @@
                     { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." }
                 ],
                 "description": "Requests data from object store or index."
+            },
+            {
+                "name": "clearObjectStore",
+                "async": true,
+                "parameters": [
+                    { "name": "securityOrigin", "type": "string", "description": "Security origin." },
+                    { "name": "databaseName", "type": "string", "description": "Database name." },
+                    { "name": "objectStoreName", "type": "string", "description": "Object store name." }
+                ],
+                "returns": [
+                ],
+                "description": "Clears all entries from an object store."
             }
         ]
     },

Modified: trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp (146217 => 146218)


--- trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.cpp	2013-03-19 17:29:15 UTC (rev 146218)
@@ -81,6 +81,7 @@
 typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDatabaseCallback RequestDatabaseCallback;
 typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::RequestDataCallback RequestDataCallback;
 typedef WebCore::InspectorBackendDispatcher::CallbackBase RequestCallback;
+typedef WebCore::InspectorBackendDispatcher::IndexedDBCommandHandler::ClearObjectStoreCallback ClearObjectStoreCallback;
 
 namespace WebCore {
 
@@ -213,10 +214,10 @@
     idbOpenDBRequest->addEventListener(eventNames().successEvent, callback, false);
 }
 
-static PassRefPtr<IDBTransaction> transactionForDatabase(ScriptExecutionContext* scriptExecutionContext, IDBDatabase* idbDatabase, const String& objectStoreName)
+static PassRefPtr<IDBTransaction> transactionForDatabase(ScriptExecutionContext* scriptExecutionContext, IDBDatabase* idbDatabase, const String& objectStoreName, const String& mode = IDBTransaction::modeReadOnly())
 {
     ExceptionCode ec = 0;
-    RefPtr<IDBTransaction> idbTransaction = idbDatabase->transaction(scriptExecutionContext, objectStoreName, IDBTransaction::modeReadOnly(), ec);
+    RefPtr<IDBTransaction> idbTransaction = idbDatabase->transaction(scriptExecutionContext, objectStoreName, mode, ec);
     if (ec)
         return 0;
     return idbTransaction;
@@ -689,6 +690,109 @@
     dataLoader->start(idbFactory, document->securityOrigin(), databaseName);
 }
 
+class ClearObjectStoreListener : public EventListener {
+    WTF_MAKE_NONCOPYABLE(ClearObjectStoreListener);
+public:
+    static PassRefPtr<ClearObjectStoreListener> create(PassRefPtr<ClearObjectStoreCallback> requestCallback)
+    {
+        return adoptRef(new ClearObjectStoreListener(requestCallback));
+    }
+
+    virtual ~ClearObjectStoreListener() { }
+
+    virtual bool operator==(const EventListener& other) OVERRIDE
+    {
+        return this == &other;
+    }
+
+    virtual void handleEvent(ScriptExecutionContext*, Event* event) OVERRIDE
+    {
+        if (!m_requestCallback->isActive())
+            return;
+        if (event->type() != eventNames().completeEvent) {
+            m_requestCallback->sendFailure("Unexpected event type.");
+            return;
+        }
+
+        m_requestCallback->sendSuccess();
+    }
+private:
+    ClearObjectStoreListener(PassRefPtr<ClearObjectStoreCallback> requestCallback)
+        : EventListener(EventListener::CPPEventListenerType)
+        , m_requestCallback(requestCallback)
+    {
+    }
+
+    RefPtr<ClearObjectStoreCallback> m_requestCallback;
+};
+
+
+class ClearObjectStore : public ExecutableWithDatabase {
+public:
+    static PassRefPtr<ClearObjectStore> create(ScriptExecutionContext* context, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
+    {
+        return adoptRef(new ClearObjectStore(context, objectStoreName, requestCallback));
+    }
+
+    ClearObjectStore(ScriptExecutionContext* context, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
+        : ExecutableWithDatabase(context)
+        , m_objectStoreName(objectStoreName)
+        , m_requestCallback(requestCallback)
+    {
+    }
+
+    virtual void execute(PassRefPtr<IDBDatabase> prpDatabase)
+    {
+        RefPtr<IDBDatabase> idbDatabase = prpDatabase;
+        if (!requestCallback()->isActive())
+            return;
+        RefPtr<IDBTransaction> idbTransaction = transactionForDatabase(context(), idbDatabase.get(), m_objectStoreName, IDBTransaction::modeReadWrite());
+        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;
+        }
+
+        ExceptionCode ec = 0;
+        RefPtr<IDBRequest> idbRequest = idbObjectStore->clear(context(), ec);
+        ASSERT(!ec);
+        if (ec) {
+            m_requestCallback->sendFailure(String::format("Could not clear object store '%s': %d", m_objectStoreName.utf8().data(), ec));
+            return;
+        }
+        idbTransaction->addEventListener(eventNames().completeEvent, ClearObjectStoreListener::create(m_requestCallback), false);
+    }
+
+    virtual RequestCallback* requestCallback() { return m_requestCallback.get(); }
+private:
+    const String m_objectStoreName;
+    RefPtr<ClearObjectStoreCallback> m_requestCallback;
+};
+
+void InspectorIndexedDBAgent::clearObjectStore(ErrorString* errorString, const String& securityOrigin, const String& databaseName, const String& objectStoreName, PassRefPtr<ClearObjectStoreCallback> requestCallback)
+{
+    Frame* frame = m_pageAgent->findFrameWithSecurityOrigin(securityOrigin);
+    Document* document = assertDocument(errorString, frame);
+    if (!document)
+        return;
+    IDBFactory* idbFactory = assertIDBFactory(errorString, document);
+    if (!idbFactory)
+        return;
+
+#if USE(V8)
+        v8::HandleScope handleScope;
+        v8::Handle<v8::Context> context = document->frame()->script()->mainWorldContext();
+        ASSERT(!context.IsEmpty());
+        v8::Context::Scope contextScope(context);
+#endif
+
+    RefPtr<ClearObjectStore> clearObjectStore = ClearObjectStore::create(document, objectStoreName, requestCallback);
+    clearObjectStore->start(idbFactory, document->securityOrigin(), databaseName);
+}
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR) && ENABLE(INDEXED_DATABASE)

Modified: trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.h (146217 => 146218)


--- trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.h	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/InspectorIndexedDBAgent.h	2013-03-19 17:29:15 UTC (rev 146218)
@@ -61,6 +61,7 @@
     virtual void requestDatabaseNames(ErrorString*, const String& securityOrigin, PassRefPtr<RequestDatabaseNamesCallback>);
     virtual void requestDatabase(ErrorString*, const String& securityOrigin, const String& databaseName, PassRefPtr<RequestDatabaseCallback>);
     virtual void requestData(ErrorString*, const String& securityOrigin, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange, PassRefPtr<RequestDataCallback>);
+    virtual void clearObjectStore(ErrorString*, const String& in_securityOrigin, const String& in_databaseName, const String& in_objectStoreName, PassRefPtr<ClearObjectStoreCallback>);
 
 private:
     InspectorIndexedDBAgent(InstrumentingAgents*, InspectorCompositeState*, InjectedScriptManager*, InspectorPageAgent*);

Modified: trunk/Source/WebCore/inspector/front-end/IndexedDBModel.js (146217 => 146218)


--- trunk/Source/WebCore/inspector/front-end/IndexedDBModel.js	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/front-end/IndexedDBModel.js	2013-03-19 17:29:15 UTC (rev 146218)
@@ -163,6 +163,15 @@
     },
 
     /**
+     * @param {WebInspector.IndexedDBModel.DatabaseId} databaseId
+     * @param {WebInspector.IndexedDBModel.ObjectStore} objectStore
+     */
+    clearObjectStore: function(databaseId, objectStoreName, callback)
+    {
+        IndexedDBAgent.clearObjectStore(databaseId.securityOrigin, databaseId.name, objectStoreName, callback);
+    },
+
+    /**
      * @param {WebInspector.Event} event
      */
     _securityOriginAdded: function(event)
@@ -289,7 +298,7 @@
             if (!this._databaseNamesBySecurityOrigin[databaseId.securityOrigin])
                 return;
             var databaseModel = new WebInspector.IndexedDBModel.Database(databaseId, databaseWithObjectStores.version, databaseWithObjectStores.intVersion);
-            this._databases.put(databaseId, databaseModel); 
+            this._databases.put(databaseId, databaseModel);
             for (var i = 0; i < databaseWithObjectStores.objectStores.length; ++i) {
                 var objectStore = databaseWithObjectStores.objectStores[i];
                 var objectStoreIDBKeyPath = WebInspector.IndexedDBModel.idbKeyPathFromKeyPath(objectStore.keyPath);
@@ -359,7 +368,7 @@
                 console.error("IndexedDBAgent error: " + error);
                 return;
             }
-            
+
             if (!this._databaseNamesBySecurityOrigin[databaseId.securityOrigin])
                 return;
             var entries = [];

Modified: trunk/Source/WebCore/inspector/front-end/IndexedDBViews.js (146217 => 146218)


--- trunk/Source/WebCore/inspector/front-end/IndexedDBViews.js	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/front-end/IndexedDBViews.js	2013-03-19 17:29:15 UTC (rev 146218)
@@ -127,6 +127,9 @@
     this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
     this._refreshButton.addEventListener("click", this._refreshButtonClicked, this);
 
+    this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear object store"), "clear-storage-status-bar-item");
+    this._clearButton.addEventListener("click", this._clearButtonClicked, this);
+
     this._pageSize = 50;
     this._skipCount = 0;
 
@@ -164,7 +167,7 @@
         keyColumnHeaderFragment.appendChild(document.createTextNode(prefix));
         if (keyPath === null)
             return keyColumnHeaderFragment;
-        
+
         keyColumnHeaderFragment.appendChild(document.createTextNode(" (" + WebInspector.UIString("Key path: ")));
         if (keyPath instanceof Array) {
             keyColumnHeaderFragment.appendChild(document.createTextNode("["));
@@ -298,6 +301,8 @@
         var key = this._parseKey(this._keyInputElement.value);
         var pageSize = this._pageSize;
         var skipCount = this._skipCount;
+        this._refreshButton.setEnabled(false);
+        this._clearButton.setEnabled(!this._isIndex);
 
         if (!force && this._lastKey === key && this._lastPageSize === pageSize && this._lastSkipCount === skipCount)
             return;
@@ -316,6 +321,7 @@
          */
         function callback(entries, hasMore)
         {
+            this._refreshButton.setEnabled(true);
             this.clear();
             this._entries = entries;
             for (var i = 0; i < entries.length; ++i) {
@@ -346,9 +352,19 @@
         this._updateData(true);
     },
 
+    _clearButtonClicked: function(event)
+    {
+        function cleared(result) {
+            this._clearButton.setEnabled(true);
+            this._updateData(true);
+        }
+        this._clearButton.setEnabled(false);
+        this._model.clearObjectStore(this._databaseId, this._objectStore.name, cleared.bind(this));
+    },
+
     get statusBarItems()
     {
-        return [this._refreshButton.element];
+        return [this._refreshButton.element, this._clearButton.element];
     },
 
     clear: function()

Modified: trunk/Source/WebCore/inspector/front-end/ResourcesPanel.js (146217 => 146218)


--- trunk/Source/WebCore/inspector/front-end/ResourcesPanel.js	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/front-end/ResourcesPanel.js	2013-03-19 17:29:15 UTC (rev 146218)
@@ -1729,6 +1729,27 @@
         return "indexedDB://" + this._databaseId.securityOrigin + "/" + this._databaseId.name + "/" + this._objectStore.name;
     },
 
+    onattach: function()
+    {
+        WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
+        this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
+    },
+
+    _handleContextMenuEvent: function(event)
+    {
+        var contextMenu = new WebInspector.ContextMenu(event);
+        contextMenu.appendItem(WebInspector.UIString("Clear"), this._clearObjectStore.bind(this));
+        contextMenu.show();
+    },
+
+    _clearObjectStore: function()
+    {
+        function callback(result) {
+            this.update(this._objectStore);
+        }
+        this._model.clearObjectStore(this._databaseId, this._objectStore.name, callback.bind(this));
+    },
+
    /**
      * @param {WebInspector.IndexedDBModel.ObjectStore} objectStore
      */

Modified: trunk/Source/WebCore/inspector/front-end/inspector.css (146217 => 146218)


--- trunk/Source/WebCore/inspector/front-end/inspector.css	2013-03-19 17:26:57 UTC (rev 146217)
+++ trunk/Source/WebCore/inspector/front-end/inspector.css	2013-03-19 17:29:15 UTC (rev 146218)
@@ -2242,6 +2242,10 @@
     -webkit-mask-position: -128px 0;
 }
 
+.clear-storage-status-bar-item .glyph {
+    -webkit-mask-position: -64px 0;
+}
+
 .refresh-storage-status-bar-item .glyph {
     -webkit-mask-position: 0 0;
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to