summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/net_internals
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-20 18:58:39 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-20 18:58:39 +0000
commit9679b7b8c7937e7e620c63a60ad6d17c5af7570b (patch)
tree9ef0434cad20ae8c2da7c518332f92d4645ac6a6 /chrome/browser/resources/net_internals
parent643dc3cc13eddddd66a989c11398dfd14b36afbd (diff)
downloadchromium_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.js24
-rw-r--r--chrome/browser/resources/net_internals/index.html18
-rw-r--r--chrome/browser/resources/net_internals/logviewpainter.js2
-rw-r--r--chrome/browser/resources/net_internals/main.js2
-rw-r--r--chrome/browser/resources/net_internals/socketpoolwrapper.js138
-rw-r--r--chrome/browser/resources/net_internals/socketsview.js116
-rw-r--r--chrome/browser/resources/net_internals/util.js130
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;
+};
+