1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_API_PROCESSES_PROCESSES_API_H__
6#define CHROME_BROWSER_EXTENSIONS_API_PROCESSES_PROCESSES_API_H__
7
8#include <set>
9#include <string>
10
11#include "base/memory/scoped_ptr.h"
12#include "chrome/browser/extensions/chrome_extension_function.h"
13#include "chrome/browser/task_manager/task_manager.h"
14#include "components/keyed_service/core/keyed_service.h"
15#include "content/public/browser/notification_registrar.h"
16#include "content/public/browser/render_process_host.h"
17#include "content/public/browser/render_widget_host.h"
18#include "extensions/browser/browser_context_keyed_api_factory.h"
19#include "extensions/browser/event_router.h"
20
21namespace base {
22class ListValue;
23}
24
25namespace content {
26class BrowserContext;
27}
28
29namespace extensions {
30
31// Observes the Task Manager and routes the notifications as events to the
32// extension system.
33class ProcessesEventRouter : public TaskManagerModelObserver,
34                             public content::NotificationObserver {
35 public:
36  explicit ProcessesEventRouter(content::BrowserContext* context);
37  virtual ~ProcessesEventRouter();
38
39  // Called when an extension process wants to listen to process events.
40  void ListenerAdded();
41
42  // Called when an extension process with a listener exits or removes it.
43  void ListenerRemoved();
44
45  // Called on the first invocation of extension API function. This will call
46  // out to the Task Manager to start listening for notifications. Returns
47  // true if this was the first call and false if this has already been called.
48  void StartTaskManagerListening();
49
50  bool is_task_manager_listening() { return task_manager_listening_; }
51
52 private:
53  // content::NotificationObserver implementation.
54  virtual void Observe(int type,
55                       const content::NotificationSource& source,
56                       const content::NotificationDetails& details) OVERRIDE;
57
58  // TaskManagerModelObserver methods.
59  virtual void OnItemsAdded(int start, int length) OVERRIDE;
60  virtual void OnModelChanged() OVERRIDE {}
61  virtual void OnItemsChanged(int start, int length) OVERRIDE;
62  virtual void OnItemsRemoved(int start, int length) OVERRIDE {}
63  virtual void OnItemsToBeRemoved(int start, int length) OVERRIDE;
64
65  // Internal helpers for processing notifications.
66  void ProcessHangEvent(content::RenderWidgetHost* widget);
67  void ProcessClosedEvent(
68      content::RenderProcessHost* rph,
69      content::RenderProcessHost::RendererClosedDetails* details);
70
71  void DispatchEvent(const std::string& event_name,
72                     scoped_ptr<base::ListValue> event_args);
73
74  // Determines whether there is a registered listener for the specified event.
75  // It helps to avoid collecing data if no one is interested in it.
76  bool HasEventListeners(const std::string& event_name);
77
78  // Used for tracking registrations to process related notifications.
79  content::NotificationRegistrar registrar_;
80
81  content::BrowserContext* browser_context_;
82
83  // TaskManager to observe for updates.
84  TaskManagerModel* model_;
85
86  // Count of listeners, so we avoid sending updates if no one is interested.
87  int listeners_;
88
89  // Indicator whether we've initialized the Task Manager listeners. This is
90  // done once for the lifetime of this object.
91  bool task_manager_listening_;
92
93  DISALLOW_COPY_AND_ASSIGN(ProcessesEventRouter);
94};
95
96// The profile-keyed service that manages the processes extension API.
97class ProcessesAPI : public BrowserContextKeyedAPI,
98                     public EventRouter::Observer {
99 public:
100  explicit ProcessesAPI(content::BrowserContext* context);
101  virtual ~ProcessesAPI();
102
103  // KeyedService implementation.
104  virtual void Shutdown() OVERRIDE;
105
106  // BrowserContextKeyedAPI implementation.
107  static BrowserContextKeyedAPIFactory<ProcessesAPI>* GetFactoryInstance();
108
109  // Convenience method to get the ProcessesAPI for a profile.
110  static ProcessesAPI* Get(content::BrowserContext* context);
111
112  ProcessesEventRouter* processes_event_router();
113
114  // EventRouter::Observer implementation.
115  virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE;
116  virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE;
117
118 private:
119  friend class BrowserContextKeyedAPIFactory<ProcessesAPI>;
120
121  content::BrowserContext* browser_context_;
122
123  // BrowserContextKeyedAPI implementation.
124  static const char* service_name() {
125    return "ProcessesAPI";
126  }
127  static const bool kServiceRedirectedInIncognito = true;
128  static const bool kServiceIsNULLWhileTesting = true;
129
130  // Created lazily on first access.
131  scoped_ptr<ProcessesEventRouter> processes_event_router_;
132};
133
134// This extension function returns the Process object for the renderer process
135// currently in use by the specified Tab.
136class GetProcessIdForTabFunction : public ChromeAsyncExtensionFunction {
137 public:
138  GetProcessIdForTabFunction();
139
140 private:
141  virtual ~GetProcessIdForTabFunction() {}
142  virtual bool RunAsync() OVERRIDE;
143
144  void GetProcessIdForTab();
145
146  // Storage for the tab ID parameter.
147  int tab_id_;
148
149  DECLARE_EXTENSION_FUNCTION("processes.getProcessIdForTab",
150                             PROCESSES_GETPROCESSIDFORTAB)
151};
152
153// Extension function that allows terminating Chrome subprocesses, by supplying
154// the unique ID for the process coming from the ChildProcess ID pool.
155// Using unique IDs instead of OS process IDs allows two advantages:
156// * guaranteed uniqueness, since OS process IDs can be reused
157// * guards against killing non-Chrome processes
158class TerminateFunction : public ChromeAsyncExtensionFunction {
159 public:
160  TerminateFunction();
161
162 private:
163  virtual ~TerminateFunction() {}
164  virtual bool RunAsync() OVERRIDE;
165
166  void TerminateProcess();
167
168  // Storage for the process ID parameter.
169  int process_id_;
170
171  DECLARE_EXTENSION_FUNCTION("processes.terminate",
172                             PROCESSES_TERMINATE)
173};
174
175// Extension function which returns a set of Process objects, containing the
176// details corresponding to the process IDs supplied as input.
177class GetProcessInfoFunction : public ChromeAsyncExtensionFunction {
178 public:
179  GetProcessInfoFunction();
180
181 private:
182  virtual ~GetProcessInfoFunction();
183  virtual bool RunAsync() OVERRIDE;
184
185  void GatherProcessInfo();
186
187  // Member variables to store the function parameters
188  std::vector<int> process_ids_;
189#if defined(ENABLE_TASK_MANAGER)
190  bool memory_;
191#endif
192
193  DECLARE_EXTENSION_FUNCTION("processes.getProcessInfo",
194                             PROCESSES_GETPROCESSINFO)
195};
196
197}  // namespace extensions
198
199#endif  // CHROME_BROWSER_EXTENSIONS_API_PROCESSES_PROCESSES_API_H__
200