diff options
-rw-r--r-- | chrome/browser/browser_about_handler.cc | 14 | ||||
-rw-r--r-- | chrome/common/url_constants.cc | 2 | ||||
-rw-r--r-- | chrome/common/url_constants.h | 2 | ||||
-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 |
8 files changed, 329 insertions, 6 deletions
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index d7c14fc..4c8226e 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -65,7 +65,6 @@ using base::TimeDelta; namespace { // The paths used for the about pages. -const char kCachePath[] = "cache"; const char kDnsPath[] = "dns"; const char kHistogramsPath[] = "histograms"; const char kObjectsPath[] = "objects"; @@ -783,6 +782,19 @@ bool WillHandleBrowserAboutURL(GURL* url, Profile* profile) { return true; } + // Handle rewriting net-internal URLs. This allows us to load + // about:net-internal. + if (StartsWithASCII(url->spec(), chrome::kAboutNetInternalURL, true)) { + // Create a mapping from about:net-internal to the view-net-internal: + // internal URL. + std::string path; + size_t split = url->spec().find('/'); + if (split != std::string::npos) + path = url->spec().substr(split + 1); + *url = GURL(std::string(chrome::kViewNetInternalScheme) + ":" + path); + return true; + } + // Handle URL to crash the browser process. if (LowerCaseEqualsASCII(url->spec(), chrome::kAboutBrowserCrash)) { // Induce an intentional crash in the browser process. diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 03d048f..ed128cd 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc @@ -21,12 +21,14 @@ const char kMailToScheme[] = "mailto"; const char kPrintScheme[] = "print"; const char kUserScriptScheme[] = "chrome-user-script"; const char kViewCacheScheme[] = "view-cache"; +const char kViewNetInternalScheme[] = "view-net-internal"; const char kViewSourceScheme[] = "view-source"; const char kStandardSchemeSeparator[] = "://"; const char kAboutBlankURL[] = "about:blank"; const char kAboutCacheURL[] = "about:cache"; +const char kAboutNetInternalURL[] = "about:net-internal"; const char kAboutCrashURL[] = "about:crash"; const char kAboutHangURL[] = "about:hang"; const char kAboutMemoryURL[] = "about:memory"; diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 5917aaa..c647339 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h @@ -25,6 +25,7 @@ extern const char kMailToScheme[]; extern const char kPrintScheme[]; extern const char kUserScriptScheme[]; extern const char kViewCacheScheme[]; +extern const char kViewNetInternalScheme[]; extern const char kViewSourceScheme[]; // Used to separate a standard scheme and the hostname: "://". @@ -34,6 +35,7 @@ extern const char kStandardSchemeSeparator[]; extern const char kAboutBlankURL[]; extern const char kAboutBrowserCrash[]; extern const char kAboutCacheURL[]; +extern const char kAboutNetInternalURL[]; extern const char kAboutCrashURL[]; extern const char kAboutHangURL[]; extern const char kAboutMemoryURL[]; 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_ |