1 // Copyright 2014 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.
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "webkit/browser/fileapi/file_system_url.h"
11 #include "webkit/browser/fileapi/isolated_context.h"
13 #define FPL(x) FILE_PATH_LITERAL(x)
15 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
16 #define DRIVE FPL("C:")
21 using fileapi::FileSystemMountOption;
22 using fileapi::FileSystemType;
23 using fileapi::FileSystemURL;
24 using fileapi::IsolatedContext;
25 using fileapi::kFileSystemTypeDragged;
26 using fileapi::kFileSystemTypeIsolated;
27 using fileapi::kFileSystemTypeNativeLocal;
31 typedef IsolatedContext::MountPointInfo FileInfo;
35 const base::FilePath kTestPaths[] = {
36 base::FilePath(DRIVE FPL("/a/b.txt")),
37 base::FilePath(DRIVE FPL("/c/d/e")),
38 base::FilePath(DRIVE FPL("/h/")),
39 base::FilePath(DRIVE FPL("/")),
40 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
41 base::FilePath(DRIVE FPL("\\foo\\bar")),
42 base::FilePath(DRIVE FPL("\\")),
44 // For duplicated base name test.
45 base::FilePath(DRIVE FPL("/")),
46 base::FilePath(DRIVE FPL("/f/e")),
47 base::FilePath(DRIVE FPL("/f/b.txt")),
52 class IsolatedContextTest : public testing::Test {
54 IsolatedContextTest() {
55 for (size_t i = 0; i < arraysize(kTestPaths); ++i)
56 fileset_.insert(kTestPaths[i].NormalizePathSeparators());
59 virtual void SetUp() {
60 IsolatedContext::FileInfoSet files;
61 for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
64 files.AddPath(kTestPaths[i].NormalizePathSeparators(), &name));
65 names_.push_back(name);
67 id_ = IsolatedContext::GetInstance()->RegisterDraggedFileSystem(files);
68 IsolatedContext::GetInstance()->AddReference(id_);
69 ASSERT_FALSE(id_.empty());
72 virtual void TearDown() {
73 IsolatedContext::GetInstance()->RemoveReference(id_);
76 IsolatedContext* isolated_context() const {
77 return IsolatedContext::GetInstance();
82 std::multiset<base::FilePath> fileset_;
83 std::vector<std::string> names_;
86 DISALLOW_COPY_AND_ASSIGN(IsolatedContextTest);
89 TEST_F(IsolatedContextTest, RegisterAndRevokeTest) {
90 // See if the returned top-level entries match with what we registered.
91 std::vector<FileInfo> toplevels;
92 ASSERT_TRUE(isolated_context()->GetDraggedFileInfo(id_, &toplevels));
93 ASSERT_EQ(fileset_.size(), toplevels.size());
94 for (size_t i = 0; i < toplevels.size(); ++i) {
95 ASSERT_TRUE(fileset_.find(toplevels[i].path) != fileset_.end());
98 // See if the name of each registered kTestPaths (that is what we
99 // register in SetUp() by RegisterDraggedFileSystem) is properly cracked as
100 // a valid virtual path in the isolated filesystem.
101 for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
102 base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_)
103 .AppendASCII(names_[i]);
104 std::string cracked_id;
105 base::FilePath cracked_path;
106 FileSystemType cracked_type;
107 FileSystemMountOption cracked_option;
108 ASSERT_TRUE(isolated_context()->CrackVirtualPath(
109 virtual_path, &cracked_id, &cracked_type, &cracked_path,
111 ASSERT_EQ(kTestPaths[i].NormalizePathSeparators().value(),
112 cracked_path.value());
113 ASSERT_EQ(id_, cracked_id);
114 ASSERT_EQ(kFileSystemTypeDragged, cracked_type);
117 // Make sure GetRegisteredPath returns false for id_ since it is
118 // registered for dragged files.
120 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id_, &path));
122 // Deref the current one and registering a new one.
123 isolated_context()->RemoveReference(id_);
125 std::string id2 = isolated_context()->RegisterFileSystemForPath(
126 kFileSystemTypeNativeLocal, base::FilePath(DRIVE FPL("/foo")), NULL);
128 // Make sure the GetDraggedFileInfo returns false for both ones.
129 ASSERT_FALSE(isolated_context()->GetDraggedFileInfo(id2, &toplevels));
130 ASSERT_FALSE(isolated_context()->GetDraggedFileInfo(id_, &toplevels));
132 // Make sure the GetRegisteredPath returns true only for the new one.
133 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id_, &path));
134 ASSERT_TRUE(isolated_context()->GetRegisteredPath(id2, &path));
136 // Try registering three more file systems for the same path as id2.
137 std::string id3 = isolated_context()->RegisterFileSystemForPath(
138 kFileSystemTypeNativeLocal, path, NULL);
139 std::string id4 = isolated_context()->RegisterFileSystemForPath(
140 kFileSystemTypeNativeLocal, path, NULL);
141 std::string id5 = isolated_context()->RegisterFileSystemForPath(
142 kFileSystemTypeNativeLocal, path, NULL);
144 // Remove file system for id4.
145 isolated_context()->AddReference(id4);
146 isolated_context()->RemoveReference(id4);
148 // Only id4 should become invalid now.
149 ASSERT_TRUE(isolated_context()->GetRegisteredPath(id2, &path));
150 ASSERT_TRUE(isolated_context()->GetRegisteredPath(id3, &path));
151 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id4, &path));
152 ASSERT_TRUE(isolated_context()->GetRegisteredPath(id5, &path));
154 // Revoke file system id5, after adding multiple references.
155 isolated_context()->AddReference(id5);
156 isolated_context()->AddReference(id5);
157 isolated_context()->AddReference(id5);
158 isolated_context()->RevokeFileSystem(id5);
160 // No matter how many references we add id5 must be invalid now.
161 ASSERT_TRUE(isolated_context()->GetRegisteredPath(id2, &path));
162 ASSERT_TRUE(isolated_context()->GetRegisteredPath(id3, &path));
163 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id4, &path));
164 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id5, &path));
166 // Revoke the file systems by path.
167 isolated_context()->RevokeFileSystemByPath(path);
169 // Now all the file systems associated to the path must be invalid.
170 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id2, &path));
171 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id3, &path));
172 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id4, &path));
173 ASSERT_FALSE(isolated_context()->GetRegisteredPath(id5, &path));
176 TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
178 base::FilePath::StringType path;
181 { FPL("foo"), true },
182 { FPL("foo/bar"), true },
183 { FPL(".."), false },
184 { FPL("foo/.."), false },
185 { FPL("foo/../bar"), false },
186 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
187 # define SHOULD_FAIL_WITH_WIN_SEPARATORS false
189 # define SHOULD_FAIL_WITH_WIN_SEPARATORS true
191 { FPL("foo\\..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
192 { FPL("foo/..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
195 for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
196 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(relatives); ++j) {
197 SCOPED_TRACE(testing::Message() << "Testing "
198 << kTestPaths[i].value() << " " << relatives[j].path);
199 base::FilePath virtual_path =
200 isolated_context()->CreateVirtualRootPath(id_).AppendASCII(
201 names_[i]).Append(relatives[j].path);
202 std::string cracked_id;
203 base::FilePath cracked_path;
204 FileSystemType cracked_type;
205 FileSystemMountOption cracked_option;
206 if (!relatives[j].valid) {
207 ASSERT_FALSE(isolated_context()->CrackVirtualPath(
208 virtual_path, &cracked_id, &cracked_type, &cracked_path,
212 ASSERT_TRUE(isolated_context()->CrackVirtualPath(
213 virtual_path, &cracked_id, &cracked_type, &cracked_path,
215 ASSERT_EQ(kTestPaths[i].Append(relatives[j].path)
216 .NormalizePathSeparators().value(),
217 cracked_path.value());
218 ASSERT_EQ(id_, cracked_id);
219 ASSERT_EQ(kFileSystemTypeDragged, cracked_type);
224 TEST_F(IsolatedContextTest, CrackURLWithRelativePaths) {
226 base::FilePath::StringType path;
229 { FPL("foo"), true },
230 { FPL("foo/bar"), true },
231 { FPL(".."), false },
232 { FPL("foo/.."), false },
233 { FPL("foo/../bar"), false },
234 #if defined(FILE_PATH_USES_WIN_SEPARATORS)
235 # define SHOULD_FAIL_WITH_WIN_SEPARATORS false
237 # define SHOULD_FAIL_WITH_WIN_SEPARATORS true
239 { FPL("foo\\..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
240 { FPL("foo/..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
243 for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
244 for (size_t j = 0; j < ARRAYSIZE_UNSAFE(relatives); ++j) {
245 SCOPED_TRACE(testing::Message() << "Testing "
246 << kTestPaths[i].value() << " " << relatives[j].path);
247 base::FilePath virtual_path =
248 isolated_context()->CreateVirtualRootPath(id_).AppendASCII(
249 names_[i]).Append(relatives[j].path);
251 FileSystemURL cracked = isolated_context()->CreateCrackedFileSystemURL(
252 GURL("http://chromium.org"), kFileSystemTypeIsolated, virtual_path);
254 ASSERT_EQ(relatives[j].valid, cracked.is_valid());
256 if (!relatives[j].valid)
258 ASSERT_EQ(GURL("http://chromium.org"), cracked.origin());
259 ASSERT_EQ(kTestPaths[i].Append(relatives[j].path)
260 .NormalizePathSeparators().value(),
261 cracked.path().value());
262 ASSERT_EQ(virtual_path.NormalizePathSeparators(), cracked.virtual_path());
263 ASSERT_EQ(id_, cracked.filesystem_id());
264 ASSERT_EQ(kFileSystemTypeDragged, cracked.type());
265 ASSERT_EQ(kFileSystemTypeIsolated, cracked.mount_type());
270 TEST_F(IsolatedContextTest, TestWithVirtualRoot) {
271 std::string cracked_id;
272 base::FilePath cracked_path;
273 FileSystemMountOption cracked_option;
275 // Trying to crack virtual root "/" returns true but with empty cracked path
276 // as "/" of the isolated filesystem is a pure virtual directory
277 // that has no corresponding platform directory.
278 base::FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_);
279 ASSERT_TRUE(isolated_context()->CrackVirtualPath(
280 virtual_path, &cracked_id, NULL, &cracked_path, &cracked_option));
281 ASSERT_EQ(FPL(""), cracked_path.value());
282 ASSERT_EQ(id_, cracked_id);
284 // Trying to crack "/foo" should fail (because "foo" is not the one
285 // included in the kTestPaths).
286 virtual_path = isolated_context()->CreateVirtualRootPath(
287 id_).AppendASCII("foo");
288 ASSERT_FALSE(isolated_context()->CrackVirtualPath(
289 virtual_path, &cracked_id, NULL, &cracked_path, &cracked_option));
292 TEST_F(IsolatedContextTest, CanHandleURL) {
293 const GURL test_origin("http://chromium.org");
294 const base::FilePath test_path(FPL("/mount"));
296 // Should handle isolated file system.
297 EXPECT_TRUE(isolated_context()->HandlesFileSystemMountType(
298 fileapi::kFileSystemTypeIsolated));
300 // Shouldn't handle the rest.
301 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
302 fileapi::kFileSystemTypeExternal));
303 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
304 fileapi::kFileSystemTypeTemporary));
305 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
306 fileapi::kFileSystemTypePersistent));
307 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
308 fileapi::kFileSystemTypeTest));
309 // Not even if it's isolated subtype.
310 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
311 fileapi::kFileSystemTypeNativeLocal));
312 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
313 fileapi::kFileSystemTypeDragged));
314 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
315 fileapi::kFileSystemTypeNativeMedia));
316 EXPECT_FALSE(isolated_context()->HandlesFileSystemMountType(
317 fileapi::kFileSystemTypeDeviceMedia));
320 TEST_F(IsolatedContextTest, VirtualFileSystemTests) {
321 // Should be able to register empty and non-absolute paths
322 std::string empty_fsid = isolated_context()->RegisterFileSystemForVirtualPath(
323 fileapi::kFileSystemTypeIsolated, "_", base::FilePath());
324 std::string relative_fsid =
325 isolated_context()->RegisterFileSystemForVirtualPath(
326 fileapi::kFileSystemTypeIsolated, "_",
327 base::FilePath(FPL("relpath")));
328 ASSERT_FALSE(empty_fsid.empty());
329 ASSERT_FALSE(relative_fsid.empty());
331 // Make sure that filesystem root is not prepended to cracked virtual paths.
332 base::FilePath database_root = base::FilePath(DRIVE FPL("/database_path"));
333 std::string database_fsid =
334 isolated_context()->RegisterFileSystemForVirtualPath(
335 fileapi::kFileSystemTypeIsolated, "_", database_root);
337 base::FilePath test_virtual_path =
338 base::FilePath().AppendASCII("virtualdir").AppendASCII("virtualfile.txt");
340 base::FilePath whole_virtual_path =
341 isolated_context()->CreateVirtualRootPath(database_fsid)
342 .AppendASCII("_").Append(test_virtual_path);
344 std::string cracked_id;
345 base::FilePath cracked_path;
346 FileSystemMountOption cracked_option;
347 ASSERT_TRUE(isolated_context()->CrackVirtualPath(
348 whole_virtual_path, &cracked_id, NULL, &cracked_path, &cracked_option));
349 ASSERT_EQ(database_fsid, cracked_id);
350 ASSERT_EQ(test_virtual_path, cracked_path);
353 } // namespace content