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.
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_registry.h"
10 #include "athena/extensions/public/extensions_delegate.h"
11 #include "athena/resource_manager/public/resource_manager.h"
12 #include "athena/test/athena_test_base.h"
13 #include "extensions/common/extension_set.h"
14 #include "ui/aura/window.h"
15 #include "ui/views/view.h"
16 #include "ui/views/widget/widget.h"
27 // An identifier for the running apps.
28 const char kDummyApp1
[] = "aaaaaaa";
29 const char kDummyApp2
[] = "bbbbbbb";
31 // A dummy test app activity which works without content / ShellAppWindow.
32 class TestAppActivity
: public AppActivity
{
34 explicit TestAppActivity(const std::string
& app_id
)
35 : AppActivity(app_id
),
36 view_(new views::View()),
37 current_state_(ACTIVITY_VISIBLE
) {
38 app_activity_registry_
=
39 AppRegistry::Get()->GetAppActivityRegistry(app_id
, NULL
);
40 app_activity_registry_
->RegisterAppActivity(this);
42 virtual ~TestAppActivity() {
43 app_activity_registry_
->UnregisterAppActivity(this);
46 AppActivityRegistry
* app_activity_registry() {
47 return app_activity_registry_
;
51 virtual ActivityViewModel
* GetActivityViewModel() OVERRIDE
{
54 virtual void SetCurrentState(Activity::ActivityState state
) OVERRIDE
{
55 current_state_
= state
;
56 if (state
== ACTIVITY_UNLOADED
)
57 app_activity_registry_
->Unload();
59 virtual ActivityState
GetCurrentState() OVERRIDE
{
60 return current_state_
;
62 virtual bool IsVisible() OVERRIDE
{
65 virtual ActivityMediaState
GetMediaState() OVERRIDE
{
66 return Activity::ACTIVITY_MEDIA_STATE_NONE
;
68 virtual aura::Window
* GetWindow() OVERRIDE
{
69 return view_
->GetWidget()->GetNativeWindow();
73 virtual void Init() OVERRIDE
{}
74 virtual SkColor
GetRepresentativeColor() const OVERRIDE
{ return 0; }
75 virtual base::string16
GetTitle() const OVERRIDE
{ return title_
; }
76 virtual bool UsesFrame() const OVERRIDE
{ return true; }
77 virtual views::View
* GetContentsView() OVERRIDE
{ return view_
; }
78 virtual views::Widget
* CreateWidget() OVERRIDE
{ return NULL
; }
79 virtual gfx::ImageSkia
GetOverviewModeImage() OVERRIDE
{
80 return gfx::ImageSkia();
84 // If known the registry which holds all activities for the associated app.
85 AppActivityRegistry
* app_activity_registry_
;
87 // The title of the activity.
88 base::string16 title_
;
93 // The current state for this activity.
94 ActivityState current_state_
;
96 DISALLOW_COPY_AND_ASSIGN(TestAppActivity
);
99 // An AppContentDelegateClass which we can query for call stats.
100 class TestExtensionsDelegate
: public ExtensionsDelegate
{
102 TestExtensionsDelegate() : unload_called_(0), restart_called_(0) {}
103 virtual ~TestExtensionsDelegate() {}
105 int unload_called() const { return unload_called_
; }
106 int restart_called() const { return restart_called_
; }
108 // ExtensionsDelegate:
109 virtual content::BrowserContext
* GetBrowserContext() const OVERRIDE
{
112 virtual const extensions::ExtensionSet
& GetInstalledExtensions() OVERRIDE
{
113 return extension_set_
;
115 // Unload an application. Returns true when unloaded.
116 virtual bool UnloadApp(const std::string
& app_id
) OVERRIDE
{
118 // Since we did not close anything we let the framework clean up.
121 // Restarts an application. Returns true when the restart was initiated.
122 virtual bool LaunchApp(const std::string
& app_id
) OVERRIDE
{
131 extensions::ExtensionSet extension_set_
;
133 DISALLOW_COPY_AND_ASSIGN(TestExtensionsDelegate
);
139 class AppActivityTest
: public AthenaTestBase
{
141 AppActivityTest() : test_extensions_delegate_(NULL
) {}
142 virtual ~AppActivityTest() {}
145 virtual void SetUp() OVERRIDE
{
146 AthenaTestBase::SetUp();
147 // Create and install our TestAppContentDelegate with instrumentation.
148 ExtensionsDelegate::Shutdown();
149 // The instance will be deleted by ExtensionsDelegate::Shutdown().
150 test_extensions_delegate_
= new TestExtensionsDelegate();
153 // A function to create an Activity.
154 TestAppActivity
* CreateAppActivity(const std::string
& app_id
) {
155 TestAppActivity
* activity
= new TestAppActivity(app_id
);
156 ActivityManager::Get()->AddActivity(activity
);
160 void DeleteActivity(Activity
* activity
) {
161 Activity::Delete(activity
);
162 RunAllPendingInMessageLoop();
165 // Get the position of the activity in the navigation history.
166 int GetActivityPosition(Activity
* activity
) {
167 aura::Window
* window
= activity
->GetActivityViewModel()->GetContentsView()
168 ->GetWidget()->GetNativeWindow();
169 aura::Window::Windows windows
= activity
->GetWindow()->parent()->children();
170 for (size_t i
= 0; i
< windows
.size(); i
++) {
171 if (windows
[i
] == window
)
177 // To avoid interference of the ResourceManager in these AppActivity
178 // framework tests, we disable the ResourceManager for some tests.
179 // Every use/interference of this function gets explained.
180 void DisableResourceManager() {
181 ResourceManager::Get()->Pause(true);
185 TestExtensionsDelegate
* test_extensions_delegate() {
186 return test_extensions_delegate_
;
190 TestExtensionsDelegate
* test_extensions_delegate_
;
192 DISALLOW_COPY_AND_ASSIGN(AppActivityTest
);
195 // Only creates one activity and destroys it.
196 TEST_F(AppActivityTest
, OneAppActivity
) {
197 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
199 TestAppActivity
* app_activity
= CreateAppActivity(kDummyApp1
);
200 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
201 EXPECT_EQ(1, app_activity
->app_activity_registry()->NumberOfActivities());
202 EXPECT_EQ(AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1
, NULL
),
203 app_activity
->app_activity_registry());
204 DeleteActivity(app_activity
);
206 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
207 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
208 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
211 // Test running of two applications.
212 TEST_F(AppActivityTest
, TwoAppsWithOneActivityEach
) {
213 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
215 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
216 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
217 EXPECT_EQ(1, app_activity1
->app_activity_registry()->NumberOfActivities());
218 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp2
);
219 EXPECT_EQ(2, AppRegistry::Get()->NumberOfApplications());
220 EXPECT_EQ(1, app_activity2
->app_activity_registry()->NumberOfActivities());
221 EXPECT_EQ(1, app_activity1
->app_activity_registry()->NumberOfActivities());
222 DeleteActivity(app_activity1
);
223 DeleteActivity(app_activity2
);
225 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
226 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
227 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
230 // Create and destroy two activities for the same application.
231 TEST_F(AppActivityTest
, TwoAppActivities
) {
232 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
234 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
235 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp1
);
236 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
237 EXPECT_EQ(2, app_activity1
->app_activity_registry()->NumberOfActivities());
238 EXPECT_EQ(app_activity1
->app_activity_registry(),
239 app_activity2
->app_activity_registry());
240 DeleteActivity(app_activity1
);
241 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
242 EXPECT_EQ(1, app_activity2
->app_activity_registry()->NumberOfActivities());
243 DeleteActivity(app_activity2
);
245 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
247 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
248 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp1
);
249 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
250 EXPECT_EQ(2, app_activity1
->app_activity_registry()->NumberOfActivities());
251 EXPECT_EQ(app_activity1
->app_activity_registry(),
252 app_activity2
->app_activity_registry());
253 DeleteActivity(app_activity2
);
254 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
255 EXPECT_EQ(1, app_activity1
->app_activity_registry()->NumberOfActivities());
256 DeleteActivity(app_activity1
);
258 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
259 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
260 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
263 // Test unload and the creation of the proxy, then "closing the activity".
264 TEST_F(AppActivityTest
, TestUnloadFollowedByClose
) {
265 // We do not want the ResourceManager to interfere with this test. In this
266 // case it would (dependent on its current internal implementation)
267 // automatically re-load the unloaded activity if it is in an "active"
269 DisableResourceManager();
270 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
272 TestAppActivity
* app_activity
= CreateAppActivity(kDummyApp1
);
273 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
274 AppActivityRegistry
* app_activity_registry
=
275 app_activity
->app_activity_registry();
276 EXPECT_EQ(1, app_activity_registry
->NumberOfActivities());
277 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity
->GetCurrentState());
279 // Calling Unload now should not do anything since at least one activity in
280 // the registry is still visible.
281 app_activity_registry
->Unload();
282 RunAllPendingInMessageLoop();
283 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
285 // After setting our activity to unloaded however the application should get
286 // unloaded as requested.
287 app_activity
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
288 RunAllPendingInMessageLoop();
289 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
291 // Check that our created application is gone, and instead a proxy got
293 ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications());
294 ASSERT_EQ(app_activity_registry
,
295 AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1
, NULL
));
296 EXPECT_EQ(0, app_activity_registry
->NumberOfActivities());
297 Activity
* activity_proxy
= app_activity_registry
->unloaded_activity_proxy();
298 ASSERT_TRUE(activity_proxy
);
299 EXPECT_NE(app_activity
, activity_proxy
);
300 EXPECT_EQ(Activity::ACTIVITY_UNLOADED
, activity_proxy
->GetCurrentState());
301 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
303 // Close the proxy object and make sure that nothing bad happens.
304 DeleteActivity(activity_proxy
);
306 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
307 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
308 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
311 // Test that when unloading an app while multiple apps / activities are present,
312 // the proxy gets created in the correct location.
313 TEST_F(AppActivityTest
, TestUnloadProxyLocation
) {
314 // Disable the resource manager since some build bots run this test for an
315 // extended amount of time which allows the MemoryPressureNotifier to fire.
316 DisableResourceManager();
317 // Set up some activities for some applications.
318 TestAppActivity
* app_activity1a
= CreateAppActivity(kDummyApp1
);
319 TestAppActivity
* app_activity2a
= CreateAppActivity(kDummyApp2
);
320 TestAppActivity
* app_activity2b
= CreateAppActivity(kDummyApp2
);
321 TestAppActivity
* app_activity1b
= CreateAppActivity(kDummyApp1
);
322 EXPECT_EQ(3, GetActivityPosition(app_activity1b
));
323 EXPECT_EQ(2, GetActivityPosition(app_activity2b
));
324 EXPECT_EQ(1, GetActivityPosition(app_activity2a
));
325 EXPECT_EQ(0, GetActivityPosition(app_activity1a
));
327 // Unload an app and make sure that the proxy is in the newest activity slot.
328 AppActivityRegistry
* app_activity_registry
=
329 app_activity2a
->app_activity_registry();
330 app_activity2a
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
331 app_activity2b
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
332 RunAllPendingInMessageLoop();
333 EXPECT_EQ(0, app_activity_registry
->NumberOfActivities());
334 Activity
* activity_proxy
= app_activity_registry
->unloaded_activity_proxy();
335 RunAllPendingInMessageLoop();
337 EXPECT_EQ(2, GetActivityPosition(app_activity1b
));
338 EXPECT_EQ(1, GetActivityPosition(activity_proxy
));
339 EXPECT_EQ(0, GetActivityPosition(app_activity1a
));
340 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
342 DeleteActivity(activity_proxy
);
343 DeleteActivity(app_activity1b
);
344 DeleteActivity(app_activity1a
);
347 // Test that an unload with multiple activities of the same app will only unload
348 // when all activities were marked for unloading.
349 TEST_F(AppActivityTest
, TestMultipleActivityUnloadLock
) {
350 // Disable the resource manager since some build bots run this test for an
351 // extended amount of time which allows the MemoryPressureNotifier to fire.
352 DisableResourceManager();
354 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
356 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
357 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp1
);
358 TestAppActivity
* app_activity3
= CreateAppActivity(kDummyApp1
);
360 // Check that we have 3 activities of the same application.
361 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
362 AppActivityRegistry
* app_activity_registry
=
363 app_activity1
->app_activity_registry();
364 EXPECT_EQ(app_activity_registry
, app_activity2
->app_activity_registry());
365 EXPECT_EQ(app_activity_registry
, app_activity3
->app_activity_registry());
366 EXPECT_EQ(3, app_activity_registry
->NumberOfActivities());
367 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity1
->GetCurrentState());
368 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity2
->GetCurrentState());
369 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity3
->GetCurrentState());
371 // After setting all activities to UNLOADED the application should unload.
372 app_activity1
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
373 RunAllPendingInMessageLoop();
374 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
375 app_activity2
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
376 RunAllPendingInMessageLoop();
377 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
378 app_activity3
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
379 RunAllPendingInMessageLoop();
380 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
382 // Now there should only be the proxy activity left.
383 ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications());
384 ASSERT_EQ(app_activity_registry
,
385 AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1
, NULL
));
386 EXPECT_EQ(0, app_activity_registry
->NumberOfActivities());
387 Activity
* activity_proxy
= app_activity_registry
->unloaded_activity_proxy();
388 ASSERT_TRUE(activity_proxy
);
389 EXPECT_NE(app_activity1
, activity_proxy
);
390 EXPECT_NE(app_activity2
, activity_proxy
);
391 EXPECT_NE(app_activity3
, activity_proxy
);
392 EXPECT_EQ(Activity::ACTIVITY_UNLOADED
, activity_proxy
->GetCurrentState());
394 // Close the proxy object and make sure that nothing bad happens.
395 DeleteActivity(activity_proxy
);
397 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
398 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
399 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
402 // Test that activating the proxy will reload the application.
403 TEST_F(AppActivityTest
, TestUnloadWithReload
) {
404 // We do not want the ResourceManager to interfere with this test. In this
405 // case it would (dependent on its current internal implementation)
406 // automatically re-load the unloaded activity if it is in an "active"
408 DisableResourceManager();
409 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
411 TestAppActivity
* app_activity
= CreateAppActivity(kDummyApp1
);
412 AppActivityRegistry
* app_activity_registry
=
413 app_activity
->app_activity_registry();
415 // Unload the activity.
416 app_activity
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
417 RunAllPendingInMessageLoop();
418 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
420 // Try to activate the activity again. This will force the application to
422 Activity
* activity_proxy
= app_activity_registry
->unloaded_activity_proxy();
423 activity_proxy
->SetCurrentState(Activity::ACTIVITY_VISIBLE
);
424 EXPECT_EQ(1, test_extensions_delegate()->restart_called());
426 // However - the restart in this test framework does not really restart and
427 // all objects should be still there..
428 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
429 EXPECT_TRUE(app_activity_registry
->unloaded_activity_proxy());
430 Activity::Delete(app_activity_registry
->unloaded_activity_proxy());
431 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
435 } // namespace athena