Changeset 84625 in webkit
- Timestamp:
- Apr 22, 2011 6:49:04 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r84619 r84625 1 2011-04-22 Pavel Podivilov <podivilov@chromium.org> 2 3 Reviewed by Pavel Feldman. 4 5 Web Inspector: fix de-obfuscation of scripts inlined in html. 6 https://bugs.webkit.org/show_bug.cgi?id=58538 7 8 * inspector/debugger/resources/obfuscated.js: 9 * inspector/debugger/script-formatter-expected.txt: 10 * inspector/debugger/script-formatter.html: Renamed from LayoutTests/inspector/debugger/script-formatter.html-disabled. 11 1 12 2011-04-22 Mikhail Naganov <mnaganov@chromium.org> 2 13 -
trunk/LayoutTests/inspector/debugger/resources/obfuscated.js
r83748 r84625 1 onmessage=function(event){var source=event.data;var formattedSource=beautify(source);var mapping=buildMapping(source,formattedSource);postMessage({formattedSource:formattedSource,mapping:mapping})};function beautify(source){var ast=parse.parse(source);var beautifyOptions=1 try{onmessage=function(event){var source=event.data;var formattedSource=beautify(source);var mapping=buildMapping(source,formattedSource);postMessage({formattedSource:formattedSource,mapping:mapping})};function beautify(source){var ast=parse.parse(source);var beautifyOptions= 2 2 {indent_level:4,indent_start:0,quote_keys:false,space_colon:false};return process.gen_code(ast,beautifyOptions)}function buildMapping(source,formattedSource){var mapping={original:[],formatted:[]};var lastPosition=0;var regexp=/(^|[^\\])\b((?=\D)[\$\.\w]+)\b/g;while(true) 3 3 {var match=regexp.exec(formattedSource);if(!match)break;var position=source.indexOf(match[2],lastPosition);if(position===-1)throw"No match found in original source for "+match[2];mapping.original.push(position);mapping.formatted.push(match.index+match[1].length); 4 lastPosition=position+match[2].length}return mapping}function require(){return parse}var exports={};importScripts("UglifyJS/parse-js.js");var parse=exports;var exports={};importScripts("UglifyJS/process.js");var process=exports; 4 lastPosition=position+match[2].length}return mapping}function require(){return parse}var exports={};importScripts("UglifyJS/parse-js.js");var parse=exports;var exports={};importScripts("UglifyJS/process.js");var process=exports;}catch(e){} -
trunk/LayoutTests/inspector/debugger/script-formatter-expected.txt
r83748 r84625 6 6 7 7 Running: testSourceMapping 8 9 Running: testFormatInlinedScripts 10 <html><body><script> 11 function f() { 12 } 13 </script><script> 14 function g() { 15 } 16 </script></body></html> 8 17 Debugger was disabled. 9 18 -
trunk/LayoutTests/inspector/debugger/script-formatter.html
r84624 r84625 16 16 worker.onmessage = InspectorTest.safeWrap(function(event) 17 17 { 18 InspectorTest.assertEquals("var x = 0 ;", event.data.formattedSource);18 InspectorTest.assertEquals("var x = 0\n", event.data.content); 19 19 next(); 20 20 }); … … 26 26 }; 27 27 28 worker.postMessage( "var x=0");28 worker.postMessage({ mimeType: "text/javascript", content: "var x=0" }); 29 29 }, 30 30 … … 34 34 { 35 35 var source = WebInspector.panels.scripts.visibleView._content; 36 var formattedSource = event.data. formattedSource;36 var formattedSource = event.data.content; 37 37 var mapping = event.data.mapping; 38 38 … … 40 40 { 41 41 var position = source.indexOf(string); 42 var formattedPosition = mapping.formatted[mapping.original.upperBound(position - 1)]; 42 var index = mapping.original.upperBound(position) - 1; 43 var delta = position - mapping.original[index]; 44 var formattedPosition = Math.min(mapping.formatted[index] + delta, mapping.formatted[index + 1]); 43 45 InspectorTest.assertEquals(string, formattedSource.substr(formattedPosition, string.length)); 44 46 } … … 63 65 function didShowScriptSource(sourceFrame) 64 66 { 65 worker.postMessage( sourceFrame._content);67 worker.postMessage({ mimeType: "text/javascript", content: sourceFrame._content }); 66 68 } 69 }, 70 71 function testFormatInlinedScripts(next) 72 { 73 worker.onmessage = InspectorTest.safeWrap(function(event) 74 { 75 InspectorTest.addResult(event.data.content); 76 next(); 77 }); 78 79 worker.onerror = function(event) 80 { 81 InspectorTest.addResult("Error in worker: " + event.data); 82 next(); 83 }; 84 85 var content = "<html><body><script>function f(){}<" + "/script><script>function g(){}<" + "/script></body></html>"; 86 worker.postMessage({ mimeType: "text/html", content: content }); 67 87 } 68 88 ]); -
trunk/Source/WebCore/ChangeLog
r84624 r84625 1 2011-04-22 Pavel Podivilov <podivilov@chromium.org> 2 3 Reviewed by Pavel Feldman. 4 5 Web Inspector: fix de-obfuscation of scripts inlined in html. 6 https://bugs.webkit.org/show_bug.cgi?id=58538 7 8 Use html tokenizer to find script boundaries instead of relying on scriptParsed events. 9 10 Test: inspector/debugger/script-formatter.html 11 12 * WebCore.gypi: 13 * WebCore.vcproj/WebCore.vcproj: 14 * inspector/front-end/JavaScriptFormatter.js: Renamed from Source/WebCore/inspector/front-end/UglifyJS/JavaScriptFormatter.js. 15 * inspector/front-end/ScriptFormatter.js: 16 (WebInspector.ScriptFormatter): 17 (WebInspector.ScriptFormatter.prototype.formatContent): 18 (WebInspector.ScriptFormatter.prototype._didFormatContent): 19 * inspector/front-end/ScriptFormatterWorker.js: 20 (onmessage): 21 (formatScript): 22 (HTMLScriptFormatter): 23 (HTMLScriptFormatter.prototype.format): 24 (HTMLScriptFormatter.prototype.scriptStarted): 25 (HTMLScriptFormatter.prototype.scriptEnded): 26 (HTMLScriptFormatter.prototype.styleSheetStarted): 27 (HTMLScriptFormatter.prototype.styleSheetEnded): 28 * inspector/front-end/SourceFile.js: 29 (WebInspector.FormattedSourceFile.prototype._didRequestContent): 30 * inspector/front-end/SourceHTMLTokenizer.js: 31 (WebInspector.SourceHTMLTokenizer.prototype.scriptStarted): 32 (WebInspector.SourceHTMLTokenizer.prototype.scriptEnded): 33 (WebInspector.SourceHTMLTokenizer.prototype.styleSheetStarted): 34 (WebInspector.SourceHTMLTokenizer.prototype.styleSheetEnded): 35 (WebInspector.SourceHTMLTokenizer.prototype.nextToken): 36 * inspector/front-end/SourceHTMLTokenizer.re2js: 37 * inspector/front-end/WebKit.qrc: 38 1 39 2011-04-22 Andrey Kosyakov <caseq@chromium.org> 2 40 -
trunk/Source/WebCore/WebCore.gypi
r84620 r84625 6235 6235 'inspector/front-end/InjectedFakeWorker.js', 6236 6236 'inspector/front-end/inspector.js', 6237 'inspector/front-end/JavaScriptFormatter.js', 6237 6238 'inspector/front-end/KeyboardShortcut.js', 6238 6239 'inspector/front-end/MetricsSidebarPane.js', … … 6312 6313 ], 6313 6314 'webinspector_uglifyjs_files': [ 6314 'inspector/front-end/UglifyJS/JavaScriptFormatter.js',6315 6315 'inspector/front-end/UglifyJS/parse-js.js', 6316 6316 ], -
trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj
r84620 r84625 67438 67438 </File> 67439 67439 <File 67440 RelativePath="..\inspector\front-end\JavaScriptFormatter.js" 67441 > 67442 </File> 67443 <File 67440 67444 RelativePath="..\inspector\front-end\KeyboardShortcut.js" 67441 67445 > -
trunk/Source/WebCore/inspector/front-end/JavaScriptFormatter.js
r84624 r84625 29 29 */ 30 30 31 function FormattedContentBuilder(content )31 function FormattedContentBuilder(content, mapping, originalOffset, formattedOffset) 32 32 { 33 33 this._originalContent = content; 34 this._original Positions = [0];34 this._originalOffset = originalOffset; 35 35 this._lastOriginalPosition = 0; 36 36 37 37 this._formattedContent = []; 38 38 this._formattedContentLength = 0; 39 this._formattedPositions = [0]; 40 this._lastFormattedlPosition = 0; 39 this._formattedOffset = formattedOffset; 40 this._lastFormattedPosition = 0; 41 42 this._mapping = mapping; 41 43 42 44 this._lineNumber = 0; … … 64 66 65 67 if (token.pos - this._lastOriginalPosition !== this._formattedContentLength - this._lastFormattedPosition) { 66 this._originalPositions.push(token.pos); 67 this._formattedPositions.push(this._formattedContentLength); 68 this._mapping.original.push(this._originalOffset + token.pos); 68 69 this._lastOriginalPosition = token.pos; 70 this._mapping.formatted.push(this._formattedOffset + this._formattedContentLength); 69 71 this._lastFormattedPosition = this._formattedContentLength; 70 72 } -
trunk/Source/WebCore/inspector/front-end/ScriptFormatter.js
r84620 r84625 32 32 { 33 33 this._worker = new Worker("ScriptFormatterWorker.js"); 34 this._worker.onmessage = this._handleMessage.bind(this); 35 this._worker.onerror = this._handleError.bind(this); 34 this._worker.onmessage = this._didFormatContent.bind(this); 36 35 this._tasks = []; 37 36 } … … 59 58 } 60 59 61 WebInspector.ScriptFormatter.findScriptRanges = function(lineEndings, scripts)62 {63 var scriptRanges = [];64 for (var i = 0; i < scripts.length; ++i) {65 var start = { lineNumber: scripts[i].lineOffset, columnNumber: scripts[i].columnOffset };66 start.position = WebInspector.ScriptFormatter.locationToPosition(lineEndings, start);67 var endPosition = start.position + scripts[i].length;68 var end = WebInspector.ScriptFormatter.positionToLocation(lineEndings, endPosition);69 end.position = endPosition;70 scriptRanges.push({ start: start, end: end, sourceID: scripts[i].sourceID });71 }72 scriptRanges.sort(function(x, y) { return x.start.position - y.start.position; });73 return scriptRanges;74 }75 76 60 WebInspector.ScriptFormatter.prototype = { 77 formatContent: function( text, scripts, callback)61 formatContent: function(mimeType, content, callback) 78 62 { 79 text = text.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''); 80 var scriptRanges = WebInspector.ScriptFormatter.findScriptRanges(text.lineEndings(), scripts); 81 var chunks = this._splitContentIntoChunks(text, scriptRanges); 82 83 function didFormatChunks() 84 { 85 var result = this._buildContentFromChunks(chunks); 86 result.mapping.originalLineEndings = text.lineEndings(); 87 callback(result.text, result.mapping); 88 } 89 this._formatChunks(chunks, 0, didFormatChunks.bind(this)); 63 content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''); 64 var data = { mimeType: mimeType, content: content }; 65 this._tasks.push({ data: data, callback: callback }); 66 this._worker.postMessage(data); 90 67 }, 91 68 92 _splitContentIntoChunks: function(text, scriptRanges) 93 { 94 var chunks = []; 95 function addChunk(start, end, isScript) 96 { 97 var chunk = {}; 98 chunk.start = start; 99 chunk.end = end; 100 chunk.isScript = isScript; 101 chunk.text = text.substring(start, end); 102 chunks.push(chunk); 103 } 104 var currentPosition = 0; 105 for (var i = 0; i < scriptRanges.length; ++i) { 106 var start = scriptRanges[i].start.position; 107 var end = scriptRanges[i].end.position; 108 if (currentPosition < start) 109 addChunk(currentPosition, start, false); 110 addChunk(start, end, true); 111 currentPosition = end; 112 } 113 if (currentPosition < text.length) 114 addChunk(currentPosition, text.length, false); 115 return chunks; 116 }, 117 118 _formatChunks: function(chunks, index, callback) 119 { 120 while(true) { 121 if (index === chunks.length) { 122 callback(); 123 return; 124 } 125 var chunk = chunks[index++]; 126 if (chunk.isScript) 127 break; 128 } 129 130 function didFormat(formattedSource, mapping) 131 { 132 chunk.text = formattedSource; 133 chunk.mapping = mapping; 134 this._formatChunks(chunks, index, callback); 135 } 136 this._formatScript(chunk.text, didFormat.bind(this)); 137 }, 138 139 _buildContentFromChunks: function(chunks) 140 { 141 var text = ""; 142 var mapping = { original: [], formatted: [] }; 143 for (var i = 0; i < chunks.length; ++i) { 144 var chunk = chunks[i]; 145 mapping.original.push(chunk.start); 146 mapping.formatted.push(text.length); 147 if (chunk.isScript) { 148 if (text) 149 text += "\n"; 150 for (var j = 0; j < chunk.mapping.original.length; ++j) { 151 mapping.original.push(chunk.mapping.original[j] + chunk.start); 152 mapping.formatted.push(chunk.mapping.formatted[j] + text.length); 153 } 154 text += chunk.text; 155 } else { 156 if (text) 157 text += "\n"; 158 text += chunk.text; 159 } 160 mapping.original.push(chunk.end); 161 mapping.formatted.push(text.length); 162 } 163 return { text: text, mapping: mapping }; 164 }, 165 166 _formatScript: function(source, callback) 167 { 168 this._tasks.push({ source: source, callback: callback }); 169 this._worker.postMessage(source); 170 }, 171 172 _handleMessage: function(event) 69 _didFormatContent: function(event) 173 70 { 174 71 var task = this._tasks.shift(); 175 task.callback(event.data.formattedSource, event.data.mapping); 176 }, 177 178 _handleError: function(event) 179 { 180 console.warn("Error in script formatter worker:", event); 181 event.preventDefault() 182 var task = this._tasks.shift(); 183 task.callback(task.source, { original: [], formatted: [] }); 72 event.data.mapping.originalLineEndings = task.data.content.lineEndings(); 73 task.callback(event.data.content, event.data.mapping); 184 74 } 185 75 } -
trunk/Source/WebCore/inspector/front-end/ScriptFormatterWorker.js
r84620 r84625 30 30 31 31 onmessage = function(event) { 32 var source = event.data; 33 var tokenizer = new Tokenizer(source); 34 var builder = new FormattedContentBuilder(tokenizer.content()); 35 var formatter = new JavaScriptFormatter(tokenizer, builder); 36 formatter.format(); 37 postMessage({ formattedSource: builder.content(), mapping: builder.mapping() }); 32 var result = {}; 33 if (event.data.mimeType === "text/html") { 34 var formatter = new HTMLScriptFormatter(); 35 result = formatter.format(event.data.content); 36 } else { 37 result.mapping = { original: [], formatted: [] }; 38 result.content = formatScript(event.data.content, result.mapping, 0, 0); 39 } 40 postMessage(result); 38 41 }; 42 43 function formatScript(content, mapping, offset, formattedOffset) 44 { 45 var formattedContent; 46 try { 47 var tokenizer = new Tokenizer(content); 48 var builder = new FormattedContentBuilder(tokenizer.content(), mapping, offset, formattedOffset); 49 var formatter = new JavaScriptFormatter(tokenizer, builder); 50 formatter.format(); 51 formattedContent = builder.content(); 52 } catch (e) { 53 formattedContent = content; 54 } 55 return formattedContent; 56 } 57 58 WebInspector = {}; 59 importScripts("SourceTokenizer.js"); 60 importScripts("SourceHTMLTokenizer.js"); 61 62 HTMLScriptFormatter = function() 63 { 64 WebInspector.SourceHTMLTokenizer.call(this); 65 } 66 67 HTMLScriptFormatter.prototype = { 68 format: function(content) 69 { 70 this.line = content; 71 this._content = content; 72 this._formattedContent = ""; 73 this._mapping = { original: [], formatted: [] }; 74 this._position = 0; 75 76 var cursor = 0; 77 while (cursor < this._content.length) 78 cursor = this.nextToken(cursor); 79 80 this._formattedContent += this._content.substring(this._position); 81 return { content: this._formattedContent, mapping: this._mapping }; 82 }, 83 84 scriptStarted: function(cursor) 85 { 86 this._formattedContent += this._content.substring(this._position, cursor); 87 this._formattedContent += "\n"; 88 this._position = cursor; 89 }, 90 91 scriptEnded: function(cursor) 92 { 93 if (cursor === this._position) 94 return; 95 96 var scriptContent = this._content.substring(this._position, cursor); 97 var formattedScriptContent = formatScript(scriptContent, this._mapping, this._position, this._formattedContent.length); 98 99 this._formattedContent += formattedScriptContent; 100 this._position = cursor; 101 }, 102 103 styleSheetStarted: function(cursor) 104 { 105 }, 106 107 styleSheetEnded: function(cursor) 108 { 109 } 110 } 111 112 HTMLScriptFormatter.prototype.__proto__ = WebInspector.SourceHTMLTokenizer.prototype; 39 113 40 114 function require() … … 47 121 var parse = exports; 48 122 49 importScripts(" UglifyJS/JavaScriptFormatter.js");123 importScripts("JavaScriptFormatter.js"); -
trunk/Source/WebCore/inspector/front-end/SourceFile.js
r84620 r84625 253 253 WebInspector.SourceFile.prototype._didRequestContent.call(this, mimeType, formattedText); 254 254 } 255 this._formatter.formatContent( text, this._scripts, didFormatContent.bind(this));255 this._formatter.formatContent(mimeType, text, didFormatContent.bind(this)); 256 256 } 257 257 } -
trunk/Source/WebCore/inspector/front-end/SourceHTMLTokenizer.js
r76943 r84625 1 /* Generated by re2c 0.13.5 on Fri Jan 28 18:32:272011 */1 /* Generated by re2c 0.13.5 on Thu Apr 14 15:53:19 2011 */ 2 2 /* 3 3 * Copyright (C) 2009 Google Inc. All rights reserved. … … 140 140 }, 141 141 142 scriptStarted: function(cursor) 143 { 144 if (!this._internalJavaScriptTokenizer) { 145 this._internalJavaScriptTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript"); 146 this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.initialCondition; 147 } 148 }, 149 150 scriptEnded: function(cursor) 151 { 152 }, 153 154 styleSheetStarted: function(cursor) 155 { 156 if (!this._internalCSSTokenizer) { 157 this._internalCSSTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css"); 158 this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.initialCondition; 159 } 160 }, 161 162 styleSheetEnded: function(cursor) 163 { 164 }, 165 142 166 nextToken: function(cursor) 143 167 { … … 545 569 this.tokenType = "html-tag"; 546 570 this._condition.parseCondition = this._parseConditions.INITIAL; 571 this.scriptEnded(cursor - 8); 547 572 return cursor; 548 573 } … … 690 715 this.tokenType = "html-tag"; 691 716 if (this._condition.parseCondition & this._parseConditions.SCRIPT) { 692 if (!this._internalJavaScriptTokenizer) { 693 this._internalJavaScriptTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript"); 694 this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.initialCondition; 695 } 717 this.scriptStarted(cursor); 696 718 // Do not tokenize script tag contents. 697 719 return cursor; … … 699 721 700 722 if (this._condition.parseCondition & this._parseConditions.STYLE) { 701 if (!this._internalCSSTokenizer) { 702 this._internalCSSTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css"); 703 this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.initialCondition; 704 } 723 this.styleSheetStarted(cursor); 705 724 // Do not tokenize style tag contents. 706 725 return cursor; -
trunk/Source/WebCore/inspector/front-end/SourceHTMLTokenizer.re2js
r76943 r84625 139 139 }, 140 140 141 scriptStarted: function(cursor) 142 { 143 if (!this._internalJavaScriptTokenizer) { 144 this._internalJavaScriptTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript"); 145 this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.initialCondition; 146 } 147 }, 148 149 scriptEnded: function(cursor) 150 { 151 }, 152 153 styleSheetStarted: function(cursor) 154 { 155 if (!this._internalCSSTokenizer) { 156 this._internalCSSTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css"); 157 this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.initialCondition; 158 } 159 }, 160 161 styleSheetEnded: function(cursor) 162 { 163 }, 164 141 165 nextToken: function(cursor) 142 166 { … … 239 263 this.tokenType = "html-tag"; 240 264 this._condition.parseCondition = this._parseConditions.INITIAL; 265 this.scriptEnded(cursor - 8); 241 266 return cursor; 242 267 } … … 260 285 this.tokenType = "html-tag"; 261 286 this._condition.parseCondition = this._parseConditions.INITIAL; 287 this.styleEnded(cursor - 7); 262 288 return cursor; 263 289 } … … 276 302 return cursor; 277 303 } 278 304 279 305 <TAG> GT => INITIAL 280 306 { 281 307 this.tokenType = "html-tag"; 282 308 if (this._condition.parseCondition & this._parseConditions.SCRIPT) { 283 if (!this._internalJavaScriptTokenizer) { 284 this._internalJavaScriptTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript"); 285 this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.initialCondition; 286 } 309 this.scriptStarted(cursor); 287 310 // Do not tokenize script tag contents. 288 311 return cursor; … … 290 313 291 314 if (this._condition.parseCondition & this._parseConditions.STYLE) { 292 if (!this._internalCSSTokenizer) { 293 this._internalCSSTokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css"); 294 this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.initialCondition; 295 } 315 this.styleSheetStarted(cursor); 296 316 // Do not tokenize style tag contents. 297 317 return cursor; -
trunk/Source/WebCore/inspector/front-end/WebKit.qrc
r84620 r84625 59 59 <file>inspector.js</file> 60 60 <file>InspectorFrontendHostStub.js</file> 61 <file>JavaScriptFormatter.js</file> 61 62 <file>KeyboardShortcut.js</file> 62 63 <file>MetricsSidebarPane.js</file> … … 124 125 <file>WelcomeView.js</file> 125 126 <file>WorkersSidebarPane.js</file> 126 <file>UglifyJS/JavaScriptFormatter.js</file>127 127 <file>UglifyJS/parse-js.js</file> 128 128 <file>audits.css</file>
Note: See TracChangeset
for help on using the changeset viewer.