| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include <sstream> |
| 6 |
| 7 #include "net/url_request/url_request_view_net_internal_job.h" |
| 8 |
| 9 #include "base/stl_util-inl.h" |
| 10 #include "base/string_util.h" |
| 11 #include "net/base/escape.h" |
| 12 #include "net/base/load_log_util.h" |
| 13 #include "net/base/net_errors.h" |
| 14 #include "net/proxy/proxy_service.h" |
| 15 #include "net/url_request/url_request_context.h" |
| 16 |
| 17 namespace { |
| 18 |
| 19 //------------------------------------------------------------------------------ |
| 20 // Format helpers. |
| 21 //------------------------------------------------------------------------------ |
| 22 |
| 23 void OutputTextInPre(const std::string& text, std::string* out) { |
| 24 out->append("<pre>"); |
| 25 out->append(EscapeForHTML(text)); |
| 26 out->append("</pre>"); |
| 27 } |
| 28 |
| 29 //------------------------------------------------------------------------------ |
| 30 // Subsection definitions. |
| 31 //------------------------------------------------------------------------------ |
| 32 |
| 33 class SubSection { |
| 34 public: |
| 35 // |name| is the URL path component for this subsection. |
| 36 // |title| is the textual description. |
| 37 SubSection(SubSection* parent, const char* name, const char* title) |
| 38 : parent_(parent), |
| 39 name_(name), |
| 40 title_(title) { |
| 41 } |
| 42 |
| 43 virtual ~SubSection() { |
| 44 STLDeleteContainerPointers(children_.begin(), children_.end()); |
| 45 } |
| 46 |
| 47 // Outputs the subsection's contents to |out|. |
| 48 virtual void OutputBody(URLRequestContext* context, std::string* out) {} |
| 49 |
| 50 // Outputs this subsection, and all of its children. |
| 51 void OutputRecursive(URLRequestContext* context, std::string* out) { |
| 52 if (!is_root()) { |
| 53 // Print the heading. |
| 54 out->append(StringPrintf("<div>" |
| 55 "<span class=subsection_title>%s</span> " |
| 56 "<span class=subsection_name>(about:net-internal/%s)<span>" |
| 57 "</div>", |
| 58 EscapeForHTML(title_).c_str(), |
| 59 EscapeForHTML(GetFullyQualifiedName()).c_str())); |
| 60 |
| 61 out->append("<div class=subsection_body>"); |
| 62 } |
| 63 |
| 64 OutputBody(context, out); |
| 65 |
| 66 for (size_t i = 0; i < children_.size(); ++i) |
| 67 children_[i]->OutputRecursive(context, out); |
| 68 |
| 69 if (!is_root()) |
| 70 out->append("</div>"); |
| 71 } |
| 72 |
| 73 // Returns the SubSection contained by |this| with fully qualified name |
| 74 // |dotted_name|, or NULL if none was found. |
| 75 SubSection* FindSubSectionByName(const std::string& dotted_name) { |
| 76 if (dotted_name == "") |
| 77 return this; |
| 78 |
| 79 std::string child_name; |
| 80 std::string child_sub_name; |
| 81 |
| 82 size_t split_pos = dotted_name.find('.'); |
| 83 if (split_pos == std::string::npos) { |
| 84 child_name = dotted_name; |
| 85 child_sub_name = std::string(); |
| 86 } else { |
| 87 child_name = dotted_name.substr(0, split_pos); |
| 88 child_sub_name = dotted_name.substr(split_pos + 1); |
| 89 } |
| 90 |
| 91 for (size_t i = 0; i < children_.size(); ++i) { |
| 92 if (children_[i]->name_ == child_name) |
| 93 return children_[i]->FindSubSectionByName(child_sub_name); |
| 94 } |
| 95 |
| 96 return NULL; // Not found. |
| 97 } |
| 98 |
| 99 std::string GetFullyQualifiedName() { |
| 100 if (!parent_) |
| 101 return name_; |
| 102 |
| 103 std::string parent_name = parent_->GetFullyQualifiedName(); |
| 104 if (parent_name.empty()) |
| 105 return name_; |
| 106 |
| 107 return parent_name + "." + name_; |
| 108 } |
| 109 |
| 110 bool is_root() const { |
| 111 return parent_ == NULL; |
| 112 } |
| 113 |
| 114 protected: |
| 115 typedef std::vector<SubSection*> SubSectionList; |
| 116 |
| 117 void AddSubSection(SubSection* subsection) { |
| 118 children_.push_back(subsection); |
| 119 } |
| 120 |
| 121 SubSection* parent_; |
| 122 std::string name_; |
| 123 std::string title_; |
| 124 |
| 125 SubSectionList children_; |
| 126 }; |
| 127 |
| 128 class ProxyServiceCurrentConfigSubSection : public SubSection { |
| 129 public: |
| 130 ProxyServiceCurrentConfigSubSection(SubSection* parent) |
| 131 : SubSection(parent, "config", "Current configuration") { |
| 132 } |
| 133 |
| 134 virtual void OutputBody(URLRequestContext* context, std::string* out) { |
| 135 net::ProxyService* proxy_service = context->proxy_service(); |
| 136 if (proxy_service->config_has_been_initialized()) { |
| 137 // net::ProxyConfig defines an operator<<. |
| 138 std::ostringstream stream; |
| 139 stream << proxy_service->config(); |
| 140 OutputTextInPre(stream.str(), out); |
| 141 } else { |
| 142 out->append("<i>Not yet initialized</i>"); |
| 143 } |
| 144 } |
| 145 }; |
| 146 |
| 147 class ProxyServiceLastInitLogSubSection : public SubSection { |
| 148 public: |
| 149 ProxyServiceLastInitLogSubSection(SubSection* parent) |
| 150 : SubSection(parent, "init_log", "Last initialized load log") { |
| 151 } |
| 152 |
| 153 virtual void OutputBody(URLRequestContext* context, std::string* out) { |
| 154 net::ProxyService* proxy_service = context->proxy_service(); |
| 155 net::LoadLog* log = proxy_service->init_proxy_resolver_log(); |
| 156 if (log) { |
| 157 OutputTextInPre(net::LoadLogUtil::PrettyPrintAsEventTree(log), out); |
| 158 } else { |
| 159 out->append("<i>None.</i>"); |
| 160 } |
| 161 } |
| 162 }; |
| 163 |
| 164 class ProxyServiceBadProxiesSubSection : public SubSection { |
| 165 public: |
| 166 ProxyServiceBadProxiesSubSection(SubSection* parent) |
| 167 : SubSection(parent, "bad_proxies", "Bad Proxies") { |
| 168 } |
| 169 |
| 170 virtual void OutputBody(URLRequestContext* context, std::string* out) { |
| 171 out->append("TODO"); |
| 172 } |
| 173 }; |
| 174 |
| 175 class ProxyServiceSubSection : public SubSection { |
| 176 public: |
| 177 ProxyServiceSubSection(SubSection* parent) |
| 178 : SubSection(parent, "proxyservice", "ProxyService") { |
| 179 AddSubSection(new ProxyServiceCurrentConfigSubSection(this)); |
| 180 AddSubSection(new ProxyServiceLastInitLogSubSection(this)); |
| 181 AddSubSection(new ProxyServiceBadProxiesSubSection(this)); |
| 182 } |
| 183 |
| 184 virtual std::string GetName() { |
| 185 return "proxyservice"; |
| 186 } |
| 187 }; |
| 188 |
| 189 class HostResolverCacheSubSection : public SubSection { |
| 190 public: |
| 191 HostResolverCacheSubSection(SubSection* parent) |
| 192 : SubSection(parent, "hostcache", "HostCache") { |
| 193 } |
| 194 |
| 195 virtual void OutputBody(URLRequestContext* context, std::string* out) { |
| 196 out->append("TODO"); |
| 197 } |
| 198 }; |
| 199 |
| 200 class HostResolverSubSection : public SubSection { |
| 201 public: |
| 202 HostResolverSubSection(SubSection* parent) |
| 203 : SubSection(parent, "hostresolver", "HostResolver") { |
| 204 AddSubSection(new HostResolverCacheSubSection(this)); |
| 205 } |
| 206 }; |
| 207 |
| 208 class URLRequestSubSection : public SubSection { |
| 209 public: |
| 210 URLRequestSubSection(SubSection* parent) |
| 211 : SubSection(parent, "urlrequest", "URLRequest") { |
| 212 } |
| 213 |
| 214 virtual void OutputBody(URLRequestContext* context, std::string* out) { |
| 215 out->append("TODO"); |
| 216 } |
| 217 }; |
| 218 |
| 219 class AllSubSections : public SubSection { |
| 220 public: |
| 221 AllSubSections() : SubSection(NULL, "", "") { |
| 222 AddSubSection(new ProxyServiceSubSection(this)); |
| 223 AddSubSection(new HostResolverSubSection(this)); |
| 224 AddSubSection(new URLRequestSubSection(this)); |
| 225 } |
| 226 }; |
| 227 |
| 228 } // namespace |
| 229 |
| 230 // static |
| 231 URLRequestJob* URLRequestViewNetInternalJob::Factory( |
| 232 URLRequest* request, const std::string& scheme) { |
| 233 return new URLRequestViewNetInternalJob(request); |
| 234 } |
| 235 |
| 236 bool URLRequestViewNetInternalJob::GetData(std::string* mime_type, |
| 237 std::string* charset, |
| 238 std::string* data) const { |
| 239 DCHECK_EQ(std::string("view-net-internal"), request_->url().scheme()); |
| 240 |
| 241 mime_type->assign("text/html"); |
| 242 charset->assign("UTF-8"); |
| 243 |
| 244 URLRequestContext* context = request_->context(); |
| 245 std::string path = request_->url().path(); |
| 246 |
| 247 data->clear(); |
| 248 data->append("<html><head><title>Network internals</title>" |
| 249 "<style>" |
| 250 "body { font-family: sans-serif; }\n" |
| 251 ".subsection_body { margin: 10px 0 10px 2em; }\n" |
| 252 ".subsection_title { font-weight: bold; }\n" |
| 253 ".subsection_name { font-size: 80%; }\n" |
| 254 "</style>" |
| 255 "</head><body>"); |
| 256 |
| 257 SubSection* all = Singleton<AllSubSections>::get(); |
| 258 SubSection* section = all; |
| 259 |
| 260 // Display only the subsection tree asked for. |
| 261 if (!path.empty()) |
| 262 section = all->FindSubSectionByName(path); |
| 263 |
| 264 if (section) { |
| 265 section->OutputRecursive(context, data); |
| 266 } else { |
| 267 data->append("<i>Nothing found for \""); |
| 268 data->append(EscapeForHTML(path)); |
| 269 data->append("\"</i>"); |
| 270 } |
| 271 |
| 272 data->append("</body></html>"); |
| 273 |
| 274 return true; |
| 275 } |
| 276 |
| OLD | NEW |