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 "chrome/browser/apps/ephemeral_app_browsertest.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "apps/app_restore_service.h" | |
10 #include "apps/saved_files_service.h" | |
11 #include "base/files/scoped_temp_dir.h" | |
12 #include "base/scoped_observer.h" | |
13 #include "base/stl_util.h" | |
14 #include "chrome/browser/apps/app_browsertest_util.h" | |
15 #include "chrome/browser/apps/ephemeral_app_service.h" | |
16 #include "chrome/browser/extensions/api/file_system/file_system_api.h" | |
17 #include "chrome/browser/extensions/extension_service.h" | |
18 #include "chrome/browser/extensions/extension_sync_data.h" | |
19 #include "chrome/browser/extensions/extension_sync_service.h" | |
20 #include "chrome/browser/extensions/extension_util.h" | |
21 #include "chrome/browser/notifications/notifier_state_tracker.h" | |
22 #include "chrome/browser/notifications/notifier_state_tracker_factory.h" | |
23 #include "content/public/browser/power_save_blocker.h" | |
24 #include "content/public/test/browser_test.h" | |
25 #include "content/public/test/test_utils.h" | |
26 #include "extensions/browser/api/power/power_api.h" | |
27 #include "extensions/browser/app_sorting.h" | |
28 #include "extensions/browser/event_router.h" | |
29 #include "extensions/browser/extension_prefs.h" | |
30 #include "extensions/browser/extension_registry.h" | |
31 #include "extensions/browser/extension_registry_observer.h" | |
32 #include "extensions/browser/extension_system.h" | |
33 #include "extensions/browser/extension_util.h" | |
34 #include "extensions/browser/process_manager.h" | |
35 #include "extensions/browser/test_extension_registry_observer.h" | |
36 #include "extensions/browser/uninstall_reason.h" | |
37 #include "extensions/common/api/alarms.h" | |
38 #include "extensions/common/extension.h" | |
39 #include "extensions/test/extension_test_message_listener.h" | |
40 #include "extensions/test/result_catcher.h" | |
41 #include "sync/api/fake_sync_change_processor.h" | |
42 #include "sync/api/sync_change_processor_wrapper_for_test.h" | |
43 #include "sync/api/sync_error_factory_mock.h" | |
44 #include "ui/app_list/app_list_switches.h" | |
45 #include "ui/message_center/message_center.h" | |
46 #include "ui/message_center/notifier_settings.h" | |
47 | |
48 using extensions::AppSorting; | |
49 using extensions::Event; | |
50 using extensions::EventRouter; | |
51 using extensions::Extension; | |
52 using extensions::ExtensionPrefs; | |
53 using extensions::ExtensionRegistry; | |
54 using extensions::ExtensionRegistryObserver; | |
55 using extensions::ExtensionSyncData; | |
56 using extensions::ExtensionSystem; | |
57 using extensions::Manifest; | |
58 using extensions::ResultCatcher; | |
59 | |
60 namespace { | |
61 | |
62 namespace alarms = extensions::api::alarms; | |
63 | |
64 const char kPowerTestApp[] = "ephemeral_apps/power"; | |
65 | |
66 // Enabling sync causes these tests to be flaky on Windows. Disable sync so that | |
67 // everything else can be tested. See crbug.com/401028 | |
68 #if defined(OS_WIN) | |
69 const bool kEnableSync = false; | |
70 #else | |
71 const bool kEnableSync = true; | |
72 #endif | |
73 | |
74 typedef std::vector<message_center::Notifier*> NotifierList; | |
75 | |
76 bool IsNotifierInList(const message_center::NotifierId& notifier_id, | |
77 const NotifierList& notifiers) { | |
78 for (NotifierList::const_iterator it = notifiers.begin(); | |
79 it != notifiers.end(); ++it) { | |
80 const message_center::Notifier* notifier = *it; | |
81 if (notifier->notifier_id == notifier_id) | |
82 return true; | |
83 } | |
84 | |
85 return false; | |
86 } | |
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 ~InstallObserver() override {} | |
109 | |
110 const InstallParameters& Last() { | |
111 CHECK(!install_params_.empty()); | |
112 return install_params_.back(); | |
113 } | |
114 | |
115 private: | |
116 void OnExtensionWillBeInstalled(content::BrowserContext* browser_context, | |
117 const Extension* extension, | |
118 bool is_update, | |
119 bool from_ephemeral, | |
120 const std::string& old_name) override { | |
121 install_params_.push_back( | |
122 InstallParameters(extension->id(), is_update, from_ephemeral)); | |
123 } | |
124 | |
125 std::vector<InstallParameters> install_params_; | |
126 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> | |
127 registry_observer_; | |
128 }; | |
129 | |
130 // Instead of actually changing the system power settings, tests will just | |
131 // issue requests to this mock. | |
132 class PowerSettingsMock { | |
133 public: | |
134 PowerSettingsMock() : keep_awake_count_(0) {} | |
135 | |
136 void request_keep_awake() { ++keep_awake_count_; } | |
137 | |
138 void release_keep_awake() { | |
139 --keep_awake_count_; | |
140 ASSERT_GE(keep_awake_count_, 0); | |
141 } | |
142 | |
143 int keep_awake_count() const { return keep_awake_count_; } | |
144 | |
145 private: | |
146 int keep_awake_count_; | |
147 | |
148 DISALLOW_COPY_AND_ASSIGN(PowerSettingsMock); | |
149 }; | |
150 | |
151 // Stub implementation of content::PowerSaveBlocker that updates the | |
152 // PowerSettingsMock. | |
153 class PowerSaveBlockerStub : public content::PowerSaveBlocker { | |
154 public: | |
155 explicit PowerSaveBlockerStub(PowerSettingsMock* power_settings) | |
156 : power_settings_(power_settings) { | |
157 power_settings_->request_keep_awake(); | |
158 } | |
159 | |
160 ~PowerSaveBlockerStub() override { power_settings_->release_keep_awake(); } | |
161 | |
162 static scoped_ptr<PowerSaveBlocker> Create(PowerSettingsMock* power_settings, | |
163 PowerSaveBlockerType type, | |
164 Reason reason, | |
165 const std::string& description) { | |
166 return scoped_ptr<PowerSaveBlocker>( | |
167 new PowerSaveBlockerStub(power_settings)); | |
168 } | |
169 | |
170 private: | |
171 PowerSettingsMock* power_settings_; // Not owned. | |
172 | |
173 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub); | |
174 }; | |
175 | |
176 } // namespace | |
177 | |
178 | |
179 // EphemeralAppTestBase: | |
180 | |
181 const char EphemeralAppTestBase::kMessagingReceiverApp[] = | |
182 "ephemeral_apps/messaging_receiver"; | |
183 const char EphemeralAppTestBase::kMessagingReceiverAppV2[] = | |
184 "ephemeral_apps/messaging_receiver2"; | |
185 const char EphemeralAppTestBase::kDispatchEventTestApp[] = | |
186 "ephemeral_apps/dispatch_event"; | |
187 const char EphemeralAppTestBase::kNotificationsTestApp[] = | |
188 "ephemeral_apps/notification_settings"; | |
189 const char EphemeralAppTestBase::kFileSystemTestApp[] = | |
190 "ephemeral_apps/filesystem_retain_entries"; | |
191 | |
192 EphemeralAppTestBase::EphemeralAppTestBase() {} | |
193 | |
194 EphemeralAppTestBase::~EphemeralAppTestBase() {} | |
195 | |
196 void EphemeralAppTestBase::SetUpCommandLine(base::CommandLine* command_line) { | |
197 // Skip PlatformAppBrowserTest, which sets different values for the switches | |
198 // below. | |
199 ExtensionBrowserTest::SetUpCommandLine(command_line); | |
200 | |
201 // Make event pages get suspended immediately. | |
202 extensions::ProcessManager::SetEventPageIdleTimeForTesting(1); | |
203 extensions::ProcessManager::SetEventPageSuspendingTimeForTesting(1); | |
204 | |
205 // Enable ephemeral apps, which are gated by the experimental app launcher | |
206 // flag. | |
207 command_line->AppendSwitch(app_list::switches::kEnableExperimentalAppList); | |
208 } | |
209 | |
210 void EphemeralAppTestBase::SetUpOnMainThread() { | |
211 PlatformAppBrowserTest::SetUpOnMainThread(); | |
212 | |
213 // Disable ephemeral apps immediately after they stop running in tests. | |
214 EphemeralAppService::Get(profile())->set_disable_delay_for_test(0); | |
215 } | |
216 | |
217 base::FilePath EphemeralAppTestBase::GetTestPath(const char* test_path) { | |
218 return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path); | |
219 } | |
220 | |
221 const Extension* EphemeralAppTestBase::InstallEphemeralApp( | |
222 const char* test_path, Manifest::Location manifest_location) { | |
223 const Extension* extension = InstallEphemeralAppWithSourceAndFlags( | |
224 GetTestPath(test_path), 1, manifest_location, Extension::NO_FLAGS); | |
225 EXPECT_TRUE(extension); | |
226 if (extension) | |
227 EXPECT_TRUE(extensions::util::IsEphemeralApp(extension->id(), profile())); | |
228 return extension; | |
229 } | |
230 | |
231 const Extension* EphemeralAppTestBase::InstallEphemeralApp( | |
232 const char* test_path) { | |
233 return InstallEphemeralApp(test_path, Manifest::INTERNAL); | |
234 } | |
235 | |
236 const Extension* EphemeralAppTestBase::InstallAndLaunchEphemeralApp( | |
237 const char* test_path) { | |
238 ExtensionTestMessageListener launched_listener("launched", false); | |
239 const Extension* extension = InstallEphemeralApp(test_path); | |
240 EXPECT_TRUE(extension); | |
241 if (!extension) | |
242 return NULL; | |
243 | |
244 LaunchPlatformApp(extension); | |
245 bool wait_result = launched_listener.WaitUntilSatisfied(); | |
246 EXPECT_TRUE(wait_result); | |
247 if (!wait_result) | |
248 return NULL; | |
249 | |
250 return extension; | |
251 } | |
252 | |
253 const Extension* EphemeralAppTestBase::UpdateEphemeralApp( | |
254 const std::string& app_id, | |
255 const base::FilePath& test_dir, | |
256 const base::FilePath& pem_path) { | |
257 // Pack a new version of the app. | |
258 base::ScopedTempDir temp_dir; | |
259 EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); | |
260 | |
261 base::FilePath crx_path = temp_dir.path().AppendASCII("temp.crx"); | |
262 if (!base::DeleteFile(crx_path, false)) { | |
263 ADD_FAILURE() << "Failed to delete existing crx: " << crx_path.value(); | |
264 return NULL; | |
265 } | |
266 | |
267 base::FilePath app_v2_path = PackExtensionWithOptions( | |
268 test_dir, crx_path, pem_path, base::FilePath()); | |
269 EXPECT_FALSE(app_v2_path.empty()); | |
270 | |
271 // Update the ephemeral app and wait for the update to finish. | |
272 extensions::CrxInstaller* crx_installer = NULL; | |
273 content::WindowedNotificationObserver windowed_observer( | |
274 extensions::NOTIFICATION_CRX_INSTALLER_DONE, | |
275 content::Source<extensions::CrxInstaller>(crx_installer)); | |
276 ExtensionService* service = | |
277 ExtensionSystem::Get(profile())->extension_service(); | |
278 EXPECT_TRUE(service->UpdateExtension( | |
279 extensions::CRXFileInfo(app_id, app_v2_path), true, &crx_installer)); | |
280 windowed_observer.Wait(); | |
281 | |
282 return ExtensionRegistry::Get(profile()) | |
283 ->GetExtensionById(app_id, ExtensionRegistry::EVERYTHING); | |
284 } | |
285 | |
286 void EphemeralAppTestBase::PromoteEphemeralApp( | |
287 const extensions::Extension* app) { | |
288 ExtensionService* extension_service = | |
289 ExtensionSystem::Get(profile())->extension_service(); | |
290 ASSERT_TRUE(extension_service); | |
291 extension_service->PromoteEphemeralApp(app, false); | |
292 } | |
293 | |
294 void EphemeralAppTestBase::DisableEphemeralApp( | |
295 const Extension* app, | |
296 Extension::DisableReason disable_reason) { | |
297 ExtensionSystem::Get(profile())->extension_service()->DisableExtension( | |
298 app->id(), disable_reason); | |
299 | |
300 ASSERT_TRUE(ExtensionRegistry::Get(profile())->disabled_extensions().Contains( | |
301 app->id())); | |
302 } | |
303 | |
304 void EphemeralAppTestBase::CloseApp(const std::string& app_id) { | |
305 EXPECT_EQ(1U, GetAppWindowCountForApp(app_id)); | |
306 extensions::AppWindow* app_window = GetFirstAppWindowForApp(app_id); | |
307 ASSERT_TRUE(app_window); | |
308 CloseAppWindow(app_window); | |
309 } | |
310 | |
311 void EphemeralAppTestBase::CloseAppWaitForUnload(const std::string& app_id) { | |
312 // Ephemeral apps are unloaded from extension system after they stop running. | |
313 extensions::TestExtensionRegistryObserver observer( | |
314 ExtensionRegistry::Get(profile()), app_id); | |
315 CloseApp(app_id); | |
316 observer.WaitForExtensionUnloaded(); | |
317 } | |
318 | |
319 void EphemeralAppTestBase::EvictApp(const std::string& app_id) { | |
320 // Uninstall the app, which is what happens when ephemeral apps get evicted | |
321 // from the cache. | |
322 extensions::TestExtensionRegistryObserver observer( | |
323 ExtensionRegistry::Get(profile()), app_id); | |
324 | |
325 ExtensionService* service = | |
326 ExtensionSystem::Get(profile())->extension_service(); | |
327 ASSERT_TRUE(service); | |
328 service->UninstallExtension( | |
329 app_id, | |
330 extensions::UNINSTALL_REASON_ORPHANED_EPHEMERAL_EXTENSION, | |
331 base::Bind(&base::DoNothing), | |
332 NULL); | |
333 | |
334 observer.WaitForExtensionUninstalled(); | |
335 } | |
336 | |
337 // EphemeralAppBrowserTest: | |
338 | |
339 class EphemeralAppBrowserTest : public EphemeralAppTestBase { | |
340 protected: | |
341 bool LaunchAppAndRunTest(const Extension* app, const char* test_name) { | |
342 // Ephemeral apps are unloaded after they are closed. Ensure they are | |
343 // enabled before launch. | |
344 ExtensionService* service = | |
345 ExtensionSystem::Get(profile())->extension_service(); | |
346 service->EnableExtension(app->id()); | |
347 | |
348 ExtensionTestMessageListener launched_listener("launched", true); | |
349 LaunchPlatformApp(app); | |
350 if (!launched_listener.WaitUntilSatisfied()) { | |
351 message_ = "Failed to receive launched message from test"; | |
352 return false; | |
353 } | |
354 | |
355 ResultCatcher catcher; | |
356 launched_listener.Reply(test_name); | |
357 | |
358 bool result = catcher.GetNextResult(); | |
359 message_ = catcher.message(); | |
360 | |
361 CloseAppWaitForUnload(app->id()); | |
362 return result; | |
363 } | |
364 | |
365 // Verify that the event page of the app has not been loaded. | |
366 void VerifyAppNotLoaded(const std::string& app_id) { | |
367 EXPECT_FALSE(extensions::ProcessManager::Get(profile()) | |
368 ->GetBackgroundHostForExtension(app_id)); | |
369 } | |
370 | |
371 // Verify properties of ephemeral apps. | |
372 void VerifyEphemeralApp(const std::string& app_id) { | |
373 EXPECT_TRUE(extensions::util::IsEphemeralApp(app_id, profile())); | |
374 | |
375 // Ephemeral apps should not be synced. | |
376 scoped_ptr<ExtensionSyncData> sync_change = GetLastSyncChangeForApp(app_id); | |
377 EXPECT_FALSE(sync_change.get()); | |
378 | |
379 // Ephemeral apps should not be assigned ordinals. | |
380 AppSorting* app_sorting = ExtensionSystem::Get(profile())->app_sorting(); | |
381 EXPECT_FALSE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); | |
382 EXPECT_FALSE(app_sorting->GetPageOrdinal(app_id).IsValid()); | |
383 } | |
384 | |
385 // Verify that after ephemeral apps stop running, they reside in extension | |
386 // system in a disabled and unloaded state. | |
387 void VerifyInactiveEphemeralApp(const std::string& app_id) { | |
388 EXPECT_TRUE( | |
389 ExtensionRegistry::Get(profile())->disabled_extensions().Contains( | |
390 app_id)); | |
391 | |
392 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | |
393 EXPECT_TRUE(prefs->IsExtensionDisabled(app_id)); | |
394 EXPECT_NE(0, | |
395 prefs->GetDisableReasons(app_id) & | |
396 Extension::DISABLE_INACTIVE_EPHEMERAL_APP); | |
397 } | |
398 | |
399 // Verify the state of an app that has been promoted from an ephemeral to a | |
400 // fully installed app. | |
401 void VerifyPromotedApp(const std::string& app_id, | |
402 ExtensionRegistry::IncludeFlag expected_set) { | |
403 const Extension* app = ExtensionRegistry::Get(profile()) | |
404 ->GetExtensionById(app_id, expected_set); | |
405 ASSERT_TRUE(app) << "App not found in expected set: " << expected_set; | |
406 | |
407 // The app should not be ephemeral. | |
408 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); | |
409 ASSERT_TRUE(prefs); | |
410 EXPECT_FALSE(prefs->IsEphemeralApp(app_id)); | |
411 EXPECT_EQ(0, | |
412 prefs->GetDisableReasons(app_id) & | |
413 Extension::DISABLE_INACTIVE_EPHEMERAL_APP); | |
414 | |
415 // Check sort ordinals. | |
416 AppSorting* app_sorting = ExtensionSystem::Get(profile())->app_sorting(); | |
417 EXPECT_TRUE(app_sorting->GetAppLaunchOrdinal(app_id).IsValid()); | |
418 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).IsValid()); | |
419 } | |
420 | |
421 // Dispatch a fake alarm event to the app. | |
422 void DispatchAlarmEvent(EventRouter* event_router, | |
423 const std::string& app_id) { | |
424 alarms::Alarm dummy_alarm; | |
425 dummy_alarm.name = "test_alarm"; | |
426 | |
427 scoped_ptr<base::ListValue> args(new base::ListValue()); | |
428 args->Append(dummy_alarm.ToValue().release()); | |
429 scoped_ptr<Event> event(new Event(extensions::events::ALARMS_ON_ALARM, | |
430 alarms::OnAlarm::kEventName, | |
431 args.Pass())); | |
432 | |
433 event_router->DispatchEventToExtension(app_id, event.Pass()); | |
434 } | |
435 | |
436 // Simulates the scenario where an app is installed, via the normal | |
437 // installation route, on top of an ephemeral app. This can occur due to race | |
438 // conditions. | |
439 const Extension* ReplaceEphemeralApp(const std::string& app_id, | |
440 const char* test_path, | |
441 int expected_enabled_change) { | |
442 return UpdateExtensionWaitForIdle( | |
443 app_id, GetTestPath(test_path), expected_enabled_change); | |
444 } | |
445 | |
446 void PromoteEphemeralAppAndVerify( | |
447 const Extension* app, | |
448 ExtensionRegistry::IncludeFlag expected_set, | |
449 bool expect_sync_enabled) { | |
450 ASSERT_TRUE(app); | |
451 | |
452 // Ephemeral apps should not be synced. | |
453 scoped_ptr<ExtensionSyncData> sync_change = | |
454 GetLastSyncChangeForApp(app->id()); | |
455 EXPECT_FALSE(sync_change.get()); | |
456 | |
457 // Promote the app to a regular installed app. | |
458 InstallObserver installed_observer(profile()); | |
459 PromoteEphemeralApp(app); | |
460 VerifyPromotedApp(app->id(), expected_set); | |
461 | |
462 // Check the notification parameters. | |
463 const InstallObserver::InstallParameters& params = | |
464 installed_observer.Last(); | |
465 EXPECT_EQ(app->id(), params.id); | |
466 EXPECT_TRUE(params.is_update); | |
467 EXPECT_TRUE(params.from_ephemeral); | |
468 | |
469 // The installation should now be synced. | |
470 sync_change = GetLastSyncChangeForApp(app->id()); | |
471 VerifySyncChange(sync_change.get(), expect_sync_enabled); | |
472 } | |
473 | |
474 void PromoteEphemeralAppAndVerify( | |
475 const Extension* app, | |
476 ExtensionRegistry::IncludeFlag expected_set) { | |
477 PromoteEphemeralAppAndVerify(app, expected_set, | |
478 expected_set == ExtensionRegistry::ENABLED); | |
479 } | |
480 | |
481 void PromoteEphemeralAppFromSyncAndVerify( | |
482 const Extension* app, | |
483 bool enable_from_sync, | |
484 ExtensionRegistry::IncludeFlag expected_set) { | |
485 ASSERT_TRUE(app); | |
486 | |
487 // Simulate an install from sync. | |
488 int disable_reasons = enable_from_sync ? 0 : Extension::DISABLE_USER_ACTION; | |
489 const syncer::StringOrdinal kAppLaunchOrdinal("x"); | |
490 const syncer::StringOrdinal kPageOrdinal("y"); | |
491 ExtensionSyncData app_sync_data( | |
492 *app, | |
493 enable_from_sync, | |
494 disable_reasons, | |
495 false /* incognito enabled */, | |
496 false /* remote install */, | |
497 extensions::ExtensionSyncData::BOOLEAN_UNSET, | |
498 kAppLaunchOrdinal, | |
499 kPageOrdinal, | |
500 extensions::LAUNCH_TYPE_REGULAR); | |
501 | |
502 std::string app_id = app->id(); | |
503 app = NULL; | |
504 | |
505 ExtensionSyncService::Get(profile())->ProcessSyncChanges( | |
506 FROM_HERE, | |
507 syncer::SyncChangeList( | |
508 1, app_sync_data.GetSyncChange(syncer::SyncChange::ACTION_ADD))); | |
509 | |
510 // Verify the installation. | |
511 VerifyPromotedApp(app_id, expected_set); | |
512 | |
513 // The sort ordinals from sync should not be overridden. | |
514 AppSorting* app_sorting = ExtensionSystem::Get(profile())->app_sorting(); | |
515 EXPECT_TRUE( | |
516 app_sorting->GetAppLaunchOrdinal(app_id).Equals(kAppLaunchOrdinal)); | |
517 EXPECT_TRUE(app_sorting->GetPageOrdinal(app_id).Equals(kPageOrdinal)); | |
518 } | |
519 | |
520 void InitSyncService() { | |
521 if (!kEnableSync) | |
522 return; | |
523 | |
524 ExtensionSyncService* sync_service = ExtensionSyncService::Get(profile()); | |
525 sync_service->MergeDataAndStartSyncing( | |
526 syncer::APPS, | |
527 syncer::SyncDataList(), | |
528 scoped_ptr<syncer::SyncChangeProcessor>( | |
529 new syncer::SyncChangeProcessorWrapperForTest( | |
530 &mock_sync_processor_)), | |
531 scoped_ptr<syncer::SyncErrorFactory>( | |
532 new syncer::SyncErrorFactoryMock())); | |
533 } | |
534 | |
535 scoped_ptr<ExtensionSyncData> GetLastSyncChangeForApp(const std::string& id) { | |
536 scoped_ptr<ExtensionSyncData> sync_data; | |
537 for (syncer::SyncChangeList::iterator it = | |
538 mock_sync_processor_.changes().begin(); | |
539 it != mock_sync_processor_.changes().end(); ++it) { | |
540 scoped_ptr<ExtensionSyncData> data( | |
541 ExtensionSyncData::CreateFromSyncChange(*it)); | |
542 if (data.get() && data->id() == id) | |
543 sync_data.reset(data.release()); | |
544 } | |
545 | |
546 return sync_data.Pass(); | |
547 } | |
548 | |
549 void VerifySyncChange(const ExtensionSyncData* sync_change, | |
550 bool expect_enabled) { | |
551 if (!kEnableSync) | |
552 return; | |
553 | |
554 ASSERT_TRUE(sync_change); | |
555 EXPECT_TRUE(sync_change->page_ordinal().IsValid()); | |
556 EXPECT_TRUE(sync_change->app_launch_ordinal().IsValid()); | |
557 EXPECT_FALSE(sync_change->uninstalled()); | |
558 EXPECT_EQ(expect_enabled, sync_change->enabled()); | |
559 } | |
560 | |
561 void TestInstallEvent(bool close_app) { | |
562 ExtensionTestMessageListener first_msg_listener(false); | |
563 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp); | |
564 ASSERT_TRUE(app); | |
565 | |
566 // When an ephemeral app is first added, it should not receive the | |
567 // onInstalled event, hence the first message received from the test should | |
568 // be "launched" and not "installed". | |
569 ASSERT_TRUE(first_msg_listener.WaitUntilSatisfied()); | |
570 EXPECT_EQ(std::string("launched"), first_msg_listener.message()); | |
571 | |
572 if (close_app) | |
573 CloseAppWaitForUnload(app->id()); | |
574 | |
575 // When installed permanently, the app should receive the onInstalled event. | |
576 ExtensionTestMessageListener install_listener("installed", false); | |
577 PromoteEphemeralApp(app); | |
578 ASSERT_TRUE(install_listener.WaitUntilSatisfied()); | |
579 } | |
580 | |
581 private: | |
582 syncer::FakeSyncChangeProcessor mock_sync_processor_; | |
583 }; | |
584 | |
585 // Verify that ephemeral apps can be launched and receive system events when | |
586 // they are running. Once they are inactive they should not receive system | |
587 // events. | |
588 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, EventDispatchWhenLaunched) { | |
589 const Extension* extension = | |
590 InstallAndLaunchEphemeralApp(kDispatchEventTestApp); | |
591 ASSERT_TRUE(extension); | |
592 | |
593 // Send a fake alarm event to the app and verify that a response is | |
594 // received. | |
595 EventRouter* event_router = EventRouter::Get(profile()); | |
596 ASSERT_TRUE(event_router); | |
597 | |
598 ExtensionTestMessageListener alarm_received_listener("alarm_received", false); | |
599 DispatchAlarmEvent(event_router, extension->id()); | |
600 ASSERT_TRUE(alarm_received_listener.WaitUntilSatisfied()); | |
601 | |
602 CloseAppWaitForUnload(extension->id()); | |
603 | |
604 // Dispatch the alarm event again and verify that the event page did not get | |
605 // loaded for the app. | |
606 DispatchAlarmEvent(event_router, extension->id()); | |
607 VerifyAppNotLoaded(extension->id()); | |
608 } | |
609 | |
610 // Verify that ephemeral apps will receive messages while they are running. | |
611 // Flaky test: crbug.com/394426 | |
612 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
613 DISABLED_ReceiveMessagesWhenLaunched) { | |
614 const Extension* receiver = | |
615 InstallAndLaunchEphemeralApp(kMessagingReceiverApp); | |
616 ASSERT_TRUE(receiver); | |
617 | |
618 // Verify that messages are received while the app is running. | |
619 ResultCatcher result_catcher; | |
620 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_success", | |
621 "Launched"); | |
622 EXPECT_TRUE(result_catcher.GetNextResult()); | |
623 | |
624 CloseAppWaitForUnload(receiver->id()); | |
625 | |
626 // Verify that messages are not received while the app is inactive. | |
627 LoadAndLaunchPlatformApp("ephemeral_apps/messaging_sender_fail", "Launched"); | |
628 EXPECT_TRUE(result_catcher.GetNextResult()); | |
629 } | |
630 | |
631 // Verifies that the chrome.runtime.onInstalled() event is received by a running | |
632 // ephemeral app only when it is promoted. | |
633 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
634 InstallEventReceivedWhileRunning) { | |
635 TestInstallEvent(false /* close app */); | |
636 } | |
637 | |
638 // Verifies that when an idle ephemeral app is promoted, it will be loaded to | |
639 // receive the chrome.runtime.onInstalled() event. | |
640 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, InstallEventReceivedWhileIdle) { | |
641 TestInstallEvent(true /* close app */); | |
642 } | |
643 | |
644 // Verifies that the chrome.runtime.onRestarted() event is received by an | |
645 // ephemeral app. | |
646 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RestartEventReceived) { | |
647 const Extension* app = InstallAndLaunchEphemeralApp(kDispatchEventTestApp); | |
648 ASSERT_TRUE(app); | |
649 CloseAppWaitForUnload(app->id()); | |
650 | |
651 // Fake ephemeral app running before restart. | |
652 ExtensionSystem::Get(profile())->extension_service()->EnableExtension( | |
653 app->id()); | |
654 ASSERT_TRUE(ExtensionRegistry::Get(profile())->enabled_extensions().Contains( | |
655 app->id())); | |
656 ExtensionPrefs::Get(profile())->SetExtensionRunning(app->id(), true); | |
657 | |
658 ExtensionTestMessageListener restart_listener("restarted", false); | |
659 apps::AppRestoreService::Get(profile())->HandleStartup(true); | |
660 EXPECT_TRUE(restart_listener.WaitUntilSatisfied()); | |
661 } | |
662 | |
663 // Verify that an updated ephemeral app will still have its ephemeral flag | |
664 // enabled. | |
665 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, UpdateEphemeralApp) { | |
666 InitSyncService(); | |
667 | |
668 const Extension* app_v1 = InstallAndLaunchEphemeralApp(kMessagingReceiverApp); | |
669 ASSERT_TRUE(app_v1); | |
670 VerifyEphemeralApp(app_v1->id()); | |
671 CloseAppWaitForUnload(app_v1->id()); | |
672 VerifyInactiveEphemeralApp(app_v1->id()); | |
673 | |
674 std::string app_id = app_v1->id(); | |
675 base::Version app_original_version = *app_v1->version(); | |
676 | |
677 // Update to version 2 of the app. | |
678 app_v1 = NULL; // The extension object will be destroyed during update. | |
679 InstallObserver installed_observer(profile()); | |
680 const Extension* app_v2 = | |
681 UpdateEphemeralApp(app_id, | |
682 GetTestPath(kMessagingReceiverAppV2), | |
683 GetTestPath(kMessagingReceiverApp) | |
684 .ReplaceExtension(FILE_PATH_LITERAL(".pem"))); | |
685 | |
686 // Check the notification parameters. | |
687 const InstallObserver::InstallParameters& params = installed_observer.Last(); | |
688 EXPECT_EQ(app_id, params.id); | |
689 EXPECT_TRUE(params.is_update); | |
690 EXPECT_FALSE(params.from_ephemeral); | |
691 | |
692 // The ephemeral flag should still be set. | |
693 ASSERT_TRUE(app_v2); | |
694 EXPECT_GT(app_v2->version()->CompareTo(app_original_version), 0); | |
695 VerifyEphemeralApp(app_id); | |
696 | |
697 // The app should still be disabled in extension system. | |
698 VerifyInactiveEphemeralApp(app_id); | |
699 } | |
700 | |
701 // Verify that if notifications have been disabled for an ephemeral app, it will | |
702 // remain disabled even after being evicted from the cache. | |
703 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, StickyNotificationSettings) { | |
704 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
705 ASSERT_TRUE(app); | |
706 | |
707 // Disable notifications for this app. | |
708 NotifierStateTracker* notifier_state_tracker = | |
709 NotifierStateTrackerFactory::GetForProfile(profile()); | |
710 ASSERT_TRUE(notifier_state_tracker); | |
711 | |
712 message_center::NotifierId notifier_id( | |
713 message_center::NotifierId::APPLICATION, app->id()); | |
714 EXPECT_TRUE(notifier_state_tracker->IsNotifierEnabled(notifier_id)); | |
715 notifier_state_tracker->SetNotifierEnabled(notifier_id, false); | |
716 EXPECT_FALSE(notifier_state_tracker->IsNotifierEnabled(notifier_id)); | |
717 | |
718 // Remove the app. | |
719 CloseAppWaitForUnload(app->id()); | |
720 EvictApp(app->id()); | |
721 | |
722 // Reinstall the ephemeral app and verify that notifications remain disabled. | |
723 app = InstallEphemeralApp(kNotificationsTestApp); | |
724 ASSERT_TRUE(app); | |
725 message_center::NotifierId reinstalled_notifier_id( | |
726 message_center::NotifierId::APPLICATION, app->id()); | |
727 EXPECT_FALSE(notifier_state_tracker->IsNotifierEnabled( | |
728 reinstalled_notifier_id)); | |
729 } | |
730 | |
731 // Verify that only running ephemeral apps will appear in the Notification | |
732 // Settings UI. Inactive, cached ephemeral apps should not appear. | |
733 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
734 IncludeRunningEphemeralAppsInNotifiers) { | |
735 message_center::NotifierSettingsProvider* settings_provider = | |
736 message_center::MessageCenter::Get()->GetNotifierSettingsProvider(); | |
737 DCHECK(settings_provider); | |
738 | |
739 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
740 ASSERT_TRUE(app); | |
741 message_center::NotifierId notifier_id( | |
742 message_center::NotifierId::APPLICATION, app->id()); | |
743 | |
744 // Since the ephemeral app is running, it should be included in the list | |
745 // of notifiers to show in the UI. | |
746 NotifierList notifiers; | |
747 STLElementDeleter<NotifierList> notifier_deleter(¬ifiers); | |
748 | |
749 settings_provider->GetNotifierList(¬ifiers); | |
750 EXPECT_TRUE(IsNotifierInList(notifier_id, notifiers)); | |
751 STLDeleteElements(¬ifiers); | |
752 | |
753 // Close the ephemeral app. | |
754 CloseAppWaitForUnload(app->id()); | |
755 | |
756 // Inactive ephemeral apps should not be included in the list of notifiers to | |
757 // show in the UI. | |
758 settings_provider->GetNotifierList(¬ifiers); | |
759 EXPECT_FALSE(IsNotifierInList(notifier_id, notifiers)); | |
760 } | |
761 | |
762 // Verify that ephemeral apps will have no ability to retain file entries after | |
763 // close. Normal retainEntry behavior for installed apps is tested in | |
764 // FileSystemApiTest. | |
765 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
766 DisableRetainFileSystemEntries) { | |
767 // Create a dummy file that we can just return to the test. | |
768 base::ScopedTempDir temp_dir; | |
769 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
770 base::FilePath temp_file; | |
771 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file)); | |
772 | |
773 using extensions::FileSystemChooseEntryFunction; | |
774 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( | |
775 &temp_file); | |
776 // The temporary file needs to be registered for the tests to pass on | |
777 // ChromeOS. | |
778 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest( | |
779 "temp", temp_dir.path()); | |
780 | |
781 // The first test opens the file and writes the file handle to local storage. | |
782 const Extension* app = InstallEphemeralApp(kFileSystemTestApp, | |
783 Manifest::UNPACKED); | |
784 ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_; | |
785 | |
786 // Verify that after the app has been closed, all retained entries are | |
787 // flushed. | |
788 std::vector<apps::SavedFileEntry> file_entries = | |
789 apps::SavedFilesService::Get(profile()) | |
790 ->GetAllFileEntries(app->id()); | |
791 EXPECT_TRUE(file_entries.empty()); | |
792 | |
793 // The second test verifies that the file cannot be reopened. | |
794 ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_; | |
795 } | |
796 | |
797 // Checks the process of launching an ephemeral app and then promoting the app | |
798 // while it is running. | |
799 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileRunning) { | |
800 InitSyncService(); | |
801 | |
802 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
803 ASSERT_TRUE(app); | |
804 | |
805 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED); | |
806 | |
807 // Ensure that the app is not unloaded and disabled after it is closed. | |
808 CloseApp(app->id()); | |
809 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); | |
810 } | |
811 | |
812 // Checks the process of launching an ephemeral app and then promoting the app | |
813 // while it is idle. | |
814 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppWhileIdle) { | |
815 InitSyncService(); | |
816 | |
817 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
818 ASSERT_TRUE(app); | |
819 CloseAppWaitForUnload(app->id()); | |
820 VerifyInactiveEphemeralApp(app->id()); | |
821 | |
822 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED); | |
823 } | |
824 | |
825 // Verifies that promoting an ephemeral app that was disabled due to a | |
826 // permissions increase will enable it. | |
827 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppAndGrantPermissions) { | |
828 InitSyncService(); | |
829 | |
830 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
831 ASSERT_TRUE(app); | |
832 CloseAppWaitForUnload(app->id()); | |
833 DisableEphemeralApp(app, Extension::DISABLE_PERMISSIONS_INCREASE); | |
834 | |
835 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::ENABLED); | |
836 EXPECT_FALSE(ExtensionPrefs::Get(profile()) | |
837 ->DidExtensionEscalatePermissions(app->id())); | |
838 } | |
839 | |
840 // Verifies that promoting an ephemeral app that has unsupported requirements | |
841 // will not enable it. | |
842 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
843 PromoteUnsupportedEphemeralApp) { | |
844 InitSyncService(); | |
845 | |
846 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
847 ASSERT_TRUE(app); | |
848 CloseAppWaitForUnload(app->id()); | |
849 DisableEphemeralApp(app, Extension::DISABLE_UNSUPPORTED_REQUIREMENT); | |
850 | |
851 // When promoted to a regular installed app, it should remain disabled. | |
852 // However, DISABLE_UNSUPPORTED_REQUIREMENT is not a syncable disable reason, | |
853 // so sync should still say "enabled". | |
854 bool expect_sync_enabled = true; | |
855 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::DISABLED, | |
856 expect_sync_enabled); | |
857 } | |
858 | |
859 // Verifies that promoting an ephemeral app that is blacklisted will not enable | |
860 // it. | |
861 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
862 PromoteBlacklistedEphemeralApp) { | |
863 InitSyncService(); | |
864 | |
865 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
866 ASSERT_TRUE(app); | |
867 CloseAppWaitForUnload(app->id()); | |
868 | |
869 ExtensionService* service = | |
870 ExtensionSystem::Get(profile())->extension_service(); | |
871 service->BlacklistExtensionForTest(app->id()); | |
872 ASSERT_TRUE( | |
873 ExtensionRegistry::Get(profile())->blacklisted_extensions().Contains( | |
874 app->id())); | |
875 | |
876 // When promoted to a regular installed app, it should remain blacklisted. | |
877 PromoteEphemeralAppAndVerify(app, ExtensionRegistry::BLACKLISTED); | |
878 | |
879 // The app should be synced, but disabled. | |
880 scoped_ptr<ExtensionSyncData> sync_change = | |
881 GetLastSyncChangeForApp(app->id()); | |
882 VerifySyncChange(sync_change.get(), false); | |
883 } | |
884 | |
885 // Checks the process of promoting an ephemeral app from sync while the app is | |
886 // running. | |
887 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
888 PromoteAppFromSyncWhileRunning) { | |
889 InitSyncService(); | |
890 | |
891 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
892 ASSERT_TRUE(app); | |
893 | |
894 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED); | |
895 | |
896 // Ensure that the app is not unloaded and disabled after it is closed. | |
897 CloseApp(app->id()); | |
898 VerifyPromotedApp(app->id(), ExtensionRegistry::ENABLED); | |
899 } | |
900 | |
901 // Checks the process of promoting an ephemeral app from sync while the app is | |
902 // idle. | |
903 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, PromoteAppFromSyncWhileIdle) { | |
904 InitSyncService(); | |
905 | |
906 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
907 ASSERT_TRUE(app); | |
908 CloseAppWaitForUnload(app->id()); | |
909 VerifyInactiveEphemeralApp(app->id()); | |
910 | |
911 PromoteEphemeralAppFromSyncAndVerify(app, true, ExtensionRegistry::ENABLED); | |
912 } | |
913 | |
914 // Checks the process of promoting an ephemeral app from sync, where the app | |
915 // from sync is disabled, and the ephemeral app is running. | |
916 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
917 PromoteDisabledAppFromSyncWhileRunning) { | |
918 InitSyncService(); | |
919 | |
920 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
921 ASSERT_TRUE(app); | |
922 | |
923 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED); | |
924 } | |
925 | |
926 // Checks the process of promoting an ephemeral app from sync, where the app | |
927 // from sync is disabled, and the ephemeral app is idle. | |
928 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
929 PromoteDisabledAppFromSyncWhileIdle) { | |
930 InitSyncService(); | |
931 | |
932 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
933 ASSERT_TRUE(app); | |
934 CloseAppWaitForUnload(app->id()); | |
935 VerifyInactiveEphemeralApp(app->id()); | |
936 | |
937 PromoteEphemeralAppFromSyncAndVerify(app, false, ExtensionRegistry::DISABLED); | |
938 } | |
939 | |
940 // In most cases, ExtensionService::PromoteEphemeralApp() will be called to | |
941 // permanently install an ephemeral app. However, there may be cases where an | |
942 // install occurs through the usual route of installing from the Web Store (due | |
943 // to race conditions). Ensure that the app is still installed correctly. | |
944 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
945 ReplaceEphemeralAppWithInstalledApp) { | |
946 InitSyncService(); | |
947 | |
948 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
949 ASSERT_TRUE(app); | |
950 CloseAppWaitForUnload(app->id()); | |
951 std::string app_id = app->id(); | |
952 app = NULL; | |
953 | |
954 InstallObserver installed_observer(profile()); | |
955 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 1); | |
956 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); | |
957 | |
958 // Check the notification parameters. | |
959 const InstallObserver::InstallParameters& params = installed_observer.Last(); | |
960 EXPECT_EQ(app_id, params.id); | |
961 EXPECT_TRUE(params.is_update); | |
962 EXPECT_TRUE(params.from_ephemeral); | |
963 } | |
964 | |
965 // This is similar to ReplaceEphemeralAppWithInstalledApp, but installs will | |
966 // be delayed until the app is idle. | |
967 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
968 ReplaceEphemeralAppWithDelayedInstalledApp) { | |
969 InitSyncService(); | |
970 const Extension* app = InstallAndLaunchEphemeralApp(kNotificationsTestApp); | |
971 ASSERT_TRUE(app); | |
972 std::string app_id = app->id(); | |
973 app = NULL; | |
974 | |
975 // Initiate install. | |
976 ReplaceEphemeralApp(app_id, kNotificationsTestApp, 0); | |
977 | |
978 // The delayed installation will occur when the ephemeral app is closed. | |
979 extensions::TestExtensionRegistryObserver observer( | |
980 ExtensionRegistry::Get(profile()), app_id); | |
981 InstallObserver installed_observer(profile()); | |
982 CloseAppWaitForUnload(app_id); | |
983 observer.WaitForExtensionWillBeInstalled(); | |
984 VerifyPromotedApp(app_id, ExtensionRegistry::ENABLED); | |
985 | |
986 // Check the notification parameters. | |
987 const InstallObserver::InstallParameters& params = installed_observer.Last(); | |
988 EXPECT_EQ(app_id, params.id); | |
989 EXPECT_TRUE(params.is_update); | |
990 EXPECT_TRUE(params.from_ephemeral); | |
991 } | |
992 | |
993 // Verifies that an installed app cannot turn into an ephemeral app as result of | |
994 // race conditions, i.e. an ephemeral app can be promoted to an installed app, | |
995 // but not vice versa. | |
996 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
997 ReplaceInstalledAppWithEphemeralApp) { | |
998 const Extension* app = InstallPlatformApp(kNotificationsTestApp); | |
999 ASSERT_TRUE(app); | |
1000 std::string app_id = app->id(); | |
1001 app = NULL; | |
1002 | |
1003 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile())); | |
1004 app = | |
1005 InstallEphemeralAppWithSourceAndFlags(GetTestPath(kNotificationsTestApp), | |
1006 0, | |
1007 Manifest::INTERNAL, | |
1008 Extension::NO_FLAGS); | |
1009 EXPECT_FALSE(extensions::util::IsEphemeralApp(app_id, profile())); | |
1010 } | |
1011 | |
1012 // Ephemerality was previously encoded by the Extension::IS_EPHEMERAL creation | |
1013 // flag. This was changed to an "ephemeral_app" property. Check that the prefs | |
1014 // are handled correctly. | |
1015 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, | |
1016 ExtensionPrefBackcompatibility) { | |
1017 // Ensure that apps with the old prefs are recognized as ephemeral. | |
1018 const Extension* app = | |
1019 InstallExtensionWithSourceAndFlags(GetTestPath(kNotificationsTestApp), | |
1020 1, | |
1021 Manifest::INTERNAL, | |
1022 Extension::IS_EPHEMERAL); | |
1023 ASSERT_TRUE(app); | |
1024 EXPECT_TRUE(extensions::util::IsEphemeralApp(app->id(), profile())); | |
1025 | |
1026 // Ensure that when the app is promoted to an installed app, the bit in the | |
1027 // creation flags is cleared. | |
1028 PromoteEphemeralApp(app); | |
1029 EXPECT_FALSE(extensions::util::IsEphemeralApp(app->id(), profile())); | |
1030 | |
1031 int creation_flags = | |
1032 ExtensionPrefs::Get(profile())->GetCreationFlags(app->id()); | |
1033 EXPECT_EQ(0, creation_flags & Extension::IS_EPHEMERAL); | |
1034 } | |
1035 | |
1036 // Verifies that the power keep awake will be automatically released for | |
1037 // ephemeral apps that stop running. Well behaved apps should actually call | |
1038 // chrome.power.releaseKeepAwake() themselves. | |
1039 IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, ReleasePowerKeepAwake) { | |
1040 PowerSettingsMock power_settings; | |
1041 extensions::PowerAPI::Get(profile())->SetCreateBlockerFunctionForTesting( | |
1042 base::Bind(&PowerSaveBlockerStub::Create, &power_settings)); | |
1043 | |
1044 const Extension* app = InstallAndLaunchEphemeralApp(kPowerTestApp); | |
1045 ASSERT_TRUE(app); | |
1046 EXPECT_EQ(1, power_settings.keep_awake_count()); | |
1047 | |
1048 CloseAppWaitForUnload(app->id()); | |
1049 | |
1050 EXPECT_EQ(0, power_settings.keep_awake_count()); | |
1051 } | |
OLD | NEW |