diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/devtools/front_end/sdk/IndexedDBModel.js')
-rw-r--r-- | chromium/third_party/WebKit/Source/devtools/front_end/sdk/IndexedDBModel.js | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/sdk/IndexedDBModel.js b/chromium/third_party/WebKit/Source/devtools/front_end/sdk/IndexedDBModel.js new file mode 100644 index 00000000000..d79cfdc29f9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/devtools/front_end/sdk/IndexedDBModel.js @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @constructor + * @extends {WebInspector.TargetAwareObject} + */ +WebInspector.IndexedDBModel = function(target) +{ + WebInspector.TargetAwareObject.call(this, target); + this._agent = target.indexedDBAgent(); + this._agent.enable(); + + target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginAdded, this._securityOriginAdded, this); + target.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginRemoved, this._securityOriginRemoved, this); + + /** @type {!Map.<!WebInspector.IndexedDBModel.DatabaseId, !WebInspector.IndexedDBModel.Database>} */ + this._databases = new Map(); + /** @type {!Object.<string, !Array.<string>>} */ + this._databaseNamesBySecurityOrigin = {}; + this._reset(); +} + +WebInspector.IndexedDBModel.KeyTypes = { + NumberType: "number", + StringType: "string", + DateType: "date", + ArrayType: "array" +}; + +WebInspector.IndexedDBModel.KeyPathTypes = { + NullType: "null", + StringType: "string", + ArrayType: "array" +}; + +/** + * @param {*} idbKey + * @return {?Object} + */ +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; +} + +/** + * @param {?IDBKeyRange=} idbKeyRange + * @return {?{lower: ?Object, upper: ?Object, lowerOpen: *, upperOpen: *}} + */ +WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange = function(idbKeyRange) +{ + 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; +} + +/** + * @param {!IndexedDBAgent.KeyPath} keyPath + * @return {?string|!Array.<string>|undefined} + */ +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; +} + +/** + * @param {?string|!Array.<string>|undefined} idbKeyPath + * @return {?string} + */ +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 = this.target().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); + }, + + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + */ + refreshDatabase: function(databaseId) + { + this._loadDatabase(databaseId); + }, + + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + * @param {string} objectStoreName + * @param {function()} callback + */ + clearObjectStore: function(databaseId, objectStoreName, callback) + { + this._agent.clearObjectStore(databaseId.securityOrigin, databaseId.name, objectStoreName, callback); + }, + + /** + * @param {!WebInspector.Event} event + */ + _securityOriginAdded: function(event) + { + var securityOrigin = /** @type {string} */ (event.data); + this._addOrigin(securityOrigin); + }, + + /** + * @param {!WebInspector.Event} event + */ + _securityOriginRemoved: function(event) + { + var securityOrigin = /** @type {string} */ (event.data); + this._removeOrigin(securityOrigin); + }, + + /** + * @param {string} securityOrigin + */ + _addOrigin: function(securityOrigin) + { + console.assert(!this._databaseNamesBySecurityOrigin[securityOrigin]); + this._databaseNamesBySecurityOrigin[securityOrigin] = []; + this._loadDatabaseNames(securityOrigin); + }, + + /** + * @param {string} 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]; + }, + + /** + * @param {string} securityOrigin + * @param {!Array.<string>} databaseNames + */ + _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); + } + }, + + /** + * @param {string} securityOrigin + * @param {string} databaseName + */ + _databaseAdded: function(securityOrigin, databaseName) + { + var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName); + this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseAdded, databaseId); + }, + + /** + * @param {string} securityOrigin + * @param {string} databaseName + */ + _databaseRemoved: function(securityOrigin, databaseName) + { + var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName); + this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseRemoved, databaseId); + }, + + /** + * @param {string} securityOrigin + */ + _loadDatabaseNames: function(securityOrigin) + { + /** + * @param {?Protocol.Error} error + * @param {!Array.<string>} databaseNames + * @this {WebInspector.IndexedDBModel} + */ + function callback(error, databaseNames) + { + if (error) { + console.error("IndexedDBAgent error: " + error); + return; + } + + if (!this._databaseNamesBySecurityOrigin[securityOrigin]) + return; + this._updateOriginDatabaseNames(securityOrigin, databaseNames); + } + + this._agent.requestDatabaseNames(securityOrigin, callback.bind(this)); + }, + + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + */ + _loadDatabase: function(databaseId) + { + /** + * @param {?Protocol.Error} error + * @param {!IndexedDBAgent.DatabaseWithObjectStores} databaseWithObjectStores + * @this {WebInspector.IndexedDBModel} + */ + 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); + } + + this._agent.requestDatabase(databaseId.securityOrigin, databaseId.name, callback.bind(this)); + }, + + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + * @param {string} objectStoreName + * @param {?IDBKeyRange} idbKeyRange + * @param {number} skipCount + * @param {number} pageSize + * @param {function(!Array.<!WebInspector.IndexedDBModel.Entry>, boolean)} callback + */ + loadObjectStoreData: function(databaseId, objectStoreName, idbKeyRange, skipCount, pageSize, callback) + { + this._requestData(databaseId, databaseId.name, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback); + }, + + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + * @param {string} objectStoreName + * @param {string} indexName + * @param {?IDBKeyRange} idbKeyRange + * @param {number} skipCount + * @param {number} pageSize + * @param {function(!Array.<!WebInspector.IndexedDBModel.Entry>, boolean)} callback + */ + loadIndexData: function(databaseId, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) + { + this._requestData(databaseId, databaseId.name, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback); + }, + + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + * @param {string} databaseName + * @param {string} objectStoreName + * @param {string} indexName + * @param {?IDBKeyRange} idbKeyRange + * @param {number} skipCount + * @param {number} pageSize + * @param {function(!Array.<!WebInspector.IndexedDBModel.Entry>, boolean)} callback + */ + _requestData: function(databaseId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback) + { + /** + * @param {?Protocol.Error} error + * @param {!Array.<!IndexedDBAgent.DataEntry>} dataEntries + * @param {boolean} hasMore + * @this {WebInspector.IndexedDBModel} + */ + 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.fromLocalObject(JSON.parse(dataEntries[i].key)); + var primaryKey = WebInspector.RemoteObject.fromLocalObject(JSON.parse(dataEntries[i].primaryKey)); + var value = WebInspector.RemoteObject.fromLocalObject(JSON.parse(dataEntries[i].value)); + entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value)); + } + callback(entries, hasMore); + } + + var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange); + this._agent.requestData(databaseId.securityOrigin, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback.bind(this)); + }, + + __proto__: WebInspector.TargetAwareObject.prototype +} + +/** + * @constructor + * @param {!WebInspector.RemoteObject} key + * @param {!WebInspector.RemoteObject} primaryKey + * @param {!WebInspector.RemoteObject} value + */ +WebInspector.IndexedDBModel.Entry = function(key, primaryKey, value) +{ + this.key = key; + this.primaryKey = primaryKey; + this.value = value; +} + +/** + * @constructor + * @param {string} securityOrigin + * @param {string} name + */ +WebInspector.IndexedDBModel.DatabaseId = function(securityOrigin, name) +{ + this.securityOrigin = securityOrigin; + this.name = name; +} + +WebInspector.IndexedDBModel.DatabaseId.prototype = { + /** + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + * @return {boolean} + */ + equals: function(databaseId) + { + return this.name === databaseId.name && this.securityOrigin === databaseId.securityOrigin; + }, +} +/** + * @constructor + * @param {!WebInspector.IndexedDBModel.DatabaseId} databaseId + * @param {string} version + * @param {number} intVersion + */ +WebInspector.IndexedDBModel.Database = function(databaseId, version, intVersion) +{ + this.databaseId = databaseId; + this.version = version; + this.intVersion = intVersion; + this.objectStores = {}; +} + +/** + * @constructor + * @param {string} name + * @param {*} keyPath + * @param {boolean} autoIncrement + */ +WebInspector.IndexedDBModel.ObjectStore = function(name, keyPath, autoIncrement) +{ + this.name = name; + this.keyPath = keyPath; + this.autoIncrement = autoIncrement; + this.indexes = {}; +} + +WebInspector.IndexedDBModel.ObjectStore.prototype = { + /** + * @type {string} + */ + get keyPathString() + { + return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath); + } +} + +/** + * @constructor + * @param {string} name + * @param {*} keyPath + * @param {boolean} unique + * @param {boolean} multiEntry + */ +WebInspector.IndexedDBModel.Index = function(name, keyPath, unique, multiEntry) +{ + this.name = name; + this.keyPath = keyPath; + this.unique = unique; + this.multiEntry = multiEntry; +} + +WebInspector.IndexedDBModel.Index.prototype = { + /** + * @type {string} + */ + get keyPathString() + { + return WebInspector.IndexedDBModel.keyPathStringFromIDBKeyPath(this.keyPath); + } +} |