Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: chrome/browser/browser_about_handler.cc

Issue 8623001: Move remaining about: handlers to webUI. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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("/&lt;secs&gt;)");
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, "&nbsp;&nbsp;", IDS_ABOUT_SANDBOX_PID_NAMESPACES,
1099 status & ZygoteHost::kSandboxPIDNS);
1100 AboutSandboxRow(&data, "&nbsp;&nbsp;", 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
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
OLDNEW
« no previous file with comments | « chrome/browser/browser_about_handler.h ('k') | chrome/browser/browser_about_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698