OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/boot_times_loader.h" | 5 #include "chrome/browser/chromeos/boot_times_loader.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 ++i) { | 62 ++i) { |
63 WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i); | 63 WebContents* tab = browser->tab_strip_model()->GetWebContentsAt(i); |
64 if (tab->GetRenderWidgetHostView() == rwhv) { | 64 if (tab->GetRenderWidgetHostView() == rwhv) { |
65 return tab->GetLastCommittedURL().spec(); | 65 return tab->GetLastCommittedURL().spec(); |
66 } | 66 } |
67 } | 67 } |
68 } | 68 } |
69 return std::string(); | 69 return std::string(); |
70 } | 70 } |
71 | 71 |
72 void PostCallbackIfNotCanceled( | |
73 const CancelableTaskTracker::IsCanceledCallback& is_canceled_cb, | |
74 base::TaskRunner* task_runner, | |
75 const chromeos::BootTimesLoader::GetBootTimesCallback& callback, | |
76 const chromeos::BootTimesLoader::BootTimes& boot_times) { | |
77 if (is_canceled_cb.Run()) | |
78 return; | |
79 task_runner->PostTask(FROM_HERE, base::Bind(callback, boot_times)); | |
80 } | |
81 | |
82 } // namespace | 72 } // namespace |
83 | 73 |
84 namespace chromeos { | 74 namespace chromeos { |
85 | 75 |
86 #define FPL(value) FILE_PATH_LITERAL(value) | 76 #define FPL(value) FILE_PATH_LITERAL(value) |
87 | 77 |
88 // Dir uptime & disk logs are located in. | 78 // Dir uptime & disk logs are located in. |
89 static const base::FilePath::CharType kLogPath[] = FPL("/tmp"); | 79 static const base::FilePath::CharType kLogPath[] = FPL("/tmp"); |
90 // Dir log{in,out} logs are located in. | 80 // Dir log{in,out} logs are located in. |
91 static const base::FilePath::CharType kLoginLogPath[] = | 81 static const base::FilePath::CharType kLoginLogPath[] = |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 logout_time_markers_.reserve(30); | 118 logout_time_markers_.reserve(30); |
129 } | 119 } |
130 | 120 |
131 BootTimesLoader::~BootTimesLoader() {} | 121 BootTimesLoader::~BootTimesLoader() {} |
132 | 122 |
133 // static | 123 // static |
134 BootTimesLoader* BootTimesLoader::Get() { | 124 BootTimesLoader* BootTimesLoader::Get() { |
135 return g_boot_times_loader.Pointer(); | 125 return g_boot_times_loader.Pointer(); |
136 } | 126 } |
137 | 127 |
138 CancelableTaskTracker::TaskId BootTimesLoader::GetBootTimes( | |
139 const GetBootTimesCallback& callback, | |
140 CancelableTaskTracker* tracker) { | |
141 if (!BrowserThread::IsMessageLoopValid(BrowserThread::FILE)) { | |
142 // This should only happen if Chrome is shutting down, so we don't do | |
143 // anything. | |
144 return CancelableTaskTracker::kBadTaskId; | |
145 } | |
146 | |
147 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | |
148 if (command_line.HasSwitch(switches::kTestType)) { | |
149 // TODO(davemoore) This avoids boottimes for tests. This needs to be | |
150 // replaced with a mock of BootTimesLoader. | |
151 return CancelableTaskTracker::kBadTaskId; | |
152 } | |
153 | |
154 CancelableTaskTracker::IsCanceledCallback is_canceled; | |
155 CancelableTaskTracker::TaskId id = tracker->NewTrackedTaskId(&is_canceled); | |
156 | |
157 GetBootTimesCallback callback_runner = | |
158 base::Bind(&PostCallbackIfNotCanceled, | |
159 is_canceled, base::MessageLoopProxy::current(), callback); | |
160 BrowserThread::PostTask( | |
161 BrowserThread::FILE, | |
162 FROM_HERE, | |
163 base::Bind(&Backend::GetBootTimesAndRunCallback, | |
164 backend_, is_canceled, callback_runner)); | |
165 return id; | |
166 } | |
167 | |
168 // Extracts the uptime value from files located in /tmp, returning the | |
169 // value as a double in value. | |
170 static bool GetTime(const base::FilePath::StringType& log, double* value) { | |
171 base::FilePath log_dir(kLogPath); | |
172 base::FilePath log_file = log_dir.Append(log); | |
173 std::string contents; | |
174 *value = 0.0; | |
175 if (file_util::ReadFileToString(log_file, &contents)) { | |
176 size_t space_index = contents.find(' '); | |
177 size_t chars_left = | |
178 space_index != std::string::npos ? space_index : std::string::npos; | |
179 std::string value_string = contents.substr(0, chars_left); | |
180 return base::StringToDouble(value_string, value); | |
181 } | |
182 return false; | |
183 } | |
184 | |
185 // Converts double seconds to a TimeDelta object. | |
186 static base::TimeDelta SecondsToTimeDelta(double seconds) { | |
187 double ms = seconds * base::Time::kMillisecondsPerSecond; | |
188 return base::TimeDelta::FromMilliseconds(static_cast<int64>(ms)); | |
189 } | |
190 | |
191 // Reports the collected boot times to UMA if they haven't been | |
192 // reported yet and if metrics collection is enabled. | |
193 static void SendBootTimesToUMA(const BootTimesLoader::BootTimes& boot_times) { | |
194 // Checks if the times for the most recent boot event have been | |
195 // reported already to avoid sending boot time histogram samples | |
196 // every time the user logs out. | |
197 static const base::FilePath::CharType kBootTimesSent[] = | |
198 FPL("/tmp/boot-times-sent"); | |
199 base::FilePath sent(kBootTimesSent); | |
200 if (base::PathExists(sent)) | |
201 return; | |
202 | |
203 UMA_HISTOGRAM_TIMES("BootTime.Total", | |
204 SecondsToTimeDelta(boot_times.total)); | |
205 UMA_HISTOGRAM_TIMES("BootTime.Firmware", | |
206 SecondsToTimeDelta(boot_times.firmware)); | |
207 UMA_HISTOGRAM_TIMES("BootTime.Kernel", | |
208 SecondsToTimeDelta(boot_times.pre_startup)); | |
209 UMA_HISTOGRAM_TIMES("BootTime.System", | |
210 SecondsToTimeDelta(boot_times.system)); | |
211 if (boot_times.chrome > 0) { | |
212 UMA_HISTOGRAM_TIMES("BootTime.Chrome", | |
213 SecondsToTimeDelta(boot_times.chrome)); | |
214 } | |
215 | |
216 // Stores the boot times to a file in /tmp to indicate that the | |
217 // times for the most recent boot event have been reported | |
218 // already. The file will be deleted at system shutdown/reboot. | |
219 std::string boot_times_text = base::StringPrintf("total: %.2f\n" | |
220 "firmware: %.2f\n" | |
221 "kernel: %.2f\n" | |
222 "system: %.2f\n" | |
223 "chrome: %.2f\n", | |
224 boot_times.total, | |
225 boot_times.firmware, | |
226 boot_times.pre_startup, | |
227 boot_times.system, | |
228 boot_times.chrome); | |
229 file_util::WriteFile(sent, boot_times_text.data(), boot_times_text.size()); | |
230 DCHECK(base::PathExists(sent)); | |
231 } | |
232 | |
233 void BootTimesLoader::Backend::GetBootTimesAndRunCallback( | |
234 const CancelableTaskTracker::IsCanceledCallback& is_canceled_cb, | |
235 const GetBootTimesCallback& callback) { | |
236 if (is_canceled_cb.Run()) | |
237 return; | |
238 | |
239 const base::FilePath::CharType kFirmwareBootTime[] = | |
240 FPL("firmware-boot-time"); | |
241 const base::FilePath::CharType kPreStartup[] = FPL("pre-startup"); | |
242 const base::FilePath::CharType kChromeExec[] = FPL("chrome-exec"); | |
243 const base::FilePath::CharType kChromeMain[] = FPL("chrome-main"); | |
244 const base::FilePath::CharType kXStarted[] = FPL("x-started"); | |
245 const base::FilePath::CharType kLoginPromptReady[] = | |
246 FPL("login-prompt-ready"); | |
247 const base::FilePath::StringType uptime_prefix = kUptimePrefix; | |
248 | |
249 // Wait until firmware-boot-time file exists by reposting. | |
250 base::FilePath log_dir(kLogPath); | |
251 base::FilePath log_file = log_dir.Append(kFirmwareBootTime); | |
252 if (!base::PathExists(log_file)) { | |
253 BrowserThread::PostDelayedTask( | |
254 BrowserThread::FILE, | |
255 FROM_HERE, | |
256 base::Bind(&Backend::GetBootTimesAndRunCallback, | |
257 this, is_canceled_cb, callback), | |
258 base::TimeDelta::FromMilliseconds(kReadAttemptDelayMs)); | |
259 return; | |
260 } | |
261 | |
262 BootTimes boot_times; | |
263 | |
264 GetTime(kFirmwareBootTime, &boot_times.firmware); | |
265 GetTime(uptime_prefix + kPreStartup, &boot_times.pre_startup); | |
266 GetTime(uptime_prefix + kXStarted, &boot_times.x_started); | |
267 GetTime(uptime_prefix + kChromeExec, &boot_times.chrome_exec); | |
268 GetTime(uptime_prefix + kChromeMain, &boot_times.chrome_main); | |
269 GetTime(uptime_prefix + kLoginPromptReady, &boot_times.login_prompt_ready); | |
270 | |
271 boot_times.total = boot_times.firmware + boot_times.login_prompt_ready; | |
272 if (boot_times.chrome_exec > 0) { | |
273 boot_times.system = boot_times.chrome_exec - boot_times.pre_startup; | |
274 boot_times.chrome = boot_times.login_prompt_ready - boot_times.chrome_exec; | |
275 } else { | |
276 boot_times.system = boot_times.login_prompt_ready - boot_times.pre_startup; | |
277 } | |
278 | |
279 SendBootTimesToUMA(boot_times); | |
280 | |
281 callback.Run(boot_times); | |
282 } | |
283 | |
284 // Appends the given buffer into the file. Returns the number of bytes | 128 // Appends the given buffer into the file. Returns the number of bytes |
285 // written, or -1 on error. | 129 // written, or -1 on error. |
286 // TODO(satorux): Move this to file_util. | 130 // TODO(satorux): Move this to file_util. |
287 static int AppendFile(const base::FilePath& file_path, | 131 static int AppendFile(const base::FilePath& file_path, |
288 const char* data, | 132 const char* data, |
289 int size) { | 133 int size) { |
290 FILE* file = file_util::OpenFile(file_path, "a"); | 134 FILE* file = file_util::OpenFile(file_path, "a"); |
291 if (!file) { | 135 if (!file) { |
292 return -1; | 136 return -1; |
293 } | 137 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 GetRenderWidgetHost(&web_contents->GetController()); | 380 GetRenderWidgetHost(&web_contents->GetController()); |
537 render_widget_hosts_loading_.erase(render_widget_host); | 381 render_widget_hosts_loading_.erase(render_widget_host); |
538 break; | 382 break; |
539 } | 383 } |
540 default: | 384 default: |
541 break; | 385 break; |
542 } | 386 } |
543 } | 387 } |
544 | 388 |
545 } // namespace chromeos | 389 } // namespace chromeos |
OLD | NEW |