• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "webkit/browser/fileapi/file_system_url.h"
6 
7 #include <sstream>
8 
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"
14 
15 namespace fileapi {
16 
17 namespace {
18 
19 }  // namespace
20 
FileSystemURL()21 FileSystemURL::FileSystemURL()
22     : is_valid_(false),
23       mount_type_(kFileSystemTypeUnknown),
24       type_(kFileSystemTypeUnknown),
25       mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
26 }
27 
28 // static
CreateForTest(const GURL & url)29 FileSystemURL FileSystemURL::CreateForTest(const GURL& url) {
30   return FileSystemURL(url);
31 }
32 
CreateForTest(const GURL & origin,FileSystemType mount_type,const base::FilePath & virtual_path)33 FileSystemURL FileSystemURL::CreateForTest(const GURL& origin,
34                                            FileSystemType mount_type,
35                                            const base::FilePath& virtual_path) {
36   return FileSystemURL(origin, mount_type, virtual_path);
37 }
38 
39 // static
ParseFileSystemSchemeURL(const GURL & url,GURL * origin_url,FileSystemType * mount_type,base::FilePath * virtual_path)40 bool FileSystemURL::ParseFileSystemSchemeURL(
41     const GURL& url,
42     GURL* origin_url,
43     FileSystemType* mount_type,
44     base::FilePath* virtual_path) {
45   GURL origin;
46   FileSystemType file_system_type = kFileSystemTypeUnknown;
47 
48   if (!url.is_valid() || !url.SchemeIsFileSystem())
49     return false;
50 
51   const struct {
52     FileSystemType type;
53     const char* dir;
54   } kValidTypes[] = {
55     { kFileSystemTypePersistent, kPersistentDir },
56     { kFileSystemTypeTemporary, kTemporaryDir },
57     { kFileSystemTypeIsolated, kIsolatedDir },
58     { kFileSystemTypeExternal, kExternalDir },
59     { kFileSystemTypeTest, kTestDir },
60   };
61 
62   // A path of the inner_url contains only mount type part (e.g. "/temporary").
63   DCHECK(url.inner_url());
64   std::string inner_path = url.inner_url()->path();
65   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidTypes); ++i) {
66     if (inner_path == kValidTypes[i].dir) {
67       file_system_type = kValidTypes[i].type;
68       break;
69     }
70   }
71 
72   if (file_system_type == kFileSystemTypeUnknown)
73     return false;
74 
75   std::string path = net::UnescapeURLComponent(url.path(),
76       net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS |
77       net::UnescapeRule::CONTROL_CHARS);
78 
79   // Ensure the path is relative.
80   while (!path.empty() && path[0] == '/')
81     path.erase(0, 1);
82 
83   base::FilePath converted_path = base::FilePath::FromUTF8Unsafe(path);
84 
85   // All parent references should have been resolved in the renderer.
86   if (converted_path.ReferencesParent())
87     return false;
88 
89   if (origin_url)
90     *origin_url = url.GetOrigin();
91   if (mount_type)
92     *mount_type = file_system_type;
93   if (virtual_path)
94     *virtual_path = converted_path.NormalizePathSeparators().
95         StripTrailingSeparators();
96 
97   return true;
98 }
99 
FileSystemURL(const GURL & url)100 FileSystemURL::FileSystemURL(const GURL& url)
101     : mount_type_(kFileSystemTypeUnknown),
102       type_(kFileSystemTypeUnknown),
103       mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
104   is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_,
105                                        &virtual_path_);
106   path_ = virtual_path_;
107   type_ = mount_type_;
108 }
109 
FileSystemURL(const GURL & origin,FileSystemType mount_type,const base::FilePath & virtual_path)110 FileSystemURL::FileSystemURL(const GURL& origin,
111                              FileSystemType mount_type,
112                              const base::FilePath& virtual_path)
113     : is_valid_(true),
114       origin_(origin),
115       mount_type_(mount_type),
116       virtual_path_(virtual_path.NormalizePathSeparators()),
117       type_(mount_type),
118       path_(virtual_path.NormalizePathSeparators()),
119       mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
120 }
121 
FileSystemURL(const GURL & origin,FileSystemType mount_type,const base::FilePath & virtual_path,const std::string & mount_filesystem_id,FileSystemType cracked_type,const base::FilePath & cracked_path,const std::string & filesystem_id,const FileSystemMountOption & mount_option)122 FileSystemURL::FileSystemURL(const GURL& origin,
123                              FileSystemType mount_type,
124                              const base::FilePath& virtual_path,
125                              const std::string& mount_filesystem_id,
126                              FileSystemType cracked_type,
127                              const base::FilePath& cracked_path,
128                              const std::string& filesystem_id,
129                              const FileSystemMountOption& mount_option)
130     : is_valid_(true),
131       origin_(origin),
132       mount_type_(mount_type),
133       virtual_path_(virtual_path.NormalizePathSeparators()),
134       mount_filesystem_id_(mount_filesystem_id),
135       type_(cracked_type),
136       path_(cracked_path.NormalizePathSeparators()),
137       filesystem_id_(filesystem_id),
138       mount_option_(mount_option) {
139 }
140 
~FileSystemURL()141 FileSystemURL::~FileSystemURL() {}
142 
ToGURL() const143 GURL FileSystemURL::ToGURL() const {
144   if (!is_valid_)
145     return GURL();
146 
147   std::string url = GetFileSystemRootURI(origin_, mount_type_).spec();
148   if (url.empty())
149     return GURL();
150 
151   url.append(virtual_path_.AsUTF8Unsafe());
152 
153   // Build nested GURL.
154   return GURL(url);
155 }
156 
DebugString() const157 std::string FileSystemURL::DebugString() const {
158   if (!is_valid_)
159     return "invalid filesystem: URL";
160   std::ostringstream ss;
161   ss << GetFileSystemRootURI(origin_, mount_type_);
162 
163   // filesystem_id_ will be non empty for (and only for) cracked URLs.
164   if (!filesystem_id_.empty()) {
165     ss << virtual_path_.value();
166     ss << " (";
167     ss << GetFileSystemTypeString(type_) << "@" << filesystem_id_ << ":";
168     ss << path_.value();
169     ss << ")";
170   } else {
171     ss << path_.value();
172   }
173   return ss.str();
174 }
175 
IsParent(const FileSystemURL & child) const176 bool FileSystemURL::IsParent(const FileSystemURL& child) const {
177   return IsInSameFileSystem(child) &&
178          path().IsParent(child.path());
179 }
180 
IsInSameFileSystem(const FileSystemURL & other) const181 bool FileSystemURL::IsInSameFileSystem(const FileSystemURL& other) const {
182   return origin() == other.origin() &&
183          type() == other.type() &&
184          filesystem_id() == other.filesystem_id();
185 }
186 
operator ==(const FileSystemURL & that) const187 bool FileSystemURL::operator==(const FileSystemURL& that) const {
188   return origin_ == that.origin_ &&
189       type_ == that.type_ &&
190       path_ == that.path_ &&
191       filesystem_id_ == that.filesystem_id_ &&
192       is_valid_ == that.is_valid_;
193 }
194 
operator ()(const FileSystemURL & lhs,const FileSystemURL & rhs) const195 bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs,
196                                            const FileSystemURL& rhs) const {
197   DCHECK(lhs.is_valid_ && rhs.is_valid_);
198   if (lhs.origin_ != rhs.origin_)
199     return lhs.origin_ < rhs.origin_;
200   if (lhs.type_ != rhs.type_)
201     return lhs.type_ < rhs.type_;
202   if (lhs.filesystem_id_ != rhs.filesystem_id_)
203     return lhs.filesystem_id_ < rhs.filesystem_id_;
204   return lhs.path_ < rhs.path_;
205 }
206 
207 }  // namespace fileapi
208