| Index: chrome/browser/chromeos/power/renderer_freezer_unittest.cc
|
| diff --git a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
|
| index ec809caa930fbfd7946148b9707d530a67a181a2..557768b6eadf89d6d1e3a621cea3f34c5601d7d9 100644
|
| --- a/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
|
| +++ b/chrome/browser/chromeos/power/renderer_freezer_unittest.cc
|
| @@ -6,10 +6,33 @@
|
|
|
| #include <string>
|
|
|
| +#include "base/command_line.h"
|
| +#include "base/memory/ref_counted.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/scoped_test_user_manager.h"
|
| +#include "chrome/browser/chromeos/settings/cros_settings.h"
|
| +#include "chrome/browser/chromeos/settings/device_settings_service.h"
|
| +#include "chrome/browser/extensions/extension_service.h"
|
| +#include "chrome/browser/extensions/test_extension_system.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/browser/notification_service.h"
|
| +#include "content/public/browser/notification_source.h"
|
| +#include "content/public/browser/notification_types.h"
|
| +#include "content/public/browser/site_instance.h"
|
| +#include "content/public/test/mock_render_process_host.h"
|
| +#include "content/public/test/test_browser_thread_bundle.h"
|
| +#include "extensions/browser/notification_types.h"
|
| +#include "extensions/browser/process_manager.h"
|
| +#include "extensions/browser/process_map.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-death-test.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| @@ -49,6 +72,8 @@ class ActionRecorder {
|
| };
|
|
|
| // Actions that can be returned by TestDelegate::GetActions().
|
| +const char kSetShouldFreezeRenderer[] = "set_should_freeze_renderer";
|
| +const char kSetShouldNotFreezeRenderer[] = "set_should_not_freeze_renderer";
|
| const char kFreezeRenderers[] = "freeze_renderers";
|
| const char kThawRenderers[] = "thaw_renderers";
|
| const char kNoActions[] = "";
|
| @@ -62,20 +87,25 @@ class TestDelegate : public RendererFreezer::Delegate, public ActionRecorder {
|
| freeze_renderers_result_(true),
|
| thaw_renderers_result_(true) {}
|
|
|
| - virtual ~TestDelegate() {}
|
| + ~TestDelegate() override {}
|
|
|
| // RendererFreezer::Delegate overrides.
|
| - virtual bool FreezeRenderers() override {
|
| + void SetShouldFreezeRenderer(base::ProcessHandle handle,
|
| + bool frozen) override {
|
| + AppendAction(frozen ? kSetShouldFreezeRenderer
|
| + : kSetShouldNotFreezeRenderer);
|
| + }
|
| + bool FreezeRenderers() override {
|
| AppendAction(kFreezeRenderers);
|
|
|
| return freeze_renderers_result_;
|
| }
|
| - virtual bool ThawRenderers() override {
|
| + bool ThawRenderers() override {
|
| AppendAction(kThawRenderers);
|
|
|
| return thaw_renderers_result_;
|
| }
|
| - virtual bool CanFreezeRenderers() override { return can_freeze_renderers_; }
|
| + bool CanFreezeRenderers() override { return can_freeze_renderers_; }
|
|
|
| void set_freeze_renderers_result(bool result) {
|
| freeze_renderers_result_ = result;
|
| @@ -115,25 +145,28 @@ class RendererFreezerTest : public testing::Test {
|
| scoped_ptr<PowerManagerClient>(power_manager_client_));
|
| }
|
|
|
| - virtual ~RendererFreezerTest() {
|
| + ~RendererFreezerTest() override {
|
| renderer_freezer_.reset();
|
|
|
| DBusThreadManager::Shutdown();
|
| }
|
|
|
| + protected:
|
| void Init() {
|
| renderer_freezer_.reset(new RendererFreezer(
|
| scoped_ptr<RendererFreezer::Delegate>(test_delegate_)));
|
| }
|
|
|
| - protected:
|
| + // Owned by DBusThreadManager.
|
| FakePowerManagerClient* power_manager_client_;
|
| - TestDelegate* test_delegate_;
|
|
|
| + // Owned by |renderer_freezer_|.
|
| + TestDelegate* test_delegate_;
|
| scoped_ptr<RendererFreezer> renderer_freezer_;
|
|
|
| private:
|
| - base::MessageLoop message_loop_;
|
| + content::TestBrowserThreadBundle browser_thread_bundle_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(RendererFreezerTest);
|
| };
|
|
|
| @@ -143,16 +176,6 @@ TEST_F(RendererFreezerTest, SuspendResume) {
|
| Init();
|
|
|
| power_manager_client_->SendSuspendImminent();
|
| -
|
| - // The RendererFreezer should have grabbed an asynchronous callback and done
|
| - // nothing else.
|
| - EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| - EXPECT_EQ(kNoActions, test_delegate_->GetActions());
|
| -
|
| - // The RendererFreezer should eventually freeze the renderers and run the
|
| - // callback.
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
|
|
|
| // The renderers should be thawed when we resume.
|
| @@ -160,38 +183,14 @@ TEST_F(RendererFreezerTest, SuspendResume) {
|
| EXPECT_EQ(kThawRenderers, test_delegate_->GetActions());
|
| }
|
|
|
| -// Tests that the RendereFreezer doesn't freeze renderers if the suspend attempt
|
| -// was canceled before it had a chance to complete.
|
| -TEST_F(RendererFreezerTest, SuspendCanceled) {
|
| - Init();
|
| -
|
| - // We shouldn't do anything yet.
|
| - power_manager_client_->SendSuspendImminent();
|
| - EXPECT_EQ(kNoActions, test_delegate_->GetActions());
|
| -
|
| - // If a suspend gets canceled for any reason, we should see a SuspendDone().
|
| - power_manager_client_->SendSuspendDone();
|
| -
|
| - // We shouldn't try to freeze the renderers now.
|
| - base::RunLoop().RunUntilIdle();
|
| - EXPECT_EQ(kNoActions, test_delegate_->GetActions());
|
| -}
|
| -
|
| // Tests that the renderer freezer does nothing if the delegate cannot freeze
|
| // renderers.
|
| TEST_F(RendererFreezerTest, DelegateCannotFreezeRenderers) {
|
| test_delegate_->set_can_freeze_renderers(false);
|
| Init();
|
|
|
| + // Nothing happens on suspend.
|
| power_manager_client_->SendSuspendImminent();
|
| -
|
| - // The RendererFreezer should not have grabbed a callback or done anything
|
| - // else.
|
| - EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| - EXPECT_EQ(kNoActions, test_delegate_->GetActions());
|
| -
|
| - // There should be nothing in the message loop.
|
| - base::RunLoop().RunUntilIdle();
|
| EXPECT_EQ(kNoActions, test_delegate_->GetActions());
|
|
|
| // Nothing happens on resume.
|
| @@ -205,13 +204,9 @@ TEST_F(RendererFreezerTest, ErrorFreezingRenderers) {
|
| Init();
|
| test_delegate_->set_freeze_renderers_result(false);
|
|
|
| + // The freezing operation will fail.
|
| power_manager_client_->SendSuspendImminent();
|
| - EXPECT_EQ(1, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
| -
|
| - // The freezing operation should fail, but we should still report readiness.
|
| - base::RunLoop().RunUntilIdle();
|
| EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
|
| - EXPECT_EQ(0, power_manager_client_->GetNumPendingSuspendReadinessCallbacks());
|
|
|
| // Since the delegate reported that the freezing was unsuccessful, don't do
|
| // anything on resume.
|
| @@ -223,15 +218,176 @@ TEST_F(RendererFreezerTest, ErrorFreezingRenderers) {
|
| // Tests that the RendererFreezer crashes the browser if the freezing operation
|
| // was successful but the thawing operation failed.
|
| TEST_F(RendererFreezerTest, ErrorThawingRenderers) {
|
| + // The "threadsafe" style of death test re-executes the unit test binary,
|
| + // which in turn re-initializes some global state leading to failed CHECKs.
|
| + // Instead, we use the "fast" style here to prevent re-initialization.
|
| + ::testing::FLAGS_gtest_death_test_style = "fast";
|
| Init();
|
| test_delegate_->set_thaw_renderers_result(false);
|
|
|
| power_manager_client_->SendSuspendImminent();
|
| - base::RunLoop().RunUntilIdle();
|
| EXPECT_EQ(kFreezeRenderers, test_delegate_->GetActions());
|
|
|
| EXPECT_DEATH(power_manager_client_->SendSuspendDone(), "Unable to thaw");
|
| }
|
| #endif // GTEST_HAS_DEATH_TEST
|
|
|
| +class RendererFreezerTestWithExtensions : public RendererFreezerTest {
|
| + public:
|
| + RendererFreezerTestWithExtensions() {}
|
| + ~RendererFreezerTestWithExtensions() override {}
|
| +
|
| + // testing::Test overrides.
|
| + void SetUp() override {
|
| + RendererFreezerTest::SetUp();
|
| +
|
| + profile_manager_.reset(
|
| + new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
|
| +
|
| + // Must be called from testing::Test::SetUp.
|
| + EXPECT_TRUE(profile_manager_->SetUp());
|
| +
|
| + profile_ = profile_manager_->CreateTestingProfile("RendererFreezerTest");
|
| +
|
| + extensions::TestExtensionSystem* extension_system =
|
| + static_cast<extensions::TestExtensionSystem*>(
|
| + extensions::ExtensionSystem::Get(profile_));
|
| + extension_system->CreateExtensionService(
|
| + base::CommandLine::ForCurrentProcess(),
|
| + base::FilePath() /* install_directory */,
|
| + false /* autoupdate_enabled*/);
|
| + }
|
| + void TearDown() override {
|
| + extensions::ExtensionSystem::Get(profile_)->Shutdown();
|
| +
|
| + profile_ = NULL;
|
| +
|
| + profile_manager_->DeleteAllTestingProfiles();
|
| +
|
| + base::RunLoop().RunUntilIdle();
|
| +
|
| + profile_manager_.reset();
|
| +
|
| + RendererFreezerTest::TearDown();
|
| + }
|
| +
|
| + protected:
|
| + void CreateRenderProcessForExtension(extensions::Extension* extension) {
|
| + scoped_ptr<content::MockRenderProcessHostFactory> rph_factory(
|
| + new content::MockRenderProcessHostFactory());
|
| + scoped_refptr<content::SiteInstance> site_instance(
|
| + extensions::ProcessManager::Get(profile_)->GetSiteInstanceForURL(
|
| + extensions::BackgroundInfo::GetBackgroundURL(extension)));
|
| + scoped_ptr<content::RenderProcessHost> rph(
|
| + rph_factory->CreateRenderProcessHost(profile_, site_instance.get()));
|
| +
|
| + // Fake that the RenderProcessHost is hosting the gcm app.
|
| + extensions::ProcessMap::Get(profile_)
|
| + ->Insert(extension->id(), rph->GetID(), site_instance->GetId());
|
| +
|
| + // Send the notification that the RenderProcessHost has been created.
|
| + content::NotificationService::current()->Notify(
|
| + content::NOTIFICATION_RENDERER_PROCESS_CREATED,
|
| + content::Source<content::RenderProcessHost>(rph.get()),
|
| + content::NotificationService::NoDetails());
|
| + }
|
| +
|
| + // Owned by |profile_manager_|.
|
| + TestingProfile* profile_;
|
| + scoped_ptr<TestingProfileManager> profile_manager_;
|
| +
|
| + private:
|
| + // Chrome OS needs extra services to run in the following order.
|
| + chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
|
| + chromeos::ScopedTestCrosSettings test_cros_settings_;
|
| + chromeos::ScopedTestUserManager test_user_manager_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(RendererFreezerTestWithExtensions);
|
| +};
|
| +
|
| +// Tests that the RendererFreezer freezes renderers that are not hosting
|
| +// GCM extensions.
|
| +TEST_F(RendererFreezerTestWithExtensions, FreezesNonExtensionRenderers) {
|
| + Init();
|
| +
|
| + // Create the mock RenderProcessHost.
|
| + scoped_ptr<content::MockRenderProcessHostFactory> rph_factory(
|
| + new content::MockRenderProcessHostFactory());
|
| + scoped_refptr<content::SiteInstance> site_instance(
|
| + content::SiteInstance::Create(profile_));
|
| + scoped_ptr<content::RenderProcessHost> rph(
|
| + rph_factory->CreateRenderProcessHost(profile_, site_instance.get()));
|
| +
|
| + // Send the notification that the RenderProcessHost has been created.
|
| + content::NotificationService::current()->Notify(
|
| + content::NOTIFICATION_RENDERER_PROCESS_CREATED,
|
| + content::Source<content::RenderProcessHost>(rph.get()),
|
| + content::NotificationService::NoDetails());
|
| +
|
| + EXPECT_EQ(kSetShouldFreezeRenderer, test_delegate_->GetActions());
|
| +}
|
| +
|
| +// Tests that the RendererFreezer does not freeze renderers that are hosting
|
| +// extensions that use GCM.
|
| +TEST_F(RendererFreezerTestWithExtensions, DoesNotFreezeGcmExtensionRenderers) {
|
| + Init();
|
| +
|
| + // First build the GCM extension.
|
| + scoped_refptr<extensions::Extension> gcm_app =
|
| + extensions::ExtensionBuilder()
|
| + .SetManifest(extensions::DictionaryBuilder()
|
| + .Set("name", "GCM App")
|
| + .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("gcm")))
|
| + .Build();
|
| +
|
| + // Now install it and give it a renderer.
|
| + extensions::ExtensionSystem::Get(profile_)
|
| + ->extension_service()
|
| + ->AddExtension(gcm_app.get());
|
| + CreateRenderProcessForExtension(gcm_app.get());
|
| +
|
| + EXPECT_EQ(kSetShouldNotFreezeRenderer, test_delegate_->GetActions());
|
| +}
|
| +
|
| +// Tests that the RendererFreezer freezes renderers that are hosting extensions
|
| +// that do not use GCM.
|
| +TEST_F(RendererFreezerTestWithExtensions, FreezesNonGcmExtensionRenderers) {
|
| + Init();
|
| +
|
| + // First build the extension.
|
| + scoped_refptr<extensions::Extension> background_app =
|
| + extensions::ExtensionBuilder()
|
| + .SetManifest(extensions::DictionaryBuilder()
|
| + .Set("name", "Background App")
|
| + .Set("version", "1.0.0")
|
| + .Set("manifest_version", 2)
|
| + .Set("app",
|
| + extensions::DictionaryBuilder()
|
| + .Set("background",
|
| + extensions::DictionaryBuilder()
|
| + .Set("scripts",
|
| + extensions::ListBuilder()
|
| + .Append("background.js")))))
|
| + .Build();
|
| +
|
| + // Now install it and give it a renderer.
|
| + extensions::ExtensionSystem::Get(profile_)
|
| + ->extension_service()
|
| + ->AddExtension(background_app.get());
|
| + CreateRenderProcessForExtension(background_app.get());
|
| +
|
| + EXPECT_EQ(kSetShouldFreezeRenderer, test_delegate_->GetActions());
|
| +}
|
| +
|
| } // namespace chromeos
|
|
|