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