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