diff options
author | simonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-20 22:17:03 +0000 |
---|---|---|
committer | simonjam@chromium.org <simonjam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-20 22:17:03 +0000 |
commit | 837c4f559f45a1b66c1e6af28924ce51a1133c03 (patch) | |
tree | 15d3465f40abd57ccebae87c9df0c05bdc2668f0 /chrome | |
parent | 096fa7b6ccf1c147a4c510516c6aa93419bb4d0a (diff) | |
download | chromium_src-837c4f559f45a1b66c1e6af28924ce51a1133c03.zip chromium_src-837c4f559f45a1b66c1e6af28924ce51a1133c03.tar.gz chromium_src-837c4f559f45a1b66c1e6af28924ce51a1133c03.tar.bz2 |
Add HTTP pipelining to net-internals:
- Make HttpPipelinedConnection its own NetLog::Source
- Report when pipelines are constructed and deleted
- Report pipelining feedback
- Add a HTTP Pipelining tab with status, active pipelines, and known hosts.
BUG=None
TEST=chrome://net-internals
Review URL: http://codereview.chromium.org/8947012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@115197 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
16 files changed, 336 insertions, 3 deletions
diff --git a/chrome/browser/net/passive_log_collector.cc b/chrome/browser/net/passive_log_collector.cc index 3185387..d7b93e0 100644 --- a/chrome/browser/net/passive_log_collector.cc +++ b/chrome/browser/net/passive_log_collector.cc @@ -83,6 +83,8 @@ PassiveLogCollector::PassiveLogCollector() trackers_[net::NetLog::SOURCE_UDP_SOCKET] = &udp_socket_tracker_; trackers_[net::NetLog::SOURCE_CERT_VERIFIER_JOB] = &cert_verifier_job_tracker_; + trackers_[net::NetLog::SOURCE_HTTP_PIPELINED_CONNECTION] = + &http_pipelined_connection_tracker_; // Make sure our mapping is up-to-date. for (size_t i = 0; i < arraysize(trackers_); ++i) DCHECK(trackers_[i]) << "Unhandled SourceType: " << i; @@ -785,3 +787,30 @@ PassiveLogCollector::CertVerifierJobTracker::DoAddEntry( } return ACTION_NONE; } + +//---------------------------------------------------------------------------- +// HttpPipelinedConnectionTracker +//---------------------------------------------------------------------------- + +const size_t +PassiveLogCollector::HttpPipelinedConnectionTracker::kMaxNumSources = 100; + +const size_t +PassiveLogCollector::HttpPipelinedConnectionTracker::kMaxGraveyardSize = 25; + +PassiveLogCollector:: + HttpPipelinedConnectionTracker::HttpPipelinedConnectionTracker() + : SourceTracker(kMaxNumSources, kMaxGraveyardSize, NULL) { +} + +PassiveLogCollector::SourceTracker::Action +PassiveLogCollector::HttpPipelinedConnectionTracker::DoAddEntry( + const ChromeNetLog::Entry& entry, + SourceInfo* out_info) { + AddEntryToSourceInfo(entry, out_info); + if (entry.type == net::NetLog::TYPE_HTTP_PIPELINED_CONNECTION && + entry.phase == net::NetLog::PHASE_END) { + return ACTION_MOVE_TO_GRAVEYARD; + } + return ACTION_NONE; +} diff --git a/chrome/browser/net/passive_log_collector.h b/chrome/browser/net/passive_log_collector.h index 7a67925..b1a079a 100644 --- a/chrome/browser/net/passive_log_collector.h +++ b/chrome/browser/net/passive_log_collector.h @@ -400,7 +400,7 @@ class PassiveLogCollector : public ChromeNetLog::ThreadSafeObserverImpl { DISALLOW_COPY_AND_ASSIGN(UDPSocketTracker); }; - // Tracks the log entries for the last seen SOURCE_CERT_VERIFIER_JOB + // Tracks the log entries for the last seen SOURCE_CERT_VERIFIER_JOB. class CertVerifierJobTracker : public SourceTracker { public: static const size_t kMaxNumSources; @@ -415,6 +415,21 @@ class PassiveLogCollector : public ChromeNetLog::ThreadSafeObserverImpl { DISALLOW_COPY_AND_ASSIGN(CertVerifierJobTracker); }; + // Tracks the log entries for the last seen SOURCE_HTTP_PIPELINED_CONNECTION. + class HttpPipelinedConnectionTracker : public SourceTracker { + public: + static const size_t kMaxNumSources; + static const size_t kMaxGraveyardSize; + + HttpPipelinedConnectionTracker(); + + private: + virtual Action DoAddEntry(const ChromeNetLog::Entry& entry, + SourceInfo* out_info) OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(HttpPipelinedConnectionTracker); + }; + PassiveLogCollector(); virtual ~PassiveLogCollector(); @@ -459,6 +474,7 @@ class PassiveLogCollector : public ChromeNetLog::ThreadSafeObserverImpl { AsyncHostResolverRequestTracker async_host_resolver_request_tracker_; UDPSocketTracker udp_socket_tracker_; CertVerifierJobTracker cert_verifier_job_tracker_; + HttpPipelinedConnectionTracker http_pipelined_connection_tracker_; // This array maps each NetLog::SourceType to one of the tracker instances // defined above. Use of this array avoid duplicating the list of trackers diff --git a/chrome/browser/resources/net_internals/browser_bridge.js b/chrome/browser/resources/net_internals/browser_bridge.js index 8c65479..969df1c 100644 --- a/chrome/browser/resources/net_internals/browser_bridge.js +++ b/chrome/browser/resources/net_internals/browser_bridge.js @@ -61,6 +61,9 @@ var BrowserBridge = (function() { this.pollableDataHelpers_.prerenderInfo = new PollableDataHelper('onPrerenderInfoChanged', this.sendGetPrerenderInfo.bind(this)); + this.pollableDataHelpers_.httpPipeliningStatus = + new PollableDataHelper('onHttpPipeliningStatusChanged', + this.sendGetHttpPipeliningStatus.bind(this)); // NetLog entries are all sent to the |SourceTracker|, which both tracks // them and manages its own observer list. @@ -234,6 +237,10 @@ var BrowserBridge = (function() { this.send('importONCFile', [fileContent, passcode]); }, + sendGetHttpPipeliningStatus: function() { + this.send('getHttpPipeliningStatus'); + }, + //-------------------------------------------------------------------------- // Messages received from the browser. //-------------------------------------------------------------------------- @@ -341,6 +348,11 @@ var BrowserBridge = (function() { this.pollableDataHelpers_.prerenderInfo.update(prerenderInfo); }, + receivedHttpPipeliningStatus: function(httpPipeliningStatus) { + this.pollableDataHelpers_.httpPipeliningStatus.update( + httpPipeliningStatus); + }, + //-------------------------------------------------------------------------- /** @@ -548,6 +560,17 @@ var BrowserBridge = (function() { }, /** + * Adds a listener of HTTP pipelining status. |observer| will be called + * back when data is received, through: + * + * observer.onHttpPipelineStatusChanged(httpPipeliningStatus) + */ + addHttpPipeliningStatusObserver: function(observer, ignoreWhenUnchanged) { + this.pollableDataHelpers_.httpPipeliningStatus.addObserver( + observer, ignoreWhenUnchanged); + }, + + /** * If |force| is true, calls all startUpdate functions. Otherwise, just * runs updates with active observers. */ diff --git a/chrome/browser/resources/net_internals/category_tabs.html b/chrome/browser/resources/net_internals/category_tabs.html index e617a20..6025cf7 100644 --- a/chrome/browser/resources/net_internals/category_tabs.html +++ b/chrome/browser/resources/net_internals/category_tabs.html @@ -9,6 +9,7 @@ <a href="#dns" id=tab-handle-dns>DNS</a> <a href="#sockets" id=tab-handle-sockets>Sockets</a> <a href="#spdy" id=tab-handle-spdy>SPDY</a> + <a href="#httpPipeline" id=tab-handle-http-pipeline>HTTP Pipelining</a> <a href="#httpCache" id=tab-handle-http-cache>HTTP Cache</a> <a href="#httpThrottling" id=tab-handle-http-throttling>HTTP Throttling</a> <!-- Tab is only shown on Windows --> diff --git a/chrome/browser/resources/net_internals/http_pipeline_view.html b/chrome/browser/resources/net_internals/http_pipeline_view.html new file mode 100644 index 0000000..d2991ad --- /dev/null +++ b/chrome/browser/resources/net_internals/http_pipeline_view.html @@ -0,0 +1,23 @@ +<div id=http-pipeline-view-tab-content> + <h4>HTTP Pipelining Status</h4> + <ul> + <li>HTTP Pipelining Enabled: <span id=http-pipeline-view-enabled-span>????</span></li> + </ul> + + <h4>HTTP Pipelined Connections</h4> + <!-- Only one of these two are shown --> + <span id=http-pipeline-view-connections-none-span>None</span> + <span id=http-pipeline-view-connections-link-span style="display: none;"> + <a href="#events&q=type:HTTP_PIPELINED_CONNECTION%20is:active">View live HTTP pipelined connections</a> + </span> + <p> + <div id=http-pipeline-view-connections-div> + </div> + </p> + + <h4>Known Hosts</h4> + <p> + <div id=http-pipeline-view-known-hosts-div> + </div> + </p> +</div> diff --git a/chrome/browser/resources/net_internals/http_pipeline_view.js b/chrome/browser/resources/net_internals/http_pipeline_view.js new file mode 100644 index 0000000..39652be --- /dev/null +++ b/chrome/browser/resources/net_internals/http_pipeline_view.js @@ -0,0 +1,169 @@ +// Copyright (c) 2011 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. + +/** + * This view displays a summary of the state of each HTTP pipelined connection, + * and has links to display them in the events tab. + */ +var HttpPipelineView = (function() { + 'use strict'; + + // We inherit from DivView. + var superClass = DivView; + + /** + * @constructor + */ + function HttpPipelineView() { + assertFirstConstructorCall(HttpPipelineView); + + // Call superclass's constructor. + superClass.call(this, HttpPipelineView.MAIN_BOX_ID); + + g_browser.addHttpPipeliningStatusObserver(this, true); + + this.httpPipeliningEnabledSpan_ = $(HttpPipelineView.ENABLED_SPAN_ID); + this.httpPipelineConnectionsNoneSpan_ = + $(HttpPipelineView.CONNECTIONS_NONE_SPAN_ID); + this.httpPipelineConnectionsLinkSpan_ = + $(HttpPipelineView.CONNECTIONS_LINK_SPAN_ID); + this.httpPipelineConnectionsDiv_ = $(HttpPipelineView.CONNECTIONS_DIV_ID); + this.httpPipelineKnownHostsDiv_ = $(HttpPipelineView.KNOWN_HOSTS_DIV_ID); + } + + // ID for special HTML element in category_tabs.html + HttpPipelineView.TAB_HANDLE_ID = 'tab-handle-http-pipeline'; + + // IDs for special HTML elements in http_pipeline_view.html + HttpPipelineView.MAIN_BOX_ID = 'http-pipeline-view-tab-content'; + HttpPipelineView.ENABLED_SPAN_ID = 'http-pipeline-view-enabled-span'; + HttpPipelineView.CONNECTIONS_NONE_SPAN_ID = + 'http-pipeline-view-connections-none-span'; + HttpPipelineView.CONNECTIONS_LINK_SPAN_ID = + 'http-pipeline-view-connections-link-span'; + HttpPipelineView.CONNECTIONS_DIV_ID = 'http-pipeline-view-connections-div'; + HttpPipelineView.KNOWN_HOSTS_DIV_ID = 'http-pipeline-view-known-hosts-div'; + + cr.addSingletonGetter(HttpPipelineView); + + HttpPipelineView.prototype = { + // Inherit the superclass's methods. + __proto__: superClass.prototype, + + onLoadLogFinish: function(data) { + return this.onHttpPipeliningStatusChanged(data.httpPipeliningStatus); + }, + + /** + * Displays information on the global HTTP pipelining status. + */ + onHttpPipeliningStatusChanged: function(httpPipelineStatus) { + return this.displayHttpPipeliningEnabled(httpPipelineStatus) && + this.displayHttpPipelinedConnectionInfo( + httpPipelineStatus.pipelined_connection_info) && + this.displayHttpPipeliningKnownHosts( + httpPipelineStatus.pipelined_host_info); + }, + + displayHttpPipeliningEnabled: function(httpPipelineStatus) { + this.httpPipeliningEnabledSpan_.textContent = + httpPipelineStatus.pipelining_enabled; + + return httpPipelineStatus.pipelining_enabled; + }, + + /** + * If |httpPipelinedConnectionInfo| is not empty, then display information + * on each HTTP pipelined connection. Otherwise, displays "None". + */ + displayHttpPipelinedConnectionInfo: + function(httpPipelinedConnectionInfo) { + this.httpPipelineConnectionsDiv_.innerHTML = ''; + + var hasInfo = (httpPipelinedConnectionInfo != null && + httpPipelinedConnectionInfo.length > 0); + setNodeDisplay(this.httpPipelineConnectionsNoneSpan_, !hasInfo); + setNodeDisplay(this.httpPipelineConnectionsLinkSpan_, hasInfo); + + if (hasInfo) { + var tablePrinter = createConnectionTablePrinter( + httpPipelinedConnectionInfo); + tablePrinter.toHTML(this.httpPipelineConnectionsDiv_, 'styledTable'); + } + + return true; + }, + + /** + * If |httpPipeliningKnownHosts| is not empty, displays a single table + * with information on known pipelining hosts. Otherwise, displays "None". + */ + displayHttpPipeliningKnownHosts: function(httpPipeliningKnownHosts) { + this.httpPipelineKnownHostsDiv_.innerHTML = ''; + + if (httpPipeliningKnownHosts != null && + httpPipeliningKnownHosts.length > 0) { + var tabPrinter = createKnownHostsTablePrinter(httpPipeliningKnownHosts); + tabPrinter.toHTML( + this.httpPipelineKnownHostsDiv_, 'styledTable'); + } else { + this.httpPipelineKnownHostsDiv_.innerHTML = 'None'; + } + return true; + } + }; + + /** + * Creates a table printer to print out the state of a list of HTTP pipelined + * connections. + */ + function createConnectionTablePrinter(httpPipelinedConnectionInfo) { + var tablePrinter = new TablePrinter(); + tablePrinter.addHeaderCell('Host'); + tablePrinter.addHeaderCell('Depth'); + tablePrinter.addHeaderCell('Capacity'); + tablePrinter.addHeaderCell('Usable'); + tablePrinter.addHeaderCell('Active'); + tablePrinter.addHeaderCell('ID'); + + for (var i = 0; i < httpPipelinedConnectionInfo.length; i++) { + var host = httpPipelinedConnectionInfo[i]; + for (var j = 0; j < host.length; j++) { + var connection = host[j]; + tablePrinter.addRow(); + + tablePrinter.addCell(connection.host); + tablePrinter.addCell(connection.depth); + tablePrinter.addCell(connection.capacity); + tablePrinter.addCell(connection.usable); + tablePrinter.addCell(connection.active); + + var idCell = tablePrinter.addCell(connection.source_id); + idCell.link = '#events&q=id:' + connection.source_id; + } + } + return tablePrinter; + } + + /** + * Creates a table printer to print out the list of known hosts and whether or + * not they support pipelining. + */ + function createKnownHostsTablePrinter(httpPipeliningKnownHosts) { + var tablePrinter = new TablePrinter(); + tablePrinter.addHeaderCell('Host'); + tablePrinter.addHeaderCell('Pipelining Capalibility'); + + for (var i = 0; i < httpPipeliningKnownHosts.length; i++) { + var entry = httpPipeliningKnownHosts[i]; + tablePrinter.addRow(); + + tablePrinter.addCell(entry.host); + tablePrinter.addCell(entry.capability); + } + return tablePrinter; + } + + return HttpPipelineView; +})(); diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html index 33b6c87f..6cf099a 100644 --- a/chrome/browser/resources/net_internals/index.html +++ b/chrome/browser/resources/net_internals/index.html @@ -25,6 +25,7 @@ found in the LICENSE file. <include src="dns_view.html"/> <include src="sockets_view.html"/> <include src="spdy_view.html"/> + <include src="http_pipeline_view.html"/> <include src="http_cache_view.html"/> <include src="http_throttling_view.html"/> <include src="prerender_view.html"/> diff --git a/chrome/browser/resources/net_internals/index.js b/chrome/browser/resources/net_internals/index.js index 2954b1f..b002ee6e 100644 --- a/chrome/browser/resources/net_internals/index.js +++ b/chrome/browser/resources/net_internals/index.js @@ -40,6 +40,7 @@ <include src="logs_view.js"/> <include src="prerender_view.js"/> <include src="chromeos_view.js"/> +<include src="http_pipeline_view.js"/> document.addEventListener('DOMContentLoaded', function() { MainView.getInstance(); // from main.js diff --git a/chrome/browser/resources/net_internals/main.css b/chrome/browser/resources/net_internals/main.css index 2ebc737..655e27b 100644 --- a/chrome/browser/resources/net_internals/main.css +++ b/chrome/browser/resources/net_internals/main.css @@ -56,6 +56,7 @@ body { #http-throttling-view-tab-content, #logs-view-tab-content, #prerender-view-tab-content, +#http-pipeline-view-tab-content, #chromeos-view-tab-content { overflow: auto; padding: 10px; diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js index 293399a..034abf2 100644 --- a/chrome/browser/resources/net_internals/main.js +++ b/chrome/browser/resources/net_internals/main.js @@ -90,6 +90,8 @@ var MainView = (function() { tabs.addTab(SocketsView.TAB_HANDLE_ID, SocketsView.getInstance(), false, true); tabs.addTab(SpdyView.TAB_HANDLE_ID, SpdyView.getInstance(), false, true); + tabs.addTab(HttpPipelineView.TAB_HANDLE_ID, HttpPipelineView.getInstance(), + false, true); tabs.addTab(HttpCacheView.TAB_HANDLE_ID, HttpCacheView.getInstance(), false, true); tabs.addTab(HttpThrottlingView.TAB_HANDLE_ID, diff --git a/chrome/browser/resources/net_internals/source_entry.js b/chrome/browser/resources/net_internals/source_entry.js index e80e3b5..1a244db 100644 --- a/chrome/browser/resources/net_internals/source_entry.js +++ b/chrome/browser/resources/net_internals/source_entry.js @@ -98,6 +98,10 @@ var SourceEntry = (function() { if (e.params.host) this.description_ = e.params.host + ' (' + e.params.proxy + ')'; break; + case LogSourceType.HTTP_PIPELINED_CONNECTION: + if (e.params.host_and_port) + this.description_ = e.params.host_and_port; + break; case LogSourceType.SOCKET: // Use description of parent source, if any. if (e.params.source_dependency != undefined) { diff --git a/chrome/browser/resources/net_internals/spdy_view.html b/chrome/browser/resources/net_internals/spdy_view.html index 57d3553..c4dcef5 100644 --- a/chrome/browser/resources/net_internals/spdy_view.html +++ b/chrome/browser/resources/net_internals/spdy_view.html @@ -12,7 +12,7 @@ <!-- Only one of these two are shown --> <span id=spdy-view-session-none-span>None</span> <span id=spdy-view-session-link-span style="display: none;"> - <a href='#events&q=type:SPDY_SESSION%20is:active'>View live SPDY sessions</a> + <a href="#events&q=type:SPDY_SESSION%20is:active">View live SPDY sessions</a> </span> <p> <div id=spdy-view-session-div> @@ -20,7 +20,8 @@ </p> <h4>Alternate Protocol Mappings</h4> - <p /> + <p> <div id=spdy-view-alternate-protocol-mappings-div> </div> + </p> </div> diff --git a/chrome/browser/ui/webui/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals_ui.cc index 806bb18..581e32e 100644 --- a/chrome/browser/ui/webui/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals_ui.cc @@ -333,6 +333,7 @@ class NetInternalsMessageHandler::IOThreadImpl #ifdef OS_WIN void OnGetServiceProviders(const ListValue* list); #endif + void OnGetHttpPipeliningStatus(const ListValue* list); void OnSetLogLevel(const ListValue* list); // ChromeNetLog::ThreadSafeObserver implementation: @@ -538,6 +539,10 @@ void NetInternalsMessageHandler::RegisterMessages() { #endif web_ui_->RegisterMessageCallback( + "getHttpPipeliningStatus", + base::Bind(&IOThreadImpl::CallbackHelper, + &IOThreadImpl::OnGetHttpPipeliningStatus, proxy_)); + web_ui_->RegisterMessageCallback( "setLogLevel", base::Bind(&IOThreadImpl::CallbackHelper, &IOThreadImpl::OnSetLogLevel, proxy_)); @@ -1304,6 +1309,60 @@ void NetInternalsMessageHandler::OnImportONCFile(const ListValue* list) { } #endif +void NetInternalsMessageHandler::IOThreadImpl::OnGetHttpPipeliningStatus( + const ListValue* list) { + DictionaryValue* status_dict = new DictionaryValue(); + + status_dict->Set("pipelining_enabled", + Value::CreateBooleanValue( + net::HttpStreamFactory::http_pipelining_enabled())); + + net::HttpNetworkSession* http_network_session = + GetHttpNetworkSession(context_getter_->GetURLRequestContext()); + Value* pipelined_conneciton_info = + http_network_session->http_stream_factory()->PipelineInfoToValue(); + status_dict->Set("pipelined_connection_info", pipelined_conneciton_info); + + const net::HttpServerProperties& http_server_properties = + *context_getter_->GetURLRequestContext()->http_server_properties(); + + // TODO(simonjam): This call is slow. + const net::PipelineCapabilityMap pipeline_capability_map = + http_server_properties.GetPipelineCapabilityMap(); + + ListValue* known_hosts_list = new ListValue(); + net::PipelineCapabilityMap::const_iterator it; + for (it = pipeline_capability_map.begin(); + it != pipeline_capability_map.end(); ++it) { + DictionaryValue* host_dict = new DictionaryValue(); + host_dict->SetString("host", it->first.ToString()); + std::string capability; + switch (it->second) { + case net::PIPELINE_CAPABLE: + capability = "capable"; + break; + + case net::PIPELINE_PROBABLY_CAPABLE: + capability = "probably capable"; + break; + + case net::PIPELINE_INCAPABLE: + capability = "incapable"; + break; + + case net::PIPELINE_UNKNOWN: + default: + capability = "unknown"; + break; + } + host_dict->SetString("capability", capability); + known_hosts_list->Append(host_dict); + } + status_dict->Set("pipelined_host_info", known_hosts_list); + + SendJavascriptCommand("receivedHttpPipeliningStatus", status_dict); +} + void NetInternalsMessageHandler::IOThreadImpl::OnSetLogLevel( const ListValue* list) { int log_level; diff --git a/chrome/test/data/webui/net_internals/log_util.js b/chrome/test/data/webui/net_internals/log_util.js index 4b571b7..b76f938 100644 --- a/chrome/test/data/webui/net_internals/log_util.js +++ b/chrome/test/data/webui/net_internals/log_util.js @@ -28,6 +28,7 @@ netInternalsTest.test('netInternalsExportImportDump', function() { dns: true, sockets: true, spdy: true, + httpPipeline: false, httpCache: true, httpThrottling: false, serviceProviders: cr.isWindows, diff --git a/chrome/test/data/webui/net_internals/main.js b/chrome/test/data/webui/net_internals/main.js index fde7ef9..5fd1337 100644 --- a/chrome/test/data/webui/net_internals/main.js +++ b/chrome/test/data/webui/net_internals/main.js @@ -27,6 +27,7 @@ netInternalsTest.test('netInternalsTourTabs', function() { dns: true, sockets: true, spdy: true, + httpPipeline: true, httpCache: true, httpThrottling: true, serviceProviders: cr.isWindows, diff --git a/chrome/test/data/webui/net_internals/net_internals_test.js b/chrome/test/data/webui/net_internals/net_internals_test.js index fa6230e..b906514 100644 --- a/chrome/test/data/webui/net_internals/net_internals_test.js +++ b/chrome/test/data/webui/net_internals/net_internals_test.js @@ -39,6 +39,7 @@ var netInternalsTest = (function() { dns: DnsView.TAB_HANDLE_ID, sockets: SocketsView.TAB_HANDLE_ID, spdy: SpdyView.TAB_HANDLE_ID, + httpPipeline: HttpPipelineView.TAB_HANDLE_ID, httpCache: HttpCacheView.TAB_HANDLE_ID, httpThrottling: HttpThrottlingView.TAB_HANDLE_ID, serviceProviders: ServiceProvidersView.TAB_HANDLE_ID, |