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

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

Issue 2602473003: Run tools/clang-format-js on chrome/browser/resources/net_internals (Closed)
Patch Set: Created 4 years 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // TODO(eroman): put these methods into a namespace. 5 // TODO(eroman): put these methods into a namespace.
6 6
7 var createLogEntryTablePrinter; 7 var createLogEntryTablePrinter;
8 var proxySettingsToString; 8 var proxySettingsToString;
9 var stripPrivacyInfo; 9 var stripPrivacyInfo;
10 10
11 // Start of anonymous namespace. 11 // Start of anonymous namespace.
12 (function() { 12 (function() {
13 'use strict'; 13 'use strict';
14 14
15 function canCollapseBeginWithEnd(beginEntry) { 15 function canCollapseBeginWithEnd(beginEntry) {
16 return beginEntry && 16 return beginEntry && beginEntry.isBegin() && beginEntry.end &&
17 beginEntry.isBegin() && 17 beginEntry.end.index == beginEntry.index + 1 &&
18 beginEntry.end && 18 (!beginEntry.orig.params || !beginEntry.end.orig.params);
19 beginEntry.end.index == beginEntry.index + 1 && 19 }
20 (!beginEntry.orig.params || !beginEntry.end.orig.params); 20
21 } 21 /**
22 22 * Creates a TablePrinter for use by the above two functions. baseTime is
23 /** 23 * the time relative to which other times are displayed.
24 * Creates a TablePrinter for use by the above two functions. baseTime is 24 */
25 * the time relative to which other times are displayed. 25 createLogEntryTablePrinter = function(
26 */ 26 logEntries, privacyStripping, baseTime, logCreationTime) {
27 createLogEntryTablePrinter = function(logEntries, privacyStripping, 27 var entries = LogGroupEntry.createArrayFrom(logEntries);
28 baseTime, logCreationTime) { 28 var tablePrinter = new TablePrinter();
29 var entries = LogGroupEntry.createArrayFrom(logEntries); 29 var parameterOutputter = new ParameterOutputter(tablePrinter);
30 var tablePrinter = new TablePrinter(); 30
31 var parameterOutputter = new ParameterOutputter(tablePrinter); 31 if (entries.length == 0)
32 32 return tablePrinter;
33 if (entries.length == 0) 33
34 var startTime = timeutil.convertTimeTicksToTime(entries[0].orig.time);
35
36 for (var i = 0; i < entries.length; ++i) {
37 var entry = entries[i];
38
39 // Avoid printing the END for a BEGIN that was immediately before, unless
40 // both have extra parameters.
41 if (!entry.isEnd() || !canCollapseBeginWithEnd(entry.begin)) {
42 var entryTime = timeutil.convertTimeTicksToTime(entry.orig.time);
43 addRowWithTime(
44 tablePrinter, entryTime - baseTime, startTime - baseTime);
45
46 for (var j = entry.getDepth(); j > 0; --j)
47 tablePrinter.addCell(' ');
48
49 var eventText = getTextForEvent(entry);
50 // Get the elapsed time, and append it to the event text.
51 if (entry.isBegin()) {
52 var dt = '?';
53 // Definite time.
54 if (entry.end) {
55 dt = entry.end.orig.time - entry.orig.time;
56 } else if (logCreationTime != undefined) {
57 dt = (logCreationTime - entryTime) + '+';
58 }
59 eventText += ' [dt=' + dt + ']';
60 }
61
62 var mainCell = tablePrinter.addCell(eventText);
63 mainCell.allowOverflow = true;
64 }
65
66 // Output the extra parameters.
67 if (typeof entry.orig.params == 'object') {
68 // Those 5 skipped cells are: two for "t=", and three for "st=".
69 tablePrinter.setNewRowCellIndent(5 + entry.getDepth());
70 writeParameters(entry.orig, privacyStripping, parameterOutputter);
71
72 tablePrinter.setNewRowCellIndent(0);
73 }
74 }
75
76 // If viewing a saved log file, add row with just the time the log was
77 // created, if the event never completed.
78 var lastEntry = entries[entries.length - 1];
79 // If the last entry has a non-zero depth or is a begin event, the source is
80 // still active.
81 var isSourceActive = lastEntry.getDepth() != 0 || lastEntry.isBegin();
82 if (logCreationTime != undefined && isSourceActive) {
83 addRowWithTime(
84 tablePrinter, logCreationTime - baseTime, startTime - baseTime);
85 }
86
34 return tablePrinter; 87 return tablePrinter;
35 88 };
36 var startTime = timeutil.convertTimeTicksToTime(entries[0].orig.time); 89
37 90 /**
38 for (var i = 0; i < entries.length; ++i) { 91 * Adds a new row to the given TablePrinter, and adds five cells containing
39 var entry = entries[i]; 92 * information about the time an event occured.
40 93 * Format is '[t=<time of the event in ms>] [st=<ms since the source
41 // Avoid printing the END for a BEGIN that was immediately before, unless 94 * started>]'.
42 // both have extra parameters. 95 * @param {TablePrinter} tablePrinter The table printer to add the cells to.
43 if (!entry.isEnd() || !canCollapseBeginWithEnd(entry.begin)) { 96 * @param {number} eventTime The time the event occured, in milliseconds,
44 var entryTime = timeutil.convertTimeTicksToTime(entry.orig.time); 97 * relative to some base time.
45 addRowWithTime(tablePrinter, entryTime - baseTime, startTime - baseTime); 98 * @param {number} startTime The time the first event for the source occured,
46 99 * relative to the same base time as eventTime.
47 for (var j = entry.getDepth(); j > 0; --j) 100 */
48 tablePrinter.addCell(' '); 101 function addRowWithTime(tablePrinter, eventTime, startTime) {
49 102 tablePrinter.addRow();
50 var eventText = getTextForEvent(entry); 103 tablePrinter.addCell('t=');
51 // Get the elapsed time, and append it to the event text. 104 var tCell = tablePrinter.addCell(eventTime);
52 if (entry.isBegin()) { 105 tCell.alignRight = true;
53 var dt = '?'; 106 tablePrinter.addCell(' [st=');
54 // Definite time. 107 var stCell = tablePrinter.addCell(eventTime - startTime);
55 if (entry.end) { 108 stCell.alignRight = true;
56 dt = entry.end.orig.time - entry.orig.time; 109 tablePrinter.addCell('] ');
57 } else if (logCreationTime != undefined) { 110 }
58 dt = (logCreationTime - entryTime) + '+'; 111
112 /**
113 * |hexString| must be a string of hexadecimal characters with no whitespace,
114 * whose length is a multiple of two. Writes multiple lines to |out| with
115 * the hexadecimal characters from |hexString| on the left, in groups of
116 * two, and their corresponding ASCII characters on the right.
117 *
118 * 16 bytes will be placed on each line of the output string, split into two
119 * columns of 8.
120 */
121 function writeHexString(hexString, out) {
122 var asciiCharsPerLine = 16;
123 // Number of transferred bytes in a line of output. Length of a
124 // line is roughly 4 times larger.
125 var hexCharsPerLine = 2 * asciiCharsPerLine;
126 for (var i = 0; i < hexString.length; i += hexCharsPerLine) {
127 var hexLine = '';
128 var asciiLine = '';
129 for (var j = i; j < i + hexCharsPerLine && j < hexString.length; j += 2) {
130 // Split into two columns of 8 bytes each.
131 if (j == i + hexCharsPerLine / 2)
132 hexLine += ' ';
133 var hex = hexString.substr(j, 2);
134 hexLine += hex + ' ';
135 var charCode = parseInt(hex, 16);
136 // For ASCII codes 32 though 126, display the corresponding
137 // characters. Use a space for nulls, and a period for
138 // everything else.
139 if (charCode >= 0x20 && charCode <= 0x7E) {
140 asciiLine += String.fromCharCode(charCode);
141 } else if (charCode == 0x00) {
142 asciiLine += ' ';
143 } else {
144 asciiLine += '.';
59 } 145 }
60 eventText += ' [dt=' + dt + ']'; 146 }
61 } 147
62 148 // Make the ASCII text for the last line of output align with the previous
63 var mainCell = tablePrinter.addCell(eventText); 149 // lines.
64 mainCell.allowOverflow = true; 150 hexLine +=
65 } 151 makeRepeatedString(' ', 3 * asciiCharsPerLine + 1 - hexLine.length);
66 152 out.writeLine(' ' + hexLine + ' ' + asciiLine);
67 // Output the extra parameters. 153 }
68 if (typeof entry.orig.params == 'object') { 154 }
69 // Those 5 skipped cells are: two for "t=", and three for "st=". 155
70 tablePrinter.setNewRowCellIndent(5 + entry.getDepth()); 156 /**
71 writeParameters(entry.orig, privacyStripping, parameterOutputter); 157 * Wrapper around a TablePrinter to simplify outputting lines of text for
72 158 * event
73 tablePrinter.setNewRowCellIndent(0); 159 * parameters.
74 } 160 */
75 } 161 var ParameterOutputter = (function() {
76
77 // If viewing a saved log file, add row with just the time the log was
78 // created, if the event never completed.
79 var lastEntry = entries[entries.length - 1];
80 // If the last entry has a non-zero depth or is a begin event, the source is
81 // still active.
82 var isSourceActive = lastEntry.getDepth() != 0 || lastEntry.isBegin();
83 if (logCreationTime != undefined && isSourceActive) {
84 addRowWithTime(tablePrinter,
85 logCreationTime - baseTime,
86 startTime - baseTime);
87 }
88
89 return tablePrinter;
90 };
91
92 /**
93 * Adds a new row to the given TablePrinter, and adds five cells containing
94 * information about the time an event occured.
95 * Format is '[t=<time of the event in ms>] [st=<ms since the source started>]'.
96 * @param {TablePrinter} tablePrinter The table printer to add the cells to.
97 * @param {number} eventTime The time the event occured, in milliseconds,
98 * relative to some base time.
99 * @param {number} startTime The time the first event for the source occured,
100 * relative to the same base time as eventTime.
101 */
102 function addRowWithTime(tablePrinter, eventTime, startTime) {
103 tablePrinter.addRow();
104 tablePrinter.addCell('t=');
105 var tCell = tablePrinter.addCell(eventTime);
106 tCell.alignRight = true;
107 tablePrinter.addCell(' [st=');
108 var stCell = tablePrinter.addCell(eventTime - startTime);
109 stCell.alignRight = true;
110 tablePrinter.addCell('] ');
111 }
112
113 /**
114 * |hexString| must be a string of hexadecimal characters with no whitespace,
115 * whose length is a multiple of two. Writes multiple lines to |out| with
116 * the hexadecimal characters from |hexString| on the left, in groups of
117 * two, and their corresponding ASCII characters on the right.
118 *
119 * 16 bytes will be placed on each line of the output string, split into two
120 * columns of 8.
121 */
122 function writeHexString(hexString, out) {
123 var asciiCharsPerLine = 16;
124 // Number of transferred bytes in a line of output. Length of a
125 // line is roughly 4 times larger.
126 var hexCharsPerLine = 2 * asciiCharsPerLine;
127 for (var i = 0; i < hexString.length; i += hexCharsPerLine) {
128 var hexLine = '';
129 var asciiLine = '';
130 for (var j = i; j < i + hexCharsPerLine && j < hexString.length; j += 2) {
131 // Split into two columns of 8 bytes each.
132 if (j == i + hexCharsPerLine / 2)
133 hexLine += ' ';
134 var hex = hexString.substr(j, 2);
135 hexLine += hex + ' ';
136 var charCode = parseInt(hex, 16);
137 // For ASCII codes 32 though 126, display the corresponding
138 // characters. Use a space for nulls, and a period for
139 // everything else.
140 if (charCode >= 0x20 && charCode <= 0x7E) {
141 asciiLine += String.fromCharCode(charCode);
142 } else if (charCode == 0x00) {
143 asciiLine += ' ';
144 } else {
145 asciiLine += '.';
146 }
147 }
148
149 // Make the ASCII text for the last line of output align with the previous
150 // lines.
151 hexLine += makeRepeatedString(' ',
152 3 * asciiCharsPerLine + 1 - hexLine.length);
153 out.writeLine(' ' + hexLine + ' ' + asciiLine);
154 }
155 }
156
157 /**
158 * Wrapper around a TablePrinter to simplify outputting lines of text for event
159 * parameters.
160 */
161 var ParameterOutputter = (function() {
162 /**
163 * @constructor
164 */
165 function ParameterOutputter(tablePrinter) {
166 this.tablePrinter_ = tablePrinter;
167 }
168
169 ParameterOutputter.prototype = {
170 /** 162 /**
171 * Outputs a single line. 163 * @constructor
172 */ 164 */
173 writeLine: function(line) { 165 function ParameterOutputter(tablePrinter) {
174 this.tablePrinter_.addRow(); 166 this.tablePrinter_ = tablePrinter;
175 var cell = this.tablePrinter_.addCell(line); 167 }
176 cell.allowOverflow = true; 168
177 return cell; 169 ParameterOutputter.prototype = {
178 }, 170 /**
179 171 * Outputs a single line.
180 /** 172 */
181 * Outputs a key=value line which looks like: 173 writeLine: function(line) {
182 * 174 this.tablePrinter_.addRow();
183 * --> key = value 175 var cell = this.tablePrinter_.addCell(line);
184 */ 176 cell.allowOverflow = true;
185 writeArrowKeyValue: function(key, value, link) { 177 return cell;
186 var cell = this.writeLine(kArrow + key + ' = ' + value); 178 },
187 cell.link = link; 179
188 }, 180 /**
189 181 * Outputs a key=value line which looks like:
190 /** 182 *
191 * Outputs a key= line which looks like: 183 * --> key = value
192 * 184 */
193 * --> key = 185 writeArrowKeyValue: function(key, value, link) {
194 */ 186 var cell = this.writeLine(kArrow + key + ' = ' + value);
195 writeArrowKey: function(key) { 187 cell.link = link;
196 this.writeLine(kArrow + key + ' ='); 188 },
197 }, 189
198 190 /**
199 /** 191 * Outputs a key= line which looks like:
200 * Outputs multiple lines, each indented by numSpaces. 192 *
201 * For instance if numSpaces=8 it might look like this: 193 * --> key =
202 * 194 */
203 * line 1 195 writeArrowKey: function(key) {
204 * line 2 196 this.writeLine(kArrow + key + ' =');
205 * line 3 197 },
206 */ 198
207 writeSpaceIndentedLines: function(numSpaces, lines) { 199 /**
208 var prefix = makeRepeatedString(' ', numSpaces); 200 * Outputs multiple lines, each indented by numSpaces.
209 for (var i = 0; i < lines.length; ++i) 201 * For instance if numSpaces=8 it might look like this:
210 this.writeLine(prefix + lines[i]); 202 *
211 }, 203 * line 1
212 204 * line 2
213 /** 205 * line 3
214 * Outputs multiple lines such that the first line has 206 */
215 * an arrow pointing at it, and subsequent lines 207 writeSpaceIndentedLines: function(numSpaces, lines) {
216 * align with the first one. For example: 208 var prefix = makeRepeatedString(' ', numSpaces);
217 * 209 for (var i = 0; i < lines.length; ++i)
218 * --> line 1 210 this.writeLine(prefix + lines[i]);
219 * line 2 211 },
220 * line 3 212
221 */ 213 /**
222 writeArrowIndentedLines: function(lines) { 214 * Outputs multiple lines such that the first line has
223 if (lines.length == 0) 215 * an arrow pointing at it, and subsequent lines
224 return; 216 * align with the first one. For example:
225 217 *
226 this.writeLine(kArrow + lines[0]); 218 * --> line 1
227 219 * line 2
228 for (var i = 1; i < lines.length; ++i) 220 * line 3
229 this.writeLine(kArrowIndentation + lines[i]); 221 */
230 } 222 writeArrowIndentedLines: function(lines) {
231 }; 223 if (lines.length == 0)
232 224 return;
233 var kArrow = ' --> '; 225
234 var kArrowIndentation = ' '; 226 this.writeLine(kArrow + lines[0]);
235 227
236 return ParameterOutputter; 228 for (var i = 1; i < lines.length; ++i)
237 })(); // end of ParameterOutputter 229 this.writeLine(kArrowIndentation + lines[i]);
238 230 }
239 /** 231 };
240 * Formats the parameters for |entry| and writes them to |out|. 232
241 * Certain event types have custom pretty printers. Everything else will 233 var kArrow = ' --> ';
242 * default to a JSON-like format. 234 var kArrowIndentation = ' ';
243 */ 235
244 function writeParameters(entry, privacyStripping, out) { 236 return ParameterOutputter;
245 if (privacyStripping) { 237 })(); // end of ParameterOutputter
246 // If privacy stripping is enabled, remove data as needed. 238
247 entry = stripPrivacyInfo(entry); 239 /**
248 } else { 240 * Formats the parameters for |entry| and writes them to |out|.
249 // If headers are in an object, convert them to an array for better display. 241 * Certain event types have custom pretty printers. Everything else will
250 entry = reformatHeaders(entry); 242 * default to a JSON-like format.
251 } 243 */
252 244 function writeParameters(entry, privacyStripping, out) {
253 // Use any parameter writer available for this event type. 245 if (privacyStripping) {
254 var paramsWriter = getParameterWriterForEventType(entry.type); 246 // If privacy stripping is enabled, remove data as needed.
255 var consumedParams = {}; 247 entry = stripPrivacyInfo(entry);
256 if (paramsWriter) 248 } else {
257 paramsWriter(entry, out, consumedParams); 249 // If headers are in an object, convert them to an array for better
258 250 // display.
259 // Write any un-consumed parameters. 251 entry = reformatHeaders(entry);
260 for (var k in entry.params) { 252 }
261 if (consumedParams[k]) 253
262 continue; 254 // Use any parameter writer available for this event type.
263 defaultWriteParameter(k, entry.params[k], out); 255 var paramsWriter = getParameterWriterForEventType(entry.type);
264 } 256 var consumedParams = {};
265 } 257 if (paramsWriter)
266 258 paramsWriter(entry, out, consumedParams);
267 /** 259
260 // Write any un-consumed parameters.
261 for (var k in entry.params) {
262 if (consumedParams[k])
263 continue;
264 defaultWriteParameter(k, entry.params[k], out);
265 }
266 }
267
268 /**
268 * Finds a writer to format the parameters for events of type |eventType|. 269 * Finds a writer to format the parameters for events of type |eventType|.
269 * 270 *
270 * @return {function} The returned function "writer" can be invoked 271 * @return {function} The returned function "writer" can be invoked
271 * as |writer(entry, writer, consumedParams)|. It will 272 * as |writer(entry, writer, consumedParams)|. It will
272 * output the parameters of |entry| to |out|, and fill 273 * output the parameters of |entry| to |out|, and fill
273 * |consumedParams| with the keys of the parameters 274 * |consumedParams| with the keys of the parameters
274 * consumed. If no writer is available for |eventType| then 275 * consumed. If no writer is available for |eventType| then
275 * returns null. 276 * returns null.
276 */ 277 */
277 function getParameterWriterForEventType(eventType) { 278 function getParameterWriterForEventType(eventType) {
278 switch (eventType) { 279 switch (eventType) {
279 case EventType.HTTP_TRANSACTION_SEND_REQUEST_HEADERS: 280 case EventType.HTTP_TRANSACTION_SEND_REQUEST_HEADERS:
280 case EventType.HTTP_TRANSACTION_SEND_TUNNEL_HEADERS: 281 case EventType.HTTP_TRANSACTION_SEND_TUNNEL_HEADERS:
281 case EventType.TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS: 282 case EventType.TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS:
282 return writeParamsForRequestHeaders; 283 return writeParamsForRequestHeaders;
283 284
284 case EventType.PROXY_CONFIG_CHANGED: 285 case EventType.PROXY_CONFIG_CHANGED:
285 return writeParamsForProxyConfigChanged; 286 return writeParamsForProxyConfigChanged;
286 287
287 case EventType.CERT_VERIFIER_JOB: 288 case EventType.CERT_VERIFIER_JOB:
288 case EventType.SSL_CERTIFICATES_RECEIVED: 289 case EventType.SSL_CERTIFICATES_RECEIVED:
289 return writeParamsForCertificates; 290 return writeParamsForCertificates;
290 case EventType.CERT_CT_COMPLIANCE_CHECKED: 291 case EventType.CERT_CT_COMPLIANCE_CHECKED:
291 case EventType.EV_CERT_CT_COMPLIANCE_CHECKED: 292 case EventType.EV_CERT_CT_COMPLIANCE_CHECKED:
292 return writeParamsForCheckedCertificates; 293 return writeParamsForCheckedCertificates;
293 294
294 case EventType.SSL_VERSION_FALLBACK: 295 case EventType.SSL_VERSION_FALLBACK:
295 return writeParamsForSSLVersionFallback; 296 return writeParamsForSSLVersionFallback;
296 } 297 }
297 return null; 298 return null;
298 } 299 }
299 300
300 /** 301 /**
301 * Default parameter writer that outputs a visualization of field named |key| 302 * Default parameter writer that outputs a visualization of field named |key|
302 * with value |value| to |out|. 303 * with value |value| to |out|.
303 */ 304 */
304 function defaultWriteParameter(key, value, out) { 305 function defaultWriteParameter(key, value, out) {
305 if (key == 'headers' && value instanceof Array) { 306 if (key == 'headers' && value instanceof Array) {
306 out.writeArrowIndentedLines(value); 307 out.writeArrowIndentedLines(value);
307 return; 308 return;
308 } 309 }
309 310
310 // For transferred bytes, display the bytes in hex and ASCII. 311 // For transferred bytes, display the bytes in hex and ASCII.
311 if (key == 'hex_encoded_bytes' && typeof value == 'string') { 312 if (key == 'hex_encoded_bytes' && typeof value == 'string') {
312 out.writeArrowKey(key); 313 out.writeArrowKey(key);
313 writeHexString(value, out); 314 writeHexString(value, out);
314 return; 315 return;
315 } 316 }
316 317
317 // Handle source_dependency entries - add link and map source type to 318 // Handle source_dependency entries - add link and map source type to
318 // string. 319 // string.
319 if (key == 'source_dependency' && typeof value == 'object') { 320 if (key == 'source_dependency' && typeof value == 'object') {
320 var link = '#events&s=' + value.id; 321 var link = '#events&s=' + value.id;
321 var valueStr = value.id + ' (' + EventSourceTypeNames[value.type] + ')'; 322 var valueStr = value.id + ' (' + EventSourceTypeNames[value.type] + ')';
322 out.writeArrowKeyValue(key, valueStr, link); 323 out.writeArrowKeyValue(key, valueStr, link);
323 return; 324 return;
324 } 325 }
325 326
326 if (key == 'net_error' && typeof value == 'number') { 327 if (key == 'net_error' && typeof value == 'number') {
327 var valueStr = value + ' (' + netErrorToString(value) + ')'; 328 var valueStr = value + ' (' + netErrorToString(value) + ')';
328 out.writeArrowKeyValue(key, valueStr); 329 out.writeArrowKeyValue(key, valueStr);
329 return; 330 return;
330 } 331 }
331 332
332 if (key == 'quic_error' && typeof value == 'number') { 333 if (key == 'quic_error' && typeof value == 'number') {
333 var valueStr = value + ' (' + quicErrorToString(value) + ')'; 334 var valueStr = value + ' (' + quicErrorToString(value) + ')';
334 out.writeArrowKeyValue(key, valueStr); 335 out.writeArrowKeyValue(key, valueStr);
335 return; 336 return;
336 } 337 }
337 338
338 if (key == 'quic_crypto_handshake_message' && typeof value == 'string') { 339 if (key == 'quic_crypto_handshake_message' && typeof value == 'string') {
339 var lines = value.split('\n'); 340 var lines = value.split('\n');
340 out.writeArrowIndentedLines(lines); 341 out.writeArrowIndentedLines(lines);
341 return; 342 return;
342 } 343 }
343 344
344 if (key == 'quic_rst_stream_error' && typeof value == 'number') { 345 if (key == 'quic_rst_stream_error' && typeof value == 'number') {
345 var valueStr = value + ' (' + quicRstStreamErrorToString(value) + ')'; 346 var valueStr = value + ' (' + quicRstStreamErrorToString(value) + ')';
346 out.writeArrowKeyValue(key, valueStr); 347 out.writeArrowKeyValue(key, valueStr);
347 return; 348 return;
348 } 349 }
349 350
350 if (key == 'load_flags' && typeof value == 'number') { 351 if (key == 'load_flags' && typeof value == 'number') {
351 var valueStr = value + ' (' + getLoadFlagSymbolicString(value) + ')'; 352 var valueStr = value + ' (' + getLoadFlagSymbolicString(value) + ')';
352 out.writeArrowKeyValue(key, valueStr); 353 out.writeArrowKeyValue(key, valueStr);
353 return; 354 return;
354 } 355 }
355 356
356 if (key == 'load_state' && typeof value == 'number') { 357 if (key == 'load_state' && typeof value == 'number') {
357 var valueStr = value + ' (' + getKeyWithValue(LoadState, value) + ')'; 358 var valueStr = value + ' (' + getKeyWithValue(LoadState, value) + ')';
358 out.writeArrowKeyValue(key, valueStr); 359 out.writeArrowKeyValue(key, valueStr);
359 return; 360 return;
360 } 361 }
361 362
362 if (key == 'sdch_problem_code' && typeof value == 'number') { 363 if (key == 'sdch_problem_code' && typeof value == 'number') {
363 var valueStr = value + ' (' + sdchProblemCodeToString(value) + ')'; 364 var valueStr = value + ' (' + sdchProblemCodeToString(value) + ')';
364 out.writeArrowKeyValue(key, valueStr); 365 out.writeArrowKeyValue(key, valueStr);
365 return; 366 return;
366 } 367 }
367 368
368 // Otherwise just default to JSON formatting of the value. 369 // Otherwise just default to JSON formatting of the value.
369 out.writeArrowKeyValue(key, JSON.stringify(value)); 370 out.writeArrowKeyValue(key, JSON.stringify(value));
370 } 371 }
371 372
372 /** 373 /**
373 * Returns the set of LoadFlags that make up the integer |loadFlag|. 374 * Returns the set of LoadFlags that make up the integer |loadFlag|.
374 * For example: getLoadFlagSymbolicString( 375 * For example: getLoadFlagSymbolicString(
375 */ 376 */
376 function getLoadFlagSymbolicString(loadFlag) { 377 function getLoadFlagSymbolicString(loadFlag) {
377 378 return getSymbolicString(
378 return getSymbolicString(loadFlag, LoadFlag, 379 loadFlag, LoadFlag, getKeyWithValue(LoadFlag, loadFlag));
379 getKeyWithValue(LoadFlag, loadFlag)); 380 }
380 } 381
381 382 /**
382 /** 383 * Returns the set of CertStatusFlags that make up the integer
383 * Returns the set of CertStatusFlags that make up the integer |certStatusFlag| 384 * |certStatusFlag|
384 */ 385 */
385 function getCertStatusFlagSymbolicString(certStatusFlag) { 386 function getCertStatusFlagSymbolicString(certStatusFlag) {
386 return getSymbolicString(certStatusFlag, CertStatusFlag, ''); 387 return getSymbolicString(certStatusFlag, CertStatusFlag, '');
387 } 388 }
388 389
389 /** 390 /**
390 * Returns a string representing the flags composing the given bitmask. 391 * Returns a string representing the flags composing the given bitmask.
391 */ 392 */
392 function getSymbolicString(bitmask, valueToName, zeroName) { 393 function getSymbolicString(bitmask, valueToName, zeroName) {
393 var matchingFlagNames = []; 394 var matchingFlagNames = [];
394 395
395 for (var k in valueToName) { 396 for (var k in valueToName) {
396 if (bitmask & valueToName[k]) 397 if (bitmask & valueToName[k])
397 matchingFlagNames.push(k); 398 matchingFlagNames.push(k);
398 } 399 }
399 400
400 // If no flags were matched, returns a special value. 401 // If no flags were matched, returns a special value.
401 if (matchingFlagNames.length == 0) 402 if (matchingFlagNames.length == 0)
402 return zeroName; 403 return zeroName;
403 404
404 return matchingFlagNames.join(' | '); 405 return matchingFlagNames.join(' | ');
405 } 406 }
406 407
407 /** 408 /**
408 * Converts an SSL version number to a textual representation. 409 * Converts an SSL version number to a textual representation.
409 * For instance, SSLVersionNumberToName(0x0301) returns 'TLS 1.0'. 410 * For instance, SSLVersionNumberToName(0x0301) returns 'TLS 1.0'.
410 */ 411 */
411 function SSLVersionNumberToName(version) { 412 function SSLVersionNumberToName(version) {
412 if ((version & 0xFFFF) != version) { 413 if ((version & 0xFFFF) != version) {
413 // If the version number is more than 2 bytes long something is wrong. 414 // If the version number is more than 2 bytes long something is wrong.
414 // Print it as hex. 415 // Print it as hex.
415 return 'SSL 0x' + version.toString(16); 416 return 'SSL 0x' + version.toString(16);
416 } 417 }
417 418
418 // See if it is a known TLS name. 419 // See if it is a known TLS name.
419 var kTLSNames = { 420 var kTLSNames = {0x0301: 'TLS 1.0', 0x0302: 'TLS 1.1', 0x0303: 'TLS 1.2'};
420 0x0301: 'TLS 1.0', 421 var name = kTLSNames[version];
421 0x0302: 'TLS 1.1', 422 if (name)
422 0x0303: 'TLS 1.2' 423 return name;
423 }; 424
424 var name = kTLSNames[version]; 425 // Otherwise label it as an SSL version.
425 if (name) 426 var major = (version & 0xFF00) >> 8;
426 return name; 427 var minor = version & 0x00FF;
427 428
428 // Otherwise label it as an SSL version. 429 return 'SSL ' + major + '.' + minor;
429 var major = (version & 0xFF00) >> 8; 430 }
430 var minor = version & 0x00FF; 431
431 432 /**
432 return 'SSL ' + major + '.' + minor; 433 * TODO(eroman): get rid of this, as it is only used by 1 callsite.
433 } 434 *
434 435 * Indent |lines| by |start|.
435 /** 436 *
436 * TODO(eroman): get rid of this, as it is only used by 1 callsite. 437 * For example, if |start| = ' -> ' and |lines| = ['line1', 'line2', 'line3']
437 * 438 * the output will be:
438 * Indent |lines| by |start|. 439 *
439 * 440 * " -> line1\n" +
440 * For example, if |start| = ' -> ' and |lines| = ['line1', 'line2', 'line3'] 441 * " line2\n" +
441 * the output will be: 442 * " line3"
442 * 443 */
443 * " -> line1\n" + 444 function indentLines(start, lines) {
444 * " line2\n" + 445 return start + lines.join('\n' + makeRepeatedString(' ', start.length));
445 * " line3" 446 }
446 */ 447
447 function indentLines(start, lines) { 448 /**
448 return start + lines.join('\n' + makeRepeatedString(' ', start.length)); 449 * If entry.param.headers exists and is an object other than an array,
449 } 450 * converts
450 451 * it into an array and returns a new entry. Otherwise, just returns the
451 /** 452 * original entry.
452 * If entry.param.headers exists and is an object other than an array, converts 453 */
453 * it into an array and returns a new entry. Otherwise, just returns the 454 function reformatHeaders(entry) {
454 * original entry. 455 // If there are no headers, or it is not an object other than an array,
455 */ 456 // return |entry| without modification.
456 function reformatHeaders(entry) { 457 if (!entry.params || entry.params.headers === undefined ||
457 // If there are no headers, or it is not an object other than an array, 458 typeof entry.params.headers != 'object' ||
458 // return |entry| without modification. 459 entry.params.headers instanceof Array) {
459 if (!entry.params || entry.params.headers === undefined || 460 return entry;
460 typeof entry.params.headers != 'object' || 461 }
461 entry.params.headers instanceof Array) { 462
463 // Duplicate the top level object, and |entry.params|, so the original
464 // object
465 // will not be modified.
466 entry = shallowCloneObject(entry);
467 entry.params = shallowCloneObject(entry.params);
468
469 // Convert headers to an array.
470 var headers = [];
471 for (var key in entry.params.headers)
472 headers.push(key + ': ' + entry.params.headers[key]);
473 entry.params.headers = headers;
474
462 return entry; 475 return entry;
463 } 476 }
464 477
465 // Duplicate the top level object, and |entry.params|, so the original object 478 /**
466 // will not be modified. 479 * Removes a cookie or unencrypted login information from a single HTTP header
467 entry = shallowCloneObject(entry); 480 * line, if present, and returns the modified line. Otherwise, just returns
468 entry.params = shallowCloneObject(entry.params); 481 * the original line.
469 482 *
470 // Convert headers to an array. 483 * Note: this logic should be kept in sync with
471 var headers = []; 484 * net::ElideHeaderValueForNetLog in net/http/http_log_util.cc.
472 for (var key in entry.params.headers) 485 */
473 headers.push(key + ': ' + entry.params.headers[key]); 486 function stripCookieOrLoginInfo(line) {
474 entry.params.headers = headers; 487 var patterns = [
475
476 return entry;
477 }
478
479 /**
480 * Removes a cookie or unencrypted login information from a single HTTP header
481 * line, if present, and returns the modified line. Otherwise, just returns
482 * the original line.
483 *
484 * Note: this logic should be kept in sync with
485 * net::ElideHeaderValueForNetLog in net/http/http_log_util.cc.
486 */
487 function stripCookieOrLoginInfo(line) {
488 var patterns = [
489 // Cookie patterns 488 // Cookie patterns
490 /^set-cookie: /i, 489 /^set-cookie: /i, /^set-cookie2: /i, /^cookie: /i,
491 /^set-cookie2: /i,
492 /^cookie: /i,
493 490
494 // Unencrypted authentication patterns 491 // Unencrypted authentication patterns
495 /^authorization: \S*\s*/i, 492 /^authorization: \S*\s*/i, /^proxy-authorization: \S*\s*/i
496 /^proxy-authorization: \S*\s*/i]; 493 ];
497 494
498 // Prefix will hold the first part of the string that contains no private 495 // Prefix will hold the first part of the string that contains no private
499 // information. If null, no part of the string contains private information. 496 // information. If null, no part of the string contains private
500 var prefix = null; 497 // information.
501 for (var i = 0; i < patterns.length; i++) { 498 var prefix = null;
502 var match = patterns[i].exec(line); 499 for (var i = 0; i < patterns.length; i++) {
503 if (match != null) { 500 var match = patterns[i].exec(line);
504 prefix = match[0]; 501 if (match != null) {
505 break; 502 prefix = match[0];
506 }
507 }
508
509 // Look for authentication information from data received from the server in
510 // multi-round Negotiate authentication.
511 if (prefix === null) {
512 var challengePatterns = [
513 /^www-authenticate: (\S*)\s*/i,
514 /^proxy-authenticate: (\S*)\s*/i];
515 for (var i = 0; i < challengePatterns.length; i++) {
516 var match = challengePatterns[i].exec(line);
517 if (!match)
518 continue;
519
520 // If there's no data after the scheme name, do nothing.
521 if (match[0].length == line.length)
522 break; 503 break;
523 504 }
524 // Ignore lines with commas, as they may contain lists of schemes, and 505 }
525 // the information we want to hide is Base64 encoded, so has no commas. 506
526 if (line.indexOf(',') >= 0) 507 // Look for authentication information from data received from the server in
508 // multi-round Negotiate authentication.
509 if (prefix === null) {
510 var challengePatterns =
511 [/^www-authenticate: (\S*)\s*/i, /^proxy-authenticate: (\S*)\s*/i];
512 for (var i = 0; i < challengePatterns.length; i++) {
513 var match = challengePatterns[i].exec(line);
514 if (!match)
515 continue;
516
517 // If there's no data after the scheme name, do nothing.
518 if (match[0].length == line.length)
519 break;
520
521 // Ignore lines with commas, as they may contain lists of schemes, and
522 // the information we want to hide is Base64 encoded, so has no commas.
523 if (line.indexOf(',') >= 0)
524 break;
525
526 // Ignore Basic and Digest authentication challenges, as they contain
527 // public information.
528 if (/^basic$/i.test(match[1]) || /^digest$/i.test(match[1]))
529 break;
530
531 prefix = match[0];
527 break; 532 break;
528 533 }
529 // Ignore Basic and Digest authentication challenges, as they contain 534 }
530 // public information. 535
531 if (/^basic$/i.test(match[1]) || /^digest$/i.test(match[1])) 536 if (prefix) {
532 break; 537 var suffix = line.slice(prefix.length);
533 538 // If private information has already been removed, keep the line as-is.
534 prefix = match[0]; 539 // This is often the case when viewing a loaded log.
535 break; 540 if (suffix.search(/^\[[0-9]+ bytes were stripped\]$/) == -1) {
536 } 541 return prefix + '[' + suffix.length + ' bytes were stripped]';
537 } 542 }
538 543 }
539 if (prefix) { 544
540 var suffix = line.slice(prefix.length); 545 return line;
541 // If private information has already been removed, keep the line as-is. 546 }
542 // This is often the case when viewing a loaded log. 547
543 if (suffix.search(/^\[[0-9]+ bytes were stripped\]$/) == -1) { 548 /**
544 return prefix + '[' + suffix.length + ' bytes were stripped]'; 549 * Remove debug data from HTTP/2 GOAWAY frame due to privacy considerations,
545 } 550 * see
546 } 551 * https://httpwg.github.io/specs/rfc7540.html#GOAWAY.
547 552 *
548 return line; 553 * Note: this logic should be kept in sync with
549 } 554 * net::ElideGoAwayDebugDataForNetLog in net/http/http_log_util.cc.
550 555 */
551 /** 556 function stripGoAwayDebugData(value) {
552 * Remove debug data from HTTP/2 GOAWAY frame due to privacy considerations, see 557 return '[' + value.length + ' bytes were stripped]';
553 * https://httpwg.github.io/specs/rfc7540.html#GOAWAY. 558 }
554 * 559
555 * Note: this logic should be kept in sync with 560 /**
556 * net::ElideGoAwayDebugDataForNetLog in net/http/http_log_util.cc. 561 * If |entry| has headers, returns a copy of |entry| with all cookie and
557 */ 562 * unencrypted login text removed. Otherwise, returns original |entry|
558 function stripGoAwayDebugData(value) { 563 * object.
559 return '[' + value.length + ' bytes were stripped]'; 564 * This is needed so that JSON log dumps can be made without affecting the
560 } 565 * source data. Converts headers stored in objects to arrays.
561 566 */
562 /** 567 stripPrivacyInfo = function(entry) {
563 * If |entry| has headers, returns a copy of |entry| with all cookie and 568 if (!entry.params) {
564 * unencrypted login text removed. Otherwise, returns original |entry| object. 569 return entry;
565 * This is needed so that JSON log dumps can be made without affecting the 570 }
566 * source data. Converts headers stored in objects to arrays. 571
567 */ 572 if (entry.type == EventType.HTTP2_SESSION_GOAWAY &&
568 stripPrivacyInfo = function(entry) { 573 entry.params.debug_data != undefined) {
569 if (!entry.params) { 574 // Duplicate the top level object, and |entry.params|. All other fields
570 return entry; 575 // are
571 } 576 // just pointers to the original values, as they won't be modified, other
572 577 // than |entry.params.debug_data|.
573 if (entry.type == EventType.HTTP2_SESSION_GOAWAY && 578 entry = shallowCloneObject(entry);
574 entry.params.debug_data != undefined) { 579 entry.params = shallowCloneObject(entry.params);
580 entry.params.debug_data = stripGoAwayDebugData(entry.params.debug_data);
581 return entry;
582 }
583
584 if (entry.params.headers === undefined ||
585 !(entry.params.headers instanceof Object)) {
586 return entry;
587 }
588
589 // Make sure entry's headers are in an array.
590 entry = reformatHeaders(entry);
591
575 // Duplicate the top level object, and |entry.params|. All other fields are 592 // Duplicate the top level object, and |entry.params|. All other fields are
576 // just pointers to the original values, as they won't be modified, other 593 // just pointers to the original values, as they won't be modified, other
577 // than |entry.params.debug_data|. 594 // than
595 // |entry.params.headers|.
578 entry = shallowCloneObject(entry); 596 entry = shallowCloneObject(entry);
579 entry.params = shallowCloneObject(entry.params); 597 entry.params = shallowCloneObject(entry.params);
580 entry.params.debug_data = 598
581 stripGoAwayDebugData(entry.params.debug_data); 599 entry.params.headers = entry.params.headers.map(stripCookieOrLoginInfo);
582 return entry; 600 return entry;
583 } 601 };
584 602
585 if (entry.params.headers === undefined || 603 /**
586 !(entry.params.headers instanceof Object)) { 604 * Outputs the request header parameters of |entry| to |out|.
587 return entry; 605 */
588 } 606 function writeParamsForRequestHeaders(entry, out, consumedParams) {
589 607 var params = entry.params;
590 // Make sure entry's headers are in an array. 608
591 entry = reformatHeaders(entry); 609 if (!(typeof params.line == 'string') ||
592 610 !(params.headers instanceof Array)) {
593 // Duplicate the top level object, and |entry.params|. All other fields are 611 // Unrecognized params.
594 // just pointers to the original values, as they won't be modified, other than 612 return;
595 // |entry.params.headers|. 613 }
596 entry = shallowCloneObject(entry); 614
597 entry.params = shallowCloneObject(entry.params); 615 // Strip the trailing CRLF that params.line contains.
598 616 var lineWithoutCRLF = params.line.replace(/\r\n$/g, '');
599 entry.params.headers = entry.params.headers.map(stripCookieOrLoginInfo); 617 out.writeArrowIndentedLines([lineWithoutCRLF].concat(params.headers));
600 return entry; 618
601 }; 619 consumedParams.line = true;
602 620 consumedParams.headers = true;
603 /** 621 }
604 * Outputs the request header parameters of |entry| to |out|. 622
605 */ 623 function writeCertificateParam(
606 function writeParamsForRequestHeaders(entry, out, consumedParams) { 624 certs_container, out, consumedParams, paramName) {
607 var params = entry.params; 625 if (certs_container.certificates instanceof Array) {
608 626 var certs =
609 if (!(typeof params.line == 'string') || !(params.headers instanceof Array)) { 627 certs_container.certificates.reduce(function(previous, current) {
610 // Unrecognized params. 628 return previous.concat(current.split('\n'));
611 return; 629 }, new Array());
612 } 630 out.writeArrowKey(paramName);
613 631 out.writeSpaceIndentedLines(8, certs);
614 // Strip the trailing CRLF that params.line contains. 632 consumedParams[paramName] = true;
615 var lineWithoutCRLF = params.line.replace(/\r\n$/g, ''); 633 }
616 out.writeArrowIndentedLines([lineWithoutCRLF].concat(params.headers)); 634 }
617 635
618 consumedParams.line = true; 636 /**
619 consumedParams.headers = true; 637 * Outputs the certificate parameters of |entry| to |out|.
620 } 638 */
621 639 function writeParamsForCertificates(entry, out, consumedParams) {
622 function writeCertificateParam( 640 writeCertificateParam(entry.params, out, consumedParams, 'certificates');
623 certs_container, out, consumedParams, paramName) { 641
624 if (certs_container.certificates instanceof Array) { 642 if (typeof(entry.params.verified_cert) == 'object')
625 var certs = certs_container.certificates.reduce( 643 writeCertificateParam(
626 function(previous, current) { 644 entry.params.verified_cert, out, consumedParams, 'verified_cert');
627 return previous.concat(current.split('\n')); 645
628 }, new Array()); 646 if (typeof(entry.params.cert_status) == 'number') {
629 out.writeArrowKey(paramName); 647 var valueStr = entry.params.cert_status + ' (' +
630 out.writeSpaceIndentedLines(8, certs); 648 getCertStatusFlagSymbolicString(entry.params.cert_status) + ')';
631 consumedParams[paramName] = true; 649 out.writeArrowKeyValue('cert_status', valueStr);
632 } 650 consumedParams.cert_status = true;
633 } 651 }
634 652 }
635 /** 653
636 * Outputs the certificate parameters of |entry| to |out|. 654 function writeParamsForCheckedCertificates(entry, out, consumedParams) {
637 */ 655 if (typeof(entry.params.certificate) == 'object')
638 function writeParamsForCertificates(entry, out, consumedParams) { 656 writeCertificateParam(
639 writeCertificateParam(entry.params, out, consumedParams, 'certificates'); 657 entry.params.certificate, out, consumedParams, 'certificate');
640 658 }
641 if (typeof(entry.params.verified_cert) == 'object') 659
642 writeCertificateParam( 660 /**
643 entry.params.verified_cert, out, consumedParams, 'verified_cert'); 661 * Outputs the SSL version fallback parameters of |entry| to |out|.
644 662 */
645 if (typeof(entry.params.cert_status) == 'number') { 663 function writeParamsForSSLVersionFallback(entry, out, consumedParams) {
646 var valueStr = entry.params.cert_status + ' (' + 664 var params = entry.params;
647 getCertStatusFlagSymbolicString(entry.params.cert_status) + ')'; 665
648 out.writeArrowKeyValue('cert_status', valueStr); 666 if (typeof params.version_before != 'number' ||
649 consumedParams.cert_status = true; 667 typeof params.version_after != 'number') {
650 } 668 // Unrecognized params.
651 669 return;
652 } 670 }
653 671
654 function writeParamsForCheckedCertificates(entry, out, consumedParams) { 672 var line = SSLVersionNumberToName(params.version_before) + ' ==> ' +
655 if (typeof(entry.params.certificate) == 'object') 673 SSLVersionNumberToName(params.version_after);
656 writeCertificateParam( 674 out.writeArrowIndentedLines([line]);
657 entry.params.certificate, out, consumedParams, 'certificate'); 675
658 } 676 consumedParams.version_before = true;
659 677 consumedParams.version_after = true;
660 /** 678 }
661 * Outputs the SSL version fallback parameters of |entry| to |out|. 679
662 */ 680 function writeParamsForProxyConfigChanged(entry, out, consumedParams) {
663 function writeParamsForSSLVersionFallback(entry, out, consumedParams) { 681 var params = entry.params;
664 var params = entry.params; 682
665 683 if (typeof params.new_config != 'object') {
666 if (typeof params.version_before != 'number' || 684 // Unrecognized params.
667 typeof params.version_after != 'number') { 685 return;
668 // Unrecognized params. 686 }
669 return; 687
670 } 688 if (typeof params.old_config == 'object') {
671 689 var oldConfigString = proxySettingsToString(params.old_config);
672 var line = SSLVersionNumberToName(params.version_before) + 690 // The previous configuration may not be present in the case of
673 ' ==> ' + 691 // the initial proxy settings fetch.
674 SSLVersionNumberToName(params.version_after); 692 out.writeArrowKey('old_config');
675 out.writeArrowIndentedLines([line]); 693
676 694 out.writeSpaceIndentedLines(8, oldConfigString.split('\n'));
677 consumedParams.version_before = true; 695
678 consumedParams.version_after = true; 696 consumedParams.old_config = true;
679 } 697 }
680 698
681 function writeParamsForProxyConfigChanged(entry, out, consumedParams) { 699 var newConfigString = proxySettingsToString(params.new_config);
682 var params = entry.params; 700 out.writeArrowKey('new_config');
683 701 out.writeSpaceIndentedLines(8, newConfigString.split('\n'));
684 if (typeof params.new_config != 'object') { 702
685 // Unrecognized params. 703 consumedParams.new_config = true;
686 return; 704 }
687 } 705
688 706 function getTextForEvent(entry) {
689 if (typeof params.old_config == 'object') { 707 var text = '';
690 var oldConfigString = proxySettingsToString(params.old_config); 708
691 // The previous configuration may not be present in the case of 709 if (entry.isBegin() && canCollapseBeginWithEnd(entry)) {
692 // the initial proxy settings fetch. 710 // Don't prefix with '+' if we are going to collapse the END event.
693 out.writeArrowKey('old_config'); 711 text = ' ';
694 712 } else if (entry.isBegin()) {
695 out.writeSpaceIndentedLines(8, oldConfigString.split('\n')); 713 text = '+' + text;
696 714 } else if (entry.isEnd()) {
697 consumedParams.old_config = true; 715 text = '-' + text;
698 } 716 } else {
699 717 text = ' ';
700 var newConfigString = proxySettingsToString(params.new_config); 718 }
701 out.writeArrowKey('new_config'); 719
702 out.writeSpaceIndentedLines(8, newConfigString.split('\n')); 720 text += EventTypeNames[entry.orig.type];
703 721 return text;
704 consumedParams.new_config = true; 722 }
705 } 723
706 724 proxySettingsToString = function(config) {
707 function getTextForEvent(entry) { 725 if (!config)
708 var text = ''; 726 return '';
709 727
710 if (entry.isBegin() && canCollapseBeginWithEnd(entry)) { 728 // TODO(eroman): if |config| has unexpected properties, print it as JSON
711 // Don't prefix with '+' if we are going to collapse the END event. 729 // rather than hide them.
712 text = ' '; 730
713 } else if (entry.isBegin()) { 731 function getProxyListString(proxies) {
714 text = '+' + text; 732 // Older versions of Chrome would set these values as strings, whereas
715 } else if (entry.isEnd()) { 733 // newer
716 text = '-' + text; 734 // logs use arrays.
717 } else { 735 // TODO(eroman): This behavior changed in M27. Support for older logs can
718 text = ' '; 736 // safely be removed circa M29.
719 } 737 if (Array.isArray(proxies)) {
720 738 var listString = proxies.join(', ');
721 text += EventTypeNames[entry.orig.type]; 739 if (proxies.length > 1)
722 return text; 740 return '[' + listString + ']';
723 } 741 return listString;
724 742 }
725 proxySettingsToString = function(config) { 743 return proxies;
726 if (!config) 744 }
727 return ''; 745
728 746 // The proxy settings specify up to three major fallback choices
729 // TODO(eroman): if |config| has unexpected properties, print it as JSON 747 // (auto-detect, custom pac url, or manual settings).
730 // rather than hide them. 748 // We enumerate these to a list so we can later number them.
731 749 var modes = [];
732 function getProxyListString(proxies) { 750
733 // Older versions of Chrome would set these values as strings, whereas newer 751 // Output any automatic settings.
734 // logs use arrays. 752 if (config.auto_detect)
735 // TODO(eroman): This behavior changed in M27. Support for older logs can 753 modes.push(['Auto-detect']);
736 // safely be removed circa M29. 754 if (config.pac_url)
737 if (Array.isArray(proxies)) { 755 modes.push(['PAC script: ' + config.pac_url]);
738 var listString = proxies.join(', '); 756
739 if (proxies.length > 1) 757 // Output any manual settings.
740 return '[' + listString + ']'; 758 if (config.single_proxy || config.proxy_per_scheme) {
741 return listString; 759 var lines = [];
742 } 760
743 return proxies; 761 if (config.single_proxy) {
744 } 762 lines.push('Proxy server: ' + getProxyListString(config.single_proxy));
745 763 } else if (config.proxy_per_scheme) {
746 // The proxy settings specify up to three major fallback choices 764 for (var urlScheme in config.proxy_per_scheme) {
747 // (auto-detect, custom pac url, or manual settings). 765 if (urlScheme != 'fallback') {
748 // We enumerate these to a list so we can later number them. 766 lines.push(
749 var modes = []; 767 'Proxy server for ' + urlScheme.toUpperCase() + ': ' +
750 768 getProxyListString(config.proxy_per_scheme[urlScheme]));
751 // Output any automatic settings. 769 }
752 if (config.auto_detect) 770 }
753 modes.push(['Auto-detect']); 771 if (config.proxy_per_scheme.fallback) {
754 if (config.pac_url) 772 lines.push(
755 modes.push(['PAC script: ' + config.pac_url]); 773 'Proxy server for everything else: ' +
756 774 getProxyListString(config.proxy_per_scheme.fallback));
757 // Output any manual settings.
758 if (config.single_proxy || config.proxy_per_scheme) {
759 var lines = [];
760
761 if (config.single_proxy) {
762 lines.push('Proxy server: ' + getProxyListString(config.single_proxy));
763 } else if (config.proxy_per_scheme) {
764 for (var urlScheme in config.proxy_per_scheme) {
765 if (urlScheme != 'fallback') {
766 lines.push('Proxy server for ' + urlScheme.toUpperCase() + ': ' +
767 getProxyListString(config.proxy_per_scheme[urlScheme]));
768 } 775 }
769 } 776 }
770 if (config.proxy_per_scheme.fallback) { 777
771 lines.push('Proxy server for everything else: ' + 778 // Output any proxy bypass rules.
772 getProxyListString(config.proxy_per_scheme.fallback)); 779 if (config.bypass_list) {
780 if (config.reverse_bypass) {
781 lines.push('Reversed bypass list: ');
782 } else {
783 lines.push('Bypass list: ');
784 }
785
786 for (var i = 0; i < config.bypass_list.length; ++i)
787 lines.push(' ' + config.bypass_list[i]);
773 } 788 }
774 } 789
775 790 modes.push(lines);
776 // Output any proxy bypass rules. 791 }
777 if (config.bypass_list) { 792
778 if (config.reverse_bypass) { 793 var result = [];
779 lines.push('Reversed bypass list: '); 794 if (modes.length < 1) {
780 } else { 795 // If we didn't find any proxy settings modes, we are using DIRECT.
781 lines.push('Bypass list: '); 796 result.push('Use DIRECT connections.');
782 } 797 } else if (modes.length == 1) {
783 798 // If there was just one mode, don't bother numbering it.
784 for (var i = 0; i < config.bypass_list.length; ++i) 799 result.push(modes[0].join('\n'));
785 lines.push(' ' + config.bypass_list[i]); 800 } else {
786 } 801 // Otherwise concatenate all of the modes into a numbered list
787 802 // (which correspond with the fallback order).
788 modes.push(lines); 803 for (var i = 0; i < modes.length; ++i)
789 } 804 result.push(indentLines('(' + (i + 1) + ') ', modes[i]));
790 805 }
791 var result = []; 806
792 if (modes.length < 1) { 807 if (config.source != undefined && config.source != 'UNKNOWN')
793 // If we didn't find any proxy settings modes, we are using DIRECT. 808 result.push('Source: ' + config.source);
794 result.push('Use DIRECT connections.'); 809
795 } else if (modes.length == 1) { 810 return result.join('\n');
796 // If there was just one mode, don't bother numbering it. 811 };
797 result.push(modes[0].join('\n')); 812
798 } else { 813 // End of anonymous namespace.
799 // Otherwise concatenate all of the modes into a numbered list
800 // (which correspond with the fallback order).
801 for (var i = 0; i < modes.length; ++i)
802 result.push(indentLines('(' + (i + 1) + ') ', modes[i]));
803 }
804
805 if (config.source != undefined && config.source != 'UNKNOWN')
806 result.push('Source: ' + config.source);
807
808 return result.join('\n');
809 };
810
811 // End of anonymous namespace.
812 })(); 814 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698