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

Unified Diff: extensions/browser/api/runtime/restart_after_delay_api_unittest.cc

Issue 1970613003: Add a new app API to enable watchdog behavior restarts in kiosk apps (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Nitty nit. Created 4 years, 6 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
« no previous file with comments | « chrome/browser/prefs/browser_prefs.cc ('k') | extensions/browser/api/runtime/runtime_api.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
diff --git a/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc b/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..604f747eb0de5321056cdee453d0cf380e818da1
--- /dev/null
+++ b/extensions/browser/api/runtime/restart_after_delay_api_unittest.cc
@@ -0,0 +1,247 @@
+// Copyright 2016 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 "base/callback_helpers.h"
+#include "base/run_loop.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/pref_registry/testing_pref_service_syncable.h"
+#include "extensions/browser/api/runtime/runtime_api.h"
+#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/api_unittest.h"
+#include "extensions/browser/test_extensions_browser_client.h"
+#include "extensions/browser/test_runtime_api_delegate.h"
+#include "extensions/common/manifest.h"
+
+namespace extensions {
+
+namespace {
+
+// A RuntimeAPIDelegate that simulates a successful restart request every time.
+class DelayedRestartTestApiDelegate : public TestRuntimeAPIDelegate {
+ public:
+ DelayedRestartTestApiDelegate() {}
+ ~DelayedRestartTestApiDelegate() override {}
+
+ // TestRuntimeAPIDelegate:
+ bool RestartDevice(std::string* error_message) override {
+ if (!quit_closure_.is_null())
+ base::ResetAndReturn(&quit_closure_).Run();
+
+ *error_message = "Success.";
+ restart_done_ = true;
+
+ return true;
+ }
+
+ base::TimeTicks WaitForSuccessfulRestart() {
+ if (!restart_done_) {
+ base::RunLoop run_loop;
+ quit_closure_ = run_loop.QuitClosure();
+ run_loop.Run();
+ }
+ restart_done_ = false;
+ return base::TimeTicks::Now();
+ }
+
+ private:
+ base::Closure quit_closure_;
+
+ bool restart_done_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(DelayedRestartTestApiDelegate);
+};
+
+class DelayedRestartExtensionsBrowserClient
+ : public TestExtensionsBrowserClient {
+ public:
+ DelayedRestartExtensionsBrowserClient(content::BrowserContext* context)
+ : TestExtensionsBrowserClient(context) {}
+ ~DelayedRestartExtensionsBrowserClient() override {}
+
+ // TestExtensionsBrowserClient:
+ PrefService* GetPrefServiceForContext(
+ content::BrowserContext* context) override {
+ return &testing_pref_service_;
+ }
+
+ std::unique_ptr<RuntimeAPIDelegate> CreateRuntimeAPIDelegate(
+ content::BrowserContext* context) const override {
+ const_cast<DelayedRestartExtensionsBrowserClient*>(this)->api_delegate_ =
+ new DelayedRestartTestApiDelegate();
+ return base::WrapUnique(api_delegate_);
+ }
+
+ user_prefs::TestingPrefServiceSyncable* testing_pref_service() {
+ return &testing_pref_service_;
+ }
+
+ DelayedRestartTestApiDelegate* api_delegate() const {
+ CHECK(api_delegate_);
+ return api_delegate_;
+ }
+
+ private:
+ DelayedRestartTestApiDelegate* api_delegate_ = nullptr; // Not owned.
+
+ user_prefs::TestingPrefServiceSyncable testing_pref_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(DelayedRestartExtensionsBrowserClient);
+};
+
+} // namespace
+
+class RestartAfterDelayApiTest : public ApiUnitTest {
+ public:
+ RestartAfterDelayApiTest() {}
+ ~RestartAfterDelayApiTest() override {}
+
+ void SetUp() override {
+ ApiUnitTest::SetUp();
+
+ // Use our ExtensionsBrowserClient that returns our RuntimeAPIDelegate.
+ test_browser_client_.reset(
+ new DelayedRestartExtensionsBrowserClient(browser_context()));
+ test_browser_client_->set_extension_system_factory(
+ extensions_browser_client()->extension_system_factory());
+ ExtensionsBrowserClient::Set(test_browser_client_.get());
+
+ // The RuntimeAPI should only be accessed (i.e. constructed) after the above
+ // ExtensionsBrowserClient has been setup.
+ RuntimeAPI* runtime_api =
+ RuntimeAPI::GetFactoryInstance()->Get(browser_context());
+ runtime_api->set_min_duration_between_restarts_for_testing(
+ base::TimeDelta::FromSeconds(2));
+ runtime_api->AllowNonKioskAppsInRestartAfterDelayForTesting();
+
+ RuntimeAPI::RegisterPrefs(
+ test_browser_client_->testing_pref_service()->registry());
+ }
+
+ base::TimeTicks WaitForSuccessfulRestart() {
+ return test_browser_client_->api_delegate()->WaitForSuccessfulRestart();
+ }
+
+ bool IsDelayedRestartTimerRunning() {
+ return RuntimeAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->restart_after_delay_timer_.IsRunning();
+ }
+
+ base::TimeTicks desired_restart_time() {
+ return RuntimeAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->restart_after_delay_timer_.desired_run_time();
+ }
+
+ void RunRestartAfterDelayFunction(const std::string& args,
+ const std::string& expected_error) {
+ RunRestartAfterDelayFunctionForExtention(args, extension(), expected_error);
+ }
+
+ void RunRestartAfterDelayFunctionForExtention(
+ const std::string& args,
+ const Extension* extension,
+ const std::string& expected_error) {
+ std::string error = RunFunctionGetError(
+ new RuntimeRestartAfterDelayFunction(), extension, args);
+ ASSERT_EQ(error, expected_error);
+ }
+
+ void RunRestartFunctionAssertNoError() {
+ std::string error =
+ RunFunctionGetError(new RuntimeRestartFunction(), extension(), "[]");
+ ASSERT_TRUE(error.empty()) << error;
+ }
+
+ private:
+ std::string RunFunctionGetError(UIThreadExtensionFunction* function,
+ const Extension* extension,
+ const std::string& args) {
+ scoped_refptr<ExtensionFunction> function_owner(function);
+ function->set_extension(extension);
+ function->set_has_callback(true);
+ api_test_utils::RunFunction(function, args, browser_context());
+ return function->GetError();
+ }
+
+ std::unique_ptr<DelayedRestartExtensionsBrowserClient> test_browser_client_;
+
+ DISALLOW_COPY_AND_ASSIGN(RestartAfterDelayApiTest);
+};
+
+TEST_F(RestartAfterDelayApiTest, RestartAfterDelayTest) {
+ RunRestartAfterDelayFunction("[-1]", "");
+ ASSERT_FALSE(IsDelayedRestartTimerRunning());
+
+ RunRestartAfterDelayFunction("[-2]", "Invalid argument: -2.");
+
+ // Request a restart after 3 seconds.
+ base::TimeTicks now = base::TimeTicks::Now();
+ RunRestartAfterDelayFunction("[3]", "");
+ ASSERT_TRUE(IsDelayedRestartTimerRunning());
+ ASSERT_GE(desired_restart_time() - now, base::TimeDelta::FromSeconds(3));
+
+ // Request another restart after 4 seconds. It should reschedule the previous
+ // request.
+ now = base::TimeTicks::Now();
+ RunRestartAfterDelayFunction("[4]", "");
+ ASSERT_TRUE(IsDelayedRestartTimerRunning());
+ ASSERT_GE(desired_restart_time() - now, base::TimeDelta::FromSeconds(4));
+
+ // Create another extension and make it attempt to use the api, and expect a
+ // failure.
+ std::unique_ptr<base::DictionaryValue> test_extension_value(
+ api_test_utils::ParseDictionary("{\n"
+ " \"name\": \"Test\",\n"
+ " \"version\": \"2.0\",\n"
+ " \"app\": {\n"
+ " \"background\": {\n"
+ " \"scripts\": [\"background.js\"]\n"
+ " }\n"
+ " }\n"
+ "}"));
+ scoped_refptr<Extension> test_extension(api_test_utils::CreateExtension(
+ Manifest::INTERNAL, test_extension_value.get(), "id2"));
+ RunRestartAfterDelayFunctionForExtention(
+ "[5]", test_extension.get(), "Not the first extension to call this API.");
+
+ // Cancel restart requests.
+ RunRestartAfterDelayFunction("[-1]", "");
+ ASSERT_FALSE(IsDelayedRestartTimerRunning());
+
+ // Schedule a restart and wait for it to happen.
+ now = base::TimeTicks::Now();
+ RunRestartAfterDelayFunction("[1]", "");
+ ASSERT_TRUE(IsDelayedRestartTimerRunning());
+ ASSERT_GE(desired_restart_time() - now, base::TimeDelta::FromSeconds(1));
+ base::TimeTicks last_restart_time = WaitForSuccessfulRestart();
+ ASSERT_FALSE(IsDelayedRestartTimerRunning());
+ ASSERT_GE(base::TimeTicks::Now() - now, base::TimeDelta::FromSeconds(1));
+
+ // This is a restart request that will be throttled, because it happens too
+ // soon after a successful restart.
+ RunRestartAfterDelayFunction(
+ "[1]", "Restart was requested too soon. It was throttled instead.");
+ ASSERT_TRUE(IsDelayedRestartTimerRunning());
+ // Restart will happen 2 seconds later, even though the request was just one
+ // second.
+ ASSERT_NEAR((desired_restart_time() - last_restart_time).InSecondsF(),
+ base::TimeDelta::FromSeconds(2).InSecondsF(), 0.01);
+
+ // Calling chrome.runtime.restart() will not clear the throttle, and any
+ // subsequent calls to chrome.runtime.restartAfterDelay will still be
+ // throttled.
+ WaitForSuccessfulRestart();
+ RunRestartFunctionAssertNoError();
+ last_restart_time = WaitForSuccessfulRestart();
+ RunRestartAfterDelayFunction(
+ "[1]", "Restart was requested too soon. It was throttled instead.");
+ ASSERT_TRUE(IsDelayedRestartTimerRunning());
+ // Restart will happen 2 seconds later, even though the request was just one
+ // second.
+ ASSERT_NEAR((desired_restart_time() - last_restart_time).InSecondsF(),
+ base::TimeDelta::FromSeconds(2).InSecondsF(), 0.01);
+}
+
+} // namespace extensions
« no previous file with comments | « chrome/browser/prefs/browser_prefs.cc ('k') | extensions/browser/api/runtime/runtime_api.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698