perf_provider_chromeos.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/rand_util.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/metrics/perf_provider_chromeos.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_list_observer.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/debug_daemon_client.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default time in seconds between invocations of perf.
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This period is roughly 6.5 hours.
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This is chosen to be relatively prime with the number of seconds in:
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// - one minute (60)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// - one hour (3600)
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// - one day (86400)
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kPerfCommandIntervalDefaultSeconds = 23093;
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The first collection interval is different from the interval above. This is
36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// because we want to collect the first profile quickly after Chrome is started.
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// If this period is too long, the user will log off and Chrome will be killed
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// before it is triggered. The following 2 variables determine the upper and
39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// lower bound on the interval.
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The reason we do not always want to collect the initial profile after a fixed
41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// period is to not over-represent task X in the profile where task X always
42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// runs at a fixed period after start-up. By selecting a period randomly between
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// a lower and upper bound, we will hopefully collect a more fair profile.
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kPerfCommandStartIntervalLowerBoundMinutes = 10;
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kPerfCommandStartIntervalUpperBoundMinutes = 20;
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default time in seconds perf is run for.
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kPerfCommandDurationDefaultSeconds = 2;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Limit the total size of protobufs that can be cached, so they don't take up
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// too much memory. If the size of cached protobufs exceeds this value, stop
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// collecting further perf data. The current value is 4 MB.
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Enumeration representing success and various failure modes for collecting and
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// sending perf data.
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)enum GetPerfDataOutcome {
59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  SUCCESS,
60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOT_READY_TO_UPLOAD,
61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOT_READY_TO_COLLECT,
62a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  INCOGNITO_ACTIVE,
63a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  INCOGNITO_LAUNCHED,
64a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PROTOBUF_NOT_PARSED,
65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NUM_OUTCOMES
66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)};
67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Name of the histogram that represents the success and various failure modes
69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// for collecting and sending perf data.
70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData";
71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void AddToPerfHistogram(GetPerfDataOutcome outcome) {
73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram,
74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            outcome,
75a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            NUM_OUTCOMES);
76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true if a normal user is logged in. Returns false if logged in as an
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// guest or as a kiosk app.
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsNormalUserLoggedIn() {
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState* login_state = chromeos::LoginState::Get();
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (login_state->IsUserLoggedIn() && !login_state->IsGuestUser() &&
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          !login_state->IsKioskApp());
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace metrics {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class must be created and used on the UI thread. It watches for any
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// incognito window being opened from the time it is instantiated to the time it
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is destroyed.
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class WindowedIncognitoObserver : public chrome::BrowserListObserver {
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WindowedIncognitoObserver() : incognito_launched_(false) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserList::AddObserver(this);
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~WindowedIncognitoObserver() {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserList::RemoveObserver(this);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method can be checked to see whether any incognito window has been
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // opened since the time this object was created.
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool incognito_launched() {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return incognito_launched_;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // chrome::BrowserListObserver implementation.
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser->profile()->IsOffTheRecord())
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      incognito_launched_ = true;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool incognito_launched_;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PerfProvider::PerfProvider()
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : login_observer_(this),
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        weak_factory_(this) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Register the login observer with LoginState.
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState::Get()->AddObserver(&login_observer_);
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check the login state. At the time of writing, this class is instantiated
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // before login. A subsequent login would activate the profiling. However,
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // that behavior may change in the future so that the user is already logged
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // when this class is instantiated. By calling LoggedInStateChanged() here,
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // PerfProvider will recognize that the system is already logged in.
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  login_observer_.LoggedInStateChanged();
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PerfProvider::~PerfProvider() {
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState::Get()->RemoveObserver(&login_observer_);
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool PerfProvider::GetPerfData(std::vector<PerfDataProto>* perf_data) {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cached_perf_data_.empty()) {
141a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_UPLOAD);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
143a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  perf_data->swap(cached_perf_data_);
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.clear();
147a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
148a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  AddToPerfHistogram(SUCCESS);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider)
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : perf_provider_(perf_provider) {}
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::LoginObserver::LoggedInStateChanged() {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (IsNormalUserLoggedIn())
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    perf_provider_->Activate();
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    perf_provider_->Deactivate();
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::Activate() {
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t collection_interval_minutes = base::RandInt(
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      kPerfCommandStartIntervalLowerBoundMinutes,
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      kPerfCommandStartIntervalUpperBoundMinutes);
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ScheduleCollection(base::TimeDelta::FromMinutes(collection_interval_minutes));
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::Deactivate() {
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Stop the timer, but leave |cached_perf_data_| intact.
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  timer_.Stop();
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PerfProvider::ScheduleCollection(const base::TimeDelta& interval) {
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (timer_.IsRunning())
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  timer_.Start(FROM_HERE, interval, this,
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               &PerfProvider::CollectIfNecessaryAndReschedule);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PerfProvider::CollectIfNecessary() {
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
185c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Do not collect further data if we've already collected a substantial amount
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  size_t cached_perf_data_size = 0;
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < cached_perf_data_.size(); ++i) {
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cached_perf_data_size += cached_perf_data_[i].ByteSize();
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) {
193a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_COLLECT);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
195a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For privacy reasons, Chrome should only collect perf data if there is no
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // incognito session active (or gets spawned during the collection).
199a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (BrowserList::IsOffTheRecordSessionActive()) {
200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_ACTIVE);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<WindowedIncognitoObserver> incognito_observer(
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new WindowedIncognitoObserver);
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chromeos::DebugDaemonClient* client =
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kPerfCommandDurationDefaultSeconds);
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client->GetPerfData(collection_duration.InSeconds(),
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::Bind(&PerfProvider::ParseProtoIfValid,
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 weak_factory_.GetWeakPtr(),
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 base::Passed(&incognito_observer)));
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void PerfProvider::CollectIfNecessaryAndReschedule() {
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CollectIfNecessary();
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ScheduleCollection(
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::TimeDelta::FromSeconds(kPerfCommandIntervalDefaultSeconds));
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PerfProvider::ParseProtoIfValid(
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<WindowedIncognitoObserver> incognito_observer,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<uint8>& data) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
230a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (incognito_observer->incognito_launched()) {
231a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_LAUNCHED);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PerfDataProto perf_data_proto;
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!perf_data_proto.ParseFromArray(data.data(), data.size())) {
237a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(PROTOBUF_NOT_PARSED);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Append a new PerfDataProto to the |cached_perf_data_| vector and swap in
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // the contents.
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.resize(cached_perf_data_.size() + 1);
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.back().Swap(&perf_data_proto);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace metrics
248