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/test/athena_test_base.h"
12 #include "extensions/common/extension_set.h"
13 #include "ui/aura/window.h"
14 #include "ui/views/view.h"
15 #include "ui/views/widget/widget.h"
26 // An identifier for the running apps.
27 const char kDummyApp1
[] = "aaaaaaa";
28 const char kDummyApp2
[] = "bbbbbbb";
30 // A dummy test app activity which works without content / ShellAppWindow.
31 class TestAppActivity
: public AppActivity
{
33 explicit TestAppActivity(const std::string
& app_id
)
34 : AppActivity(app_id
),
35 view_(new views::View()),
36 current_state_(ACTIVITY_VISIBLE
) {
37 app_activity_registry_
=
38 AppRegistry::Get()->GetAppActivityRegistry(app_id
, NULL
);
39 app_activity_registry_
->RegisterAppActivity(this);
41 virtual ~TestAppActivity() {
42 app_activity_registry_
->UnregisterAppActivity(this);
45 AppActivityRegistry
* app_activity_registry() {
46 return app_activity_registry_
;
50 virtual ActivityViewModel
* GetActivityViewModel() OVERRIDE
{
53 virtual void SetCurrentState(Activity::ActivityState state
) OVERRIDE
{
54 current_state_
= state
;
56 virtual ActivityState
GetCurrentState() OVERRIDE
{
57 return current_state_
;
59 virtual bool IsVisible() OVERRIDE
{
62 virtual ActivityMediaState
GetMediaState() OVERRIDE
{
63 return Activity::ACTIVITY_MEDIA_STATE_NONE
;
65 virtual aura::Window
* GetWindow() OVERRIDE
{
66 return view_
->GetWidget()->GetNativeWindow();
70 virtual content::WebContents
* GetWebContents() OVERRIDE
{ return NULL
; }
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 void CreateOverviewModeImage() OVERRIDE
{}
81 // If known the registry which holds all activities for the associated app.
82 AppActivityRegistry
* app_activity_registry_
;
84 // The title of the activity.
85 base::string16 title_
;
90 // The current state for this activity.
91 ActivityState current_state_
;
93 DISALLOW_COPY_AND_ASSIGN(TestAppActivity
);
96 // An AppContentDelegateClass which we can query for call stats.
97 class TestExtensionsDelegate
: public ExtensionsDelegate
{
99 TestExtensionsDelegate() : unload_called_(0), restart_called_(0) {}
100 virtual ~TestExtensionsDelegate() {}
102 int unload_called() const { return unload_called_
; }
103 int restart_called() const { return restart_called_
; }
105 // ExtensionsDelegate:
106 virtual content::BrowserContext
* GetBrowserContext() const OVERRIDE
{
109 virtual const extensions::ExtensionSet
& GetInstalledExtensions() OVERRIDE
{
110 return extension_set_
;
112 // Unload an application. Returns true when unloaded.
113 virtual bool UnloadApp(const std::string
& app_id
) OVERRIDE
{
115 // Since we did not close anything we let the framework clean up.
118 // Restarts an application. Returns true when the restart was initiated.
119 virtual bool LaunchApp(const std::string
& app_id
) OVERRIDE
{
128 extensions::ExtensionSet extension_set_
;
130 DISALLOW_COPY_AND_ASSIGN(TestExtensionsDelegate
);
136 class AppActivityTest
: public AthenaTestBase
{
138 AppActivityTest() : test_extensions_delegate_(NULL
) {}
139 virtual ~AppActivityTest() {}
142 virtual void SetUp() OVERRIDE
{
143 AthenaTestBase::SetUp();
144 // Create and install our TestAppContentDelegate with instrumentation.
145 ExtensionsDelegate::Shutdown();
146 // The instance will be deleted by ExtensionsDelegate::Shutdown().
147 test_extensions_delegate_
= new TestExtensionsDelegate();
150 // A function to create an Activity.
151 TestAppActivity
* CreateAppActivity(const std::string
& app_id
) {
152 TestAppActivity
* activity
= new TestAppActivity(app_id
);
153 ActivityManager::Get()->AddActivity(activity
);
157 void CloseActivity(Activity
* activity
) {
159 RunAllPendingInMessageLoop();
162 // Get the position of the activity in the navigation history.
163 int GetActivityPosition(Activity
* activity
) {
164 aura::Window
* window
= activity
->GetActivityViewModel()->GetContentsView()
165 ->GetWidget()->GetNativeWindow();
166 aura::Window::Windows windows
= activity
->GetWindow()->parent()->children();
167 for (size_t i
= 0; i
< windows
.size(); i
++) {
168 if (windows
[i
] == window
)
175 TestExtensionsDelegate
* test_extensions_delegate() {
176 return test_extensions_delegate_
;
180 TestExtensionsDelegate
* test_extensions_delegate_
;
182 DISALLOW_COPY_AND_ASSIGN(AppActivityTest
);
185 // Only creates one activity and destroys it.
186 TEST_F(AppActivityTest
, OneAppActivity
) {
187 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
189 TestAppActivity
* app_activity
= CreateAppActivity(kDummyApp1
);
190 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
191 EXPECT_EQ(1, app_activity
->app_activity_registry()->NumberOfActivities());
192 EXPECT_EQ(AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1
, NULL
),
193 app_activity
->app_activity_registry());
194 CloseActivity(app_activity
);
196 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
197 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
198 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
201 // Test running of two applications.
202 TEST_F(AppActivityTest
, TwoAppsWithOneActivityEach
) {
203 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
205 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
206 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
207 EXPECT_EQ(1, app_activity1
->app_activity_registry()->NumberOfActivities());
208 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp2
);
209 EXPECT_EQ(2, AppRegistry::Get()->NumberOfApplications());
210 EXPECT_EQ(1, app_activity2
->app_activity_registry()->NumberOfActivities());
211 EXPECT_EQ(1, app_activity1
->app_activity_registry()->NumberOfActivities());
212 CloseActivity(app_activity1
);
213 CloseActivity(app_activity2
);
215 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
216 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
217 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
220 // Create and destroy two activities for the same application.
221 TEST_F(AppActivityTest
, TwoAppActivities
) {
222 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
224 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
225 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp1
);
226 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
227 EXPECT_EQ(2, app_activity1
->app_activity_registry()->NumberOfActivities());
228 EXPECT_EQ(app_activity1
->app_activity_registry(),
229 app_activity2
->app_activity_registry());
230 CloseActivity(app_activity1
);
231 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
232 EXPECT_EQ(1, app_activity2
->app_activity_registry()->NumberOfActivities());
233 CloseActivity(app_activity2
);
235 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
237 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
238 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp1
);
239 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
240 EXPECT_EQ(2, app_activity1
->app_activity_registry()->NumberOfActivities());
241 EXPECT_EQ(app_activity1
->app_activity_registry(),
242 app_activity2
->app_activity_registry());
243 CloseActivity(app_activity2
);
244 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
245 EXPECT_EQ(1, app_activity1
->app_activity_registry()->NumberOfActivities());
246 CloseActivity(app_activity1
);
248 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
249 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
250 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
253 // Test unload and the creation of the proxy, then "closing the activity".
254 TEST_F(AppActivityTest
, TestUnloadFollowedByClose
) {
255 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
257 TestAppActivity
* app_activity
= CreateAppActivity(kDummyApp1
);
258 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
259 AppActivityRegistry
* app_activity_registry
=
260 app_activity
->app_activity_registry();
261 EXPECT_EQ(1, app_activity_registry
->NumberOfActivities());
262 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity
->GetCurrentState());
264 // Calling Unload now should not do anything since at least one activity in
265 // the registry is still visible.
266 app_activity_registry
->Unload();
267 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
269 // After setting our activity to unloaded however the application should get
270 // unloaded as requested.
271 app_activity
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
272 app_activity_registry
->Unload();
273 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
275 // Check that our created application is gone, and instead a proxy got
277 ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications());
278 ASSERT_EQ(app_activity_registry
,
279 AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1
, NULL
));
280 EXPECT_EQ(0, app_activity_registry
->NumberOfActivities());
281 Activity
* activity_proxy
=
282 app_activity_registry
->unloaded_activity_proxy_for_test();
283 ASSERT_TRUE(activity_proxy
);
284 EXPECT_NE(app_activity
, activity_proxy
);
285 EXPECT_EQ(Activity::ACTIVITY_UNLOADED
, activity_proxy
->GetCurrentState());
287 // Close the proxy object and make sure that nothing bad happens.
288 CloseActivity(activity_proxy
);
290 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
291 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
292 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
295 // Test that when unloading an app while multiple apps / activities are present,
296 // the proxy gets created in the correct location.
297 TEST_F(AppActivityTest
, TestUnloadProxyLocation
) {
298 // Set up some activities for some applications.
299 TestAppActivity
* app_activity1a
= CreateAppActivity(kDummyApp1
);
300 TestAppActivity
* app_activity2a
= CreateAppActivity(kDummyApp2
);
301 TestAppActivity
* app_activity2b
= CreateAppActivity(kDummyApp2
);
302 TestAppActivity
* app_activity1b
= CreateAppActivity(kDummyApp1
);
303 EXPECT_EQ(3, GetActivityPosition(app_activity1b
));
304 EXPECT_EQ(2, GetActivityPosition(app_activity2b
));
305 EXPECT_EQ(1, GetActivityPosition(app_activity2a
));
306 EXPECT_EQ(0, GetActivityPosition(app_activity1a
));
308 // Unload an app and make sure that the proxy is in the newest activity slot.
309 AppActivityRegistry
* app_activity_registry
=
310 app_activity2a
->app_activity_registry();
311 app_activity2a
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
312 app_activity2b
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
313 app_activity2a
->app_activity_registry()->Unload();
314 EXPECT_EQ(0, app_activity_registry
->NumberOfActivities());
315 Activity
* activity_proxy
=
316 app_activity_registry
->unloaded_activity_proxy_for_test();
317 RunAllPendingInMessageLoop();
319 EXPECT_EQ(2, GetActivityPosition(app_activity1b
));
320 EXPECT_EQ(1, GetActivityPosition(activity_proxy
));
321 EXPECT_EQ(0, GetActivityPosition(app_activity1a
));
323 CloseActivity(activity_proxy
);
324 CloseActivity(app_activity1b
);
325 CloseActivity(app_activity1a
);
328 // Test that an unload with multiple activities of the same app will only unload
329 // when all activities were marked for unloading.
330 TEST_F(AppActivityTest
, TestMultipleActivityUnloadLock
) {
331 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
333 TestAppActivity
* app_activity1
= CreateAppActivity(kDummyApp1
);
334 TestAppActivity
* app_activity2
= CreateAppActivity(kDummyApp1
);
335 TestAppActivity
* app_activity3
= CreateAppActivity(kDummyApp1
);
337 // Check that we have 3 activities of the same application.
338 EXPECT_EQ(1, AppRegistry::Get()->NumberOfApplications());
339 AppActivityRegistry
* app_activity_registry
=
340 app_activity1
->app_activity_registry();
341 EXPECT_EQ(app_activity_registry
, app_activity2
->app_activity_registry());
342 EXPECT_EQ(app_activity_registry
, app_activity3
->app_activity_registry());
343 EXPECT_EQ(3, app_activity_registry
->NumberOfActivities());
344 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity1
->GetCurrentState());
345 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity2
->GetCurrentState());
346 EXPECT_EQ(Activity::ACTIVITY_VISIBLE
, app_activity3
->GetCurrentState());
348 // After setting all activities to UNLOADED the application should unload.
349 app_activity1
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
350 app_activity1
->app_activity_registry()->Unload();
351 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
352 app_activity2
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
353 app_activity2
->app_activity_registry()->Unload();
354 EXPECT_EQ(0, test_extensions_delegate()->unload_called());
355 app_activity3
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
356 app_activity3
->app_activity_registry()->Unload();
357 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
359 // Now there should only be the proxy activity left.
360 ASSERT_EQ(1, AppRegistry::Get()->NumberOfApplications());
361 ASSERT_EQ(app_activity_registry
,
362 AppRegistry::Get()->GetAppActivityRegistry(kDummyApp1
, NULL
));
363 EXPECT_EQ(0, app_activity_registry
->NumberOfActivities());
364 Activity
* activity_proxy
=
365 app_activity_registry
->unloaded_activity_proxy_for_test();
366 ASSERT_TRUE(activity_proxy
);
367 EXPECT_NE(app_activity1
, activity_proxy
);
368 EXPECT_NE(app_activity2
, activity_proxy
);
369 EXPECT_NE(app_activity3
, activity_proxy
);
370 EXPECT_EQ(Activity::ACTIVITY_UNLOADED
, activity_proxy
->GetCurrentState());
372 // Close the proxy object and make sure that nothing bad happens.
373 CloseActivity(activity_proxy
);
375 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
376 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
377 EXPECT_EQ(0, test_extensions_delegate()->restart_called());
380 // Test that activating the proxy will reload the application.
381 TEST_F(AppActivityTest
, TestUnloadWithReload
) {
382 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
384 TestAppActivity
* app_activity
= CreateAppActivity(kDummyApp1
);
385 AppActivityRegistry
* app_activity_registry
=
386 app_activity
->app_activity_registry();
388 // Unload the activity.
389 app_activity
->SetCurrentState(Activity::ACTIVITY_UNLOADED
);
390 app_activity_registry
->Unload();
391 EXPECT_EQ(1, test_extensions_delegate()->unload_called());
393 // Try to activate the activity again. This will force the application to
395 Activity
* activity_proxy
=
396 app_activity_registry
->unloaded_activity_proxy_for_test();
397 activity_proxy
->SetCurrentState(Activity::ACTIVITY_VISIBLE
);
398 EXPECT_EQ(1, test_extensions_delegate()->restart_called());
400 // However - the restart in this test framework does not really restart and
401 // all objects should be gone now.
402 EXPECT_EQ(0, AppRegistry::Get()->NumberOfApplications());
406 } // namespace athena