OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include "chrome/browser/apps/ephemeral_app_browsertest.h" |
| 6 |
| 7 #include <vector> |
| 8 |
5 #include "apps/saved_files_service.h" | 9 #include "apps/saved_files_service.h" |
6 #include "base/files/scoped_temp_dir.h" | 10 #include "base/files/scoped_temp_dir.h" |
| 11 #include "base/scoped_observer.h" |
7 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
8 #include "chrome/browser/apps/app_browsertest_util.h" | 13 #include "chrome/browser/apps/app_browsertest_util.h" |
9 #include "chrome/browser/apps/ephemeral_app_service.h" | 14 #include "chrome/browser/apps/ephemeral_app_service.h" |
10 #include "chrome/browser/extensions/api/file_system/file_system_api.h" | 15 #include "chrome/browser/extensions/api/file_system/file_system_api.h" |
| 16 #include "chrome/browser/extensions/app_sync_data.h" |
11 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/extension_sync_service.h" |
12 #include "chrome/browser/extensions/extension_test_message_listener.h" | 19 #include "chrome/browser/extensions/extension_test_message_listener.h" |
13 #include "chrome/browser/extensions/extension_util.h" | 20 #include "chrome/browser/extensions/extension_util.h" |
14 #include "chrome/browser/notifications/desktop_notification_service.h" | 21 #include "chrome/browser/notifications/desktop_notification_service.h" |
15 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | 22 #include "chrome/browser/notifications/desktop_notification_service_factory.h" |
| 23 #include "chrome/common/chrome_switches.h" |
16 #include "chrome/common/extensions/api/alarms.h" | 24 #include "chrome/common/extensions/api/alarms.h" |
17 #include "content/public/test/browser_test.h" | 25 #include "content/public/test/browser_test.h" |
18 #include "content/public/test/test_utils.h" | 26 #include "content/public/test/test_utils.h" |
| 27 #include "extensions/browser/app_sorting.h" |
19 #include "extensions/browser/event_router.h" | 28 #include "extensions/browser/event_router.h" |
20 #include "extensions/browser/extension_prefs.h" | 29 #include "extensions/browser/extension_prefs.h" |
| 30 #include "extensions/browser/extension_registry.h" |
| 31 #include "extensions/browser/extension_registry_observer.h" |
21 #include "extensions/browser/extension_system.h" | 32 #include "extensions/browser/extension_system.h" |
22 #include "extensions/browser/extension_util.h" | 33 #include "extensions/browser/extension_util.h" |
23 #include "extensions/browser/process_manager.h" | 34 #include "extensions/browser/process_manager.h" |
| 35 #include "extensions/common/extension.h" |
24 #include "extensions/common/switches.h" | 36 #include "extensions/common/switches.h" |
| 37 #include "sync/api/fake_sync_change_processor.h" |
| 38 #include "sync/api/sync_change_processor_wrapper_for_test.h" |
| 39 #include "sync/api/sync_error_factory_mock.h" |
25 #include "ui/message_center/message_center.h" | 40 #include "ui/message_center/message_center.h" |
26 #include "ui/message_center/notifier_settings.h" | 41 #include "ui/message_center/notifier_settings.h" |
27 | 42 |
| 43 using extensions::AppSyncData; |
28 using extensions::Event; | 44 using extensions::Event; |
29 using extensions::EventRouter; | 45 using extensions::EventRouter; |
30 using extensions::Extension; | 46 using extensions::Extension; |
31 using extensions::ExtensionInfo; | 47 using extensions::ExtensionInfo; |
32 using extensions::ExtensionPrefs; | 48 using extensions::ExtensionPrefs; |
| 49 using extensions::ExtensionRegistry; |
| 50 using extensions::ExtensionRegistryObserver; |
33 using extensions::ExtensionSystem; | 51 using extensions::ExtensionSystem; |
34 using extensions::Manifest; | 52 using extensions::Manifest; |
35 using extensions::PlatformAppBrowserTest; | |
36 | 53 |
37 namespace { | 54 namespace { |
38 | 55 |
39 namespace alarms = extensions::api::alarms; | 56 namespace alarms = extensions::api::alarms; |
40 | 57 |
41 const char kDispatchEventTestApp[] = "ephemeral_apps/dispatch_event"; | 58 const char kDispatchEventTestApp[] = "ephemeral_apps/dispatch_event"; |
42 const char kMessagingReceiverApp[] = "ephemeral_apps/messaging_receiver"; | |
43 const char kMessagingReceiverAppV2[] = "ephemeral_apps/messaging_receiver2"; | |
44 const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings"; | 59 const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings"; |
45 const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries"; | 60 const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries"; |
46 const char kRetainDataApp[] = "ephemeral_apps/retain_data"; | 61 const char kRetainDataApp[] = "ephemeral_apps/retain_data"; |
47 | 62 |
48 typedef std::vector<message_center::Notifier*> NotifierList; | 63 typedef std::vector<message_center::Notifier*> NotifierList; |
49 | 64 |
50 bool IsNotifierInList(const message_center::NotifierId& notifier_id, | 65 bool IsNotifierInList(const message_center::NotifierId& notifier_id, |
51 const NotifierList& notifiers) { | 66 const NotifierList& notifiers) { |
52 for (NotifierList::const_iterator it = notifiers.begin(); | 67 for (NotifierList::const_iterator it = notifiers.begin(); |
53 it != notifiers.end(); ++it) { | 68 it != notifiers.end(); ++it) { |
54 const message_center::Notifier* notifier = *it; | 69 const message_center::Notifier* notifier = *it; |
55 if (notifier->notifier_id == notifier_id) | 70 if (notifier->notifier_id == notifier_id) |
56 return true; | 71 return true; |
57 } | 72 } |
58 | 73 |
59 return false; | 74 return false; |
60 } | 75 } |
61 | 76 |
62 bool IsAppInExtensionsInfo(const ExtensionPrefs::ExtensionsInfo& ext_info, | 77 bool IsAppInExtensionsInfo(const ExtensionPrefs::ExtensionsInfo& ext_info, |
63 const std::string& extension_id) { | 78 const std::string& extension_id) { |
64 for (size_t i = 0; i < ext_info.size(); ++i) { | 79 for (size_t i = 0; i < ext_info.size(); ++i) { |
65 ExtensionInfo* info = ext_info.at(i).get(); | 80 ExtensionInfo* info = ext_info.at(i).get(); |
66 if (info->extension_id == extension_id) | 81 if (info->extension_id == extension_id) |
67 return true; | 82 return true; |
68 } | 83 } |
69 | 84 |
70 return false; | 85 return false; |
71 } | 86 } |
72 | 87 |
| 88 // Saves some parameters from the extension installed notification in order |
| 89 // to verify them in tests. |
| 90 class InstallObserver : public ExtensionRegistryObserver { |
| 91 public: |
| 92 struct InstallParameters { |
| 93 std::string id; |
| 94 bool is_update; |
| 95 bool from_ephemeral; |
| 96 |
| 97 InstallParameters( |
| 98 const std::string& id, |
| 99 bool is_update, |
| 100 bool from_ephemeral) |
| 101 : id(id), is_update(is_update), from_ephemeral(from_ephemeral) {} |
| 102 }; |
| 103 |
| 104 explicit InstallObserver(Profile* profile) : registry_observer_(this) { |
| 105 registry_observer_.Add(ExtensionRegistry::Get(profile)); |
| 106 } |
| 107 |
| 108 virtual ~InstallObserver() {} |
| 109 |
| 110 const InstallParameters& Last() { |
| 111 CHECK(!install_params_.empty()); |
| 112 return install_params_.back(); |
| 113 } |
| 114 |
| 115 private: |
| 116 virtual void OnExtensionWillBeInstalled( |
| 117 content::BrowserContext* browser_context, |
| 118 const Extension* extension, |
| 119 bool is_update, |
| 120 bool from_ephemeral, |
| 121 const std::string& old_name) OVERRIDE { |
| 122 install_params_.push_back( |
| 123 InstallParameters(extension->id(), is_update, from_ephemeral)); |
| 124 } |
| 125 |
| 126 std::vector<InstallParameters> install_params_; |
| 127 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> |
| 128 registry_observer_; |
| 129 }; |
| 130 |
73 } // namespace | 131 } // namespace |
74 | 132 |
75 class EphemeralAppBrowserTest : public PlatformAppBrowserTest { | |
76 protected: | |
77 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
78 // Skip PlatformAppBrowserTest, which sets different values for the switches | |
79 // below. | |
80 ExtensionBrowserTest::SetUpCommandLine(command_line); | |
81 | 133 |
82 // Make event pages get suspended immediately. | 134 // EphemeralAppTestBase: |
83 command_line->AppendSwitchASCII( | 135 |
84 extensions::switches::kEventPageIdleTime, "10"); | 136 const char EphemeralAppTestBase::kMessagingReceiverApp[] = |
85 command_line->AppendSwitchASCII( | 137 "ephemeral_apps/messaging_receiver"; |
86 extensions::switches::kEventPageSuspendingTime, "10"); | 138 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] = |
| 139 "ephemeral_apps/messaging_receiver2"; |
| 140 |
| 141 EphemeralAppTestBase::EphemeralAppTestBase() {} |
| 142 |
| 143 EphemeralAppTestBase::~EphemeralAppTestBase() {} |
| 144 |
| 145 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) { |
| 146 // Skip PlatformAppBrowserTest, which sets different values for the switches |
| 147 // below. |
| 148 ExtensionBrowserTest::SetUpCommandLine(command_line); |
| 149 |
| 150 // Make event pages get suspended immediately. |
| 151 command_line->AppendSwitchASCII( |
| 152 extensions::switches::kEventPageIdleTime, "10"); |
| 153 command_line->AppendSwitchASCII( |
| 154 extensions::switches::kEventPageSuspendingTime, "10"); |
| 155 |
| 156 // Enable ephemeral apps flag. |
| 157 command_line->AppendSwitch(switches::kEnableEphemeralApps); |
| 158 } |
| 159 |
| 160 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) { |
| 161 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); |
| 162 } |
| 163 |
| 164 const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
| 165 const char* test_path, Manifest::Location manifest_location) { |
| 166 const Extension* extension = InstallEphemeralAppWithSourceAndFlags( |
| 167 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS); |
| 168 EXPECT_TRUE(extension); |
| 169 if (extension) |
| 170 EXPECT_TRUE(extensions::util::IsEphemeralApp(extension->id(), profile())); |
| 171 return extension; |
| 172 } |
| 173 |
| 174 const Extension* EphemeralAppTestBase::InstallEphemeralApp( |
| 175 const char* test_path) { |
| 176 return InstallEphemeralApp(test_path, Manifest::INTERNAL); |
| 177 } |
| 178 |
| 179 const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp( |
| 180 const char* test_path) { |
| 181 ExtensionTestMessageListener launched_listener("launched", false); |
| 182 const Extension* extension = InstallEphemeralApp(test_path); |
| 183 EXPECT_TRUE(extension); |
| 184 if (!extension) |
| 185 return NULL; |
| 186 |
| 187 LaunchPlatformApp(extension); |
| 188 bool wait_result = launched_listener.WaitUntilSatisfied(); |
| 189 EXPECT_TRUE(wait_result); |
| 190 if (!wait_result) |
| 191 return NULL; |
| 192 |
| 193 return extension; |
| 194 } |
| 195 |
| 196 const Extension* EphemeralAppTestBase::UpdateEphemeralApp( |
| 197 const std::string& app_id, |
| 198 const base::FilePath& test_dir, |
| 199 const base::FilePath& pem_path) { |
| 200 // Pack a new version of the app. |
| 201 base::ScopedTempDir temp_dir; |
| 202 EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 203 |
| 204 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx"); |
| 205 if (!base::DeleteFile(crx_path, false)) { |
| 206 ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value(); |
| 207 return NULL; |
87 } | 208 } |
88 | 209 |
89 base::FilePath GetTestPath(const char* test_path) { | 210 base::FilePath app_v2_path = PackExtensionWithOptions( |
90 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); | 211 test_dir, crx_path, pem_path, base::FilePath()); |
91 } | 212 EXPECT_FALSE(app_v2_path.empty()); |
92 | 213 |
93 const Extension* InstallEphemeralApp(const char* test_path, | 214 // Update the ephemeral app and wait for the update to finish. |
94 Manifest::Location manifest_location) { | 215 extensions::CrxInstaller* crx_installer = NULL; |
95 const Extension* extension = | 216 content::WindowedNotificationObserver windowed_observer( |
96 InstallEphemeralAppWithSourceAndFlags( | 217 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
97 GetTestPath(test_path), | 218 content::Source<extensions::CrxInstaller>(crx_installer)); |
98 1, | 219 ExtensionService* service = |
99 manifest_location, | 220 ExtensionSystem::Get(profile())->extension_service(); |
100 Extension::NO_FLAGS); | 221 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true, |
101 return extension; | 222 &crx_installer)); |
102 } | 223 windowed_observer.Wait(); |
103 | 224 |
104 const Extension* InstallEphemeralApp(const char* test_path) { | 225 return service->GetExtensionById(app_id, false); |
105 return InstallEphemeralApp(test_path, Manifest::INTERNAL); | 226 } |
106 } | |
107 | 227 |
108 const Extension* InstallAndLaunchEphemeralApp(const char* test_path) { | 228 void EphemeralAppTestBase::PromoteEphemeralApp( |
109 ExtensionTestMessageListener launched_listener("launched", false); | 229 const extensions::Extension* app) { |
110 const Extension* extension = InstallEphemeralApp(test_path); | 230 ExtensionService* extension_service = |
111 EXPECT_TRUE(extension); | 231 ExtensionSystem::Get(profile())->extension_service(); |
112 if (!extension) | 232 ASSERT_TRUE(extension_service); |
113 return NULL; | 233 extension_service->PromoteEphemeralApp(app, false); |
| 234 } |
114 | 235 |
115 LaunchPlatformApp(extension); | 236 void EphemeralAppTestBase::CloseApp(const std::string& app_id) { |
116 bool wait_result = launched_listener.WaitUntilSatisfied(); | 237 content::WindowedNotificationObserver event_page_destroyed_signal( |
117 EXPECT_TRUE(wait_result); | 238 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, |
118 if (!wait_result) | 239 content::Source<Profile>(profile())); |
119 return NULL; | |
120 | 240 |
121 return extension; | 241 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); |
122 } | 242 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id); |
| 243 ASSERT_TRUE(app_window); |
| 244 CloseAppWindow(app_window); |
123 | 245 |
| 246 event_page_destroyed_signal.Wait(); |
| 247 } |
| 248 |
| 249 void EphemeralAppTestBase::EvictApp(const std::string& app_id) { |
| 250 // Uninstall the app, which is what happens when ephemeral apps get evicted |
| 251 // from the cache. |
| 252 content::WindowedNotificationObserver uninstalled_signal( |
| 253 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, |
| 254 content::Source<Profile>(profile())); |
| 255 |
| 256 ExtensionService* service = |
| 257 ExtensionSystem::Get(profile())->extension_service(); |
| 258 ASSERT_TRUE(service); |
| 259 service->UninstallExtension(app_id, false, NULL); |
| 260 |
| 261 uninstalled_signal.Wait(); |
| 262 } |
| 263 |
| 264 // EphemeralAppBrowserTest: |
| 265 |
| 266 class EphemeralAppBrowserTest : public EphemeralAppTestBase { |
| 267 protected: |
124 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { | 268 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { |
125 ExtensionTestMessageListener launched_listener("launched", true); | 269 ExtensionTestMessageListener launched_listener("launched", true); |
126 LaunchPlatformApp(app); | 270 LaunchPlatformApp(app); |
127 if (!launched_listener.WaitUntilSatisfied()) { | 271 if (!launched_listener.WaitUntilSatisfied()) { |
128 message_ = "Failed to receive launched message from test"; | 272 message_ = "Failed to receive launched message from test"; |
129 return false; | 273 return false; |
130 } | 274 } |
131 | 275 |
132 ResultCatcher catcher; | 276 ResultCatcher catcher; |
133 launched_listener.Reply(test_name); | 277 launched_listener.Reply(test_name); |
134 | 278 |
135 bool result = catcher.GetNextResult(); | 279 bool result = catcher.GetNextResult(); |
136 message_ = catcher.message(); | 280 message_ = catcher.message(); |
137 | 281 |
138 CloseApp(app->id()); | 282 CloseApp(app->id()); |
139 return result; | 283 return result; |
140 } | 284 } |
141 | 285 |
142 void CloseApp(const std::string& app_id) { | |
143 content::WindowedNotificationObserver event_page_destroyed_signal( | |
144 chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, | |
145 content::Source<Profile>(browser()->profile())); | |
146 | |
147 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); | |
148 apps::AppWindow* app_window = GetFirstAppWindowForApp(app_id); | |
149 ASSERT_TRUE(app_window); | |
150 CloseAppWindow(app_window); | |
151 | |
152 event_page_destroyed_signal.Wait(); | |
153 } | |
154 | |
155 void EvictApp(const std::string& app_id) { | |
156 // Uninstall the app, which is what happens when ephemeral apps get evicted | |
157 // from the cache. | |
158 content::WindowedNotificationObserver uninstalled_signal( | |
159 chrome::NOTIFICATION_EXTENSION_UNINSTALLED, | |
160 content::Source<Profile>(browser()->profile())); | |
161 | |
162 ExtensionService* service = | |
163 ExtensionSystem::Get(browser()->profile())->extension_service(); | |
164 ASSERT_TRUE(service); | |
165 service->UninstallExtension(app_id, false, NULL); | |
166 | |
167 uninstalled_signal.Wait(); | |
168 } | |
169 | |
170 void VerifyAppNotLoaded(const std::string& app_id) { | 286 void VerifyAppNotLoaded(const std::string& app_id) { |
171 EXPECT_FALSE(ExtensionSystem::Get(browser()->profile())-> | 287 EXPECT_FALSE(ExtensionSystem::Get(profile())-> |
172 process_manager()->GetBackgroundHostForExtension(app_id)); | 288 process_manager()->GetBackgroundHostForExtension(app_id)); |
173 } | 289 } |
174 | 290 |
175 void DispatchAlarmEvent(EventRouter* event_router, | 291 void DispatchAlarmEvent(EventRouter* event_router, |
176 const std::string& app_id) { | 292 const std::string& app_id) { |
177 alarms::Alarm dummy_alarm; | 293 alarms::Alarm dummy_alarm; |
178 dummy_alarm.name = "test_alarm"; | 294 dummy_alarm.name = "test_alarm"; |
179 | 295 |
180 scoped_ptr<base::ListValue> args(new base::ListValue()); | 296 scoped_ptr<base::ListValue> args(new base::ListValue()); |
181 args->Append(dummy_alarm.ToValue().release()); | 297 args->Append(dummy_alarm.ToValue().release()); |
182 scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, | 298 scoped_ptr<Event> event(new Event(alarms::OnAlarm::kEventName, |
183 args.Pass())); | 299 args.Pass())); |
184 | 300 |
185 event_router->DispatchEventToExtension(app_id, event.Pass()); | 301 event_router->DispatchEventToExtension(app_id, event.Pass()); |
186 } | 302 } |
187 | 303 |
188 void GarbageCollectData() { | 304 void GarbageCollectData() { |
189 EphemeralAppService* service = | 305 EphemeralAppService* service = |
190 EphemeralAppService::Get(browser()->profile()); | 306 EphemeralAppService::Get(profile()); |
191 ASSERT_TRUE(service); | 307 ASSERT_TRUE(service); |
192 service->GarbageCollectData(); | 308 service->GarbageCollectData(); |
193 } | 309 } |
| 310 |
| 311 const Extension* ReplaceEphemeralApp(const std::string& app_id, |
| 312 const char* test_path) { |
| 313 return UpdateExtensionWaitForIdle(app_id, GetTestPath(test_path), 0); |
| 314 } |
| 315 |
| 316 void VerifyPromotedApp(const std::string& app_id, |
| 317 ExtensionRegistry::IncludeFlag expected_set) { |
| 318 const Extension* app = ExtensionRegistry::Get(profile())->GetExtensionById( |
| 319 app_id, expected_set); |
| 320 ASSERT_TRUE(app); |
| 321 |
| 322 // The app should not be ephemeral. |
| 323 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 324 ASSERT_TRUE(prefs); |
| 325 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); |
| 326 |
| 327 // Check sort ordinals. |
| 328 extensions::AppSorting* app_sorting = prefs->app_sorting(); |
| 329 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); |
| 330 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid()); |
| 331 } |
| 332 |
| 333 void InitSyncService() { |
| 334 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
| 335 sync_service->MergeDataAndStartSyncing( |
| 336 syncer::APPS, |
| 337 syncer::SyncDataList(), |
| 338 scoped_ptr<syncer::SyncChangeProcessor>( |
| 339 new syncer::SyncChangeProcessorWrapperForTest( |
| 340 &mock_sync_processor_)), |
| 341 scoped_ptr<syncer::SyncErrorFactory>( |
| 342 new syncer::SyncErrorFactoryMock())); |
| 343 } |
| 344 |
| 345 scoped_ptr<AppSyncData> GetFirstSyncChangeForApp(const std::string& id) { |
| 346 scoped_ptr<AppSyncData> sync_data; |
| 347 for (syncer::SyncChangeList::iterator it = |
| 348 mock_sync_processor_.changes().begin(); |
| 349 it != mock_sync_processor_.changes().end(); ++it) { |
| 350 sync_data.reset(new AppSyncData(*it)); |
| 351 if (sync_data->id() == id) |
| 352 return sync_data.Pass(); |
| 353 } |
| 354 |
| 355 return scoped_ptr<AppSyncData>(); |
| 356 } |
| 357 |
| 358 void VerifySyncChange(const AppSyncData* sync_change, bool expect_enabled) { |
| 359 ASSERT_TRUE(sync_change); |
| 360 EXPECT_TRUE(sync_change->page_ordinal().IsValid()); |
| 361 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid()); |
| 362 EXPECT_FALSE(sync_change->uninstalled()); |
| 363 EXPECT_EQ(expect_enabled, sync_change->extension_sync_data().enabled()); |
| 364 } |
| 365 |
| 366 syncer::FakeSyncChangeProcessor mock_sync_processor_; |
194 }; | 367 }; |
195 | 368 |
196 // Verify that ephemeral apps can be launched and receive system events when | 369 // Verify that ephemeral apps can be launched and receive system events when |
197 // they are running. Once they are inactive they should not receive system | 370 // they are running. Once they are inactive they should not receive system |
198 // events. | 371 // events. |
199 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { | 372 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { |
200 const Extension* extension = | 373 const Extension* extension = |
201 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); | 374 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); |
202 ASSERT_TRUE(extension); | 375 ASSERT_TRUE(extension); |
203 | 376 |
204 // Send a fake alarm event to the app and verify that a response is | 377 // Send a fake alarm event to the app and verify that a response is |
205 // received. | 378 // received. |
206 EventRouter* event_router = EventRouter::Get(browser()->profile()); | 379 EventRouter* event_router = EventRouter::Get(profile()); |
207 ASSERT_TRUE(event_router); | 380 ASSERT_TRUE(event_router); |
208 | 381 |
209 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); | 382 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); |
210 DispatchAlarmEvent(event_router, extension->id()); | 383 DispatchAlarmEvent(event_router, extension->id()); |
211 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); | 384 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); |
212 | 385 |
213 CloseApp(extension->id()); | 386 CloseApp(extension->id()); |
214 | 387 |
215 // The app needs to be launched once in order to have the onAlarm() event | 388 // The app needs to be launched once in order to have the onAlarm() event |
216 // registered. | 389 // registered. |
(...skipping 22 matching lines...) Expand all Loading... |
239 // Verify that messages are not received while the app is inactive. | 412 // Verify that messages are not received while the app is inactive. |
240 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail"); | 413 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail"); |
241 EXPECT_TRUE(result_catcher.GetNextResult()); | 414 EXPECT_TRUE(result_catcher.GetNextResult()); |
242 } | 415 } |
243 | 416 |
244 // Verify that an updated ephemeral app will still have its ephemeral flag | 417 // Verify that an updated ephemeral app will still have its ephemeral flag |
245 // enabled. | 418 // enabled. |
246 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { | 419 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { |
247 const Extension* app_v1 = InstallEphemeralApp(kMessagingReceiverApp); | 420 const Extension* app_v1 = InstallEphemeralApp(kMessagingReceiverApp); |
248 ASSERT_TRUE(app_v1); | 421 ASSERT_TRUE(app_v1); |
249 ASSERT_TRUE(extensions::util::IsEphemeralApp(app_v1->id(), profile())); | |
250 std::string app_id = app_v1->id(); | 422 std::string app_id = app_v1->id(); |
251 base::Version app_original_version = *app_v1->version(); | 423 base::Version app_original_version = *app_v1->version(); |
252 app_v1 = NULL; // The extension object will be destroyed during update. | 424 app_v1 = NULL; // The extension object will be destroyed during update. |
253 | 425 |
254 // Pack version 2 of the app. | 426 // Update to version 2 of the app. |
255 base::ScopedTempDir temp_dir; | 427 InstallObserver installed_observer(profile()); |
256 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 428 const Extension* app_v2 = UpdateEphemeralApp( |
| 429 app_id, GetTestPath(kMessagingReceiverAppV2), |
| 430 GetTestPath(kMessagingReceiverApp).ReplaceExtension( |
| 431 FILE_PATH_LITERAL(".pem"))); |
257 | 432 |
258 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx"); | 433 // Check the notification parameters. |
259 if (!base::DeleteFile(crx_path, false)) { | 434 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
260 ADD_FAILURE() << "Failed to delete crx: " << crx_path.value(); | 435 EXPECT_EQ(app_id, params.id); |
261 return; | 436 EXPECT_TRUE(params.is_update); |
262 } | 437 EXPECT_FALSE(params.from_ephemeral); |
263 | 438 |
264 base::FilePath app_v2_path = PackExtensionWithOptions( | 439 // The ephemeral flag should still be enabled. |
265 GetTestPath(kMessagingReceiverAppV2), | |
266 crx_path, | |
267 GetTestPath(kMessagingReceiverApp).ReplaceExtension( | |
268 FILE_PATH_LITERAL(".pem")), | |
269 base::FilePath()); | |
270 ASSERT_FALSE(app_v2_path.empty()); | |
271 | |
272 // Update the ephemeral app and wait for the update to finish. | |
273 extensions::CrxInstaller* crx_installer = NULL; | |
274 content::WindowedNotificationObserver windowed_observer( | |
275 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | |
276 content::Source<extensions::CrxInstaller>(crx_installer)); | |
277 ExtensionService* service = | |
278 ExtensionSystem::Get(browser()->profile())->extension_service(); | |
279 EXPECT_TRUE(service->UpdateExtension(app_id, app_v2_path, true, | |
280 &crx_installer)); | |
281 windowed_observer.Wait(); | |
282 | |
283 const Extension* app_v2 = service->GetExtensionById(app_id, false); | |
284 ASSERT_TRUE(app_v2); | 440 ASSERT_TRUE(app_v2); |
285 EXPECT_TRUE(app_v2->version()->CompareTo(app_original_version) > 0); | 441 EXPECT_TRUE(app_v2->version()->CompareTo(app_original_version) > 0); |
286 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_v2->id(), profile())); | 442 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_v2->id(), profile())); |
287 } | 443 } |
288 | 444 |
289 // Verify that if notifications have been disabled for an ephemeral app, it will | 445 // Verify that if notifications have been disabled for an ephemeral app, it will |
290 // remain disabled even after being evicted from the cache. | 446 // remain disabled even after being evicted from the cache. |
291 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { | 447 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { |
292 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); | 448 const Extension* app = InstallEphemeralApp(kNotificationsTestApp); |
293 ASSERT_TRUE(app); | 449 ASSERT_TRUE(app); |
294 | 450 |
295 // Disable notifications for this app. | 451 // Disable notifications for this app. |
296 DesktopNotificationService* notification_service = | 452 DesktopNotificationService* notification_service = |
297 DesktopNotificationServiceFactory::GetForProfile(browser()->profile()); | 453 DesktopNotificationServiceFactory::GetForProfile(profile()); |
298 ASSERT_TRUE(notification_service); | 454 ASSERT_TRUE(notification_service); |
299 | 455 |
300 message_center::NotifierId notifier_id( | 456 message_center::NotifierId notifier_id( |
301 message_center::NotifierId::APPLICATION, app->id()); | 457 message_center::NotifierId::APPLICATION, app->id()); |
302 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id)); | 458 EXPECT_TRUE(notification_service->IsNotifierEnabled(notifier_id)); |
303 notification_service->SetNotifierEnabled(notifier_id, false); | 459 notification_service->SetNotifierEnabled(notifier_id, false); |
304 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id)); | 460 EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id)); |
305 | 461 |
306 // Remove the app. | 462 // Remove the app. |
307 EvictApp(app->id()); | 463 EvictApp(app->id()); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 "temp", temp_dir.path()); | 525 "temp", temp_dir.path()); |
370 | 526 |
371 // The first test opens the file and writes the file handle to local storage. | 527 // The first test opens the file and writes the file handle to local storage. |
372 const Extension* app = InstallEphemeralApp(kFileSystemTestApp, | 528 const Extension* app = InstallEphemeralApp(kFileSystemTestApp, |
373 Manifest::UNPACKED); | 529 Manifest::UNPACKED); |
374 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_; | 530 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_; |
375 | 531 |
376 // Verify that after the app has been closed, all retained entries are | 532 // Verify that after the app has been closed, all retained entries are |
377 // flushed. | 533 // flushed. |
378 std::vector<apps::SavedFileEntry> file_entries = | 534 std::vector<apps::SavedFileEntry> file_entries = |
379 apps::SavedFilesService::Get(browser()->profile()) | 535 apps::SavedFilesService::Get(profile()) |
380 ->GetAllFileEntries(app->id()); | 536 ->GetAllFileEntries(app->id()); |
381 EXPECT_TRUE(file_entries.empty()); | 537 EXPECT_TRUE(file_entries.empty()); |
382 | 538 |
383 // The second test verifies that the file cannot be reopened. | 539 // The second test verifies that the file cannot be reopened. |
384 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; | 540 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; |
385 } | 541 } |
386 | 542 |
387 // Verify that once evicted from the cache, the data of ephemeral apps will not | 543 // Verify that once evicted from the cache, the data of ephemeral apps will not |
388 // be deleted. | 544 // be deleted. |
389 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) { | 545 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) { |
390 // Phase 1 - Install the ephemeral app and write data to various storage. | 546 // Phase 1 - Install the ephemeral app and write data to various storage. |
391 const Extension* app = InstallEphemeralApp(kRetainDataApp); | 547 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
392 ASSERT_TRUE(app); | 548 ASSERT_TRUE(app); |
393 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; | 549 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; |
394 | 550 |
395 // Sanity check to ensure that the ReadData tests should pass before the app | 551 // Sanity check to ensure that the ReadData tests should pass before the app |
396 // is removed. | 552 // is removed. |
397 ASSERT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; | 553 ASSERT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; |
398 | 554 |
399 // Remove the app. | 555 // Remove the app. |
400 const std::string app_id = app->id(); | 556 const std::string app_id = app->id(); |
401 EvictApp(app->id()); | 557 EvictApp(app->id()); |
402 app = NULL; | 558 app = NULL; |
403 | 559 |
404 // The app should be in the list of evicted apps. | 560 // The app should be in the list of evicted apps. |
405 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 561 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
406 ASSERT_TRUE(prefs); | 562 ASSERT_TRUE(prefs); |
407 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 563 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
408 prefs->GetEvictedEphemeralAppsInfo()); | 564 prefs->GetEvictedEphemeralAppsInfo()); |
409 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 565 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
410 scoped_ptr<ExtensionInfo> single_extension_info( | 566 scoped_ptr<ExtensionInfo> single_extension_info( |
411 prefs->GetEvictedEphemeralAppInfo(app_id)); | 567 prefs->GetEvictedEphemeralAppInfo(app_id)); |
412 EXPECT_TRUE(single_extension_info.get()); | 568 EXPECT_TRUE(single_extension_info.get()); |
413 | 569 |
414 // The app should not be in the list of installed extensions. | 570 // The app should not be in the list of installed extensions. |
415 extensions_info = prefs->GetInstalledExtensionsInfo(); | 571 extensions_info = prefs->GetInstalledExtensionsInfo(); |
416 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 572 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
| 573 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); |
417 | 574 |
418 // Ensure the evicted app is considered to have isolated storage. This will | 575 // Ensure the evicted app is considered to have isolated storage. This will |
419 // prevent its data from getting garbage collected by | 576 // prevent its data from getting garbage collected by |
420 // ExtensionService::GarbageCollectIsolatedStorage(). | 577 // ExtensionService::GarbageCollectIsolatedStorage(). |
421 GURL site_url = extensions::util::GetSiteForExtensionId( | 578 GURL site_url = extensions::util::GetSiteForExtensionId( |
422 app_id, browser()->profile()); | 579 app_id, profile()); |
423 EXPECT_TRUE(extensions::util::SiteHasIsolatedStorage( | 580 EXPECT_TRUE(extensions::util::SiteHasIsolatedStorage( |
424 site_url, browser()->profile())); | 581 site_url, profile())); |
425 | 582 |
426 // Phase 2 - Reinstall the ephemeral app and verify that data still exists | 583 // Phase 2 - Reinstall the ephemeral app and verify that data still exists |
427 // in the storage. | 584 // in the storage. |
428 app = InstallEphemeralApp(kRetainDataApp); | 585 app = InstallEphemeralApp(kRetainDataApp); |
429 ASSERT_TRUE(app); | 586 ASSERT_TRUE(app); |
430 EXPECT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; | 587 EXPECT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_; |
431 | 588 |
432 // The app should now be in the list of installed extensions, but not in the | 589 // The app should now be in the list of installed extensions, but not in the |
433 // list of evicted apps. | 590 // list of evicted apps. |
434 extensions_info = prefs->GetInstalledExtensionsInfo(); | 591 extensions_info = prefs->GetInstalledExtensionsInfo(); |
435 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 592 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
436 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); | 593 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); |
437 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 594 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
438 single_extension_info = prefs->GetEvictedEphemeralAppInfo(app_id); | 595 single_extension_info = prefs->GetEvictedEphemeralAppInfo(app_id); |
439 EXPECT_FALSE(single_extension_info.get()); | 596 EXPECT_FALSE(single_extension_info.get()); |
| 597 EXPECT_TRUE(prefs->IsEphemeralApp(app_id)); |
440 } | 598 } |
441 | 599 |
442 // Verify that preferences are updated correctly when an evicted ephemeral app | 600 // Verify that preferences are updated correctly when an evicted ephemeral app |
443 // is re-installed permanently. | 601 // is re-installed permanently. |
444 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEvictedEphemeralApp) { | 602 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEvictedEphemeralApp) { |
445 const Extension* app = InstallEphemeralApp(kRetainDataApp); | 603 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
446 ASSERT_TRUE(app); | 604 ASSERT_TRUE(app); |
447 | 605 |
448 // Remove the app. | 606 // Remove the app. |
449 EvictApp(app->id()); | 607 EvictApp(app->id()); |
450 app = NULL; | 608 app = NULL; |
451 | 609 |
452 // Install the app permanently. | 610 // Install the app permanently. |
453 app = InstallPlatformApp(kRetainDataApp); | 611 app = InstallPlatformApp(kRetainDataApp); |
454 ASSERT_TRUE(app); | 612 ASSERT_TRUE(app); |
455 | 613 |
456 // Verify that preferences are correct. | 614 // Verify that preferences are correct. |
457 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 615 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
458 ASSERT_TRUE(prefs); | 616 ASSERT_TRUE(prefs); |
459 EXPECT_FALSE(prefs->IsEphemeralApp(app->id())); | 617 EXPECT_FALSE(prefs->IsEphemeralApp(app->id())); |
460 | 618 |
461 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 619 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
462 prefs->GetEvictedEphemeralAppsInfo()); | 620 prefs->GetEvictedEphemeralAppsInfo()); |
463 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app->id())); | 621 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app->id())); |
464 extensions_info = prefs->GetInstalledExtensionsInfo(); | 622 extensions_info = prefs->GetInstalledExtensionsInfo(); |
465 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app->id())); | 623 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app->id())); |
466 } | 624 } |
467 | 625 |
468 // Verify that the data of regular installed apps are deleted on uninstall. | 626 // Verify that the data of regular installed apps are deleted on uninstall. |
469 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RemoveInstalledData) { | 627 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RemoveInstalledData) { |
470 // Install the ephemeral app and write data to various storage. | 628 // Install the ephemeral app and write data to various storage. |
471 const Extension* app = InstallPlatformApp(kRetainDataApp); | 629 const Extension* app = InstallPlatformApp(kRetainDataApp); |
472 ASSERT_TRUE(app); | 630 ASSERT_TRUE(app); |
473 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; | 631 ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_; |
474 | 632 |
475 // Remove the app. | 633 // Remove the app. |
476 const std::string app_id = app->id(); | 634 const std::string app_id = app->id(); |
477 EvictApp(app->id()); | 635 EvictApp(app->id()); |
478 app = NULL; | 636 app = NULL; |
479 | 637 |
480 // The app should not be in the preferences. | 638 // The app should not be in the preferences. |
481 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 639 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
482 ASSERT_TRUE(prefs); | 640 ASSERT_TRUE(prefs); |
483 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 641 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
484 prefs->GetEvictedEphemeralAppsInfo()); | 642 prefs->GetEvictedEphemeralAppsInfo()); |
485 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 643 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
486 extensions_info = prefs->GetInstalledExtensionsInfo(); | 644 extensions_info = prefs->GetInstalledExtensionsInfo(); |
487 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); | 645 EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id)); |
488 | 646 |
489 // Reinstall the app and verify that all data has been reset. | 647 // Reinstall the app and verify that all data has been reset. |
490 app = InstallPlatformApp(kRetainDataApp); | 648 app = InstallPlatformApp(kRetainDataApp); |
491 ASSERT_TRUE(LaunchAppAndRunTest(app, "DataReset")) << message_; | 649 ASSERT_TRUE(LaunchAppAndRunTest(app, "DataReset")) << message_; |
(...skipping 11 matching lines...) Expand all Loading... |
503 std::string evict_app_id = evict_app->id(); | 661 std::string evict_app_id = evict_app->id(); |
504 EvictApp(evict_app_id); | 662 EvictApp(evict_app_id); |
505 evict_app = NULL; | 663 evict_app = NULL; |
506 | 664 |
507 const Extension* retain_app = InstallEphemeralApp(kDispatchEventTestApp); | 665 const Extension* retain_app = InstallEphemeralApp(kDispatchEventTestApp); |
508 ASSERT_TRUE(retain_app); | 666 ASSERT_TRUE(retain_app); |
509 std::string retain_app_id = retain_app->id(); | 667 std::string retain_app_id = retain_app->id(); |
510 EvictApp(retain_app_id); | 668 EvictApp(retain_app_id); |
511 retain_app = NULL; | 669 retain_app = NULL; |
512 | 670 |
513 ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); | 671 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
514 ASSERT_TRUE(prefs); | 672 ASSERT_TRUE(prefs); |
515 | 673 |
516 // Both apps should be in the list of evicted apps. | 674 // Both apps should be in the list of evicted apps. |
517 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( | 675 scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info( |
518 prefs->GetEvictedEphemeralAppsInfo()); | 676 prefs->GetEvictedEphemeralAppsInfo()); |
519 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); | 677 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); |
520 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); | 678 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); |
521 | 679 |
522 // Set a fake last launch time so that the ephemeral app's data will be | 680 // Set a fake last launch time so that the ephemeral app's data will be |
523 // garbage collected. | 681 // garbage collected. |
524 base::Time launch_time = | 682 base::Time launch_time = |
525 base::Time::Now() - base::TimeDelta::FromDays( | 683 base::Time::Now() - base::TimeDelta::FromDays( |
526 EphemeralAppService::kDataInactiveThreshold + 1); | 684 EphemeralAppService::kDataInactiveThreshold + 1); |
527 prefs->SetLastLaunchTime(evict_app_id, launch_time); | 685 prefs->SetLastLaunchTime(evict_app_id, launch_time); |
528 prefs->SetLastLaunchTime(retain_app_id, base::Time::Now()); | 686 prefs->SetLastLaunchTime(retain_app_id, base::Time::Now()); |
529 | 687 |
530 // Garbage collect data. | 688 // Garbage collect data. |
531 GarbageCollectData(); | 689 GarbageCollectData(); |
532 | 690 |
533 // The garbage collected app should no longer be in the preferences. | 691 // The garbage collected app should no longer be in the preferences. |
534 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); | 692 extensions_info = prefs->GetEvictedEphemeralAppsInfo(); |
535 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); | 693 EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id)); |
536 ASSERT_FALSE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); | 694 ASSERT_FALSE(IsAppInExtensionsInfo(*extensions_info, evict_app_id)); |
537 | 695 |
538 // Reinstall the app and verify that all data has been reset. | 696 // Reinstall the app and verify that all data has been reset. |
539 evict_app = InstallEphemeralApp(kRetainDataApp); | 697 evict_app = InstallEphemeralApp(kRetainDataApp); |
540 ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_; | 698 ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_; |
541 } | 699 } |
| 700 |
| 701 // Checks the process of installing and then promoting an ephemeral app. |
| 702 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralApp) { |
| 703 InitSyncService(); |
| 704 |
| 705 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 706 ASSERT_TRUE(app); |
| 707 |
| 708 // Ephemeral apps should not be synced. |
| 709 scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
| 710 EXPECT_FALSE(sync_change.get()); |
| 711 |
| 712 // Promote the app to a regular installed app. |
| 713 InstallObserver installed_observer(profile()); |
| 714 PromoteEphemeralApp(app); |
| 715 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); |
| 716 |
| 717 // Check the notification parameters. |
| 718 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 719 EXPECT_EQ(app->id(), params.id); |
| 720 EXPECT_TRUE(params.is_update); |
| 721 EXPECT_TRUE(params.from_ephemeral); |
| 722 |
| 723 // The installation should now be synced. |
| 724 sync_change = GetFirstSyncChangeForApp(app->id()); |
| 725 VerifySyncChange(sync_change.get(), true); |
| 726 } |
| 727 |
| 728 // Verifies that promoting an ephemeral app will enable it. |
| 729 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppAndEnable) { |
| 730 InitSyncService(); |
| 731 |
| 732 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 733 ASSERT_TRUE(app); |
| 734 |
| 735 // Disable the ephemeral app. |
| 736 ExtensionService* service = |
| 737 ExtensionSystem::Get(profile())->extension_service(); |
| 738 service->DisableExtension(app->id(), Extension::DISABLE_PERMISSIONS_INCREASE); |
| 739 ASSERT_TRUE(ExtensionRegistry::Get(profile())-> |
| 740 GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); |
| 741 |
| 742 // Promote to a regular installed app. It should be enabled. |
| 743 PromoteEphemeralApp(app); |
| 744 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); |
| 745 |
| 746 scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
| 747 VerifySyncChange(sync_change.get(), true); |
| 748 } |
| 749 |
| 750 // Verifies that promoting an ephemeral app that has unsupported requirements |
| 751 // will not enable it. |
| 752 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 753 PromoteUnsupportedEphemeralApp) { |
| 754 InitSyncService(); |
| 755 |
| 756 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 757 ASSERT_TRUE(app); |
| 758 |
| 759 // Disable the ephemeral app. |
| 760 ExtensionService* service = |
| 761 ExtensionSystem::Get(profile())->extension_service(); |
| 762 service->DisableExtension( |
| 763 app->id(), Extension::DISABLE_UNSUPPORTED_REQUIREMENT); |
| 764 ASSERT_TRUE(ExtensionRegistry::Get(profile())-> |
| 765 GetExtensionById(app->id(), ExtensionRegistry::DISABLED)); |
| 766 |
| 767 // Promote to a regular installed app. It should remain disabled. |
| 768 PromoteEphemeralApp(app); |
| 769 VerifyPromotedApp(app->id(), ExtensionRegistry::DISABLED); |
| 770 |
| 771 scoped_ptr<AppSyncData> sync_change = GetFirstSyncChangeForApp(app->id()); |
| 772 VerifySyncChange(sync_change.get(), false); |
| 773 } |
| 774 |
| 775 // Checks the process of promoting an ephemeral app from sync. |
| 776 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteEphemeralAppFromSync) { |
| 777 InitSyncService(); |
| 778 |
| 779 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 780 ASSERT_TRUE(app); |
| 781 std::string app_id = app->id(); |
| 782 |
| 783 // Simulate an install from sync. |
| 784 const syncer::StringOrdinal kAppLaunchOrdinal("x"); |
| 785 const syncer::StringOrdinal kPageOrdinal("y"); |
| 786 AppSyncData app_sync_data( |
| 787 *app, |
| 788 true /* enabled */, |
| 789 false /* incognito enabled */, |
| 790 false /* remote install */, |
| 791 kAppLaunchOrdinal, |
| 792 kPageOrdinal, |
| 793 extensions::LAUNCH_TYPE_REGULAR); |
| 794 |
| 795 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); |
| 796 sync_service->ProcessAppSyncData(app_sync_data); |
| 797 |
| 798 // Verify the installation. |
| 799 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
| 800 |
| 801 // The sort ordinals from sync should not be overridden. |
| 802 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); |
| 803 extensions::AppSorting* app_sorting = prefs->app_sorting(); |
| 804 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).Equals( |
| 805 kAppLaunchOrdinal)); |
| 806 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal)); |
| 807 } |
| 808 |
| 809 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to |
| 810 // permanently install an ephemeral app. However, there may be cases where an |
| 811 // install occurs through the usual route of installing from the Web Store (due |
| 812 // to race conditions). Ensure that the app is still installed correctly. |
| 813 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 814 ReplaceEphemeralAppWithInstalledApp) { |
| 815 const Extension* app = InstallEphemeralApp(kRetainDataApp); |
| 816 ASSERT_TRUE(app); |
| 817 std::string app_id = app->id(); |
| 818 app = NULL; |
| 819 |
| 820 InstallObserver installed_observer(profile()); |
| 821 ReplaceEphemeralApp(app_id, kRetainDataApp); |
| 822 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
| 823 |
| 824 // Check the notification parameters. |
| 825 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 826 EXPECT_EQ(app_id, params.id); |
| 827 EXPECT_TRUE(params.is_update); |
| 828 EXPECT_TRUE(params.from_ephemeral); |
| 829 } |
| 830 |
| 831 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will |
| 832 // be delayed until the app is idle. |
| 833 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, |
| 834 ReplaceEphemeralAppWithDelayedInstalledApp) { |
| 835 const Extension* app = InstallAndLaunchEphemeralApp(kRetainDataApp); |
| 836 ASSERT_TRUE(app); |
| 837 std::string app_id = app->id(); |
| 838 app = NULL; |
| 839 |
| 840 // Initiate install. |
| 841 ReplaceEphemeralApp(app_id, kRetainDataApp); |
| 842 |
| 843 // The delayed installation will occur when the ephemeral app is closed. |
| 844 content::WindowedNotificationObserver installed_signal( |
| 845 chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED, |
| 846 content::Source<Profile>(profile())); |
| 847 InstallObserver installed_observer(profile()); |
| 848 CloseApp(app_id); |
| 849 installed_signal.Wait(); |
| 850 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); |
| 851 |
| 852 // Check the notification parameters. |
| 853 const InstallObserver::InstallParameters& params = installed_observer.Last(); |
| 854 EXPECT_EQ(app_id, params.id); |
| 855 EXPECT_TRUE(params.is_update); |
| 856 EXPECT_TRUE(params.from_ephemeral); |
| 857 } |
OLD | NEW |