 Chromium Code Reviews
 Chromium Code Reviews Issue 1663723002:
  [DevTools] Add sourceMap support for blackboxing  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@call-set-blackboxed-ranges-on-script-parsed
    
  
    Issue 1663723002:
  [DevTools] Add sourceMap support for blackboxing  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@call-set-blackboxed-ranges-on-script-parsed| 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..b4bce4e97e3d414e14c520486e206aa03cfa1f0f | 
| --- /dev/null | 
| +++ b/third_party/WebKit/Source/devtools/front_end/bindings/BlackboxManager.js | 
| @@ -0,0 +1,314 @@ | 
| +// 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 | 
| + */ | 
| +WebInspector.BlackboxManager = function() | 
| +{ | 
| + WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this); | 
| + WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._patternChanged.bind(this)); | 
| + WebInspector.moduleSetting("skipContentScripts").addChangeListener(this._patternChanged.bind(this)); | 
| + | 
| + /** @type {!Map<string, string>} */ | 
| + this._scripts = new Map(); | 
| 
dgozman
2016/02/09 23:44:50
Clean this up on GlobalObjectCleared.
 
dgozman
2016/02/09 23:44:50
Store blackbox ranges per script instead.
 
kozy
2016/02/10 01:19:41
Done.
 
kozy
2016/02/10 01:19:41
Done.
 | 
| + /** @type {!Map<string, boolean>} */ | 
| + this._isBlackboxedURLCache = new Map(); | 
| 
dgozman
2016/02/09 23:44:50
Let's clear on GlobalObjectCleared to avoid leaks.
 
kozy
2016/02/10 01:19:41
Done.
 | 
| +} | 
| + | 
| +WebInspector.BlackboxManager.ScriptState = { | 
| 
dgozman
2016/02/09 23:44:50
Make this a enum and use in JSDocs.
 
kozy
2016/02/10 01:19:41
Removed.
 | 
| + NotBlackboxed: "NotBlackboxed", | 
| + Blackboxed: "Blackboxed", | 
| + PartiallyBlackboxed: "PartiallyBlackboxed" | 
| +} | 
| + | 
| +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.Script} script | 
| + * @return {boolean} | 
| + */ | 
| + isBlackboxedScript: function(script) | 
| 
dgozman
2016/02/09 23:44:50
Remove this method, add one with rawLocation inste
 
kozy
2016/02/10 01:19:41
Done.
 | 
| + { | 
| + if (!this._scripts.has(script.scriptId)) | 
| + return false; | 
| + if (this._scripts.get(script.scriptId) !== WebInspector.BlackboxManager.ScriptState.NotBlackboxed) | 
| + return true; | 
| + return false; | 
| + }, | 
| + | 
| + /** | 
| + * @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; | 
| + }, | 
| + | 
| + /** | 
| + * @return {boolean} | 
| + */ | 
| + isBlackboxedContentScripts: function() | 
| 
dgozman
2016/02/09 23:44:50
Replace with isUISourceCodeBlackboxed.
 
kozy
2016/02/10 01:19:41
Done.
 | 
