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 20using storage::ExternalMountPoints; 21using storage::FileSystemURL; 22 23namespace { 24 25FileSystemURL 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 34TEST(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 64TEST(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 111TEST(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 207TEST(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