Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/fileapi/file_system_path_manager.h" | 5 #include "webkit/fileapi/file_system_path_manager.h" |
| 6 | 6 |
| 7 #include "base/rand_util.h" | 7 #include "base/rand_util.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| 11 #include "base/scoped_callback_factory.h" | 11 #include "base/scoped_callback_factory.h" |
| 12 #include "base/scoped_ptr.h" | 12 #include "base/scoped_ptr.h" |
| 13 #include "base/stringprintf.h" | 13 #include "base/stringprintf.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
| 16 #include "googleurl/src/gurl.h" | 16 #include "googleurl/src/gurl.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
|
kinuko
2011/03/14 11:03:57
line 17,19 not needed
ericu
2011/03/15 02:43:11
Done.
| |
| 20 #include "webkit/fileapi/file_system_util.h" | |
| 21 #include "webkit/fileapi/sandbox_mount_point_provider.h" | |
| 20 #include "webkit/glue/webkit_glue.h" | 22 #include "webkit/glue/webkit_glue.h" |
| 21 | 23 |
| 22 // We use some of WebKit types for conversions between origin identifiers | 24 // We use some of WebKit types for conversions between origin identifiers |
| 23 // and origin URLs. | 25 // and origin URLs. |
| 24 using WebKit::WebFileSystem; | 26 using WebKit::WebFileSystem; |
| 25 using WebKit::WebSecurityOrigin; | 27 using WebKit::WebSecurityOrigin; |
| 26 using WebKit::WebString; | 28 using WebKit::WebString; |
|
kinuko
2011/03/14 11:03:57
line 27,28 not needed
ericu
2011/03/15 02:43:11
Done.
| |
| 27 | 29 |
| 28 using base::PlatformFileError; | 30 using base::PlatformFileError; |
| 29 | 31 |
| 30 namespace fileapi { | |
| 31 | |
| 32 const FilePath::CharType FileSystemPathManager::kFileSystemDirectory[] = | |
| 33 FILE_PATH_LITERAL("FileSystem"); | |
| 34 | |
| 35 const char FileSystemPathManager::kPersistentName[] = "Persistent"; | |
| 36 const char FileSystemPathManager::kTemporaryName[] = "Temporary"; | |
| 37 | |
| 38 static const FilePath::CharType kFileSystemUniqueNamePrefix[] = | |
| 39 FILE_PATH_LITERAL("chrome-"); | |
| 40 static const int kFileSystemUniqueLength = 16; | |
| 41 static const unsigned kFileSystemUniqueDirectoryNameLength = | |
| 42 kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1; | |
| 43 | |
| 44 namespace { | |
| 45 | |
| 46 // Restricted names. | |
| 47 // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions | |
| 48 static const char* const kRestrictedNames[] = { | |
| 49 "con", "prn", "aux", "nul", | |
| 50 "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9", | |
| 51 "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", | |
| 52 }; | |
| 53 | |
| 54 // Restricted chars. | |
| 55 static const FilePath::CharType kRestrictedChars[] = { | |
| 56 '/', '\\', '<', '>', ':', '?', '*', '"', '|', | |
| 57 }; | |
| 58 | |
| 59 inline std::string FilePathStringToASCII( | |
| 60 const FilePath::StringType& path_string) { | |
| 61 #if defined(OS_WIN) | |
| 62 return WideToASCII(path_string); | |
| 63 #elif defined(OS_POSIX) | |
| 64 return path_string; | |
| 65 #endif | |
| 66 } | |
| 67 | |
| 68 FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) { | |
| 69 // This can be anything but need to be unpredictable. | |
| 70 static const FilePath::CharType letters[] = FILE_PATH_LITERAL( | |
| 71 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); | |
| 72 FilePath::StringType unique(kFileSystemUniqueNamePrefix); | |
| 73 for (int i = 0; i < kFileSystemUniqueLength; ++i) | |
| 74 unique += letters[base::RandInt(0, arraysize(letters) - 2)]; | |
| 75 return unique; | |
| 76 } | |
| 77 | |
| 78 static const char kExtensionScheme[] = "chrome-extension"; | 32 static const char kExtensionScheme[] = "chrome-extension"; |
| 79 | 33 |
| 80 } // anonymous namespace | 34 namespace fileapi { |
| 81 | |
| 82 class FileSystemPathManager::GetFileSystemRootPathTask | |
| 83 : public base::RefCountedThreadSafe< | |
| 84 FileSystemPathManager::GetFileSystemRootPathTask> { | |
| 85 public: | |
| 86 GetFileSystemRootPathTask( | |
| 87 scoped_refptr<base::MessageLoopProxy> file_message_loop, | |
| 88 const std::string& name, | |
| 89 FileSystemPathManager::GetRootPathCallback* callback) | |
| 90 : file_message_loop_(file_message_loop), | |
| 91 origin_message_loop_proxy_( | |
| 92 base::MessageLoopProxy::CreateForCurrentThread()), | |
| 93 name_(name), | |
| 94 callback_(callback) { | |
| 95 } | |
| 96 | |
| 97 void Start(const GURL& origin_url, | |
| 98 const FilePath& origin_base_path, | |
| 99 bool create) { | |
| 100 file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | |
| 101 &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread, | |
| 102 origin_url, origin_base_path, create)); | |
| 103 } | |
| 104 | |
| 105 private: | |
| 106 void GetFileSystemRootPathOnFileThread( | |
| 107 const GURL& origin_url, | |
| 108 const FilePath& base_path, | |
| 109 bool create) { | |
| 110 FilePath root; | |
| 111 if (ReadOriginDirectory(base_path, origin_url, &root)) { | |
| 112 DispatchCallbackOnCallerThread(root); | |
| 113 return; | |
| 114 } | |
| 115 | |
| 116 if (!create) { | |
| 117 DispatchCallbackOnCallerThread(FilePath()); | |
| 118 return; | |
| 119 } | |
| 120 | |
| 121 // Creates the root directory. | |
| 122 root = base_path.Append(CreateUniqueDirectoryName(origin_url)); | |
| 123 if (!file_util::CreateDirectory(root)) { | |
| 124 DispatchCallbackOnCallerThread(FilePath()); | |
| 125 return; | |
| 126 } | |
| 127 DispatchCallbackOnCallerThread(root); | |
| 128 } | |
| 129 | |
| 130 bool ReadOriginDirectory(const FilePath& base_path, | |
| 131 const GURL& origin_url, | |
| 132 FilePath* unique) { | |
| 133 file_util::FileEnumerator file_enum( | |
| 134 base_path, false /* recursive */, | |
| 135 file_util::FileEnumerator::DIRECTORIES, | |
| 136 FilePath::StringType(kFileSystemUniqueNamePrefix) + | |
| 137 FILE_PATH_LITERAL("*")); | |
| 138 FilePath current; | |
| 139 bool found = false; | |
| 140 while (!(current = file_enum.Next()).empty()) { | |
| 141 if (current.BaseName().value().length() != | |
| 142 kFileSystemUniqueDirectoryNameLength) | |
| 143 continue; | |
| 144 if (found) { | |
| 145 // TODO(kinuko): Should notify the user to ask for some action. | |
| 146 LOG(WARNING) << "Unexpectedly found more than one FileSystem " | |
| 147 << "directories for " << origin_url; | |
| 148 return false; | |
| 149 } | |
| 150 found = true; | |
| 151 *unique = current; | |
| 152 } | |
| 153 return !unique->empty(); | |
| 154 } | |
| 155 | |
| 156 void DispatchCallbackOnCallerThread(const FilePath& root_path) { | |
| 157 origin_message_loop_proxy_->PostTask(FROM_HERE, | |
| 158 NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback, | |
| 159 root_path)); | |
| 160 } | |
| 161 | |
| 162 void DispatchCallback(const FilePath& root_path) { | |
| 163 callback_->Run(!root_path.empty(), root_path, name_); | |
| 164 callback_.reset(); | |
| 165 } | |
| 166 | |
| 167 scoped_refptr<base::MessageLoopProxy> file_message_loop_; | |
| 168 scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_; | |
| 169 std::string name_; | |
| 170 scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_; | |
| 171 }; | |
| 172 | 35 |
| 173 FileSystemPathManager::FileSystemPathManager( | 36 FileSystemPathManager::FileSystemPathManager( |
| 174 scoped_refptr<base::MessageLoopProxy> file_message_loop, | 37 scoped_refptr<base::MessageLoopProxy> file_message_loop, |
| 175 const FilePath& profile_path, | 38 const FilePath& profile_path, |
| 176 bool is_incognito, | 39 bool is_incognito, |
| 177 bool allow_file_access_from_files) | 40 bool allow_file_access_from_files) |
| 178 : file_message_loop_(file_message_loop), | 41 : is_incognito_(is_incognito), |
| 179 base_path_(profile_path.Append(kFileSystemDirectory)), | 42 allow_file_access_from_files_(allow_file_access_from_files), |
| 180 is_incognito_(is_incognito), | 43 sandbox_provider_( |
| 181 allow_file_access_from_files_(allow_file_access_from_files) { | 44 new SandboxMountPointProvider( |
| 45 ALLOW_THIS_IN_INITIALIZER_LIST(this), | |
| 46 file_message_loop, | |
| 47 profile_path)) { | |
| 182 } | 48 } |
| 183 | 49 |
| 184 FileSystemPathManager::~FileSystemPathManager() {} | 50 FileSystemPathManager::~FileSystemPathManager() {} |
| 185 | 51 |
| 186 void FileSystemPathManager::GetFileSystemRootPath( | 52 void FileSystemPathManager::GetFileSystemRootPath( |
| 187 const GURL& origin_url, fileapi::FileSystemType type, | 53 const GURL& origin_url, fileapi::FileSystemType type, |
| 188 bool create, GetRootPathCallback* callback_ptr) { | 54 bool create, GetRootPathCallback* callback_ptr) { |
| 189 scoped_ptr<GetRootPathCallback> callback(callback_ptr); | 55 |
| 190 if (is_incognito_) { | 56 switch (type) { |
| 191 // TODO(kinuko): return an isolated temporary directory. | 57 case kFileSystemTypeTemporary: |
| 192 callback->Run(false, FilePath(), std::string()); | 58 case kFileSystemTypePersistent: |
| 193 return; | 59 sandbox_provider_->GetFileSystemRootPath( |
| 60 origin_url, type, create, callback_ptr); | |
| 61 break; | |
| 62 case kFileSystemTypeUnknown: | |
| 63 default: | |
| 64 NOTREACHED(); | |
| 65 callback_ptr->Run(false, FilePath(), std::string()); | |
| 194 } | 66 } |
| 67 } | |
| 195 | 68 |
| 196 if (!IsAllowedScheme(origin_url)) { | 69 FilePath FileSystemPathManager::GetFileSystemRootPathOnFileThread( |
| 197 callback->Run(false, FilePath(), std::string()); | 70 const GURL& origin_url, FileSystemType type, bool create) { |
| 198 return; | 71 switch (type) { |
| 72 case kFileSystemTypeTemporary: | |
| 73 case kFileSystemTypePersistent: | |
| 74 return sandbox_provider_->GetFileSystemRootPathOnFileThread( | |
| 75 origin_url, type, create); | |
| 76 break; | |
| 77 case kFileSystemTypeUnknown: | |
| 78 default: | |
| 79 NOTREACHED(); | |
| 80 return FilePath(); | |
| 199 } | 81 } |
| 200 | |
| 201 std::string origin_identifier = GetOriginIdentifierFromURL(origin_url); | |
| 202 FilePath origin_base_path = GetFileSystemBaseDirectoryForOriginAndType( | |
| 203 base_path(), origin_identifier, type); | |
| 204 if (origin_base_path.empty()) { | |
| 205 callback->Run(false, FilePath(), std::string()); | |
| 206 return; | |
| 207 } | |
| 208 | |
| 209 std::string type_string = GetFileSystemTypeString(type); | |
| 210 DCHECK(!type_string.empty()); | |
| 211 | |
| 212 scoped_refptr<GetFileSystemRootPathTask> task( | |
| 213 new GetFileSystemRootPathTask(file_message_loop_, | |
| 214 origin_identifier + ":" + type_string, | |
| 215 callback.release())); | |
| 216 task->Start(origin_url, origin_base_path, create); | |
| 217 } | 82 } |
| 218 | 83 |
| 219 bool FileSystemPathManager::CrackFileSystemPath( | 84 bool FileSystemPathManager::CrackFileSystemPath( |
| 220 const FilePath& path, GURL* origin_url, FileSystemType* type, | 85 const FilePath& path, GURL* origin_url, FileSystemType* type, |
| 221 FilePath* virtual_path) const { | 86 FilePath* virtual_path) const { |
| 222 // Any paths that includes parent references are considered invalid. | 87 // TODO(ericu): |
| 223 if (path.ReferencesParent()) | 88 // Paths come in here [for now] as a URL, followed by a virtual path in |
| 89 // platform format. For example, on Windows, this will look like | |
| 90 // filesystem:http://www.example.com/temporary/\path\to\file.txt. | |
| 91 // A potentially dangerous malicious path on Windows might look like: | |
| 92 // filesystem:http://www.example.com/temporary/foo/../../\path\to\file.txt. | |
| 93 // This code is ugly, but will get cleaned up as we fix the calling side. | |
| 94 // We should be passing these to WebKit as string, not FilePath, for ease of | |
| 95 // manipulation, or possibly as GURL/KURL. | |
| 96 | |
| 97 std::string path_as_string; | |
| 98 #ifdef OS_WIN | |
| 99 path_as_string = WideToUTF8(path.value()); | |
| 100 #else | |
| 101 path_as_string = path.value(); | |
| 102 #endif | |
| 103 GURL path_as_url(path_as_string); | |
| 104 | |
| 105 FilePath local_path; | |
| 106 GURL local_url; | |
| 107 FileSystemType local_type; | |
| 108 if (!CrackFileSystemURL(path_as_url, &local_url, &local_type, &local_path)) | |
| 224 return false; | 109 return false; |
| 225 | 110 |
| 226 // The path should be a child of the profile FileSystem path. | 111 #if defined(FILE_PATH_USES_WIN_SEPARATORS) |
| 227 FilePath relative; | 112 // TODO(ericu): This puts the separators back to windows-standard; they come |
| 228 if (!base_path_.AppendRelativePath(path, &relative)) | 113 // out of the above code as '/' no matter the platform. Long-term, we'll |
| 229 return false; | 114 // want to let the underlying FileSystemFileUtil implementation do this part, |
| 115 // since they won't all need it. | |
| 116 local_path = local_path.NormalizeWindowsPathSeparators(); | |
| 117 #endif | |
| 230 | 118 |
| 231 // The relative path from the profile FileSystem path should contain | 119 // Any paths that include parent references are considered invalid. |
| 232 // at least three components, one for storage identifier, one for type | 120 // These should have been taken care of in CrackFileSystemURL. |
| 233 // and one for the 'unique' part. | 121 DCHECK(!local_path.ReferencesParent()); |
|
kinuko
2011/03/14 11:03:57
Can't we get rid of these checks (line 111 to 121)
ericu
2011/03/15 02:43:11
111->117 fixes up separators that are the wrong wa
kinuko
2011/03/16 19:33:38
Ok... can we add some comments about that? (A sho
ericu
2011/03/16 23:47:31
Added a small addendum to the upper comment in thi
| |
| 234 std::vector<FilePath::StringType> components; | |
| 235 relative.GetComponents(&components); | |
| 236 if (components.size() < 3) | |
| 237 return false; | |
| 238 | 122 |
| 239 // The second component of the relative path to the root directory | 123 // The given |local_path| seems valid. Populates the |origin_url|, |type| |
| 240 // must be kPersistent or kTemporary. | |
| 241 if (!IsStringASCII(components[1])) | |
| 242 return false; | |
| 243 | |
| 244 std::string ascii_type_component = FilePathStringToASCII(components[1]); | |
| 245 FileSystemType cracked_type = kFileSystemTypeUnknown; | |
| 246 if (ascii_type_component == kPersistentName) | |
| 247 cracked_type = kFileSystemTypePersistent; | |
| 248 else if (ascii_type_component == kTemporaryName) | |
| 249 cracked_type = kFileSystemTypeTemporary; | |
| 250 else | |
| 251 return false; | |
| 252 | |
| 253 DCHECK(cracked_type != kFileSystemTypeUnknown); | |
| 254 | |
| 255 // The given |path| seems valid. Populates the |origin_url|, |type| | |
| 256 // and |virtual_path| if they are given. | 124 // and |virtual_path| if they are given. |
| 257 | 125 |
| 258 if (origin_url) { | 126 if (origin_url) { |
| 259 WebSecurityOrigin web_security_origin = | 127 *origin_url = local_url; |
| 260 WebSecurityOrigin::createFromDatabaseIdentifier( | |
| 261 webkit_glue::FilePathStringToWebString(components[0])); | |
| 262 *origin_url = GURL(web_security_origin.toString()); | |
| 263 | |
| 264 // We need this work-around for file:/// URIs as | |
| 265 // createFromDatabaseIdentifier returns empty origin_url for them. | |
| 266 if (allow_file_access_from_files_ && origin_url->spec().empty() && | |
| 267 components[0].find(FILE_PATH_LITERAL("file")) == 0) | |
| 268 *origin_url = GURL("file:///"); | |
| 269 } | 128 } |
| 270 | 129 |
| 271 if (type) | 130 if (type) |
| 272 *type = cracked_type; | 131 *type = local_type; |
| 273 | 132 |
| 274 if (virtual_path) { | 133 if (virtual_path) { |
| 275 virtual_path->clear(); | 134 *virtual_path = local_path; |
| 276 for (size_t i = 3; i < components.size(); ++i) | |
| 277 *virtual_path = virtual_path->Append(components[i]); | |
| 278 } | 135 } |
| 279 | 136 |
| 280 return true; | 137 return true; |
| 281 } | 138 } |
| 282 | 139 |
| 283 bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const { | 140 bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const { |
| 284 // Basically we only accept http or https. We allow file:// URLs | 141 // Basically we only accept http or https. We allow file:// URLs |
| 285 // only if --allow-file-access-from-files flag is given. | 142 // only if --allow-file-access-from-files flag is given. |
| 286 return url.SchemeIs("http") || url.SchemeIs("https") || | 143 return url.SchemeIs("http") || url.SchemeIs("https") || |
| 287 url.SchemeIs(kExtensionScheme) || | 144 url.SchemeIs(kExtensionScheme) || |
| 288 (url.SchemeIsFile() && allow_file_access_from_files_); | 145 (url.SchemeIsFile() && allow_file_access_from_files_); |
| 289 } | 146 } |
| 290 | 147 |
| 291 // static | 148 // static |
| 292 bool FileSystemPathManager::IsRestrictedFileName(const FilePath& filename) { | |
| 293 if (filename.value().empty()) | |
| 294 return false; | |
| 295 | |
| 296 if (IsWhitespace(filename.value()[filename.value().size() - 1]) || | |
| 297 filename.value()[filename.value().size() - 1] == '.') | |
| 298 return true; | |
| 299 | |
| 300 std::string filename_lower = StringToLowerASCII( | |
| 301 FilePathStringToASCII(filename.value())); | |
| 302 | |
| 303 for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) { | |
| 304 // Exact match. | |
| 305 if (filename_lower == kRestrictedNames[i]) | |
| 306 return true; | |
| 307 // Starts with "RESTRICTED_NAME.". | |
| 308 if (filename_lower.find(std::string(kRestrictedNames[i]) + ".") == 0) | |
| 309 return true; | |
| 310 } | |
| 311 | |
| 312 for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) { | |
| 313 if (filename.value().find(kRestrictedChars[i]) != | |
| 314 FilePath::StringType::npos) | |
| 315 return true; | |
| 316 } | |
| 317 | |
| 318 return false; | |
| 319 } | |
| 320 | |
| 321 // static | |
| 322 std::string FileSystemPathManager::GetFileSystemTypeString( | 149 std::string FileSystemPathManager::GetFileSystemTypeString( |
| 323 fileapi::FileSystemType type) { | 150 fileapi::FileSystemType type) { |
| 324 if (type == fileapi::kFileSystemTypeTemporary) | 151 if (type == fileapi::kFileSystemTypeTemporary) |
| 325 return fileapi::FileSystemPathManager::kTemporaryName; | 152 return fileapi::SandboxMountPointProvider::kTemporaryName; |
| 326 else if (type == fileapi::kFileSystemTypePersistent) | 153 else if (type == fileapi::kFileSystemTypePersistent) |
| 327 return fileapi::FileSystemPathManager::kPersistentName; | 154 return fileapi::SandboxMountPointProvider::kPersistentName; |
| 328 return std::string(); | 155 return std::string(); |
| 329 } | 156 } |
| 330 | 157 |
| 331 // static | 158 // Checks if a given |name| contains any restricted names/chars in it. |
| 332 std::string FileSystemPathManager::GetOriginIdentifierFromURL( | 159 bool FileSystemPathManager::IsRestrictedFileName( |
| 333 const GURL& url) { | 160 FileSystemType type, const FilePath& filename) { |
| 334 WebKit::WebSecurityOrigin web_security_origin = | 161 switch (type) { |
| 335 WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec())); | 162 case kFileSystemTypeTemporary: |
| 336 return web_security_origin.databaseIdentifier().utf8(); | 163 case kFileSystemTypePersistent: |
| 337 } | 164 return sandbox_provider_->IsRestrictedFileName(filename); |
| 338 | 165 case kFileSystemTypeUnknown: |
| 339 // static | 166 default: |
| 340 FilePath FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType( | 167 NOTREACHED(); |
| 341 const FilePath& base_path, const std::string& origin_identifier, | 168 return true; |
| 342 fileapi::FileSystemType type) { | |
| 343 if (origin_identifier.empty()) | |
| 344 return FilePath(); | |
| 345 std::string type_string = GetFileSystemTypeString(type); | |
| 346 if (type_string.empty()) { | |
| 347 LOG(WARNING) << "Unknown filesystem type is requested:" << type; | |
| 348 return FilePath(); | |
| 349 } | 169 } |
| 350 return base_path.AppendASCII(origin_identifier) | |
| 351 .AppendASCII(type_string); | |
| 352 } | |
| 353 | |
| 354 FileSystemPathManager::OriginEnumerator::OriginEnumerator( | |
| 355 const FilePath& base_path) | |
| 356 : enumerator_(base_path, false /* recursive */, | |
| 357 file_util::FileEnumerator::DIRECTORIES) { | |
| 358 } | |
| 359 | |
| 360 std::string FileSystemPathManager::OriginEnumerator::Next() { | |
| 361 current_ = enumerator_.Next(); | |
| 362 return FilePathStringToASCII(current_.BaseName().value()); | |
| 363 } | |
| 364 | |
| 365 bool FileSystemPathManager::OriginEnumerator::HasTemporary() { | |
| 366 return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII( | |
| 367 FileSystemPathManager::kTemporaryName)); | |
| 368 } | |
| 369 | |
| 370 bool FileSystemPathManager::OriginEnumerator::HasPersistent() { | |
| 371 return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII( | |
| 372 FileSystemPathManager::kPersistentName)); | |
| 373 } | 170 } |
| 374 | 171 |
| 375 } // namespace fileapi | 172 } // namespace fileapi |
| 376 | 173 |
| 377 COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \ | 174 COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \ |
| 378 int(fileapi::kFileSystemTypeTemporary), mismatching_enums); | 175 int(fileapi::kFileSystemTypeTemporary), mismatching_enums); |
| 379 COMPILE_ASSERT(int(WebFileSystem::TypePersistent) == \ | 176 COMPILE_ASSERT(int(WebFileSystem::TypePersistent) == \ |
| 380 int(fileapi::kFileSystemTypePersistent), mismatching_enums); | 177 int(fileapi::kFileSystemTypePersistent), mismatching_enums); |
| OLD | NEW |