Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Unified Diff: third_party/WebKit/Source/devtools/front_end/bindings/BlackboxManager.js

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
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;

Powered by Google App Engine
This is Rietveld 408576698