diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/devtools/front_end/SASSSourceMapping.js')
-rw-r--r-- | chromium/third_party/WebKit/Source/devtools/front_end/SASSSourceMapping.js | 609 |
1 files changed, 0 insertions, 609 deletions
diff --git a/chromium/third_party/WebKit/Source/devtools/front_end/SASSSourceMapping.js b/chromium/third_party/WebKit/Source/devtools/front_end/SASSSourceMapping.js deleted file mode 100644 index 467b77e858e..00000000000 --- a/chromium/third_party/WebKit/Source/devtools/front_end/SASSSourceMapping.js +++ /dev/null @@ -1,609 +0,0 @@ -/* - * 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 - * @implements {WebInspector.SourceMapping} - * @param {!WebInspector.CSSStyleModel} cssModel - * @param {!WebInspector.Workspace} workspace - * @param {!WebInspector.SimpleWorkspaceProvider} networkWorkspaceProvider - */ -WebInspector.SASSSourceMapping = function(cssModel, workspace, networkWorkspaceProvider) -{ - this.pollPeriodMs = 5000; - this.pollIntervalMs = 200; - - this._cssModel = cssModel; - this._workspace = workspace; - this._networkWorkspaceProvider = networkWorkspaceProvider; - this._addingRevisionCounter = 0; - this._reset(); - WebInspector.fileManager.addEventListener(WebInspector.FileManager.EventTypes.SavedURL, this._fileSaveFinished, this); - WebInspector.settings.cssSourceMapsEnabled.addChangeListener(this._toggleSourceMapSupport, this) - this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this); - this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); - this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeContentCommitted, this._uiSourceCodeContentCommitted, this); - this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._reset, this); -} - -WebInspector.SASSSourceMapping.prototype = { - /** - * @param {!WebInspector.Event} event - */ - _styleSheetChanged: function(event) - { - var id = /** @type {!CSSAgent.StyleSheetId} */ (event.data.styleSheetId); - if (this._addingRevisionCounter) { - --this._addingRevisionCounter; - return; - } - var header = this._cssModel.styleSheetHeaderForId(id); - if (!header) - return; - - this.removeHeader(header); - }, - - /** - * @param {!WebInspector.Event} event - */ - _toggleSourceMapSupport: function(event) - { - var enabled = /** @type {boolean} */ (event.data); - var headers = this._cssModel.styleSheetHeaders(); - for (var i = 0; i < headers.length; ++i) { - if (enabled) - this.addHeader(headers[i]); - else - this.removeHeader(headers[i]); - } - }, - - /** - * @param {!WebInspector.Event} event - */ - _fileSaveFinished: function(event) - { - var sassURL = /** @type {string} */ (event.data); - this._sassFileSaved(sassURL, false); - }, - - /** - * @param {string} headerName - * @param {!NetworkAgent.Headers} headers - * @return {?string} - */ - _headerValue: function(headerName, headers) - { - headerName = headerName.toLowerCase(); - var value = null; - for (var name in headers) { - if (name.toLowerCase() === headerName) { - value = headers[name]; - break; - } - } - return value; - }, - - /** - * @param {!NetworkAgent.Headers} headers - * @return {?Date} - */ - _lastModified: function(headers) - { - var lastModifiedHeader = this._headerValue("last-modified", headers); - if (!lastModifiedHeader) - return null; - var lastModified = new Date(lastModifiedHeader); - if (isNaN(lastModified.getTime())) - return null; - return lastModified; - }, - - /** - * @param {!NetworkAgent.Headers} headers - * @param {string} url - * @return {?Date} - */ - _checkLastModified: function(headers, url) - { - var lastModified = this._lastModified(headers); - if (lastModified) - return lastModified; - - var etagMessage = this._headerValue("etag", headers) ? ", \"ETag\" response header found instead" : ""; - var message = String.sprintf("The \"Last-Modified\" response header is missing or invalid for %s%s. The CSS auto-reload functionality will not work correctly.", url, etagMessage); - WebInspector.log(message); - return null; - }, - - /** - * @param {string} sassURL - * @param {boolean} wasLoadedFromFileSystem - */ - _sassFileSaved: function(sassURL, wasLoadedFromFileSystem) - { - var cssURLs = this._cssURLsForSASSURL[sassURL]; - if (!cssURLs) - return; - if (!WebInspector.settings.cssReloadEnabled.get()) - return; - - var sassFile = this._workspace.uiSourceCodeForURL(sassURL); - console.assert(sassFile); - if (wasLoadedFromFileSystem) - sassFile.requestMetadata(metadataReceived.bind(this)); - else - NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFrame.id, sassURL, undefined, sassLoadedViaNetwork.bind(this)); - - /** - * @param {?Protocol.Error} error - * @param {number} statusCode - * @param {!NetworkAgent.Headers} headers - * @param {string} content - * @this {WebInspector.SASSSourceMapping} - */ - function sassLoadedViaNetwork(error, statusCode, headers, content) - { - if (error || statusCode >= 400) { - console.error("Could not load content for " + sassURL + " : " + (error || ("HTTP status code: " + statusCode))); - return; - } - var lastModified = this._checkLastModified(headers, sassURL); - if (!lastModified) - return; - metadataReceived.call(this, lastModified); - } - - /** - * @param {?Date} timestamp - * @this {WebInspector.SASSSourceMapping} - */ - function metadataReceived(timestamp) - { - if (!timestamp) - return; - - var now = Date.now(); - var deadlineMs = now + this.pollPeriodMs; - var pollData = this._pollDataForSASSURL[sassURL]; - if (pollData) { - var dataByURL = pollData.dataByURL; - for (var url in dataByURL) - clearTimeout(dataByURL[url].timer); - } - pollData = { dataByURL: {}, deadlineMs: deadlineMs, sassTimestamp: timestamp }; - this._pollDataForSASSURL[sassURL] = pollData; - for (var i = 0; i < cssURLs.length; ++i) { - pollData.dataByURL[cssURLs[i]] = { previousPoll: now }; - this._pollCallback(cssURLs[i], sassURL, false); - } - } - }, - - /** - * @param {string} cssURL - * @param {string} sassURL - * @param {boolean} stopPolling - */ - _pollCallback: function(cssURL, sassURL, stopPolling) - { - var now; - var pollData = this._pollDataForSASSURL[sassURL]; - if (!pollData) - return; - - if (stopPolling || (now = new Date().getTime()) > pollData.deadlineMs) { - delete pollData.dataByURL[cssURL]; - if (!Object.keys(pollData.dataByURL).length) - delete this._pollDataForSASSURL[sassURL]; - return; - } - var nextPoll = this.pollIntervalMs + pollData.dataByURL[cssURL].previousPoll; - var remainingTimeoutMs = Math.max(0, nextPoll - now); - pollData.dataByURL[cssURL].previousPoll = now + remainingTimeoutMs; - pollData.dataByURL[cssURL].timer = setTimeout(this._reloadCSS.bind(this, cssURL, sassURL, this._pollCallback.bind(this)), remainingTimeoutMs); - }, - - /** - * @param {string} cssURL - * @param {string} sassURL - * @param {function(string, string, boolean)} callback - */ - _reloadCSS: function(cssURL, sassURL, callback) - { - var cssUISourceCode = this._workspace.uiSourceCodeForURL(cssURL); - if (!cssUISourceCode) { - WebInspector.log(cssURL + " resource missing. Please reload the page."); - callback(cssURL, sassURL, true); - return; - } - - if (this._workspace.hasMappingForURL(sassURL)) - this._reloadCSSFromFileSystem(cssUISourceCode, sassURL, callback); - else - this._reloadCSSFromNetwork(cssUISourceCode, sassURL, callback); - }, - - /** - * @param {!WebInspector.UISourceCode} cssUISourceCode - * @param {string} sassURL - * @param {function(string, string, boolean)} callback - */ - _reloadCSSFromNetwork: function(cssUISourceCode, sassURL, callback) - { - var cssURL = cssUISourceCode.url; - var data = this._pollDataForSASSURL[sassURL]; - if (!data) { - callback(cssURL, sassURL, true); - return; - } - var headers = { "if-modified-since": new Date(data.sassTimestamp.getTime() - 1000).toUTCString() }; - NetworkAgent.loadResourceForFrontend(WebInspector.resourceTreeModel.mainFrame.id, cssURL, headers, contentLoaded.bind(this)); - - /** - * @param {?Protocol.Error} error - * @param {number} statusCode - * @param {!NetworkAgent.Headers} headers - * @param {string} content - * @this {WebInspector.SASSSourceMapping} - */ - function contentLoaded(error, statusCode, headers, content) - { - if (error || statusCode >= 400) { - console.error("Could not load content for " + cssURL + " : " + (error || ("HTTP status code: " + statusCode))); - callback(cssURL, sassURL, true); - return; - } - if (!this._pollDataForSASSURL[sassURL]) { - callback(cssURL, sassURL, true); - return; - } - if (statusCode === 304) { - callback(cssURL, sassURL, false); - return; - } - var lastModified = this._checkLastModified(headers, cssURL); - if (!lastModified) { - callback(cssURL, sassURL, true); - return; - } - if (lastModified.getTime() < data.sassTimestamp.getTime()) { - callback(cssURL, sassURL, false); - return; - } - this._updateCSSRevision(cssUISourceCode, content, sassURL, callback); - } - }, - - /** - * @param {!WebInspector.UISourceCode} cssUISourceCode - * @param {string} content - * @param {string} sassURL - * @param {function(string, string, boolean)} callback - */ - _updateCSSRevision: function(cssUISourceCode, content, sassURL, callback) - { - ++this._addingRevisionCounter; - cssUISourceCode.addRevision(content); - this._cssUISourceCodeUpdated(cssUISourceCode.url, sassURL, callback); - }, - - /** - * @param {!WebInspector.UISourceCode} cssUISourceCode - * @param {string} sassURL - * @param {function(string, string, boolean)} callback - */ - _reloadCSSFromFileSystem: function(cssUISourceCode, sassURL, callback) - { - cssUISourceCode.requestMetadata(metadataCallback.bind(this)); - - /** - * @param {?Date} timestamp - * @this {WebInspector.SASSSourceMapping} - */ - function metadataCallback(timestamp) - { - var cssURL = cssUISourceCode.url; - if (!timestamp) { - callback(cssURL, sassURL, false); - return; - } - var cssTimestamp = timestamp.getTime(); - var pollData = this._pollDataForSASSURL[sassURL]; - if (!pollData) { - callback(cssURL, sassURL, true); - return; - } - - if (cssTimestamp < pollData.sassTimestamp.getTime()) { - callback(cssURL, sassURL, false); - return; - } - - cssUISourceCode.requestOriginalContent(contentCallback.bind(this)); - - /** - * @param {?string} content - * @this {WebInspector.SASSSourceMapping} - */ - function contentCallback(content) - { - // Empty string is a valid value, null means error. - if (content === null) - return; - this._updateCSSRevision(cssUISourceCode, content, sassURL, callback); - } - } - }, - - /** - * @param {string} cssURL - * @param {string} sassURL - * @param {function(string, string, boolean)} callback - */ - _cssUISourceCodeUpdated: function(cssURL, sassURL, callback) - { - var completeSourceMapURL = this._completeSourceMapURLForCSSURL[cssURL]; - if (!completeSourceMapURL) - return; - var ids = this._cssModel.styleSheetIdsForURL(cssURL); - if (!ids) - return; - var headers = []; - for (var i = 0; i < ids.length; ++i) - headers.push(this._cssModel.styleSheetHeaderForId(ids[i])); - for (var i = 0; i < ids.length; ++i) - this._loadSourceMapAndBindUISourceCode(headers, true, completeSourceMapURL); - callback(cssURL, sassURL, true); - }, - - /** - * @param {!WebInspector.CSSStyleSheetHeader} header - */ - addHeader: function(header) - { - if (!header.sourceMapURL || !header.sourceURL || header.isInline || !WebInspector.settings.cssSourceMapsEnabled.get()) - return; - var completeSourceMapURL = WebInspector.ParsedURL.completeURL(header.sourceURL, header.sourceMapURL); - if (!completeSourceMapURL) - return; - this._completeSourceMapURLForCSSURL[header.sourceURL] = completeSourceMapURL; - this._loadSourceMapAndBindUISourceCode([header], false, completeSourceMapURL); - }, - - /** - * @param {!WebInspector.CSSStyleSheetHeader} header - */ - removeHeader: function(header) - { - var sourceURL = header.sourceURL; - if (!sourceURL || !header.sourceMapURL || header.isInline || !this._completeSourceMapURLForCSSURL[sourceURL]) - return; - delete this._sourceMapByStyleSheetURL[sourceURL]; - delete this._completeSourceMapURLForCSSURL[sourceURL]; - for (var sassURL in this._cssURLsForSASSURL) { - var urls = this._cssURLsForSASSURL[sassURL]; - urls.remove(sourceURL); - if (!urls.length) - delete this._cssURLsForSASSURL[sassURL]; - } - var completeSourceMapURL = WebInspector.ParsedURL.completeURL(sourceURL, header.sourceMapURL); - if (completeSourceMapURL) - delete this._sourceMapByURL[completeSourceMapURL]; - header.updateLocations(); - }, - - /** - * @param {!Array.<!WebInspector.CSSStyleSheetHeader>} headersWithSameSourceURL - * @param {boolean} forceRebind - * @param {string} completeSourceMapURL - */ - _loadSourceMapAndBindUISourceCode: function(headersWithSameSourceURL, forceRebind, completeSourceMapURL) - { - console.assert(headersWithSameSourceURL.length); - var sourceURL = headersWithSameSourceURL[0].sourceURL; - this._loadSourceMapForStyleSheet(completeSourceMapURL, sourceURL, forceRebind, sourceMapLoaded.bind(this)); - - /** - * @param {?WebInspector.SourceMap} sourceMap - * @this {WebInspector.SASSSourceMapping} - */ - function sourceMapLoaded(sourceMap) - { - if (!sourceMap) - return; - - this._sourceMapByStyleSheetURL[sourceURL] = sourceMap; - for (var i = 0; i < headersWithSameSourceURL.length; ++i) { - if (forceRebind) - headersWithSameSourceURL[i].updateLocations(); - else - this._bindUISourceCode(headersWithSameSourceURL[i], sourceMap); - } - } - }, - - /** - * @param {string} cssURL - * @param {string} sassURL - */ - _addCSSURLforSASSURL: function(cssURL, sassURL) - { - var cssURLs; - if (this._cssURLsForSASSURL.hasOwnProperty(sassURL)) - cssURLs = this._cssURLsForSASSURL[sassURL]; - else { - cssURLs = []; - this._cssURLsForSASSURL[sassURL] = cssURLs; - } - if (cssURLs.indexOf(cssURL) === -1) - cssURLs.push(cssURL); - }, - - /** - * @param {string} completeSourceMapURL - * @param {string} completeStyleSheetURL - * @param {boolean} forceReload - * @param {function(?WebInspector.SourceMap)} callback - */ - _loadSourceMapForStyleSheet: function(completeSourceMapURL, completeStyleSheetURL, forceReload, callback) - { - var sourceMap = this._sourceMapByURL[completeSourceMapURL]; - if (sourceMap && !forceReload) { - callback(sourceMap); - return; - } - - var pendingCallbacks = this._pendingSourceMapLoadingCallbacks[completeSourceMapURL]; - if (pendingCallbacks) { - pendingCallbacks.push(callback); - return; - } - - pendingCallbacks = [callback]; - this._pendingSourceMapLoadingCallbacks[completeSourceMapURL] = pendingCallbacks; - - WebInspector.SourceMap.load(completeSourceMapURL, completeStyleSheetURL, sourceMapLoaded.bind(this)); - - /** - * @param {?WebInspector.SourceMap} sourceMap - * @this {WebInspector.SASSSourceMapping} - */ - function sourceMapLoaded(sourceMap) - { - var callbacks = this._pendingSourceMapLoadingCallbacks[completeSourceMapURL]; - delete this._pendingSourceMapLoadingCallbacks[completeSourceMapURL]; - if (!callbacks) - return; - if (sourceMap) - this._sourceMapByURL[completeSourceMapURL] = sourceMap; - else - delete this._sourceMapByURL[completeSourceMapURL]; - for (var i = 0; i < callbacks.length; ++i) - callbacks[i](sourceMap); - } - }, - - /** - * @param {!WebInspector.CSSStyleSheetHeader} header - * @param {!WebInspector.SourceMap} sourceMap - */ - _bindUISourceCode: function(header, sourceMap) - { - header.pushSourceMapping(this); - var rawURL = header.sourceURL; - var sources = sourceMap.sources(); - for (var i = 0; i < sources.length; ++i) { - var url = sources[i]; - this._addCSSURLforSASSURL(rawURL, url); - if (!this._workspace.hasMappingForURL(url) && !this._workspace.uiSourceCodeForURL(url)) { - var contentProvider = sourceMap.sourceContentProvider(url, WebInspector.resourceTypes.Stylesheet); - this._networkWorkspaceProvider.addFileForURL(url, contentProvider, true); - } - } - }, - - /** - * @param {!WebInspector.RawLocation} rawLocation - * @return {?WebInspector.UILocation} - */ - rawLocationToUILocation: function(rawLocation) - { - var location = /** @type WebInspector.CSSLocation */ (rawLocation); - var entry; - var sourceMap = this._sourceMapByStyleSheetURL[location.url]; - if (!sourceMap) - return null; - entry = sourceMap.findEntry(location.lineNumber, location.columnNumber); - if (!entry || entry.length === 2) - return null; - var uiSourceCode = this._workspace.uiSourceCodeForURL(entry[2]); - if (!uiSourceCode) - return null; - return new WebInspector.UILocation(uiSourceCode, entry[3], entry[4]); - }, - - /** - * @param {!WebInspector.UISourceCode} uiSourceCode - * @param {number} lineNumber - * @param {number} columnNumber - * @return {!WebInspector.RawLocation} - */ - uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) - { - // FIXME: Implement this when ui -> raw mapping has clients. - return new WebInspector.CSSLocation(uiSourceCode.url || "", lineNumber, columnNumber); - }, - - /** - * @param {!WebInspector.Event} event - */ - _uiSourceCodeAdded: function(event) - { - var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); - var cssURLs = this._cssURLsForSASSURL[uiSourceCode.url]; - if (!cssURLs) - return; - for (var i = 0; i < cssURLs.length; ++i) { - var ids = this._cssModel.styleSheetIdsForURL(cssURLs[i]); - for (var j = 0; j < ids.length; ++j) { - var header = this._cssModel.styleSheetHeaderForId(ids[j]); - console.assert(header); - header.updateLocations(); - } - } - }, - - /** - * @param {!WebInspector.Event} event - */ - _uiSourceCodeContentCommitted: function(event) - { - var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode); - if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) - this._sassFileSaved(uiSourceCode.url, true); - }, - - _reset: function() - { - this._addingRevisionCounter = 0; - this._completeSourceMapURLForCSSURL = {}; - this._cssURLsForSASSURL = {}; - /** @type {!Object.<string, !Array.<function(?WebInspector.SourceMap)>>} */ - this._pendingSourceMapLoadingCallbacks = {}; - /** @type {!Object.<string, {deadlineMs: number, dataByURL: !Object.<string, !{timer: number, previousPoll: number}>}>} */ - this._pollDataForSASSURL = {}; - /** @type {!Object.<string, !WebInspector.SourceMap>} */ - this._sourceMapByURL = {}; - this._sourceMapByStyleSheetURL = {}; - } -} |