1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/power/extension_event_observer.h"
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
14 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
15 #include "chrome/browser/chromeos/settings/cros_settings.h"
16 #include "chrome/browser/chromeos/settings/device_settings_service.h"
17 #include "chrome/common/extensions/api/gcm.h"
18 #include "chrome/test/base/testing_browser_process.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "chrome/test/base/testing_profile_manager.h"
21 #include "chromeos/dbus/dbus_thread_manager.h"
22 #include "chromeos/dbus/fake_power_manager_client.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/public/test/test_renderer_host.h"
25 #include "extensions/browser/extension_host.h"
26 #include "extensions/browser/process_manager.h"
27 #include "extensions/common/extension.h"
28 #include "extensions/common/extension_builder.h"
29 #include "extensions/common/manifest_handlers/background_info.h"
30 #include "extensions/common/value_builder.h"
31 #include "testing/gtest/include/gtest/gtest.h"
35 class ExtensionEventObserverTest
: public ::testing::Test
{
37 ExtensionEventObserverTest()
38 : power_manager_client_(new FakePowerManagerClient()),
39 fake_user_manager_(new FakeChromeUserManager()),
40 scoped_user_manager_enabler_(fake_user_manager_
) {
41 DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient(
42 make_scoped_ptr(power_manager_client_
));
44 profile_manager_
.reset(
45 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
47 extension_event_observer_
.reset(new ExtensionEventObserver());
48 test_api_
= extension_event_observer_
->CreateTestApi();
51 ~ExtensionEventObserverTest() override
{
52 extension_event_observer_
.reset();
53 profile_manager_
.reset();
54 DBusThreadManager::Shutdown();
57 // ::testing::Test overrides.
58 void SetUp() override
{
59 ::testing::Test::SetUp();
61 // Must be called from ::testing::Test::SetUp.
62 ASSERT_TRUE(profile_manager_
->SetUp());
64 const char kUserProfile
[] = "profile1@example.com";
65 fake_user_manager_
->AddUser(kUserProfile
);
66 fake_user_manager_
->LoginUser(kUserProfile
);
67 profile_
= profile_manager_
->CreateTestingProfile(kUserProfile
);
69 profile_manager_
->SetLoggedIn(true);
71 void TearDown() override
{
73 profile_manager_
->DeleteAllTestingProfiles();
75 ::testing::Test::TearDown();
79 scoped_refptr
<extensions::Extension
> CreateApp(const std::string
& name
,
81 scoped_refptr
<extensions::Extension
> app
=
82 extensions::ExtensionBuilder()
84 extensions::DictionaryBuilder()
86 .Set("version", "1.0.0")
87 .Set("manifest_version", 2)
89 extensions::DictionaryBuilder().Set(
91 extensions::DictionaryBuilder().Set(
92 "scripts", extensions::ListBuilder().Append(
94 .Set("permissions", extensions::ListBuilder().Append(
95 uses_gcm
? "gcm" : "")))
98 created_apps_
.push_back(app
);
103 extensions::ExtensionHost
* CreateHostForApp(Profile
* profile
,
104 extensions::Extension
* app
) {
105 extensions::ProcessManager::Get(profile
)->CreateBackgroundHost(
106 app
, extensions::BackgroundInfo::GetBackgroundURL(app
));
107 base::RunLoop().RunUntilIdle();
109 return extensions::ProcessManager::Get(profile
)
110 ->GetBackgroundHostForExtension(app
->id());
113 // Owned by DBusThreadManager.
114 FakePowerManagerClient
* power_manager_client_
;
116 scoped_ptr
<ExtensionEventObserver
> extension_event_observer_
;
117 scoped_ptr
<ExtensionEventObserver::TestApi
> test_api_
;
119 // Owned by |profile_manager_|.
120 TestingProfile
* profile_
;
121 scoped_ptr
<TestingProfileManager
> profile_manager_
;
124 content::TestBrowserThreadBundle browser_thread_bundle_
;
126 // Needed to ensure we don't end up creating actual RenderViewHosts
127 // and RenderProcessHosts.
128 content::RenderViewHostTestEnabler render_view_host_test_enabler_
;
130 // Chrome OS needs extra services to run in the following order.
131 ScopedTestDeviceSettingsService test_device_settings_service_
;
132 ScopedTestCrosSettings test_cros_settings_
;
134 // Owned by |scoped_user_manager_enabler_|.
135 FakeChromeUserManager
* fake_user_manager_
;
136 ScopedUserManagerEnabler scoped_user_manager_enabler_
;
138 std::vector
<scoped_refptr
<extensions::Extension
>> created_apps_
;
140 DISALLOW_COPY_AND_ASSIGN(ExtensionEventObserverTest
);
143 // Tests that the ExtensionEventObserver reports readiness for suspend when
144 // there is nothing interesting going on.
145 TEST_F(ExtensionEventObserverTest
, BasicSuspendAndDarkSuspend
) {
146 power_manager_client_
->SendSuspendImminent();
147 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
149 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
150 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
152 power_manager_client_
->SendDarkSuspendImminent();
153 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
155 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
156 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
159 // Tests that the ExtensionEventObserver properly handles a canceled suspend
161 TEST_F(ExtensionEventObserverTest
, CanceledSuspend
) {
162 power_manager_client_
->SendSuspendImminent();
163 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
165 power_manager_client_
->SendSuspendDone();
166 EXPECT_FALSE(test_api_
->MaybeRunSuspendReadinessCallback());
169 // Tests that the ExtensionEventObserver delays suspends and dark suspends while
170 // there is a push message pending for an app that uses GCM.
171 TEST_F(ExtensionEventObserverTest
, PushMessagesDelaySuspend
) {
172 scoped_refptr
<extensions::Extension
> gcm_app
=
173 CreateApp("DelaysSuspendForPushMessages", true /* uses_gcm */);
174 extensions::ExtensionHost
* host
= CreateHostForApp(profile_
, gcm_app
.get());
176 EXPECT_TRUE(test_api_
->WillDelaySuspendForExtensionHost(host
));
178 // Test that a push message received before a suspend attempt delays the
180 const int kSuspendPushId
= 23874;
181 extension_event_observer_
->OnExtensionMessageDispatched(
182 host
, extensions::api::gcm::OnMessage::kEventName
, kSuspendPushId
);
183 power_manager_client_
->SendSuspendImminent();
185 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
186 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
188 extension_event_observer_
->OnExtensionMessageAcked(host
, kSuspendPushId
);
189 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
191 // Now test receiving the suspend attempt before the push message.
192 const int kDarkSuspendPushId
= 56674;
193 power_manager_client_
->SendDarkSuspendImminent();
194 extension_event_observer_
->OnExtensionMessageDispatched(
195 host
, extensions::api::gcm::OnMessage::kEventName
, kDarkSuspendPushId
);
197 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
198 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
200 extension_event_observer_
->OnExtensionMessageAcked(host
, kDarkSuspendPushId
);
201 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
203 // Test that non-push messages do not delay the suspend.
204 const int kNonPushId
= 5687;
205 power_manager_client_
->SendDarkSuspendImminent();
206 extension_event_observer_
->OnExtensionMessageDispatched(host
, "FakeMessage",
209 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
210 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
213 // Tests that messages sent for apps that don't use GCM are ignored.
214 TEST_F(ExtensionEventObserverTest
, IgnoresNonGCMApps
) {
215 scoped_refptr
<extensions::Extension
> app
= CreateApp("Non-GCM", false);
216 extensions::ExtensionHost
* host
= CreateHostForApp(profile_
, app
.get());
219 EXPECT_FALSE(test_api_
->WillDelaySuspendForExtensionHost(host
));
221 power_manager_client_
->SendSuspendImminent();
222 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
223 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
226 // Tests that network requests started by an app while it is processing a push
227 // message delay any suspend attempt.
228 TEST_F(ExtensionEventObserverTest
, NetworkRequestsMayDelaySuspend
) {
229 scoped_refptr
<extensions::Extension
> app
= CreateApp("NetworkRequests", true);
230 extensions::ExtensionHost
* host
= CreateHostForApp(profile_
, app
.get());
232 EXPECT_TRUE(test_api_
->WillDelaySuspendForExtensionHost(host
));
234 // Test that network requests started while there is no pending push message
236 const uint64 kNonPushRequestId
= 5170725;
237 extension_event_observer_
->OnNetworkRequestStarted(host
, kNonPushRequestId
);
238 power_manager_client_
->SendSuspendImminent();
240 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
241 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
243 // Test that network requests started while a push message is pending delay
244 // the suspend even after the push message has been acked.
245 const int kPushMessageId
= 178674;
246 const uint64 kNetworkRequestId
= 78917089;
247 power_manager_client_
->SendDarkSuspendImminent();
248 extension_event_observer_
->OnExtensionMessageDispatched(
249 host
, extensions::api::gcm::OnMessage::kEventName
, kPushMessageId
);
251 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
252 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
254 extension_event_observer_
->OnNetworkRequestStarted(host
, kNetworkRequestId
);
255 extension_event_observer_
->OnExtensionMessageAcked(host
, kPushMessageId
);
256 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
258 extension_event_observer_
->OnNetworkRequestDone(host
, kNetworkRequestId
);
259 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
262 // Tests that any outstanding push messages or network requests for an
263 // ExtensionHost that is destroyed do not end up blocking system suspend.
264 TEST_F(ExtensionEventObserverTest
, DeletedExtensionHostDoesNotBlockSuspend
) {
265 scoped_refptr
<extensions::Extension
> app
=
266 CreateApp("DeletedExtensionHost", true);
268 // The easiest way to delete an extension host is to delete the Profile it is
269 // associated with so we create a new Profile here.
270 const char kProfileName
[] = "DeletedExtensionHostProfile";
271 Profile
* new_profile
= profile_manager_
->CreateTestingProfile(kProfileName
);
273 extensions::ExtensionHost
* host
= CreateHostForApp(new_profile
, app
.get());
275 EXPECT_TRUE(test_api_
->WillDelaySuspendForExtensionHost(host
));
277 const int kPushId
= 156178;
278 const uint64 kNetworkId
= 791605;
279 extension_event_observer_
->OnExtensionMessageDispatched(
280 host
, extensions::api::gcm::OnMessage::kEventName
, kPushId
);
281 extension_event_observer_
->OnNetworkRequestStarted(host
, kNetworkId
);
283 // Now delete the Profile. This has the side-effect of also deleting all the
285 profile_manager_
->DeleteTestingProfile(kProfileName
);
287 power_manager_client_
->SendSuspendImminent();
288 EXPECT_TRUE(test_api_
->MaybeRunSuspendReadinessCallback());
289 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
292 // Tests that the ExtensionEventObserver does not delay suspend attempts when it
294 TEST_F(ExtensionEventObserverTest
, DoesNotDelaySuspendWhenDisabled
) {
295 scoped_refptr
<extensions::Extension
> app
=
296 CreateApp("NoDelayWhenDisabled", true);
297 extensions::ExtensionHost
* host
= CreateHostForApp(profile_
, app
.get());
299 EXPECT_TRUE(test_api_
->WillDelaySuspendForExtensionHost(host
));
301 // Test that disabling the suspend delay while a suspend is pending will cause
302 // the ExtensionEventObserver to immediately report readiness.
303 const int kPushId
= 416753;
304 extension_event_observer_
->OnExtensionMessageDispatched(
305 host
, extensions::api::gcm::OnMessage::kEventName
, kPushId
);
306 power_manager_client_
->SendSuspendImminent();
307 EXPECT_EQ(1, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
309 extension_event_observer_
->SetShouldDelaySuspend(false);
310 EXPECT_FALSE(test_api_
->MaybeRunSuspendReadinessCallback());
311 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
313 // Test that the ExtensionEventObserver does not delay suspend attempts when
315 power_manager_client_
->SendDarkSuspendImminent();
316 EXPECT_EQ(0, power_manager_client_
->GetNumPendingSuspendReadinessCallbacks());
319 } // namespace chromeos