OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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¶m1=value1¶m2=value2&...". | 208 * Takes the current hash in form of "#tab¶m1=value1¶m2=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 Loading... |
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() { |
| 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 Loading... |
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 var numInvalidLines = 0; |
| 455 |
| 456 for (var i = 0; i < lines.length; ++i) { |
| 457 if (lines[i].trim().length == 0) |
| 458 continue; |
| 459 // Parse all valid lines, skipping any others. |
| 460 try { |
| 461 var entry = JSON.parse(lines[i]); |
| 462 if (entry && |
| 463 typeof(entry) == 'object' && |
| 464 entry.phase != undefined && |
| 465 entry.source != undefined && |
| 466 entry.time != undefined && |
| 467 entry.type != undefined) { |
| 468 entries.push(entry); |
| 469 continue; |
| 470 } |
| 471 } catch (err) { |
| 472 } |
| 473 ++numInvalidLines; |
| 474 console.log('Unable to parse log line: ' + lines[i]); |
| 475 } |
| 476 |
| 477 if (entries.length == 0) { |
| 478 window.alert('Loading log file failed.'); |
| 479 return; |
| 480 } |
| 481 |
| 482 this.deleteAllEvents(); |
| 483 |
| 484 this.setIsViewingLogFile_(true); |
| 485 |
| 486 var validEntries = []; |
| 487 for (var i = 0; i < entries.length; ++i) { |
| 488 entries[i].wasPassivelyCaptured = true; |
| 489 if (LogEventType[entries[i].type] != undefined && |
| 490 LogSourceType[entries[i].source.type] != undefined && |
| 491 LogEventPhase[entries[i].phase] != undefined) { |
| 492 entries[i].type = LogEventType[entries[i].type]; |
| 493 entries[i].source.type = LogSourceType[entries[i].source.type]; |
| 494 entries[i].phase = LogEventPhase[entries[i].phase]; |
| 495 validEntries.push(entries[i]); |
| 496 } else { |
| 497 // TODO(mmenke): Do something reasonable when the event type isn't |
| 498 // found, which could happen when event types are |
| 499 // removed or added between versions. Could also happen |
| 500 // with source types, but less likely. |
| 501 console.log( |
| 502 'Unrecognized values in log entry: ' + JSON.stringify(entry)); |
| 503 } |
| 504 } |
| 505 |
| 506 this.numPassivelyCapturedEvents_ = validEntries.length; |
| 507 this.addLogEntries(validEntries); |
| 508 |
| 509 var numInvalidEntries = entries.length - validEntries.length; |
| 510 if (numInvalidEntries > 0 || numInvalidLines > 0) { |
| 511 window.alert( |
| 512 numInvalidLines.toString() + |
| 513 ' could not be parsed as JSON strings, and ' + |
| 514 numInvalidEntries.toString() + |
| 515 ' entries don\'t have valid data.\n\n' + |
| 516 'Unparseable lines may indicate log file corruption.\n' + |
| 517 'Entries with invalid data may be caused by version differences.\n\n' + |
| 518 'See console for more information.'); |
| 519 } |
| 520 } |
| 521 |
442 //------------------------------------------------------------------------------ | 522 //------------------------------------------------------------------------------ |
443 | 523 |
444 /** | 524 /** |
| 525 * Sets the |categoryTabSwitcher_| of BrowserBridge. Since views depend on |
| 526 * g_browser being initialized, have to have a BrowserBridge prior to tab |
| 527 * construction. |
| 528 */ |
| 529 BrowserBridge.prototype.setTabSwitcher = function(categoryTabSwitcher) { |
| 530 this.categoryTabSwitcher_ = categoryTabSwitcher; |
| 531 }; |
| 532 |
| 533 /** |
445 * Adds a listener of log entries. |observer| will be called back when new log | 534 * Adds a listener of log entries. |observer| will be called back when new log |
446 * data arrives, through: | 535 * data arrives, through: |
447 * | 536 * |
448 * observer.onLogEntryAdded(logEntry) | 537 * observer.onLogEntryAdded(logEntry) |
449 */ | 538 */ |
450 BrowserBridge.prototype.addLogObserver = function(observer) { | 539 BrowserBridge.prototype.addLogObserver = function(observer) { |
451 this.logObservers_.push(observer); | 540 this.logObservers_.push(observer); |
452 }; | 541 }; |
453 | 542 |
454 /** | 543 /** |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 | 674 |
586 /** | 675 /** |
587 * Returns the number of events that were captured passively by the | 676 * Returns the number of events that were captured passively by the |
588 * browser prior to when the net-internals page was started. | 677 * browser prior to when the net-internals page was started. |
589 */ | 678 */ |
590 BrowserBridge.prototype.getNumPassivelyCapturedEvents = function() { | 679 BrowserBridge.prototype.getNumPassivelyCapturedEvents = function() { |
591 return this.numPassivelyCapturedEvents_; | 680 return this.numPassivelyCapturedEvents_; |
592 }; | 681 }; |
593 | 682 |
594 /** | 683 /** |
| 684 * Sends each entry to all log observers, and updates |capturedEvents_|. |
| 685 * Also assigns unique ids to log entries without a source. |
| 686 */ |
| 687 BrowserBridge.prototype.addLogEntries = function(logEntries) { |
| 688 for (var e = 0; e < logEntries.length; ++e) { |
| 689 var logEntry = logEntries[e]; |
| 690 |
| 691 // Assign unique ID, if needed. |
| 692 if (logEntry.source.id == 0) { |
| 693 logEntry.source.id = this.nextSourcelessEventId_; |
| 694 --this.nextSourcelessEventId_; |
| 695 } |
| 696 this.capturedEvents_.push(logEntry); |
| 697 for (var i = 0; i < this.logObservers_.length; ++i) |
| 698 this.logObservers_[i].onLogEntryAdded(logEntry); |
| 699 } |
| 700 }; |
| 701 |
| 702 /** |
595 * Deletes captured events with source IDs in |sourceIds|. | 703 * Deletes captured events with source IDs in |sourceIds|. |
596 */ | 704 */ |
597 BrowserBridge.prototype.deleteEventsBySourceId = function(sourceIds) { | 705 BrowserBridge.prototype.deleteEventsBySourceId = function(sourceIds) { |
598 var sourceIdDict = {}; | 706 var sourceIdDict = {}; |
599 for (var i = 0; i < sourceIds.length; i++) | 707 for (var i = 0; i < sourceIds.length; i++) |
600 sourceIdDict[sourceIds[i]] = true; | 708 sourceIdDict[sourceIds[i]] = true; |
601 | 709 |
602 var newEventList = []; | 710 var newEventList = []; |
603 for (var i = 0; i < this.capturedEvents_.length; ++i) { | 711 for (var i = 0; i < this.capturedEvents_.length; ++i) { |
604 var id = this.capturedEvents_[i].source.id; | 712 var id = this.capturedEvents_[i].source.id; |
(...skipping 14 matching lines...) Expand all Loading... |
619 * Deletes all captured events. | 727 * Deletes all captured events. |
620 */ | 728 */ |
621 BrowserBridge.prototype.deleteAllEvents = function() { | 729 BrowserBridge.prototype.deleteAllEvents = function() { |
622 this.capturedEvents_ = []; | 730 this.capturedEvents_ = []; |
623 this.numPassivelyCapturedEvents_ = 0; | 731 this.numPassivelyCapturedEvents_ = 0; |
624 for (var i = 0; i < this.logObservers_.length; ++i) | 732 for (var i = 0; i < this.logObservers_.length; ++i) |
625 this.logObservers_[i].onAllLogEntriesDeleted(); | 733 this.logObservers_[i].onAllLogEntriesDeleted(); |
626 }; | 734 }; |
627 | 735 |
628 /** | 736 /** |
| 737 * Informs log observers whether or not future events will be from a log file. |
| 738 * Hides all tabs except the events and data tabs when viewing a log file, shows |
| 739 * them all otherwise. |
| 740 */ |
| 741 BrowserBridge.prototype.setIsViewingLogFile_ = function(isViewingLogFile) { |
| 742 this.isViewingLogFile_ = isViewingLogFile; |
| 743 var tabIds = this.categoryTabSwitcher_.getAllTabIds(); |
| 744 |
| 745 for (var i = 0; i < this.logObservers_.length; ++i) |
| 746 this.logObservers_[i].onSetIsViewingLogFile(isViewingLogFile); |
| 747 |
| 748 // Shows/hides tabs not used when viewing a log file. |
| 749 for (var i = 0; i < tabIds.length; ++i) { |
| 750 if (tabIds[i] == 'eventsTab' || tabIds[i] == 'dataTab') |
| 751 continue; |
| 752 this.categoryTabSwitcher_.showTabHandleNode(tabIds[i], !isViewingLogFile); |
| 753 } |
| 754 |
| 755 if (isViewingLogFile) { |
| 756 var activeTab = this.categoryTabSwitcher_.findActiveTab(); |
| 757 if (activeTab.id != 'eventsTab') |
| 758 this.categoryTabSwitcher_.switchToTab('dataTab', null); |
| 759 } |
| 760 }; |
| 761 |
| 762 /** |
| 763 * Returns true if a log file is currently being viewed. |
| 764 */ |
| 765 BrowserBridge.prototype.isViewingLogFile = function() { |
| 766 return this.isViewingLogFile_; |
| 767 }; |
| 768 |
| 769 /** |
629 * If |force| is true, calls all startUpdate functions. Otherwise, just | 770 * If |force| is true, calls all startUpdate functions. Otherwise, just |
630 * runs updates with active observers. | 771 * runs updates with active observers. |
631 */ | 772 */ |
632 BrowserBridge.prototype.checkForUpdatedInfo = function(force) { | 773 BrowserBridge.prototype.checkForUpdatedInfo = function(force) { |
633 for (name in this.pollableDataHelpers_) { | 774 for (name in this.pollableDataHelpers_) { |
634 var helper = this.pollableDataHelpers_[name]; | 775 var helper = this.pollableDataHelpers_[name]; |
635 if (force || helper.hasActiveObserver()) | 776 if (force || helper.hasActiveObserver()) |
636 helper.startUpdate(); | 777 helper.startUpdate(); |
637 } | 778 } |
638 }; | 779 }; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
755 return true; | 896 return true; |
756 }; | 897 }; |
757 | 898 |
758 UpdateAllObserver.prototype.onDataReceived_ = function(helper, name, data) { | 899 UpdateAllObserver.prototype.onDataReceived_ = function(helper, name, data) { |
759 helper.removeObserver(this); | 900 helper.removeObserver(this); |
760 --this.observingCount_; | 901 --this.observingCount_; |
761 this.updatedData_[name] = data; | 902 this.updatedData_[name] = data; |
762 if (this.observingCount_ == 0) | 903 if (this.observingCount_ == 0) |
763 this.callback_(this.updatedData_); | 904 this.callback_(this.updatedData_); |
764 }; | 905 }; |
OLD | NEW |