1 // Copyright (c) 2012 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 "base/run_loop.h"
6 #include "base/stl_util.h"
7 #include "chrome/browser/chromeos/drive/file_change.h"
8 #include "chrome/browser/chromeos/extensions/file_manager/event_router.h"
9 #include "chrome/browser/chromeos/file_manager/drive_test_util.h"
10 #include "chrome/browser/chromeos/file_manager/file_watcher.h"
11 #include "chrome/browser/extensions/extension_apitest.h"
12 #include "chrome/test/base/testing_profile.h"
13 #include "chrome/test/base/ui_test_utils.h"
14 #include "chromeos/dbus/cros_disks_client.h"
15 #include "chromeos/disks/mock_disk_mount_manager.h"
16 #include "extensions/common/extension.h"
17 #include "extensions/common/install_warning.h"
18 #include "google_apis/drive/test_util.h"
19 #include "storage/browser/fileapi/external_mount_points.h"
22 using ::testing::ReturnRef
;
24 using chromeos::disks::DiskMountManager
;
29 const char* system_path
;
30 const char* file_path
;
31 const char* device_label
;
32 const char* drive_label
;
33 const char* vendor_id
;
34 const char* vendor_name
;
35 const char* product_id
;
36 const char* product_name
;
38 const char* system_path_prefix
;
39 chromeos::DeviceType device_type
;
45 bool on_removable_device
;
49 struct TestMountPoint
{
50 std::string source_path
;
51 std::string mount_path
;
52 chromeos::MountType mount_type
;
53 chromeos::disks::MountCondition mount_condition
;
55 // -1 if there is no disk info.
59 TestDiskInfo kTestDisks
[] = {
70 "system_path_prefix1",
71 chromeos::DEVICE_TYPE_USB
,
90 "system_path_prefix2",
91 chromeos::DEVICE_TYPE_MOBILE
,
110 "system_path_prefix3",
111 chromeos::DEVICE_TYPE_OPTICAL_DISC
,
122 void DispatchDirectoryChangeEventImpl(
124 const base::FilePath
& virtual_path
,
125 const drive::FileChange
* list
,
127 const std::vector
<std::string
>& extension_ids
) {
131 void AddFileWatchCallback(bool success
) {}
133 bool InitializeLocalFileSystem(std::string mount_point_name
,
134 base::ScopedTempDir
* temp_dir
,
135 base::FilePath
* mount_point_dir
) {
136 const char kTestFileContent
[] = "The five boxing wizards jumped quickly";
137 if (!temp_dir
->CreateUniqueTempDir())
140 *mount_point_dir
= temp_dir
->path().AppendASCII(mount_point_name
);
141 // Create the mount point.
142 if (!base::CreateDirectory(*mount_point_dir
))
145 const base::FilePath test_dir
= mount_point_dir
->AppendASCII("test_dir");
146 if (!base::CreateDirectory(test_dir
))
149 const base::FilePath test_file
= test_dir
.AppendASCII("test_file.txt");
150 if (!google_apis::test_util::WriteStringToFile(test_file
, kTestFileContent
))
158 class FileManagerPrivateApiTest
: public ExtensionApiTest
{
160 FileManagerPrivateApiTest()
161 : disk_mount_manager_mock_(NULL
) {
165 ~FileManagerPrivateApiTest() override
{
166 DCHECK(!disk_mount_manager_mock_
);
167 DCHECK(!testing_profile_
);
168 DCHECK(!event_router_
);
169 STLDeleteValues(&volumes_
);
172 void SetUpOnMainThread() override
{
173 ExtensionApiTest::SetUpOnMainThread();
175 testing_profile_
.reset(new TestingProfile());
176 event_router_
.reset(new file_manager::EventRouter(testing_profile_
.get()));
179 void TearDownOnMainThread() override
{
180 event_router_
->Shutdown();
182 event_router_
.reset();
183 testing_profile_
.reset();
185 ExtensionApiTest::TearDownOnMainThread();
188 // ExtensionApiTest override
189 void SetUpInProcessBrowserTestFixture() override
{
190 ExtensionApiTest::SetUpInProcessBrowserTestFixture();
191 disk_mount_manager_mock_
= new chromeos::disks::MockDiskMountManager
;
192 chromeos::disks::DiskMountManager::InitializeForTesting(
193 disk_mount_manager_mock_
);
194 disk_mount_manager_mock_
->SetupDefaultReplies();
196 // override mock functions.
197 ON_CALL(*disk_mount_manager_mock_
, FindDiskBySourcePath(_
)).WillByDefault(
198 Invoke(this, &FileManagerPrivateApiTest::FindVolumeBySourcePath
));
199 EXPECT_CALL(*disk_mount_manager_mock_
, disks())
200 .WillRepeatedly(ReturnRef(volumes_
));
201 EXPECT_CALL(*disk_mount_manager_mock_
, mount_points())
202 .WillRepeatedly(ReturnRef(mount_points_
));
205 // ExtensionApiTest override
206 void TearDownInProcessBrowserTestFixture() override
{
207 chromeos::disks::DiskMountManager::Shutdown();
208 disk_mount_manager_mock_
= NULL
;
210 ExtensionApiTest::TearDownInProcessBrowserTestFixture();
214 void InitMountPoints() {
215 const TestMountPoint kTestMountPoints
[] = {
218 chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII(
219 "mount_path1").AsUTF8Unsafe(),
220 chromeos::MOUNT_TYPE_DEVICE
,
221 chromeos::disks::MOUNT_CONDITION_NONE
,
226 chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII(
227 "mount_path2").AsUTF8Unsafe(),
228 chromeos::MOUNT_TYPE_DEVICE
,
229 chromeos::disks::MOUNT_CONDITION_NONE
,
234 chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII(
235 "mount_path3").AsUTF8Unsafe(),
236 chromeos::MOUNT_TYPE_DEVICE
,
237 chromeos::disks::MOUNT_CONDITION_NONE
,
241 // Set source path inside another mounted volume.
242 chromeos::CrosDisksClient::GetRemovableDiskMountPoint().AppendASCII(
243 "mount_path3/archive.zip").AsUTF8Unsafe(),
244 chromeos::CrosDisksClient::GetArchiveMountPoint().AppendASCII(
245 "archive_mount_path").AsUTF8Unsafe(),
246 chromeos::MOUNT_TYPE_ARCHIVE
,
247 chromeos::disks::MOUNT_CONDITION_NONE
,
252 for (size_t i
= 0; i
< arraysize(kTestMountPoints
); i
++) {
253 mount_points_
.insert(DiskMountManager::MountPointMap::value_type(
254 kTestMountPoints
[i
].mount_path
,
255 DiskMountManager::MountPointInfo(kTestMountPoints
[i
].source_path
,
256 kTestMountPoints
[i
].mount_path
,
257 kTestMountPoints
[i
].mount_type
,
258 kTestMountPoints
[i
].mount_condition
)
260 int disk_info_index
= kTestMountPoints
[i
].disk_info_index
;
261 if (kTestMountPoints
[i
].disk_info_index
>= 0) {
262 EXPECT_GT(arraysize(kTestDisks
), static_cast<size_t>(disk_info_index
));
263 if (static_cast<size_t>(disk_info_index
) >= arraysize(kTestDisks
))
266 volumes_
.insert(DiskMountManager::DiskMap::value_type(
267 kTestMountPoints
[i
].source_path
,
268 new DiskMountManager::Disk(
269 kTestMountPoints
[i
].source_path
,
270 kTestMountPoints
[i
].mount_path
,
271 kTestDisks
[disk_info_index
].system_path
,
272 kTestDisks
[disk_info_index
].file_path
,
273 kTestDisks
[disk_info_index
].device_label
,
274 kTestDisks
[disk_info_index
].drive_label
,
275 kTestDisks
[disk_info_index
].vendor_id
,
276 kTestDisks
[disk_info_index
].vendor_name
,
277 kTestDisks
[disk_info_index
].product_id
,
278 kTestDisks
[disk_info_index
].product_name
,
279 kTestDisks
[disk_info_index
].fs_uuid
,
280 kTestDisks
[disk_info_index
].system_path_prefix
,
281 kTestDisks
[disk_info_index
].device_type
,
282 kTestDisks
[disk_info_index
].size_in_bytes
,
283 kTestDisks
[disk_info_index
].is_parent
,
284 kTestDisks
[disk_info_index
].is_read_only
,
285 kTestDisks
[disk_info_index
].has_media
,
286 kTestDisks
[disk_info_index
].on_boot_device
,
287 kTestDisks
[disk_info_index
].on_removable_device
,
288 kTestDisks
[disk_info_index
].is_hidden
295 const DiskMountManager::Disk
* FindVolumeBySourcePath(
296 const std::string
& source_path
) {
297 DiskMountManager::DiskMap::const_iterator volume_it
=
298 volumes_
.find(source_path
);
299 return (volume_it
== volumes_
.end()) ? NULL
: volume_it
->second
;
303 chromeos::disks::MockDiskMountManager
* disk_mount_manager_mock_
;
304 DiskMountManager::DiskMap volumes_
;
305 DiskMountManager::MountPointMap mount_points_
;
306 scoped_ptr
<TestingProfile
> testing_profile_
;
307 scoped_ptr
<file_manager::EventRouter
> event_router_
;
310 IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest
, Mount
) {
311 file_manager::test_util::WaitUntilDriveMountPointIsAdded(
312 browser()->profile());
314 // We will call fileManagerPrivate.unmountVolume once. To test that method, we
315 // check that UnmountPath is really called with the same value.
316 EXPECT_CALL(*disk_mount_manager_mock_
, UnmountPath(_
, _
, _
))
318 EXPECT_CALL(*disk_mount_manager_mock_
,
320 chromeos::CrosDisksClient::GetArchiveMountPoint().AppendASCII(
321 "archive_mount_path").AsUTF8Unsafe(),
322 chromeos::UNMOUNT_OPTIONS_NONE
, _
)).Times(1);
324 ASSERT_TRUE(RunComponentExtensionTest("file_browser/mount_test"))
328 IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest
, Permissions
) {
330 RunExtensionTestIgnoreManifestWarnings("file_browser/permissions"));
331 const extensions::Extension
* extension
= GetSingleLoadedExtension();
332 ASSERT_TRUE(extension
);
333 ASSERT_EQ(1u, extension
->install_warnings().size());
334 const extensions::InstallWarning
& warning
= extension
->install_warnings()[0];
335 EXPECT_EQ("fileManagerPrivate", warning
.key
);
338 IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest
, OnFileChanged
) {
339 // In drive volume, deletion of a directory is notified via OnFileChanged.
340 // Local changes directly come to HandleFileWatchNotification from
342 typedef drive::FileChange FileChange
;
343 typedef drive::FileChange::FileType FileType
;
344 typedef drive::FileChange::ChangeType ChangeType
;
347 event_router_
->SetDispatchDirectoryChangeEventImplForTesting(
348 base::Bind(&DispatchDirectoryChangeEventImpl
, &counter
));
350 // /a/b/c and /a/d/e are being watched.
351 event_router_
->AddFileWatch(
352 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/a/b/c")),
353 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs-virtual/root/a/b/c")),
354 "extension_1", base::Bind(&AddFileWatchCallback
));
356 event_router_
->AddFileWatch(
357 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/a/d/e")),
358 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs-hash/root/a/d/e")),
359 "extension_2", base::Bind(&AddFileWatchCallback
));
361 event_router_
->AddFileWatch(
362 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/aaa")),
363 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs-hash/root/aaa")),
364 "extension_3", base::Bind(&AddFileWatchCallback
));
366 // event_router->addFileWatch create some tasks which are performed on message
367 // loop of BrowserThread::FILE. Wait until they are done.
368 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
369 // We also wait the UI thread here, since some tasks which are performed above
370 // message loop back results to the UI thread.
371 base::RunLoop().RunUntilIdle();
373 // When /a is deleted (1 and 2 is notified).
374 FileChange first_change
;
376 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/a")),
377 FileType::FILE_TYPE_DIRECTORY
, ChangeType::DELETE
);
378 event_router_
->OnFileChanged(first_change
);
379 EXPECT_EQ(2, counter
);
381 // When /a/b/c is deleted (1 is notified).
382 FileChange second_change
;
383 second_change
.Update(
384 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/a/b/c")),
385 FileType::FILE_TYPE_DIRECTORY
, ChangeType::DELETE
);
386 event_router_
->OnFileChanged(second_change
);
387 EXPECT_EQ(3, counter
);
389 // When /z/y is deleted (Not notified).
390 FileChange third_change
;
392 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/z/y")),
393 FileType::FILE_TYPE_DIRECTORY
, ChangeType::DELETE
);
394 event_router_
->OnFileChanged(third_change
);
395 EXPECT_EQ(3, counter
);
397 // Remove file watchers.
398 event_router_
->RemoveFileWatch(
399 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/a/b/c")),
401 event_router_
->RemoveFileWatch(
402 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/a/d/e")),
404 event_router_
->RemoveFileWatch(
405 base::FilePath(FILE_PATH_LITERAL("/no-existing-fs/root/aaa")),
408 // event_router->removeFileWatch create some tasks which are performed on
409 // message loop of BrowserThread::FILE. Wait until they are done.
410 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
413 IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest
, ContentChecksum
) {
414 base::ScopedTempDir temp_dir
;
415 base::FilePath mount_point_dir
;
416 const char kLocalMountPointName
[] = "local";
418 ASSERT_TRUE(InitializeLocalFileSystem(kLocalMountPointName
, &temp_dir
,
420 << "Failed to initialize test file system";
422 EXPECT_TRUE(content::BrowserContext::GetMountPoints(browser()->profile())
423 ->RegisterFileSystem(
424 kLocalMountPointName
, storage::kFileSystemTypeNativeLocal
,
425 storage::FileSystemMountOption(), mount_point_dir
));
426 file_manager::VolumeManager::Get(browser()->profile())
427 ->AddVolumeInfoForTesting(mount_point_dir
,
428 file_manager::VOLUME_TYPE_TESTING
,
429 chromeos::DEVICE_TYPE_UNKNOWN
);
431 ASSERT_TRUE(RunComponentExtensionTest("file_browser/content_checksum_test"));