Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2933)

Unified Diff: chrome/browser/chromeos/boot_times_loader.cc

Issue 303233004: Write "logout-started" event on next boot. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update after review. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/boot_times_loader.cc
diff --git a/chrome/browser/chromeos/boot_times_loader.cc b/chrome/browser/chromeos/boot_times_loader.cc
index 94a675de5433dbcf712824ddd5fa02b548b1c978..26d8a3ce10ac8942e0d69a27f9738b1efcf944b0 100644
--- a/chrome/browser/chromeos/boot_times_loader.cc
+++ b/chrome/browser/chromeos/boot_times_loader.cc
@@ -10,11 +10,14 @@
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -29,6 +32,7 @@
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_service.h"
@@ -43,6 +47,9 @@ using content::WebContents;
namespace {
+const char kUptime[] = "uptime";
+const char kDisk[] = "disk";
+
RenderWidgetHost* GetRenderWidgetHost(NavigationController* tab) {
WebContents* web_contents = tab->GetWebContents();
if (web_contents) {
@@ -70,6 +77,19 @@ const std::string GetTabUrl(RenderWidgetHost* rwh) {
return std::string();
}
+// Appends the given buffer into the file. Returns the number of bytes
+// written, or -1 on error.
+// TODO(satorux): Move this to file_util.
+int AppendFile(const base::FilePath& file_path, const char* data, int size) {
+ FILE* file = base::OpenFile(file_path, "a");
+ if (!file)
+ return -1;
+
+ const int num_bytes_written = fwrite(data, 1, size, file);
+ base::CloseFile(file);
+ return num_bytes_written;
+}
+
} // namespace
namespace chromeos {
@@ -112,40 +132,98 @@ static const char kLogoutTimes[] = "logout-times";
static base::LazyInstance<BootTimesLoader> g_boot_times_loader =
LAZY_INSTANCE_INITIALIZER;
-BootTimesLoader::BootTimesLoader()
- : backend_(new Backend()),
- have_registered_(false),
- login_done_(false),
- restart_requested_(false) {
- login_time_markers_.reserve(30);
- logout_time_markers_.reserve(30);
+// static
+BootTimesLoader::Stats BootTimesLoader::Stats::GetCurrentStats() {
+ const base::FilePath kProcUptime(FPL("/proc/uptime"));
+ const base::FilePath kDiskStat(FPL("/sys/block/sda/stat"));
+ Stats stats;
+ // Callers of this method expect synchronous behavior.
+ // It's safe to allow IO here, because only virtual FS are accessed.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ base::ReadFileToString(kProcUptime, &stats.uptime_);
+ base::ReadFileToString(kDiskStat, &stats.disk_);
+ return stats;
}
-BootTimesLoader::~BootTimesLoader() {}
+std::string BootTimesLoader::Stats::SerializeToString() const {
+ if (uptime_.empty() || disk_.empty())
+ return std::string();
+ base::DictionaryValue dictionary;
+ dictionary.SetString(kUptime, uptime_);
+ dictionary.SetString(kDisk, disk_);
+
+ std::string result;
+ if (!base::JSONWriter::Write(&dictionary, &result)) {
+ LOG(WARNING) << "BootTimesLoader::Stats::SerializeToString(): failed.";
+ return result;
stevenjb 2014/06/02 19:11:38 nit: don't return here ('return result' occurs bel
Alexander Alekseev 2014/06/02 19:18:45 Done.
+ }
-// static
-BootTimesLoader* BootTimesLoader::Get() {
- return g_boot_times_loader.Pointer();
+ return result;
}
-// Appends the given buffer into the file. Returns the number of bytes
-// written, or -1 on error.
-// TODO(satorux): Move this to file_util.
-static int AppendFile(const base::FilePath& file_path,
- const char* data,
- int size) {
- FILE* file = base::OpenFile(file_path, "a");
- if (!file) {
- return -1;
+// static
+BootTimesLoader::Stats BootTimesLoader::Stats::DeserializeFromString(
+ const std::string& source) {
+ if (source.empty())
+ return Stats();
+
+ scoped_ptr<base::Value> value(base::JSONReader::Read(source));
+ base::DictionaryValue* dictionary;
+ if (!value || !value->GetAsDictionary(&dictionary)) {
+ LOG(ERROR) << "BootTimesLoader::Stats::DeserializeFromString(): not a "
+ "dictionary: '" << source << "'";
+ return Stats();
}
- const int num_bytes_written = fwrite(data, 1, size, file);
- base::CloseFile(file);
- return num_bytes_written;
+
+ Stats result;
+ if (!dictionary->GetString(kUptime, &result.uptime_) ||
+ !dictionary->GetString(kDisk, &result.disk_)) {
+ LOG(ERROR)
+ << "BootTimesLoader::Stats::DeserializeFromString(): format error: '"
+ << source << "'";
+ return Stats();
stevenjb 2014/06/02 19:11:38 nit: Here also, explicit return isn't necessary.
Alexander Alekseev 2014/06/02 19:18:45 It is dangerous, because if first call succeeds, b
stevenjb 2014/06/02 19:26:33 Good point, looks good.
+ }
+
+ return result;
+}
+
+bool BootTimesLoader::Stats::UptimeDouble(double* result) const {
+ std::string uptime = uptime_;
+ const size_t space_at = uptime.find_first_of(' ');
+ if (space_at == std::string::npos)
+ return false;
+
+ uptime.resize(space_at);
+
+ if (base::StringToDouble(uptime, result))
+ return true;
+
+ return false;
+}
+
+void BootTimesLoader::Stats::RecordStats(const std::string& name) const {
+ BrowserThread::PostBlockingPoolTask(
+ FROM_HERE,
+ base::Bind(&BootTimesLoader::Stats::RecordStatsImpl,
+ base::Owned(new Stats(*this)),
+ name));
}
-static void RecordStatsDelayed(const base::FilePath::StringType& name,
- const std::string& uptime,
- const std::string& disk) {
+void BootTimesLoader::Stats::RecordStatsWithCallback(
+ const std::string& name,
+ const base::Closure& callback) const {
+ BrowserThread::PostBlockingPoolTaskAndReply(
+ FROM_HERE,
+ base::Bind(&BootTimesLoader::Stats::RecordStatsImpl,
+ base::Owned(new Stats(*this)),
+ name),
+ callback);
+}
+
+void BootTimesLoader::Stats::RecordStatsImpl(
+ const base::FilePath::StringType& name) const {
+ DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+
const base::FilePath log_path(kLogPath);
const base::FilePath uptime_output =
log_path.Append(base::FilePath(kUptimePrefix + name));
@@ -153,8 +231,25 @@ static void RecordStatsDelayed(const base::FilePath::StringType& name,
log_path.Append(base::FilePath(kDiskPrefix + name));
// Append numbers to the files.
- AppendFile(uptime_output, uptime.data(), uptime.size());
- AppendFile(disk_output, disk.data(), disk.size());
+ AppendFile(uptime_output, uptime_.data(), uptime_.size());
+ AppendFile(disk_output, disk_.data(), disk_.size());
+}
+
+BootTimesLoader::BootTimesLoader()
+ : backend_(new Backend()),
+ have_registered_(false),
+ login_done_(false),
+ restart_requested_(false) {
+ login_time_markers_.reserve(30);
+ logout_time_markers_.reserve(30);
+}
+
+BootTimesLoader::~BootTimesLoader() {
+}
+
+// static
+BootTimesLoader* BootTimesLoader::Get() {
+ return g_boot_times_loader.Pointer();
}
// static
@@ -265,32 +360,63 @@ void BootTimesLoader::WriteLogoutTimes() {
logout_time_markers_);
}
-void BootTimesLoader::RecordStats(const std::string& name, const Stats& stats) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&RecordStatsDelayed, name, stats.uptime, stats.disk));
+// static
+void BootTimesLoader::ClearLogoutStartedLastPreference() {
+ PrefService* local_state = g_browser_process->local_state();
+ local_state->ClearPref(prefs::kLogoutStartedLast);
}
-BootTimesLoader::Stats BootTimesLoader::GetCurrentStats() {
- const base::FilePath kProcUptime(FPL("/proc/uptime"));
- const base::FilePath kDiskStat(FPL("/sys/block/sda/stat"));
- Stats stats;
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- base::ReadFileToString(kProcUptime, &stats.uptime);
- base::ReadFileToString(kDiskStat, &stats.disk);
- return stats;
+void BootTimesLoader::OnChromeProcessStart() {
+ PrefService* local_state = g_browser_process->local_state();
+ const std::string logout_started_last_str =
+ local_state->GetString(prefs::kLogoutStartedLast);
+ if (logout_started_last_str.empty())
+ return;
+
+ // Note that kLogoutStartedLast is not cleared on format error to stay in
+ // logs in case of other fatal system errors.
+
+ const Stats logout_started_last_stats =
+ Stats::DeserializeFromString(logout_started_last_str);
+ if (logout_started_last_stats.uptime().empty())
+ return;
+
+ double logout_started_last;
+ double uptime;
+ if (!logout_started_last_stats.UptimeDouble(&logout_started_last) ||
+ !Stats::GetCurrentStats().UptimeDouble(&uptime)) {
+ return;
+ }
+
+ if (logout_started_last >= uptime) {
+ // Reboot happened.
+ ClearLogoutStartedLastPreference();
+ return;
+ }
+
+ // Write /tmp/uptime-logout-started as well.
+ const char kLogoutStarted[] = "logout-started";
+ logout_started_last_stats.RecordStatsWithCallback(
+ kLogoutStarted,
+ base::Bind(&BootTimesLoader::ClearLogoutStartedLastPreference));
+}
+
+void BootTimesLoader::OnLogoutStarted(PrefService* state) {
+ const std::string uptime = Stats::GetCurrentStats().SerializeToString();
+ if (!uptime.empty())
+ state->SetString(prefs::kLogoutStartedLast, uptime);
}
void BootTimesLoader::RecordCurrentStats(const std::string& name) {
- RecordStats(name, GetCurrentStats());
+ Stats::GetCurrentStats().RecordStats(name);
}
void BootTimesLoader::SaveChromeMainStats() {
- chrome_main_stats_ = GetCurrentStats();
+ chrome_main_stats_ = Stats::GetCurrentStats();
}
void BootTimesLoader::RecordChromeMainStats() {
- RecordStats(kChromeMain, chrome_main_stats_);
+ chrome_main_stats_.RecordStats(kChromeMain);
}
void BootTimesLoader::RecordLoginAttempted() {
« no previous file with comments | « chrome/browser/chromeos/boot_times_loader.h ('k') | chrome/browser/chromeos/chrome_browser_main_chromeos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698