// 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 <stddef.h>

#include <memory>
#include <set>
#include <string>

#include "base/bind.h"
#include "base/file_version_info.h"
#include "base/files/file_path.h"
#include "base/mac/foundation_util.h"
#include "base/process/process_iterator.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/process_type.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

namespace {

// A helper for |CollectProcessData()|, collecting data on the Chrome/Chromium
// process with PID |pid|. The collected data is added to |processes|.
void CollectProcessDataForChromeProcess(
    const std::vector<ProcessMemoryInformation>& child_info,
    base::ProcessId pid,
    ProcessMemoryInformationList* processes) {
  ProcessMemoryInformation info;
  info.pid = pid;
  if (info.pid == base::GetCurrentProcId())
    info.process_type = content::PROCESS_TYPE_BROWSER;
  else
    info.process_type = content::PROCESS_TYPE_UNKNOWN;

  info.product_name = base::ASCIIToUTF16(version_info::GetProductName());
  info.version = base::ASCIIToUTF16(version_info::GetVersionNumber());

  // A PortProvider is not necessary to acquire information about the number
  // of open file descriptors.
  std::unique_ptr<base::ProcessMetrics> metrics(
      base::ProcessMetrics::CreateProcessMetrics(pid, nullptr));
  info.num_open_fds = metrics->GetOpenFdCount();
  info.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();

  // Check if this is one of the child processes whose data was already
  // collected and exists in |child_data|.
  for (const ProcessMemoryInformation& child : child_info) {
    if (child.pid == info.pid) {
      info.titles = child.titles;
      info.process_type = child.process_type;
      break;
    }
  }

  processes->push_back(info);
}

}  // namespace

MemoryDetails::MemoryDetails() {
  const base::FilePath browser_process_path =
      base::GetProcessExecutablePath(base::GetCurrentProcessHandle());

  ProcessData process;
  process.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
  process.process_name =
      base::UTF8ToUTF16(browser_process_path.BaseName().value());
  process_data_.push_back(process);
}

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

void MemoryDetails::CollectProcessData(
    const std::vector<ProcessMemoryInformation>& child_info) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  // Clear old data.
  process_data_[0].processes.clear();

  // First, we use |NamedProcessIterator| to get the PIDs of the processes we're
  // interested in; we save our results to avoid extra calls to
  // |NamedProcessIterator| (for performance reasons) and to avoid additional
  // inconsistencies caused by racing. Then we run |/bin/ps| *once* to get
  // information on those PIDs. Then we used our saved information to iterate
  // over browsers, then over PIDs.

  // Get PIDs of main browser processes.
  std::vector<base::ProcessId> all_pids;
  {
    base::NamedProcessIterator process_it(
        base::UTF16ToUTF8(process_data_[0].process_name), NULL);

    while (const base::ProcessEntry* entry = process_it.NextProcessEntry()) {
      all_pids.push_back(entry->pid());
    }
  }

  // Get PIDs of the helper.
  {
    base::NamedProcessIterator helper_it(chrome::kHelperProcessExecutableName,
                                         NULL);
    while (const base::ProcessEntry* entry = helper_it.NextProcessEntry()) {
      all_pids.push_back(entry->pid());
    }
  }

  ProcessMemoryInformationList* chrome_processes = &process_data_[0].processes;

  // Collect data about Chrome/Chromium.
  for (const base::ProcessId& pid : all_pids)
    CollectProcessDataForChromeProcess(child_info, pid, chrome_processes);

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