• 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/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 
GetInstance()20 HistogramController* HistogramController::GetInstance() {
21   return Singleton<HistogramController>::get();
22 }
23 
HistogramController()24 HistogramController::HistogramController() : subscriber_(NULL) {
25 }
26 
~HistogramController()27 HistogramController::~HistogramController() {
28 }
29 
OnPendingProcesses(int sequence_number,int pending_processes,bool end)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 
OnHistogramDataCollected(int sequence_number,const std::vector<std::string> & pickled_histograms)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 
Register(HistogramSubscriber * subscriber)58 void HistogramController::Register(HistogramSubscriber* subscriber) {
59   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
60   DCHECK(!subscriber_);
61   subscriber_ = subscriber;
62 }
63 
Unregister(const HistogramSubscriber * subscriber)64 void HistogramController::Unregister(
65     const HistogramSubscriber* subscriber) {
66   DCHECK_EQ(subscriber_, subscriber);
67   subscriber_ = NULL;
68 }
69 
GetHistogramDataFromChildProcesses(int sequence_number)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 
GetHistogramData(int sequence_number)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