Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / ui / webui / profiler_ui.cc
blob11397f318d967e05447d38ceb727cefe29fcf3be
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.
5 #include "chrome/browser/ui/webui/profiler_ui.h"
7 #include <string>
9 // When testing the javacript code, it is cumbersome to have to keep
10 // re-building the resouces package and reloading the browser. To solve
11 // this, enable the following flag to read the webapp's source files
12 // directly off disk, so all you have to do is refresh the page to
13 // test the modifications.
14 // #define USE_SOURCE_FILES_DIRECTLY
16 #include "base/bind.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/strings/string_util.h"
19 #include "base/tracked_objects.h"
20 #include "base/values.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/task_profiler/task_profiler_data_serializer.h"
23 #include "chrome/common/url_constants.h"
24 #include "components/metrics/profiler/tracking_synchronizer.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/url_data_source.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/browser/web_ui.h"
29 #include "content/public/browser/web_ui_data_source.h"
30 #include "content/public/browser/web_ui_message_handler.h"
31 #include "grit/browser_resources.h"
33 #ifdef USE_SOURCE_FILES_DIRECTLY
34 #include "base/base_paths.h"
35 #include "base/files/file_util.h"
36 #include "base/memory/ref_counted_memory.h"
37 #include "base/path_service.h"
38 #endif // USE_SOURCE_FILES_DIRECTLY
40 using content::BrowserThread;
41 using content::WebContents;
42 using content::WebUIMessageHandler;
43 using metrics::TrackingSynchronizer;
45 namespace {
47 #ifdef USE_SOURCE_FILES_DIRECTLY
49 class ProfilerWebUIDataSource : public content::URLDataSource {
50 public:
51 ProfilerWebUIDataSource() {
54 protected:
55 // content::URLDataSource implementation.
56 virtual std::string GetSource() override {
57 return chrome::kChromeUIProfilerHost;
60 virtual std::string GetMimeType(const std::string& path) const override {
61 if (EndsWith(path, ".js", false))
62 return "application/javascript";
63 return "text/html";
66 virtual void StartDataRequest(
67 const std::string& path,
68 bool is_incognito,
69 const content::URLDataSource::GotDataCallback& callback) override {
70 base::FilePath base_path;
71 PathService::Get(base::DIR_SOURCE_ROOT, &base_path);
72 base_path = base_path.AppendASCII("chrome");
73 base_path = base_path.AppendASCII("browser");
74 base_path = base_path.AppendASCII("resources");
75 base_path = base_path.AppendASCII("profiler");
77 // If no resource was specified, default to profiler.html.
78 std::string filename = path.empty() ? "profiler.html" : path;
80 base::FilePath file_path;
81 file_path = base_path.AppendASCII(filename);
83 // Read the file synchronously and send it as the response.
84 base::ThreadRestrictions::ScopedAllowIO allow;
85 std::string file_contents;
86 if (!base::ReadFileToString(file_path, &file_contents))
87 LOG(ERROR) << "Couldn't read file: " << file_path.value();
88 scoped_refptr<base::RefCountedString> response =
89 new base::RefCountedString();
90 response->data() = file_contents;
91 callback.Run(response);
94 private:
95 DISALLOW_COPY_AND_ASSIGN(ProfilerWebUIDataSource);
98 #else // USE_SOURCE_FILES_DIRECTLY
100 content::WebUIDataSource* CreateProfilerHTMLSource() {
101 content::WebUIDataSource* source =
102 content::WebUIDataSource::Create(chrome::kChromeUIProfilerHost);
104 source->SetJsonPath("strings.js");
105 source->AddResourcePath("profiler.js", IDR_PROFILER_JS);
106 source->SetDefaultResource(IDR_PROFILER_HTML);
107 return source;
110 #endif
112 // This class receives javascript messages from the renderer.
113 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
114 // this class's methods are expected to run on the UI thread.
115 class ProfilerMessageHandler : public WebUIMessageHandler {
116 public:
117 ProfilerMessageHandler() {}
119 // WebUIMessageHandler implementation.
120 virtual void RegisterMessages() override;
122 // Messages.
123 void OnGetData(const base::ListValue* list);
124 void OnResetData(const base::ListValue* list);
126 private:
127 DISALLOW_COPY_AND_ASSIGN(ProfilerMessageHandler);
130 void ProfilerMessageHandler::RegisterMessages() {
131 DCHECK_CURRENTLY_ON(BrowserThread::UI);
133 web_ui()->RegisterMessageCallback("getData",
134 base::Bind(&ProfilerMessageHandler::OnGetData, base::Unretained(this)));
135 web_ui()->RegisterMessageCallback("resetData",
136 base::Bind(&ProfilerMessageHandler::OnResetData,
137 base::Unretained(this)));
140 void ProfilerMessageHandler::OnGetData(const base::ListValue* list) {
141 ProfilerUI* profiler_ui = static_cast<ProfilerUI*>(web_ui()->GetController());
142 profiler_ui->GetData();
145 void ProfilerMessageHandler::OnResetData(const base::ListValue* list) {
146 tracked_objects::ThreadData::ResetAllThreadData();
149 } // namespace
151 ProfilerUI::ProfilerUI(content::WebUI* web_ui)
152 : WebUIController(web_ui),
153 weak_ptr_factory_(this) {
154 web_ui->AddMessageHandler(new ProfilerMessageHandler());
156 // Set up the chrome://profiler/ source.
157 Profile* profile = Profile::FromWebUI(web_ui);
158 #if defined(USE_SOURCE_FILES_DIRECTLY)
159 content::URLDataSource::Add(profile, new ProfilerWebUIDataSource);
160 #else
161 content::WebUIDataSource::Add(profile, CreateProfilerHTMLSource());
162 #endif
165 ProfilerUI::~ProfilerUI() {
168 void ProfilerUI::GetData() {
169 TrackingSynchronizer::FetchProfilerDataAsynchronously(
170 weak_ptr_factory_.GetWeakPtr());
173 void ProfilerUI::ReceivedProfilerData(
174 const tracked_objects::ProcessDataSnapshot& profiler_data,
175 int process_type) {
176 // Serialize the data to JSON.
177 base::DictionaryValue json_data;
178 task_profiler::TaskProfilerDataSerializer::ToValue(profiler_data,
179 process_type,
180 &json_data);
182 // Send the data to the renderer.
183 web_ui()->CallJavascriptFunction("g_browserBridge.receivedData", json_data);