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 "storage/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 "storage/common/fileapi/file_system_types.h"
13#include "storage/common/fileapi/file_system_util.h"
14
15namespace storage {
16
17namespace {
18
19}  // namespace
20
21FileSystemURL::FileSystemURL()
22    : is_valid_(false),
23      mount_type_(kFileSystemTypeUnknown),
24      type_(kFileSystemTypeUnknown),
25      mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
26}
27
28// static
29FileSystemURL FileSystemURL::CreateForTest(const GURL& url) {
30  return FileSystemURL(url);
31}
32
33FileSystemURL 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
39FileSystemURL FileSystemURL::CreateForTest(
40    const GURL& origin,
41    FileSystemType mount_type,
42    const base::FilePath& virtual_path,
43    const std::string& mount_filesystem_id,
44    FileSystemType cracked_type,
45    const base::FilePath& cracked_path,
46    const std::string& filesystem_id,
47    const FileSystemMountOption& mount_option) {
48  return FileSystemURL(origin,
49                       mount_type,
50                       virtual_path,
51                       mount_filesystem_id,
52                       cracked_type,
53                       cracked_path,
54                       filesystem_id,
55                       mount_option);
56}
57
58FileSystemURL::FileSystemURL(const GURL& url)
59    : mount_type_(kFileSystemTypeUnknown),
60      type_(kFileSystemTypeUnknown),
61      mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
62  is_valid_ = ParseFileSystemSchemeURL(url, &origin_, &mount_type_,
63                                       &virtual_path_);
64  path_ = virtual_path_;
65  type_ = mount_type_;
66}
67
68FileSystemURL::FileSystemURL(const GURL& origin,
69                             FileSystemType mount_type,
70                             const base::FilePath& virtual_path)
71    : is_valid_(true),
72      origin_(origin),
73      mount_type_(mount_type),
74      virtual_path_(virtual_path.NormalizePathSeparators()),
75      type_(mount_type),
76      path_(virtual_path.NormalizePathSeparators()),
77      mount_option_(COPY_SYNC_OPTION_NO_SYNC) {
78}
79
80FileSystemURL::FileSystemURL(const GURL& origin,
81                             FileSystemType mount_type,
82                             const base::FilePath& virtual_path,
83                             const std::string& mount_filesystem_id,
84                             FileSystemType cracked_type,
85                             const base::FilePath& cracked_path,
86                             const std::string& filesystem_id,
87                             const FileSystemMountOption& mount_option)
88    : is_valid_(true),
89      origin_(origin),
90      mount_type_(mount_type),
91      virtual_path_(virtual_path.NormalizePathSeparators()),
92      mount_filesystem_id_(mount_filesystem_id),
93      type_(cracked_type),
94      path_(cracked_path.NormalizePathSeparators()),
95      filesystem_id_(filesystem_id),
96      mount_option_(mount_option) {
97}
98
99FileSystemURL::~FileSystemURL() {}
100
101GURL FileSystemURL::ToGURL() const {
102  if (!is_valid_)
103    return GURL();
104
105  std::string url = GetFileSystemRootURI(origin_, mount_type_).spec();
106  if (url.empty())
107    return GURL();
108
109  // Exactly match with DOMFileSystemBase::createFileSystemURL()'s encoding
110  // behavior, where the path is escaped by KURL::encodeWithURLEscapeSequences
111  // which is essentially encodeURIComponent except '/'.
112  std::string escaped = net::EscapeQueryParamValue(
113      virtual_path_.NormalizePathSeparatorsTo('/').AsUTF8Unsafe(),
114      false /* use_plus */);
115  ReplaceSubstringsAfterOffset(&escaped, 0, "%2F", "/");
116  url.append(escaped);
117
118  // Build nested GURL.
119  return GURL(url);
120}
121
122std::string FileSystemURL::DebugString() const {
123  if (!is_valid_)
124    return "invalid filesystem: URL";
125  std::ostringstream ss;
126  ss << GetFileSystemRootURI(origin_, mount_type_);
127
128  // filesystem_id_ will be non empty for (and only for) cracked URLs.
129  if (!filesystem_id_.empty()) {
130    ss << virtual_path_.value();
131    ss << " (";
132    ss << GetFileSystemTypeString(type_) << "@" << filesystem_id_ << ":";
133    ss << path_.value();
134    ss << ")";
135  } else {
136    ss << path_.value();
137  }
138  return ss.str();
139}
140
141bool FileSystemURL::IsParent(const FileSystemURL& child) const {
142  return IsInSameFileSystem(child) &&
143         path().IsParent(child.path());
144}
145
146bool FileSystemURL::IsInSameFileSystem(const FileSystemURL& other) const {
147  return origin() == other.origin() &&
148         type() == other.type() &&
149         filesystem_id() == other.filesystem_id();
150}
151
152bool FileSystemURL::operator==(const FileSystemURL& that) const {
153  return origin_ == that.origin_ &&
154      type_ == that.type_ &&
155      path_ == that.path_ &&
156      filesystem_id_ == that.filesystem_id_ &&
157      is_valid_ == that.is_valid_;
158}
159
160bool FileSystemURL::Comparator::operator()(const FileSystemURL& lhs,
161                                           const FileSystemURL& rhs) const {
162  DCHECK(lhs.is_valid_ && rhs.is_valid_);
163  if (lhs.origin_ != rhs.origin_)
164    return lhs.origin_ < rhs.origin_;
165  if (lhs.type_ != rhs.type_)
166    return lhs.type_ < rhs.type_;
167  if (lhs.filesystem_id_ != rhs.filesystem_id_)
168    return lhs.filesystem_id_ < rhs.filesystem_id_;
169  return lhs.path_ < rhs.path_;
170}
171
172}  // namespace storage
173