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