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