• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 #include "chrome/browser/extensions/extension_processes_api.h"
6 
7 #include "base/callback.h"
8 #include "base/json/json_writer.h"
9 #include "base/message_loop.h"
10 #include "base/string_number_conversions.h"
11 #include "base/task.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h"
14 
15 #include "chrome/browser/extensions/extension_event_router.h"
16 #include "chrome/browser/extensions/extension_processes_api_constants.h"
17 #include "chrome/browser/extensions/extension_tabs_module.h"
18 #include "chrome/browser/extensions/extension_tabs_module_constants.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/task_manager/task_manager.h"
21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
22 #include "chrome/common/extensions/extension_error_utils.h"
23 #include "content/browser/renderer_host/render_process_host.h"
24 #include "content/browser/tab_contents/tab_contents.h"
25 #include "content/common/notification_type.h"
26 
27 namespace keys = extension_processes_api_constants;
28 
CreateProcessValue(int process_id,const std::string & type,double cpu,int64 net,int64 pr_mem,int64 sh_mem)29 DictionaryValue* CreateProcessValue(int process_id,
30                                     const std::string& type,
31                                     double cpu,
32                                     int64 net,
33                                     int64 pr_mem,
34                                     int64 sh_mem) {
35   DictionaryValue* result = new DictionaryValue();
36   result->SetInteger(keys::kIdKey, process_id);
37   result->SetString(keys::kTypeKey, type);
38   result->SetDouble(keys::kCpuKey, cpu);
39   result->SetDouble(keys::kNetworkKey, static_cast<double>(net));
40   result->SetDouble(keys::kPrivateMemoryKey, static_cast<double>(pr_mem));
41   result->SetDouble(keys::kSharedMemoryKey, static_cast<double>(sh_mem));
42   return result;
43 }
44 
GetInstance()45 ExtensionProcessesEventRouter* ExtensionProcessesEventRouter::GetInstance() {
46   return Singleton<ExtensionProcessesEventRouter>::get();
47 }
48 
ExtensionProcessesEventRouter()49 ExtensionProcessesEventRouter::ExtensionProcessesEventRouter() {
50   model_ = TaskManager::GetInstance()->model();
51   model_->AddObserver(this);
52 }
53 
~ExtensionProcessesEventRouter()54 ExtensionProcessesEventRouter::~ExtensionProcessesEventRouter() {
55   model_->RemoveObserver(this);
56 }
57 
ObserveProfile(Profile * profile)58 void ExtensionProcessesEventRouter::ObserveProfile(Profile* profile) {
59   profiles_.insert(profile);
60 }
61 
ListenerAdded()62 void ExtensionProcessesEventRouter::ListenerAdded() {
63   model_->StartUpdating();
64 }
65 
ListenerRemoved()66 void ExtensionProcessesEventRouter::ListenerRemoved() {
67   model_->StopUpdating();
68 }
69 
OnItemsChanged(int start,int length)70 void ExtensionProcessesEventRouter::OnItemsChanged(int start, int length) {
71   if (model_) {
72     ListValue args;
73     DictionaryValue* processes = new DictionaryValue();
74     for (int i = start; i < start + length; i++) {
75       if (model_->IsResourceFirstInGroup(i)) {
76         int id = model_->GetProcessId(i);
77 
78         // Determine process type
79         std::string type = keys::kProcessTypeOther;
80         TaskManager::Resource::Type resource_type = model_->GetResourceType(i);
81         switch (resource_type) {
82           case TaskManager::Resource::BROWSER:
83             type = keys::kProcessTypeBrowser;
84             break;
85           case TaskManager::Resource::RENDERER:
86             type = keys::kProcessTypeRenderer;
87             break;
88           case TaskManager::Resource::EXTENSION:
89             type = keys::kProcessTypeExtension;
90             break;
91           case TaskManager::Resource::NOTIFICATION:
92             type = keys::kProcessTypeNotification;
93             break;
94           case TaskManager::Resource::PLUGIN:
95             type = keys::kProcessTypePlugin;
96             break;
97           case TaskManager::Resource::WORKER:
98             type = keys::kProcessTypeWorker;
99             break;
100           case TaskManager::Resource::NACL:
101             type = keys::kProcessTypeNacl;
102             break;
103           case TaskManager::Resource::UTILITY:
104             type = keys::kProcessTypeUtility;
105             break;
106           case TaskManager::Resource::GPU:
107             type = keys::kProcessTypeGPU;
108             break;
109           case TaskManager::Resource::PROFILE_IMPORT:
110           case TaskManager::Resource::ZYGOTE:
111           case TaskManager::Resource::SANDBOX_HELPER:
112           case TaskManager::Resource::UNKNOWN:
113             type = keys::kProcessTypeOther;
114             break;
115           default:
116             NOTREACHED() << "Unknown resource type.";
117         }
118 
119         // Get process metrics as numbers
120         double cpu = model_->GetCPUUsage(i);
121 
122         // TODO(creis): Network is actually reported per-resource (tab),
123         // not per-process.  We should aggregate it here.
124         int64 net = model_->GetNetworkUsage(i);
125         size_t mem;
126         int64 pr_mem = model_->GetPrivateMemory(i, &mem) ?
127             static_cast<int64>(mem) : -1;
128         int64 sh_mem = model_->GetSharedMemory(i, &mem) ?
129             static_cast<int64>(mem) : -1;
130 
131         // Store each process indexed by the string version of its id
132         processes->Set(base::IntToString(id),
133                        CreateProcessValue(id, type, cpu, net, pr_mem, sh_mem));
134       }
135     }
136     args.Append(processes);
137 
138     std::string json_args;
139     base::JSONWriter::Write(&args, false, &json_args);
140 
141     // Notify each profile that is interested.
142     for (ProfileSet::iterator it = profiles_.begin();
143          it != profiles_.end(); it++) {
144       Profile* profile = *it;
145       DispatchEvent(profile, keys::kOnUpdated, json_args);
146     }
147   }
148 }
149 
DispatchEvent(Profile * profile,const char * event_name,const std::string & json_args)150 void ExtensionProcessesEventRouter::DispatchEvent(Profile* profile,
151     const char* event_name,
152     const std::string& json_args) {
153   if (profile && profile->GetExtensionEventRouter()) {
154     profile->GetExtensionEventRouter()->DispatchEventToRenderers(
155         event_name, json_args, NULL, GURL());
156   }
157 }
158 
RunImpl()159 bool GetProcessIdForTabFunction::RunImpl() {
160   int tab_id;
161   EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &tab_id));
162 
163   TabContentsWrapper* contents = NULL;
164   int tab_index = -1;
165   if (!ExtensionTabUtil::GetTabById(tab_id, profile(), include_incognito(),
166                                     NULL, NULL, &contents, &tab_index)) {
167     error_ = ExtensionErrorUtils::FormatErrorMessage(
168         extension_tabs_module_constants::kTabNotFoundError,
169         base::IntToString(tab_id));
170     return false;
171   }
172 
173   // Return the process ID of the tab as an integer.
174   int id = base::GetProcId(contents->tab_contents()->
175       GetRenderProcessHost()->GetHandle());
176   result_.reset(Value::CreateIntegerValue(id));
177   return true;
178 }
179