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

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

Issue 7155031: Save net-internals log dumps directly to disk. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 6 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
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
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
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
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
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
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 };
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/resources/net_internals/index.html » ('j') | chrome/browser/resources/net_internals/index.html » ('J')

Powered by Google App Engine
This is Rietveld 408576698