forked from adobe/brackets
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enable opening of remote(http|https) files in Brackets (adobe#14153)
* Enable opening of remote(http|https) files in Brackets * Adding jasmine tests * Hooking to QuickOpen for remote file open * Remove console statements * Address code review comments * Providing additional checks * Unifying file existense check in MRU * Include Remote file entries in MROF display list by stubbing existence check * Handle image viewer and pixel mapping
- Loading branch information
Showing
9 changed files
with
534 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
/* | ||
* Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a | ||
* copy of this software and associated documentation files (the "Software"), | ||
* to deal in the Software without restriction, including without limitation | ||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
* and/or sell copies of the Software, and to permit persons to whom the | ||
* Software is furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
* DEALINGS IN THE SOFTWARE. | ||
* | ||
*/ | ||
|
||
define(function (require, exports, module) { | ||
"use strict"; | ||
|
||
var FileSystemError = brackets.getModule("filesystem/FileSystemError"), | ||
FileSystemStats = brackets.getModule("filesystem/FileSystemStats"); | ||
|
||
var SESSION_START_TIME = new Date(); | ||
|
||
/** | ||
* Create a new file stat. See the FileSystemStats class for more details. | ||
* | ||
* @param {!string} fullPath The full path for this File. | ||
* @return {FileSystemStats} stats. | ||
*/ | ||
function _getStats(uri) { | ||
return new FileSystemStats({ | ||
isFile: true, | ||
mtime: SESSION_START_TIME.toISOString(), | ||
size: 0, | ||
realPath: uri, | ||
hash: uri | ||
}); | ||
} | ||
|
||
/** | ||
* Model for a RemoteFile. | ||
* | ||
* This class should *not* be instantiated directly. Use FileSystem.getFileForPath | ||
* | ||
* See the FileSystem class for more details. | ||
* | ||
* @constructor | ||
* @param {!string} fullPath The full path for this File. | ||
* @param {!FileSystem} fileSystem The file system associated with this File. | ||
*/ | ||
function RemoteFile(protocol, fullPath, fileSystem) { | ||
this._isFile = true; | ||
this._isDirectory = false; | ||
this._path = fullPath; | ||
this._stat = _getStats(fullPath); | ||
this._id = fullPath; | ||
this._name = fullPath.split('/').pop(); | ||
this._fileSystem = fileSystem; | ||
this.donotWatch = true; | ||
this.protocol = protocol; | ||
this.encodedPath = fullPath; | ||
} | ||
|
||
// Add "fullPath", "name", "parent", "id", "isFile" and "isDirectory" getters | ||
Object.defineProperties(RemoteFile.prototype, { | ||
"fullPath": { | ||
get: function () { return this._path; }, | ||
set: function () { throw new Error("Cannot set fullPath"); } | ||
}, | ||
"name": { | ||
get: function () { return this._name; }, | ||
set: function () { throw new Error("Cannot set name"); } | ||
}, | ||
"parentPath": { | ||
get: function () { return this._parentPath; }, | ||
set: function () { throw new Error("Cannot set parentPath"); } | ||
}, | ||
"id": { | ||
get: function () { return this._id; }, | ||
set: function () { throw new Error("Cannot set id"); } | ||
}, | ||
"isFile": { | ||
get: function () { return this._isFile; }, | ||
set: function () { throw new Error("Cannot set isFile"); } | ||
}, | ||
"isDirectory": { | ||
get: function () { return this._isDirectory; }, | ||
set: function () { throw new Error("Cannot set isDirectory"); } | ||
}, | ||
"_impl": { | ||
get: function () { return this._fileSystem._impl; }, | ||
set: function () { throw new Error("Cannot set _impl"); } | ||
} | ||
}); | ||
|
||
/** | ||
* Helpful toString for debugging and equality check purposes | ||
*/ | ||
RemoteFile.prototype.toString = function () { | ||
return "[RemoteFile " + this._path + "]"; | ||
}; | ||
|
||
/** | ||
* Returns the stats for the remote entry. | ||
* | ||
* @param {function (?string, FileSystemStats=)} callback Callback with a | ||
* FileSystemError string or FileSystemStats object. | ||
*/ | ||
RemoteFile.prototype.stat = function (callback) { | ||
if (this._stat) { | ||
callback(null, this._stat); | ||
} else { | ||
callback(FileSystemError.NOT_FOUND); | ||
} | ||
}; | ||
|
||
RemoteFile.prototype.constructor = RemoteFile; | ||
|
||
/** | ||
* Cached contents of this file. This value is nullable but should NOT be undefined. | ||
* @private | ||
* @type {?string} | ||
*/ | ||
RemoteFile.prototype._contents = null; | ||
|
||
|
||
/** | ||
* @private | ||
* @type {?string} | ||
*/ | ||
RemoteFile.prototype._encoding = "utf8"; | ||
|
||
/** | ||
* @private | ||
* @type {?bool} | ||
*/ | ||
RemoteFile.prototype._preserveBOM = false; | ||
|
||
|
||
/** | ||
* Clear any cached data for this file. Note that this explicitly does NOT | ||
* clear the file's hash. | ||
* @private | ||
*/ | ||
RemoteFile.prototype._clearCachedData = function () { | ||
// no-op | ||
}; | ||
|
||
/** | ||
* Reads a remote file. | ||
* | ||
* @param {Object=} options Currently unused. | ||
* @param {function (?string, string=, FileSystemStats=)} callback Callback that is passed the | ||
* FileSystemError string or the file's contents and its stats. | ||
*/ | ||
RemoteFile.prototype.read = function (options, callback) { | ||
if (typeof (options) === "function") { | ||
callback = options; | ||
} | ||
this._encoding = "utf8"; | ||
|
||
if (this._contents !== null && this._stat) { | ||
callback(null, this._contents, this._encoding, this._stat); | ||
return; | ||
} | ||
|
||
var self = this; | ||
$.ajax({ | ||
url: this.fullPath | ||
}) | ||
.done(function (data) { | ||
self._contents = data; | ||
callback(null, data, self._encoding, self._stat); | ||
}) | ||
.fail(function (e) { | ||
callback(FileSystemError.NOT_FOUND); | ||
}); | ||
}; | ||
|
||
/** | ||
* Write a file. | ||
* | ||
* @param {string} data Data to write. | ||
* @param {object=} options Currently unused. | ||
* @param {function (?string, FileSystemStats=)=} callback Callback that is passed the | ||
* FileSystemError string or the file's new stats. | ||
*/ | ||
RemoteFile.prototype.write = function (data, encoding, callback) { | ||
if (typeof (encoding) === "function") { | ||
callback = encoding; | ||
} | ||
callback(FileSystemError.NOT_FOUND); | ||
}; | ||
|
||
RemoteFile.prototype.exists = function (callback) { | ||
callback(null, true); | ||
}; | ||
|
||
RemoteFile.prototype.unlink = function (callback) { | ||
callback(FileSystemError.NOT_FOUND); | ||
}; | ||
|
||
RemoteFile.prototype.rename = function (newName, callback) { | ||
callback(FileSystemError.NOT_FOUND); | ||
}; | ||
|
||
RemoteFile.prototype.moveToTrash = function (callback) { | ||
callback(FileSystemError.NOT_FOUND); | ||
}; | ||
|
||
// Export this class | ||
module.exports = RemoteFile; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
* Copyright (c) 2018 - present Adobe Systems Incorporated. All rights reserved. | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a | ||
* copy of this software and associated documentation files (the "Software"), | ||
* to deal in the Software without restriction, including without limitation | ||
* the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
* and/or sell copies of the Software, and to permit persons to whom the | ||
* Software is furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
* DEALINGS IN THE SOFTWARE. | ||
* | ||
*/ | ||
|
||
define(function (require, exports, module) { | ||
"use strict"; | ||
|
||
var AppInit = brackets.getModule("utils/AppInit"), | ||
FileSystem = brackets.getModule("filesystem/FileSystem"), | ||
QuickOpen = brackets.getModule("search/QuickOpen"), | ||
PathUtils = brackets.getModule("thirdparty/path-utils/path-utils"), | ||
CommandManager = brackets.getModule("command/CommandManager"), | ||
Commands = brackets.getModule("command/Commands"), | ||
RemoteFile = require("RemoteFile"); | ||
|
||
var HTTP_PROTOCOL = "http:", | ||
HTTPS_PROTOCOL = "https:"; | ||
|
||
AppInit.htmlReady(function () { | ||
var protocolAdapter = { | ||
priority: 0, // Default priority | ||
fileImpl: RemoteFile, | ||
canRead: function (filePath) { | ||
return true; // Always claim true, we are the default adpaters | ||
} | ||
}; | ||
|
||
// Register the custom object as HTTP and HTTPS protocol adapter | ||
FileSystem.registerProtocolAdapter(HTTP_PROTOCOL, protocolAdapter); | ||
FileSystem.registerProtocolAdapter(HTTPS_PROTOCOL, protocolAdapter); | ||
|
||
// Register as quick open plugin for file URI's having HTTP:|HTTPS: protocol | ||
QuickOpen.addQuickOpenPlugin( | ||
{ | ||
name: "Remote file URI input", | ||
languageIds: [], // for all language modes | ||
search: function () { | ||
return $.Deferred().resolve([arguments[0]]); | ||
}, | ||
match: function (query) { | ||
var protocol = PathUtils.parseUrl(query).protocol; | ||
return [HTTP_PROTOCOL, HTTPS_PROTOCOL].indexOf(protocol) !== -1; | ||
}, | ||
itemFocus: function (query) { | ||
}, // no op | ||
itemSelect: function () { | ||
CommandManager.execute(Commands.FILE_OPEN, {fullPath: arguments[0]}); | ||
} | ||
} | ||
); | ||
}); | ||
|
||
}); |
Oops, something went wrong.