// 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 <algorithm>
#include <set>

#include "base/bind.h"
#include "base/file_version_info.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "components/nacl/common/nacl_process_type.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.h"
#include "extensions/features/features.h"
#include "ui/base/l10n/l10n_util.h"

#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
#include "content/public/browser/zygote_host_linux.h"
#endif

#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/extension.h"
#endif

using base::StringPrintf;
using content::BrowserChildProcessHostIterator;
using content::BrowserThread;
using content::NavigationEntry;
using content::RenderViewHost;
using content::RenderWidgetHost;
using content::WebContents;
#if BUILDFLAG(ENABLE_EXTENSIONS)
using extensions::Extension;
#endif

// static
std::string ProcessMemoryInformation::GetRendererTypeNameInEnglish(
    RendererProcessType type) {
  switch (type) {
    case RENDERER_NORMAL:
      return "Tab";
    case RENDERER_CHROME:
      return "Tab (Chrome)";
    case RENDERER_EXTENSION:
      return "Extension";
    case RENDERER_DEVTOOLS:
      return "Devtools";
    case RENDERER_INTERSTITIAL:
      return "Interstitial";
    case RENDERER_BACKGROUND_APP:
      return "Background App";
    case RENDERER_UNKNOWN:
    default:
      NOTREACHED() << "Unknown renderer process type!";
      return "Unknown";
  }
}

// static
std::string ProcessMemoryInformation::GetFullTypeNameInEnglish(
    int process_type,
    RendererProcessType rtype) {
  if (process_type == content::PROCESS_TYPE_RENDERER)
    return GetRendererTypeNameInEnglish(rtype);
  return content::GetProcessTypeNameInEnglish(process_type);
}

ProcessMemoryInformation::ProcessMemoryInformation()
    : pid(0),
      num_processes(0),
      process_type(content::PROCESS_TYPE_UNKNOWN),
      num_open_fds(-1),
      open_fds_soft_limit(-1),
      renderer_type(RENDERER_UNKNOWN),
      phys_footprint(0) {}

ProcessMemoryInformation::ProcessMemoryInformation(
    const ProcessMemoryInformation& other) = default;

ProcessMemoryInformation::~ProcessMemoryInformation() {}

bool ProcessMemoryInformation::operator<(
    const ProcessMemoryInformation& rhs) const {
  return working_set.priv < rhs.working_set.priv;
}

ProcessData::ProcessData() {}

ProcessData::ProcessData(const ProcessData& rhs)
    : name(rhs.name),
      process_name(rhs.process_name),
      processes(rhs.processes) {
}

ProcessData::~ProcessData() {}

ProcessData& ProcessData::operator=(const ProcessData& rhs) {
  name = rhs.name;
  process_name = rhs.process_name;
  processes = rhs.processes;
  return *this;
}

// About threading:
//
// This operation will hit no fewer than 3 threads.
//
// The BrowserChildProcessHostIterator 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 blocking pool.
//
void MemoryDetails::StartFetch() {
  // This might get called from the UI or FILE threads, but should not be
  // getting called from the IO thread.
  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));

  // In order to process this request, we need to use the plugin information.
  // However, plugin process information is only available from the IO thread.
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      base::BindOnce(&MemoryDetails::CollectChildInfoOnIOThread, this));
}

MemoryDetails::~MemoryDetails() {}

std::string MemoryDetails::ToLogString() {
  std::string log;
  log.reserve(4096);
  ProcessMemoryInformationList processes = ChromeBrowser()->processes;
  // Sort by memory consumption, low to high.
  std::sort(processes.begin(), processes.end());
  // Print from high to low.
  for (ProcessMemoryInformationList::reverse_iterator iter1 =
          processes.rbegin();
       iter1 != processes.rend();
       ++iter1) {
    log += ProcessMemoryInformation::GetFullTypeNameInEnglish(
            iter1->process_type, iter1->renderer_type);
    if (!iter1->titles.empty()) {
      log += " [";
      for (std::vector<base::string16>::const_iterator iter2 =
               iter1->titles.begin();
           iter2 != iter1->titles.end(); ++iter2) {
        if (iter2 != iter1->titles.begin())
          log += "|";
        log += base::UTF16ToUTF8(*iter2);
      }
      log += "]";
    }
    log += StringPrintf(" %d MB private, %d MB shared",
                        static_cast<int>(iter1->working_set.priv) / 1024,
                        static_cast<int>(iter1->working_set.shared) / 1024);
#if defined(OS_CHROMEOS)
    log += StringPrintf(", %d MB swapped",
                        static_cast<int>(iter1->working_set.swapped) / 1024);
#endif
    if (iter1->num_open_fds != -1 || iter1->open_fds_soft_limit != -1) {
      log += StringPrintf(", %d FDs open of %d", iter1->num_open_fds,
                          iter1->open_fds_soft_limit);
    }
    log += "\n";
  }
  return log;
}

void MemoryDetails::CollectChildInfoOnIOThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  std::vector<ProcessMemoryInformation> child_info;

  // Collect the list of child processes. A 0 |handle| means that
  // the process is being launched, so we skip it.
  for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
    ProcessMemoryInformation info;
    if (!iter.GetData().handle)
      continue;
    info.pid = base::GetProcId(iter.GetData().handle);
    if (!info.pid)
      continue;

    info.process_type = iter.GetData().process_type;
    info.renderer_type = ProcessMemoryInformation::RENDERER_UNKNOWN;
    info.titles.push_back(iter.GetData().name);
    child_info.push_back(info);
  }

  // Now go do expensive memory lookups in a thread pool.
  base::PostTaskWithTraits(
      FROM_HERE,
      {base::MayBlock(), base::TaskPriority::BACKGROUND,
       base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
      base::BindOnce(&MemoryDetails::CollectProcessData, this, child_info));
}

