Chromium Code Reviews| Index: chrome/browser/dom_ui/gpu_internals_ui.cc |
| =================================================================== |
| --- chrome/browser/dom_ui/gpu_internals_ui.cc (revision 0) |
| +++ chrome/browser/dom_ui/gpu_internals_ui.cc (revision 0) |
| @@ -0,0 +1,356 @@ |
| +// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/dom_ui/gpu_internals_ui.h" |
| + |
| +#include <algorithm> |
| +#include <string> |
| +#include <utility> |
| +#include <vector> |
| + |
| +#include "app/l10n_util.h" |
| +#include "app/resource_bundle.h" |
| +#include "base/command_line.h" |
| +#include "base/file_util.h" |
| +#include "base/message_loop.h" |
| +#include "base/path_service.h" |
| +#include "base/singleton.h" |
| +#include "base/string_number_conversions.h" |
| +#include "base/string_piece.h" |
| +#include "base/utf_string_conversions.h" |
| +#include "base/values.h" |
| +#include "chrome/browser/browser_process.h" |
| +#include "chrome/browser/browser_thread.h" |
| +#include "chrome/browser/dom_ui/chrome_url_data_manager.h" |
| +#include "chrome/browser/gpu_process_host.h" |
| +#include "chrome/browser/gpu_process_host_ui_shim.h" |
| +#include "chrome/browser/io_thread.h" |
| +#include "chrome/browser/net/chrome_net_log.h" |
| +#include "chrome/browser/net/connection_tester.h" |
| +#include "chrome/browser/net/passive_log_collector.h" |
| +#include "chrome/browser/net/url_fixer_upper.h" |
| +#include "chrome/browser/platform_util.h" |
| +#include "chrome/common/chrome_paths.h" |
| +#include "chrome/common/chrome_version_info.h" |
| +#include "chrome/common/jstemplate_builder.h" |
| +#include "chrome/common/net/url_request_context_getter.h" |
| +#include "chrome/common/url_constants.h" |
| +#include "grit/browser_resources.h" |
| +#include "grit/generated_resources.h" |
| +#include "net/base/escape.h" |
| + |
| + |
| +namespace { |
| + |
| +class GpuHTMLSource : public ChromeURLDataManager::DataSource { |
| + public: |
| + GpuHTMLSource(); |
| + |
| + // Called when the network layer has requested a resource underneath |
| + // the path we registered. |
| + virtual void StartDataRequest(const std::string& path, |
| + bool is_off_the_record, |
| + int request_id); |
| + virtual std::string GetMimeType(const std::string&) const; |
| + |
| + private: |
| + ~GpuHTMLSource() {} |
| + DISALLOW_COPY_AND_ASSIGN(GpuHTMLSource); |
| +}; |
| + |
| +// This class receives javascript messages from the renderer. |
| +// Note that the DOMUI infrastructure runs on the UI thread, therefore all of |
| +// this class's methods are expected to run on the UI thread. |
| +// |
| +// Since the network code we want to run lives on the IO thread, we proxy |
| +// everything over to GpuMessageHandler::IOThreadImpl, which runs |
| +// on the IO thread. |
| +// |
| +// TODO(eroman): Can we start on the IO thread to begin with? |
|
eroman
2010/12/09 02:46:45
Looks like you copied this comment block from net_
nduca
2010/12/09 17:24:54
Done.
|
| +class GpuMessageHandler |
| + : public DOMMessageHandler, |
| + public base::SupportsWeakPtr<GpuMessageHandler> { |
| + public: |
| + GpuMessageHandler(); |
| + virtual ~GpuMessageHandler(); |
| + |
| + // DOMMessageHandler implementation. |
| + virtual DOMMessageHandler* Attach(DOMUI* dom_ui); |
| + virtual void RegisterMessages(); |
| + |
| + // Mesages |
| + void OnCallAsync(const ListValue* list); |
| + |
| + // Submessages dispatched from OnCallAsync |
| + Value* OnRequestGpuInfo(const ListValue* list); |
| + Value* OnRequestClientInfo(const ListValue* list); |
| + |
| + // Executes the javascript function |function_name| in the renderer, passing |
| + // it the argument |value|. |
| + void CallJavascriptFunction(const std::wstring& function_name, |
| + const Value* value); |
| + |
| + private: |
| + DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler); |
| +}; |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// |
| +// GpuHTMLSource |
| +// |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| +GpuHTMLSource::GpuHTMLSource() |
| + : DataSource(chrome::kChromeUIGpuInternalsHost, MessageLoop::current()) { |
| +} |
| + |
| +void GpuHTMLSource::StartDataRequest(const std::string& path, |
| + bool is_off_the_record, |
|
eroman
2010/12/09 02:46:45
indentation.
nduca
2010/12/09 17:24:54
Done.
|
| + int request_id) { |
| + DictionaryValue localized_strings; |
| + SetFontAndTextDirection(&localized_strings); |
| + |
| + static const base::StringPiece gpu_html( |
|
eroman
2010/12/09 02:46:45
Why static?
Seems incorrect to save a StringPiece
nduca
2010/12/09 17:24:54
This is copied from options_ui.cc, which does this
|
| + ResourceBundle::GetSharedInstance().GetRawDataResource( |
| + IDR_GPU_INTERNALS_HTML)); |
| + std::string full_html(gpu_html.data(), gpu_html.size()); |
| + jstemplate_builder::AppendJsonHtml(&localized_strings, &full_html); |
| + jstemplate_builder::AppendI18nTemplateSourceHtml(&full_html); |
| + jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html); |
| + jstemplate_builder::AppendJsTemplateSourceHtml(&full_html); |
| + |
| + |
| + scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); |
| + html_bytes->data.resize(full_html.size()); |
| + std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); |
| + |
| + SendResponse(request_id, html_bytes); |
| +} |
| + |
| +std::string GpuHTMLSource::GetMimeType(const std::string&) const { |
| + return "text/html"; |
| +} |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// |
| +// GpuMessageHandler |
| +// |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| +GpuMessageHandler::GpuMessageHandler() { |
| +} |
| + |
| +GpuMessageHandler::~GpuMessageHandler() {} |
| + |
| +DOMMessageHandler* GpuMessageHandler::Attach(DOMUI* dom_ui) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui); |
| + return result; |
| +} |
| + |
| +/* BrowserBridge.callAsync prepends a requestID to these messages. */ |
| +void GpuMessageHandler::RegisterMessages() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + dom_ui_->RegisterMessageCallback( |
| + "callAsync", |
| + NewCallback(this, &GpuMessageHandler::OnCallAsync)); |
| +} |
| + |
| +void GpuMessageHandler::OnCallAsync(const ListValue* args) { |
| + DCHECK_GE(args->GetSize(), static_cast<size_t>(2)); |
| + // unpack args into requestId, submessage and submessageArgs |
| + bool ok; |
| + Value* requestId; |
| + ok = args->Get(0, &requestId); |
| + DCHECK(ok); |
| + |
| + std::string submessage; |
| + ok = args->GetString(1, &submessage); |
| + DCHECK(ok); |
| + |
| + ListValue* submessageArgs = new ListValue(); |
| + for (size_t i = 2; i < args->GetSize(); ++i) { |
| + Value* arg; |
| + ok = args->Get(i, &arg); |
| + DCHECK(ok); |
| + |
| + Value* argCopy = arg->DeepCopy(); |
| + submessageArgs->Append(argCopy); |
| + } |
| + |
| + // call the submessage handler |
| + Value* ret = NULL; |
| + if (submessage == "requestGpuInfo") { |
| + ret = OnRequestGpuInfo(submessageArgs); |
| + } else if (submessage == "requestClientInfo") { |
| + ret = OnRequestClientInfo(submessageArgs); |
| + } else { // unrecognized submessage |
| + NOTREACHED(); |
| + delete submessageArgs; |
| + return; |
| + } |
| + delete submessageArgs; |
| + |
| + // call BrowserBridge.onCallAsyncReply with result |
| + if (ret) { |
| + dom_ui_->CallJavascriptFunction(L"browserBridge.onCallAsyncReply", |
| + *requestId, |
| + *ret); |
| + delete ret; |
| + } else { |
| + dom_ui_->CallJavascriptFunction(L"browserBridge.onCallAsyncReply", |
| + *requestId); |
| + } |
| +} |
| + |
| +Value* GpuMessageHandler::OnRequestClientInfo(const ListValue* list) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + DictionaryValue* dict = new DictionaryValue(); |
| + |
| + chrome::VersionInfo version_info; |
| + |
| + if (!version_info.is_valid()) { |
| + DLOG(ERROR) << "Unable to create chrome::VersionInfo"; |
| + } else { |
| + // We have everything we need to send the right values. |
| + dict->SetString("version", version_info.Version()); |
| + dict->SetString("cl", version_info.LastChange()); |
| + dict->SetString("version_mod", |
| + platform_util::GetVersionStringModifier()); |
| + dict->SetString("official", |
| + l10n_util::GetStringUTF16( |
| + version_info.IsOfficialBuild() ? |
| + IDS_ABOUT_VERSION_OFFICIAL |
| + : IDS_ABOUT_VERSION_UNOFFICIAL)); |
| + |
| + dict->SetString("command_line", |
| + CommandLine::ForCurrentProcess()->command_line_string()); |
| + } |
| + |
| + return dict; |
| +} |
| + |
| +DictionaryValue* NewDescriptionValuePair(const std::string& desc, |
| + const std::string& value) { |
| + DictionaryValue* dict = new DictionaryValue(); |
| + dict->SetString("description", EscapeForHTML(desc)); |
| + dict->SetString("value", EscapeForHTML(value)); |
| + return dict; |
| +} |
| + |
| +DictionaryValue* NewDescriptionValuePair(const std::string& desc, |
| + Value* value) { |
| + DictionaryValue* dict = new DictionaryValue(); |
| + dict->SetString("description", EscapeForHTML(desc)); |
| + dict->Set("value", value); |
| + return dict; |
| +} |
| + |
| +#if defined(OS_WIN) |
| +// Output DxDiagNode tree as nested array of {description,value} pairs |
| +ListValue* DxDiagNodeToList(const DxDiagNode& node) { |
| + ListValue* list = new ListValue(); |
| + for (std::map<std::string, std::string>::const_iterator it = |
| + node.values.begin(); |
| + it != node.values.end(); |
| + ++it) { |
| + list->Append(NewDescriptionValuePair(it->first, it->second)); |
| + } |
| + |
| + for (std::map<std::string, DxDiagNode>::const_iterator it = |
| + node.children.begin(); |
| + it != node.children.end(); |
| + ++it) { |
| + ListValue* sublist = DxDiagNodeToList(it->second); |
| + list->Append(NewDescriptionValuePair(it->first, sublist)); |
| + } |
| + return list; |
| +} |
| + |
| +#endif // OS_WIN |
| + |
| +std::string VersionNumberToString(uint32 value) { |
| + int hi = (value >> 8) & 0xff; |
| + int low = value & 0xff; |
| + return base::IntToString(hi) + "." + base::IntToString(low); |
| +} |
| + |
| +DictionaryValue* GpuInfoToDict(const GPUInfo& gpu_info) { |
| + ListValue* basic_info = new ListValue(); |
| + basic_info->Append(NewDescriptionValuePair("Initialization time", |
| + base::Int64ToString(gpu_info.initialization_time().InMilliseconds()))); |
| + basic_info->Append(NewDescriptionValuePair("Vendor Id", |
| + base::StringPrintf("0x%04x", gpu_info.vendor_id()))); |
| + basic_info->Append(NewDescriptionValuePair("Device Id", |
| + base::StringPrintf("0x%04x", gpu_info.device_id()))); |
| + basic_info->Append(NewDescriptionValuePair("Driver version", |
| + WideToASCII(gpu_info.driver_version()).c_str())); |
| + basic_info->Append(NewDescriptionValuePair("Pixel shader version", |
| + VersionNumberToString(gpu_info.pixel_shader_version()))); |
| + basic_info->Append(NewDescriptionValuePair("Vertex shader version", |
| + VersionNumberToString(gpu_info.vertex_shader_version()))); |
| + basic_info->Append(NewDescriptionValuePair("GL version", |
| + VersionNumberToString(gpu_info.gl_version()))); |
| + |
| + DictionaryValue* info = new DictionaryValue(); |
| + info->Set("basic_info", basic_info); |
| + |
| + if (gpu_info.progress() == GPUInfo::kPartial) { |
| + info->SetString("progress", "partial"); |
| + } else { |
| + info->SetString("progress", "complete"); |
| + } |
| +#if defined(OS_WIN) |
| + if (gpu_info.progress() == GPUInfo::kComplete) { |
| + ListValue* dx_info = DxDiagNodeToList(gpu_info.dx_diagnostics()); |
| + info->Set("diagnostics", dx_info); |
| + } |
| +#endif |
| + |
| + return info; |
| +} |
| + |
| +Value* GpuMessageHandler::OnRequestGpuInfo(const ListValue* list) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + |
| + // Get GPU Info. |
| + GPUInfo gpu_info = GpuProcessHostUIShim::Get()->gpu_info(); |
| + |
| + std::string html; |
| + if (gpu_info.progress() != GPUInfo::kComplete) { |
| + GpuProcessHostUIShim::Get()->CollectGraphicsInfoAsynchronously(); |
| + } |
| + |
| + if (gpu_info.progress() != GPUInfo::kUninitialized) { |
| + return GpuInfoToDict(gpu_info); |
| + } else { |
| + return NULL; |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| + |
| +//////////////////////////////////////////////////////////////////////////////// |
| +// |
| +// GpuUI |
| +// |
| +//////////////////////////////////////////////////////////////////////////////// |
| + |
| +GpuUI::GpuUI(TabContents* contents) : DOMUI(contents) { |
| + AddMessageHandler((new GpuMessageHandler())->Attach(this)); |
| + |
| + GpuHTMLSource* html_source = new GpuHTMLSource(); |
| + |
| + // Set up the chrome://gpu/ source. |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + NewRunnableMethod( |
| + Singleton<ChromeURLDataManager>::get(), |
| + &ChromeURLDataManager::AddDataSource, |
| + make_scoped_refptr(html_source))); |
| +} |
| + |
| Property changes on: chrome/browser/dom_ui/gpu_internals_ui.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |