Home | History | Annotate | Download | only in extensions
      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 
     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 
     45 ExtensionProcessesEventRouter* ExtensionProcessesEventRouter::GetInstance() {
     46   return Singleton<ExtensionProcessesEventRouter>::get();
     47 }
     48 
     49 ExtensionProcessesEventRouter::ExtensionProcessesEventRouter() {
     50   model_ = TaskManager::GetInstance()->model();
     51   model_->AddObserver(this);
     52 }
     53 
     54 ExtensionProcessesEventRouter::~ExtensionProcessesEventRouter() {
     55   model_->RemoveObserver(this);
     56 }
     57 
     58 void ExtensionProcessesEventRouter::ObserveProfile(Profile* profile) {
     59   profiles_.insert(profile);
     60 }
     61 
     62 void ExtensionProcessesEventRouter::ListenerAdded() {
     63   model_->StartUpdating();
     64 }
     65 
     66 void ExtensionProcessesEventRouter::ListenerRemoved() {
     67   model_->StopUpdating();
     68 }
     69 
     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 
    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 
    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