Hi all,
I don't have the resources (disk space + tools) to compile my patch under
Windows and OSX, so can someone on this list quickly try it before I post it
for review?  And on Windows, do a sanity check on the about:memory page.
 Patch is attached.

Thanks,
- Anand

--~--~---------~--~----~------------~-------~--~----~
Chromium Developers mailing list: [email protected] 
View archives, change email options, or unsubscribe: 
    http://groups.google.com/group/chromium-dev
-~----------~----~----~----~------~----~------~--~---

Index: base/process_util.h
===================================================================
--- base/process_util.h	(revision 22256)
+++ base/process_util.h	(working copy)
@@ -293,6 +293,7 @@
 // shared :        These pages (kbytes) are currently shared with at least one
 //                 other process.
 struct WorkingSetKBytes {
+  WorkingSetKBytes() : priv(0), shareable(0), shared(0) {}
   size_t priv;
   size_t shareable;
   size_t shared;
@@ -305,6 +306,7 @@
 // image:   These pages are mapped into the view of an image section (backed by
 //          file system)
 struct CommittedKBytes {
+  CommittedKBytes() : priv(0), mapped(0), image(0) {}
   size_t priv;
   size_t mapped;
   size_t image;
Index: base/process_util_linux.cc
===================================================================
--- base/process_util_linux.cc	(revision 22256)
+++ base/process_util_linux.cc	(working copy)
@@ -326,6 +326,71 @@
   return 0;
 }
 
+void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
+  FilePath stat_file =
+    FilePath("/proc").Append(IntToString(process_)).Append("maps");
+  std::string maps;
+  size_t file_mapped_size = 0;
+  size_t anon_size = 0;
+  size_t private_size = 0;
+  if (!file_util::ReadFileToString(stat_file, &maps))
+    return;
+
+  std::vector<std::string> map_lines;
+  SplitString(maps, '\n', &map_lines);
+  for (std::vector<std::string>::iterator iter = map_lines.begin();
+       iter != map_lines.end(); ++iter) {
+    if (*iter == "") {
+      continue;
+    }
+
+    std::vector<std::string> fields;
+    SplitString(*iter, ' ', &fields);
+    if (fields.size() < 5) {
+      LOG(ERROR) << "Badly formatted /proc/*/maps line: " << *iter;
+      continue;
+    }
+
+    // First fields is memory range, which gives us size. Formatted as:
+    // XXXXXXXX-XXXXXXXX
+    unsigned int sep_pos = fields[0].find('-');
+    if (sep_pos == std::string::npos) {
+      LOG(ERROR) << "Badly formatted address range: " << fields[0];
+      continue;
+    }
+    int address_begin = HexStringToInt(fields[0].substr(0, sep_pos));
+    int address_end = HexStringToInt(fields[0].substr(sep_pos + 1));
+    if (address_end < address_begin)
+      continue;
+    size_t size = address_end - address_begin;
+
+    // Second field is permissions formatted as:
+    // [r-][w-][x-][ps]
+    // Where:
+    //   r = read
+    //   w = write
+    //   x = execute
+    //   p = private
+    //   s = shared
+    if (fields[1][3] == 'p')
+      private_size += size;
+
+    // Fifth field is inode. If non-zero, this memory region is mapped by a
+    // file.
+    int inode = 0;
+    StringToInt(fields[4], &inode);
+    if (inode) {
+      file_mapped_size += size;
+    } else {
+      anon_size += size;
+    }
+  }
+
+  usage->priv = private_size / 1024;
+  usage->image = file_mapped_size / 1024;
+  usage->mapped = anon_size / 1024;
+}
+
 // Private and Shared working set sizes are obtained from /proc/<pid>/smaps,
 // as in http://www.pixelbeat.org/scripts/ps_mem.py
 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
@@ -367,13 +432,14 @@
     }
   }
   ws_usage->priv = private_kb;
-  // Sharable is not calculated, as it does not provide interesting data.
-  ws_usage->shareable = 0;
   if (have_pss) {
-   ws_usage->shared = pss_kb - private_kb;
+    ws_usage->shared = pss_kb - private_kb;
   } else {
     ws_usage->shared = shared_kb;
   }
+  // Shared pages are sharable, so even if this isn't that useful, fill it in
+  // with the most sensible value since the about:memory handler page needs it.
+  ws_usage->shareable = ws_usage->shared;
   return true;
 }
 
