perf_provider_chromeos.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/metrics/perf_provider_chromeos.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_list_observer.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_switches.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/debug_daemon_client.h"
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/notification_service.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Partition time since login into successive intervals of this size. In each
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// interval, pick a random time to collect a profile.
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// This interval is twenty-four hours.
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const size_t kPerfProfilingIntervalMs = 24 * 60 * 60 * 1000;
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Default time in seconds perf is run for.
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const size_t kPerfCommandDurationDefaultSeconds = 2;
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Limit the total size of protobufs that can be cached, so they don't take up
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// too much memory. If the size of cached protobufs exceeds this value, stop
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// collecting further perf data. The current value is 4 MB.
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochconst size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// There may be too many suspends to collect a profile each time there is a
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// resume. To limit the number of profiles, collect one for 1 in 10 resumes.
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Adjust this number as needed.
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const int kResumeSamplingFactor = 10;
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// There may be too many session restores to collect a profile each time. Limit
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// the collection rate by collecting one per 10 restores. Adjust this number as
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// needed.
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kRestoreSessionSamplingFactor = 10;
51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// This is used to space out session restore collections in the face of several
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// notifications in a short period of time. There should be no less than this
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// much time between collections. The current value is 30 seconds.
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kMinIntervalBetweenSessionRestoreCollectionsMs = 30 * 1000;
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// If collecting after a resume, add a random delay before collecting. The delay
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// should be randomly selected between 0 and this value. Currently the value is
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// equal to 5 seconds.
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kMaxResumeCollectionDelayMs = 5 * 1000;
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// If collecting after a session restore, add a random delay before collecting.
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// The delay should be randomly selected between 0 and this value. Currently the
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// value is equal to 10 seconds.
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kMaxRestoreSessionCollectionDelayMs = 10 * 1000;
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
67a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Enumeration representing success and various failure modes for collecting and
68a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// sending perf data.
69a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)enum GetPerfDataOutcome {
70a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  SUCCESS,
71a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOT_READY_TO_UPLOAD,
72a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NOT_READY_TO_COLLECT,
73a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  INCOGNITO_ACTIVE,
74a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  INCOGNITO_LAUNCHED,
75a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  PROTOBUF_NOT_PARSED,
76a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  NUM_OUTCOMES
77a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)};
78a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
79a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// Name of the histogram that represents the success and various failure modes
80a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)// for collecting and sending perf data.
81a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)const char kGetPerfDataOutcomeHistogram[] = "UMA.Perf.GetData";
82a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
83a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void AddToPerfHistogram(GetPerfDataOutcome outcome) {
84a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(kGetPerfDataOutcomeHistogram,
85a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            outcome,
86a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            NUM_OUTCOMES);
87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
88a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Returns true if a normal user is logged in. Returns false otherwise (e.g. if
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// logged in as a guest or as a kiosk app).
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsNormalUserLoggedIn() {
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return chromeos::LoginState::Get()->IsUserAuthenticated();
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace metrics {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This class must be created and used on the UI thread. It watches for any
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// incognito window being opened from the time it is instantiated to the time it
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is destroyed.
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class WindowedIncognitoObserver : public chrome::BrowserListObserver {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WindowedIncognitoObserver() : incognito_launched_(false) {
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserList::AddObserver(this);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~WindowedIncognitoObserver() {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserList::RemoveObserver(this);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This method can be checked to see whether any incognito window has been
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // opened since the time this object was created.
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool incognito_launched() {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return incognito_launched_;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // chrome::BrowserListObserver implementation.
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (browser->profile()->IsOffTheRecord())
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      incognito_launched_ = true;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool incognito_launched_;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)PerfProvider::PerfProvider()
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      : login_observer_(this),
13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        next_profiling_interval_start_(base::TimeTicks::Now()),
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        weak_factory_(this) {
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Register the login observer with LoginState.
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState::Get()->AddObserver(&login_observer_);
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Register as an observer of power manager events.
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      AddObserver(this);
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Register as an observer of session restore.
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // TODO(sque): clean this up to use something other than notifications.
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_restore_registrar_.Add(
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      this,
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      chrome::NOTIFICATION_SESSION_RESTORE_DONE,
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      content::NotificationService::AllBrowserContextsAndSources());
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check the login state. At the time of writing, this class is instantiated
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // before login. A subsequent login would activate the profiling. However,
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // that behavior may change in the future so that the user is already logged
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // when this class is instantiated. By calling LoggedInStateChanged() here,
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // PerfProvider will recognize that the system is already logged in.
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  login_observer_.LoggedInStateChanged();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PerfProvider::~PerfProvider() {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  chromeos::LoginState::Get()->RemoveObserver(&login_observer_);
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool PerfProvider::GetSampledProfiles(
16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    std::vector<SampledProfile>* sampled_profiles) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cached_perf_data_.empty()) {
163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_UPLOAD);
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  sampled_profiles->swap(cached_perf_data_);
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.clear();
169a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
170a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  AddToPerfHistogram(SUCCESS);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : perf_provider_(perf_provider) {}
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::LoginObserver::LoggedInStateChanged() {
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (IsNormalUserLoggedIn())
17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    perf_provider_->OnUserLoggedIn();
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    perf_provider_->Deactivate();
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void PerfProvider::SuspendDone(const base::TimeDelta& sleep_duration) {
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // A zero value for the suspend duration indicates that the suspend was
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // canceled. Do not collect anything if that's the case.
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (sleep_duration == base::TimeDelta())
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Do not collect a profile unless logged in. The system behavior when closing
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // the lid or idling when not logged in is currently to shut down instead of
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // suspending. But it's good to enforce the rule here in case that changes.
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!IsNormalUserLoggedIn())
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // collecting too much data.
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (base::RandGenerator(kResumeSamplingFactor) != 0)
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Override any existing profiling.
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (timer_.IsRunning())
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    timer_.Stop();
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Randomly pick a delay before doing the collection.
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::TimeDelta collection_delay =
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::TimeDelta::FromMilliseconds(
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::RandGenerator(kMaxResumeCollectionDelayMs));
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  timer_.Start(FROM_HERE,
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               collection_delay,
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch               base::Bind(&PerfProvider::CollectPerfDataAfterResume,
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          weak_factory_.GetWeakPtr(),
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          sleep_duration,
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          collection_delay));
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PerfProvider::Observe(int type,
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           const content::NotificationSource& source,
219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                           const content::NotificationDetails& details) {
220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Only handle session restore notifications.
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK_EQ(type, chrome::NOTIFICATION_SESSION_RESTORE_DONE);
222116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
223116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Do not collect a profile unless logged in as a normal user.
224116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!IsNormalUserLoggedIn())
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
226116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
227116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // avoid collecting too much data and potentially causing UI latency.
229116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0)
230116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
231116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
232116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const base::TimeDelta min_interval =
233116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::TimeDelta::FromMilliseconds(
234116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          kMinIntervalBetweenSessionRestoreCollectionsMs);
235116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const base::TimeDelta time_since_last_collection =
236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      (base::TimeTicks::Now() - last_session_restore_collection_time_);
237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Do not collect if there hasn't been enough elapsed time since the last
238116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // collection.
239116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!last_session_restore_collection_time_.is_null() &&
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      time_since_last_collection < min_interval) {
241116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
242116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
243116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
244116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Stop any existing scheduled collection.
245116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (timer_.IsRunning())
246116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    timer_.Stop();
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Randomly pick a delay before doing the collection.
249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::TimeDelta collection_delay =
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::TimeDelta::FromMilliseconds(
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::RandGenerator(kMaxRestoreSessionCollectionDelayMs));
252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  timer_.Start(
253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      FROM_HERE,
254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      collection_delay,
255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore,
256116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 weak_factory_.GetWeakPtr(),
257116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                 collection_delay));
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::OnUserLoggedIn() {
26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  login_time_ = base::TimeTicks::Now();
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScheduleIntervalCollection();
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PerfProvider::Deactivate() {
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Stop the timer, but leave |cached_perf_data_| intact.
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  timer_.Stop();
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PerfProvider::ScheduleIntervalCollection() {
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (timer_.IsRunning())
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Pick a random time in the current interval.
27646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::TimeTicks scheduled_time =
27746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      next_profiling_interval_start_ +
27846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(
27946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          base::RandGenerator(kPerfProfilingIntervalMs));
28046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If the scheduled time has already passed in the time it took to make the
28246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // above calculations, trigger the collection event immediately.
28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (scheduled_time < now)
28546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scheduled_time = now;
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  timer_.Start(FROM_HERE, scheduled_time - now, this,
28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)               &PerfProvider::DoPeriodicCollection);
28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Update the profiling interval tracker to the start of the next interval.
29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  next_profiling_interval_start_ +=
29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::CollectIfNecessary(
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<SampledProfile> sampled_profile) {
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
298c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
299116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Schedule another interval collection. This call makes sense regardless of
300116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // whether or not the current collection was interval-triggered. If it had
301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // been another type of trigger event, the interval timer would have been
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // halted, so it makes sense to reschedule a new interval collection.
303116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScheduleIntervalCollection();
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
305c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Do not collect further data if we've already collected a substantial amount
306c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
307c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  size_t cached_perf_data_size = 0;
308c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  for (size_t i = 0; i < cached_perf_data_.size(); ++i) {
309c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cached_perf_data_size += cached_perf_data_[i].ByteSize();
310c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
311c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) {
312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(NOT_READY_TO_COLLECT);
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For privacy reasons, Chrome should only collect perf data if there is no
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // incognito session active (or gets spawned during the collection).
318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (BrowserList::IsOffTheRecordSessionActive()) {
319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_ACTIVE);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<WindowedIncognitoObserver> incognito_observer(
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new WindowedIncognitoObserver);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chromeos::DebugDaemonClient* client =
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kPerfCommandDurationDefaultSeconds);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client->GetPerfData(collection_duration.InSeconds(),
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::Bind(&PerfProvider::ParseProtoIfValid,
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 weak_factory_.GetWeakPtr(),
33546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                 base::Passed(&incognito_observer),
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 base::Passed(&sampled_profile)));
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
33946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void PerfProvider::DoPeriodicCollection() {
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CollectIfNecessary(sampled_profile.Pass());
344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
346116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PerfProvider::CollectPerfDataAfterResume(
347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::TimeDelta& sleep_duration,
348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::TimeDelta& time_after_resume) {
349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Fill out a SampledProfile protobuf that will contain the collected data.
350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND);
352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  sampled_profile->set_suspend_duration_ms(sleep_duration.InMilliseconds());
353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  sampled_profile->set_ms_after_resume(time_after_resume.InMilliseconds());
354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CollectIfNecessary(sampled_profile.Pass());
356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
358116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PerfProvider::CollectPerfDataAfterSessionRestore(
359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    const base::TimeDelta& time_after_restore) {
360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Fill out a SampledProfile protobuf that will contain the collected data.
361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
362116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
363116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
364116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CollectIfNecessary(sampled_profile.Pass());
366116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  last_session_restore_collection_time_ = base::TimeTicks::Now();
367868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PerfProvider::ParseProtoIfValid(
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<WindowedIncognitoObserver> incognito_observer,
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<SampledProfile> sampled_profile,
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<uint8>& data) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
375a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (incognito_observer->incognito_launched()) {
376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(INCOGNITO_LAUNCHED);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
378a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
380c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  PerfDataProto perf_data_proto;
381c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!perf_data_proto.ParseFromArray(data.data(), data.size())) {
382a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    AddToPerfHistogram(PROTOBUF_NOT_PARSED);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Populate a profile collection protobuf with the collected perf data and
38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // extra metadata.
388c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cached_perf_data_.resize(cached_perf_data_.size() + 1);
38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SampledProfile& collection_data = cached_perf_data_.back();
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  collection_data.Swap(sampled_profile.get());
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Fill out remaining fields of the SampledProfile protobuf.
39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  collection_data.set_ms_after_boot(
39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond);
39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(!login_time_.is_null());
39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  collection_data.
39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      set_ms_after_login((base::TimeTicks::Now() - login_time_)
39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          .InMilliseconds());
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Finally, store the perf data itself.
402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  collection_data.mutable_perf_data()->Swap(&perf_data_proto);
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace metrics
406