summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-18 03:12:54 +0000
committertbarzic@chromium.org <tbarzic@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-18 03:12:54 +0000
commit9d5d6986dfaed15ef3719250fbf7fb8347bebd80 (patch)
treea472d1593efc197e15d9474d26e93530b939ec7f
parentd22af016d12e789ac7c5976c300c819ebe4340b3 (diff)
downloadchromium_src-9d5d6986dfaed15ef3719250fbf7fb8347bebd80.zip
chromium_src-9d5d6986dfaed15ef3719250fbf7fb8347bebd80.tar.gz
chromium_src-9d5d6986dfaed15ef3719250fbf7fb8347bebd80.tar.bz2
Extract external file systems handling from isolated context.
Move mount point info bookeeping from CrosMountPointProvider to ExternalMountPoints. Add some tests for CrosMountPointProvider. BUG=158837 TEST=content_unittests:CrosMountPointProvider* TBR=benwells@chromium.org Review URL: https://chromiumcodereview.appspot.com/11648027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177578 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/drive/drive_file_system_proxy.h2
-rw-r--r--chrome/browser/extensions/api/file_system/file_system_api.cc8
-rw-r--r--chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc8
-rw-r--r--content/content_tests.gypi2
-rw-r--r--webkit/chromeos/fileapi/cros_mount_point_provider.cc138
-rw-r--r--webkit/chromeos/fileapi/cros_mount_point_provider.h52
-rw-r--r--webkit/chromeos/fileapi/cros_mount_point_provider_unittest.cc325
-rw-r--r--webkit/chromeos/fileapi/remote_file_stream_writer.cc2
-rw-r--r--webkit/chromeos/fileapi/remote_file_system_operation.h2
-rw-r--r--webkit/fileapi/external_mount_points.cc331
-rw-r--r--webkit/fileapi/external_mount_points.h155
-rw-r--r--webkit/fileapi/external_mount_points_unittest.cc227
-rw-r--r--webkit/fileapi/file_system_context.cc8
-rw-r--r--webkit/fileapi/file_system_mount_point_provider.h8
-rw-r--r--webkit/fileapi/file_system_url.cc7
-rw-r--r--webkit/fileapi/file_system_url_unittest.cc13
-rw-r--r--webkit/fileapi/isolated_context.cc235
-rw-r--r--webkit/fileapi/isolated_context.h137
-rw-r--r--webkit/fileapi/isolated_context_unittest.cc12
-rw-r--r--webkit/fileapi/isolated_file_util.cc2
-rw-r--r--webkit/fileapi/mount_points.cc15
-rw-r--r--webkit/fileapi/mount_points.h77
-rw-r--r--webkit/fileapi/remote_file_system_proxy.h (renamed from webkit/chromeos/fileapi/remote_file_system_proxy.h)0
-rw-r--r--webkit/fileapi/syncable/canned_syncable_file_system.cc1
-rw-r--r--webkit/fileapi/syncable/syncable_file_system_util.cc7
-rw-r--r--webkit/fileapi/syncable/syncable_file_system_util_unittest.cc2
-rw-r--r--webkit/fileapi/webkit_fileapi.gypi6
27 files changed, 1399 insertions, 383 deletions
diff --git a/chrome/browser/chromeos/drive/drive_file_system_proxy.h b/chrome/browser/chromeos/drive/drive_file_system_proxy.h
index d2db758..d66b473 100644
--- a/chrome/browser/chromeos/drive/drive_file_system_proxy.h
+++ b/chrome/browser/chromeos/drive/drive_file_system_proxy.h
@@ -6,7 +6,7 @@
#define CHROME_BROWSER_CHROMEOS_DRIVE_DRIVE_FILE_SYSTEM_PROXY_H_
#include "chrome/browser/chromeos/drive/drive_file_error.h"
-#include "webkit/chromeos/fileapi/remote_file_system_proxy.h"
+#include "webkit/fileapi/remote_file_system_proxy.h"
namespace fileapi {
class FileSystemURL;
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
index 2b5301b..0faa9e9 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -156,10 +156,10 @@ bool GetFilePathOfFileEntry(const std::string& filesystem_name,
FilePath relative_path = FilePath::FromUTF8Unsafe(filesystem_path);
FilePath virtual_path = context->CreateVirtualRootPath(filesystem_id)
.Append(relative_path);
- if (!context->CrackIsolatedPath(virtual_path,
- &filesystem_id,
- NULL,
- file_path)) {
+ if (!context->CrackVirtualPath(virtual_path,
+ &filesystem_id,
+ NULL,
+ file_path)) {
*error = kInvalidParameters;
return false;
}
diff --git a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
index 62faaa7..dcc3934 100644
--- a/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
+++ b/chrome/browser/ui/views/select_file_dialog_extension_browsertest.cc
@@ -28,6 +28,7 @@
#include "content/public/test/test_utils.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/selected_file_info.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_mount_point_provider.h"
@@ -119,7 +120,12 @@ class SelectFileDialogExtensionBrowserTest : public ExtensionBrowserTest {
fileapi::ExternalFileSystemMountPointProvider* provider =
BrowserContext::GetDefaultStoragePartition(browser()->profile())->
GetFileSystemContext()->external_provider();
- provider->AddLocalMountPoint(path);
+
+ // The Downloads mount point already exists so it must be removed before
+ // adding the test mount point (which will also be mapped as Downloads).
+ fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ path.BaseName().AsUTF8Unsafe());
+ EXPECT_TRUE(provider->AddLocalMountPoint(path));
}
void CheckJavascriptErrors() {
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 6a0dac1..804605d 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -404,6 +404,7 @@
'../webkit/blob/mock_blob_url_request_context.cc',
'../webkit/blob/mock_blob_url_request_context.h',
'../webkit/blob/shareable_file_reference_unittest.cc',
+ '../webkit/chromeos/fileapi/cros_mount_point_provider_unittest.cc',
'../webkit/database/database_connections_unittest.cc',
'../webkit/database/database_quota_client_unittest.cc',
'../webkit/database/databases_table_unittest.cc',
@@ -415,6 +416,7 @@
'../webkit/dom_storage/dom_storage_database_unittest.cc',
'../webkit/dom_storage/dom_storage_map_unittest.cc',
'../webkit/dom_storage/session_storage_database_unittest.cc',
+ '../webkit/fileapi/external_mount_points_unittest.cc',
'../webkit/fileapi/file_system_database_test_helper.cc',
'../webkit/fileapi/file_system_database_test_helper.h',
'../webkit/fileapi/file_system_directory_database_unittest.cc',
diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider.cc b/webkit/chromeos/fileapi/cros_mount_point_provider.cc
index f61e3cc..33bcbf1 100644
--- a/webkit/chromeos/fileapi/cros_mount_point_provider.cc
+++ b/webkit/chromeos/fileapi/cros_mount_point_provider.cc
@@ -8,7 +8,6 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
-#include "base/path_service.h"
#include "base/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/utf_string_conversions.h"
@@ -19,6 +18,7 @@
#include "webkit/chromeos/fileapi/file_access_permissions.h"
#include "webkit/chromeos/fileapi/remote_file_stream_writer.h"
#include "webkit/chromeos/fileapi/remote_file_system_operation.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/file_system_file_stream_reader.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_url.h"
@@ -47,16 +47,14 @@ bool CrosMountPointProvider::CanHandleURL(const fileapi::FileSystemURL& url) {
}
CrosMountPointProvider::CrosMountPointProvider(
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy)
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points,
+ fileapi::ExternalMountPoints* system_mount_points)
: special_storage_policy_(special_storage_policy),
file_access_permissions_(new FileAccessPermissions()),
- local_file_util_(new fileapi::IsolatedFileUtil()) {
- FilePath home_path;
- if (PathService::Get(base::DIR_HOME, &home_path))
- AddLocalMountPoint(home_path.AppendASCII("Downloads"));
- AddLocalMountPoint(FilePath(FILE_PATH_LITERAL("/media/archive")));
- AddLocalMountPoint(FilePath(FILE_PATH_LITERAL("/media/removable")));
- AddRestrictedLocalMountPoint(FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
+ local_file_util_(new fileapi::IsolatedFileUtil()),
+ mount_points_(mount_points),
+ system_mount_points_(system_mount_points) {
}
CrosMountPointProvider::~CrosMountPointProvider() {
@@ -80,8 +78,11 @@ FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread(
return FilePath();
FilePath root_path;
- if (!isolated_context()->GetRegisteredPath(url.filesystem_id(), &root_path))
+ std::string mount_name = url.filesystem_id();
+ if (!mount_points_->GetRegisteredPath(mount_name, &root_path) &&
+ !system_mount_points_->GetRegisteredPath(mount_name, &root_path)) {
return FilePath();
+ }
return root_path.DirName();
}
@@ -128,56 +129,47 @@ void CrosMountPointProvider::DeleteFileSystem(
callback.Run(base::PLATFORM_FILE_ERROR_INVALID_OPERATION);
}
-bool CrosMountPointProvider::HasMountPoint(const FilePath& mount_point) {
+bool CrosMountPointProvider::HasMountPoint(const FilePath& mount_point) const {
std::string mount_name = mount_point.BaseName().AsUTF8Unsafe();
FilePath path;
- const bool valid = isolated_context()->GetRegisteredPath(mount_name, &path);
+
+ const bool valid = mount_points_->GetRegisteredPath(mount_name, &path);
return valid && path == mount_point;
}
-void CrosMountPointProvider::AddLocalMountPoint(const FilePath& mount_point) {
+bool CrosMountPointProvider::AddLocalMountPoint(const FilePath& mount_point) {
std::string mount_name = mount_point.BaseName().AsUTF8Unsafe();
- isolated_context()->RevokeFileSystem(mount_name);
- isolated_context()->RegisterExternalFileSystem(
- mount_name,
- fileapi::kFileSystemTypeNativeLocal,
- mount_point);
- base::AutoLock locker(mount_point_map_lock_);
- local_to_virtual_map_[mount_point] = mount_point.BaseName();
+ return mount_points_->RegisterFileSystem(
+ mount_name,
+ fileapi::kFileSystemTypeNativeLocal,
+ mount_point);
}
-void CrosMountPointProvider::AddRestrictedLocalMountPoint(
+bool CrosMountPointProvider::AddRestrictedLocalMountPoint(
const FilePath& mount_point) {
std::string mount_name = mount_point.BaseName().AsUTF8Unsafe();
- isolated_context()->RevokeFileSystem(mount_name);
- isolated_context()->RegisterExternalFileSystem(
- mount_name,
- fileapi::kFileSystemTypeRestrictedNativeLocal,
- mount_point);
- base::AutoLock locker(mount_point_map_lock_);
- local_to_virtual_map_[mount_point] = mount_point.BaseName();
+ return mount_points_->RegisterFileSystem(
+ mount_name,
+ fileapi::kFileSystemTypeRestrictedNativeLocal,
+ mount_point);
}
-void CrosMountPointProvider::AddRemoteMountPoint(
+bool CrosMountPointProvider::AddRemoteMountPoint(
const FilePath& mount_point,
fileapi::RemoteFileSystemProxyInterface* remote_proxy) {
DCHECK(remote_proxy);
std::string mount_name = mount_point.BaseName().AsUTF8Unsafe();
- isolated_context()->RevokeFileSystem(mount_name);
- isolated_context()->RegisterExternalFileSystem(mount_name,
+ return mount_points_->RegisterRemoteFileSystem(mount_name,
fileapi::kFileSystemTypeDrive,
+ remote_proxy,
mount_point);
- base::AutoLock locker(mount_point_map_lock_);
- remote_proxy_map_[mount_name] = remote_proxy;
- local_to_virtual_map_[mount_point] = mount_point.BaseName();
}
void CrosMountPointProvider::RemoveMountPoint(const FilePath& mount_point) {
+ if (!HasMountPoint(mount_point))
+ return;
std::string mount_name = mount_point.BaseName().AsUTF8Unsafe();
- isolated_context()->RevokeFileSystem(mount_name);
- base::AutoLock locker(mount_point_map_lock_);
- remote_proxy_map_.erase(mount_name);
- local_to_virtual_map_.erase(mount_point);
+ mount_points_->RevokeFileSystem(mount_name);
}
void CrosMountPointProvider::GrantFullAccessToExtension(
@@ -185,8 +177,11 @@ void CrosMountPointProvider::GrantFullAccessToExtension(
DCHECK(special_storage_policy_->IsFileHandler(extension_id));
if (!special_storage_policy_->IsFileHandler(extension_id))
return;
- std::vector<fileapi::IsolatedContext::FileInfo> files =
- isolated_context()->GetExternalMountPoints();
+
+ std::vector<fileapi::MountPoints::MountPointInfo> files;
+ mount_points_->AddMountPointInfosTo(&files);
+ system_mount_points_->AddMountPointInfosTo(&files);
+
for (size_t i = 0; i < files.size(); ++i) {
file_access_permissions_->GrantAccessPermission(
extension_id,
@@ -204,7 +199,11 @@ void CrosMountPointProvider::GrantFileAccessToExtension(
std::string id;
fileapi::FileSystemType type;
FilePath path;
- isolated_context()->CrackIsolatedPath(virtual_path, &id, &type, &path);
+ if (!mount_points_->CrackVirtualPath(virtual_path, &id, &type, &path) &&
+ !system_mount_points_->CrackVirtualPath(virtual_path,
+ &id, &type, &path)) {
+ return;
+ }
if (type == fileapi::kFileSystemTypeRestrictedNativeLocal) {
LOG(ERROR) << "Can't grant access for restricted mount point";
@@ -220,11 +219,13 @@ void CrosMountPointProvider::RevokeAccessForExtension(
}
std::vector<FilePath> CrosMountPointProvider::GetRootDirectories() const {
- std::vector<fileapi::IsolatedContext::FileInfo> files =
- isolated_context()->GetExternalMountPoints();
+ std::vector<fileapi::MountPoints::MountPointInfo> mount_points;
+ mount_points_->AddMountPointInfosTo(&mount_points);
+ system_mount_points_->AddMountPointInfosTo(&mount_points);
+
std::vector<FilePath> root_dirs;
- for (size_t i = 0; i < files.size(); ++i)
- root_dirs.push_back(files[i].path);
+ for (size_t i = 0; i < mount_points.size(); ++i)
+ root_dirs.push_back(mount_points[i].path);
return root_dirs;
}
@@ -249,16 +250,16 @@ fileapi::FileSystemOperation* CrosMountPointProvider::CreateFileSystemOperation(
const fileapi::FileSystemURL& url,
fileapi::FileSystemContext* context,
base::PlatformFileError* error_code) const {
+ DCHECK(url.is_valid());
+
if (url.type() == fileapi::kFileSystemTypeDrive) {
- base::AutoLock locker(mount_point_map_lock_);
- RemoteProxyMap::const_iterator found = remote_proxy_map_.find(
- url.filesystem_id());
- if (found != remote_proxy_map_.end()) {
- return new chromeos::RemoteFileSystemOperation(found->second);
- } else {
+ fileapi::RemoteFileSystemProxyInterface* remote_proxy =
+ GetRemoteProxy(url.filesystem_id());
+ if (!remote_proxy) {
*error_code = base::PLATFORM_FILE_ERROR_NOT_FOUND;
return NULL;
}
+ return new chromeos::RemoteFileSystemOperation(remote_proxy);
}
DCHECK(url.type() == fileapi::kFileSystemTypeNativeLocal ||
@@ -285,15 +286,14 @@ fileapi::FileStreamWriter* CrosMountPointProvider::CreateFileStreamWriter(
const fileapi::FileSystemURL& url,
int64 offset,
fileapi::FileSystemContext* context) const {
- if (!url.is_valid())
- return NULL;
+ DCHECK(url.is_valid());
+
if (url.type() == fileapi::kFileSystemTypeDrive) {
- base::AutoLock locker(mount_point_map_lock_);
- RemoteProxyMap::const_iterator found = remote_proxy_map_.find(
- url.filesystem_id());
- if (found == remote_proxy_map_.end())
+ fileapi::RemoteFileSystemProxyInterface* remote_proxy =
+ GetRemoteProxy(url.filesystem_id());
+ if (!remote_proxy)
return NULL;
- return new fileapi::RemoteFileStreamWriter(found->second, url, offset);
+ return new fileapi::RemoteFileStreamWriter(remote_proxy, url, offset);
}
if (url.type() == fileapi::kFileSystemTypeRestrictedNativeLocal)
@@ -305,21 +305,17 @@ fileapi::FileStreamWriter* CrosMountPointProvider::CreateFileStreamWriter(
bool CrosMountPointProvider::GetVirtualPath(const FilePath& filesystem_path,
FilePath* virtual_path) {
- base::AutoLock locker(mount_point_map_lock_);
- std::map<FilePath, FilePath>::reverse_iterator iter(
- local_to_virtual_map_.upper_bound(filesystem_path));
- if (iter == local_to_virtual_map_.rend())
- return false;
- if (iter->first == filesystem_path) {
- *virtual_path = iter->second;
- return true;
- }
- return iter->first.DirName().AppendRelativePath(
- filesystem_path, virtual_path);
+ return mount_points_->GetVirtualPath(filesystem_path, virtual_path) ||
+ system_mount_points_->GetVirtualPath(filesystem_path, virtual_path);
}
-fileapi::IsolatedContext* CrosMountPointProvider::isolated_context() const {
- return fileapi::IsolatedContext::GetInstance();
+fileapi::RemoteFileSystemProxyInterface* CrosMountPointProvider::GetRemoteProxy(
+ const std::string& mount_name) const {
+ fileapi::RemoteFileSystemProxyInterface* proxy =
+ mount_points_->GetRemoteFileSystemProxy(mount_name);
+ if (proxy)
+ return proxy;
+ return system_mount_points_->GetRemoteFileSystemProxy(mount_name);
}
} // namespace chromeos
diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider.h b/webkit/chromeos/fileapi/cros_mount_point_provider.h
index 6f7b38b..d34c209 100644
--- a/webkit/chromeos/fileapi/cros_mount_point_provider.h
+++ b/webkit/chromeos/fileapi/cros_mount_point_provider.h
@@ -18,6 +18,7 @@
#include "webkit/storage/webkit_storage_export.h"
namespace fileapi {
+class ExternalMountPoints;
class FileSystemFileUtil;
class FileSystemURL;
class IsolatedContext;
@@ -35,8 +36,13 @@ class WEBKIT_STORAGE_EXPORT CrosMountPointProvider
using fileapi::FileSystemMountPointProvider::ValidateFileSystemCallback;
using fileapi::FileSystemMountPointProvider::DeleteFileSystemCallback;
+ // CrosMountPointProvider will take an ownership of a |mount_points|
+ // reference. On the other hand, |system_mount_points| will be kept as a raw
+ // pointer and it should outlive CrosMountPointProvider instance.
CrosMountPointProvider(
- scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy);
+ scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy,
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points,
+ fileapi::ExternalMountPoints* system_mount_points);
virtual ~CrosMountPointProvider();
// Returns true if CrosMountpointProvider can handle |url|, i.e. its
@@ -88,11 +94,14 @@ class WEBKIT_STORAGE_EXPORT CrosMountPointProvider
const std::string& extension_id, const FilePath& virtual_path) OVERRIDE;
virtual void RevokeAccessForExtension(
const std::string& extension_id) OVERRIDE;
- virtual bool HasMountPoint(const FilePath& mount_point) OVERRIDE;
- virtual void AddLocalMountPoint(const FilePath& mount_point) OVERRIDE;
- virtual void AddRestrictedLocalMountPoint(
+ // Note: This will ignore |system_mount_points_|. The reasoning behind this is
+ // the method should be used paired with Add/RemoveMountPoint methods, which
+ // don't affect |system_mount_points_|.
+ virtual bool HasMountPoint(const FilePath& mount_point) const OVERRIDE;
+ virtual bool AddLocalMountPoint(const FilePath& mount_point) OVERRIDE;
+ virtual bool AddRestrictedLocalMountPoint(
const FilePath& mount_point) OVERRIDE;
- virtual void AddRemoteMountPoint(
+ virtual bool AddRemoteMountPoint(
const FilePath& mount_point,
fileapi::RemoteFileSystemProxyInterface* remote_proxy) OVERRIDE;
virtual void RemoveMountPoint(const FilePath& mount_point) OVERRIDE;
@@ -100,22 +109,31 @@ class WEBKIT_STORAGE_EXPORT CrosMountPointProvider
FilePath* virtual_path) OVERRIDE;
private:
- typedef scoped_refptr<fileapi::RemoteFileSystemProxyInterface> RemoteProxy;
- typedef std::map<FilePath::StringType, RemoteProxy> RemoteProxyMap;
-
- fileapi::IsolatedContext* isolated_context() const;
-
- // Represents a map from mount point name to a remote proxy.
- RemoteProxyMap remote_proxy_map_;
-
- // Reverse map for GetVirtualPath.
- std::map<FilePath, FilePath> local_to_virtual_map_;
-
- mutable base::Lock mount_point_map_lock_;
+ fileapi::RemoteFileSystemProxyInterface* GetRemoteProxy(
+ const std::string& mount_name) const;
scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_;
scoped_ptr<FileAccessPermissions> file_access_permissions_;
scoped_ptr<fileapi::LocalFileUtil> local_file_util_;
+
+ // Mount points specific to the owning context.
+ //
+ // Add/Remove MountPoints will affect only these mount points.
+ //
+ // It is legal to have mount points with the same name as in
+ // system_mount_points_. Also, mount point paths may overlap with mount point
+ // paths in system_mount_points_. In both cases mount points in
+ // |mount_points_| will have a priority.
+ // E.g. if |mount_points_| map 'foo1' to '/foo/foo1' and
+ // |file_system_mount_points_| map 'xxx' to '/foo/foo1/xxx', |GetVirtualPaths|
+ // will resolve '/foo/foo1/xxx/yyy' as 'foo1/xxx/yyy' (i.e. the mapping from
+ // |mount_points_| will be used).
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points_;
+
+ // Globally visible mount points. System MountPonts instance should outlive
+ // all CrosMountPointProvider instances, so raw pointer is safe.
+ fileapi::ExternalMountPoints* system_mount_points_;
+
DISALLOW_COPY_AND_ASSIGN(CrosMountPointProvider);
};
diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider_unittest.cc b/webkit/chromeos/fileapi/cros_mount_point_provider_unittest.cc
new file mode 100644
index 0000000..3dfda44
--- /dev/null
+++ b/webkit/chromeos/fileapi/cros_mount_point_provider_unittest.cc
@@ -0,0 +1,325 @@
+// Copyright (c) 2013 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/chromeos/fileapi/cros_mount_point_provider.h"
+
+#include <set>
+
+#include "base/file_path.h"
+#include "googleurl/src/url_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/fileapi/external_mount_points.h"
+#include "webkit/fileapi/file_system_url.h"
+#include "webkit/fileapi/isolated_context.h"
+#include "webkit/quota/mock_special_storage_policy.h"
+
+#define FPL(x) FILE_PATH_LITERAL(x)
+
+namespace {
+
+fileapi::FileSystemURL CreateFileSystemURL(const std::string& extension,
+ const char* path) {
+ return fileapi::FileSystemURL(GURL("chrome-extension://" + extension + "/"),
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath::FromUTF8Unsafe(path));
+}
+
+TEST(CrosMountPointProviderTest, DefaultMountPoints) {
+ scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
+ new quota::MockSpecialStoragePolicy();
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+ chromeos::CrosMountPointProvider provider(
+ storage_policy,
+ mount_points.get(),
+ fileapi::ExternalMountPoints::GetSystemInstance());
+ // By default there should be 4 mount points.
+ std::vector<FilePath> root_dirs = provider.GetRootDirectories();
+ std::set<FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
+ EXPECT_EQ(4u, root_dirs.size());
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/media/removable"))));
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/media/archive"))));
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/usr/share/oem"))));
+ // Fourth mount point is Downloads, but its local path is device specific.
+}
+
+TEST(CrosMountPointProviderTest, GetRootDirectories) {
+ scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
+ new quota::MockSpecialStoragePolicy();
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ chromeos::CrosMountPointProvider provider(
+ storage_policy,
+ mount_points.get(),
+ system_mount_points.get());
+
+ // Register 'local' test mount points.
+ mount_points->RegisterFileSystem("c",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FPL("/a/b/c")));
+ mount_points->RegisterFileSystem("d",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FPL("/b/c/d")));
+
+ // Register system test mount points.
+ system_mount_points->RegisterFileSystem("d",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FPL("/g/c/d")));
+ system_mount_points->RegisterFileSystem("e",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FPL("/g/d/e")));
+
+ std::vector<FilePath> root_dirs = provider.GetRootDirectories();
+ std::set<FilePath> root_dirs_set(root_dirs.begin(), root_dirs.end());
+ EXPECT_EQ(4u, root_dirs.size());
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/a/b/c"))));
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/b/c/d"))));
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/g/c/d"))));
+ EXPECT_TRUE(root_dirs_set.count(FilePath(FPL("/g/d/e"))));
+}
+
+TEST(CrosMountPointProviderTest, MountPointsVisibility) {
+ scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
+ new quota::MockSpecialStoragePolicy();
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<fileapi::ExternalMountPoints> sibling_mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ chromeos::CrosMountPointProvider provider(
+ storage_policy,
+ mount_points.get(),
+ system_mount_points.get());
+
+ // A provider that shares system_mount_points with |provider|.
+ chromeos::CrosMountPointProvider sibling_provider(
+ storage_policy,
+ sibling_mount_points.get(),
+ system_mount_points.get());
+
+ FilePath ignored;
+
+ // Adding empty mount point should fail.
+ EXPECT_FALSE(provider.AddLocalMountPoint(FilePath()));
+
+ // Add mount point to the provider.
+ EXPECT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/a/b/c"))));
+
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/a/b/c"))));
+ // The mount point with the same name exists, but path is different.
+ EXPECT_FALSE(provider.HasMountPoint(FilePath(FPL("/x/a/b/c"))));
+ EXPECT_FALSE(sibling_provider.HasMountPoint(FilePath(FPL("/a/b/c"))));
+ EXPECT_TRUE(mount_points->GetRegisteredPath("c", &ignored));
+ EXPECT_FALSE(system_mount_points->GetRegisteredPath("c", &ignored));
+
+ // Add mount point directly to |mount_points|. It should be seen by
+ // |provider|.
+ EXPECT_TRUE(mount_points->RegisterFileSystem(
+ "d", fileapi::kFileSystemTypeNativeLocal, FilePath(FPL("/b/c/d"))));
+
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/b/c/d"))));
+ EXPECT_FALSE(sibling_provider.HasMountPoint(FilePath(FPL("/b/c/d"))));
+
+ // Add mount point to system mount points.
+ EXPECT_TRUE(system_mount_points->RegisterFileSystem(
+ "e", fileapi::kFileSystemTypeNativeLocal, FilePath(FPL("/g/c/d/e"))));
+
+ EXPECT_FALSE(provider.HasMountPoint(FilePath(FPL("/g/c/d/e"))));
+ EXPECT_FALSE(sibling_provider.HasMountPoint(FilePath(FPL("/g/c/d/e"))));
+
+ // Can't remove system mount point.
+ provider.RemoveMountPoint(FilePath(FPL("/g/c/d/e")));
+ EXPECT_TRUE(system_mount_points->GetRegisteredPath("e", &ignored));
+
+ // Add a mount points whose paths overlap with the system one's.
+ // The same path:
+ EXPECT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/g/c/d/e"))));
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/g/c/d/e"))));
+ provider.RemoveMountPoint(FilePath(FPL("/g/c/d/e")));
+ EXPECT_FALSE(provider.HasMountPoint(FilePath(FPL("/g/c/d/e"))));
+ // Parent path:
+ EXPECT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/g"))));
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/g"))));
+ provider.RemoveMountPoint(FilePath(FPL("/g")));
+ // Child path:
+ EXPECT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/g/c/d/e/f/g"))));
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/g/c/d/e/f/g"))));
+ provider.RemoveMountPoint(FilePath(FPL("/g/c/d/e/f/g")));
+
+ // Add mount point with the same name as a global one. Should succeed.
+ EXPECT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/d/e"))));
+
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/d/e"))));
+
+ // Remove system mount point with the same name as the added one.
+ // Should fail.
+ provider.RemoveMountPoint(FilePath(FPL("/g/c/d/e")));
+
+ EXPECT_TRUE(provider.HasMountPoint(FilePath(FPL("/d/e"))));
+ EXPECT_TRUE(system_mount_points->GetRegisteredPath("e", &ignored));
+
+ // Remove mount point.
+ provider.RemoveMountPoint(FilePath(FPL("/d/e")));
+
+ EXPECT_FALSE(provider.HasMountPoint(FilePath(FPL("/d/e"))));
+}
+
+TEST(CrosMountPointProviderTest, AccessPermissions) {
+ url_util::AddStandardScheme("chrome-extension");
+
+ scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy =
+ new quota::MockSpecialStoragePolicy();
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+ chromeos::CrosMountPointProvider provider(
+ storage_policy,
+ mount_points.get(),
+ system_mount_points.get());
+
+ std::string extension("ddammdhioacbehjngdmkjcjbnfginlla");
+
+ storage_policy->AddFileHandler(extension);
+
+ // Initialize mount points.
+ system_mount_points->RegisterFileSystem("system",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FPL("/g/system")));
+ ASSERT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/media/removable"))));
+ ASSERT_TRUE(provider.AddRestrictedLocalMountPoint(
+ FilePath(FPL("/usr/share/oem"))));
+
+ // Provider specific mount point access.
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "removable/foo")));
+
+ provider.GrantFileAccessToExtension(extension,
+ FilePath(FPL("removable/foo")));
+ EXPECT_TRUE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "removable/foo")));
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "removable/foo1")));
+
+ // System mount point access.
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "system/foo")));
+
+ provider.GrantFileAccessToExtension(extension, FilePath(FPL("system/foo")));
+ EXPECT_TRUE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "system/foo")));
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "system/foo1")));
+
+ // oem is restricted file system.
+ provider.GrantFileAccessToExtension(extension, FilePath(FPL("oem/foo")));
+ // The extension should not be able to access the file even if
+ // GrantFileAccessToExtension was called.
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "oem/foo")));
+
+ provider.GrantFullAccessToExtension(extension);
+ // The extension should be able to access restricted file system after it was
+ // granted full access.
+ EXPECT_TRUE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "oem/foo")));
+ // The extension which was granted full access should be able to access any
+ // path on current file systems.
+ EXPECT_TRUE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "removable/foo1")));
+ EXPECT_TRUE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "system/foo1")));
+
+ // The extension still cannot access new mount points.
+ ASSERT_TRUE(provider.AddLocalMountPoint(FilePath(FPL("/foo/test"))));
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "test_/foo")));
+
+ provider.RevokeAccessForExtension(extension);
+ EXPECT_FALSE(provider.IsAccessAllowed(
+ CreateFileSystemURL(extension, "removable/foo")));
+
+ fileapi::FileSystemURL internal_url(GURL("chrome://foo"),
+ fileapi::kFileSystemTypeExternal,
+ FilePath(FPL("removable/")));
+ // Internal WebUI should have full access.
+ EXPECT_TRUE(provider.IsAccessAllowed(internal_url));
+}
+
+TEST(CrosMountPointProvider, GetVirtualPathConflictWithSystemPoints) {
+ scoped_refptr<quota::MockSpecialStoragePolicy> storage_policy =
+ new quota::MockSpecialStoragePolicy();
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+ scoped_refptr<fileapi::ExternalMountPoints> system_mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+ chromeos::CrosMountPointProvider provider(storage_policy,
+ mount_points.get(),
+ system_mount_points.get());
+
+ const fileapi::FileSystemType type = fileapi::kFileSystemTypeNativeLocal;
+
+ // Provider specific mount points.
+ ASSERT_TRUE(
+ mount_points->RegisterFileSystem("b", type, FilePath(FPL("/a/b"))));
+ ASSERT_TRUE(
+ mount_points->RegisterFileSystem("y", type, FilePath(FPL("/z/y"))));
+ ASSERT_TRUE(
+ mount_points->RegisterFileSystem("n", type, FilePath(FPL("/m/n"))));
+
+ // System mount points
+ ASSERT_TRUE(system_mount_points->RegisterFileSystem(
+ "gb", type, FilePath(FPL("/a/b"))));
+ ASSERT_TRUE(
+ system_mount_points->RegisterFileSystem("gz", type, FilePath(FPL("/z"))));
+ ASSERT_TRUE(system_mount_points->RegisterFileSystem(
+ "gp", type, FilePath(FPL("/m/n/o/p"))));
+
+ struct TestCase {
+ const FilePath::CharType* const local_path;
+ bool success;
+ const FilePath::CharType* const virtual_path;
+ };
+
+ const TestCase kTestCases[] = {
+ // Same paths in both mount points.
+ { FPL("/a/b/c/d"), true, FPL("b/c/d") },
+ // System mount points path more specific.
+ { FPL("/m/n/o/p/r/s"), true, FPL("n/o/p/r/s") },
+ // System mount points path less specific.
+ { FPL("/z/y/x"), true, FPL("y/x") },
+ // Only system mount points path matches.
+ { FPL("/z/q/r/s"), true, FPL("gz/q/r/s") },
+ // No match.
+ { FPL("/foo/xxx"), false, FPL("") },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ // Initialize virtual path with a value.
+ FilePath virtual_path(FPL("/mount"));
+ FilePath local_path(kTestCases[i].local_path);
+ EXPECT_EQ(kTestCases[i].success,
+ provider.GetVirtualPath(local_path, &virtual_path))
+ << "Resolving " << kTestCases[i].local_path;
+
+ // There are no guarantees for |virtual_path| value if |GetVirtualPath|
+ // fails.
+ if (!kTestCases[i].success)
+ continue;
+
+ FilePath expected_virtual_path(kTestCases[i].virtual_path);
+ EXPECT_EQ(expected_virtual_path, virtual_path)
+ << "Resolving " << kTestCases[i].local_path;
+ }
+}
+
+} // namespace
+
diff --git a/webkit/chromeos/fileapi/remote_file_stream_writer.cc b/webkit/chromeos/fileapi/remote_file_stream_writer.cc
index 187a79a..6fcbd65 100644
--- a/webkit/chromeos/fileapi/remote_file_stream_writer.cc
+++ b/webkit/chromeos/fileapi/remote_file_stream_writer.cc
@@ -8,8 +8,8 @@
#include "net/base/net_errors.h"
#include "webkit/blob/local_file_stream_reader.h"
#include "webkit/blob/shareable_file_reference.h"
-#include "webkit/chromeos/fileapi/remote_file_system_proxy.h"
#include "webkit/fileapi/local_file_stream_writer.h"
+#include "webkit/fileapi/remote_file_system_proxy.h"
namespace fileapi {
diff --git a/webkit/chromeos/fileapi/remote_file_system_operation.h b/webkit/chromeos/fileapi/remote_file_system_operation.h
index 3b51707..84a6f7d 100644
--- a/webkit/chromeos/fileapi/remote_file_system_operation.h
+++ b/webkit/chromeos/fileapi/remote_file_system_operation.h
@@ -5,9 +5,9 @@
#ifndef WEBKIT_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
#define WEBKIT_CHROMEOS_FILEAPI_REMOTE_FILE_SYSTEM_OPERATION_H_
-#include "webkit/chromeos/fileapi/remote_file_system_proxy.h"
#include "webkit/fileapi/file_system_operation.h"
#include "webkit/fileapi/file_writer_delegate.h"
+#include "webkit/fileapi/remote_file_system_proxy.h"
namespace base {
class Value;
diff --git a/webkit/fileapi/external_mount_points.cc b/webkit/fileapi/external_mount_points.cc
new file mode 100644
index 0000000..9abba42
--- /dev/null
+++ b/webkit/fileapi/external_mount_points.cc
@@ -0,0 +1,331 @@
+// Copyright (c) 2013 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/external_mount_points.h"
+
+#include "base/file_path.h"
+#include "base/lazy_instance.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "webkit/fileapi/remote_file_system_proxy.h"
+
+namespace {
+
+// Normalizes file path so it has normalized separators and ends with exactly
+// one separator. Paths have to be normalized this way for use in
+// GetVirtualPath method. Separators cannot be completely stripped, or
+// GetVirtualPath could not working in some edge cases.
+// For example, /a/b/c(1)/d would be erroneously resolved as c/d if the
+// following mount points were registered: "/a/b/c", "/a/b/c(1)". (Note:
+// "/a/b/c" < "/a/b/c(1)" < "/a/b/c/").
+FilePath NormalizeFilePath(const FilePath& path) {
+ if (path.empty())
+ return path;
+
+ FilePath::StringType path_str = path.StripTrailingSeparators().value();
+ if (!FilePath::IsSeparator(path_str[path_str.length() - 1]))
+ path_str.append(FILE_PATH_LITERAL("/"));
+
+ return FilePath(path_str).NormalizePathSeparators();
+}
+
+// Wrapper around ref-counted ExternalMountPoints that will be used to lazily
+// create and initialize LazyInstance system ExternalMountPoints.
+class SystemMountPointsLazyWrapper {
+ public:
+ SystemMountPointsLazyWrapper()
+ : system_mount_points_(fileapi::ExternalMountPoints::CreateRefCounted()) {
+ RegisterDefaultMountPoints();
+ }
+
+ ~SystemMountPointsLazyWrapper() {}
+
+ fileapi::ExternalMountPoints* get() {
+ return system_mount_points_.get();
+ }
+
+ private:
+ void RegisterDefaultMountPoints() {
+#if defined(OS_CHROMEOS)
+ // Add default system mount points.
+ system_mount_points_->RegisterFileSystem(
+ "archive",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FILE_PATH_LITERAL("/media/archive")));
+ system_mount_points_->RegisterFileSystem(
+ "removable",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FILE_PATH_LITERAL("/media/removable")));
+ system_mount_points_->RegisterFileSystem(
+ "oem",
+ fileapi::kFileSystemTypeRestrictedNativeLocal,
+ FilePath(FILE_PATH_LITERAL("/usr/share/oem")));
+
+ // TODO(tbarzic): Move this out of here.
+ FilePath home_path;
+ if (PathService::Get(base::DIR_HOME, &home_path)) {
+ system_mount_points_->RegisterFileSystem(
+ "Downloads",
+ fileapi::kFileSystemTypeNativeLocal,
+ home_path.AppendASCII("Downloads"));
+ }
+#endif // defined(OS_CHROMEOS)
+ }
+
+ scoped_refptr<fileapi::ExternalMountPoints> system_mount_points_;
+};
+
+base::LazyInstance<SystemMountPointsLazyWrapper>::Leaky
+ g_external_mount_points = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+namespace fileapi {
+
+class ExternalMountPoints::Instance {
+ public:
+ Instance(FileSystemType type,
+ const FilePath& path,
+ RemoteFileSystemProxyInterface* remote_proxy);
+
+ ~Instance();
+
+ FileSystemType type() const { return type_; }
+ const FilePath& path() const { return path_; }
+ RemoteFileSystemProxyInterface* remote_proxy() const {
+ return remote_proxy_.get();
+ }
+
+ private:
+ const FileSystemType type_;
+ const FilePath path_;
+
+ // For file systems that have a remote file system proxy.
+ scoped_refptr<RemoteFileSystemProxyInterface> remote_proxy_;
+
+ DISALLOW_COPY_AND_ASSIGN(Instance);
+};
+
+ExternalMountPoints::Instance::Instance(FileSystemType type,
+ const FilePath& path,
+ RemoteFileSystemProxyInterface* proxy)
+ : type_(type),
+ path_(path.StripTrailingSeparators()),
+ remote_proxy_(proxy) {
+ DCHECK(!proxy || (kFileSystemTypeDrive == type_));
+}
+
+ExternalMountPoints::Instance::~Instance() {}
+
+//--------------------------------------------------------------------------
+
+// static
+ExternalMountPoints* ExternalMountPoints::GetSystemInstance() {
+ return g_external_mount_points.Pointer()->get();
+}
+
+// static
+scoped_refptr<ExternalMountPoints> ExternalMountPoints::CreateRefCounted() {
+ return new ExternalMountPoints();
+}
+
+bool ExternalMountPoints::RegisterFileSystem(
+ const std::string& mount_name,
+ FileSystemType type,
+ const FilePath& path) {
+ return RegisterRemoteFileSystem(mount_name, type, NULL, path);
+}
+
+bool ExternalMountPoints::RegisterRemoteFileSystem(
+ const std::string& mount_name,
+ FileSystemType type,
+ RemoteFileSystemProxyInterface* remote_proxy,
+ const FilePath& path_in) {
+ base::AutoLock locker(lock_);
+
+ FilePath path = NormalizeFilePath(path_in);
+ if (!ValidateNewMountPoint(mount_name, path))
+ return false;
+
+ instance_map_[mount_name] = new Instance(type, path, remote_proxy);
+ if (!path.empty())
+ path_to_name_map_.insert(std::make_pair(path, mount_name));
+ return true;
+}
+
+bool ExternalMountPoints::RevokeFileSystem(const std::string& mount_name) {
+ base::AutoLock locker(lock_);
+ NameToInstance::iterator found = instance_map_.find(mount_name);
+ if (found == instance_map_.end())
+ return false;
+ Instance* instance = found->second;
+ path_to_name_map_.erase(NormalizeFilePath(instance->path()));
+ delete found->second;
+ instance_map_.erase(found);
+ return true;
+}
+
+bool ExternalMountPoints::GetRegisteredPath(
+ const std::string& filesystem_id, FilePath* path) const {
+ DCHECK(path);
+ base::AutoLock locker(lock_);
+ NameToInstance::const_iterator found = instance_map_.find(filesystem_id);
+ if (found == instance_map_.end())
+ return false;
+ *path = found->second->path();
+ return true;
+}
+
+bool ExternalMountPoints::CrackVirtualPath(const FilePath& virtual_path,
+ std::string* mount_name,
+ FileSystemType* type,
+ FilePath* path) const {
+ DCHECK(mount_name);
+ DCHECK(path);
+
+ // The path should not contain any '..' references.
+ if (virtual_path.ReferencesParent())
+ return false;
+
+ // The virtual_path should comprise of <mount_name> and <relative_path> parts.
+ std::vector<FilePath::StringType> components;
+ virtual_path.GetComponents(&components);
+ if (components.size() < 1)
+ return false;
+
+ std::vector<FilePath::StringType>::iterator component_iter =
+ components.begin();
+ std::string maybe_mount_name = FilePath(*component_iter++).MaybeAsASCII();
+ if (maybe_mount_name.empty())
+ return false;
+
+ FilePath cracked_path;
+ {
+ base::AutoLock locker(lock_);
+ NameToInstance::const_iterator found_instance =
+ instance_map_.find(maybe_mount_name);
+ if (found_instance == instance_map_.end())
+ return false;
+
+ *mount_name = maybe_mount_name;
+ const Instance* instance = found_instance->second;
+ if (type)
+ *type = instance->type();
+ cracked_path = instance->path();
+ }
+
+ for (; component_iter != components.end(); ++component_iter)
+ cracked_path = cracked_path.Append(*component_iter);
+ *path = cracked_path;
+ return true;
+}
+
+RemoteFileSystemProxyInterface* ExternalMountPoints::GetRemoteFileSystemProxy(
+ const std::string& mount_name) const {
+ base::AutoLock locker(lock_);
+ NameToInstance::const_iterator found = instance_map_.find(mount_name);
+ if (found == instance_map_.end())
+ return NULL;
+ return found->second->remote_proxy();
+}
+
+void ExternalMountPoints::AddMountPointInfosTo(
+ std::vector<MountPointInfo>* mount_points) const {
+ base::AutoLock locker(lock_);
+ DCHECK(mount_points);
+ for (NameToInstance::const_iterator iter = instance_map_.begin();
+ iter != instance_map_.end(); ++iter) {
+ mount_points->push_back(MountPointInfo(iter->first, iter->second->path()));
+ }
+}
+
+bool ExternalMountPoints::GetVirtualPath(const FilePath& path_in,
+ FilePath* virtual_path) {
+ DCHECK(virtual_path);
+
+ base::AutoLock locker(lock_);
+
+ FilePath path = NormalizeFilePath(path_in);
+ std::map<FilePath, std::string>::reverse_iterator iter(
+ path_to_name_map_.upper_bound(path));
+ if (iter == path_to_name_map_.rend())
+ return false;
+
+ *virtual_path = CreateVirtualRootPath(iter->second);
+ if (iter->first == path)
+ return true;
+ return iter->first.AppendRelativePath(path, virtual_path);
+}
+
+FilePath ExternalMountPoints::CreateVirtualRootPath(
+ const std::string& mount_name) const {
+ return FilePath().AppendASCII(mount_name);
+}
+
+ExternalMountPoints::ExternalMountPoints() {}
+
+ExternalMountPoints::~ExternalMountPoints() {
+ STLDeleteContainerPairSecondPointers(instance_map_.begin(),
+ instance_map_.end());
+}
+
+bool ExternalMountPoints::ValidateNewMountPoint(const std::string& mount_name,
+ const FilePath& path) {
+ lock_.AssertAcquired();
+
+ // Mount name must not be empty.
+ if (mount_name.empty())
+ return false;
+
+ // Verify there is no registered mount point with the same name.
+ NameToInstance::iterator found = instance_map_.find(mount_name);
+ if (found != instance_map_.end())
+ return false;
+
+ // Allow empty paths.
+ if (path.empty())
+ return true;
+
+ // Verify path is legal.
+ if (path.ReferencesParent() || !path.IsAbsolute())
+ return false;
+
+ // Check there the new path does not overlap with one of the existing ones.
+ std::map<FilePath, std::string>::reverse_iterator potential_parent(
+ path_to_name_map_.upper_bound(path));
+ if (potential_parent != path_to_name_map_.rend()) {
+ if (potential_parent->first == path ||
+ potential_parent->first.IsParent(path)) {
+ return false;
+ }
+ }
+
+ std::map<FilePath, std::string>::iterator potential_child =
+ path_to_name_map_.upper_bound(path);
+ if (potential_child == path_to_name_map_.end())
+ return true;
+ return !(potential_child->first == path) &&
+ !path.IsParent(potential_child->first);
+}
+
+ScopedExternalFileSystem::ScopedExternalFileSystem(
+ const std::string& mount_name,
+ FileSystemType type,
+ const FilePath& path)
+ : mount_name_(mount_name) {
+ ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ mount_name, type, path);
+}
+
+FilePath ScopedExternalFileSystem::GetVirtualRootPath() const {
+ return ExternalMountPoints::GetSystemInstance()->
+ CreateVirtualRootPath(mount_name_);
+}
+
+ScopedExternalFileSystem::~ScopedExternalFileSystem() {
+ ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(mount_name_);
+}
+
+} // namespace fileapi
+
diff --git a/webkit/fileapi/external_mount_points.h b/webkit/fileapi/external_mount_points.h
new file mode 100644
index 0000000..fe8d4d0
--- /dev/null
+++ b/webkit/fileapi/external_mount_points.h
@@ -0,0 +1,155 @@
+// Copyright (c) 2013 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.
+
+#ifndef WEBKIT_FILEAPI_EXTERNAL_MOUNT_POINTS_H_
+#define WEBKIT_FILEAPI_EXTERNAL_MOUNT_POINTS_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "webkit/fileapi/file_system_types.h"
+#include "webkit/fileapi/mount_points.h"
+#include "webkit/storage/webkit_storage_export.h"
+
+class FilePath;
+
+namespace fileapi {
+class RemoteFileSystemProxyInterface;
+}
+
+namespace fileapi {
+
+// Manages external filesystem namespaces that are identified by 'mount name'
+// and are persisted until RevokeFileSystem is called.
+// Files in an external filesystem are identified by a filesystem URL like:
+//
+// filesystem:<origin>/external/<mount_name>/relative/path
+//
+class WEBKIT_STORAGE_EXPORT ExternalMountPoints
+ : public base::RefCountedThreadSafe<ExternalMountPoints>,
+ public MountPoints {
+ public:
+ static ExternalMountPoints* GetSystemInstance();
+ static scoped_refptr<ExternalMountPoints> CreateRefCounted();
+
+ // Registers a new named external filesystem.
+ // The |path| is registered as the root path of the mount point which
+ // is identified by a URL "filesystem:.../external/mount_name".
+ //
+ // For example, if the path "/media/removable" is registered with
+ // the mount_name "removable", a filesystem URL like
+ // "filesystem:.../external/removable/a/b" will be resolved as
+ // "/media/removable/a/b".
+ //
+ // The |mount_name| should NOT contain a path separator '/'.
+ // Returns false if the given name is already registered.
+ //
+ // Overlapping mount points in a single MountPoints instance are not allowed.
+ // Adding mount point whose path overlaps with an existing mount point will
+ // fail.
+ //
+ // If not empty, |path| must be absolute. It is allowed for the path to be
+ // empty, but |GetVirtualPath| will not work for those mount points.
+ //
+ // An external file system registered by this method can be revoked
+ // by calling RevokeFileSystem with |mount_name|.
+ bool RegisterFileSystem(const std::string& mount_name,
+ FileSystemType type,
+ const FilePath& path);
+
+ // Same as |RegisterExternalFileSystem|, but also registers a remote file
+ // system proxy for the file system.
+ bool RegisterRemoteFileSystem(const std::string& mount_name,
+ FileSystemType type,
+ RemoteFileSystemProxyInterface* remote_proxy,
+ const FilePath& path);
+
+ // MountPoints overrides.
+ virtual bool RevokeFileSystem(const std::string& mount_name) OVERRIDE;
+ virtual bool GetRegisteredPath(const std::string& mount_name,
+ FilePath* path) const OVERRIDE;
+ virtual bool CrackVirtualPath(const FilePath& virtual_path,
+ std::string* mount_name,
+ FileSystemType* type,
+ FilePath* path) const OVERRIDE;
+
+ // Retrieves the remote file system proxy for the registered file system.
+ // Returns NULL if there is no file system with the given name, or if the file
+ // system does not have a remote file system proxy.
+ RemoteFileSystemProxyInterface* GetRemoteFileSystemProxy(
+ const std::string& mount_name) const;
+
+ // Returns a list of registered MountPointInfos (of <mount_name, path>).
+ void AddMountPointInfosTo(std::vector<MountPointInfo>* mount_points) const;
+
+ // Converts a path on a registered file system to virtual path relative to the
+ // file system root. E.g. if 'Downloads' file system is mapped to
+ // '/usr/local/home/Downloads', and |absolute| path is set to
+ // '/usr/local/home/Downloads/foo', the method will set |virtual_path| to
+ // 'Downloads/foo'.
+ // Returns false if the path cannot be resolved (e.g. if the path is not
+ // part of any registered filesystem).
+ //
+ // Returned virtual_path will have normalized path separators.
+ bool GetVirtualPath(const FilePath& absolute_path, FilePath* virtual_path);
+
+ // Returns the virtual root path that looks like /<mount_name>.
+ FilePath CreateVirtualRootPath(const std::string& mount_name) const;
+
+ private:
+ friend class base::RefCountedThreadSafe<ExternalMountPoints>;
+
+ // Represents each file system instance (defined in the .cc).
+ class Instance;
+
+ typedef std::map<std::string, Instance*> NameToInstance;
+
+ // Reverse map from registered path to its corresponding mount name.
+ typedef std::map<FilePath, std::string> PathToName;
+
+ // Use |GetSystemInstance| of |CreateRefCounted| to get an instance.
+ ExternalMountPoints();
+ virtual ~ExternalMountPoints();
+
+ // Performs sanity checks on the new mount point.
+ // Checks the following:
+ // - there is no registered mount point with mount_name
+ // - path does not contain a reference to a parent
+ // - path is absolute
+ // - path does not overlap with an existing mount point path.
+ //
+ // |lock_| should be taken before calling this method.
+ bool ValidateNewMountPoint(const std::string& mount_name,
+ const FilePath& path);
+
+ // This lock needs to be obtained when accessing the instance_map_.
+ mutable base::Lock lock_;
+
+ NameToInstance instance_map_;
+ PathToName path_to_name_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalMountPoints);
+};
+
+// Registers a scoped external filesystem which gets revoked when it scopes out.
+class WEBKIT_STORAGE_EXPORT ScopedExternalFileSystem {
+ public:
+ ScopedExternalFileSystem(const std::string& mount_name,
+ FileSystemType type,
+ const FilePath& path);
+ ~ScopedExternalFileSystem();
+
+ FilePath GetVirtualRootPath() const;
+
+ private:
+ const std::string mount_name_;
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_EXTERNAL_MOUNT_POINTS_H_
+
diff --git a/webkit/fileapi/external_mount_points_unittest.cc b/webkit/fileapi/external_mount_points_unittest.cc
new file mode 100644
index 0000000..379d146
--- /dev/null
+++ b/webkit/fileapi/external_mount_points_unittest.cc
@@ -0,0 +1,227 @@
+// Copyright (c) 2013 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/external_mount_points.h"
+
+#include <string>
+
+#include "base/file_path.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define FPL FILE_PATH_LITERAL
+
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+#define DRIVE FPL("C:")
+#else
+#define DRIVE
+#endif
+
+namespace {
+
+TEST(ExternalMountPointsTest, AddMountPoint) {
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ struct TestCase {
+ // The mount point's name.
+ const char* const name;
+ // The mount point's path.
+ const FilePath::CharType* const path;
+ // Whether the mount point registration should succeed.
+ bool success;
+ // Path returned by GetRegisteredPath. NULL if the method is expected to
+ // fail.
+ const FilePath::CharType* const registered_path;
+ };
+
+ const TestCase kTestCases[] = {
+ // Valid mount point.
+ { "test", DRIVE FPL("/foo/test"), true, DRIVE FPL("/foo/test") },
+ // Valid mount point with only one path component.
+ { "bbb", DRIVE FPL("/bbb"), true, DRIVE FPL("/bbb") },
+ // Existing mount point path is substring of the mount points path.
+ { "test11", DRIVE FPL("/foo/test11"), true, DRIVE FPL("/foo/test11") },
+ // Path substring of an existing path.
+ { "test1", DRIVE FPL("/foo/test1"), true, DRIVE FPL("/foo/test1") },
+ // Empty mount point name and path.
+ { "", DRIVE FPL(""), false, NULL },
+ // Empty mount point name.
+ { "", DRIVE FPL("/ddd"), false, NULL },
+ // Empty mount point path.
+ { "empty_path", FPL(""), true, FPL("") },
+ // Name different from path's base name.
+ { "not_base_name", DRIVE FPL("/x/y/z"), true, DRIVE FPL("/x/y/z") },
+ // References parent.
+ { "invalid", DRIVE FPL("../foo/invalid"), false, NULL },
+ // Relative path.
+ { "relative", DRIVE FPL("foo/relative"), false, NULL },
+ // Existing mount point path.
+ { "path_exists", DRIVE FPL("/foo/test"), false, NULL },
+ // Mount point with the same name exists.
+ { "test", DRIVE FPL("/foo/a/test_name_exists"), false,
+ DRIVE FPL("/foo/test") },
+ // Child of an existing mount point.
+ { "a1", DRIVE FPL("/foo/test/a"), false, NULL },
+ // Parent of an existing mount point.
+ { "foo1", DRIVE FPL("/foo"), false, NULL },
+ // Bit bigger depth.
+ { "g", DRIVE FPL("/foo/a/b/c/d/e/f/g"), true,
+ DRIVE FPL("/foo/a/b/c/d/e/f/g") },
+ // Sibling mount point (with similar name) exists.
+ { "ff", DRIVE FPL("/foo/a/b/c/d/e/ff"), true,
+ DRIVE FPL("/foo/a/b/c/d/e/ff") },
+ // Lexicographically last among existing mount points.
+ { "yyy", DRIVE FPL("/zzz/yyy"), true, DRIVE FPL("/zzz/yyy") },
+ // Parent of the lexicographically last mount point.
+ { "zzz1", DRIVE FPL("/zzz"), false, NULL },
+ // Child of the lexicographically last mount point.
+ { "xxx1", DRIVE FPL("/zzz/yyy/xxx"), false, NULL },
+ // Lexicographically first among existing mount points.
+ { "b", DRIVE FPL("/a/b"), true, DRIVE FPL("/a/b") },
+ // Parent of lexicographically first mount point.
+ { "a2", DRIVE FPL("/a"), false, NULL },
+ // Child of lexicographically last mount point.
+ { "c1", DRIVE FPL("/a/b/c"), false, NULL },
+ // Parent to all of the mount points.
+ { "root", DRIVE FPL("/"), false, NULL },
+ // Path contains .. component.
+ { "funky", DRIVE FPL("/tt/fun/../funky"), false, NULL },
+ // Windows separators.
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ { "win", DRIVE FPL("\\try\\separators\\win"), true,
+ DRIVE FPL("\\try\\separators\\win") },
+ { "win1", DRIVE FPL("\\try/separators\\win1"), true,
+ DRIVE FPL("\\try/separators\\win1") },
+ { "win2", DRIVE FPL("\\try/separators\\win"), false, NULL },
+#else
+ { "win", DRIVE FPL("\\separators\\win"), false, NULL },
+ { "win1", DRIVE FPL("\\try/separators\\win1"), false, NULL },
+#endif
+ // Win separators, but relative path.
+ { "win2", DRIVE FPL("try\\separators\\win2"), false, NULL },
+ };
+
+ // Test adding mount points.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ EXPECT_EQ(kTestCases[i].success,
+ mount_points->RegisterFileSystem(
+ kTestCases[i].name,
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(kTestCases[i].path)))
+ << "Adding mount point: " << kTestCases[i].name << " with path "
+ << kTestCases[i].path;
+ }
+
+ // Test that final mount point presence state is as expected.
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ FilePath found_path;
+ EXPECT_EQ(kTestCases[i].registered_path != NULL,
+ mount_points->GetRegisteredPath(kTestCases[i].name, &found_path))
+ << "Test case: " << i;
+
+ if (kTestCases[i].registered_path) {
+ FilePath expected_path(kTestCases[i].registered_path);
+ EXPECT_EQ(expected_path.NormalizePathSeparators(), found_path);
+ }
+ }
+}
+
+TEST(ExternalMountPointsTest, GetVirtualPath) {
+ scoped_refptr<fileapi::ExternalMountPoints> mount_points(
+ fileapi::ExternalMountPoints::CreateRefCounted());
+
+ mount_points->RegisterFileSystem("c",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(DRIVE FPL("/a/b/c")));
+ // Note that "/a/b/c" < "/a/b/c(1)" < "/a/b/c/".
+ mount_points->RegisterFileSystem("c(1)",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(DRIVE FPL("/a/b/c(1)")));
+ mount_points->RegisterFileSystem("x",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(DRIVE FPL("/z/y/x")));
+ mount_points->RegisterFileSystem("o",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(DRIVE FPL("/m/n/o")));
+ // A mount point whose name does not match its path base name.
+ mount_points->RegisterFileSystem("mount",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(DRIVE FPL("/root/foo")));
+ // A mount point with an empty path.
+ mount_points->RegisterFileSystem("empty_path",
+ fileapi::kFileSystemTypeNativeLocal,
+ FilePath(FPL("")));
+
+ struct TestCase {
+ const FilePath::CharType* const local_path;
+ bool success;
+ const FilePath::CharType* const virtual_path;
+ };
+
+ const TestCase kTestCases[] = {
+ // Empty path.
+ { FPL(""), false, FPL("") },
+ // No registered mount point (but is parent to a mount point).
+ { DRIVE FPL("/a/b"), false, FPL("") },
+ // No registered mount point (but is parent to a mount point).
+ { DRIVE FPL("/z/y"), false, FPL("") },
+ // No registered mount point (but is parent to a mount point).
+ { DRIVE FPL("/m/n"), false, FPL("") },
+ // No registered mount point.
+ { DRIVE FPL("/foo/mount"), false, FPL("") },
+ // An existing mount point path is substring.
+ { DRIVE FPL("/a/b/c1"), false, FPL("") },
+ // No leading /.
+ { DRIVE FPL("a/b/c"), false, FPL("") },
+ // Sibling to a root path.
+ { DRIVE FPL("/a/b/d/e"), false, FPL("") },
+ // Sibling to a root path.
+ { DRIVE FPL("/z/y/v/u"), false, FPL("") },
+ // Sibling to a root path.
+ { DRIVE FPL("/m/n/p/q"), false, FPL("") },
+ // Mount point root path.
+ { DRIVE FPL("/a/b/c"), true, FPL("c") },
+ // Mount point root path.
+ { DRIVE FPL("/z/y/x"), true, FPL("x") },
+ // Mount point root path.
+ { DRIVE FPL("/m/n/o"), true, FPL("o") },
+ // Mount point child path.
+ { DRIVE FPL("/a/b/c/d/e"), true, FPL("c/d/e") },
+ // Mount point child path.
+ { DRIVE FPL("/z/y/x/v/u"), true, FPL("x/v/u") },
+ // Mount point child path.
+ { DRIVE FPL("/m/n/o/p/q"), true, FPL("o/p/q") },
+ // Name doesn't match mount point path base name.
+ { DRIVE FPL("/root/foo/a/b/c"), true, FPL("mount/a/b/c") },
+ { DRIVE FPL("/root/foo"), true, FPL("mount") },
+ // Mount point contains character whose ASCII code is smaller than file path
+ // separator's.
+ { DRIVE FPL("/a/b/c(1)/d/e"), true, FPL("c(1)/d/e") },
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+ // Path with win separators mixed in.
+ { DRIVE FPL("/a\\b\\c/d"), true, FPL("c/d") },
+#endif
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
+ // Initialize virtual path with a value.
+ FilePath virtual_path(DRIVE FPL("/mount"));
+ FilePath local_path(kTestCases[i].local_path);
+ EXPECT_EQ(kTestCases[i].success,
+ mount_points->GetVirtualPath(local_path, &virtual_path))
+ << "Resolving " << kTestCases[i].local_path;
+
+ // There are no guarantees for |virtual_path| value if |GetVirtualPath|
+ // fails.
+ if (!kTestCases[i].success)
+ continue;
+
+ FilePath expected_virtual_path(kTestCases[i].virtual_path);
+ EXPECT_EQ(expected_virtual_path.NormalizePathSeparators(), virtual_path)
+ << "Resolving " << kTestCases[i].local_path;
+ }
+}
+
+} // namespace
+
diff --git a/webkit/fileapi/file_system_context.cc b/webkit/fileapi/file_system_context.cc
index 93a0aa7..bf285ea 100644
--- a/webkit/fileapi/file_system_context.cc
+++ b/webkit/fileapi/file_system_context.cc
@@ -8,6 +8,7 @@
#include "base/stl_util.h"
#include "base/single_thread_task_runner.h"
#include "googleurl/src/gurl.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/file_system_file_util.h"
#include "webkit/fileapi/file_system_operation.h"
#include "webkit/fileapi/file_system_options.h"
@@ -75,7 +76,11 @@ FileSystemContext::FileSystemContext(
}
#if defined(OS_CHROMEOS)
external_provider_.reset(
- new chromeos::CrosMountPointProvider(special_storage_policy));
+ new chromeos::CrosMountPointProvider(
+ special_storage_policy,
+ // TODO(tbarzic): Switch this to |external_mount_points_|.
+ fileapi::ExternalMountPoints::GetSystemInstance(),
+ fileapi::ExternalMountPoints::GetSystemInstance()));
#endif
}
@@ -243,6 +248,7 @@ FileSystemOperation* FileSystemContext::CreateFileSystemOperation(
*error_code = base::PLATFORM_FILE_ERROR_INVALID_URL;
return NULL;
}
+
FileSystemMountPointProvider* mount_point_provider =
GetMountPointProvider(url.type());
if (!mount_point_provider) {
diff --git a/webkit/fileapi/file_system_mount_point_provider.h b/webkit/fileapi/file_system_mount_point_provider.h
index 4f0950e..24c00fe 100644
--- a/webkit/fileapi/file_system_mount_point_provider.h
+++ b/webkit/fileapi/file_system_mount_point_provider.h
@@ -141,14 +141,14 @@ class ExternalFileSystemMountPointProvider
virtual void RevokeAccessForExtension(
const std::string& extension_id) = 0;
// Checks if a given |mount_point| already exists.
- virtual bool HasMountPoint(const FilePath& mount_point) = 0;
+ virtual bool HasMountPoint(const FilePath& mount_point) const = 0;
// Adds a new local mount point.
- virtual void AddLocalMountPoint(const FilePath& mount_point) = 0;
+ virtual bool AddLocalMountPoint(const FilePath& mount_point) = 0;
// Adds a new local mount point that will be accessible only by extensions
// that have been granted full acess for all external file systems.
- virtual void AddRestrictedLocalMountPoint(const FilePath& mount_point) = 0;
+ virtual bool AddRestrictedLocalMountPoint(const FilePath& mount_point) = 0;
// Adds a new remote mount point.
- virtual void AddRemoteMountPoint(
+ virtual bool AddRemoteMountPoint(
const FilePath& mount_point,
RemoteFileSystemProxyInterface* remote_proxy) = 0;
// Removes a mount point.
diff --git a/webkit/fileapi/file_system_url.cc b/webkit/fileapi/file_system_url.cc
index 9e2fdf5..b69eda1 100644
--- a/webkit/fileapi/file_system_url.cc
+++ b/webkit/fileapi/file_system_url.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/string_util.h"
#include "net/base/escape.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/isolated_context.h"
@@ -158,7 +159,11 @@ void FileSystemURL::MayCrackIsolatedPath() {
if (is_valid_ && IsolatedContext::IsIsolatedType(type_)) {
// If the type is isolated, crack the path further to get the 'real'
// filesystem type and path.
- is_valid_ = IsolatedContext::GetInstance()->CrackIsolatedPath(
+ is_valid_ = ExternalMountPoints::GetSystemInstance()->CrackVirtualPath(
+ virtual_path_, &filesystem_id_, &type_, &path_);
+ if (is_valid_)
+ return;
+ is_valid_ = IsolatedContext::GetInstance()->CrackVirtualPath(
virtual_path_, &filesystem_id_, &type_, &path_);
}
}
diff --git a/webkit/fileapi/file_system_url_unittest.cc b/webkit/fileapi/file_system_url_unittest.cc
index c6608cc..c1c01a3 100644
--- a/webkit/fileapi/file_system_url_unittest.cc
+++ b/webkit/fileapi/file_system_url_unittest.cc
@@ -7,6 +7,7 @@
#include "base/file_path.h"
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/isolated_context.h"
@@ -14,6 +15,12 @@
#define FPL FILE_PATH_LITERAL
+#if defined(FILE_PATH_USES_DRIVE_LETTERS)
+#define DRIVE FPL("C:")
+#else
+#define DRIVE FPL("/a/")
+#endif
+
namespace fileapi {
namespace {
@@ -214,8 +221,10 @@ TEST(FileSystemURLTest, DebugString) {
NormalizedUTF8Path(kPath),
kURL1.DebugString());
- const FilePath kRoot(FPL("root"));
- ScopedExternalFileSystem scoped_fs("foo", kFileSystemTypeNativeLocal, kRoot);
+ const FilePath kRoot(DRIVE FPL("/root"));
+ ScopedExternalFileSystem scoped_fs("foo",
+ kFileSystemTypeNativeLocal,
+ kRoot.NormalizePathSeparators());
const FileSystemURL kURL2(kOrigin, kFileSystemTypeExternal,
scoped_fs.GetVirtualRootPath().Append(kPath));
EXPECT_EQ("filesystem:http://example.com/external/" +
diff --git a/webkit/fileapi/isolated_context.cc b/webkit/fileapi/isolated_context.cc
index 057d508..1433e72 100644
--- a/webkit/fileapi/isolated_context.cc
+++ b/webkit/fileapi/isolated_context.cc
@@ -42,7 +42,7 @@ FilePath::StringType GetRegisterNameForPath(const FilePath& path) {
bool IsSinglePathIsolatedFileSystem(FileSystemType type) {
switch (type) {
// As of writing dragged file system is the only filesystem
- // which could have multiple toplevel paths.
+ // which could have multiple top-level paths.
case kFileSystemTypeDragged:
return false;
@@ -57,15 +57,10 @@ bool IsSinglePathIsolatedFileSystem(FileSystemType type) {
return true;
}
-} // namespace
-
static base::LazyInstance<IsolatedContext>::Leaky g_isolated_context =
LAZY_INSTANCE_INITIALIZER;
-IsolatedContext::FileInfo::FileInfo() {}
-IsolatedContext::FileInfo::FileInfo(
- const std::string& name, const FilePath& path)
- : name(name), path(path) {}
+} // namespace
IsolatedContext::FileInfoSet::FileInfoSet() {}
IsolatedContext::FileInfoSet::~FileInfoSet() {}
@@ -78,7 +73,8 @@ bool IsolatedContext::FileInfoSet::AddPath(
FilePath::StringType name = GetRegisterNameForPath(path);
std::string utf8name = FilePath(name).AsUTF8Unsafe();
FilePath normalized_path = path.NormalizePathSeparators();
- bool inserted = fileset_.insert(FileInfo(utf8name, normalized_path)).second;
+ bool inserted =
+ fileset_.insert(MountPointInfo(utf8name, normalized_path)).second;
if (!inserted) {
int suffix = 1;
std::string basepart = FilePath(name).RemoveExtension().AsUTF8Unsafe();
@@ -87,7 +83,8 @@ bool IsolatedContext::FileInfoSet::AddPath(
utf8name = base::StringPrintf("%s (%d)", basepart.c_str(), suffix++);
if (!ext.empty())
utf8name.append(ext);
- inserted = fileset_.insert(FileInfo(utf8name, normalized_path)).second;
+ inserted =
+ fileset_.insert(MountPointInfo(utf8name, normalized_path)).second;
}
}
if (registered_name)
@@ -100,34 +97,29 @@ bool IsolatedContext::FileInfoSet::AddPathWithName(
// The given path should not contain any '..' and should be absolute.
if (path.ReferencesParent() || !path.IsAbsolute())
return false;
- return fileset_.insert(FileInfo(name, path.NormalizePathSeparators())).second;
+ return fileset_.insert(
+ MountPointInfo(name, path.NormalizePathSeparators())).second;
}
//--------------------------------------------------------------------------
class IsolatedContext::Instance {
public:
- typedef FileSystemType MountType;
-
// For a single-path isolated file system, which could be registered by
// IsolatedContext::RegisterFileSystemForPath().
// Most of isolated file system contexts should be of this type.
- Instance(FileSystemType type, const FileInfo& file_info);
+ Instance(FileSystemType type, const MountPointInfo& file_info);
// For a multi-paths isolated file system. As of writing only file system
// type which could have multi-paths is Dragged file system, and
// could be registered by IsolatedContext::RegisterDraggedFileSystem().
- Instance(FileSystemType type, const std::set<FileInfo>& files);
-
- // For a single-path external file system.
- Instance(FileSystemType type, const FilePath& path);
+ Instance(FileSystemType type, const std::set<MountPointInfo>& files);
~Instance();
- MountType mount_type() const { return mount_type_; }
FileSystemType type() const { return type_; }
- const FileInfo& file_info() const { return file_info_; }
- const std::set<FileInfo>& files() const { return files_; }
+ const MountPointInfo& file_info() const { return file_info_; }
+ const std::set<MountPointInfo>& files() const { return files_; }
int ref_counts() const { return ref_counts_; }
void AddRef() { ++ref_counts_; }
@@ -139,14 +131,13 @@ class IsolatedContext::Instance {
bool IsSinglePathInstance() const;
private:
- const MountType mount_type_;
const FileSystemType type_;
// For single-path instance.
- const FileInfo file_info_;
+ const MountPointInfo file_info_;
// For multiple-path instance (e.g. dragged file system).
- const std::set<FileInfo> files_;
+ const std::set<MountPointInfo> files_;
// Reference counts. Note that an isolated filesystem is created with ref==0
// and will get deleted when the ref count reaches <=0.
@@ -156,32 +147,21 @@ class IsolatedContext::Instance {
};
IsolatedContext::Instance::Instance(FileSystemType type,
- const FileInfo& file_info)
- : mount_type_(kFileSystemTypeIsolated),
- type_(type),
+ const MountPointInfo& file_info)
+ : type_(type),
file_info_(file_info),
ref_counts_(0) {
DCHECK(IsSinglePathIsolatedFileSystem(type_));
}
IsolatedContext::Instance::Instance(FileSystemType type,
- const std::set<FileInfo>& files)
- : mount_type_(kFileSystemTypeIsolated),
- type_(type),
+ const std::set<MountPointInfo>& files)
+ : type_(type),
files_(files),
ref_counts_(0) {
DCHECK(!IsSinglePathIsolatedFileSystem(type_));
}
-IsolatedContext::Instance::Instance(FileSystemType type,
- const FilePath& path)
- : mount_type_(kFileSystemTypeExternal),
- type_(type),
- file_info_(FileInfo("", path)),
- ref_counts_(0) {
- DCHECK(IsSinglePathIsolatedFileSystem(type_));
-}
-
IsolatedContext::Instance::~Instance() {}
bool IsolatedContext::Instance::ResolvePathForName(const std::string& name,
@@ -190,8 +170,8 @@ bool IsolatedContext::Instance::ResolvePathForName(const std::string& name,
*path = file_info_.path;
return file_info_.name == name;
}
- std::set<FileInfo>::const_iterator found = files_.find(
- FileInfo(name, FilePath()));
+ std::set<MountPointInfo>::const_iterator found = files_.find(
+ MountPointInfo(name, FilePath()));
if (found == files_.end())
return false;
*path = found->path;
@@ -240,83 +220,28 @@ std::string IsolatedContext::RegisterFileSystemForPath(
base::AutoLock locker(lock_);
std::string filesystem_id = GetNewFileSystemId();
- instance_map_[filesystem_id] = new Instance(type, FileInfo(name, path));
+ instance_map_[filesystem_id] = new Instance(type, MountPointInfo(name, path));
path_to_id_map_[path].insert(filesystem_id);
return filesystem_id;
}
-bool IsolatedContext::RegisterExternalFileSystem(const std::string& mount_name,
- FileSystemType type,
- const FilePath& path) {
- base::AutoLock locker(lock_);
- IDToInstance::iterator found = instance_map_.find(mount_name);
- if (found != instance_map_.end())
- return false;
- instance_map_[mount_name] = new Instance(type, path);
- path_to_id_map_[path].insert(mount_name);
- return true;
-}
-
-std::vector<IsolatedContext::FileInfo>
-IsolatedContext::GetExternalMountPoints() const {
- base::AutoLock locker(lock_);
- std::vector<FileInfo> files;
- for (IDToInstance::const_iterator iter = instance_map_.begin();
- iter != instance_map_.end();
- ++iter) {
- if (iter->second->mount_type() == kFileSystemTypeExternal)
- files.push_back(FileInfo(iter->first, iter->second->file_info().path));
- }
- return files;
-}
-
bool IsolatedContext::RevokeFileSystem(const std::string& filesystem_id) {
base::AutoLock locker(lock_);
return UnregisterFileSystem(filesystem_id);
}
-void IsolatedContext::RevokeFileSystemByPath(const FilePath& path_in) {
- base::AutoLock locker(lock_);
- FilePath path(path_in.NormalizePathSeparators());
- PathToID::iterator ids_iter = path_to_id_map_.find(path);
- if (ids_iter == path_to_id_map_.end())
- return;
- std::set<std::string>& ids = ids_iter->second;
- for (std::set<std::string>::iterator iter = ids.begin();
- iter != ids.end(); ++iter) {
- IDToInstance::iterator found = instance_map_.find(*iter);
- if (found != instance_map_.end()) {
- delete found->second;
- instance_map_.erase(found);
- }
- }
- path_to_id_map_.erase(ids_iter);
-}
-
-void IsolatedContext::AddReference(const std::string& filesystem_id) {
- base::AutoLock locker(lock_);
- DCHECK(instance_map_.find(filesystem_id) != instance_map_.end());
- instance_map_[filesystem_id]->AddRef();
-}
-
-void IsolatedContext::RemoveReference(const std::string& filesystem_id) {
+bool IsolatedContext::GetRegisteredPath(
+ const std::string& filesystem_id, FilePath* path) const {
+ DCHECK(path);
base::AutoLock locker(lock_);
- // This could get called for non-existent filesystem if it has been
- // already deleted by RevokeFileSystemByPath.
- IDToInstance::iterator found = instance_map_.find(filesystem_id);
- if (found == instance_map_.end())
- return;
- Instance* instance = found->second;
- DCHECK_GT(instance->ref_counts(), 0);
- instance->RemoveRef();
- if (instance->ref_counts() == 0 &&
- instance->mount_type() != kFileSystemTypeExternal) {
- bool deleted = UnregisterFileSystem(filesystem_id);
- DCHECK(deleted);
- }
+ IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
+ if (found == instance_map_.end() || !found->second->IsSinglePathInstance())
+ return false;
+ *path = found->second->file_info().path;
+ return true;
}
-bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
+bool IsolatedContext::CrackVirtualPath(const FilePath& virtual_path,
std::string* id_or_name,
FileSystemType* type,
FilePath* path) const {
@@ -348,26 +273,17 @@ bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
const Instance* instance = found_instance->second;
if (type)
*type = instance->type();
- switch (instance->mount_type()) {
- case kFileSystemTypeIsolated: {
- if (component_iter == components.end()) {
- // The virtual root case.
- path->clear();
- return true;
- }
- // *component_iter should be a name of the registered path.
- std::string name = FilePath(*component_iter++).AsUTF8Unsafe();
- if (!instance->ResolvePathForName(name, &cracked_path))
- return false;
- break;
- }
- case kFileSystemTypeExternal:
- cracked_path = instance->file_info().path;
- break;
- default:
- NOTREACHED();
- break;
+
+ if (component_iter == components.end()) {
+ // The virtual root case.
+ path->clear();
+ return true;
}
+
+ // *component_iter should be a name of the registered path.
+ std::string name = FilePath(*component_iter++).AsUTF8Unsafe();
+ if (!instance->ResolvePathForName(name, &cracked_path))
+ return false;
}
for (; component_iter != components.end(); ++component_iter)
@@ -376,8 +292,49 @@ bool IsolatedContext::CrackIsolatedPath(const FilePath& virtual_path,
return true;
}
+void IsolatedContext::RevokeFileSystemByPath(const FilePath& path_in) {
+ base::AutoLock locker(lock_);
+ FilePath path(path_in.NormalizePathSeparators());
+ PathToID::iterator ids_iter = path_to_id_map_.find(path);
+ if (ids_iter == path_to_id_map_.end())
+ return;
+ std::set<std::string>& ids = ids_iter->second;
+ for (std::set<std::string>::iterator iter = ids.begin();
+ iter != ids.end(); ++iter) {
+ IDToInstance::iterator found = instance_map_.find(*iter);
+ if (found != instance_map_.end()) {
+ delete found->second;
+ instance_map_.erase(found);
+ }
+ }
+ path_to_id_map_.erase(ids_iter);
+}
+
+void IsolatedContext::AddReference(const std::string& filesystem_id) {
+ base::AutoLock locker(lock_);
+ DCHECK(instance_map_.find(filesystem_id) != instance_map_.end());
+ instance_map_[filesystem_id]->AddRef();
+}
+
+void IsolatedContext::RemoveReference(const std::string& filesystem_id) {
+ base::AutoLock locker(lock_);
+ // This could get called for non-existent filesystem if it has been
+ // already deleted by RevokeFileSystemByPath.
+ IDToInstance::iterator found = instance_map_.find(filesystem_id);
+ if (found == instance_map_.end())
+ return;
+ Instance* instance = found->second;
+ DCHECK_GT(instance->ref_counts(), 0);
+ instance->RemoveRef();
+ if (instance->ref_counts() == 0) {
+ bool deleted = UnregisterFileSystem(filesystem_id);
+ DCHECK(deleted);
+ }
+}
+
bool IsolatedContext::GetDraggedFileInfo(
- const std::string& filesystem_id, std::vector<FileInfo>* files) const {
+ const std::string& filesystem_id,
+ std::vector<MountPointInfo>* files) const {
DCHECK(files);
base::AutoLock locker(lock_);
IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
@@ -389,17 +346,6 @@ bool IsolatedContext::GetDraggedFileInfo(
return true;
}
-bool IsolatedContext::GetRegisteredPath(
- const std::string& filesystem_id, FilePath* path) const {
- DCHECK(path);
- base::AutoLock locker(lock_);
- IDToInstance::const_iterator found = instance_map_.find(filesystem_id);
- if (found == instance_map_.end() || !found->second->IsSinglePathInstance())
- return false;
- *path = found->second->file_info().path;
- return true;
-}
-
FilePath IsolatedContext::CreateVirtualRootPath(
const std::string& filesystem_id) const {
return FilePath().AppendASCII(filesystem_id);
@@ -444,21 +390,4 @@ std::string IsolatedContext::GetNewFileSystemId() const {
return id;
}
-ScopedExternalFileSystem::ScopedExternalFileSystem(
- const std::string& mount_name,
- FileSystemType type,
- const FilePath& path)
- : mount_name_(mount_name) {
- IsolatedContext::GetInstance()->RegisterExternalFileSystem(
- mount_name, type, path);
-}
-
-FilePath ScopedExternalFileSystem::GetVirtualRootPath() const {
- return IsolatedContext::GetInstance()->CreateVirtualRootPath(mount_name_);
-}
-
-ScopedExternalFileSystem::~ScopedExternalFileSystem() {
- IsolatedContext::GetInstance()->RevokeFileSystem(mount_name_);
-}
-
} // namespace fileapi
diff --git a/webkit/fileapi/isolated_context.h b/webkit/fileapi/isolated_context.h
index e0cea7c..63cab56 100644
--- a/webkit/fileapi/isolated_context.h
+++ b/webkit/fileapi/isolated_context.h
@@ -16,60 +16,25 @@
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
#include "webkit/fileapi/file_system_types.h"
+#include "webkit/fileapi/mount_points.h"
#include "webkit/storage/webkit_storage_export.h"
namespace fileapi {
-// Manages isolated filesystem namespaces.
-// This context class is a singleton and access to the context is
-// thread-safe (protected with a lock).
-//
-// There are two types of filesystems managed by this context:
-// isolated and external.
-// The former is transient while the latter is persistent.
-//
-// * Transient isolated file systems have no name and are identified by
-// string 'filesystem ID', which usually just looks like random value.
-// This type of filesystem can be created on the fly and may go away
-// when it has no references from renderers.
-// Files in an isolated filesystem are registered with corresponding names
-// and identified by a filesystem URL like:
+// Manages isolated filesystem mount points which have no well-known names
+// and are identified by a string 'filesystem ID', which usually just looks
+// like random value.
+// This type of filesystem can be created on the fly and may go away when it has
+// no references from renderers.
+// Files in an isolated filesystem are registered with corresponding names and
+// identified by a filesystem URL like:
//
// filesystem:<origin>/isolated/<filesystem_id>/<name>/relative/path
//
-// * Persistent external file systems are identified by 'mount name'
-// and are persisted until RevokeFileSystem is called.
-// Files in an external filesystem are identified by a filesystem URL like:
-//
-// filesystem:<origin>/external/<mount_name>/relative/path
-//
-// A filesystem instance is represented by IsolatedContext::Instance, and
-// managed as a map instance_map_ which maps from filesystem ID (or name)
-// to the instance.
-//
// Some methods of this class are virtual just for mocking.
//
-// TODO(kinuko): This should have a better name since this handles both
-// isolated and external file systems.
-//
-class WEBKIT_STORAGE_EXPORT IsolatedContext {
+class WEBKIT_STORAGE_EXPORT IsolatedContext : public MountPoints {
public:
- struct WEBKIT_STORAGE_EXPORT FileInfo {
- FileInfo();
- FileInfo(const std::string& name, const FilePath& path);
-
- // The name to be used to register the file. The registered file can
- // be referred by a virtual path /<filesystem_id>/<name>.
- // The name should NOT contain a path separator '/'.
- std::string name;
-
- // The path of the file.
- FilePath path;
-
- // For STL operation.
- bool operator<(const FileInfo& that) const { return name < that.name; }
- };
-
class WEBKIT_STORAGE_EXPORT FileInfoSet {
public:
FileInfoSet();
@@ -86,10 +51,10 @@ class WEBKIT_STORAGE_EXPORT IsolatedContext {
// is not valid and could not be added.
bool AddPathWithName(const FilePath& path, const std::string& name);
- const std::set<FileInfo>& fileset() const { return fileset_; }
+ const std::set<MountPointInfo>& fileset() const { return fileset_; }
private:
- std::set<FileInfo> fileset_;
+ std::set<MountPointInfo> fileset_;
};
// The instance is lazily created per browser process.
@@ -133,30 +98,14 @@ class WEBKIT_STORAGE_EXPORT IsolatedContext {
const FilePath& path,
std::string* register_name);
- // Registers a new named external filesystem.
- // The |path| is registered as the root path of the mount point which
- // is identified by a URL "filesystem:.../external/mount_name".
- //
- // For example, if the path "/media/removable" is registered with
- // the mount_name "removable", a filesystem URL like
- // "filesystem:.../external/removable/a/b" will be resolved as
- // "/media/removable/a/b".
- //
- // The |mount_name| should NOT contain a path separator '/'.
- // Returns false if the given name is already registered.
- //
- // An external file system registered by this method can be revoked
- // by calling RevokeFileSystem with |mount_name|.
- bool RegisterExternalFileSystem(const std::string& mount_name,
- FileSystemType type,
- const FilePath& path);
-
- // Returns a set of FilePath (of <mount_name, path>) registered as external.
- std::vector<FileInfo> GetExternalMountPoints() const;
-
- // Revokes the filesystem |filesystem_id|.
- // Returns false if the |filesystem_id| is not (no longer) registered.
- bool RevokeFileSystem(const std::string& filesystem_id);
+ // MountPoints override.
+ virtual bool RevokeFileSystem(const std::string& filesystem_id) OVERRIDE;
+ virtual bool GetRegisteredPath(const std::string& filesystem_id,
+ FilePath* path) const OVERRIDE;
+ virtual bool CrackVirtualPath(const FilePath& virtual_path,
+ std::string* filesystem_id,
+ FileSystemType* type,
+ FilePath* path) const OVERRIDE;
// Revokes all filesystem(s) registered for the given path.
// This is assumed to be called when the registered path becomes
@@ -173,41 +122,17 @@ class WEBKIT_STORAGE_EXPORT IsolatedContext {
// Removes a reference to a filesystem specified by the given filesystem_id.
// If the reference count reaches 0 the isolated context gets destroyed.
- // It is ok to call this on the filesystem that has been already deleted
+ // It is OK to call this on the filesystem that has been already deleted
// (e.g. by RevokeFileSystemByPath).
void RemoveReference(const std::string& filesystem_id);
- // Cracks the given |virtual_path| (which is the path part of a filesystem URL
- // without '/isolated' or '/external' prefix) and populates the
- // |id_or_name|, |type|, and |path| if the <id_or_name> part embedded in
- // the |virtual_path| (i.e. the first component of the |virtual_path|) is a
- // valid registered filesystem ID or mount name for an isolated or external
- // filesystem.
- //
- // Returns false if the given virtual_path or the cracked id_or_name
- // is not valid.
- //
- // Note that |path| is set to empty paths if the filesystem type is isolated
- // and |virtual_path| has no <relative_path> part (i.e. pointing to the
- // virtual root).
- bool CrackIsolatedPath(const FilePath& virtual_path,
- std::string* id_or_name,
- FileSystemType* type,
- FilePath* path) const;
-
- // Returns a set of dragged FileInfo's registered for the |filesystem_id|.
+ // Returns a set of dragged MountPointInfos registered for the
+ // |filesystem_id|.
// The filesystem_id must be pointing to a dragged file system
// (i.e. must be the one registered by RegisterDraggedFileSystem).
// Returns false if the |filesystem_id| is not valid.
bool GetDraggedFileInfo(const std::string& filesystem_id,
- std::vector<FileInfo>* files) const;
-
- // Returns the file path registered for the |filesystem_id|.
- // The filesystem_id must NOT be pointing to a dragged file system
- // (i.e. must be the one registered by RegisterFileSystemForPath).
- // Returns false if the |filesystem_id| is not valid.
- bool GetRegisteredPath(const std::string& filesystem_id,
- FilePath* path) const;
+ std::vector<MountPointInfo>* files) const;
// Returns the virtual root path that looks like /<filesystem_id>.
FilePath CreateVirtualRootPath(const std::string& filesystem_id) const;
@@ -225,7 +150,7 @@ class WEBKIT_STORAGE_EXPORT IsolatedContext {
// Obtain an instance of this class via GetInstance().
IsolatedContext();
- ~IsolatedContext();
+ virtual ~IsolatedContext();
// Unregisters a file system of given |filesystem_id|. Must be called with
// lock_ held. Returns true if the file system is unregistered.
@@ -243,20 +168,6 @@ class WEBKIT_STORAGE_EXPORT IsolatedContext {
DISALLOW_COPY_AND_ASSIGN(IsolatedContext);
};
-// Registers a scoped external filesystem which gets revoked when it scopes out.
-class WEBKIT_STORAGE_EXPORT ScopedExternalFileSystem {
- public:
- ScopedExternalFileSystem(const std::string& mount_name,
- FileSystemType type,
- const FilePath& path);
- ~ScopedExternalFileSystem();
-
- FilePath GetVirtualRootPath() const;
-
- private:
- const std::string mount_name_;
-};
-
} // namespace fileapi
#endif // WEBKIT_FILEAPI_ISOLATED_CONTEXT_H_
diff --git a/webkit/fileapi/isolated_context_unittest.cc b/webkit/fileapi/isolated_context_unittest.cc
index 78efd16..bf36df9 100644
--- a/webkit/fileapi/isolated_context_unittest.cc
+++ b/webkit/fileapi/isolated_context_unittest.cc
@@ -19,7 +19,7 @@
namespace fileapi {
-typedef IsolatedContext::FileInfo FileInfo;
+typedef IsolatedContext::MountPointInfo FileInfo;
namespace {
@@ -95,7 +95,7 @@ TEST_F(IsolatedContextTest, RegisterAndRevokeTest) {
std::string cracked_id;
FilePath cracked_path;
FileSystemType cracked_type;
- ASSERT_TRUE(isolated_context()->CrackIsolatedPath(
+ ASSERT_TRUE(isolated_context()->CrackVirtualPath(
virtual_path, &cracked_id, &cracked_type, &cracked_path));
ASSERT_EQ(kTestPaths[i].NormalizePathSeparators().value(),
cracked_path.value());
@@ -191,11 +191,11 @@ TEST_F(IsolatedContextTest, CrackWithRelativePaths) {
FilePath cracked_path;
FileSystemType cracked_type;
if (!relatives[j].valid) {
- ASSERT_FALSE(isolated_context()->CrackIsolatedPath(
+ ASSERT_FALSE(isolated_context()->CrackVirtualPath(
virtual_path, &cracked_id, &cracked_type, &cracked_path));
continue;
}
- ASSERT_TRUE(isolated_context()->CrackIsolatedPath(
+ ASSERT_TRUE(isolated_context()->CrackVirtualPath(
virtual_path, &cracked_id, &cracked_type, &cracked_path));
ASSERT_EQ(kTestPaths[i].Append(relatives[j].path)
.NormalizePathSeparators().value(),
@@ -214,7 +214,7 @@ TEST_F(IsolatedContextTest, TestWithVirtualRoot) {
// as "/" of the isolated filesystem is a pure virtual directory
// that has no corresponding platform directory.
FilePath virtual_path = isolated_context()->CreateVirtualRootPath(id_);
- ASSERT_TRUE(isolated_context()->CrackIsolatedPath(
+ ASSERT_TRUE(isolated_context()->CrackVirtualPath(
virtual_path, &cracked_id, NULL, &cracked_path));
ASSERT_EQ(FPL(""), cracked_path.value());
ASSERT_EQ(id_, cracked_id);
@@ -223,7 +223,7 @@ TEST_F(IsolatedContextTest, TestWithVirtualRoot) {
// included in the kTestPaths).
virtual_path = isolated_context()->CreateVirtualRootPath(
id_).AppendASCII("foo");
- ASSERT_FALSE(isolated_context()->CrackIsolatedPath(
+ ASSERT_FALSE(isolated_context()->CrackVirtualPath(
virtual_path, &cracked_id, NULL, &cracked_path));
}
diff --git a/webkit/fileapi/isolated_file_util.cc b/webkit/fileapi/isolated_file_util.cc
index cf3f0ce..d50549e 100644
--- a/webkit/fileapi/isolated_file_util.cc
+++ b/webkit/fileapi/isolated_file_util.cc
@@ -19,7 +19,7 @@ using base::PlatformFileInfo;
namespace fileapi {
-typedef IsolatedContext::FileInfo FileInfo;
+typedef IsolatedContext::MountPointInfo FileInfo;
namespace {
diff --git a/webkit/fileapi/mount_points.cc b/webkit/fileapi/mount_points.cc
new file mode 100644
index 0000000..d754b25
--- /dev/null
+++ b/webkit/fileapi/mount_points.cc
@@ -0,0 +1,15 @@
+// Copyright (c) 2013 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/mount_points.h"
+
+namespace fileapi {
+
+MountPoints::MountPointInfo::MountPointInfo() {}
+MountPoints::MountPointInfo::MountPointInfo(
+ const std::string& name, const FilePath& path)
+ : name(name), path(path) {}
+
+} // namespace fileapi
+
diff --git a/webkit/fileapi/mount_points.h b/webkit/fileapi/mount_points.h
new file mode 100644
index 0000000..0cfb57b
--- /dev/null
+++ b/webkit/fileapi/mount_points.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2013 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.
+
+#ifndef WEBKIT_FILEAPI_MOUNT_POINTS_H_
+#define WEBKIT_FILEAPI_MOUNT_POINTS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "webkit/fileapi/file_system_util.h"
+#include "webkit/storage/webkit_storage_export.h"
+
+class GURL;
+
+namespace fileapi {
+
+// Represents a set of mount points for File API.
+class WEBKIT_STORAGE_EXPORT MountPoints {
+ public:
+ struct WEBKIT_STORAGE_EXPORT MountPointInfo {
+ MountPointInfo();
+ MountPointInfo(const std::string& name, const FilePath& path);
+
+ // The name to be used to register the path. The registered file can
+ // be referred by a virtual path /<filesystem_id>/<name>.
+ // The name should NOT contain a path separator '/'.
+ std::string name;
+
+ // The path of the file.
+ FilePath path;
+
+ // For STL operation.
+ bool operator<(const MountPointInfo& that) const {
+ return name < that.name;
+ }
+ };
+
+ MountPoints() {}
+ virtual ~MountPoints() {}
+
+ // Revokes a mount point identified by |mount_name|.
+ // Returns false if the |mount_name| is not (no longer) registered.
+ // TODO(kinuko): Probably this should be rather named RevokeMountPoint.
+ virtual bool RevokeFileSystem(const std::string& mount_name) = 0;
+
+ // Returns the mount point root path registered for a given |mount_name|.
+ // Returns false if the given |mount_name| is not valid.
+ virtual bool GetRegisteredPath(const std::string& mount_name,
+ FilePath* path) const = 0;
+
+ // Cracks the given |virtual_path| (which is the path part of a filesystem URL
+ // without '/external' or '/isolated' prefix part) and populates the
+ // |mount_name|, |type|, and |path| if the <mount_name> part embedded in
+ // the |virtual_path| (i.e. the first component of the |virtual_path|) is a
+ // valid registered filesystem ID or mount name for an existing mount point.
+ //
+ // Returns false if the given virtual_path cannot be cracked.
+ //
+ // Note that |path| is set to empty paths if the filesystem type is isolated
+ // and |virtual_path| has no <relative_path> part (i.e. pointing to the
+ // virtual root).
+ virtual bool CrackVirtualPath(const FilePath& virtual_path,
+ std::string* mount_name,
+ FileSystemType* type,
+ FilePath* path) const = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MountPoints);
+};
+
+} // namespace fileapi
+
+#endif // WEBKIT_FILEAPI_MOUNT_POINTS_H_
+
diff --git a/webkit/chromeos/fileapi/remote_file_system_proxy.h b/webkit/fileapi/remote_file_system_proxy.h
index e54a266..e54a266 100644
--- a/webkit/chromeos/fileapi/remote_file_system_proxy.h
+++ b/webkit/fileapi/remote_file_system_proxy.h
diff --git a/webkit/fileapi/syncable/canned_syncable_file_system.cc b/webkit/fileapi/syncable/canned_syncable_file_system.cc
index 05448f3..e960959 100644
--- a/webkit/fileapi/syncable/canned_syncable_file_system.cc
+++ b/webkit/fileapi/syncable/canned_syncable_file_system.cc
@@ -16,7 +16,6 @@
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_operation_context.h"
#include "webkit/fileapi/file_system_task_runners.h"
-#include "webkit/fileapi/isolated_context.h"
#include "webkit/fileapi/local_file_system_operation.h"
#include "webkit/fileapi/mock_file_system_options.h"
#include "webkit/fileapi/sandbox_mount_point_provider.h"
diff --git a/webkit/fileapi/syncable/syncable_file_system_util.cc b/webkit/fileapi/syncable/syncable_file_system_util.cc
index 207f802..21652d0 100644
--- a/webkit/fileapi/syncable/syncable_file_system_util.cc
+++ b/webkit/fileapi/syncable/syncable_file_system_util.cc
@@ -4,21 +4,22 @@
#include "webkit/fileapi/syncable/syncable_file_system_util.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/file_observers.h"
#include "webkit/fileapi/file_system_context.h"
#include "webkit/fileapi/file_system_util.h"
-#include "webkit/fileapi/isolated_context.h"
#include "webkit/fileapi/sandbox_mount_point_provider.h"
namespace fileapi {
bool RegisterSyncableFileSystem(const std::string& service_name) {
- return IsolatedContext::GetInstance()->RegisterExternalFileSystem(
+ return ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
service_name, kFileSystemTypeSyncable, FilePath());
}
bool RevokeSyncableFileSystem(const std::string& service_name) {
- return IsolatedContext::GetInstance()->RevokeFileSystem(service_name);
+ return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+ service_name);
}
GURL GetSyncableFileSystemRootURI(const GURL& origin,
diff --git a/webkit/fileapi/syncable/syncable_file_system_util_unittest.cc b/webkit/fileapi/syncable/syncable_file_system_util_unittest.cc
index b8d92f6..356ff53 100644
--- a/webkit/fileapi/syncable/syncable_file_system_util_unittest.cc
+++ b/webkit/fileapi/syncable/syncable_file_system_util_unittest.cc
@@ -8,7 +8,7 @@
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "webkit/fileapi/isolated_context.h"
+#include "webkit/fileapi/external_mount_points.h"
#include "webkit/fileapi/syncable/canned_syncable_file_system.h"
#include "webkit/fileapi/syncable/local_file_sync_context.h"
diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi
index 39288ee..324f9e5 100644
--- a/webkit/fileapi/webkit_fileapi.gypi
+++ b/webkit/fileapi/webkit_fileapi.gypi
@@ -5,6 +5,8 @@
{
'variables': {
'webkit_fileapi_sources': [
+ '../fileapi/external_mount_points.cc',
+ '../fileapi/external_mount_points.h',
'../fileapi/file_observers.h',
'../fileapi/file_permission_policy.cc',
'../fileapi/file_permission_policy.h',
@@ -70,10 +72,13 @@
'../fileapi/media/mtp_device_file_system_config.h',
'../fileapi/media/native_media_file_util.cc',
'../fileapi/media/native_media_file_util.h',
+ '../fileapi/mount_points.cc',
+ '../fileapi/mount_points.h',
'../fileapi/native_file_util.cc',
'../fileapi/native_file_util.h',
'../fileapi/obfuscated_file_util.cc',
'../fileapi/obfuscated_file_util.h',
+ '../fileapi/remote_file_system_proxy.h',
'../fileapi/sandbox_file_stream_writer.cc',
'../fileapi/sandbox_file_stream_writer.h',
'../fileapi/sandbox_mount_point_provider.cc',
@@ -120,7 +125,6 @@
'../chromeos/fileapi/file_util_async.h',
'../chromeos/fileapi/remote_file_system_operation.cc',
'../chromeos/fileapi/remote_file_system_operation.h',
- '../chromeos/fileapi/remote_file_system_proxy.h',
'../chromeos/fileapi/remote_file_stream_writer.cc',
'../chromeos/fileapi/remote_file_stream_writer.h',
],