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