1// Copyright (c) 2012 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 "content/browser/tcmalloc_internals_request_job.h"
6
7#include "base/allocator/allocator_extension.h"
8#include "content/common/child_process_messages.h"
9#include "content/public/browser/browser_child_process_host_iterator.h"
10#include "content/public/browser/browser_thread.h"
11#include "content/public/browser/render_process_host.h"
12#include "content/public/common/process_type.h"
13#include "net/base/net_errors.h"
14
15namespace content {
16
17// static
18AboutTcmallocOutputs* AboutTcmallocOutputs::GetInstance() {
19  return Singleton<AboutTcmallocOutputs>::get();
20}
21
22AboutTcmallocOutputs::AboutTcmallocOutputs() {}
23
24AboutTcmallocOutputs::~AboutTcmallocOutputs() {}
25
26void AboutTcmallocOutputs::OnStatsForChildProcess(
27    base::ProcessId pid, int process_type,
28    const std::string& output) {
29  std::string header = GetProcessTypeNameInEnglish(process_type);
30  base::StringAppendF(&header, " PID %d", static_cast<int>(pid));
31  SetOutput(header, output);
32}
33
34void AboutTcmallocOutputs::SetOutput(const std::string& header,
35                                     const std::string& output) {
36  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
37
38  outputs_[header] = output;
39}
40
41void AboutTcmallocOutputs::DumpToHTMLTable(std::string* data) {
42  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
43
44  data->append("<table width=\"100%\">\n");
45  for (AboutTcmallocOutputsType::const_iterator oit = outputs_.begin();
46       oit != outputs_.end();
47       oit++) {
48    data->append("<tr><td bgcolor=\"yellow\">");
49    data->append(oit->first);
50    data->append("</td></tr>\n");
51    data->append("<tr><td><pre>\n");
52    data->append(oit->second);
53    data->append("</pre></td></tr>\n");
54  }
55  data->append("</table>\n");
56  outputs_.clear();
57}
58
59TcmallocInternalsRequestJob::TcmallocInternalsRequestJob(
60    net::URLRequest* request, net::NetworkDelegate* network_delegate)
61    : net::URLRequestSimpleJob(request, network_delegate) {
62}
63
64#if defined(USE_TCMALLOC)
65void RequestTcmallocStatsFromChildRenderProcesses() {
66  RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
67  while (!it.IsAtEnd()) {
68    it.GetCurrentValue()->Send(new ChildProcessMsg_GetTcmallocStats);
69    it.Advance();
70  }
71}
72
73void AboutTcmalloc(std::string* data) {
74  data->append("<!DOCTYPE html>\n<html>\n<head>\n");
75  data->append(
76      "<meta http-equiv=\"Content-Security-Policy\" "
77      "content=\"object-src 'none'; script-src 'none'\">");
78  data->append("<title>tcmalloc stats</title>");
79  data->append("</head><body>");
80
81  // Display any stats for which we sent off requests the last time.
82  data->append("<p>Stats as of last page load;");
83  data->append("reload to get stats as of this page load.</p>\n");
84  data->append("<table width=\"100%\">\n");
85
86  AboutTcmallocOutputs::GetInstance()->DumpToHTMLTable(data);
87
88  data->append("</body></html>\n");
89
90  // Populate the collector with stats from the local browser process
91  // and send off requests to all the renderer processes.
92  char buffer[1024 * 32];
93  base::allocator::GetStats(buffer, sizeof(buffer));
94  std::string browser("Browser");
95  AboutTcmallocOutputs::GetInstance()->SetOutput(browser, buffer);
96
97  for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
98    iter.Send(new ChildProcessMsg_GetTcmallocStats);
99  }
100
101  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
102      &RequestTcmallocStatsFromChildRenderProcesses));
103}
104#endif
105
106int TcmallocInternalsRequestJob::GetData(
107    std::string* mime_type,
108    std::string* charset,
109    std::string* data,
110    const net::CompletionCallback& callback) const {
111  mime_type->assign("text/html");
112  charset->assign("UTF8");
113
114  data->clear();
115#if defined(USE_TCMALLOC)
116  AboutTcmalloc(data);
117#endif
118  return net::OK;
119}
120
121} // namespace content
122