| Index: chrome/browser/chromeos/power/extension_event_observer_unittest.cc
|
| diff --git a/chrome/browser/chromeos/power/extension_event_observer_unittest.cc b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..acc30b7140c56a5470c3ac9393436ef195c58c74
|
| --- /dev/null
|
| +++ b/chrome/browser/chromeos/power/extension_event_observer_unittest.cc
|
| @@ -0,0 +1,319 @@
|
| +// Copyright 2015 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 "chrome/browser/chromeos/power/extension_event_observer.h"
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/macros.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/run_loop.h"
|
| +#include "chrome/browser/chromeos/login/users/fake_user_manager.h"
|
| +#include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
|
| +#include "chrome/browser/chromeos/settings/cros_settings.h"
|
| +#include "chrome/browser/chromeos/settings/device_settings_service.h"
|
| +#include "chrome/common/extensions/api/gcm.h"
|
| +#include "chrome/test/base/testing_browser_process.h"
|
| +#include "chrome/test/base/testing_profile.h"
|
| +#include "chrome/test/base/testing_profile_manager.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| +#include "chromeos/dbus/fake_power_manager_client.h"
|
| +#include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "content/public/test/test_renderer_host.h"
|
| +#include "extensions/browser/extension_host.h"
|
| +#include "extensions/browser/process_manager.h"
|
| +#include "extensions/common/extension.h"
|
| +#include "extensions/common/extension_builder.h"
|
| +#include "extensions/common/manifest_handlers/background_info.h"
|
| +#include "extensions/common/value_builder.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace chromeos {
|
| +
|
| +class ExtensionEventObserverTest : public ::testing::Test {
|
| + public:
|
| + ExtensionEventObserverTest()
|
| + : power_manager_client_(new FakePowerManagerClient()),
|
| + fake_user_manager_(new FakeUserManager()),
|
| + scoped_user_manager_enabler_(fake_user_manager_) {
|
| + DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient(
|
| + make_scoped_ptr(power_manager_client_));
|
| +
|
| + profile_manager_.reset(
|
| + new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
|
| +
|
| + extension_event_observer_.reset(new ExtensionEventObserver());
|
| + test_api_ = extension_event_observer_->CreateTestApi();
|
| + }
|
| +
|
| + ~ExtensionEventObserverTest() override {
|
| + extension_event_observer_.reset();
|
| + profile_manager_.reset();
|
| + DBusThreadManager::Shutdown();
|
| + }
|
| +
|
| + // ::testing::Test overrides.
|
| + void SetUp() override {
|
| + ::testing::Test::SetUp();
|
| +
|
| + // Must be called from ::testing::Test::SetUp.
|
| + ASSERT_TRUE(profile_manager_->SetUp());
|
| +
|
| + const char kUserProfile[] = "profile1@example.com";
|
| + fake_user_manager_->AddUser(kUserProfile);
|
| + fake_user_manager_->LoginUser(kUserProfile);
|
| + profile_ = profile_manager_->CreateTestingProfile(kUserProfile);
|
| +
|
| + profile_manager_->SetLoggedIn(true);
|
| + }
|
| + void TearDown() override {
|
| + profile_ = NULL;
|
| + profile_manager_->DeleteAllTestingProfiles();
|
| +
|
| + ::testing::Test::TearDown();
|
| + }
|
| +
|
| + protected:
|
| + scoped_refptr<extensions::Extension> CreateApp(const std::string& name,
|
| + bool uses_gcm) {
|
| + scoped_refptr<extensions::Extension> app =
|
| + extensions::ExtensionBuilder()
|
| + .SetManifest(
|
| + extensions::DictionaryBuilder()
|
| + .Set("name", name)
|
| + .Set("version", "1.0.0")
|
| + .Set("manifest_version", 2)
|
| + .Set("app",
|
| + extensions::DictionaryBuilder().Set(
|
| + "background",
|
| + extensions::DictionaryBuilder().Set(
|
| + "scripts", extensions::ListBuilder().Append(
|
| + "background.js"))))
|
| + .Set("permissions", extensions::ListBuilder().Append(
|
| + uses_gcm ? "gcm" : "")))
|
| + .Build();
|
| +
|
| + created_apps_.push_back(app);
|
| +
|
| + return app;
|
| + }
|
| +
|
| + extensions::ExtensionHost* CreateHostForApp(Profile* profile,
|
| + extensions::Extension* app) {
|
| + extensions::ProcessManager::Get(profile)->CreateBackgroundHost(
|
| + app, extensions::BackgroundInfo::GetBackgroundURL(app));
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + return extensions::ProcessManager::Get(profile)
|
| + ->GetBackgroundHostForExtension(app->id());
|
| + }
|
| +
|
| + // Owned by DBusThreadManager.
|
| + FakePowerManagerClient* power_manager_client_;
|
| +
|
| + scoped_ptr<ExtensionEventObserver> extension_event_observer_;
|
| + scoped_ptr<ExtensionEventObserver::TestApi> test_api_;
|
| +
|
| + // Owned by |profile_manager_|.
|
| + TestingProfile* profile_;
|
| + scoped_ptr<TestingProfileManager> profile_manager_;
|
| +
|
| + private:
|
| + content::TestBrowserThreadBundle browser_thread_bundle_;
|
| +
|
| + // Needed to ensure we don't end up creating actual RenderViewHosts
|
| + // and RenderProcessHosts.
|
| + content::RenderViewHostTestEnabler render_view_host_test_enabler_;
|
| +
|
| + // Chrome OS needs extra services to run in the following order.
|
| + ScopedTestDeviceSettingsService test_device_settings_service_;
|
| + ScopedTestCrosSettings test_cros_settings_;
|
| +
|
| + // Owned by |scoped_user_manager_enabler_|.
|
| + FakeUserManager* fake_user_manager_;
|
| + ScopedUserManagerEnabler scoped_user_manager_enabler_;
|
| +
|
| + std::vector<scoped_refptr<extensions::Extension>> created_apps_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ExtensionEventObserverTest);
|
| +};
|
| +
|
| +// Tests that the ExtensionEventObserver reports readiness for suspend when
|
| +// there is nothing interesting going on.
|
| +TEST_F(ExtensionEventObserverTest, BasicSuspendAndDarkSuspend) {
|
| + power_manager_client_->SendSuspendImminent();
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + power_manager_client_->SendDarkSuspendImminent();
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +}
|
| +
|
| +// Tests that the ExtensionEventObserver properly handles a canceled suspend
|
| +// attempt.
|
| +TEST_F(ExtensionEventObserverTest, CanceledSuspend) {
|
| + power_manager_client_->SendSuspendImminent();
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + power_manager_client_->SendSuspendDone();
|
| + EXPECT_FALSE(test_api_->MaybeRunSuspendReadinessCallback());
|
| +}
|
| +
|
| +// Tests that the ExtensionEventObserver delays suspends and dark suspends while
|
| +// there is a push message pending for an app that uses GCM.
|
| +TEST_F(ExtensionEventObserverTest, PushMessagesDelaySuspend) {
|
| + scoped_refptr<extensions::Extension> gcm_app =
|
| + CreateApp("DelaysSuspendForPushMessages", true /* uses_gcm */);
|
| + extensions::ExtensionHost* host = CreateHostForApp(profile_, gcm_app.get());
|
| + ASSERT_TRUE(host);
|
| + EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host));
|
| +
|
| + // Test that a push message received before a suspend attempt delays the
|
| + // attempt.
|
| + const int kSuspendPushId = 23874;
|
| + extension_event_observer_->OnExtensionMessageDispatched(
|
| + host, extensions::api::gcm::OnMessage::kEventName, kSuspendPushId);
|
| + power_manager_client_->SendSuspendImminent();
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + extension_event_observer_->OnExtensionMessageAcked(host, kSuspendPushId);
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + // Now test receiving the suspend attempt before the push message.
|
| + const int kDarkSuspendPushId = 56674;
|
| + power_manager_client_->SendDarkSuspendImminent();
|
| + extension_event_observer_->OnExtensionMessageDispatched(
|
| + host, extensions::api::gcm::OnMessage::kEventName, kDarkSuspendPushId);
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + extension_event_observer_->OnExtensionMessageAcked(host, kDarkSuspendPushId);
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + // Test that non-push messages do not delay the suspend.
|
| + const int kNonPushId = 5687;
|
| + power_manager_client_->SendDarkSuspendImminent();
|
| + extension_event_observer_->OnExtensionMessageDispatched(host, "FakeMessage",
|
| + kNonPushId);
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +}
|
| +
|
| +// Tests that messages sent for apps that don't use GCM are ignored.
|
| +TEST_F(ExtensionEventObserverTest, IgnoresNonGCMApps) {
|
| + scoped_refptr<extensions::Extension> app = CreateApp("Non-GCM", false);
|
| + extensions::ExtensionHost* host = CreateHostForApp(profile_, app.get());
|
| + ASSERT_TRUE(host);
|
| +
|
| + EXPECT_FALSE(test_api_->WillDelaySuspendForExtensionHost(host));
|
| +
|
| + power_manager_client_->SendSuspendImminent();
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +}
|
| +
|
| +// Tests that network requests started by an app while it is processing a push
|
| +// message delay any suspend attempt.
|
| +TEST_F(ExtensionEventObserverTest, NetworkRequestsMayDelaySuspend) {
|
| + scoped_refptr<extensions::Extension> app = CreateApp("NetworkRequests", true);
|
| + extensions::ExtensionHost* host = CreateHostForApp(profile_, app.get());
|
| + ASSERT_TRUE(host);
|
| + EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host));
|
| +
|
| + // Test that network requests started while there is no pending push message
|
| + // are ignored.
|
| + const uint64 kNonPushRequestId = 5170725;
|
| + extension_event_observer_->OnNetworkRequestStarted(host, kNonPushRequestId);
|
| + power_manager_client_->SendSuspendImminent();
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + // Test that network requests started while a push message is pending delay
|
| + // the suspend even after the push message has been acked.
|
| + const int kPushMessageId = 178674;
|
| + const uint64 kNetworkRequestId = 78917089;
|
| + power_manager_client_->SendDarkSuspendImminent();
|
| + extension_event_observer_->OnExtensionMessageDispatched(
|
| + host, extensions::api::gcm::OnMessage::kEventName, kPushMessageId);
|
| +
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + extension_event_observer_->OnNetworkRequestStarted(host, kNetworkRequestId);
|
| + extension_event_observer_->OnExtensionMessageAcked(host, kPushMessageId);
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + extension_event_observer_->OnNetworkRequestDone(host, kNetworkRequestId);
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +}
|
| +
|
| +// Tests that any outstanding push messages or network requests for an
|
| +// ExtensionHost that is destroyed do not end up blocking system suspend.
|
| +TEST_F(ExtensionEventObserverTest, DeletedExtensionHostDoesNotBlockSuspend) {
|
| + scoped_refptr<extensions::Extension> app =
|
| + CreateApp("DeletedExtensionHost", true);
|
| +
|
| + // The easiest way to delete an extension host is to delete the Profile it is
|
| + // associated with so we create a new Profile here.
|
| + const char kProfileName[] = "DeletedExtensionHostProfile";
|
| + Profile* new_profile = profile_manager_->CreateTestingProfile(kProfileName);
|
| +
|
| + extensions::ExtensionHost* host = CreateHostForApp(new_profile, app.get());
|
| + ASSERT_TRUE(host);
|
| + EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host));
|
| +
|
| + const int kPushId = 156178;
|
| + const uint64 kNetworkId = 791605;
|
| + extension_event_observer_->OnExtensionMessageDispatched(
|
| + host, extensions::api::gcm::OnMessage::kEventName, kPushId);
|
| + extension_event_observer_->OnNetworkRequestStarted(host, kNetworkId);
|
| +
|
| + // Now delete the Profile. This has the side-effect of also deleting all the
|
| + // ExtensionHosts.
|
| + profile_manager_->DeleteTestingProfile(kProfileName);
|
| +
|
| + power_manager_client_->SendSuspendImminent();
|
| + EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +}
|
| +
|
| +// Tests that the ExtensionEventObserver does not delay suspend attempts when it
|
| +// is disabled.
|
| +TEST_F(ExtensionEventObserverTest, DoesNotDelaySuspendWhenDisabled) {
|
| + scoped_refptr<extensions::Extension> app =
|
| + CreateApp("NoDelayWhenDisabled", true);
|
| + extensions::ExtensionHost* host = CreateHostForApp(profile_, app.get());
|
| + ASSERT_TRUE(host);
|
| + EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host));
|
| +
|
| + // Test that disabling the suspend delay while a suspend is pending will cause
|
| + // the ExtensionEventObserver to immediately report readiness.
|
| + const int kPushId = 416753;
|
| + extension_event_observer_->OnExtensionMessageDispatched(
|
| + host, extensions::api::gcm::OnMessage::kEventName, kPushId);
|
| + power_manager_client_->SendSuspendImminent();
|
| + EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + extension_event_observer_->SetShouldDelaySuspend(false);
|
| + EXPECT_FALSE(test_api_->MaybeRunSuspendReadinessCallback());
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +
|
| + // Test that the ExtensionEventObserver does not delay suspend attempts when
|
| + // it is disabled.
|
| + power_manager_client_->SendDarkSuspendImminent();
|
| + EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| +}
|
| +
|
| +} // namespace chromeos
|
|
|