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 "chrome/browser/apps/app_browsertest_util.h"
6 #include "chrome/browser/extensions/extension_service.h"
7 #include "chrome/browser/extensions/extension_system.h"
8 #include "chrome/browser/extensions/extension_test_message_listener.h"
9 #include "chrome/common/extensions/api/alarms.h"
10 #include "content/public/test/browser_test.h"
11 #include "content/public/test/test_utils.h"
12 #include "extensions/browser/event_router.h"
13 #include "extensions/browser/process_manager.h"
14 #include "extensions/common/switches.h"
16 using extensions::Event
;
17 using extensions::EventRouter
;
18 using extensions::Extension
;
19 using extensions::ExtensionSystem
;
20 using extensions::PlatformAppBrowserTest
;
24 namespace alarms
= extensions::api::alarms
;
26 const char kDispatchEventTestApp
[] =
27 "platform_apps/ephemeral_apps/dispatch_event";
29 const char kMessagingReceiverApp
[] =
30 "platform_apps/ephemeral_apps/messaging_receiver";
32 const char kMessagingReceiverAppV2
[] =
33 "platform_apps/ephemeral_apps/messaging_receiver2";
35 class EphemeralAppBrowserTest
: public PlatformAppBrowserTest
{
37 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
38 // Skip PlatformAppBrowserTest, which sets different values for the switches
40 ExtensionBrowserTest::SetUpCommandLine(command_line
);
42 // Make event pages get suspended immediately.
43 command_line
->AppendSwitchASCII(
44 extensions::switches::kEventPageIdleTime
, "10");
45 command_line
->AppendSwitchASCII(
46 extensions::switches::kEventPageSuspendingTime
, "10");
49 const Extension
* InstallEphemeralApp(const char* test_path
) {
50 base::FilePath path
= test_data_dir_
.AppendASCII(test_path
);
51 const Extension
* extension
=
52 InstallExtensionWithSourceAndFlags(
55 extensions::Manifest::UNPACKED
,
56 Extension::IS_EPHEMERAL
);
60 const Extension
* InstallAndLaunchEphemeralApp(const char* test_path
) {
61 ExtensionTestMessageListener
launched_listener("launched", false);
62 const Extension
* extension
= InstallEphemeralApp(test_path
);
63 EXPECT_TRUE(extension
);
67 LaunchPlatformApp(extension
);
68 bool wait_result
= launched_listener
.WaitUntilSatisfied();
69 EXPECT_TRUE(wait_result
);
76 void CloseApp(const std::string
& app_id
) {
77 content::WindowedNotificationObserver
event_page_destroyed_signal(
78 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED
,
79 content::Source
<Profile
>(browser()->profile()));
81 EXPECT_EQ(1U, GetShellWindowCountForApp(app_id
));
82 apps::ShellWindow
* shell_window
= GetFirstShellWindowForApp(app_id
);
83 ASSERT_TRUE(shell_window
);
84 CloseShellWindow(shell_window
);
86 event_page_destroyed_signal
.Wait();
89 void VerifyAppNotLoaded(const std::string
& app_id
) {
90 EXPECT_FALSE(ExtensionSystem::Get(browser()->profile())->
91 process_manager()->GetBackgroundHostForExtension(app_id
));
94 void DispatchAlarmEvent(EventRouter
* event_router
,
95 const std::string
& app_id
) {
96 alarms::Alarm dummy_alarm
;
97 dummy_alarm
.name
= "test_alarm";
99 scoped_ptr
<base::ListValue
> args(new base::ListValue());
100 args
->Append(dummy_alarm
.ToValue().release());
101 scoped_ptr
<Event
> event(new Event(alarms::OnAlarm::kEventName
,
104 event_router
->DispatchEventToExtension(app_id
, event
.Pass());
110 // Verify that ephemeral apps can be launched and receive system events when
111 // they are running. Once they are inactive they should not receive system
113 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, EventDispatchWhenLaunched
) {
114 const Extension
* extension
=
115 InstallAndLaunchEphemeralApp(kDispatchEventTestApp
);
116 ASSERT_TRUE(extension
);
118 // Send a fake alarm event to the app and verify that a response is
120 EventRouter
* event_router
=
121 ExtensionSystem::Get(browser()->profile())->event_router();
122 ASSERT_TRUE(event_router
);
124 ExtensionTestMessageListener
alarm_received_listener("alarm_received", false);
125 DispatchAlarmEvent(event_router
, extension
->id());
126 ASSERT_TRUE(alarm_received_listener
.WaitUntilSatisfied());
128 CloseApp(extension
->id());
130 // The app needs to be launched once in order to have the onAlarm() event
132 ASSERT_TRUE(event_router
->ExtensionHasEventListener(
133 extension
->id(), alarms::OnAlarm::kEventName
));
135 // Dispatch the alarm event again and verify that the event page did not get
136 // loaded for the app.
137 DispatchAlarmEvent(event_router
, extension
->id());
138 VerifyAppNotLoaded(extension
->id());
141 // Verify that ephemeral apps will receive messages while they are running.
142 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, ReceiveMessagesWhenLaunched
) {
143 const Extension
* receiver
=
144 InstallAndLaunchEphemeralApp(kMessagingReceiverApp
);
145 ASSERT_TRUE(receiver
);
147 // Verify that messages are received while the app is running.
148 ExtensionApiTest::ResultCatcher result_catcher
;
149 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success");
150 EXPECT_TRUE(result_catcher
.GetNextResult());
152 CloseApp(receiver
->id());
154 // Verify that messages are not received while the app is inactive.
155 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail");
156 EXPECT_TRUE(result_catcher
.GetNextResult());
159 // Verify that an updated ephemeral app will still have its ephemeral flag
161 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest
, UpdateEphemeralApp
) {
162 const Extension
* app_v1
= InstallEphemeralApp(kMessagingReceiverApp
);
164 ASSERT_TRUE(app_v1
->is_ephemeral());
165 std::string app_id
= app_v1
->id();
166 base::Version app_original_version
= *app_v1
->version();
167 app_v1
= NULL
; // The extension object will be destroyed during update.
169 // Pack version 2 of the app.
170 base::ScopedTempDir temp_dir
;
171 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
173 base::FilePath crx_path
= temp_dir
.path().AppendASCII("temp.crx");
174 if (!base::DeleteFile(crx_path
, false)) {
175 ADD_FAILURE() << "Failed to delete crx: " << crx_path
.value();
179 base::FilePath app_v2_path
= PackExtensionWithOptions(
180 test_data_dir_
.AppendASCII(kMessagingReceiverAppV2
),
182 test_data_dir_
.AppendASCII(kMessagingReceiverApp
).ReplaceExtension(
183 FILE_PATH_LITERAL(".pem")),
185 ASSERT_FALSE(app_v2_path
.empty());
187 // Update the ephemeral app and wait for the update to finish.
188 extensions::CrxInstaller
* crx_installer
= NULL
;
189 content::WindowedNotificationObserver
windowed_observer(
190 chrome::NOTIFICATION_CRX_INSTALLER_DONE
,
191 content::Source
<extensions::CrxInstaller
>(crx_installer
));
192 ExtensionService
* service
=
193 ExtensionSystem::Get(browser()->profile())->extension_service();
195 service
->UpdateExtension(app_id
, app_v2_path
, GURL(), &crx_installer
));
196 windowed_observer
.Wait();
198 const Extension
* app_v2
= service
->GetExtensionById(app_id
, false);
200 EXPECT_TRUE(app_v2
->version()->CompareTo(app_original_version
) > 0);
201 EXPECT_TRUE(app_v2
->is_ephemeral());