|
OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2010 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/dom_ui/gpu_internals_ui.h" | |
6 | |
7 #include <algorithm> | |
8 #include <string> | |
9 #include <utility> | |
10 #include <vector> | |
11 | |
12 #include "app/l10n_util.h" | |
13 #include "app/resource_bundle.h" | |
14 #include "base/command_line.h" | |
15 #include "base/file_util.h" | |
16 #include "base/message_loop.h" | |
17 #include "base/path_service.h" | |
18 #include "base/singleton.h" | |
19 #include "base/string_number_conversions.h" | |
20 #include "base/string_piece.h" | |
21 #include "base/utf_string_conversions.h" | |
22 #include "base/values.h" | |
23 #include "chrome/browser/browser_process.h" | |
24 #include "chrome/browser/browser_thread.h" | |
25 #include "chrome/browser/dom_ui/chrome_url_data_manager.h" | |
26 #include "chrome/browser/gpu_process_host.h" | |
27 #include "chrome/browser/gpu_process_host_ui_shim.h" | |
28 #include "chrome/browser/io_thread.h" | |
29 #include "chrome/browser/net/chrome_net_log.h" | |
30 #include "chrome/browser/net/connection_tester.h" | |
31 #include "chrome/browser/net/passive_log_collector.h" | |
32 #include "chrome/browser/net/url_fixer_upper.h" | |
33 #include "chrome/browser/platform_util.h" | |
34 #include "chrome/browser/profile.h" | |
35 #include "chrome/common/chrome_paths.h" | |
36 #include "chrome/common/chrome_version_info.h" | |
37 #include "chrome/common/jstemplate_builder.h" | |
38 #include "chrome/common/net/url_request_context_getter.h" | |
39 #include "chrome/common/url_constants.h" | |
40 #include "grit/browser_resources.h" | |
41 #include "grit/generated_resources.h" | |
42 #include "net/base/escape.h" | |
43 | |
44 | |
45 namespace { | |
46 | |
47 class GpuHTMLSource : public ChromeURLDataManager::DataSource { | |
arv (Not doing code reviews)
2010/12/06 19:45:57
Should this be named GPUHTMLSource? It looks very
nduca
2010/12/07 01:03:40
I hear you. This is based on the rest of the Chrom
| |
48 public: | |
49 GpuHTMLSource(); | |
50 | |
51 // Called when the network layer has requested a resource underneath | |
52 // the path we registered. | |
53 virtual void StartDataRequest(const std::string& path, | |
54 bool is_off_the_record, | |
55 int request_id); | |
56 virtual std::string GetMimeType(const std::string&) const; | |
57 | |
58 private: | |
59 ~GpuHTMLSource() {} | |
60 DISALLOW_COPY_AND_ASSIGN(GpuHTMLSource); | |
61 }; | |
62 | |
63 // This class receives javascript messages from the renderer. | |
64 // Note that the DOMUI infrastructure runs on the UI thread, therefore all of | |
65 // this class's methods are expected to run on the UI thread. | |
66 // | |
67 // Since the network code we want to run lives on the IO thread, we proxy | |
68 // everything over to GpuMessageHandler::IOThreadImpl, which runs | |
69 // on the IO thread. | |
70 // | |
71 // TODO(eroman): Can we start on the IO thread to begin with? | |
72 class GpuMessageHandler | |
73 : public DOMMessageHandler, | |
74 public base::SupportsWeakPtr<GpuMessageHandler> { | |
75 public: | |
76 GpuMessageHandler(); | |
77 virtual ~GpuMessageHandler(); | |
78 | |
79 // DOMMessageHandler implementation. | |
80 virtual DOMMessageHandler* Attach(DOMUI* dom_ui); | |
81 virtual void RegisterMessages(); | |
82 | |
83 // Mesages | |
84 void OnCallAsync(const ListValue* list); | |
85 | |
86 // Submessages dispatched from OnCallAsync | |
87 Value* OnRequestGpuInfo(const ListValue* list); | |
88 Value* OnRequestClientInfo(const ListValue* list); | |
89 | |
90 // Executes the javascript function |function_name| in the renderer, passing | |
91 // it the argument |value|. | |
92 void CallJavascriptFunction(const std::wstring& function_name, | |
93 const Value* value); | |
94 | |
95 private: | |
96 bool collecting_graphics_info_; | |
97 DISALLOW_COPY_AND_ASSIGN(GpuMessageHandler); | |
98 }; | |
99 | |
100 //////////////////////////////////////////////////////////////////////////////// | |
101 // | |
102 // GpuHTMLSource | |
103 // | |
104 //////////////////////////////////////////////////////////////////////////////// | |
105 | |
106 GpuHTMLSource::GpuHTMLSource() | |
107 : DataSource(chrome::kChromeUIGpuInternalsHost, MessageLoop::current()) { | |
108 } | |
109 | |
110 void GpuHTMLSource::StartDataRequest(const std::string& path, | |
111 bool is_off_the_record, | |
112 int request_id) { | |
113 DictionaryValue* localized_strings = new DictionaryValue(); | |
114 SetFontAndTextDirection(localized_strings); | |
115 | |
116 static const base::StringPiece options_html( | |
117 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
118 IDR_GPU_INTERNALS_HTML)); | |
119 const std::string full_html = jstemplate_builder::GetI18nTemplateHtml( | |
120 options_html, localized_strings); | |
121 | |
122 scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); | |
123 html_bytes->data.resize(full_html.size()); | |
124 std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin()); | |
125 | |
126 SendResponse(request_id, html_bytes); | |
127 } | |
128 | |
129 std::string GpuHTMLSource::GetMimeType(const std::string&) const { | |
130 return "text/html"; | |
131 } | |
132 | |
133 //////////////////////////////////////////////////////////////////////////////// | |
134 // | |
135 // GpuMessageHandler | |
136 // | |
137 //////////////////////////////////////////////////////////////////////////////// | |
138 | |
139 GpuMessageHandler::GpuMessageHandler() | |
140 : collecting_graphics_info_(false) { | |
141 } | |
142 | |
143 GpuMessageHandler::~GpuMessageHandler() {} | |
144 | |
145 DOMMessageHandler* GpuMessageHandler::Attach(DOMUI* dom_ui) { | |
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
147 DOMMessageHandler* result = DOMMessageHandler::Attach(dom_ui); | |
148 return result; | |
149 } | |
150 | |
151 /* BrowserBridge.callAsync prepends a requestID to these messages. */ | |
152 void GpuMessageHandler::RegisterMessages() { | |
153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
154 | |
155 dom_ui_->RegisterMessageCallback( | |
156 "callAsync", | |
157 NewCallback(this, &GpuMessageHandler::OnCallAsync)); | |
158 } | |
159 | |
160 void GpuMessageHandler::OnCallAsync(const ListValue* args) { | |
161 DCHECK(args->GetSize() >= 2); | |
162 // unpack args into requestId, submessage and submessageArgs | |
163 bool ok; | |
164 Value* requestId; | |
165 ok = args->Get(0, &requestId); | |
166 DCHECK(ok); | |
167 | |
168 std::string submessage; | |
169 ok = args->GetString(1, &submessage); | |
170 DCHECK(ok); | |
171 | |
172 ListValue* submessageArgs = new ListValue(); | |
173 for (size_t i = 2; i < args->GetSize(); ++i) { | |
174 Value* arg; | |
175 ok = args->Get(i, &arg); | |
176 DCHECK(ok); | |
177 | |
178 Value* argCopy = arg->DeepCopy(); | |
179 submessageArgs->Append(argCopy); | |
180 } | |
181 | |
182 // call the submessage handler | |
183 Value* ret = NULL; | |
184 if (submessage == "requestGpuInfo") { | |
arv (Not doing code reviews)
2010/12/06 19:45:57
I find this strange. DOMUI RegisterMessageCallback
nduca
2010/12/07 01:03:40
I'm fine doing that, but question though first.
I
arv (Not doing code reviews)
2010/12/08 17:55:19
One option would be to extend chrome.send to take
| |
185 ret = OnRequestGpuInfo(submessageArgs); | |
186 } else if (submessage == "requestClientInfo") { | |
187 ret = OnRequestClientInfo(submessageArgs); | |
188 } else { // unrecognized submessage | |
189 NOTREACHED(); | |
190 delete submessageArgs; | |
191 return; | |
192 } | |
193 delete submessageArgs; | |
194 | |
195 // call BrowserBridge.onCallAsyncReply with result | |
196 if (ret) { | |
197 dom_ui_->CallJavascriptFunction(L"browser.onCallAsyncReply", | |
arv (Not doing code reviews)
2010/12/06 19:45:57
Same goes for calling into js
| |
198 *requestId, | |
199 *ret); | |
200 delete ret; | |
201 } else { | |
202 dom_ui_->CallJavascriptFunction(L"browser.onCallAsyncReply", | |
203 *requestId); | |
204 } | |
205 } | |
206 | |
207 Value* GpuMessageHandler::OnRequestClientInfo(const ListValue* list) { | |
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
209 | |
210 DictionaryValue* dict = new DictionaryValue(); | |
arv (Not doing code reviews)
2010/12/06 19:45:57
Who is deleting this?
nduca
2010/12/07 01:03:40
OnCallAsync, line 200, "delete ret" after we've se
| |
211 | |
212 chrome::VersionInfo version_info; | |
213 | |
214 if (!version_info.is_valid()) { | |
215 DLOG(ERROR) << "Unable to create chrome::VersionInfo"; | |
216 } else { | |
217 // We have everything we need to send the right values. | |
218 dict->SetString("version", version_info.Version()); | |
219 dict->SetString("cl", version_info.LastChange()); | |
220 dict->SetString("version_mod", | |
221 platform_util::GetVersionStringModifier()); | |
222 dict->SetString("official", | |
223 l10n_util::GetStringUTF16( | |
224 version_info.IsOfficialBuild() ? | |
225 IDS_ABOUT_VERSION_OFFICIAL | |
226 : IDS_ABOUT_VERSION_UNOFFICIAL)); | |
227 | |
228 dict->SetString("command_line", | |
229 CommandLine::ForCurrentProcess()->command_line_string()); | |
230 } | |
231 | |
232 return dict; | |
233 } | |
234 | |
235 | |
236 #if defined(OS_WIN) | |
237 // Output DxDiagNode tree as HTML tables and nested HTML unordered list | |
238 // elements. | |
239 DictionaryValue* DxDiagNodeToDict(const DxDiagNode& node) { | |
240 DictionaryValue* dict = new DictionaryValue(); | |
arv (Not doing code reviews)
2010/12/06 19:45:57
Who is deleting this?
nduca
2010/12/07 01:03:40
Caller.
On 2010/12/06 19:45:57, arv wrote:
| |
241 for (std::map<std::string, std::string>::const_iterator it = | |
242 node.values.begin(); | |
243 it != node.values.end(); | |
244 ++it) { | |
245 dict->SetString(EscapeForHTML(it->first), EscapeForHTML(it->second)); | |
246 } | |
247 | |
248 for (std::map<std::string, DxDiagNode>::const_iterator it = | |
249 node.children.begin(); | |
250 it != node.children.end(); | |
251 ++it) { | |
252 DictionaryValue* subdict = DxDiagNodeToDict(it->second); | |
253 dict->Set(EscapeForHTML(it->first), subdict); | |
254 } | |
255 return dict; | |
256 } | |
257 | |
258 #endif // OS_WIN | |
259 | |
260 std::string VersionNumberToString(uint32 value) { | |
261 int hi = (value >> 8) & 0xff; | |
262 int low = value & 0xff; | |
263 return base::IntToString(hi) + "." + base::IntToString(low); | |
264 } | |
265 | |
266 DictionaryValue* GpuInfoToDict(const GPUInfo& gpu_info) { | |
267 DictionaryValue* info = new DictionaryValue(); | |
arv (Not doing code reviews)
2010/12/06 19:45:57
Who is deleting this?
nduca
2010/12/07 01:03:40
Caller.
On 2010/12/06 19:45:57, arv wrote:
| |
268 info->SetString("Initialization time", | |
269 base::Int64ToString(gpu_info.initialization_time().InMilliseconds())); | |
270 info->SetString("Vendor Id", | |
271 base::StringPrintf("0x%04x", gpu_info.vendor_id())); | |
272 info->SetString("Device Id", | |
273 base::StringPrintf("0x%04x", gpu_info.device_id())); | |
274 info->SetString("Driver version", | |
275 WideToASCII(gpu_info.driver_version()).c_str()); | |
276 info->SetString("Pixel shader version", | |
277 VersionNumberToString(gpu_info.pixel_shader_version())); | |
278 info->SetString("Vertex shader version", | |
279 VersionNumberToString(gpu_info.vertex_shader_version())); | |
280 info->SetString("GL version", VersionNumberToString(gpu_info.gl_version())); | |
281 | |
282 DictionaryValue* dict = new DictionaryValue(); | |
283 dict->Set("Basic GPU Information", info); | |
284 | |
285 #if defined(OS_WIN) | |
286 DictionaryValue* dx_info = DxDiagNodeToDict(gpu_info.dx_diagnostics()); | |
287 dict->Set("DirectX diagnostics", dx_info); | |
288 #endif | |
289 | |
290 return dict; | |
291 } | |
292 | |
293 Value* GpuMessageHandler::OnRequestGpuInfo(const ListValue* list) { | |
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
295 | |
296 // Get GPU Info. | |
297 GPUInfo gpu_info = GpuProcessHostUIShim::Get()->gpu_info(); | |
298 | |
299 std::string html; | |
300 if (gpu_info.progress() != GPUInfo::kComplete) { | |
301 if (!collecting_graphics_info_) { | |
302 GpuProcessHostUIShim::Get()->CollectGraphicsInfoAsynchronously(); | |
303 collecting_graphics_info_ = true; | |
304 } | |
305 return NULL; | |
306 } else { | |
307 collecting_graphics_info_ = false; | |
308 | |
309 return GpuInfoToDict(gpu_info); | |
310 } | |
311 } | |
312 | |
313 } // namespace | |
314 | |
315 | |
316 //////////////////////////////////////////////////////////////////////////////// | |
317 // | |
318 // GpuUI | |
319 // | |
320 //////////////////////////////////////////////////////////////////////////////// | |
321 | |
322 GpuUI::GpuUI(TabContents* contents) : DOMUI(contents) { | |
323 AddMessageHandler((new GpuMessageHandler())->Attach(this)); | |
324 | |
325 GpuHTMLSource* html_source = new GpuHTMLSource(); | |
326 | |
327 // Set up the chrome://gpu/ source. | |
328 BrowserThread::PostTask( | |
329 BrowserThread::IO, FROM_HERE, | |
330 NewRunnableMethod( | |
331 Singleton<ChromeURLDataManager>::get(), | |
332 &ChromeURLDataManager::AddDataSource, | |
333 make_scoped_refptr(html_source))); | |
334 } | |
335 | |
OLD | NEW |