OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "chrome/browser/chromeos/power/extension_event_observer.h" | |
6 | |
7 #include <string> | |
8 | |
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/scoped_test_user_manager.h" | |
14 #include "chrome/browser/chromeos/settings/cros_settings.h" | |
15 #include "chrome/browser/chromeos/settings/device_settings_service.h" | |
16 #include "chrome/common/extensions/api/gcm.h" | |
17 #include "chrome/test/base/testing_browser_process.h" | |
18 #include "chrome/test/base/testing_profile.h" | |
19 #include "chrome/test/base/testing_profile_manager.h" | |
20 #include "chromeos/dbus/dbus_thread_manager.h" | |
21 #include "chromeos/dbus/fake_power_manager_client.h" | |
22 #include "content/public/test/test_browser_thread_bundle.h" | |
23 #include "content/public/test/test_renderer_host.h" | |
24 #include "extensions/browser/extension_host.h" | |
25 #include "extensions/browser/process_manager.h" | |
26 #include "extensions/common/extension.h" | |
27 #include "extensions/common/extension_builder.h" | |
28 #include "extensions/common/manifest_handlers/background_info.h" | |
29 #include "extensions/common/value_builder.h" | |
30 #include "testing/gtest/include/gtest/gtest.h" | |
31 | |
32 namespace chromeos { | |
33 | |
34 class ExtensionEventObserverTest : public ::testing::Test { | |
35 public: | |
36 ExtensionEventObserverTest() | |
37 : power_manager_client_(new FakePowerManagerClient()) { | |
38 DBusThreadManager::GetSetterForTesting()->SetPowerManagerClient( | |
39 make_scoped_ptr(power_manager_client_)); | |
40 | |
41 profile_manager_.reset( | |
42 new TestingProfileManager(TestingBrowserProcess::GetGlobal())); | |
43 | |
44 extension_event_observer_.reset(new ExtensionEventObserver()); | |
45 test_api_ = extension_event_observer_->GetApiForTesting(); | |
46 } | |
47 | |
48 ~ExtensionEventObserverTest() { | |
Daniel Erat
2015/01/13 23:49:10
override
Chirantan Ekbote
2015/01/15 05:06:36
Done.
| |
49 extension_event_observer_.reset(); | |
50 profile_manager_.reset(); | |
51 DBusThreadManager::Shutdown(); | |
52 } | |
53 | |
54 // ::testing::Test overrides. | |
55 void SetUp() override { | |
56 ::testing::Test::SetUp(); | |
57 | |
58 // Must be called from ::testing::Test::SetUp. | |
59 ASSERT_TRUE(profile_manager_->SetUp()); | |
60 | |
61 profile_ = profile_manager_->CreateTestingProfile("Profile 1"); | |
62 } | |
63 void TearDown() override { | |
64 profile_ = NULL; | |
65 profile_manager_->DeleteAllTestingProfiles(); | |
66 | |
67 ::testing::Test::TearDown(); | |
68 } | |
69 | |
70 protected: | |
71 scoped_refptr<extensions::Extension> CreateApp(const std::string& name, | |
72 bool uses_gcm) { | |
73 scoped_refptr<extensions::Extension> app = | |
74 extensions::ExtensionBuilder() | |
75 .SetManifest( | |
76 extensions::DictionaryBuilder() | |
77 .Set("name", name) | |
78 .Set("version", "1.0.0") | |
79 .Set("manifest_version", 2) | |
80 .Set("app", | |
81 extensions::DictionaryBuilder().Set( | |
82 "background", | |
83 extensions::DictionaryBuilder().Set( | |
84 "scripts", extensions::ListBuilder().Append( | |
85 "background.js")))) | |
86 .Set("permissions", extensions::ListBuilder().Append( | |
87 uses_gcm ? "gcm" : ""))) | |
88 .Build(); | |
89 | |
90 created_apps_.push_back(app); | |
91 | |
92 return app; | |
93 } | |
94 | |
95 extensions::ExtensionHost* CreateHostForApp(Profile* profile, | |
96 extensions::Extension* app) { | |
97 extensions::ProcessManager::Get(profile)->CreateBackgroundHost( | |
98 app, extensions::BackgroundInfo::GetBackgroundURL(app)); | |
99 base::RunLoop().RunUntilIdle(); | |
100 | |
101 return extensions::ProcessManager::Get(profile) | |
102 ->GetBackgroundHostForExtension(app->id()); | |
103 } | |
104 | |
105 // Owned by DBusThreadManager. | |
106 FakePowerManagerClient* power_manager_client_; | |
107 | |
108 scoped_ptr<ExtensionEventObserver> extension_event_observer_; | |
109 scoped_ptr<ExtensionEventObserver::TestApi> test_api_; | |
110 | |
111 // Owned by |profile_manager_|. | |
112 TestingProfile* profile_; | |
113 scoped_ptr<TestingProfileManager> profile_manager_; | |
114 | |
115 private: | |
116 content::TestBrowserThreadBundle browser_thread_bundle_; | |
117 | |
118 // Needed to ensure we don't end up creating actual RenderViewHosts | |
119 // and RenderProcessHosts. | |
120 content::RenderViewHostTestEnabler render_view_host_test_enabler_; | |
121 | |
122 // Chrome OS needs extra services to run in the following order. | |
123 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; | |
124 chromeos::ScopedTestCrosSettings test_cros_settings_; | |
125 chromeos::ScopedTestUserManager test_user_manager_; | |
126 | |
127 std::vector<scoped_refptr<extensions::Extension>> created_apps_; | |
128 | |
129 DISALLOW_COPY_AND_ASSIGN(ExtensionEventObserverTest); | |
130 }; | |
131 | |
132 // Tests that the ExtensionEventObserver reports readiness for suspend when | |
133 // there is nothing interesting going on. | |
134 TEST_F(ExtensionEventObserverTest, BasicSuspendAndDarkSuspend) { | |
135 power_manager_client_->SendSuspendImminent(); | |
136 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
Daniel Erat
2015/01/13 23:49:10
here and elsewhere in the file: should be EXPECT_E
Chirantan Ekbote
2015/01/15 05:06:36
Done.
| |
137 | |
138 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
139 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
140 | |
141 power_manager_client_->SendDarkSuspendImminent(); | |
142 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
143 | |
144 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
145 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
146 } | |
147 | |
148 // Tests that the ExtensionEventObserver properly handles a canceled suspend | |
149 // attempt. | |
150 TEST_F(ExtensionEventObserverTest, CanceledSuspend) { | |
151 power_manager_client_->SendSuspendImminent(); | |
152 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
153 | |
154 power_manager_client_->SendSuspendDone(); | |
155 EXPECT_FALSE(test_api_->MaybeRunSuspendReadinessCallback()); | |
156 } | |
157 | |
158 // Tests that the ExtensionEventObserver delays suspends and dark suspends while | |
159 // there is a push message pending for an app that uses GCM. | |
160 TEST_F(ExtensionEventObserverTest, PushMessagesDelaySuspend) { | |
161 scoped_refptr<extensions::Extension> gcm_app = | |
162 CreateApp("DelaysSuspendForPushMessages", true /* uses_gcm */); | |
163 extensions::ExtensionHost* host = CreateHostForApp(profile_, gcm_app.get()); | |
164 ASSERT_TRUE(host); | |
165 EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host)); | |
166 | |
167 // Test that a push message received before a suspend attempt delays the | |
168 // attempt. | |
169 const int kSuspendPushId = 23874; | |
170 extension_event_observer_->OnExtensionMessageDispatched( | |
171 host, extensions::api::gcm::OnMessage::kEventName, kSuspendPushId); | |
172 power_manager_client_->SendSuspendImminent(); | |
173 | |
174 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
175 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
176 | |
177 extension_event_observer_->OnExtensionMessageAcked(host, kSuspendPushId); | |
178 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
179 | |
180 // Now test receiving the suspend attempt before the push message. | |
181 const int kDarkSuspendPushId = 56674; | |
182 power_manager_client_->SendDarkSuspendImminent(); | |
183 extension_event_observer_->OnExtensionMessageDispatched( | |
184 host, extensions::api::gcm::OnMessage::kEventName, kDarkSuspendPushId); | |
185 | |
186 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
187 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
188 | |
189 extension_event_observer_->OnExtensionMessageAcked(host, kDarkSuspendPushId); | |
190 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
191 | |
192 // Test that non-push messages do not delay the suspend. | |
193 const int kNonPushId = 5687; | |
194 power_manager_client_->SendDarkSuspendImminent(); | |
195 extension_event_observer_->OnExtensionMessageDispatched(host, "FakeMessage", | |
196 kNonPushId); | |
197 | |
198 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
199 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
200 } | |
201 | |
202 // Tests that messages sent for apps that don't use GCM are ignored. | |
203 TEST_F(ExtensionEventObserverTest, IgnoresNonGCMApps) { | |
204 scoped_refptr<extensions::Extension> app = CreateApp("Non-GCM", false); | |
205 extensions::ExtensionHost* host = CreateHostForApp(profile_, app.get()); | |
206 ASSERT_TRUE(host); | |
207 | |
208 EXPECT_FALSE(test_api_->WillDelaySuspendForExtensionHost(host)); | |
209 | |
210 power_manager_client_->SendSuspendImminent(); | |
211 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
212 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
213 } | |
214 | |
215 // Tests that network requests started by an app while it is processing a push | |
216 // message delay any suspend attempt. | |
217 TEST_F(ExtensionEventObserverTest, NetworkRequestsMayDelaySuspend) { | |
218 scoped_refptr<extensions::Extension> app = CreateApp("NetworkRequests", true); | |
219 extensions::ExtensionHost* host = CreateHostForApp(profile_, app.get()); | |
220 ASSERT_TRUE(host); | |
221 EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host)); | |
222 | |
223 // Test that network requests started while there is no pending push message | |
224 // are ignored. | |
225 const uint64 kNonPushRequestId = 5170725; | |
226 extension_event_observer_->OnNetworkRequestStarted(host, kNonPushRequestId); | |
227 power_manager_client_->SendSuspendImminent(); | |
228 | |
229 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
230 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
231 | |
232 // Test that network requests started while a push message is pending delay | |
233 // the suspend even after the push message has been acked. | |
234 const int kPushMessageId = 178674; | |
235 const uint64 kNetworkRequestId = 78917089; | |
236 power_manager_client_->SendDarkSuspendImminent(); | |
237 extension_event_observer_->OnExtensionMessageDispatched( | |
238 host, extensions::api::gcm::OnMessage::kEventName, kPushMessageId); | |
239 | |
240 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
241 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
242 | |
243 extension_event_observer_->OnNetworkRequestStarted(host, kNetworkRequestId); | |
244 extension_event_observer_->OnExtensionMessageAcked(host, kPushMessageId); | |
245 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
246 | |
247 extension_event_observer_->OnNetworkRequestDone(host, kNetworkRequestId); | |
248 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
249 } | |
250 | |
251 // Tests that any outstanding push messages or network requests for an | |
252 // ExtensionHost that is destroyed do not end up blocking system suspend. | |
253 TEST_F(ExtensionEventObserverTest, DeletedExtensionHostDoesNotBlockSuspend) { | |
254 scoped_refptr<extensions::Extension> app = | |
255 CreateApp("DeletedExtensionHost", true); | |
256 | |
257 // The easiest way to delete an extension host is to delete the Profile it is | |
258 // associated with so we create a new Profile here. | |
259 const char kProfileName[] = "DeletedExtensionHostProfile"; | |
260 Profile* new_profile = profile_manager_->CreateTestingProfile(kProfileName); | |
261 | |
262 extensions::ExtensionHost* host = CreateHostForApp(new_profile, app.get()); | |
263 ASSERT_TRUE(host); | |
264 EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host)); | |
265 | |
266 const int kPushId = 156178; | |
267 const uint64 kNetworkId = 791605; | |
268 extension_event_observer_->OnExtensionMessageDispatched( | |
269 host, extensions::api::gcm::OnMessage::kEventName, kPushId); | |
270 extension_event_observer_->OnNetworkRequestStarted(host, kNetworkId); | |
271 | |
272 // Now delete the Profile. This has the side-effect of also deleting all the | |
273 // ExtensionHosts. | |
274 profile_manager_->DeleteTestingProfile(kProfileName); | |
275 | |
276 power_manager_client_->SendSuspendImminent(); | |
277 EXPECT_TRUE(test_api_->MaybeRunSuspendReadinessCallback()); | |
278 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
279 } | |
280 | |
281 // Tests that the ExtensionEventObserver does not delay suspend attempts when it | |
282 // is disabled. | |
283 TEST_F(ExtensionEventObserverTest, DoesNotDelaySuspendWhenDisabled) { | |
284 scoped_refptr<extensions::Extension> app = | |
285 CreateApp("NoDelayWhenDisabled", true); | |
286 extensions::ExtensionHost* host = CreateHostForApp(profile_, app.get()); | |
287 ASSERT_TRUE(host); | |
288 EXPECT_TRUE(test_api_->WillDelaySuspendForExtensionHost(host)); | |
289 | |
290 // Test that disabling the suspend delay while a suspend is pending will cause | |
291 // the ExtensionEventObserver to immediately report readiness. | |
292 const int kPushId = 416753; | |
293 extension_event_observer_->OnExtensionMessageDispatched( | |
294 host, extensions::api::gcm::OnMessage::kEventName, kPushId); | |
295 power_manager_client_->SendSuspendImminent(); | |
296 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 1); | |
297 | |
298 extension_event_observer_->ShouldDelaySuspend(false); | |
299 EXPECT_FALSE(test_api_->MaybeRunSuspendReadinessCallback()); | |
300 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
301 | |
302 // Test that the ExtensionEventObserver does not delay suspend attempts when | |
303 // it is disabled. | |
304 power_manager_client_->SendDarkSuspendImminent(); | |
305 EXPECT_EQ(power_manager_client_->GetNumPendingSuspendReadinessCallbacks(), 0); | |
306 } | |
307 | |
308 } // namespace chromeos | |
OLD | NEW |