177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt// Copyright (c) 2012 The Chromium Authors. All rights reserved. 277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt// Use of this source code is governed by a BSD-style license that can be 377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt// found in the LICENSE file. 477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "chrome/browser/ui/webui/about_ui.h" 677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include <algorithm> 877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include <string> 977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include <utility> 1077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include <vector> 1177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 1277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/bind.h" 1377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/bind_helpers.h" 1477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/callback.h" 1577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/command_line.h" 1677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/file_util.h" 1777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/i18n/number_formatting.h" 1877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/json/json_writer.h" 1977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/memory/singleton.h" 2077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/metrics/statistics_recorder.h" 2177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/metrics/stats_table.h" 2277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/path_service.h" 2377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/strings/string_number_conversions.h" 2477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/strings/string_piece.h" 2577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/strings/string_util.h" 2677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/strings/stringprintf.h" 2777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "base/strings/utf_string_conversions.h" 28f6ca4a304bf920ea6913b08638fb8eb3e020d446Eric Anholt#include "base/threading/thread.h" 29ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "base/values.h" 30ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "chrome/browser/about_flags.h" 31ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "chrome/browser/browser_process.h" 32ecadb51bbcb972a79f3ed79e65a7986b9396e757Brian Paul#include "chrome/browser/defaults.h" 332d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg#include "chrome/browser/memory_details.h" 34d7322c9d420e484bc3c7cecb873b04cf7da7f33aKristian Høgsberg#include "chrome/browser/net/predictor.h" 3545a56e4730a74a012ad712fd9b6013d900b04742Vinson Lee#include "chrome/browser/profiles/profile.h" 366c244b0f326504ae6add1ddcb407e73c3e72da78Brian Paul#include "chrome/browser/profiles/profile_manager.h" 3777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "chrome/browser/ui/browser_dialogs.h" 3877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "chrome/common/chrome_paths.h" 3977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "chrome/common/net/url_fixer_upper.h" 4077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "chrome/common/render_messages.h" 41a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "chrome/common/url_constants.h" 42a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "content/public/browser/browser_thread.h" 43e9bf3e4cc9a7e4bcd4c45bd707541d26ecdf0409Jesse Barnes#include "content/public/browser/render_process_host.h" 44fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "content/public/browser/render_view_host.h" 45fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "content/public/browser/url_data_source.h" 46fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "content/public/browser/web_contents.h" 47f75843a517bd188639e6866db2a7b04de3524e16Dave Airlie#include "content/public/common/content_client.h" 48fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "content/public/common/process_type.h" 49fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "google_apis/gaia/google_service_auth_error.h" 50fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "grit/browser_resources.h" 51fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "grit/chromium_strings.h" 52fe91c05b5494b889c8adda77ff562712116d2e59Eric Anholt#include "grit/generated_resources.h" 531ba96651e12b3c74fb9c8f5a61b183ef36a27b1eEric Anholt#include "grit/locale_settings.h" 548e7a8d65931a650534e0f5c4e0d8118cd6f7636eEric Anholt#include "net/base/escape.h" 558e7a8d65931a650534e0f5c4e0d8118cd6f7636eEric Anholt#include "net/base/load_flags.h" 568e7a8d65931a650534e0f5c4e0d8118cd6f7636eEric Anholt#include "net/base/net_util.h" 571ba96651e12b3c74fb9c8f5a61b183ef36a27b1eEric Anholt#include "net/http/http_response_headers.h" 58b30dc2c66aeaad6661eef515a08a3da89aa07cb2Eric Anholt#include "net/url_request/url_fetcher.h" 59b30dc2c66aeaad6661eef515a08a3da89aa07cb2Eric Anholt#include "net/url_request/url_request_status.h" 60b30dc2c66aeaad6661eef515a08a3da89aa07cb2Eric Anholt#include "ui/base/l10n/l10n_util.h" 61b30dc2c66aeaad6661eef515a08a3da89aa07cb2Eric Anholt#include "ui/base/resource/resource_bundle.h" 62a58514cc9c5cc5867f9140700462c5ac5749550dEric Anholt#include "ui/base/webui/jstemplate_builder.h" 63862a2a55b35d1dec9224b025a6e7a0cf8593a6a7Eric Anholt#include "ui/base/webui/web_ui_util.h" 64862a2a55b35d1dec9224b025a6e7a0cf8593a6a7Eric Anholt#include "url/gurl.h" 65862a2a55b35d1dec9224b025a6e7a0cf8593a6a7Eric Anholt 66a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#if defined(ENABLE_THEMES) 67a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "chrome/browser/ui/webui/theme_source.h" 68a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#endif 69acba9c1771d653126fd6f604cb80c050b9e8ffb3Michel Dänzer 70a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#if defined(OS_LINUX) || defined(OS_OPENBSD) 71a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "content/public/browser/zygote_host_linux.h" 72a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "content/public/common/sandbox_linux.h" 7340bc2748c2781600c748e546160bcc2aab637825Eric Anholt#endif 74f3687284c12f34268172b9c60e2effd697162129Eric Anholt 7581aa5d717bd0098608e9cc292b316293800c7e11Eric Anholt#if defined(OS_WIN) 7681aa5d717bd0098608e9cc292b316293800c7e11Eric Anholt#include "chrome/browser/enumerate_modules_model_win.h" 7781aa5d717bd0098608e9cc292b316293800c7e11Eric Anholt#endif 7881aa5d717bd0098608e9cc292b316293800c7e11Eric Anholt 79a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#if defined(OS_CHROMEOS) 80a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "chrome/browser/browser_process_platform_part_chromeos.h" 81a0e453a5eca7ed4b57a7f4c1e418d368815e3957Eric Anholt#include "chrome/browser/chromeos/customization_document.h" 821e4677a61f0576c32e65e9202fa08e81e1162f65Eric Anholt#include "chrome/browser/chromeos/memory/oom_priority_manager.h" 8377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#include "chromeos/chromeos_switches.h" 84df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholt#endif 85df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholt 86df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtusing base::Time; 87df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtusing base::TimeDelta; 88df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtusing content::BrowserThread; 89df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtusing content::WebContents; 90df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholt 91df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtnamespace { 92df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholt 93df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtconst char kCreditsJsPath[] = "credits.js"; 94df9f89154471ec162227ebce1681c5010f64e6e6Eric Anholtconst char kMemoryJsPath[] = "memory.js"; 9577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholtconst char kMemoryCssPath[] = "about_memory.css"; 9685063f14ea431b586d710f249563fc73481552c7Eric Anholtconst char kStatsJsPath[] = "stats.js"; 9777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholtconst char kStringsJsPath[] = "strings.js"; 9877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 996d48779c7e5c9002d1bec4b1266ca05a474218efKristian Høgsberg#if defined(OS_CHROMEOS) 1006d48779c7e5c9002d1bec4b1266ca05a474218efKristian Høgsberg// chrome://terms falls back to offline page after kOnlineTermsTimeoutSec. 1016d48779c7e5c9002d1bec4b1266ca05a474218efKristian Høgsbergconst int kOnlineTermsTimeoutSec = 7; 10266175aac7609ad314f25fbdff0d3958af310dc24Eric Anholt#endif // defined(OS_CHROMEOS) 1036d48779c7e5c9002d1bec4b1266ca05a474218efKristian Høgsberg 1046d48779c7e5c9002d1bec4b1266ca05a474218efKristian Høgsberg// When you type about:memory, it actually loads this intermediate URL that 1057c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// redirects you to the final page. This avoids the problem where typing 1067c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// "about:memory" on the new tab page or any other page where a process 1077c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// transition would occur to the about URL will cause some confusion. 108dea5e57861ec998cb7ee913a8819752cb9fa946bEric Anholt// 109dea5e57861ec998cb7ee913a8819752cb9fa946bEric Anholt// The problem is that during the processing of the memory page, there are two 1107c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// processes active, the original and the destination one. This can create the 1117c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// impression that we're using more resources than we actually are. This 1127c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// redirect solves the problem by eliminating the process transition during the 1137c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// time that about memory is being computed. 1142e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunkestd::string GetAboutMemoryRedirectResponse(Profile* profile) { 115e67c338b415c983bee570e6644b9684d8d1fc99bKristian Høgsberg return base::StringPrintf("<meta http-equiv='refresh' content='0;%s'>", 1168d68a90e225d831a395ba788e425cb717eec1f9aChris Wilson chrome::kChromeUIMemoryRedirectURL); 1178d68a90e225d831a395ba788e425cb717eec1f9aChris Wilson} 1187c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg 1197c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// Handling about:memory is complicated enough to encapsulate its related 1207c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// methods into a single class. The user should create it (on the heap) and call 1217c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg// its |StartFetch()| method. 1227c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsbergclass AboutMemoryHandler : public MemoryDetails { 123e67c338b415c983bee570e6644b9684d8d1fc99bKristian Høgsberg public: 1247c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg explicit AboutMemoryHandler( 1257c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg const content::URLDataSource::GotDataCallback& callback) 126c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg : callback_(callback) { 1279ec0b2a45e18c045fd3dbcdf846fad7faf97494cKristian Høgsberg } 128c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 129c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg virtual void OnDetailsAvailable() OVERRIDE; 130c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 1319ec0b2a45e18c045fd3dbcdf846fad7faf97494cKristian Høgsberg private: 132c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg virtual ~AboutMemoryHandler() {} 133c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 134c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg void BindProcessMetrics(DictionaryValue* data, 135c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg ProcessMemoryInformation* info); 136c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg void AppendProcess(ListValue* child_data, ProcessMemoryInformation* info); 137c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 138c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg content::URLDataSource::GotDataCallback callback_; 139c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 140c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg DISALLOW_COPY_AND_ASSIGN(AboutMemoryHandler); 141c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg}; 142c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 143c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg#if defined(OS_CHROMEOS) 144c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 145c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg// Helper class that fetches the online Chrome OS terms. Empty string is 146c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg// returned once fetching failed or exceeded |kOnlineTermsTimeoutSec|. 147c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsbergclass ChromeOSOnlineTermsHandler : public net::URLFetcherDelegate { 148c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg public: 149c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg typedef base::Callback<void (ChromeOSOnlineTermsHandler*)> FetchCallback; 150c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 151c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg explicit ChromeOSOnlineTermsHandler(const FetchCallback& callback, 152c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg const std::string& locale) 153c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg : fetch_callback_(callback) { 154c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg std::string eula_URL = base::StringPrintf(chrome::kOnlineEulaURLPath, 1559fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu locale.c_str()); 1569fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu eula_fetcher_.reset(net::URLFetcher::Create(0 /* ID used for testing */, 1579fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu GURL(eula_URL), 1589fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu net::URLFetcher::GET, 1599fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu this)); 160c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg eula_fetcher_->SetRequestContext( 161c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg g_browser_process->system_request_context()); 162c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg eula_fetcher_->AddExtraRequestHeader("Accept: text/html"); 163c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg eula_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 164c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg net::LOAD_DO_NOT_SAVE_COOKIES | 165c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg net::LOAD_DISABLE_CACHE); 166c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg eula_fetcher_->Start(); 167c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // Abort the download attempt if it takes longer than one minute. 1689ec0b2a45e18c045fd3dbcdf846fad7faf97494cKristian Høgsberg download_timer_.Start(FROM_HERE, 1699087ba128089ed0dc00e6eb38f37126fb7557d3bKristian Høgsberg base::TimeDelta::FromSeconds(kOnlineTermsTimeoutSec), 170c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg this, 171c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg &ChromeOSOnlineTermsHandler::OnDownloadTimeout); 172c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 173c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 174c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg void GetResponseResult(std::string* response_string) { 175c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg std::string mime_type; 176c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg if (!eula_fetcher_ || 177c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg !eula_fetcher_->GetStatus().is_success() || 178c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg eula_fetcher_->GetResponseCode() != 200 || 179c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg !eula_fetcher_->GetResponseHeaders()->GetMimeType(&mime_type) || 180c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg mime_type != "text/html" || 181c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg !eula_fetcher_->GetResponseAsString(response_string)) { 182c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg response_string->clear(); 183c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 184c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 185c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 186c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg private: 187c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // Prevents allocation on the stack. ChromeOSOnlineTermsHandler should be 188d7322c9d420e484bc3c7cecb873b04cf7da7f33aKristian Høgsberg // created by 'operator new'. |this| takes care of destruction. 189c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg virtual ~ChromeOSOnlineTermsHandler() {} 190c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 191c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // net::URLFetcherDelegate: 192c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE { 193c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg if (source != eula_fetcher_.get()) { 194c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg NOTREACHED() << "Callback from foreign URL fetcher"; 195c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg return; 196c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 197c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg fetch_callback_.Run(this); 198c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg delete this; 199c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 200c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 201c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg void OnDownloadTimeout() { 202c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg eula_fetcher_.reset(); 203c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg fetch_callback_.Run(this); 204c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg delete this; 205c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 206c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 207c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // Timer that enforces a timeout on the attempt to download the 208c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // ChromeOS Terms. 209c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg base::OneShotTimer<ChromeOSOnlineTermsHandler> download_timer_; 210c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 211c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // |fetch_callback_| called when fetching succeeded or failed. 212c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg FetchCallback fetch_callback_; 213c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 214c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // Helper to fetch online eula. 215c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg scoped_ptr<net::URLFetcher> eula_fetcher_; 216f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg 217f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg DISALLOW_COPY_AND_ASSIGN(ChromeOSOnlineTermsHandler); 218f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg}; 219f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg 220f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsbergclass ChromeOSTermsHandler 221f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg : public base::RefCountedThreadSafe<ChromeOSTermsHandler> { 222f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg public: 223f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg static void Start(const std::string& path, 224e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg const content::URLDataSource::GotDataCallback& callback) { 225f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg scoped_refptr<ChromeOSTermsHandler> handler( 226f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg new ChromeOSTermsHandler(path, callback)); 227e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg handler->StartOnUIThread(); 228e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg } 229e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg 230e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg private: 231e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg friend class base::RefCountedThreadSafe<ChromeOSTermsHandler>; 232e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg 233e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg ChromeOSTermsHandler(const std::string& path, 234f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg const content::URLDataSource::GotDataCallback& callback) 235f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg : path_(path), 236f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg callback_(callback), 237f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg // Previously we were using "initial locale" http://crbug.com/145142 238f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg locale_(g_browser_process->GetApplicationLocale()) { 239f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 240f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg 241f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg virtual ~ChromeOSTermsHandler() {} 242f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg 243f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg void StartOnUIThread() { 244f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 245f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg if (path_ == chrome::kOemEulaURLPath) { 246f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg // Load local OEM EULA from the disk. 247f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg BrowserThread::PostTask( 248f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg BrowserThread::FILE, FROM_HERE, 249f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg base::Bind(&ChromeOSTermsHandler::LoadOemEulaFileOnFileThread, this)); 250f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } else if (CommandLine::ForCurrentProcess()->HasSwitch( 251f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg chromeos::switches::kDisableOnlineEULA)) { 252f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg // Fallback to the local file. 253f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg BrowserThread::PostTask( 2549fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu BrowserThread::FILE, FROM_HERE, 2559fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu base::Bind(&ChromeOSTermsHandler::LoadEulaFileOnFileThread, this)); 2569fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu } else { 2579fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu // Try to load online version of ChromeOS terms first. 2589fe197c62611815ebe74248033271ad9fd07ae06Chia-I Wu // ChromeOSOnlineTermsHandler object destroys itself. 259f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg new ChromeOSOnlineTermsHandler( 260f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg base::Bind(&ChromeOSTermsHandler::OnOnlineEULAFetched, this), 261f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg locale_); 262f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 263f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 264f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg 265f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg void OnOnlineEULAFetched(ChromeOSOnlineTermsHandler* loader) { 266f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 267f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg loader->GetResponseResult(&contents_); 268e5169e9615e8391ea369415b356168717b8f7be0Kristian Høgsberg if (contents_.empty()) { 2692e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke // Load local ChromeOS terms from the file. 270f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg BrowserThread::PostTask( 271f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg BrowserThread::FILE, FROM_HERE, 272f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg base::Bind(&ChromeOSTermsHandler::LoadEulaFileOnFileThread, this)); 273f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } else { 274f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg ResponseOnUIThread(); 275f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 276f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 277f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg 278f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg void LoadOemEulaFileOnFileThread() { 279f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 280f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg const chromeos::StartupCustomizationDocument* customization = 281f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg chromeos::StartupCustomizationDocument::GetInstance(); 282f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg if (customization->IsReady()) { 283f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg base::FilePath oem_eula_file_path; 2842e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke if (net::FileURLToFilePath(GURL(customization->GetEULAPage(locale_)), 285f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg &oem_eula_file_path)) { 2868004a1cb95b8a195f3f4bbaa8d39d2f3297167deEric Anholt if (!base::ReadFileToString(oem_eula_file_path, &contents_)) { 2872e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke contents_.clear(); 288f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 289f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 290f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 2912e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke BrowserThread::PostTask( 292f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg BrowserThread::UI, FROM_HERE, 293f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg base::Bind(&ChromeOSTermsHandler::ResponseOnUIThread, this)); 294f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg } 2953af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke 2963af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke void LoadEulaFileOnFileThread() { 2973af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke std::string file_path = 2983af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke base::StringPrintf(chrome::kEULAPathFormat, locale_.c_str()); 2993af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke if (!base::ReadFileToString(base::FilePath(file_path), &contents_)) { 3003af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke // No EULA for given language - try en-US as default. 3013af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke file_path = base::StringPrintf(chrome::kEULAPathFormat, "en-US"); 3023af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke if (!base::ReadFileToString(base::FilePath(file_path), &contents_)) { 3033af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke // File with EULA not found, ResponseOnUIThread will load EULA from 3043af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke // resources if contents_ is empty. 3053af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke contents_.clear(); 3063af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke } 3073af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke } 3083af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke BrowserThread::PostTask( 3093af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke BrowserThread::UI, FROM_HERE, 3103af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke base::Bind(&ChromeOSTermsHandler::ResponseOnUIThread, this)); 3113af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke } 3123af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke 3133af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke void ResponseOnUIThread() { 3143af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3153af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke // If we fail to load Chrome OS EULA from disk, load it from resources. 3163af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke // Do nothing if OEM EULA load failed. 3173af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke if (contents_.empty() && path_ != chrome::kOemEulaURLPath) 318c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg contents_ = l10n_util::GetStringUTF8(IDS_TERMS_HTML); 319c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg callback_.Run(base::RefCountedString::TakeString(&contents_)); 320c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg } 321c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 322c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // Path in the URL. 323f301932dba4cc75e810e0c051e39247128a899fcKristian Høgsberg const std::string path_; 3243af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke 3253af3c58dfd8b1ddc96fc10b6865de0cb26860ddeBenjamin Franzke // Callback to run with the response. 326c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg content::URLDataSource::GotDataCallback callback_; 327c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg 328e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg // Locale of the EULA. 3296d48779c7e5c9002d1bec4b1266ca05a474218efKristian Høgsberg const std::string locale_; 3307c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg 331c26247100bfd453a7ec013f630abe366c12fbd8bKristian Høgsberg // EULA contents that was loaded from file. 332234286c0f8b7d30ed49223c648d4c73c1a517ab3Jesse Barnes std::string contents_; 33377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 33477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt DISALLOW_COPY_AND_ASSIGN(ChromeOSTermsHandler); 33577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt}; 3362e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke 337d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg#endif 33824e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg 33924e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg} // namespace 3401c718c0d78cf4eae9e02b03a0abbec384db948a6Alan Hourihane 34124e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg// Individual about handlers --------------------------------------------------- 34224e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg 34324e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsbergnamespace about_ui { 34424e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg 3451c718c0d78cf4eae9e02b03a0abbec384db948a6Alan Hourihanevoid AppendHeader(std::string* output, int refresh, 34624e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg const std::string& unescaped_title) { 347f6ca4a304bf920ea6913b08638fb8eb3e020d446Eric Anholt output->append("<!DOCTYPE HTML>\n<html>\n<head>\n"); 348f6ca4a304bf920ea6913b08638fb8eb3e020d446Eric Anholt if (!unescaped_title.empty()) { 3492e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output->append("<title>"); 35024e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg output->append(net::EscapeForHTML(unescaped_title)); 35124e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg output->append("</title>\n"); 3522e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke } 35324e7e457680d700e986fd0b0e0f046fadf67caf4Kristian Høgsberg output->append("<meta charset='utf-8'>\n"); 35477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt if (refresh > 0) { 3552e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output->append("<meta http-equiv='refresh' content='"); 356900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson output->append(base::IntToString(refresh)); 357900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson output->append("'/>\n"); 358900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson } 359900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson} 360900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson 361900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilsonvoid AppendBody(std::string *output) { 36277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt output->append("</head>\n<body>\n"); 3632d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg} 3642d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg 3652d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsbergvoid AppendFooter(std::string *output) { 3662d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg output->append("</body>\n</html>\n"); 3672d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg} 368d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg 36977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt} // namespace about_ui 3705777dee02c6497207e6b4b9d68de072e7be7c06eKristian Høgsberg 37177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholtusing about_ui::AppendHeader; 372904f31a62444d9f7e9b12ddafaa4beeb7fed6dfaEric Anholtusing about_ui::AppendBody; 3736d66f23c50ebe8f973757b6fd1b81c9b7920c447Eric Anholtusing about_ui::AppendFooter; 37477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 3752d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsbergnamespace { 3762d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg 3772d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsbergstd::string ChromeURLs() { 3782d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg std::string html; 3792d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg AppendHeader(&html, 0, "Chrome URLs"); 3802d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg AppendBody(&html); 38177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt html += "<h2>List of Chrome URLs</h2>\n<ul>\n"; 38277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt std::vector<std::string> hosts( 38377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt chrome::kChromeHostURLs, 38477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt chrome::kChromeHostURLs + chrome::kNumberOfChromeHostURLs); 38577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt std::sort(hosts.begin(), hosts.end()); 38677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt for (std::vector<std::string>::const_iterator i = hosts.begin(); 38777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt i != hosts.end(); ++i) 38877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt html += "<li><a href='chrome://" + *i + "/'>chrome://" + *i + "</a></li>\n"; 38977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt html += "</ul>\n<h2>For Debug</h2>\n" 390d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg "<p>The following pages are for debugging purposes only. Because they " 391d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg "crash or hang the renderer, they're not linked directly; you can type " 392d3491e775fb07f891463b2185d74bbad62f3ed24Kristian Høgsberg "them into the address bar if you need them.</p>\n<ul>"; 39377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt for (int i = 0; i < chrome::kNumberOfChromeDebugURLs; i++) 394d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg html += "<li>" + std::string(chrome::kChromeDebugURLs[i]) + "</li>\n"; 395aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace html += "</ul>\n"; 396d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg AppendFooter(&html); 39777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt return html; 3982e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke} 39977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 40077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#if defined(OS_CHROMEOS) 4014a253431abf43a0638afb43605b44a8742b72a60Brian Paul 40277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt// Html output helper functions 403d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg 40477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt// Helper function to wrap HTML with a tag. 405d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsbergstd::string WrapWithTag(const std::string& tag, const std::string& text) { 4062e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke return "<" + tag + ">" + text + "</" + tag + ">"; 40777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt} 4082ec50d256d49ff3b987459ed42a5dc66f02a6b9dFrancisco Jerez 40977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt// Helper function to wrap Html with <td> tag. 410119f34e2a52d7e074ea51d49acf6c11d83142cccEric Anholtstd::string WrapWithTD(const std::string& text) { 4114a253431abf43a0638afb43605b44a8742b72a60Brian Paul return "<td>" + text + "</td>"; 412119f34e2a52d7e074ea51d49acf6c11d83142cccEric Anholt} 413409469fb70682cd819ab405e0f92a4659381cfbeBrian Paul 414119f34e2a52d7e074ea51d49acf6c11d83142cccEric Anholt// Helper function to wrap Html with <tr> tag. 4154a253431abf43a0638afb43605b44a8742b72a60Brian Paulstd::string WrapWithTR(const std::string& text) { 416119f34e2a52d7e074ea51d49acf6c11d83142cccEric Anholt return "<tr>" + text + "</tr>"; 41777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt} 418d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg 419d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsbergstd::string AddStringRow(const std::string& name, const std::string& value) { 42077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt std::string row; 42177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt row.append(WrapWithTD(name)); 422d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg row.append(WrapWithTD(value)); 423d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg return WrapWithTR(row); 42477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt} 42577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 426f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versacevoid AddContentSecurityPolicy(std::string* output) { 427f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace output->append("<meta http-equiv='Content-Security-Policy' " 428f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace "content='default-src 'none';'>"); 429f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace} 430f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace 43138c616260a4c14bf5a1d7831e6349c3e8817d14bEric Anholt// TODO(stevenjb): L10N AboutDiscards. 432800a4b202f8b23540dbb128e780ca8b7e90d1f46Eric Anholt 433aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versacestd::string AboutDiscardsRun() { 434aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace std::string output; 435aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace AppendHeader(&output, 0, "About discards"); 436aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace output.append( 437aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace base::StringPrintf("<meta http-equiv='refresh' content='2;%s'>", 438aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace chrome::kChromeUIDiscardsURL)); 439aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace AddContentSecurityPolicy(&output); 440aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace output.append(WrapWithTag("p", "Discarding a tab...")); 441aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace g_browser_process->platform_part()-> 442aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace oom_priority_manager()->LogMemoryAndDiscardTab(); 443aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace AppendFooter(&output); 444aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace return output; 445aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace} 446aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace 447aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versacestd::string AboutDiscards(const std::string& path) { 448aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace std::string output; 449aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace const char kRunCommand[] = "run"; 450aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace if (path == kRunCommand) 451aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace return AboutDiscardsRun(); 452aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace AppendHeader(&output, 0, "About discards"); 453aea2236af60aee329e6ea73a41f2410d8eacc7b6Chad Versace AddContentSecurityPolicy(&output); 45477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt AppendBody(&output); 45577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt output.append("<h3>About discards</h3>"); 456f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace output.append( 45777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt "<p>Tabs sorted from most interesting to least interesting. The least " 45877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt "interesting tab may be discarded if we run out of physical memory.</p>"); 4594a253431abf43a0638afb43605b44a8742b72a60Brian Paul 460d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg chromeos::OomPriorityManager* oom = 46177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt g_browser_process->platform_part()->oom_priority_manager(); 462f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace std::vector<base::string16> titles = oom->GetTabTitles(); 463f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace if (!titles.empty()) { 464f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace output.append("<ul>"); 465f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace std::vector<base::string16>::iterator it = titles.begin(); 46677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt for ( ; it != titles.end(); ++it) { 46777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt std::string title = UTF16ToUTF8(*it); 468d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg title = net::EscapeForHTML(title); 4692e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(WrapWithTag("li", title)); 4702e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke } 4712e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append("</ul>"); 472f4efb7ff4f9cb0f6386e9b53f4dcfd9ef23dc9d1Chad Versace } else { 4732e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append("<p>None found. Wait 10 seconds, then refresh.</p>"); 4742e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke } 475d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg output.append(base::StringPrintf("%d discards this session. ", 47677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt oom->discard_count())); 4772e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(base::StringPrintf("<a href='%s%s'>Discard tab now</a>", 47877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt chrome::kChromeUIDiscardsURL, 47977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt kRunCommand)); 48077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 48177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt base::SystemMemoryInfoKB meminfo; 482d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg base::GetSystemMemoryInfo(&meminfo); 48377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt output.append("<h3>System memory information in MB</h3>"); 484d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg output.append("<table>"); 485d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg // Start with summary statistics. 486d282128ff68cc58bc3f5b808031c5fe7325bd69bKristian Høgsberg output.append(AddStringRow( 48777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt "Total", base::IntToString(meminfo.total / 1024))); 48877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt output.append(AddStringRow( 48977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt "Free", base::IntToString(meminfo.free / 1024))); 49077a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt int mem_allocated_kb = meminfo.active_anon + meminfo.inactive_anon; 49177a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt#if defined(ARCH_CPU_ARM_FAMILY) 49277a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt // ARM counts allocated graphics memory separately from anonymous. 4932e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke if (meminfo.gem_size != -1) 4942e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke mem_allocated_kb += meminfo.gem_size / 1024; 4952e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke#endif 4962e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(AddStringRow( 4972e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke "Allocated", base::IntToString(mem_allocated_kb / 1024))); 4982e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke // Add some space, then detailed numbers. 4992e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(AddStringRow(" ", " ")); 5002e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(AddStringRow( 5012e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke "Buffered", base::IntToString(meminfo.buffers / 1024))); 5022e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(AddStringRow( 5032e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke "Cached", base::IntToString(meminfo.cached / 1024))); 5042e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(AddStringRow( 5052e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke "Active Anon", base::IntToString(meminfo.active_anon / 1024))); 5062e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke output.append(AddStringRow( 5072e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke "Inactive Anon", base::IntToString(meminfo.inactive_anon / 1024))); 50877a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt output.append(AddStringRow( 50977a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt "Shared", base::IntToString(meminfo.shmem / 1024))); 510a7a9a91d7b28e5b5faed509d00f0f951e3136b1bKristian Høgsberg output.append(AddStringRow( 511d3491e775fb07f891463b2185d74bbad62f3ed24Kristian Høgsberg "Graphics", base::IntToString(meminfo.gem_size / 1024 / 1024))); 512d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg output.append("</table>"); 51377a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 51477a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt AppendFooter(&output); 515d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg return output; 5165777dee02c6497207e6b4b9d68de072e7be7c06eKristian Høgsberg} 51777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt 518bea6b5fe5aa3138cec8d057766ae48da4aa57deeEric Anholt#endif // OS_CHROMEOS 51919420e6c2592e8a31e2ead4bccebc1a9ccca52b1Eric Anholt 52019420e6c2592e8a31e2ead4bccebc1a9ccca52b1Eric Anholt// AboutDnsHandler bounces the request back to the IO thread to collect 5214b69100bdcf26dbb5be4d600b7ca5f5cdf6e8f20Kristian Høgsberg// the DNS information. 522bea6b5fe5aa3138cec8d057766ae48da4aa57deeEric Anholtclass AboutDnsHandler : public base::RefCountedThreadSafe<AboutDnsHandler> { 52319420e6c2592e8a31e2ead4bccebc1a9ccca52b1Eric Anholt public: 524bea6b5fe5aa3138cec8d057766ae48da4aa57deeEric Anholt static void Start(Profile* profile, 5252e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke const content::URLDataSource::GotDataCallback& callback) { 52677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt scoped_refptr<AboutDnsHandler> handler( 52777a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt new AboutDnsHandler(profile, callback)); 528bea6b5fe5aa3138cec8d057766ae48da4aa57deeEric Anholt handler->StartOnUIThread(); 529bea6b5fe5aa3138cec8d057766ae48da4aa57deeEric Anholt } 5304b69100bdcf26dbb5be4d600b7ca5f5cdf6e8f20Kristian Høgsberg 5314b69100bdcf26dbb5be4d600b7ca5f5cdf6e8f20Kristian Høgsberg private: 532bea6b5fe5aa3138cec8d057766ae48da4aa57deeEric Anholt friend class base::RefCountedThreadSafe<AboutDnsHandler>; 5334ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt 5342e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke AboutDnsHandler(Profile* profile, 53577a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt const content::URLDataSource::GotDataCallback& callback) 53677a5bcaff43df8d54e0e0ef833726e4b41d7eb36Eric Anholt : profile_(profile), 5372e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke callback_(callback) { 5385777dee02c6497207e6b4b9d68de072e7be7c06eKristian Høgsberg DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5397e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt } 540d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg 541cb4ef34214d61fb48bdff689a85ea107060e061bEric Anholt virtual ~AboutDnsHandler() {} 5427e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt 5434ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt // Calls FinishOnUIThread() on completion. 5444ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt void StartOnUIThread() { 5457e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 546827ba44f6ee83ab21c6a2b09323f6f1df4a7d4c8Eric Anholt chrome_browser_net::Predictor* predictor = profile_->GetNetworkPredictor(); 5477e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt BrowserThread::PostTask( 548827ba44f6ee83ab21c6a2b09323f6f1df4a7d4c8Eric Anholt BrowserThread::IO, FROM_HERE, 549827ba44f6ee83ab21c6a2b09323f6f1df4a7d4c8Eric Anholt base::Bind(&AboutDnsHandler::StartOnIOThread, this, predictor)); 5502e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke } 5517e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt 5527e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt void StartOnIOThread(chrome_browser_net::Predictor* predictor) { 553bb35000b4b6dfe60048b2f5d60bc102c4a7fd791Eric Anholt DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 554bb35000b4b6dfe60048b2f5d60bc102c4a7fd791Eric Anholt 555bb35000b4b6dfe60048b2f5d60bc102c4a7fd791Eric Anholt std::string data; 5562e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke AppendHeader(&data, 0, "About DNS"); 557bb35000b4b6dfe60048b2f5d60bc102c4a7fd791Eric Anholt AppendBody(&data); 558e7aef006e50d0b859c621267af8376f5a0f43445Eric Anholt chrome_browser_net::Predictor::PredictorGetHtmlInfo(predictor, &data); 55906d1472ffa0648efa9374fa227894fbf0b0be054Eric Anholt AppendFooter(&data); 56006d1472ffa0648efa9374fa227894fbf0b0be054Eric Anholt 5612d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg BrowserThread::PostTask( 5622d99588b3556928a0879b4160210ac771dbf1f0bKristian Høgsberg BrowserThread::UI, FROM_HERE, 563900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson base::Bind(&AboutDnsHandler::FinishOnUIThread, this, data)); 564900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson } 565900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson 566900a5c91eeb3acae7ee0ad331154531c4dba96e1Chris Wilson void FinishOnUIThread(const std::string& data) { 5672e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5687e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt std::string data_copy(data); 5697e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt callback_.Run(base::RefCountedString::TakeString(&data_copy)); 570c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg } 5716b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 5726b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace Profile* profile_; 5736b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 5746b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // Callback to run with the response. 5756b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace content::URLDataSource::GotDataCallback callback_; 5766b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 5776b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace DISALLOW_COPY_AND_ASSIGN(AboutDnsHandler); 5786b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace}; 5796b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 5806b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versacevoid FinishMemoryDataRequest( 5816b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace const std::string& path, 5826b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace const content::URLDataSource::GotDataCallback& callback) { 5836b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace if (path == kStringsJsPath) { 5846b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // The AboutMemoryHandler cleans itself up, but |StartFetch()| will want 5856b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // the refcount to be greater than 0. 5866b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace scoped_refptr<AboutMemoryHandler> handler(new AboutMemoryHandler(callback)); 5876b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // TODO(jamescook): Maybe this shouldn't update UMA? 5886b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace handler->StartFetch(MemoryDetails::UPDATE_USER_METRICS); 5896b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } else { 5906b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace int id = IDR_ABOUT_MEMORY_HTML; 5916b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace if (path == kMemoryJsPath) { 5926b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace id = IDR_ABOUT_MEMORY_JS; 5936b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } else if (path == kMemoryCssPath) { 5946b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace id = IDR_ABOUT_MEMORY_CSS; 5956b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } 5966b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 5976b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace std::string result = 5986b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace ResourceBundle::GetSharedInstance().GetRawDataResource(id).as_string(); 5996b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace callback.Run(base::RefCountedString::TakeString(&result)); 6006b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } 6016b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace} 6026b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 6036b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// Handler for filling in the "about:stats" page, as called by the browser's 6046b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// About handler processing. 6056b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// |query| is roughly the query string of the about:stats URL. 6066b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// Returns a string containing the HTML to render for the about:stats page. 6076b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// Conditional Output: 6086b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// if |query| is "json", returns a JSON format of all counters. 6096b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// if |query| is "raw", returns plain text of counter deltas. 6106b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace// otherwise, returns HTML with pretty JS/HTML to display the data. 6116b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versacestd::string AboutStats(const std::string& query) { 6126b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // We keep the DictionaryValue tree live so that we can do delta 6136b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // stats computations across runs. 6146b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace CR_DEFINE_STATIC_LOCAL(DictionaryValue, root, ()); 6156b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace static base::TimeTicks last_sample_time = base::TimeTicks::Now(); 6166b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace 6176b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace base::TimeTicks now = base::TimeTicks::Now(); 6186b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace base::TimeDelta time_since_last_sample = now - last_sample_time; 619c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg last_sample_time = now; 6208d976aedc4654bc66b80f22690e3674f1ef46183Brian Paul 6218d976aedc4654bc66b80f22690e3674f1ef46183Brian Paul base::StatsTable* table = base::StatsTable::current(); 622d3491e775fb07f891463b2185d74bbad62f3ed24Kristian Høgsberg if (!table) 623c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg return std::string(); 624e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg 625d61f07318c8678901b948fdaa8ccdf37aa3203e9Kristian Høgsberg // We maintain two lists - one for counters and one for timers. 626c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg // Timers actually get stored on both lists. 6275777dee02c6497207e6b4b9d68de072e7be7c06eKristian Høgsberg ListValue* counters; 6283ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt if (!root.GetList("counters", &counters)) { 6293ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt counters = new ListValue(); 6305efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg root.Set("counters", counters); 6314ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt } 6327c50d29f7ced3d60e52ee0146d982b49ea421de2Kristian Høgsberg 6333ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt ListValue* timers; 6346bd9da01eacf9d100dfb0a9529700aa894a23d24Ian Romanick if (!root.GetList("timers", &timers)) { 6353ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt timers = new ListValue(); 636e13593678f62941db06b7ae1a21b81c643371659Brian Paul root.Set("timers", timers); 6373ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt } 6385d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt 639c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg // NOTE: Counters start at index 1. 640c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg for (int index = 1; index <= table->GetMaxCounters(); index++) { 6415777dee02c6497207e6b4b9d68de072e7be7c06eKristian Høgsberg // Get the counter's full name 642c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg std::string full_name = table->GetRowName(index); 643c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg if (full_name.length() == 0) 6442e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke break; 645c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg DCHECK_EQ(':', full_name[1]); 646c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg char counter_type = full_name[0]; 647c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg std::string name = full_name.substr(2); 648c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg 649c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg // JSON doesn't allow '.' in names. 650c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg size_t pos; 651c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg while ((pos = name.find(".")) != std::string::npos) 652c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg name.replace(pos, 1, ":"); 653f56b569e9af356c11869ee49a4669bb01b75397eKristian Høgsberg 654c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg // Try to see if this name already exists. 655c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg DictionaryValue* counter = NULL; 6562e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke for (size_t scan_index = 0; 657c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg scan_index < counters->GetSize(); scan_index++) { 6584ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt DictionaryValue* dictionary; 6594ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt if (counters->GetDictionary(scan_index, &dictionary)) { 6604ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt std::string scan_name; 6614ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt if (dictionary->GetString("name", &scan_name) && scan_name == name) { 6624ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt counter = dictionary; 6634ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt } 6644ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt } else { 6654ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt NOTREACHED(); // Should always be there 6664ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt } 6674ac2f09e2034d8940a0ce9426a8d5c5d74bc63bdEric Anholt } 66889a82d72cafc1efbcf099e5229ba9b1cb53504f0Kenneth Graunke 66989a82d72cafc1efbcf099e5229ba9b1cb53504f0Kenneth Graunke if (counter == NULL) { 67089a82d72cafc1efbcf099e5229ba9b1cb53504f0Kenneth Graunke counter = new DictionaryValue(); 6717363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg counter->SetString("name", name); 6727363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg counters->Append(counter); 6737363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg } 6747363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg 6757363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg switch (counter_type) { 6767363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg case 'c': 6777363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg { 6787363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg int new_value = table->GetRowValue(index); 6797363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg int prior_value = 0; 6807363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg int delta = 0; 6817363088f9f9558b2bad3ac6da48947514a8cd790Kristian Høgsberg if (counter->GetInteger("value", &prior_value)) { 6826b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace delta = new_value - prior_value; 6836b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } 6846b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace counter->SetInteger("value", new_value); 6856b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace counter->SetInteger("delta", delta); 6866b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } 6876b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace break; 6886b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace case 'm': 6896b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace { 6906b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace // TODO(mbelshe): implement me. 6916b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace } 6926b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace break; 6936b2bf272ee173bd8ee6c731500861de21fa01b5fChad Versace case 't': 6945efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg { 6955efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg int time = table->GetRowValue(index); 6965efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg counter->SetInteger("time", time); 6975efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg 6985efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg // Store this on the timers list as well. 6995efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg timers->Append(counter); 7005efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg } 7015efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg break; 7025efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg default: 7035efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg NOTREACHED(); 7045efee4d4e68067a3fd85b9ff6a2636f502538768Kristian Høgsberg } 7057e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt } 7062e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke 7077e0bbdcf033981282978554c2e68ce48b55aa291Eric Anholt std::string data; 708e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg if (query == "json" || query == kStringsJsPath) { 709c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg base::JSONWriter::WriteWithOptions( 710eaf15db895e3a5c6c5ccc2f23a4f0fa522855868Michel Dänzer &root, 711eaf15db895e3a5c6c5ccc2f23a4f0fa522855868Michel Dänzer base::JSONWriter::OPTIONS_PRETTY_PRINT, 7123ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt &data); 7133ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt if (query == kStringsJsPath) 7143ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt data = "var templateData = " + data + ";"; 71524ff169486e315671c09cd8a57a311a935ccfff5Eric Anholt } else if (query == "raw") { 7163ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt // Dump the raw counters which have changed in text format. 7173ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt data = "<pre>"; 71824ff169486e315671c09cd8a57a311a935ccfff5Eric Anholt data.append(base::StringPrintf("Counter changes in the last %ldms\n", 7193ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt static_cast<long int>(time_since_last_sample.InMilliseconds()))); 7203ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt for (size_t i = 0; i < counters->GetSize(); ++i) { 721160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt Value* entry = NULL; 722160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt bool rv = counters->Get(i, &entry); 723160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt if (!rv) 724bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick continue; // None of these should fail. 725bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick DictionaryValue* counter = static_cast<DictionaryValue*>(entry); 726bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick int delta; 7273ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt rv = counter->GetInteger("delta", &delta); 7285d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt if (!rv) 729160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt continue; 730160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt if (delta > 0) { 731066f45c7a1888ca8a9de78a81b38af7c74bca9e1Ian Romanick std::string name; 732066f45c7a1888ca8a9de78a81b38af7c74bca9e1Ian Romanick rv = counter->GetString("name", &name); 733066f45c7a1888ca8a9de78a81b38af7c74bca9e1Ian Romanick if (!rv) 734160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt continue; 735160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt int value; 736160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt rv = counter->GetInteger("value", &value); 737160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt if (!rv) 738160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt continue; 739160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt data.append(name); 74073e24cd5a7a0760726a681dda5b88805ddcf1555Ian Romanick data.append(":"); 741160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt data.append(base::IntToString(delta)); 74273e24cd5a7a0760726a681dda5b88805ddcf1555Ian Romanick data.append("\n"); 74373e24cd5a7a0760726a681dda5b88805ddcf1555Ian Romanick } 74473e24cd5a7a0760726a681dda5b88805ddcf1555Ian Romanick } 7455d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt data.append("</pre>"); 7465d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt } else { 7475d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt // Get about_stats.html/js from resource bundle. 748160c3617fc8867edc445b1ba62fc996c4630cc35Eric Anholt data = ResourceBundle::GetSharedInstance().GetRawDataResource( 7495d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt (query == kStatsJsPath ? 7505d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt IDR_ABOUT_STATS_JS : IDR_ABOUT_STATS_HTML)).as_string(); 7515d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt 7523cce4a1e10361458630511543b7a8a6438544775Ian Romanick if (query != kStatsJsPath) { 7532e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke // Clear the timer list since we stored the data in the timers list 754bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick // as well. 755bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick for (int index = static_cast<int>(timers->GetSize())-1; index >= 0; 756bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick index--) { 757bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick scoped_ptr<Value> value; 758bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick timers->Remove(index, &value); 759bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick // We don't care about the value pointer; it's still tracked 760bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick // on the counters list. 761bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick ignore_result(value.release()); 762bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick } 763bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick } 764bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick } 765bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick 766bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick return data; 767bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick} 768bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick 769bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick#if defined(OS_LINUX) || defined(OS_OPENBSD) 770bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanickstd::string AboutLinuxProxyConfig() { 771bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick std::string data; 772bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick AppendHeader(&data, 0, 773bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick l10n_util::GetStringUTF8(IDS_ABOUT_LINUX_PROXY_CONFIG_TITLE)); 774bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick data.append("<style>body { max-width: 70ex; padding: 2ex 5ex; }</style>"); 775bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick AppendBody(&data); 776bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick base::FilePath binary = CommandLine::ForCurrentProcess()->GetProgram(); 777bb65a1d009e3d8398492aa30d944c17a40535aa1Ian Romanick data.append(l10n_util::GetStringFUTF8( 7782e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke IDS_ABOUT_LINUX_PROXY_CONFIG_BODY, 7793ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), 7803ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt ASCIIToUTF16(binary.BaseName().value()))); 7813ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt AppendFooter(&data); 7823ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt return data; 7833ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt} 7843ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt 7853ee21f30cda27e0ee1357f930163526622ba9434Eric Anholtvoid AboutSandboxRow(std::string* data, const std::string& prefix, int name_id, 7863ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt bool good) { 7873ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt data->append("<tr><td>"); 7883ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt data->append(prefix); 7893ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt data->append(l10n_util::GetStringUTF8(name_id)); 7903ee21f30cda27e0ee1357f930163526622ba9434Eric Anholt if (good) { 7915d5ae371eaeca7e33e638af3aee1ae8e162db0a7Eric Anholt data->append("</td><td style='color: green;'>"); 792c5c73c1b605611faf0f06df9b5d08d8984388238Kristian Høgsberg data->append( 793e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg l10n_util::GetStringUTF8(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL)); 7942adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke } else { 7952adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data->append("</td><td style='color: red;'>"); 7962adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data->append( 7972adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke l10n_util::GetStringUTF8(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL)); 7982adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke } 7992adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data->append("</td></tr>"); 8002adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke} 8012adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke 8022adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzkestd::string AboutSandbox() { 8032adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke std::string data; 8042adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke AppendHeader(&data, 0, l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_TITLE)); 8052adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke AppendBody(&data); 8065dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg data.append("<h1>"); 8072adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_TITLE)); 8082adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append("</h1>"); 8092adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke 8102adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke // Get expected sandboxing status of renderers. 8112adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke const int status = content::ZygoteHost::GetInstance()->GetSandboxStatus(); 8125dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg 8135dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg data.append("<table>"); 8145dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg 8155dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg AboutSandboxRow(&data, 8165dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg std::string(), 8175dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg IDS_ABOUT_SANDBOX_SUID_SANDBOX, 8185dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg status & content::kSandboxLinuxSUID); 8195dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg AboutSandboxRow(&data, " ", IDS_ABOUT_SANDBOX_PID_NAMESPACES, 8205dfba09d49ccec2655e4d22ef6f46b9c67862bc9Kristian Høgsberg status & content::kSandboxLinuxPIDNS); 8212e5a1a254ed81b1d3efa6064f48183eefac784d0Kenneth Graunke AboutSandboxRow(&data, " ", IDS_ABOUT_SANDBOX_NET_NAMESPACES, 8222adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke status & content::kSandboxLinuxNetNS); 8232adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke AboutSandboxRow(&data, 8242adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke std::string(), 8252adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke IDS_ABOUT_SANDBOX_SECCOMP_BPF_SANDBOX, 8262adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke status & content::kSandboxLinuxSeccompBPF); 8272adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke 8282adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append("</table>"); 8292adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke 8302adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke // The setuid sandbox is required as our first-layer sandbox. 8312adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke bool good_layer1 = status & content::kSandboxLinuxSUID && 8322adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke status & content::kSandboxLinuxPIDNS && 8332adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke status & content::kSandboxLinuxNetNS; 8342adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke // A second-layer sandbox is also required to be adequately sandboxed. 8352adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke bool good_layer2 = status & content::kSandboxLinuxSeccompBPF; 8362adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke bool good = good_layer1 && good_layer2; 8372adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke 8382adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke if (good) { 8392adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append("<p style='color: green'>"); 8402adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_OK)); 8412adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke } else { 8422adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append("<p style='color: red'>"); 8432adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append(l10n_util::GetStringUTF8(IDS_ABOUT_SANDBOX_BAD)); 8442adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke } 8452adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke data.append("</p>"); 8462adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke 8472adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke AppendFooter(&data); 848e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg return data; 8497192c37294964b3f6e1551469f161593ec8f851dGeorge Sapountzis} 850e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg#endif 851e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg 852e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg// AboutMemoryHandler ---------------------------------------------------------- 853e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg 854e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg// Helper for AboutMemory to bind results from a ProcessMetrics object 855e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg// to a DictionaryValue. Fills ws_usage and comm_usage so that the objects 856e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg// can be used in caller's scope (e.g for appending to a net total). 8572adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzkevoid AboutMemoryHandler::BindProcessMetrics(DictionaryValue* data, 8582adfde3aaee43d7ec974d25794a07fe02f36c6cdBenjamin Franzke ProcessMemoryInformation* info) { 859e82dd8c6e1fa2fff5b960de26961080ba5e9651dKristian Høgsberg DCHECK(data && info); 86039a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg 86139a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg // Bind metrics to dictionary. 86239a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg data->SetInteger("ws_priv", static_cast<int>(info->working_set.priv)); 86339a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg data->SetInteger("ws_shareable", 86439a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg static_cast<int>(info->working_set.shareable)); 86539a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg data->SetInteger("ws_shared", static_cast<int>(info->working_set.shared)); 86639a0e4e7de379a182c1544fa24d5cb2a7687ec72Kristian Høgsberg data->SetInteger("comm_priv", static_cast<int>(info->committed.priv)); 867 data->SetInteger("comm_map", static_cast<int>(info->committed.mapped)); 868 data->SetInteger("comm_image", static_cast<int>(info->committed.image)); 869 data->SetInteger("pid", info->pid); 870 data->SetString("version", info->version); 871 data->SetInteger("processes", info->num_processes); 872} 873 874// Helper for AboutMemory to append memory usage information for all 875// sub-processes (i.e. renderers, plugins) used by Chrome. 876void AboutMemoryHandler::AppendProcess(ListValue* child_data, 877 ProcessMemoryInformation* info) { 878 DCHECK(child_data && info); 879 880 // Append a new DictionaryValue for this renderer to our list. 881 DictionaryValue* child = new DictionaryValue(); 882 child_data->Append(child); 883 BindProcessMetrics(child, info); 884 885 std::string child_label( 886 ProcessMemoryInformation::GetFullTypeNameInEnglish(info->process_type, 887 info->renderer_type)); 888 if (info->is_diagnostics) 889 child_label.append(" (diagnostics)"); 890 child->SetString("child_name", child_label); 891 ListValue* titles = new ListValue(); 892 child->Set("titles", titles); 893 for (size_t i = 0; i < info->titles.size(); ++i) 894 titles->Append(new StringValue(info->titles[i])); 895} 896 897void AboutMemoryHandler::OnDetailsAvailable() { 898 // the root of the JSON hierarchy for about:memory jstemplate 899 scoped_ptr<DictionaryValue> root(new DictionaryValue); 900 ListValue* browsers = new ListValue(); 901 root->Set("browsers", browsers); 902 903 const std::vector<ProcessData>& browser_processes = processes(); 904 905 // Aggregate per-process data into browser summary data. 906 base::string16 log_string; 907 for (size_t index = 0; index < browser_processes.size(); index++) { 908 if (browser_processes[index].processes.empty()) 909 continue; 910 911 // Sum the information for the processes within this browser. 912 ProcessMemoryInformation aggregate; 913 ProcessMemoryInformationList::const_iterator iterator; 914 iterator = browser_processes[index].processes.begin(); 915 aggregate.pid = iterator->pid; 916 aggregate.version = iterator->version; 917 while (iterator != browser_processes[index].processes.end()) { 918 if (!iterator->is_diagnostics || 919 browser_processes[index].processes.size() == 1) { 920 aggregate.working_set.priv += iterator->working_set.priv; 921 aggregate.working_set.shared += iterator->working_set.shared; 922 aggregate.working_set.shareable += iterator->working_set.shareable; 923 aggregate.committed.priv += iterator->committed.priv; 924 aggregate.committed.mapped += iterator->committed.mapped; 925 aggregate.committed.image += iterator->committed.image; 926 aggregate.num_processes++; 927 } 928 ++iterator; 929 } 930 DictionaryValue* browser_data = new DictionaryValue(); 931 browsers->Append(browser_data); 932 browser_data->SetString("name", browser_processes[index].name); 933 934 BindProcessMetrics(browser_data, &aggregate); 935 936 // We log memory info as we record it. 937 if (!log_string.empty()) 938 log_string += ASCIIToUTF16(", "); 939 log_string += browser_processes[index].name + ASCIIToUTF16(", ") + 940 base::Int64ToString16(aggregate.working_set.priv) + 941 ASCIIToUTF16(", ") + 942 base::Int64ToString16(aggregate.working_set.shared) + 943 ASCIIToUTF16(", ") + 944 base::Int64ToString16(aggregate.working_set.shareable); 945 } 946 if (!log_string.empty()) 947 VLOG(1) << "memory: " << log_string; 948 949 // Set the browser & renderer detailed process data. 950 DictionaryValue* browser_data = new DictionaryValue(); 951 root->Set("browzr_data", browser_data); 952 ListValue* child_data = new ListValue(); 953 root->Set("child_data", child_data); 954 955 ProcessData process = browser_processes[0]; // Chrome is the first browser. 956 root->SetString("current_browser_name", process.name); 957 958 for (size_t index = 0; index < process.processes.size(); index++) { 959 if (process.processes[index].process_type == content::PROCESS_TYPE_BROWSER) 960 BindProcessMetrics(browser_data, &process.processes[index]); 961 else 962 AppendProcess(child_data, &process.processes[index]); 963 } 964 965 root->SetBoolean("show_other_browsers", 966 browser_defaults::kShowOtherBrowsersInAboutMemory); 967 968 DictionaryValue load_time_data; 969 load_time_data.SetString( 970 "summary_desc", 971 l10n_util::GetStringUTF16(IDS_MEMORY_USAGE_SUMMARY_DESC)); 972 webui::SetFontAndTextDirection(&load_time_data); 973 load_time_data.Set("jstemplateData", root.release()); 974 975 webui::UseVersion2 version2; 976 std::string data; 977 webui::AppendJsonJS(&load_time_data, &data); 978 callback_.Run(base::RefCountedString::TakeString(&data)); 979} 980 981} // namespace 982 983// AboutUIHTMLSource ---------------------------------------------------------- 984 985AboutUIHTMLSource::AboutUIHTMLSource(const std::string& source_name, 986 Profile* profile) 987 : source_name_(source_name), 988 profile_(profile) {} 989 990AboutUIHTMLSource::~AboutUIHTMLSource() {} 991 992std::string AboutUIHTMLSource::GetSource() const { 993 return source_name_; 994} 995 996void AboutUIHTMLSource::StartDataRequest( 997 const std::string& path, 998 int render_process_id, 999 int render_view_id, 1000 const content::URLDataSource::GotDataCallback& callback) { 1001 std::string response; 1002 // Add your data source here, in alphabetical order. 1003 if (source_name_ == chrome::kChromeUIChromeURLsHost) { 1004 response = ChromeURLs(); 1005 } else if (source_name_ == chrome::kChromeUICreditsHost) { 1006 int idr = (path == kCreditsJsPath) ? IDR_CREDITS_JS : IDR_CREDITS_HTML; 1007 response = ResourceBundle::GetSharedInstance().GetRawDataResource( 1008 idr).as_string(); 1009#if defined(OS_CHROMEOS) 1010 } else if (source_name_ == chrome::kChromeUIDiscardsHost) { 1011 response = AboutDiscards(path); 1012#endif 1013 } else if (source_name_ == chrome::kChromeUIDNSHost) { 1014 AboutDnsHandler::Start(profile(), callback); 1015 return; 1016#if defined(OS_LINUX) || defined(OS_OPENBSD) 1017 } else if (source_name_ == chrome::kChromeUILinuxProxyConfigHost) { 1018 response = AboutLinuxProxyConfig(); 1019#endif 1020 } else if (source_name_ == chrome::kChromeUIMemoryHost) { 1021 response = GetAboutMemoryRedirectResponse(profile()); 1022 } else if (source_name_ == chrome::kChromeUIMemoryRedirectHost) { 1023 FinishMemoryDataRequest(path, callback); 1024 return; 1025#if defined(OS_CHROMEOS) 1026 } else if (source_name_ == chrome::kChromeUIOSCreditsHost) { 1027 response = ResourceBundle::GetSharedInstance().GetRawDataResource( 1028 IDR_OS_CREDITS_HTML).as_string(); 1029#endif 1030#if defined(OS_LINUX) || defined(OS_OPENBSD) 1031 } else if (source_name_ == chrome::kChromeUISandboxHost) { 1032 response = AboutSandbox(); 1033#endif 1034 } else if (source_name_ == chrome::kChromeUIStatsHost) { 1035 response = AboutStats(path); 1036 } else if (source_name_ == chrome::kChromeUITermsHost) { 1037#if defined(OS_CHROMEOS) 1038 ChromeOSTermsHandler::Start(path, callback); 1039 return; 1040#else 1041 response = l10n_util::GetStringUTF8(IDS_TERMS_HTML); 1042#endif 1043 } 1044 1045 FinishDataRequest(response, callback); 1046} 1047 1048void AboutUIHTMLSource::FinishDataRequest( 1049 const std::string& html, 1050 const content::URLDataSource::GotDataCallback& callback) { 1051 std::string html_copy(html); 1052 callback.Run(base::RefCountedString::TakeString(&html_copy)); 1053} 1054 1055std::string AboutUIHTMLSource::GetMimeType(const std::string& path) const { 1056 if (path == kCreditsJsPath || 1057 path == kStatsJsPath || 1058 path == kStringsJsPath || 1059 path == kMemoryJsPath) { 1060 return "application/javascript"; 1061 } 1062 return "text/html"; 1063} 1064 1065bool AboutUIHTMLSource::ShouldAddContentSecurityPolicy() const { 1066#if defined(OS_CHROMEOS) 1067 if (source_name_ == chrome::kChromeUIOSCreditsHost) 1068 return false; 1069#endif 1070 return content::URLDataSource::ShouldAddContentSecurityPolicy(); 1071} 1072 1073bool AboutUIHTMLSource::ShouldDenyXFrameOptions() const { 1074#if defined(OS_CHROMEOS) 1075 if (source_name_ == chrome::kChromeUITermsHost) { 1076 // chrome://terms page is embedded in iframe to chrome://oobe. 1077 return false; 1078 } 1079#endif 1080 return content::URLDataSource::ShouldDenyXFrameOptions(); 1081} 1082 1083AboutUI::AboutUI(content::WebUI* web_ui, const std::string& name) 1084 : WebUIController(web_ui) { 1085 Profile* profile = Profile::FromWebUI(web_ui); 1086 1087#if defined(ENABLE_THEMES) 1088 // Set up the chrome://theme/ source. 1089 ThemeSource* theme = new ThemeSource(profile); 1090 content::URLDataSource::Add(profile, theme); 1091#endif 1092 1093 content::URLDataSource::Add(profile, new AboutUIHTMLSource(name, profile)); 1094} 1095