OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/browser_about_handler.h" | 5 #include "chrome/browser/browser_about_handler.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <string> | 7 #include <string> |
9 #include <vector> | |
10 | 8 |
11 #include "base/bind.h" | 9 #include "base/logging.h" |
12 #include "base/bind_helpers.h" | |
13 #include "base/callback.h" | |
14 #include "base/command_line.h" | |
15 #include "base/file_util.h" | |
16 #include "base/i18n/number_formatting.h" | |
17 #include "base/json/json_writer.h" | |
18 #include "base/memory/singleton.h" | 10 #include "base/memory/singleton.h" |
19 #include "base/metrics/histogram.h" | |
20 #include "base/metrics/stats_table.h" | |
21 #include "base/path_service.h" | |
22 #include "base/string_number_conversions.h" | |
23 #include "base/string_piece.h" | |
24 #include "base/string_util.h" | 11 #include "base/string_util.h" |
25 #include "base/stringprintf.h" | |
26 #include "base/threading/thread.h" | |
27 #include "base/utf_string_conversions.h" | |
28 #include "base/values.h" | |
29 #include "chrome/browser/about_flags.h" | |
30 #include "chrome/browser/browser_process.h" | |
31 #include "chrome/browser/defaults.h" | |
32 #include "chrome/browser/memory_details.h" | |
33 #include "chrome/browser/metrics/histogram_synchronizer.h" | |
34 #include "chrome/browser/net/predictor.h" | |
35 #include "chrome/browser/net/url_fixer_upper.h" | 12 #include "chrome/browser/net/url_fixer_upper.h" |
36 #include "chrome/browser/plugin_prefs.h" | |
37 #include "chrome/browser/profiles/profile.h" | |
38 #include "chrome/browser/profiles/profile_manager.h" | |
39 #include "chrome/browser/ui/browser_dialogs.h" | 13 #include "chrome/browser/ui/browser_dialogs.h" |
40 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" | |
41 #include "chrome/common/about_handler.h" | 14 #include "chrome/common/about_handler.h" |
42 #include "chrome/common/chrome_paths.h" | |
43 #include "chrome/common/chrome_version_info.h" | |
44 #include "chrome/common/jstemplate_builder.h" | |
45 #include "chrome/common/net/gaia/google_service_auth_error.h" | |
46 #include "chrome/common/render_messages.h" | |
47 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
48 #include "content/browser/gpu/gpu_process_host_ui_shim.h" | 16 #include "content/browser/gpu/gpu_process_host_ui_shim.h" |
49 #include "content/browser/plugin_service.h" | |
50 #include "content/browser/renderer_host/render_view_host.h" | |
51 #include "content/browser/sensors/sensors_provider.h" | 17 #include "content/browser/sensors/sensors_provider.h" |
52 #include "content/public/browser/browser_thread.h" | |
53 #include "content/public/browser/render_process_host.h" | |
54 #include "content/public/common/content_client.h" | |
55 #include "crypto/nss_util.h" | |
56 #include "googleurl/src/gurl.h" | |
57 #include "grit/browser_resources.h" | |
58 #include "grit/chromium_strings.h" | |
59 #include "grit/generated_resources.h" | |
60 #include "grit/locale_settings.h" | |
61 #include "net/base/escape.h" | |
62 #include "net/base/net_util.h" | |
63 #include "ui/base/l10n/l10n_util.h" | |
64 #include "ui/base/resource/resource_bundle.h" | |
65 #include "v8/include/v8.h" | |
66 #include "webkit/glue/user_agent.h" | |
67 #include "webkit/glue/webkit_glue.h" | |
68 #include "webkit/plugins/webplugininfo.h" | |
69 | |
70 #if defined(OS_WIN) | |
71 #include "chrome/browser/enumerate_modules_model_win.h" | |
72 #elif defined(OS_CHROMEOS) | |
73 #include "chrome/browser/chromeos/cros/cros_library.h" | |
74 #include "chrome/browser/chromeos/cros/cryptohome_library.h" | |
75 #include "chrome/browser/chromeos/cros/network_library.h" | |
76 #include "chrome/browser/chromeos/customization_document.h" | |
77 #include "chrome/browser/chromeos/login/wizard_controller.h" | |
78 #include "chrome/browser/chromeos/version_loader.h" | |
79 #include "chrome/browser/oom_priority_manager.h" | |
80 #include "content/browser/zygote_host_linux.h" | |
81 #elif defined(OS_LINUX) || defined(OS_OPENBSD) | |
82 #include "content/browser/zygote_host_linux.h" | |
83 #endif | |
84 | 18 |
85 #if defined(USE_TCMALLOC) | 19 #if defined(USE_TCMALLOC) |
86 #include "third_party/tcmalloc/chromium/src/google/malloc_extension.h" | 20 #include "third_party/tcmalloc/chromium/src/google/malloc_extension.h" |
87 #endif | 21 #endif |
88 | 22 |
89 using base::Time; | |
90 using base::TimeDelta; | |
91 using content::BrowserThread; | |
92 | |
93 #if defined(USE_TCMALLOC) | |
94 // static | |
95 AboutTcmallocOutputs* AboutTcmallocOutputs::GetInstance() { | |
96 return Singleton<AboutTcmallocOutputs>::get(); | |
97 } | |
98 | |
99 AboutTcmallocOutputs::AboutTcmallocOutputs() {} | |
100 | |
101 AboutTcmallocOutputs::~AboutTcmallocOutputs() {} | |
102 | |
103 // Glue between the callback task and the method in the singleton. | |
104 void AboutTcmallocRendererCallback(base::ProcessId pid, | |
105 const std::string& output) { | |
106 AboutTcmallocOutputs::GetInstance()->RendererCallback(pid, output); | |
107 } | |
108 #endif | |
109 | |
110 namespace { | 23 namespace { |
111 | 24 |
112 // Add paths here to be included in chrome://chrome-urls (about:about). | 25 // Add paths here to be included in chrome://chrome-urls (about:about). |
113 // These paths will also be suggested by BuiltinProvider. | 26 // These paths will also be suggested by BuiltinProvider. |
114 const char* const kChromePaths[] = { | 27 const char* const kChromePaths[] = { |
115 chrome::kChromeUIAppCacheInternalsHost, | 28 chrome::kChromeUIAppCacheInternalsHost, |
116 chrome::kChromeUIBlobInternalsHost, | 29 chrome::kChromeUIBlobInternalsHost, |
117 chrome::kChromeUIBookmarksHost, | 30 chrome::kChromeUIBookmarksHost, |
118 chrome::kChromeUICacheHost, | 31 chrome::kChromeUICacheHost, |
119 chrome::kChromeUIChromeURLsHost, | 32 chrome::kChromeUIChromeURLsHost, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 chrome::kChromeUIKeyboardOverlayHost, | 76 chrome::kChromeUIKeyboardOverlayHost, |
164 chrome::kChromeUILoginHost, | 77 chrome::kChromeUILoginHost, |
165 chrome::kChromeUINetworkHost, | 78 chrome::kChromeUINetworkHost, |
166 chrome::kChromeUIOobeHost, | 79 chrome::kChromeUIOobeHost, |
167 chrome::kChromeUIOSCreditsHost, | 80 chrome::kChromeUIOSCreditsHost, |
168 chrome::kChromeUIProxySettingsHost, | 81 chrome::kChromeUIProxySettingsHost, |
169 chrome::kChromeUISystemInfoHost, | 82 chrome::kChromeUISystemInfoHost, |
170 #endif | 83 #endif |
171 }; | 84 }; |
172 | 85 |
173 // AboutSource handles these chrome:// paths. | |
174 const char* const kAboutSourceNames[] = { | |
175 chrome::kChromeUIChromeURLsHost, | |
176 chrome::kChromeUICreditsHost, | |
177 chrome::kChromeUIDNSHost, | |
178 chrome::kChromeUIHistogramsHost, | |
179 chrome::kChromeUIMemoryHost, | |
180 chrome::kChromeUIMemoryRedirectHost, | |
181 chrome::kChromeUIStatsHost, | |
182 chrome::kChromeUITaskManagerHost, | |
183 chrome::kChromeUITermsHost, | |
184 chrome::kChromeUIVersionHost, | |
185 #if defined(USE_TCMALLOC) | |
186 chrome::kChromeUITCMallocHost, | |
187 #endif | |
188 #if defined(OS_LINUX) || defined(OS_OPENBSD) | |
189 chrome::kChromeUILinuxProxyConfigHost, | |
190 chrome::kChromeUISandboxHost, | |
191 #endif | |
192 #if defined(OS_CHROMEOS) | |
193 chrome::kChromeUICryptohomeHost, | |
194 chrome::kChromeUIDiscardsHost, | |
195 chrome::kChromeUINetworkHost, | |
196 chrome::kChromeUIOSCreditsHost, | |
197 #endif | |
198 }; | |
199 | |
200 const char kCreditsJsPath[] = "credits.js"; | |
201 const char kMemoryJsPath[] = "memory.js"; | |
202 const char kStatsJsPath[] = "stats.js"; | |
203 const char kStringsJsPath[] = "strings.js"; | |
204 const char kVersionJsPath[] = "version.js"; | |
205 | |
206 class AboutSource : public ChromeURLDataManager::DataSource { | |
207 public: | |
208 // Construct a data source for the specified |source_name|. | |
209 AboutSource(const std::string& source_name, Profile* profile); | |
210 | |
211 // Called when the network layer has requested a resource underneath | |
212 // the path we registered. | |
213 virtual void StartDataRequest(const std::string& path, | |
214 bool is_incognito, | |
215 int request_id) OVERRIDE; | |
216 | |
217 virtual std::string GetMimeType(const std::string& path) const OVERRIDE; | |
218 | |
219 // Send the response data. | |
220 void FinishDataRequest(const std::string& html, int request_id); | |
221 | |
222 Profile* profile() { return profile_; } | |
223 | |
224 private: | |
225 virtual ~AboutSource(); | |
226 | |
227 Profile* profile_; | |
228 | |
229 DISALLOW_COPY_AND_ASSIGN(AboutSource); | |
230 }; | |
231 | |
232 // When you type about:memory, it actually loads this intermediate URL that | |
233 // redirects you to the final page. This avoids the problem where typing | |
234 // "about:memory" on the new tab page or any other page where a process | |
235 // transition would occur to the about URL will cause some confusion. | |
236 // | |
237 // The problem is that during the processing of the memory page, there are two | |
238 // processes active, the original and the destination one. This can create the | |
239 // impression that we're using more resources than we actually are. This | |
240 // redirect solves the problem by eliminating the process transition during the | |
241 // time that about memory is being computed. | |
242 std::string GetAboutMemoryRedirectResponse(Profile* profile) { | |
243 InitializeAboutDataSource(chrome::kChromeUIMemoryRedirectHost, profile); | |
244 return StringPrintf("<meta http-equiv=\"refresh\" content=\"0;%s\">", | |
245 chrome::kChromeUIMemoryRedirectURL); | |
246 } | |
247 | |
248 // Handling about:memory is complicated enough to encapsulate its related | |
249 // methods into a single class. The user should create it (on the heap) and call | |
250 // its |StartFetch()| method. | |
251 class AboutMemoryHandler : public MemoryDetails { | |
252 public: | |
253 AboutMemoryHandler(AboutSource* source, int request_id) | |
254 : source_(source), | |
255 request_id_(request_id) { | |
256 } | |
257 | |
258 virtual void OnDetailsAvailable() OVERRIDE; | |
259 | |
260 private: | |
261 ~AboutMemoryHandler() {} | |
262 | |
263 void BindProcessMetrics(DictionaryValue* data, | |
264 ProcessMemoryInformation* info); | |
265 void AppendProcess(ListValue* child_data, ProcessMemoryInformation* info); | |
266 | |
267 scoped_refptr<AboutSource> source_; | |
268 int request_id_; | |
269 | |
270 DISALLOW_COPY_AND_ASSIGN(AboutMemoryHandler); | |
271 }; | |
272 | |
273 #if defined(OS_CHROMEOS) | |
274 // ChromeOSAboutVersionHandler is responsible for loading the Chrome OS | |
275 // version. | |
276 // ChromeOSAboutVersionHandler handles deleting itself once the version has | |
277 // been obtained and AboutSource notified. | |
278 class ChromeOSAboutVersionHandler { | |
279 public: | |
280 ChromeOSAboutVersionHandler(AboutSource* source, int request_id); | |
281 | |
282 // Callback from chromeos::VersionLoader giving the version. | |
283 void OnVersion(chromeos::VersionLoader::Handle handle, | |
284 std::string version); | |
285 | |
286 private: | |
287 // Where the results are fed to. | |
288 scoped_refptr<AboutSource> source_; | |
289 | |
290 // ID identifying the request. | |
291 int request_id_; | |
292 | |
293 // Handles asynchronously loading the version. | |
294 chromeos::VersionLoader loader_; | |
295 | |
296 // Used to request the version. | |
297 CancelableRequestConsumer consumer_; | |
298 | |
299 DISALLOW_COPY_AND_ASSIGN(ChromeOSAboutVersionHandler); | |
300 }; | |
301 | |
302 class ChromeOSTermsHandler | |
303 : public base::RefCountedThreadSafe<ChromeOSTermsHandler> { | |
304 public: | |
305 static void Start(AboutSource* source, | |
306 const std::string& path, | |
307 int request_id) { | |
308 scoped_refptr<ChromeOSTermsHandler> handler( | |
309 new ChromeOSTermsHandler(source, path, request_id)); | |
310 handler->StartOnUIThread(); | |
311 } | |
312 | |
313 private: | |
314 ChromeOSTermsHandler(AboutSource* source, | |
315 const std::string& path, | |
316 int request_id) | |
317 : source_(source), | |
318 path_(path), | |
319 request_id_(request_id), | |
320 locale_(chromeos::WizardController::GetInitialLocale()) { | |
321 } | |
322 | |
323 void StartOnUIThread() { | |
324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
325 BrowserThread::PostTask( | |
326 BrowserThread::FILE, FROM_HERE, | |
327 NewRunnableMethod(this, &ChromeOSTermsHandler::LoadFileOnFileThread)); | |
328 } | |
329 | |
330 void LoadFileOnFileThread() { | |
331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
332 if (path_ == chrome::kOemEulaURLPath) { | |
333 const chromeos::StartupCustomizationDocument* customization = | |
334 chromeos::StartupCustomizationDocument::GetInstance(); | |
335 if (customization->IsReady()) { | |
336 FilePath oem_eula_file_path; | |
337 if (net::FileURLToFilePath(GURL(customization->GetEULAPage(locale_)), | |
338 &oem_eula_file_path)) { | |
339 if (!file_util::ReadFileToString(oem_eula_file_path, &contents_)) { | |
340 contents_.clear(); | |
341 } | |
342 } | |
343 } | |
344 } else { | |
345 std::string file_path = | |
346 StringPrintf(chrome::kEULAPathFormat, locale_.c_str()); | |
347 if (!file_util::ReadFileToString(FilePath(file_path), &contents_)) { | |
348 // No EULA for given language - try en-US as default. | |
349 file_path = StringPrintf(chrome::kEULAPathFormat, "en-US"); | |
350 if (!file_util::ReadFileToString(FilePath(file_path), &contents_)) { | |
351 // File with EULA not found, ResponseOnUIThread will load EULA from | |
352 // resources if contents_ is empty. | |
353 contents_.clear(); | |
354 } | |
355 } | |
356 } | |
357 BrowserThread::PostTask( | |
358 BrowserThread::UI, FROM_HERE, | |
359 NewRunnableMethod(this, &ChromeOSTermsHandler::ResponseOnUIThread)); | |
360 } | |
361 | |
362 void ResponseOnUIThread() { | |
363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
364 // If we fail to load Chrome OS EULA from disk, load it from resources. | |
365 // Do nothing if OEM EULA load failed. | |
366 if (contents_.empty() && path_ != chrome::kOemEulaURLPath) { | |
367 contents_ = ResourceBundle::GetSharedInstance().GetRawDataResource( | |
368 IDR_TERMS_HTML).as_string(); | |
369 } | |
370 source_->FinishDataRequest(contents_, request_id_); | |
371 } | |
372 | |
373 // Where the results are fed to. | |
374 scoped_refptr<AboutSource> source_; | |
375 | |
376 // Path in the URL. | |
377 std::string path_; | |
378 | |
379 // ID identifying the request. | |
380 int request_id_; | |
381 | |
382 // Locale of the EULA. | |
383 std::string locale_; | |
384 | |
385 // EULA contents that was loaded from file. | |
386 std::string contents_; | |
387 | |
388 DISALLOW_COPY_AND_ASSIGN(ChromeOSTermsHandler); | |
389 }; | |
390 | |
391 #endif | |
392 | |
393 // Individual about handlers --------------------------------------------------- | |
394 | |
395 void AppendHeader(std::string* output, int refresh, | |
396 const std::string& unescaped_title) { | |
397 output->append("<!DOCTYPE HTML>\n<html>\n<head>\n"); | |
398 if (!unescaped_title.empty()) { | |
399 output->append("<title>"); | |
400 output->append(net::EscapeForHTML(unescaped_title)); | |
401 output->append("</title>\n"); | |
402 } | |
403 output->append("<meta charset=\"utf-8\">\n"); | |
404 if (refresh > 0) { | |
405 output->append("<meta http-equiv=\"refresh\" content=\""); | |
406 output->append(base::IntToString(refresh)); | |
407 output->append("\"/>\n"); | |
408 } | |
409 } | |
410 | |
411 void AppendBody(std::string *output) { | |
412 output->append("</head>\n<body>\n"); | |
413 } | |
414 | |
415 void AppendFooter(std::string *output) { | |
416 output->append("</body>\n</html>\n"); | |
417 } | |
418 | |
419 std::string ChromeURLs() { | |
420 std::string html; | |
421 AppendHeader(&html, 0, "Chrome URLs"); | |
422 AppendBody(&html); | |
423 html += "<h2>List of Chrome URLs</h2>\n<ul>\n"; | |
424 std::vector<std::string> paths(ChromePaths()); | |
425 for (std::vector<std::string>::const_iterator i = paths.begin(); | |
426 i != paths.end(); ++i) | |
427 html += "<li><a href='chrome://" + *i + "/'>chrome://" + *i + "</a></li>\n"; | |
428 html += "</ul>\n<h2>For Debug</h2>\n" | |
429 "<p>The following pages are for debugging purposes only. Because they " | |
430 "crash or hang the renderer, they're not linked directly; you can type " | |
431 "them into the address bar if you need them.</p>\n<ul>"; | |
432 for (int i = 0; i < chrome::kNumberOfChromeDebugURLs; i++) | |
433 html += "<li>" + std::string(chrome::kChromeDebugURLs[i]) + "</li>\n"; | |
434 html += "</ul>\n"; | |
435 AppendFooter(&html); | |
436 return html; | |
437 } | |
438 | |
439 #if defined(OS_CHROMEOS) | |
440 | |
441 // Html output helper functions | |
442 // TODO(stevenjb): L10N this. | |
443 | |
444 // Helper function to wrap HTML with a tag. | |
445 std::string WrapWithTag(const std::string& tag, const std::string& text) { | |
446 return "<" + tag + ">" + text + "</" + tag + ">"; | |
447 } | |
448 | |
449 // Helper function to wrap Html with <th> tag. | |
450 std::string WrapWithTH(const std::string& text) { | |
451 return "<th>" + text + "</th>"; | |
452 } | |
453 | |
454 // Helper function to wrap Html with <td> tag. | |
455 std::string WrapWithTD(const std::string& text) { | |
456 return "<td>" + text + "</td>"; | |
457 } | |
458 | |
459 // Helper function to wrap Html with <tr> tag. | |
460 std::string WrapWithTR(const std::string& text) { | |
461 return "<tr>" + text + "</tr>"; | |
462 } | |
463 | |
464 void AppendRefresh(std::string *output, int refresh, const std::string& name) { | |
465 if (refresh > 0) { | |
466 output->append("(Auto-refreshing page every "); | |
467 output->append(base::IntToString(refresh)); | |
468 output->append("s)"); | |
469 } else { | |
470 output->append("(To auto-refresh this page: about:"); | |
471 output->append(name); | |
472 output->append("/<secs>)"); | |
473 } | |
474 } | |
475 | |
476 // Helper function to create an Html table header for a Network. | |
477 std::string ToHtmlTableHeader(const chromeos::Network* network) { | |
478 std::string str = | |
479 WrapWithTH("Name") + | |
480 WrapWithTH("Active") + | |
481 WrapWithTH("State"); | |
482 if (network->type() == chromeos::TYPE_WIFI || | |
483 network->type() == chromeos::TYPE_CELLULAR) { | |
484 str += WrapWithTH("Auto-Connect"); | |
485 str += WrapWithTH("Strength"); | |
486 } | |
487 if (network->type() == chromeos::TYPE_WIFI) { | |
488 str += WrapWithTH("Encryption"); | |
489 str += WrapWithTH("Passphrase"); | |
490 str += WrapWithTH("Identity"); | |
491 } | |
492 if (network->type() == chromeos::TYPE_CELLULAR) { | |
493 str += WrapWithTH("Technology"); | |
494 str += WrapWithTH("Connectivity"); | |
495 str += WrapWithTH("Activation"); | |
496 str += WrapWithTH("Roaming"); | |
497 } | |
498 if (network->type() == chromeos::TYPE_VPN) { | |
499 str += WrapWithTH("Host"); | |
500 str += WrapWithTH("Provider Type"); | |
501 str += WrapWithTH("PSK Passphrase"); | |
502 str += WrapWithTH("Username"); | |
503 str += WrapWithTH("User Passphrase"); | |
504 } | |
505 str += WrapWithTH("Error"); | |
506 str += WrapWithTH("IP Address"); | |
507 return WrapWithTR(str); | |
508 } | |
509 | |
510 // Helper function to create an Html table row for a Network. | |
511 std::string ToHtmlTableRow(const chromeos::Network* network) { | |
512 std::string str = | |
513 WrapWithTD(network->name()) + | |
514 WrapWithTD(base::IntToString(network->is_active())) + | |
515 WrapWithTD(network->GetStateString()); | |
516 if (network->type() == chromeos::TYPE_WIFI || | |
517 network->type() == chromeos::TYPE_CELLULAR) { | |
518 const chromeos::WirelessNetwork* wireless = | |
519 static_cast<const chromeos::WirelessNetwork*>(network); | |
520 str += WrapWithTD(base::IntToString(wireless->auto_connect())); | |
521 str += WrapWithTD(base::IntToString(wireless->strength())); | |
522 } | |
523 if (network->type() == chromeos::TYPE_WIFI) { | |
524 const chromeos::WifiNetwork* wifi = | |
525 static_cast<const chromeos::WifiNetwork*>(network); | |
526 str += WrapWithTD(wifi->GetEncryptionString()); | |
527 str += WrapWithTD(std::string(wifi->passphrase().length(), '*')); | |
528 str += WrapWithTD(wifi->identity()); | |
529 } | |
530 if (network->type() == chromeos::TYPE_CELLULAR) { | |
531 const chromeos::CellularNetwork* cell = | |
532 static_cast<const chromeos::CellularNetwork*>(network); | |
533 str += WrapWithTH(cell->GetNetworkTechnologyString()); | |
534 str += WrapWithTH(cell->GetActivationStateString()); | |
535 str += WrapWithTH(cell->GetRoamingStateString()); | |
536 } | |
537 if (network->type() == chromeos::TYPE_VPN) { | |
538 const chromeos::VirtualNetwork* vpn = | |
539 static_cast<const chromeos::VirtualNetwork*>(network); | |
540 str += WrapWithTH(vpn->server_hostname()); | |
541 str += WrapWithTH(vpn->GetProviderTypeString()); | |
542 str += WrapWithTD(std::string(vpn->psk_passphrase().length(), '*')); | |
543 str += WrapWithTH(vpn->username()); | |
544 str += WrapWithTD(std::string(vpn->user_passphrase().length(), '*')); | |
545 } | |
546 str += WrapWithTD(network->failed() ? network->GetErrorString() : ""); | |
547 str += WrapWithTD(network->ip_address()); | |
548 return WrapWithTR(str); | |
549 } | |
550 | |
551 std::string GetNetworkHtmlInfo(int refresh) { | |
552 chromeos::NetworkLibrary* cros = | |
553 chromeos::CrosLibrary::Get()->GetNetworkLibrary(); | |
554 std::string output; | |
555 AppendHeader(&output, refresh, "About Network"); | |
556 AppendBody(&output); | |
557 AppendRefresh(&output, refresh, "network"); | |
558 | |
559 if (cros->ethernet_enabled()) { | |
560 output.append("<h3>Ethernet:</h3><table border=1>"); | |
561 const chromeos::EthernetNetwork* ethernet = cros->ethernet_network(); | |
562 if (ethernet) { | |
563 output.append(ToHtmlTableHeader(ethernet)); | |
564 output.append(ToHtmlTableRow(ethernet)); | |
565 } | |
566 } | |
567 | |
568 if (cros->wifi_enabled()) { | |
569 output.append("</table><h3>Wifi Networks:</h3><table border=1>"); | |
570 const chromeos::WifiNetworkVector& wifi_networks = cros->wifi_networks(); | |
571 for (size_t i = 0; i < wifi_networks.size(); ++i) { | |
572 if (i == 0) | |
573 output.append(ToHtmlTableHeader(wifi_networks[i])); | |
574 output.append(ToHtmlTableRow(wifi_networks[i])); | |
575 } | |
576 } | |
577 | |
578 if (cros->cellular_enabled()) { | |
579 output.append("</table><h3>Cellular Networks:</h3><table border=1>"); | |
580 const chromeos::CellularNetworkVector& cellular_networks = | |
581 cros->cellular_networks(); | |
582 for (size_t i = 0; i < cellular_networks.size(); ++i) { | |
583 if (i == 0) | |
584 output.append(ToHtmlTableHeader(cellular_networks[i])); | |
585 output.append(ToHtmlTableRow(cellular_networks[i])); | |
586 } | |
587 } | |
588 | |
589 { | |
590 output.append("</table><h3>Virtual Networks:</h3><table border=1>"); | |
591 const chromeos::VirtualNetworkVector& virtual_networks = | |
592 cros->virtual_networks(); | |
593 for (size_t i = 0; i < virtual_networks.size(); ++i) { | |
594 if (i == 0) | |
595 output.append(ToHtmlTableHeader(virtual_networks[i])); | |
596 output.append(ToHtmlTableRow(virtual_networks[i])); | |
597 } | |
598 } | |
599 | |
600 { | |
601 output.append( | |
602 "</table><h3>Remembered Wi-Fi Networks:</h3><table border=1>"); | |
603 const chromeos::WifiNetworkVector& remembered_wifi_networks = | |
604 cros->remembered_wifi_networks(); | |
605 for (size_t i = 0; i < remembered_wifi_networks.size(); ++i) { | |
606 if (i == 0) | |
607 output.append( | |
608 ToHtmlTableHeader(remembered_wifi_networks[i])); | |
609 output.append(ToHtmlTableRow(remembered_wifi_networks[i])); | |
610 } | |
611 } | |
612 | |
613 output.append("</table>"); | |
614 AppendFooter(&output); | |
615 return output; | |
616 } | |
617 | |
618 std::string AboutNetwork(const std::string& query) { | |
619 int refresh; | |
620 base::StringToInt(query, &refresh); | |
621 return GetNetworkHtmlInfo(refresh); | |
622 } | |
623 | |
624 std::string AddBoolRow(const std::string& name, bool value) { | |
625 std::string row; | |
626 row.append(WrapWithTD(name)); | |
627 row.append(WrapWithTD(value ? "true" : "false")); | |
628 return WrapWithTR(row); | |
629 } | |
630 | |
631 std::string AddStringRow(const std::string& name, const std::string& value) { | |
632 std::string row; | |
633 row.append(WrapWithTD(name)); | |
634 row.append(WrapWithTD(value)); | |
635 return WrapWithTR(row); | |
636 } | |
637 | |
638 std::string GetCryptohomeHtmlInfo(int refresh) { | |
639 chromeos::CryptohomeLibrary* cryptohome = | |
640 chromeos::CrosLibrary::Get()->GetCryptohomeLibrary(); | |
641 std::string output; | |
642 AppendHeader(&output, refresh, "About Cryptohome"); | |
643 AppendBody(&output); | |
644 AppendRefresh(&output, refresh, "cryptohome"); | |
645 | |
646 output.append("<h3>CryptohomeLibrary:</h3>"); | |
647 output.append("<table>"); | |
648 output.append(AddBoolRow("IsMounted", cryptohome->IsMounted())); | |
649 output.append(AddBoolRow("TpmIsReady", cryptohome->TpmIsReady())); | |
650 output.append(AddBoolRow("TpmIsEnabled", cryptohome->TpmIsEnabled())); | |
651 output.append(AddBoolRow("TpmIsOwned", cryptohome->TpmIsOwned())); | |
652 output.append(AddBoolRow("TpmIsBeingOwned", cryptohome->TpmIsBeingOwned())); | |
653 output.append(AddBoolRow("Pkcs11IsTpmTokenReady", | |
654 cryptohome->Pkcs11IsTpmTokenReady())); | |
655 output.append("</table>"); | |
656 | |
657 std::string token_name, user_pin; | |
658 crypto::GetTPMTokenInfo(&token_name, &user_pin); | |
659 output.append("<h3>crypto:</h3>"); | |
660 output.append("<table>"); | |
661 output.append(AddBoolRow("IsTPMTokenReady", crypto::IsTPMTokenReady())); | |
662 output.append(AddStringRow("token_name", token_name)); | |
663 output.append(AddStringRow("user_pin", std::string(user_pin.length(), '*'))); | |
664 output.append("</table>"); | |
665 AppendFooter(&output); | |
666 | |
667 return output; | |
668 } | |
669 | |
670 std::string AboutCryptohome(const std::string& query) { | |
671 int refresh; | |
672 base::StringToInt(query, &refresh); | |
673 return GetCryptohomeHtmlInfo(refresh); | |
674 } | |
675 | |
676 std::string AboutDiscardsRun() { | |
677 std::string output; | |
678 AppendHeader(&output, 0, "About discards"); | |
679 output.append(StringPrintf("<meta http-equiv=\"refresh\" content=\"2;%s\">", | |
680 chrome::kChromeUIDiscardsURL)); | |
681 output.append(WrapWithTag("p", "Discarding a tab...")); | |
682 g_browser_process->oom_priority_manager()->DiscardTab(); | |
683 AppendFooter(&output); | |
684 return output; | |
685 } | |
686 | |
687 std::string AboutDiscards(const std::string& path) { | |
688 std::string output; | |
689 const char kRunCommand[] = "run"; | |
690 if (path == kRunCommand) | |
691 return AboutDiscardsRun(); | |
692 AppendHeader(&output, 0, "About discards"); | |
693 AppendBody(&output); | |
694 output.append("<h3>About discards</h3>"); | |
695 output.append( | |
696 "<p>Tabs sorted from most interesting to least interesting. The least " | |
697 "interesting tab may be discarded if we run out of physical memory.</p>"); | |
698 | |
699 std::vector<string16> titles = | |
700 g_browser_process->oom_priority_manager()->GetTabTitles(); | |
701 if (!titles.empty()) { | |
702 output.append("<ol>"); | |
703 std::vector<string16>::iterator it = titles.begin(); | |
704 for ( ; it != titles.end(); ++it) { | |
705 std::string title = UTF16ToUTF8(*it); | |
706 output.append(WrapWithTag("li", title)); | |
707 } | |
708 output.append("</ol>"); | |
709 } else { | |
710 output.append("<p>None found. Wait 10 seconds, then refresh.</p>"); | |
711 } | |
712 output.append(StringPrintf("<a href='%s%s'>Discard tab now</a>", | |
713 chrome::kChromeUIDiscardsURL, | |
714 kRunCommand)); | |
715 | |
716 base::SystemMemoryInfoKB meminfo; | |
717 base::GetSystemMemoryInfo(&meminfo); | |
718 output.append("<h3>System memory information in MB</h3>"); | |
719 output.append("<table>"); | |
720 output.append(AddStringRow( | |
721 "Total", base::IntToString(meminfo.total / 1024))); | |
722 output.append(AddStringRow( | |
723 "Free", base::IntToString(meminfo.free / 1024))); | |
724 output.append(AddStringRow( | |
725 "Buffered", base::IntToString(meminfo.buffers / 1024))); | |
726 output.append(AddStringRow( | |
727 "Cached", base::IntToString(meminfo.cached / 1024))); | |
728 output.append(AddStringRow( | |
729 "Committed", base::IntToString( | |
730 (meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached) / 1024))); | |
731 output.append(AddStringRow( | |
732 "Active Anon", base::IntToString(meminfo.active_anon / 1024))); | |
733 output.append(AddStringRow( | |
734 "Inactive Anon", base::IntToString(meminfo.inactive_anon / 1024))); | |
735 output.append(AddStringRow( | |
736 "Shared", base::IntToString(meminfo.shmem / 1024))); | |
737 output.append("</table>"); | |
738 | |
739 AppendFooter(&output); | |
740 return output; | |
741 } | |
742 | |
743 #endif // OS_CHROMEOS | |
744 | |
745 // AboutDnsHandler bounces the request back to the IO thread to collect | |
746 // the DNS information. | |
747 class AboutDnsHandler : public base::RefCountedThreadSafe<AboutDnsHandler> { | |
748 public: | |
749 static void Start(AboutSource* source, int request_id) { | |
750 scoped_refptr<AboutDnsHandler> handler( | |
751 new AboutDnsHandler(source, request_id)); | |
752 handler->StartOnUIThread(); | |
753 } | |
754 | |
755 private: | |
756 AboutDnsHandler(AboutSource* source, int request_id) | |
757 : source_(source), | |
758 request_id_(request_id) { | |
759 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
760 } | |
761 | |
762 // Calls FinishOnUIThread() on completion. | |
763 void StartOnUIThread() { | |
764 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
765 chrome_browser_net::Predictor* predictor = | |
766 source_->profile()->GetNetworkPredictor(); | |
767 BrowserThread::PostTask( | |
768 BrowserThread::IO, FROM_HERE, | |
769 NewRunnableMethod(this, &AboutDnsHandler::StartOnIOThread, predictor)); | |
770 } | |
771 | |
772 void StartOnIOThread(chrome_browser_net::Predictor* predictor) { | |
773 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
774 | |
775 std::string data; | |
776 AppendHeader(&data, 0, "About DNS"); | |
777 AppendBody(&data); | |
778 chrome_browser_net::Predictor::PredictorGetHtmlInfo(predictor, &data); | |
779 AppendFooter(&data); | |
780 | |
781 BrowserThread::PostTask( | |
782 BrowserThread::UI, FROM_HERE, | |
783 NewRunnableMethod(this, &AboutDnsHandler::FinishOnUIThread, data)); | |
784 } | |
785 | |
786 void FinishOnUIThread(const std::string& data) { | |
787 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
788 source_->FinishDataRequest(data, request_id_); | |
789 } | |
790 | |
791 // Where the results are fed to. | |
792 scoped_refptr<AboutSource> source_; | |
793 | |
794 // ID identifying the request. | |
795 int request_id_; | |
796 | |
797 DISALLOW_COPY_AND_ASSIGN(AboutDnsHandler); | |
798 }; | |
799 | |
800 #if defined(USE_TCMALLOC) | |
801 std::string AboutTcmalloc() { | |
802 std::string data; | |
803 AboutTcmallocOutputsType* outputs = | |
804 AboutTcmallocOutputs::GetInstance()->outputs(); | |
805 | |
806 // Display any stats for which we sent off requests the last time. | |
807 AppendHeader(&data, 0, "About tcmalloc"); | |
808 AppendBody(&data); | |
809 data.append("<p>Stats as of last page load;"); | |
810 data.append("reload to get stats as of this page load.</p>\n"); | |
811 data.append("<table width=\"100%\">\n"); | |
812 for (AboutTcmallocOutputsType::const_iterator oit = outputs->begin(); | |
813 oit != outputs->end(); | |
814 oit++) { | |
815 data.append("<tr><td bgcolor=\"yellow\">"); | |
816 data.append(oit->first); | |
817 data.append("</td></tr>\n"); | |
818 data.append("<tr><td><pre>\n"); | |
819 data.append(oit->second); | |
820 data.append("</pre></td></tr>\n"); | |
821 } | |
822 data.append("</table>\n"); | |
823 AppendFooter(&data); | |
824 | |
825 // Reset our collector singleton. | |
826 outputs->clear(); | |
827 | |
828 // Populate the collector with stats from the local browser process | |
829 // and send off requests to all the renderer processes. | |
830 char buffer[1024 * 32]; | |
831 MallocExtension::instance()->GetStats(buffer, sizeof(buffer)); | |
832 std::string browser("Browser"); | |
833 AboutTcmallocOutputs::GetInstance()->SetOutput(browser, buffer); | |
834 content::RenderProcessHost::iterator | |
835 it(content::RenderProcessHost::AllHostsIterator()); | |
836 while (!it.IsAtEnd()) { | |
837 it.GetCurrentValue()->Send(new ChromeViewMsg_GetRendererTcmalloc); | |
838 it.Advance(); | |
839 } | |
840 | |
841 return data; | |
842 } | |
843 #endif | |
844 | |
845 std::string AboutHistograms(const std::string& query) { | |
846 TimeDelta wait_time = TimeDelta::FromMilliseconds(10000); | |
847 | |
848 #ifndef NDEBUG | |
849 base::StatisticsRecorder::CollectHistogramStats("Browser"); | |
850 #endif | |
851 | |
852 HistogramSynchronizer* current_synchronizer = | |
853 HistogramSynchronizer::CurrentSynchronizer(); | |
854 DCHECK(current_synchronizer != NULL); | |
855 current_synchronizer->FetchRendererHistogramsSynchronously(wait_time); | |
856 | |
857 std::string unescaped_query; | |
858 std::string unescaped_title("About Histograms"); | |
859 if (!query.empty()) { | |
860 unescaped_query = net::UnescapeURLComponent(query, | |
861 net::UnescapeRule::NORMAL); | |
862 unescaped_title += " - " + unescaped_query; | |
863 } | |
864 | |
865 std::string data; | |
866 AppendHeader(&data, 0, unescaped_title); | |
867 AppendBody(&data); | |
868 base::StatisticsRecorder::WriteHTMLGraph(unescaped_query, &data); | |
869 AppendFooter(&data); | |
870 return data; | |
871 } | |
872 | |
873 void AboutMemory(const std::string& path, AboutSource* source, int request_id) { | |
874 if (path == kStringsJsPath) { | |
875 // The AboutMemoryHandler cleans itself up, but |StartFetch()| will want the | |
876 // refcount to be greater than 0. | |
877 scoped_refptr<AboutMemoryHandler> | |
878 handler(new AboutMemoryHandler(source, request_id)); | |
879 handler->StartFetch(); | |
880 } else { | |
881 source->FinishDataRequest( | |
882 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
883 path == kMemoryJsPath ? IDR_ABOUT_MEMORY_JS : | |
884 IDR_ABOUT_MEMORY_HTML).as_string(), request_id); | |
885 } | |
886 } | |
887 | |
888 // Handler for filling in the "about:stats" page, as called by the browser's | |
889 // About handler processing. | |
890 // |query| is roughly the query string of the about:stats URL. | |
891 // Returns a string containing the HTML to render for the about:stats page. | |
892 // Conditional Output: | |
893 // if |query| is "json", returns a JSON format of all counters. | |
894 // if |query| is "raw", returns plain text of counter deltas. | |
895 // otherwise, returns HTML with pretty JS/HTML to display the data. | |
896 std::string AboutStats(const std::string& query) { | |
897 // We keep the DictionaryValue tree live so that we can do delta | |
898 // stats computations across runs. | |
899 CR_DEFINE_STATIC_LOCAL(DictionaryValue, root, ()); | |
900 static base::TimeTicks last_sample_time = base::TimeTicks::Now(); | |
901 | |
902 base::TimeTicks now = base::TimeTicks::Now(); | |
903 base::TimeDelta time_since_last_sample = now - last_sample_time; | |
904 last_sample_time = now; | |
905 | |
906 base::StatsTable* table = base::StatsTable::current(); | |
907 if (!table) | |
908 return std::string(); | |
909 | |
910 // We maintain two lists - one for counters and one for timers. | |
911 // Timers actually get stored on both lists. | |
912 ListValue* counters; | |
913 if (!root.GetList("counters", &counters)) { | |
914 counters = new ListValue(); | |
915 root.Set("counters", counters); | |
916 } | |
917 | |
918 ListValue* timers; | |
919 if (!root.GetList("timers", &timers)) { | |
920 timers = new ListValue(); | |
921 root.Set("timers", timers); | |
922 } | |
923 | |
924 // NOTE: Counters start at index 1. | |
925 for (int index = 1; index <= table->GetMaxCounters(); index++) { | |
926 // Get the counter's full name | |
927 std::string full_name = table->GetRowName(index); | |
928 if (full_name.length() == 0) | |
929 break; | |
930 DCHECK_EQ(':', full_name[1]); | |
931 char counter_type = full_name[0]; | |
932 std::string name = full_name.substr(2); | |
933 | |
934 // JSON doesn't allow '.' in names. | |
935 size_t pos; | |
936 while ((pos = name.find(".")) != std::string::npos) | |
937 name.replace(pos, 1, ":"); | |
938 | |
939 // Try to see if this name already exists. | |
940 DictionaryValue* counter = NULL; | |
941 for (size_t scan_index = 0; | |
942 scan_index < counters->GetSize(); scan_index++) { | |
943 DictionaryValue* dictionary; | |
944 if (counters->GetDictionary(scan_index, &dictionary)) { | |
945 std::string scan_name; | |
946 if (dictionary->GetString("name", &scan_name) && scan_name == name) { | |
947 counter = dictionary; | |
948 } | |
949 } else { | |
950 NOTREACHED(); // Should always be there | |
951 } | |
952 } | |
953 | |
954 if (counter == NULL) { | |
955 counter = new DictionaryValue(); | |
956 counter->SetString("name", name); | |
957 counters->Append(counter); | |
958 } | |
959 | |
960 switch (counter_type) { | |
961 case 'c': | |
962 { | |
963 int new_value = table->GetRowValue(index); | |
964 int prior_value = 0; | |
965 int delta = 0; | |
966 if (counter->GetInteger("value", &prior_value)) { | |
967 delta = new_value - prior_value; | |
968 } | |
969 counter->SetInteger("value", new_value); | |
970 counter->SetInteger("delta", delta); | |
971 } | |
972 break; | |
973 case 'm': | |
974 { | |
975 // TODO(mbelshe): implement me. | |
976 } | |
977 break; | |
978 case 't': | |
979 { | |
980 int time = table->GetRowValue(index); | |
981 counter->SetInteger("time", time); | |
982 | |
983 // Store this on the timers list as well. | |
984 timers->Append(counter); | |
985 } | |
986 break; | |
987 default: | |
988 NOTREACHED(); | |
989 } | |
990 } | |
991 | |
992 std::string data; | |
993 if (query == "json" || query == kStringsJsPath) { | |
994 base::JSONWriter::WriteWithOptions( | |
995 &root, true, base::JSONWriter::OPTIONS_DO_NOT_ESCAPE, &data); | |
996 if (query == kStringsJsPath) | |
997 data = "var templateData = " + data + ";"; | |
998 } else if (query == "raw") { | |
999 // Dump the raw counters which have changed in text format. | |
1000 data = "<pre>"; | |
1001 data.append(StringPrintf("Counter changes in the last %ldms\n", | |
1002 static_cast<long int>(time_since_last_sample.InMilliseconds()))); | |
1003 for (size_t i = 0; i < counters->GetSize(); ++i) { | |
1004 Value* entry = NULL; | |
1005 bool rv = counters->Get(i, &entry); | |
1006 if (!rv) | |
1007 continue; // None of these should fail. | |
1008 DictionaryValue* counter = static_cast<DictionaryValue*>(entry); | |
1009 int delta; | |
1010 rv = counter->GetInteger("delta", &delta); | |
1011 if (!rv) | |
1012 continue; | |
1013 if (delta > 0) { | |
1014 std::string name; | |
1015 rv = counter->GetString("name", &name); | |
1016 if (!rv) | |
1017 continue; | |
1018 int value; | |
1019 rv = counter->GetInteger("value", &value); | |
1020 if (!rv) | |
1021 continue; | |
1022 data.append(name); | |
1023 data.append(":"); | |
1024 data.append(base::IntToString(delta)); | |
1025 data.append("\n"); | |
1026 } | |
1027 } | |
1028 data.append("</pre>"); | |
1029 } else { | |
1030 // Get about_stats.html/js from resource bundle. | |
1031 data = ResourceBundle::GetSharedInstance().GetRawDataResource( | |
1032 (query == kStatsJsPath ? IDR_ABOUT_STATS_JS : IDR_ABOUT_STATS_HTML)). | |
1033 as_string(); | |
1034 | |
1035 if (query != kStatsJsPath) { | |
1036 // Clear the timer list since we stored the data in the timers list | |
1037 // as well. | |
1038 for (int index = static_cast<int>(timers->GetSize())-1; index >= 0; | |
1039 index--) { | |
1040 Value* value; | |
1041 timers->Remove(index, &value); | |
1042 // We don't care about the value pointer; it's still tracked | |
1043 // on the counters list. | |
1044 } | |
1045 } | |
1046 } | |
1047 | |
1048 return data; | |
1049 } | |
1050 | |
1051 #if defined(OS_LINUX) || defined(OS_OPENBSD) | |
1052 std::string AboutLinuxProxyConfig() { | |
1053 std::string data; | |
1054 AppendHeader(&data, 0, | |
1055 l10n_util::GetStringUTF8(IDS_ABOUT_LINUX_PROXY_CONFIG_TITLE)); | |
1056 data.append("<style>body { max-width: 70ex; padding: 2ex 5ex; }</style>"); | |
1057 AppendBody(&data); | |
1058 FilePath binary = CommandLine::ForCurrentProcess()->GetProgram(); | |
1059 data.append(l10n_util::GetStringFUTF8( | |
1060 IDS_ABOUT_LINUX_PROXY_CONFIG_BODY, | |
1061 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), | |
1062 ASCIIToUTF16(binary.BaseName().value()))); | |
1063 AppendFooter(&data); | |
1064 return data; | |
1065 } | |
1066 | |
1067 void AboutSandboxRow(std::string* data, const std::string& prefix, int name_id, | |
1068 bool good) { | |
1069 data->append("<tr><td>"); | |
1070 data->append(prefix); | |
1071 data->append(l10n_util::GetStringUTF8(name_id)); | |
1072 if (good) { | |
1073 data->append("</td><td style=\"color: green;\">"); | |
1074 data->append( | |
1075 l10n_util::GetStringUTF8(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL)); | |
1076 } else { | |
1077 data->append("</td><td style=\"color: red;\">"); | |
1078 data->append( | |
1079 l10n_util::GetStringUTF8(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL)); | |
1080 } | |
1081 data->append("</td></tr>"); | |
1082 } | |
1083 | |
1084 std::string AboutSandbox() { | |
1085 std::string data; | |
1086 AppendHeader(&data, 0, l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_TITLE)); | |
1087 AppendBody(&data); | |
1088 data.append("<h1>"); | |
1089 data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_TITLE)); | |
1090 data.append("</h1>"); | |
1091 | |
1092 const int status = ZygoteHost::GetInstance()->sandbox_status(); | |
1093 | |
1094 data.append("<table>"); | |
1095 | |
1096 AboutSandboxRow(&data, "", IDS_ABOUT_SANDBOX_SUID_SANDBOX, | |
1097 status & ZygoteHost::kSandboxSUID); | |
1098 AboutSandboxRow(&data, " ", IDS_ABOUT_SANDBOX_PID_NAMESPACES, | |
1099 status & ZygoteHost::kSandboxPIDNS); | |
1100 AboutSandboxRow(&data, " ", IDS_ABOUT_SANDBOX_NET_NAMESPACES, | |
1101 status & ZygoteHost::kSandboxNetNS); | |
1102 AboutSandboxRow(&data, "", IDS_ABOUT_SANDBOX_SECCOMP_SANDBOX, | |
1103 status & ZygoteHost::kSandboxSeccomp); | |
1104 | |
1105 data.append("</table>"); | |
1106 | |
1107 bool good = ((status & ZygoteHost::kSandboxSUID) && | |
1108 (status & ZygoteHost::kSandboxPIDNS)) || | |
1109 (status & ZygoteHost::kSandboxSeccomp); | |
1110 if (good) { | |
1111 data.append("<p style=\"color: green\">"); | |
1112 data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_OK)); | |
1113 } else { | |
1114 data.append("<p style=\"color: red\">"); | |
1115 data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_BAD)); | |
1116 } | |
1117 data.append("</p>"); | |
1118 | |
1119 AppendFooter(&data); | |
1120 return data; | |
1121 } | |
1122 #endif | |
1123 | |
1124 std::string AboutVersionStaticContent(const std::string& query) { | |
1125 return ResourceBundle::GetSharedInstance().GetRawDataResource( | |
1126 query == kVersionJsPath ? | |
1127 IDR_ABOUT_VERSION_JS : | |
1128 IDR_ABOUT_VERSION_HTML).as_string(); | |
1129 } | |
1130 | |
1131 std::string AboutVersionStrings(DictionaryValue* localized_strings, | |
1132 Profile* profile) { | |
1133 localized_strings->SetString("title", | |
1134 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_TITLE)); | |
1135 chrome::VersionInfo version_info; | |
1136 | |
1137 localized_strings->SetString("name", | |
1138 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); | |
1139 localized_strings->SetString("version", version_info.Version()); | |
1140 // Bug 79458: Need to evaluate the use of getting the version string on | |
1141 // this thread. | |
1142 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
1143 localized_strings->SetString("version_modifier", | |
1144 chrome::VersionInfo::GetVersionStringModifier()); | |
1145 localized_strings->SetString("os_name", | |
1146 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_OS)); | |
1147 localized_strings->SetString("platform", | |
1148 l10n_util::GetStringUTF16(IDS_PLATFORM_LABEL)); | |
1149 localized_strings->SetString("os_type", version_info.OSType()); | |
1150 localized_strings->SetString("webkit_version", | |
1151 webkit_glue::GetWebKitVersion()); | |
1152 localized_strings->SetString("js_engine", "V8"); | |
1153 localized_strings->SetString("js_version", v8::V8::GetVersion()); | |
1154 | |
1155 // Obtain the version of the first enabled Flash plugin. | |
1156 std::vector<webkit::WebPluginInfo> info_array; | |
1157 PluginService::GetInstance()->GetPluginInfoArray( | |
1158 GURL(), "application/x-shockwave-flash", false, &info_array, NULL); | |
1159 string16 flash_version = | |
1160 l10n_util::GetStringUTF16(IDS_PLUGINS_DISABLED_PLUGIN); | |
1161 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile); | |
1162 for (size_t i = 0; i < info_array.size(); ++i) { | |
1163 if (plugin_prefs->IsPluginEnabled(info_array[i])) { | |
1164 flash_version = info_array[i].version; | |
1165 break; | |
1166 } | |
1167 } | |
1168 localized_strings->SetString("flash_plugin", "Flash"); | |
1169 localized_strings->SetString("flash_version", flash_version); | |
1170 localized_strings->SetString("company", | |
1171 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COMPANY_NAME)); | |
1172 localized_strings->SetString("copyright", | |
1173 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COPYRIGHT)); | |
1174 localized_strings->SetString("cl", version_info.LastChange()); | |
1175 localized_strings->SetString("official", | |
1176 l10n_util::GetStringUTF16( | |
1177 version_info.IsOfficialBuild() ? | |
1178 IDS_ABOUT_VERSION_OFFICIAL | |
1179 : IDS_ABOUT_VERSION_UNOFFICIAL)); | |
1180 localized_strings->SetString("user_agent_name", | |
1181 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_USER_AGENT)); | |
1182 localized_strings->SetString("useragent", content::GetUserAgent(GURL())); | |
1183 localized_strings->SetString("command_line_name", | |
1184 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_COMMAND_LINE)); | |
1185 | |
1186 #if defined(OS_WIN) | |
1187 localized_strings->SetString("command_line", | |
1188 WideToUTF16(CommandLine::ForCurrentProcess()->GetCommandLineString())); | |
1189 #elif defined(OS_POSIX) | |
1190 std::string command_line = ""; | |
1191 typedef std::vector<std::string> ArgvList; | |
1192 const ArgvList& argv = CommandLine::ForCurrentProcess()->argv(); | |
1193 for (ArgvList::const_iterator iter = argv.begin(); iter != argv.end(); iter++) | |
1194 command_line += " " + *iter; | |
1195 // TODO(viettrungluu): |command_line| could really have any encoding, whereas | |
1196 // below we assumes it's UTF-8. | |
1197 localized_strings->SetString("command_line", command_line); | |
1198 #endif | |
1199 | |
1200 // Allow IO temporarily based on allow_io (defined above) | |
1201 // since the following operation will complete quickly | |
1202 localized_strings->SetString("executable_path_name", | |
1203 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_EXECUTABLE_PATH)); | |
1204 FilePath executable_path = CommandLine::ForCurrentProcess()->GetProgram(); | |
1205 if (file_util::AbsolutePath(&executable_path)) { | |
1206 localized_strings->SetString("executable_path", executable_path.value()); | |
1207 } else { | |
1208 localized_strings->SetString("executable_path", | |
1209 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_PATH_NOTFOUND)); | |
1210 } | |
1211 localized_strings->SetString("profile_path_name", | |
1212 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_PROFILE_PATH)); | |
1213 if (profile) { | |
1214 FilePath profile_path = profile->GetPath(); | |
1215 if (file_util::AbsolutePath(&profile_path)) { | |
1216 localized_strings->SetString("profile_path", profile_path.value()); | |
1217 } else { | |
1218 localized_strings->SetString("profile_path", | |
1219 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_PATH_NOTFOUND)); | |
1220 } | |
1221 } else { | |
1222 localized_strings->SetString("profile_path", | |
1223 l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_PATH_NOTFOUND)); | |
1224 } | |
1225 | |
1226 std::string data; | |
1227 jstemplate_builder::AppendJsonJS(localized_strings, &data); | |
1228 return data; | |
1229 } | |
1230 | |
1231 // Used as a callback for PluginService::GetPlugins(). | |
1232 void HandleAboutVersionStrings(AboutSource* source, | |
1233 int request_id, | |
1234 const std::vector<webkit::WebPluginInfo>&) { | |
1235 #if defined(OS_CHROMEOS) | |
1236 new ChromeOSAboutVersionHandler(source, request_id); | |
1237 #else | |
1238 DictionaryValue localized_strings; | |
1239 localized_strings.SetString("os_version", ""); | |
1240 source->FinishDataRequest( | |
1241 AboutVersionStrings(&localized_strings, source->profile()), | |
1242 request_id); | |
1243 #endif | |
1244 } | |
1245 | |
1246 // AboutMemoryHandler ---------------------------------------------------------- | |
1247 | |
1248 // Helper for AboutMemory to bind results from a ProcessMetrics object | |
1249 // to a DictionaryValue. Fills ws_usage and comm_usage so that the objects | |
1250 // can be used in caller's scope (e.g for appending to a net total). | |
1251 void AboutMemoryHandler::BindProcessMetrics(DictionaryValue* data, | |
1252 ProcessMemoryInformation* info) { | |
1253 DCHECK(data && info); | |
1254 | |
1255 // Bind metrics to dictionary. | |
1256 data->SetInteger("ws_priv", static_cast<int>(info->working_set.priv)); | |
1257 data->SetInteger("ws_shareable", | |
1258 static_cast<int>(info->working_set.shareable)); | |
1259 data->SetInteger("ws_shared", static_cast<int>(info->working_set.shared)); | |
1260 data->SetInteger("comm_priv", static_cast<int>(info->committed.priv)); | |
1261 data->SetInteger("comm_map", static_cast<int>(info->committed.mapped)); | |
1262 data->SetInteger("comm_image", static_cast<int>(info->committed.image)); | |
1263 data->SetInteger("pid", info->pid); | |
1264 data->SetString("version", info->version); | |
1265 data->SetInteger("processes", info->num_processes); | |
1266 } | |
1267 | |
1268 // Helper for AboutMemory to append memory usage information for all | |
1269 // sub-processes (i.e. renderers, plugins) used by Chrome. | |
1270 void AboutMemoryHandler::AppendProcess(ListValue* child_data, | |
1271 ProcessMemoryInformation* info) { | |
1272 DCHECK(child_data && info); | |
1273 | |
1274 // Append a new DictionaryValue for this renderer to our list. | |
1275 DictionaryValue* child = new DictionaryValue(); | |
1276 child_data->Append(child); | |
1277 BindProcessMetrics(child, info); | |
1278 | |
1279 std::string child_label( | |
1280 ProcessMemoryInformation::GetFullTypeNameInEnglish(info->type, | |
1281 info->renderer_type)); | |
1282 if (info->is_diagnostics) | |
1283 child_label.append(" (diagnostics)"); | |
1284 child->SetString("child_name", child_label); | |
1285 ListValue* titles = new ListValue(); | |
1286 child->Set("titles", titles); | |
1287 for (size_t i = 0; i < info->titles.size(); ++i) | |
1288 titles->Append(new StringValue(info->titles[i])); | |
1289 } | |
1290 | |
1291 | |
1292 void AboutMemoryHandler::OnDetailsAvailable() { | |
1293 // the root of the JSON hierarchy for about:memory jstemplate | |
1294 DictionaryValue root; | |
1295 ListValue* browsers = new ListValue(); | |
1296 root.Set("browsers", browsers); | |
1297 | |
1298 const std::vector<ProcessData>& browser_processes = processes(); | |
1299 | |
1300 // Aggregate per-process data into browser summary data. | |
1301 std::wstring log_string; | |
1302 for (size_t index = 0; index < browser_processes.size(); index++) { | |
1303 if (browser_processes[index].processes.empty()) | |
1304 continue; | |
1305 | |
1306 // Sum the information for the processes within this browser. | |
1307 ProcessMemoryInformation aggregate; | |
1308 ProcessMemoryInformationList::const_iterator iterator; | |
1309 iterator = browser_processes[index].processes.begin(); | |
1310 aggregate.pid = iterator->pid; | |
1311 aggregate.version = iterator->version; | |
1312 while (iterator != browser_processes[index].processes.end()) { | |
1313 if (!iterator->is_diagnostics || | |
1314 browser_processes[index].processes.size() == 1) { | |
1315 aggregate.working_set.priv += iterator->working_set.priv; | |
1316 aggregate.working_set.shared += iterator->working_set.shared; | |
1317 aggregate.working_set.shareable += iterator->working_set.shareable; | |
1318 aggregate.committed.priv += iterator->committed.priv; | |
1319 aggregate.committed.mapped += iterator->committed.mapped; | |
1320 aggregate.committed.image += iterator->committed.image; | |
1321 aggregate.num_processes++; | |
1322 } | |
1323 ++iterator; | |
1324 } | |
1325 DictionaryValue* browser_data = new DictionaryValue(); | |
1326 browsers->Append(browser_data); | |
1327 browser_data->SetString("name", browser_processes[index].name); | |
1328 | |
1329 BindProcessMetrics(browser_data, &aggregate); | |
1330 | |
1331 // We log memory info as we record it. | |
1332 if (log_string.length() > 0) | |
1333 log_string.append(L", "); | |
1334 log_string.append(UTF16ToWide(browser_processes[index].name)); | |
1335 log_string.append(L", "); | |
1336 log_string.append(UTF8ToWide( | |
1337 base::Int64ToString(aggregate.working_set.priv))); | |
1338 log_string.append(L", "); | |
1339 log_string.append(UTF8ToWide( | |
1340 base::Int64ToString(aggregate.working_set.shared))); | |
1341 log_string.append(L", "); | |
1342 log_string.append(UTF8ToWide( | |
1343 base::Int64ToString(aggregate.working_set.shareable))); | |
1344 } | |
1345 if (log_string.length() > 0) | |
1346 VLOG(1) << "memory: " << log_string; | |
1347 | |
1348 // Set the browser & renderer detailed process data. | |
1349 DictionaryValue* browser_data = new DictionaryValue(); | |
1350 root.Set("browzr_data", browser_data); | |
1351 ListValue* child_data = new ListValue(); | |
1352 root.Set("child_data", child_data); | |
1353 | |
1354 ProcessData process = browser_processes[0]; // Chrome is the first browser. | |
1355 root.SetString("current_browser_name", process.name); | |
1356 | |
1357 for (size_t index = 0; index < process.processes.size(); index++) { | |
1358 if (process.processes[index].type == ChildProcessInfo::BROWSER_PROCESS) | |
1359 BindProcessMetrics(browser_data, &process.processes[index]); | |
1360 else | |
1361 AppendProcess(child_data, &process.processes[index]); | |
1362 } | |
1363 | |
1364 root.SetBoolean("show_other_browsers", | |
1365 browser_defaults::kShowOtherBrowsersInAboutMemory); | |
1366 | |
1367 std::string data; | |
1368 jstemplate_builder::AppendJsonJS(&root, &data); | |
1369 source_->FinishDataRequest(data, request_id_); | |
1370 } | |
1371 | |
1372 #if defined(OS_CHROMEOS) | |
1373 // ChromeOSAboutVersionHandler ----------------------------------------------- | |
1374 | |
1375 ChromeOSAboutVersionHandler::ChromeOSAboutVersionHandler( | |
1376 AboutSource* source, | |
1377 int request_id) | |
1378 : source_(source), | |
1379 request_id_(request_id) { | |
1380 loader_.GetVersion(&consumer_, | |
1381 base::Bind(&ChromeOSAboutVersionHandler::OnVersion, | |
1382 base::Unretained(this)), | |
1383 chromeos::VersionLoader::VERSION_FULL); | |
1384 } | |
1385 | |
1386 void ChromeOSAboutVersionHandler::OnVersion( | |
1387 chromeos::VersionLoader::Handle handle, | |
1388 std::string version) { | |
1389 DictionaryValue localized_strings; | |
1390 localized_strings.SetString("os_version", version); | |
1391 source_->FinishDataRequest(AboutVersionStrings( | |
1392 &localized_strings, source_->profile()), request_id_); | |
1393 | |
1394 // CancelableRequestProvider isn't happy when it's deleted and servicing a | |
1395 // task, so we delay the deletion. | |
1396 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
1397 } | |
1398 | |
1399 #endif | |
1400 | |
1401 } // namespace | 86 } // namespace |
1402 | 87 |
1403 // AboutSource ----------------------------------------------------------------- | |
1404 | |
1405 AboutSource::AboutSource(const std::string& source_name, Profile* profile) | |
1406 : DataSource(source_name, MessageLoop::current()), | |
1407 profile_(profile) { | |
1408 } | |
1409 | |
1410 AboutSource::~AboutSource() { | |
1411 } | |
1412 | |
1413 void AboutSource::StartDataRequest(const std::string& path, | |
1414 bool is_incognito, | |
1415 int request_id) { | |
1416 std::string response; | |
1417 std::string host = source_name(); | |
1418 // Add your data source here, in alphabetical order. | |
1419 if (host == chrome::kChromeUIChromeURLsHost) { | |
1420 response = ChromeURLs(); | |
1421 } else if (host == chrome::kChromeUICreditsHost) { | |
1422 int idr = (path == kCreditsJsPath) ? IDR_CREDITS_JS : IDR_CREDITS_HTML; | |
1423 response = ResourceBundle::GetSharedInstance().GetRawDataResource( | |
1424 idr).as_string(); | |
1425 #if defined(OS_CHROMEOS) | |
1426 } else if (host == chrome::kChromeUICryptohomeHost) { | |
1427 response = AboutCryptohome(path); | |
1428 } else if (host == chrome::kChromeUIDiscardsHost) { | |
1429 response = AboutDiscards(path); | |
1430 #endif | |
1431 } else if (host == chrome::kChromeUIDNSHost) { | |
1432 AboutDnsHandler::Start(this, request_id); | |
1433 return; | |
1434 } else if (host == chrome::kChromeUIHistogramsHost) { | |
1435 response = AboutHistograms(path); | |
1436 #if defined(OS_LINUX) || defined(OS_OPENBSD) | |
1437 } else if (host == chrome::kChromeUILinuxProxyConfigHost) { | |
1438 response = AboutLinuxProxyConfig(); | |
1439 #endif | |
1440 } else if (host == chrome::kChromeUIMemoryHost) { | |
1441 response = GetAboutMemoryRedirectResponse(profile()); | |
1442 } else if (host == chrome::kChromeUIMemoryRedirectHost) { | |
1443 AboutMemory(path, this, request_id); | |
1444 return; | |
1445 #if defined(OS_CHROMEOS) | |
1446 } else if (host == chrome::kChromeUINetworkHost) { | |
1447 response = AboutNetwork(path); | |
1448 } else if (host == chrome::kChromeUIOSCreditsHost) { | |
1449 response = ResourceBundle::GetSharedInstance().GetRawDataResource( | |
1450 IDR_OS_CREDITS_HTML).as_string(); | |
1451 #endif | |
1452 #if defined(OS_LINUX) || defined(OS_OPENBSD) | |
1453 } else if (host == chrome::kChromeUISandboxHost) { | |
1454 response = AboutSandbox(); | |
1455 #endif | |
1456 } else if (host == chrome::kChromeUIStatsHost) { | |
1457 response = AboutStats(path); | |
1458 #if defined(USE_TCMALLOC) | |
1459 } else if (host == chrome::kChromeUITCMallocHost) { | |
1460 response = AboutTcmalloc(); | |
1461 #endif | |
1462 } else if (host == chrome::kChromeUITermsHost) { | |
1463 #if defined(OS_CHROMEOS) | |
1464 ChromeOSTermsHandler::Start(this, path, request_id); | |
1465 return; | |
1466 #else | |
1467 response = ResourceBundle::GetSharedInstance().GetRawDataResource( | |
1468 IDR_TERMS_HTML).as_string(); | |
1469 #endif | |
1470 } else if (host == chrome::kChromeUIVersionHost) { | |
1471 if (path == kStringsJsPath) { | |
1472 // The Flash version information is needed on this page, so make sure | |
1473 // the plugins are loaded. | |
1474 PluginService::GetInstance()->GetPlugins( | |
1475 base::Bind(&HandleAboutVersionStrings, | |
1476 make_scoped_refptr(this), request_id)); | |
1477 return; | |
1478 } else { | |
1479 response = AboutVersionStaticContent(path); | |
1480 } | |
1481 } | |
1482 | |
1483 FinishDataRequest(response, request_id); | |
1484 } | |
1485 | |
1486 void AboutSource::FinishDataRequest(const std::string& html, int request_id) { | |
1487 std::string html_copy(html); | |
1488 SendResponse(request_id, base::RefCountedString::TakeString(&html_copy)); | |
1489 } | |
1490 | |
1491 std::string AboutSource::GetMimeType(const std::string& path) const { | |
1492 if (path == kCreditsJsPath || | |
1493 path == kStatsJsPath || | |
1494 path == kStringsJsPath || | |
1495 path == kVersionJsPath || | |
1496 path == kMemoryJsPath) { | |
1497 return "application/javascript"; | |
1498 } | |
1499 return "text/html"; | |
1500 } | |
1501 | |
1502 // ----------------------------------------------------------------------------- | |
1503 | |
1504 void InitializeAboutDataSource(const std::string& name, | |
1505 content::BrowserContext* browser_context) { | |
1506 Profile* profile = static_cast<Profile*>(browser_context); | |
1507 ChromeURLDataManager* manager = profile->GetChromeURLDataManager(); | |
1508 for (size_t i = 0; i < arraysize(kAboutSourceNames); i++) { | |
1509 if (name == kAboutSourceNames[i]) { | |
1510 manager->AddDataSource(new AboutSource(name, profile)); | |
1511 return; | |
1512 } | |
1513 } | |
1514 } | |
1515 | |
1516 bool WillHandleBrowserAboutURL(GURL* url, | 88 bool WillHandleBrowserAboutURL(GURL* url, |
1517 content::BrowserContext* browser_context) { | 89 content::BrowserContext* browser_context) { |
1518 // TODO(msw): Eliminate "about:*" constants and literals from code and tests, | 90 // TODO(msw): Eliminate "about:*" constants and literals from code and tests, |
1519 // then hopefully we can remove this forced fixup. | 91 // then hopefully we can remove this forced fixup. |
1520 *url = URLFixerUpper::FixupURL(url->possibly_invalid_spec(), std::string()); | 92 *url = URLFixerUpper::FixupURL(url->possibly_invalid_spec(), std::string()); |
1521 | 93 |
1522 // Check that about: URLs are fixed up to chrome: by URLFixerUpper::FixupURL. | 94 // Check that about: URLs are fixed up to chrome: by URLFixerUpper::FixupURL. |
1523 DCHECK((*url == GURL(chrome::kAboutBlankURL)) || | 95 DCHECK((*url == GURL(chrome::kAboutBlankURL)) || |
1524 !url->SchemeIs(chrome::kAboutScheme)); | 96 !url->SchemeIs(chrome::kAboutScheme)); |
1525 | 97 |
(...skipping 24 matching lines...) Expand all Loading... |
1550 } else if (host == chrome::kChromeUIExtensionsHost) { | 122 } else if (host == chrome::kChromeUIExtensionsHost) { |
1551 host = chrome::kChromeUISettingsHost; | 123 host = chrome::kChromeUISettingsHost; |
1552 path = chrome::kExtensionsSubPage; | 124 path = chrome::kExtensionsSubPage; |
1553 } | 125 } |
1554 GURL::Replacements replacements; | 126 GURL::Replacements replacements; |
1555 replacements.SetHostStr(host); | 127 replacements.SetHostStr(host); |
1556 if (!path.empty()) | 128 if (!path.empty()) |
1557 replacements.SetPathStr(path); | 129 replacements.SetPathStr(path); |
1558 *url = url->ReplaceComponents(replacements); | 130 *url = url->ReplaceComponents(replacements); |
1559 | 131 |
| 132 // Having re-written the URL, make the chrome: handler process it. |
| 133 return false; |
| 134 } |
| 135 |
| 136 bool HandleNonNavigationAboutURL(const GURL& url) { |
| 137 std::string host(url.host()); |
| 138 |
| 139 // chrome://ipc/ is currently buggy, so we disable it for official builds. |
| 140 #if !defined(OFFICIAL_BUILD) |
| 141 |
| 142 #if (defined(OS_MACOSX) || defined(OS_WIN)) && defined(IPC_MESSAGE_LOG_ENABLED) |
| 143 if (LowerCaseEqualsASCII(url.spec(), chrome::kChromeUIIPCURL)) { |
| 144 // Run the dialog. This will re-use the existing one if it's already up. |
| 145 browser::ShowAboutIPCDialog(); |
| 146 return true; |
| 147 } |
| 148 #endif |
| 149 |
| 150 #endif // OFFICIAL_BUILD |
| 151 |
1560 // Handle URLs to crash the browser or wreck the gpu process. | 152 // Handle URLs to crash the browser or wreck the gpu process. |
1561 if (host == chrome::kChromeUIBrowserCrashHost) { | 153 if (host == chrome::kChromeUIBrowserCrashHost) { |
1562 // Induce an intentional crash in the browser process. | 154 // Induce an intentional crash in the browser process. |
1563 CHECK(false); | 155 CHECK(false); |
1564 } else if (host == chrome::kChromeUIGpuCleanHost) { | 156 } |
| 157 |
| 158 if (host == chrome::kChromeUIGpuCleanHost) { |
1565 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); | 159 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); |
1566 if (shim) | 160 if (shim) |
1567 shim->SimulateRemoveAllContext(); | 161 shim->SimulateRemoveAllContext(); |
1568 } else if (host == chrome::kChromeUIGpuCrashHost) { | 162 return true; |
| 163 } |
| 164 |
| 165 if (host == chrome::kChromeUIGpuCrashHost) { |
1569 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); | 166 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); |
1570 if (shim) | 167 if (shim) |
1571 shim->SimulateCrash(); | 168 shim->SimulateCrash(); |
1572 } else if (host == chrome::kChromeUIGpuHangHost) { | 169 return true; |
| 170 } |
| 171 |
| 172 if (host == chrome::kChromeUIGpuHangHost) { |
1573 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); | 173 GpuProcessHostUIShim* shim = GpuProcessHostUIShim::GetOneInstance(); |
1574 if (shim) | 174 if (shim) |
1575 shim->SimulateHang(); | 175 shim->SimulateHang(); |
| 176 return true; |
| 177 } |
| 178 |
1576 #if defined(OS_CHROMEOS) | 179 #if defined(OS_CHROMEOS) |
1577 } else if (host == chrome::kChromeUIRotateHost) { | 180 if (host == chrome::kChromeUIRotateHost) { |
1578 content::ScreenOrientation change = content::SCREEN_ORIENTATION_TOP; | 181 content::ScreenOrientation change = content::SCREEN_ORIENTATION_TOP; |
1579 std::string query(url->query()); | 182 std::string query(url.query()); |
1580 if (query == "left") { | 183 if (query == "left") { |
1581 change = content::SCREEN_ORIENTATION_LEFT; | 184 change = content::SCREEN_ORIENTATION_LEFT; |
1582 } else if (query == "right") { | 185 } else if (query == "right") { |
1583 change = content::SCREEN_ORIENTATION_RIGHT; | 186 change = content::SCREEN_ORIENTATION_RIGHT; |
1584 } else if (query == "top") { | 187 } else if (query == "top") { |
1585 change = content::SCREEN_ORIENTATION_TOP; | 188 change = content::SCREEN_ORIENTATION_TOP; |
1586 } else if (query == "bottom") { | 189 } else if (query == "bottom") { |
1587 change = content::SCREEN_ORIENTATION_BOTTOM; | 190 change = content::SCREEN_ORIENTATION_BOTTOM; |
1588 } else { | 191 } else { |
1589 NOTREACHED() << "Unknown orientation"; | 192 NOTREACHED() << "Unknown orientation"; |
1590 } | 193 } |
1591 sensors::Provider::GetInstance()->ScreenOrientationChanged(change); | 194 sensors::Provider::GetInstance()->ScreenOrientationChanged(change); |
1592 // Nothing to communicate to the user, so show a blank page. | |
1593 host = chrome::kChromeUIBlankHost; | |
1594 *url = GURL(chrome::kChromeUIBlankHost); | |
1595 #endif | |
1596 } | |
1597 | |
1598 // Initialize any potentially corresponding AboutSource handler. | |
1599 InitializeAboutDataSource(host, browser_context); | |
1600 return true; | |
1601 } | |
1602 | |
1603 bool HandleNonNavigationAboutURL(const GURL& url) { | |
1604 // chrome://ipc/ is currently buggy, so we disable it for official builds. | |
1605 #if !defined(OFFICIAL_BUILD) | |
1606 | |
1607 #if (defined(OS_MACOSX) || defined(OS_WIN)) && defined(IPC_MESSAGE_LOG_ENABLED) | |
1608 if (LowerCaseEqualsASCII(url.spec(), chrome::kChromeUIIPCURL)) { | |
1609 // Run the dialog. This will re-use the existing one if it's already up. | |
1610 browser::ShowAboutIPCDialog(); | |
1611 return true; | 195 return true; |
1612 } | 196 } |
1613 #endif | 197 #endif |
1614 | 198 |
1615 #endif // OFFICIAL_BUILD | |
1616 | |
1617 return false; | 199 return false; |
1618 } | 200 } |
1619 | 201 |
1620 std::vector<std::string> ChromePaths() { | 202 std::vector<std::string> ChromePaths() { |
1621 std::vector<std::string> paths; | 203 std::vector<std::string> paths; |
1622 paths.reserve(arraysize(kChromePaths)); | 204 paths.reserve(arraysize(kChromePaths)); |
1623 for (size_t i = 0; i < arraysize(kChromePaths); i++) | 205 for (size_t i = 0; i < arraysize(kChromePaths); i++) |
1624 paths.push_back(kChromePaths[i]); | 206 paths.push_back(kChromePaths[i]); |
1625 return paths; | 207 return paths; |
1626 } | 208 } |
| 209 |
| 210 #if defined(USE_TCMALLOC) |
| 211 // static |
| 212 AboutTcmallocOutputs* AboutTcmallocOutputs::GetInstance() { |
| 213 return Singleton<AboutTcmallocOutputs>::get(); |
| 214 } |
| 215 |
| 216 AboutTcmallocOutputs::AboutTcmallocOutputs() {} |
| 217 |
| 218 AboutTcmallocOutputs::~AboutTcmallocOutputs() {} |
| 219 |
| 220 // Glue between the callback task and the method in the singleton. |
| 221 void AboutTcmallocRendererCallback(base::ProcessId pid, |
| 222 const std::string& output) { |
| 223 AboutTcmallocOutputs::GetInstance()->RendererCallback(pid, output); |
| 224 } |
| 225 #endif |
OLD | NEW |