Commit c5b061b0 authored by rch@chromium.org's avatar rch@chromium.org

Integrate QUIC info into net-internals.


Review URL: https://chromiumcodereview.appspot.com/11696010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@175239 0039d316-1c4b-4281-b951-d872f2087c98
parent 41ec4391
......@@ -54,6 +54,9 @@ var BrowserBridge = (function() {
this.pollableDataHelpers_.historicNetworkStats =
new PollableDataHelper('onHistoricNetworkStatsChanged',
this.sendGetHistoricNetworkStats.bind(this));
this.pollableDataHelpers_.quicInfo =
new PollableDataHelper('onQuicInfoChanged',
this.sendGetQuicInfo.bind(this));
this.pollableDataHelpers_.spdySessionInfo =
new PollableDataHelper('onSpdySessionInfoChanged',
this.sendGetSpdySessionInfo.bind(this));
......@@ -212,6 +215,10 @@ var BrowserBridge = (function() {
this.send('flushSocketPools');
},
sendGetQuicInfo: function() {
this.send('getQuicInfo');
},
sendGetSpdySessionInfo: function() {
this.send('getSpdySessionInfo');
},
......@@ -327,6 +334,10 @@ var BrowserBridge = (function() {
historicNetworkStats);
},
receivedQuicInfo: function(quicInfo) {
this.pollableDataHelpers_.quicInfo.update(quicInfo);
},
receivedSpdySessionInfo: function(spdySessionInfo) {
this.pollableDataHelpers_.spdySessionInfo.update(spdySessionInfo);
},
......@@ -504,6 +515,17 @@ var BrowserBridge = (function() {
observer, ignoreWhenUnchanged);
},
/**
* Adds a listener of the QUIC info. |observer| will be called back
* when data is received, through:
*
* observer.onQuicInfoChanged(quicInfo)
*/
addQuicInfoObserver: function(observer, ignoreWhenUnchanged) {
this.pollableDataHelpers_.quicInfo.addObserver(
observer, ignoreWhenUnchanged);
},
/**
* Adds a listener of the SPDY info. |observer| will be called back
* when data is received, through:
......
......@@ -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="#quic" id=tab-handle-quic>QUIC</a>
<a href="#httpPipeline" id=tab-handle-http-pipeline>Pipelining</a>
<a href="#httpCache" id=tab-handle-http-cache>Cache</a>
<!-- Tab is only shown on Windows -->
......
......@@ -28,6 +28,7 @@ found in the LICENSE file.
<include src="dns_view.html"/>
<include src="sockets_view.html"/>
<include src="spdy_view.html"/>
<include src="quic_view.html"/>
<include src="http_pipeline_view.html"/>
<include src="http_cache_view.html"/>
<include src="bandwidth_view.html"/>
......
......@@ -37,6 +37,7 @@
<include src="log_view_painter.js"/>
<include src="log_grouper.js"/>
<include src="proxy_view.js"/>
<include src="quic_view.js"/>
<include src="socket_pool_wrapper.js"/>
<include src="sockets_view.js"/>
<include src="spdy_view.js"/>
......
......@@ -90,6 +90,7 @@ 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(QuicView.TAB_HANDLE_ID, QuicView.getInstance(), false, true);
tabs.addTab(HttpPipelineView.TAB_HANDLE_ID, HttpPipelineView.getInstance(),
false, true);
tabs.addTab(HttpCacheView.TAB_HANDLE_ID, HttpCacheView.getInstance(),
......
<div id=quic-view-tab-content class=content-box>
<h4>QUIC Status</h4>
<ul>
<li>QUIC Enabled: <span id=quic-view-enabled-span>????</span></li>
<li>Origin Port To Force QUIC On: <span id=quic-view-force-port-span>????</span></li>
</ul>
<h4>QUIC sessions</h4>
<!-- Only one of these two are shown -->
<span id=quic-view-session-none-span>None</span>
<span id=quic-view-session-link-span style="display: none;">
<a href="#events&q=type:QUIC_SESSION%20is:active">View live QUIC sessions</a>
</span>
<p>
<div id=quic-view-session-div>
</div>
</p>
<h4>Alternate Protocol Mappings</h4>
<p>
<div id=quic-view-alternate-protocol-mappings-div>
</div>
</p>
</div>
// Copyright (c) 2013 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 QUIC session, and
* has links to display them in the events tab.
*/
var QuicView = (function() {
'use strict';
// We inherit from DivView.
var superClass = DivView;
/**
* @constructor
*/
function QuicView() {
assertFirstConstructorCall(QuicView);
// Call superclass's constructor.
superClass.call(this, QuicView.MAIN_BOX_ID);
g_browser.addQuicInfoObserver(this, true);
this.quicEnabledSpan_ = $(QuicView.ENABLED_SPAN_ID);
this.quicForcePortSpan_ = $(QuicView.FORCE_PORT_SPAN_ID);
this.quicSessionNoneSpan_ = $(QuicView.SESSION_NONE_SPAN_ID);
this.quicSessionLinkSpan_ = $(QuicView.SESSION_LINK_SPAN_ID);
this.quicSessionDiv_ = $(QuicView.SESSION_DIV_ID);
}
// ID for special HTML element in category_tabs.html
QuicView.TAB_HANDLE_ID = 'tab-handle-quic';
// IDs for special HTML elements in quic_view.html
QuicView.MAIN_BOX_ID = 'quic-view-tab-content';
QuicView.ENABLED_SPAN_ID = 'quic-view-enabled-span';
QuicView.FORCE_PORT_SPAN_ID = 'quic-view-force-port-span';
QuicView.SESSION_NONE_SPAN_ID = 'quic-view-session-none-span';
QuicView.SESSION_LINK_SPAN_ID = 'quic-view-session-link-span';
QuicView.SESSION_DIV_ID = 'quic-view-session-div';
cr.addSingletonGetter(QuicView);
QuicView.prototype = {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
onLoadLogFinish: function(data) {
return this.onQuicInfoChanged(data.quicInfo);
},
/**
* If there are any sessions, display a single table with
* information on each QUIC session. Otherwise, displays "None".
*/
onQuicInfoChanged: function(quicInfo) {
this.quicSessionDiv_.innerHTML = '';
var hasNoSession =
(!quicInfo || !quicInfo.sessions || quicInfo.sessions.length == 0);
setNodeDisplay(this.quicSessionNoneSpan_, hasNoSession);
setNodeDisplay(this.quicSessionLinkSpan_, !hasNoSession);
// Only want to be hide the tab if there's no data. In the case of having
// data but no sessions, still show the tab.
if (!quicInfo)
return false;
this.quicEnabledSpan_.textContent = quicInfo.quic_enabled;
this.quicForcePortSpan_.textContent =
quicInfo.origin_port_to_force_quic_on;
if (!hasNoSession) {
var tablePrinter = createSessionTablePrinter(quicInfo.sessions);
tablePrinter.toHTML(this.quicSessionDiv_, 'styled-table');
}
return true;
},
};
/**
* Creates a table printer to print out the state of list of QUIC sessions.
*/
function createSessionTablePrinter(quicSessions) {
var tablePrinter = new TablePrinter();
tablePrinter.addHeaderCell('Host');
tablePrinter.addHeaderCell('Peer address');
tablePrinter.addHeaderCell('GUID');
tablePrinter.addHeaderCell('Active streams');
for (var i = 0; i < quicSessions.length; i++) {
var session = quicSessions[i];
tablePrinter.addRow();
var host = session.host_port_pair;
if (session.aliases)
host += ' ' + session.aliases.join(' ');
tablePrinter.addCell(host);
tablePrinter.addCell(session.peer_address);
tablePrinter.addCell(session.guid);
tablePrinter.addCell(session.open_streams);
}
return tablePrinter;
}
return QuicView;
})();
......@@ -514,6 +514,7 @@ class NetInternalsMessageHandler::IOThreadImpl
void OnGetSpdySessionInfo(const ListValue* list);
void OnGetSpdyStatus(const ListValue* list);
void OnGetSpdyAlternateProtocolMappings(const ListValue* list);
void OnGetQuicInfo(const ListValue* list);
#if defined(OS_WIN)
void OnGetServiceProviders(const ListValue* list);
#endif
......@@ -722,6 +723,10 @@ void NetInternalsMessageHandler::RegisterMessages() {
"getSpdyAlternateProtocolMappings",
base::Bind(&IOThreadImpl::CallbackHelper,
&IOThreadImpl::OnGetSpdyAlternateProtocolMappings, proxy_));
web_ui()->RegisterMessageCallback(
"getQuicInfo",
base::Bind(&IOThreadImpl::CallbackHelper,
&IOThreadImpl::OnGetQuicInfo, proxy_));
#if defined(OS_WIN)
web_ui()->RegisterMessageCallback(
"getServiceProviders",
......@@ -1425,6 +1430,17 @@ NetInternalsMessageHandler::IOThreadImpl::OnGetSpdyAlternateProtocolMappings(
SendJavascriptCommand("receivedSpdyAlternateProtocolMappings", dict_list);
}
void NetInternalsMessageHandler::IOThreadImpl::OnGetQuicInfo(
const ListValue* list) {
DCHECK(!list);
net::HttpNetworkSession* http_network_session =
GetHttpNetworkSession(GetMainContext());
Value* quic_info = http_network_session ?
http_network_session->QuicInfoToValue() : NULL;
SendJavascriptCommand("receivedQuicInfo", quic_info);
}
#if defined(OS_WIN)
void NetInternalsMessageHandler::IOThreadImpl::OnGetServiceProviders(
const ListValue* list) {
......
......@@ -113,6 +113,7 @@ function checkViewsAfterLogLoaded() {
dns: true,
sockets: true,
spdy: true,
quic: true,
httpPipeline: false,
httpCache: true,
serviceProviders: cr.isWindows,
......
......@@ -30,6 +30,7 @@ TEST_F('NetInternalsTest', 'netInternalsTourTabs', function() {
dns: true,
sockets: true,
spdy: true,
quic: true,
httpPipeline: true,
httpCache: true,
serviceProviders: cr.isWindows,
......
......@@ -247,6 +247,7 @@ var NetInternalsTest = (function() {
dns: DnsView.TAB_HANDLE_ID,
sockets: SocketsView.TAB_HANDLE_ID,
spdy: SpdyView.TAB_HANDLE_ID,
quic: QuicView.TAB_HANDLE_ID,
httpPipeline: HttpPipelineView.TAB_HANDLE_ID,
httpCache: HttpCacheView.TAB_HANDLE_ID,
serviceProviders: ServiceProvidersView.TAB_HANDLE_ID,
......
......@@ -179,6 +179,16 @@ Value* HttpNetworkSession::SpdySessionPoolInfoToValue() const {
return spdy_session_pool_.SpdySessionPoolInfoToValue();
}
Value* HttpNetworkSession::QuicInfoToValue() const {
base::DictionaryValue* dict = new base::DictionaryValue();
dict->Set("sessions", quic_stream_factory_.QuicStreamFactoryInfoToValue());
dict->SetBoolean("quic_enabled", params_.origin_port_to_force_quic_on != 0);
dict->SetInteger("origin_port_to_force_quic_on",
params_.origin_port_to_force_quic_on);
return dict;
}
void HttpNetworkSession::CloseAllConnections() {
normal_socket_pool_manager_->FlushSocketPoolsWithError(ERR_ABORTED);
websocket_socket_pool_manager_->FlushSocketPoolsWithError(ERR_ABORTED);
......
......@@ -141,6 +141,10 @@ class NET_EXPORT HttpNetworkSession
// responsible for deleting the returned value.
base::Value* SpdySessionPoolInfoToValue() const;
// Creates a Value summary of the state of the QUIC sessions and
// configuration. The caller is responsible for deleting the returned value.
base::Value* QuicInfoToValue() const;
void CloseAllConnections();
void CloseIdleConnections();
......
......@@ -6,6 +6,8 @@
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
#include "base/values.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/quic/quic_connection_helper.h"
......@@ -113,6 +115,15 @@ void QuicClientSession::CloseSessionOnError(int error) {
stream_factory_->OnSessionClose(this);
}
Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
DictionaryValue* dict = new DictionaryValue();
dict->SetString("host_port_pair", pair.ToString());
dict->SetInteger("open_streams", GetNumOpenStreams());
dict->SetString("peer_address", peer_address().ToString());
dict->SetString("guid", base::Uint64ToString(guid()));
return dict;
}
void QuicClientSession::OnReadComplete(int result) {
read_pending_ = false;
// TODO(rch): Inform the connection about the result.
......
......@@ -48,6 +48,8 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
// Close the session because of |error|.
void CloseSessionOnError(int error);
base::Value* GetInfoAsValue(const HostPortPair& pair) const;
protected:
// QuicSession methods:
virtual ReliableQuicStream* CreateIncomingReliableStream(
......
......@@ -267,7 +267,7 @@ bool QuicSession::IsClosedStream(QuicStreamId id) {
implicitly_created_streams_.count(id) == 0;
}
size_t QuicSession::GetNumOpenStreams() {
size_t QuicSession::GetNumOpenStreams() const {
return stream_map_.size() + implicitly_created_streams_.size();
}
......
......@@ -76,12 +76,13 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
const IPEndPoint& peer_address() const {
return connection_->peer_address();
}
QuicGuid guid() const { return connection_->guid(); }
QuicPacketCreator::Options* options() { return connection()->options(); }
// Returns the number of currently open streams, including those which have
// been implicitly created.
virtual size_t GetNumOpenStreams();
virtual size_t GetNumOpenStreams() const;
void MarkWriteBlocked(QuicStreamId id);
......
......@@ -10,6 +10,7 @@
#include "base/message_loop_proxy.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "net/base/host_resolver.h"
#include "net/base/net_errors.h"
#include "net/base/single_request_host_resolver.h"
......@@ -333,6 +334,19 @@ void QuicStreamFactory::CloseAllSessions(int error) {
DCHECK(all_sessions_.empty());
}
base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
base::ListValue* list = new base::ListValue();
for (SessionMap::const_iterator it = active_sessions_.begin();
it != active_sessions_.end(); ++it) {
const HostPortProxyPair& pair = it->first;
const QuicClientSession* session = it->second;
list->Append(session->GetInfoAsValue(pair.first));
}
return list;
}
bool QuicStreamFactory::HasActiveSession(
const HostPortProxyPair& host_port_proxy_pair) {
return ContainsKey(active_sessions_, host_port_proxy_pair);
......
......@@ -93,6 +93,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory {
// Closes all current sessions.
void CloseAllSessions(int error);
base::Value* QuicStreamFactoryInfoToValue() const;
private:
class Job;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment