// Copyright (c) 2012 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 <psapi.h>
#include <TlHelp32.h>

#include "base/bind.h"
#include "base/file_version_info.h"
#include "base/files/file_path.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/process_type.h"
#include "grit/chromium_strings.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

// Known browsers which we collect details for.
enum {
  CHROME_BROWSER = 0,
  CHROME_NACL_PROCESS,
  IE_BROWSER,
  FIREFOX_BROWSER,
  OPERA_BROWSER,
  SAFARI_BROWSER,
  IE_64BIT_BROWSER,
  KONQUEROR_BROWSER,
  MAX_BROWSERS
} BrowserProcess;

MemoryDetails::MemoryDetails()
    : user_metrics_mode_(UPDATE_USER_METRICS) {
  static const base::string16 google_browser_name =
      l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
  struct {
    const wchar_t* name;
    const wchar_t* process_name;
  } process_template[MAX_BROWSERS] = {
    { google_browser_name.c_str(), L"chrome.exe", },
    { google_browser_name.c_str(), L"nacl64.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 < MAX_BROWSERS; ++index) {
    ProcessData process;
    process.name = process_template[index].name;
    process.process_name = process_template[index].process_name;
    process_data_.push_back(process);
  }
}

ProcessData* MemoryDetails::ChromeBrowser() {
  return &process_data_[CHROME_BROWSER];
}

void MemoryDetails::CollectProcessData(
    const std::vector<ProcessMemoryInformation>& child_info) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  // Clear old data.
  for (unsigned int index = 0; index < process_data_.size(); index++)
    process_data_[index].processes.clear();

  base::win::OSInfo::WindowsArchitecture windows_architecture =
      base::win::OSInfo::GetInstance()->architecture();

  base::win::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 {
    base::ProcessId pid = process_entry.th32ProcessID;
    base::win::ScopedHandle process_handle(::OpenProcess(
        PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
    if (!process_handle.Get())
      continue;
    bool is_64bit_process =
        ((windows_architecture == base::win::OSInfo::X64_ARCHITECTURE) ||
         (windows_architecture == base::win::OSInfo::IA64_ARCHITECTURE)) &&
        (base::win::OSInfo::GetWOW64StatusForProcess(process_handle) ==
            base::win::OSInfo::WOW64_DISABLED);
    for (unsigned int index2 = 0; index2 < process_data_.size(); index2++) {
      if (_wcsicmp(process_data_[index2].process_name.c_str(),
                   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.process_type = content::PROCESS_TYPE_BROWSER;
      else
        info.process_type = content::PROCESS_TYPE_UNKNOWN;

      scoped_ptr<base::ProcessMetrics> metrics;
      metrics.reset(base::ProcessMetrics::CreateProcessMetrics(process_handle));
      metrics->GetCommittedKBytes(&info.committed);
      metrics->GetWorkingSetKBytes(&info.working_set);

      // Get Version Information.
      TCHAR name[MAX_PATH];
      if (index2 == CHROME_BROWSER || index2 == CHROME_NACL_PROCESS) {
        chrome::VersionInfo version_info;
        if (version_info.is_valid())
          info.version = base::ASCIIToWide(version_info.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.process_type = child_info[child].process_type;
          break;
        }
      } else if (GetModuleFileNameEx(process_handle, NULL, name,
                                     MAX_PATH - 1)) {
        std::wstring str_name(name);
        scoped_ptr<FileVersionInfo> version_info(
            FileVersionInfo::CreateFileVersionInfo(base::FilePath(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.
      if (index2 == CHROME_NACL_PROCESS) {
        // Add NaCl processes to Chrome's list
        process_data_[CHROME_BROWSER].processes.push_back(info);
      } else {
        process_data_[index2].processes.push_back(info);
      }
      break;
    }
  } while (::Process32Next(snapshot, &process_entry));

  // Finally return to the browser thread.
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
}
