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

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

Issue 6025017: Adds the ability to load JSON log files to about:net-internals. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 * Dictionary of constants (initialized by browser). 6 * Dictionary of constants (initialized by browser).
7 */ 7 */
8 var LogEventType = null; 8 var LogEventType = null;
9 var LogEventPhase = null; 9 var LogEventPhase = null;
10 var ClientInfo = null; 10 var ClientInfo = null;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 'hostResolverIPv6Disabled', 68 'hostResolverIPv6Disabled',
69 'hostResolverEnableIPv6', 69 'hostResolverEnableIPv6',
70 'hostResolverCacheCapacity', 70 'hostResolverCacheCapacity',
71 'hostResolverCacheTTLSuccess', 71 'hostResolverCacheTTLSuccess',
72 'hostResolverCacheTTLFailure'); 72 'hostResolverCacheTTLFailure');
73 73
74 // Create a view which will display import/export options to control the 74 // Create a view which will display import/export options to control the
75 // captured data. 75 // captured data.
76 var dataView = new DataView('dataTabContent', 'exportedDataText', 76 var dataView = new DataView('dataTabContent', 'exportedDataText',
77 'exportToText', 'securityStrippingCheckbox', 77 'exportToText', 'securityStrippingCheckbox',
78 'byteLoggingCheckbox', 78 'byteLoggingCheckbox', 'passivelyCapturedCount',
79 'passivelyCapturedCount', 79 'activelyCapturedCount', 'dataViewDeleteAll',
80 'activelyCapturedCount', 80 'dataViewDumpDataDiv', 'dataViewLoadDataDiv',
81 'dataViewDeleteAll'); 81 'dataViewLoadLogFile',
82 'dataViewCapturingTextSpan',
83 'dataViewLoggingTextSpan');
82 84
83 // Create a view which will display the results and controls for connection 85 // Create a view which will display the results and controls for connection
84 // tests. 86 // tests.
85 var testView = new TestView('testTabContent', 'testUrlInput', 87 var testView = new TestView('testTabContent', 'testUrlInput',
86 'connectionTestsForm', 'testSummary'); 88 'connectionTestsForm', 'testSummary');
87 89
88 var httpCacheView = new HttpCacheView('httpCacheTabContent', 90 var httpCacheView = new HttpCacheView('httpCacheTabContent',
89 'httpCacheStats'); 91 'httpCacheStats');
90 92
91 var socketsView = new SocketsView('socketsTabContent', 93 var socketsView = new SocketsView('socketsTabContent',
92 'socketPoolDiv', 94 'socketPoolDiv',
93 'socketPoolGroupsDiv'); 95 'socketPoolGroupsDiv');
94 96
95 var spdyView = new SpdyView('spdyTabContent', 97 var spdyView = new SpdyView('spdyTabContent',
96 'spdySessionNoneSpan', 98 'spdySessionNoneSpan',
97 'spdySessionLinkSpan', 99 'spdySessionLinkSpan',
98 'spdySessionDiv'); 100 'spdySessionDiv');
99 101
100 102
101 var serviceView; 103 var serviceView;
102 if (g_browser.isPlatformWindows()) { 104 if (g_browser.isPlatformWindows()) {
103 serviceView = new ServiceProvidersView('serviceProvidersTab', 105 serviceView = new ServiceProvidersView('serviceProvidersTab',
104 'serviceProvidersTabContent', 106 'serviceProvidersTabContent',
105 'serviceProvidersTbody', 107 'serviceProvidersTbody',
106 'namespaceProvidersTbody'); 108 'namespaceProvidersTbody');
107 } 109 }
108 110
109 // Create a view which lets you tab between the different sub-views. 111 // Create a view which lets you tab between the different sub-views.
110 var categoryTabSwitcher = new TabSwitcherView('categoryTabHandles'); 112 var categoryTabSwitcher = new TabSwitcherView('categoryTabHandles');
113 g_browser.setTabSwitcher(categoryTabSwitcher);
111 114
112 // Populate the main tabs. 115 // Populate the main tabs.
113 categoryTabSwitcher.addTab('eventsTab', eventsView, false); 116 categoryTabSwitcher.addTab('eventsTab', eventsView, false);
114 categoryTabSwitcher.addTab('proxyTab', proxyView, false); 117 categoryTabSwitcher.addTab('proxyTab', proxyView, false);
115 categoryTabSwitcher.addTab('dnsTab', dnsView, false); 118 categoryTabSwitcher.addTab('dnsTab', dnsView, false);
116 categoryTabSwitcher.addTab('socketsTab', socketsView, false); 119 categoryTabSwitcher.addTab('socketsTab', socketsView, false);
117 categoryTabSwitcher.addTab('spdyTab', spdyView, false); 120 categoryTabSwitcher.addTab('spdyTab', spdyView, false);
118 categoryTabSwitcher.addTab('httpCacheTab', httpCacheView, false); 121 categoryTabSwitcher.addTab('httpCacheTab', httpCacheView, false);
119 categoryTabSwitcher.addTab('dataTab', dataView, false); 122 categoryTabSwitcher.addTab('dataTab', dataView, false);
120 if (g_browser.isPlatformWindows()) 123 if (g_browser.isPlatformWindows())
(...skipping 16 matching lines...) Expand all
137 140
138 // Make this category tab widget the primary view, that fills the whole page. 141 // Make this category tab widget the primary view, that fills the whole page.
139 var windowView = new WindowView(categoryTabSwitcher); 142 var windowView = new WindowView(categoryTabSwitcher);
140 143
141 // Trigger initial layout. 144 // Trigger initial layout.
142 windowView.resetGeometry(); 145 windowView.resetGeometry();
143 146
144 // Select the initial view based on the current URL. 147 // Select the initial view based on the current URL.
145 window.onhashchange(); 148 window.onhashchange();
146 149
150 // Inform observers a log file is not currently being displayed.
151 g_browser.setIsViewingLogFile(false);
152
147 // Tell the browser that we are ready to start receiving log events. 153 // Tell the browser that we are ready to start receiving log events.
148 g_browser.sendReady(); 154 g_browser.sendReady();
149 } 155 }
150 156
151 /** 157 /**
152 * This class provides a "bridge" for communicating between the javascript and 158 * This class provides a "bridge" for communicating between the javascript and
153 * the browser. 159 * the browser.
154 * 160 *
155 * @constructor 161 * @constructor
156 */ 162 */
(...skipping 27 matching lines...) Expand all
184 this.sendGetServiceProviders.bind(this)); 190 this.sendGetServiceProviders.bind(this));
185 } 191 }
186 192
187 // Cache of the data received. 193 // Cache of the data received.
188 this.numPassivelyCapturedEvents_ = 0; 194 this.numPassivelyCapturedEvents_ = 0;
189 this.capturedEvents_ = []; 195 this.capturedEvents_ = [];
190 196
191 // Next unique id to be assigned to a log entry without a source. 197 // Next unique id to be assigned to a log entry without a source.
192 // Needed to simplify deletion, identify associated GUI elements, etc. 198 // Needed to simplify deletion, identify associated GUI elements, etc.
193 this.nextSourcelessEventId_ = -1; 199 this.nextSourcelessEventId_ = -1;
200
201 // True when viewing a log file rather than actively logged events.
202 // When viewing a log file, all tabs are hidden except the event view,
203 // and all received events are ignored.
204 this.isViewingLogFile_ = false;
194 } 205 }
195 206
196 /* 207 /*
197 * Takes the current hash in form of "#tab&param1=value1&param2=value2&...". 208 * Takes the current hash in form of "#tab&param1=value1&param2=value2&...".
198 * Puts the parameters in an object, and passes the resulting object to 209 * Puts the parameters in an object, and passes the resulting object to
199 * |categoryTabSwitcher|. Uses tab and |anchorMap| to find a tab ID, 210 * |categoryTabSwitcher|. Uses tab and |anchorMap| to find a tab ID,
200 * which it also passes to the tab switcher. 211 * which it also passes to the tab switcher.
201 * 212 *
202 * Parameters and values are decoded with decodeURIComponent(). 213 * Parameters and values are decoded with decodeURIComponent().
203 */ 214 */
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 }; 306 };
296 307
297 BrowserBridge.prototype.enableIPv6 = function() { 308 BrowserBridge.prototype.enableIPv6 = function() {
298 chrome.send('enableIPv6'); 309 chrome.send('enableIPv6');
299 }; 310 };
300 311
301 BrowserBridge.prototype.setLogLevel = function(logLevel) { 312 BrowserBridge.prototype.setLogLevel = function(logLevel) {
302 chrome.send('setLogLevel', ['' + logLevel]); 313 chrome.send('setLogLevel', ['' + logLevel]);
303 } 314 }
304 315
316 BrowserBridge.prototype.loadLogFile = function(logLevel) {
eroman 2011/01/12 05:57:34 the parameter here is unused.
mmenke 2011/01/13 03:45:29 Oops...Removed.
317 chrome.send('loadLogFile');
318 }
319
305 //------------------------------------------------------------------------------ 320 //------------------------------------------------------------------------------
306 // Messages received from the browser 321 // Messages received from the browser
307 //------------------------------------------------------------------------------ 322 //------------------------------------------------------------------------------
308 323
309 BrowserBridge.prototype.receivedLogEntries = function(logEntries) { 324 BrowserBridge.prototype.receivedLogEntries = function(logEntries) {
310 for (var e = 0; e < logEntries.length; ++e) { 325 // Does nothing if viewing a log file.
311 var logEntry = logEntries[e]; 326 if (this.isViewingLogFile_)
312 327 return;
313 // Assign unique ID, if needed. 328 this.addLogEntries(logEntries);
314 if (logEntry.source.id == 0) {
315 logEntry.source.id = this.nextSourcelessEventId_;
316 --this.nextSourcelessEventId_;
317 }
318 this.capturedEvents_.push(logEntry);
319 for (var i = 0; i < this.logObservers_.length; ++i)
320 this.logObservers_[i].onLogEntryAdded(logEntry);
321 }
322 }; 329 };
323 330
324 BrowserBridge.prototype.receivedLogEventTypeConstants = function(constantsMap) { 331 BrowserBridge.prototype.receivedLogEventTypeConstants = function(constantsMap) {
325 LogEventType = constantsMap; 332 LogEventType = constantsMap;
326 }; 333 };
327 334
328 BrowserBridge.prototype.receivedClientInfo = 335 BrowserBridge.prototype.receivedClientInfo =
329 function(info) { 336 function(info) {
330 ClientInfo = info; 337 ClientInfo = info;
331 }; 338 };
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 439
433 BrowserBridge.prototype.receivedCompletedConnectionTestSuite = function() { 440 BrowserBridge.prototype.receivedCompletedConnectionTestSuite = function() {
434 for (var i = 0; i < this.connectionTestsObservers_.length; ++i) 441 for (var i = 0; i < this.connectionTestsObservers_.length; ++i)
435 this.connectionTestsObservers_[i].onCompletedConnectionTestSuite(); 442 this.connectionTestsObservers_[i].onCompletedConnectionTestSuite();
436 }; 443 };
437 444
438 BrowserBridge.prototype.receivedHttpCacheInfo = function(info) { 445 BrowserBridge.prototype.receivedHttpCacheInfo = function(info) {
439 this.pollableDataHelpers_.httpCacheInfo.update(info); 446 this.pollableDataHelpers_.httpCacheInfo.update(info);
440 }; 447 };
441 448
449 BrowserBridge.prototype.loadedLogFile = function(logFileContents) {
450 var match;
451 // Replace carriage returns with linebreaks and then split around linebreaks.
452 var lines = logFileContents.replace(/\r/g, '\n').split('\n');
453 var entries = [];
454
455 for (var i = 0; i < lines.length; ++i) {
456 // Parse all valid lines, skipping any others.
457 try {
458 var entry = JSON.parse(lines[i]);
459 if (entry &&
460 typeof(entry) == 'object' &&
461 entry.phase != undefined &&
462 entry.source != undefined &&
463 entry.time != undefined &&
464 entry.type != undefined) {
465 entries.push(entry);
466 }
467 } catch (err) {
468 err = err;
eroman 2011/01/12 05:57:34 is this line intended to be a no-op? Perhaps we s
mmenke 2011/01/13 03:45:29 Forgot to remove that line. Was using it as a bre
469 }
470 }
471
472 if (entries.length == 0) {
473 window.alert("Loading log file failed.");
474 return;
475 }
476
477 this.deleteAllEvents();
478
479 this.setIsViewingLogFile(true);
480
481 var validEntries = [];
482 for (var i = 0; i < entries.length; ++i) {
483 entries[i].wasPassivelyCaptured = true;
eroman 2011/01/12 05:57:34 any reason to initialize this to true rather than
mmenke 2011/01/13 03:45:29 I was just thinking the (P) emphasizes that we're
484 entries[i].source.type = LogSourceType[entries[i].source.type]
485 entries[i].type = LogEventType[entries[i].type]
486 entries[i].phase = LogEventPhase[entries[i].phase];
487 if (entries[i].source.type != undefined &&
488 entries[i].type != undefined &&
489 entries[i].phase != undefined) {
490 // TODO(mmenke): Do something reasonable when the event type isn't
491 // found, which could happen when event types are
492 // removed or added between versions. Could also happen
493 // with source types, but less likely.
494 validEntries.push(entries[i]);
495 }
496 }
497
498 this.numPassivelyCapturedEvents_ = validEntries.length;
499 this.addLogEntries(validEntries);
500
501 var numInvalidEntries = entries.length - validEntries.length;
502 if (numInvalidEntries > 0) {
503 window.alert(numInvalidEntries.toString() +
504 " entries could not be loaded, possibly due to version differences.");
505 }
506 }
507
442 //------------------------------------------------------------------------------ 508 //------------------------------------------------------------------------------
443 509
444 /** 510 /**
511 * Sets the |categoryTabSwitcher_| of BrowserBridge. Since views depend on
512 * g_browser being initialized, have to have a BrowserBridge prior to tab
513 * construction.
514 */
515 BrowserBridge.prototype.setTabSwitcher = function(categoryTabSwitcher) {
516 this.categoryTabSwitcher_ = categoryTabSwitcher;
517 };
518
519 /**
445 * Adds a listener of log entries. |observer| will be called back when new log 520 * Adds a listener of log entries. |observer| will be called back when new log
446 * data arrives, through: 521 * data arrives, through:
447 * 522 *
448 * observer.onLogEntryAdded(logEntry) 523 * observer.onLogEntryAdded(logEntry)
449 */ 524 */
450 BrowserBridge.prototype.addLogObserver = function(observer) { 525 BrowserBridge.prototype.addLogObserver = function(observer) {
451 this.logObservers_.push(observer); 526 this.logObservers_.push(observer);
452 }; 527 };
453 528
454 /** 529 /**
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 660
586 /** 661 /**
587 * Returns the number of events that were captured passively by the 662 * Returns the number of events that were captured passively by the
588 * browser prior to when the net-internals page was started. 663 * browser prior to when the net-internals page was started.
589 */ 664 */
590 BrowserBridge.prototype.getNumPassivelyCapturedEvents = function() { 665 BrowserBridge.prototype.getNumPassivelyCapturedEvents = function() {
591 return this.numPassivelyCapturedEvents_; 666 return this.numPassivelyCapturedEvents_;
592 }; 667 };
593 668
594 /** 669 /**
670 * Sends each entry to all log observers, and updates |capturedEvents_|.
671 * Also assigns unique ids to log entries without a source.
672 */
673 BrowserBridge.prototype.addLogEntries = function(logEntries) {
674 for (var e = 0; e < logEntries.length; ++e) {
675 var logEntry = logEntries[e];
676
677 // Assign unique ID, if needed.
678 if (logEntry.source.id == 0) {
679 logEntry.source.id = this.nextSourcelessEventId_;
680 --this.nextSourcelessEventId_;
681 }
682 this.capturedEvents_.push(logEntry);
683 for (var i = 0; i < this.logObservers_.length; ++i)
684 this.logObservers_[i].onLogEntryAdded(logEntry);
685 }
686 };
687
688 /**
595 * Deletes captured events with source IDs in |sourceIds|. 689 * Deletes captured events with source IDs in |sourceIds|.
596 */ 690 */
597 BrowserBridge.prototype.deleteEventsBySourceId = function(sourceIds) { 691 BrowserBridge.prototype.deleteEventsBySourceId = function(sourceIds) {
598 var sourceIdDict = {}; 692 var sourceIdDict = {};
599 for (var i = 0; i < sourceIds.length; i++) 693 for (var i = 0; i < sourceIds.length; i++)
600 sourceIdDict[sourceIds[i]] = true; 694 sourceIdDict[sourceIds[i]] = true;
601 695
602 var newEventList = []; 696 var newEventList = [];
603 for (var i = 0; i < this.capturedEvents_.length; ++i) { 697 for (var i = 0; i < this.capturedEvents_.length; ++i) {
604 var id = this.capturedEvents_[i].source.id; 698 var id = this.capturedEvents_[i].source.id;
(...skipping 14 matching lines...) Expand all
619 * Deletes all captured events. 713 * Deletes all captured events.
620 */ 714 */
621 BrowserBridge.prototype.deleteAllEvents = function() { 715 BrowserBridge.prototype.deleteAllEvents = function() {
622 this.capturedEvents_ = []; 716 this.capturedEvents_ = [];
623 this.numPassivelyCapturedEvents_ = 0; 717 this.numPassivelyCapturedEvents_ = 0;
624 for (var i = 0; i < this.logObservers_.length; ++i) 718 for (var i = 0; i < this.logObservers_.length; ++i)
625 this.logObservers_[i].onAllLogEntriesDeleted(); 719 this.logObservers_[i].onAllLogEntriesDeleted();
626 }; 720 };
627 721
628 /** 722 /**
629 * If |force| is true, calls all startUpdate functions. Otherwise, just 723 * Informs log observers whether or not future events will be from a log file.
630 * runs updates with active observers. 724 * Hides all tabs except the events and data tabs when viewing a log file, shows
725 * them all otherwise.
726 */
727 BrowserBridge.prototype.setIsViewingLogFile = function(isViewingLogFile) {
728 this.isViewingLogFile_ = isViewingLogFile;
729 var tabIds = this.categoryTabSwitcher_.getAllTabIds();
730
731 for (var i = 0; i < this.logObservers_.length; ++i)
732 this.logObservers_[i].onSetIsViewingLogFile(isViewingLogFile);
733
734 // Shows/hides tabs not used when viewing a log file.
735 for (var i = 0; i < tabIds.length; ++i) {
736 if (tabIds[i] == 'eventsTab' || tabIds[i] == 'dataTab')
737 continue;
738 this.categoryTabSwitcher_.showTabHandleNode(tabIds[i], !isViewingLogFile);
739 }
740
741 if (isViewingLogFile) {
742 var activeTab = this.categoryTabSwitcher_.findActiveTab();
743 if (activeTab.id != 'eventsTab')
744 this.categoryTabSwitcher_.switchToTab('dataTab', null);
745 }
746 };
747
748 /**
749 * If |force| is true, calls all startUpdate functions. Otherwise, just runs
750 * updates with active observers.
631 */ 751 */
632 BrowserBridge.prototype.checkForUpdatedInfo = function(force) { 752 BrowserBridge.prototype.checkForUpdatedInfo = function(force) {
633 for (name in this.pollableDataHelpers_) { 753 for (name in this.pollableDataHelpers_) {
634 var helper = this.pollableDataHelpers_[name]; 754 var helper = this.pollableDataHelpers_[name];
635 if (force || helper.hasActiveObserver()) 755 if (force || helper.hasActiveObserver())
636 helper.startUpdate(); 756 helper.startUpdate();
637 } 757 }
638 }; 758 };
639 759
640 /** 760 /**
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 return true; 875 return true;
756 }; 876 };
757 877
758 UpdateAllObserver.prototype.onDataReceived_ = function(helper, name, data) { 878 UpdateAllObserver.prototype.onDataReceived_ = function(helper, name, data) {
759 helper.removeObserver(this); 879 helper.removeObserver(this);
760 --this.observingCount_; 880 --this.observingCount_;
761 this.updatedData_[name] = data; 881 this.updatedData_[name] = data;
762 if (this.observingCount_ == 0) 882 if (this.observingCount_ == 0)
763 this.callback_(this.updatedData_); 883 this.callback_(this.updatedData_);
764 }; 884 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698