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/histogram_controller.h" 6 7 #include "base/bind.h" 8 #include "base/metrics/histogram.h" 9 #include "base/process/process_handle.h" 10 #include "content/browser/histogram_subscriber.h" 11 #include "content/common/child_process_messages.h" 12 #include "content/public/browser/browser_child_process_host_iterator.h" 13 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/child_process_data.h" 15 #include "content/public/browser/render_process_host.h" 16 #include "content/public/common/process_type.h" 17 18 namespace content { 19 20 HistogramController* HistogramController::GetInstance() { 21 return Singleton<HistogramController>::get(); 22 } 23 24 HistogramController::HistogramController() : subscriber_(NULL) { 25 } 26 27 HistogramController::~HistogramController() { 28 } 29 30 void HistogramController::OnPendingProcesses(int sequence_number, 31 int pending_processes, 32 bool end) { 33 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 34 if (subscriber_) 35 subscriber_->OnPendingProcesses(sequence_number, pending_processes, end); 36 } 37 38 void HistogramController::OnHistogramDataCollected( 39 int sequence_number, 40 const std::vector<std::string>& pickled_histograms) { 41 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 42 BrowserThread::PostTask( 43 BrowserThread::UI, FROM_HERE, 44 base::Bind(&HistogramController::OnHistogramDataCollected, 45 base::Unretained(this), 46 sequence_number, 47 pickled_histograms)); 48 return; 49 } 50 51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 52 if (subscriber_) { 53 subscriber_->OnHistogramDataCollected(sequence_number, 54 pickled_histograms); 55 } 56 } 57 58 void HistogramController::Register(HistogramSubscriber* subscriber) { 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 60 DCHECK(!subscriber_); 61 subscriber_ = subscriber; 62 } 63 64 void HistogramController::Unregister( 65 const HistogramSubscriber* subscriber) { 66 DCHECK_EQ(subscriber_, subscriber); 67 subscriber_ = NULL; 68 } 69 70 void HistogramController::GetHistogramDataFromChildProcesses( 71 int sequence_number) { 72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 73 74 int pending_processes = 0; 75 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { 76 const ChildProcessData& data = iter.GetData(); 77 int type = data.process_type; 78 if (type != PROCESS_TYPE_PLUGIN && 79 type != PROCESS_TYPE_GPU && 80 type != PROCESS_TYPE_PPAPI_PLUGIN && 81 type != PROCESS_TYPE_PPAPI_BROKER) { 82 continue; 83 } 84 85 // In some cases, there may be no child process of the given type (for 86 // example, the GPU process may not exist and there may instead just be a 87 // GPU thread in the browser process). If that's the case, then the process 88 // handle will be base::kNullProcessHandle and we shouldn't ask it for data. 89 if (data.handle == base::kNullProcessHandle) 90 continue; 91 92 ++pending_processes; 93 if (!iter.Send(new ChildProcessMsg_GetChildHistogramData(sequence_number))) 94 --pending_processes; 95 } 96 97 BrowserThread::PostTask( 98 BrowserThread::UI, 99 FROM_HERE, 100 base::Bind( 101 &HistogramController::OnPendingProcesses, 102 base::Unretained(this), 103 sequence_number, 104 pending_processes, 105 true)); 106 } 107 108 void HistogramController::GetHistogramData(int sequence_number) { 109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 110 111 int pending_processes = 0; 112 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); 113 !it.IsAtEnd(); it.Advance()) { 114 ++pending_processes; 115 if (!it.GetCurrentValue()->Send( 116 new ChildProcessMsg_GetChildHistogramData(sequence_number))) { 117 --pending_processes; 118 } 119 } 120 OnPendingProcesses(sequence_number, pending_processes, false); 121 122 BrowserThread::PostTask( 123 BrowserThread::IO, 124 FROM_HERE, 125 base::Bind(&HistogramController::GetHistogramDataFromChildProcesses, 126 base::Unretained(this), 127 sequence_number)); 128 } 129 130 } // namespace content 131