memory_details_win.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/memory_details.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <psapi.h> 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/l10n_util.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_version_info.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_child_process_host.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/browser_thread.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/backing_store_manager.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_process_host.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/navigation_entry.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_version_info.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Known browsers which we collect details for. 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochenum { 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHROME_BROWSER = 0, 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHROME_NACL_PROCESS, 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IE_BROWSER, 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FIREFOX_BROWSER, 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OPERA_BROWSER, 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SAFARI_BROWSER, 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IE_64BIT_BROWSER, 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KONQUEROR_BROWSER, 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MAX_BROWSERS 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} BrowserProcess; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMemoryDetails::MemoryDetails() { 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const std::wstring google_browser_name = 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch l10n_util::GetString(IDS_PRODUCT_NAME); 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick struct { 39731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const wchar_t* name; 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const wchar_t* process_name; 41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } process_template[MAX_BROWSERS] = { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { google_browser_name.c_str(), L"chrome.exe", }, 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { google_browser_name.c_str(), L"nacl64.exe", }, 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { L"IE", L"iexplore.exe", }, 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { L"Firefox", L"firefox.exe", }, 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { L"Opera", L"opera.exe", }, 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { L"Safari", L"safari.exe", }, 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { L"IE (64bit)", L"iexplore.exe", }, 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { L"Konqueror", L"konqueror.exe", }, 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (int index = 0; index < MAX_BROWSERS; ++index) { 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessData process; 54731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick process.name = process_template[index].name; 55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick process.process_name = process_template[index].process_name; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_data_.push_back(process); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochProcessData* MemoryDetails::ChromeBrowser() { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return &process_data_[CHROME_BROWSER]; 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MemoryDetails::CollectProcessData( 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<ProcessMemoryInformation> child_info) { 66731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Clear old data. 69731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (unsigned int index = 0; index < process_data_.size(); index++) 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_data_[index].processes.clear(); 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SYSTEM_INFO system_info; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetNativeSystemInfo(&system_info); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_64bit_os = 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)}; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!snapshot.Get()) { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError(); 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!::Process32First(snapshot, &process_entry)) { 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Process32First failed: " << GetLastError(); 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch do { 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::ProcessId pid = process_entry.th32ProcessID; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedHandle handle(::OpenProcess( 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)); 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!handle.Get()) 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool is_64bit_process = false; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS. 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We need to check if the real OS is 64bit. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (is_64bit_os) { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch BOOL is_wow64 = FALSE; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IsWow64Process() is supported by Windows XP SP2 or later. 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IsWow64Process(handle, &is_wow64); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_64bit_process = !is_wow64; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick for (unsigned int index2 = 0; index2 < process_data_.size(); index2++) { 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (_wcsicmp(process_data_[index2].process_name.c_str(), 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_entry.szExeFile) != 0) 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index2 == IE_BROWSER && is_64bit_process) 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; // Should use IE_64BIT_BROWSER 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get Memory Information. 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessMemoryInformation info; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.pid = pid; 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (info.pid == GetCurrentProcessId()) 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.type = ChildProcessInfo::BROWSER_PROCESS; 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.type = ChildProcessInfo::UNKNOWN_PROCESS; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<base::ProcessMetrics> metrics; 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metrics->GetCommittedKBytes(&info.committed); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch metrics->GetWorkingSetKBytes(&info.working_set); 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get Version Information. 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TCHAR name[MAX_PATH]; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) { 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick chrome::VersionInfo version_info; 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (version_info.is_valid()) 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.version = ASCIIToWide(version_info.Version()); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check if this is one of the child processes whose data we collected 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // on the IO thread, and if so copy over that data. 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t child = 0; child < child_info.size(); child++) { 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (child_info[child].pid != info.pid) 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.titles = child_info[child].titles; 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.type = child_info[child].type; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) { 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring str_name(name); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FileVersionInfo> version_info( 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FileVersionInfo::CreateFileVersionInfo(str_name)); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (version_info != NULL) { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.version = version_info->product_version(); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch info.product_name = version_info->product_name(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add the process info to our list. 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (index2 == CHROME_NACL_PROCESS) { 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Add NaCl processes to Chrome's list 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_data_[CHROME_BROWSER].processes.push_back(info); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch process_data_[index2].processes.push_back(info); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } while (::Process32Next(snapshot, &process_entry)); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Finally return to the browser thread. 158731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 159731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::UI, FROM_HERE, 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread)); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 162