summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-24 20:18:43 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-24 20:18:43 +0000
commit833f6f330a38bdde0d8ee80513cd68ecc9b989a0 (patch)
treeb92b0dd4b242ff0bed497ebe5996f21adcbe806a
parent1927037efe8fc7d1e4cc83070dfb8b064b0844f2 (diff)
downloadchromium_src-833f6f330a38bdde0d8ee80513cd68ecc9b989a0.zip
chromium_src-833f6f330a38bdde0d8ee80513cd68ecc9b989a0.tar.gz
chromium_src-833f6f330a38bdde0d8ee80513cd68ecc9b989a0.tar.bz2
app_mode: Add runtime.onRestartRequired event.
BUG=242983 R=bartfab@chromium.org, mpcomplete@chromium.org, sky@chromium.org Review URL: https://codereview.chromium.org/16844020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@208250 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/browser_process_platform_part_chromeos.cc15
-rw-r--r--chrome/browser/browser_process_platform_part_chromeos.h16
-rw-r--r--chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc77
-rw-r--r--chrome/browser/chromeos/app_mode/kiosk_app_update_service.h29
-rw-r--r--chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc118
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.cc8
-rw-r--r--chrome/browser/chromeos/chrome_browser_main_chromeos.h2
-rw-r--r--chrome/browser/chromeos/system/automatic_reboot_manager.cc26
-rw-r--r--chrome/browser/chromeos/system/automatic_reboot_manager.h8
-rw-r--r--chrome/browser/chromeos/system/automatic_reboot_manager_observer.h32
-rw-r--r--chrome/browser/extensions/activity_log/api_name_constants.h3
-rw-r--r--chrome/browser/extensions/api/runtime/runtime_api.cc25
-rw-r--r--chrome/browser/extensions/api/runtime/runtime_api.h9
-rw-r--r--chrome/browser/extensions/extension_messages_apitest.cc1
-rw-r--r--chrome/chrome_browser_chromeos.gypi1
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/extensions/api/runtime.json19
-rw-r--r--chrome/test/data/extensions/api_test/runtime/on_restart_required/background.js9
-rw-r--r--chrome/test/data/extensions/api_test/runtime/on_restart_required/manifest.json10
19 files changed, 371 insertions, 38 deletions
diff --git a/chrome/browser/browser_process_platform_part_chromeos.cc b/chrome/browser/browser_process_platform_part_chromeos.cc
index 11cacb3..1821785 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.cc
+++ b/chrome/browser/browser_process_platform_part_chromeos.cc
@@ -4,8 +4,12 @@
#include "chrome/browser/browser_process_platform_part_chromeos.h"
+#include "base/logging.h"
+#include "base/time/default_tick_clock.h"
+#include "base/time/tick_clock.h"
#include "chrome/browser/chromeos/memory/oom_priority_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
BrowserProcessPlatformPart::BrowserProcessPlatformPart()
: created_profile_helper_(false) {
@@ -14,6 +18,17 @@ BrowserProcessPlatformPart::BrowserProcessPlatformPart()
BrowserProcessPlatformPart::~BrowserProcessPlatformPart() {
}
+void BrowserProcessPlatformPart::InitializeAutomaticRebootManager() {
+ DCHECK(!automatic_reboot_manager_);
+
+ automatic_reboot_manager_.reset(new chromeos::system::AutomaticRebootManager(
+ scoped_ptr<base::TickClock>(new base::DefaultTickClock)));
+}
+
+void BrowserProcessPlatformPart::ShutdownAutomaticRebootManager() {
+ automatic_reboot_manager_.reset();
+}
+
chromeos::OomPriorityManager*
BrowserProcessPlatformPart::oom_priority_manager() {
DCHECK(CalledOnValidThread());
diff --git a/chrome/browser/browser_process_platform_part_chromeos.h b/chrome/browser/browser_process_platform_part_chromeos.h
index 3eb1236..08dc683 100644
--- a/chrome/browser/browser_process_platform_part_chromeos.h
+++ b/chrome/browser/browser_process_platform_part_chromeos.h
@@ -15,12 +15,21 @@ class OomPriorityManager;
class ProfileHelper;
}
+namespace chromeos {
+namespace system {
+class AutomaticRebootManager;
+}
+}
+
class BrowserProcessPlatformPart : public BrowserProcessPlatformPartBase,
public base::NonThreadSafe {
public:
BrowserProcessPlatformPart();
virtual ~BrowserProcessPlatformPart();
+ void InitializeAutomaticRebootManager();
+ void ShutdownAutomaticRebootManager();
+
// Returns the out-of-memory priority manager.
virtual chromeos::OomPriorityManager* oom_priority_manager();
@@ -31,6 +40,10 @@ class BrowserProcessPlatformPart : public BrowserProcessPlatformPartBase,
// Overridden from BrowserProcessPlatformPartBase:
virtual void StartTearDown() OVERRIDE;
+ chromeos::system::AutomaticRebootManager* automatic_reboot_manager() {
+ return automatic_reboot_manager_.get();
+ }
+
protected:
virtual void CreateProfileHelper();
@@ -40,6 +53,9 @@ class BrowserProcessPlatformPart : public BrowserProcessPlatformPartBase,
private:
scoped_ptr<chromeos::OomPriorityManager> oom_priority_manager_;
+ scoped_ptr<chromeos::system::AutomaticRebootManager>
+ automatic_reboot_manager_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserProcessPlatformPart);
};
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc
index 0b789f9..e9a0384 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.cc
@@ -6,6 +6,10 @@
#include "base/logging.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part_chromeos.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
+#include "chrome/browser/extensions/api/runtime/runtime_api.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_system_factory.h"
@@ -22,17 +26,39 @@ const int kForceRestartWaitTimeMs = 24 * 3600 * 1000; // 24 hours.
} // namespace
-KioskAppUpdateService::KioskAppUpdateService(Profile* profile)
- : profile_(profile) {
+KioskAppUpdateService::KioskAppUpdateService(
+ Profile* profile,
+ system::AutomaticRebootManager* automatic_reboot_manager)
+ : profile_(profile),
+ automatic_reboot_manager_(automatic_reboot_manager) {
ExtensionService* service =
extensions::ExtensionSystem::Get(profile_)->extension_service();
if (service)
service->AddUpdateObserver(this);
+
+ if (automatic_reboot_manager_)
+ automatic_reboot_manager_->AddObserver(this);
}
KioskAppUpdateService::~KioskAppUpdateService() {
}
+void KioskAppUpdateService::StartAppUpdateRestartTimer() {
+ if (restart_timer_.IsRunning())
+ return;
+
+ // Setup timer to force restart once the wait period expires.
+ restart_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(kForceRestartWaitTimeMs),
+ this, &KioskAppUpdateService::ForceAppUpdateRestart);
+}
+
+void KioskAppUpdateService::ForceAppUpdateRestart() {
+ // Force a chrome restart (not a logout or reboot) by closing all browsers.
+ LOG(WARNING) << "Force closing all browsers to update kiosk app.";
+ chrome::CloseAllBrowsers();
+}
+
void KioskAppUpdateService::Shutdown() {
ExtensionService* service = profile_->GetExtensionService();
if (service)
@@ -44,23 +70,38 @@ void KioskAppUpdateService::OnAppUpdateAvailable(const std::string& app_id) {
if (app_id != app_id_)
return;
- StartRestartTimer();
-}
+ extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent(
+ profile_,
+ app_id_,
+ extensions::api::runtime::OnRestartRequired::REASON_APP_UPDATE);
-void KioskAppUpdateService::StartRestartTimer() {
- if (restart_timer_.IsRunning())
- return;
+ StartAppUpdateRestartTimer();
+}
- // Setup timer to force restart once the wait period expires.
- restart_timer_.Start(
- FROM_HERE, base::TimeDelta::FromMilliseconds(kForceRestartWaitTimeMs),
- this, &KioskAppUpdateService::ForceRestart);
+void KioskAppUpdateService::OnRebootScheduled(Reason reason) {
+ extensions::api::runtime::OnRestartRequired::Reason restart_reason =
+ extensions::api::runtime::OnRestartRequired::REASON_NONE;
+ switch (reason) {
+ case REBOOT_REASON_OS_UPDATE:
+ restart_reason =
+ extensions::api::runtime::OnRestartRequired::REASON_OS_UPDATE;
+ break;
+ case REBOOT_REASON_PERIODIC:
+ restart_reason =
+ extensions::api::runtime::OnRestartRequired::REASON_PERIODIC;
+ break;
+ default:
+ NOTREACHED() << "Unknown reboot reason=" << reason;
+ return;
+ }
+
+ extensions::RuntimeEventRouter::DispatchOnRestartRequiredEvent(
+ profile_, app_id_, restart_reason);
}
-void KioskAppUpdateService::ForceRestart() {
- // Force a chrome restart (not a logout or reboot) by closing all browsers.
- LOG(WARNING) << "Force closing all browsers to update kiosk app.";
- chrome::CloseAllBrowsers();
+void KioskAppUpdateService::WillDestroyAutomaticRebootManager() {
+ automatic_reboot_manager_->RemoveObserver(this);
+ automatic_reboot_manager_ = NULL;
}
KioskAppUpdateServiceFactory::KioskAppUpdateServiceFactory()
@@ -92,8 +133,10 @@ KioskAppUpdateServiceFactory* KioskAppUpdateServiceFactory::GetInstance() {
BrowserContextKeyedService*
KioskAppUpdateServiceFactory::BuildServiceInstanceFor(
- content::BrowserContext* profile) const {
- return new KioskAppUpdateService(static_cast<Profile*>(profile));
+ content::BrowserContext* context) const {
+ return new KioskAppUpdateService(
+ Profile::FromBrowserContext(context),
+ g_browser_process->platform_part()->automatic_reboot_manager());
}
} // namespace chromeos
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h
index 7421a81..729da7f 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service.h
@@ -11,6 +11,7 @@
#include "base/compiler_specific.h"
#include "base/memory/singleton.h"
#include "base/timer.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
#include "chrome/browser/extensions/update_observer.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service.h"
#include "components/browser_context_keyed_service/browser_context_keyed_service_factory.h"
@@ -19,34 +20,48 @@ class Profile;
namespace chromeos {
+namespace system {
+class AutomaticRebootManager;
+}
+
// This class enforces automatic restart on app and Chrome updates in app mode.
class KioskAppUpdateService : public BrowserContextKeyedService,
- public extensions::UpdateObserver {
+ public extensions::UpdateObserver,
+ public system::AutomaticRebootManagerObserver {
public:
- explicit KioskAppUpdateService(Profile* profile);
+ KioskAppUpdateService(
+ Profile* profile,
+ system::AutomaticRebootManager* automatic_reboot_manager);
virtual ~KioskAppUpdateService();
void set_app_id(const std::string& app_id) { app_id_ = app_id; }
std::string get_app_id() const { return app_id_; }
private:
- void StartRestartTimer();
- void ForceRestart();
+ friend class KioskAppUpdateServiceTest;
+
+ void StartAppUpdateRestartTimer();
+ void ForceAppUpdateRestart();
+
+ // BrowserContextKeyedService overrides:
+ virtual void Shutdown() OVERRIDE;
// extensions::UpdateObserver overrides:
virtual void OnAppUpdateAvailable(const std::string& app_id) OVERRIDE;
virtual void OnChromeUpdateAvailable() OVERRIDE {}
- // BrowserContextKeyedService overrides:
- virtual void Shutdown() OVERRIDE;
+ // system::AutomaticRebootManagerObserver overrides:
+ virtual void OnRebootScheduled(Reason reason) OVERRIDE;
+ virtual void WillDestroyAutomaticRebootManager() OVERRIDE;
- private:
Profile* profile_;
std::string app_id_;
// After we detect an upgrade we start a one-short timer to force restart.
base::OneShotTimer<KioskAppUpdateService> restart_timer_;
+ system::AutomaticRebootManager* automatic_reboot_manager_; // Not owned.
+
DISALLOW_COPY_AND_ASSIGN(KioskAppUpdateService);
};
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
new file mode 100644
index 0000000..4b1c987
--- /dev/null
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc
@@ -0,0 +1,118 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_path_override.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "base/time.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/app_mode/kiosk_app_update_service.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/platform_app_browsertest_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/chromeos_paths.h"
+#include "chromeos/dbus/update_engine_client.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+class KioskAppUpdateServiceTest : public extensions::PlatformAppBrowserTest {
+ public:
+ KioskAppUpdateServiceTest() : app_(NULL), update_service_(NULL) {}
+ virtual ~KioskAppUpdateServiceTest() {}
+
+ // extensions::PlatformAppBrowserTest overrides:
+ virtual void SetUpOnMainThread() OVERRIDE {
+ extensions::PlatformAppBrowserTest::SetUpOnMainThread();
+
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ const base::FilePath& temp_dir = temp_dir_.path();
+
+ const base::TimeDelta uptime = base::TimeDelta::FromHours(1);
+ const std::string uptime_seconds =
+ base::DoubleToString(uptime.InSecondsF());
+ const base::FilePath uptime_file = temp_dir.Append("uptime");
+ ASSERT_EQ(static_cast<int>(uptime_seconds.size()),
+ file_util::WriteFile(
+ uptime_file, uptime_seconds.c_str(), uptime_seconds.size()));
+ uptime_file_override_.reset(
+ new base::ScopedPathOverride(chromeos::FILE_UPTIME, uptime_file));
+
+ app_ = LoadExtension(
+ test_data_dir_.AppendASCII("api_test/runtime/on_restart_required"));
+
+ // Fake app mode command line.
+ CommandLine* command = CommandLine::ForCurrentProcess();
+ command->AppendSwitch(switches::kForceAppMode);
+ command->AppendSwitchASCII(switches::kAppId, app_->id());
+
+ update_service_ = KioskAppUpdateServiceFactory::GetForProfile(profile());
+ update_service_->set_app_id(app_->id());
+
+ content::BrowserThread::GetBlockingPool()->FlushForTesting();
+ content::RunAllPendingInMessageLoop();
+ }
+
+ void FireAppUpdateAvailable() {
+ update_service_->OnAppUpdateAvailable(app_->id());
+ }
+
+ void FireUpdatedNeedReboot() {
+ UpdateEngineClient::Status status;
+ status.status = UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
+ g_browser_process->platform_part()->automatic_reboot_manager()->
+ UpdateStatusChanged(status);
+ }
+
+ private:
+ base::ScopedTempDir temp_dir_;
+ scoped_ptr<base::ScopedPathOverride> uptime_file_override_;
+ const extensions::Extension* app_; // Not owned.
+ KioskAppUpdateService* update_service_; // Not owned.
+
+ DISALLOW_COPY_AND_ASSIGN(KioskAppUpdateServiceTest);
+};
+
+IN_PROC_BROWSER_TEST_F(KioskAppUpdateServiceTest, AppUpdate) {
+ FireAppUpdateAvailable();
+
+ ExtensionTestMessageListener listener("app_update", false);
+ listener.WaitUntilSatisfied();
+}
+
+IN_PROC_BROWSER_TEST_F(KioskAppUpdateServiceTest, OsUpdate) {
+ g_browser_process->local_state()->SetBoolean(prefs::kRebootAfterUpdate, true);
+ FireUpdatedNeedReboot();
+
+ ExtensionTestMessageListener listener("os_update", false);
+ listener.WaitUntilSatisfied();
+}
+
+IN_PROC_BROWSER_TEST_F(KioskAppUpdateServiceTest, Periodic) {
+ g_browser_process->local_state()->SetInteger(
+ prefs::kUptimeLimit, base::TimeDelta::FromMinutes(30).InSeconds());
+
+ ExtensionTestMessageListener listener("periodic", false);
+ listener.WaitUntilSatisfied();
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index a698d93..085d0b4 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -21,8 +21,6 @@
#include "base/prefs/pref_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/tick_clock.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part_chromeos.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -72,7 +70,6 @@
#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/owner_key_util.h"
-#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
#include "chrome/browser/chromeos/system/device_change_handler.h"
#include "chrome/browser/chromeos/system/statistics_provider.h"
#include "chrome/browser/chromeos/system_key_event_listener.h"
@@ -699,8 +696,7 @@ void ChromeBrowserMainPartsChromeos::PostProfileInit() {
display_configuration_observer_.reset(
new DisplayConfigurationObserver());
- automatic_reboot_manager_.reset(new system::AutomaticRebootManager(
- scoped_ptr<base::TickClock>(new base::DefaultTickClock)));
+ g_browser_process->platform_part()->InitializeAutomaticRebootManager();
// This observer cannot be created earlier because it requires the shell to be
// available.
@@ -841,7 +837,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// Let the AutomaticRebootManager unregister itself as an observer of several
// subsystems.
- automatic_reboot_manager_.reset();
+ g_browser_process->platform_part()->ShutdownAutomaticRebootManager();
// Clean up dependency on CrosSettings and stop pending data fetches.
KioskAppManager::Shutdown();
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.h b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
index d9ac4a7..0213132 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.h
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.h
@@ -44,7 +44,6 @@ class DBusServices;
}
namespace system {
-class AutomaticRebootManager;
class DeviceChangeHandler;
}
@@ -86,7 +85,6 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux {
scoped_ptr<UserActivityNotifier> user_activity_notifier_;
scoped_ptr<VideoActivityNotifier> video_activity_notifier_;
scoped_ptr<StorageMonitorCros> storage_monitor_;
- scoped_ptr<system::AutomaticRebootManager> automatic_reboot_manager_;
scoped_ptr<IdleActionWarningObserver> idle_action_warning_observer_;
scoped_ptr<system::DeviceChangeHandler> device_change_handler_;
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.cc b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
index b13db1c..c77d06e 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.cc
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
@@ -33,6 +33,7 @@
#include "base/time/tick_clock.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager_observer.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
#include "chromeos/chromeos_paths.h"
@@ -194,6 +195,10 @@ AutomaticRebootManager::AutomaticRebootManager(
}
AutomaticRebootManager::~AutomaticRebootManager() {
+ FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
+ observers_,
+ WillDestroyAutomaticRebootManager());
+
DBusThreadManager* dbus_thread_manager = DBusThreadManager::Get();
dbus_thread_manager->GetPowerManagerClient()->RemoveObserver(this);
dbus_thread_manager->GetUpdateEngineClient()->RemoveObserver(this);
@@ -201,6 +206,16 @@ AutomaticRebootManager::~AutomaticRebootManager() {
ash::Shell::GetInstance()->user_activity_detector()->RemoveObserver(this);
}
+void AutomaticRebootManager::AddObserver(
+ AutomaticRebootManagerObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void AutomaticRebootManager::RemoveObserver(
+ AutomaticRebootManagerObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
void AutomaticRebootManager::SystemResumed(
const base::TimeDelta& sleep_duration) {
MaybeReboot(true);
@@ -303,6 +318,8 @@ void AutomaticRebootManager::Reschedule() {
reboot_requested_ = false;
const base::TimeDelta kZeroTimeDelta;
+ AutomaticRebootManagerObserver::Reason reboot_reason =
+ AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN;
// If an uptime limit is set, calculate the time at which it should cause a
// reboot to be requested.
@@ -310,6 +327,8 @@ void AutomaticRebootManager::Reschedule() {
local_state_registrar_.prefs()->GetInteger(prefs::kUptimeLimit));
base::TimeTicks reboot_request_time = boot_time_ + uptime_limit;
bool have_reboot_request_time = uptime_limit != kZeroTimeDelta;
+ if (have_reboot_request_time)
+ reboot_reason = AutomaticRebootManagerObserver::REBOOT_REASON_PERIODIC;
// If the policy to automatically reboot after an update is enabled and an
// update has been applied, set the time at which a reboot should be
@@ -321,6 +340,7 @@ void AutomaticRebootManager::Reschedule() {
update_reboot_needed_time_ < reboot_request_time)) {
reboot_request_time = update_reboot_needed_time_;
have_reboot_request_time = true;
+ reboot_reason = AutomaticRebootManagerObserver::REBOOT_REASON_OS_UPDATE;
}
// If no reboot should be requested, remove any grace period.
@@ -355,6 +375,12 @@ void AutomaticRebootManager::Reschedule() {
std::max(grace_end_time - now, kZeroTimeDelta),
base::Bind(&AutomaticRebootManager::Reboot,
base::Unretained(this)));
+
+ DCHECK_NE(AutomaticRebootManagerObserver::REBOOT_REASON_UNKNOWN,
+ reboot_reason);
+ FOR_EACH_OBSERVER(AutomaticRebootManagerObserver,
+ observers_,
+ OnRebootScheduled(reboot_reason));
}
void AutomaticRebootManager::RequestReboot() {
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.h b/chrome/browser/chromeos/system/automatic_reboot_manager.h
index 9d29262..4892f6f 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.h
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/time.h"
#include "base/timer.h"
@@ -27,6 +28,8 @@ class TickClock;
namespace chromeos {
namespace system {
+class AutomaticRebootManagerObserver;
+
// Schedules and executes automatic reboots.
//
// Automatic reboots may be scheduled for any number of reasons. Currently, the
@@ -90,6 +93,9 @@ class AutomaticRebootManager : public PowerManagerClient::Observer,
explicit AutomaticRebootManager(scoped_ptr<base::TickClock> clock);
virtual ~AutomaticRebootManager();
+ void AddObserver(AutomaticRebootManagerObserver* observer);
+ void RemoveObserver(AutomaticRebootManagerObserver* observer);
+
// PowerManagerClient::Observer:
virtual void SystemResumed(const base::TimeDelta& sleep_duration) OVERRIDE;
@@ -160,6 +166,8 @@ class AutomaticRebootManager : public PowerManagerClient::Observer,
base::WeakPtrFactory<AutomaticRebootManager> weak_ptr_factory_;
+ ObserverList<AutomaticRebootManagerObserver, true> observers_;
+
DISALLOW_COPY_AND_ASSIGN(AutomaticRebootManager);
};
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h b/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
new file mode 100644
index 0000000..67c1b50
--- /dev/null
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager_observer.h
@@ -0,0 +1,32 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
+#define CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
+
+namespace chromeos {
+namespace system {
+
+class AutomaticRebootManagerObserver {
+ public:
+ enum Reason {
+ REBOOT_REASON_UNKNOWN,
+ REBOOT_REASON_OS_UPDATE,
+ REBOOT_REASON_PERIODIC,
+ };
+
+ // Invoked when a reboot is scheduled.
+ virtual void OnRebootScheduled(Reason reason) = 0;
+
+ // Invoked before the automatic reboot manager is destroyed.
+ virtual void WillDestroyAutomaticRebootManager() = 0;
+
+ protected:
+ virtual ~AutomaticRebootManagerObserver() {}
+};
+
+} // namespace system
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_SYSTEM_AUTOMATIC_REBOOT_MANAGER_OBSERVER_H_
diff --git a/chrome/browser/extensions/activity_log/api_name_constants.h b/chrome/browser/extensions/activity_log/api_name_constants.h
index 350ac21..7a6383d 100644
--- a/chrome/browser/extensions/activity_log/api_name_constants.h
+++ b/chrome/browser/extensions/activity_log/api_name_constants.h
@@ -191,7 +191,8 @@ const char* const kNames[] = {
"windows.onFocusChanged", "windows.onRemoved", "windows.remove",
"windows.update",
"tabs.getSelected", "tabs.sendRequest",
- "systemInfo.cpu.get", "systemInfo.memory.get"
+ "systemInfo.cpu.get", "systemInfo.memory.get",
+ "runtime.onRestartRequired"
};
} // namespace activity_log_api_name_constants
diff --git a/chrome/browser/extensions/api/runtime/runtime_api.cc b/chrome/browser/extensions/api/runtime/runtime_api.cc
index bdfff1f..c04d181 100644
--- a/chrome/browser/extensions/api/runtime/runtime_api.cc
+++ b/chrome/browser/extensions/api/runtime/runtime_api.cc
@@ -4,7 +4,11 @@
#include "chrome/browser/extensions/api/runtime/runtime_api.h"
+#include <utility>
+
+#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/event_router.h"
#include "chrome/browser/extensions/extension_host.h"
@@ -19,7 +23,6 @@
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/extensions/api/runtime.h"
#include "chrome/common/extensions/background_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/omaha_query_params/omaha_query_params.h"
@@ -42,6 +45,7 @@ const char kOnInstalledEvent[] = "runtime.onInstalled";
const char kOnUpdateAvailableEvent[] = "runtime.onUpdateAvailable";
const char kOnBrowserUpdateAvailableEvent[] =
"runtime.onBrowserUpdateAvailable";
+const char kOnRestartRequiredEvent[] = "runtime.onRestartRequired";
const char kNoBackgroundPageError[] = "You do not have a background page.";
const char kPageLoadError[] = "Background page failed to load.";
const char kInstallReason[] = "reason";
@@ -193,8 +197,25 @@ void RuntimeEventRouter::DispatchOnBrowserUpdateAvailableEvent(
}
// static
+void RuntimeEventRouter::DispatchOnRestartRequiredEvent(
+ Profile* profile,
+ const std::string& app_id,
+ api::runtime::OnRestartRequired::Reason reason) {
+ ExtensionSystem* system = ExtensionSystem::Get(profile);
+ if (!system)
+ return;
+
+ scoped_ptr<Event> event(
+ new Event(kOnRestartRequiredEvent,
+ api::runtime::OnRestartRequired::Create(reason)));
+
+ DCHECK(system->event_router());
+ system->event_router()->DispatchEventToExtension(app_id, event.Pass());
+}
+
+// static
void RuntimeEventRouter::OnExtensionUninstalled(
- Profile *profile,
+ Profile* profile,
const std::string& extension_id) {
#if defined(ENABLE_EXTENSIONS)
GURL uninstall_url(GetUninstallUrl(ExtensionPrefs::Get(profile),
diff --git a/chrome/browser/extensions/api/runtime/runtime_api.h b/chrome/browser/extensions/api/runtime/runtime_api.h
index c21255e..d936945 100644
--- a/chrome/browser/extensions/api/runtime/runtime_api.h
+++ b/chrome/browser/extensions/api/runtime/runtime_api.h
@@ -5,7 +5,10 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_RUNTIME_RUNTIME_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_RUNTIME_RUNTIME_API_H_
+#include <string>
+
#include "chrome/browser/extensions/extension_function.h"
+#include "chrome/common/extensions/api/runtime.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -40,6 +43,12 @@ class RuntimeEventRouter {
// Dispatches the onBrowserUpdateAvailable event to all extensions.
static void DispatchOnBrowserUpdateAvailableEvent(Profile* profile);
+ // Dispatches the onRestartRequired event to the given app.
+ static void DispatchOnRestartRequiredEvent(
+ Profile* profile,
+ const std::string& app_id,
+ api::runtime::OnRestartRequired::Reason reason);
+
// Does any work needed at extension uninstall (e.g. load uninstall url).
static void OnExtensionUninstalled(Profile* profile,
const std::string& extension_id);
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index d561dfa..7e98128 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -175,6 +175,7 @@ class ExternallyConnectableMessagingTest : public ExtensionApiTest {
"onConnectExternal",
"onMessage",
"onMessageExternal",
+ "onRestartRequired",
"id",
};
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 87832b6..d644b40 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -737,6 +737,7 @@
'browser/chromeos/system/ash_system_tray_delegate.h',
'browser/chromeos/system/automatic_reboot_manager.cc',
'browser/chromeos/system/automatic_reboot_manager.h',
+ 'browser/chromeos/system/automatic_reboot_manager_observer.h',
'browser/chromeos/system/device_change_handler.cc',
'browser/chromeos/system/device_change_handler.h',
'browser/chromeos/system/input_device_settings.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 987004d..1741152 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1209,6 +1209,7 @@
'browser/chromeos/accessibility/accessibility_manager_browsertest.cc',
'browser/chromeos/accessibility/magnification_manager_browsertest.cc',
'browser/chromeos/app_mode/kiosk_app_manager_browsertest.cc',
+ 'browser/chromeos/app_mode/kiosk_app_update_service_browsertest.cc',
'browser/chromeos/cros/cros_in_process_browser_test.cc',
'browser/chromeos/cros/cros_in_process_browser_test.h',
'browser/chromeos/cros/cros_mock.cc',
diff --git a/chrome/common/extensions/api/runtime.json b/chrome/common/extensions/api/runtime.json
index d1a1d3a..4be0200 100644
--- a/chrome/common/extensions/api/runtime.json
+++ b/chrome/common/extensions/api/runtime.json
@@ -372,9 +372,12 @@
]
},
{
+ // TODO(xiyuan): onBrowserUpdateAvailable is deprecated in favor of
+ // onRestartRequired. We should remove it when we are sure it is unused.
"name": "onBrowserUpdateAvailable",
"type": "function",
"description": "Fired when a Chrome update is available, but isn't installed immediately because a browser restart is required.",
+ "nodoc": true,
"parameters": []
},
{
@@ -428,10 +431,20 @@
"optional": "true",
"description": "Return true from the event listener if you wish to call <code>sendResponse</code> after the event listener returns."
}
+ },
+ {
+ "name": "onRestartRequired",
+ "type": "function",
+ "description": "Fired when an app or the device that it runs on needs to be restarted. The app should close all its windows at its earliest convenient time to let the restart to happen. If the app does nothing, a restart will be enforced after a 24-hour grace period has passed. Currently, this event is only fired for Chrome OS kiosk apps.",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "reason",
+ "description": "The reason that the event is being dispatched. 'app_update' is used when the restart is needed because the application is updated to a newer version. 'os_update' is used when the restart is needed because the browser/OS is updated to a newer version. 'periodic' is used when the system runs for more than the permitted uptime set in the enterprise policy.",
+ "enum": ["app_update", "os_update", "periodic"]
+ }
+ ]
}
-
-
-
]
}
]
diff --git a/chrome/test/data/extensions/api_test/runtime/on_restart_required/background.js b/chrome/test/data/extensions/api_test/runtime/on_restart_required/background.js
new file mode 100644
index 0000000..64d4d0b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/runtime/on_restart_required/background.js
@@ -0,0 +1,9 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function onRestartRequired(reason) {
+ chrome.test.sendMessage(reason);
+}
+
+chrome.runtime.onRestartRequired.addListener(onRestartRequired);
diff --git a/chrome/test/data/extensions/api_test/runtime/on_restart_required/manifest.json b/chrome/test/data/extensions/api_test/runtime/on_restart_required/manifest.json
new file mode 100644
index 0000000..1d52e8f
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/runtime/on_restart_required/manifest.json
@@ -0,0 +1,10 @@
+{
+ "name": "chrome.runtime.onRestartRequired test app",
+ "version": "0.1",
+ "description": "Test for chrome.runtime.onRestartRequired.",
+ "app": {
+ "background": {
+ "scripts": ["background.js"]
+ }
+ }
+}