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 "content/browser/histogram_subscriber.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/render_process_host.h" 15 #include "content/public/common/process_type.h" 16 17 namespace content { 18 19 HistogramController* HistogramController::GetInstance() { 20 return Singleton<HistogramController>::get(); 21 } 22 23 HistogramController::HistogramController() : subscriber_(NULL) { 24 } 25 26 HistogramController::~HistogramController() { 27 } 28 29 void HistogramController::OnPendingProcesses(int sequence_number, 30 int pending_processes, 31 bool end) { 32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 33 if (subscriber_) 34 subscriber_->OnPendingProcesses(sequence_number, pending_processes, end); 35 } 36 37 void HistogramController::OnHistogramDataCollected( 38 int sequence_number, 39 const std::vector<std::string>& pickled_histograms) { 40 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 41 BrowserThread::PostTask( 42 BrowserThread::UI, FROM_HERE, 43 base::Bind(&HistogramController::OnHistogramDataCollected, 44 base::Unretained(this), 45 sequence_number, 46 pickled_histograms)); 47 return; 48 } 49 50 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 51 if (subscriber_) { 52 subscriber_->OnHistogramDataCollected(sequence_number, 53 pickled_histograms); 54 } 55 } 56 57 void HistogramController::Register(HistogramSubscriber* subscriber) { 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 59 DCHECK(!subscriber_); 60 subscriber_ = subscriber; 61 } 62 63 void HistogramController::Unregister( 64 const HistogramSubscriber* subscriber) { 65 DCHECK_EQ(subscriber_, subscriber); 66 subscriber_ = NULL; 67 } 68 69 void HistogramController::GetHistogramDataFromChildProcesses( 70 int sequence_number) { 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 72 73 int pending_processes = 0; 74 for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { 75 int type = iter.GetData().process_type; 76 if (type != PROCESS_TYPE_PLUGIN && 77 type != PROCESS_TYPE_GPU && 78 type != PROCESS_TYPE_PPAPI_PLUGIN && 79 type != PROCESS_TYPE_PPAPI_BROKER) { 80 continue; 81 } 82 83 ++pending_processes; 84 if (!iter.Send(new ChildProcessMsg_GetChildHistogramData(sequence_number))) 85 --pending_processes; 86 } 87 88 BrowserThread::PostTask( 89 BrowserThread::UI, 90 FROM_HERE, 91 base::Bind( 92 &HistogramController::OnPendingProcesses, 93 base::Unretained(this), 94 sequence_number, 95 pending_processes, 96 true)); 97 } 98 99 void HistogramController::GetHistogramData(int sequence_number) { 100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 101 102 int pending_processes = 0; 103 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); 104 !it.IsAtEnd(); it.Advance()) { 105 ++pending_processes; 106 if (!it.GetCurrentValue()->Send( 107 new ChildProcessMsg_GetChildHistogramData(sequence_number))) { 108 --pending_processes; 109 } 110 } 111 OnPendingProcesses(sequence_number, pending_processes, false); 112 113 BrowserThread::PostTask( 114 BrowserThread::IO, 115 FROM_HERE, 116 base::Bind(&HistogramController::GetHistogramDataFromChildProcesses, 117 base::Unretained(this), 118 sequence_number)); 119 } 120 121 } // namespace content 122