// 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 std::wstring google_browser_name =
      UTF16ToWide(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 = 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));
}
