15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/boot_times_loader.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 1346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/json/json_reader.h" 1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/json/json_writer.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h" 179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/prefs/pref_service.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 225e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 235e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_restrictions.h" 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/common/pref_names.h" 346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/user_manager/user_manager.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/navigation_controller.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHost; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderWidgetHostView; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kUptime[] = "uptime"; 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const char kDisk[] = "disk"; 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents = tab->GetWebContents(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (web_contents) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHostView* render_widget_host_view = 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetRenderWidgetHostView(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_widget_host_view) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return render_widget_host_view->GetRenderWidgetHost(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string GetTabUrl(RenderWidgetHost* rwh) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHostView* rwhv = rwh->GetView(); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser = *it; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0, tab_count = browser->tab_strip_model()->count(); 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i < tab_count; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++i) { 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab->GetRenderWidgetHostView() == rwhv) { 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return tab->GetLastCommittedURL().spec(); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Appends the given buffer into the file. Returns the number of bytes 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// written, or -1 on error. 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// TODO(satorux): Move this to file_util. 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int AppendFile(const base::FilePath& file_path, const char* data, int size) { 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FILE* file = base::OpenFile(file_path, "a"); 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!file) 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return -1; 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const int num_bytes_written = fwrite(data, 1, size, file); 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::CloseFile(file); 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return num_bytes_written; 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FPL(value) FILE_PATH_LITERAL(value) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dir uptime & disk logs are located in. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLogPath[] = FPL("/tmp"); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dir log{in,out} logs are located in. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLoginLogPath[] = 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FPL("/home/chronos/user"); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prefix for the time measurement files. 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kUptimePrefix[] = FPL("uptime-"); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prefix for the disk usage files. 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kDiskPrefix[] = FPL("disk-"); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Name of the time that Chrome's main() is called. 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kChromeMain[] = FPL("chrome-main"); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delay in milliseconds before writing the login times to disk. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int64 kLoginTimeWriteDelayMs = 3000; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Names of login stats files. 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLoginSuccess[] = FPL("login-success"); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kChromeFirstRender[] = 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FPL("chrome-first-render"); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Names of login UMA values. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kUmaLogin[] = "BootTime.Login"; 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const char kUmaLoginNewUser[] = "BootTime.LoginNewUser"; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kUmaLoginPrefix[] = "BootTime."; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kUmaLogout[] = "ShutdownTime.Logout"; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kUmaLogoutPrefix[] = "ShutdownTime."; 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)static const char kUmaRestart[] = "ShutdownTime.Restart"; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Name of file collecting login times. 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static const base::FilePath::CharType kLoginTimes[] = FPL("login-times"); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Name of file collecting logout times. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kLogoutTimes[] = "logout-times"; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<BootTimesLoader> g_boot_times_loader = 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LAZY_INSTANCE_INITIALIZER; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 13546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BootTimesLoader::Stats BootTimesLoader::Stats::GetCurrentStats() { 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::FilePath kProcUptime(FPL("/proc/uptime")); 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::FilePath kDiskStat(FPL("/sys/block/sda/stat")); 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Stats stats; 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Callers of this method expect synchronous behavior. 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // It's safe to allow IO here, because only virtual FS are accessed. 14146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::ThreadRestrictions::ScopedAllowIO allow_io; 14246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::ReadFileToString(kProcUptime, &stats.uptime_); 14346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::ReadFileToString(kDiskStat, &stats.disk_); 14446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return stats; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)std::string BootTimesLoader::Stats::SerializeToString() const { 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (uptime_.empty() && disk_.empty()) 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return std::string(); 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::DictionaryValue dictionary; 15146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) dictionary.SetString(kUptime, uptime_); 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) dictionary.SetString(kDisk, disk_); 15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 15446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string result; 15546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!base::JSONWriter::Write(&dictionary, &result)) { 15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(WARNING) << "BootTimesLoader::Stats::SerializeToString(): failed."; 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return std::string(); 15846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return result; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BootTimesLoader::Stats BootTimesLoader::Stats::DeserializeFromString( 16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& source) { 16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (source.empty()) 16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return Stats(); 16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::Value> value(base::JSONReader::Read(source)); 17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::DictionaryValue* dictionary; 17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!value || !value->GetAsDictionary(&dictionary)) { 17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(ERROR) << "BootTimesLoader::Stats::DeserializeFromString(): not a " 17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "dictionary: '" << source << "'"; 17446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return Stats(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Stats result; 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!dictionary->GetString(kUptime, &result.uptime_) || 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !dictionary->GetString(kDisk, &result.disk_)) { 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(ERROR) 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << "BootTimesLoader::Stats::DeserializeFromString(): format error: '" 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << source << "'"; 18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return Stats(); 18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return result; 18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool BootTimesLoader::Stats::UptimeDouble(double* result) const { 19046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) std::string uptime = uptime_; 19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const size_t space_at = uptime.find_first_of(' '); 19246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (space_at == std::string::npos) 19346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 19446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uptime.resize(space_at); 19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (base::StringToDouble(uptime, result)) 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return true; 19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 20146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 20246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 20346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BootTimesLoader::Stats::RecordStats(const std::string& name) const { 20446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostBlockingPoolTask( 20546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 20646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&BootTimesLoader::Stats::RecordStatsImpl, 20746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Owned(new Stats(*this)), 20846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) name)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BootTimesLoader::Stats::RecordStatsWithCallback( 21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string& name, 21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::Closure& callback) const { 21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostBlockingPoolTaskAndReply( 21546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 21646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&BootTimesLoader::Stats::RecordStatsImpl, 21746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Owned(new Stats(*this)), 21846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) name), 21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) callback); 22046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 22146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 22246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BootTimesLoader::Stats::RecordStatsImpl( 22346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const base::FilePath::StringType& name) const { 22446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 22546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath log_path(kLogPath); 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath uptime_output = 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) log_path.Append(base::FilePath(kUptimePrefix + name)); 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath disk_output = 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) log_path.Append(base::FilePath(kDiskPrefix + name)); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Append numbers to the files. 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) AppendFile(uptime_output, uptime_.data(), uptime_.size()); 23446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) AppendFile(disk_output, disk_.data(), disk_.size()); 23546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 23646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 23746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BootTimesLoader::BootTimesLoader() 23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : backend_(new Backend()), 23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) have_registered_(false), 24046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) login_done_(false), 24146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) restart_requested_(false) { 24246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) login_time_markers_.reserve(30); 24346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) logout_time_markers_.reserve(30); 24446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 24546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 24646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BootTimesLoader::~BootTimesLoader() { 24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)BootTimesLoader* BootTimesLoader::Get() { 25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return g_boot_times_loader.Pointer(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::WriteTimes( 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string base_name, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string uma_name, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string uma_prefix, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<TimeMarker> login_times) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMinTimeMillis = 1; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kMaxTimeMillis = 30000; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kNumBuckets = 100; 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath log_path(kLoginLogPath); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to sort by time since the entries may have been pushed onto the 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // vector (on the UI thread) in a different order from which they were 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // created (potentially on other threads). 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(login_times.begin(), login_times.end()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time first = login_times.front().time(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last = login_times.back().time(); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta total = last - first; 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::HistogramBase* total_hist = base::Histogram::FactoryTimeGet( 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uma_name, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMinTimeMillis), 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxTimeMillis), 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kNumBuckets, 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::HistogramBase::kUmaTargetedHistogramFlag); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_hist->AddTime(total); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string output = 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPrintf("%s: %.2f", uma_name.c_str(), total.InSecondsF()); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time prev = first; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned int i = 0; i < login_times.size(); ++i) { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeMarker tm = login_times[i]; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta since_first = tm.time() - first; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta since_prev = tm.time() - prev; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tm.send_to_uma()) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = uma_prefix + tm.name(); 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::HistogramBase* prev_hist = base::Histogram::FactoryTimeGet( 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMinTimeMillis), 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kMaxTimeMillis), 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kNumBuckets, 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::HistogramBase::kUmaTargetedHistogramFlag); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev_hist->AddTime(since_prev); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = tm.name(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StringPrintf( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n%.2f +%.4f %s", 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) since_first.InSecondsF(), 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) since_prev.InSecondsF(), 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name.data()); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev = tm.time(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += '\n'; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::WriteFile(log_path.Append(base_name), output.data(), output.size()); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void BootTimesLoader::LoginDone(bool is_user_new) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (login_done_) 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) login_done_ = true; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddLoginTimeMarker("LoginDone", false); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordCurrentStats(kChromeFirstRender); 322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (have_registered_) { 323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registrar_.Remove(this, 324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NOTIFICATION_LOAD_START, 325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::AllSources()); 326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registrar_.Remove(this, 327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NOTIFICATION_LOAD_STOP, 328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::AllSources()); 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registrar_.Remove(this, 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::AllSources()); 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) registrar_.Remove( 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) this, 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::AllSources()); 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't swamp the FILE thread right away. 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostDelayedTask( 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BrowserThread::FILE, 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FROM_HERE, 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::Bind(&WriteTimes, 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kLoginTimes, 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (is_user_new ? kUmaLoginNewUser : kUmaLogin), 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kUmaLoginPrefix, 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_time_markers_), 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(kLoginTimeWriteDelayMs)); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::WriteLogoutTimes() { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either we're on the browser thread, or (more likely) Chrome is in the 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process of shutting down and we're on the main thread but the message loop 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // has already been terminated. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !BrowserThread::IsMessageLoopValid(BrowserThread::UI)); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteTimes(kLogoutTimes, 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (restart_requested_ ? kUmaRestart : kUmaLogout), 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kUmaLogoutPrefix, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logout_time_markers_); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// static 36346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BootTimesLoader::ClearLogoutStartedLastPreference() { 36446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 36546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state->ClearPref(prefs::kLogoutStartedLast); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BootTimesLoader::OnChromeProcessStart() { 36946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PrefService* local_state = g_browser_process->local_state(); 37046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string logout_started_last_str = 37146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) local_state->GetString(prefs::kLogoutStartedLast); 37246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (logout_started_last_str.empty()) 37346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 37446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 37546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Note that kLogoutStartedLast is not cleared on format error to stay in 37646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // logs in case of other fatal system errors. 37746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 37846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const Stats logout_started_last_stats = 37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Stats::DeserializeFromString(logout_started_last_str); 38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (logout_started_last_stats.uptime().empty()) 38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 38246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 38346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) double logout_started_last; 38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) double uptime; 38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!logout_started_last_stats.UptimeDouble(&logout_started_last) || 38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) !Stats::GetCurrentStats().UptimeDouble(&uptime)) { 38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 38946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 39046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (logout_started_last >= uptime) { 39146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Reboot happened. 39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ClearLogoutStartedLastPreference(); 39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 39546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Write /tmp/uptime-logout-started as well. 39746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const char kLogoutStarted[] = "logout-started"; 39846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) logout_started_last_stats.RecordStatsWithCallback( 39946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) kLogoutStarted, 40046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&BootTimesLoader::ClearLogoutStartedLastPreference)); 40146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 40246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 40346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void BootTimesLoader::OnLogoutStarted(PrefService* state) { 40446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const std::string uptime = Stats::GetCurrentStats().SerializeToString(); 40546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!uptime.empty()) 40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) state->SetString(prefs::kLogoutStartedLast, uptime); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::RecordCurrentStats(const std::string& name) { 41046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) Stats::GetCurrentStats().RecordStats(name); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::SaveChromeMainStats() { 41446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) chrome_main_stats_ = Stats::GetCurrentStats(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::RecordChromeMainStats() { 41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) chrome_main_stats_.RecordStats(kChromeMain); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::RecordLoginAttempted() { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (login_done_) 424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) login_time_markers_.clear(); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddLoginTimeMarker("LoginStarted", false); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!have_registered_) { 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) have_registered_ = true; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_LOAD_START, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_LOAD_STOP, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllSources()); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::AddLoginTimeMarker( 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& marker_name, bool send_to_uma) { 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddMarker(&login_time_markers_, TimeMarker(marker_name, send_to_uma)); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::AddLogoutTimeMarker( 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& marker_name, bool send_to_uma) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddMarker(&logout_time_markers_, TimeMarker(marker_name, send_to_uma)); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::AddMarker(std::vector<TimeMarker>* vector, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeMarker marker) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The marker vectors can only be safely manipulated on the main thread. 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we're late in the process of shutting down (eg. as can be the case at 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // logout), then we have to assume we're on the main thread already. 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::UI) || 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !BrowserThread::IsMessageLoopValid(BrowserThread::UI)) { 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector->push_back(marker); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the marker on the UI thread. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that it's safe to use an unretained pointer to the vector because 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BootTimesLoader's lifetime exceeds that of the UI thread message loop. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, FROM_HERE, 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BootTimesLoader::AddMarker, 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(vector), 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) marker)); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BootTimesLoader::RecordAuthenticationSuccess() { 47603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) AddLoginTimeMarker("Authenticate", true); 47703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) RecordCurrentStats(kLoginSuccess); 47803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 47903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 48003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BootTimesLoader::RecordAuthenticationFailure() { 48103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Do nothing for now. 48203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 48303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BootTimesLoader::Observe( 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_LOAD_START: { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationController* tab = 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(source).ptr(); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHost* rwh = GetRenderWidgetHost(tab); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(rwh); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddLoginTimeMarker("TabLoad-Start: " + GetTabUrl(rwh), false); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_widget_hosts_loading_.insert(rwh); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_LOAD_STOP: { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NavigationController* tab = 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(source).ptr(); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHost* rwh = GetRenderWidgetHost(tab); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_widget_hosts_loading_.find(rwh) != 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_widget_hosts_loading_.end()) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddLoginTimeMarker("TabLoad-End: " + GetTabUrl(rwh), false); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE: { 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHost* rwh = content::Source<RenderWidgetHost>(source).ptr(); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (render_widget_hosts_loading_.find(rwh) != 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_widget_hosts_loading_.end()) { 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddLoginTimeMarker("TabPaint: " + GetTabUrl(rwh), false); 5136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) LoginDone(user_manager::UserManager::Get()->IsCurrentUserNew()); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents = content::Source<WebContents>(source).ptr(); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderWidgetHost* render_widget_host = 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetRenderWidgetHost(&web_contents->GetController()); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_widget_hosts_loading_.erase(render_widget_host); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chromeos 530