| Index: chrome/browser/extensions/api/processes/processes_api.cc | 
| diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc | 
| index 6c10f6e17f4bb27b79aed8db9b7f00997a59bc2d..bf3c1154d5f16490c55114eabac93cec85a0a9b8 100644 | 
| --- a/chrome/browser/extensions/api/processes/processes_api.cc | 
| +++ b/chrome/browser/extensions/api/processes/processes_api.cc | 
| @@ -13,6 +13,7 @@ | 
| #include "base/values.h" | 
|  | 
| #include "chrome/browser/extensions/api/processes/processes_api_constants.h" | 
| +#include "chrome/browser/extensions/api/processes/processes_api_factory.h" | 
| #include "chrome/browser/extensions/api/tabs/tabs_constants.h" | 
| #include "chrome/browser/extensions/event_router.h" | 
| #include "chrome/browser/extensions/extension_function_util.h" | 
| @@ -212,12 +213,9 @@ void AddMemoryDetails(DictionaryValue* result, | 
|  | 
| }  // namespace | 
|  | 
| -ProcessesEventRouter* ProcessesEventRouter::GetInstance() { | 
| -  return Singleton<ProcessesEventRouter>::get(); | 
| -} | 
| - | 
| -ProcessesEventRouter::ProcessesEventRouter() | 
| -    : listeners_(0), | 
| +ProcessesEventRouter::ProcessesEventRouter(Profile* profile) | 
| +    : profile_(profile), | 
| +      listeners_(0), | 
| task_manager_listening_(false) { | 
| #if defined(ENABLE_TASK_MANAGER) | 
| model_ = TaskManager::GetInstance()->model(); | 
| @@ -244,10 +242,6 @@ ProcessesEventRouter::~ProcessesEventRouter() { | 
| #endif  // defined(ENABLE_TASK_MANAGER) | 
| } | 
|  | 
| -void ProcessesEventRouter::ObserveProfile(Profile* profile) { | 
| -  profiles_.insert(profile); | 
| -} | 
| - | 
| void ProcessesEventRouter::ListenerAdded() { | 
| #if defined(ENABLE_TASK_MANAGER) | 
| // The task manager has its own ref count to balance other callers of | 
| @@ -323,7 +317,7 @@ void ProcessesEventRouter::OnItemsAdded(int start, int length) { | 
|  | 
| args->Append(process); | 
|  | 
| -  NotifyProfiles(keys::kOnCreated, args.Pass()); | 
| +  DispatchEvent(keys::kOnCreated, args.Pass()); | 
| #endif  // defined(ENABLE_TASK_MANAGER) | 
| } | 
|  | 
| @@ -370,7 +364,7 @@ void ProcessesEventRouter::OnItemsChanged(int start, int length) { | 
|  | 
| scoped_ptr<ListValue> args(new ListValue()); | 
| args->Append(processes); | 
| -    NotifyProfiles(keys::kOnUpdated, args.Pass()); | 
| +    DispatchEvent(keys::kOnUpdated, args.Pass()); | 
| } | 
|  | 
| if (updated_memory) { | 
| @@ -389,7 +383,7 @@ void ProcessesEventRouter::OnItemsChanged(int start, int length) { | 
|  | 
| scoped_ptr<ListValue> args(new ListValue()); | 
| args->Append(processes); | 
| -    NotifyProfiles(keys::kOnUpdatedWithMemory, args.Pass()); | 
| +    DispatchEvent(keys::kOnUpdatedWithMemory, args.Pass()); | 
| } | 
| #endif  // defined(ENABLE_TASK_MANAGER) | 
| } | 
| @@ -418,7 +412,7 @@ void ProcessesEventRouter::OnItemsToBeRemoved(int start, int length) { | 
| // Third arg: The exit code for the process. | 
| args->Append(Value::CreateIntegerValue(0)); | 
|  | 
| -  NotifyProfiles(keys::kOnExited, args.Pass()); | 
| +  DispatchEvent(keys::kOnExited, args.Pass()); | 
| #endif  // defined(ENABLE_TASK_MANAGER) | 
| } | 
|  | 
| @@ -448,7 +442,7 @@ void ProcessesEventRouter::ProcessHangEvent(content::RenderWidgetHost* widget) { | 
| scoped_ptr<ListValue> args(new ListValue()); | 
| args->Append(process); | 
|  | 
| -  NotifyProfiles(keys::kOnUnresponsive, args.Pass()); | 
| +  DispatchEvent(keys::kOnUnresponsive, args.Pass()); | 
| #endif  // defined(ENABLE_TASK_MANAGER) | 
| } | 
|  | 
| @@ -468,49 +462,65 @@ void ProcessesEventRouter::ProcessClosedEvent( | 
| // Third arg: The exit code for the process. | 
| args->Append(Value::CreateIntegerValue(details->exit_code)); | 
|  | 
| -  NotifyProfiles(keys::kOnExited, args.Pass()); | 
| +  DispatchEvent(keys::kOnExited, args.Pass()); | 
| #endif  // defined(ENABLE_TASK_MANAGER) | 
| } | 
|  | 
| -void ProcessesEventRouter::DispatchEvent(Profile* profile, | 
| -                                         const char* event_name, | 
| +void ProcessesEventRouter::DispatchEvent(const char* event_name, | 
| scoped_ptr<ListValue> event_args) { | 
| -  if (profile && extensions::ExtensionSystem::Get(profile)->event_router()) { | 
| -    extensions::ExtensionSystem::Get(profile)->event_router()-> | 
| +  if (extensions::ExtensionSystem::Get(profile_)->event_router()) { | 
| +    extensions::ExtensionSystem::Get(profile_)->event_router()-> | 
| DispatchEventToRenderers(event_name, event_args.Pass(), NULL, GURL(), | 
| extensions::EventFilteringInfo()); | 
| } | 
| } | 
|  | 
| -void ProcessesEventRouter::NotifyProfiles(const char* event_name, | 
| -                                          scoped_ptr<ListValue> event_args) { | 
| -  for (ProfileSet::iterator it = profiles_.begin(); | 
| -       it != profiles_.end(); ++it) { | 
| -    Profile* profile = *it; | 
| -    scoped_ptr<ListValue> event_args_copy(event_args->DeepCopy()); | 
| -    DispatchEvent(profile, event_name, event_args_copy.Pass()); | 
| -  } | 
| -} | 
| - | 
| -// In order to determine whether there are any listeners for the event of | 
| -// interest, we need to ask each profile whether it has one registered. | 
| -// We only need to look for the profiles that have registered with the | 
| -// this extension API. | 
| bool ProcessesEventRouter::HasEventListeners(const std::string& event_name) { | 
| -  for (ProfileSet::iterator it = profiles_.begin(); | 
| -       it != profiles_.end(); ++it) { | 
| -    Profile* profile = *it; | 
| -    extensions::EventRouter* router = | 
| -        extensions::ExtensionSystem::Get(profile)->event_router(); | 
| -    if (!router) | 
| -      continue; | 
| - | 
| -    if (router->HasEventListener(event_name)) | 
| +  extensions::EventRouter* router = | 
| +      extensions::ExtensionSystem::Get(profile_)->event_router(); | 
| +    if (router && router->HasEventListener(event_name)) | 
| return true; | 
| -  } | 
| return false; | 
| } | 
|  | 
| +ProcessesAPI::ProcessesAPI(Profile* profile) : profile_(profile) { | 
| +  ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 
| +      this, processes_api_constants::kOnUpdated); | 
| +  ExtensionSystem::Get(profile_)->event_router()->RegisterObserver( | 
| +      this, processes_api_constants::kOnUpdatedWithMemory); | 
| +} | 
| + | 
| +ProcessesAPI::~ProcessesAPI() { | 
| +} | 
| + | 
| +void ProcessesAPI::Shutdown() { | 
| +  ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this); | 
| +} | 
| + | 
| +// static | 
| +ProcessesAPI* ProcessesAPI::Get(Profile* profile) { | 
| +  return ProcessesAPIFactory::GetForProfile(profile); | 
| +} | 
| + | 
| +ProcessesEventRouter* ProcessesAPI::processes_event_router() { | 
| +  if (!processes_event_router_) | 
| +    processes_event_router_.reset(new ProcessesEventRouter(profile_)); | 
| +  return processes_event_router_.get(); | 
| +} | 
| + | 
| +void ProcessesAPI::OnListenerAdded(const std::string& event_name) { | 
| +  // We lazily tell the TaskManager to start updating when listeners to the | 
| +  // processes.onUpdated or processes.onUpdatedWithMemory events arrive. | 
| +  processes_event_router()->ListenerAdded(); | 
| +} | 
| + | 
| +void ProcessesAPI::OnListenerRemoved(const std::string& event_name) { | 
| +  // If a processes.onUpdated or processes.onUpdatedWithMemory event listener | 
| +  // is removed (or a process with one exits), then we let the extension API | 
| +  // know that it has one fewer listener. | 
| +  processes_event_router()->ListenerRemoved(); | 
| +} | 
| + | 
| GetProcessIdForTabFunction::GetProcessIdForTabFunction() : tab_id_(-1) { | 
| } | 
|  | 
| @@ -526,14 +536,16 @@ bool GetProcessIdForTabFunction::RunImpl() { | 
| // which will invoke the callback once we have returned from this function. | 
| // Otherwise, wait for the notification that the task manager is done with | 
| // the data gathering. | 
| -  if (ProcessesEventRouter::GetInstance()->is_task_manager_listening()) { | 
| +  if (ProcessesAPI::Get(profile_)->processes_event_router()-> | 
| +      is_task_manager_listening()) { | 
| MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 
| &GetProcessIdForTabFunction::GetProcessIdForTab, this)); | 
| } else { | 
| registrar_.Add(this, | 
| chrome::NOTIFICATION_TASK_MANAGER_CHILD_PROCESSES_DATA_READY, | 
| content::NotificationService::AllSources()); | 
| -    ProcessesEventRouter::GetInstance()->StartTaskManagerListening(); | 
| +    ProcessesAPI::Get(profile_)->processes_event_router()-> | 
| +        StartTaskManagerListening(); | 
| } | 
|  | 
| return true; | 
| @@ -587,14 +599,16 @@ bool TerminateFunction::RunImpl() { | 
| // which will invoke the callback once we have returned from this function. | 
| // Otherwise, wait for the notification that the task manager is done with | 
| // the data gathering. | 
| -  if (ProcessesEventRouter::GetInstance()->is_task_manager_listening()) { | 
| +  if (ProcessesAPI::Get(profile_)->processes_event_router()-> | 
| +      is_task_manager_listening()) { | 
| MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 
| &TerminateFunction::TerminateProcess, this)); | 
| } else { | 
| registrar_.Add(this, | 
| chrome::NOTIFICATION_TASK_MANAGER_CHILD_PROCESSES_DATA_READY, | 
| content::NotificationService::AllSources()); | 
| -    ProcessesEventRouter::GetInstance()->StartTaskManagerListening(); | 
| +    ProcessesAPI::Get(profile_)->processes_event_router()-> | 
| +        StartTaskManagerListening(); | 
| } | 
|  | 
| return true; | 
| @@ -673,14 +687,16 @@ bool GetProcessInfoFunction::RunImpl() { | 
| // which will invoke the callback once we have returned from this function. | 
| // Otherwise, wait for the notification that the task manager is done with | 
| // the data gathering. | 
| -  if (ProcessesEventRouter::GetInstance()->is_task_manager_listening()) { | 
| +  if (ProcessesAPI::Get(profile_)->processes_event_router()-> | 
| +      is_task_manager_listening()) { | 
| MessageLoop::current()->PostTask(FROM_HERE, base::Bind( | 
| &GetProcessInfoFunction::GatherProcessInfo, this)); | 
| } else { | 
| registrar_.Add(this, | 
| chrome::NOTIFICATION_TASK_MANAGER_CHILD_PROCESSES_DATA_READY, | 
| content::NotificationService::AllSources()); | 
| -    ProcessesEventRouter::GetInstance()->StartTaskManagerListening(); | 
| +    ProcessesAPI::Get(profile_)->processes_event_router()-> | 
| +        StartTaskManagerListening(); | 
| } | 
| return true; | 
|  | 
|  |