| Index: webkit/fileapi/sandbox_mount_point_provider.cc
|
| ===================================================================
|
| --- webkit/fileapi/sandbox_mount_point_provider.cc (revision 0)
|
| +++ webkit/fileapi/sandbox_mount_point_provider.cc (revision 0)
|
| @@ -0,0 +1,312 @@
|
| +// 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.
|
| +
|
| +#include "webkit/fileapi/sandbox_mount_point_provider.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/message_loop_proxy.h"
|
| +#include "base/rand_util.h"
|
| +#include "base/scoped_callback_factory.h"
|
| +#include "base/scoped_ptr.h"
|
| +#include "base/string_util.h"
|
| +#include "base/stringprintf.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/WebSecurityOrigin.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
|
| +#include "webkit/fileapi/file_system_path_manager.h"
|
| +#include "webkit/fileapi/file_system_util.h"
|
| +#include "webkit/glue/webkit_glue.h"
|
| +
|
| +namespace {
|
| +
|
| +static const FilePath::CharType kFileSystemUniqueNamePrefix[] =
|
| + FILE_PATH_LITERAL("chrome-");
|
| +static const int kFileSystemUniqueLength = 16;
|
| +static const unsigned kFileSystemUniqueDirectoryNameLength =
|
| + kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1;
|
| +
|
| +// 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;
|
| +}
|
| +
|
| +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();
|
| +}
|
| +
|
| +FilePath GetFileSystemRootPathOnFileThreadHelper(
|
| + const GURL& origin_url, const FilePath &origin_base_path, bool create) {
|
| + FilePath root;
|
| + if (ReadOriginDirectory(origin_base_path, origin_url, &root))
|
| + return root;
|
| +
|
| + if (!create)
|
| + return FilePath();
|
| +
|
| + // Creates the root directory.
|
| + root = origin_base_path.Append(CreateUniqueDirectoryName(origin_url));
|
| + if (!file_util::CreateDirectory(root))
|
| + return FilePath();
|
| +
|
| + return root;
|
| +}
|
| +
|
| +} // anonymous namespace
|
| +
|
| +namespace fileapi {
|
| +
|
| +const FilePath::CharType SandboxMountPointProvider::kFileSystemDirectory[] =
|
| + FILE_PATH_LITERAL("FileSystem");
|
| +
|
| +const char SandboxMountPointProvider::kPersistentName[] = "Persistent";
|
| +const char SandboxMountPointProvider::kTemporaryName[] = "Temporary";
|
| +
|
| +SandboxMountPointProvider::SandboxMountPointProvider(
|
| + FileSystemPathManager* path_manager,
|
| + scoped_refptr<base::MessageLoopProxy> file_message_loop,
|
| + const FilePath& profile_path)
|
| + : path_manager_(path_manager),
|
| + file_message_loop_(file_message_loop),
|
| + base_path_(profile_path.Append(kFileSystemDirectory)) {
|
| +}
|
| +
|
| +bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url) {
|
| + // We essentially depend on quota to do our access controls.
|
| + return path_manager_->IsAllowedScheme(origin_url);
|
| +}
|
| +
|
| +class SandboxMountPointProvider::GetFileSystemRootPathTask
|
| + : public base::RefCountedThreadSafe<
|
| + SandboxMountPointProvider::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& origin_base_path,
|
| + bool create) {
|
| + DispatchCallbackOnCallerThread(
|
| + GetFileSystemRootPathOnFileThreadHelper(
|
| + origin_url, origin_base_path, create));
|
| + }
|
| +
|
| + 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_;
|
| +};
|
| +
|
| +bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename)
|
| + const {
|
| + 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;
|
| +}
|
| +
|
| +void SandboxMountPointProvider::GetFileSystemRootPath(
|
| + const GURL& origin_url, fileapi::FileSystemType type,
|
| + bool create, FileSystemPathManager::GetRootPathCallback* callback_ptr) {
|
| + scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback(callback_ptr);
|
| + std::string name;
|
| + FilePath origin_base_path;
|
| +
|
| + if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, &name)) {
|
| + callback->Run(false, FilePath(), std::string());
|
| + return;
|
| + }
|
| +
|
| + scoped_refptr<GetFileSystemRootPathTask> task(
|
| + new GetFileSystemRootPathTask(file_message_loop_,
|
| + name,
|
| + callback.release()));
|
| + task->Start(origin_url, origin_base_path, create);
|
| +};
|
| +
|
| +FilePath SandboxMountPointProvider::GetFileSystemRootPathOnFileThread(
|
| + const GURL& origin_url, FileSystemType type, bool create) {
|
| + FilePath origin_base_path;
|
| + if (!GetOriginBasePathAndName(origin_url, &origin_base_path, type, NULL)) {
|
| + return FilePath();
|
| + }
|
| + return GetFileSystemRootPathOnFileThreadHelper(
|
| + origin_url, origin_base_path, create);
|
| +}
|
| +
|
| +// static
|
| +std::string SandboxMountPointProvider::GetOriginIdentifierFromURL(
|
| + const GURL& url) {
|
| + WebKit::WebSecurityOrigin web_security_origin =
|
| + WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
|
| + return web_security_origin.databaseIdentifier().utf8();
|
| +}
|
| +
|
| +// static
|
| +FilePath SandboxMountPointProvider::GetFileSystemBaseDirectoryForOriginAndType(
|
| + const FilePath& base_path, const std::string& origin_identifier,
|
| + fileapi::FileSystemType type) {
|
| + if (origin_identifier.empty())
|
| + return FilePath();
|
| + std::string type_string =
|
| + FileSystemPathManager::GetFileSystemTypeString(type);
|
| + if (type_string.empty()) {
|
| + LOG(WARNING) << "Unknown filesystem type is requested:" << type;
|
| + return FilePath();
|
| + }
|
| + return base_path.AppendASCII(origin_identifier)
|
| + .AppendASCII(type_string);
|
| +}
|
| +
|
| +SandboxMountPointProvider::OriginEnumerator::OriginEnumerator(
|
| + const FilePath& base_path)
|
| + : enumerator_(base_path, false /* recursive */,
|
| + file_util::FileEnumerator::DIRECTORIES) {
|
| +}
|
| +
|
| +std::string SandboxMountPointProvider::OriginEnumerator::Next() {
|
| + current_ = enumerator_.Next();
|
| + return FilePathStringToASCII(current_.BaseName().value());
|
| +}
|
| +
|
| +bool SandboxMountPointProvider::OriginEnumerator::HasTemporary() {
|
| + return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
|
| + SandboxMountPointProvider::kTemporaryName));
|
| +}
|
| +
|
| +bool SandboxMountPointProvider::OriginEnumerator::HasPersistent() {
|
| + return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII(
|
| + SandboxMountPointProvider::kPersistentName));
|
| +}
|
| +
|
| +bool SandboxMountPointProvider::GetOriginBasePathAndName(
|
| + const GURL& origin_url,
|
| + FilePath* origin_base_path,
|
| + FileSystemType type,
|
| + std::string* name) {
|
| +
|
| + if (path_manager_->is_incognito())
|
| + // TODO(kinuko): return an isolated temporary directory.
|
| + return false;
|
| +
|
| + if (!path_manager_->IsAllowedScheme(origin_url))
|
| + return false;
|
| +
|
| + std::string origin_identifier = GetOriginIdentifierFromURL(origin_url);
|
| + *origin_base_path = GetFileSystemBaseDirectoryForOriginAndType(
|
| + base_path(), origin_identifier, type);
|
| + if (origin_base_path->empty())
|
| + return false;
|
| +
|
| + std::string type_string =
|
| + FileSystemPathManager::GetFileSystemTypeString(type);
|
| + DCHECK(!type_string.empty());
|
| + if (name)
|
| + *name = origin_identifier + ":" + type_string;
|
| + return true;
|
| +}
|
| +
|
| +} // namespace fileapi
|
|
|
| Property changes on: webkit\fileapi\sandbox_mount_point_provider.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|