perf_provider_chromeos.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 <string>
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/command_line.h"
11#include "base/compiler_specific.h"
12#include "base/metrics/histogram.h"
13#include "base/process_util.h"
14#include "base/string_number_conversions.h"
15#include "base/threading/sequenced_worker_pool.h"
16#include "chrome/browser/metrics/perf_provider_chromeos.h"
17#include "chrome/browser/profiles/profile.h"
18#include "chrome/browser/ui/browser.h"
19#include "chrome/browser/ui/browser_list.h"
20#include "chrome/browser/ui/browser_list_observer.h"
21#include "chrome/common/chrome_switches.h"
22#include "chromeos/dbus/dbus_thread_manager.h"
23#include "chromeos/dbus/debug_daemon_client.h"
24#include "content/public/browser/browser_thread.h"
25
26namespace {
27
28// Default time in seconds between invocations of perf.
29// This is chosen to be relatively prime with the number of seconds in a day
30// (86400). This period is roughly 13 hours.
31const unsigned kPerfCommandIntervalDefaultSeconds = 47221;
32
33// Default time in seconds perf is run for.
34const unsigned kPerfCommandDurationDefaultSeconds = 2;
35
36} // namespace
37
38
39namespace metrics {
40
41// This class must be created and used on the UI thread. It watches for any
42// incognito window being opened from the time it is instantiated to the time it
43// is destroyed.
44class WindowedIncognitoObserver : public chrome::BrowserListObserver {
45 public:
46  WindowedIncognitoObserver() : incognito_launched_(false) {
47    BrowserList::AddObserver(this);
48  }
49
50  virtual ~WindowedIncognitoObserver() {
51    BrowserList::RemoveObserver(this);
52  }
53
54  // This method can be checked to see whether any incognito window has been
55  // opened since the time this object was created.
56  bool incognito_launched() {
57    return incognito_launched_;
58  }
59
60 private:
61  // chrome::BrowserListObserver implementation.
62  virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
63    if (browser->profile()->IsOffTheRecord())
64      incognito_launched_ = true;
65  }
66
67  bool incognito_launched_;
68};
69
70PerfProvider::PerfProvider()
71      : state_(READY_TO_COLLECT),
72      ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
73  ScheduleCollection();
74}
75
76PerfProvider::~PerfProvider() {}
77
78bool PerfProvider::GetPerfData(PerfDataProto* perf_data_proto) {
79  DCHECK(CalledOnValidThread());
80  if (state_ != READY_TO_UPLOAD)
81    return false;
82
83  *perf_data_proto = perf_data_proto_;
84  state_ = READY_TO_COLLECT;
85  return true;
86}
87
88void PerfProvider::ScheduleCollection() {
89  DCHECK(CalledOnValidThread());
90  if (timer_.IsRunning())
91    return;
92
93  base::TimeDelta collection_interval = base::TimeDelta::FromSeconds(
94      kPerfCommandIntervalDefaultSeconds);
95
96  timer_.Start(FROM_HERE, collection_interval, this,
97               &PerfProvider::CollectIfNecessary);
98}
99
100void PerfProvider::CollectIfNecessary() {
101  DCHECK(CalledOnValidThread());
102  if (state_ != READY_TO_COLLECT)
103    return;
104
105  // For privacy reasons, Chrome should only collect perf data if there is no
106  // incognito session active (or gets spawned during the collection).
107  if (BrowserList::IsOffTheRecordSessionActive())
108    return;
109
110  scoped_ptr<WindowedIncognitoObserver> incognito_observer(
111      new WindowedIncognitoObserver);
112
113  chromeos::DebugDaemonClient* client =
114      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
115
116  base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
117      kPerfCommandDurationDefaultSeconds);
118
119  client->GetPerfData(collection_duration.InSeconds(),
120                      base::Bind(&PerfProvider::ParseProtoIfValid,
121                                 weak_factory_.GetWeakPtr(),
122                                 base::Passed(&incognito_observer)));
123}
124
125
126void PerfProvider::ParseProtoIfValid(
127    scoped_ptr<WindowedIncognitoObserver> incognito_observer,
128    const std::vector<uint8>& data) {
129  DCHECK(CalledOnValidThread());
130
131  if (incognito_observer->incognito_launched())
132    return;
133
134  if (!perf_data_proto_.ParseFromArray(data.data(), data.size())) {
135    perf_data_proto_.Clear();
136    return;
137  }
138
139  state_ = READY_TO_UPLOAD;
140}
141} // namespace metrics
142