OLD | NEW |
| (Empty) |
1 /// Copyright 2014 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 "athena/activity/public/activity_factory.h" | |
6 #include "athena/activity/public/activity_manager.h" | |
7 #include "athena/content/app_activity.h" | |
8 #include "athena/content/app_activity_registry.h" | |
9 #include "athena/content/public/app_content_control_delegate.h" | |
10 #include "athena/content/public/app_registry.h" | |
11 #include "athena/test/athena_test_base.h" | |
12 #include "extensions/shell/browser/shell_app_window.h" | |
13 #include "ui/aura/window.h" | |
14 #include "ui/views/view.h" | |
15 #include "ui/views/widget/widget.h" | |
16 | |
17 | |
18 namespace content { | |
19 class BrowserContext; | |
20 } | |
21 | |
22 namespace athena { | |
23 namespace test { | |
24 | |
25 namespace { | |
26 | |
27 // An identifier for the running apps. | |
28 const char kDummyApp1[] = "aaaaaaa"; | |
29 const char kDummyApp2[] = "bbbbbbb"; | |
30 | |
31 // A dummy test app activity which works without content / ShellAppWindow. | |
32 class TestAppActivity : public AppActivity { | |
33 public: | |
34 explicit TestAppActivity(const std::string& app_id) : | |
35 AppActivity(NULL), | |
36 app_id_(app_id), | |
37 view_(new views::View()), | |
38 current_state_(ACTIVITY_VISIBLE) { | |
39 app_activity_registry_ = | |
40 AppRegistry::Get()->GetAppActivityRegistry(app_id, NULL); | |
41 app_activity_registry_->RegisterAppActivity(this); | |
42 } | |
43 virtual ~TestAppActivity() { | |
44 app_activity_registry_->UnregisterAppActivity(this); | |
45 } | |
46 | |
47 AppActivityRegistry* app_activity_registry() { | |
48 return app_activity_registry_; | |
49 } | |
50 | |
51 // Activity: | |
52 virtual ActivityViewModel* GetActivityViewModel() OVERRIDE { | |
53 return this; | |
54 } | |
55 virtual void SetCurrentState(Activity::ActivityState state) OVERRIDE { | |
56 current_state_ = state; | |
57 } | |
58 virtual ActivityState GetCurrentState() OVERRIDE { | |
59 return current_state_; | |
60 } | |
61 virtual bool IsVisible() OVERRIDE { | |
62 return true; | |
63 } | |
64 virtual ActivityMediaState GetMediaState() OVERRIDE { | |
65 return Activity::ACTIVITY_MEDIA_STATE_NONE; | |
66 } | |
67 virtual aura::Window* GetWindow() OVERRIDE { | |
68 return view_->GetWidget()->GetNativeWindow(); | |
69 } | |
70 | |
71 // ActivityViewModel: | |
72 virtual void Init() OVERRIDE {} | |
73 virtual SkColor GetRepresentativeColor() const OVERRIDE { return 0; } | |
74 virtual base::string16 GetTitle() const OVERRIDE { return title_; } | |
75 virtual bool UsesFrame() const OVERRIDE { return true; } | |
76 virtual views::View* GetContentsView() OVERRIDE { return view_; } | |
77 virtual void CreateOverviewModeImage() OVERRIDE {} | |
78 | |
79 private: | |
80 // If known the registry which holds all activities for the associated app. | |
81 AppActivityRegistry* app_activity_registry_; | |
82 | |
83 // The application ID. | |
84 const std::string& app_id_; | |
85 | |
86 // The title of the activity. | |
87 base::string16 title_; | |
88 | |
89 // Our view. | |
90 views::View* view_; | |
91 | |
92 // The current state for this activity. | |
93 ActivityState current_state_; | |
94 | |
95 DISALLOW_COPY_AND_ASSIGN(TestAppActivity); | |
96 }; | |
97 | |
98 // An AppContentDelegateClass which we can query for call stats. | |
99 class TestAppContentControlDelegate : public AppContentControlDelegate { | |
100 public: | |
101 TestAppContentControlDelegate() : unload_called_(0), | |
102 restart_called_(0) {} | |
103 virtual ~TestAppContentControlDelegate() {} | |
104 | |
105 int unload_called() { return unload_called_; } | |
106 int restart_called() { return restart_called_; } | |
107 void SetExtensionID(const std::string& extension_id) { | |
108 extension_id_to_return_ = extension_id; | |
109 } | |
110 | |
111 // Unload an application. Returns true when unloaded. | |
112 virtual bool UnloadApplication( | |
113 const std::string& app_id, | |
114 content::BrowserContext* browser_context) OVERRIDE { | |
115 unload_called_++; | |
116 // Since we did not close anything we let the framework clean up. | |
117 return false; | |
118 } | |
119 // Restarts an application. Returns true when the restart was initiated. | |
120 virtual bool RestartApplication( | |
121 const std::string& app_id, | |
122 content::BrowserContext* browser_context) OVERRIDE { | |
123 restart_called_++; | |
124 return true; | |
125 } | |
126 // Returns the application ID (or an empty string) for a given web content. | |
127 virtual std::string GetApplicationID( | |
128 content::WebContents* web_contents) OVERRIDE { | |
129 return extension_id_to_return_; | |
130 } | |
131 | |
132 private: | |
133 int unload_called_; | |
134 int restart_called_; | |
135 std::string extension_id_to_return_; | |
136 | |
137 DISALLOW_COPY_AND_ASSIGN(TestAppContentControlDelegate); | |
138 }; | |
139 | |
140 } // namespace | |
141 | |
142 // Our testing base. | |
143 class AppActivityTest : public AthenaTestBase { | |
144 public: | |
145 AppActivityTest() : test_app_content_control_delegate_(NULL) {} | |
146 virtual ~AppActivityTest() {} | |
147 | |
148 // AthenaTestBase: | |
149 virtual void SetUp() OVERRIDE { | |
150 AthenaTestBase::SetUp(); | |
151 // Create and install our TestAppContentDelegate with instrumentation. | |
152 test_app_content_control_delegate_ = new TestAppContentControlDelegate(); | |
153 AppRegistry::Get()->SetDelegate(test_app_content_control_delegate_); | |
154 } | |
155 | |
156 // A function to create an Activity. | |
157 TestAppActivity* CreateAppActivity(const std::string& app_id) { | |
158 TestAppActivity* activity = new TestAppActivity(app_id); | |
159 ActivityManager::Get()->AddActivity(activity); | |
160 return activity; | |
161 } | |
162 | |
163 void CloseActivity(Activity* activity) { | |
164 delete activity; | |
165 RunAllPendingInMessageLoop(); | |
166 } | |
167 | |
168 // Get the position of the activity in the navigation history. | |
169 int GetActivityPosition(Activity* activity) { | |
170 aura::Window* window = activity->GetActivityViewModel()->GetContentsView() | |
171 ->GetWidget()->GetNativeWindow(); | |
172 aura::Window::Windows windows = activity->GetWindow()->parent()->children(); | |
173 for (size_t i = 0; i < windows.size(); i++) { | |
174 if (windows[i] == window) | |
175 return i; | |
176 } | |
177 return -1; | |
178 } | |
179 | |
180 protected: | |
181 TestAppContentControlDelegate* test_app_content_control_delegate() { | |
182 return test_app_content_control_delegate_; | |
183 } | |
184 | |
185 private: | |
186 TestAppContentControlDelegate* test_app_content_control_delegate_; | |
187 | |
188 DISALLOW_COPY_AND_ASSIGN(AppActivityTest); | |
189 }; | |
190 | |
191 // Only creates one activity and destroys it. | |
192 TEST_F(AppActivityTest, OneAppActivity) { | |
193 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
194 { | |
195 TestAppActivity* app_activity = CreateAppActivity(kDummyApp1); | |
196 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
197 EXPECT_EQ(1, app_activity->app_activity_registry()->NumberOfActivities()); | |
198 EXPECT_EQ(AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1, NULL), | |
199 app_activity->app_activity_registry()); | |
200 CloseActivity(app_activity); | |
201 } | |
202 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
203 EXPECT_EQ(0, test_app_content_control_delegate()->unload_called()); | |
204 EXPECT_EQ(0, test_app_content_control_delegate()->restart_called()); | |
205 } | |
206 | |
207 // Test running of two applications. | |
208 TEST_F(AppActivityTest, TwoAppsWithOneActivityEach) { | |
209 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
210 { | |
211 TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1); | |
212 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
213 EXPECT_EQ(1, app_activity1->app_activity_registry()->NumberOfActivities()); | |
214 TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp2); | |
215 EXPECT_EQ(2, AppRegistry::Get()->NumberOfApplications()); | |
216 EXPECT_EQ(1, app_activity2->app_activity_registry()->NumberOfActivities()); | |
217 EXPECT_EQ(1, app_activity1->app_activity_registry()->NumberOfActivities()); | |
218 CloseActivity(app_activity1); | |
219 CloseActivity(app_activity2); | |
220 } | |
221 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
222 EXPECT_EQ(0, test_app_content_control_delegate()->unload_called()); | |
223 EXPECT_EQ(0, test_app_content_control_delegate()->restart_called()); | |
224 } | |
225 | |
226 // Create and destroy two activities for the same application. | |
227 TEST_F(AppActivityTest, TwoAppActivities) { | |
228 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
229 { | |
230 TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1); | |
231 TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp1); | |
232 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
233 EXPECT_EQ(2, app_activity1->app_activity_registry()->NumberOfActivities()); | |
234 EXPECT_EQ(app_activity1->app_activity_registry(), | |
235 app_activity2->app_activity_registry()); | |
236 CloseActivity(app_activity1); | |
237 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
238 EXPECT_EQ(1, app_activity2->app_activity_registry()->NumberOfActivities()); | |
239 CloseActivity(app_activity2); | |
240 } | |
241 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
242 { | |
243 TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1); | |
244 TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp1); | |
245 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
246 EXPECT_EQ(2, app_activity1->app_activity_registry()->NumberOfActivities()); | |
247 EXPECT_EQ(app_activity1->app_activity_registry(), | |
248 app_activity2->app_activity_registry()); | |
249 CloseActivity(app_activity2); | |
250 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
251 EXPECT_EQ(1, app_activity1->app_activity_registry()->NumberOfActivities()); | |
252 CloseActivity(app_activity1); | |
253 } | |
254 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
255 EXPECT_EQ(0, test_app_content_control_delegate()->unload_called()); | |
256 EXPECT_EQ(0, test_app_content_control_delegate()->restart_called()); | |
257 } | |
258 | |
259 // Test unload and the creation of the proxy, then "closing the activity". | |
260 TEST_F(AppActivityTest, TestUnloadFollowedByClose) { | |
261 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
262 | |
263 TestAppActivity* app_activity = CreateAppActivity(kDummyApp1); | |
264 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
265 AppActivityRegistry* app_activity_registry = | |
266 app_activity->app_activity_registry(); | |
267 EXPECT_EQ(1, app_activity_registry->NumberOfActivities()); | |
268 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity->GetCurrentState()); | |
269 | |
270 // Calling Unload now should not do anything since at least one activity in | |
271 // the registry is still visible. | |
272 app_activity_registry->Unload(); | |
273 EXPECT_EQ(0, test_app_content_control_delegate()->unload_called()); | |
274 | |
275 // After setting our activity to unloaded however the application should get | |
276 // unloaded as requested. | |
277 app_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
278 app_activity_registry->Unload(); | |
279 EXPECT_EQ(1, test_app_content_control_delegate()->unload_called()); | |
280 | |
281 // Check that our created application is gone, and instead a proxy got | |
282 // created. | |
283 ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
284 ASSERT_EQ(app_activity_registry, | |
285 AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1, NULL)); | |
286 EXPECT_EQ(0, app_activity_registry->NumberOfActivities()); | |
287 Activity* activity_proxy = | |
288 app_activity_registry->unloaded_activity_proxy_for_test(); | |
289 ASSERT_TRUE(activity_proxy); | |
290 EXPECT_NE(app_activity, activity_proxy); | |
291 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, activity_proxy->GetCurrentState()); | |
292 | |
293 // Close the proxy object and make sure that nothing bad happens. | |
294 CloseActivity(activity_proxy); | |
295 | |
296 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
297 EXPECT_EQ(1, test_app_content_control_delegate()->unload_called()); | |
298 EXPECT_EQ(0, test_app_content_control_delegate()->restart_called()); | |
299 } | |
300 | |
301 // Test that when unloading an app while multiple apps / activities are present, | |
302 // the proxy gets created in the correct location. | |
303 TEST_F(AppActivityTest, TestUnloadProxyLocation) { | |
304 // Set up some activities for some applications. | |
305 TestAppActivity* app_activity1a = CreateAppActivity(kDummyApp1); | |
306 TestAppActivity* app_activity2a = CreateAppActivity(kDummyApp2); | |
307 TestAppActivity* app_activity2b = CreateAppActivity(kDummyApp2); | |
308 TestAppActivity* app_activity1b = CreateAppActivity(kDummyApp1); | |
309 EXPECT_EQ(3, GetActivityPosition(app_activity1b)); | |
310 EXPECT_EQ(2, GetActivityPosition(app_activity2b)); | |
311 EXPECT_EQ(1, GetActivityPosition(app_activity2a)); | |
312 EXPECT_EQ(0, GetActivityPosition(app_activity1a)); | |
313 | |
314 // Unload an app and make sure that the proxy is in the newest activity slot. | |
315 AppActivityRegistry* app_activity_registry = | |
316 app_activity2a->app_activity_registry(); | |
317 app_activity2a->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
318 app_activity2b->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
319 app_activity2a->app_activity_registry()->Unload(); | |
320 EXPECT_EQ(0, app_activity_registry->NumberOfActivities()); | |
321 Activity* activity_proxy = | |
322 app_activity_registry->unloaded_activity_proxy_for_test(); | |
323 RunAllPendingInMessageLoop(); | |
324 | |
325 EXPECT_EQ(2, GetActivityPosition(app_activity1b)); | |
326 EXPECT_EQ(1, GetActivityPosition(activity_proxy)); | |
327 EXPECT_EQ(0, GetActivityPosition(app_activity1a)); | |
328 | |
329 CloseActivity(activity_proxy); | |
330 CloseActivity(app_activity1b); | |
331 CloseActivity(app_activity1a); | |
332 } | |
333 | |
334 // Test that an unload with multiple activities of the same app will only unload | |
335 // when all activities were marked for unloading. | |
336 TEST_F(AppActivityTest, TestMultipleActivityUnloadLock) { | |
337 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
338 | |
339 TestAppActivity* app_activity1 = CreateAppActivity(kDummyApp1); | |
340 TestAppActivity* app_activity2 = CreateAppActivity(kDummyApp1); | |
341 TestAppActivity* app_activity3 = CreateAppActivity(kDummyApp1); | |
342 | |
343 // Check that we have 3 activities of the same application. | |
344 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
345 AppActivityRegistry* app_activity_registry = | |
346 app_activity1->app_activity_registry(); | |
347 EXPECT_EQ(app_activity_registry, app_activity2->app_activity_registry()); | |
348 EXPECT_EQ(app_activity_registry, app_activity3->app_activity_registry()); | |
349 EXPECT_EQ(3, app_activity_registry->NumberOfActivities()); | |
350 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity1->GetCurrentState()); | |
351 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity2->GetCurrentState()); | |
352 EXPECT_EQ(Activity::ACTIVITY_VISIBLE, app_activity3->GetCurrentState()); | |
353 | |
354 // After setting all activities to UNLOADED the application should unload. | |
355 app_activity1->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
356 app_activity1->app_activity_registry()->Unload(); | |
357 EXPECT_EQ(0, test_app_content_control_delegate()->unload_called()); | |
358 app_activity2->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
359 app_activity2->app_activity_registry()->Unload(); | |
360 EXPECT_EQ(0, test_app_content_control_delegate()->unload_called()); | |
361 app_activity3->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
362 app_activity3->app_activity_registry()->Unload(); | |
363 EXPECT_EQ(1, test_app_content_control_delegate()->unload_called()); | |
364 | |
365 // Now there should only be the proxy activity left. | |
366 ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications()); | |
367 ASSERT_EQ(app_activity_registry, | |
368 AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1, NULL)); | |
369 EXPECT_EQ(0, app_activity_registry->NumberOfActivities()); | |
370 Activity* activity_proxy = | |
371 app_activity_registry->unloaded_activity_proxy_for_test(); | |
372 ASSERT_TRUE(activity_proxy); | |
373 EXPECT_NE(app_activity1, activity_proxy); | |
374 EXPECT_NE(app_activity2, activity_proxy); | |
375 EXPECT_NE(app_activity3, activity_proxy); | |
376 EXPECT_EQ(Activity::ACTIVITY_UNLOADED, activity_proxy->GetCurrentState()); | |
377 | |
378 // Close the proxy object and make sure that nothing bad happens. | |
379 CloseActivity(activity_proxy); | |
380 | |
381 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
382 EXPECT_EQ(1, test_app_content_control_delegate()->unload_called()); | |
383 EXPECT_EQ(0, test_app_content_control_delegate()->restart_called()); | |
384 } | |
385 | |
386 // Test that activating the proxy will reload the application. | |
387 TEST_F(AppActivityTest, TestUnloadWithReload) { | |
388 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
389 | |
390 TestAppActivity* app_activity = CreateAppActivity(kDummyApp1); | |
391 AppActivityRegistry* app_activity_registry = | |
392 app_activity->app_activity_registry(); | |
393 | |
394 // Unload the activity. | |
395 app_activity->SetCurrentState(Activity::ACTIVITY_UNLOADED); | |
396 app_activity_registry->Unload(); | |
397 EXPECT_EQ(1, test_app_content_control_delegate()->unload_called()); | |
398 | |
399 // Try to activate the activity again. This will force the application to | |
400 // reload. | |
401 Activity* activity_proxy = | |
402 app_activity_registry->unloaded_activity_proxy_for_test(); | |
403 activity_proxy->SetCurrentState(Activity::ACTIVITY_VISIBLE); | |
404 EXPECT_EQ(1, test_app_content_control_delegate()->restart_called()); | |
405 | |
406 // However - the restart in this test framework does not really restart and | |
407 // all objects should be gone now. | |
408 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications()); | |
409 } | |
410 | |
411 } // namespace test | |
412 } // namespace athena | |
OLD | NEW |