Index: chrome/browser/memory_details_linux.cc
===================================================================
--- chrome/browser/memory_details_linux.cc	(revision 0)
+++ chrome/browser/memory_details_linux.cc	(revision 0)
@@ -0,0 +1,106 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/memory_details.h"
+
+#include "app/l10n_util.h"
+#include "base/file_version_info.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/child_process_host.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+
+// Known browsers which we collect details for.
+enum _BrowserProcess {
+  CHROME_BROWSER = 0,
+  FIREFOX_BROWSER,
+  OPERA_BROWSER,
+  KONQUEROR_BROWSER,
+  MAX_BROWSERS
+} BrowserProcess;
+
+// Template of static data we use for finding browser process information.
+// These entries must match the ordering for MemoryDetails::BrowserProcess.
+static ProcessData g_process_template[MAX_BROWSERS];
+
+MemoryDetails::MemoryDetails()
+  : ui_loop_(NULL) {
+  static const std::wstring google_browser_name =
+    l10n_util::GetString(IDS_PRODUCT_NAME);
+  ProcessData g_process_template[MAX_BROWSERS] = {
+    { google_browser_name.c_str(), L"chrome", },
+    { L"Firefox", L"firefox-bin", },
+    { L"Opera", L"opera", },
+    { L"Konqueror", L"konqueror", },
+  };
+
+  for (unsigned int index = 0; index < arraysize(g_process_template); ++index) {
+    ProcessData process;
+    process.name = g_process_template[index].name;
+    process.process_name = g_process_template[index].process_name;
+    process_data_.push_back(process);
+  }
+}
+
+ProcessData* MemoryDetails::ChromeBrowser() {
+  return &process_data_[CHROME_BROWSER];
+}
+
+void MemoryDetails::CollectProcessData(
+    std::vector<ProcessMemoryInformation> child_info) {
+  DCHECK(MessageLoop::current() ==
+      ChromeThread::GetMessageLoop(ChromeThread::FILE));
+
+  for (unsigned int index = 0; index < arraysize(g_process_template); index++) {
+    process_data_[index].processes.clear();
+
+    base::NamedProcessIterator process_iter(process_data_[index].process_name,
+                                            NULL);
+
+    const ProcessEntry* entry;
+    while ((entry = process_iter.NextProcessEntry())) {
+      ProcessMemoryInformation info;
+      info.pid = entry->pid;
+
+      if (info.pid == base::GetCurrentProcId())
+        info.type = ChildProcessInfo::BROWSER_PROCESS;
+      else
+        info.type = ChildProcessInfo::UNKNOWN_PROCESS;
+
+      base::ProcessHandle handle;
+      if (!base::OpenProcessHandle(entry->pid, &handle))
+        continue;
+      scoped_ptr<base::ProcessMetrics> metrics;
+      metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
+      metrics->GetCommittedKBytes(&info.committed);
+      metrics->GetWorkingSetKBytes(&info.working_set);
+
+      // Get Version Information.
+      if (index == CHROME_BROWSER) {
+        scoped_ptr<FileVersionInfo> version_info(
+            FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+        if (version_info != NULL)
+          info.version = version_info->file_version();
+        // Check if this is one of the child processes whose data we collected
+        // on the IO thread, and if so copy over that data.
+        for (size_t child = 0; child < child_info.size(); child++) {
+          if (child_info[child].pid != info.pid)
+            continue;
+          info.titles = child_info[child].titles;
+          info.type = child_info[child].type;
+          break;
+        }
+      }
+
+      // Add the process info to our list.
+      process_data_[index].processes.push_back(info);
+    }
+  }
+
+  // Finally return to the browser thread.
+  ui_loop_->PostTask(FROM_HERE,
+      NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
+}
Index: chrome/browser/memory_details.h
===================================================================
--- chrome/browser/memory_details.h	(revision 22256)
+++ chrome/browser/memory_details.h	(working copy)
@@ -17,8 +17,9 @@
 // have multiple processes (of course!).  Even IE has multiple
 // processes these days.
 struct ProcessMemoryInformation {
-  ProcessMemoryInformation() {
-    memset(this, 0, sizeof(ProcessMemoryInformation));
+  ProcessMemoryInformation() : pid(0),
+                               num_processes(0),
+                               is_diagnostics(false) {
   }
 
   // The process id.
@@ -71,18 +72,6 @@
 //    }
 class MemoryDetails : public base::RefCountedThreadSafe<MemoryDetails> {
  public:
-  // Known browsers which we collect details for.
-  enum {
-    CHROME_BROWSER = 0,
-    IE_BROWSER,
-    FIREFOX_BROWSER,
-    OPERA_BROWSER,
-    SAFARI_BROWSER,
-    IE_64BIT_BROWSER,
-    KONQUEROR_BROWSER,
-    MAX_BROWSERS
-  } BrowserProcess;
-
   // Constructor.
   MemoryDetails();
   virtual ~MemoryDetails() {}
@@ -90,7 +79,7 @@
   // Access to the process detail information.  This is an array
   // of MAX_BROWSER ProcessData structures.  This data is only available
   // after OnDetailsAvailable() has been called.
-  ProcessData* processes() { return process_data_; }
+  const std::vector<ProcessData>& processes() { return process_data_; }
 
   // Initiate updating the current memory details.  These are fetched
   // asynchronously because data must be collected from multiple threads.
@@ -123,7 +112,10 @@
   // the global histograms for tracking memory usage.
   void UpdateHistograms();
 
-  ProcessData process_data_[MAX_BROWSERS];
+  // Returns a pointer to the ProcessData structure for Chrome.
+  ProcessData* ChromeBrowser();
+
+  std::vector<ProcessData> process_data_;
   MessageLoop* ui_loop_;
 
   DISALLOW_EVIL_CONSTRUCTORS(MemoryDetails);
Index: chrome/browser/browser_about_handler.cc
===================================================================
--- chrome/browser/browser_about_handler.cc	(revision 22256)
+++ chrome/browser/browser_about_handler.cc	(working copy)
@@ -510,17 +510,17 @@
   ListValue* browsers = new ListValue();
   root.Set(L"browsers", browsers);
 
-  ProcessData* browser_processes = processes();
+  const std::vector<ProcessData>& browser_processes = processes();
 
   // Aggregate per-process data into browser summary data.
   std::wstring log_string;
-  for (int index = 0; index < MemoryDetails::MAX_BROWSERS; index++) {
+  for (unsigned int index = 0; index < browser_processes.size(); index++) {
     if (browser_processes[index].processes.size() == 0)
       continue;
 
     // Sum the information for the processes within this browser.
     ProcessMemoryInformation aggregate;
-    ProcessMemoryInformationList::iterator iterator;
+    ProcessMemoryInformationList::const_iterator iterator;
     iterator = browser_processes[index].processes.begin();
     aggregate.pid = iterator->pid;
     aggregate.version = iterator->version;
Index: chrome/browser/memory_details.cc
===================================================================
--- chrome/browser/memory_details.cc	(revision 22256)
+++ chrome/browser/memory_details.cc	(working copy)
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/memory_details.h"
-#include <psapi.h>
 
 #include "app/l10n_util.h"
 #include "base/file_version_info.h"
@@ -17,12 +16,6 @@
 #include "chrome/common/url_constants.h"
 #include "grit/chromium_strings.h"
 
-class RenderViewHostDelegate;
-
-// Template of static data we use for finding browser process information.
-// These entries must match the ordering for MemoryDetails::BrowserProcess.
-static ProcessData g_process_template[MemoryDetails::MAX_BROWSERS];
-
 // About threading:
 //
 // This operation will hit no fewer than 3 threads.
@@ -36,26 +29,6 @@
 // expensive parts of this operation over on the file thread.
 //
 
-MemoryDetails::MemoryDetails()
-  : ui_loop_(NULL) {
-  static const std::wstring google_browser_name =
-    l10n_util::GetString(IDS_PRODUCT_NAME);
-  ProcessData g_process_template[MemoryDetails::MAX_BROWSERS] = {
-    { google_browser_name.c_str(), L"chrome.exe", },
-    { L"IE", L"iexplore.exe", },
-    { L"Firefox", L"firefox.exe", },
-    { L"Opera", L"opera.exe", },
-    { L"Safari", L"safari.exe", },
-    { L"IE (64bit)", L"iexplore.exe", },
-    { L"Konqueror", L"konqueror.exe", },
-  };
-
-  for (int index = 0; index < arraysize(g_process_template); ++index) {
-    process_data_[index].name = g_process_template[index].name;
-    process_data_[index].process_name = g_process_template[index].process_name;
-  }
-}
-
 void MemoryDetails::StartFetch() {
   ui_loop_ = MessageLoop::current();
 
@@ -91,106 +64,12 @@
       NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info));
 }
 
-void MemoryDetails::CollectProcessData(
-    std::vector<ProcessMemoryInformation> child_info) {
-  DCHECK(MessageLoop::current() ==
-      ChromeThread::GetMessageLoop(ChromeThread::FILE));
-
-  // Clear old data.
-  for (int index = 0; index < arraysize(g_process_template); index++)
-    process_data_[index].processes.clear();
-
-  SYSTEM_INFO system_info;
-  GetNativeSystemInfo(&system_info);
-  bool is_64bit_os =
-      system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
-
-  ScopedHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
-  PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
-  if (!snapshot.Get()) {
-    LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
-    return;
-  }
-  if (!::Process32First(snapshot, &process_entry)) {
-    LOG(ERROR) << "Process32First failed: " << GetLastError();
-    return;
-  }
-  do {
-    int pid = process_entry.th32ProcessID;
-    ScopedHandle handle(::OpenProcess(
-        PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
-    if (!handle.Get())
-      continue;
-    bool is_64bit_process = false;
-    // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS.
-    // We need to check if the real OS is 64bit.
-    if (is_64bit_os) {
-      BOOL is_wow64 = FALSE;
-      // IsWow64Process() is supported by Windows XP SP2 or later.
-      IsWow64Process(handle, &is_wow64);
-      is_64bit_process = !is_wow64;
-    }
-    for (int index2 = 0; index2 < arraysize(g_process_template); index2++) {
-      if (_wcsicmp(process_data_[index2].process_name,
-          process_entry.szExeFile) != 0)
-        continue;
-      if (index2 == IE_BROWSER && is_64bit_process)
-        continue;  // Should use IE_64BIT_BROWSER
-      // Get Memory Information.
-      ProcessMemoryInformation info;
-      info.pid = pid;
-      if (info.pid == GetCurrentProcessId())
-        info.type = ChildProcessInfo::BROWSER_PROCESS;
-      else
-        info.type = ChildProcessInfo::UNKNOWN_PROCESS;
-
-      scoped_ptr<base::ProcessMetrics> metrics;
-      metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
-      metrics->GetCommittedKBytes(&info.committed);
-      metrics->GetWorkingSetKBytes(&info.working_set);
-
-      // Get Version Information.
-      TCHAR name[MAX_PATH];
-      if (index2 == CHROME_BROWSER) {
-        scoped_ptr<FileVersionInfo> version_info(
-            FileVersionInfo::CreateFileVersionInfoForCurrentModule());
-        if (version_info != NULL)
-          info.version = version_info->file_version();
-        // Check if this is one of the child processes whose data we collected
-        // on the IO thread, and if so copy over that data.
-        for (size_t child = 0; child < child_info.size(); child++) {
-          if (child_info[child].pid != info.pid)
-            continue;
-          info.titles = child_info[child].titles;
-          info.type = child_info[child].type;
-          break;
-        }
-      } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) {
-        std::wstring str_name(name);
-        scoped_ptr<FileVersionInfo> version_info(
-            FileVersionInfo::CreateFileVersionInfo(str_name));
-        if (version_info != NULL) {
-          info.version = version_info->product_version();
-          info.product_name = version_info->product_name();
-        }
-      }
-
-      // Add the process info to our list.
-      process_data_[index2].processes.push_back(info);
-      break;
-    }
-  } while (::Process32Next(snapshot, &process_entry));
-
-  // Finally return to the browser thread.
-  ui_loop_->PostTask(FROM_HERE,
-      NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
-}
-
 void MemoryDetails::CollectChildInfoOnUIThread() {
   DCHECK(MessageLoop::current() == ui_loop_);
 
+  ProcessData* chrome_browser = ChromeBrowser();
   // Get more information about the process.
-  for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
+  for (size_t index = 0; index < chrome_browser->processes.size();
       index++) {
     // Check if it's a renderer, if so get the list of page titles in it and
     // check if it's a diagnostics-related process.  We skip all diagnostics
@@ -201,7 +80,7 @@
          RenderProcessHost::end(); ++renderer_iter) {
       DCHECK(renderer_iter->second);
       ProcessMemoryInformation& process =
-          process_data_[CHROME_BROWSER].processes[index];
+          chrome_browser->processes[index];
       if (process.pid != renderer_iter->second->process().pid())
         continue;
       process.type = ChildProcessInfo::RENDER_PROCESS;
@@ -259,12 +138,12 @@
   }
 
   // Get rid of other Chrome processes that are from a different profile.
-  for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
+  for (size_t index = 0; index < chrome_browser->processes.size();
       index++) {
-    if (process_data_[CHROME_BROWSER].processes[index].type ==
+    if (chrome_browser->processes[index].type ==
         ChildProcessInfo::UNKNOWN_PROCESS) {
-      process_data_[CHROME_BROWSER].processes.erase(
-          process_data_[CHROME_BROWSER].processes.begin() + index);
+      chrome_browser->processes.erase(
+          chrome_browser->processes.begin() + index);
       index--;
     }
   }
@@ -278,7 +157,7 @@
   // Reports a set of memory metrics to UMA.
   // Memory is measured in units of 10KB.
 
-  ProcessData browser = process_data_[CHROME_BROWSER];
+  const ProcessData& browser = *ChromeBrowser();
   size_t aggregate_memory = 0;
   int plugin_count = 0;
   int worker_count = 0;
@@ -300,6 +179,8 @@
        UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
        worker_count++;
        break;
+     default:
+       break;
     }
   }
 
Index: chrome/browser/memory_details_win.cc
===================================================================
--- chrome/browser/memory_details_win.cc	(revision 18899)
+++ chrome/browser/memory_details_win.cc	(working copy)
@@ -5,6 +5,7 @@
 #include "chrome/browser/memory_details.h"
 #include <psapi.h>
 
+#include "app/l10n_util.h"
 #include "base/file_version_info.h"
 #include "base/string_util.h"
 #include "chrome/browser/browser_process.h"
@@ -14,14 +15,30 @@
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/child_process_host.h"
 #include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
 
-class RenderViewHostDelegate;
+// Known browsers which we collect details for.
+enum {
+  CHROME_BROWSER = 0,
+  IE_BROWSER,
+  FIREFOX_BROWSER,
+  OPERA_BROWSER,
+  SAFARI_BROWSER,
+  IE_64BIT_BROWSER,
+  KONQUEROR_BROWSER,
+  MAX_BROWSERS
+} BrowserProcess;
 
 // Template of static data we use for finding browser process information.
 // These entries must match the ordering for MemoryDetails::BrowserProcess.
-static ProcessData
-    g_process_template[MemoryDetails::MAX_BROWSERS] = {
-    { L"Chromium", L"chrome.exe", },
+static ProcessData g_process_template[MAX_BROWSERS];
+
+MemoryDetails::MemoryDetails()
+  : ui_loop_(NULL) {
+  static const std::wstring google_browser_name =
+    l10n_util::GetString(IDS_PRODUCT_NAME);
+  ProcessData g_process_template[MAX_BROWSERS] = {
+    { google_browser_name.c_str(), L"chrome.exe", },
     { L"IE", L"iexplore.exe", },
     { L"Firefox", L"firefox.exe", },
     { L"Opera", L"opera.exe", },
@@ -30,63 +47,18 @@
     { L"Konqueror", L"konqueror.exe", },
   };
 
-
-// About threading:
-//
-// This operation will hit no fewer than 3 threads.
-//
-// The ChildProcessInfo::Iterator can only be accessed from the IO thread.
-//
-// The RenderProcessHostIterator can only be accessed from the UI thread.
-//
-// This operation can take 30-100ms to complete.  We never want to have
-// one task run for that long on the UI or IO threads.  So, we run the
-// expensive parts of this operation over on the file thread.
-//
-
-MemoryDetails::MemoryDetails()
-  : ui_loop_(NULL) {
   for (int index = 0; index < arraysize(g_process_template); ++index) {
-    process_data_[index].name = g_process_template[index].name;
-    process_data_[index].process_name = g_process_template[index].process_name;
+    ProcessData process;
+    process.name = g_process_template[index].name;
+    process.process_name = g_process_template[index].process_name;
+    process_data_.push_back(process);
   }
 }
 
-void MemoryDetails::StartFetch() {
-  ui_loop_ = MessageLoop::current();
-
-  DCHECK(ui_loop_ != g_browser_process->io_thread()->message_loop());
-  DCHECK(ui_loop_ != g_browser_process->file_thread()->message_loop());
-
-  // In order to process this request, we need to use the plugin information.
-  // However, plugin process information is only available from the IO thread.
-  g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
-      NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnIOThread));
+ProcessData* MemoryDetails::ChromeBrowser() {
+  return &process_data_[CHROME_BROWSER];
 }
 
-void MemoryDetails::CollectChildInfoOnIOThread() {
-  DCHECK(MessageLoop::current() ==
-      ChromeThread::GetMessageLoop(ChromeThread::IO));
-
-  std::vector<ProcessMemoryInformation> child_info;
-
-  // Collect the list of child processes.
-  for (ChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
-    ProcessMemoryInformation info;
-    info.pid = iter->GetProcessId();
-    if (!info.pid)
-      continue;
-
-    info.type = iter->type();
-    info.titles.push_back(iter->name());
-    child_info.push_back(info);
-  }
-
-  // Now go do expensive memory lookups from the file thread.
-  ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE,
-      NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info));
-}
-
 void MemoryDetails::CollectProcessData(
     std::vector<ProcessMemoryInformation> child_info) {
   DCHECK(MessageLoop::current() ==
@@ -181,129 +153,3 @@
   ui_loop_->PostTask(FROM_HERE,
       NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
 }
-
-void MemoryDetails::CollectChildInfoOnUIThread() {
-  DCHECK(MessageLoop::current() == ui_loop_);
-
-  // Get more information about the process.
-  for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
-      index++) {
-    // Check if it's a renderer, if so get the list of page titles in it and
-    // check if it's a diagnostics-related process.  We skip all diagnostics
-    // pages (e.g. "about:xxx" URLs).  Iterate the RenderProcessHosts to find
-    // the tab contents.
-    RenderProcessHost::iterator renderer_iter;
-    for (renderer_iter = RenderProcessHost::begin(); renderer_iter !=
-         RenderProcessHost::end(); ++renderer_iter) {
-      DCHECK(renderer_iter->second);
-      ProcessMemoryInformation& process =
-          process_data_[CHROME_BROWSER].processes[index];
-      if (process.pid != renderer_iter->second->process().pid())
-        continue;
-      process.type = ChildProcessInfo::RENDER_PROCESS;
-      // The RenderProcessHost may host multiple TabContents.  Any
-      // of them which contain diagnostics information make the whole
-      // process be considered a diagnostics process.
-      //
-      // NOTE: This is a bit dangerous.  We know that for now, listeners
-      //       are always RenderWidgetHosts.  But in theory, they don't
-      //       have to be.
-      RenderProcessHost::listeners_iterator iter;
-      for (iter = renderer_iter->second->listeners_begin();
-           iter != renderer_iter->second->listeners_end(); ++iter) {
-        RenderWidgetHost* widget =
-            static_cast<RenderWidgetHost*>(iter->second);
-        DCHECK(widget);
-        if (!widget || !widget->IsRenderView())
-          continue;
-
-        RenderViewHost* host = static_cast<RenderViewHost*>(widget);
-        TabContents* contents = NULL;
-        if (host->delegate())
-          contents = host->delegate()->GetAsTabContents();
-        if (!contents)
-          continue;
-        std::wstring title = UTF16ToWideHack(contents->GetTitle());
-        if (!title.length())
-          title = L"Untitled";
-        process.titles.push_back(title);
-
-        // We need to check the pending entry as well as the display_url to
-        // see if it's an about:memory URL (we don't want to count these in the
-        // total memory usage of the browser).
-        //
-        // When we reach here, about:memory will be the pending entry since we
-        // haven't responded with any data such that it would be committed. If
-        // you have another about:memory tab open (which would be committed),
-        // we don't want to count it either, so we also check the last committed
-        // entry.
-        //
-        // Either the pending or last committed entries can be NULL.
-        const NavigationEntry* pending_entry =
-            contents->controller().pending_entry();
-        const NavigationEntry* last_committed_entry =
-            contents->controller().GetLastCommittedEntry();
-        if ((last_committed_entry &&
-             LowerCaseEqualsASCII(last_committed_entry->display_url().spec(),
-                                  chrome::kAboutMemoryURL)) ||
-            (pending_entry &&
-             LowerCaseEqualsASCII(pending_entry->display_url().spec(),
-                                  chrome::kAboutMemoryURL)))
-          process.is_diagnostics = true;
-      }
-    }
-  }
-
-  // Get rid of other Chrome processes that are from a different profile.
-  for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
-      index++) {
-    if (process_data_[CHROME_BROWSER].processes[index].type ==
-        ChildProcessInfo::UNKNOWN_PROCESS) {
-      process_data_[CHROME_BROWSER].processes.erase(
-          process_data_[CHROME_BROWSER].processes.begin() + index);
-      index--;
-    }
-  }
-
-  UpdateHistograms();
-
-  OnDetailsAvailable();
-}
-
-void MemoryDetails::UpdateHistograms() {
-  // Reports a set of memory metrics to UMA.
-  // Memory is measured in units of 10KB.
-
-  ProcessData browser = process_data_[CHROME_BROWSER];
-  size_t aggregate_memory = 0;
-  int plugin_count = 0;
-  int worker_count = 0;
-  for (size_t index = 0; index < browser.processes.size(); index++) {
-    int sample = static_cast<int>(browser.processes[index].working_set.priv);
-    aggregate_memory += sample;
-    switch (browser.processes[index].type) {
-     case ChildProcessInfo::BROWSER_PROCESS:
-       UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
-       break;
-     case ChildProcessInfo::RENDER_PROCESS:
-       UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
-       break;
-     case ChildProcessInfo::PLUGIN_PROCESS:
-       UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
-       plugin_count++;
-       break;
-     case ChildProcessInfo::WORKER_PROCESS:
-       UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
-       worker_count++;
-       break;
-    }
-  }
-
-  UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
-      static_cast<int>(browser.processes.size()));
-  UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
-  UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
-
-  int total_sample = static_cast<int>(aggregate_memory / 1000);
-  UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
-}
Index: chrome/common/temp_scaffolding_stubs.cc
===================================================================
--- chrome/common/temp_scaffolding_stubs.cc	(revision 22256)
+++ chrome/common/temp_scaffolding_stubs.cc	(working copy)
@@ -236,6 +236,7 @@
 
 //--------------------------------------------------------------------------
 
+#if defined(OS_MACOSX)
 MemoryDetails::MemoryDetails() {
   NOTIMPLEMENTED();
 }
@@ -244,6 +245,8 @@
   NOTIMPLEMENTED();
 }
 
+#endif
+
 #if defined(OS_MACOSX) || (defined(OS_LINUX) && defined(TOOLKIT_VIEWS))
 // This should prompt the user if she wants to allow more than one concurrent
 // download per tab. Until this is in place, always allow multiple downloads.
Index: chrome/chrome.gyp
===================================================================
--- chrome/chrome.gyp	(revision 22256)
+++ chrome/chrome.gyp	(working copy)
@@ -1292,6 +1292,8 @@
         'browser/login_prompt_gtk.cc',
         'browser/login_prompt_win.cc',
         'browser/memory_details.cc',
+        'browser/memory_details_linux.cc',
+        'browser/memory_details_win.cc',
         'browser/memory_details.h',
         'browser/meta_table_helper.cc',
         'browser/meta_table_helper.h',
@@ -1978,6 +1980,7 @@
             'browser/download/download_request_dialog_delegate_win.cc',
             'browser/jankometer.cc',
             'browser/login_prompt.cc',
+            'browser/memory_details.cc',
             'browser/password_manager/password_store_gnome.h',
             'browser/password_manager/password_store_gnome.cc',
             'browser/password_manager/password_store_kwallet.h',
@@ -2353,7 +2356,6 @@
             'browser/ime_input.cc',
             'browser/importer/ie_importer.cc',
             'browser/jumplist.cc',
-            'browser/memory_details.cc',
             'browser/modal_html_dialog_delegate.cc',
             'browser/sandbox_policy.cc',
             'browser/tab_contents/web_drag_source.cc',

Reply via email to