perf_provider_chromeos.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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)
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Partition time since login into successive intervals of this size. In each
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// interval, pick a random time to collect a profile.
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// This interval is twenty-four hours.
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const size_t kPerfProfilingIntervalMs = 24 * 60 * 60 * 1000;
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default time in seconds perf is run for.
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kPerfCommandDurationDefaultSeconds = 2;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Limit the total size of protobufs that can be cached, so they don't take up
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// too much memory. If the size of cached protobufs exceeds this value, stop
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// collecting further perf data. The current value is 4 MB.
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
40a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Enumeration representing success and various failure modes for collecting and
41a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// sending perf data.
42a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)enum GetPerfDataOutcome {
43a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  SUCCESS,
44a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOT_READY_TO_UPLOAD,
45a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOT_READY_TO_COLLECT,
46a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  INCOGNITO_ACTIVE,
47a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  INCOGNITO_LAUNCHED,
48a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PROTOBUF_NOT_PARSED,
49a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NUM_OUTCOMES
50a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)};
51a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
52a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Name of the histogram that represents the success and various failure modes
53a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// for collecting and sending perf data.
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData";
55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void AddToPerfHistogram(GetPerfDataOutcome outcome) {
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram,
58a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            outcome,
59a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            NUM_OUTCOMES);
60a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
61a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true if a normal user is logged in. Returns false if logged in as an
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// guest or as a kiosk app.
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsNormalUserLoggedIn() {
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState* login_state = chromeos::LoginState::Get();
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (login_state->IsUserLoggedIn() && !login_state->IsGuestUser() &&
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          !login_state->IsKioskApp());
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace metrics {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class must be created and used on the UI thread. It watches for any
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// incognito window being opened from the time it is instantiated to the time it
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is destroyed.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class WindowedIncognitoObserver : public chrome::BrowserListObserver {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WindowedIncognitoObserver() : incognito_launched_(false) {
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserList::AddObserver(this);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~WindowedIncognitoObserver() {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserList::RemoveObserver(this);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method can be checked to see whether any incognito window has been
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // opened since the time this object was created.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool incognito_launched() {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return incognito_launched_;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // chrome::BrowserListObserver implementation.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser->profile()->IsOffTheRecord())
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      incognito_launched_ = true;
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool incognito_launched_;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PerfProvider::PerfProvider()
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : login_observer_(this),
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        next_profiling_interval_start_(base::TimeTicks::Now()),
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        weak_factory_(this) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Register the login observer with LoginState.
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState::Get()->AddObserver(&login_observer_);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check the login state. At the time of writing, this class is instantiated
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // before login. A subsequent login would activate the profiling. However,
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // that behavior may change in the future so that the user is already logged
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // when this class is instantiated. By calling LoggedInStateChanged() here,
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // PerfProvider will recognize that the system is already logged in.
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  login_observer_.LoggedInStateChanged();
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PerfProvider::~PerfProvider() {
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState::Get()->RemoveObserver(&login_observer_);
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool PerfProvider::GetSampledProfiles(
12446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::vector<SampledProfile>* sampled_profiles) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cached_perf_data_.empty()) {
127a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_UPLOAD);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
129a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  sampled_profiles->swap(cached_perf_data_);
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.clear();
133a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
134a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  AddToPerfHistogram(SUCCESS);
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider)
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : perf_provider_(perf_provider) {}
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::LoginObserver::LoggedInStateChanged() {
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (IsNormalUserLoggedIn())
14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    perf_provider_->OnUserLoggedIn();
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    perf_provider_->Deactivate();
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::OnUserLoggedIn() {
14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  login_time_ = base::TimeTicks::Now();
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ScheduleCollection();
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::Deactivate() {
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Stop the timer, but leave |cached_perf_data_| intact.
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  timer_.Stop();
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::ScheduleCollection() {
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (timer_.IsRunning())
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Pick a random time in the current interval.
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::TimeTicks scheduled_time =
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      next_profiling_interval_start_ +
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          base::RandGenerator(kPerfProfilingIntervalMs));
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the scheduled time has already passed in the time it took to make the
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // above calculations, trigger the collection event immediately.
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (scheduled_time < now)
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scheduled_time = now;
17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  timer_.Start(FROM_HERE, scheduled_time - now, this,
17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)               &PerfProvider::DoPeriodicCollection);
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Update the profiling interval tracker to the start of the next interval.
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  next_profiling_interval_start_ +=
18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::CollectIfNecessary(
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SampledProfile::TriggerEvent trigger_event) {
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
187c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Do not collect further data if we've already collected a substantial amount
188c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
189c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  size_t cached_perf_data_size = 0;
190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < cached_perf_data_.size(); ++i) {
191c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cached_perf_data_size += cached_perf_data_[i].ByteSize();
192c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
193c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) {
194a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_COLLECT);
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
196a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For privacy reasons, Chrome should only collect perf data if there is no
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // incognito session active (or gets spawned during the collection).
200a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (BrowserList::IsOffTheRecordSessionActive()) {
201a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_ACTIVE);
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
203a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<WindowedIncognitoObserver> incognito_observer(
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new WindowedIncognitoObserver);
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chromeos::DebugDaemonClient* client =
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kPerfCommandDurationDefaultSeconds);
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client->GetPerfData(collection_duration.InSeconds(),
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::Bind(&PerfProvider::ParseProtoIfValid,
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 weak_factory_.GetWeakPtr(),
21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 base::Passed(&incognito_observer),
21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 trigger_event));
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::DoPeriodicCollection() {
22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  CollectIfNecessary(SampledProfile::PERIODIC_COLLECTION);
22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  ScheduleCollection();
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PerfProvider::ParseProtoIfValid(
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<WindowedIncognitoObserver> incognito_observer,
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    SampledProfile::TriggerEvent trigger_event,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<uint8>& data) {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (incognito_observer->incognito_launched()) {
233a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_LAUNCHED);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
235a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PerfDataProto perf_data_proto;
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!perf_data_proto.ParseFromArray(data.data(), data.size())) {
239a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(PROTOBUF_NOT_PARSED);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Populate a profile collection protobuf with the collected perf data and
24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // extra metadata.
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.resize(cached_perf_data_.size() + 1);
24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SampledProfile& collection_data = cached_perf_data_.back();
24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  collection_data.set_trigger_event(trigger_event);
24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  collection_data.set_ms_after_boot(
24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond);
25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!login_time_.is_null());
25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  collection_data.
25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      set_ms_after_login((base::TimeTicks::Now() - login_time_)
25446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          .InMilliseconds());
25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  *collection_data.mutable_perf_data() = perf_data_proto;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace metrics
259