diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 23:13:15 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 23:13:15 +0000 |
commit | e3dfa2a3ce1f897eff53d69f8b6a0bc247069e6c (patch) | |
tree | f4e921df92574c3d069e52edd6b3ce2fe5f120fa /net | |
parent | dc5e89230025a8202e0314410a388ad91138020c (diff) | |
download | chromium_src-e3dfa2a3ce1f897eff53d69f8b6a0bc247069e6c.zip chromium_src-e3dfa2a3ce1f897eff53d69f8b6a0bc247069e6c.tar.gz chromium_src-e3dfa2a3ce1f897eff53d69f8b6a0bc247069e6c.tar.bz2 |
Add skeleton for an about:net-internal page.
This page contains low-level debug information that is of interest to power users, and bug investigators.
The output can be filtered by using special sub-URLs.
The sub-URLs themselves are listed when visiting about:net-internal, but to give an idea:
about:net-internal -- everything
about:net-internal/proxyservice -- all things proxy
about:net-internal/proxyservice.config -- current settings
about:net-internal/hostresolver.hostcache -- dns cache
BUG=http://crbug.com/14478
R=darin
Review URL: http://codereview.chromium.org/173024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25109 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/net.gyp | 2 | ||||
-rw-r--r-- | net/proxy/proxy_service.h | 15 | ||||
-rw-r--r-- | net/url_request/url_request_job_manager.cc | 2 | ||||
-rw-r--r-- | net/url_request/url_request_view_net_internal_job.cc | 272 | ||||
-rw-r--r-- | net/url_request/url_request_view_net_internal_job.h | 26 |
5 files changed, 312 insertions, 5 deletions
diff --git a/net/net.gyp b/net/net.gyp index 376bc1c..da8f4b5 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -357,6 +357,8 @@ 'url_request/url_request_test_job.h', 'url_request/url_request_view_cache_job.cc', 'url_request/url_request_view_cache_job.h', + 'url_request/url_request_view_net_internal_job.cc', + 'url_request/url_request_view_net_internal_job.h', ], 'sources!': [ 'build/precompiled_net.h', diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index cd76453..b38938f 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h @@ -107,6 +107,16 @@ class ProxyService : public base::RefCountedThreadSafe<ProxyService> { return init_proxy_resolver_log_; } + // Returns true if we have called UpdateConfig() at least once. + bool config_has_been_initialized() const { + return config_.id() != ProxyConfig::INVALID_ID; + } + + // Returns the last configuration fetched from ProxyConfigService. + const ProxyConfig& config() { + return config_; + } + // Creates a proxy service using the specified settings. If |pc| is NULL then // the system's default proxy settings will be used (on Windows this will // use IE's settings). @@ -162,11 +172,6 @@ class ProxyService : public base::RefCountedThreadSafe<ProxyService> { // Identifies the proxy configuration. ProxyConfig::ID config_id() const { return config_.id(); } - // Returns true if we have called UpdateConfig() at least once. - bool config_has_been_initialized() const { - return config_.id() != ProxyConfig::INVALID_ID; - } - // Checks to see if the proxy configuration changed, and then updates config_ // to reference the new configuration. void UpdateConfig(); diff --git a/net/url_request/url_request_job_manager.cc b/net/url_request/url_request_job_manager.cc index 0b193c4..241edec 100644 --- a/net/url_request/url_request_job_manager.cc +++ b/net/url_request/url_request_job_manager.cc @@ -20,6 +20,7 @@ #endif #include "net/url_request/url_request_http_job.h" #include "net/url_request/url_request_view_cache_job.h" +#include "net/url_request/url_request_view_net_internal_job.h" // The built-in set of protocol factories namespace { @@ -42,6 +43,7 @@ static const SchemeToFactory kBuiltinFactories[] = { #endif { "about", URLRequestAboutJob::Factory }, { "view-cache", URLRequestViewCacheJob::Factory }, + { "view-net-internal", URLRequestViewNetInternalJob::Factory }, }; URLRequestJobManager::URLRequestJobManager() { diff --git a/net/url_request/url_request_view_net_internal_job.cc b/net/url_request/url_request_view_net_internal_job.cc new file mode 100644 index 0000000..dba83b1 --- /dev/null +++ b/net/url_request/url_request_view_net_internal_job.cc @@ -0,0 +1,272 @@ +// Copyright (c) 2009 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. + +#include <sstream> + +#include "net/url_request/url_request_view_net_internal_job.h" + +#include "base/stl_util-inl.h" +#include "base/string_util.h" +#include "net/base/escape.h" +#include "net/base/load_log_util.h" +#include "net/base/net_errors.h" +#include "net/proxy/proxy_service.h" +#include "net/url_request/url_request_context.h" + +namespace { + +//------------------------------------------------------------------------------ +// Format helpers. +//------------------------------------------------------------------------------ + +void OutputTextInPre(const std::string& text, std::string* out) { + out->append("<pre>"); + out->append(EscapeForHTML(text)); + out->append("</pre>"); +} + +//------------------------------------------------------------------------------ +// Subsection definitions. +//------------------------------------------------------------------------------ + +class SubSection { + public: + // |name| is the URL path component for this subsection. + // |title| is the textual description. + SubSection(SubSection* parent, const char* name, const char* title) + : parent_(parent), + name_(name), + title_(title) { + } + + virtual ~SubSection() { + STLDeleteContainerPointers(children_.begin(), children_.end()); + } + + // Outputs the subsection's contents to |out|. + virtual void OutputBody(URLRequestContext* context, std::string* out) {} + + // Outputs this subsection, and all of its children. + void OutputRecursive(URLRequestContext* context, std::string* out) { + if (!is_root()) { + // Print the heading. + out->append(StringPrintf("<div>" + "<span class=subsection_title>%s</span> " + "<span class=subsection_name>(about:net-internal/%s)<span>" + "</div>", + EscapeForHTML(title_).c_str(), + EscapeForHTML(GetFullyQualifiedName()).c_str())); + + out->append("<div class=subsection_body>"); + } + + OutputBody(context, out); + + for (size_t i = 0; i < children_.size(); ++i) + children_[i]->OutputRecursive(context, out); + + if (!is_root()) + out->append("</div>"); + } + + // Returns the SubSection contained by |this| with fully qualified name + // |dotted_name|, or NULL if none was found. + SubSection* FindSubSectionByName(const std::string& dotted_name) { + if (dotted_name == "") + return this; + + std::string child_name; + std::string child_sub_name; + + size_t split_pos = dotted_name.find('.'); + if (split_pos == std::string::npos) { + child_name = dotted_name; + child_sub_name = std::string(); + } else { + child_name = dotted_name.substr(0, split_pos); + child_sub_name = dotted_name.substr(split_pos + 1); + } + + for (size_t i = 0; i < children_.size(); ++i) { + if (children_[i]->name_ == child_name) + return children_[i]->FindSubSectionByName(child_sub_name); + } + + return NULL; // Not found. + } + + std::string GetFullyQualifiedName() { + if (!parent_) + return name_; + + std::string parent_name = parent_->GetFullyQualifiedName(); + if (parent_name.empty()) + return name_; + + return parent_name + "." + name_; + } + + bool is_root() const { + return parent_ == NULL; + } + + protected: + typedef std::vector<SubSection*> SubSectionList; + + void AddSubSection(SubSection* subsection) { + children_.push_back(subsection); + } + + SubSection* parent_; + std::string name_; + std::string title_; + + SubSectionList children_; +}; + +class ProxyServiceCurrentConfigSubSection : public SubSection { + public: + ProxyServiceCurrentConfigSubSection(SubSection* parent) + : SubSection(parent, "config", "Current configuration") { + } + + virtual void OutputBody(URLRequestContext* context, std::string* out) { + net::ProxyService* proxy_service = context->proxy_service(); + if (proxy_service->config_has_been_initialized()) { + // net::ProxyConfig defines an operator<<. + std::ostringstream stream; + stream << proxy_service->config(); + OutputTextInPre(stream.str(), out); + } else { + out->append("<i>Not yet initialized</i>"); + } + } +}; + +class ProxyServiceLastInitLogSubSection : public SubSection { + public: + ProxyServiceLastInitLogSubSection(SubSection* parent) + : SubSection(parent, "init_log", "Last initialized load log") { + } + + virtual void OutputBody(URLRequestContext* context, std::string* out) { + net::ProxyService* proxy_service = context->proxy_service(); + net::LoadLog* log = proxy_service->init_proxy_resolver_log(); + if (log) { + OutputTextInPre(net::LoadLogUtil::PrettyPrintAsEventTree(log), out); + } else { + out->append("<i>None.</i>"); + } + } +}; + +class ProxyServiceBadProxiesSubSection : public SubSection { + public: + ProxyServiceBadProxiesSubSection(SubSection* parent) + : SubSection(parent, "bad_proxies", "Bad Proxies") { + } + + virtual void OutputBody(URLRequestContext* context, std::string* out) { + out->append("TODO"); + } +}; + +class ProxyServiceSubSection : public SubSection { + public: + ProxyServiceSubSection(SubSection* parent) + : SubSection(parent, "proxyservice", "ProxyService") { + AddSubSection(new ProxyServiceCurrentConfigSubSection(this)); + AddSubSection(new ProxyServiceLastInitLogSubSection(this)); + AddSubSection(new ProxyServiceBadProxiesSubSection(this)); + } +}; + +class HostResolverCacheSubSection : public SubSection { + public: + HostResolverCacheSubSection(SubSection* parent) + : SubSection(parent, "hostcache", "HostCache") { + } + + virtual void OutputBody(URLRequestContext* context, std::string* out) { + out->append("TODO"); + } +}; + +class HostResolverSubSection : public SubSection { + public: + HostResolverSubSection(SubSection* parent) + : SubSection(parent, "hostresolver", "HostResolver") { + AddSubSection(new HostResolverCacheSubSection(this)); + } +}; + +class URLRequestSubSection : public SubSection { + public: + URLRequestSubSection(SubSection* parent) + : SubSection(parent, "urlrequest", "URLRequest") { + } + + virtual void OutputBody(URLRequestContext* context, std::string* out) { + out->append("TODO"); + } +}; + +class AllSubSections : public SubSection { + public: + AllSubSections() : SubSection(NULL, "", "") { + AddSubSection(new ProxyServiceSubSection(this)); + AddSubSection(new HostResolverSubSection(this)); + AddSubSection(new URLRequestSubSection(this)); + } +}; + +} // namespace + +// static +URLRequestJob* URLRequestViewNetInternalJob::Factory( + URLRequest* request, const std::string& scheme) { + return new URLRequestViewNetInternalJob(request); +} + +bool URLRequestViewNetInternalJob::GetData(std::string* mime_type, + std::string* charset, + std::string* data) const { + DCHECK_EQ(std::string("view-net-internal"), request_->url().scheme()); + + mime_type->assign("text/html"); + charset->assign("UTF-8"); + + URLRequestContext* context = request_->context(); + std::string path = request_->url().path(); + + data->clear(); + data->append("<html><head><title>Network internals</title>" + "<style>" + "body { font-family: sans-serif; }\n" + ".subsection_body { margin: 10px 0 10px 2em; }\n" + ".subsection_title { font-weight: bold; }\n" + ".subsection_name { font-size: 80%; }\n" + "</style>" + "</head><body>"); + + SubSection* all = Singleton<AllSubSections>::get(); + SubSection* section = all; + + // Display only the subsection tree asked for. + if (!path.empty()) + section = all->FindSubSectionByName(path); + + if (section) { + section->OutputRecursive(context, data); + } else { + data->append("<i>Nothing found for \""); + data->append(EscapeForHTML(path)); + data->append("\"</i>"); + } + + data->append("</body></html>"); + + return true; +} + diff --git a/net/url_request/url_request_view_net_internal_job.h b/net/url_request/url_request_view_net_internal_job.h new file mode 100644 index 0000000..4044041 --- /dev/null +++ b/net/url_request/url_request_view_net_internal_job.h @@ -0,0 +1,26 @@ +// Copyright (c) 2009 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. + +#ifndef NET_URL_REQUEST_URL_REQUEST_VIEW_NET_INTERNAL_JOB_H_ +#define NET_URL_REQUEST_URL_REQUEST_VIEW_NET_INTERNAL_JOB_H_ + +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_simple_job.h" + +// A job subclass that implements the view-net-internal: protocol, which simply +// provides a debug view of the various network components. +class URLRequestViewNetInternalJob : public URLRequestSimpleJob { + public: + URLRequestViewNetInternalJob(URLRequest* request) + : URLRequestSimpleJob(request) {} + + static URLRequest::ProtocolFactory Factory; + + // override from URLRequestSimpleJob + virtual bool GetData(std::string* mime_type, + std::string* charset, + std::string* data) const; +}; + +#endif // NET_URL_REQUEST_URL_REQUEST_VIEW_NET_INTERNAL_JOB_H_ |