• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/process/process_handle.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 
17 namespace content {
18 
GetInstance()19 ProfilerController* ProfilerController::GetInstance() {
20   return ProfilerControllerImpl::GetInstance();
21 }
22 
GetInstance()23 ProfilerControllerImpl* ProfilerControllerImpl::GetInstance() {
24   return Singleton<ProfilerControllerImpl>::get();
25 }
26 
ProfilerControllerImpl()27 ProfilerControllerImpl::ProfilerControllerImpl() : subscriber_(NULL) {
28 }
29 
~ProfilerControllerImpl()30 ProfilerControllerImpl::~ProfilerControllerImpl() {
31 }
32 
OnPendingProcesses(int sequence_number,int pending_processes,bool end)33 void ProfilerControllerImpl::OnPendingProcesses(int sequence_number,
34                                                 int pending_processes,
35                                                 bool end) {
36   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
37   if (subscriber_)
38     subscriber_->OnPendingProcesses(sequence_number, pending_processes, end);
39 }
40 
OnProfilerDataCollected(int sequence_number,const tracked_objects::ProcessDataSnapshot & profiler_data,int process_type)41 void ProfilerControllerImpl::OnProfilerDataCollected(
42     int sequence_number,
43     const tracked_objects::ProcessDataSnapshot& profiler_data,
44     int process_type) {
45   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
46     BrowserThread::PostTask(
47         BrowserThread::UI, FROM_HERE,
48         base::Bind(&ProfilerControllerImpl::OnProfilerDataCollected,
49                    base::Unretained(this),
50                    sequence_number,
51                    profiler_data,
52                    process_type));
53     return;
54   }
55 
56   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
57   if (subscriber_) {
58     subscriber_->OnProfilerDataCollected(sequence_number, profiler_data,
59                                          process_type);
60   }
61 }
62 
Register(ProfilerSubscriber * subscriber)63 void ProfilerControllerImpl::Register(ProfilerSubscriber* subscriber) {
64   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
65   DCHECK(!subscriber_);
66   subscriber_ = subscriber;
67 }
68 
Unregister(const ProfilerSubscriber * subscriber)69 void ProfilerControllerImpl::Unregister(const ProfilerSubscriber* subscriber) {
70   DCHECK_EQ(subscriber_, subscriber);
71   subscriber_ = NULL;
72 }
73 
GetProfilerDataFromChildProcesses(int sequence_number)74 void ProfilerControllerImpl::GetProfilerDataFromChildProcesses(
75     int sequence_number) {
76   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
77 
78   int pending_processes = 0;
79   for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
80     // In some cases, there may be no child process of the given type (for
81     // example, the GPU process may not exist and there may instead just be a
82     // GPU thread in the browser process). If that's the case, then the process
83     // handle will be base::kNullProcessHandle and we shouldn't ask it for data.
84     if (iter.GetData().handle == base::kNullProcessHandle)
85       continue;
86 
87     ++pending_processes;
88     if (!iter.Send(new ChildProcessMsg_GetChildProfilerData(sequence_number)))
89       --pending_processes;
90   }
91 
92   BrowserThread::PostTask(
93       BrowserThread::UI,
94       FROM_HERE,
95       base::Bind(
96           &ProfilerControllerImpl::OnPendingProcesses,
97           base::Unretained(this),
98           sequence_number,
99           pending_processes,
100           true));
101 }
102 
GetProfilerData(int sequence_number)103 void ProfilerControllerImpl::GetProfilerData(int sequence_number) {
104   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105 
106   int pending_processes = 0;
107   for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
108        !it.IsAtEnd(); it.Advance()) {
109     ++pending_processes;
110     if (!it.GetCurrentValue()->Send(
111             new ChildProcessMsg_GetChildProfilerData(sequence_number))) {
112       --pending_processes;
113     }
114   }
115   OnPendingProcesses(sequence_number, pending_processes, false);
116 
117   BrowserThread::PostTask(
118       BrowserThread::IO,
119       FROM_HERE,
120       base::Bind(&ProfilerControllerImpl::GetProfilerDataFromChildProcesses,
121                  base::Unretained(this),
122                  sequence_number));
123 }
124 
125 }  // namespace content
126