+2012-02-13 Vsevolod Vlasov <vsevik@chromium.org>
+
+ Web Inspector: [InspectorIndexedDB] Pass data entries from object stores and indexes to front-end.
+ https://bugs.webkit.org/show_bug.cgi?id=78503
+
+ Reviewed by Yury Semikhatsky.
+
+ * http/tests/inspector/indexeddb/database-data-expected.txt: Added.
+ * http/tests/inspector/indexeddb/database-data.html: Added.
+ * http/tests/inspector/indexeddb/database-names-expected.txt:
+ * http/tests/inspector/indexeddb/database-structure-expected.txt:
+ * http/tests/inspector/indexeddb/indexeddb-test.js:
+ (initialize_IndexedDBTest.InspectorTest.evaluateWithCallback):
+ (initialize_IndexedDBTest.InspectorTest.addIDBValue):
+ (initialize_IndexedDBTest):
+ (doWithReadWriteTransaction.step2.innerCommitCallback):
+ (doWithReadWriteTransaction.step2):
+ (doWithReadWriteTransaction):
+ (addIDBValue.doWithReadWriteTransaction.withTransactionCallback):
+ (addIDBValue):
+
2012-02-15 Kent Tamura <tkent@chromium.org>
Unreviewed, change the encoding of a test HTML.
--- /dev/null
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback1
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback2
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback3
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback4
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback5
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback6
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback7
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback8
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback9
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback10
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback11
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback12
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback13
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback14
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback15
+Tests that data is correctly loaded by IndexedDBModel from IndexedDB object store and index.
+
+Dumping values, fromIndex = false, skipCount = 0, pageSize = 3, idbKeyRange = null
+ Key = key_01, primaryKey = key_01, value = {"key":"key_01","value":"value_01"}
+ Key = key_02, primaryKey = key_02, value = {"key":"key_02","value":"value_02"}
+ Key = key_03, primaryKey = key_03, value = {"key":"key_03","value":"value_03"}
+ hasMore = true
+Dumping values, fromIndex = false, skipCount = 3, pageSize = 3, idbKeyRange = null
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ hasMore = true
+Dumping values, fromIndex = false, skipCount = 6, pageSize = 3, idbKeyRange = null
+ Key = key_07, primaryKey = key_07, value = {"key":"key_07","value":"value_07"}
+ Key = key_08, primaryKey = key_08, value = {"key":"key_08","value":"value_08"}
+ Key = key_09, primaryKey = key_09, value = {"key":"key_09","value":"value_09"}
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 7, pageSize = 3, idbKeyRange = null
+ Key = key_08, primaryKey = key_08, value = {"key":"key_08","value":"value_08"}
+ Key = key_09, primaryKey = key_09, value = {"key":"key_09","value":"value_09"}
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 9, pageSize = 3, idbKeyRange = null
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 10, pageSize = 3, idbKeyRange = null
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 0, pageSize = 4, idbKeyRange = {lower:"key_02",lowerOpen:true,upper:"key_07",upperOpen:false}
+ Key = key_03, primaryKey = key_03, value = {"key":"key_03","value":"value_03"}
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ hasMore = true
+Dumping values, fromIndex = false, skipCount = 0, pageSize = 5, idbKeyRange = {lower:"key_02",lowerOpen:true,upper:"key_07",upperOpen:false}
+ Key = key_03, primaryKey = key_03, value = {"key":"key_03","value":"value_03"}
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ Key = key_07, primaryKey = key_07, value = {"key":"key_07","value":"value_07"}
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 0, pageSize = 6, idbKeyRange = {lower:"key_02",lowerOpen:true,upper:"key_07",upperOpen:false}
+ Key = key_03, primaryKey = key_03, value = {"key":"key_03","value":"value_03"}
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ Key = key_07, primaryKey = key_07, value = {"key":"key_07","value":"value_07"}
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 1, pageSize = 4, idbKeyRange = {lower:"key_02",lowerOpen:true,upper:"key_07",upperOpen:false}
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ Key = key_07, primaryKey = key_07, value = {"key":"key_07","value":"value_07"}
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 1, pageSize = 5, idbKeyRange = {lower:"key_02",lowerOpen:true,upper:"key_07",upperOpen:false}
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ Key = key_07, primaryKey = key_07, value = {"key":"key_07","value":"value_07"}
+ hasMore = false
+Dumping values, fromIndex = false, skipCount = 1, pageSize = 6, idbKeyRange = {lower:"key_02",lowerOpen:true,upper:"key_07",upperOpen:false}
+ Key = key_04, primaryKey = key_04, value = {"key":"key_04","value":"value_04"}
+ Key = key_05, primaryKey = key_05, value = {"key":"key_05","value":"value_05"}
+ Key = key_06, primaryKey = key_06, value = {"key":"key_06","value":"value_06"}
+ Key = key_07, primaryKey = key_07, value = {"key":"key_07","value":"value_07"}
+ hasMore = false
+Dumping values, fromIndex = true, skipCount = 0, pageSize = 3, idbKeyRange = null
+ 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"}
+ Key = value_03, primaryKey = key_03, value = {"key":"key_03","value":"value_03"}
+ hasMore = true
+
--- /dev/null
+<html>
+<head>
+<script src="../inspector-test.js"></script>
+<script src="indexeddb-test.js"></script>
+<script>
+function test()
+{
+ var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
+ var indexedDBModel = new WebInspector.IndexedDBModel();
+ var mainFrameId = WebInspector.resourceTreeModel.mainFrame.id;
+ var databaseName = "testDatabase";
+ var objectStoreName = "testObjectStore";
+ var indexName = "testIndexName";
+
+ function addIDBValues(count, callback)
+ {
+ var i = 0;
+ addValues();
+
+ function addValues()
+ {
+ if (i == count) {
+ callback();
+ return;
+ }
+ ++i;
+ var id = i < 10 ? "0" + i : i;
+ var key = "key_" + id;
+ var value = "value_" + id;
+ InspectorTest.addIDBValue(mainFrameId, databaseName, objectStoreName, { key: key, value: value }, "", addValues);
+ }
+ }
+
+ function loadValuesAndDump(fromIndex, idbKeyRange, skipCount, pageSize, callback)
+ {
+ var idbKeyRangeString = idbKeyRange ? "{lower:\"" + idbKeyRange.lower + "\",lowerOpen:" + idbKeyRange.lowerOpen + ",upper:\"" + idbKeyRange.upper + "\",upperOpen:" + idbKeyRange.upperOpen + "}" : "null";
+ InspectorTest.addResult("Dumping values, fromIndex = " + fromIndex + ", skipCount = " + skipCount + ", pageSize = " + pageSize + ", idbKeyRange = " + idbKeyRangeString);
+ if (fromIndex)
+ indexedDBModel.loadIndexData(mainFrameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, innerCallback);
+ else
+ indexedDBModel.loadObjectStoreData(mainFrameId, databaseName, objectStoreName, idbKeyRange, skipCount, pageSize, innerCallback);
+
+ function innerCallback(entries, hasMore)
+ {
+ var index = 0;
+ var entry;
+ dumpEntries();
+
+ function dumpEntries()
+ {
+ if (index === entries.length) {
+ InspectorTest.addResult(" hasMore = " + hasMore);
+ callback();
+ return;
+ }
+ entry = entries[index];
+ entry.value.callFunctionJSON(dumpMe, dumped.bind(this));
+ ++index;
+ }
+
+ function dumpMe()
+ {
+ return "{\"key\":\"" + this.key + "\",\"value\":\"" + this.value + "\"}";
+ }
+
+ function dumped(value)
+ {
+ InspectorTest.addResult(" Key = " + entry.key + ", primaryKey = " + entry.primaryKey + ", value = " + value);
+ dumpEntries();
+ }
+ }
+ }
+
+ InspectorTest.addSniffer(WebInspector.IndexedDBDispatcher.prototype, "databaseNamesLoaded", fillDatabase, false);
+
+ function fillDatabase()
+ {
+ InspectorTest.createDatabase(mainFrameId, databaseName, step2);
+
+ function step2()
+ {
+ InspectorTest.createObjectStore(mainFrameId, databaseName, objectStoreName, "key", true, step3);
+ }
+
+ function step3()
+ {
+ InspectorTest.createObjectStoreIndex(mainFrameId, databaseName, objectStoreName, indexName, "value", false, true, step4);
+ }
+
+ function step4()
+ {
+ addIDBValues(9, refreshDatabase);
+ }
+ }
+
+ function refreshDatabase()
+ {
+ InspectorTest.addSniffer(WebInspector.IndexedDBDispatcher.prototype, "databaseLoaded", runObjectStoreTests, false);
+ indexedDBModel.refreshDatabase(mainFrameId, databaseName);
+ }
+
+ function runObjectStoreTests()
+ {
+ loadValuesAndDump(false, null, 0, 3, step2)
+
+ function step2()
+ {
+ loadValuesAndDump(false, null, 3, 3, step3)
+ }
+
+ function step3()
+ {
+ loadValuesAndDump(false, null, 6, 3, step4);
+ }
+
+ function step4()
+ {
+ loadValuesAndDump(false, null, 7, 3, step5);
+ }
+
+ function step5()
+ {
+ loadValuesAndDump(false, null, 9, 3, step6);
+ }
+
+ function step6()
+ {
+ loadValuesAndDump(false, null, 10, 3, step7);
+ }
+
+ function step7()
+ {
+ loadValuesAndDump(false, IDBKeyRange.bound("key_02", "key_07", true, false), 0, 4, step8);
+ }
+
+ function step8()
+ {
+ loadValuesAndDump(false, IDBKeyRange.bound("key_02", "key_07", true, false), 0, 5, step9);
+ }
+
+ function step9()
+ {
+ loadValuesAndDump(false, IDBKeyRange.bound("key_02", "key_07", true, false), 0, 6, step10);
+ }
+
+ function step10()
+ {
+ loadValuesAndDump(false, IDBKeyRange.bound("key_02", "key_07", true, false), 1, 4, step11);
+ }
+
+ function step11()
+ {
+ loadValuesAndDump(false, IDBKeyRange.bound("key_02", "key_07", true, false), 1, 5, step12);
+ }
+
+ function step12()
+ {
+ loadValuesAndDump(false, IDBKeyRange.bound("key_02", "key_07", true, false), 1, 6, step13);
+ }
+
+ function step13()
+ {
+ runIndexTests();
+ }
+ }
+
+ function runIndexTests()
+ {
+ loadValuesAndDump(true, null, 0, 3, step2)
+
+ function step2()
+ {
+ clearDatabase();
+ }
+ }
+
+ function clearDatabase()
+ {
+ InspectorTest.deleteObjectStoreIndex(mainFrameId, databaseName, objectStoreName, indexName, step2);
+
+ function step2()
+ {
+ InspectorTest.deleteObjectStore(mainFrameId, databaseName, objectStoreName, step3);
+ }
+
+ function step3()
+ {
+ InspectorTest.deleteDatabase(mainFrameId, databaseName, step4);
+ }
+
+ function step4()
+ {
+ InspectorTest.completeTest();
+ }
+ }
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests that data is correctly loaded by IndexedDBModel from IndexedDB object store and index.</p>
+</body>
+</html>
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback1
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback2
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback3
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback4
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback1
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback2
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback3
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback4
Tests that database names are correctly loaded and saved in IndexedDBModel.
Dumping database names:
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback1
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback2
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback3
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback4
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback5
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback6
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback7
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback8
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback9
-CONSOLE MESSAGE: line 77: InspectorTest.IndexedDB_callback10
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback1
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback2
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback3
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback4
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback5
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback6
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback7
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback8
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback9
+CONSOLE MESSAGE: line 79: InspectorTest.IndexedDB_callback10
Tests that database names are correctly loaded and saved in IndexedDBModel.
Dumping database:
var callbackId = ++lastCallbackId;
callbacks[callbackId] = callback;
var parametersString = "\"" + callbackIdPrefix + callbackId + "\"";
- for (var i = 0; i < parameters.length; ++i) {
- if (typeof(parameters[i]) === "string")
- parametersString += ", \"" + parameters[i] + "\"";
- else if ((typeof(parameters[i]) === "number") || (typeof(parameters[i]) === "boolean"))
- parametersString += ", " + parameters[i];
- }
+ for (var i = 0; i < parameters.length; ++i)
+ parametersString += ", " + JSON.stringify(parameters[i]);
var requestString = methodName + "(" + parametersString + ")";
InspectorTest.evaluateInPage(requestString);
InspectorTest.evaluateWithCallback(frameId, "deleteObjectStoreIndex", [databaseName, objectStoreName, objectStoreIndexName], callback)
};
+InspectorTest.addIDBValue = function(frameId, databaseName, objectStoreName, value, key, callback)
+{
+ InspectorTest.evaluateWithCallback(frameId, "addIDBValue", [databaseName, objectStoreName, value, key], callback)
+};
+
};
var indexedDB = window.indexeddb || window.webkitIndexedDB;
+var IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
function dispatchCallback(callbackId)
{
}
}
+function doWithReadWriteTransaction(databaseName, objectStoreName, callback, commitCallback)
+{
+ doWithDatabase(databaseName, step2);
+
+ function step2(db)
+ {
+ var transaction = db.transaction([objectStoreName], IDBTransaction.READ_WRITE);
+ var objectStore = transaction.objectStore(objectStoreName);
+ callback(objectStore, innerCommitCallback);
+
+ function innerCommitCallback()
+ {
+ db.close();
+ commitCallback();
+ }
+ }
+}
+
function createDatabase(callbackId, databaseName)
{
var request = indexedDB.open(databaseName, 0);
}
}
+function addIDBValue(callbackId, databaseName, objectStoreName, value, key)
+{
+ doWithReadWriteTransaction(databaseName, objectStoreName, withTransactionCallback, dispatchCallback.bind(this, callbackId))
+
+ function withTransactionCallback(objectStore, commitCallback)
+ {
+ var request;
+ if (key)
+ request = objectStore.add(value, key);
+ else
+ request = objectStore.add(value);
+ request.onerror = onIndexedDBError;
+ request.onsuccess = commitCallback;
+ }
+}
+
+2012-02-13 Vsevolod Vlasov <vsevik@chromium.org>
+
+ Web Inspector: [InspectorIndexedDB] Pass data entries from object stores and indexes to front-end.
+ https://bugs.webkit.org/show_bug.cgi?id=78503
+
+ Reviewed by Yury Semikhatsky.
+
+ Test: http/tests/inspector/indexeddb/database-data.html
+
+ * bindings/js/SerializedScriptValue.cpp:
+ (WebCore::SerializedScriptValue::deserializeForInspector):
+ (WebCore):
+ * bindings/js/SerializedScriptValue.h:
+ (SerializedScriptValue):
+ * bindings/v8/SerializedScriptValue.cpp:
+ (WebCore::SerializedScriptValue::deserializeForInspector):
+ (WebCore):
+ * bindings/v8/SerializedScriptValue.h:
+ (SerializedScriptValue):
+ * inspector/InjectedScript.cpp:
+ (WebCore::InjectedScript::wrapObject):
+ (WebCore::InjectedScript::wrapSerializedObject):
+ (WebCore):
+ (WebCore::InjectedScript::canAccessInspectedWindow):
+ * inspector/InjectedScript.h:
+ (InjectedScript):
+ * inspector/Inspector.json:
+ * inspector/InspectorController.cpp:
+ (WebCore::InspectorController::InspectorController):
+ * inspector/InspectorIndexedDBAgent.cpp:
+ (WebCore):
+ (WebCore::InspectorIndexedDBAgent::InspectorIndexedDBAgent):
+ (WebCore::assertFrame):
+ (WebCore::assertDocument):
+ (WebCore::InspectorIndexedDBAgent::requestData):
+ * inspector/InspectorIndexedDBAgent.h:
+ (WebCore):
+ (WebCore::InspectorIndexedDBAgent::create):
+ (InspectorIndexedDBAgent):
+ * inspector/front-end/IndexedDBModel.js:
+ (WebInspector.IndexedDBModel.idbKeyFromKey):
+ (WebInspector.IndexedDBModel.keyFromIDBKey):
+ (WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange):
+ (WebInspector.IndexedDBModel.prototype._loadDatabase):
+ (WebInspector.IndexedDBModel.prototype.loadObjectStoreData):
+ (WebInspector.IndexedDBModel.prototype.loadIndexData):
+ (WebInspector.IndexedDBModel.Entry):
+ (WebInspector.IndexedDBRequestManager):
+ (WebInspector.IndexedDBRequestManager.prototype._requestData.innerCallback):
+ (WebInspector.IndexedDBRequestManager.prototype._requestData):
+ (WebInspector.IndexedDBRequestManager.prototype.requestObjectStoreData):
+ (WebInspector.IndexedDBRequestManager.prototype._objectStoreDataLoaded):
+ (WebInspector.IndexedDBRequestManager.prototype.requestIndexData):
+ (WebInspector.IndexedDBRequestManager.prototype._indexDataLoaded):
+ (WebInspector.IndexedDBRequestManager.prototype._frameDetached):
+ (WebInspector.IndexedDBRequestManager.prototype._databaseRemoved):
+ (WebInspector.IndexedDBRequestManager.prototype._reset):
+ (WebInspector.IndexedDBRequestManager.DataRequest):
+ (WebInspector.IndexedDBDispatcher.prototype.databaseLoaded):
+ (WebInspector.IndexedDBDispatcher.prototype.objectStoreDataLoaded):
+ (WebInspector.IndexedDBDispatcher.prototype.indexDataLoaded):
+
2012-02-15 Hajime Morrita <morrita@chromium.org>
REGRESSION(r107518): DeviceOrientationController doesn't remove registered DOMWindows
#include "JSImageData.h"
#include "JSMessagePort.h"
#include "JSNavigator.h"
+#include "ScriptValue.h"
#include "SharedBuffer.h"
#include <limits>
#include <JavaScriptCore/APICast.h>
return result.first;
}
+#if ENABLE(INSPECTOR)
+ScriptValue SerializedScriptValue::deserializeForInspector(ScriptState* scriptState)
+{
+ JSValue value = deserialize(scriptState, scriptState->lexicalGlobalObject(), 0);
+ return ScriptValue(scriptState->globalData(), value);
+}
+#endif
+
JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception, MessagePortArray* messagePorts)
{
ExecState* exec = toJS(destinationContext);
#ifndef SerializedScriptValue_h
#define SerializedScriptValue_h
+#include "ScriptState.h"
#include <heap/Strong.h>
#include <runtime/JSValue.h>
#include <wtf/Forward.h>
enum SerializationErrorMode { NonThrowing, Throwing };
+class ScriptValue;
class SharedBuffer;
class SerializedScriptValue : public RefCounted<SerializedScriptValue> {
JSValueRef deserialize(JSContextRef, JSValueRef* exception, MessagePortArray*);
JSValueRef deserialize(JSContextRef, JSValueRef* exception);
+#if ENABLE(INSPECTOR)
+ ScriptValue deserializeForInspector(ScriptState*);
+#endif
+
const Vector<uint8_t>& data() { return m_data; }
~SerializedScriptValue();
return deserializer.deserialize();
}
+#if ENABLE(INSPECTOR)
+ScriptValue SerializedScriptValue::deserializeForInspector(ScriptState* scriptState)
+{
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(scriptState->context());
+
+ return ScriptValue(deserialize());
+}
+#endif
+
} // namespace WebCore
// case of failure.
v8::Handle<v8::Value> deserialize(MessagePortArray* = 0);
+#if ENABLE(INSPECTOR)
+ ScriptValue deserializeForInspector(ScriptState*);
+#endif
+
private:
enum StringDataMode {
StringValue,
}
#endif
-PassRefPtr<InspectorObject> InjectedScript::wrapObject(ScriptValue value, const String& groupName)
+PassRefPtr<InspectorObject> InjectedScript::wrapObject(ScriptValue value, const String& groupName) const
{
ASSERT(!hasNoValue());
ScriptFunctionCall wrapFunction(m_injectedScriptObject, "wrapObject");
return wrapObject(nodeAsScriptValue(node), groupName);
}
+PassRefPtr<InspectorObject> InjectedScript::wrapSerializedObject(SerializedScriptValue* serializedScriptValue, const String& groupName) const
+{
+ ScriptValue scriptValue = serializedScriptValue->deserializeForInspector(m_injectedScriptObject.scriptState());
+ return scriptValue.hasNoValue() ? 0 : wrapObject(scriptValue, groupName);
+}
+
void InjectedScript::inspectNode(Node* node)
{
ASSERT(!hasNoValue());
releaseFunction.call();
}
-bool InjectedScript::canAccessInspectedWindow()
+bool InjectedScript::canAccessInspectedWindow() const
{
return m_inspectedStateAccessCheck(m_injectedScriptObject.scriptState());
}
PassRefPtr<InspectorArray> wrapCallFrames(const ScriptValue&);
#endif
- PassRefPtr<InspectorObject> wrapObject(ScriptValue, const String& groupName);
+ PassRefPtr<InspectorObject> wrapObject(ScriptValue, const String& groupName) const;
PassRefPtr<InspectorObject> wrapNode(Node*, const String& groupName);
+ PassRefPtr<InspectorObject> wrapSerializedObject(SerializedScriptValue*, const String& groupName) const;
void inspectNode(Node*);
void releaseObjectGroup(const String&);
ScriptState* scriptState() const { return m_injectedScriptObject.scriptState(); }
typedef bool (*InspectedStateAccessCheck)(ScriptState*);
InjectedScript(ScriptObject, InspectedStateAccessCheck);
- bool canAccessInspectedWindow();
+ bool canAccessInspectedWindow() const;
void makeCall(ScriptFunctionCall&, RefPtr<InspectorValue>* result);
void makeEvalCall(ErrorString*, ScriptFunctionCall&, RefPtr<InspectorObject>* result, bool* wasThrown);
ScriptValue nodeAsScriptValue(Node*);
{ "name": "unique", "type": "boolean", "description": "If true, index is unique." },
{ "name": "multiEntry", "type": "boolean", "description": "If true, index allows multiple entries for a key." }
]
+ },
+ {
+ "id": "Key",
+ "type": "object",
+ "description": "Key.",
+ "properties": [
+ { "name": "type", "type": "string", "enum": ["number", "string", "date", "array"], "description": "Key type." },
+ { "name": "number", "type": "number", "optional": true, "description": "Number value." },
+ { "name": "string", "type": "string", "optional": true, "description": "String value." },
+ { "name": "date", "type": "number", "optional": true, "description": "Date value." },
+ { "name": "array", "type": "array", "optional": true, "items": { "$ref": "Key" }, "description": "Array value." }
+ ]
+ },
+ {
+ "id": "KeyRange",
+ "type": "object",
+ "description": "Key range.",
+ "properties": [
+ { "name": "lower", "$ref": "Key", "optional": true, "description": "Lower bound." },
+ { "name": "upper", "$ref": "Key", "optional": true, "description": "Upper bound." },
+ { "name": "lowerOpen", "type": "boolean", "description": "If true lower bound is open." },
+ { "name": "upperOpen", "type": "boolean", "description": "If true upper bound is open." }
+ ]
+ },
+ {
+ "id": "DataEntry",
+ "type": "object",
+ "description": "Key.",
+ "properties": [
+ { "name": "key", "$ref": "Key", "description": "Key." },
+ { "name": "primaryKey", "$ref": "Key", "description": "Primary key." },
+ { "name": "value", "$ref": "Runtime.RemoteObject", "description": "Value." }
+ ]
}
],
"commands": [
"name": "requestDatabase",
"parameters": [
{ "name": "requestId", "type": "integer", "description": "Request id." },
- { "name": "frameId", "$ref": "Network.FrameId" },
- { "name": "databaseName", "type": "string" }
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame id." },
+ { "name": "databaseName", "type": "string", "description": "Database name." }
],
"description": "Requests database with given name in given frame."
+ },
+ {
+ "name": "requestData",
+ "parameters": [
+ { "name": "requestId", "type": "integer", "description": "Request id." },
+ { "name": "frameId", "$ref": "Network.FrameId", "description": "Frame id." },
+ { "name": "databaseName", "type": "string", "description": "Database name." },
+ { "name": "objectStoreName", "type": "string", "description": "Object store name." },
+ { "name": "indexName", "type": "string", "description": "Index name, empty string for object store data requests." },
+ { "name": "skipCount", "type": "integer", "description": "Number of records to skip." },
+ { "name": "pageSize", "type": "integer", "description": "Number of records to fetch." },
+ { "name": "keyRange", "$ref": "KeyRange", "optional": true, "description": "Key range." }
+ ],
+ "description": "Requests data from object store or index."
}
],
"events": [
{ "name": "requestId", "type": "integer", "description": "Request id." },
{ "name": "databaseWithObjectStores", "$ref": "DatabaseWithObjectStores", "description": "Database with an array of object stores." }
]
+ },
+ {
+ "name": "objectStoreDataLoaded",
+ "parameters": [
+ { "name": "requestId", "type": "integer", "description": "Request id." },
+ { "name": "objectStoreDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of object store data entries." },
+ { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." }
+ ]
+ },
+ {
+ "name": "indexDataLoaded",
+ "parameters": [
+ { "name": "requestId", "type": "integer", "description": "Request id." },
+ { "name": "indexDataEntries", "type": "array", "items": { "$ref": "DataEntry" }, "description": "Array of index data entries." },
+ { "name": "hasMore", "type": "boolean", "description": "If true, there are more entries to fetch in the given range." }
+ ]
}
]
},
#endif
#if ENABLE(INDEXED_DATABASE)
- m_agents.append(InspectorIndexedDBAgent::create(m_instrumentingAgents.get(), m_state.get(), pageAgent));
+ m_agents.append(InspectorIndexedDBAgent::create(m_instrumentingAgents.get(), m_state.get(), m_injectedScriptManager.get(), pageAgent));
#endif
#if ENABLE(FILE_SYSTEM)
#include "Frame.h"
#include "GroupSettings.h"
#include "IDBCallbacks.h"
+#include "IDBCursor.h"
#include "IDBDatabaseBackendInterface.h"
#include "IDBFactoryBackendInterface.h"
#include "IDBIndexBackendInterface.h"
+#include "IDBKey.h"
+#include "IDBKeyRange.h"
#include "IDBObjectStoreBackendInterface.h"
+#include "IDBPendingTransactionMonitor.h"
#include "IDBTransaction.h"
#include "IDBTransactionBackendInterface.h"
+#include "InjectedScript.h"
#include "InspectorFrontend.h"
#include "InspectorPageAgent.h"
#include "InspectorState.h"
#include <wtf/Vector.h>
+using WebCore::TypeBuilder::Array;
using WebCore::TypeBuilder::IndexedDB::SecurityOriginWithDatabaseNames;
using WebCore::TypeBuilder::IndexedDB::DatabaseWithObjectStores;
+using WebCore::TypeBuilder::IndexedDB::DataEntry;
+using WebCore::TypeBuilder::IndexedDB::Key;
+using WebCore::TypeBuilder::IndexedDB::KeyRange;
using WebCore::TypeBuilder::IndexedDB::ObjectStore;
using WebCore::TypeBuilder::IndexedDB::ObjectStoreIndex;
virtual void onBlocked() { }
};
+class InspectorIDBTransactionCallback : public IDBTransactionCallbacks {
+public:
+ static PassRefPtr<InspectorIDBTransactionCallback> create()
+ {
+ return adoptRef(new InspectorIDBTransactionCallback());
+ }
+
+ virtual ~InspectorIDBTransactionCallback() { }
+
+ virtual void onAbort() { }
+ virtual void onComplete() { }
+private:
+ InspectorIDBTransactionCallback() { }
+};
+
class GetDatabaseNamesCallback : public InspectorIDBCallback {
public:
static PassRefPtr<GetDatabaseNamesCallback> create(InspectorIndexedDBAgent::FrontendProvider* frontendProvider, int requestId, const String& securityOrigin)
int m_requestId;
};
+static PassRefPtr<IDBKey> idbKeyFromInspectorObject(InspectorObject* key)
+{
+ RefPtr<IDBKey> idbKey;
+
+ String type;
+ if (!key->getString("type", &type))
+ return 0;
+
+ DEFINE_STATIC_LOCAL(String, number, ("number"));
+ DEFINE_STATIC_LOCAL(String, string, ("string"));
+ DEFINE_STATIC_LOCAL(String, date, ("date"));
+ DEFINE_STATIC_LOCAL(String, array, ("array"));
+
+ if (type == number) {
+ double number;
+ if (!key->getNumber("number", &number))
+ return 0;
+ idbKey = IDBKey::createNumber(number);
+ } else if (type == string) {
+ String string;
+ if (!key->getString("string", &string))
+ return 0;
+ idbKey = IDBKey::createString(string);
+ } else if (type == date) {
+ double date;
+ if (!key->getNumber("date", &date))
+ return 0;
+ idbKey = IDBKey::createDate(date);
+ } else if (type == array) {
+ IDBKey::KeyArray keyArray;
+ RefPtr<InspectorArray> array = key->getArray("array");
+ for (size_t i = 0; i < array->length(); ++i) {
+ RefPtr<InspectorValue> value = array->get(i);
+ RefPtr<InspectorObject> object;
+ if (!value->asObject(&object))
+ return 0;
+ keyArray.append(idbKeyFromInspectorObject(object.get()));
+ }
+ idbKey = IDBKey::createArray(keyArray);
+ } else
+ return 0;
+
+ return idbKey.release();
+}
+
+static PassRefPtr<IDBKeyRange> idbKeyRangeFromKeyRange(InspectorObject* keyRange)
+{
+ RefPtr<InspectorObject> lower = keyRange->getObject("lower");
+ RefPtr<IDBKey> idbLower = lower ? idbKeyFromInspectorObject(lower.get()) : 0;
+ if (lower && !idbLower)
+ return 0;
+
+ RefPtr<InspectorObject> upper = keyRange->getObject("upper");
+ RefPtr<IDBKey> idbUpper = upper ? idbKeyFromInspectorObject(upper.get()) : 0;
+ if (upper && !idbUpper)
+ return 0;
+
+ bool lowerOpen;
+ if (!keyRange->getBoolean("lowerOpen", &lowerOpen))
+ return 0;
+ IDBKeyRange::LowerBoundType lowerBoundType = lowerOpen ? IDBKeyRange::LowerBoundOpen : IDBKeyRange::LowerBoundClosed;
+
+ bool upperOpen;
+ if (!keyRange->getBoolean("upperOpen", &upperOpen))
+ return 0;
+ IDBKeyRange::UpperBoundType upperBoundType = upperOpen ? IDBKeyRange::UpperBoundOpen : IDBKeyRange::UpperBoundClosed;
+
+ RefPtr<IDBKeyRange> idbKeyRange = IDBKeyRange::create(idbLower, idbUpper, lowerBoundType, upperBoundType);
+ return idbKeyRange.release();
+}
+
+static PassRefPtr<Key> keyFromIDBKey(IDBKey* idbKey)
+{
+ if (!idbKey || !idbKey->valid())
+ return 0;
+
+ RefPtr<Key> key;
+ switch (idbKey->type()) {
+ case IDBKey::InvalidType:
+ case IDBKey::MinType:
+ return 0;
+ case IDBKey::NumberType: {
+ RefPtr<Key> tmpKey = Key::create().setType(Key::Type::Number);
+ key = tmpKey;
+ key->setNumber(idbKey->number());
+ break;
+ }
+ case IDBKey::StringType: {
+ RefPtr<Key> tmpKey = Key::create().setType(Key::Type::String);
+ key = tmpKey;
+ key->setString(idbKey->string());
+ break;
+ }
+ case IDBKey::DateType: {
+ RefPtr<Key> tmpKey = Key::create().setType(Key::Type::Date);
+ key = tmpKey;
+ key->setDate(idbKey->date());
+ break;
+ }
+ case IDBKey::ArrayType: {
+ RefPtr<Key> tmpKey = Key::create().setType(Key::Type::Array);
+ key = tmpKey;
+ RefPtr<InspectorArray> array = InspectorArray::create();
+ IDBKey::KeyArray keyArray = idbKey->array();
+ for (size_t i = 0; i < keyArray.size(); ++i)
+ array->pushObject(keyFromIDBKey(keyArray[i].get()));
+ key->setArray(array);
+ break;
+ }
+ }
+ return key.release();
+}
+
+class OpenCursorCallback : public InspectorIDBCallback {
+public:
+ enum CursorType {
+ ObjectStoreDataCursor,
+ IndexDataCursor
+ };
+
+ static PassRefPtr<OpenCursorCallback> create(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, InjectedScript injectedScript, PassRefPtr<IDBTransactionBackendInterface> idbTransaction, CursorType cursorType, int requestId, int skipCount, unsigned pageSize)
+ {
+ return adoptRef(new OpenCursorCallback(frontendProvider, injectedScript, idbTransaction, cursorType, requestId, skipCount, pageSize));
+ }
+
+ virtual ~OpenCursorCallback() { }
+
+ virtual void onSuccess(PassRefPtr<SerializedScriptValue>)
+ {
+ end(false);
+ }
+
+ virtual void onSuccess(PassRefPtr<IDBCursorBackendInterface> idbCursor)
+ {
+ m_idbCursor = idbCursor;
+ onSuccessWithContinuation();
+ }
+
+ virtual void onSuccessWithContinuation()
+ {
+ if (m_skipCount) {
+ --m_skipCount;
+ next();
+ return;
+ }
+
+ if (m_result->length() == m_pageSize) {
+ end(true);
+ return;
+ }
+
+ RefPtr<IDBKey> key = m_idbCursor->key();
+ RefPtr<IDBKey> primaryKey = m_idbCursor->primaryKey();
+ RefPtr<SerializedScriptValue> value = m_idbCursor->value();
+ RefPtr<InspectorObject> wrappedValue = m_injectedScript.wrapSerializedObject(value.get(), String());
+ RefPtr<DataEntry> dataEntry = DataEntry::create()
+ .setKey(keyFromIDBKey(key.get()))
+ .setPrimaryKey(keyFromIDBKey(primaryKey.get()))
+ .setValue(wrappedValue);
+ m_result->addItem(dataEntry);
+
+ next();
+ }
+
+ void next()
+ {
+ m_idbTransaction->didCompleteTaskEvents();
+
+ ExceptionCode ec = 0;
+ m_idbCursor->continueFunction(0, this, ec);
+ }
+
+ void end(bool hasMore)
+ {
+ if (!m_frontendProvider->frontend())
+ return;
+
+ m_idbTransaction->didCompleteTaskEvents();
+
+ switch (m_cursorType) {
+ case ObjectStoreDataCursor:
+ m_frontendProvider->frontend()->objectStoreDataLoaded(m_requestId, m_result.release(), hasMore);
+ break;
+ case IndexDataCursor:
+ m_frontendProvider->frontend()->indexDataLoaded(m_requestId, m_result.release(), hasMore);
+ break;
+ }
+ }
+
+private:
+ OpenCursorCallback(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, InjectedScript injectedScript, PassRefPtr<IDBTransactionBackendInterface> idbTransaction, CursorType cursorType, int requestId, int skipCount, unsigned pageSize)
+ : m_frontendProvider(frontendProvider)
+ , m_injectedScript(injectedScript)
+ , m_idbTransaction(idbTransaction)
+ , m_cursorType(cursorType)
+ , m_requestId(requestId)
+ , m_skipCount(skipCount)
+ , m_pageSize(pageSize)
+ {
+ m_result = Array<DataEntry>::create();
+ m_idbTransaction->setCallbacks(InspectorIDBTransactionCallback::create().get());
+ }
+ RefPtr<InspectorIndexedDBAgent::FrontendProvider> m_frontendProvider;
+ InjectedScript m_injectedScript;
+ RefPtr<IDBTransactionBackendInterface> m_idbTransaction;
+ CursorType m_cursorType;
+ int m_requestId;
+ int m_skipCount;
+ unsigned m_pageSize;
+ RefPtr<Array<DataEntry> > m_result;
+ RefPtr<IDBCursorBackendInterface> m_idbCursor;
+};
+
+class DataLoaderCallback : public ExecutableWithDatabase {
+public:
+ static PassRefPtr<DataLoaderCallback> create(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, int requestId, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize)
+ {
+ return adoptRef(new DataLoaderCallback(frontendProvider, requestId, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize));
+ }
+
+ virtual ~DataLoaderCallback() { }
+
+ virtual void execute(PassRefPtr<IDBDatabaseBackendInterface> idbDatabase)
+ {
+ if (!m_frontendProvider->frontend())
+ return;
+
+ RefPtr<IDBTransactionBackendInterface> idbTransaction = transactionForDatabase(idbDatabase.get(), m_objectStoreName);
+ if (!idbTransaction)
+ return;
+ RefPtr<IDBObjectStoreBackendInterface> idbObjectStore = objectStoreForTransaction(idbTransaction.get(), m_objectStoreName);
+ if (!idbObjectStore)
+ return;
+
+ if (!m_indexName.isEmpty()) {
+ RefPtr<IDBIndexBackendInterface> idbIndex = indexForObjectStore(idbObjectStore.get(), m_indexName);
+ if (!idbIndex)
+ return;
+
+ RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_frontendProvider, m_injectedScript, idbTransaction.get(), OpenCursorCallback::IndexDataCursor, m_requestId, m_skipCount, m_pageSize);
+
+ ExceptionCode ec = 0;
+ idbIndex->openCursor(m_idbKeyRange, IDBCursor::NEXT, openCursorCallback, idbTransaction.get(), ec);
+ } else {
+ RefPtr<OpenCursorCallback> openCursorCallback = OpenCursorCallback::create(m_frontendProvider, m_injectedScript, idbTransaction.get(), OpenCursorCallback::ObjectStoreDataCursor, m_requestId, m_skipCount, m_pageSize);
+
+ ExceptionCode ec = 0;
+ idbObjectStore->openCursor(m_idbKeyRange, IDBCursor::NEXT, openCursorCallback, idbTransaction.get(), ec);
+ }
+ }
+
+private:
+ DataLoaderCallback(PassRefPtr<InspectorIndexedDBAgent::FrontendProvider> frontendProvider, int requestId, const InjectedScript& injectedScript, const String& objectStoreName, const String& indexName, PassRefPtr<IDBKeyRange> idbKeyRange, int skipCount, unsigned pageSize)
+ : m_frontendProvider(frontendProvider)
+ , m_requestId(requestId)
+ , m_injectedScript(injectedScript)
+ , m_objectStoreName(objectStoreName)
+ , m_indexName(indexName)
+ , m_idbKeyRange(idbKeyRange)
+ , m_skipCount(skipCount)
+ , m_pageSize(pageSize) { }
+ RefPtr<InspectorIndexedDBAgent::FrontendProvider> m_frontendProvider;
+ int m_requestId;
+ InjectedScript m_injectedScript;
+ String m_objectStoreName;
+ String m_indexName;
+ RefPtr<IDBKeyRange> m_idbKeyRange;
+ int m_skipCount;
+ unsigned m_pageSize;
+};
+
} // namespace
-InspectorIndexedDBAgent::InspectorIndexedDBAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, InspectorPageAgent* pageAgent)
+InspectorIndexedDBAgent::InspectorIndexedDBAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, InjectedScriptManager* injectedScriptManager, InspectorPageAgent* pageAgent)
: InspectorBaseAgent<InspectorIndexedDBAgent>("IndexedDB", instrumentingAgents, state)
+ , m_injectedScriptManager(injectedScriptManager)
, m_pageAgent(pageAgent)
{
}
m_state->setBoolean(IndexedDBAgentState::indexedDBAgentEnabled, false);
}
-static Document* assertDocument(const String& frameId, InspectorPageAgent* pageAgent, ErrorString* error)
+static Frame* assertFrame(ErrorString* errorString, const String& frameId, InspectorPageAgent* pageAgent)
{
Frame* frame = pageAgent->frameForId(frameId);
+
+ if (!frame)
+ *errorString = "Frame not found";
+
+ return frame;
+}
+
+static Document* assertDocument(ErrorString* errorString, Frame* frame)
+{
Document* document = frame ? frame->document() : 0;
if (!document)
- *error = "No document for given frame found";
+ *errorString = "No document for given frame found";
return document;
}
-static IDBFactoryBackendInterface* assertIDBFactory(Document* document, ErrorString* error)
+static Document* assertDocument(ErrorString* errorString, const String& frameId, InspectorPageAgent* pageAgent)
+{
+ Frame* frame = pageAgent->frameForId(frameId);
+ Document* document = frame ? frame->document() : 0;
+
+ if (!document)
+ *errorString = "No document for given frame found";
+
+ return document;
+}
+
+static IDBFactoryBackendInterface* assertIDBFactory(ErrorString* errorString, Document* document)
{
Page* page = document ? document->page() : 0;
IDBFactoryBackendInterface* idbFactory = page ? page->group().idbFactory() : 0;
if (!idbFactory)
- *error = "No IndexedDB factory for given frame found";
+ *errorString = "No IndexedDB factory for given frame found";
return idbFactory;
}
-void InspectorIndexedDBAgent::requestDatabaseNamesForFrame(ErrorString* error, int requestId, const String& frameId)
+void InspectorIndexedDBAgent::requestDatabaseNamesForFrame(ErrorString* errorString, int requestId, const String& frameId)
{
- Document* document = assertDocument(frameId, m_pageAgent, error);
+ Document* document = assertDocument(errorString, frameId, m_pageAgent);
if (!document)
return;
- IDBFactoryBackendInterface* idbFactory = assertIDBFactory(document, error);
+ IDBFactoryBackendInterface* idbFactory = assertIDBFactory(errorString, document);
if (!idbFactory)
return;
idbFactory->getDatabaseNames(callback.get(), document->securityOrigin(), document->frame(), groupSettings->indexedDBDatabasePath());
}
-void InspectorIndexedDBAgent::requestDatabase(ErrorString* error, int requestId, const String& frameId, const String& databaseName)
+void InspectorIndexedDBAgent::requestDatabase(ErrorString* errorString, int requestId, const String& frameId, const String& databaseName)
{
- Document* document = assertDocument(frameId, m_pageAgent, error);
+ Document* document = assertDocument(errorString, frameId, m_pageAgent);
if (!document)
return;
- IDBFactoryBackendInterface* idbFactory = assertIDBFactory(document, error);
+ IDBFactoryBackendInterface* idbFactory = assertIDBFactory(errorString, document);
if (!idbFactory)
return;
databaseLoaderCallback->start(idbFactory, document->securityOrigin(), document->frame(), databaseName);
}
+void InspectorIndexedDBAgent::requestData(ErrorString* errorString, int requestId, const String& frameId, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange)
+{
+ Frame* frame = assertFrame(errorString, frameId, m_pageAgent);
+ if (!frame)
+ return;
+ Document* document = assertDocument(errorString, frame);
+ if (!document)
+ return;
+ IDBFactoryBackendInterface* idbFactory = assertIDBFactory(errorString, document);
+ if (!idbFactory)
+ return;
+
+ InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(mainWorldScriptState(frame));
+
+ RefPtr<IDBKeyRange> idbKeyRange = keyRange ? idbKeyRangeFromKeyRange(keyRange->get()) : 0;
+ if (keyRange && !idbKeyRange) {
+ *errorString = "Can not parse key range.";
+ return;
+ }
+
+ RefPtr<DataLoaderCallback> dataLoaderCallback = DataLoaderCallback::create(m_frontendProvider, requestId, injectedScript, objectStoreName, indexName, idbKeyRange, skipCount, pageSize);
+ dataLoaderCallback->start(idbFactory, document->securityOrigin(), document->frame(), databaseName);
+}
+
} // namespace WebCore
#endif // ENABLE(INSPECTOR) && ENABLE(INDEXED_DATABASE)
namespace WebCore {
+class InjectedScriptManager;
class InspectorPageAgent;
typedef String ErrorString;
public:
class FrontendProvider;
- static PassOwnPtr<InspectorIndexedDBAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* state, InspectorPageAgent* pageAgent)
+ static PassOwnPtr<InspectorIndexedDBAgent> create(InstrumentingAgents* instrumentingAgents, InspectorState* state, InjectedScriptManager* injectedScriptManager, InspectorPageAgent* pageAgent)
{
- return adoptPtr(new InspectorIndexedDBAgent(instrumentingAgents, state, pageAgent));
+ return adoptPtr(new InspectorIndexedDBAgent(instrumentingAgents, state, injectedScriptManager, pageAgent));
}
~InspectorIndexedDBAgent();
virtual void disable(ErrorString*);
virtual void requestDatabaseNamesForFrame(ErrorString*, int requestId, const String& frameId);
virtual void requestDatabase(ErrorString*, int requestId, const String& frameId, const String& databaseName);
+ virtual void requestData(ErrorString*, int requestId, const String& frameId, const String& databaseName, const String& objectStoreName, const String& indexName, int skipCount, int pageSize, const RefPtr<InspectorObject>* keyRange);
private:
- InspectorIndexedDBAgent(InstrumentingAgents*, InspectorState*, InspectorPageAgent*);
+ InspectorIndexedDBAgent(InstrumentingAgents*, InspectorState*, InjectedScriptManager*, InspectorPageAgent*);
+ InjectedScriptManager* m_injectedScriptManager;
InspectorPageAgent* m_pageAgent;
RefPtr<FrontendProvider> m_frontendProvider;
bool m_enabled;
WebInspector.IndexedDBModel = function()
{
this._indexedDBRequestManager = new WebInspector.IndexedDBRequestManager();
-
+
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this);
-
+
this._frames = {};
this._frameIdsBySecurityOrigin = {};
this._databaseNamesBySecurityOrigin = {};
this.refreshDatabaseNames();
}
+WebInspector.IndexedDBModel.KeyTypes = {
+ NumberType: "number",
+ StringType: "string",
+ DateType: "date",
+ ArrayType: "array"
+};
+
+/**
+ * @param {IndexedDBAgent.Key} key
+ */
+WebInspector.IndexedDBModel.idbKeyFromKey = function(key)
+{
+ var idbKey;
+ switch (key.type) {
+ case WebInspector.IndexedDBModel.KeyTypes.NumberType:
+ idbKey = key.number;
+ break;
+ case WebInspector.IndexedDBModel.KeyTypes.StringType:
+ idbKey = key.string;
+ break;
+ case WebInspector.IndexedDBModel.KeyTypes.DateType:
+ idbKey = new Date(key.date);
+ break;
+ case WebInspector.IndexedDBModel.KeyTypes.ArrayType:
+ idbKey = [];
+ for (var i = 0; i < key.length; ++i)
+ idbKey.push(WebInspector.IndexedDBModel.idbKeyFromKey(key.array[i]));
+ break;
+ }
+ return idbKey;
+}
+
+WebInspector.IndexedDBModel.keyFromIDBKey = function(idbKey)
+{
+ if (typeof(idbKey) === "undefined" || idbKey === null)
+ return null;
+
+ var key = {};
+ switch (typeof(idbKey)) {
+ case "number":
+ key.number = idbKey;
+ key.type = WebInspector.IndexedDBModel.KeyTypes.NumberType;
+ break;
+ case "string":
+ key.string = idbKey;
+ key.type = WebInspector.IndexedDBModel.KeyTypes.StringType;
+ break;
+ case "object":
+ if (idbKey instanceof Date) {
+ key.date = idbKey.getTime();
+ key.type = WebInspector.IndexedDBModel.KeyTypes.DateType;
+ } else if (idbKey instanceof Array) {
+ key.array = [];
+ for (var i = 0; i < idbKey.length; ++i)
+ key.array.push(WebInspector.IndexedDBModel.keyFromIDBKey(idbKey[i]));
+ key.type = WebInspector.IndexedDBModel.KeyTypes.ArrayType;
+ }
+ break;
+ default:
+ return null;
+ }
+ return key;
+}
+
+WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange = function(idbKeyRange)
+{
+ var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
+ if (typeof(idbKeyRange) === "undefined" || idbKeyRange === null)
+ return null;
+
+ var keyRange = {};
+ keyRange.lower = WebInspector.IndexedDBModel.keyFromIDBKey(idbKeyRange.lower);
+ keyRange.upper = WebInspector.IndexedDBModel.keyFromIDBKey(idbKeyRange.upper);
+ keyRange.lowerOpen = idbKeyRange.lowerOpen;
+ keyRange.upperOpen = idbKeyRange.upperOpen;
+ return keyRange;
+}
+
WebInspector.IndexedDBModel.prototype = {
refreshDatabaseNames: function()
{
this._reset();
this._framesNavigatedRecursively(WebInspector.resourceTreeModel.mainFrame);
},
-
+
refreshDatabase: function(frameId, databaseName)
{
this._loadDatabase(frameId, databaseName);
},
-
+
/**
* @param {WebInspector.ResourceTreeFrame} resourceTreeFrame
*/
{
this._processFrameNavigated(resourceTreeFrame);
for (var i = 0; i < resourceTreeFrame.childFrames.length; ++i)
- this._framesNavigatedRecursively(resourceTreeFrame.childFrames[i]);
+ this._framesNavigatedRecursively(resourceTreeFrame.childFrames[i]);
},
-
+
/**
* @param {WebInspector.Event} event
*/
var resourceTreeFrame = /** @type {WebInspector.ResourceTreeFrame} */ event.data;
this._processFrameNavigated(resourceTreeFrame);
},
-
+
/**
* @param {WebInspector.Event} event
*/
}
this._indexedDBRequestManager.requestDatabase(frameId, databaseName, callback.bind(this));
+ },
+
+ /**
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {string} objectStoreName
+ * @param {webkitIDBKeyRange} idbKeyRange
+ * @param {number} skipCount
+ * @param {number} pageSize
+ * @param {function(Array.<WebInspector.IndexedDBModel.Entry>, boolean)} callback
+ */
+ loadObjectStoreData: function(frameId, databaseName, objectStoreName, idbKeyRange, skipCount, pageSize, callback)
+ {
+ /**
+ * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries
+ * @param {boolean} hasMore
+ */
+ function innerCallback(dataEntries, hasMore)
+ {
+ var entries = [];
+ for (var i = 0; i < dataEntries.length; ++i) {
+ var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key);
+ var primaryKey = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].primaryKey);
+ var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value);
+ entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value));
+ }
+ callback(entries, hasMore);
+ }
+
+ this._indexedDBRequestManager.requestObjectStoreData(frameId, databaseName, objectStoreName, idbKeyRange, skipCount, pageSize, innerCallback);
+ },
+
+ /**
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {string} objectStoreName
+ * @param {string} indexName
+ * @param {webkitIDBKeyRange} idbKeyRange
+ * @param {number} skipCount
+ * @param {number} pageSize
+ * @param {function(Array.<WebInspector.IndexedDBModel.Entry>, boolean)} callback
+ */
+ loadIndexData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
+ {
+ /**
+ * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries
+ * @param {boolean} hasMore
+ */
+ function innerCallback(dataEntries, hasMore)
+ {
+ var entries = [];
+ for (var i = 0; i < dataEntries.length; ++i) {
+ var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key);
+ var primaryKey = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].primaryKey);
+ var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value);
+ entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value));
+ }
+ callback(entries, hasMore);
+ }
+
+ this._indexedDBRequestManager.requestIndexData(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, innerCallback.bind(this));
}
}
/**
* @constructor
+ * @param {*} key
+ * @param {*} primaryKey
+ * @param {WebInspector.RemoteObject} value
+ */
+WebInspector.IndexedDBModel.Entry = function(key, primaryKey, value)
+{
+ this.key = key;
+ this.primaryKey = primaryKey;
+ this.value = value;
+}
+
+/**
+ * @constructor
* @param {string} frameId
* @param {string} securityOrigin
*/
{
this._lastRequestId = 0;
this._requestDatabaseNamesForFrameCallbacks = {};
+ this._requestDatabaseCallbacks = {};
+ this._requestDataCallbacks = {};
IndexedDBAgent.enable();
InspectorBackend.registerIndexedDBDispatcher(new WebInspector.IndexedDBDispatcher(this));
IndexedDBAgent.requestDatabase(requestId, frameId, databaseName, innerCallback);
},
-
+
/**
* @param {number} requestId
* @param {IndexedDBAgent.DatabaseWithObjectStores} databaseWithObjectStores
},
/**
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {string} objectStoreName
+ * @param {string} indexName
+ * @param {webkitIDBKeyRange} idbKeyRange
+ * @param {number} skipCount
+ * @param {number} pageSize
+ * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback
+ */
+ _requestData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
+ {
+ var requestId = this._requestId();
+ var request = new WebInspector.IndexedDBRequestManager.DataRequest(frameId, databaseName, objectStoreName, indexName, callback);
+ this._requestDataCallbacks[requestId] = request;
+
+ function innerCallback(error)
+ {
+ if (error) {
+ console.error("IndexedDBAgent error: " + error);
+ return;
+ }
+ }
+
+ var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange);
+ IndexedDBAgent.requestData(requestId, frameId, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback);
+ },
+
+ /**
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {string} objectStoreName
+ * @param {webkitIDBKeyRange} idbKeyRange
+ * @param {number} skipCount
+ * @param {number} pageSize
+ * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback
+ */
+ requestObjectStoreData: function(frameId, databaseName, objectStoreName, idbKeyRange, skipCount, pageSize, callback)
+ {
+ this._requestData(frameId, databaseName, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback);
+ },
+
+ /**
+ * @param {number} requestId
+ * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries
+ * @param {boolean} hasMore
+ */
+ _objectStoreDataLoaded: function(requestId, dataEntries, hasMore)
+ {
+ var request = this._requestDataCallbacks[requestId];
+ if (!request.callback)
+ return;
+
+ request.callback(dataEntries, hasMore);
+ },
+
+ /**
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {string} objectStoreName
+ * @param {string} indexName
+ * @param {webkitIDBKeyRange} idbKeyRange
+ * @param {number} skipCount
+ * @param {number} pageSize
+ * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback
+ */
+ requestIndexData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
+ {
+ this._requestData(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback);
+ },
+
+ /**
+ * @param {number} requestId
+ * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries
+ * @param {boolean} hasMore
+ */
+ _indexDataLoaded: function(requestId, dataEntries, hasMore)
+ {
+ var request = this._requestDataCallbacks[requestId];
+ if (!request.callback)
+ return;
+
+ request.callback(dataEntries, hasMore);
+ },
+
+ /**
* @return {number}
*/
_requestId: function()
if (this._requestDatabaseNamesForFrameCallbacks[requestId].frameId === frameId)
delete this._requestDatabaseNamesForFrameCallbacks[requestId];
}
-
+
for (var requestId in this._requestDatabaseCallbacks) {
if (this._requestDatabaseCallbacks[requestId].frameId === frameId)
delete this._requestDatabaseCallbacks[requestId];
}
+
+ for (var requestId in this._requestDataCallbacks) {
+ if (this._requestDataCallbacks[requestId].frameId === frameId)
+ delete this._requestDataCallbacks[requestId];
+ }
},
/**
if (this._requestDatabaseCallbacks[requestId].frameId === frameId && this._requestDatabaseCallbacks[requestId].databaseName === databaseName)
delete this._requestDatabaseCallbacks[requestId];
}
+
+ for (var requestId in this._requestDataCallbacks) {
+ if (this._requestDataCallbacks[requestId].frameId === frameId && this._requestDataCallbacks[requestId].databaseName === databaseName)
+ delete this._requestDataCallbacks[requestId];
+ }
},
_reset: function()
{
this._requestDatabaseNamesForFrameCallbacks = {};
this._requestDatabaseCallbacks = {};
-
+ this._requestDataCallbacks = {};
}
}
/**
* @constructor
- */
+ * @param {string} frameId
+ * @param {function(IndexedDBAgent.SecurityOriginWithDatabaseNames)} callback
+*/
WebInspector.IndexedDBRequestManager.DatabasesForFrameRequest = function(frameId, callback)
{
this.frameId = frameId;
/**
* @constructor
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {function(IndexedDBAgent.DatabaseWithObjectStores)} callback
*/
WebInspector.IndexedDBRequestManager.DatabaseRequest = function(frameId, databaseName, callback)
{
/**
* @constructor
+ * @param {string} frameId
+ * @param {string} databaseName
+ * @param {string} objectStoreName
+ * @param {string} indexName
+ * @param {function(Array.<IndexedDBAgent.DataEntry>, boolean)} callback
+ */
+WebInspector.IndexedDBRequestManager.DataRequest = function(frameId, databaseName, objectStoreName, indexName, callback)
+{
+ this.frameId = frameId;
+ this.databaseName = databaseName;
+ this.objectStoreName = objectStoreName;
+ this.indexName = indexName;
+ this.callback = callback;
+}
+
+/**
+ * @constructor
* @implements {IndexedDBAgent.Dispatcher}
* @param {WebInspector.IndexedDBRequestManager} indexedDBRequestManager
*/
databaseLoaded: function(requestId, databaseWithObjectStores)
{
this._agentWrapper._databaseLoaded(requestId, databaseWithObjectStores);
+ },
+
+ /**
+ * @param {number} requestId
+ * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries
+ * @param {boolean} hasMore
+ */
+ objectStoreDataLoaded: function(requestId, dataEntries, hasMore)
+ {
+ this._agentWrapper._objectStoreDataLoaded(requestId, dataEntries, hasMore);
+ },
+
+ /**
+ * @param {number} requestId
+ * @param {Array.<IndexedDBAgent.DataEntry>} dataEntries
+ * @param {boolean} hasMore
+ */
+ indexDataLoaded: function(requestId, dataEntries, hasMore)
+ {
+ this._agentWrapper._indexDataLoaded(requestId, dataEntries, hasMore);
}
}
+