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

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: Response to kinuko's comments 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
« no previous file with comments | « no previous file | chrome/browser/resources/net_internals/index.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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, 16 downloadIframeId,
17 exportTextButtonId, 17 exportFileButtonId,
18 securityStrippingCheckboxId, 18 securityStrippingCheckboxId,
19 byteLoggingCheckboxId, 19 byteLoggingCheckboxId,
20 passivelyCapturedCountId, 20 passivelyCapturedCountId,
21 activelyCapturedCountId, 21 activelyCapturedCountId,
22 deleteAllId, 22 deleteAllId,
23 dumpDataDivId, 23 dumpDataDivId,
24 loadDataDivId, 24 loadDataDivId,
25 loadLogFileId, 25 loadLogFileId,
26 capturingTextSpanId, 26 capturingTextSpanId,
27 loggingTextSpanId) { 27 loggingTextSpanId) {
28 DivView.call(this, mainBoxId); 28 DivView.call(this, mainBoxId);
29 29
30 this.textPre_ = document.getElementById(outputTextBoxId);
31
32 var securityStrippingCheckbox = 30 var securityStrippingCheckbox =
33 document.getElementById(securityStrippingCheckboxId); 31 document.getElementById(securityStrippingCheckboxId);
34 securityStrippingCheckbox.onclick = 32 securityStrippingCheckbox.onclick =
35 this.onSetSecurityStripping_.bind(this, securityStrippingCheckbox); 33 this.onSetSecurityStripping_.bind(this, securityStrippingCheckbox);
36 34
37 var byteLoggingCheckbox = document.getElementById(byteLoggingCheckboxId); 35 var byteLoggingCheckbox = document.getElementById(byteLoggingCheckboxId);
38 byteLoggingCheckbox.onclick = 36 byteLoggingCheckbox.onclick =
39 this.onSetByteLogging_.bind(this, byteLoggingCheckbox); 37 this.onSetByteLogging_.bind(this, byteLoggingCheckbox);
40 38
41 var exportTextButton = document.getElementById(exportTextButtonId); 39 this.downloadIframe_ = document.getElementById(downloadIframeId);
42 exportTextButton.onclick = this.onExportToText_.bind(this); 40
41 this.exportFileButton_ = document.getElementById(exportFileButtonId);
42 this.exportFileButton_.onclick = this.onExportToText_.bind(this);
43 43
44 this.activelyCapturedCountBox_ = 44 this.activelyCapturedCountBox_ =
45 document.getElementById(activelyCapturedCountId); 45 document.getElementById(activelyCapturedCountId);
46 this.passivelyCapturedCountBox_ = 46 this.passivelyCapturedCountBox_ =
47 document.getElementById(passivelyCapturedCountId); 47 document.getElementById(passivelyCapturedCountId);
48 document.getElementById(deleteAllId).onclick = 48 document.getElementById(deleteAllId).onclick =
49 g_browser.deleteAllEvents.bind(g_browser); 49 g_browser.deleteAllEvents.bind(g_browser);
50 50
51 this.dumpDataDiv_ = document.getElementById(dumpDataDivId); 51 this.dumpDataDiv_ = document.getElementById(dumpDataDivId);
52 this.loadDataDiv_ = document.getElementById(loadDataDivId); 52 this.loadDataDiv_ = document.getElementById(loadDataDivId);
53 this.capturingTextSpan_ = document.getElementById(capturingTextSpanId); 53 this.capturingTextSpan_ = document.getElementById(capturingTextSpanId);
54 this.loggingTextSpan_ = document.getElementById(loggingTextSpanId); 54 this.loggingTextSpan_ = document.getElementById(loggingTextSpanId);
55 55
56 var loadLogFileElement = document.getElementById(loadLogFileId); 56 var loadLogFileElement = document.getElementById(loadLogFileId);
57 loadLogFileElement.onchange = 57 loadLogFileElement.onchange =
58 this.logFileChanged.bind(this, loadLogFileElement); 58 this.logFileChanged.bind(this, loadLogFileElement);
59 59
60 this.updateEventCounts_(); 60 this.updateEventCounts_();
61 this.waitingForUpdate_ = false;
62 61
63 g_browser.addLogObserver(this); 62 g_browser.addLogObserver(this);
64 } 63 }
65 64
66 inherits(DataView, DivView); 65 inherits(DataView, DivView);
67 66
68 /** 67 /**
69 * Called whenever a new event is received. 68 * Called whenever a new event is received.
70 */ 69 */
71 DataView.prototype.onLogEntryAdded = function(logEntry) { 70 DataView.prototype.onLogEntryAdded = function(logEntry) {
(...skipping 17 matching lines...) Expand all
89 88
90 /** 89 /**
91 * Called when either a log file is loaded or when going back to actively 90 * 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, 91 * logging events. In either case, called after clearing the old entries,
93 * but before getting any new ones. 92 * but before getting any new ones.
94 */ 93 */
95 DataView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) { 94 DataView.prototype.onSetIsViewingLogFile = function(isViewingLogFile) {
96 setNodeDisplay(this.dumpDataDiv_, !isViewingLogFile); 95 setNodeDisplay(this.dumpDataDiv_, !isViewingLogFile);
97 setNodeDisplay(this.capturingTextSpan_, !isViewingLogFile); 96 setNodeDisplay(this.capturingTextSpan_, !isViewingLogFile);
98 setNodeDisplay(this.loggingTextSpan_, isViewingLogFile); 97 setNodeDisplay(this.loggingTextSpan_, isViewingLogFile);
99 this.setText_('');
100 }; 98 };
101 99
102 /** 100 /**
103 * Updates the counters showing how many events have been captured. 101 * Updates the counters showing how many events have been captured.
104 */ 102 */
105 DataView.prototype.updateEventCounts_ = function() { 103 DataView.prototype.updateEventCounts_ = function() {
106 this.activelyCapturedCountBox_.innerText = 104 this.activelyCapturedCountBox_.innerText =
107 g_browser.getNumActivelyCapturedEvents() 105 g_browser.getNumActivelyCapturedEvents()
108 this.passivelyCapturedCountBox_.innerText = 106 this.passivelyCapturedCountBox_.innerText =
109 g_browser.getNumPassivelyCapturedEvents(); 107 g_browser.getNumPassivelyCapturedEvents();
(...skipping 13 matching lines...) Expand all
123 121
124 /** 122 /**
125 * Depending on the value of the checkbox, enables or disables stripping 123 * Depending on the value of the checkbox, enables or disables stripping
126 * cookies and passwords from log dumps and displayed events. 124 * cookies and passwords from log dumps and displayed events.
127 */ 125 */
128 DataView.prototype.onSetSecurityStripping_ = 126 DataView.prototype.onSetSecurityStripping_ =
129 function(securityStrippingCheckbox) { 127 function(securityStrippingCheckbox) {
130 g_browser.setSecurityStripping(securityStrippingCheckbox.checked); 128 g_browser.setSecurityStripping(securityStrippingCheckbox.checked);
131 }; 129 };
132 130
133 /**
134 * Clears displayed text when security stripping is toggled.
135 */
136 DataView.prototype.onSecurityStrippingChanged = function() { 131 DataView.prototype.onSecurityStrippingChanged = function() {
137 this.setText_(''); 132 };
138 }
139 133
140 /** 134 /**
141 * Called when a log file is selected. 135 * Called when a log file is selected.
142 * 136 *
143 * Gets the log file from the input element and tries to read from it. 137 * Gets the log file from the input element and tries to read from it.
144 */ 138 */
145 DataView.prototype.logFileChanged = function(loadLogFileElement) { 139 DataView.prototype.logFileChanged = function(loadLogFileElement) {
146 var logFile = loadLogFileElement.files[0]; 140 var logFile = loadLogFileElement.files[0];
147 if (logFile) { 141 if (logFile) {
148 var fileReader = new FileReader(); 142 var fileReader = new FileReader();
149 143
150 fileReader.onload = this.onLoadLogFile.bind(this); 144 fileReader.onload = this.onLoadLogFile.bind(this);
151 fileReader.onerror = this.onLoadLogFileError.bind(this); 145 fileReader.onerror = this.onLoadLogFileError.bind(this);
152 146
153 fileReader.readAsText(logFile); 147 fileReader.readAsText(logFile);
154 } 148 }
155 } 149 };
156 150
157 /** 151 /**
158 * Displays an error message when unable to read the selected log file. 152 * Displays an error message when unable to read the selected log file.
159 */ 153 */
160 DataView.prototype.onLoadLogFileError = function(event) { 154 DataView.prototype.onLoadLogFileError = function(event) {
161 alert('Error ' + event.target.error.code + '. Unable to load file.'); 155 alert('Error ' + event.target.error.code + '. Unable to load file.');
162 } 156 };
163 157
164 /** 158 /**
165 * Tries to load the contents of the log file. 159 * Tries to load the contents of the log file.
166 */ 160 */
167 DataView.prototype.onLoadLogFile = function(event) { 161 DataView.prototype.onLoadLogFile = function(event) {
168 g_browser.loadedLogFile(event.target.result); 162 g_browser.loadedLogFile(event.target.result);
169 } 163 };
164
165 DataView.prototype.enableExportFileButton_ = function(enabled) {
166 this.exportFileButton_.disabled = !enabled;
167 };
170 168
171 /** 169 /**
172 * If not already waiting for results from all updates, triggers all 170 * If not already waiting for results from all updates, triggers all
173 * updates and starts waiting for them to complete. 171 * updates and starts waiting for them to complete.
174 */ 172 */
175 DataView.prototype.onExportToText_ = function() { 173 DataView.prototype.onExportToText_ = function() {
176 if (this.waitingForUpdate_) 174 if (this.exportFileButton_.disabled)
177 return; 175 return;
178 this.waitingForUpdate = true; 176 this.enableExportFileButton_(false);
179 this.setText_('Generating...'); 177
180 g_browser.updateAllInfo(this.onUpdateAllCompleted.bind(this)); 178 g_browser.updateAllInfo(this.onUpdateAllCompleted.bind(this));
181 }; 179 };
182 180
183 /** 181 /**
184 * Presents the captured data as formatted text. 182 * Presents the captured data as formatted text.
185 */ 183 */
186 DataView.prototype.onUpdateAllCompleted = function(data) { 184 DataView.prototype.onUpdateAllCompleted = function(data) {
187 // It's possible for a log file to be loaded while a dump is being generated. 185 // 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. 186 // When that happens, don't display the log dump, to avoid any confusion.
189 if (g_browser.isViewingLogFile()) 187 if (g_browser.isViewingLogFile())
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 var provider = namespaceProviders[i]; 395 var provider = namespaceProviders[i];
398 text.push('name: ' + provider.name); 396 text.push('name: ' + provider.name);
399 text.push('version: ' + provider.version); 397 text.push('version: ' + provider.version);
400 text.push('type: ' + 398 text.push('type: ' +
401 ServiceProvidersView.getNamespaceProviderType(provider)); 399 ServiceProvidersView.getNamespaceProviderType(provider));
402 text.push('active: ' + provider.active); 400 text.push('active: ' + provider.active);
403 text.push(''); 401 text.push('');
404 } 402 }
405 } 403 }
406 404
407 // Open a new window to display this text. 405 var blobBuilder = new WebKitBlobBuilder();
408 this.setText_(text.join('\n')); 406 blobBuilder.append(text.join('\n'), 'native');
407 var textBlob = blobBuilder.getBlob('octet/stream');
409 408
410 this.selectText_(); 409 window.webkitRequestFileSystem(
410 window.TEMPORARY, textBlob.size,
411 this.onFileSystemCreate_.bind(this, textBlob),
412 this.onFileError_.bind(this, 'Unable to create file system.'));
413 };
414
415 // Once we have access to the file system, create a log file.
416 DataView.prototype.onFileSystemCreate_ = function(textBlob, fileSystem) {
417 fileSystem.root.getFile(
418 'net_internals_log.txt', {create: true},
419 this.onFileCreate_.bind(this, textBlob),
420 this.onFileError_.bind(this, 'Unable to create file.'));
421 };
422
423 // Once the file is created, or an existing one has been opened, create a
424 // writer for it.
425 DataView.prototype.onFileCreate_ = function(textBlob, fileEntry) {
426 fileEntry.createWriter(
427 this.onFileCreateWriter_.bind(this, textBlob, fileEntry),
428 this.onFileError_.bind(this, 'Unable to create writer.'));
429 };
430
431 // Once the |fileWriter| has been created, truncate the file, in case it already
432 // existed.
433 DataView.prototype.onFileCreateWriter_ = function(textBlob,
434 fileEntry, fileWriter) {
435 fileWriter.onerror = this.onFileError_.bind(this, 'Truncate failed.');
436 fileWriter.onwriteend = this.onFileTruncate_.bind(this, textBlob,
437 fileWriter, fileEntry);
438 fileWriter.truncate(0);
439 };
440
441 // Once the file has been truncated, write |textBlob| to the file.
442 DataView.prototype.onFileTruncate_ = function(textBlob, fileWriter, fileEntry) {
443 fileWriter.onerror = this.onFileError_.bind(this, 'Write failed.');
444 fileWriter.onwriteend = this.onFileWriteComplete_.bind(this, fileEntry);
445 fileWriter.write(textBlob);
446 };
447
448 // Once the file has been written to, start the download.
449 DataView.prototype.onFileWriteComplete_ = function(fileEntry) {
450 this.downloadIframe_.src = fileEntry.toURL();
451 this.enableExportFileButton_(true);
452 };
453
454 // On any Javascript File API error, enable the export button and display
455 // |errorText|, followed by the specific error.
456 DataView.prototype.onFileError_ = function(errorText, error) {
457 this.enableExportFileButton_(true);
458 alert(errorText + ' ' + getKeyWithValue(FileError, error.code));
411 }; 459 };
412 460
413 DataView.prototype.appendEventsPrintedAsText_ = function(out) { 461 DataView.prototype.appendEventsPrintedAsText_ = function(out) {
414 var allEvents = g_browser.getAllCapturedEvents(); 462 var allEvents = g_browser.getAllCapturedEvents();
415 463
416 // Group the events into buckets by source ID, and buckets by source type. 464 // Group the events into buckets by source ID, and buckets by source type.
417 var sourceIds = []; 465 var sourceIds = [];
418 var sourceIdToEventList = {}; 466 var sourceIdToEventList = {};
419 var sourceTypeToSourceIdList = {}; 467 var sourceTypeToSourceIdList = {};
420 468
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 521
474 for (var i = 0; i < socketPools.length; ++i) { 522 for (var i = 0; i < socketPools.length; ++i) {
475 if (socketPools[i].origPool.groups == undefined) 523 if (socketPools[i].origPool.groups == undefined)
476 continue; 524 continue;
477 var groupTablePrinter = socketPools[i].createGroupTablePrinter(); 525 var groupTablePrinter = socketPools[i].createGroupTablePrinter();
478 text.push(groupTablePrinter.toText(2)); 526 text.push(groupTablePrinter.toText(2));
479 } 527 }
480 }; 528 };
481 529
482 /** 530 /**
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. 531 * Format a time ticks count as a timestamp.
492 */ 532 */
493 DataView.prototype.formatExpirationTime_ = function(timeTicks) { 533 DataView.prototype.formatExpirationTime_ = function(timeTicks) {
494 var d = g_browser.convertTimeTicksToDate(timeTicks); 534 var d = g_browser.convertTimeTicksToDate(timeTicks);
495 var isExpired = d.getTime() < (new Date()).getTime(); 535 var isExpired = d.getTime() < (new Date()).getTime();
496 return 't=' + d.getTime() + (isExpired ? ' [EXPIRED]' : ''); 536 return 't=' + d.getTime() + (isExpired ? ' [EXPIRED]' : '');
497 }; 537 };
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') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698