| OLD | NEW |
| (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._scripts = 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._scripts.has(location.scriptId)) |
| 53 return false; |
| 54 var positions = this._scripts.get(location.scriptId); |
| 55 var index = positions.lowerBound(location, comparator); |
| 56 return !!(index % 2); |
| 57 |
| 58 function comparator(a, b) |
| 59 { |
| 60 if (a.lineNumber !== b.line) |
| 61 return a.lineNumber - b.line; |
| 62 return a.columnNumber - b.column; |
| 63 } |
| 64 }, |
| 65 |
| 66 /** |
| 67 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 68 * @return {boolean} |
| 69 */ |
| 70 isBlackboxedUISourceCode: function(uiSourceCode) |
| 71 { |
| 72 var projectType = uiSourceCode.project().type(); |
| 73 var isContentScript = projectType === WebInspector.projectTypes.ContentS
cripts; |
| 74 if (isContentScript && WebInspector.moduleSetting("skipContentScripts").
get()) |
| 75 return true; |
| 76 var networkURL = this._networkMapping.networkURL(uiSourceCode); |
| 77 var url = projectType === WebInspector.projectTypes.Formatter ? uiSource
Code.url() : networkURL; |
| 78 return this.isBlackboxedURL(url); |
| 79 }, |
| 80 |
| 81 /** |
| 82 * @param {string} url |
| 83 * @return {boolean} |
| 84 */ |
| 85 isBlackboxedURL: function(url) |
| 86 { |
| 87 if (this._isBlackboxedURLCache.has(url)) |
| 88 return !!this._isBlackboxedURLCache.get(url); |
| 89 var regex = WebInspector.moduleSetting("skipStackFramesPattern").asRegEx
p(); |
| 90 var isBlackboxed = regex && regex.test(url); |
| 91 this._isBlackboxedURLCache.set(url, isBlackboxed); |
| 92 return isBlackboxed; |
| 93 }, |
| 94 |
| 95 /** |
| 96 * @param {!WebInspector.Script} script |
| 97 * @param {?WebInspector.SourceMap} sourceMap |
| 98 */ |
| 99 sourceMapLoaded: function(script, sourceMap) |
| 100 { |
| 101 if (!sourceMap) |
| 102 return; |
| 103 if (!this._scripts.has(script.scriptId)) |
| 104 return; |
| 105 |
| 106 var mappings = sourceMap.mappings().slice(); |
| 107 mappings.sort(mappingComparator); |
| 108 |
| 109 var previousScriptState = this._scripts.get(script.scriptId); |
| 110 if (!mappings.length) { |
| 111 if (previousScriptState.length > 0) |
| 112 script.setBlackboxedRanges([]).then(this._setScriptState.bind(th
is, script)); |
| 113 return; |
| 114 } |
| 115 |
| 116 var currentBlackboxed = false; |
| 117 var isBlackboxed = false; |
| 118 var positions = []; |
| 119 if (mappings[0].lineNumber !== 0 || mappings[0].columnNumber !== 0) { |
| 120 positions.push({ line: 0, column: 0}); |
| 121 currentBlackboxed = true; |
| 122 } |
| 123 for (var mapping of sourceMap.mappings()) { |
| 124 if (currentBlackboxed !== this.isBlackboxedURL(mapping.sourceURL)) { |
| 125 positions.push({ line: mapping.lineNumber, column: mapping.colum
nNumber }); |
| 126 currentBlackboxed = !currentBlackboxed; |
| 127 } |
| 128 if (currentBlackboxed) |
| 129 isBlackboxed = true; |
| 130 } |
| 131 |
| 132 var isChanged = previousScriptState.length !== positions.length; |
| 133 for (var i = 0; !isChanged && i < positions.length; ++i) |
| 134 isChanged = positions[i].line !== previousScriptState[i].line || pos
itions[i].column !== previousScriptState[i].column; |
| 135 if (!isChanged) |
| 136 return; |
| 137 |
| 138 if (isBlackboxed) |
| 139 script.setBlackboxedRanges(positions).then(this._setScriptState.bind
(this, script)); |
| 140 else |
| 141 script.setBlackboxedRanges([]).then(this._setScriptState.bind(this,
script)); |
| 142 /** |
| 143 * @param {!WebInspector.SourceMap.Entry} a |
| 144 * @param {!WebInspector.SourceMap.Entry} b |
| 145 */ |
| 146 function mappingComparator(a, b) |
| 147 { |
| 148 if (a.lineNumber !== b.lineNumber) |
| 149 return a.lineNumber - b.lineNumber; |
| 150 return a.columnNumber - b.columnNumber; |
| 151 } |
| 152 }, |
| 153 |
| 154 /** |
| 155 * @param {string} url |
| 156 * @return {boolean} |
| 157 */ |
| 158 canBlackboxURL: function(url) |
| 159 { |
| 160 return !!this._urlToRegExpString(url); |
| 161 }, |
| 162 |
| 163 /** |
| 164 * @param {string} url |
| 165 */ |
| 166 blackboxURL: function(url) |
| 167 { |
| 168 var regexPatterns = WebInspector.moduleSetting("skipStackFramesPattern")
.getAsArray(); |
| 169 var regexValue = this._urlToRegExpString(url); |
| 170 if (!regexValue) |
| 171 return; |
| 172 var found = false; |
| 173 for (var i = 0; i < regexPatterns.length; ++i) { |
| 174 var item = regexPatterns[i]; |
| 175 if (item.pattern === regexValue) { |
| 176 item.disabled = false; |
| 177 found = true; |
| 178 break; |
| 179 } |
| 180 } |
| 181 if (!found) |
| 182 regexPatterns.push({ pattern: regexValue }); |
| 183 WebInspector.moduleSetting("skipStackFramesPattern").setAsArray(regexPat
terns); |
| 184 }, |
| 185 |
| 186 /** |
| 187 * @param {string} url |
| 188 * @param {boolean} isContentScript |
| 189 */ |
| 190 unblackbox: function(url, isContentScript) |
| 191 { |
| 192 if (isContentScript) |
| 193 WebInspector.moduleSetting("skipContentScripts").set(false); |
| 194 |
| 195 var regexPatterns = WebInspector.moduleSetting("skipStackFramesPattern")
.getAsArray(); |
| 196 var regexValue = WebInspector.blackboxManager._urlToRegExpString(url); |
| 197 if (!regexValue) |
| 198 return; |
| 199 regexPatterns = regexPatterns.filter(function(item) { |
| 200 return item.pattern !== regexValue; |
| 201 }); |
| 202 for (var i = 0; i < regexPatterns.length; ++i) { |
| 203 var item = regexPatterns[i]; |
| 204 if (item.disabled) |
| 205 continue; |
| 206 try { |
| 207 var regex = new RegExp(item.pattern); |
| 208 if (regex.test(url)) |
| 209 item.disabled = true; |
| 210 } catch (e) { |
| 211 } |
| 212 } |
| 213 WebInspector.moduleSetting("skipStackFramesPattern").setAsArray(regexPat
terns); |
| 214 }, |
| 215 |
| 216 _patternChanged: function() |
| 217 { |
| 218 this._isBlackboxedURLCache.clear(); |
| 219 this._scripts.clear(); |
| 220 |
| 221 var promises = []; |
| 222 for (var debuggerModel of WebInspector.DebuggerModel.instances()) { |
| 223 for (var scriptId in debuggerModel.scripts) { |
| 224 var script = debuggerModel.scripts[scriptId]; |
| 225 promises.push(this._addScript(script).then(loadSourceMap.bind(th
is, script))); |
| 226 } |
| 227 } |
| 228 Promise.all(promises).then(this._patternChangeFinishedForTests); |
| 229 |
| 230 /** |
| 231 * @param {!WebInspector.Script} script |
| 232 * @this {!WebInspector.BlackboxManager} |
| 233 */ |
| 234 function loadSourceMap(script) |
| 235 { |
| 236 this.sourceMapLoaded(script, this._sourceMapForScript(script)); |
| 237 } |
| 238 }, |
| 239 |
| 240 // This method is sniffed in tests. |
| 241 _patternChangeFinishedForTests: function() |
| 242 { |
| 243 }, |
| 244 |
| 245 _globalObjectCleared: function() |
| 246 { |
| 247 this._scripts.clear(); |
| 248 this._isBlackboxedURLCache.clear(); |
| 249 }, |
| 250 |
| 251 /** |
| 252 * @param {!WebInspector.Event} event |
| 253 */ |
| 254 _parsedScriptSource: function(event) |
| 255 { |
| 256 var script = /** @type {!WebInspector.Script} */ (event.data); |
| 257 this._addScript(script); |
| 258 }, |
| 259 |
| 260 /** |
| 261 * @param {!WebInspector.Script} script |
| 262 * @return {!Promise<undefined>} |
| 263 */ |
| 264 _addScript: function(script) |
| 265 { |
| 266 var blackboxed = this._isBlackboxedScript(script); |
| 267 if (!blackboxed) |
| 268 return Promise.resolve(this._setScriptState(script, [])); |
| 269 return script.setBlackboxedRanges([ { line: 0, column: 0 } ]).then(this.
_setScriptState.bind(this, script)); |
| 270 }, |
| 271 |
| 272 /** |
| 273 * @param {!WebInspector.Script} script |
| 274 * @return {boolean} |
| 275 */ |
| 276 _isBlackboxedScript: function(script) |
| 277 { |
| 278 if (script.isContentScript() && WebInspector.moduleSetting("skipContentS
cripts").get()) |
| 279 return true; |
| 280 return this.isBlackboxedURL(script.sourceURL); |
| 281 }, |
| 282 |
| 283 /** |
| 284 * @param {!WebInspector.Script} script |
| 285 * @return {?WebInspector.SourceMap} |
| 286 */ |
| 287 _sourceMapForScript: function(script) |
| 288 { |
| 289 return this._debuggerWorkspaceBinding.sourceMapForScript(script); |
| 290 }, |
| 291 |
| 292 /** |
| 293 * @param {!WebInspector.Script} script |
| 294 * @param {?Array<!DebuggerAgent.ScriptPosition>} positions |
| 295 */ |
| 296 _setScriptState: function(script, positions) |
| 297 { |
| 298 if (positions) |
| 299 this._scripts.set(script.scriptId, positions); |
| 300 else if (!this._scripts.has(script.scriptId)) |
| 301 this._scripts.set(script.scriptId, []); |
| 302 }, |
| 303 |
| 304 /** |
| 305 * @param {string} url |
| 306 * @return {string} |
| 307 */ |
| 308 _urlToRegExpString: function(url) |
| 309 { |
| 310 var parsedURL = new WebInspector.ParsedURL(url); |
| 311 if (parsedURL.isAboutBlank() || parsedURL.isDataURL()) |
| 312 return ""; |
| 313 if (!parsedURL.isValid) |
| 314 return "^" + url.escapeForRegExp() + "$"; |
| 315 var name = parsedURL.lastPathComponent; |
| 316 if (name) |
| 317 name = "/" + name; |
| 318 else if (parsedURL.folderPathComponents) |
| 319 name = parsedURL.folderPathComponents + "/"; |
| 320 if (!name) |
| 321 name = parsedURL.host; |
| 322 if (!name) |
| 323 return ""; |
| 324 var scheme = parsedURL.scheme; |
| 325 var prefix = ""; |
| 326 if (scheme && scheme !== "http" && scheme !== "https") { |
| 327 prefix = "^" + scheme + "://"; |
| 328 if (scheme === "chrome-extension") |
| 329 prefix += parsedURL.host + "\\b"; |
| 330 prefix += ".*"; |
| 331 } |
| 332 return prefix + name.escapeForRegExp() + (url.endsWith(name) ? "$" : "\\
b"); |
| 333 } |
| 334 } |
| 335 |
| 336 /** @type {!WebInspector.BlackboxManager} */ |
| 337 WebInspector.blackboxManager; |
| OLD | NEW |