Home | History | Annotate | Download | only in fileapi
      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 
     21 FileSystemURL::FileSystemURL()
     22     : is_valid_(false),
     23       mount_type_(kFileSystemTypeUnknown),
     24       type_(kFileSystemTypeUnknown) {
     25 }
     26 
     27 // static
     28 FileSystemURL FileSystemURL::CreateForTest(const GURL& url) {
     29   return FileSystemURL(url);
     30 }
     31 
     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);
     36 }
     37 
     38 // static
     39 bool FileSystemURL::ParseFileSystemSchemeURL(
     40     const GURL& url,
     41     GURL* origin_url,
     42     FileSystemType* mount_type,
     43     base::FilePath* virtual_path) {
     44   GURL origin;
     45   FileSystemType file_system_type = kFileSystemTypeUnknown;
     46 
     47   if (!url.is_valid() || !url.SchemeIsFileSystem())
     48     return false;
     49   DCHECK(url.inner_url());
     50 
     51   std::string inner_path = url.inner_url()->path();
     52 
     53   const struct {
     54     FileSystemType type;
     55     const char* dir;
     56   } kValidTypes[] = {
     57     { kFileSystemTypePersistent, kPersistentDir },
     58     { kFileSystemTypeTemporary, kTemporaryDir },
     59     { kFileSystemTypeIsolated, kIsolatedDir },
     60     { kFileSystemTypeExternal, kExternalDir },
     61     { kFileSystemTypeTest, kTestDir },
     62   };
     63 
     64   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kValidTypes); ++i) {
     65     if (StartsWithASCII(inner_path, kValidTypes[i].dir, true)) {
     66       file_system_type = kValidTypes[i].type;
     67       break;
     68     }
     69   }
     70 
     71   if (file_system_type == kFileSystemTypeUnknown)
     72     return false;
     73 
     74   std::string path = net::UnescapeURLComponent(url.path(),
     75       net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS |
     76       net::UnescapeRule::CONTROL_CHARS);
     77 
     78   // Ensure the path is relative.
     79   while (!path.empty() && path[0] == '/')
     80     path.erase(0, 1);
     81 
     82   base::FilePath converted_path = base::FilePath::FromUTF8Unsafe(path);
     83 
     84   // All parent references should have been resolved in the renderer.
     85   if (converted_path.ReferencesParent())
     86     return false;
     87 
     88   if (origin_url)
     89     *origin_url = url.GetOrigin();
     90   if (mount_type)
     91     *mount_type = file_system_type;
     92   if (virtual_path)
     93     *virtual_path = converted_path.NormalizePathSeparators().
     94         StripTrailingSeparators();
     95 
     96   return true;
     97 }
     98 
     99 FileSystemURL::FileSystemURL(const GURL& url)
    100     : mount_type_(kFileSystemTypeUnknown),
    101       type_(kFileSystemTypeUnknown) {
    102   is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_,
    103                                        &virtual_path_);
    104   path_ = virtual_path_;
    105   type_ = mount_type_;
    106 }
    107 
    108 FileSystemURL::FileSystemURL(const GURL& origin,
    109                              FileSystemType mount_type,
    110                              const base::FilePath& virtual_path)
    111     : is_valid_(true),
    112       origin_(origin),
    113       mount_type_(mount_type),
    114       virtual_path_(virtual_path.NormalizePathSeparators()),
    115       type_(mount_type),
    116       path_(virtual_path.NormalizePathSeparators()) {
    117 }
    118 
    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)
    126     : is_valid_(true),
    127       origin_(origin),
    128       mount_type_(mount_type),
    129       virtual_path_(virtual_path.NormalizePathSeparators()),
    130       mount_filesystem_id_(mount_filesystem_id),
    131       type_(cracked_type),
    132       path_(cracked_path.NormalizePathSeparators()),
    133       filesystem_id_(filesystem_id) {
    134 }
    135 
    136 FileSystemURL::~FileSystemURL() {}
    137 
    138 std::string FileSystemURL::DebugString() const {
    139   if (!is_valid_)
    140     return "invalid filesystem: URL";
    141   std::ostringstream ss;
    142   ss << GetFileSystemRootURI(origin_, mount_type_);
    143 
    144   // filesystem_id_ will be non empty for (and only for) cracked URLs.
    145   if (!filesystem_id_.empty()) {
    146     ss << virtual_path_.value();
    147     ss << " (";
    148     ss << GetFileSystemTypeString(type_) << "@" << filesystem_id_ << ":";
    149     ss << path_.value();
    150     ss << ")";
    151   } else {
    152     ss << path_.value();
    153   }
    154   return ss.str();
    155 }
    156 
    157 bool FileSystemURL::IsParent(const FileSystemURL& child) const {
    158   return IsInSameFileSystem(child) &&
    159          path().IsParent(child.path());
    160 }
    161 
    162 bool FileSystemURL::IsInSameFileSystem(const FileSystemURL& other) const {
    163   return origin() == other.origin() &&
    164          type() == other.type() &&
    165          filesystem_id() == other.filesystem_id();
    166 }
    167 
    168 bool FileSystemURL::operator==(const FileSystemURL& that) const {
    169   return origin_ == that.origin_ &&
    170       type_ == that.type_ &&
    171       path_ == that.path_ &&
    172       filesystem_id_ == that.filesystem_id_ &&
    173       is_valid_ == that.is_valid_;
    174 }
    175 
    176 bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs,
    177                                            const FileSystemURL& rhs) const {
    178   DCHECK(lhs.is_valid_ && rhs.is_valid_);
    179   if (lhs.origin_ != rhs.origin_)
    180     return lhs.origin_ < rhs.origin_;
    181   if (lhs.type_ != rhs.type_)
    182     return lhs.type_ < rhs.type_;
    183   if (lhs.filesystem_id_ != rhs.filesystem_id_)
    184     return lhs.filesystem_id_ < rhs.filesystem_id_;
    185   return lhs.path_ < rhs.path_;
    186 }
    187 
    188 }  // namespace fileapi
    189