Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/bindings/BlackboxManager.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/bindings/BlackboxManager.js b/third_party/WebKit/Source/devtools/front_end/bindings/BlackboxManager.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..4fcfa0c67fda193ab15d0aa1c182e0e8b8402767 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/devtools/front_end/bindings/BlackboxManager.js |
| @@ -0,0 +1,337 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +/** |
| + * @constructor |
| + * @param {!WebInspector.DebuggerWorkspaceBinding} debuggerWorkspaceBinding |
| + * @param {!WebInspector.NetworkMapping} networkMapping |
| + */ |
| +WebInspector.BlackboxManager = function(debuggerWorkspaceBinding, networkMapping) |
| +{ |
| + this._debuggerWorkspaceBinding = debuggerWorkspaceBinding; |
| + this._networkMapping = networkMapping; |
| + |
| + WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this); |
| + WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._globalObjectCleared, this); |
| + WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._patternChanged.bind(this)); |
| + WebInspector.moduleSetting("skipContentScripts").addChangeListener(this._patternChanged.bind(this)); |
| + |
| + /** @type {!Map<string, !Array<!DebuggerAgent.ScriptPosition>>} */ |
| + this._scripts = new Map(); |
|
dgozman
2016/02/17 01:34:44
this._scriptIdToPositions
kozy
2016/02/17 03:40:42
Done.
|
| + /** @type {!Map<string, boolean>} */ |
| + this._isBlackboxedURLCache = new Map(); |
| +} |
| + |
| +WebInspector.BlackboxManager.prototype = { |
| + |
| + /** |
| + * @param {function(!WebInspector.Event)} listener |
| + * @param {!Object=} thisObject |
| + */ |
| + addChangeListener: function(listener, thisObject) |
| + { |
| + WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(listener, thisObject); |
| + }, |
| + |
| + /** |
| + * @param {function(!WebInspector.Event)} listener |
| + * @param {!Object=} thisObject |
| + */ |
| + removeChangeListener: function(listener, thisObject) |
| + { |
| + WebInspector.moduleSetting("skipStackFramesPattern").removeChangeListener(listener, thisObject); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.DebuggerModel.Location} location |
| + * @return {boolean} |
| + */ |
| + isBlackboxedRawLocation: function(location) |
| + { |
| + if (!this._scripts.has(location.scriptId)) |
| + return false; |
| + var positions = this._scripts.get(location.scriptId); |
| + var index = positions.lowerBound(location, comparator); |
| + return !!(index % 2); |
| + |
| + function comparator(a, b) |
|
dgozman
2016/02/17 01:34:44
JSDoc plesae.
kozy
2016/02/17 03:40:43
Done.
|
| + { |
| + if (a.lineNumber !== b.line) |
| + return a.lineNumber - b.line; |
| + return a.columnNumber - b.column; |
| + } |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.UISourceCode} uiSourceCode |
| + * @return {boolean} |
| + */ |
| + isBlackboxedUISourceCode: function(uiSourceCode) |
| + { |
| + var projectType = uiSourceCode.project().type(); |
| + var isContentScript = projectType === WebInspector.projectTypes.ContentScripts; |
| + if (isContentScript && WebInspector.moduleSetting("skipContentScripts").get()) |
| + return true; |
| + var networkURL = this._networkMapping.networkURL(uiSourceCode); |
| + var url = projectType === WebInspector.projectTypes.Formatter ? uiSourceCode.url() : networkURL; |
| + return this.isBlackboxedURL(url); |
| + }, |
| + |
| + /** |
| + * @param {string} url |
| + * @return {boolean} |
| + */ |
| + isBlackboxedURL: function(url) |
| + { |
| + if (this._isBlackboxedURLCache.has(url)) |
| + return !!this._isBlackboxedURLCache.get(url); |
| + var regex = WebInspector.moduleSetting("skipStackFramesPattern").asRegExp(); |
| + var isBlackboxed = regex && regex.test(url); |
| + this._isBlackboxedURLCache.set(url, isBlackboxed); |
| + return isBlackboxed; |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Script} script |
| + * @param {?WebInspector.SourceMap} sourceMap |
| + */ |
| + sourceMapLoaded: function(script, sourceMap) |
| + { |
| + if (!sourceMap) |
| + return; |
| + if (!this._scripts.has(script.scriptId)) |
| + return; |
| + |
| + var mappings = sourceMap.mappings().slice(); |
| + mappings.sort(mappingComparator); |
| + |
| + var previousScriptState = this._scripts.get(script.scriptId); |
| + if (!mappings.length) { |
| + if (previousScriptState.length > 0) |
| + script.setBlackboxedRanges([]).then(this._setScriptState.bind(this, script)); |
| + return; |
| + } |
| + |
| + var currentBlackboxed = false; |
| + var isBlackboxed = false; |
| + var positions = []; |
| + if (mappings[0].lineNumber !== 0 || mappings[0].columnNumber !== 0) { |
|
dgozman
2016/02/17 01:34:44
Let's add a comment.
kozy
2016/02/17 03:40:43
Done.
|
| + positions.push({ line: 0, column: 0}); |
| + currentBlackboxed = true; |
| + } |
| + for (var mapping of sourceMap.mappings()) { |
| + if (currentBlackboxed !== this.isBlackboxedURL(mapping.sourceURL)) { |
| + positions.push({ line: mapping.lineNumber, column: mapping.columnNumber }); |
| + currentBlackboxed = !currentBlackboxed; |
| + } |
| + if (currentBlackboxed) |
| + isBlackboxed = true; |
| + } |
| + |
| + var isChanged = previousScriptState.length !== positions.length; |
| + for (var i = 0; !isChanged && i < positions.length; ++i) |
| + isChanged = positions[i].line !== previousScriptState[i].line || positions[i].column !== previousScriptState[i].column; |
| + if (!isChanged) |
|
dgozman
2016/02/17 01:34:44
hasChanged
kozy
2016/02/17 03:40:42
Done.
|
| + return; |
| + |
| + if (isBlackboxed) |
|
dgozman
2016/02/17 01:34:44
Can we get rid of this flag?
kozy
2016/02/17 03:40:42
We can't rid of this because when positions.length
|
| + script.setBlackboxedRanges(positions).then(this._setScriptState.bind(this, script)); |
| + else |
| + script.setBlackboxedRanges([]).then(this._setScriptState.bind(this, script)); |
| + /** |
| + * @param {!WebInspector.SourceMap.Entry} a |
| + * @param {!WebInspector.SourceMap.Entry} b |
|
dgozman
2016/02/17 01:34:44
@return {number}
kozy
2016/02/17 03:40:43
Done.
|
| + */ |
| + function mappingComparator(a, b) |
| + { |
| + if (a.lineNumber !== b.lineNumber) |
| + return a.lineNumber - b.lineNumber; |
| + return a.columnNumber - b.columnNumber; |
| + } |
| + }, |
| + |
| + /** |
| + * @param {string} url |
| + * @return {boolean} |
| + */ |
| + canBlackboxURL: function(url) |
| + { |
| + return !!this._urlToRegExpString(url); |
| + }, |
| + |
| + /** |
| + * @param {string} url |
| + */ |
| + blackboxURL: function(url) |
| + { |
| + var regexPatterns = WebInspector.moduleSetting("skipStackFramesPattern").getAsArray(); |
| + var regexValue = this._urlToRegExpString(url); |
| + if (!regexValue) |
| + return; |
| + var found = false; |
| + for (var i = 0; i < regexPatterns.length; ++i) { |
| + var item = regexPatterns[i]; |
| + if (item.pattern === regexValue) { |
| + item.disabled = false; |
| + found = true; |
| + break; |
| + } |
| + } |
| + if (!found) |
| + regexPatterns.push({ pattern: regexValue }); |
| + WebInspector.moduleSetting("skipStackFramesPattern").setAsArray(regexPatterns); |
| + }, |
| + |
| + /** |
| + * @param {string} url |
| + * @param {boolean} isContentScript |
| + */ |
| + unblackbox: function(url, isContentScript) |
| + { |
| + if (isContentScript) |
| + WebInspector.moduleSetting("skipContentScripts").set(false); |
| + |
| + var regexPatterns = WebInspector.moduleSetting("skipStackFramesPattern").getAsArray(); |
| + var regexValue = WebInspector.blackboxManager._urlToRegExpString(url); |
| + if (!regexValue) |
| + return; |
| + regexPatterns = regexPatterns.filter(function(item) { |
| + return item.pattern !== regexValue; |
| + }); |
| + for (var i = 0; i < regexPatterns.length; ++i) { |
| + var item = regexPatterns[i]; |
| + if (item.disabled) |
| + continue; |
| + try { |
| + var regex = new RegExp(item.pattern); |
| + if (regex.test(url)) |
| + item.disabled = true; |
| + } catch (e) { |
| + } |
| + } |
| + WebInspector.moduleSetting("skipStackFramesPattern").setAsArray(regexPatterns); |
| + }, |
| + |
| + _patternChanged: function() |
| + { |
| + this._isBlackboxedURLCache.clear(); |
| + this._scripts.clear(); |
| + |
| + var promises = []; |
| + for (var debuggerModel of WebInspector.DebuggerModel.instances()) { |
| + for (var scriptId in debuggerModel.scripts) { |
| + var script = debuggerModel.scripts[scriptId]; |
| + promises.push(this._addScript(script).then(loadSourceMap.bind(this, script))); |
|
dgozman
2016/02/17 01:34:44
this._addScript(script)
.then(() => this._sour
kozy
2016/02/17 03:40:42
Done.
|
| + } |
| + } |
| + Promise.all(promises).then(this._patternChangeFinishedForTests); |
| + |
| + /** |
| + * @param {!WebInspector.Script} script |
| + * @this {!WebInspector.BlackboxManager} |
| + */ |
| + function loadSourceMap(script) |
| + { |
| + this.sourceMapLoaded(script, this._sourceMapForScript(script)); |
| + } |
| + }, |
| + |
| + // This method is sniffed in tests. |
| + _patternChangeFinishedForTests: function() |
| + { |
| + }, |
| + |
| + _globalObjectCleared: function() |
| + { |
| + this._scripts.clear(); |
| + this._isBlackboxedURLCache.clear(); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Event} event |
| + */ |
| + _parsedScriptSource: function(event) |
| + { |
| + var script = /** @type {!WebInspector.Script} */ (event.data); |
| + this._addScript(script); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Script} script |
| + * @return {!Promise<undefined>} |
| + */ |
| + _addScript: function(script) |
| + { |
| + var blackboxed = this._isBlackboxedScript(script); |
| + if (!blackboxed) |
| + return Promise.resolve(this._setScriptState(script, [])); |
| + return script.setBlackboxedRanges([ { line: 0, column: 0 } ]).then(this._setScriptState.bind(this, script)); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Script} script |
| + * @return {boolean} |
| + */ |
| + _isBlackboxedScript: function(script) |
| + { |
| + if (script.isContentScript() && WebInspector.moduleSetting("skipContentScripts").get()) |
| + return true; |
| + return this.isBlackboxedURL(script.sourceURL); |
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Script} script |
| + * @return {?WebInspector.SourceMap} |
| + */ |
| + _sourceMapForScript: function(script) |
| + { |
| + return this._debuggerWorkspaceBinding.sourceMapForScript(script); |
|
dgozman
2016/02/17 01:34:44
Inline it!
kozy
2016/02/17 03:40:43
Done.
|
| + }, |
| + |
| + /** |
| + * @param {!WebInspector.Script} script |
| + * @param {?Array<!DebuggerAgent.ScriptPosition>} positions |
| + */ |
| + _setScriptState: function(script, positions) |
| + { |
| + if (positions) |
| + this._scripts.set(script.scriptId, positions); |
| + else if (!this._scripts.has(script.scriptId)) |
| + this._scripts.set(script.scriptId, []); |
| + }, |
| + |
| + /** |
| + * @param {string} url |
| + * @return {string} |
| + */ |
| + _urlToRegExpString: function(url) |
| + { |
| + var parsedURL = new WebInspector.ParsedURL(url); |
| + if (parsedURL.isAboutBlank() || parsedURL.isDataURL()) |
| + return ""; |
| + if (!parsedURL.isValid) |
| + return "^" + url.escapeForRegExp() + "$"; |
| + var name = parsedURL.lastPathComponent; |
| + if (name) |
| + name = "/" + name; |
| + else if (parsedURL.folderPathComponents) |
| + name = parsedURL.folderPathComponents + "/"; |
| + if (!name) |
| + name = parsedURL.host; |
| + if (!name) |
| + return ""; |
| + var scheme = parsedURL.scheme; |
| + var prefix = ""; |
| + if (scheme && scheme !== "http" && scheme !== "https") { |
| + prefix = "^" + scheme + "://"; |
| + if (scheme === "chrome-extension") |
| + prefix += parsedURL.host + "\\b"; |
| + prefix += ".*"; |
| + } |
| + return prefix + name.escapeForRegExp() + (url.endsWith(name) ? "$" : "\\b"); |
| + } |
| +} |
| + |
| +/** @type {!WebInspector.BlackboxManager} */ |
| +WebInspector.blackboxManager; |