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

Side by Side Diff: chrome/browser/chromeos/system/automatic_reboot_manager.cc

Issue 727363002: Fire notifications when reboot is requested, not scheduled (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@managed_cros
Patch Set: Removed debug logging. Ready for re-review. Created 6 years, 1 month 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/system/automatic_reboot_manager.h" 5 #include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
6 6
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <sys/stat.h> 8 #include <sys/stat.h>
9 #include <sys/types.h> 9 #include <sys/types.h>
10 10
11 #include <algorithm> 11 #include <algorithm>
12 #include <string> 12 #include <string>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/callback.h" 16 #include "base/callback.h"
17 #include "base/files/file_path.h" 17 #include "base/files/file_path.h"
18 #include "base/files/file_util.h" 18 #include "base/files/file_util.h"
19 #include "base/files/scoped_file.h" 19 #include "base/files/scoped_file.h"
20 #include "base/location.h" 20 #include "base/location.h"
21 #include "base/logging.h" 21 #include "base/logging.h"
22 #include "base/memory/ref_counted.h" 22 #include "base/memory/ref_counted.h"
23 #include "base/message_loop/message_loop.h"
23 #include "base/path_service.h" 24 #include "base/path_service.h"
24 #include "base/posix/eintr_wrapper.h" 25 #include "base/posix/eintr_wrapper.h"
25 #include "base/prefs/pref_registry_simple.h" 26 #include "base/prefs/pref_registry_simple.h"
26 #include "base/prefs/pref_service.h" 27 #include "base/prefs/pref_service.h"
27 #include "base/single_thread_task_runner.h" 28 #include "base/single_thread_task_runner.h"
28 #include "base/strings/string_number_conversions.h" 29 #include "base/strings/string_number_conversions.h"
29 #include "base/thread_task_runner_handle.h" 30 #include "base/thread_task_runner_handle.h"
30 #include "base/threading/sequenced_worker_pool.h" 31 #include "base/threading/sequenced_worker_pool.h"
31 #include "base/threading/thread_restrictions.h" 32 #include "base/threading/thread_restrictions.h"
32 #include "base/time/tick_clock.h" 33 #include "base/time/tick_clock.h"
33 #include "chrome/browser/browser_process.h" 34 #include "chrome/browser/browser_process.h"
34 #include "chrome/browser/chrome_notification_types.h" 35 #include "chrome/browser/chrome_notification_types.h"
35 #include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
36 #include "chrome/common/pref_names.h" 36 #include "chrome/common/pref_names.h"
37 #include "chromeos/chromeos_paths.h" 37 #include "chromeos/chromeos_paths.h"
38 #include "chromeos/chromeos_switches.h" 38 #include "chromeos/chromeos_switches.h"
39 #include "chromeos/dbus/dbus_thread_manager.h" 39 #include "chromeos/dbus/dbus_thread_manager.h"
40 #include "components/user_manager/user_manager.h" 40 #include "components/user_manager/user_manager.h"
41 #include "content/public/browser/browser_thread.h" 41 #include "content/public/browser/browser_thread.h"
42 #include "content/public/browser/notification_details.h" 42 #include "content/public/browser/notification_details.h"
43 #include "content/public/browser/notification_service.h" 43 #include "content/public/browser/notification_service.h"
44 #include "content/public/browser/notification_source.h" 44 #include "content/public/browser/notification_source.h"
45 #include "ui/wm/core/user_activity_detector.h" 45 #include "ui/wm/core/user_activity_detector.h"
46 46
47 namespace chromeos { 47 namespace chromeos {
48 namespace system { 48 namespace system {
49 49
50 namespace { 50 namespace {
51 51
52 const int kMinRebootUptimeMs = 60 * 60 * 1000; // 1 hour. 52 const int kMinRebootUptimeMs = 60 * 60 * 1000; // 1 hour.
53 const int kLoginManagerIdleTimeoutMs = 60 * 1000; // 60 seconds. 53 const int kLoginManagerIdleTimeoutMs = 60 * 1000; // 60 seconds.
54 const int kGracePeriodMs = 24 * 60 * 60 * 1000; // 24 hours. 54 const int kGracePeriodMs = 24 * 60 * 60 * 1000; // 24 hours.
55 const int kOneKilobyte = 1 << 10; // 1 kB in bytes. 55 const int kOneKilobyte = 1 << 10; // 1 kB in bytes.
56 56
57 const char kSequenceToken[] = "automatic-reboot-manager";
58
57 base::TimeDelta ReadTimeDeltaFromFile(const base::FilePath& path) { 59 base::TimeDelta ReadTimeDeltaFromFile(const base::FilePath& path) {
58 base::ThreadRestrictions::AssertIOAllowed(); 60 base::ThreadRestrictions::AssertIOAllowed();
59 base::ScopedFD fd( 61 base::ScopedFD fd(
60 HANDLE_EINTR(open(path.value().c_str(), O_RDONLY | O_NOFOLLOW))); 62 HANDLE_EINTR(open(path.value().c_str(), O_RDONLY | O_NOFOLLOW)));
61 if (!fd.is_valid()) 63 if (!fd.is_valid())
62 return base::TimeDelta(); 64 return base::TimeDelta();
63 65
64 std::string contents; 66 std::string contents;
65 char buffer[kOneKilobyte]; 67 char buffer[kOneKilobyte];
66 ssize_t length; 68 ssize_t length;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 // necessary in base::TimeTicks::Now() ticks. 146 // necessary in base::TimeTicks::Now() ticks.
145 update_reboot_needed_time = boot_time + update_reboot_needed_uptime; 147 update_reboot_needed_time = boot_time + update_reboot_needed_uptime;
146 has_update_reboot_needed_time = true; 148 has_update_reboot_needed_time = true;
147 } 149 }
148 150
149 AutomaticRebootManager::AutomaticRebootManager( 151 AutomaticRebootManager::AutomaticRebootManager(
150 scoped_ptr<base::TickClock> clock) 152 scoped_ptr<base::TickClock> clock)
151 : clock_(clock.Pass()), 153 : clock_(clock.Pass()),
152 have_boot_time_(false), 154 have_boot_time_(false),
153 have_update_reboot_needed_time_(false), 155 have_update_reboot_needed_time_(false),
156 reboot_reason_(AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN),
154 reboot_requested_(false), 157 reboot_requested_(false),
155 weak_ptr_factory_(this) { 158 weak_ptr_factory_(this) {
156 local_state_registrar_.Init(g_browser_process->local_state()); 159 local_state_registrar_.Init(g_browser_process->local_state());
157 local_state_registrar_.Add(prefs::kUptimeLimit, 160 local_state_registrar_.Add(prefs::kUptimeLimit,
158 base::Bind(&AutomaticRebootManager::Reschedule, 161 base::Bind(&AutomaticRebootManager::Reschedule,
159 base::Unretained(this))); 162 base::Unretained(this)));
160 local_state_registrar_.Add(prefs::kRebootAfterUpdate, 163 local_state_registrar_.Add(prefs::kRebootAfterUpdate,
161 base::Bind(&AutomaticRebootManager::Reschedule, 164 base::Bind(&AutomaticRebootManager::Reschedule,
162 base::Unretained(this))); 165 base::Unretained(this)));
163 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 166 notification_registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
(...skipping 13 matching lines...) Expand all
177 content::NotificationService::AllSources()); 180 content::NotificationService::AllSources());
178 login_screen_idle_timer_.reset( 181 login_screen_idle_timer_.reset(
179 new base::OneShotTimer<AutomaticRebootManager>); 182 new base::OneShotTimer<AutomaticRebootManager>);
180 OnUserActivity(NULL); 183 OnUserActivity(NULL);
181 } 184 }
182 185
183 // In a regular browser, base::ThreadTaskRunnerHandle::Get() and 186 // In a regular browser, base::ThreadTaskRunnerHandle::Get() and
184 // base::MessageLoopProxy::current() return pointers to the same object. 187 // base::MessageLoopProxy::current() return pointers to the same object.
185 // In unit tests, using base::ThreadTaskRunnerHandle::Get() has the advantage 188 // In unit tests, using base::ThreadTaskRunnerHandle::Get() has the advantage
186 // that it allows a custom base::SingleThreadTaskRunner to be injected. 189 // that it allows a custom base::SingleThreadTaskRunner to be injected.
187 content::BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( 190 base::SequencedWorkerPool* worker_pool =
191 content::BrowserThread::GetBlockingPool();
192 worker_pool->PostSequencedWorkerTaskWithShutdownBehavior(
193 worker_pool->GetNamedSequenceToken(kSequenceToken),
188 FROM_HERE, 194 FROM_HERE,
189 base::Bind(&GetSystemEventTimes, 195 base::Bind(&GetSystemEventTimes,
190 base::ThreadTaskRunnerHandle::Get(), 196 base::ThreadTaskRunnerHandle::Get(),
191 base::Bind(&AutomaticRebootManager::Init, 197 base::Bind(&AutomaticRebootManager::Init,
192 weak_ptr_factory_.GetWeakPtr())), 198 weak_ptr_factory_.GetWeakPtr())),
193 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); 199 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
194 } 200 }
195 201
196 AutomaticRebootManager::~AutomaticRebootManager() { 202 AutomaticRebootManager::~AutomaticRebootManager() {
197 FOR_EACH_OBSERVER(AutomaticRebootManagerObserver, 203 FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 void AutomaticRebootManager::Reschedule() { 316 void AutomaticRebootManager::Reschedule() {
311 // Safeguard against reboot loops under error conditions: If the boot time is 317 // Safeguard against reboot loops under error conditions: If the boot time is
312 // unavailable because /proc/uptime could not be read, do nothing. 318 // unavailable because /proc/uptime could not be read, do nothing.
313 if (!have_boot_time_) 319 if (!have_boot_time_)
314 return; 320 return;
315 321
316 // Assume that no reboot has been requested. 322 // Assume that no reboot has been requested.
317 reboot_requested_ = false; 323 reboot_requested_ = false;
318 324
319 const base::TimeDelta kZeroTimeDelta; 325 const base::TimeDelta kZeroTimeDelta;
320 AutomaticRebootManagerObserver::Reason reboot_reason =
321 AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN;
322 326
323 // If an uptime limit is set, calculate the time at which it should cause a 327 // If an uptime limit is set, calculate the time at which it should cause a
324 // reboot to be requested. 328 // reboot to be requested.
325 const base::TimeDelta uptime_limit = base::TimeDelta::FromSeconds( 329 const base::TimeDelta uptime_limit = base::TimeDelta::FromSeconds(
326 local_state_registrar_.prefs()->GetInteger(prefs::kUptimeLimit)); 330 local_state_registrar_.prefs()->GetInteger(prefs::kUptimeLimit));
327 base::TimeTicks reboot_request_time = boot_time_ + uptime_limit; 331 base::TimeTicks reboot_request_time = boot_time_ + uptime_limit;
328 bool have_reboot_request_time = uptime_limit != kZeroTimeDelta; 332 bool have_reboot_request_time = uptime_limit != kZeroTimeDelta;
329 if (have_reboot_request_time) 333 if (have_reboot_request_time)
330 reboot_reason = AutomaticRebootManagerObserver::REBOOT_REASON_PERIODIC; 334 reboot_reason_ = AutomaticRebootManagerObserver::REBOOT_REASON_PERIODIC;
331 335
332 // If the policy to automatically reboot after an update is enabled and an 336 // If the policy to automatically reboot after an update is enabled and an
333 // update has been applied, set the time at which a reboot should be 337 // update has been applied, set the time at which a reboot should be
334 // requested to the minimum of its current value and the time when the reboot 338 // requested to the minimum of its current value and the time when the reboot
335 // became necessary. 339 // became necessary.
336 if (have_update_reboot_needed_time_ && 340 if (have_update_reboot_needed_time_ &&
337 local_state_registrar_.prefs()->GetBoolean(prefs::kRebootAfterUpdate) && 341 local_state_registrar_.prefs()->GetBoolean(prefs::kRebootAfterUpdate) &&
338 (!have_reboot_request_time || 342 (!have_reboot_request_time ||
339 update_reboot_needed_time_ < reboot_request_time)) { 343 update_reboot_needed_time_ < reboot_request_time)) {
340 reboot_request_time = update_reboot_needed_time_; 344 reboot_request_time = update_reboot_needed_time_;
341 have_reboot_request_time = true; 345 have_reboot_request_time = true;
342 reboot_reason = AutomaticRebootManagerObserver::REBOOT_REASON_OS_UPDATE; 346 reboot_reason_ = AutomaticRebootManagerObserver::REBOOT_REASON_OS_UPDATE;
343 } 347 }
344 348
345 // If no reboot should be requested, remove any grace period. 349 // If no reboot should be requested, remove any grace period.
346 if (!have_reboot_request_time) { 350 if (!have_reboot_request_time) {
347 grace_start_timer_.reset(); 351 grace_start_timer_.reset();
348 grace_end_timer_.reset(); 352 grace_end_timer_.reset();
349 return; 353 return;
350 } 354 }
351 355
352 // Safeguard against reboot loops: Ensure that the uptime after which a reboot 356 // Safeguard against reboot loops: Ensure that the uptime after which a reboot
353 // is actually requested and the grace period begins is never less than 357 // is actually requested and the grace period begins is never less than
354 // |kMinRebootUptimeMs|. 358 // |kMinRebootUptimeMs|.
355 const base::TimeTicks now = clock_->NowTicks(); 359 const base::TimeTicks now = clock_->NowTicks();
356 const base::TimeTicks grace_start_time = std::max(reboot_request_time, 360 const base::TimeTicks grace_start_time = std::max(reboot_request_time,
357 boot_time_ + base::TimeDelta::FromMilliseconds(kMinRebootUptimeMs)); 361 boot_time_ + base::TimeDelta::FromMilliseconds(kMinRebootUptimeMs));
362
358 // Set up a timer for the start of the grace period. If the grace period 363 // Set up a timer for the start of the grace period. If the grace period
359 // started in the past, the timer is still used with its delay set to zero. 364 // started in the past, the timer is still used with its delay set to zero.
360 if (!grace_start_timer_) 365 if (!grace_start_timer_)
361 grace_start_timer_.reset(new base::OneShotTimer<AutomaticRebootManager>); 366 grace_start_timer_.reset(new base::OneShotTimer<AutomaticRebootManager>);
362 grace_start_timer_->Start(FROM_HERE, 367 grace_start_timer_->Start(FROM_HERE,
363 std::max(grace_start_time - now, kZeroTimeDelta), 368 std::max(grace_start_time - now, kZeroTimeDelta),
364 base::Bind(&AutomaticRebootManager::RequestReboot, 369 base::Bind(&AutomaticRebootManager::RequestReboot,
365 base::Unretained(this))); 370 base::Unretained(this)));
366 371
367 const base::TimeTicks grace_end_time = grace_start_time + 372 const base::TimeTicks grace_end_time = grace_start_time +
368 base::TimeDelta::FromMilliseconds(kGracePeriodMs); 373 base::TimeDelta::FromMilliseconds(kGracePeriodMs);
369 // Set up a timer for the end of the grace period. If the grace period ended 374 // Set up a timer for the end of the grace period. If the grace period ended
370 // in the past, the timer is still used with its delay set to zero. 375 // in the past, the timer is still used with its delay set to zero.
371 if (!grace_end_timer_) 376 if (!grace_end_timer_)
372 grace_end_timer_.reset(new base::OneShotTimer<AutomaticRebootManager>); 377 grace_end_timer_.reset(new base::OneShotTimer<AutomaticRebootManager>);
373 grace_end_timer_->Start(FROM_HERE, 378 grace_end_timer_->Start(FROM_HERE,
374 std::max(grace_end_time - now, kZeroTimeDelta), 379 std::max(grace_end_time - now, kZeroTimeDelta),
375 base::Bind(&AutomaticRebootManager::Reboot, 380 base::Bind(&AutomaticRebootManager::Reboot,
376 base::Unretained(this))); 381 base::Unretained(this)));
377
378 DCHECK_NE(AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN,
379 reboot_reason);
380 FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
381 observers_,
382 OnRebootScheduled(reboot_reason));
383 } 382 }
384 383
385 void AutomaticRebootManager::RequestReboot() { 384 void AutomaticRebootManager::RequestReboot() {
386 reboot_requested_ = true; 385 reboot_requested_ = true;
386 DCHECK_NE(AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN,
387 reboot_reason_);
388 FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
389 observers_,
390 OnRebootRequested(reboot_reason_));
387 MaybeReboot(false); 391 MaybeReboot(false);
388 } 392 }
389 393
390 void AutomaticRebootManager::MaybeReboot(bool ignore_session) { 394 void AutomaticRebootManager::MaybeReboot(bool ignore_session) {
391 // Do not reboot if any of the following applies: 395 // Do not reboot if any of the following applies:
392 // * No reboot has been requested. 396 // * No reboot has been requested.
393 // * A user is interacting with the login screen. 397 // * A user is interacting with the login screen.
394 // * A session is in progress and |ignore_session| is not set. 398 // * A session is in progress and |ignore_session| is not set.
395 if (!reboot_requested_ || 399 if (!reboot_requested_ ||
396 (login_screen_idle_timer_ && login_screen_idle_timer_->IsRunning()) || 400 (login_screen_idle_timer_ && login_screen_idle_timer_->IsRunning()) ||
(...skipping 12 matching lines...) Expand all
409 } 413 }
410 414
411 login_screen_idle_timer_.reset(); 415 login_screen_idle_timer_.reset();
412 grace_start_timer_.reset(); 416 grace_start_timer_.reset();
413 grace_end_timer_.reset(); 417 grace_end_timer_.reset();
414 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart(); 418 DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
415 } 419 }
416 420
417 } // namespace system 421 } // namespace system
418 } // namespace chromeos 422 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698