blob: 75db8468d17e47d8c10454babe8f2b360dd05aad [file] [log] [blame]
/*
* Copyright (C) 2011 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}
* @implements {WebInspector.ContentProvider}
* @param {!WebInspector.Project} project
* @param {string} parentPath
* @param {string} name
* @param {string} url
* @param {!WebInspector.ResourceType} contentType
* @param {boolean} isEditable
*/
WebInspector.UISourceCode = function(project, parentPath, name, originURL, url, contentType, isEditable)
{
this._project = project;
this._parentPath = parentPath;
this._name = name;
this._originURL = originURL;
this._url = url;
this._contentType = contentType;
this._isEditable = isEditable;
/** @type {!Array.<function(?string)>} */
this._requestContentCallbacks = [];
/** @type {!Set.<!WebInspector.LiveLocation>} */
this._liveLocations = new Set();
/** @type {!Array.<!WebInspector.PresentationConsoleMessage>} */
this._consoleMessages = [];
/** @type {!Array.<!WebInspector.Revision>} */
this.history = [];
if (this.isEditable() && this._url)
this._restoreRevisionHistory();
this._formatterMapping = new WebInspector.IdentityFormatterSourceMapping();
}
WebInspector.UISourceCode.Events = {
FormattedChanged: "FormattedChanged",
WorkingCopyChanged: "WorkingCopyChanged",
WorkingCopyCommitted: "WorkingCopyCommitted",
TitleChanged: "TitleChanged",
SavedStateUpdated: "SavedStateUpdated",
ConsoleMessageAdded: "ConsoleMessageAdded",
ConsoleMessageRemoved: "ConsoleMessageRemoved",
ConsoleMessagesCleared: "ConsoleMessagesCleared",
SourceMappingChanged: "SourceMappingChanged",
}
WebInspector.UISourceCode.prototype = {
/**
* @return {string}
*/
get url()
{
return this._url;
},
/**
* @return {string}
*/
name: function()
{
return this._name;
},
/**
* @return {string}
*/
parentPath: function()
{
return this._parentPath;
},
/**
* @return {string}
*/
path: function()
{
return this._parentPath ? this._parentPath + "/" + this._name : this._name;
},
/**
* @return {string}
*/
fullDisplayName: function()
{
return this._project.displayName() + "/" + (this._parentPath ? this._parentPath + "/" : "") + this.displayName(true);
},
/**
* @param {boolean=} skipTrim
* @return {string}
*/
displayName: function(skipTrim)
{
var displayName = this.name() || WebInspector.UIString("(index)");
return skipTrim ? displayName : displayName.trimEnd(100);
},
/**
* @return {string}
*/
uri: function()
{
var path = this.path();
if (!this._project.id())
return path;
if (!path)
return this._project.id();
return this._project.id() + "/" + path;
},
/**
* @return {string}
*/
originURL: function()
{
return this._originURL;
},
/**
* @return {boolean}
*/
canRename: function()
{
return this._project.canRename();
},
/**
* @param {string} newName
* @param {function(boolean)} callback
*/
rename: function(newName, callback)
{
this._project.rename(this, newName, innerCallback.bind(this));
/**
* @param {boolean} success
* @param {string=} newName
* @param {string=} newURL
* @param {string=} newOriginURL
* @param {!WebInspector.ResourceType=} newContentType
* @this {WebInspector.UISourceCode}
*/
function innerCallback(success, newName, newURL, newOriginURL, newContentType)
{
if (success)
this._updateName(/** @type {string} */ (newName), /** @type {string} */ (newURL), /** @type {string} */ (newOriginURL), /** @type {!WebInspector.ResourceType} */ (newContentType));
callback(success);
}
},
/**
* @param {string} name
* @param {string} url
* @param {string} originURL
* @param {!WebInspector.ResourceType=} contentType
*/
_updateName: function(name, url, originURL, contentType)
{
var oldURI = this.uri();
this._name = name;
if (url)
this._url = url;
if (originURL)
this._originURL = originURL;
if (contentType)
this._contentType = contentType;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.TitleChanged, oldURI);
},
/**
* @return {string}
*/
contentURL: function()
{
return this.originURL();
},
/**
* @return {!WebInspector.ResourceType}
*/
contentType: function()
{
return this._contentType;
},
/**
* @return {?WebInspector.ScriptFile}
*/
scriptFile: function()
{
return this._scriptFile;
},
/**
* @param {?WebInspector.ScriptFile} scriptFile
*/
setScriptFile: function(scriptFile)
{
this._scriptFile = scriptFile;
},
/**
* @return {!WebInspector.Project}
*/
project: function()
{
return this._project;
},
/**
* @param {function(?Date, ?number)} callback
*/
requestMetadata: function(callback)
{
this._project.requestMetadata(this, callback);
},
/**
* @param {function(?string)} callback
*/
requestContent: function(callback)
{
if (this._content || this._contentLoaded) {
callback(this._content);
return;
}
this._requestContentCallbacks.push(callback);
if (this._requestContentCallbacks.length === 1)
this._project.requestFileContent(this, this._fireContentAvailable.bind(this));
},
/**
* @param {function()=} callback
*/
checkContentUpdated: function(callback)
{
if (!this._project.canSetFileContent())
return;
if (this._checkingContent)
return;
this._checkingContent = true;
this._project.requestFileContent(this, contentLoaded.bind(this));
/**
* @param {?string} updatedContent
* @this {WebInspector.UISourceCode}
*/
function contentLoaded(updatedContent)
{
if (updatedContent === null) {
var workingCopy = this.workingCopy();
this._commitContent("", false);
this.setWorkingCopy(workingCopy);
delete this._checkingContent;
if (callback)
callback();
return;
}
if (typeof this._lastAcceptedContent === "string" && this._lastAcceptedContent === updatedContent) {
delete this._checkingContent;
if (callback)
callback();
return;
}
if (this._content === updatedContent) {
delete this._lastAcceptedContent;
delete this._checkingContent;
if (callback)
callback();
return;
}
if (!this.isDirty()) {
this._commitContent(updatedContent, false);
delete this._checkingContent;
if (callback)
callback();
return;
}
var shouldUpdate = window.confirm(WebInspector.UIString("This file was changed externally. Would you like to reload it?"));
if (shouldUpdate)
this._commitContent(updatedContent, false);
else
this._lastAcceptedContent = updatedContent;
delete this._checkingContent;
if (callback)
callback();
}
},
/**
* @param {function(?string)} callback
*/
requestOriginalContent: function(callback)
{
this._project.requestFileContent(this, callback);
},
/**
* @param {string} content
* @param {boolean} shouldSetContentInProject
*/
_commitContent: function(content, shouldSetContentInProject)
{
delete this._lastAcceptedContent;
this._content = content;
this._contentLoaded = true;
var lastRevision = this.history.length ? this.history[this.history.length - 1] : null;
if (!lastRevision || lastRevision._content !== this._content) {
var revision = new WebInspector.Revision(this, this._content, new Date());
this.history.push(revision);
revision._persist();
}
this._innerResetWorkingCopy();
this._hasCommittedChanges = true;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCopyCommitted);
if (this._url && WebInspector.fileManager.isURLSaved(this._url))
this._saveURLWithFileManager(false, this._content);
if (shouldSetContentInProject)
this._project.setFileContent(this, this._content, function() { });
},
/**
* @param {boolean} forceSaveAs
* @param {?string} content
*/
_saveURLWithFileManager: function(forceSaveAs, content)
{
WebInspector.fileManager.save(this._url, content, forceSaveAs, callback.bind(this));
WebInspector.fileManager.close(this._url);
/**
* @param {boolean} accepted
* @this {WebInspector.UISourceCode}
*/
function callback(accepted)
{
if (!accepted)
return;
this._savedWithFileManager = true;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.SavedStateUpdated);
}
},
/**
* @param {boolean} forceSaveAs
*/
saveToFileSystem: function(forceSaveAs)
{
if (this.isDirty()) {
this._saveURLWithFileManager(forceSaveAs, this.workingCopy());
this.commitWorkingCopy(function() { });
return;
}
this.requestContent(this._saveURLWithFileManager.bind(this, forceSaveAs));
},
/**
* @return {boolean}
*/
hasUnsavedCommittedChanges: function()
{
if (this._savedWithFileManager || this.project().canSetFileContent() || !this._isEditable)
return false;
if (WebInspector.extensionServer.hasSubscribers(WebInspector.extensionAPI.Events.ResourceContentCommitted))
return false;
return !!this._hasCommittedChanges;
},
/**
* @param {string} content
*/
addRevision: function(content)
{
this._commitContent(content, true);
},
_restoreRevisionHistory: function()
{
if (!window.localStorage)
return;
var registry = WebInspector.Revision._revisionHistoryRegistry();
var historyItems = registry[this.url];
if (!historyItems)
return;
function filterOutStale(historyItem)
{
// FIXME: Main frame might not have been loaded yet when uiSourceCodes for snippets are created.
if (!WebInspector.resourceTreeModel.mainFrame)
return false;
return historyItem.loaderId === WebInspector.resourceTreeModel.mainFrame.loaderId;
}
historyItems = historyItems.filter(filterOutStale);
if (!historyItems.length)
return;
for (var i = 0; i < historyItems.length; ++i) {
var content = window.localStorage[historyItems[i].key];
var timestamp = new Date(historyItems[i].timestamp);
var revision = new WebInspector.Revision(this, content, timestamp);
this.history.push(revision);
}
this._content = this.history[this.history.length - 1].content;
this._hasCommittedChanges = true;
this._contentLoaded = true;
},
_clearRevisionHistory: function()
{
if (!window.localStorage)
return;
var registry = WebInspector.Revision._revisionHistoryRegistry();
var historyItems = registry[this.url];
for (var i = 0; historyItems && i < historyItems.length; ++i)
delete window.localStorage[historyItems[i].key];
delete registry[this.url];
window.localStorage["revision-history"] = JSON.stringify(registry);
},
revertToOriginal: function()
{
/**
* @this {WebInspector.UISourceCode}
* @param {?string} content
*/
function callback(content)
{
if (typeof content !== "string")
return;
this.addRevision(content);
}
this.requestOriginalContent(callback.bind(this));
WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
action: WebInspector.UserMetrics.UserActionNames.ApplyOriginalContent,
url: this.url
});
},
/**
* @param {function(!WebInspector.UISourceCode)} callback
*/
revertAndClearHistory: function(callback)
{
/**
* @this {WebInspector.UISourceCode}
* @param {?string} content
*/
function revert(content)
{
if (typeof content !== "string")
return;
this.addRevision(content);
this._clearRevisionHistory();
this.history = [];
callback(this);
}
this.requestOriginalContent(revert.bind(this));
WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
action: WebInspector.UserMetrics.UserActionNames.RevertRevision,
url: this.url
});
},
/**
* @return {boolean}
*/
isEditable: function()
{
return this._isEditable;
},
/**
* @return {string}
*/
workingCopy: function()
{
if (this._workingCopyGetter) {
this._workingCopy = this._workingCopyGetter();
delete this._workingCopyGetter;
}
if (this.isDirty())
return this._workingCopy;
return this._content;
},
resetWorkingCopy: function()
{
this._innerResetWorkingCopy();
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCopyChanged);
},
_innerResetWorkingCopy: function()
{
delete this._workingCopy;
delete this._workingCopyGetter;
},
/**
* @param {string} newWorkingCopy
*/
setWorkingCopy: function(newWorkingCopy)
{
this._workingCopy = newWorkingCopy;
delete this._workingCopyGetter;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCopyChanged);
},
setWorkingCopyGetter: function(workingCopyGetter)
{
this._workingCopyGetter = workingCopyGetter;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.WorkingCopyChanged);
},
removeWorkingCopyGetter: function()
{
if (!this._workingCopyGetter)
return;
this._workingCopy = this._workingCopyGetter();
delete this._workingCopyGetter;
},
/**
* @param {function(?string)} callback
*/
commitWorkingCopy: function(callback)
{
if (!this.isDirty()) {
callback(null);
return;
}
this._commitContent(this.workingCopy(), true);
callback(null);
WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
action: WebInspector.UserMetrics.UserActionNames.FileSaved,
url: this.url
});
},
/**
* @return {boolean}
*/
isDirty: function()
{
return typeof this._workingCopy !== "undefined" || typeof this._workingCopyGetter !== "undefined";
},
/**
* @return {string}
*/
_mimeType: function()
{
return this.contentType().canonicalMimeType();
},
/**
* @return {string}
*/
highlighterType: function()
{
var lastIndexOfDot = this._name.lastIndexOf(".");
var extension = lastIndexOfDot !== -1 ? this._name.substr(lastIndexOfDot + 1) : "";
var indexOfQuestionMark = extension.indexOf("?");
if (indexOfQuestionMark !== -1)
extension = extension.substr(0, indexOfQuestionMark);
var mimeType = WebInspector.ResourceType.mimeTypesForExtensions[extension.toLowerCase()];
return mimeType || this.contentType().canonicalMimeType();
},
/**
* @return {?string}
*/
content: function()
{
return this._content;
},
/**
* @param {string} query
* @param {boolean} caseSensitive
* @param {boolean} isRegex
* @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
*/
searchInContent: function(query, caseSensitive, isRegex, callback)
{
var content = this.content();
if (content) {
var provider = new WebInspector.StaticContentProvider(this.contentType(), content);
provider.searchInContent(query, caseSensitive, isRegex, callback);
return;
}
this._project.searchInFileContent(this, query, caseSensitive, isRegex, callback);
},
/**
* @param {?string} content
*/
_fireContentAvailable: function(content)
{
this._contentLoaded = true;
this._content = content;
var callbacks = this._requestContentCallbacks.slice();
this._requestContentCallbacks = [];
for (var i = 0; i < callbacks.length; ++i)
callbacks[i](content);
if (this._formatOnLoad) {
delete this._formatOnLoad;
this.setFormatted(true);
}
},
/**
* @return {boolean}
*/
contentLoaded: function()
{
return this._contentLoaded;
},
/**
* @param {number} lineNumber
* @param {number} columnNumber
* @return {?WebInspector.RawLocation}
*/
uiLocationToRawLocation: function(lineNumber, columnNumber)
{
if (!this._sourceMapping)
return null;
var location = this._formatterMapping.formattedToOriginal(lineNumber, columnNumber);
return this._sourceMapping.uiLocationToRawLocation(this, location[0], location[1]);
},
/**
* @param {!WebInspector.LiveLocation} liveLocation
*/
addLiveLocation: function(liveLocation)
{
this._liveLocations.add(liveLocation);
},
/**
* @param {!WebInspector.LiveLocation} liveLocation
*/
removeLiveLocation: function(liveLocation)
{
this._liveLocations.remove(liveLocation);
},
updateLiveLocations: function()
{
var items = this._liveLocations.items();
for (var i = 0; i < items.length; ++i)
items[i].update();
},
/**
* @param {!WebInspector.UILocation} uiLocation
*/
overrideLocation: function(uiLocation)
{
var location = this._formatterMapping.originalToFormatted(uiLocation.lineNumber, uiLocation.columnNumber);
uiLocation.lineNumber = location[0];
uiLocation.columnNumber = location[1];
return uiLocation;
},
/**
* @return {!Array.<!WebInspector.PresentationConsoleMessage>}
*/
consoleMessages: function()
{
return this._consoleMessages;
},
/**
* @param {!WebInspector.PresentationConsoleMessage} message
*/
consoleMessageAdded: function(message)
{
this._consoleMessages.push(message);
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMessageAdded, message);
},
/**
* @param {!WebInspector.PresentationConsoleMessage} message
*/
consoleMessageRemoved: function(message)
{
this._consoleMessages.remove(message);
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMessageRemoved, message);
},
consoleMessagesCleared: function()
{
this._consoleMessages = [];
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMessagesCleared);
},
/**
* @return {boolean}
*/
formatted: function()
{
return !!this._formatted;
},
/**
* @param {boolean} formatted
*/
setFormatted: function(formatted)
{
if (!this.contentLoaded()) {
this._formatOnLoad = formatted;
return;
}
if (this._formatted === formatted)
return;
if (this.isDirty())
return;
this._formatted = formatted;
// Re-request content
this._contentLoaded = false;
this._content = false;
this.requestContent(didGetContent.bind(this));
/**
* @this {WebInspector.UISourceCode}
* @param {?string} content
*/
function didGetContent(content)
{
var formatter;
if (!formatted)
formatter = new WebInspector.IdentityFormatter();
else
formatter = WebInspector.Formatter.createFormatter(this.contentType());
formatter.formatContent(this.highlighterType(), content || "", formattedChanged.bind(this));
/**
* @this {WebInspector.UISourceCode}
* @param {string} content
* @param {!WebInspector.FormatterSourceMapping} formatterMapping
*/
function formattedChanged(content, formatterMapping)
{
this._content = content;
this._innerResetWorkingCopy();
var oldFormatter = this._formatterMapping;
this._formatterMapping = formatterMapping;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.FormattedChanged, {
content: content,
oldFormatter: oldFormatter,
newFormatter: this._formatterMapping,
});
this.updateLiveLocations();
}
}
},
/**
* @return {?WebInspector.Formatter} formatter
*/
createFormatter: function()
{
// overridden by subclasses.
return null;
},
/**
* @return {boolean}
*/
hasSourceMapping: function()
{
return !!this._sourceMapping;
},
/**
* @param {?WebInspector.SourceMapping} sourceMapping
*/
setSourceMapping: function(sourceMapping)
{
if (this._sourceMapping === sourceMapping)
return;
this._sourceMapping = sourceMapping;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.SourceMappingChanged);
},
__proto__: WebInspector.Object.prototype
}
/**
* @constructor
* @param {!WebInspector.UISourceCode} uiSourceCode
* @param {number} lineNumber
* @param {number} columnNumber
*/
WebInspector.UILocation = function(uiSourceCode, lineNumber, columnNumber)
{
this.uiSourceCode = uiSourceCode;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}
WebInspector.UILocation.prototype = {
/**
* @return {?WebInspector.RawLocation}
*/
uiLocationToRawLocation: function()
{
return this.uiSourceCode.uiLocationToRawLocation(this.lineNumber, this.columnNumber);
},
/**
* @return {?string}
*/
url: function()
{
return this.uiSourceCode.contentURL();
},
/**
* @return {string}
*/
linkText: function()
{
var linkText = this.uiSourceCode.displayName();
if (typeof this.lineNumber === "number")
linkText += ":" + (this.lineNumber + 1);
return linkText;
}
}
/**
* @interface
*/
WebInspector.RawLocation = function()
{
}
/**
* @constructor
* @param {!WebInspector.RawLocation} rawLocation
* @param {function(!WebInspector.UILocation):(boolean|undefined)} updateDelegate
*/
WebInspector.LiveLocation = function(rawLocation, updateDelegate)
{
this._rawLocation = rawLocation;
this._updateDelegate = updateDelegate;
this._uiSourceCodes = [];
}
WebInspector.LiveLocation.prototype = {
update: function()
{
var uiLocation = this.uiLocation();
if (uiLocation) {
var uiSourceCode = uiLocation.uiSourceCode;
if (this._uiSourceCodes.indexOf(uiSourceCode) === -1) {
uiSourceCode.addLiveLocation(this);
this._uiSourceCodes.push(uiSourceCode);
}
var oneTime = this._updateDelegate(uiLocation);
if (oneTime)
this.dispose();
}
},
/**
* @return {!WebInspector.RawLocation}
*/
rawLocation: function()
{
return this._rawLocation;
},
/**
* @return {!WebInspector.UILocation}
*/
uiLocation: function()
{
// Should be overridden by subclasses.
},
dispose: function()
{
for (var i = 0; i < this._uiSourceCodes.length; ++i)
this._uiSourceCodes[i].removeLiveLocation(this);
this._uiSourceCodes = [];
}
}
/**
* @constructor
* @implements {WebInspector.ContentProvider}
* @param {!WebInspector.UISourceCode} uiSourceCode
* @param {?string|undefined} content
* @param {!Date} timestamp
*/
WebInspector.Revision = function(uiSourceCode, content, timestamp)
{
this._uiSourceCode = uiSourceCode;
this._content = content;
this._timestamp = timestamp;
}
WebInspector.Revision._revisionHistoryRegistry = function()
{
if (!WebInspector.Revision._revisionHistoryRegistryObject) {
if (window.localStorage) {
var revisionHistory = window.localStorage["revision-history"];
try {
WebInspector.Revision._revisionHistoryRegistryObject = revisionHistory ? JSON.parse(revisionHistory) : {};
} catch (e) {
WebInspector.Revision._revisionHistoryRegistryObject = {};
}
} else
WebInspector.Revision._revisionHistoryRegistryObject = {};
}
return WebInspector.Revision._revisionHistoryRegistryObject;
}
WebInspector.Revision.filterOutStaleRevisions = function()
{
if (!window.localStorage)
return;
var registry = WebInspector.Revision._revisionHistoryRegistry();
var filteredRegistry = {};
for (var url in registry) {
var historyItems = registry[url];
var filteredHistoryItems = [];
for (var i = 0; historyItems && i < historyItems.length; ++i) {
var historyItem = historyItems[i];
if (historyItem.loaderId === WebInspector.resourceTreeModel.mainFrame.loaderId) {
filteredHistoryItems.push(historyItem);
filteredRegistry[url] = filteredHistoryItems;
} else
delete window.localStorage[historyItem.key];
}
}
WebInspector.Revision._revisionHistoryRegistryObject = filteredRegistry;
function persist()
{
window.localStorage["revision-history"] = JSON.stringify(filteredRegistry);
}
// Schedule async storage.
setTimeout(persist, 0);
}
WebInspector.Revision.prototype = {
/**
* @return {!WebInspector.UISourceCode}
*/
get uiSourceCode()
{
return this._uiSourceCode;
},
/**
* @return {!Date}
*/
get timestamp()
{
return this._timestamp;
},
/**
* @return {?string}
*/
get content()
{
return this._content || null;
},
revertToThis: function()
{
/**
* @param {string} content
* @this {WebInspector.Revision}
*/
function revert(content)
{
if (this._uiSourceCode._content !== content)
this._uiSourceCode.addRevision(content);
}
this.requestContent(revert.bind(this));
},
/**
* @return {string}
*/
contentURL: function()
{
return this._uiSourceCode.originURL();
},
/**
* @return {!WebInspector.ResourceType}
*/
contentType: function()
{
return this._uiSourceCode.contentType();
},
/**
* @param {function(string)} callback
*/
requestContent: function(callback)
{
callback(this._content || "");
},
/**
* @param {string} query
* @param {boolean} caseSensitive
* @param {boolean} isRegex
* @param {function(!Array.<!WebInspector.ContentProvider.SearchMatch>)} callback
*/
searchInContent: function(query, caseSensitive, isRegex, callback)
{
callback([]);
},
_persist: function()
{
if (this._uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem)
return;
if (!window.localStorage)
return;
var url = this.contentURL();
if (!url || url.startsWith("inspector://"))
return;
var loaderId = WebInspector.resourceTreeModel.mainFrame.loaderId;
var timestamp = this.timestamp.getTime();
var key = "revision-history|" + url + "|" + loaderId + "|" + timestamp;
var registry = WebInspector.Revision._revisionHistoryRegistry();
var historyItems = registry[url];
if (!historyItems) {
historyItems = [];
registry[url] = historyItems;
}
historyItems.push({url: url, loaderId: loaderId, timestamp: timestamp, key: key});
/**
* @this {WebInspector.Revision}
*/
function persist()
{
window.localStorage[key] = this._content;
window.localStorage["revision-history"] = JSON.stringify(registry);
}
// Schedule async storage.
setTimeout(persist.bind(this), 0);
}
}