blob: 161d6d4cdf1e9b25406f6196d445b154067aa466 [file] [log] [blame]
/*
* 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.Object}
*/
WebInspector.FileSystemModel = function()
{
WebInspector.Object.call(this);
this._fileSystemsForOrigin = {};
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginAdded, this._securityOriginAdded, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginRemoved, this._securityOriginRemoved, this);
FileSystemAgent.enable();
this._reset();
}
WebInspector.FileSystemModel.prototype = {
_reset: function()
{
for (var securityOrigin in this._fileSystemsForOrigin)
this._removeOrigin(securityOrigin);
var securityOrigins = WebInspector.resourceTreeModel.securityOrigins();
for (var i = 0; i < securityOrigins.length; ++i)
this._addOrigin(securityOrigins[i]);
},
/**
* @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)
{
this._fileSystemsForOrigin[securityOrigin] = {};
var types = ["persistent", "temporary"];
for (var i = 0; i < types.length; ++i)
this._requestFileSystemRoot(securityOrigin, types[i], this._fileSystemRootReceived.bind(this, securityOrigin, types[i], this._fileSystemsForOrigin[securityOrigin]));
},
/**
* @param {string} securityOrigin
*/
_removeOrigin: function(securityOrigin)
{
for (var type in this._fileSystemsForOrigin[securityOrigin]) {
var fileSystem = this._fileSystemsForOrigin[securityOrigin][type];
delete this._fileSystemsForOrigin[securityOrigin][type];
this._fileSystemRemoved(fileSystem);
}
delete this._fileSystemsForOrigin[securityOrigin];
},
/**
* @param {string} origin
* @param {string} type
* @param {function(number, !FileSystemAgent.Entry=)} callback
*/
_requestFileSystemRoot: function(origin, type, callback)
{
/**
* @param {?Protocol.Error} error
* @param {number} errorCode
* @param {!FileSystemAgent.Entry=} backendRootEntry
*/
function innerCallback(error, errorCode, backendRootEntry)
{
if (error) {
callback(FileError.SECURITY_ERR);
return;
}
callback(errorCode, backendRootEntry);
}
FileSystemAgent.requestFileSystemRoot(origin, type, innerCallback.bind(this));
},
/**
* @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
*/
_fileSystemAdded: function(fileSystem)
{
this.dispatchEventToListeners(WebInspector.FileSystemModel.EventTypes.FileSystemAdded, fileSystem);
},
/**
* @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
*/
_fileSystemRemoved: function(fileSystem)
{
this.dispatchEventToListeners(WebInspector.FileSystemModel.EventTypes.FileSystemRemoved, fileSystem);
},
refreshFileSystemList: function()
{
this._reset();
},
/**
* @param {string} origin
* @param {string} type
* @param {!Object.<string, !WebInspector.FileSystemModel.FileSystem>} store
* @param {number} errorCode
* @param {!FileSystemAgent.Entry=} backendRootEntry
*/
_fileSystemRootReceived: function(origin, type, store, errorCode, backendRootEntry)
{
if (!errorCode && backendRootEntry && this._fileSystemsForOrigin[origin] === store) {
var fileSystem = new WebInspector.FileSystemModel.FileSystem(this, origin, type, backendRootEntry);
store[type] = fileSystem;
this._fileSystemAdded(fileSystem);
}
},
/**
* @param {!WebInspector.FileSystemModel.Directory} directory
* @param {function(number, !Array.<!WebInspector.FileSystemModel.Entry>=)} callback
*/
requestDirectoryContent: function(directory, callback)
{
this._requestDirectoryContent(directory.url, this._directoryContentReceived.bind(this, directory, callback));
},
/**
* @param {string} url
* @param {function(number, !Array.<!FileSystemAgent.Entry>=)} callback
*/
_requestDirectoryContent: function(url, callback)
{
/**
* @param {?Protocol.Error} error
* @param {number} errorCode
* @param {!Array.<!FileSystemAgent.Entry>=} backendEntries
*/
function innerCallback(error, errorCode, backendEntries)
{
if (error) {
callback(FileError.SECURITY_ERR);
return;
}
if (errorCode !== 0) {
callback(errorCode);
return;
}
callback(errorCode, backendEntries);
}
FileSystemAgent.requestDirectoryContent(url, innerCallback.bind(this));
},
/**
* @param {!WebInspector.FileSystemModel.Directory} parentDirectory
* @param {function(number, !Array.<!WebInspector.FileSystemModel.Entry>=)} callback
* @param {number} errorCode
* @param {!Array.<!FileSystemAgent.Entry>=} backendEntries
*/
_directoryContentReceived: function(parentDirectory, callback, errorCode, backendEntries)
{
if (!backendEntries) {
callback(errorCode);
return;
}
var entries = [];
for (var i = 0; i < backendEntries.length; ++i) {
if (backendEntries[i].isDirectory)
entries.push(new WebInspector.FileSystemModel.Directory(this, parentDirectory.fileSystem, backendEntries[i]));
else
entries.push(new WebInspector.FileSystemModel.File(this, parentDirectory.fileSystem, backendEntries[i]));
}
callback(errorCode, entries);
},
/**
* @param {!WebInspector.FileSystemModel.Entry} entry
* @param {function(number, !FileSystemAgent.Metadata=)} callback
*/
requestMetadata: function(entry, callback)
{
/**
* @param {?Protocol.Error} error
* @param {number} errorCode
* @param {!FileSystemAgent.Metadata=} metadata
*/
function innerCallback(error, errorCode, metadata)
{
if (error) {
callback(FileError.SECURITY_ERR);
return;
}
callback(errorCode, metadata);
}
FileSystemAgent.requestMetadata(entry.url, innerCallback.bind(this));
},
/**
* @param {!WebInspector.FileSystemModel.File} file
* @param {boolean} readAsText
* @param {number=} start
* @param {number=} end
* @param {string=} charset
* @param {function(number, string=, string=)=} callback
*/
requestFileContent: function(file, readAsText, start, end, charset, callback)
{
this._requestFileContent(file.url, readAsText, start, end, charset, callback);
},
/**
* @param {string} url
* @param {boolean} readAsText
* @param {number=} start
* @param {number=} end
* @param {string=} charset
* @param {function(number, string=, string=)=} callback
*/
_requestFileContent: function(url, readAsText, start, end, charset, callback)
{
/**
* @param {?Protocol.Error} error
* @param {number} errorCode
* @param {string=} content
* @param {string=} charset
*/
function innerCallback(error, errorCode, content, charset)
{
if (error) {
if (callback)
callback(FileError.SECURITY_ERR);
return;
}
if (callback)
callback(errorCode, content, charset);
}
FileSystemAgent.requestFileContent(url, readAsText, start, end, charset, innerCallback.bind(this));
},
/**
* @param {!WebInspector.FileSystemModel.Entry} entry
* @param {function(number)=} callback
*/
deleteEntry: function(entry, callback)
{
var fileSystemModel = this;
if (entry === entry.fileSystem.root)
this._deleteEntry(entry.url, hookFileSystemDeletion);
else
this._deleteEntry(entry.url, callback);
function hookFileSystemDeletion(errorCode)
{
callback(errorCode);
if (!errorCode)
fileSystemModel._removeFileSystem(entry.fileSystem);
}
},
/**
* @param {string} url
* @param {function(number)=} callback
*/
_deleteEntry: function(url, callback)
{
/**
* @param {?Protocol.Error} error
* @param {number} errorCode
*/
function innerCallback(error, errorCode)
{
if (error) {
if (callback)
callback(FileError.SECURITY_ERR);
return;
}
if (callback)
callback(errorCode);
}
FileSystemAgent.deleteEntry(url, innerCallback.bind(this));
},
/**
* @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
*/
_removeFileSystem: function(fileSystem)
{
var origin = fileSystem.origin;
var type = fileSystem.type;
if (this._fileSystemsForOrigin[origin] && this._fileSystemsForOrigin[origin][type]) {
delete this._fileSystemsForOrigin[origin][type];
this._fileSystemRemoved(fileSystem);
if (Object.isEmpty(this._fileSystemsForOrigin[origin]))
delete this._fileSystemsForOrigin[origin];
}
},
__proto__: WebInspector.Object.prototype
}
WebInspector.FileSystemModel.EventTypes = {
FileSystemAdded: "FileSystemAdded",
FileSystemRemoved: "FileSystemRemoved"
}
/**
* @constructor
* @param {!WebInspector.FileSystemModel} fileSystemModel
* @param {string} origin
* @param {string} type
* @param {!FileSystemAgent.Entry} backendRootEntry
*/
WebInspector.FileSystemModel.FileSystem = function(fileSystemModel, origin, type, backendRootEntry)
{
this.origin = origin;
this.type = type;
this.root = new WebInspector.FileSystemModel.Directory(fileSystemModel, this, backendRootEntry);
}
WebInspector.FileSystemModel.FileSystem.prototype = {
/**
* @type {string}
*/
get name()
{
return "filesystem:" + this.origin + "/" + this.type;
}
}
/**
* @constructor
* @param {!WebInspector.FileSystemModel} fileSystemModel
* @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
* @param {!FileSystemAgent.Entry} backendEntry
*/
WebInspector.FileSystemModel.Entry = function(fileSystemModel, fileSystem, backendEntry)
{
this._fileSystemModel = fileSystemModel;
this._fileSystem = fileSystem;
this._url = backendEntry.url;
this._name = backendEntry.name;
this._isDirectory = backendEntry.isDirectory;
}
/**
* @param {!WebInspector.FileSystemModel.Entry} x
* @param {!WebInspector.FileSystemModel.Entry} y
* @return {number}
*/
WebInspector.FileSystemModel.Entry.compare = function(x, y)
{
if (x.isDirectory != y.isDirectory)
return y.isDirectory ? 1 : -1;
return x.name.compareTo(y.name);
}
WebInspector.FileSystemModel.Entry.prototype = {
/**
* @type {!WebInspector.FileSystemModel}
*/
get fileSystemModel()
{
return this._fileSystemModel;
},
/**
* @type {!WebInspector.FileSystemModel.FileSystem}
*/
get fileSystem()
{
return this._fileSystem;
},
/**
* @type {string}
*/
get url()
{
return this._url;
},
/**
* @type {string}
*/
get name()
{
return this._name;
},
/**
* @type {boolean}
*/
get isDirectory()
{
return this._isDirectory;
},
/**
* @param {function(number, !FileSystemAgent.Metadata)} callback
*/
requestMetadata: function(callback)
{
this.fileSystemModel.requestMetadata(this, callback);
},
/**
* @param {function(number)} callback
*/
deleteEntry: function(callback)
{
this.fileSystemModel.deleteEntry(this, callback);
}
}
/**
* @constructor
* @extends {WebInspector.FileSystemModel.Entry}
* @param {!WebInspector.FileSystemModel} fileSystemModel
* @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
* @param {!FileSystemAgent.Entry} backendEntry
*/
WebInspector.FileSystemModel.Directory = function(fileSystemModel, fileSystem, backendEntry)
{
WebInspector.FileSystemModel.Entry.call(this, fileSystemModel, fileSystem, backendEntry);
}
WebInspector.FileSystemModel.Directory.prototype = {
/**
* @param {function(number, !Array.<!WebInspector.FileSystemModel.Directory>)} callback
*/
requestDirectoryContent: function(callback)
{
this.fileSystemModel.requestDirectoryContent(this, callback);
},
__proto__: WebInspector.FileSystemModel.Entry.prototype
}
/**
* @constructor
* @extends {WebInspector.FileSystemModel.Entry}
* @param {!WebInspector.FileSystemModel} fileSystemModel
* @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
* @param {!FileSystemAgent.Entry} backendEntry
*/
WebInspector.FileSystemModel.File = function(fileSystemModel, fileSystem, backendEntry)
{
WebInspector.FileSystemModel.Entry.call(this, fileSystemModel, fileSystem, backendEntry);
this._mimeType = backendEntry.mimeType;
this._resourceType = WebInspector.resourceTypes[backendEntry.resourceType];
this._isTextFile = backendEntry.isTextFile;
}
WebInspector.FileSystemModel.File.prototype = {
/**
* @type {string}
*/
get mimeType()
{
return this._mimeType;
},
/**
* @type {!WebInspector.ResourceType}
*/
get resourceType()
{
return this._resourceType;
},
/**
* @type {boolean}
*/
get isTextFile()
{
return this._isTextFile;
},
/**
* @param {boolean} readAsText
* @param {number=} start
* @param {number=} end
* @param {string=} charset
* @param {function(number, string=)=} callback
*/
requestFileContent: function(readAsText, start, end, charset, callback)
{
this.fileSystemModel.requestFileContent(this, readAsText, start, end, charset, callback);
},
__proto__: WebInspector.FileSystemModel.Entry.prototype
}