1 // Copyright (c) 2013 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 "apps/app_restore_service.h" 6 #include "apps/app_restore_service_factory.h" 7 #include "apps/saved_files_service.h" 8 #include "chrome/browser/apps/app_browsertest_util.h" 9 #include "chrome/browser/extensions/api/file_system/file_system_api.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "content/public/browser/notification_service.h" 12 #include "content/public/test/test_utils.h" 13 #include "extensions/browser/extension_prefs.h" 14 #include "extensions/browser/notification_types.h" 15 #include "extensions/common/extension.h" 16 #include "extensions/test/extension_test_message_listener.h" 17 18 using extensions::Extension; 19 using extensions::ExtensionPrefs; 20 using extensions::ExtensionSystem; 21 using extensions::FileSystemChooseEntryFunction; 22 23 // TODO(benwells): Move PlatformAppBrowserTest to apps namespace in apps 24 // component. 25 using extensions::PlatformAppBrowserTest; 26 27 namespace apps { 28 29 // Tests that a running app is recorded in the preferences as such. 30 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, RunningAppsAreRecorded) { 31 content::WindowedNotificationObserver extension_suspended( 32 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, 33 content::NotificationService::AllSources()); 34 35 const Extension* extension = LoadExtension( 36 test_data_dir_.AppendASCII("platform_apps/restart_test")); 37 ASSERT_TRUE(extension); 38 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile()); 39 40 // App is running. 41 ASSERT_TRUE(extension_prefs->IsExtensionRunning(extension->id())); 42 43 // Wait for the extension to get suspended. 44 extension_suspended.Wait(); 45 46 // App isn't running because it got suspended. 47 ASSERT_FALSE(extension_prefs->IsExtensionRunning(extension->id())); 48 49 // Pretend that the app is supposed to be running. 50 extension_prefs->SetExtensionRunning(extension->id(), true); 51 52 ExtensionTestMessageListener restart_listener("onRestarted", false); 53 apps::AppRestoreServiceFactory::GetForProfile(browser()->profile())-> 54 HandleStartup(true); 55 restart_listener.WaitUntilSatisfied(); 56 } 57 58 // Tests that apps are recorded in the preferences as active when and only when 59 // they have visible windows. 60 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ActiveAppsAreRecorded) { 61 ExtensionTestMessageListener ready_listener("ready", true); 62 const Extension* extension = 63 LoadExtension(test_data_dir_.AppendASCII("platform_apps/active_test")); 64 ASSERT_TRUE(extension); 65 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser()->profile()); 66 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 67 68 // Open a visible window and check the app is marked active. 69 ready_listener.Reply("create"); 70 ready_listener.Reset(); 71 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 72 ASSERT_TRUE(extension_prefs->IsActive(extension->id())); 73 74 // Close the window, then open a minimized window and check the app is active. 75 ready_listener.Reply("closeLastWindow"); 76 ready_listener.Reset(); 77 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 78 ready_listener.Reply("createMinimized"); 79 ready_listener.Reset(); 80 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 81 ASSERT_TRUE(extension_prefs->IsActive(extension->id())); 82 83 // Close the window, then open a hidden window and check the app is not 84 // marked active. 85 ready_listener.Reply("closeLastWindow"); 86 ready_listener.Reset(); 87 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 88 ready_listener.Reply("createHidden"); 89 ready_listener.Reset(); 90 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 91 ASSERT_FALSE(extension_prefs->IsActive(extension->id())); 92 93 // Open another window and check the app is marked active. 94 ready_listener.Reply("create"); 95 ready_listener.Reset(); 96 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 97 ASSERT_TRUE(extension_prefs->IsActive(extension->id())); 98 99 // Close the visible window and check the app has been marked inactive. 100 ready_listener.Reply("closeLastWindow"); 101 ready_listener.Reset(); 102 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 103 ASSERT_FALSE(extension_prefs->IsActive(extension->id())); 104 105 // Close the last window and exit. 106 ready_listener.Reply("closeLastWindow"); 107 ready_listener.Reset(); 108 ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); 109 ready_listener.Reply("exit"); 110 } 111 112 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, FileAccessIsSavedToPrefs) { 113 content::WindowedNotificationObserver extension_suspended( 114 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, 115 content::NotificationService::AllSources()); 116 117 base::ScopedTempDir temp_directory; 118 ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); 119 base::FilePath temp_file; 120 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.path(), 121 &temp_file)); 122 123 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( 124 &temp_file); 125 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest( 126 "temp", temp_directory.path()); 127 128 const Extension* extension = LoadAndLaunchPlatformApp( 129 "file_access_saved_to_prefs_test", "fileWritten"); 130 ASSERT_TRUE(extension); 131 132 SavedFilesService* saved_files_service = SavedFilesService::Get(profile()); 133 134 std::vector<SavedFileEntry> file_entries = 135 saved_files_service->GetAllFileEntries(extension->id()); 136 // One for the read-only file entry and one for the writable file entry. 137 ASSERT_EQ(2u, file_entries.size()); 138 139 extension_suspended.Wait(); 140 file_entries = saved_files_service->GetAllFileEntries(extension->id()); 141 // File entries should be cleared when the extension is suspended. 142 ASSERT_TRUE(file_entries.empty()); 143 } 144 145 // Flaky: crbug.com/269613 146 #if defined(OS_LINUX) || defined(OS_WIN) 147 #define MAYBE_FileAccessIsRestored DISABLED_FileAccessIsRestored 148 #else 149 #define MAYBE_FileAccessIsRestored FileAccessIsRestored 150 #endif 151 152 IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, MAYBE_FileAccessIsRestored) { 153 content::WindowedNotificationObserver extension_suspended( 154 extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED, 155 content::NotificationService::AllSources()); 156 157 base::ScopedTempDir temp_directory; 158 ASSERT_TRUE(temp_directory.CreateUniqueTempDir()); 159 base::FilePath temp_file; 160 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_directory.path(), 161 &temp_file)); 162 163 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( 164 &temp_file); 165 FileSystemChooseEntryFunction::RegisterTempExternalFileSystemForTest( 166 "temp", temp_directory.path()); 167 168 ExtensionTestMessageListener access_ok_listener( 169 "restartedFileAccessOK", false); 170 171 const Extension* extension = 172 LoadAndLaunchPlatformApp("file_access_restored_test", "fileWritten"); 173 ASSERT_TRUE(extension); 174 175 ExtensionPrefs* extension_prefs = 176 ExtensionPrefs::Get(browser()->profile()); 177 SavedFilesService* saved_files_service = SavedFilesService::Get(profile()); 178 std::vector<SavedFileEntry> file_entries = 179 saved_files_service->GetAllFileEntries(extension->id()); 180 extension_suspended.Wait(); 181 182 // Simulate a restart by populating the preferences as if the browser didn't 183 // get time to clean itself up. 184 extension_prefs->SetExtensionRunning(extension->id(), true); 185 for (std::vector<SavedFileEntry>::const_iterator it = file_entries.begin(); 186 it != file_entries.end(); ++it) { 187 saved_files_service->RegisterFileEntry( 188 extension->id(), it->id, it->path, it->is_directory); 189 } 190 191 apps::AppRestoreServiceFactory::GetForProfile(browser()->profile())-> 192 HandleStartup(true); 193 194 access_ok_listener.WaitUntilSatisfied(); 195 } 196 197 } // namespace apps 198