diff options
-rw-r--r-- | chrome/browser/dom_ui/net_internals_ui.cc | 33 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/dataview.js | 14 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/index.html | 14 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/main.css | 1 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/main.js | 27 | ||||
-rw-r--r-- | chrome/browser/resources/net_internals/spdyview.js | 87 | ||||
-rw-r--r-- | net/base/net_log.cc | 11 | ||||
-rw-r--r-- | net/base/net_log.h | 4 | ||||
-rw-r--r-- | net/http/http_network_session.cc | 4 | ||||
-rw-r--r-- | net/http/http_network_session.h | 4 | ||||
-rw-r--r-- | net/socket/client_socket_pool_manager.cc | 1 | ||||
-rw-r--r-- | net/spdy/spdy_session.cc | 30 | ||||
-rw-r--r-- | net/spdy/spdy_session.h | 4 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.cc | 16 | ||||
-rw-r--r-- | net/spdy/spdy_session_pool.h | 4 |
15 files changed, 238 insertions, 16 deletions
diff --git a/chrome/browser/dom_ui/net_internals_ui.cc b/chrome/browser/dom_ui/net_internals_ui.cc index ffdb9a1..93e1262 100644 --- a/chrome/browser/dom_ui/net_internals_ui.cc +++ b/chrome/browser/dom_ui/net_internals_ui.cc @@ -45,11 +45,7 @@ #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" #include "net/http/http_network_session.h" -#include "net/http/http_proxy_client_socket_pool.h" #include "net/proxy/proxy_service.h" -#include "net/socket/socks_client_socket_pool.h" -#include "net/socket/ssl_client_socket_pool.h" -#include "net/socket/tcp_client_socket_pool.h" #include "net/url_request/url_request_context.h" #ifdef OS_WIN #include "chrome/browser/net/service_providers_win.h" @@ -57,11 +53,6 @@ namespace { -// Formats |t| as a decimal number, in milliseconds. -std::string TickCountToString(const base::TimeTicks& t) { - return base::Int64ToString((t - base::TimeTicks()).InMilliseconds()); -} - // Returns the HostCache for |context|'s primary HostResolver, or NULL if // there is none. net::HostCache* GetHostResolverCache(URLRequestContext* context) { @@ -214,6 +205,7 @@ class NetInternalsMessageHandler::IOThreadImpl void OnStartConnectionTests(const ListValue* list); void OnGetHttpCacheInfo(const ListValue* list); void OnGetSocketPoolInfo(const ListValue* list); + void OnGetSpdySessionInfo(const ListValue* list); #ifdef OS_WIN void OnGetServiceProviders(const ListValue* list); #endif @@ -403,6 +395,9 @@ void NetInternalsMessageHandler::RegisterMessages() { dom_ui_->RegisterMessageCallback( "getSocketPoolInfo", proxy_->CreateCallback(&IOThreadImpl::OnGetSocketPoolInfo)); + dom_ui_->RegisterMessageCallback( + "getSpdySessionInfo", + proxy_->CreateCallback(&IOThreadImpl::OnGetSpdySessionInfo)); #ifdef OS_WIN dom_ui_->RegisterMessageCallback( "getServiceProviders", @@ -610,6 +605,7 @@ void NetInternalsMessageHandler::IOThreadImpl::OnRendererReady( OnGetHostResolverInfo(NULL); OnGetHttpCacheInfo(NULL); OnGetSocketPoolInfo(NULL); + OnGetSpdySessionInfo(NULL); #ifdef OS_WIN OnGetServiceProviders(NULL); #endif @@ -654,7 +650,8 @@ void NetInternalsMessageHandler::IOThreadImpl::OnGetBadProxies( DictionaryValue* dict = new DictionaryValue(); dict->SetString("proxy_uri", proxy_uri); - dict->SetString("bad_until", TickCountToString(retry_info.bad_until)); + dict->SetString("bad_until", + net::NetLog::TickCountToString(retry_info.bad_until)); dict_list->Append(dict); } @@ -715,7 +712,8 @@ void NetInternalsMessageHandler::IOThreadImpl::OnGetHostResolverInfo( entry_dict->SetString("hostname", key.hostname); entry_dict->SetInteger("address_family", static_cast<int>(key.address_family)); - entry_dict->SetString("expiration", TickCountToString(entry->expiration)); + entry_dict->SetString("expiration", + net::NetLog::TickCountToString(entry->expiration)); if (entry->error != net::OK) { entry_dict->SetInteger("error", entry->error); @@ -837,6 +835,19 @@ void NetInternalsMessageHandler::IOThreadImpl::OnGetSocketPoolInfo( CallJavascriptFunction(L"g_browser.receivedSocketPoolInfo", socket_pool_info); } +void NetInternalsMessageHandler::IOThreadImpl::OnGetSpdySessionInfo( + const ListValue* list) { + net::HttpNetworkSession* http_network_session = + GetHttpNetworkSession(context_getter_->GetURLRequestContext()); + + Value* spdy_info = NULL; + if (http_network_session) { + spdy_info = http_network_session->SpdySessionPoolInfoToValue(); + } + + CallJavascriptFunction(L"g_browser.receivedSpdySessionInfo", spdy_info); +} + #ifdef OS_WIN void NetInternalsMessageHandler::IOThreadImpl::OnGetServiceProviders( const ListValue* list) { diff --git a/chrome/browser/resources/net_internals/dataview.js b/chrome/browser/resources/net_internals/dataview.js index 58aaccf..2138a83 100644 --- a/chrome/browser/resources/net_internals/dataview.js +++ b/chrome/browser/resources/net_internals/dataview.js @@ -222,6 +222,20 @@ DataView.prototype.onUpdateAllCompleted = function(data) { this.appendSocketPoolsAsText_(text, data.socketPoolInfo); + text.push(''); + text.push('----------------------------------------------'); + text.push(' SPDY Sessions'); + text.push('----------------------------------------------'); + text.push(''); + + if (data.spdySessionInfo == null || data.spdySessionInfo.length == 0) { + text.push('None'); + } else { + var spdyTablePrinter = + SpdyView.createSessionTablePrinter(data.spdySessionInfo); + text.push(spdyTablePrinter.toText(2)); + } + if (g_browser.isPlatformWindows()) { text.push(''); text.push('----------------------------------------------'); diff --git a/chrome/browser/resources/net_internals/index.html b/chrome/browser/resources/net_internals/index.html index 1ab90e6..483d932 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. <script src="proxyview.js"></script> <script src="socketpoolwrapper.js"></script> <script src="socketsview.js"></script> + <script src="spdyview.js"></script> <script src="serviceprovidersview.js"></script> </head> <body onload="onLoaded()"> @@ -36,6 +37,7 @@ found in the LICENSE file. <li><a href="#events" id=eventsTab>Events</a></li> <li><a href="#dns" id=dnsTab>DNS</a></li> <li><a href="#sockets" id=socketsTab>Sockets</a></li> + <li><a href="#spdy" id=spdyTab>SPDY</a></li> <li><a href="#httpCache" id=httpCacheTab>HTTP Cache</a></li> <!-- Tab is only shown on Windows --> <li><a href="#serviceProviders" id=serviceProvidersTab style="display: none;">SPIs</a></li> @@ -131,6 +133,18 @@ found in the LICENSE file. </div> </p> </div> + <div id=spdyTabContent> + <h4>SPDY sessions</h4> + <!-- Only one of these two are shown --> + <span id=spdySessionNoneSpan>None</span> + <span id=spdySessionLinkSpan style="display: none;"> + <a href='#events&q=type:SPDY_SESSION%20is:active'>View live SPDY sessions</a> + </span> + <p> + <div id=spdySessionDiv> + </div> + </p> + </div> <div id=httpCacheTabContent> <h4>Entries</h4> <a href="chrome://view-http-cache" target=_blank>Explore cache entries</a> diff --git a/chrome/browser/resources/net_internals/main.css b/chrome/browser/resources/net_internals/main.css index 0102cfb..7861a35 100644 --- a/chrome/browser/resources/net_internals/main.css +++ b/chrome/browser/resources/net_internals/main.css @@ -202,6 +202,7 @@ body { #dataTabContent, #dnsTabContent, #socketsTabContent, +#spdyTabContent, #serviceProvidersTabContent, #testTabContent { overflow: auto; diff --git a/chrome/browser/resources/net_internals/main.js b/chrome/browser/resources/net_internals/main.js index 50102c6..1702085 100644 --- a/chrome/browser/resources/net_internals/main.js +++ b/chrome/browser/resources/net_internals/main.js @@ -89,6 +89,11 @@ function onLoaded() { "socketPoolDiv", "socketPoolGroupsDiv"); + var spdyView = new SpdyView("spdyTabContent", + "spdySessionNoneSpan", + "spdySessionLinkSpan", + "spdySessionDiv"); + var serviceView; if (g_browser.isPlatformWindows()) { @@ -107,6 +112,7 @@ function onLoaded() { categoryTabSwitcher.addTab('proxyTab', proxyView, false); categoryTabSwitcher.addTab('dnsTab', dnsView, false); categoryTabSwitcher.addTab('socketsTab', socketsView, false); + categoryTabSwitcher.addTab('spdyTab', spdyView, false); categoryTabSwitcher.addTab('httpCacheTab', httpCacheView, false); categoryTabSwitcher.addTab('dataTab', dataView, false); if (g_browser.isPlatformWindows()) @@ -167,6 +173,9 @@ function BrowserBridge() { this.pollableDataHelpers_.socketPoolInfo = new PollableDataHelper('onSocketPoolInfoChanged', this.sendGetSocketPoolInfo.bind(this)); + this.pollableDataHelpers_.spdySessionInfo = + new PollableDataHelper('onSpdySessionInfoChanged', + this.sendGetSpdySessionInfo.bind(this)); if (this.isPlatformWindows()) { this.pollableDataHelpers_.serviceProviders = new PollableDataHelper('onServiceProvidersChanged', @@ -275,6 +284,10 @@ BrowserBridge.prototype.sendGetSocketPoolInfo = function() { chrome.send('getSocketPoolInfo'); }; +BrowserBridge.prototype.sendGetSpdySessionInfo = function() { + chrome.send('getSpdySessionInfo'); +}; + BrowserBridge.prototype.sendGetServiceProviders = function() { chrome.send('getServiceProviders'); }; @@ -354,6 +367,10 @@ BrowserBridge.prototype.receivedSocketPoolInfo = function(socketPoolInfo) { this.pollableDataHelpers_.socketPoolInfo.update(socketPoolInfo); }; +BrowserBridge.prototype.receivedSpdySessionInfo = function(spdySessionInfo) { + this.pollableDataHelpers_.spdySessionInfo.update(spdySessionInfo); +}; + BrowserBridge.prototype.receivedServiceProviders = function(serviceProviders) { this.pollableDataHelpers_.serviceProviders.update(serviceProviders); }; @@ -475,6 +492,16 @@ BrowserBridge.prototype.addSocketPoolInfoObserver = function(observer) { }; /** + * Adds a listener of the SPDY info. |observer| will be called back + * when data is received, through: + * + * observer.onSpdySessionInfoChanged(spdySessionInfo) + */ +BrowserBridge.prototype.addSpdySessionInfoObserver = function(observer) { + this.pollableDataHelpers_.spdySessionInfo.addObserver(observer); +}; + +/** * Adds a listener of the service providers info. |observer| will be called * back when data is received, through: * diff --git a/chrome/browser/resources/net_internals/spdyview.js b/chrome/browser/resources/net_internals/spdyview.js new file mode 100644 index 0000000..e0d0bd2 --- /dev/null +++ b/chrome/browser/resources/net_internals/spdyview.js @@ -0,0 +1,87 @@ +// 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. + +/** + * This view displays a summary of the state of each SPDY sessions, and + * has links to display them in the events tab. + * + * @constructor + */ +function SpdyView(mainBoxId, spdySessionNoneSpanId, spdySessionLinkSpanId, + spdySessionDivId) { + DivView.call(this, mainBoxId); + g_browser.addSpdySessionInfoObserver(this); + + this.spdySessionNoneSpan_ = document.getElementById(spdySessionNoneSpanId); + this.spdySessionLinkSpan_ = document.getElementById(spdySessionLinkSpanId); + this.spdySessionDiv_ = document.getElementById(spdySessionDivId); +} + +inherits(SpdyView, DivView); + +/** + * If |spdySessionInfo| is not null, displays a single table with information + * on each SPDY session. Otherwise, displays "None". + */ +SpdyView.prototype.onSpdySessionInfoChanged = function(spdySessionInfo) { + this.spdySessionDiv_.innerHTML = ''; + + var hasNoSession = (spdySessionInfo == null || spdySessionInfo.length == 0); + setNodeDisplay(this.spdySessionNoneSpan_, hasNoSession); + setNodeDisplay(this.spdySessionLinkSpan_, !hasNoSession); + + if (hasNoSession) + return; + + var tablePrinter = SpdyView.createSessionTablePrinter(spdySessionInfo); + tablePrinter.toHTML(this.spdySessionDiv_, 'styledTable'); +}; + +/** + * Creates a table printer to print out the state of list of SPDY sessions. + */ +SpdyView.createSessionTablePrinter = function(spdySessions) { + var tablePrinter = new TablePrinter(); + tablePrinter.addHeaderCell('Host'); + tablePrinter.addHeaderCell('Proxy'); + tablePrinter.addHeaderCell('ID'); + tablePrinter.addHeaderCell('Active streams'); + tablePrinter.addHeaderCell('Unclaimed pushed'); + tablePrinter.addHeaderCell('Max'); + tablePrinter.addHeaderCell('Initiated'); + tablePrinter.addHeaderCell('Pushed'); + tablePrinter.addHeaderCell('Pushed and claimed'); + tablePrinter.addHeaderCell('Abandoned'); + tablePrinter.addHeaderCell('Received frames'); + tablePrinter.addHeaderCell('Secure'); + tablePrinter.addHeaderCell('Sent settings'); + tablePrinter.addHeaderCell('Received settings'); + tablePrinter.addHeaderCell('Error'); + + for (var i = 0; i < spdySessions.length; i++) { + var session = spdySessions[i]; + tablePrinter.addRow(); + + tablePrinter.addCell(session.host_port_pair); + tablePrinter.addCell(session.proxy); + + var idCell = tablePrinter.addCell(session.source_id); + idCell.link = '#events&q=id:' + session.source_id; + + tablePrinter.addCell(session.active_streams); + tablePrinter.addCell(session.unclaimed_pushed_streams); + tablePrinter.addCell(session.max_concurrent_streams); + tablePrinter.addCell(session.streams_initiated_count); + tablePrinter.addCell(session.streams_pushed_count); + tablePrinter.addCell(session.streams_pushed_and_claimed_count); + tablePrinter.addCell(session.streams_abandoned_count); + tablePrinter.addCell(session.frames_received); + tablePrinter.addCell(session.is_secure); + tablePrinter.addCell(session.sent_settings); + tablePrinter.addCell(session.received_settings); + tablePrinter.addCell(session.error); + } + return tablePrinter; +}; + diff --git a/net/base/net_log.cc b/net/base/net_log.cc index 2cc149f..f9f31c7 100644 --- a/net/base/net_log.cc +++ b/net/base/net_log.cc @@ -19,6 +19,12 @@ Value* NetLog::Source::ToValue() const { } // static +std::string NetLog::TickCountToString(const base::TimeTicks& time) { + int64 delta_time = (time - base::TimeTicks()).InMilliseconds(); + return base::Int64ToString(delta_time); +} + +// static const char* NetLog::EventTypeToString(EventType event) { switch (event) { #define EVENT_TYPE(label) case TYPE_ ## label: return #label; @@ -71,10 +77,7 @@ Value* NetLog::EntryToDictionaryValue(net::NetLog::EventType type, bool use_strings) { DictionaryValue* entry_dict = new DictionaryValue(); - // Set the entry time. (Note that we send it as a string since integers - // might overflow). - int64 delta_time = (time - base::TimeTicks()).InMilliseconds(); - entry_dict->SetString("time", base::Int64ToString(delta_time)); + entry_dict->SetString("time", TickCountToString(time)); // Set the entry source. DictionaryValue* source_dict = new DictionaryValue(); diff --git a/net/base/net_log.h b/net/base/net_log.h index c97eb1a..f240105 100644 --- a/net/base/net_log.h +++ b/net/base/net_log.h @@ -130,6 +130,10 @@ class NetLog { // and saving expensive log entries. virtual LogLevel GetLogLevel() const = 0; + // Converts a time to the string format that the NetLog uses to represent + // times. Strings are used since integers may overflow. + static std::string TickCountToString(const base::TimeTicks& time); + // Returns a C-String symbolic name for |event_type|. static const char* EventTypeToString(EventType event_type); diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 4613629..056feaf 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc @@ -64,4 +64,8 @@ void HttpNetworkSession::RemoveResponseDrainer( response_drainers_.erase(drainer); } +Value* HttpNetworkSession::SpdySessionPoolInfoToValue() const { + return spdy_session_pool_->SpdySessionPoolInfoToValue(); +} + } // namespace net diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index 0cfe08f..e23ecd6 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h @@ -126,6 +126,10 @@ class HttpNetworkSession : public base::RefCounted<HttpNetworkSession>, return socket_pool_manager_.SocketPoolInfoToValue(); } + // Creates a Value summary of the state of the SPDY sessions. The caller is + // responsible for deleting the returned value. + Value* SpdySessionPoolInfoToValue() const; + void FlushSocketPools() { socket_pool_manager_.FlushSocketPools(); } diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc index 264cdf8..0fca83d 100644 --- a/net/socket/client_socket_pool_manager.cc +++ b/net/socket/client_socket_pool_manager.cc @@ -41,7 +41,6 @@ static void AddSocketPoolsToList(ListValue* list, const MapType& socket_pools, const std::string& type, bool include_nested_pools) { - typename MapType::const_iterator socket_pool_it = socket_pools.begin(); for (typename MapType::const_iterator it = socket_pools.begin(); it != socket_pools.end(); it++) { list->Append(it->second->GetInfoAsValue(it->first.ToString(), diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index a360c52..d0ebff9 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -839,6 +839,36 @@ void SpdySession::CloseSessionOnError(net::Error err, bool remove_from_pool) { } } +Value* SpdySession::GetInfoAsValue() const { + DictionaryValue* dict = new DictionaryValue(); + + dict->SetInteger("source_id", net_log_.source().id); + + dict->SetString("host_port_pair", host_port_proxy_pair_.first.ToString()); + dict->SetString("proxy", host_port_proxy_pair_.second.ToURI()); + + dict->SetInteger("active_streams", active_streams_.size()); + + dict->SetInteger("unclaimed_pushed_streams", + unclaimed_pushed_streams_.size()); + + dict->SetBoolean("is_secure", is_secure_); + + dict->SetInteger("error", error_); + dict->SetInteger("max_concurrent_streams", max_concurrent_streams_); + + dict->SetInteger("streams_initiated_count", streams_initiated_count_); + dict->SetInteger("streams_pushed_count", streams_pushed_count_); + dict->SetInteger("streams_pushed_and_claimed_count", + streams_pushed_and_claimed_count_); + dict->SetInteger("streams_abandoned_count", streams_abandoned_count_); + dict->SetInteger("frames_received", frames_received_); + + dict->SetBoolean("sent_settings", sent_settings_); + dict->SetBoolean("received_settings", received_settings_); + return dict; +} + void SpdySession::ActivateStream(SpdyStream* stream) { const spdy::SpdyStreamId id = stream->stream_id(); DCHECK(!IsStreamActive(id)); diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h index de5f0e2..f90907d 100644 --- a/net/spdy/spdy_session.h +++ b/net/spdy/spdy_session.h @@ -155,6 +155,10 @@ class SpdySession : public base::RefCounted<SpdySession>, // session pool. void CloseSessionOnError(net::Error err, bool remove_from_pool); + // Retrieves information on the current state of the SPDY session as a + // Value. Caller takes possession of the returned value. + Value* GetInfoAsValue() const; + // Indicates whether the session is being reused after having successfully // used to send/receive data in the past. bool IsReused() const { diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index 086fa9f..fe2a310 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc @@ -5,6 +5,7 @@ #include "net/spdy/spdy_session_pool.h" #include "base/logging.h" +#include "base/values.h" #include "net/http/http_network_session.h" #include "net/spdy/spdy_session.h" @@ -109,6 +110,21 @@ void SpdySessionPool::Remove(const scoped_refptr<SpdySession>& session) { RemoveSessionList(session->host_port_proxy_pair()); } +Value* SpdySessionPool::SpdySessionPoolInfoToValue() { + ListValue* list = new ListValue(); + + SpdySessionsMap::const_iterator spdy_session_pool_it = sessions_.begin(); + for (SpdySessionsMap::const_iterator it = sessions_.begin(); + it != sessions_.end(); it++) { + SpdySessionList* sessions = it->second; + for (SpdySessionList::const_iterator session = sessions->begin(); + session != sessions->end(); session++) { + list->Append(session->get()->GetInfoAsValue()); + } + } + return list; +} + void SpdySessionPool::OnIPAddressChanged() { CloseCurrentSessions(); } diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 49f9e45..6b346f6 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h @@ -88,6 +88,10 @@ class SpdySessionPool // by SpdySession, because otherwise session->state_ is not set to CLOSED. void Remove(const scoped_refptr<SpdySession>& session); + // Creates a Value summary of the state of the spdy session pool. The caller + // responsible for deleting the returned value. + Value* SpdySessionPoolInfoToValue(); + // NetworkChangeNotifier::Observer methods: // We flush all idle sessions and release references to the active ones so |