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. 4 5#include "content/browser/gpu/gpu_internals_ui.h" 6 7#include <string> 8 9#include "base/bind.h" 10#include "base/bind_helpers.h" 11#include "base/command_line.h" 12#include "base/i18n/time_formatting.h" 13#include "base/strings/string_number_conversions.h" 14#include "base/strings/stringprintf.h" 15#include "base/sys_info.h" 16#include "base/values.h" 17#include "cc/base/switches.h" 18#include "content/browser/gpu/gpu_data_manager_impl.h" 19#include "content/public/browser/browser_thread.h" 20#include "content/public/browser/compositor_util.h" 21#include "content/public/browser/gpu_data_manager_observer.h" 22#include "content/public/browser/web_contents.h" 23#include "content/public/browser/web_ui.h" 24#include "content/public/browser/web_ui_data_source.h" 25#include "content/public/browser/web_ui_message_handler.h" 26#include "content/public/common/content_client.h" 27#include "content/public/common/content_switches.h" 28#include "content/public/common/url_constants.h" 29#include "gpu/config/gpu_feature_type.h" 30#include "gpu/config/gpu_info.h" 31#include "grit/content_resources.h" 32#include "third_party/angle_dx11/src/common/version.h" 33 34namespace content { 35namespace { 36 37struct GpuFeatureInfo { 38 std::string name; 39 uint32 blocked; 40 bool disabled; 41 std::string disabled_description; 42 bool fallback_to_software; 43}; 44 45WebUIDataSource* CreateGpuHTMLSource() { 46 WebUIDataSource* source = WebUIDataSource::Create(kChromeUIGpuHost); 47 48 source->SetJsonPath("strings.js"); 49 source->AddResourcePath("gpu_internals.js", IDR_GPU_INTERNALS_JS); 50 source->SetDefaultResource(IDR_GPU_INTERNALS_HTML); 51 return source; 52} 53 54base::DictionaryValue* NewDescriptionValuePair(const std::string& desc, 55 const std::string& value) { 56 base::DictionaryValue* dict = new base::DictionaryValue(); 57 dict->SetString("description", desc); 58 dict->SetString("value", value); 59 return dict; 60} 61 62base::DictionaryValue* NewDescriptionValuePair(const std::string& desc, 63 base::Value* value) { 64 base::DictionaryValue* dict = new base::DictionaryValue(); 65 dict->SetString("description", desc); 66 dict->Set("value", value); 67 return dict; 68} 69 70base::Value* NewStatusValue(const char* name, const char* status) { 71 base::DictionaryValue* value = new base::DictionaryValue(); 72 value->SetString("name", name); 73 value->SetString("status", status); 74 return value; 75} 76 77#if defined(OS_WIN) 78// Output DxDiagNode tree as nested array of {description,value} pairs 79base::ListValue* DxDiagNodeToList(const gpu::DxDiagNode& node) { 80 base::ListValue* list = new base::ListValue(); 81 for (std::map<std::string, std::string>::const_iterator it = 82 node.values.begin(); 83 it != node.values.end(); 84 ++it) { 85 list->Append(NewDescriptionValuePair(it->first, it->second)); 86 } 87 88 for (std::map<std::string, gpu::DxDiagNode>::const_iterator it = 89 node.children.begin(); 90 it != node.children.end(); 91 ++it) { 92 base::ListValue* sublist = DxDiagNodeToList(it->second); 93 list->Append(NewDescriptionValuePair(it->first, sublist)); 94 } 95 return list; 96} 97#endif 98 99std::string GPUDeviceToString(const gpu::GPUInfo::GPUDevice& gpu) { 100 std::string vendor = base::StringPrintf("0x%04x", gpu.vendor_id); 101 if (!gpu.vendor_string.empty()) 102 vendor += " [" + gpu.vendor_string + "]"; 103 std::string device = base::StringPrintf("0x%04x", gpu.device_id); 104 if (!gpu.device_string.empty()) 105 device += " [" + gpu.device_string + "]"; 106 return base::StringPrintf( 107 "VENDOR = %s, DEVICE= %s", vendor.c_str(), device.c_str()); 108} 109 110base::DictionaryValue* GpuInfoAsDictionaryValue() { 111 gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo(); 112 base::ListValue* basic_info = new base::ListValue(); 113 basic_info->Append(NewDescriptionValuePair( 114 "Initialization time", 115 base::Int64ToString(gpu_info.initialization_time.InMilliseconds()))); 116 basic_info->Append(NewDescriptionValuePair( 117 "Sandboxed", new base::FundamentalValue(gpu_info.sandboxed))); 118 basic_info->Append(NewDescriptionValuePair( 119 "GPU0", GPUDeviceToString(gpu_info.gpu))); 120 for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) { 121 basic_info->Append(NewDescriptionValuePair( 122 base::StringPrintf("GPU%d", static_cast<int>(i + 1)), 123 GPUDeviceToString(gpu_info.secondary_gpus[i]))); 124 } 125 basic_info->Append(NewDescriptionValuePair( 126 "Optimus", new base::FundamentalValue(gpu_info.optimus))); 127 basic_info->Append(NewDescriptionValuePair( 128 "AMD switchable", new base::FundamentalValue(gpu_info.amd_switchable))); 129 if (gpu_info.lenovo_dcute) { 130 basic_info->Append(NewDescriptionValuePair( 131 "Lenovo dCute", new base::FundamentalValue(true))); 132 } 133 if (gpu_info.display_link_version.IsValid()) { 134 basic_info->Append(NewDescriptionValuePair( 135 "DisplayLink Version", gpu_info.display_link_version.GetString())); 136 } 137 basic_info->Append(NewDescriptionValuePair("Driver vendor", 138 gpu_info.driver_vendor)); 139 basic_info->Append(NewDescriptionValuePair("Driver version", 140 gpu_info.driver_version)); 141 basic_info->Append(NewDescriptionValuePair("Driver date", 142 gpu_info.driver_date)); 143 basic_info->Append(NewDescriptionValuePair("Pixel shader version", 144 gpu_info.pixel_shader_version)); 145 basic_info->Append(NewDescriptionValuePair("Vertex shader version", 146 gpu_info.vertex_shader_version)); 147 basic_info->Append(NewDescriptionValuePair("Machine model", 148 gpu_info.machine_model)); 149 basic_info->Append(NewDescriptionValuePair("GL version", 150 gpu_info.gl_version)); 151 basic_info->Append(NewDescriptionValuePair("GL_VENDOR", 152 gpu_info.gl_vendor)); 153 basic_info->Append(NewDescriptionValuePair("GL_RENDERER", 154 gpu_info.gl_renderer)); 155 basic_info->Append(NewDescriptionValuePair("GL_VERSION", 156 gpu_info.gl_version_string)); 157 basic_info->Append(NewDescriptionValuePair("GL_EXTENSIONS", 158 gpu_info.gl_extensions)); 159 basic_info->Append(NewDescriptionValuePair("Window system binding vendor", 160 gpu_info.gl_ws_vendor)); 161 basic_info->Append(NewDescriptionValuePair("Window system binding version", 162 gpu_info.gl_ws_version)); 163 basic_info->Append(NewDescriptionValuePair("Window system binding extensions", 164 gpu_info.gl_ws_extensions)); 165 std::string reset_strategy = 166 base::StringPrintf("0x%04x", gpu_info.gl_reset_notification_strategy); 167 basic_info->Append(NewDescriptionValuePair( 168 "Reset notification strategy", reset_strategy)); 169 170 base::DictionaryValue* info = new base::DictionaryValue(); 171 info->Set("basic_info", basic_info); 172 173#if defined(OS_WIN) 174 base::ListValue* perf_info = new base::ListValue(); 175 perf_info->Append(NewDescriptionValuePair( 176 "Graphics", 177 base::StringPrintf("%.1f", gpu_info.performance_stats.graphics))); 178 perf_info->Append(NewDescriptionValuePair( 179 "Gaming", 180 base::StringPrintf("%.1f", gpu_info.performance_stats.gaming))); 181 perf_info->Append(NewDescriptionValuePair( 182 "Overall", 183 base::StringPrintf("%.1f", gpu_info.performance_stats.overall))); 184 info->Set("performance_info", perf_info); 185 186 base::Value* dx_info = gpu_info.dx_diagnostics.children.size() ? 187 DxDiagNodeToList(gpu_info.dx_diagnostics) : 188 base::Value::CreateNullValue(); 189 info->Set("diagnostics", dx_info); 190#endif 191 192 return info; 193} 194 195// Determine if accelerated-2d-canvas is supported, which depends on whether 196// lose_context could happen. 197bool SupportsAccelerated2dCanvas() { 198 if (GpuDataManagerImpl::GetInstance()->GetGPUInfo().can_lose_context) 199 return false; 200 return true; 201} 202 203base::Value* GetFeatureStatus() { 204 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 205 GpuDataManagerImpl* manager = GpuDataManagerImpl::GetInstance(); 206 std::string gpu_access_blocked_reason; 207 bool gpu_access_blocked = 208 !manager->GpuAccessAllowed(&gpu_access_blocked_reason); 209 210 base::DictionaryValue* status = new base::DictionaryValue(); 211 212 const GpuFeatureInfo kGpuFeatureInfo[] = { 213 { 214 "2d_canvas", 215 manager->IsFeatureBlacklisted( 216 gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS), 217 command_line.HasSwitch(switches::kDisableAccelerated2dCanvas) || 218 !SupportsAccelerated2dCanvas(), 219 "Accelerated 2D canvas is unavailable: either disabled at the command" 220 " line or not supported by the current system.", 221 true 222 }, 223 { 224 "compositing", 225 manager->IsFeatureBlacklisted( 226 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING), 227 command_line.HasSwitch(switches::kDisableAcceleratedCompositing), 228 "Accelerated compositing has been disabled, either via about:flags or" 229 " command line. This adversely affects performance of all hardware" 230 " accelerated features.", 231 true 232 }, 233 { 234 "3d_css", 235 manager->IsFeatureBlacklisted( 236 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || 237 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS), 238 command_line.HasSwitch(switches::kDisableAcceleratedLayers), 239 "Accelerated layers have been disabled at the command line.", 240 false 241 }, 242 { 243 "css_animation", 244 manager->IsFeatureBlacklisted( 245 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING) || 246 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_3D_CSS), 247 command_line.HasSwitch(cc::switches::kDisableThreadedAnimation) || 248 command_line.HasSwitch(switches::kDisableAcceleratedCompositing) || 249 command_line.HasSwitch(switches::kDisableAcceleratedLayers), 250 "Accelerated CSS animation has been disabled at the command line.", 251 true 252 }, 253 { 254 "webgl", 255 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL), 256 command_line.HasSwitch(switches::kDisableExperimentalWebGL), 257 "WebGL has been disabled, either via about:flags or command line.", 258 false 259 }, 260 { 261 "multisampling", 262 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_MULTISAMPLING), 263 command_line.HasSwitch(switches::kDisableGLMultisampling), 264 "Multisampling has been disabled, either via about:flags or command" 265 " line.", 266 false 267 }, 268 { 269 "flash_3d", 270 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH3D), 271 command_line.HasSwitch(switches::kDisableFlash3d), 272 "Using 3d in flash has been disabled, either via about:flags or" 273 " command line.", 274 false 275 }, 276 { 277 "flash_stage3d", 278 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D), 279 command_line.HasSwitch(switches::kDisableFlashStage3d), 280 "Using Stage3d in Flash has been disabled, either via about:flags or" 281 " command line.", 282 false 283 }, 284 { 285 "flash_stage3d_baseline", 286 manager->IsFeatureBlacklisted( 287 gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D_BASELINE) || 288 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_FLASH_STAGE3D), 289 command_line.HasSwitch(switches::kDisableFlashStage3d), 290 "Using Stage3d Baseline profile in Flash has been disabled, either" 291 " via about:flags or command line.", 292 false 293 }, 294 { 295 "texture_sharing", 296 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_TEXTURE_SHARING), 297 command_line.HasSwitch(switches::kDisableImageTransportSurface), 298 "Sharing textures between processes has been disabled, either via" 299 " about:flags or command line.", 300 false 301 }, 302 { 303 "video_decode", 304 manager->IsFeatureBlacklisted( 305 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE), 306 command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode), 307 "Accelerated video decode has been disabled, either via about:flags" 308 " or command line.", 309 true 310 }, 311 { 312 "video", 313 manager->IsFeatureBlacklisted( 314 gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO), 315 command_line.HasSwitch(switches::kDisableAcceleratedVideo) || 316 command_line.HasSwitch(switches::kDisableAcceleratedCompositing), 317 "Accelerated video presentation has been disabled, either via" 318 " about:flags or command line.", 319 true 320 }, 321#if defined(OS_CHROMEOS) 322 { 323 "panel_fitting", 324 manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_PANEL_FITTING), 325 command_line.HasSwitch(switches::kDisablePanelFitting), 326 "Panel fitting has been disabled, either via about:flags or command" 327 " line.", 328 false 329 }, 330#endif 331 { 332 "force_compositing_mode", 333 manager->IsFeatureBlacklisted( 334 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE) && 335 !IsForceCompositingModeEnabled(), 336 !IsForceCompositingModeEnabled() && 337 !manager->IsFeatureBlacklisted( 338 gpu::GPU_FEATURE_TYPE_FORCE_COMPOSITING_MODE), 339 "Force compositing mode is off, either disabled at the command" 340 " line or not supported by the current system.", 341 false 342 }, 343 }; 344 const size_t kNumFeatures = sizeof(kGpuFeatureInfo) / sizeof(GpuFeatureInfo); 345 346 // Build the feature_status field. 347 { 348 base::ListValue* feature_status_list = new base::ListValue(); 349 350 for (size_t i = 0; i < kNumFeatures; ++i) { 351 // force_compositing_mode status is part of the compositing status. 352 if (kGpuFeatureInfo[i].name == "force_compositing_mode") 353 continue; 354 355 std::string status; 356 if (kGpuFeatureInfo[i].disabled) { 357 status = "disabled"; 358 if (kGpuFeatureInfo[i].name == "css_animation") { 359 status += "_software_animated"; 360 } else if (kGpuFeatureInfo[i].name == "raster") { 361 if (cc::switches::IsImplSidePaintingEnabled()) 362 status += "_software_multithreaded"; 363 else 364 status += "_software"; 365 } else { 366 if (kGpuFeatureInfo[i].fallback_to_software) 367 status += "_software"; 368 else 369 status += "_off"; 370 } 371 } else if (GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) { 372 status = "unavailable_software"; 373 } else if (kGpuFeatureInfo[i].blocked || 374 gpu_access_blocked) { 375 status = "unavailable"; 376 if (kGpuFeatureInfo[i].fallback_to_software) 377 status += "_software"; 378 else 379 status += "_off"; 380 } else { 381 status = "enabled"; 382 if (kGpuFeatureInfo[i].name == "webgl" && 383 (command_line.HasSwitch(switches::kDisableAcceleratedCompositing) || 384 manager->IsFeatureBlacklisted( 385 gpu::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING))) 386 status += "_readback"; 387 bool has_thread = IsThreadedCompositingEnabled(); 388 if (kGpuFeatureInfo[i].name == "compositing") { 389 bool force_compositing = IsForceCompositingModeEnabled(); 390 if (force_compositing) 391 status += "_force"; 392 if (has_thread) 393 status += "_threaded"; 394 } 395 if (kGpuFeatureInfo[i].name == "css_animation") { 396 if (has_thread) 397 status = "accelerated_threaded"; 398 else 399 status = "accelerated"; 400 } 401 } 402 // TODO(reveman): Remove this when crbug.com/223286 has been fixed. 403 if (kGpuFeatureInfo[i].name == "raster" && 404 cc::switches::IsImplSidePaintingEnabled()) { 405 status = "disabled_software_multithreaded"; 406 } 407 feature_status_list->Append( 408 NewStatusValue(kGpuFeatureInfo[i].name.c_str(), status.c_str())); 409 } 410 gpu::GpuSwitchingOption gpu_switching_option = 411 GpuDataManagerImpl::GetInstance()->GetGpuSwitchingOption(); 412 if (gpu_switching_option != gpu::GPU_SWITCHING_OPTION_UNKNOWN) { 413 std::string gpu_switching; 414 switch (gpu_switching_option) { 415 case gpu::GPU_SWITCHING_OPTION_AUTOMATIC: 416 gpu_switching = "gpu_switching_automatic"; 417 break; 418 case gpu::GPU_SWITCHING_OPTION_FORCE_DISCRETE: 419 gpu_switching = "gpu_switching_force_discrete"; 420 break; 421 case gpu::GPU_SWITCHING_OPTION_FORCE_INTEGRATED: 422 gpu_switching = "gpu_switching_force_integrated"; 423 break; 424 default: 425 break; 426 } 427 feature_status_list->Append( 428 NewStatusValue("gpu_switching", gpu_switching.c_str())); 429 } 430 status->Set("featureStatus", feature_status_list); 431 } 432 433 // Build the problems list. 434 { 435 base::ListValue* problem_list = new base::ListValue(); 436 GpuDataManagerImpl::GetInstance()->GetBlacklistReasons(problem_list); 437 438 if (gpu_access_blocked) { 439 base::DictionaryValue* problem = new base::DictionaryValue(); 440 problem->SetString("description", 441 "GPU process was unable to boot: " + gpu_access_blocked_reason); 442 problem->Set("crBugs", new base::ListValue()); 443 problem->Set("webkitBugs", new base::ListValue()); 444 problem_list->Insert(0, problem); 445 } 446 447 for (size_t i = 0; i < kNumFeatures; ++i) { 448 if (kGpuFeatureInfo[i].disabled) { 449 base::DictionaryValue* problem = new base::DictionaryValue(); 450 problem->SetString( 451 "description", kGpuFeatureInfo[i].disabled_description); 452 problem->Set("crBugs", new base::ListValue()); 453 problem->Set("webkitBugs", new base::ListValue()); 454 problem_list->Append(problem); 455 } 456 } 457 458 status->Set("problems", problem_list); 459 } 460 461 // Build driver bug workaround list. 462 { 463 base::ListValue* workaround_list = new base::ListValue(); 464 GpuDataManagerImpl::GetInstance()->GetDriverBugWorkarounds(workaround_list); 465 status->Set("workarounds", workaround_list); 466 } 467 468 return status; 469} 470 471// This class receives javascript messages from the renderer. 472// Note that the WebUI infrastructure runs on the UI thread, therefore all of 473// this class's methods are expected to run on the UI thread. 474class GpuMessageHandler 475 : public WebUIMessageHandler, 476 public base::SupportsWeakPtr<GpuMessageHandler>, 477 public GpuDataManagerObserver { 478 public: 479 GpuMessageHandler(); 480 virtual ~GpuMessageHandler(); 481 482 // WebUIMessageHandler implementation. 483 virtual void RegisterMessages() OVERRIDE; 484 485 // GpuDataManagerObserver implementation. 486 virtual void OnGpuInfoUpdate() OVERRIDE; 487 virtual void OnGpuSwitching() OVERRIDE; 488 489 // Messages 490 void OnBrowserBridgeInitialized(const base::ListValue* list); 491 void OnCallAsync(const base::ListValue* list); 492 493 // Submessages dispatched from OnCallAsync 494 base::Value* OnRequestClientInfo(const base::ListValue* list); 495 base::Value* OnRequestLogMessages(const base::ListValue* list); 496 497 private: 498 // True if observing the GpuDataManager (re-attaching as observer would 499 // DCHECK). 500 bool observing_; 501 502 DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler); 503}; 504 505//////////////////////////////////////////////////////////////////////////////// 506// 507// GpuMessageHandler 508// 509//////////////////////////////////////////////////////////////////////////////// 510 511GpuMessageHandler::GpuMessageHandler() 512 : observing_(false) { 513} 514 515GpuMessageHandler::~GpuMessageHandler() { 516 GpuDataManagerImpl::GetInstance()->RemoveObserver(this); 517} 518 519/* BrowserBridge.callAsync prepends a requestID to these messages. */ 520void GpuMessageHandler::RegisterMessages() { 521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 522 523 web_ui()->RegisterMessageCallback("browserBridgeInitialized", 524 base::Bind(&GpuMessageHandler::OnBrowserBridgeInitialized, 525 base::Unretained(this))); 526 web_ui()->RegisterMessageCallback("callAsync", 527 base::Bind(&GpuMessageHandler::OnCallAsync, 528 base::Unretained(this))); 529} 530 531void GpuMessageHandler::OnCallAsync(const base::ListValue* args) { 532 DCHECK_GE(args->GetSize(), static_cast<size_t>(2)); 533 // unpack args into requestId, submessage and submessageArgs 534 bool ok; 535 const base::Value* requestId; 536 ok = args->Get(0, &requestId); 537 DCHECK(ok); 538 539 std::string submessage; 540 ok = args->GetString(1, &submessage); 541 DCHECK(ok); 542 543 base::ListValue* submessageArgs = new base::ListValue(); 544 for (size_t i = 2; i < args->GetSize(); ++i) { 545 const base::Value* arg; 546 ok = args->Get(i, &arg); 547 DCHECK(ok); 548 549 base::Value* argCopy = arg->DeepCopy(); 550 submessageArgs->Append(argCopy); 551 } 552 553 // call the submessage handler 554 base::Value* ret = NULL; 555 if (submessage == "requestClientInfo") { 556 ret = OnRequestClientInfo(submessageArgs); 557 } else if (submessage == "requestLogMessages") { 558 ret = OnRequestLogMessages(submessageArgs); 559 } else { // unrecognized submessage 560 NOTREACHED(); 561 delete submessageArgs; 562 return; 563 } 564 delete submessageArgs; 565 566 // call BrowserBridge.onCallAsyncReply with result 567 if (ret) { 568 web_ui()->CallJavascriptFunction("browserBridge.onCallAsyncReply", 569 *requestId, 570 *ret); 571 delete ret; 572 } else { 573 web_ui()->CallJavascriptFunction("browserBridge.onCallAsyncReply", 574 *requestId); 575 } 576} 577 578void GpuMessageHandler::OnBrowserBridgeInitialized( 579 const base::ListValue* args) { 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 581 582 // Watch for changes in GPUInfo 583 if (!observing_) 584 GpuDataManagerImpl::GetInstance()->AddObserver(this); 585 observing_ = true; 586 587 // Tell GpuDataManager it should have full GpuInfo. If the 588 // Gpu process has not run yet, this will trigger its launch. 589 GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded(); 590 591 // Run callback immediately in case the info is ready and no update in the 592 // future. 593 OnGpuInfoUpdate(); 594} 595 596base::Value* GpuMessageHandler::OnRequestClientInfo( 597 const base::ListValue* list) { 598 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 599 600 base::DictionaryValue* dict = new base::DictionaryValue(); 601 602 dict->SetString("version", GetContentClient()->GetProduct()); 603 dict->SetString("command_line", 604 CommandLine::ForCurrentProcess()->GetCommandLineString()); 605 dict->SetString("operating_system", 606 base::SysInfo::OperatingSystemName() + " " + 607 base::SysInfo::OperatingSystemVersion()); 608 dict->SetString("angle_revision", base::UintToString(BUILD_REVISION)); 609 dict->SetString("graphics_backend", "Skia"); 610 dict->SetString("blacklist_version", 611 GpuDataManagerImpl::GetInstance()->GetBlacklistVersion()); 612 dict->SetString("driver_bug_list_version", 613 GpuDataManagerImpl::GetInstance()->GetDriverBugListVersion()); 614 615 return dict; 616} 617 618base::Value* GpuMessageHandler::OnRequestLogMessages(const base::ListValue*) { 619 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 620 621 return GpuDataManagerImpl::GetInstance()->GetLogMessages(); 622} 623 624void GpuMessageHandler::OnGpuInfoUpdate() { 625 // Get GPU Info. 626 scoped_ptr<base::DictionaryValue> gpu_info_val(GpuInfoAsDictionaryValue()); 627 628 // Add in blacklisting features 629 base::Value* feature_status = GetFeatureStatus(); 630 if (feature_status) 631 gpu_info_val->Set("featureStatus", feature_status); 632 633 // Send GPU Info to javascript. 634 web_ui()->CallJavascriptFunction("browserBridge.onGpuInfoUpdate", 635 *(gpu_info_val.get())); 636} 637 638void GpuMessageHandler::OnGpuSwitching() { 639 GpuDataManagerImpl::GetInstance()->RequestCompleteGpuInfoIfNeeded(); 640} 641 642} // namespace 643 644 645//////////////////////////////////////////////////////////////////////////////// 646// 647// GpuInternalsUI 648// 649//////////////////////////////////////////////////////////////////////////////// 650 651GpuInternalsUI::GpuInternalsUI(WebUI* web_ui) 652 : WebUIController(web_ui) { 653 web_ui->AddMessageHandler(new GpuMessageHandler()); 654 655 // Set up the chrome://gpu/ source. 656 BrowserContext* browser_context = 657 web_ui->GetWebContents()->GetBrowserContext(); 658 WebUIDataSource::Add(browser_context, CreateGpuHTMLSource()); 659} 660 661} // namespace content 662