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