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

Unified Diff: chrome/browser/chromeos/power/extension_event_observer_unittest.cc

Issue 823703004: Tracking push events for lucid sleep (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Kill renderer if it sends a bad message id Created 5 years, 11 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
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

Powered by Google App Engine
This is Rietveld 408576698