Home | History | Annotate | Download | only in browser
      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