| + { | 
| + return WebInspector.moduleSetting("skipContentScripts").get(); | 
| + }, | 
| + | 
| + /** | 
| + * @param {!WebInspector.Script} script | 
| + * @param {?WebInspector.SourceMap} sourceMap | 
| + */ | 
| + sourceMapLoaded: function(script, sourceMap) | 
| + { | 
| + if (!sourceMap) | 
| + return; | 
| + if (!this._scripts.has(script.scriptId)) | 
| + return; | 
| + | 
| + var previousScriptState = this._scripts.get(script.scriptId); | 
| + console.assert(previousScriptState !== WebInspector.BlackboxManager.ScriptState.Blackboxed, "Source map is loaded for blackboxed script."); | 
| + | 
| + var mappings = sourceMap.mappings().slice(); | 
| + mappings.sort(mappingComparator); | 
| + | 
| + if (!mappings.length) { | 
| + if (previousScriptState === WebInspector.BlackboxManager.ScriptState.PartiallyBlackboxed) | 
| + script.setBlackboxedRanges([]).then(this._setScriptState.bind(this, script, WebInspector.BlackboxManager.ScriptState.NotBlackboxed)); | 
| + return; | 
| + } | 
| + | 
| + var currentBlackboxed = false; | 
| + var isBlackboxed = false; | 
| + var positions = []; | 
| + if (mappings[0].lineNumber !== 0 || mappings[0].columnNumber !== 0) { | 
| + 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; | 
| + } | 
| + | 
| + if (isBlackboxed) | 
| + script.setBlackboxedRanges(positions).then(this._setScriptState.bind(this, script, WebInspector.BlackboxManager.ScriptState.PartiallyBlackboxed)); | 
| + else | 
| + script.setBlackboxedRanges([]).then(this._setScriptState.bind(this, script, WebInspector.BlackboxManager.ScriptState.NotBlackboxed)); | 
| + /** | 
| + * @param {!WebInspector.SourceMap.Entry} a | 
| + * @param {!WebInspector.SourceMap.Entry} b | 
| + */ | 
| + 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(checkSourceMap.bind(this, script))); | 
| + } | 
| + } | 
| + Promise.all(promises).then(this._patternChangeFinished); | 
| + | 
| + /** | 
| + * @param {!WebInspector.Script} script | 
| + * @param {boolean} isBlackboxed | 
| + * @this {!WebInspector.BlackboxManager} | 
| + */ | 
| + function checkSourceMap(script, isBlackboxed) | 
| + { | 
| + if (isBlackboxed) | 
| + return; | 
| + this.sourceMapLoaded(script, this._sourceMapForScript(script)); | 
| + } | 
| + }, | 
| + | 
| + _patternChangeFinished: function() | 
| 
dgozman
2016/02/09 23:44:51
...forTests
 
kozy
2016/02/10 01:19:41
Done.
 | 
| + { | 
| 
dgozman
2016/02/09 23:44:50
// This method is sniffed in tests.
 
kozy
2016/02/10 01:19:41
Done.
 | 
| + }, | 
| + | 
| + /** | 
| + * @param {!WebInspector.Event} event | 
| + */ | 
| + _parsedScriptSource: function(event) | 
| + { | 
| + var script = /** @type {!WebInspector.Script} */ (event.data); | 
| + this._addScript(script); | 
| + }, | 
| + | 
| + /** | 
| + * @param {!WebInspector.Script} script | 
| + * @return {!Promise<boolean>} | 
| + */ | 
| + _addScript: function(script) | 
| + { | 
| + var blackboxed = this._isBlackboxedScript(script); | 
| + if (!blackboxed) | 
| + return Promise.resolve(this._setScriptState(script, WebInspector.BlackboxManager.ScriptState.NotBlackboxed)); | 
| + return script.setBlackboxedRanges([ { line: 0, column: 0 } ]).then(this._setScriptState.bind(this, script, WebInspector.BlackboxManager.ScriptState.Blackboxed)); | 
| + }, | 
| + | 
| + /** | 
| + * @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 WebInspector.debuggerWorkspaceBinding.sourceMapForScript(script); | 
| 
dgozman
2016/02/09 23:44:50
Pass it as a parameter in constructor.
 
kozy
2016/02/10 01:19:41
Done.
 | 
| + }, | 
| + | 
| + /** | 
| + * @param {!WebInspector.Script} script | 
| + * @param {string} state | 
| + * @return {boolean} | 
| + */ | 
| + _setScriptState: function(script, state) | 
| + { | 
| + this._scripts.set(script.scriptId, state); | 
| + return state !== WebInspector.BlackboxManager.ScriptState.NotBlackboxed; | 
| + }, | 
| + | 
| + /** | 
| + * @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; |