Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(523)

Side by Side Diff: chrome/browser/ui/webui/tracing_ui.cc

Issue 7555005: Moving the contents of chrome://gpu Profiling to chrome://tracing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 "chrome/browser/ui/webui/tracing_ui.h"
6
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/scoped_ptr.h"
12 #include "base/string_number_conversions.h"
13 #include "base/utf_string_conversions.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/shell_dialogs.h"
16 #include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "chrome/common/url_constants.h"
19 #include "content/browser/gpu/gpu_data_manager.h"
20 #include "content/browser/renderer_host/render_view_host.h"
21 #include "content/browser/tab_contents/tab_contents.h"
22 #include "content/browser/tab_contents/tab_contents_view.h"
23 #include "content/browser/trace_controller.h"
24 #include "grit/browser_resources.h"
25 #include "grit/generated_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27
28 namespace {
29
30 ChromeWebUIDataSource* CreateTracingHTMLSource() {
31 ChromeWebUIDataSource* source =
32 new ChromeWebUIDataSource(chrome::kChromeUITracingHost);
33
34 source->set_json_path("strings.js");
35 source->add_resource_path("tracing.js", IDR_TRACING_JS);
36 source->set_default_resource(IDR_TRACING_HTML);
37 return source;
38 }
39
40 // This class receives javascript messages from the renderer.
41 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
42 // this class's methods are expected to run on the UI thread.
43 class TracingMessageHandler
44 : public WebUIMessageHandler,
45 public SelectFileDialog::Listener,
46 public base::SupportsWeakPtr<TracingMessageHandler>,
47 public TraceSubscriber {
48 public:
49 TracingMessageHandler();
50 virtual ~TracingMessageHandler();
51
52 // WebUIMessageHandler implementation.
53 virtual WebUIMessageHandler* Attach(WebUI* web_ui);
54 virtual void RegisterMessages();
55
56 // Mesages
James Hawkins 2011/08/04 17:26:35 You're intermingling added methods with interface
dominich 2011/08/04 22:56:12 Done.
57 void OnBeginTracing(const ListValue* list);
58 void OnEndTracingAsync(const ListValue* list);
59 void OnBeginRequestBufferPercentFull(const ListValue* list);
60 void OnLoadTraceFile(const ListValue* list);
61 void OnSaveTraceFile(const ListValue* list);
62
63 // SelectFileDialog::Listener implementation
64 virtual void FileSelected(const FilePath& path, int index, void* params);
65 virtual void FileSelectionCanceled(void* params);
66
67 // Callbacks.
68 void LoadTraceFileComplete(std::string* file_contents);
69 void SaveTraceFileComplete();
70
71 // TraceSubscriber implementation.
72 virtual void OnEndTracingComplete();
73 virtual void OnTraceDataCollected(const std::string& json_events);
74 virtual void OnTraceBufferPercentFullReply(float percent_full);
75
76 // Executes the javascript function |function_name| in the renderer, passing
77 // it the argument |value|.
78 void CallJavascriptFunction(const std::wstring& function_name,
79 const Value* value);
80
81 private:
82 DISALLOW_COPY_AND_ASSIGN(TracingMessageHandler);
James Hawkins 2011/08/04 17:26:35 This should be at the bottom of the class.
dominich 2011/08/04 22:56:12 Done.
83
84 scoped_refptr<SelectFileDialog> select_trace_file_dialog_;
James Hawkins 2011/08/04 17:26:35 Document vars.
dominich 2011/08/04 22:56:12 Done.
85 SelectFileDialog::Type select_trace_file_dialog_type_;
86 scoped_ptr<std::string> trace_data_to_save_;
87
88 bool trace_enabled_;
89 };
90
91 class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
James Hawkins 2011/08/04 17:26:35 Document this class.
dominich 2011/08/04 22:56:12 Done.
92 public:
93 explicit TaskProxy(const base::WeakPtr<TracingMessageHandler>& handler)
94 : handler_(handler) {}
95 void LoadTraceFileCompleteProxy(std::string* file_contents) {
96 if (handler_)
97 handler_->LoadTraceFileComplete(file_contents);
98 delete file_contents;
99 }
100
101 void SaveTraceFileCompleteProxy() {
102 if (handler_)
103 handler_->SaveTraceFileComplete();
104 }
105
106 private:
107 base::WeakPtr<TracingMessageHandler> handler_;
James Hawkins 2011/08/04 17:26:35 Document vars.
dominich 2011/08/04 22:56:12 Done.
108 friend class base::RefCountedThreadSafe<TaskProxy>;
109 DISALLOW_COPY_AND_ASSIGN(TaskProxy);
110 };
111
112 ////////////////////////////////////////////////////////////////////////////////
113 //
114 // TracingMessageHandler
115 //
116 ////////////////////////////////////////////////////////////////////////////////
117
118 TracingMessageHandler::TracingMessageHandler()
119 : select_trace_file_dialog_type_(SelectFileDialog::SELECT_NONE),
120 trace_enabled_(false) {
121 }
122
123 TracingMessageHandler::~TracingMessageHandler() {
124 if (select_trace_file_dialog_)
125 select_trace_file_dialog_->ListenerDestroyed();
126
127 // If we are the current subscriber, this will result in ending tracing.
128 TraceController::GetInstance()->CancelSubscriber(this);
129 }
130
131 WebUIMessageHandler* TracingMessageHandler::Attach(WebUI* web_ui) {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
133 WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
134 return result;
135 }
136
137 void TracingMessageHandler::RegisterMessages() {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139
140 web_ui_->RegisterMessageCallback(
141 "beginTracing",
142 NewCallback(this, &TracingMessageHandler::OnBeginTracing));
143 web_ui_->RegisterMessageCallback(
144 "endTracingAsync",
145 NewCallback(this, &TracingMessageHandler::OnEndTracingAsync));
146 web_ui_->RegisterMessageCallback(
147 "beginRequestBufferPercentFull",
148 NewCallback(this,
149 &TracingMessageHandler::OnBeginRequestBufferPercentFull));
150 web_ui_->RegisterMessageCallback(
151 "loadTraceFile",
152 NewCallback(this, &TracingMessageHandler::OnLoadTraceFile));
153 web_ui_->RegisterMessageCallback(
154 "saveTraceFile",
155 NewCallback(this, &TracingMessageHandler::OnSaveTraceFile));
156 }
157
158 void TracingMessageHandler::OnBeginRequestBufferPercentFull(
159 const ListValue* list) {
160 TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this);
161 }
162
163 class ReadTraceFileTask : public Task {
164 public:
165 ReadTraceFileTask(TaskProxy* proxy, const FilePath& path)
166 : proxy_(proxy)
167 , path_(path) {}
James Hawkins 2011/08/04 17:26:35 Comma must be on the previous line.
dominich 2011/08/04 22:56:12 Done.
168
169 virtual void Run() {
170 std::string* file_contents = new std::string();
171 if (!file_util::ReadFileToString(path_, file_contents)) {
172 delete file_contents;
173 return;
174 }
175 BrowserThread::PostTask(
176 BrowserThread::UI, FROM_HERE,
177 NewRunnableMethod(proxy_.get(),
178 &TaskProxy::LoadTraceFileCompleteProxy,
179 file_contents));
180 }
181
182 private:
183 scoped_refptr<TaskProxy> proxy_;
184
185 // Path of the file to open.
186 const FilePath path_;
187 };
188
189 class WriteTraceFileTask : public Task {
James Hawkins 2011/08/04 17:26:35 Document class.
dominich 2011/08/04 22:56:12 Done.
190 public:
191 WriteTraceFileTask(TaskProxy* proxy,
192 const FilePath& path,
193 std::string* contents)
194 : proxy_(proxy)
195 , path_(path)
196 , contents_(contents) {}
197
198 virtual void Run() {
199 if (!file_util::WriteFile(path_, contents_->c_str(), contents_->size()))
200 return;
201 BrowserThread::PostTask(
202 BrowserThread::UI, FROM_HERE,
203 NewRunnableMethod(proxy_.get(),
204 &TaskProxy::SaveTraceFileCompleteProxy));
205 }
206
207 private:
208 scoped_refptr<TaskProxy> proxy_;
209
210 // Path of the file to save.
211 const FilePath path_;
212
213 // What to save
214 scoped_ptr<std::string> contents_;
215 };
216
217 void TracingMessageHandler::FileSelected(
218 const FilePath& path, int index, void* params) {
219 if (select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE)
220 BrowserThread::PostTask(
221 BrowserThread::FILE, FROM_HERE,
222 new ReadTraceFileTask(new TaskProxy(AsWeakPtr()), path));
223 else
224 BrowserThread::PostTask(
225 BrowserThread::FILE, FROM_HERE,
226 new WriteTraceFileTask(new TaskProxy(AsWeakPtr()), path,
227 trace_data_to_save_.release()));
228 select_trace_file_dialog_.release();
229 }
230
231 void TracingMessageHandler::FileSelectionCanceled(void* params) {
232 select_trace_file_dialog_.release();
233 if (select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE) {
234 web_ui_->CallJavascriptFunction(
235 "tracingController.onLoadTraceFileCanceled");
236 } else {
237 web_ui_->CallJavascriptFunction(
238 "tracingController.onSaveTraceFileCanceled");
239 }
240 }
241
242 void TracingMessageHandler::OnLoadTraceFile(const ListValue* list) {
243 // Only allow a single dialog at a time.
244 if (select_trace_file_dialog_.get())
245 return;
246 select_trace_file_dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE;
247 select_trace_file_dialog_ = SelectFileDialog::Create(this);
248 select_trace_file_dialog_->SelectFile(
249 SelectFileDialog::SELECT_OPEN_FILE,
250 string16(),
251 FilePath(),
252 NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
253 web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
254 }
255
256 void TracingMessageHandler::LoadTraceFileComplete(std::string* file_contents) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258 std::wstring javascript;
259 javascript += L"tracingController.onLoadTraceFileComplete(";
260 javascript += UTF8ToWide(*file_contents);
261 javascript += L");";
262
263 web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(),
264 WideToUTF16Hack(javascript));
265 }
266
267 void TracingMessageHandler::OnSaveTraceFile(const ListValue* list) {
268 // Only allow a single dialog at a time.
269 if (select_trace_file_dialog_.get())
270 return;
271
272 DCHECK(list->GetSize() == 1);
273
274 std::string* trace_data = new std::string();
275 bool ok = list->GetString(0, trace_data);
276 DCHECK(ok);
277 trace_data_to_save_.reset(trace_data);
278
279 select_trace_file_dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE;
280 select_trace_file_dialog_ = SelectFileDialog::Create(this);
281 select_trace_file_dialog_->SelectFile(
282 SelectFileDialog::SELECT_SAVEAS_FILE,
283 string16(),
284 FilePath(),
285 NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
286 web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
287 }
288
289 void TracingMessageHandler::SaveTraceFileComplete() {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
291 std::wstring javascript;
292 web_ui_->CallJavascriptFunction("tracingController.onSaveTraceFileComplete");
293 }
294
295 DictionaryValue* NewDescriptionValuePair(const std::string& desc,
296 const std::string& value) {
297 DictionaryValue* dict = new DictionaryValue();
298 dict->SetString("description", desc);
299 dict->SetString("value", value);
300 return dict;
301 }
302
303 DictionaryValue* NewDescriptionValuePair(const std::string& desc,
304 Value* value) {
305 DictionaryValue* dict = new DictionaryValue();
306 dict->SetString("description", desc);
307 dict->Set("value", value);
308 return dict;
309 }
310
311 void TracingMessageHandler::OnBeginTracing(const ListValue* args) {
312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313 trace_enabled_ = true;
314 // TODO(jbates) This may fail, but that's OK for current use cases.
315 // Ex: Multiple about:gpu traces can not trace simultaneously.
316 // TODO(nduca) send feedback to javascript about whether or not BeginTracing
317 // was successful.
318 TraceController::GetInstance()->BeginTracing(this);
319 }
320
321 void TracingMessageHandler::OnEndTracingAsync(const ListValue* list) {
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
323
324 // TODO(nduca): fix javascript code to make sure trace_enabled_ is always true
325 // here. triggered a false condition by just clicking stop
326 // trace a few times when it was going slow, and maybe switching
327 // between tabs.
328 if (trace_enabled_ &&
329 !TraceController::GetInstance()->EndTracingAsync(this)) {
330 // Set to false now, since it turns out we never were the trace subscriber.
331 OnEndTracingComplete();
332 }
333 }
334
335 void TracingMessageHandler::OnEndTracingComplete() {
336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337 trace_enabled_ = false;
338 web_ui_->CallJavascriptFunction("tracingController.onEndTracingComplete");
339 }
340
341 void TracingMessageHandler::OnTraceDataCollected(
342 const std::string& json_events) {
343 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
344 std::wstring javascript;
345 javascript += L"tracingController.onTraceDataCollected(";
346 javascript += UTF8ToWide(json_events);
347 javascript += L");";
348
349 web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(),
350 WideToUTF16Hack(javascript));
351 }
352
353 void TracingMessageHandler::OnTraceBufferPercentFullReply(float percent_full) {
354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
355 web_ui_->CallJavascriptFunction(
356 "tracingController.onRequestBufferPercentFullComplete",
357 *scoped_ptr<Value>(Value::CreateDoubleValue(percent_full)));
358 }
359
360 } // namespace
361
362
363 ////////////////////////////////////////////////////////////////////////////////
364 //
365 // TracingUI
366 //
367 ////////////////////////////////////////////////////////////////////////////////
368
369 TracingUI::TracingUI(TabContents* contents) : ChromeWebUI(contents) {
370 printf("TracingUI::TracingUI\n");
371 AddMessageHandler((new TracingMessageHandler())->Attach(this));
372
373 // Set up the chrome://tracing/ source.
374 Profile::FromBrowserContext(contents->browser_context())->
375 GetChromeURLDataManager()->AddDataSource(CreateTracingHTMLSource());
376 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698