Home | History | Annotate | Download | only in browser
      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 #include "content/browser/profiler_controller_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/command_line.h"
      9 #include "base/tracked_objects.h"
     10 #include "content/common/child_process_messages.h"
     11 #include "content/public/browser/browser_child_process_host_iterator.h"
     12 #include "content/public/browser/browser_thread.h"
     13 #include "content/public/browser/child_process_data.h"
     14 #include "content/public/browser/profiler_subscriber.h"
     15 #include "content/public/browser/render_process_host.h"
     16 #include "content/public/common/content_switches.h"
     17 
     18 namespace content {
     19 
     20 ProfilerController* ProfilerController::GetInstance() {
     21   return ProfilerControllerImpl::GetInstance();
     22 }
     23 
     24 ProfilerControllerImpl* ProfilerControllerImpl::GetInstance() {
     25   return Singleton<ProfilerControllerImpl>::get();
     26 }
     27 
     28 ProfilerControllerImpl::ProfilerControllerImpl() : subscriber_(NULL) {
     29 }
     30 
     31 ProfilerControllerImpl::~ProfilerControllerImpl() {
     32 }
     33 
     34 void ProfilerControllerImpl::OnPendingProcesses(int sequence_number,
     35                                                 int pending_processes,
     36                                                 bool end) {
     37   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     38   if (subscriber_)
     39     subscriber_->OnPendingProcesses(sequence_number, pending_processes, end);
     40 }
     41 
     42 void ProfilerControllerImpl::OnProfilerDataCollected(
     43     int sequence_number,
     44     const tracked_objects::ProcessDataSnapshot& profiler_data,
     45     int process_type) {
     46   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     47     BrowserThread::PostTask(
     48         BrowserThread::UI, FROM_HERE,
     49         base::Bind(&ProfilerControllerImpl::OnProfilerDataCollected,
     50                    base::Unretained(this),
     51                    sequence_number,
     52                    profiler_data,
     53                    process_type));
     54     return;
     55   }
     56 
     57   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     58   if (subscriber_) {
     59     subscriber_->OnProfilerDataCollected(sequence_number, profiler_data,
     60                                          process_type);
     61   }
     62 }
     63 
     64 void ProfilerControllerImpl::Register(ProfilerSubscriber* subscriber) {
     65   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     66   DCHECK(!subscriber_);
     67   subscriber_ = subscriber;
     68 }
     69 
     70 void ProfilerControllerImpl::Unregister(const ProfilerSubscriber* subscriber) {
     71   DCHECK_EQ(subscriber_, subscriber);
     72   subscriber_ = NULL;
     73 }
     74 
     75 void ProfilerControllerImpl::GetProfilerDataFromChildProcesses(
     76     int sequence_number) {
     77   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     78 
     79   int pending_processes = 0;
     80   for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
     81     // Skips requesting profiler data from the "GPU Process" if we are using in
     82     // process GPU. Those stats should be in the Browser-process's GPU thread.
     83     if (iter.GetData().process_type == PROCESS_TYPE_GPU &&
     84         CommandLine::ForCurrentProcess()->HasSwitch(switches::kInProcessGPU)) {
     85       continue;
     86     }
     87 
     88     ++pending_processes;
     89     if (!iter.Send(new ChildProcessMsg_GetChildProfilerData(sequence_number)))
     90       --pending_processes;
     91   }
     92 
     93   BrowserThread::PostTask(
     94       BrowserThread::UI,
     95       FROM_HERE,
     96       base::Bind(
     97           &ProfilerControllerImpl::OnPendingProcesses,
     98           base::Unretained(this),
     99           sequence_number,
    100           pending_processes,
    101           true));
    102 }
    103 
    104 void ProfilerControllerImpl::GetProfilerData(int sequence_number) {
    105   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    106 
    107   int pending_processes = 0;
    108   for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
    109        !it.IsAtEnd(); it.Advance()) {
    110     ++pending_processes;
    111     if (!it.GetCurrentValue()->Send(
    112             new ChildProcessMsg_GetChildProfilerData(sequence_number))) {
    113       --pending_processes;
    114     }
    115   }
    116   OnPendingProcesses(sequence_number, pending_processes, false);
    117 
    118   BrowserThread::PostTask(
    119       BrowserThread::IO,
    120       FROM_HERE,
    121       base::Bind(&ProfilerControllerImpl::GetProfilerDataFromChildProcesses,
    122                  base::Unretained(this),
    123                  sequence_number));
    124 }
    125 
    126 }  // namespace content
    127