| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 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/ui/webui/about_ui.h" | 5 #include "chrome/browser/ui/webui/about_ui.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 #include "base/strings/stringprintf.h" | 30 #include "base/strings/stringprintf.h" |
| 31 #include "base/strings/utf_string_conversions.h" | 31 #include "base/strings/utf_string_conversions.h" |
| 32 #include "base/threading/thread.h" | 32 #include "base/threading/thread.h" |
| 33 #include "base/values.h" | 33 #include "base/values.h" |
| 34 #include "build/build_config.h" | 34 #include "build/build_config.h" |
| 35 #include "chrome/browser/about_flags.h" | 35 #include "chrome/browser/about_flags.h" |
| 36 #include "chrome/browser/browser_process.h" | 36 #include "chrome/browser/browser_process.h" |
| 37 #include "chrome/browser/defaults.h" | 37 #include "chrome/browser/defaults.h" |
| 38 #include "chrome/browser/memory/tab_manager.h" | 38 #include "chrome/browser/memory/tab_manager.h" |
| 39 #include "chrome/browser/memory/tab_stats.h" | 39 #include "chrome/browser/memory/tab_stats.h" |
| 40 #include "chrome/browser/memory_details.h" | |
| 41 #include "chrome/browser/net/predictor.h" | 40 #include "chrome/browser/net/predictor.h" |
| 42 #include "chrome/browser/profiles/profile.h" | 41 #include "chrome/browser/profiles/profile.h" |
| 43 #include "chrome/browser/profiles/profile_manager.h" | 42 #include "chrome/browser/profiles/profile_manager.h" |
| 44 #include "chrome/browser/ui/browser_dialogs.h" | 43 #include "chrome/browser/ui/browser_dialogs.h" |
| 45 #include "chrome/common/chrome_paths.h" | 44 #include "chrome/common/chrome_paths.h" |
| 46 #include "chrome/common/url_constants.h" | 45 #include "chrome/common/url_constants.h" |
| 47 #include "chrome/grit/chromium_strings.h" | 46 #include "chrome/grit/chromium_strings.h" |
| 48 #include "chrome/grit/generated_resources.h" | 47 #include "chrome/grit/generated_resources.h" |
| 49 #include "chrome/grit/locale_settings.h" | 48 #include "chrome/grit/locale_settings.h" |
| 50 #include "components/strings/grit/components_locale_settings.h" | 49 #include "components/strings/grit/components_locale_settings.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 #endif | 88 #endif |
| 90 | 89 |
| 91 using base::Time; | 90 using base::Time; |
| 92 using base::TimeDelta; | 91 using base::TimeDelta; |
| 93 using content::BrowserThread; | 92 using content::BrowserThread; |
| 94 using content::WebContents; | 93 using content::WebContents; |
| 95 | 94 |
| 96 namespace { | 95 namespace { |
| 97 | 96 |
| 98 const char kCreditsJsPath[] = "credits.js"; | 97 const char kCreditsJsPath[] = "credits.js"; |
| 99 const char kMemoryJsPath[] = "memory.js"; | |
| 100 const char kMemoryCssPath[] = "about_memory.css"; | |
| 101 const char kStatsJsPath[] = "stats.js"; | 98 const char kStatsJsPath[] = "stats.js"; |
| 102 const char kStringsJsPath[] = "strings.js"; | 99 const char kStringsJsPath[] = "strings.js"; |
| 103 | 100 |
| 104 // When you type about:memory, it actually loads this intermediate URL that | |
| 105 // redirects you to the final page. This avoids the problem where typing | |
| 106 // "about:memory" on the new tab page or any other page where a process | |
| 107 // transition would occur to the about URL will cause some confusion. | |
| 108 // | |
| 109 // The problem is that during the processing of the memory page, there are two | |
| 110 // processes active, the original and the destination one. This can create the | |
| 111 // impression that we're using more resources than we actually are. This | |
| 112 // redirect solves the problem by eliminating the process transition during the | |
| 113 // time that about memory is being computed. | |
| 114 std::string GetAboutMemoryRedirectResponse(Profile* profile) { | |
| 115 return base::StringPrintf("<meta http-equiv='refresh' content='0;%s'>", | |
| 116 chrome::kChromeUIMemoryRedirectURL); | |
| 117 } | |
| 118 | |
| 119 // Handling about:memory is complicated enough to encapsulate its related | |
| 120 // methods into a single class. The user should create it (on the heap) and call | |
| 121 // its |StartFetch()| method. | |
| 122 class AboutMemoryHandler : public MemoryDetails { | |
| 123 public: | |
| 124 explicit AboutMemoryHandler( | |
| 125 const content::URLDataSource::GotDataCallback& callback) | |
| 126 : callback_(callback) { | |
| 127 } | |
| 128 | |
| 129 void OnDetailsAvailable() override; | |
| 130 | |
| 131 private: | |
| 132 ~AboutMemoryHandler() override {} | |
| 133 | |
| 134 void BindProcessMetrics(base::DictionaryValue* data, | |
| 135 ProcessMemoryInformation* info); | |
| 136 void AppendProcess(base::ListValue* child_data, | |
| 137 ProcessMemoryInformation* info); | |
| 138 | |
| 139 content::URLDataSource::GotDataCallback callback_; | |
| 140 | |
| 141 DISALLOW_COPY_AND_ASSIGN(AboutMemoryHandler); | |
| 142 }; | |
| 143 | |
| 144 #if defined(OS_CHROMEOS) | 101 #if defined(OS_CHROMEOS) |
| 145 | 102 |
| 146 const char kKeyboardUtilsPath[] = "keyboard_utils.js"; | 103 const char kKeyboardUtilsPath[] = "keyboard_utils.js"; |
| 147 | 104 |
| 148 // chrome://terms falls back to offline page after kOnlineTermsTimeoutSec. | 105 // chrome://terms falls back to offline page after kOnlineTermsTimeoutSec. |
| 149 const int kOnlineTermsTimeoutSec = 7; | 106 const int kOnlineTermsTimeoutSec = 7; |
| 150 | 107 |
| 151 // Helper class that fetches the online Chrome OS terms. Empty string is | 108 // Helper class that fetches the online Chrome OS terms. Empty string is |
| 152 // returned once fetching failed or exceeded |kOnlineTermsTimeoutSec|. | 109 // returned once fetching failed or exceeded |kOnlineTermsTimeoutSec|. |
| 153 class ChromeOSOnlineTermsHandler : public net::URLFetcherDelegate { | 110 class ChromeOSOnlineTermsHandler : public net::URLFetcherDelegate { |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 } | 635 } |
| 679 | 636 |
| 680 Profile* profile_; | 637 Profile* profile_; |
| 681 | 638 |
| 682 // Callback to run with the response. | 639 // Callback to run with the response. |
| 683 content::URLDataSource::GotDataCallback callback_; | 640 content::URLDataSource::GotDataCallback callback_; |
| 684 | 641 |
| 685 DISALLOW_COPY_AND_ASSIGN(AboutDnsHandler); | 642 DISALLOW_COPY_AND_ASSIGN(AboutDnsHandler); |
| 686 }; | 643 }; |
| 687 | 644 |
| 688 void FinishMemoryDataRequest( | |
| 689 const std::string& path, | |
| 690 const content::URLDataSource::GotDataCallback& callback) { | |
| 691 if (path == kStringsJsPath) { | |
| 692 // The AboutMemoryHandler cleans itself up, but |StartFetch()| will want | |
| 693 // the refcount to be greater than 0. | |
| 694 scoped_refptr<AboutMemoryHandler> handler(new AboutMemoryHandler(callback)); | |
| 695 handler->StartFetch(MemoryDetails::FROM_ALL_BROWSERS); | |
| 696 } else { | |
| 697 int id = IDR_ABOUT_MEMORY_HTML; | |
| 698 if (path == kMemoryJsPath) { | |
| 699 id = IDR_ABOUT_MEMORY_JS; | |
| 700 } else if (path == kMemoryCssPath) { | |
| 701 id = IDR_ABOUT_MEMORY_CSS; | |
| 702 } | |
| 703 | |
| 704 std::string result = | |
| 705 ResourceBundle::GetSharedInstance().GetRawDataResource(id).as_string(); | |
| 706 callback.Run(base::RefCountedString::TakeString(&result)); | |
| 707 } | |
| 708 } | |
| 709 | |
| 710 #if defined(OS_LINUX) || defined(OS_OPENBSD) | 645 #if defined(OS_LINUX) || defined(OS_OPENBSD) |
| 711 std::string AboutLinuxProxyConfig() { | 646 std::string AboutLinuxProxyConfig() { |
| 712 std::string data; | 647 std::string data; |
| 713 AppendHeader(&data, 0, | 648 AppendHeader(&data, 0, |
| 714 l10n_util::GetStringUTF8(IDS_ABOUT_LINUX_PROXY_CONFIG_TITLE)); | 649 l10n_util::GetStringUTF8(IDS_ABOUT_LINUX_PROXY_CONFIG_TITLE)); |
| 715 data.append("<style>body { max-width: 70ex; padding: 2ex 5ex; }</style>"); | 650 data.append("<style>body { max-width: 70ex; padding: 2ex 5ex; }</style>"); |
| 716 AppendBody(&data); | 651 AppendBody(&data); |
| 717 base::FilePath binary = base::CommandLine::ForCurrentProcess()->GetProgram(); | 652 base::FilePath binary = base::CommandLine::ForCurrentProcess()->GetProgram(); |
| 718 data.append(l10n_util::GetStringFUTF8( | 653 data.append(l10n_util::GetStringFUTF8( |
| 719 IDS_ABOUT_LINUX_PROXY_CONFIG_BODY, | 654 IDS_ABOUT_LINUX_PROXY_CONFIG_BODY, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 data.append("<p style='color: red'>"); | 720 data.append("<p style='color: red'>"); |
| 786 data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_BAD)); | 721 data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_BAD)); |
| 787 } | 722 } |
| 788 data.append("</p>"); | 723 data.append("</p>"); |
| 789 | 724 |
| 790 AppendFooter(&data); | 725 AppendFooter(&data); |
| 791 return data; | 726 return data; |
| 792 } | 727 } |
| 793 #endif | 728 #endif |
| 794 | 729 |
| 795 // AboutMemoryHandler ---------------------------------------------------------- | |
| 796 | |
| 797 // Helper for AboutMemory to bind results from a ProcessMetrics object | |
| 798 // to a DictionaryValue. Fills ws_usage and comm_usage so that the objects | |
| 799 // can be used in caller's scope (e.g for appending to a net total). | |
| 800 void AboutMemoryHandler::BindProcessMetrics(base::DictionaryValue* data, | |
| 801 ProcessMemoryInformation* info) { | |
| 802 DCHECK(data && info); | |
| 803 | |
| 804 // Bind metrics to dictionary. | |
| 805 data->SetInteger("ws_priv", static_cast<int>(info->working_set.priv)); | |
| 806 data->SetInteger("ws_shareable", | |
| 807 static_cast<int>(info->working_set.shareable)); | |
| 808 data->SetInteger("ws_shared", static_cast<int>(info->working_set.shared)); | |
| 809 data->SetInteger("comm_priv", static_cast<int>(info->committed.priv)); | |
| 810 data->SetInteger("comm_map", static_cast<int>(info->committed.mapped)); | |
| 811 data->SetInteger("comm_image", static_cast<int>(info->committed.image)); | |
| 812 data->SetInteger("pid", info->pid); | |
| 813 data->SetString("version", info->version); | |
| 814 data->SetInteger("processes", info->num_processes); | |
| 815 } | |
| 816 | |
| 817 // Helper for AboutMemory to append memory usage information for all | |
| 818 // sub-processes (i.e. renderers, plugins) used by Chrome. | |
| 819 void AboutMemoryHandler::AppendProcess(base::ListValue* child_data, | |
| 820 ProcessMemoryInformation* info) { | |
| 821 DCHECK(child_data && info); | |
| 822 | |
| 823 // Append a new DictionaryValue for this renderer to our list. | |
| 824 base::DictionaryValue* child = new base::DictionaryValue(); | |
| 825 child_data->Append(child); | |
| 826 BindProcessMetrics(child, info); | |
| 827 | |
| 828 std::string child_label( | |
| 829 ProcessMemoryInformation::GetFullTypeNameInEnglish(info->process_type, | |
| 830 info->renderer_type)); | |
| 831 if (info->is_diagnostics) | |
| 832 child_label.append(" (diagnostics)"); | |
| 833 child->SetString("child_name", child_label); | |
| 834 base::ListValue* titles = new base::ListValue(); | |
| 835 child->Set("titles", titles); | |
| 836 for (size_t i = 0; i < info->titles.size(); ++i) | |
| 837 titles->Append(new base::StringValue(info->titles[i])); | |
| 838 } | |
| 839 | |
| 840 void AboutMemoryHandler::OnDetailsAvailable() { | |
| 841 // the root of the JSON hierarchy for about:memory jstemplate | |
| 842 scoped_ptr<base::DictionaryValue> root(new base::DictionaryValue); | |
| 843 base::ListValue* browsers = new base::ListValue(); | |
| 844 root->Set("browsers", browsers); | |
| 845 | |
| 846 const std::vector<ProcessData>& browser_processes = processes(); | |
| 847 | |
| 848 // Aggregate per-process data into browser summary data. | |
| 849 base::string16 log_string; | |
| 850 for (size_t index = 0; index < browser_processes.size(); index++) { | |
| 851 if (browser_processes[index].processes.empty()) | |
| 852 continue; | |
| 853 | |
| 854 // Sum the information for the processes within this browser. | |
| 855 ProcessMemoryInformation aggregate; | |
| 856 ProcessMemoryInformationList::const_iterator iterator; | |
| 857 iterator = browser_processes[index].processes.begin(); | |
| 858 aggregate.pid = iterator->pid; | |
| 859 aggregate.version = iterator->version; | |
| 860 while (iterator != browser_processes[index].processes.end()) { | |
| 861 if (!iterator->is_diagnostics || | |
| 862 browser_processes[index].processes.size() == 1) { | |
| 863 aggregate.working_set.priv += iterator->working_set.priv; | |
| 864 aggregate.working_set.shared += iterator->working_set.shared; | |
| 865 aggregate.working_set.shareable += iterator->working_set.shareable; | |
| 866 aggregate.committed.priv += iterator->committed.priv; | |
| 867 aggregate.committed.mapped += iterator->committed.mapped; | |
| 868 aggregate.committed.image += iterator->committed.image; | |
| 869 aggregate.num_processes++; | |
| 870 } | |
| 871 ++iterator; | |
| 872 } | |
| 873 base::DictionaryValue* browser_data = new base::DictionaryValue(); | |
| 874 browsers->Append(browser_data); | |
| 875 browser_data->SetString("name", browser_processes[index].name); | |
| 876 | |
| 877 BindProcessMetrics(browser_data, &aggregate); | |
| 878 | |
| 879 // We log memory info as we record it. | |
| 880 if (!log_string.empty()) | |
| 881 log_string += base::ASCIIToUTF16(", "); | |
| 882 log_string += browser_processes[index].name + base::ASCIIToUTF16(", ") + | |
| 883 base::SizeTToString16(aggregate.working_set.priv) + | |
| 884 base::ASCIIToUTF16(", ") + | |
| 885 base::SizeTToString16(aggregate.working_set.shared) + | |
| 886 base::ASCIIToUTF16(", ") + | |
| 887 base::SizeTToString16(aggregate.working_set.shareable); | |
| 888 } | |
| 889 if (!log_string.empty()) | |
| 890 VLOG(1) << "memory: " << log_string; | |
| 891 | |
| 892 // Set the browser & renderer detailed process data. | |
| 893 base::DictionaryValue* browser_data = new base::DictionaryValue(); | |
| 894 root->Set("browzr_data", browser_data); | |
| 895 base::ListValue* child_data = new base::ListValue(); | |
| 896 root->Set("child_data", child_data); | |
| 897 | |
| 898 ProcessData process = browser_processes[0]; // Chrome is the first browser. | |
| 899 root->SetString("current_browser_name", process.name); | |
| 900 | |
| 901 for (size_t index = 0; index < process.processes.size(); index++) { | |
| 902 if (process.processes[index].process_type == content::PROCESS_TYPE_BROWSER) | |
| 903 BindProcessMetrics(browser_data, &process.processes[index]); | |
| 904 else | |
| 905 AppendProcess(child_data, &process.processes[index]); | |
| 906 } | |
| 907 | |
| 908 root->SetBoolean("show_other_browsers", | |
| 909 browser_defaults::kShowOtherBrowsersInAboutMemory); | |
| 910 | |
| 911 base::DictionaryValue load_time_data; | |
| 912 load_time_data.SetString( | |
| 913 "summary_desc", | |
| 914 l10n_util::GetStringUTF16(IDS_MEMORY_USAGE_SUMMARY_DESC)); | |
| 915 const std::string& app_locale = g_browser_process->GetApplicationLocale(); | |
| 916 webui::SetLoadTimeDataDefaults(app_locale, &load_time_data); | |
| 917 load_time_data.Set("jstemplateData", root.release()); | |
| 918 | |
| 919 std::string data; | |
| 920 webui::AppendJsonJS(&load_time_data, &data); | |
| 921 callback_.Run(base::RefCountedString::TakeString(&data)); | |
| 922 } | |
| 923 | |
| 924 } // namespace | 730 } // namespace |
| 925 | 731 |
| 926 // AboutUIHTMLSource ---------------------------------------------------------- | 732 // AboutUIHTMLSource ---------------------------------------------------------- |
| 927 | 733 |
| 928 AboutUIHTMLSource::AboutUIHTMLSource(const std::string& source_name, | 734 AboutUIHTMLSource::AboutUIHTMLSource(const std::string& source_name, |
| 929 Profile* profile) | 735 Profile* profile) |
| 930 : source_name_(source_name), | 736 : source_name_(source_name), |
| 931 profile_(profile) {} | 737 profile_(profile) {} |
| 932 | 738 |
| 933 AboutUIHTMLSource::~AboutUIHTMLSource() {} | 739 AboutUIHTMLSource::~AboutUIHTMLSource() {} |
| (...skipping 26 matching lines...) Expand all Loading... |
| 960 } else if (source_name_ == chrome::kChromeUIDiscardsHost) { | 766 } else if (source_name_ == chrome::kChromeUIDiscardsHost) { |
| 961 response = AboutDiscards(path); | 767 response = AboutDiscards(path); |
| 962 #endif | 768 #endif |
| 963 } else if (source_name_ == chrome::kChromeUIDNSHost) { | 769 } else if (source_name_ == chrome::kChromeUIDNSHost) { |
| 964 AboutDnsHandler::Start(profile(), callback); | 770 AboutDnsHandler::Start(profile(), callback); |
| 965 return; | 771 return; |
| 966 #if defined(OS_LINUX) || defined(OS_OPENBSD) | 772 #if defined(OS_LINUX) || defined(OS_OPENBSD) |
| 967 } else if (source_name_ == chrome::kChromeUILinuxProxyConfigHost) { | 773 } else if (source_name_ == chrome::kChromeUILinuxProxyConfigHost) { |
| 968 response = AboutLinuxProxyConfig(); | 774 response = AboutLinuxProxyConfig(); |
| 969 #endif | 775 #endif |
| 970 } else if (source_name_ == chrome::kChromeUIMemoryHost) { | |
| 971 response = GetAboutMemoryRedirectResponse(profile()); | |
| 972 } else if (source_name_ == chrome::kChromeUIMemoryRedirectHost) { | |
| 973 FinishMemoryDataRequest(path, callback); | |
| 974 return; | |
| 975 #if defined(OS_CHROMEOS) | 776 #if defined(OS_CHROMEOS) |
| 976 } else if (source_name_ == chrome::kChromeUIOSCreditsHost) { | 777 } else if (source_name_ == chrome::kChromeUIOSCreditsHost) { |
| 977 ChromeOSCreditsHandler::Start(path, callback); | 778 ChromeOSCreditsHandler::Start(path, callback); |
| 978 return; | 779 return; |
| 979 #endif | 780 #endif |
| 980 #if defined(OS_LINUX) || defined(OS_OPENBSD) | 781 #if defined(OS_LINUX) || defined(OS_OPENBSD) |
| 981 } else if (source_name_ == chrome::kChromeUISandboxHost) { | 782 } else if (source_name_ == chrome::kChromeUISandboxHost) { |
| 982 response = AboutSandbox(); | 783 response = AboutSandbox(); |
| 983 #endif | 784 #endif |
| 984 #if !defined(OS_ANDROID) | 785 #if !defined(OS_ANDROID) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1001 std::string html_copy(html); | 802 std::string html_copy(html); |
| 1002 callback.Run(base::RefCountedString::TakeString(&html_copy)); | 803 callback.Run(base::RefCountedString::TakeString(&html_copy)); |
| 1003 } | 804 } |
| 1004 | 805 |
| 1005 std::string AboutUIHTMLSource::GetMimeType(const std::string& path) const { | 806 std::string AboutUIHTMLSource::GetMimeType(const std::string& path) const { |
| 1006 if (path == kCreditsJsPath || | 807 if (path == kCreditsJsPath || |
| 1007 #if defined(OS_CHROMEOS) | 808 #if defined(OS_CHROMEOS) |
| 1008 path == kKeyboardUtilsPath || | 809 path == kKeyboardUtilsPath || |
| 1009 #endif | 810 #endif |
| 1010 path == kStatsJsPath || | 811 path == kStatsJsPath || |
| 1011 path == kStringsJsPath || | 812 path == kStringsJsPath) { |
| 1012 path == kMemoryJsPath) { | |
| 1013 return "application/javascript"; | 813 return "application/javascript"; |
| 1014 } | 814 } |
| 1015 return "text/html"; | 815 return "text/html"; |
| 1016 } | 816 } |
| 1017 | 817 |
| 1018 bool AboutUIHTMLSource::ShouldAddContentSecurityPolicy() const { | 818 bool AboutUIHTMLSource::ShouldAddContentSecurityPolicy() const { |
| 1019 #if defined(OS_CHROMEOS) | 819 #if defined(OS_CHROMEOS) |
| 1020 if (source_name_ == chrome::kChromeUIOSCreditsHost) | 820 if (source_name_ == chrome::kChromeUIOSCreditsHost) |
| 1021 return false; | 821 return false; |
| 1022 #endif | 822 #endif |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1038 Profile* profile = Profile::FromWebUI(web_ui); | 838 Profile* profile = Profile::FromWebUI(web_ui); |
| 1039 | 839 |
| 1040 #if defined(ENABLE_THEMES) | 840 #if defined(ENABLE_THEMES) |
| 1041 // Set up the chrome://theme/ source. | 841 // Set up the chrome://theme/ source. |
| 1042 ThemeSource* theme = new ThemeSource(profile); | 842 ThemeSource* theme = new ThemeSource(profile); |
| 1043 content::URLDataSource::Add(profile, theme); | 843 content::URLDataSource::Add(profile, theme); |
| 1044 #endif | 844 #endif |
| 1045 | 845 |
| 1046 content::URLDataSource::Add(profile, new AboutUIHTMLSource(name, profile)); | 846 content::URLDataSource::Add(profile, new AboutUIHTMLSource(name, profile)); |
| 1047 } | 847 } |
| OLD | NEW |