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 "storage/browser/fileapi/file_system_url.h"
6
7#include "base/files/file_path.h"
8#include "storage/common/fileapi/file_system_types.h"
9#include "storage/common/fileapi/file_system_util.h"
10#include "testing/gtest/include/gtest/gtest.h"
11#include "url/gurl.h"
12
13#define FPL FILE_PATH_LITERAL
14
15#if defined(FILE_PATH_USES_DRIVE_LETTERS)
16#define DRIVE FPL("C:")
17#else
18#define DRIVE FPL("/a/")
19#endif
20
21using storage::FileSystemURL;
22using storage::kFileSystemTypeExternal;
23using storage::kFileSystemTypeIsolated;
24using storage::kFileSystemTypePersistent;
25using storage::kFileSystemTypeTemporary;
26using storage::VirtualPath;
27
28namespace content {
29
30namespace {
31
32FileSystemURL CreateFileSystemURL(const std::string& url_string) {
33  FileSystemURL url = FileSystemURL::CreateForTest(GURL(url_string));
34  EXPECT_TRUE(url.type() != kFileSystemTypeExternal &&
35              url.type() != kFileSystemTypeIsolated);
36  return url;
37}
38
39std::string NormalizedUTF8Path(const base::FilePath& path) {
40  return path.NormalizePathSeparators().AsUTF8Unsafe();
41}
42
43}  // namespace
44
45TEST(FileSystemURLTest, ParsePersistent) {
46  FileSystemURL url = CreateFileSystemURL(
47     "filesystem:http://chromium.org/persistent/directory/file");
48  ASSERT_TRUE(url.is_valid());
49  EXPECT_EQ("http://chromium.org/", url.origin().spec());
50  EXPECT_EQ(kFileSystemTypePersistent, url.type());
51  EXPECT_EQ(FPL("file"), VirtualPath::BaseName(url.path()).value());
52  EXPECT_EQ(FPL("directory"), url.path().DirName().value());
53}
54
55TEST(FileSystemURLTest, ParseTemporary) {
56  FileSystemURL url = CreateFileSystemURL(
57      "filesystem:http://chromium.org/temporary/directory/file");
58  ASSERT_TRUE(url.is_valid());
59  EXPECT_EQ("http://chromium.org/", url.origin().spec());
60  EXPECT_EQ(kFileSystemTypeTemporary, url.type());
61  EXPECT_EQ(FPL("file"), VirtualPath::BaseName(url.path()).value());
62  EXPECT_EQ(FPL("directory"), url.path().DirName().value());
63}
64
65TEST(FileSystemURLTest, EnsureFilePathIsRelative) {
66  FileSystemURL url = CreateFileSystemURL(
67      "filesystem:http://chromium.org/temporary/////directory/file");
68  ASSERT_TRUE(url.is_valid());
69  EXPECT_EQ("http://chromium.org/", url.origin().spec());
70  EXPECT_EQ(kFileSystemTypeTemporary, url.type());
71  EXPECT_EQ(FPL("file"), VirtualPath::BaseName(url.path()).value());
72  EXPECT_EQ(FPL("directory"), url.path().DirName().value());
73  EXPECT_FALSE(url.path().IsAbsolute());
74}
75
76TEST(FileSystemURLTest, RejectBadSchemes) {
77  EXPECT_FALSE(CreateFileSystemURL("http://chromium.org/").is_valid());
78  EXPECT_FALSE(CreateFileSystemURL("https://chromium.org/").is_valid());
79  EXPECT_FALSE(CreateFileSystemURL("file:///foo/bar").is_valid());
80  EXPECT_FALSE(CreateFileSystemURL("foobar:///foo/bar").is_valid());
81}
82
83TEST(FileSystemURLTest, UnescapePath) {
84  FileSystemURL url = CreateFileSystemURL(
85      "filesystem:http://chromium.org/persistent/%7Echromium/space%20bar");
86  ASSERT_TRUE(url.is_valid());
87  EXPECT_EQ(FPL("space bar"), VirtualPath::BaseName(url.path()).value());
88  EXPECT_EQ(FPL("~chromium"), url.path().DirName().value());
89}
90
91TEST(FileSystemURLTest, RejectBadType) {
92  EXPECT_FALSE(CreateFileSystemURL(
93      "filesystem:http://c.org/foobar/file").is_valid());
94  EXPECT_FALSE(CreateFileSystemURL(
95      "filesystem:http://c.org/temporaryfoo/file").is_valid());
96}
97
98TEST(FileSystemURLTest, RejectMalformedURL) {
99  EXPECT_FALSE(CreateFileSystemURL("filesystem:///foobar/file").is_valid());
100  EXPECT_FALSE(CreateFileSystemURL("filesystem:foobar/file").is_valid());
101}
102
103TEST(FileSystemURLTest, CompareURLs) {
104  const GURL urls[] = {
105      GURL("filesystem:http://chromium.org/temporary/dir a/file a"),
106      GURL("filesystem:http://chromium.org/temporary/dir a/file a"),
107      GURL("filesystem:http://chromium.org/temporary/dir a/file b"),
108      GURL("filesystem:http://chromium.org/temporary/dir a/file aa"),
109      GURL("filesystem:http://chromium.org/temporary/dir b/file a"),
110      GURL("filesystem:http://chromium.org/temporary/dir aa/file b"),
111      GURL("filesystem:http://chromium.com/temporary/dir a/file a"),
112      GURL("filesystem:https://chromium.org/temporary/dir a/file a")
113  };
114
115  FileSystemURL::Comparator compare;
116  for (size_t i = 0; i < arraysize(urls); ++i) {
117    for (size_t j = 0; j < arraysize(urls); ++j) {
118      SCOPED_TRACE(testing::Message() << i << " < " << j);
119      EXPECT_EQ(urls[i] < urls[j],
120                compare(FileSystemURL::CreateForTest(urls[i]),
121                        FileSystemURL::CreateForTest(urls[j])));
122    }
123  }
124
125  const FileSystemURL a = CreateFileSystemURL(
126      "filesystem:http://chromium.org/temporary/dir a/file a");
127  const FileSystemURL b = CreateFileSystemURL(
128      "filesystem:http://chromium.org/persistent/dir a/file a");
129  EXPECT_EQ(a.type() < b.type(), compare(a, b));
130  EXPECT_EQ(b.type() < a.type(), compare(b, a));
131}
132
133TEST(FileSystemURLTest, IsParent) {
134  const std::string root1 = GetFileSystemRootURI(
135      GURL("http://example.com"), kFileSystemTypeTemporary).spec();
136  const std::string root2 = GetFileSystemRootURI(
137      GURL("http://example.com"), kFileSystemTypePersistent).spec();
138  const std::string root3 = GetFileSystemRootURI(
139      GURL("http://chromium.org"), kFileSystemTypeTemporary).spec();
140
141  const std::string parent("dir");
142  const std::string child("dir/child");
143  const std::string other("other");
144
145  // True cases.
146  EXPECT_TRUE(CreateFileSystemURL(root1 + parent).IsParent(
147      CreateFileSystemURL(root1 + child)));
148  EXPECT_TRUE(CreateFileSystemURL(root2 + parent).IsParent(
149      CreateFileSystemURL(root2 + child)));
150
151  // False cases: the path is not a child.
152  EXPECT_FALSE(CreateFileSystemURL(root1 + parent).IsParent(
153      CreateFileSystemURL(root1 + other)));
154  EXPECT_FALSE(CreateFileSystemURL(root1 + parent).IsParent(
155      CreateFileSystemURL(root1 + parent)));
156  EXPECT_FALSE(CreateFileSystemURL(root1 + child).IsParent(
157      CreateFileSystemURL(root1 + parent)));
158
159  // False case: different types.
160  EXPECT_FALSE(CreateFileSystemURL(root1 + parent).IsParent(
161      CreateFileSystemURL(root2 + child)));
162
163  // False case: different origins.
164  EXPECT_FALSE(CreateFileSystemURL(root1 + parent).IsParent(
165      CreateFileSystemURL(root3 + child)));
166}
167
168TEST(FileSystemURLTest, ToGURL) {
169  EXPECT_TRUE(FileSystemURL().ToGURL().is_empty());
170  const char* kTestURL[] = {
171    "filesystem:http://chromium.org/persistent/directory/file0",
172    "filesystem:http://chromium.org/temporary/directory/file1",
173    "filesystem:http://chromium.org/isolated/directory/file2",
174    "filesystem:http://chromium.org/external/directory/file2",
175    "filesystem:http://chromium.org/test/directory/file3",
176    "filesystem:http://chromium.org/test/plus%2B/space%20/colon%3A",
177  };
178
179  for (size_t i = 0; i < arraysize(kTestURL); ++i) {
180    EXPECT_EQ(
181        kTestURL[i],
182        FileSystemURL::CreateForTest(GURL(kTestURL[i])).ToGURL().spec());
183  }
184}
185
186TEST(FileSystemURLTest, DebugString) {
187  const GURL kOrigin("http://example.com");
188  const base::FilePath kPath(FPL("dir/file"));
189
190  const FileSystemURL kURL1 = FileSystemURL::CreateForTest(
191      kOrigin, kFileSystemTypeTemporary, kPath);
192  EXPECT_EQ("filesystem:http://example.com/temporary/" +
193            NormalizedUTF8Path(kPath),
194            kURL1.DebugString());
195}
196
197TEST(FileSystemURLTest, IsInSameFileSystem) {
198  FileSystemURL url_foo_temp_a = FileSystemURL::CreateForTest(
199      GURL("http://foo"), kFileSystemTypeTemporary,
200      base::FilePath::FromUTF8Unsafe("a"));
201  FileSystemURL url_foo_temp_b = FileSystemURL::CreateForTest(
202      GURL("http://foo"), kFileSystemTypeTemporary,
203      base::FilePath::FromUTF8Unsafe("b"));
204  FileSystemURL url_foo_perm_a = FileSystemURL::CreateForTest(
205      GURL("http://foo"), kFileSystemTypePersistent,
206      base::FilePath::FromUTF8Unsafe("a"));
207  FileSystemURL url_bar_temp_a = FileSystemURL::CreateForTest(
208      GURL("http://bar"), kFileSystemTypeTemporary,
209      base::FilePath::FromUTF8Unsafe("a"));
210  FileSystemURL url_bar_perm_a = FileSystemURL::CreateForTest(
211      GURL("http://bar"), kFileSystemTypePersistent,
212      base::FilePath::FromUTF8Unsafe("a"));
213
214  EXPECT_TRUE(url_foo_temp_a.IsInSameFileSystem(url_foo_temp_a));
215  EXPECT_TRUE(url_foo_temp_a.IsInSameFileSystem(url_foo_temp_b));
216  EXPECT_FALSE(url_foo_temp_a.IsInSameFileSystem(url_foo_perm_a));
217  EXPECT_FALSE(url_foo_temp_a.IsInSameFileSystem(url_bar_temp_a));
218  EXPECT_FALSE(url_foo_temp_a.IsInSameFileSystem(url_bar_perm_a));
219}
220
221}  // namespace content
222