OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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 /** | 5 /** |
6 * This view displays options for importing/exporting the captured data. Its | 6 * This view displays options for importing/exporting the captured data. Its |
7 * primarily usefulness is to allow users to copy-paste their data in an easy | 7 * primarily usefulness is to allow users to copy-paste their data in an easy |
8 * to read format for bug reports. | 8 * to read format for bug reports. |
9 * | 9 * |
10 * - Has a button to generate a text report. | 10 * - Has a button to generate a text report. |
11 * | 11 * |
12 * - Shows how many events have been captured. | 12 * - Shows how many events have been captured. |
13 * @constructor | 13 * @constructor |
14 */ | 14 */ |
15 function DataView(mainBoxId, | 15 function DataView(mainBoxId, |
16 outputTextBoxId, | |
17 exportTextButtonId, | 16 exportTextButtonId, |
18 securityStrippingCheckboxId, | 17 securityStrippingCheckboxId, |
19 byteLoggingCheckboxId, | 18 byteLoggingCheckboxId, |
20 passivelyCapturedCountId, | 19 passivelyCapturedCountId, |
21 activelyCapturedCountId, | 20 activelyCapturedCountId, |
22 deleteAllId, | 21 deleteAllId, |
23 dumpDataDivId, | 22 dumpDataDivId, |
24 loadDataDivId, | 23 loadDataDivId, |
25 loadLogFileId, | 24 loadLogFileId, |
26 capturingTextSpanId, | 25 capturingTextSpanId, |
27 loggingTextSpanId) { | 26 loggingTextSpanId) { |
28 DivView.call(this, mainBoxId); | 27 DivView.call(this, mainBoxId); |
29 | 28 |
30 this.textPre_ = document.getElementById(outputTextBoxId); | |
31 | |
32 var securityStrippingCheckbox = | 29 var securityStrippingCheckbox = |
33 document.getElementById(securityStrippingCheckboxId); | 30 document.getElementById(securityStrippingCheckboxId); |
34 securityStrippingCheckbox.onclick = | 31 securityStrippingCheckbox.onclick = |
35 this.onSetSecurityStripping_.bind(this, securityStrippingCheckbox); | 32 this.onSetSecurityStripping_.bind(this, securityStrippingCheckbox); |
36 | 33 |
37 var byteLoggingCheckbox = document.getElementById(byteLoggingCheckboxId); | 34 var byteLoggingCheckbox = document.getElementById(byteLoggingCheckboxId); |
38 byteLoggingCheckbox.onclick = | 35 byteLoggingCheckbox.onclick = |
39 this.onSetByteLogging_.bind(this, byteLoggingCheckbox); | 36 this.onSetByteLogging_.bind(this, byteLoggingCheckbox); |
40 | 37 |
41 var exportTextButton = document.getElementById(exportTextButtonId); | 38 this.exportTextButton_ = document.getElementById(exportTextButtonId); |
42 exportTextButton.onclick = this.onExportToText_.bind(this); | 39 this.exportTextButton_.onclick = this.onExportToText_.bind(this); |
43 | 40 |
44 this.activelyCapturedCountBox_ = | 41 this.activelyCapturedCountBox_ = |
45 document.getElementById(activelyCapturedCountId); | 42 document.getElementById(activelyCapturedCountId); |
46 this.passivelyCapturedCountBox_ = | 43 this.passivelyCapturedCountBox_ = |
47 document.getElementById(passivelyCapturedCountId); | 44 document.getElementById(passivelyCapturedCountId); |
48 document.getElementById(deleteAllId).onclick = | 45 document.getElementById(deleteAllId).onclick = |
49 g_browser.deleteAllEvents.bind(g_browser); | 46 g_browser.deleteAllEvents.bind(g_browser); |
50 | 47 |
51 this.dumpDataDiv_ = document.getElementById(dumpDataDivId); | 48 this.dumpDataDiv_ = document.getElementById(dumpDataDivId); |
52 this.loadDataDiv_ = document.getElementById(loadDataDivId); | 49 this.loadDataDiv_ = document.getElementById(loadDataDivId); |
53 this.capturingTextSpan_ = document.getElementById(capturingTextSpanId); | 50 this.capturingTextSpan_ = document.getElementById(capturingTextSpanId); |
54 this.loggingTextSpan_ = document.getElementById(loggingTextSpanId); | 51 this.loggingTextSpan_ = document.getElementById(loggingTextSpanId); |
55 | 52 |
56 var loadLogFileElement = document.getElementById(loadLogFileId); | 53 var loadLogFileElement = document.getElementById(loadLogFileId); |
57 loadLogFileElement.onchange = | 54 loadLogFileElement.onchange = |
58 this.logFileChanged.bind(this, loadLogFileElement); | 55 this.logFileChanged.bind(this, loadLogFileElement); |
59 | 56 |
60 this.updateEventCounts_(); | 57 this.updateEventCounts_(); |
61 this.waitingForUpdate_ = false; | |
62 | 58 |
63 g_browser.addLogObserver(this); | 59 g_browser.addLogObserver(this); |
64 } | 60 } |
65 | 61 |
66 inherits(DataView, DivView); | 62 inherits(DataView, DivView); |
67 | 63 |
68 /** | 64 /** |
69 * Called whenever a new event is received. | 65 * Called whenever a new event is received. |
70 */ | 66 */ |
71 DataView.prototype.onLogEntryAdded = function(logEntry) { | 67 DataView.prototype.onLogEntryAdded = function(logEntry) { |
(...skipping 17 matching lines...) Expand all Loading... | |
89 | 85 |
90 /** | 86 /** |
91 * Called when either a log file is loaded or when going back to actively | 87 * Called when either a log file is loaded or when going back to actively |
92 * logging events. In either case, called after clearing the old entries, | 88 * logging events. In either case, called after clearing the old entries, |
93 * but before getting any new ones. | 89 * but before getting any new ones. |
94 */ | 90 */ |
95 DataView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) { | 91 DataView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) { |
96 setNodeDisplay(this.dumpDataDiv_, !isViewingLogFile); | 92 setNodeDisplay(this.dumpDataDiv_, !isViewingLogFile); |
97 setNodeDisplay(this.capturingTextSpan_, !isViewingLogFile); | 93 setNodeDisplay(this.capturingTextSpan_, !isViewingLogFile); |
98 setNodeDisplay(this.loggingTextSpan_, isViewingLogFile); | 94 setNodeDisplay(this.loggingTextSpan_, isViewingLogFile); |
99 this.setText_(''); | |
100 }; | 95 }; |
101 | 96 |
102 /** | 97 /** |
103 * Updates the counters showing how many events have been captured. | 98 * Updates the counters showing how many events have been captured. |
104 */ | 99 */ |
105 DataView.prototype.updateEventCounts_ = function() { | 100 DataView.prototype.updateEventCounts_ = function() { |
106 this.activelyCapturedCountBox_.innerText = | 101 this.activelyCapturedCountBox_.innerText = |
107 g_browser.getNumActivelyCapturedEvents() | 102 g_browser.getNumActivelyCapturedEvents() |
108 this.passivelyCapturedCountBox_.innerText = | 103 this.passivelyCapturedCountBox_.innerText = |
109 g_browser.getNumPassivelyCapturedEvents(); | 104 g_browser.getNumPassivelyCapturedEvents(); |
(...skipping 13 matching lines...) Expand all Loading... | |
123 | 118 |
124 /** | 119 /** |
125 * Depending on the value of the checkbox, enables or disables stripping | 120 * Depending on the value of the checkbox, enables or disables stripping |
126 * cookies and passwords from log dumps and displayed events. | 121 * cookies and passwords from log dumps and displayed events. |
127 */ | 122 */ |
128 DataView.prototype.onSetSecurityStripping_ = | 123 DataView.prototype.onSetSecurityStripping_ = |
129 function(securityStrippingCheckbox) { | 124 function(securityStrippingCheckbox) { |
130 g_browser.setSecurityStripping(securityStrippingCheckbox.checked); | 125 g_browser.setSecurityStripping(securityStrippingCheckbox.checked); |
131 }; | 126 }; |
132 | 127 |
133 /** | |
134 * Clears displayed text when security stripping is toggled. | |
135 */ | |
136 DataView.prototype.onSecurityStrippingChanged = function() { | 128 DataView.prototype.onSecurityStrippingChanged = function() { |
137 this.setText_(''); | |
138 } | 129 } |
139 | 130 |
140 /** | 131 /** |
141 * Called when a log file is selected. | 132 * Called when a log file is selected. |
142 * | 133 * |
143 * Gets the log file from the input element and tries to read from it. | 134 * Gets the log file from the input element and tries to read from it. |
144 */ | 135 */ |
145 DataView.prototype.logFileChanged = function(loadLogFileElement) { | 136 DataView.prototype.logFileChanged = function(loadLogFileElement) { |
146 var logFile = loadLogFileElement.files[0]; | 137 var logFile = loadLogFileElement.files[0]; |
147 if (logFile) { | 138 if (logFile) { |
(...skipping 13 matching lines...) Expand all Loading... | |
161 alert('Error ' + event.target.error.code + '. Unable to load file.'); | 152 alert('Error ' + event.target.error.code + '. Unable to load file.'); |
162 } | 153 } |
163 | 154 |
164 /** | 155 /** |
165 * Tries to load the contents of the log file. | 156 * Tries to load the contents of the log file. |
166 */ | 157 */ |
167 DataView.prototype.onLoadLogFile = function(event) { | 158 DataView.prototype.onLoadLogFile = function(event) { |
168 g_browser.loadedLogFile(event.target.result); | 159 g_browser.loadedLogFile(event.target.result); |
169 } | 160 } |
170 | 161 |
162 DataView.prototype.EnableExportTextButton_ = function(enabled) { | |
eroman
2011/06/16 00:42:02
nit: use lowercaseCamelCase for function names in
mmenke
2011/06/16 16:16:53
Done.
| |
163 this.exportTextButton_.disabled = !enabled; | |
164 } | |
165 | |
171 /** | 166 /** |
172 * If not already waiting for results from all updates, triggers all | 167 * If not already waiting for results from all updates, triggers all |
173 * updates and starts waiting for them to complete. | 168 * updates and starts waiting for them to complete. |
174 */ | 169 */ |
175 DataView.prototype.onExportToText_ = function() { | 170 DataView.prototype.onExportToText_ = function() { |
176 if (this.waitingForUpdate_) | 171 if (this.exportTextButton_.disabled) |
177 return; | 172 return; |
178 this.waitingForUpdate = true; | 173 this.EnableExportTextButton_(false); |
179 this.setText_('Generating...'); | 174 |
180 g_browser.updateAllInfo(this.onUpdateAllCompleted.bind(this)); | 175 g_browser.updateAllInfo(this.onUpdateAllCompleted.bind(this)); |
181 }; | 176 }; |
182 | 177 |
183 /** | 178 /** |
184 * Presents the captured data as formatted text. | 179 * Presents the captured data as formatted text. |
185 */ | 180 */ |
186 DataView.prototype.onUpdateAllCompleted = function(data) { | 181 DataView.prototype.onUpdateAllCompleted = function(data) { |
187 // It's possible for a log file to be loaded while a dump is being generated. | 182 // It's possible for a log file to be loaded while a dump is being generated. |
188 // When that happens, don't display the log dump, to avoid any confusion. | 183 // When that happens, don't display the log dump, to avoid any confusion. |
189 if (g_browser.isViewingLogFile()) | 184 if (g_browser.isViewingLogFile()) |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
397 var provider = namespaceProviders[i]; | 392 var provider = namespaceProviders[i]; |
398 text.push('name: ' + provider.name); | 393 text.push('name: ' + provider.name); |
399 text.push('version: ' + provider.version); | 394 text.push('version: ' + provider.version); |
400 text.push('type: ' + | 395 text.push('type: ' + |
401 ServiceProvidersView.getNamespaceProviderType(provider)); | 396 ServiceProvidersView.getNamespaceProviderType(provider)); |
402 text.push('active: ' + provider.active); | 397 text.push('active: ' + provider.active); |
403 text.push(''); | 398 text.push(''); |
404 } | 399 } |
405 } | 400 } |
406 | 401 |
407 // Open a new window to display this text. | 402 var chunkSize = 100 * 1024; |
eroman
2011/06/16 00:42:02
chunkSize is unused.
mmenke
2011/06/16 16:16:53
Removed. Accidentally left over from one of the a
| |
408 this.setText_(text.join('\n')); | 403 var flatText = text.join('\n'); |
404 window.webkitRequestFileSystem( | |
405 window.TEMPORARY, 10*1024 + flatText.length, | |
eroman
2011/06/16 00:42:02
nit: the assumption here is that 1 character = 1 b
mmenke
2011/06/16 16:16:53
Fixed. Thanks for catching that. Be a pain to ru
| |
406 this.OnFileSystemCreate_.bind(this, flatText), | |
407 this.OnFileError_.bind(this, 'Unable to create file system.')); | |
408 }; | |
409 | 409 |
410 this.selectText_(); | 410 DataView.prototype.OnFileSystemCreate_ = function(text, fileSystem) { |
eroman
2011/06/16 00:42:02
I believe javascript style stipulates lowercase fo
mmenke
2011/06/16 16:16:53
Fixed everywhere.
| |
411 }; | 411 fileSystem.root.getFile( |
412 'net_internals_log.txt', {create: true}, | |
eroman
2011/06/16 00:42:02
I wander if we should include a unique identifier
mmenke
2011/06/16 16:16:53
I considered that, but wasn't sure it was worth th
| |
413 this.OnFileCreate_.bind(this, text), | |
414 this.OnFileError_.bind(this, 'Unable to create file.')); | |
415 } | |
eroman
2011/06/16 00:42:02
nit: can you put semicolon after all of these "sta
mmenke
2011/06/16 16:16:53
Done.
| |
416 | |
417 DataView.prototype.OnFileCreate_ = function(text, fileEntry) { | |
418 fileEntry.createWriter( | |
419 this.OnFileCreateWriter_.bind(this, text, fileEntry), | |
420 this.OnFileError_.bind(this, 'Unable to create writer.')); | |
421 } | |
422 | |
423 DataView.prototype.OnFileCreateWriter_ = function(text, fileEntry, fileWriter) { | |
424 fileWriter.onerror = this.OnFileError_.bind(this, 'Write failed.') | |
425 fileWriter.onwriteend = this.OnFileWriteComplete_.bind(this, fileEntry) | |
426 var blobBuilder = new WebKitBlobBuilder(); | |
427 blobBuilder.append(text); | |
eroman
2011/06/16 00:42:02
Do you know how it serializes strings? UTF16? UTF8
mmenke
2011/06/16 16:16:53
Experimentally, just writes out UTF8.
| |
428 fileWriter.write(blobBuilder.getBlob('octet/stream')); | |
eroman
2011/06/16 00:42:02
One annoyance is line ending on Windows are CR LF,
mmenke
2011/06/16 16:16:53
Fixed (Use CRLF on Windows only).
| |
429 } | |
430 | |
431 DataView.prototype.OnFileWriteComplete_ = function(fileEntry) { | |
432 window.location = fileEntry.toURL(); | |
eroman
2011/06/16 00:42:02
Not a big deal, but this might cause a flicker in
mmenke
2011/06/16 16:16:53
We don't actually update the address bar until we'
mmenke
2011/06/16 16:26:59
Well...I was wrong about this. I'll go ahead and
| |
433 this.EnableExportTextButton_(true); | |
434 } | |
435 | |
436 DataView.prototype.OnFileError_ = function(errorText, error) { | |
437 this.EnableExportTextButton_(true); | |
438 alert(errorText + ' Error: ' + error.code); | |
eroman
2011/06/16 00:42:02
I suggest giving a more informative message, since
mmenke
2011/06/16 16:16:53
Done.
| |
439 } | |
412 | 440 |
413 DataView.prototype.appendEventsPrintedAsText_ = function(out) { | 441 DataView.prototype.appendEventsPrintedAsText_ = function(out) { |
414 var allEvents = g_browser.getAllCapturedEvents(); | 442 var allEvents = g_browser.getAllCapturedEvents(); |
415 | 443 |
416 // Group the events into buckets by source ID, and buckets by source type. | 444 // Group the events into buckets by source ID, and buckets by source type. |
417 var sourceIds = []; | 445 var sourceIds = []; |
418 var sourceIdToEventList = {}; | 446 var sourceIdToEventList = {}; |
419 var sourceTypeToSourceIdList = {}; | 447 var sourceTypeToSourceIdList = {}; |
420 | 448 |
421 // Lists used for actual output. | 449 // Lists used for actual output. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
473 | 501 |
474 for (var i = 0; i < socketPools.length; ++i) { | 502 for (var i = 0; i < socketPools.length; ++i) { |
475 if (socketPools[i].origPool.groups == undefined) | 503 if (socketPools[i].origPool.groups == undefined) |
476 continue; | 504 continue; |
477 var groupTablePrinter = socketPools[i].createGroupTablePrinter(); | 505 var groupTablePrinter = socketPools[i].createGroupTablePrinter(); |
478 text.push(groupTablePrinter.toText(2)); | 506 text.push(groupTablePrinter.toText(2)); |
479 } | 507 } |
480 }; | 508 }; |
481 | 509 |
482 /** | 510 /** |
483 * Helper function to set this view's content to |text|. | |
484 */ | |
485 DataView.prototype.setText_ = function(text) { | |
486 this.textPre_.innerHTML = ''; | |
487 addTextNode(this.textPre_, text); | |
488 }; | |
489 | |
490 /** | |
491 * Format a time ticks count as a timestamp. | 511 * Format a time ticks count as a timestamp. |
492 */ | 512 */ |
493 DataView.prototype.formatExpirationTime_ = function(timeTicks) { | 513 DataView.prototype.formatExpirationTime_ = function(timeTicks) { |
494 var d = g_browser.convertTimeTicksToDate(timeTicks); | 514 var d = g_browser.convertTimeTicksToDate(timeTicks); |
495 var isExpired = d.getTime() < (new Date()).getTime(); | 515 var isExpired = d.getTime() < (new Date()).getTime(); |
496 return 't=' + d.getTime() + (isExpired ? ' [EXPIRED]' : ''); | 516 return 't=' + d.getTime() + (isExpired ? ' [EXPIRED]' : ''); |
497 }; | 517 }; |
498 | |
499 /** | |
500 * Select all text from log dump. | |
501 */ | |
502 DataView.prototype.selectText_ = function() { | |
503 var selection = window.getSelection(); | |
504 selection.removeAllRanges(); | |
505 | |
506 var range = document.createRange(); | |
507 range.selectNodeContents(this.textPre_); | |
508 selection.addRange(range); | |
509 }; | |
OLD | NEW |