Home | History | Annotate | Download | only in browser
      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 
     15 namespace content {
     16 
     17 // static
     18 AboutTcmallocOutputs* AboutTcmallocOutputs::GetInstance() {
     19   return Singleton<AboutTcmallocOutputs>::get();
     20 }
     21 
     22 AboutTcmallocOutputs::AboutTcmallocOutputs() {}
     23 
     24 AboutTcmallocOutputs::~AboutTcmallocOutputs() {}
     25 
     26 void 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 
     34 void AboutTcmallocOutputs::SetOutput(const std::string& header,
     35                                      const std::string& output) {
     36   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     37 
     38   outputs_[header] = output;
     39 }
     40 
     41 void 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 
     59 TcmallocInternalsRequestJob::TcmallocInternalsRequestJob(
     60     net::URLRequest* request, net::NetworkDelegate* network_delegate)
     61     : net::URLRequestSimpleJob(request, network_delegate) {
     62 }
     63 
     64 #if defined(USE_TCMALLOC)
     65 void RequestTcmallocStatsFromChildRenderProcesses() {
     66   RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
     67   while (!it.IsAtEnd()) {
     68     it.GetCurrentValue()->Send(new ChildProcessMsg_GetTcmallocStats);
     69     it.Advance();
     70   }
     71 }
     72 
     73 void 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 
    106 int 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