Fix Win8 metro startup crash from window switcher button
[chromium-blink-merge.git] / webkit / fileapi / file_system_util.cc
bloba839aa065aa4dbc868594e00e3616c31b3d68f8f
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/fileapi/file_system_util.h"
7 #include "build/build_config.h"
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/string_util.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "base/utf_string_conversions.h"
14 #include "googleurl/src/gurl.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h"
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
18 #include "webkit/base/origin_url_conversions.h"
19 #include "webkit/fileapi/file_system_url.h"
21 namespace fileapi {
23 const char kPersistentDir[] = "/persistent";
24 const char kTemporaryDir[] = "/temporary";
25 const char kIsolatedDir[] = "/isolated";
26 const char kExternalDir[] = "/external";
27 const char kTestDir[] = "/test";
29 const base::FilePath::CharType VirtualPath::kRoot[] = FILE_PATH_LITERAL("/");
30 const base::FilePath::CharType VirtualPath::kSeparator = FILE_PATH_LITERAL('/');
32 // TODO(ericu): Consider removing support for '\', even on Windows, if possible.
33 // There's a lot of test code that will need reworking, and we may have trouble
34 // with base::FilePath elsewhere [e.g. DirName and other methods may also need
35 // replacement].
36 base::FilePath VirtualPath::BaseName(const base::FilePath& virtual_path) {
37 base::FilePath::StringType path = virtual_path.value();
39 // Keep everything after the final separator, but if the pathname is only
40 // one character and it's a separator, leave it alone.
41 while (path.size() > 1 && base::FilePath::IsSeparator(path[path.size() - 1]))
42 path.resize(path.size() - 1);
43 base::FilePath::StringType::size_type last_separator =
44 path.find_last_of(base::FilePath::kSeparators);
45 if (last_separator != base::FilePath::StringType::npos &&
46 last_separator < path.size() - 1)
47 path.erase(0, last_separator + 1);
49 return base::FilePath(path);
52 base::FilePath VirtualPath::DirName(const base::FilePath& virtual_path) {
53 typedef base::FilePath::StringType StringType;
54 StringType path = virtual_path.value();
56 // The logic below is taken from that of base::FilePath::DirName, except
57 // that this version never cares about '//' or drive-letters even on win32.
59 // Strip trailing separators.
60 while (path.size() > 1 && base::FilePath::IsSeparator(path[path.size() - 1]))
61 path.resize(path.size() - 1);
63 StringType::size_type last_separator =
64 path.find_last_of(base::FilePath::kSeparators);
65 if (last_separator == StringType::npos) {
66 // path_ is in the current directory.
67 return base::FilePath(base::FilePath::kCurrentDirectory);
69 if (last_separator == 0) {
70 // path_ is in the root directory.
71 return base::FilePath(path.substr(0, 1));
73 // path_ is somewhere else, trim the basename.
74 path.resize(last_separator);
76 // Strip trailing separators.
77 while (path.size() > 1 && base::FilePath::IsSeparator(path[path.size() - 1]))
78 path.resize(path.size() - 1);
80 if (path.empty())
81 return base::FilePath(base::FilePath::kCurrentDirectory);
83 return base::FilePath(path);
86 void VirtualPath::GetComponents(
87 const base::FilePath& path,
88 std::vector<base::FilePath::StringType>* components) {
89 typedef base::FilePath::StringType StringType;
91 DCHECK(components);
92 if (!components)
93 return;
94 components->clear();
95 if (path.value().empty())
96 return;
98 StringType::size_type begin = 0, end = 0;
99 while (begin < path.value().length() && end != StringType::npos) {
100 end = path.value().find_first_of(base::FilePath::kSeparators, begin);
101 StringType component = path.value().substr(
102 begin, end == StringType::npos ? StringType::npos : end - begin);
103 if (!component.empty() && component != base::FilePath::kCurrentDirectory)
104 components->push_back(component);
105 begin = end + 1;
109 base::FilePath::StringType VirtualPath::GetNormalizedFilePath(
110 const base::FilePath& path) {
111 base::FilePath::StringType normalized_path = path.value();
112 const size_t num_separators = base::FilePath::StringType(
113 base::FilePath::kSeparators).length();
114 for (size_t i = 0; i < num_separators; ++i) {
115 std::replace(normalized_path.begin(), normalized_path.end(),
116 base::FilePath::kSeparators[i], kSeparator);
119 return (IsAbsolute(normalized_path)) ?
120 normalized_path : base::FilePath::StringType(kRoot) + normalized_path;
123 bool VirtualPath::IsAbsolute(const base::FilePath::StringType& path) {
124 return path.find(kRoot) == 0;
127 GURL GetFileSystemRootURI(const GURL& origin_url, FileSystemType type) {
128 // origin_url is based on a security origin, so http://foo.com or file:///
129 // instead of the corresponding filesystem URL.
130 DCHECK(!origin_url.SchemeIsFileSystem());
132 std::string url = "filesystem:" + origin_url.GetWithEmptyPath().spec();
133 switch (type) {
134 case kFileSystemTypeTemporary:
135 url += (kTemporaryDir + 1); // We don't want the leading slash.
136 return GURL(url + "/");
137 case kFileSystemTypePersistent:
138 url += (kPersistentDir + 1); // We don't want the leading slash.
139 return GURL(url + "/");
140 case kFileSystemTypeExternal:
141 url += (kExternalDir + 1); // We don't want the leading slash.
142 return GURL(url + "/");
143 case kFileSystemTypeIsolated:
144 url += (kIsolatedDir + 1); // We don't want the leading slash.
145 return GURL(url + "/");
146 case kFileSystemTypeTest:
147 url += (kTestDir + 1); // We don't want the leading slash.
148 return GURL(url + "/");
149 // Internal types are always pointed via isolated or external URLs.
150 default:
151 NOTREACHED();
153 NOTREACHED();
154 return GURL();
157 std::string GetFileSystemName(const GURL& origin_url, FileSystemType type) {
158 base::string16 origin_identifier =
159 webkit_base::GetOriginIdentifierFromURL(origin_url);
160 std::string type_string = GetFileSystemTypeString(type);
161 DCHECK(!type_string.empty());
162 return UTF16ToUTF8(origin_identifier) + ":" + type_string;
165 FileSystemType QuotaStorageTypeToFileSystemType(
166 quota::StorageType storage_type) {
167 switch (storage_type) {
168 case quota::kStorageTypeTemporary:
169 return kFileSystemTypeTemporary;
170 case quota::kStorageTypePersistent:
171 return kFileSystemTypePersistent;
172 case quota::kStorageTypeSyncable:
173 return kFileSystemTypeSyncable;
174 case quota::kStorageTypeUnknown:
175 return kFileSystemTypeUnknown;
177 return kFileSystemTypeUnknown;
180 quota::StorageType FileSystemTypeToQuotaStorageType(FileSystemType type) {
181 switch (type) {
182 case kFileSystemTypeTemporary:
183 return quota::kStorageTypeTemporary;
184 case kFileSystemTypePersistent:
185 return quota::kStorageTypePersistent;
186 case kFileSystemTypeSyncable:
187 return quota::kStorageTypeSyncable;
188 default:
189 return quota::kStorageTypeUnknown;
193 std::string GetFileSystemTypeString(FileSystemType type) {
194 switch (type) {
195 case kFileSystemTypeTemporary:
196 return "Temporary";
197 case kFileSystemTypePersistent:
198 return "Persistent";
199 case kFileSystemTypeIsolated:
200 return "Isolated";
201 case kFileSystemTypeExternal:
202 return "External";
203 case kFileSystemTypeTest:
204 return "Test";
205 case kFileSystemTypeNativeLocal:
206 return "NativeLocal";
207 case kFileSystemTypeRestrictedNativeLocal:
208 return "RestrictedNativeLocal";
209 case kFileSystemTypeDragged:
210 return "Dragged";
211 case kFileSystemTypeNativeMedia:
212 return "NativeMedia";
213 case kFileSystemTypeDeviceMedia:
214 return "DeviceMedia";
215 case kFileSystemTypePicasa:
216 return "Picasa";
217 case kFileSystemTypeItunes:
218 return "Itunes";
219 case kFileSystemTypeDrive:
220 return "Drive";
221 case kFileSystemTypeSyncable:
222 return "Syncable";
223 case kFileSystemTypeNativeForPlatformApp:
224 return "NativeForPlatformApp";
225 case kFileSystemTypeForTransientFile:
226 return "TransientFile";
227 case kFileSystemInternalTypeEnumStart:
228 case kFileSystemInternalTypeEnumEnd:
229 NOTREACHED();
230 // Fall through.
231 case kFileSystemTypeUnknown:
232 return "Unknown";
234 NOTREACHED();
235 return std::string();
238 std::string FilePathToString(const base::FilePath& file_path) {
239 #if defined(OS_WIN)
240 return UTF16ToUTF8(file_path.value());
241 #elif defined(OS_POSIX)
242 return file_path.value();
243 #endif
246 base::FilePath StringToFilePath(const std::string& file_path_string) {
247 #if defined(OS_WIN)
248 return base::FilePath(UTF8ToUTF16(file_path_string));
249 #elif defined(OS_POSIX)
250 return base::FilePath(file_path_string);
251 #endif
254 WebKit::WebFileError PlatformFileErrorToWebFileError(
255 base::PlatformFileError error_code) {
256 switch (error_code) {
257 case base::PLATFORM_FILE_ERROR_NOT_FOUND:
258 return WebKit::WebFileErrorNotFound;
259 case base::PLATFORM_FILE_ERROR_INVALID_OPERATION:
260 case base::PLATFORM_FILE_ERROR_EXISTS:
261 case base::PLATFORM_FILE_ERROR_NOT_EMPTY:
262 return WebKit::WebFileErrorInvalidModification;
263 case base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
264 case base::PLATFORM_FILE_ERROR_NOT_A_FILE:
265 return WebKit::WebFileErrorTypeMismatch;
266 case base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
267 return WebKit::WebFileErrorNoModificationAllowed;
268 case base::PLATFORM_FILE_ERROR_FAILED:
269 return WebKit::WebFileErrorInvalidState;
270 case base::PLATFORM_FILE_ERROR_ABORT:
271 return WebKit::WebFileErrorAbort;
272 case base::PLATFORM_FILE_ERROR_SECURITY:
273 return WebKit::WebFileErrorSecurity;
274 case base::PLATFORM_FILE_ERROR_NO_SPACE:
275 return WebKit::WebFileErrorQuotaExceeded;
276 default:
277 return WebKit::WebFileErrorInvalidModification;
281 bool GetFileSystemPublicType(
282 const std::string type_string,
283 WebKit::WebFileSystemType* type
285 DCHECK(type);
286 if (type_string == "Temporary") {
287 *type = WebKit::WebFileSystemTypeTemporary;
288 return true;
290 if (type_string == "Persistent") {
291 *type = WebKit::WebFileSystemTypePersistent;
292 return true;
294 if (type_string == "Isolated") {
295 *type = WebKit::WebFileSystemTypeIsolated;
296 return true;
298 if (type_string == "External") {
299 *type = WebKit::WebFileSystemTypeExternal;
300 return true;
302 NOTREACHED();
303 return false;
306 std::string GetIsolatedFileSystemName(const GURL& origin_url,
307 const std::string& filesystem_id) {
308 std::string name(fileapi::GetFileSystemName(origin_url,
309 fileapi::kFileSystemTypeIsolated));
310 name.append("_");
311 name.append(filesystem_id);
312 return name;
315 bool CrackIsolatedFileSystemName(const std::string& filesystem_name,
316 std::string* filesystem_id) {
317 DCHECK(filesystem_id);
319 // |filesystem_name| is of the form {origin}:isolated_{filesystem_id}.
320 std::string start_token(":");
321 start_token = start_token.append(
322 GetFileSystemTypeString(kFileSystemTypeIsolated)).append("_");
323 // WebKit uses different case in its constant for isolated file system
324 // names, so we do a case insensitive compare by converting both strings
325 // to uppercase.
326 // TODO(benwells): Remove this when WebKit uses the same constant.
327 start_token = StringToUpperASCII(start_token);
328 std::string filesystem_name_upper = StringToUpperASCII(filesystem_name);
329 size_t pos = filesystem_name_upper.find(start_token);
330 if (pos == std::string::npos)
331 return false;
332 if (pos == 0)
333 return false;
335 *filesystem_id = filesystem_name.substr(pos + start_token.length(),
336 std::string::npos);
337 if (filesystem_id->empty())
338 return false;
340 return true;
343 std::string GetIsolatedFileSystemRootURIString(
344 const GURL& origin_url,
345 const std::string& filesystem_id,
346 const std::string& optional_root_name) {
347 std::string root = GetFileSystemRootURI(origin_url,
348 kFileSystemTypeIsolated).spec();
349 if (base::FilePath::FromUTF8Unsafe(filesystem_id).ReferencesParent())
350 return std::string();
351 root.append(filesystem_id);
352 root.append("/");
353 if (!optional_root_name.empty()) {
354 if (base::FilePath::FromUTF8Unsafe(optional_root_name).ReferencesParent())
355 return std::string();
356 root.append(optional_root_name);
357 root.append("/");
359 return root;
362 bool AreSameFileSystem(const FileSystemURL& url1, const FileSystemURL& url2) {
363 return url1.origin() == url2.origin() && url1.type() == url2.type();
366 } // namespace fileapi