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