• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/gpu_internals_ui.h"
6 
7 #include <algorithm>
8 #include <string>
9 #include <utility>
10 #include <vector>
11 
12 #include "base/command_line.h"
13 #include "base/file_util.h"
14 #include "base/memory/singleton.h"
15 #include "base/message_loop.h"
16 #include "base/path_service.h"
17 #include "base/scoped_ptr.h"
18 #include "base/string_number_conversions.h"
19 #include "base/string_piece.h"
20 #include "base/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/gpu_data_manager.h"
24 #include "chrome/browser/io_thread.h"
25 #include "chrome/browser/net/chrome_net_log.h"
26 #include "chrome/browser/net/connection_tester.h"
27 #include "chrome/browser/net/passive_log_collector.h"
28 #include "chrome/browser/net/url_fixer_upper.h"
29 #include "chrome/browser/platform_util.h"
30 #include "chrome/browser/profiles/profile.h"
31 #include "chrome/browser/ui/shell_dialogs.h"
32 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
33 #include "chrome/common/chrome_paths.h"
34 #include "chrome/common/chrome_version_info.h"
35 #include "chrome/common/jstemplate_builder.h"
36 #include "chrome/common/url_constants.h"
37 #include "content/browser/browser_thread.h"
38 #include "content/browser/gpu_process_host.h"
39 #include "content/browser/renderer_host/render_view_host.h"
40 #include "content/browser/tab_contents/tab_contents.h"
41 #include "content/browser/tab_contents/tab_contents_view.h"
42 #include "content/browser/trace_controller.h"
43 #include "grit/browser_resources.h"
44 #include "grit/generated_resources.h"
45 #include "net/base/escape.h"
46 #include "net/url_request/url_request_context_getter.h"
47 #include "ui/base/l10n/l10n_util.h"
48 #include "ui/base/resource/resource_bundle.h"
49 
50 namespace {
51 
52 class GpuHTMLSource : public ChromeURLDataManager::DataSource {
53  public:
54   GpuHTMLSource();
55 
56   // Called when the network layer has requested a resource underneath
57   // the path we registered.
58   virtual void StartDataRequest(const std::string& path,
59                                 bool is_incognito,
60                                 int request_id);
61   virtual std::string GetMimeType(const std::string&) const;
62 
63  private:
~GpuHTMLSource()64   ~GpuHTMLSource() {}
65   DISALLOW_COPY_AND_ASSIGN(GpuHTMLSource);
66 };
67 
68 // This class receives javascript messages from the renderer.
69 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
70 // this class's methods are expected to run on the UI thread.
71 class GpuMessageHandler
72     : public WebUIMessageHandler,
73       public SelectFileDialog::Listener,
74       public base::SupportsWeakPtr<GpuMessageHandler>,
75       public TraceSubscriber {
76  public:
77   GpuMessageHandler();
78   virtual ~GpuMessageHandler();
79 
80   // WebUIMessageHandler implementation.
81   virtual WebUIMessageHandler* Attach(WebUI* web_ui);
82   virtual void RegisterMessages();
83 
84   // Mesages
85   void OnBeginTracing(const ListValue* list);
86   void OnEndTracingAsync(const ListValue* list);
87   void OnBrowserBridgeInitialized(const ListValue* list);
88   void OnCallAsync(const ListValue* list);
89   void OnBeginRequestBufferPercentFull(const ListValue* list);
90   void OnLoadTraceFile(const ListValue* list);
91   void OnSaveTraceFile(const ListValue* list);
92 
93   // Submessages dispatched from OnCallAsync
94   Value* OnRequestClientInfo(const ListValue* list);
95   Value* OnRequestLogMessages(const ListValue* list);
96 
97   // SelectFileDialog::Listener implementation
98   virtual void FileSelected(const FilePath& path, int index, void* params);
99   virtual void FileSelectionCanceled(void* params);
100 
101   // Callbacks.
102   void OnGpuInfoUpdate();
103   void LoadTraceFileComplete(std::string* file_contents);
104   void SaveTraceFileComplete();
105 
106   // TraceSubscriber implementation.
107   virtual void OnEndTracingComplete();
108   virtual void OnTraceDataCollected(const std::string& json_events);
109   virtual void OnTraceBufferPercentFullReply(float percent_full);
110 
111   // Executes the javascript function |function_name| in the renderer, passing
112   // it the argument |value|.
113   void CallJavascriptFunction(const std::wstring& function_name,
114                               const Value* value);
115 
116  private:
117   DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler);
118 
119   // Cache the Singleton for efficiency.
120   GpuDataManager* gpu_data_manager_;
121 
122   Callback0::Type* gpu_info_update_callback_;
123 
124   scoped_refptr<SelectFileDialog> select_trace_file_dialog_;
125   SelectFileDialog::Type select_trace_file_dialog_type_;
126   scoped_ptr<std::string> trace_data_to_save_;
127 
128   bool trace_enabled_;
129 };
130 
131 class TaskProxy : public base::RefCountedThreadSafe<TaskProxy> {
132  public:
TaskProxy(const base::WeakPtr<GpuMessageHandler> & handler)133   explicit TaskProxy(const base::WeakPtr<GpuMessageHandler>& handler)
134       : handler_(handler) {}
LoadTraceFileCompleteProxy(std::string * file_contents)135   void LoadTraceFileCompleteProxy(std::string* file_contents) {
136     if (handler_)
137       handler_->LoadTraceFileComplete(file_contents);
138     delete file_contents;
139   }
140 
SaveTraceFileCompleteProxy()141   void SaveTraceFileCompleteProxy() {
142     if (handler_)
143       handler_->SaveTraceFileComplete();
144   }
145 
146  private:
147   base::WeakPtr<GpuMessageHandler> handler_;
148   friend class base::RefCountedThreadSafe<TaskProxy>;
149   DISALLOW_COPY_AND_ASSIGN(TaskProxy);
150 };
151 
152 ////////////////////////////////////////////////////////////////////////////////
153 //
154 // GpuHTMLSource
155 //
156 ////////////////////////////////////////////////////////////////////////////////
157 
GpuHTMLSource()158 GpuHTMLSource::GpuHTMLSource()
159     : DataSource(chrome::kChromeUIGpuInternalsHost, MessageLoop::current()) {
160 }
161 
StartDataRequest(const std::string & path,bool is_incognito,int request_id)162 void GpuHTMLSource::StartDataRequest(const std::string& path,
163                                      bool is_incognito,
164                                      int request_id) {
165   DictionaryValue localized_strings;
166   SetFontAndTextDirection(&localized_strings);
167 
168   base::StringPiece gpu_html(
169       ResourceBundle::GetSharedInstance().GetRawDataResource(
170           IDR_GPU_INTERNALS_HTML));
171   std::string full_html(gpu_html.data(), gpu_html.size());
172   jstemplate_builder::AppendJsonHtml(&localized_strings, &full_html);
173   jstemplate_builder::AppendI18nTemplateSourceHtml(&full_html);
174   jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html);
175   jstemplate_builder::AppendJsTemplateSourceHtml(&full_html);
176 
177 
178   scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
179   html_bytes->data.resize(full_html.size());
180   std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
181 
182   SendResponse(request_id, html_bytes);
183 }
184 
GetMimeType(const std::string &) const185 std::string GpuHTMLSource::GetMimeType(const std::string&) const {
186   return "text/html";
187 }
188 
189 ////////////////////////////////////////////////////////////////////////////////
190 //
191 // GpuMessageHandler
192 //
193 ////////////////////////////////////////////////////////////////////////////////
194 
GpuMessageHandler()195 GpuMessageHandler::GpuMessageHandler()
196   : gpu_info_update_callback_(NULL)
197   , trace_enabled_(false) {
198   gpu_data_manager_ = GpuDataManager::GetInstance();
199   DCHECK(gpu_data_manager_);
200 }
201 
~GpuMessageHandler()202 GpuMessageHandler::~GpuMessageHandler() {
203   if (gpu_info_update_callback_) {
204     gpu_data_manager_->RemoveGpuInfoUpdateCallback(gpu_info_update_callback_);
205     delete gpu_info_update_callback_;
206   }
207 
208   if (select_trace_file_dialog_)
209     select_trace_file_dialog_->ListenerDestroyed();
210 
211   // If we are the current subscriber, this will result in ending tracing.
212   TraceController::GetInstance()->CancelSubscriber(this);
213 }
214 
Attach(WebUI * web_ui)215 WebUIMessageHandler* GpuMessageHandler::Attach(WebUI* web_ui) {
216   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
217   WebUIMessageHandler* result = WebUIMessageHandler::Attach(web_ui);
218   return result;
219 }
220 
221 /* BrowserBridge.callAsync prepends a requestID to these messages. */
RegisterMessages()222 void GpuMessageHandler::RegisterMessages() {
223   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
224 
225   web_ui_->RegisterMessageCallback(
226       "beginTracing",
227       NewCallback(this, &GpuMessageHandler::OnBeginTracing));
228   web_ui_->RegisterMessageCallback(
229       "endTracingAsync",
230       NewCallback(this, &GpuMessageHandler::OnEndTracingAsync));
231   web_ui_->RegisterMessageCallback(
232       "browserBridgeInitialized",
233       NewCallback(this, &GpuMessageHandler::OnBrowserBridgeInitialized));
234   web_ui_->RegisterMessageCallback(
235       "callAsync",
236       NewCallback(this, &GpuMessageHandler::OnCallAsync));
237   web_ui_->RegisterMessageCallback(
238       "beginRequestBufferPercentFull",
239       NewCallback(this, &GpuMessageHandler::OnBeginRequestBufferPercentFull));
240   web_ui_->RegisterMessageCallback(
241       "loadTraceFile",
242       NewCallback(this, &GpuMessageHandler::OnLoadTraceFile));
243   web_ui_->RegisterMessageCallback(
244       "saveTraceFile",
245       NewCallback(this, &GpuMessageHandler::OnSaveTraceFile));
246 }
247 
OnCallAsync(const ListValue * args)248 void GpuMessageHandler::OnCallAsync(const ListValue* args) {
249   DCHECK_GE(args->GetSize(), static_cast<size_t>(2));
250   // unpack args into requestId, submessage and submessageArgs
251   bool ok;
252   Value* requestId;
253   ok = args->Get(0, &requestId);
254   DCHECK(ok);
255 
256   std::string submessage;
257   ok = args->GetString(1, &submessage);
258   DCHECK(ok);
259 
260   ListValue* submessageArgs = new ListValue();
261   for (size_t i = 2; i < args->GetSize(); ++i) {
262     Value* arg;
263     ok = args->Get(i, &arg);
264     DCHECK(ok);
265 
266     Value* argCopy = arg->DeepCopy();
267     submessageArgs->Append(argCopy);
268   }
269 
270   // call the submessage handler
271   Value* ret = NULL;
272   if (submessage == "requestClientInfo") {
273     ret = OnRequestClientInfo(submessageArgs);
274   } else if (submessage == "requestLogMessages") {
275     ret = OnRequestLogMessages(submessageArgs);
276   } else {  // unrecognized submessage
277     NOTREACHED();
278     delete submessageArgs;
279     return;
280   }
281   delete submessageArgs;
282 
283   // call BrowserBridge.onCallAsyncReply with result
284   if (ret) {
285     web_ui_->CallJavascriptFunction("browserBridge.onCallAsyncReply",
286         *requestId,
287         *ret);
288     delete ret;
289   } else {
290     web_ui_->CallJavascriptFunction("browserBridge.onCallAsyncReply",
291         *requestId);
292   }
293 }
294 
OnBeginRequestBufferPercentFull(const ListValue * list)295 void GpuMessageHandler::OnBeginRequestBufferPercentFull(const ListValue* list) {
296   TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this);
297 }
298 
299 class ReadTraceFileTask : public Task {
300  public:
ReadTraceFileTask(TaskProxy * proxy,const FilePath & path)301   ReadTraceFileTask(TaskProxy* proxy, const FilePath& path)
302       : proxy_(proxy)
303       , path_(path) {}
304 
Run()305   virtual void Run() {
306     std::string* file_contents = new std::string();
307     if (!file_util::ReadFileToString(path_, file_contents))
308       return;
309     BrowserThread::PostTask(
310         BrowserThread::UI, FROM_HERE,
311         NewRunnableMethod(proxy_.get(),
312                           &TaskProxy::LoadTraceFileCompleteProxy,
313                           file_contents));
314   }
315 
316  private:
317   scoped_refptr<TaskProxy> proxy_;
318 
319   // Path of the file to open.
320   const FilePath path_;
321 };
322 
323 class WriteTraceFileTask : public Task {
324  public:
WriteTraceFileTask(TaskProxy * proxy,const FilePath & path,std::string * contents)325   WriteTraceFileTask(TaskProxy* proxy,
326                      const FilePath& path,
327                      std::string* contents)
328       : proxy_(proxy)
329       , path_(path)
330       , contents_(contents) {}
331 
Run()332   virtual void Run() {
333     if (!file_util::WriteFile(path_, contents_->c_str(), contents_->size()))
334       return;
335     BrowserThread::PostTask(
336         BrowserThread::UI, FROM_HERE,
337         NewRunnableMethod(proxy_.get(),
338                           &TaskProxy::SaveTraceFileCompleteProxy));
339   }
340 
341  private:
342   scoped_refptr<TaskProxy> proxy_;
343 
344   // Path of the file to save.
345   const FilePath path_;
346 
347   // What to save
348   scoped_ptr<std::string> contents_;
349 };
350 
FileSelected(const FilePath & path,int index,void * params)351 void GpuMessageHandler::FileSelected(
352     const FilePath& path, int index, void* params) {
353   if(select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE)
354     BrowserThread::PostTask(
355         BrowserThread::FILE, FROM_HERE,
356         new ReadTraceFileTask(new TaskProxy(AsWeakPtr()), path));
357   else
358     BrowserThread::PostTask(
359         BrowserThread::FILE, FROM_HERE,
360         new WriteTraceFileTask(new TaskProxy(AsWeakPtr()), path,
361                                trace_data_to_save_.release()));
362   select_trace_file_dialog_.release();
363 }
364 
FileSelectionCanceled(void * params)365 void GpuMessageHandler::FileSelectionCanceled(void* params) {
366   select_trace_file_dialog_.release();
367   if(select_trace_file_dialog_type_ == SelectFileDialog::SELECT_OPEN_FILE)
368     web_ui_->CallJavascriptFunction("tracingController.onLoadTraceFileCanceled");
369   else
370     web_ui_->CallJavascriptFunction("tracingController.onSaveTraceFileCanceled");
371 }
372 
OnLoadTraceFile(const ListValue * list)373 void GpuMessageHandler::OnLoadTraceFile(const ListValue* list) {
374   // Only allow a single dialog at a time.
375   if (select_trace_file_dialog_.get())
376     return;
377   select_trace_file_dialog_type_ = SelectFileDialog::SELECT_OPEN_FILE;
378   select_trace_file_dialog_ = SelectFileDialog::Create(this);
379   select_trace_file_dialog_->SelectFile(
380       SelectFileDialog::SELECT_OPEN_FILE,
381       string16(),
382       FilePath(),
383       NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
384       web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
385 }
386 
LoadTraceFileComplete(std::string * file_contents)387 void GpuMessageHandler::LoadTraceFileComplete(std::string* file_contents) {
388   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
389   std::wstring javascript;
390   javascript += L"tracingController.onLoadTraceFileComplete(";
391   javascript += UTF8ToWide(*file_contents);
392   javascript += L");";
393 
394   web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(),
395       WideToUTF16Hack(javascript));
396 }
397 
OnSaveTraceFile(const ListValue * list)398 void GpuMessageHandler::OnSaveTraceFile(const ListValue* list) {
399   // Only allow a single dialog at a time.
400   if (select_trace_file_dialog_.get())
401     return;
402 
403   DCHECK(list->GetSize() == 1);
404 
405   Value* tmp;
406   list->Get(0, &tmp);
407 
408   std::string* trace_data = new std::string();
409   bool ok = list->GetString(0, trace_data);
410   DCHECK(ok);
411   trace_data_to_save_.reset(trace_data);
412 
413   select_trace_file_dialog_type_ = SelectFileDialog::SELECT_SAVEAS_FILE;
414   select_trace_file_dialog_ = SelectFileDialog::Create(this);
415   select_trace_file_dialog_->SelectFile(
416       SelectFileDialog::SELECT_SAVEAS_FILE,
417       string16(),
418       FilePath(),
419       NULL, 0, FILE_PATH_LITERAL(""), web_ui_->tab_contents(),
420       web_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), NULL);
421 }
422 
SaveTraceFileComplete()423 void GpuMessageHandler::SaveTraceFileComplete() {
424   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
425   std::wstring javascript;
426   web_ui_->CallJavascriptFunction("tracingController.onSaveTraceFileComplete");
427 }
428 
OnBrowserBridgeInitialized(const ListValue * args)429 void GpuMessageHandler::OnBrowserBridgeInitialized(const ListValue* args) {
430   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
431 
432   DCHECK(!gpu_info_update_callback_);
433 
434   // Watch for changes in GPUInfo
435   gpu_info_update_callback_ =
436       NewCallback(this, &GpuMessageHandler::OnGpuInfoUpdate);
437   gpu_data_manager_->AddGpuInfoUpdateCallback(gpu_info_update_callback_);
438 
439   // Tell GpuDataManager it should have full GpuInfo. If the
440   // Gpu process has not run yet, this will trigger its launch.
441   gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
442 
443   // Run callback immediately in case the info is ready and no update in the
444   // future.
445   OnGpuInfoUpdate();
446 }
447 
OnRequestClientInfo(const ListValue * list)448 Value* GpuMessageHandler::OnRequestClientInfo(const ListValue* list) {
449   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
450 
451   DictionaryValue* dict = new DictionaryValue();
452 
453   chrome::VersionInfo version_info;
454 
455   if (!version_info.is_valid()) {
456     DLOG(ERROR) << "Unable to create chrome::VersionInfo";
457   } else {
458     // We have everything we need to send the right values.
459     dict->SetString("version", version_info.Version());
460     dict->SetString("cl", version_info.LastChange());
461     dict->SetString("version_mod",
462         platform_util::GetVersionStringModifier());
463     dict->SetString("official",
464         l10n_util::GetStringUTF16(
465             version_info.IsOfficialBuild() ?
466             IDS_ABOUT_VERSION_OFFICIAL :
467             IDS_ABOUT_VERSION_UNOFFICIAL));
468 
469     dict->SetString("command_line",
470         CommandLine::ForCurrentProcess()->command_line_string());
471   }
472 
473   dict->SetString("blacklist_version",
474       GpuDataManager::GetInstance()->GetBlacklistVersion());
475 
476   return dict;
477 }
478 
NewDescriptionValuePair(const std::string & desc,const std::string & value)479 DictionaryValue* NewDescriptionValuePair(const std::string& desc,
480     const std::string& value) {
481   DictionaryValue* dict = new DictionaryValue();
482   dict->SetString("description", desc);
483   dict->SetString("value", value);
484   return dict;
485 }
486 
NewDescriptionValuePair(const std::string & desc,Value * value)487 DictionaryValue* NewDescriptionValuePair(const std::string& desc,
488     Value* value) {
489   DictionaryValue* dict = new DictionaryValue();
490   dict->SetString("description", desc);
491   dict->Set("value", value);
492   return dict;
493 }
494 
495 #if defined(OS_WIN)
496 // Output DxDiagNode tree as nested array of {description,value} pairs
DxDiagNodeToList(const DxDiagNode & node)497 ListValue* DxDiagNodeToList(const DxDiagNode& node) {
498   ListValue* list = new ListValue();
499   for (std::map<std::string, std::string>::const_iterator it =
500       node.values.begin();
501       it != node.values.end();
502       ++it) {
503     list->Append(NewDescriptionValuePair(it->first, it->second));
504   }
505 
506   for (std::map<std::string, DxDiagNode>::const_iterator it =
507       node.children.begin();
508       it != node.children.end();
509       ++it) {
510     ListValue* sublist = DxDiagNodeToList(it->second);
511     list->Append(NewDescriptionValuePair(it->first, sublist));
512   }
513   return list;
514 }
515 
516 #endif  // OS_WIN
517 
GpuInfoToDict(const GPUInfo & gpu_info)518 DictionaryValue* GpuInfoToDict(const GPUInfo& gpu_info) {
519   ListValue* basic_info = new ListValue();
520   basic_info->Append(NewDescriptionValuePair("Initialization time",
521       base::Int64ToString(gpu_info.initialization_time.InMilliseconds())));
522   basic_info->Append(NewDescriptionValuePair("Vendor Id",
523       base::StringPrintf("0x%04x", gpu_info.vendor_id)));
524   basic_info->Append(NewDescriptionValuePair("Device Id",
525       base::StringPrintf("0x%04x", gpu_info.device_id)));
526   basic_info->Append(NewDescriptionValuePair("Driver vendor",
527       gpu_info.driver_vendor));
528   basic_info->Append(NewDescriptionValuePair("Driver version",
529       gpu_info.driver_version));
530   basic_info->Append(NewDescriptionValuePair("Driver date",
531       gpu_info.driver_date));
532   basic_info->Append(NewDescriptionValuePair("Pixel shader version",
533       gpu_info.pixel_shader_version));
534   basic_info->Append(NewDescriptionValuePair("Vertex shader version",
535       gpu_info.vertex_shader_version));
536   basic_info->Append(NewDescriptionValuePair("GL version",
537       gpu_info.gl_version));
538   basic_info->Append(NewDescriptionValuePair("GL_VENDOR",
539       gpu_info.gl_vendor));
540   basic_info->Append(NewDescriptionValuePair("GL_RENDERER",
541       gpu_info.gl_renderer));
542   basic_info->Append(NewDescriptionValuePair("GL_VERSION",
543       gpu_info.gl_version_string));
544   basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS",
545       gpu_info.gl_extensions));
546 
547   DictionaryValue* info = new DictionaryValue();
548   info->Set("basic_info", basic_info);
549 
550 #if defined(OS_WIN)
551   Value* dx_info;
552   if (gpu_info.dx_diagnostics.children.size())
553     dx_info = DxDiagNodeToList(gpu_info.dx_diagnostics);
554   else
555     dx_info = Value::CreateNullValue();
556   info->Set("diagnostics", dx_info);
557 #endif
558 
559   return info;
560 }
561 
OnRequestLogMessages(const ListValue *)562 Value* GpuMessageHandler::OnRequestLogMessages(const ListValue*) {
563   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
564 
565   return gpu_data_manager_->log_messages().DeepCopy();
566 }
567 
OnGpuInfoUpdate()568 void GpuMessageHandler::OnGpuInfoUpdate() {
569   const GPUInfo& gpu_info = gpu_data_manager_->gpu_info();
570 
571   // Get GPU Info.
572   DictionaryValue* gpu_info_val = GpuInfoToDict(gpu_info);
573 
574   // Add in blacklisting features
575   Value* feature_status = gpu_data_manager_->GetFeatureStatus();
576   if (feature_status)
577     gpu_info_val->Set("featureStatus", feature_status);
578 
579   // Send GPU Info to javascript.
580   web_ui_->CallJavascriptFunction("browserBridge.onGpuInfoUpdate",
581       *gpu_info_val);
582 
583   delete gpu_info_val;
584 }
585 
OnBeginTracing(const ListValue * args)586 void GpuMessageHandler::OnBeginTracing(const ListValue* args) {
587   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
588   trace_enabled_ = true;
589   // TODO(jbates) This may fail, but that's OK for current use cases.
590   //              Ex: Multiple about:gpu traces can not trace simultaneously.
591   // TODO(nduca) send feedback to javascript about whether or not BeginTracing
592   //             was successful.
593   TraceController::GetInstance()->BeginTracing(this);
594 }
595 
OnEndTracingAsync(const ListValue * list)596 void GpuMessageHandler::OnEndTracingAsync(const ListValue* list) {
597   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
598 
599   // TODO(nduca): fix javascript code to make sure trace_enabled_ is always true
600   //              here. triggered a false condition by just clicking stop
601   //              trace a few times when it was going slow, and maybe switching
602   //              between tabs.
603   if (trace_enabled_ &&
604       !TraceController::GetInstance()->EndTracingAsync(this)) {
605     // Set to false now, since it turns out we never were the trace subscriber.
606     OnEndTracingComplete();
607   }
608 }
609 
OnEndTracingComplete()610 void GpuMessageHandler::OnEndTracingComplete() {
611   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
612   trace_enabled_ = false;
613   web_ui_->CallJavascriptFunction("tracingController.onEndTracingComplete");
614 }
615 
OnTraceDataCollected(const std::string & json_events)616 void GpuMessageHandler::OnTraceDataCollected(const std::string& json_events) {
617   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
618   std::wstring javascript;
619   javascript += L"tracingController.onTraceDataCollected(";
620   javascript += UTF8ToWide(json_events);
621   javascript += L");";
622 
623   web_ui_->GetRenderViewHost()->ExecuteJavascriptInWebFrame(string16(),
624       WideToUTF16Hack(javascript));
625 }
626 
OnTraceBufferPercentFullReply(float percent_full)627 void GpuMessageHandler::OnTraceBufferPercentFullReply(float percent_full) {
628   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
629   web_ui_->CallJavascriptFunction(
630       "tracingController.onRequestBufferPercentFullComplete",
631       *scoped_ptr<Value>(Value::CreateDoubleValue(percent_full)));
632 }
633 
634 }  // namespace
635 
636 
637 ////////////////////////////////////////////////////////////////////////////////
638 //
639 // GpuInternalsUI
640 //
641 ////////////////////////////////////////////////////////////////////////////////
642 
GpuInternalsUI(TabContents * contents)643 GpuInternalsUI::GpuInternalsUI(TabContents* contents) : WebUI(contents) {
644   AddMessageHandler((new GpuMessageHandler())->Attach(this));
645 
646   GpuHTMLSource* html_source = new GpuHTMLSource();
647 
648   // Set up the chrome://gpu/ source.
649   contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
650 }
651