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 |