1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
7 #include "base/files/file_util.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/path_service.h"
10 #include "chrome/browser/apps/app_browsertest_util.h"
11 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
12 #include "chrome/browser/chromeos/drive/file_system_interface.h"
13 #include "chrome/browser/chromeos/drive/file_system_util.h"
14 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
15 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
16 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
17 #include "chrome/browser/chromeos/profiles/profile_helper.h"
18 #include "chrome/browser/drive/fake_drive_service.h"
19 #include "chrome/browser/extensions/component_loader.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/extensions/features/feature_channel.h"
22 #include "content/public/test/test_utils.h"
23 #include "google_apis/drive/drive_api_parser.h"
24 #include "google_apis/drive/test_util.h"
25 #include "storage/browser/fileapi/external_mount_points.h"
26 #include "ui/base/ui_base_types.h"
28 using file_manager::VolumeManager
;
30 namespace extensions
{
33 // Mount point names for chrome.fileSystem.requestFileSystem() tests.
34 const char kWritableMountPointName
[] = "writable";
35 const char kReadOnlyMountPointName
[] = "read-only";
37 // Child directory created in each of the mount points.
38 const char kChildDirectory
[] = "child-dir";
42 // Skips the user consent dialog for chrome.fileSystem.requestFileSystem() and
43 // simulates clicking of the specified dialog button.
44 class ScopedSkipRequestFileSystemDialog
{
46 explicit ScopedSkipRequestFileSystemDialog(ui::DialogButton button
) {
47 file_system_api::ConsentProviderDelegate::SetAutoDialogButtonForTest(
50 ~ScopedSkipRequestFileSystemDialog() {
51 file_system_api::ConsentProviderDelegate::SetAutoDialogButtonForTest(
52 ui::DIALOG_BUTTON_NONE
);
56 DISALLOW_COPY_AND_ASSIGN(ScopedSkipRequestFileSystemDialog
);
59 // This class contains chrome.filesystem API test specific to Chrome OS, namely,
60 // the integrated Google Drive support.
61 class FileSystemApiTestForDrive
: public PlatformAppBrowserTest
{
63 FileSystemApiTestForDrive()
64 : fake_drive_service_(NULL
),
65 integration_service_(NULL
) {
68 // Sets up fake Drive service for tests (this has to be injected before the
69 // real DriveIntegrationService instance is created.)
70 void SetUpInProcessBrowserTestFixture() override
{
71 PlatformAppBrowserTest::SetUpInProcessBrowserTestFixture();
72 extensions::ComponentLoader::EnableBackgroundExtensionsForTesting();
74 ASSERT_TRUE(test_cache_root_
.CreateUniqueTempDir());
76 create_drive_integration_service_
=
77 base::Bind(&FileSystemApiTestForDrive::CreateDriveIntegrationService
,
78 base::Unretained(this));
79 service_factory_for_test_
.reset(
80 new drive::DriveIntegrationServiceFactory::ScopedFactoryForTest(
81 &create_drive_integration_service_
));
84 // Ensure the fake service's data is fetch in the local file system. This is
85 // necessary because the fetch starts lazily upon the first read operation.
86 void SetUpOnMainThread() override
{
87 PlatformAppBrowserTest::SetUpOnMainThread();
89 scoped_ptr
<drive::ResourceEntry
> entry
;
90 drive::FileError error
= drive::FILE_ERROR_FAILED
;
91 integration_service_
->file_system()->GetResourceEntry(
92 base::FilePath::FromUTF8Unsafe("drive/root"), // whatever
93 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
94 content::RunAllBlockingPoolTasksUntilIdle();
95 ASSERT_EQ(drive::FILE_ERROR_OK
, error
);
98 void TearDown() override
{
99 FileSystemChooseEntryFunction::StopSkippingPickerForTest();
100 PlatformAppBrowserTest::TearDown();
104 drive::DriveIntegrationService
* CreateDriveIntegrationService(
106 // Ignore signin profile.
107 if (profile
->GetPath() == chromeos::ProfileHelper::GetSigninProfileDir())
110 // FileSystemApiTestForDrive doesn't expect that several user profiles could
111 // exist simultaneously.
112 DCHECK(fake_drive_service_
== NULL
);
113 fake_drive_service_
= new drive::FakeDriveService
;
114 fake_drive_service_
->LoadAppListForDriveApi("drive/applist.json");
116 SetUpTestFileHierarchy();
118 integration_service_
= new drive::DriveIntegrationService(
119 profile
, NULL
, fake_drive_service_
, std::string(),
120 test_cache_root_
.path(), NULL
);
121 return integration_service_
;
124 void SetUpTestFileHierarchy() {
125 const std::string root
= fake_drive_service_
->GetRootResourceId();
126 ASSERT_TRUE(AddTestFile("open_existing.txt", "Can you see me?", root
));
127 ASSERT_TRUE(AddTestFile("open_existing1.txt", "Can you see me?", root
));
128 ASSERT_TRUE(AddTestFile("open_existing2.txt", "Can you see me?", root
));
129 ASSERT_TRUE(AddTestFile("save_existing.txt", "Can you see me?", root
));
130 const std::string subdir
= AddTestDirectory("subdir", root
);
131 ASSERT_FALSE(subdir
.empty());
132 ASSERT_TRUE(AddTestFile("open_existing.txt", "Can you see me?", subdir
));
135 bool AddTestFile(const std::string
& title
,
136 const std::string
& data
,
137 const std::string
& parent_id
) {
138 scoped_ptr
<google_apis::FileResource
> entry
;
139 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
140 fake_drive_service_
->AddNewFile(
141 "text/plain", data
, parent_id
, title
, false,
142 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
143 content::RunAllPendingInMessageLoop();
144 return error
== google_apis::HTTP_CREATED
&& entry
;
147 std::string
AddTestDirectory(const std::string
& title
,
148 const std::string
& parent_id
) {
149 scoped_ptr
<google_apis::FileResource
> entry
;
150 google_apis::DriveApiErrorCode error
= google_apis::DRIVE_OTHER_ERROR
;
151 fake_drive_service_
->AddNewDirectory(
152 parent_id
, title
, drive::AddNewDirectoryOptions(),
153 google_apis::test_util::CreateCopyResultCallback(&error
, &entry
));
154 content::RunAllPendingInMessageLoop();
155 return error
== google_apis::HTTP_CREATED
&& entry
? entry
->file_id() : "";
158 base::ScopedTempDir test_cache_root_
;
159 drive::FakeDriveService
* fake_drive_service_
;
160 drive::DriveIntegrationService
* integration_service_
;
161 drive::DriveIntegrationServiceFactory::FactoryCallback
162 create_drive_integration_service_
;
163 scoped_ptr
<drive::DriveIntegrationServiceFactory::ScopedFactoryForTest
>
164 service_factory_for_test_
;
167 // This class contains chrome.filesystem.requestFileSystem API tests.
168 class FileSystemApiTestForRequestFileSystem
: public PlatformAppBrowserTest
{
170 FileSystemApiTestForRequestFileSystem()
171 : current_channel_(chrome::VersionInfo::CHANNEL_DEV
),
172 fake_user_manager_(nullptr) {}
174 void SetUpOnMainThread() override
{
175 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
176 CreateTestingFileSystem(kWritableMountPointName
, false /* read_only */);
177 CreateTestingFileSystem(kReadOnlyMountPointName
, true /* read_only */);
178 PlatformAppBrowserTest::SetUpOnMainThread();
181 void TearDownOnMainThread() override
{
182 PlatformAppBrowserTest::TearDownOnMainThread();
183 user_manager_enabler_
.reset();
184 fake_user_manager_
= nullptr;
188 extensions::ScopedCurrentChannel current_channel_
;
189 base::ScopedTempDir temp_dir_
;
190 chromeos::FakeChromeUserManager
* fake_user_manager_
;
191 scoped_ptr
<chromeos::ScopedUserManagerEnabler
> user_manager_enabler_
;
193 // Creates a testing file system in a testing directory.
194 void CreateTestingFileSystem(const std::string
& mount_point_name
,
196 const base::FilePath mount_point_path
=
197 temp_dir_
.path().Append(mount_point_name
);
198 LOG(ERROR
) << mount_point_path
.value();
199 ASSERT_TRUE(base::CreateDirectory(mount_point_path
));
201 base::CreateDirectory(mount_point_path
.Append(kChildDirectory
)));
202 ASSERT_TRUE(content::BrowserContext::GetMountPoints(browser()->profile())
203 ->RegisterFileSystem(
204 mount_point_name
, storage::kFileSystemTypeNativeLocal
,
205 storage::FileSystemMountOption(), mount_point_path
));
206 VolumeManager
* const volume_manager
=
207 VolumeManager::Get(browser()->profile());
208 ASSERT_TRUE(volume_manager
);
209 volume_manager
->AddVolumeForTesting(
210 mount_point_path
, file_manager::VOLUME_TYPE_TESTING
,
211 chromeos::DEVICE_TYPE_UNKNOWN
, read_only
);
214 // Simulates entering the kiosk session.
215 void EnterKioskSession() {
216 fake_user_manager_
= new chromeos::FakeChromeUserManager();
217 user_manager_enabler_
.reset(
218 new chromeos::ScopedUserManagerEnabler(fake_user_manager_
));
220 const std::string kKioskLogin
= "kiosk@foobar.com";
221 fake_user_manager_
->AddKioskAppUser(kKioskLogin
);
222 fake_user_manager_
->LoginUser(kKioskLogin
);
226 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
227 FileSystemApiOpenExistingFileTest
) {
228 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
229 browser()->profile()).AppendASCII("root/open_existing.txt");
230 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
232 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_existing"))
236 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
237 FileSystemApiOpenExistingFileWithWriteTest
) {
238 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
239 browser()->profile()).AppendASCII("root/open_existing.txt");
240 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
242 ASSERT_TRUE(RunPlatformAppTest(
243 "api_test/file_system/open_existing_with_write")) << message_
;
246 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
247 FileSystemApiOpenMultipleSuggested
) {
248 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
249 browser()->profile()).AppendASCII("root/open_existing.txt");
250 ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded(
251 chrome::DIR_USER_DOCUMENTS
, test_file
.DirName(), true, false));
252 FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest();
253 ASSERT_TRUE(RunPlatformAppTest(
254 "api_test/file_system/open_multiple_with_suggested_name"))
258 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
259 FileSystemApiOpenMultipleExistingFilesTest
) {
260 base::FilePath test_file1
= drive::util::GetDriveMountPointPath(
261 browser()->profile()).AppendASCII("root/open_existing1.txt");
262 base::FilePath test_file2
= drive::util::GetDriveMountPointPath(
263 browser()->profile()).AppendASCII("root/open_existing2.txt");
264 std::vector
<base::FilePath
> test_files
;
265 test_files
.push_back(test_file1
);
266 test_files
.push_back(test_file2
);
267 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathsForTest(
269 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_multiple_existing"))
273 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
274 FileSystemApiOpenDirectoryTest
) {
275 base::FilePath test_directory
=
276 drive::util::GetDriveMountPointPath(browser()->profile()).AppendASCII(
278 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
280 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/open_directory"))
284 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
285 FileSystemApiOpenDirectoryWithWriteTest
) {
286 base::FilePath test_directory
=
287 drive::util::GetDriveMountPointPath(browser()->profile()).AppendASCII(
289 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
292 RunPlatformAppTest("api_test/file_system/open_directory_with_write"))
296 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
297 FileSystemApiOpenDirectoryWithoutPermissionTest
) {
298 base::FilePath test_directory
=
299 drive::util::GetDriveMountPointPath(browser()->profile()).AppendASCII(
301 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
303 ASSERT_TRUE(RunPlatformAppTest(
304 "api_test/file_system/open_directory_without_permission"))
308 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
309 FileSystemApiOpenDirectoryWithOnlyWritePermissionTest
) {
310 base::FilePath test_directory
=
311 drive::util::GetDriveMountPointPath(browser()->profile()).AppendASCII(
313 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
315 ASSERT_TRUE(RunPlatformAppTest(
316 "api_test/file_system/open_directory_with_only_write"))
320 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
321 FileSystemApiSaveNewFileTest
) {
322 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
323 browser()->profile()).AppendASCII("root/save_new.txt");
324 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
326 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_new"))
330 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
331 FileSystemApiSaveExistingFileTest
) {
332 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
333 browser()->profile()).AppendASCII("root/save_existing.txt");
334 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
336 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_existing"))
340 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
341 FileSystemApiSaveNewFileWithWriteTest
) {
342 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
343 browser()->profile()).AppendASCII("root/save_new.txt");
344 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
346 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/save_new_with_write"))
350 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive
,
351 FileSystemApiSaveExistingFileWithWriteTest
) {
352 base::FilePath test_file
= drive::util::GetDriveMountPointPath(
353 browser()->profile()).AppendASCII("root/save_existing.txt");
354 FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest(
356 ASSERT_TRUE(RunPlatformAppTest(
357 "api_test/file_system/save_existing_with_write")) << message_
;
360 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
, Background
) {
362 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_OK
);
364 RunPlatformAppTest("api_test/file_system/request_file_system_background"))
368 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
, ReadOnly
) {
370 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_OK
);
372 RunPlatformAppTest("api_test/file_system/request_file_system_read_only"))
376 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
, Writable
) {
378 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_OK
);
380 RunPlatformAppTest("api_test/file_system/request_file_system_writable"))
384 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
, UserReject
) {
386 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_CANCEL
);
387 ASSERT_TRUE(RunPlatformAppTest(
388 "api_test/file_system/request_file_system_user_reject"))
392 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
, NotKioskSession
) {
393 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_OK
);
394 ASSERT_TRUE(RunPlatformAppTest(
395 "api_test/file_system/request_file_system_not_kiosk_session"))
399 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
,
400 WhitelistedComponent
) {
401 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_CANCEL
);
402 ASSERT_TRUE(RunPlatformAppTestWithFlags(
403 "api_test/file_system/request_file_system_whitelisted_component",
404 kFlagLoadAsComponent
))
408 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
,
409 NotWhitelistedComponent
) {
410 ScopedSkipRequestFileSystemDialog
dialog_skipper(ui::DIALOG_BUTTON_OK
);
411 ASSERT_TRUE(RunPlatformAppTestWithFlags(
412 "api_test/file_system/request_file_system_not_whitelisted_component",
413 kFlagLoadAsComponent
))
417 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
, GetVolumeList
) {
419 ASSERT_TRUE(RunPlatformAppTest("api_test/file_system/get_volume_list"))
423 IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem
,
424 GetVolumeList_NotKioskSession
) {
425 ASSERT_TRUE(RunPlatformAppTest(
426 "api_test/file_system/get_volume_list_not_kiosk_session"))
430 } // namespace extensions