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.
5 #include "webkit/browser/fileapi/file_system_url.h"
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
11 #include "net/base/escape.h"
12 #include "webkit/common/fileapi/file_system_types.h"
13 #include "webkit/common/fileapi/file_system_util.h"
21 FileSystemURL::FileSystemURL()
23 mount_type_(kFileSystemTypeUnknown),
24 type_(kFileSystemTypeUnknown) {
28 FileSystemURL FileSystemURL::CreateForTest(const GURL& url) {
29 return FileSystemURL(url);
32 FileSystemURL FileSystemURL::CreateForTest(const GURL& origin,
33 FileSystemType mount_type,
34 const base::FilePath& virtual_path) {
35 return FileSystemURL(origin, mount_type, virtual_path);
39 bool FileSystemURL::ParseFileSystemSchemeURL(
42 FileSystemType* mount_type,
43 base::FilePath* virtual_path) {
45 FileSystemType file_system_type = kFileSystemTypeUnknown;
47 if (!url.is_valid() || !url.SchemeIsFileSystem())
54 { kFileSystemTypePersistent, kPersistentDir },
55 { kFileSystemTypeTemporary, kTemporaryDir },
56 { kFileSystemTypeIsolated, kIsolatedDir },
57 { kFileSystemTypeExternal, kExternalDir },
58 { kFileSystemTypeTest, kTestDir },
61 // A path of the inner_url contains only mount type part (e.g. "/temporary").
62 DCHECK(url.inner_url());
63 std::string inner_path = url.inner_url()->path();
64 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidTypes); ++i) {
65 if (inner_path == kValidTypes[i].dir) {
66 file_system_type = kValidTypes[i].type;
71 if (file_system_type == kFileSystemTypeUnknown)
74 std::string path = net::UnescapeURLComponent(url.path(),
75 net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS |
76 net::UnescapeRule::CONTROL_CHARS);
78 // Ensure the path is relative.
79 while (!path.empty() && path[0] == '/')
82 base::FilePath converted_path = base::FilePath::FromUTF8Unsafe(path);
84 // All parent references should have been resolved in the renderer.
85 if (converted_path.ReferencesParent())
89 *origin_url = url.GetOrigin();
91 *mount_type = file_system_type;
93 *virtual_path = converted_path.NormalizePathSeparators().
94 StripTrailingSeparators();
99 FileSystemURL::FileSystemURL(const GURL& url)
100 : mount_type_(kFileSystemTypeUnknown),
101 type_(kFileSystemTypeUnknown) {
102 is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_,
104 path_ = virtual_path_;
108 FileSystemURL::FileSystemURL(const GURL& origin,
109 FileSystemType mount_type,
110 const base::FilePath& virtual_path)
113 mount_type_(mount_type),
114 virtual_path_(virtual_path.NormalizePathSeparators()),
116 path_(virtual_path.NormalizePathSeparators()) {
119 FileSystemURL::FileSystemURL(const GURL& origin,
120 FileSystemType mount_type,
121 const base::FilePath& virtual_path,
122 const std::string& mount_filesystem_id,
123 FileSystemType cracked_type,
124 const base::FilePath& cracked_path,
125 const std::string& filesystem_id)
128 mount_type_(mount_type),
129 virtual_path_(virtual_path.NormalizePathSeparators()),
130 mount_filesystem_id_(mount_filesystem_id),
132 path_(cracked_path.NormalizePathSeparators()),
133 filesystem_id_(filesystem_id) {
136 FileSystemURL::~FileSystemURL() {}
138 GURL FileSystemURL::ToGURL() const {
142 std::string url = GetFileSystemRootURI(origin_, mount_type_).spec();
146 url.append(virtual_path_.AsUTF8Unsafe());
148 // Build nested GURL.
152 std::string FileSystemURL::DebugString() const {
154 return "invalid filesystem: URL";
155 std::ostringstream ss;
156 ss << GetFileSystemRootURI(origin_, mount_type_);
158 // filesystem_id_ will be non empty for (and only for) cracked URLs.
159 if (!filesystem_id_.empty()) {
160 ss << virtual_path_.value();
162 ss << GetFileSystemTypeString(type_) << "@" << filesystem_id_ << ":";
171 bool FileSystemURL::IsParent(const FileSystemURL& child) const {
172 return IsInSameFileSystem(child) &&
173 path().IsParent(child.path());
176 bool FileSystemURL::IsInSameFileSystem(const FileSystemURL& other) const {
177 return origin() == other.origin() &&
178 type() == other.type() &&
179 filesystem_id() == other.filesystem_id();
182 bool FileSystemURL::operator==(const FileSystemURL& that) const {
183 return origin_ == that.origin_ &&
184 type_ == that.type_ &&
185 path_ == that.path_ &&
186 filesystem_id_ == that.filesystem_id_ &&
187 is_valid_ == that.is_valid_;
190 bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs,
191 const FileSystemURL& rhs) const {
192 DCHECK(lhs.is_valid_ && rhs.is_valid_);
193 if (lhs.origin_ != rhs.origin_)
194 return lhs.origin_ < rhs.origin_;
195 if (lhs.type_ != rhs.type_)
196 return lhs.type_ < rhs.type_;
197 if (lhs.filesystem_id_ != rhs.filesystem_id_)
198 return lhs.filesystem_id_ < rhs.filesystem_id_;
199 return lhs.path_ < rhs.path_;
202 } // namespace fileapi