Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / fileapi / isolated_context_unittest.cc
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 <string>
6
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"
12
13 #define FPL(x) FILE_PATH_LITERAL(x)
14
15 #if defined(FILE_PATH_USES_DRIVE_LETTERS)
16 #define DRIVE FPL("C:")
17 #else
18 #define DRIVE
19 #endif
20
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;
28
29 namespace content {
30
31 typedef IsolatedContext::MountPointInfo FileInfo;
32
33 namespace {
34
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("\\")),
43 #endif
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")),
48 };
49
50 }  // namespace
51
52 class IsolatedContextTest : public testing::Test {
53  public:
54   IsolatedContextTest() {
55     for (size_t i = 0; i < arraysize(kTestPaths); ++i)
56       fileset_.insert(kTestPaths[i].NormalizePathSeparators());
57   }
58
59   virtual void SetUp() {
60     IsolatedContext::FileInfoSet files;
61     for (size_t i = 0; i < arraysize(kTestPaths); ++i) {
62       std::string name;
63       ASSERT_TRUE(
64           files.AddPath(kTestPaths[i].NormalizePathSeparators(), &name));
65       names_.push_back(name);
66     }
67     id_ = IsolatedContext::GetInstance()->RegisterDraggedFileSystem(files);
68     IsolatedContext::GetInstance()->AddReference(id_);
69     ASSERT_FALSE(id_.empty());
70   }
71
72   virtual void TearDown() {
73     IsolatedContext::GetInstance()->RemoveReference(id_);
74   }
75
76   IsolatedContext* isolated_context() const {
77     return IsolatedContext::GetInstance();
78   }
79
80  protected:
81   std::string id_;
82   std::multiset<base::FilePath> fileset_;
83   std::vector<std::string> names_;
84
85  private:
86   DISALLOW_COPY_AND_ASSIGN(IsolatedContextTest);
87 };
88
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());
96   }
97
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,
110         &cracked_option));
111     ASSERT_EQ(kTestPaths[i].NormalizePathSeparators().value(),
112               cracked_path.value());
113     ASSERT_EQ(id_, cracked_id);
114     ASSERT_EQ(kFileSystemTypeDragged, cracked_type);
115   }
116
117   // Make sure GetRegisteredPath returns false for id_ since it is
118   // registered for dragged files.
119   base::FilePath path;
120   ASSERT_FALSE(isolated_context()->GetRegisteredPath(id_, &path));
121
122   // Deref the current one and registering a new one.
123   isolated_context()->RemoveReference(id_);
124
125   std::string id2 = isolated_context()->RegisterFileSystemForPath(
126       kFileSystemTypeNativeLocal, base::FilePath(DRIVE FPL("/foo")), NULL);
127
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));
131
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));
135
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);
143
144   // Remove file system for id4.
145   isolated_context()->AddReference(id4);
146   isolated_context()->RemoveReference(id4);
147
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));
153
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);
159
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));
165
166   // Revoke the file systems by path.
167   isolated_context()->RevokeFileSystemByPath(path);
168
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));
174 }
175
176 TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
177   const struct {
178     base::FilePath::StringType path;
179     bool valid;
180   } relatives[] = {
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
188 #else
189 # define SHOULD_FAIL_WITH_WIN_SEPARATORS true
190 #endif
191     { FPL("foo\\..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
192     { FPL("foo/..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
193   };
194
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,
209             &cracked_option));
210         continue;
211       }
212       ASSERT_TRUE(isolated_context()->CrackVirtualPath(
213           virtual_path, &cracked_id, &cracked_type, &cracked_path,
214           &cracked_option));
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);
220     }
221   }
222 }
223
224 TEST_F(IsolatedContextTest, CrackURLWithRelativePaths) {
225   const struct {
226     base::FilePath::StringType path;
227     bool valid;
228   } relatives[] = {
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
236 #else
237 # define SHOULD_FAIL_WITH_WIN_SEPARATORS true
238 #endif
239     { FPL("foo\\..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
240     { FPL("foo/..\\baz"), SHOULD_FAIL_WITH_WIN_SEPARATORS },
241   };
242
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);
250
251       FileSystemURL cracked = isolated_context()->CreateCrackedFileSystemURL(
252           GURL("http://chromium.org"), kFileSystemTypeIsolated, virtual_path);
253
254       ASSERT_EQ(relatives[j].valid, cracked.is_valid());
255
256       if (!relatives[j].valid)
257         continue;
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());
266     }
267   }
268 }
269
270 TEST_F(IsolatedContextTest, TestWithVirtualRoot) {
271   std::string cracked_id;
272   base::FilePath cracked_path;
273   FileSystemMountOption cracked_option;
274
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);
283
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));
290 }
291
292 TEST_F(IsolatedContextTest, CanHandleURL) {
293   const GURL test_origin("http://chromium.org");
294   const base::FilePath test_path(FPL("/mount"));
295
296   // Should handle isolated file system.
297   EXPECT_TRUE(isolated_context()->HandlesFileSystemMountType(
298       fileapi::kFileSystemTypeIsolated));
299
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));
318 }
319
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());
330
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);
336
337   base::FilePath test_virtual_path =
338       base::FilePath().AppendASCII("virtualdir").AppendASCII("virtualfile.txt");
339
340   base::FilePath whole_virtual_path =
341       isolated_context()->CreateVirtualRootPath(database_fsid)
342           .AppendASCII("_").Append(test_virtual_path);
343
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);
351 }
352
353 }  // namespace content