| // Copyright (c) 2012 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 "content/browser/tcmalloc_internals_request_job.h" |
| |
| #include "base/allocator/allocator_extension.h" |
| #include "content/common/child_process_messages.h" |
| #include "content/public/browser/browser_child_process_host_iterator.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/common/process_type.h" |
| #include "net/base/net_errors.h" |
| |
| namespace content { |
| |
| // static |
| AboutTcmallocOutputs* AboutTcmallocOutputs::GetInstance() { |
| return Singleton<AboutTcmallocOutputs>::get(); |
| } |
| |
| AboutTcmallocOutputs::AboutTcmallocOutputs() {} |
| |
| AboutTcmallocOutputs::~AboutTcmallocOutputs() {} |
| |
| void AboutTcmallocOutputs::OnStatsForChildProcess( |
| base::ProcessId pid, int process_type, |
| const std::string& output) { |
| std::string header = GetProcessTypeNameInEnglish(process_type); |
| base::StringAppendF(&header, " PID %d", static_cast<int>(pid)); |
| SetOutput(header, output); |
| } |
| |
| void AboutTcmallocOutputs::SetOutput(const std::string& header, |
| const std::string& output) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| outputs_[header] = output; |
| } |
| |
| void AboutTcmallocOutputs::DumpToHTMLTable(std::string* data) { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| |
| data->append("<table width=\"100%\">\n"); |
| for (AboutTcmallocOutputsType::const_iterator oit = outputs_.begin(); |
| oit != outputs_.end(); |
| oit++) { |
| data->append("<tr><td bgcolor=\"yellow\">"); |
| data->append(oit->first); |
| data->append("</td></tr>\n"); |
| data->append("<tr><td><pre>\n"); |
| data->append(oit->second); |
| data->append("</pre></td></tr>\n"); |
| } |
| data->append("</table>\n"); |
| outputs_.clear(); |
| } |
| |
| TcmallocInternalsRequestJob::TcmallocInternalsRequestJob( |
| net::URLRequest* request, net::NetworkDelegate* network_delegate) |
| : net::URLRequestSimpleJob(request, network_delegate) { |
| } |
| |
| #if defined(USE_TCMALLOC) |
| void RequestTcmallocStatsFromChildRenderProcesses() { |
| RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); |
| while (!it.IsAtEnd()) { |
| it.GetCurrentValue()->Send(new ChildProcessMsg_GetTcmallocStats); |
| it.Advance(); |
| } |
| } |
| |
| void AboutTcmalloc(std::string* data) { |
| data->append("<!DOCTYPE html>\n<html>\n<head>\n"); |
| data->append( |
| "<meta http-equiv=\"Content-Security-Policy\" " |
| "content=\"object-src 'none'; script-src 'none'\">"); |
| data->append("<title>tcmalloc stats</title>"); |
| data->append("</head><body>"); |
| |
| // Display any stats for which we sent off requests the last time. |
| data->append("<p>Stats as of last page load;"); |
| data->append("reload to get stats as of this page load.</p>\n"); |
| data->append("<table width=\"100%\">\n"); |
| |
| AboutTcmallocOutputs::GetInstance()->DumpToHTMLTable(data); |
| |
| data->append("</body></html>\n"); |
| |
| // Populate the collector with stats from the local browser process |
| // and send off requests to all the renderer processes. |
| char buffer[1024 * 32]; |
| base::allocator::GetStats(buffer, sizeof(buffer)); |
| std::string browser("Browser"); |
| AboutTcmallocOutputs::GetInstance()->SetOutput(browser, buffer); |
| |
| for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { |
| iter.Send(new ChildProcessMsg_GetTcmallocStats); |
| } |
| |
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind( |
| &RequestTcmallocStatsFromChildRenderProcesses)); |
| } |
| #endif |
| |
| int TcmallocInternalsRequestJob::GetData( |
| std::string* mime_type, |
| std::string* charset, |
| std::string* data, |
| const net::CompletionCallback& callback) const { |
| mime_type->assign("text/html"); |
| charset->assign("UTF8"); |
| |
| data->clear(); |
| #if defined(USE_TCMALLOC) |
| AboutTcmalloc(data); |
| #endif |
| return net::OK; |
| } |
| |
| } // namespace content |