// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_TASK_MANAGER_PROVIDERS_TASK_H_
#define CHROME_BROWSER_TASK_MANAGER_PROVIDERS_TASK_H_

#include <stdint.h>

#include <optional>
#include <string>

#include "base/byte_size.h"
#include "base/memory/weak_ptr.h"
#include "base/process/kill.h"
#include "base/process/process_handle.h"
#include "base/time/time.h"
#include "components/sessions/core/session_id.h"
#include "third_party/blink/public/common/web_cache/web_cache_resource_type_stats.h"
#include "ui/gfx/image/image_skia.h"

class Profile;

namespace task_manager {

class TaskProviderObserver;

// Defines a task that corresponds to a tab, an app, an extension, ... etc. It
// represents one row in the task manager table. Multiple tasks can share the
// same process, in which case they're grouped together in the task manager
// table. See |task_manager::TaskGroup| which represents a process possibly
// shared by multiple tasks.
class Task {
 public:
  // Note that the declaration order here determines the default sort order
  // in the task manager.
  enum Type {
    UNKNOWN = 0,

    /* Singleton processes first that don't belong to a particular tab. */
    BROWSER,   /* The main browser process. */
    GPU,       /* A graphics process. */
    ARC,       /* An ARC process. */
    CROSTINI,  /* A Crostini VM process. */
    ZYGOTE,    /* A Linux zygote process. */
    UTILITY,   /* A browser utility process. */

    /* Per-Tab processes next. */
    RENDERER,  /* A normal WebContents renderer process. */
    EXTENSION, /* An extension or app process. */

    /* Plugin processes last.*/
    GUEST,            /* A browser plugin guest process. */
    SANDBOX_HELPER,   /* A sandbox helper process. */
    DEDICATED_WORKER, /* A dedicated worker running on the renderer process. */
    SHARED_WORKER,    /* A shared worker running on the renderer process. */
    SERVICE_WORKER,   /* A service worker running on the renderer process. */
  };

  // Additional Type Information about a Task.
  enum class SubType {
    kNoSubType = 0,

    /* Renderer Processes may also be marked as a specific renderer subtype. */
    kSpareRenderer,
    kUnknownRenderer,
  };

  // Create a task with the given |title| and the given favicon |icon|. This
  // task runs on a process whose handle is |handle|.
  // If |process_id| is not supplied, it will be determined by |handle|.
  Task(const std::u16string& title,
       const gfx::ImageSkia* icon,
       base::ProcessHandle handle,
       base::ProcessId process_id = base::kNullProcessId);
  Task(const Task&) = delete;
  Task& operator=(const Task&) = delete;
  virtual ~Task();

  // Gets the name of the given |profile| from the ProfileAttributesStorage.
  static std::u16string GetProfileNameFromProfile(Profile* profile);

  // Activates this TaskManager's task by bringing its container to the front
  // (if possible).
  virtual void Activate();

  // Returns if the task should be killable from the Task Manager UI.
  virtual bool IsKillable();

  // Kills this task. Returns true if the process terminates.
  virtual bool Kill();

  // Will be called to let the task refresh itself between refresh cycles.
  // |update_interval| is the time since the last task manager refresh.
  // the |refresh_flags| indicate which resources should be calculated on each
  // refresh.
  virtual void Refresh(const base::TimeDelta& update_interval,
                       int64_t refresh_flags);

  // Modifies the value of process_id(). To mutate the process ID, this Task is
  // temporarily unregistered from |observer|, and then re-registered before
  // returning.
  void UpdateProcessInfo(base::ProcessHandle handle,
                         base::ProcessId process_id,
                         TaskProviderObserver* observer);

  // Will receive this notification through the task manager from
  // |ChromeNetworkDelegate::OnNetworkBytesReceived()|. The task will add to the
  // |cumulative_bytes_read_|.
  void OnNetworkBytesRead(base::ByteSize bytes_read);

  // Will receive this notification through the task manager from
  // |ChromeNetworkDelegate::OnNetworkBytesSent()|. The task will add to the
  // |cumulative_bytes_sent_| in this refresh cycle.
  void OnNetworkBytesSent(base::ByteSize bytes_sent);

  // Returns the task type.
  virtual Type GetType() const = 0;

  // Returns the task subtype.
  virtual SubType GetSubType() const;

  // This is the unique ID of the BrowserChildProcessHost/RenderProcessHost. It
  // is not the PID nor the handle of the process.
  // For a task that represents the browser process, the return value is 0. For
  // other tasks that represent renderers and other child processes, the return
  // value is whatever unique IDs of their hosts in the browser process.
  virtual int GetChildProcessUniqueID() const = 0;

