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;
}