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"
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/metrics/tracking_synchronizer.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/task_profiler/task_profiler_data_serializer.h"
24 #include "chrome/common/url_constants.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"
32 #include "grit/generated_resources.h"
34 #ifdef USE_SOURCE_FILES_DIRECTLY
35 #include "base/base_paths.h"
36 #include "base/file_util.h"
37 #include "base/memory/ref_counted_memory.h"
38 #include "base/path_service.h"
39 #endif // USE_SOURCE_FILES_DIRECTLY
41 using chrome_browser_metrics::TrackingSynchronizer
;
42 using content::BrowserThread
;
43 using content::WebContents
;
44 using content::WebUIMessageHandler
;
48 #ifdef USE_SOURCE_FILES_DIRECTLY
50 class ProfilerWebUIDataSource
: public content::URLDataSource
{
52 ProfilerWebUIDataSource() {
56 // content::URLDataSource implementation.
57 virtual std::string
GetSource() OVERRIDE
{
58 return chrome::kChromeUIProfilerHost
;
61 virtual std::string
GetMimeType(const std::string
& path
) const OVERRIDE
{
62 if (EndsWith(path
, ".js", false))
63 return "application/javascript";
67 virtual void StartDataRequest(
68 const std::string
& path
,
70 const content::URLDataSource::GotDataCallback
& callback
) OVERRIDE
{
71 base::FilePath base_path
;
72 PathService::Get(base::DIR_SOURCE_ROOT
, &base_path
);
73 base_path
= base_path
.AppendASCII("chrome");
74 base_path
= base_path
.AppendASCII("browser");
75 base_path
= base_path
.AppendASCII("resources");
76 base_path
= base_path
.AppendASCII("profiler");
78 // If no resource was specified, default to profiler.html.
79 std::string filename
= path
.empty() ? "profiler.html" : path
;
81 base::FilePath file_path
;
82 file_path
= base_path
.AppendASCII(filename
);
84 // Read the file synchronously and send it as the response.
85 base::ThreadRestrictions::ScopedAllowIO allow
;
86 std::string file_contents
;
87 if (!base::ReadFileToString(file_path
, &file_contents
))
88 LOG(ERROR
) << "Couldn't read file: " << file_path
.value();
89 scoped_refptr
<base::RefCountedString
> response
=
90 new base::RefCountedString();
91 response
->data() = file_contents
;
92 callback
.Run(response
);
96 DISALLOW_COPY_AND_ASSIGN(ProfilerWebUIDataSource
);
99 #else // USE_SOURCE_FILES_DIRECTLY
101 content::WebUIDataSource
* CreateProfilerHTMLSource() {
102 content::WebUIDataSource
* source
=
103 content::WebUIDataSource::Create(chrome::kChromeUIProfilerHost
);
105 source
->SetJsonPath("strings.js");
106 source
->AddResourcePath("profiler.js", IDR_PROFILER_JS
);
107 source
->SetDefaultResource(IDR_PROFILER_HTML
);
113 // This class receives javascript messages from the renderer.
114 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
115 // this class's methods are expected to run on the UI thread.
116 class ProfilerMessageHandler
: public WebUIMessageHandler
{
118 ProfilerMessageHandler() {}
120 // WebUIMessageHandler implementation.
121 virtual void RegisterMessages() OVERRIDE
;
124 void OnGetData(const base::ListValue
* list
);
125 void OnResetData(const base::ListValue
* list
);
128 DISALLOW_COPY_AND_ASSIGN(ProfilerMessageHandler
);
131 void ProfilerMessageHandler::RegisterMessages() {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
134 web_ui()->RegisterMessageCallback("getData",
135 base::Bind(&ProfilerMessageHandler::OnGetData
, base::Unretained(this)));
136 web_ui()->RegisterMessageCallback("resetData",
137 base::Bind(&ProfilerMessageHandler::OnResetData
,
138 base::Unretained(this)));
141 void ProfilerMessageHandler::OnGetData(const base::ListValue
* list
) {
142 ProfilerUI
* profiler_ui
= static_cast<ProfilerUI
*>(web_ui()->GetController());
143 profiler_ui
->GetData();
146 void ProfilerMessageHandler::OnResetData(const base::ListValue
* list
) {
147 tracked_objects::ThreadData::ResetAllThreadData();
152 ProfilerUI::ProfilerUI(content::WebUI
* web_ui
)
153 : WebUIController(web_ui
),
154 weak_ptr_factory_(this) {
155 web_ui
->AddMessageHandler(new ProfilerMessageHandler());
157 // Set up the chrome://profiler/ source.
158 Profile
* profile
= Profile::FromWebUI(web_ui
);
159 #if defined(USE_SOURCE_FILES_DIRECTLY)
160 content::URLDataSource::Add(profile
, new ProfilerWebUIDataSource
);
162 content::WebUIDataSource::Add(profile
, CreateProfilerHTMLSource());
166 ProfilerUI::~ProfilerUI() {
169 void ProfilerUI::GetData() {
170 TrackingSynchronizer::FetchProfilerDataAsynchronously(
171 weak_ptr_factory_
.GetWeakPtr());
174 void ProfilerUI::ReceivedProfilerData(
175 const tracked_objects::ProcessDataSnapshot
& profiler_data
,
177 // Serialize the data to JSON.
178 base::DictionaryValue json_data
;
179 task_profiler::TaskProfilerDataSerializer::ToValue(profiler_data
,
183 // Send the data to the renderer.
184 web_ui()->CallJavascriptFunction("g_browserBridge.receivedData", json_data
);