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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @constructor
7 * @param {!WebInspector.DebuggerWorkspaceBinding} debuggerWorkspaceBinding
8 * @param {!WebInspector.NetworkMapping} networkMapping
9 */
10 WebInspector.BlackboxManager = function(debuggerWorkspaceBinding, networkMapping )
11 {
12 this._debuggerWorkspaceBinding = debuggerWorkspaceBinding;
13 this._networkMapping = networkMapping;
14
15 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebI nspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this );
16 WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebI nspector.DebuggerModel.Events.GlobalObjectCleared, this._globalObjectCleared, th is);
17 WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this. _patternChanged.bind(this));
18 WebInspector.moduleSetting("skipContentScripts").addChangeListener(this._pat ternChanged.bind(this));
19
20 /** @type {!Map<string, !Array<!DebuggerAgent.ScriptPosition>>} */
21 this._scriptIdToPositions = new Map();
22 /** @type {!Map<string, boolean>} */
23 this._isBlackboxedURLCache = new Map();
24 }
25
26 WebInspector.BlackboxManager.prototype = {
27
28 /**
29 * @param {function(!WebInspector.Event)} listener
30 * @param {!Object=} thisObject
31 */
32 addChangeListener: function(listener, thisObject)
33 {
34 WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(l istener, thisObject);
35 },
36
37 /**
38 * @param {function(!WebInspector.Event)} listener
39 * @param {!Object=} thisObject
40 */
41 removeChangeListener: function(listener, thisObject)
42 {
43 WebInspector.moduleSetting("skipStackFramesPattern").removeChangeListene r(listener, thisObject);
44 },
45
46 /**
47 * @param {!WebInspector.DebuggerModel.Location} location
48 * @return {boolean}
49 */
50 isBlackboxedRawLocation: function(location)
51 {
52 if (!this._scriptIdToPositions.has(location.scriptId))
53 return false;
54 var positions = this._scriptIdToPositions.get(location.scriptId);
55 var index = positions.lowerBound(location, comparator);
56 return !!(index % 2);
57
58 /**
59 * @param {!WebInspector.DebuggerModel.Location} a
60 * @param {!DebuggerAgent.ScriptPosition} b
61 * @return {number}
62 */
63 function comparator(a, b)
64 {
65 if (a.lineNumber !== b.line)
66 return a.lineNumber - b.line;
67 return a.columnNumber - b.column;
68 }
69 },
70
71 /**
72 * @param {!WebInspector.UISourceCode} uiSourceCode
73 * @return {boolean}
74 */
75 isBlackboxedUISourceCode: function(uiSourceCode)
76 {
77 var projectType = uiSourceCode.project().type();
78 var isContentScript = projectType === WebInspector.projectTypes.ContentS cripts;
79 if (isContentScript && WebInspector.moduleSetting("skipContentScripts"). get())
80 return true;
81 var networkURL = this._networkMapping.networkURL(uiSourceCode);
82 var url = projectType === WebInspector.projectTypes.Formatter ? uiSource Code.url() : networkURL;
83 return this.isBlackboxedURL(url);
84 },
85
86 /**
87 * @param {string} url
88 * @return {boolean}
89 */
90 isBlackboxedURL: function(url)
91 {
92 if (this._isBlackboxedURLCache.has(url))
93 return !!this._isBlackboxedURLCache.get(url);
94 var regex = WebInspector.moduleSetting("skipStackFramesPattern").asRegEx p();
95 var isBlackboxed = regex && regex.test(url);
96 this._isBlackboxedURLCache.set(url, isBlackboxed);
97 return isBlackboxed;
98 },
99
100 /**
101 * @param {!WebInspector.Script} script
102 * @param {?WebInspector.SourceMap} sourceMap
103 * @return {!Promise<undefined>}
104 */
105 sourceMapLoaded: function(script, sourceMap)
106 {
107 if (!sourceMap)
108 return Promise.resolve();
109 if (!this._scriptIdToPositions.has(script.scriptId))
110 return Promise.resolve();
111
112 var mappings = sourceMap.mappings().slice();
113 mappings.sort(mappingComparator);
114
115 var previousScriptState = this._scriptIdToPositions.get(script.scriptId) ;
116 if (!mappings.length) {
117 if (previousScriptState.length > 0)
118 return this._setScriptState(script, []).then(this._sourceMapLoad edForTest);
119 }
120
121 var currentBlackboxed = false;
122 var isBlackboxed = false;
123 var positions = [];
124 // If content in script file begin is not mapped and one or more ranges are blackboxed then blackbox it.
125 if (mappings[0].lineNumber !== 0 || mappings[0].columnNumber !== 0) {
126 positions.push({ line: 0, column: 0});
127 currentBlackboxed = true;
128 }
129 for (var mapping of mappings) {
130 if (currentBlackboxed !== this.isBlackboxedURL(mapping.sourceURL)) {
131 positions.push({ line: mapping.lineNumber, column: mapping.colum nNumber });
132 currentBlackboxed = !currentBlackboxed;
133 }
134 isBlackboxed = currentBlackboxed || isBlackboxed;
135 }
136 return this._setScriptState(script, !isBlackboxed ? [] : positions).then (this._sourceMapLoadedForTest);
137 /**
138 * @param {!WebInspector.SourceMap.Entry} a
139 * @param {!WebInspector.SourceMap.Entry} b
140 * @return {number}
141 */
142 function mappingComparator(a, b)
143 {
144 if (a.lineNumber !== b.lineNumber)
145 return a.lineNumber - b.lineNumber;
146 return a.columnNumber - b.columnNumber;
147 }
148 },
149
150 _sourceMapLoadedForTest: function()
151 {
152 // This method is sniffed in tests.
153 },
154
155 /**
156 * @param {string} url
157 * @return {boolean}
158 */
159 canBlackboxURL: function(url)
160 {
161 return !!this._urlToRegExpString(url);
162 },
163
164 /**
165 * @param {string} url
166 */
167 blackboxURL: function(url)
168 {
169 var regexPatterns = WebInspector.moduleSetting("skipStackFramesPattern") .getAsArray();
170 var regexValue = this._urlToRegExpString(url);
171 if (!regexValue)
172 return;
173 var found = false;
174 for (var i = 0; i < regexPatterns.length; ++i) {
175 var item = regexPatterns[i];
176 if (item.pattern === regexValue) {
177 item.disabled = false;
178 found = true;
179 break;
180 }
181 }
182 if (!found)
183 regexPatterns.push({ pattern: regexValue });
184 WebInspector.moduleSetting("skipStackFramesPattern").setAsArray(regexPat terns);
185 },
186
187 /**
188 * @param {string} url
189 * @param {boolean} isContentScript
190 */
191 unblackbox: function(url, isContentScript)
192 {
193 if (isContentScript)
194 WebInspector.moduleSetting("skipContentScripts").set(false);
195
196 var regexPatterns = WebInspector.moduleSetting("skipStackFramesPattern") .getAsArray();
197 var regexValue = WebInspector.blackboxManager._urlToRegExpString(url);
198 if (!regexValue)
199 return;
200 regexPatterns = regexPatterns.filter(function(item) {
201 return item.pattern !== regexValue;
202 });
203 for (var i = 0; i < regexPatterns.length; ++i) {
204 var item = regexPatterns[i];
205 if (item.disabled)
206 continue;
207 try {
208 var regex = new RegExp(item.pattern);
209 if (regex.test(url))
210 item.disabled = true;
211 } catch (e) {
212 }
213 }
214 WebInspector.moduleSetting("skipStackFramesPattern").setAsArray(regexPat terns);
215 },
216
217 _patternChanged: function()
218 {
219 this._isBlackboxedURLCache.clear();
220
221 var promises = [];
222 for (var debuggerModel of WebInspector.DebuggerModel.instances()) {
223 for (var scriptId in debuggerModel.scripts) {
224 let script = debuggerModel.scripts[scriptId];
225 promises.push(this._addScript(script)
226 .then(() => this._debuggerWorkspaceBinding.sou rceMapForScript(script))
227 .then(loadSourceMap.bind(this, script)));
228 }
229 }
230 Promise.all(promises).then(this._patternChangeFinishedForTests);
231
232 /**
233 * @param {!WebInspector.Script} script
234 * @param {?WebInspector.SourceMap} sourceMap
235 * @return {!Promise<undefined>}
236 * @this {WebInspector.BlackboxManager}
237 */
238 function loadSourceMap(script, sourceMap)
239 {
240 return this.sourceMapLoaded(script, sourceMap);
241 }
242 },
243
244 _patternChangeFinishedForTests: function()
245 {
246 // This method is sniffed in tests.
247 },
248
249 _globalObjectCleared: function()
250 {
251 this._scriptIdToPositions.clear();
252 this._isBlackboxedURLCache.clear();
253 },
254
255 /**
256 * @param {!WebInspector.Event} event
257 */
258 _parsedScriptSource: function(event)
259 {
260 var script = /** @type {!WebInspector.Script} */ (event.data);
261 this._addScript(script);
262 },
263
264 /**
265 * @param {!WebInspector.Script} script
266 * @return {!Promise<undefined>}
267 */
268 _addScript: function(script)
269 {
270 var blackboxed = this._isBlackboxedScript(script);
271 return this._setScriptState(script, blackboxed ? [ { line: 0, column: 0 } ] : []);
272 },
273
274 /**
275 * @param {!WebInspector.Script} script
276 * @return {boolean}
277 */
278 _isBlackboxedScript: function(script)
279 {
280 if (script.isContentScript() && WebInspector.moduleSetting("skipContentS cripts").get())
281 return true;
282 return this.isBlackboxedURL(script.sourceURL);
283 },
284
285 /**
286 * @param {!WebInspector.Script} script
287 * @param {!Array<!DebuggerAgent.ScriptPosition>} positions
288 * @return {!Promise<undefined>}
289 */
290 _setScriptState: function(script, positions)
291 {
292 if (this._scriptIdToPositions.has(script.scriptId)) {
293 var hasChanged = false;
294 var previousScriptState = this._scriptIdToPositions.get(script.scrip tId);
295 hasChanged = previousScriptState.length !== positions.length;
296 for (var i = 0; !hasChanged && i < positions.length; ++i)
297 hasChanged = positions[i].line !== previousScriptState[i].line | | positions[i].column !== previousScriptState[i].column;
298 if (!hasChanged)
299 return Promise.resolve();
300 } else {
301 if (positions.length === 0)
302 return Promise.resolve().then(updateState.bind(this, false));
303 }
304
305 return script.setBlackboxedRanges(positions).then(updateState.bind(this) );
306
307 /**
308 * @param {boolean} success
309 * @this {WebInspector.BlackboxManager}
310 */
311 function updateState(success)
312 {
313 if (success)
314 this._scriptIdToPositions.set(script.scriptId, positions);
315 else if (!this._scriptIdToPositions.has(script.scriptId))
316 this._scriptIdToPositions.set(script.scriptId, []);
317 }
318 },
319
320 /**
321 * @param {string} url
322 * @return {string}
323 */
324 _urlToRegExpString: function(url)
325 {
326 var parsedURL = new WebInspector.ParsedURL(url);
327 if (parsedURL.isAboutBlank() || parsedURL.isDataURL())
328 return "";
329 if (!parsedURL.isValid)
330 return "^" + url.escapeForRegExp() + "$";
331 var name = parsedURL.lastPathComponent;
332 if (name)
333 name = "/" + name;
334 else if (parsedURL.folderPathComponents)
335 name = parsedURL.folderPathComponents + "/";
336 if (!name)
337 name = parsedURL.host;
338 if (!name)
339 return "";
340 var scheme = parsedURL.scheme;
341 var prefix = "";
342 if (scheme && scheme !== "http" && scheme !== "https") {
343 prefix = "^" + scheme + "://";
344 if (scheme === "chrome-extension")
345 prefix += parsedURL.host + "\\b";
346 prefix += ".*";
347 }
348 return prefix + name.escapeForRegExp() + (url.endsWith(name) ? "$" : "\\ b");
349 }
350 }
351
352 /** @type {!WebInspector.BlackboxManager} */
353 WebInspector.blackboxManager;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698