// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/fileapi/file_system_backend.h" #include #include "base/files/file_path.h" #include "chromeos/dbus/cros_disks_client.h" #include "storage/browser/fileapi/external_mount_points.h" #include "storage/browser/fileapi/file_system_url.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/url_util.h" #define FPL(x) FILE_PATH_LITERAL(x) using storage::ExternalMountPoints; using storage::FileSystemURL; namespace { FileSystemURL CreateFileSystemURL(const std::string& extension, const char* path, ExternalMountPoints* mount_points) { return mount_points->CreateCrackedFileSystemURL( GURL("chrome-extension://" + extension + "/"), storage::kFileSystemTypeExternal, base::FilePath::FromUTF8Unsafe(path)); } TEST(ChromeOSFileSystemBackendTest, DefaultMountPoints) { // Make sure no system-level mount points are registered before testing // to avoid flakiness. storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems(); scoped_refptr mount_points( storage::ExternalMountPoints::CreateRefCounted()); chromeos::FileSystemBackend backend( NULL, // drive_delegate NULL, // file_system_provider_delegate NULL, // mtp_delegate mount_points.get(), storage::ExternalMountPoints::GetSystemInstance()); backend.AddSystemMountPoints(); std::vector root_dirs = backend.GetRootDirectories(); std::set root_dirs_set(root_dirs.begin(), root_dirs.end()); // By default there should be 3 mount points (in system mount points): EXPECT_EQ(3u, root_dirs.size()); EXPECT_TRUE(root_dirs_set.count( chromeos::CrosDisksClient::GetRemovableDiskMountPoint())); EXPECT_TRUE(root_dirs_set.count( chromeos::CrosDisksClient::GetArchiveMountPoint())); EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/usr/share/oem")))); } TEST(ChromeOSFileSystemBackendTest, GetRootDirectories) { scoped_refptr mount_points( storage::ExternalMountPoints::CreateRefCounted()); scoped_refptr system_mount_points( storage::ExternalMountPoints::CreateRefCounted()); chromeos::FileSystemBackend backend(NULL, // drive_delegate NULL, // file_system_provider_delegate NULL, // mtp_delegate mount_points.get(), system_mount_points.get()); const size_t initial_root_dirs_size = backend.GetRootDirectories().size(); // Register 'local' test mount points. mount_points->RegisterFileSystem("c", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/a/b/c"))); mount_points->RegisterFileSystem("d", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/b/c/d"))); // Register system test mount points. system_mount_points->RegisterFileSystem("d", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/g/c/d"))); system_mount_points->RegisterFileSystem("e", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/g/d/e"))); std::vector root_dirs = backend.GetRootDirectories(); std::set root_dirs_set(root_dirs.begin(), root_dirs.end()); EXPECT_EQ(initial_root_dirs_size + 4, root_dirs.size()); EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/a/b/c")))); EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/b/c/d")))); EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/c/d")))); EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/d/e")))); } TEST(ChromeOSFileSystemBackendTest, AccessPermissions) { url::AddStandardScheme("chrome-extension", url::SCHEME_WITHOUT_PORT); scoped_refptr mount_points( storage::ExternalMountPoints::CreateRefCounted()); scoped_refptr system_mount_points( storage::ExternalMountPoints::CreateRefCounted()); chromeos::FileSystemBackend backend(NULL, // drive_delegate NULL, // file_system_provider_delegate NULL, // mtp_delegate mount_points.get(), system_mount_points.get()); std::string extension("ddammdhioacbehjngdmkjcjbnfginlla"); // Initialize mount points. ASSERT_TRUE(system_mount_points->RegisterFileSystem( "system", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/g/system")))); ASSERT_TRUE(mount_points->RegisterFileSystem( "removable", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/media/removable")))); ASSERT_TRUE(mount_points->RegisterFileSystem( "oem", storage::kFileSystemTypeRestrictedNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/usr/share/oem")))); // Backend specific mount point access. EXPECT_FALSE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "removable/foo", mount_points.get()))); backend.GrantFileAccessToExtension(extension, base::FilePath(FPL("removable/foo"))); EXPECT_TRUE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "removable/foo", mount_points.get()))); EXPECT_FALSE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "removable/foo1", mount_points.get()))); // System mount point access. EXPECT_FALSE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "system/foo", system_mount_points.get()))); backend.GrantFileAccessToExtension(extension, base::FilePath(FPL("system/foo"))); EXPECT_TRUE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "system/foo", system_mount_points.get()))); EXPECT_FALSE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "system/foo1", system_mount_points.get()))); // The extension cannot access new mount points. // TODO(tbarzic): This should probably be changed. ASSERT_TRUE( mount_points->RegisterFileSystem("test", storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), base::FilePath(FPL("/foo/test")))); EXPECT_FALSE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "test_/foo", mount_points.get()))); backend.RevokeAccessForExtension(extension); EXPECT_FALSE(backend.IsAccessAllowed( CreateFileSystemURL(extension, "removable/foo", mount_points.get()))); } TEST(ChromeOSFileSystemBackendTest, GetVirtualPathConflictWithSystemPoints) { scoped_refptr mount_points( storage::ExternalMountPoints::CreateRefCounted()); scoped_refptr system_mount_points( storage::ExternalMountPoints::CreateRefCounted()); chromeos::FileSystemBackend backend(NULL, // drive_delegate NULL, // file_system_provider_delegate NULL, // mtp_delegate mount_points.get(), system_mount_points.get()); const storage::FileSystemType type = storage::kFileSystemTypeNativeLocal; const storage::FileSystemMountOption option = storage::FileSystemMountOption(); // Backend specific mount points. ASSERT_TRUE(mount_points->RegisterFileSystem( "b", type, option, base::FilePath(FPL("/a/b")))); ASSERT_TRUE(mount_points->RegisterFileSystem( "y", type, option, base::FilePath(FPL("/z/y")))); ASSERT_TRUE(mount_points->RegisterFileSystem( "n", type, option, base::FilePath(FPL("/m/n")))); // System mount points ASSERT_TRUE(system_mount_points->RegisterFileSystem( "gb", type, option, base::FilePath(FPL("/a/b")))); ASSERT_TRUE( system_mount_points->RegisterFileSystem( "gz", type, option, base::FilePath(FPL("/z")))); ASSERT_TRUE(system_mount_points->RegisterFileSystem( "gp", type, option, base::FilePath(FPL("/m/n/o/p")))); struct TestCase { const base::FilePath::CharType* const local_path; bool success; const base::FilePath::CharType* const virtual_path; }; const TestCase kTestCases[] = { // Same paths in both mount points. { FPL("/a/b/c/d"), true, FPL("b/c/d") }, // System mount points path more specific. { FPL("/m/n/o/p/r/s"), true, FPL("n/o/p/r/s") }, // System mount points path less specific. { FPL("/z/y/x"), true, FPL("y/x") }, // Only system mount points path matches. { FPL("/z/q/r/s"), true, FPL("gz/q/r/s") }, // No match. { FPL("/foo/xxx"), false, FPL("") }, }; for (size_t i = 0; i < arraysize(kTestCases); ++i) { // Initialize virtual path with a value. base::FilePath virtual_path(FPL("/mount")); base::FilePath local_path(kTestCases[i].local_path); EXPECT_EQ(kTestCases[i].success, backend.GetVirtualPath(local_path, &virtual_path)) << "Resolving " << kTestCases[i].local_path; // There are no guarantees for |virtual_path| value if |GetVirtualPath| // fails. if (!kTestCases[i].success) continue; base::FilePath expected_virtual_path(kTestCases[i].virtual_path); EXPECT_EQ(expected_virtual_path, virtual_path) << "Resolving " << kTestCases[i].local_path; } } } // namespace