diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-20 18:58:39 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-20 18:58:39 +0000 |
commit | 9679b7b8c7937e7e620c63a60ad6d17c5af7570b (patch) | |
tree | 9ef0434cad20ae8c2da7c518332f92d4645ac6a6 /chrome/browser/resources/net_internals | |
parent | 643dc3cc13eddddd66a989c11398dfd14b36afbd (diff) | |
download | chromium_src-9679b7b8c7937e7e620c63a60ad6d17c5af7570b.zip chromium_src-9679b7b8c7937e7e620c63a60ad6d17c5af7570b.tar.gz chromium_src-9679b7b8c7937e7e620c63a60ad6d17c5af7570b.tar.bz2 |
Adds state of socket pools to net-internals data dumps as a series of tables.Extends TablePrinter to output HTML in addition to plain text tables, to avoid duplicating code to populate the tables.BUG=39756TEST=manual
Review URL: http://codereview.chromium.org/3451001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@59953 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources/net_internals')
-rw-r--r-- | chrome/browser/resources/net_internals/dataview.js | 24 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/index.html | 18 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/logviewpainter.js | 2 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/main.js | 2 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/socketpoolwrapper.js | 138 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/socketsview.js | 116 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/util.js | 130 |
7 files changed, 304 insertions, 126 deletions
diff --git a/chrome/browser/resources/net_internals/dataview.js b/chrome/browser/resources/net_internals/dataview.js index 2c97f0c..331b857 100644 --- a/chrome/browser/resources/net_internals/dataview.js +++ b/chrome/browser/resources/net_internals/dataview.js @@ -193,6 +193,14 @@ DataView.prototype.onExportToText_ = function() { for (var statName in httpCacheStats) text.push(statName + ': ' + httpCacheStats[statName]); + text.push(''); + text.push('----------------------------------------------'); + text.push(' Socket pools'); + text.push('----------------------------------------------'); + text.push(''); + + this.appendSocketPoolsAsText_(text); + // Open a new window to display this text. this.setText_(text.join('\n')); @@ -257,6 +265,22 @@ DataView.prototype.appendRequestsPrintedAsText_ = function(out) { } }; +DataView.prototype.appendSocketPoolsAsText_ = function(text) { + var socketPools = SocketPoolWrapper.createArrayFrom( + g_browser.socketPoolInfo_.currentData_); + var tablePrinter = SocketPoolWrapper.createTablePrinter(socketPools); + text.push(tablePrinter.toText(2)); + + text.push(''); + + for (var i = 0; i < socketPools.length; ++i) { + if (socketPools[i].origPool.groups == undefined) + continue; + var groupTablePrinter = socketPools[i].createGroupTablePrinter(); + text.push(groupTablePrinter.toText(2)); + } +}; + /** * Helper function to set this view's content to |text|. */ diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html index 120960a..69f5ada 100644 --- a/chrome/browser/resources/net_internals/index.html +++ b/chrome/browser/resources/net_internals/index.html @@ -23,6 +23,7 @@ found in the LICENSE file. <script src="logviewpainter.js"></script> <script src="loggrouper.js"></script> <script src="proxyview.js"></script> + <script src="socketpoolwrapper.js"></script> <script src="socketsview.js"></script> <script src="serviceprovidersview.js"></script> </head> @@ -109,21 +110,8 @@ found in the LICENSE file. </div> <div id=socketsTabContent> <h4>Socket pools</h4> - <table class="styledTable"> - <thead> - <tr> - <th>Name</th> - <th>Handed Out</th> - <th>Connecting</th> - <th>Idle</th> - <th>Max</th> - <th>Max Per Group</th> - <th>Generation Number</th> - </tr> - </thead> - <tbody id=socketTabTbody> - </tbody> - </table> + <div id=socketPoolDiv> + </div> <div id=socketPoolGroupsDiv> </div> </div> diff --git a/chrome/browser/resources/net_internals/logviewpainter.js b/chrome/browser/resources/net_internals/logviewpainter.js index d9de54b..d82a027 100644 --- a/chrome/browser/resources/net_internals/logviewpainter.js +++ b/chrome/browser/resources/net_internals/logviewpainter.js @@ -133,7 +133,7 @@ PrintSourceEntriesAsText = function(sourceEntries, doSecurityStripping) { } // Format the table for fixed-width text. - return tablePrinter.toText(); + return tablePrinter.toText(0); } function getTextForExtraParams(entry, doSecurityStripping) { diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js index 0e213b4..281524e 100644 --- a/chrome/browser/resources/net_internals/main.js +++ b/chrome/browser/resources/net_internals/main.js @@ -82,7 +82,7 @@ function onLoaded() { "httpCacheStats"); var socketsView = new SocketsView("socketsTabContent", - "socketTabTbody", + "socketPoolDiv", "socketPoolGroupsDiv"); diff --git a/chrome/browser/resources/net_internals/socketpoolwrapper.js b/chrome/browser/resources/net_internals/socketpoolwrapper.js new file mode 100644 index 0000000..48d8f37 --- /dev/null +++ b/chrome/browser/resources/net_internals/socketpoolwrapper.js @@ -0,0 +1,138 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * SocketPoolWrapper is a wrapper around socket pools entries. It's + * used by the log and sockets view to print tables containing both + * a synopsis of the state of all pools, and listing the groups within + * individual pools. + * + * The constructor takes a socket pool and its parent, and generates a + * unique name from the two, which is stored as |fullName|. |parent| + * must itself be a SocketPoolWrapper. + * + * @constructor + */ +function SocketPoolWrapper(socketPool, parent) { + this.origPool = socketPool; + this.fullName = socketPool.name; + if (this.fullName != socketPool.type) + this.fullName += ' (' + socketPool.type + ')'; + if (parent) + this.fullName = parent.fullName + '->' + this.fullName; +} + +/** + * Returns an array of SocketPoolWrappers created from each of the socket pools + * in |socketPoolInfo|. Nested socket pools appear immediately after their + * parent, and groups of nodes from trees with root nodes with the same id are + * placed adjacent to each other. + */ +SocketPoolWrapper.createArrayFrom = function(socketPoolInfo) { + // Create SocketPoolWrappers for each socket pool and separate socket pools + // them into different arrays based on root node name. + var socketPoolGroups = []; + var socketPoolNameLists = {}; + for (var i = 0; i < socketPoolInfo.length; ++i) { + var name = socketPoolInfo[i].name; + if (!socketPoolNameLists[name]) { + socketPoolNameLists[name] = []; + socketPoolGroups.push(socketPoolNameLists[name]); + } + SocketPoolWrapper.addSocketPoolsToList_(socketPoolNameLists[name], + socketPoolInfo[i], null); + } + + // Merge the arrays. + var socketPoolList = []; + for (var i = 0; i < socketPoolGroups.length; ++i) { + socketPoolList = socketPoolList.concat(socketPoolGroups[i]); + } + return socketPoolList; +}; + +/** + * Recursively creates SocketPoolWrappers from |origPool| and all its + * children and adds them all to |socketPoolList|. |parent| is the + * SocketPoolWrapper for the parent of |origPool|, or null, if it's + * a top level socket pool. + */ +SocketPoolWrapper.addSocketPoolsToList_ = function(socketPoolList, + origPool, + parent) { + var socketPool = new SocketPoolWrapper(origPool, parent); + socketPoolList.push(socketPool); + if (origPool.nested_pools) { + for (var i = 0; i < origPool.nested_pools.length; ++i) { + SocketPoolWrapper.addSocketPoolsToList_(socketPoolList, + origPool.nested_pools[i], + socketPool); + } + } +}; + +/** + * Returns a table printer containing information on each + * SocketPoolWrapper in |socketPools|. + */ +SocketPoolWrapper.createTablePrinter = function(socketPools) { + var tablePrinter = new TablePrinter(); + tablePrinter.addHeaderCell('Name'); + tablePrinter.addHeaderCell('Handed Out'); + tablePrinter.addHeaderCell('Connecting'); + tablePrinter.addHeaderCell('Idle'); + tablePrinter.addHeaderCell('Max'); + tablePrinter.addHeaderCell('Max Per Group'); + tablePrinter.addHeaderCell('Generation'); + + for (var i = 0; i < socketPools.length; i++) { + var origPool = socketPools[i].origPool; + + tablePrinter.addRow(); + tablePrinter.addCell(socketPools[i].fullName); + tablePrinter.addCell(origPool.connecting_socket_count); + tablePrinter.addCell(origPool.handed_out_socket_count); + tablePrinter.addCell(origPool.idle_socket_count); + tablePrinter.addCell(origPool.max_socket_count); + tablePrinter.addCell(origPool.max_sockets_per_group); + tablePrinter.addCell(origPool.pool_generation_number); + } + return tablePrinter; +}; + +/** + * Returns a table printer containing information on all a + * socket pool's groups. + */ +SocketPoolWrapper.prototype.createGroupTablePrinter = function() { + var tablePrinter = new TablePrinter(); + tablePrinter.setTitle(this.fullName); + + tablePrinter.addHeaderCell('Name'); + tablePrinter.addHeaderCell('Pending'); + tablePrinter.addHeaderCell('Top Priority'); + tablePrinter.addHeaderCell('Active'); + tablePrinter.addHeaderCell('Idle'); + tablePrinter.addHeaderCell('Connect Jobs'); + tablePrinter.addHeaderCell('Backup Job'); + tablePrinter.addHeaderCell('Stalled'); + + for (var groupName in this.origPool.groups) { + var group = this.origPool.groups[groupName]; + + tablePrinter.addRow(); + tablePrinter.addCell(groupName); + tablePrinter.addCell(group.pending_request_count); + if (group.top_pending_priority != undefined) + tablePrinter.addCell(group.top_pending_priority); + else + tablePrinter.addCell('-'); + tablePrinter.addCell(group.active_socket_count); + tablePrinter.addCell(group.idle_socket_count); + tablePrinter.addCell(group.connect_job_count); + tablePrinter.addCell(group.has_backup_job); + tablePrinter.addCell(group.is_stalled); + } + return tablePrinter; +}; diff --git a/chrome/browser/resources/net_internals/socketsview.js b/chrome/browser/resources/net_internals/socketsview.js index 97e66cc..1815999 100644 --- a/chrome/browser/resources/net_internals/socketsview.js +++ b/chrome/browser/resources/net_internals/socketsview.js @@ -11,122 +11,34 @@ * * @constructor */ -function SocketsView(mainBoxId, socketPoolsTbodyId, socketPoolGroupsDivId) { +function SocketsView(mainBoxId, socketPoolDivId, socketPoolGroupsDivId) { DivView.call(this, mainBoxId); g_browser.addSocketPoolInfoObserver(this); - this.socketPoolsTbody_ = document.getElementById(socketPoolsTbodyId); + this.socketPoolDiv_ = document.getElementById(socketPoolDivId); this.socketPoolGroupsDiv_ = document.getElementById(socketPoolGroupsDivId); } inherits(SocketsView, DivView); SocketsView.prototype.onSocketPoolInfoChanged = function(socketPoolInfo) { - this.socketPoolsTbody_.innerHTML = ''; + this.socketPoolDiv_.innerHTML = ''; this.socketPoolGroupsDiv_.innerHTML = ''; if (!socketPoolInfo) return; - socketPoolGroups = this.groupSocketPoolsByName_(socketPoolInfo); - - for (var i = 0; i < socketPoolGroups.length; ++i) { - for (var j = 0; j < socketPoolGroups[i].length; ++j) - this.addSocketPool_(socketPoolGroups[i][j], ''); - } -}; - -/** - * Puts socket pools with the same name in lists contained within a new list. - */ -SocketsView.prototype.groupSocketPoolsByName_ = function(socketPoolInfo) { - var socketPoolGroups = []; - var socketPoolNameLists = {}; - for (var i = 0; i < socketPoolInfo.length; ++i) { - var name = socketPoolInfo[i].name; - if (!socketPoolNameLists[name]) { - socketPoolNameLists[name] = []; - socketPoolGroups.push(socketPoolNameLists[name]); - } - socketPoolNameLists[name].push(socketPoolInfo[i]); - } - return socketPoolGroups; -}; - -/** - * Adds the socket pool to the bottom of the main table and, if there are - * any groups, creates a table at the bottom listing those as well. - * Recursively called on nested socket pools, if any. - * |prefix| is added before a socket pool's name to indicate nesting - * relationships. - */ -SocketsView.prototype.addSocketPool_ = function(socketPool, prefix) { - var socketPoolRow = addNode(this.socketPoolsTbody_, 'tr'); - - var socketPoolName = prefix + socketPool.name; - if (socketPool.name != socketPool.type) - socketPoolName += ' (' + socketPool.type + ')'; - - addNodeWithText(socketPoolRow, 'td', socketPoolName); - addNodeWithText(socketPoolRow, 'td', socketPool.connecting_socket_count); - addNodeWithText(socketPoolRow, 'td', socketPool.handed_out_socket_count); - addNodeWithText(socketPoolRow, 'td', socketPool.idle_socket_count); - addNodeWithText(socketPoolRow, 'td', socketPool.max_socket_count); - addNodeWithText(socketPoolRow, 'td', socketPool.max_sockets_per_group); - addNodeWithText(socketPoolRow, 'td', socketPool.pool_generation_number); - - if (socketPool.groups != undefined) - this.addSocketPoolGroupTable_(socketPoolName, socketPool); - - if (socketPool.nested_pools) { - for (var i = 0; i < socketPool.nested_pools.length; ++i) { - this.addSocketPool_(socketPool.nested_pools[i], socketPoolName + ' ->'); + var socketPools = SocketPoolWrapper.createArrayFrom(socketPoolInfo); + var tablePrinter = SocketPoolWrapper.createTablePrinter(socketPools); + tablePrinter.toHTML(this.socketPoolDiv_, 'styledTable'); + + // Add table for each socket pool with information on each of its groups. + for (var i = 0; i < socketPools.length; ++i) { + if (socketPools[i].origPool.groups != undefined) { + var p = addNode(this.socketPoolGroupsDiv_, 'p'); + var br = addNode(p, 'br'); + var groupTablePrinter = socketPools[i].createGroupTablePrinter(); + groupTablePrinter.toHTML(p, 'styledTable'); } } }; - -/** - * Creates a table at the bottom listing all a socket pool's groups. - */ -SocketsView.prototype.addSocketPoolGroupTable_ = function(socketPoolName, - socketPool) { - var p = addNode(this.socketPoolGroupsDiv_, 'p'); - var br = addNode(p, 'br'); - var table = addNode(p, 'table'); - table.setAttribute('class', 'styledTable'); - - var thead = addNode(table, 'thead'); - var tableTitleRow = addNode(thead, 'tr'); - var tableTitle = addNodeWithText(tableTitleRow, 'th', socketPoolName); - tableTitle.colSpan = 8; - changeClassName(tableTitle, 'title', true); - - var headerRow = addNode(thead, 'tr'); - addNodeWithText(headerRow, 'th', 'Name'); - addNodeWithText(headerRow, 'th', 'Pending'); - addNodeWithText(headerRow, 'th', 'Top Priority'); - addNodeWithText(headerRow, 'th', 'Active'); - addNodeWithText(headerRow, 'th', 'Idle'); - addNodeWithText(headerRow, 'th', 'Connect Jobs'); - addNodeWithText(headerRow, 'th', 'Backup Job'); - addNodeWithText(headerRow, 'th', 'Stalled'); - - var tbody = addNode(table, 'tbody'); - for (var groupName in socketPool.groups) { - var group = socketPool.groups[groupName]; - var tr = addNode(tbody, 'tr'); - - addNodeWithText(tr, 'td', groupName); - addNodeWithText(tr, 'td', group.pending_request_count); - if (group.top_pending_priority != undefined) - addNodeWithText(tr, 'td', group.top_pending_priority); - else - addNodeWithText(tr, 'td', '-'); - addNodeWithText(tr, 'td', group.active_socket_count); - addNodeWithText(tr, 'td', group.idle_socket_count); - addNodeWithText(tr, 'td', group.connect_job_count); - addNodeWithText(tr, 'td', group.has_backup_job); - addNodeWithText(tr, 'td', group.is_stalled); - } -}; - diff --git a/chrome/browser/resources/net_internals/util.js b/chrome/browser/resources/net_internals/util.js index 2c5c056..7b85229 100644 --- a/chrome/browser/resources/net_internals/util.js +++ b/chrome/browser/resources/net_internals/util.js @@ -115,13 +115,26 @@ function makeRepeatedString(str, count) { } /** - * TablePrinter is a helper to format a table as ascii art. + * TablePrinter is a helper to format a table as ascii art or an HTML table. * - * Usage: call addRow() and addCell() repeatedly to specify the data. Ones - * all the fields have been inputted, call toText() to format it as text. + * Usage: call addRow() and addCell() repeatedly to specify the data. + * + * addHeaderCell() can optionally be called to specify header cells for a + * single header row. The header row appears at the top of an HTML formatted + * table, and uses thead and th tags. In ascii tables, the header is separated + * from the table body by a partial row of dashes. + * + * setTitle() can optionally be used to set a title that is displayed before + * the header row. In HTML tables, it uses the title class and in ascii tables + * it's between two rows of dashes. + * + * Once all the fields have been input, call toText() to format it as text or + * toHTML() to format it as HTML. */ function TablePrinter() { this.rows_ = []; + this.hasHeaderRow_ = false; + this.title_ = null; } function TablePrinterCell(value) { @@ -149,6 +162,27 @@ TablePrinter.prototype.addCell = function(cellText) { return cell; }; +TablePrinter.prototype.setTitle = function(title) { + this.title_ = title; +}; + +/** + * Adds a header row, if not already present, and adds a new column to it, + * setting its contents to |headerText|. + * + * @returns {!TablePrinterCell} the cell that was added. + */ +TablePrinter.prototype.addHeaderCell = function(headerText) { + // Insert empty new row at start of |rows_| if currently no header row. + if (!this.hasHeaderRow_) { + this.rows_.splice(0, 0, []); + this.hasHeaderRow_ = true; + } + var cell = new TablePrinterCell(headerText); + this.rows_[0].push(cell); + return cell; +}; + /** * Returns the maximum number of columns this table contains. */ @@ -175,9 +209,10 @@ TablePrinter.prototype.getCell_ = function(rowIndex, columnIndex) { /** * Returns a formatted text representation of the table data. + * |spacing| indicates number of extra spaces, if any, to add between + * columns. */ -TablePrinter.prototype.toText = function() { - var numRows = this.rows_.length; +TablePrinter.prototype.toText = function(spacing) { var numColumns = this.getNumColumns(); // Figure out the maximum width of each column. @@ -186,6 +221,20 @@ TablePrinter.prototype.toText = function() { for (var i = 0; i < numColumns; ++i) columnWidths[i] = 0; + // If header row is present, temporarily add a spacer row to |rows_|. + if (this.hasHeaderRow_) { + var headerSpacerRow = []; + for (var c = 0; c < numColumns; ++c) { + var cell = this.getCell_(0, c); + if (!cell) + continue; + var spacerStr = makeRepeatedString('-', cell.text.length); + headerSpacerRow.push(new TablePrinterCell(spacerStr)); + } + this.rows_.splice(1, 0, headerSpacerRow); + } + + var numRows = this.rows_.length; for (var c = 0; c < numColumns; ++c) { for (var r = 0; r < numRows; ++r) { var cell = this.getCell_(r, c); @@ -195,13 +244,26 @@ TablePrinter.prototype.toText = function() { } } - // Print each row. var out = []; + + // Print title, if present. + if (this.title_) { + var titleSpacerStr = makeRepeatedString('-', this.title_.length); + out.push(titleSpacerStr); + out.push('\n'); + out.push(this.title_); + out.push('\n'); + out.push(titleSpacerStr); + out.push('\n'); + } + + // Print each row. + var spacingStr = makeRepeatedString(' ', spacing); for (var r = 0; r < numRows; ++r) { for (var c = 0; c < numColumns; ++c) { var cell = this.getCell_(r, c); if (cell) { - // Padd the cell with spaces to make it fit the maximum column width. + // Pad the cell with spaces to make it fit the maximum column width. var padding = columnWidths[c] - cell.text.length; var paddingStr = makeRepeatedString(' ', padding); @@ -212,11 +274,65 @@ TablePrinter.prototype.toText = function() { out.push(cell.text); out.push(paddingStr); } + out.push(spacingStr); } } out.push('\n'); } + // Remove spacer row under the header row, if one was added. + if (this.hasHeaderRow_) + this.rows_.splice(1, 1); + return out.join(''); }; +/** + * Adds a new HTML table to the node |parent| using the specified style. + */ +TablePrinter.prototype.toHTML = function(parent, style) { + var numRows = this.rows_.length; + var numColumns = this.getNumColumns(); + + var table = addNode(parent, 'table'); + table.setAttribute('class', style); + + var thead = addNode(table, 'thead'); + var tbody = addNode(table, 'tbody'); + + // Add title, if needed. + if (this.title_) { + var tableTitleRow = addNode(thead, 'tr'); + var tableTitle = addNodeWithText(tableTitleRow, 'th', this.title_); + tableTitle.colSpan = numColumns; + changeClassName(tableTitle, 'title', true); + } + + // Fill table body, adding header row first, if needed. + for (var r = 0; r < numRows; ++r) { + var cellType; + var row; + if (r == 0 && this.hasHeaderRow_) { + row = addNode(thead, 'tr'); + cellType = 'th'; + } else { + row = addNode(tbody, 'tr'); + cellType = 'td'; + } + for (var c = 0; c < numColumns; ++c) { + var cell = this.getCell_(r, c); + if (cell) { + var tableCell = addNodeWithText(row, cellType, cell.text); + if (cell.alignRight) + tableCell.alignRight = true; + // If allowing overflow on the rightmost cell of a row, + // make the cell span the rest of the columns. Otherwise, + // ignore the flag. + if (cell.allowOverflow && !this.getCell_(r, c + 1)) + tableCell.colSpan = numColumns - c; + } + } + } + return table; +}; + |