summaryrefslogtreecommitdiffstats
path: root/webkit/fileapi/file_system_path_manager.cc
diff options
context:
space:
mode:
authorericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-24 00:49:40 +0000
committerericu@google.com <ericu@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-24 00:49:40 +0000
commit073a04f0599beb27670d8a6738fcbbc22fa97bcf (patch)
treed7393b3cd3463dbfaf4bbdc02fdd0a4de0c83995 /webkit/fileapi/file_system_path_manager.cc
parent6bcd5f36cd94649887eff0c87df4f4496001984a (diff)
downloadchromium_src-073a04f0599beb27670d8a6738fcbbc22fa97bcf.zip
chromium_src-073a04f0599beb27670d8a6738fcbbc22fa97bcf.tar.gz
chromium_src-073a04f0599beb27670d8a6738fcbbc22fa97bcf.tar.bz2
Stop returning the true root path of each filesystem from openFileSystem.
Instead, return the FileSystem URI of the root. This will make it easier to swap in different filesystem implementations. BUG=71635 TEST=Just a couple in FileSystemUtilTests, but a bunch of existing ones [this doesn't add much new functionality]. Review URL: http://codereview.chromium.org/6603034 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79228 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi/file_system_path_manager.cc')
-rw-r--r--webkit/fileapi/file_system_path_manager.cc373
1 files changed, 84 insertions, 289 deletions
diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc
index 61aa49e..64f3274 100644
--- a/webkit/fileapi/file_system_path_manager.cc
+++ b/webkit/fileapi/file_system_path_manager.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -14,171 +14,33 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "googleurl/src/gurl.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
#include "webkit/glue/webkit_glue.h"
// We use some of WebKit types for conversions between origin identifiers
// and origin URLs.
using WebKit::WebFileSystem;
-using WebKit::WebSecurityOrigin;
-using WebKit::WebString;
using base::PlatformFileError;
-namespace fileapi {
-
-const FilePath::CharType FileSystemPathManager::kFileSystemDirectory[] =
- FILE_PATH_LITERAL("FileSystem");
-
-const char FileSystemPathManager::kPersistentName[] = "Persistent";
-const char FileSystemPathManager::kTemporaryName[] = "Temporary";
-
-static const FilePath::CharType kFileSystemUniqueNamePrefix[] =
- FILE_PATH_LITERAL("chrome-");
-static const int kFileSystemUniqueLength = 16;
-static const unsigned kFileSystemUniqueDirectoryNameLength =
- kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1;
-
-namespace {
-
-// Restricted names.
-// http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
-static const char* const kRestrictedNames[] = {
- "con", "prn", "aux", "nul",
- "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
- "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
-};
-
-// Restricted chars.
-static const FilePath::CharType kRestrictedChars[] = {
- '/', '\\', '<', '>', ':', '?', '*', '"', '|',
-};
-
-inline std::string FilePathStringToASCII(
- const FilePath::StringType& path_string) {
-#if defined(OS_WIN)
- return WideToASCII(path_string);
-#elif defined(OS_POSIX)
- return path_string;
-#endif
-}
-
-FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) {
- // This can be anything but need to be unpredictable.
- static const FilePath::CharType letters[] = FILE_PATH_LITERAL(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
- FilePath::StringType unique(kFileSystemUniqueNamePrefix);
- for (int i = 0; i < kFileSystemUniqueLength; ++i)
- unique += letters[base::RandInt(0, arraysize(letters) - 2)];
- return unique;
-}
-
static const char kExtensionScheme[] = "chrome-extension";
-} // anonymous namespace
-
-class FileSystemPathManager::GetFileSystemRootPathTask
- : public base::RefCountedThreadSafe<
- FileSystemPathManager::GetFileSystemRootPathTask> {
- public:
- GetFileSystemRootPathTask(
- scoped_refptr<base::MessageLoopProxy> file_message_loop,
- const std::string& name,
- FileSystemPathManager::GetRootPathCallback* callback)
- : file_message_loop_(file_message_loop),
- origin_message_loop_proxy_(
- base::MessageLoopProxy::CreateForCurrentThread()),
- name_(name),
- callback_(callback) {
- }
-
- void Start(const GURL& origin_url,
- const FilePath& origin_base_path,
- bool create) {
- file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
- &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread,
- origin_url, origin_base_path, create));
- }
-
- private:
- void GetFileSystemRootPathOnFileThread(
- const GURL& origin_url,
- const FilePath& base_path,
- bool create) {
- FilePath root;
- if (ReadOriginDirectory(base_path, origin_url, &root)) {
- DispatchCallbackOnCallerThread(root);
- return;
- }
-
- if (!create) {
- DispatchCallbackOnCallerThread(FilePath());
- return;
- }
-
- // Creates the root directory.
- root = base_path.Append(CreateUniqueDirectoryName(origin_url));
- if (!file_util::CreateDirectory(root)) {
- DispatchCallbackOnCallerThread(FilePath());
- return;
- }
- DispatchCallbackOnCallerThread(root);
- }
-
- bool ReadOriginDirectory(const FilePath& base_path,
- const GURL& origin_url,
- FilePath* unique) {
- file_util::FileEnumerator file_enum(
- base_path, false /* recursive */,
- file_util::FileEnumerator::DIRECTORIES,
- FilePath::StringType(kFileSystemUniqueNamePrefix) +
- FILE_PATH_LITERAL("*"));
- FilePath current;
- bool found = false;
- while (!(current = file_enum.Next()).empty()) {
- if (current.BaseName().value().length() !=
- kFileSystemUniqueDirectoryNameLength)
- continue;
- if (found) {
- // TODO(kinuko): Should notify the user to ask for some action.
- LOG(WARNING) << "Unexpectedly found more than one FileSystem "
- << "directories for " << origin_url;
- return false;
- }
- found = true;
- *unique = current;
- }
- return !unique->empty();
- }
-
- void DispatchCallbackOnCallerThread(const FilePath& root_path) {
- origin_message_loop_proxy_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback,
- root_path));
- }
-
- void DispatchCallback(const FilePath& root_path) {
- callback_->Run(!root_path.empty(), root_path, name_);
- callback_.reset();
- }
-
- scoped_refptr<base::MessageLoopProxy> file_message_loop_;
- scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
- std::string name_;
- scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_;
-};
+namespace fileapi {
FileSystemPathManager::FileSystemPathManager(
scoped_refptr<base::MessageLoopProxy> file_message_loop,
const FilePath& profile_path,
bool is_incognito,
bool allow_file_access_from_files)
- : file_message_loop_(file_message_loop),
- base_path_(profile_path.Append(kFileSystemDirectory)),
- is_incognito_(is_incognito),
- allow_file_access_from_files_(allow_file_access_from_files) {
+ : is_incognito_(is_incognito),
+ allow_file_access_from_files_(allow_file_access_from_files),
+ sandbox_provider_(
+ new SandboxMountPointProvider(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this),
+ file_message_loop,
+ profile_path)) {
}
FileSystemPathManager::~FileSystemPathManager() {}
@@ -186,95 +48,88 @@ FileSystemPathManager::~FileSystemPathManager() {}
void FileSystemPathManager::GetFileSystemRootPath(
const GURL& origin_url, fileapi::FileSystemType type,
bool create, GetRootPathCallback* callback_ptr) {
- scoped_ptr<GetRootPathCallback> callback(callback_ptr);
- if (is_incognito_) {
- // TODO(kinuko): return an isolated temporary directory.
- callback->Run(false, FilePath(), std::string());
- return;
- }
- if (!IsAllowedScheme(origin_url)) {
- callback->Run(false, FilePath(), std::string());
- return;
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ sandbox_provider_->GetFileSystemRootPath(
+ origin_url, type, create, callback_ptr);
+ break;
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ callback_ptr->Run(false, FilePath(), std::string());
}
+}
- std::string origin_identifier = GetOriginIdentifierFromURL(origin_url);
- FilePath origin_base_path = GetFileSystemBaseDirectoryForOriginAndType(
- base_path(), origin_identifier, type);
- if (origin_base_path.empty()) {
- callback->Run(false, FilePath(), std::string());
- return;
+FilePath FileSystemPathManager::GetFileSystemRootPathOnFileThread(
+ const GURL& origin_url, FileSystemType type, bool create) {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ return sandbox_provider_->GetFileSystemRootPathOnFileThread(
+ origin_url, type, create);
+ break;
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ return FilePath();
}
-
- std::string type_string = GetFileSystemTypeString(type);
- DCHECK(!type_string.empty());
-
- scoped_refptr<GetFileSystemRootPathTask> task(
- new GetFileSystemRootPathTask(file_message_loop_,
- origin_identifier + ":" + type_string,
- callback.release()));
- task->Start(origin_url, origin_base_path, create);
}
bool FileSystemPathManager::CrackFileSystemPath(
const FilePath& path, GURL* origin_url, FileSystemType* type,
FilePath* virtual_path) const {
- // Any paths that includes parent references are considered invalid.
- if (path.ReferencesParent())
- return false;
-
- // The path should be a child of the profile FileSystem path.
- FilePath relative;
- if (!base_path_.AppendRelativePath(path, &relative))
- return false;
-
- // The relative path from the profile FileSystem path should contain
- // at least three components, one for storage identifier, one for type
- // and one for the 'unique' part.
- std::vector<FilePath::StringType> components;
- relative.GetComponents(&components);
- if (components.size() < 3)
- return false;
+ // TODO(ericu):
+ // Paths come in here [for now] as a URL, followed by a virtual path in
+ // platform format. For example, on Windows, this will look like
+ // filesystem:http://www.example.com/temporary/\path\to\file.txt.
+ // A potentially dangerous malicious path on Windows might look like:
+ // filesystem:http://www.example.com/temporary/foo/../../\path\to\file.txt.
+ // This code is ugly, but will get cleaned up as we fix the calling side.
+ // Eventually there won't be a distinction between a filesystem path and a
+ // filesystem URL--they'll all be URLs.
+ // We should be passing these to WebKit as string, not FilePath, for ease of
+ // manipulation, or possibly as GURL/KURL.
+
+ std::string path_as_string;
+#ifdef OS_WIN
+ path_as_string = WideToUTF8(path.value());
+#else
+ path_as_string = path.value();
+#endif
+ GURL path_as_url(path_as_string);
- // The second component of the relative path to the root directory
- // must be kPersistent or kTemporary.
- if (!IsStringASCII(components[1]))
+ FilePath local_path;
+ GURL local_url;
+ FileSystemType local_type;
+ if (!CrackFileSystemURL(path_as_url, &local_url, &local_type, &local_path))
return false;
- std::string ascii_type_component = FilePathStringToASCII(components[1]);
- FileSystemType cracked_type = kFileSystemTypeUnknown;
- if (ascii_type_component == kPersistentName)
- cracked_type = kFileSystemTypePersistent;
- else if (ascii_type_component == kTemporaryName)
- cracked_type = kFileSystemTypeTemporary;
- else
- return false;
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ // TODO(ericu): This puts the separators back to windows-standard; they come
+ // out of the above code as '/' no matter the platform. Long-term, we'll
+ // want to let the underlying FileSystemFileUtil implementation do this part,
+ // since they won't all need it.
+ local_path = local_path.NormalizeWindowsPathSeparators();
+#endif
- DCHECK(cracked_type != kFileSystemTypeUnknown);
+ // Any paths that include parent references are considered invalid.
+ // These should have been taken care of in CrackFileSystemURL.
+ DCHECK(!local_path.ReferencesParent());
- // The given |path| seems valid. Populates the |origin_url|, |type|
+ // The given |local_path| seems valid. Populates the |origin_url|, |type|
// and |virtual_path| if they are given.
if (origin_url) {
- WebSecurityOrigin web_security_origin =
- WebSecurityOrigin::createFromDatabaseIdentifier(
- webkit_glue::FilePathStringToWebString(components[0]));
- *origin_url = GURL(web_security_origin.toString());
-
- // We need this work-around for file:/// URIs as
- // createFromDatabaseIdentifier returns empty origin_url for them.
- if (allow_file_access_from_files_ && origin_url->spec().empty() &&
- components[0].find(FILE_PATH_LITERAL("file")) == 0)
- *origin_url = GURL("file:///");
+ *origin_url = local_url;
}
if (type)
- *type = cracked_type;
+ *type = local_type;
if (virtual_path) {
- virtual_path->clear();
- for (size_t i = 3; i < components.size(); ++i)
- *virtual_path = virtual_path->Append(components[i]);
+ *virtual_path = local_path;
}
return true;
@@ -289,87 +144,27 @@ bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const {
}
// static
-bool FileSystemPathManager::IsRestrictedFileName(const FilePath& filename) {
- if (filename.value().empty())
- return false;
-
- if (IsWhitespace(filename.value()[filename.value().size() - 1]) ||
- filename.value()[filename.value().size() - 1] == '.')
- return true;
-
- std::string filename_lower = StringToLowerASCII(
- FilePathStringToASCII(filename.value()));
-
- for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
- // Exact match.
- if (filename_lower == kRestrictedNames[i])
- return true;
- // Starts with "RESTRICTED_NAME.".
- if (filename_lower.find(std::string(kRestrictedNames[i]) + ".") == 0)
- return true;
- }
-
- for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
- if (filename.value().find(kRestrictedChars[i]) !=
- FilePath::StringType::npos)
- return true;
- }
-
- return false;
-}
-
-// static
std::string FileSystemPathManager::GetFileSystemTypeString(
fileapi::FileSystemType type) {
if (type == fileapi::kFileSystemTypeTemporary)
- return fileapi::FileSystemPathManager::kTemporaryName;
+ return fileapi::SandboxMountPointProvider::kTemporaryName;
else if (type == fileapi::kFileSystemTypePersistent)
- return fileapi::FileSystemPathManager::kPersistentName;
+ return fileapi::SandboxMountPointProvider::kPersistentName;
return std::string();
}
-// static
-std::string FileSystemPathManager::GetOriginIdentifierFromURL(
- const GURL& url) {
- WebKit::WebSecurityOrigin web_security_origin =
- WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
- return web_security_origin.databaseIdentifier().utf8();
-}
-
-// static
-FilePath FileSystemPathManager::GetFileSystemBaseDirectoryForOriginAndType(
- const FilePath& base_path, const std::string& origin_identifier,
- fileapi::FileSystemType type) {
- if (origin_identifier.empty())
- return FilePath();
- std::string type_string = GetFileSystemTypeString(type);
- if (type_string.empty()) {
- LOG(WARNING) << "Unknown filesystem type is requested:" << type;
- return FilePath();
+// Checks if a given |name| contains any restricted names/chars in it.
+bool FileSystemPathManager::IsRestrictedFileName(
+ FileSystemType type, const FilePath& filename) {
+ switch (type) {
+ case kFileSystemTypeTemporary:
+ case kFileSystemTypePersistent:
+ return sandbox_provider_->IsRestrictedFileName(filename);
+ case kFileSystemTypeUnknown:
+ default:
+ NOTREACHED();
+ return true;
}
- return base_path.AppendASCII(origin_identifier)
- .AppendASCII(type_string);
-}
-
-FileSystemPathManager::OriginEnumerator::OriginEnumerator(
- const FilePath& base_path)
- : enumerator_(base_path, false /* recursive */,
- file_util::FileEnumerator::DIRECTORIES) {
-}
-
-std::string FileSystemPathManager::OriginEnumerator::Next() {
- current_ = enumerator_.Next();
- return FilePathStringToASCII(current_.BaseName().value());
-}
-
-bool FileSystemPathManager::OriginEnumerator::HasTemporary() {
- return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
- FileSystemPathManager::kTemporaryName));
-}
-
-bool FileSystemPathManager::OriginEnumerator::HasPersistent() {
- return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
- FileSystemPathManager::kPersistentName));
}
} // namespace fileapi