| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |