Home | History | Annotate | Download | only in fileapi
      1 // Copyright 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 "chrome/browser/chromeos/fileapi/file_system_backend.h"
      6 
      7 #include <set>
      8 
      9 #include "base/files/file_path.h"
     10 #include "base/path_service.h"
     11 #include "chromeos/dbus/cros_disks_client.h"
     12 #include "content/public/test/mock_special_storage_policy.h"
     13 #include "storage/browser/fileapi/external_mount_points.h"
     14 #include "storage/browser/fileapi/file_system_url.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "url/url_util.h"
     17 
     18 #define FPL(x) FILE_PATH_LITERAL(x)
     19 
     20 using storage::ExternalMountPoints;
     21 using storage::FileSystemURL;
     22 
     23 namespace {
     24 
     25 FileSystemURL CreateFileSystemURL(const std::string& extension,
     26                                   const char* path,
     27                                   ExternalMountPoints* mount_points) {
     28   return mount_points->CreateCrackedFileSystemURL(
     29       GURL("chrome-extension://" + extension + "/"),
     30       storage::kFileSystemTypeExternal,
     31       base::FilePath::FromUTF8Unsafe(path));
     32 }
     33 
     34 TEST(ChromeOSFileSystemBackendTest, DefaultMountPoints) {
     35   // Make sure no system-level mount points are registered before testing
     36   // to avoid flakiness.
     37   storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems();
     38 
     39   scoped_refptr<storage::SpecialStoragePolicy> storage_policy =
     40       new content::MockSpecialStoragePolicy();
     41   scoped_refptr<storage::ExternalMountPoints> mount_points(
     42       storage::ExternalMountPoints::CreateRefCounted());
     43   chromeos::FileSystemBackend backend(
     44       NULL,  // drive_delegate
     45       NULL,  // file_system_provider_delegate
     46       NULL,  // mtp_delegate
     47       storage_policy,
     48       mount_points.get(),
     49       storage::ExternalMountPoints::GetSystemInstance());
     50   backend.AddSystemMountPoints();
     51   std::vector<base::FilePath> root_dirs = backend.GetRootDirectories();
     52   std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
     53 
     54   // By default there should be 3 mount points (in system mount points):
     55   EXPECT_EQ(3u, root_dirs.size());
     56 
     57   EXPECT_TRUE(root_dirs_set.count(
     58       chromeos::CrosDisksClient::GetRemovableDiskMountPoint()));
     59   EXPECT_TRUE(root_dirs_set.count(
     60       chromeos::CrosDisksClient::GetArchiveMountPoint()));
     61   EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/usr/share/oem"))));
     62 }
     63 
     64 TEST(ChromeOSFileSystemBackendTest, GetRootDirectories) {
     65   scoped_refptr<storage::SpecialStoragePolicy> storage_policy =
     66       new content::MockSpecialStoragePolicy();
     67   scoped_refptr<storage::ExternalMountPoints> mount_points(
     68       storage::ExternalMountPoints::CreateRefCounted());
     69 
     70   scoped_refptr<storage::ExternalMountPoints> system_mount_points(
     71       storage::ExternalMountPoints::CreateRefCounted());
     72 
     73   chromeos::FileSystemBackend backend(NULL,  // drive_delegate
     74                                       NULL,  // file_system_provider_delegate
     75                                       NULL,  // mtp_delegate
     76                                       storage_policy,
     77                                       mount_points.get(),
     78                                       system_mount_points.get());
     79 
     80   const size_t initial_root_dirs_size = backend.GetRootDirectories().size();
     81 
     82   // Register 'local' test mount points.
     83   mount_points->RegisterFileSystem("c",
     84                                    storage::kFileSystemTypeNativeLocal,
     85                                    storage::FileSystemMountOption(),
     86                                    base::FilePath(FPL("/a/b/c")));
     87   mount_points->RegisterFileSystem("d",
     88                                    storage::kFileSystemTypeNativeLocal,
     89                                    storage::FileSystemMountOption(),
     90                                    base::FilePath(FPL("/b/c/d")));
     91 
     92   // Register system test mount points.
     93   system_mount_points->RegisterFileSystem("d",
     94                                           storage::kFileSystemTypeNativeLocal,
     95                                           storage::FileSystemMountOption(),
     96                                           base::FilePath(FPL("/g/c/d")));
     97   system_mount_points->RegisterFileSystem("e",
     98                                           storage::kFileSystemTypeNativeLocal,
     99                                           storage::FileSystemMountOption(),
    100                                           base::FilePath(FPL("/g/d/e")));
    101 
    102   std::vector<base::FilePath> root_dirs = backend.GetRootDirectories();
    103   std::set<base::FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
    104   EXPECT_EQ(initial_root_dirs_size + 4, root_dirs.size());
    105   EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/a/b/c"))));
    106   EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/b/c/d"))));
    107   EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/c/d"))));
    108   EXPECT_TRUE(root_dirs_set.count(base::FilePath(FPL("/g/d/e"))));
    109 }
    110 
    111 TEST(ChromeOSFileSystemBackendTest, AccessPermissions) {
    112   url::AddStandardScheme("chrome-extension");
    113 
    114   scoped_refptr<content::MockSpecialStoragePolicy> storage_policy =
    115       new content::MockSpecialStoragePolicy();
    116   scoped_refptr<storage::ExternalMountPoints> mount_points(
    117       storage::ExternalMountPoints::CreateRefCounted());
    118   scoped_refptr<storage::ExternalMountPoints> system_mount_points(
    119       storage::ExternalMountPoints::CreateRefCounted());
    120   chromeos::FileSystemBackend backend(NULL,  // drive_delegate
    121                                       NULL,  // file_system_provider_delegate
    122                                       NULL,  // mtp_delegate
    123                                       storage_policy,
    124                                       mount_points.get(),
    125                                       system_mount_points.get());
    126 
    127   std::string extension("ddammdhioacbehjngdmkjcjbnfginlla");
    128 
    129   storage_policy->AddFileHandler(extension);
    130 
    131   // Initialize mount points.
    132   ASSERT_TRUE(system_mount_points->RegisterFileSystem(
    133       "system",
    134       storage::kFileSystemTypeNativeLocal,
    135       storage::FileSystemMountOption(),
    136       base::FilePath(FPL("/g/system"))));
    137   ASSERT_TRUE(mount_points->RegisterFileSystem(
    138       "removable",
    139       storage::kFileSystemTypeNativeLocal,
    140       storage::FileSystemMountOption(),
    141       base::FilePath(FPL("/media/removable"))));
    142   ASSERT_TRUE(mount_points->RegisterFileSystem(
    143       "oem",
    144       storage::kFileSystemTypeRestrictedNativeLocal,
    145       storage::FileSystemMountOption(),
    146       base::FilePath(FPL("/usr/share/oem"))));
    147 
    148   // Backend specific mount point access.
    149   EXPECT_FALSE(backend.IsAccessAllowed(
    150       CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
    151 
    152   backend.GrantFileAccessToExtension(extension,
    153                                       base::FilePath(FPL("removable/foo")));
    154   EXPECT_TRUE(backend.IsAccessAllowed(
    155       CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
    156   EXPECT_FALSE(backend.IsAccessAllowed(
    157       CreateFileSystemURL(extension, "removable/foo1", mount_points.get())));
    158 
    159   // System mount point access.
    160   EXPECT_FALSE(backend.IsAccessAllowed(
    161       CreateFileSystemURL(extension, "system/foo", system_mount_points.get())));
    162 
    163   backend.GrantFileAccessToExtension(extension,
    164                                       base::FilePath(FPL("system/foo")));
    165   EXPECT_TRUE(backend.IsAccessAllowed(
    166       CreateFileSystemURL(extension, "system/foo", system_mount_points.get())));
    167   EXPECT_FALSE(backend.IsAccessAllowed(
    168       CreateFileSystemURL(extension, "system/foo1",
    169                           system_mount_points.get())));
    170 
    171   // oem is restricted file system.
    172   backend.GrantFileAccessToExtension(
    173       extension, base::FilePath(FPL("oem/foo")));
    174   // The extension should not be able to access the file even if
    175   // GrantFileAccessToExtension was called.
    176   EXPECT_FALSE(backend.IsAccessAllowed(
    177       CreateFileSystemURL(extension, "oem/foo", mount_points.get())));
    178 
    179   backend.GrantFullAccessToExtension(extension);
    180   // The extension should be able to access restricted file system after it was
    181   // granted full access.
    182   EXPECT_TRUE(backend.IsAccessAllowed(
    183       CreateFileSystemURL(extension, "oem/foo", mount_points.get())));
    184   // The extension which was granted full access should be able to access any
    185   // path on current file systems.
    186   EXPECT_TRUE(backend.IsAccessAllowed(
    187       CreateFileSystemURL(extension, "removable/foo1", mount_points.get())));
    188   EXPECT_TRUE(backend.IsAccessAllowed(
    189       CreateFileSystemURL(extension, "system/foo1",
    190                           system_mount_points.get())));
    191 
    192   // The extension cannot access new mount points.
    193   // TODO(tbarzic): This should probably be changed.
    194   ASSERT_TRUE(
    195       mount_points->RegisterFileSystem("test",
    196                                        storage::kFileSystemTypeNativeLocal,
    197                                        storage::FileSystemMountOption(),
    198                                        base::FilePath(FPL("/foo/test"))));
    199   EXPECT_FALSE(backend.IsAccessAllowed(
    200       CreateFileSystemURL(extension, "test_/foo", mount_points.get())));
    201 
    202   backend.RevokeAccessForExtension(extension);
    203   EXPECT_FALSE(backend.IsAccessAllowed(
    204       CreateFileSystemURL(extension, "removable/foo", mount_points.get())));
    205 }
    206 
    207 TEST(ChromeOSFileSystemBackendTest, GetVirtualPathConflictWithSystemPoints) {
    208   scoped_refptr<content::MockSpecialStoragePolicy> storage_policy =
    209       new content::MockSpecialStoragePolicy();
    210   scoped_refptr<storage::ExternalMountPoints> mount_points(
    211       storage::ExternalMountPoints::CreateRefCounted());
    212   scoped_refptr<storage::ExternalMountPoints> system_mount_points(
    213       storage::ExternalMountPoints::CreateRefCounted());
    214   chromeos::FileSystemBackend backend(NULL,  // drive_delegate
    215                                       NULL,  // file_system_provider_delegate
    216                                       NULL,  // mtp_delegate
    217                                       storage_policy,
    218                                       mount_points.get(),
    219                                       system_mount_points.get());
    220 
    221   const storage::FileSystemType type = storage::kFileSystemTypeNativeLocal;
    222   const storage::FileSystemMountOption option =
    223       storage::FileSystemMountOption();
    224 
    225   // Backend specific mount points.
    226   ASSERT_TRUE(mount_points->RegisterFileSystem(
    227       "b", type, option, base::FilePath(FPL("/a/b"))));
    228   ASSERT_TRUE(mount_points->RegisterFileSystem(
    229       "y", type, option, base::FilePath(FPL("/z/y"))));
    230   ASSERT_TRUE(mount_points->RegisterFileSystem(
    231       "n", type, option, base::FilePath(FPL("/m/n"))));
    232 
    233   // System mount points
    234   ASSERT_TRUE(system_mount_points->RegisterFileSystem(
    235       "gb", type, option, base::FilePath(FPL("/a/b"))));
    236   ASSERT_TRUE(
    237       system_mount_points->RegisterFileSystem(
    238           "gz", type, option, base::FilePath(FPL("/z"))));
    239   ASSERT_TRUE(system_mount_points->RegisterFileSystem(
    240        "gp", type, option, base::FilePath(FPL("/m/n/o/p"))));
    241 
    242   struct TestCase {
    243     const base::FilePath::CharType* const local_path;
    244     bool success;
    245     const base::FilePath::CharType* const virtual_path;
    246   };
    247 
    248   const TestCase kTestCases[] = {
    249     // Same paths in both mount points.
    250     { FPL("/a/b/c/d"), true, FPL("b/c/d") },
    251     // System mount points path more specific.
    252     { FPL("/m/n/o/p/r/s"), true, FPL("n/o/p/r/s") },
    253     // System mount points path less specific.
    254     { FPL("/z/y/x"), true, FPL("y/x") },
    255     // Only system mount points path matches.
    256     { FPL("/z/q/r/s"), true, FPL("gz/q/r/s") },
    257     // No match.
    258     { FPL("/foo/xxx"), false, FPL("") },
    259   };
    260 
    261   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
    262     // Initialize virtual path with a value.
    263     base::FilePath virtual_path(FPL("/mount"));
    264     base::FilePath local_path(kTestCases[i].local_path);
    265     EXPECT_EQ(kTestCases[i].success,
    266               backend.GetVirtualPath(local_path, &virtual_path))
    267         << "Resolving " << kTestCases[i].local_path;
    268 
    269     // There are no guarantees for |virtual_path| value if |GetVirtualPath|
    270     // fails.
    271     if (!kTestCases[i].success)
    272       continue;
    273 
    274     base::FilePath expected_virtual_path(kTestCases[i].virtual_path);
    275     EXPECT_EQ(expected_virtual_path, virtual_path)
    276         << "Resolving " << kTestCases[i].local_path;
    277   }
    278 }
    279 
    280 }  // namespace
    281