WebInspector.IndexedDBModel = function()
{
IndexedDBAgent.enable();
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginAdded, this._securityOriginAdded, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginRemoved, this._securityOriginRemoved, this);
this._databases = new Map();
this._databaseNamesBySecurityOrigin = {};
this._reset();
}
WebInspector.IndexedDBModel.KeyTypes = {
NumberType: "number",
StringType: "string",
DateType: "date",
ArrayType: "array"
};
WebInspector.IndexedDBModel.KeyPathTypes = {
NullType: "null",
StringType: "string",
ArrayType: "array"
};
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.idbKeyPathFromKeyPath = function(keyPath)
{
var idbKeyPath;
switch (keyPath.type) {
case WebInspector.IndexedDBModel.KeyPathTypes.NullType:
idbKeyPath = null;
break;
case WebInspector.IndexedDBModel.KeyPathTypes.StringType:
idbKeyPath = keyPath.string;
break;
case WebInspector.IndexedDBModel.KeyPathTypes.ArrayType:
idbKeyPath = keyPath.array;
break;
}
return idbKeyPath;
}
WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath = function(idbKeyPath)
{
if (typeof idbKeyPath === "string")
return "\"" + idbKeyPath + "\"";
if (idbKeyPath instanceof Array)
return "[\"" + idbKeyPath.join("\", \"") + "\"]";
return null;
}
WebInspector.IndexedDBModel.EventTypes = {
DatabaseAdded: "DatabaseAdded",
DatabaseRemoved: "DatabaseRemoved",
DatabaseLoaded: "DatabaseLoaded"
}
WebInspector.IndexedDBModel.prototype = {
_reset: function()
{
for (var securityOrigin in this._databaseNamesBySecurityOrigin)
this._removeOrigin(securityOrigin);
var securityOrigins = WebInspector.resourceTreeModel.securityOrigins();
for (var i = 0; i < securityOrigins.length; ++i)
this._addOrigin(securityOrigins[i]);
},
refreshDatabaseNames: function()
{
for (var securityOrigin in this._databaseNamesBySecurityOrigin)
this._loadDatabaseNames(securityOrigin);
},
refreshDatabase: function(databaseId)
{
this._loadDatabase(databaseId);
},
clearObjectStore: function(databaseId, objectStoreName, callback)
{
IndexedDBAgent.clearObjectStore(databaseId.securityOrigin, databaseId.name, objectStoreName, callback);
},
_securityOriginAdded: function(event)
{
var securityOrigin = (event.data);
this._addOrigin(securityOrigin);
},
_securityOriginRemoved: function(event)
{
var securityOrigin = (event.data);
this._removeOrigin(securityOrigin);
},
_addOrigin: function(securityOrigin)
{
console.assert(!this._databaseNamesBySecurityOrigin[securityOrigin]);
this._databaseNamesBySecurityOrigin[securityOrigin] = [];
this._loadDatabaseNames(securityOrigin);
},
_removeOrigin: function(securityOrigin)
{
console.assert(this._databaseNamesBySecurityOrigin[securityOrigin]);
for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i)
this._databaseRemoved(securityOrigin, this._databaseNamesBySecurityOrigin[securityOrigin][i]);
delete this._databaseNamesBySecurityOrigin[securityOrigin];
},
_updateOriginDatabaseNames: function(securityOrigin, databaseNames)
{
var newDatabaseNames = {};
for (var i = 0; i < databaseNames.length; ++i)
newDatabaseNames[databaseNames[i]] = true;
var oldDatabaseNames = {};
for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i)
oldDatabaseNames[this._databaseNamesBySecurityOrigin[securityOrigin][i]] = true;
this._databaseNamesBySecurityOrigin[securityOrigin] = databaseNames;
for (var databaseName in oldDatabaseNames) {
if (!newDatabaseNames[databaseName])
this._databaseRemoved(securityOrigin, databaseName);
}
for (var databaseName in newDatabaseNames) {
if (!oldDatabaseNames[databaseName])
this._databaseAdded(securityOrigin, databaseName);
}
},
_databaseAdded: function(securityOrigin, databaseName)
{
var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName);
this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseAdded, databaseId);
},
_databaseRemoved: function(securityOrigin, databaseName)
{
var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName);
this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseRemoved, databaseId);
},
_loadDatabaseNames: function(securityOrigin)
{
function callback(error, databaseNames)
{
if (error) {
console.error("IndexedDBAgent error: " + error);
return;
}
if (!this._databaseNamesBySecurityOrigin[securityOrigin])
return;
this._updateOriginDatabaseNames(securityOrigin, databaseNames);
}
IndexedDBAgent.requestDatabaseNames(securityOrigin, callback.bind(this));
},
_loadDatabase: function(databaseId)
{
function callback(error, databaseWithObjectStores)
{
if (error) {
console.error("IndexedDBAgent error: " + error);
return;
}
if (!this._databaseNamesBySecurityOrigin[databaseId.securityOrigin])
return;
var databaseModel = new WebInspector.IndexedDBModel.Database(databaseId, databaseWithObjectStores.version, databaseWithObjectStores.intVersion);
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);
var objectStoreModel = new WebInspector.IndexedDBModel.ObjectStore(objectStore.name, objectStoreIDBKeyPath, objectStore.autoIncrement);
for (var j = 0; j < objectStore.indexes.length; ++j) {
var index = objectStore.indexes[j];
var indexIDBKeyPath = WebInspector.IndexedDBModel.idbKeyPathFromKeyPath(index.keyPath);
var indexModel = new WebInspector.IndexedDBModel.Index(index.name, indexIDBKeyPath, index.unique, index.multiEntry);
objectStoreModel.indexes[indexModel.name] = indexModel;
}
databaseModel.objectStores[objectStoreModel.name] = objectStoreModel;
}
this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, databaseModel);
}
IndexedDBAgent.requestDatabase(databaseId.securityOrigin, databaseId.name, callback.bind(this));
},
loadObjectStoreData: function(databaseId, objectStoreName, idbKeyRange, skipCount, pageSize, callback)
{
this._requestData(databaseId, databaseId.name, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback);
},
loadIndexData: function(databaseId, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
{
this._requestData(databaseId, databaseId.name, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback);
},
_requestData: function(databaseId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
{
function innerCallback(error, dataEntries, hasMore)
{
if (error) {
console.error("IndexedDBAgent error: " + error);
return;
}
if (!this._databaseNamesBySecurityOrigin[databaseId.securityOrigin])
return;
var entries = [];
for (var i = 0; i < dataEntries.length; ++i) {
var key = WebInspector.RemoteObject.fromPayload(dataEntries[i].key);
var primaryKey = WebInspector.RemoteObject.fromPayload(dataEntries[i].primaryKey);
var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value);
entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value));
}
callback(entries, hasMore);
}
var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange);
IndexedDBAgent.requestData(databaseId.securityOrigin, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback.bind(this));
},
__proto__: WebInspector.Object.prototype
}
WebInspector.IndexedDBModel.Entry = function(key, primaryKey, value)
{
this.key = key;
this.primaryKey = primaryKey;
this.value = value;
}
WebInspector.IndexedDBModel.DatabaseId = function(securityOrigin, name)
{
this.securityOrigin = securityOrigin;
this.name = name;
}
WebInspector.IndexedDBModel.DatabaseId.prototype = {
equals: function(databaseId)
{
return this.name === databaseId.name && this.securityOrigin === databaseId.securityOrigin;
},
}
WebInspector.IndexedDBModel.Database = function(databaseId, version, intVersion)
{
this.databaseId = databaseId;
this.version = version;
this.intVersion = intVersion;
this.objectStores = {};
}
WebInspector.IndexedDBModel.ObjectStore = function(name, keyPath, autoIncrement)
{
this.name = name;
this.keyPath = keyPath;
this.autoIncrement = autoIncrement;
this.indexes = {};
}
WebInspector.IndexedDBModel.ObjectStore.prototype = {
get keyPathString()
{
return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath);
}
}
WebInspector.IndexedDBModel.Index = function(name, keyPath, unique, multiEntry)
{
this.name = name;
this.keyPath = keyPath;
this.unique = unique;
this.multiEntry = multiEntry;
}
WebInspector.IndexedDBModel.Index.prototype = {
get keyPathString()
{
return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath);
}
}