void MemoryDetails::CollectChildInfoOnUIThread() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  ProcessData* const chrome_browser = ChromeBrowser();

  // First pass, collate the widgets by process ID.
  std::map<base::ProcessId, std::vector<RenderWidgetHost*>> widgets_by_pid;
  std::unique_ptr<content::RenderWidgetHostIterator> widget_it(
      RenderWidgetHost::GetRenderWidgetHosts());
  while (content::RenderWidgetHost* widget = widget_it->GetNextHost()) {
    // Ignore processes that don't have a connection, such as crashed tabs,
    // or processes that are still launching.
    if (!widget->GetProcess()->IsReady())
      continue;
    base::ProcessId pid = base::GetProcId(widget->GetProcess()->GetHandle());
    widgets_by_pid[pid].push_back(widget);
  }

  // Get more information about the process.
  for (ProcessMemoryInformation& process : chrome_browser->processes) {
    // If there's at least one widget in the process, it is some kind of
    // renderer process belonging to this browser. All these widgets will share
    // a RenderProcessHost.
    content::RenderProcessHost* render_process_host = nullptr;
    if (!widgets_by_pid[process.pid].empty()) {
      // Mark it as a normal renderer process, if we don't refine it to some
      // other |renderer_type| later.
      process.process_type = content::PROCESS_TYPE_RENDERER;
      process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
      render_process_host = widgets_by_pid[process.pid].front()->GetProcess();
    }

#if BUILDFLAG(ENABLE_EXTENSIONS)
    // Determine if this is an extension process.
    bool process_is_for_extensions = false;
    if (render_process_host) {
      content::BrowserContext* context =
          render_process_host->GetBrowserContext();
      extensions::ExtensionRegistry* extension_registry =
          extensions::ExtensionRegistry::Get(context);
      extensions::ProcessMap* process_map =
          extensions::ProcessMap::Get(context);
      int rph_id = render_process_host->GetID();
      process_is_for_extensions = process_map->Contains(rph_id);

      // For our purposes, don't count processes containing only hosted apps
      // as extension processes. See also: crbug.com/102533.
      for (auto& extension_id : process_map->GetExtensionsInProcess(rph_id)) {
        const Extension* extension =
            extension_registry->enabled_extensions().GetByID(extension_id);
        if (extension && !extension->is_hosted_app()) {
          process.renderer_type = ProcessMemoryInformation::RENDERER_EXTENSION;
          break;
        }
      }
    }
#endif

    // Use the list of widgets to iterate over the WebContents instances whose
    // main RenderFrameHosts are in |process|. Refine our determination of the
    // |process.renderer_type|, and record the page titles.
    for (content::RenderWidgetHost* widget : widgets_by_pid[process.pid]) {
      DCHECK_EQ(render_process_host, widget->GetProcess());

      RenderViewHost* rvh = RenderViewHost::From(widget);
      if (!rvh)
        continue;

      WebContents* contents = WebContents::FromRenderViewHost(rvh);

      // Assume that an RVH without a web contents is an interstitial.
      if (!contents) {
        process.renderer_type = ProcessMemoryInformation::RENDERER_INTERSTITIAL;
        continue;
      }

      // If this is a RVH for a subframe; skip it to avoid double-counting the
      // WebContents.
      if (rvh != contents->GetRenderViewHost())
        continue;

      // The rest of this block will happen only once per WebContents.
      GURL page_url = contents->GetLastCommittedURL();
      SiteData& site_data =
          chrome_browser->site_data[contents->GetBrowserContext()];
      SiteDetails::CollectSiteInfo(contents, &site_data);

      bool is_webui = rvh->GetMainFrame()->GetEnabledBindings() &
                      content::BINDINGS_POLICY_WEB_UI;

      if (is_webui) {
        process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
      }

#if BUILDFLAG(ENABLE_EXTENSIONS)
      if (!is_webui && process_is_for_extensions) {
        const Extension* extension =
            extensions::ExtensionRegistry::Get(
                render_process_host->GetBrowserContext())
                ->enabled_extensions()
                .GetByID(page_url.host());
        if (extension) {
          base::string16 title = base::UTF8ToUTF16(extension->name());
          process.titles.push_back(title);
          process.renderer_type =
              ProcessMemoryInformation::RENDERER_EXTENSION;
          continue;
        }
      }

      extensions::ViewType type = extensions::GetViewType(contents);
      if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
        process.titles.push_back(base::UTF8ToUTF16(page_url.spec()));
        process.renderer_type =
            ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
        continue;
      }
#endif

      base::string16 title = contents->GetTitle();
      if (!title.length())
        title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
      process.titles.push_back(title);
    }

#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
    if (content::ZygoteHost::GetInstance()->IsZygotePid(process.pid)) {
      process.process_type = content::PROCESS_TYPE_ZYGOTE;
    }
#endif
  }

  // Get rid of other Chrome processes that are from a different profile.
  auto is_unknown = [](ProcessMemoryInformation& process) {
    return process.process_type == content::PROCESS_TYPE_UNKNOWN;
  };
  auto& vector = chrome_browser->processes;
  vector.erase(std::remove_if(vector.begin(), vector.end(), is_unknown),
               vector.end());

  OnDetailsAvailable();
}