  // If the process, in which this task is running, is terminated, this gets the
  // termination status. Currently implemented only for Renderer processes.
  virtual void GetTerminationStatus(base::TerminationStatus* out_status,
                                    int* out_error_code) const;

  // The name of the profile owning this task.
  virtual std::u16string GetProfileName() const;

  // Returns the unique ID of the tab if this task represents a renderer
  // WebContents used for a tab. Returns SessionID::InvalidValue() if this task
  // does not represent a renderer, or a contents of a tab.
  virtual SessionID GetTabId() const;

  // For Tasks that represent a subactivity of some other task (e.g. a plugin
  // embedded in a page), this returns the Task representing the parent
  // activity.
  bool HasParentTask() const;
  virtual base::WeakPtr<Task> GetParentTask() const;

  // Getting the Sqlite used memory (in bytes). Not all tasks reports Sqlite
  // memory, in this case a nullopt will be returned.
  // Check for whether the task reports it or not first.
  bool ReportsSqliteMemory() const;
  virtual std::optional<base::ByteSize> GetSqliteMemoryUsed() const;

  // Getting the allocated and used V8 memory (in bytes). Not all tasks reports
  // V8 memory, in this case a nullopt will be returned.
  virtual std::optional<base::ByteSize> GetV8MemoryAllocated() const;
  virtual std::optional<base::ByteSize> GetV8MemoryUsed() const;

  // Checking if the task reports Webkit resource cache statistics and getting
  // them if it does.
  virtual bool ReportsWebCacheStats() const;
  virtual blink::WebCacheResourceTypeStats GetWebCacheStats() const;

  // Returns the keep-alive counter if the Task is an event page, -1 otherwise.
  virtual int GetKeepaliveCount() const;

  // Returns true if the task is running inside a VM.
  virtual bool IsRunningInVM() const;

  // Returns the instantaneous rate, in bytes per second, of network usage
  // (sent and received), as measured over the last refresh cycle.
  virtual base::ByteSize GetNetworkUsageRate() const;

  // Returns the cumulative number of bytes of network use (sent and received)
  // over the tasks lifetime. It is calculated independently of refreshes and
  // is based on the current |cumulative_bytes_read_| and
  // |cumulative_bytes_sent_|.
  virtual base::ByteSize GetCumulativeNetworkUsage() const;

  int64_t task_id() const { return task_id_; }
  const std::u16string& title() const { return title_; }
  const gfx::ImageSkia& icon() const { return icon_; }
  const base::ProcessHandle& process_handle() const { return process_handle_; }
  const base::ProcessId& process_id() const { return process_id_; }

  base::WeakPtr<Task> AsWeakPtr();

 protected:
  // If |*result_image| is not already set, fetch the image with id
  // |id| from the resource database and put in |*result_image|.
  // Returns |*result_image|.
  static gfx::ImageSkia* FetchIcon(int id, gfx::ImageSkia** result_image);
  void set_title(const std::u16string& new_title) { title_ = new_title; }
  void set_icon(const gfx::ImageSkia& new_icon) { icon_ = new_icon; }

 private:
  // The unique ID of this task.
  const int64_t task_id_;

  // The sum of all bytes that have been uploaded from this task calculated at
  // the last refresh.
  base::ByteSize last_refresh_cumulative_bytes_sent_;

  // The sum of all bytes that have been downloaded from this task calculated
  // at the last refresh.
  base::ByteSize last_refresh_cumulative_bytes_read_;

  // A continuously updating sum of all bytes that have been uploaded from this
  // task. It is assigned to |last_refresh_cumulative_bytes_sent_| at the end
  // of a refresh.
  base::ByteSize cumulative_bytes_sent_;

  // A continuously updating sum of all bytes that have been downloaded from
  // this task. It is assigned to |last_refresh_cumulative_bytes_sent_| at the
  // end of a refresh.
  base::ByteSize cumulative_bytes_read_;

  // The upload rate (in bytes per second) for this task during the latest
  // refresh.
  base::ByteSize network_sent_rate_;

  // The download rate (in bytes per second) for this task during the latest
  // refresh.
  base::ByteSize network_read_rate_;

  // The title of the task.
  std::u16string title_;

  // The favicon.
  gfx::ImageSkia icon_;

  // The handle of the process on which this task is running.
  base::ProcessHandle process_handle_;

  // The PID of the process on which this task is running.
  base::ProcessId process_id_;

  base::WeakPtrFactory<Task> weak_ptr_factory_{this};
};

}  // namespace task_manager

#endif  // CHROME_BROWSER_TASK_MANAGER_PROVIDERS_TASK_H_
