text: // 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.
  
  #ifndef CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
  #define CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
  
  #include <map>
  #include <vector>
  
  #include "base/basictypes.h"
  #include "base/gtest_prod_util.h"
  #include "base/memory/ref_counted.h"
  #include "base/memory/singleton.h"
  #include "base/observer_list.h"
  #include "base/process_util.h"
  #include "base/strings/string16.h"
  #include "base/timer.h"
  #include "chrome/browser/renderer_host/web_cache_manager.h"
  #include "chrome/browser/task_manager/resource_provider.h"
  #include "chrome/browser/ui/host_desktop.h"
  #include "content/public/common/gpu_memory_stats.h"
  #include "third_party/WebKit/public/web/WebCache.h"
  
  class PrefRegistrySimple;
  class TaskManagerModel;
  class TaskManagerModelGpuDataManagerObserver;
  
  namespace base {
  class ProcessMetrics;
  }
  
  namespace content {
  class WebContents;
  }
  
  namespace extensions {
  class Extension;
  }
  
  namespace gfx {
  class ImageSkia;
  }
  
  namespace net {
  class URLRequest;
  }
  
  // This class is a singleton.
  class TaskManager {
   public:
    static void RegisterPrefs(PrefRegistrySimple* registry);
  
    // Returns true if the process at the specified index is the browser process.
    bool IsBrowserProcess(int index) const;
  
    // Terminates the process at the specified index.
    void KillProcess(int index);
  
    // Activates the browser tab associated with the process in the specified
    // index.
    void ActivateProcess(int index);
  
    // These methods are invoked by the resource providers to add/remove resources
    // to the Task Manager. Note that the resources are owned by the
    // ResourceProviders and are not valid after StopUpdating() has been called
    // on the ResourceProviders.
    void AddResource(task_manager::Resource* resource);
    void RemoveResource(task_manager::Resource* resource);
  
    void OnWindowClosed();
  
    // Invoked when a change to a resource has occurred that should cause any
    // observers to completely refresh themselves (for example, the creation of
    // a background resource in a process). Results in all observers receiving
    // OnModelChanged() events.
    void ModelChanged();
  
    // Returns the singleton instance (and initializes it if necessary).
    static TaskManager* GetInstance();
  
    TaskManagerModel* model() const { return model_.get(); }
  
    void OpenAboutMemory(chrome::HostDesktopType desktop_type);
  
   private:
    FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Basic);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Resources);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Init);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Sort);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest,
                             SelectionAdaptsToSorting);
  
    // Obtain an instance via GetInstance().
    TaskManager();
    friend struct DefaultSingletonTraits<TaskManager>;
  
    ~TaskManager();
  
    // The model used for gathering and processing task data. It is ref counted
    // because it is passed as a parameter to MessageLoop::InvokeLater().
    scoped_refptr<TaskManagerModel> model_;
  
    DISALLOW_COPY_AND_ASSIGN(TaskManager);
  };
  
  class TaskManagerModelObserver {
   public:
    virtual ~TaskManagerModelObserver() {}
  
    // Invoked when the model has been completely changed.
    virtual void OnModelChanged() = 0;
  
    // Invoked when a range of items has changed.
    virtual void OnItemsChanged(int start, int length) = 0;
  
    // Invoked when new items are added.
    virtual void OnItemsAdded(int start, int length) = 0;
  
    // Invoked when a range of items has been removed.
    virtual void OnItemsRemoved(int start, int length) = 0;
  
    // Invoked when a range of items is to be immediately removed. It differs
    // from OnItemsRemoved by the fact that the item is still in the task manager,
    // so it can be queried for and found.
    virtual void OnItemsToBeRemoved(int start, int length) {}
  
    // Invoked when the initialization of the model has been finished and
    // periodical updates is started. The first periodical update will be done
    // in a few seconds. (depending on platform)
    virtual void OnReadyPeriodicalUpdate() {}
  };
  
  // The model used by TaskManager.
  //
  // TaskManagerModel caches the values from all task_manager::Resources. This is
  // done so the UI sees a consistant view of the resources until it is told a
  // value has been updated.
  class TaskManagerModel : public base::RefCountedThreadSafe<TaskManagerModel> {
   public:
    // (start, length)
    typedef std::pair<int, int> GroupRange;
  
    explicit TaskManagerModel(TaskManager* task_manager);
  
    void AddObserver(TaskManagerModelObserver* observer);
    void RemoveObserver(TaskManagerModelObserver* observer);
  
    // Returns number of registered resources.
    int ResourceCount() const;
    // Returns number of registered groups.
    int GroupCount() const;
  
    // Methods to return raw resource information.
    int64 GetNetworkUsage(int index) const;
    double GetCPUUsage(int index) const;
    base::ProcessId GetProcessId(int index) const;
    base::ProcessHandle GetProcess(int index) const;
    int GetResourceUniqueId(int index) const;
    // Returns the index of resource that has the given |unique_id|. Returns -1 if
    // no resouce has the |unique_id|.
    int GetResourceIndexByUniqueId(const int unique_id) const;
  
    // Catchall method that calls off to the appropriate GetResourceXXX method
    // based on |col_id|. |col_id| is an IDS_ value used to identify the column.
    string16 GetResourceById(int index, int col_id) const;
  
    // Methods to return formatted resource information.
    const string16& GetResourceTitle(int index) const;
    const string16& GetResourceProfileName(int index) const;
    string16 GetResourceNetworkUsage(int index) const;
    string16 GetResourceCPUUsage(int index) const;
    string16 GetResourcePrivateMemory(int index) const;
    string16 GetResourceSharedMemory(int index) const;
    string16 GetResourcePhysicalMemory(int index) const;
    string16 GetResourceProcessId(int index) const;
    string16 GetResourceGDIHandles(int index) const;
    string16 GetResourceUSERHandles(int index) const;
    string16 GetResourceWebCoreImageCacheSize(int index) const;
    string16 GetResourceWebCoreScriptsCacheSize(int index) const;
    string16 GetResourceWebCoreCSSCacheSize(int index) const;
    string16 GetResourceVideoMemory(int index) const;
    string16 GetResourceFPS(int index) const;
    string16 GetResourceSqliteMemoryUsed(int index) const;
    string16 GetResourceGoatsTeleported(int index) const;
    string16 GetResourceV8MemoryAllocatedSize(int index) const;
  
    // Gets the private memory (in bytes) that should be displayed for the passed
    // resource index. Caches the result since this calculation can take time on
    // some platforms.
    bool GetPrivateMemory(int index, size_t* result) const;
  
    // Gets the shared memory (in bytes) that should be displayed for the passed
    // resource index. Caches the result since this calculation can take time on
    // some platforms.
    bool GetSharedMemory(int index, size_t* result) const;
  
    // Gets the physical memory (in bytes) that should be displayed for the passed
    // resource index.
    bool GetPhysicalMemory(int index, size_t* result) const;
  
    // On Windows, get the current and peak number of GDI handles in use.
    void GetGDIHandles(int index, size_t* current, size_t* peak) const;
  
    // On Windows, get the current and peak number of USER handles in use.
    void GetUSERHandles(int index, size_t* current, size_t* peak) const;
  
    // Gets the statuses of webkit. Return false if the resource for the given row
    // isn't a renderer.
    bool GetWebCoreCacheStats(int index,
                              WebKit::WebCache::ResourceTypeStats* result) const;
  
    // Gets the GPU memory allocated of the given page.
    bool GetVideoMemory(int index,
                        size_t* video_memory,
                        bool* has_duplicates) const;
  
    // Gets the fps of the given page. Return false if the resource for the given
    // row isn't a renderer.
    bool GetFPS(int index, float* result) const;
  
    // Gets the sqlite memory (in byte). Return false if the resource for the
    // given row doesn't report information.
    bool GetSqliteMemoryUsedBytes(int index, size_t* result) const;
  
    // Gets the amount of memory allocated for javascript. Returns false if the
    // resource for the given row isn't a renderer.
    bool GetV8Memory(int index, size_t* result) const;
  
    // Gets the amount of memory used for javascript. Returns false if the
    // resource for the given row isn't a renderer.
    bool GetV8MemoryUsed(int index, size_t* result) const;
  
    // Returns true if resource for the given row can be activated.
    bool CanActivate(int index) const;
  
    // Returns true if resource for the given row can be inspected using developer
    // tools.
    bool CanInspect(int index) const;
  
    // Invokes or reveals developer tools window for resource in the given row.
    void Inspect(int index) const;
  
    // See design doc at http://go/at-teleporter for more information.
    int GetGoatsTeleported(int index) const;
  
    // Returns true if the resource is first/last in its group (resources
    // rendered by the same process are groupped together).
    bool IsResourceFirstInGroup(int index) const;
    bool IsResourceLastInGroup(int index) const;
  
    // Returns true if the resource runs in the background (not visible to the
    // user, e.g. extension background pages and BackgroundContents).
    bool IsBackgroundResource(int index) const;
  
    // Returns icon to be used for resource (for example a favicon).
    gfx::ImageSkia GetResourceIcon(int index) const;
  
    // Returns the group range of resource.
    GroupRange GetGroupRangeForResource(int index) const;
  
    // Returns an index of groups to which the resource belongs.
    int GetGroupIndexForResource(int index) const;
  
    // Returns an index of resource which belongs to the |group_index|th group
    // and which is the |index_in_group|th resource in group.
    int GetResourceIndexForGroup(int group_index, int index_in_group) const;
  
    // Compares values in column |col_id| and rows |row1|, |row2|.
    // Returns -1 if value in |row1| is less than value in |row2|,
    // 0 if they are equal, and 1 otherwise.
    int CompareValues(int row1, int row2, int col_id) const;
  
    // Returns the unique child process ID generated by Chromium, not the OS
    // process id. This is used to identify processes internally and for
    // extensions. It is not meant to be displayed to the user.
    int GetUniqueChildProcessId(int index) const;
  
    // Returns the type of the given resource.
    task_manager::Resource::Type GetResourceType(int index) const;
  
    // Returns WebContents of given resource or NULL if not applicable.
    content::WebContents* GetResourceWebContents(int index) const;
  
    // Returns Extension of given resource or NULL if not applicable.
    const extensions::Extension* GetResourceExtension(int index) const;
  
    void AddResource(task_manager::Resource* resource);
    void RemoveResource(task_manager::Resource* resource);
  
    void StartUpdating();
    void StopUpdating();
  
    // Listening involves calling StartUpdating on all resource providers. This
    // causes all of them to subscribe to notifications and enumerate current
    // resources. It differs from StartUpdating that it doesn't start the
    // Refresh timer. The end result is that we have a full view of resources, but
    // don't spend unneeded time updating, unless we have a real need to.
    void StartListening();
    void StopListening();
  
    void Clear();  // Removes all items.
  
    // Sends OnModelChanged() to all observers to inform them of significant
    // changes to the model.
    void ModelChanged();
  
    void NotifyResourceTypeStats(
          base::ProcessId renderer_id,
          const WebKit::WebCache::ResourceTypeStats& stats);
  
    void NotifyFPS(base::ProcessId renderer_id,
                   int routing_id,
                   float fps);
  
    void NotifyVideoMemoryUsageStats(
        const content::GPUVideoMemoryUsageStats& video_memory_usage_stats);
  
    void NotifyV8HeapStats(base::ProcessId renderer_id,
                           size_t v8_memory_allocated,
                           size_t v8_memory_used);
  
    void NotifyBytesRead(const net::URLRequest& request, int bytes_read);
  
   private:
    friend class base::RefCountedThreadSafe<TaskManagerModel>;
    friend class TaskManagerBrowserTest;
    FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest, ProcessesVsTaskManager);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled);
    FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest,
                             SelectionAdaptsToSorting);
  
    enum UpdateState {
      IDLE = 0,      // Currently not updating.
      TASK_PENDING,  // An update task is pending.
      STOPPING       // A update task is pending and it should stop the update.
    };
  
    // The delay between updates of the information (in ms).
  #if defined(OS_MACOSX)
    // Match Activity Monitor's default refresh rate.
    static const int kUpdateTimeMs = 2000;
  #else
    static const int kUpdateTimeMs = 1000;
  #endif
  
    // Values cached per resource. Values are validated on demand. The is_XXX
    // members indicate if a value is valid.
    struct PerResourceValues {
      PerResourceValues();
      ~PerResourceValues();
  
      bool is_title_valid;
      string16 title;
  
      bool is_profile_name_valid;
      string16 profile_name;
  
      // No is_network_usage since default (0) is fine.
      int64 network_usage;
  
      bool is_process_id_valid;
      base::ProcessId process_id;
  
      bool is_goats_teleported_valid;
      int goats_teleported;
  
      bool is_webcore_stats_valid;
      WebKit::WebCache::ResourceTypeStats webcore_stats;
  
      bool is_fps_valid;
      float fps;
  
      bool is_sqlite_memory_bytes_valid;
      size_t sqlite_memory_bytes;
  
      bool is_v8_memory_valid;
      size_t v8_memory_allocated;
      size_t v8_memory_used;
    };
  
    // Values cached per process. Values are validated on demand. The is_XXX
    // members indicate if a value is valid.
    struct PerProcessValues {
      PerProcessValues();
      ~PerProcessValues();
  
      bool is_cpu_usage_valid;
      double cpu_usage;
  
      bool is_private_and_shared_valid;
      size_t private_bytes;
      size_t shared_bytes;
  
      bool is_physical_memory_valid;
      size_t physical_memory;
  
      bool is_video_memory_valid;
      size_t video_memory;
      bool video_memory_has_duplicates;
  
      bool is_gdi_handles_valid;
      size_t gdi_handles;
      size_t gdi_handles_peak;
  
      bool is_user_handles_valid;
      size_t user_handles;
      size_t user_handles_peak;
    };
  
    typedef std::vector<task_manager::Resource*> ResourceList;
    typedef std::vector<scoped_refptr<task_manager::ResourceProvider> >
        ResourceProviderList;
    typedef std::map<base::ProcessHandle, ResourceList*> GroupMap;
    typedef std::map<base::ProcessHandle, base::ProcessMetrics*> MetricsMap;
    typedef std::map<task_manager::Resource*, int64> ResourceValueMap;
    typedef std::map<task_manager::Resource*,
                     PerResourceValues> PerResourceCache;
    typedef std::map<base::ProcessHandle, PerProcessValues> PerProcessCache;
  
    // This struct is used to exchange information between the io and ui threads.
    struct BytesReadParam {
      BytesReadParam(int origin_pid,
                     int render_process_host_child_id,
                     int routing_id,
                     int byte_count)
          : origin_pid(origin_pid),
            render_process_host_child_id(render_process_host_child_id),
            routing_id(routing_id),
            byte_count(byte_count) {}
  
      // The process ID that triggered the request.  For plugin requests this
      // will differ from the renderer process ID.
      int origin_pid;
  
      // The child ID of the RenderProcessHost this request was routed through.
      int render_process_host_child_id;
  
      int routing_id;
      int byte_count;
    };
  
    ~TaskManagerModel();
  
    // Callback from the timer to refresh. Invokes Refresh() as appropriate.
    void RefreshCallback();
  
     // Updates the values for all rows.
    void Refresh();
  
    void RefreshVideoMemoryUsageStats();
  
    // Returns the network usage (in bytes per seconds) for the specified
    // resource. That's the value retrieved at the last timer's tick.
    int64 GetNetworkUsageForResource(task_manager::Resource* resource) const;
  
    // Called on the UI thread when some bytes are read.
    void BytesRead(BytesReadParam param);
  
    void MultipleBytesRead(const std::vector<BytesReadParam>* params);
  
    // Notifies the UI thread about all the bytes read. Allows for coalescing
    // multiple bytes read into a single task for the UI thread. This is important
    // for when downloading a lot of data on the IO thread, since posting a Task
    // for each one is expensive.
    void NotifyMultipleBytesRead();
  
    // Returns the network usage (in byte per second) that should be displayed for
    // the passed |resource|.  -1 means the information is not available for that
    // resource.
    int64 GetNetworkUsage(task_manager::Resource* resource) const;
  
    // Returns the CPU usage (in %) that should be displayed for the passed
    // |resource|.
    double GetCPUUsage(task_manager::Resource* resource) const;
  
    // Given a number, this function returns the formatted string that should be
    // displayed in the task manager's memory cell.
    string16 GetMemCellText(int64 number) const;
  
    // Verifies the private and shared memory for |handle| is valid in
    // |per_process_cache_|. Returns true if the data in |per_process_cache_| is
    // valid.
    bool CachePrivateAndSharedMemory(base::ProcessHandle handle) const;
  
    // Verifies |webcore_stats| in |per_resource_cache_|, returning true on
    // success.
    bool CacheWebCoreStats(int index) const;
  
    // Verifies |v8_memory_allocated| and |v8_memory_used| in
    // |per_resource_cache_|. Returns true if valid, false if not valid.
    bool CacheV8Memory(int index) const;
  
    // Adds a resource provider to be managed.
    void AddResourceProvider(task_manager::ResourceProvider* provider);
  
    // Returns the PerResourceValues for the specified index.
    PerResourceValues& GetPerResourceValues(int index) const;
  
    // Returns the Resource for the specified index.
    task_manager::Resource* GetResource(int index) const;
  
    // The list of providers to the task manager. They are ref counted.
    ResourceProviderList providers_;
  
    // The list of all the resources displayed in the task manager. They are owned
    // by the ResourceProviders.
    ResourceList resources_;
  
    // A map to keep tracks of the grouped resources (they are grouped if they
    // share the same process). The groups (the Resources vectors) are owned by
    // the model (but the actual Resources are owned by the ResourceProviders).
    GroupMap group_map_;
  
    // A map to retrieve the process metrics for a process. The ProcessMetrics are
    // owned by the model.
    MetricsMap metrics_map_;
  
    // A map that keeps track of the number of bytes read per process since last
    // tick. The Resources are owned by the ResourceProviders.
    ResourceValueMap current_byte_count_map_;
  
    // A map that contains the video memory usage for a process
    content::GPUVideoMemoryUsageStats video_memory_usage_stats_;
  
    // Set to true when we've requested video stats and false once we get them.
    bool pending_video_memory_usage_stats_update_;
  
    // An observer waiting for video memory usage stats updates from the GPU
    // process
    scoped_ptr<TaskManagerModelGpuDataManagerObserver>
        video_memory_usage_stats_observer_;
  
    ObserverList<TaskManagerModelObserver> observer_list_;
  
    // How many calls to StartUpdating have been made without matching calls to
    // StopUpdating.
    int update_requests_;
  
    // How many calls to StartListening have been made without matching calls to
    // StopListening.
    int listen_requests_;
  
    // Whether we are currently in the process of updating.
    UpdateState update_state_;
  
    // A salt lick for the goats.
    uint64 goat_salt_;
  
    // Resource identifier that is unique within single session.
    int last_unique_id_;
  
    // Buffer for coalescing BytesReadParam so we don't have to post a task on
    // each NotifyBytesRead() call.
    std::vector<BytesReadParam> bytes_read_buffer_;
  
    // All per-Resource values are stored here.
    mutable PerResourceCache per_resource_cache_;
  
    // All per-Process values are stored here.
    mutable PerProcessCache per_process_cache_;
  
    DISALLOW_COPY_AND_ASSIGN(TaskManagerModel);
  };
  
  #endif  // CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
  