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

Side by Side Diff: chrome/browser/resources/net_internals/logviewpainter.js

Issue 7531005: Rename the net_internals file names to include hyphens. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Add some missing files Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 * TODO(eroman): This needs better presentation, and cleaner code. This
7 * implementation is more of a transitionary step as
8 * the old net-internals is replaced.
9 */
10
11 // TODO(eroman): these functions should use lower-case names.
12 var PaintLogView;
13 var PrintSourceEntriesAsText;
14 var proxySettingsToString;
15 var stripCookiesAndLoginInfo;
16
17 // Start of anonymous namespace.
18 (function() {
19
20 PaintLogView = function(sourceEntries, node) {
21 for (var i = 0; i < sourceEntries.length; ++i) {
22 if (i != 0)
23 addNode(node, 'hr');
24 addSourceEntry_(node, sourceEntries[i]);
25 }
26 }
27
28 function addSourceEntry_(node, sourceEntry) {
29 var div = addNode(node, 'div');
30 div.className = 'logSourceEntry';
31
32 var p = addNode(div, 'p');
33 var nobr = addNode(p, 'nobr');
34
35 addTextNode(nobr, sourceEntry.getDescription());
36
37 var p2 = addNode(div, 'p');
38 var nobr2 = addNode(p2, 'nobr');
39
40 var logEntries = sourceEntry.getLogEntries();
41 var startDate = convertTimeTicksToDate(logEntries[0].time);
42 addTextNode(nobr2, 'Start Time: ' + startDate.toLocaleString());
43
44 var pre = addNode(div, 'pre');
45 addTextNode(pre, PrintSourceEntriesAsText(logEntries));
46 }
47
48 function canCollapseBeginWithEnd(beginEntry) {
49 return beginEntry &&
50 beginEntry.isBegin() &&
51 beginEntry.end &&
52 beginEntry.end.index == beginEntry.index + 1 &&
53 (!beginEntry.orig.params || !beginEntry.end.orig.params) &&
54 beginEntry.orig.wasPassivelyCaptured ==
55 beginEntry.end.orig.wasPassivelyCaptured;
56 }
57
58 PrintSourceEntriesAsText = function(sourceEntries) {
59 var entries = LogGroupEntry.createArrayFrom(sourceEntries);
60 if (entries.length == 0)
61 return '';
62
63 var startDate = convertTimeTicksToDate(entries[0].orig.time);
64 var startTime = startDate.getTime();
65
66 var tablePrinter = new TablePrinter();
67
68 for (var i = 0; i < entries.length; ++i) {
69 var entry = entries[i];
70
71 // Avoid printing the END for a BEGIN that was immediately before, unless
72 // both have extra parameters.
73 if (!entry.isEnd() || !canCollapseBeginWithEnd(entry.begin)) {
74 tablePrinter.addRow();
75
76 // Annotate this entry with "(P)" if it was passively captured.
77 tablePrinter.addCell(entry.orig.wasPassivelyCaptured ? '(P) ' : '');
78
79 tablePrinter.addCell('t=');
80 var date = convertTimeTicksToDate(entry.orig.time) ;
81 var tCell = tablePrinter.addCell(date.getTime());
82 tCell.alignRight = true;
83 tablePrinter.addCell(' [st=');
84 var stCell = tablePrinter.addCell(date.getTime() - startTime);
85 stCell.alignRight = true;
86 tablePrinter.addCell('] ');
87
88 var indentationStr = makeRepeatedString(' ', entry.getDepth() * 3);
89 var mainCell =
90 tablePrinter.addCell(indentationStr + getTextForEvent(entry));
91 tablePrinter.addCell(' ');
92
93 // Get the elapsed time.
94 if (entry.isBegin()) {
95 tablePrinter.addCell('[dt=');
96 var dt = '?';
97 // Definite time.
98 if (entry.end) {
99 dt = entry.end.orig.time - entry.orig.time;
100 }
101 var dtCell = tablePrinter.addCell(dt);
102 dtCell.alignRight = true;
103
104 tablePrinter.addCell(']');
105 } else {
106 mainCell.allowOverflow = true;
107 }
108 }
109
110 // Output the extra parameters.
111 if (entry.orig.params != undefined) {
112 // Add a continuation row for each line of text from the extra parameters.
113 var extraParamsText = getTextForExtraParams(
114 entry.orig,
115 g_browser.sourceTracker.getSecurityStripping());
116 var extraParamsTextLines = extraParamsText.split('\n');
117
118 for (var j = 0; j < extraParamsTextLines.length; ++j) {
119 tablePrinter.addRow();
120 tablePrinter.addCell(''); // Empty passive annotation.
121 tablePrinter.addCell(''); // No t=.
122 tablePrinter.addCell('');
123 tablePrinter.addCell(''); // No st=.
124 tablePrinter.addCell('');
125 tablePrinter.addCell(' ');
126
127 var mainExtraCell =
128 tablePrinter.addCell(indentationStr + extraParamsTextLines[j]);
129 mainExtraCell.allowOverflow = true;
130 }
131 }
132 }
133
134 // Format the table for fixed-width text.
135 return tablePrinter.toText(0);
136 }
137
138 /**
139 * |hexString| must be a string of hexadecimal characters with no whitespace,
140 * whose length is a multiple of two. Returns a string spanning multiple lines,
141 * with the hexadecimal characters from |hexString| on the left, in groups of
142 * two, and their corresponding ASCII characters on the right.
143 *
144 * |asciiCharsPerLine| specifies how many ASCII characters will be put on each
145 * line of the output string.
146 */
147 function formatHexString(hexString, asciiCharsPerLine) {
148 // Number of transferred bytes in a line of output. Length of a
149 // line is roughly 4 times larger.
150 var hexCharsPerLine = 2 * asciiCharsPerLine;
151 var out = [];
152 for (var i = 0; i < hexString.length; i += hexCharsPerLine) {
153 var hexLine = '';
154 var asciiLine = '';
155 for (var j = i; j < i + hexCharsPerLine && j < hexString.length; j += 2) {
156 var hex = hexString.substr(j, 2);
157 hexLine += hex + ' ';
158 var charCode = parseInt(hex, 16);
159 // For ASCII codes 32 though 126, display the corresponding
160 // characters. Use a space for nulls, and a period for
161 // everything else.
162 if (charCode >= 0x20 && charCode <= 0x7E) {
163 asciiLine += String.fromCharCode(charCode);
164 } else if (charCode == 0x00) {
165 asciiLine += ' ';
166 } else {
167 asciiLine += '.';
168 }
169 }
170
171 // Max sure the ASCII text on last line of output lines up with previous
172 // lines.
173 hexLine += makeRepeatedString(' ', 3 * asciiCharsPerLine - hexLine.length);
174 out.push(' ' + hexLine + ' ' + asciiLine);
175 }
176 return out.join('\n');
177 }
178
179 function getTextForExtraParams(entry, enableSecurityStripping) {
180 // Format the extra parameters (use a custom formatter for certain types,
181 // but default to displaying as JSON).
182
183 // If security stripping is enabled, remove data as needed.
184 if (enableSecurityStripping)
185 entry = stripCookiesAndLoginInfo(entry);
186
187 switch (entry.type) {
188 case LogEventType.HTTP_TRANSACTION_SEND_REQUEST_HEADERS:
189 case LogEventType.HTTP_TRANSACTION_SEND_TUNNEL_HEADERS:
190 return getTextForRequestHeadersExtraParam(entry);
191
192 case LogEventType.HTTP_TRANSACTION_READ_RESPONSE_HEADERS:
193 case LogEventType.HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS:
194 return getTextForResponseHeadersExtraParam(entry);
195
196 case LogEventType.PROXY_CONFIG_CHANGED:
197 return getTextForProxyConfigChangedExtraParam(entry);
198
199 default:
200 var out = [];
201 for (var k in entry.params) {
202 if (k == 'headers' && entry.params[k] instanceof Array) {
203 out.push(getTextForResponseHeadersExtraParam(entry));
204 continue;
205 }
206 var value = entry.params[k];
207 // For transferred bytes, display the bytes in hex and ASCII.
208 if (k == 'hex_encoded_bytes') {
209 out.push(' --> ' + k + ' =');
210 out.push(formatHexString(value, 20));
211 continue;
212 }
213
214 var paramStr = ' --> ' + k + ' = ' + JSON.stringify(value);
215
216 // Append the symbolic name for certain constants. (This relies
217 // on particular naming of event parameters to infer the type).
218 if (typeof value == 'number') {
219 if (k == 'net_error') {
220 paramStr += ' (' + getNetErrorSymbolicString(value) + ')';
221 } else if (k == 'load_flags') {
222 paramStr += ' (' + getLoadFlagSymbolicString(value) + ')';
223 }
224 }
225
226 out.push(paramStr);
227 }
228 return out.join('\n');
229 }
230 }
231
232 /**
233 * Returns the name for netError.
234 *
235 * Example: getNetErrorSymbolicString(-105) would return
236 * "NAME_NOT_RESOLVED".
237 */
238 function getNetErrorSymbolicString(netError) {
239 return getKeyWithValue(NetError, netError);
240 }
241
242 /**
243 * Returns the set of LoadFlags that make up the integer |loadFlag|.
244 * For example: getLoadFlagSymbolicString(
245 */
246 function getLoadFlagSymbolicString(loadFlag) {
247 // Load flag of 0 means "NORMAL". Special case this, since and-ing with
248 // 0 is always going to be false.
249 if (loadFlag == 0)
250 return getKeyWithValue(LoadFlag, loadFlag);
251
252 var matchingLoadFlagNames = [];
253
254 for (var k in LoadFlag) {
255 if (loadFlag & LoadFlag[k])
256 matchingLoadFlagNames.push(k);
257 }
258
259 return matchingLoadFlagNames.join(' | ');
260 }
261
262 /**
263 * Indent |lines| by |start|.
264 *
265 * For example, if |start| = ' -> ' and |lines| = ['line1', 'line2', 'line3']
266 * the output will be:
267 *
268 * " -> line1\n" +
269 * " line2\n" +
270 * " line3"
271 */
272 function indentLines(start, lines) {
273 return start + lines.join('\n' + makeRepeatedString(' ', start.length));
274 }
275
276 /**
277 * Removes a cookie or unencrypted login information from a single HTTP header
278 * line, if present, and returns the modified line. Otherwise, just returns
279 * the original line.
280 */
281 function stripCookieOrLoginInfo(line) {
282 var patterns = [
283 // Cookie patterns
284 /^set-cookie:/i,
285 /^set-cookie2:/i,
286 /^cookie:/i,
287
288 // Unencrypted authentication patterns
289 /^authorization: \S*/i,
290 /^proxy-authorization: \S*/i];
291 for (var i = 0; i < patterns.length; i++) {
292 var match = patterns[i].exec(line);
293 if (match != null)
294 return match[0] + ' [value was stripped]';
295 }
296
297 // Remove authentication information from data received from the server in
298 // multi-round Negotiate authentication.
299 var challengePatterns = [
300 /^www-authenticate: (\S*)\s*/i,
301 /^proxy-authenticate: (\S*)\s*/i];
302 for (var i = 0; i < challengePatterns.length; i++) {
303 var match = challengePatterns[i].exec(line);
304 if (!match)
305 continue;
306
307 // If there's no data after the scheme name, do nothing.
308 if (match[0].length == line.length)
309 break;
310
311 // Ignore lines with commas in them, as they may contain lists of schemes,
312 // and the information we want to hide is Base64 encoded, so has no commas.
313 if (line.indexOf(',') >= 0)
314 break;
315
316 // Ignore Basic and Digest authentication challenges, as they contain
317 // public information.
318 if (/^basic$/i.test(match[1]) || /^digest$/i.test(match[1]))
319 break;
320
321 return match[0] + '[value was stripped]';
322 }
323
324 return line;
325 }
326
327 /**
328 * If |entry| has headers, returns a copy of |entry| with all cookie and
329 * unencrypted login text removed. Otherwise, returns original |entry| object.
330 * This is needed so that JSON log dumps can be made without affecting the
331 * source data.
332 */
333 stripCookiesAndLoginInfo = function(entry) {
334 if (!entry.params || !entry.params.headers ||
335 !(entry.params.headers instanceof Array)) {
336 return entry;
337 }
338
339 // Duplicate the top level object, and |entry.params|. All other fields are
340 // just pointers to the original values, as they won't be modified, other than
341 // |entry.params.headers|.
342 entry = shallowCloneObject(entry);
343 entry.params = shallowCloneObject(entry.params);
344
345 entry.params.headers = entry.params.headers.map(stripCookieOrLoginInfo);
346 return entry;
347 }
348
349 function getTextForRequestHeadersExtraParam(entry) {
350 var params = entry.params;
351
352 // Strip the trailing CRLF that params.line contains.
353 var lineWithoutCRLF = params.line.replace(/\r\n$/g, '');
354 return indentLines(' --> ', [lineWithoutCRLF].concat(params.headers));
355 }
356
357 function getTextForResponseHeadersExtraParam(entry) {
358 return indentLines(' --> ', entry.params.headers);
359 }
360
361 function getTextForProxyConfigChangedExtraParam(entry) {
362 var params = entry.params;
363 var out = '';
364 var indentation = ' ';
365
366 if (params.old_config) {
367 var oldConfigString = proxySettingsToString(params.old_config);
368 // The previous configuration may not be present in the case of
369 // the initial proxy settings fetch.
370 out += ' --> old_config =\n' +
371 indentLines(indentation, oldConfigString.split('\n'));
372 out += '\n';
373 }
374
375 var newConfigString = proxySettingsToString(params.new_config);
376 out += ' --> new_config =\n' +
377 indentLines(indentation, newConfigString.split('\n'));
378
379 return out;
380 }
381
382 function getTextForEvent(entry) {
383 var text = '';
384
385 if (entry.isBegin() && canCollapseBeginWithEnd(entry)) {
386 // Don't prefix with '+' if we are going to collapse the END event.
387 text = ' ';
388 } else if (entry.isBegin()) {
389 text = '+' + text;
390 } else if (entry.isEnd()) {
391 text = '-' + text;
392 } else {
393 text = ' ';
394 }
395
396 text += getKeyWithValue(LogEventType, entry.orig.type);
397 return text;
398 }
399
400 proxySettingsToString = function(config) {
401 if (!config)
402 return '';
403
404 // The proxy settings specify up to three major fallback choices
405 // (auto-detect, custom pac url, or manual settings).
406 // We enumerate these to a list so we can later number them.
407 var modes = [];
408
409 // Output any automatic settings.
410 if (config.auto_detect)
411 modes.push(['Auto-detect']);
412 if (config.pac_url)
413 modes.push(['PAC script: ' + config.pac_url]);
414
415 // Output any manual settings.
416 if (config.single_proxy || config.proxy_per_scheme) {
417 var lines = [];
418
419 if (config.single_proxy) {
420 lines.push('Proxy server: ' + config.single_proxy);
421 } else if (config.proxy_per_scheme) {
422 for (var urlScheme in config.proxy_per_scheme) {
423 if (urlScheme != 'fallback') {
424 lines.push('Proxy server for ' + urlScheme.toUpperCase() + ': ' +
425 config.proxy_per_scheme[urlScheme]);
426 }
427 }
428 if (config.proxy_per_scheme.fallback) {
429 lines.push('Proxy server for everything else: ' +
430 config.proxy_per_scheme.fallback);
431 }
432 }
433
434 // Output any proxy bypass rules.
435 if (config.bypass_list) {
436 if (config.reverse_bypass) {
437 lines.push('Reversed bypass list: ');
438 } else {
439 lines.push('Bypass list: ');
440 }
441
442 for (var i = 0; i < config.bypass_list.length; ++i)
443 lines.push(' ' + config.bypass_list[i]);
444 }
445
446 modes.push(lines);
447 }
448
449 // If we didn't find any proxy settings modes, we are using DIRECT.
450 if (modes.length < 1)
451 return 'Use DIRECT connections.';
452
453 // If there was just one mode, don't bother numbering it.
454 if (modes.length == 1)
455 return modes[0].join('\n');
456
457 // Otherwise concatenate all of the modes into a numbered list
458 // (which correspond with the fallback order).
459 var result = [];
460 for (var i = 0; i < modes.length; ++i)
461 result.push(indentLines('(' + (i + 1) + ') ', modes[i]));
462
463 return result.join('\n');
464 };
465
466 // End of anonymous namespace.
467 })();
468
OLDNEW
« no previous file with comments | « chrome/browser/resources/net_internals/logsview.js ('k') | chrome/browser/resources/net_internals/prerender-view.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698