diff options
33 files changed, 473 insertions, 120 deletions
diff --git a/chrome/browser/extensions/extension_file_browser_private_api.cc b/chrome/browser/extensions/extension_file_browser_private_api.cc index 62a488b..448b8e2 100644 --- a/chrome/browser/extensions/extension_file_browser_private_api.cc +++ b/chrome/browser/extensions/extension_file_browser_private_api.cc @@ -79,7 +79,7 @@ bool RequestLocalFileSystemFunction::RunImpl() { profile()->GetFileSystemContext(), NULL); GURL origin_url = source_url().GetOrigin(); - operation->OpenFileSystem(origin_url, fileapi::kFileSystemTypeLocal, + operation->OpenFileSystem(origin_url, fileapi::kFileSystemTypeExternal, false); // create // Will finish asynchronously. return true; @@ -171,7 +171,7 @@ void FileDialogFunction::GetLocalPathsOnFileThread() { std::string virtual_path = virtual_paths_[i]; FilePath root = path_manager->GetFileSystemRootPathOnFileThread( origin_url, - fileapi::kFileSystemTypeLocal, + fileapi::kFileSystemTypeExternal, FilePath(virtual_path), false); if (!root.empty()) { diff --git a/chrome/browser/extensions/extension_local_filesystem_apitest.cc b/chrome/browser/extensions/extension_local_filesystem_apitest.cc index 003e56a..5a8ba72 100644 --- a/chrome/browser/extensions/extension_local_filesystem_apitest.cc +++ b/chrome/browser/extensions/extension_local_filesystem_apitest.cc @@ -6,7 +6,8 @@ #if defined(OS_CHROMEOS) -IN_PROC_BROWSER_TEST_F(ExtensionApiTest, LocalFileSystem) { +// TODO(zelidrag): Remove disable prefix on this test once API changes land. +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_LocalFileSystem) { ASSERT_TRUE(RunComponentExtensionTest("local_filesystem")) << message_; } diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 1c68cf0..7dcba6e 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc @@ -76,6 +76,9 @@ #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/extensions/file_browser_event_router.h" +#include "webkit/fileapi/file_system_context.h" +#include "webkit/fileapi/file_system_mount_point_provider.h" +#include "webkit/fileapi/file_system_path_manager.h" #endif using base::Time; @@ -1081,6 +1084,11 @@ void ExtensionService::NotifyExtensionUnloaded( profile_->UnregisterExtensionWithRequestContexts(extension); profile_->GetExtensionSpecialStoragePolicy()-> RevokeRightsForExtension(extension); +#if defined(OS_CHROMEOS) + // Revoke external file access to + profile_->GetFileSystemContext()->path_manager()->external_provider()-> + RevokeAccessForExtension(extension->id()); +#endif } bool plugins_changed = false; diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc index 90f32fa..fd3ccc4 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.cc +++ b/chrome/browser/extensions/extension_special_storage_policy.cc @@ -24,10 +24,10 @@ bool ExtensionSpecialStoragePolicy::IsStorageUnlimited(const GURL& origin) { return unlimited_extensions_.Contains(origin); } -bool ExtensionSpecialStoragePolicy::IsLocalFileSystemAccessAllowed( - const GURL& origin) { +bool ExtensionSpecialStoragePolicy::IsFileHandler( + const std::string& extension_id) { base::AutoLock locker(lock_); - return local_filesystem_extensions_.Contains(origin); + return file_handler_extensions_.ContainsExtension(extension_id); } void ExtensionSpecialStoragePolicy::GrantRightsForExtension( @@ -35,7 +35,7 @@ void ExtensionSpecialStoragePolicy::GrantRightsForExtension( DCHECK(extension); if (!extension->is_hosted_app() && !extension->HasApiPermission(Extension::kUnlimitedStoragePermission) && - !extension->HasApiPermission(Extension::kFileSystemPermission)) { + !extension->HasApiPermission(Extension::kFileBrowserHandlerPermission)) { return; } base::AutoLock locker(lock_); @@ -43,8 +43,8 @@ void ExtensionSpecialStoragePolicy::GrantRightsForExtension( protected_apps_.Add(extension); if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) unlimited_extensions_.Add(extension); - if (extension->HasApiPermission(Extension::kFileSystemPermission)) - local_filesystem_extensions_.Add(extension); + if (extension->HasApiPermission(Extension::kFileBrowserHandlerPermission)) + file_handler_extensions_.Add(extension); } void ExtensionSpecialStoragePolicy::RevokeRightsForExtension( @@ -52,7 +52,7 @@ void ExtensionSpecialStoragePolicy::RevokeRightsForExtension( DCHECK(extension); if (!extension->is_hosted_app() && !extension->HasApiPermission(Extension::kUnlimitedStoragePermission) && - !extension->HasApiPermission(Extension::kFileSystemPermission)) { + !extension->HasApiPermission(Extension::kFileBrowserHandlerPermission)) { return; } base::AutoLock locker(lock_); @@ -60,15 +60,15 @@ void ExtensionSpecialStoragePolicy::RevokeRightsForExtension( protected_apps_.Remove(extension); if (extension->HasApiPermission(Extension::kUnlimitedStoragePermission)) unlimited_extensions_.Remove(extension); - if (extension->HasApiPermission(Extension::kFileSystemPermission)) - local_filesystem_extensions_.Remove(extension); + if (extension->HasApiPermission(Extension::kFileBrowserHandlerPermission)) + file_handler_extensions_.Remove(extension); } void ExtensionSpecialStoragePolicy::RevokeRightsForAllExtensions() { base::AutoLock locker(lock_); protected_apps_.Clear(); unlimited_extensions_.Clear(); - local_filesystem_extensions_.Clear(); + file_handler_extensions_.Clear(); } //----------------------------------------------------------------------------- @@ -81,34 +81,39 @@ ExtensionSpecialStoragePolicy::SpecialCollection::~SpecialCollection() {} bool ExtensionSpecialStoragePolicy::SpecialCollection::Contains( const GURL& origin) { - CachedResults::const_iterator found = cached_resuts_.find(origin); - if (found != cached_resuts_.end()) + CachedResults::const_iterator found = cached_results_.find(origin); + if (found != cached_results_.end()) return found->second; for (Extensions::const_iterator iter = extensions_.begin(); iter != extensions_.end(); ++iter) { if (iter->second->OverlapsWithOrigin(origin)) { - cached_resuts_[origin] = true; + cached_results_[origin] = true; return true; } } - cached_resuts_[origin] = false; + cached_results_[origin] = false; return false; } +bool ExtensionSpecialStoragePolicy::SpecialCollection::ContainsExtension( + const std::string& extension_id) { + return extensions_.find(extension_id) != extensions_.end(); +} + void ExtensionSpecialStoragePolicy::SpecialCollection::Add( const Extension* extension) { - cached_resuts_.clear(); + cached_results_.clear(); extensions_[extension->id()] = extension; } void ExtensionSpecialStoragePolicy::SpecialCollection::Remove( const Extension* extension) { - cached_resuts_.clear(); + cached_results_.clear(); extensions_.erase(extension->id()); } void ExtensionSpecialStoragePolicy::SpecialCollection::Clear() { - cached_resuts_.clear(); + cached_results_.clear(); extensions_.clear(); } diff --git a/chrome/browser/extensions/extension_special_storage_policy.h b/chrome/browser/extensions/extension_special_storage_policy.h index 3a01a2e..478e271 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.h +++ b/chrome/browser/extensions/extension_special_storage_policy.h @@ -26,7 +26,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy { // data remover. These methods are safe to call on any thread. virtual bool IsStorageProtected(const GURL& origin); virtual bool IsStorageUnlimited(const GURL& origin); - virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin); + virtual bool IsFileHandler(const std::string& extension_id); // Methods used by the ExtensionService to populate this class. void GrantRightsForExtension(const Extension* extension); @@ -40,6 +40,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy { ~SpecialCollection(); bool Contains(const GURL& origin); + bool ContainsExtension(const std::string& extension_id); void Add(const Extension* extension); void Remove(const Extension* extension); void Clear(); @@ -48,7 +49,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy { typedef std::map<GURL, bool> CachedResults; typedef std::map<std::string, scoped_refptr<const Extension> > Extensions; Extensions extensions_; - CachedResults cached_resuts_; + CachedResults cached_results_; }; virtual ~ExtensionSpecialStoragePolicy(); @@ -56,7 +57,7 @@ class ExtensionSpecialStoragePolicy : public quota::SpecialStoragePolicy { base::Lock lock_; // Synchronize all access to the collections. SpecialCollection protected_apps_; SpecialCollection unlimited_extensions_; - SpecialCollection local_filesystem_extensions_; + SpecialCollection file_handler_extensions_; }; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SPECIAL_STORAGE_POLICY_H_ diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc index 3f34ccf..cbaf6ed 100644 --- a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc +++ b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc @@ -58,6 +58,59 @@ class ExtensionSpecialStoragePolicyTest : public testing::Test { EXPECT_TRUE(unlimited_app.get()) << error; return unlimited_app; } + + scoped_refptr<Extension> CreateComponentApp() { +#if defined(OS_WIN) + FilePath path(FILE_PATH_LITERAL("c:\\component")); +#elif defined(OS_POSIX) + FilePath path(FILE_PATH_LITERAL("/component")); +#endif + DictionaryValue manifest; + manifest.SetString(keys::kName, "Component"); + manifest.SetString(keys::kVersion, "1"); + manifest.SetString(keys::kPublicKey, + "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDOuXEIuoK1kAkBe0SKiJn/N9oNn3oU" \ + "xGa4dwj40MnJqPn+w0aR2vuyocm0R4Drp67aYwtLjOVPF4CICRq6ICP6eU07gGwQxGdZ" \ + "7HJASXV8hm0tab5I70oJmRLfFJyVAMCeWlFaOGq05v2i6EbifZM0qO5xALKNGQt+yjXi" \ + "5INM5wIBIw=="); + ListValue* list = new ListValue(); + list->Append(Value::CreateStringValue("unlimitedStorage")); + list->Append(Value::CreateStringValue("fileSystem")); + list->Append(Value::CreateStringValue("fileBrowserPrivate")); + manifest.Set(keys::kPermissions, list); + std::string error; + scoped_refptr<Extension> component_app = Extension::Create( + path, Extension::COMPONENT, manifest, Extension::STRICT_ERROR_CHECKS, + &error); + EXPECT_TRUE(component_app.get()) << error; + return component_app; + } + + scoped_refptr<Extension> CreateHandlerApp() { +#if defined(OS_WIN) + FilePath path(FILE_PATH_LITERAL("c:\\handler")); +#elif defined(OS_POSIX) + FilePath path(FILE_PATH_LITERAL("/handler")); +#endif + DictionaryValue manifest; + manifest.SetString(keys::kName, "Handler"); + manifest.SetString(keys::kVersion, "1"); + manifest.SetString(keys::kPublicKey, + "MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQChptAQ0n4R56N03nWQ1ogR7DVRBjGo" \ + "80Vw6G9KLjzZv44D8rq5Q5IkeQrtKgWyZfXevlsCe3LaLo18rcz8iZx6lK2xhLdUR+OR" \ + "jsjuBfdEL5a5cWeRTSxf75AcqndQsmpwMBdrMTCZ8jQNusUI+XlrihLNNJuI5TM4vNIN" \ + "I5bYFQIBIw=="); + ListValue* list = new ListValue(); + list->Append(Value::CreateStringValue("unlimitedStorage")); + list->Append(Value::CreateStringValue("fileSystem")); + manifest.Set(keys::kPermissions, list); + std::string error; + scoped_refptr<Extension> handler_app = Extension::Create( + path, Extension::INVALID, manifest, Extension::STRICT_ERROR_CHECKS, + &error); + EXPECT_TRUE(handler_app.get()) << error; + return handler_app; + } }; TEST_F(ExtensionSpecialStoragePolicyTest, EmptyPolicy) { diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index fc381a1..58410fb 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -1154,6 +1154,10 @@ const char kSetToken[] = "set-token"; // If host is specified, it also makes initial delay shorter (5 min to 5 sec) // to make it faster to test websocket live experiment code. const char kWebSocketLiveExperimentHost[] = "websocket-live-experiment-host"; + +// Debug only switch to give access to all private extension APIs to +// any non-component extension that is requesting it. +const char kExposePrivateExtensionApi[] = "expose-private-extension-api"; #endif #if defined(HAVE_XINPUT2) diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 1a377d0..e624157 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -344,6 +344,7 @@ extern const char kKeepMouseCursor[]; extern const char kClearTokenService[]; extern const char kSetToken[]; extern const char kWebSocketLiveExperimentHost[]; +extern const char kExposePrivateExtensionApi[]; #endif #if !defined(OFFICIAL_BUILD) diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index c5c88e3..5f4f7d47 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -264,6 +264,7 @@ const char Extension::kCookiePermission[] = "cookies"; const char Extension::kChromeosInfoPrivatePermissions[] = "chromeosInfoPrivate"; const char Extension::kDebuggerPermission[] = "debugger"; const char Extension::kExperimentalPermission[] = "experimental"; +const char Extension::kFileBrowserHandlerPermission[] = "fileBrowserHandler"; const char Extension::kFileSystemPermission[] = "fileSystem"; const char Extension::kFileBrowserPrivatePermission[] = "fileBrowserPrivate"; const char Extension::kGeolocationPermission[] = "geolocation"; @@ -288,6 +289,7 @@ const Extension::Permission Extension::kPermissions[] = { { kCookiePermission, 0 }, { kDebuggerPermission, IDS_EXTENSION_PROMPT_WARNING_DEBUGGER }, { kExperimentalPermission, 0 }, + { kFileBrowserHandlerPermission, 0 }, { kFileSystemPermission, 0 }, { kFileBrowserPrivatePermission, 0 }, { kGeolocationPermission, IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION }, diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index 9ccb745..8a8cfc9 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -206,6 +206,7 @@ class Extension : public base::RefCountedThreadSafe<Extension> { static const char kChromeosInfoPrivatePermissions[]; static const char kDebuggerPermission[]; static const char kExperimentalPermission[]; + static const char kFileBrowserHandlerPermission[]; static const char kFileSystemPermission[]; static const char kFileBrowserPrivatePermission[]; static const char kGeolocationPermission[]; diff --git a/chrome/common/extensions/extension_unittest.cc b/chrome/common/extensions/extension_unittest.cc index 18751b3..905fd5c 100644 --- a/chrome/common/extensions/extension_unittest.cc +++ b/chrome/common/extensions/extension_unittest.cc @@ -1023,6 +1023,10 @@ TEST(ExtensionTest, PermissionMessages) { // This permission requires explicit user action (context menu handler) // so we won't prompt for it for now. + skip.insert(Extension::kFileBrowserHandlerPermission); + + // This permission requires explicit user action (context menu handler) + // so we won't prompt for it for now. skip.insert(Extension::kFileSystemPermission); // If you've turned on the experimental command-line flag, we don't need diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 2e2bd78..36b92b1 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -328,7 +328,7 @@ class ExtensionImpl : public ExtensionBase { WebKit::WebString::fromUTF8(name.c_str()), WebKit::WebString::fromUTF8(path.c_str())); #else - return webframe->createFileSystem(fileapi::kFileSystemTypeLocal, + return webframe->createFileSystem(fileapi::kFileSystemTypeExternal, WebKit::WebString::fromUTF8(name.c_str()), WebKit::WebString::fromUTF8(path.c_str())); #endif diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider.cc b/webkit/chromeos/fileapi/cros_mount_point_provider.cc index 159dc3b..9efc5cc 100644 --- a/webkit/chromeos/fileapi/cros_mount_point_provider.cc +++ b/webkit/chromeos/fileapi/cros_mount_point_provider.cc @@ -14,14 +14,13 @@ #include "third_party/WebKit/Source/WebKit/chromium/public/WebCString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystem.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" +#include "webkit/chromeos/fileapi/file_access_permissions.h" #include "webkit/fileapi/file_system_path_manager.h" +#include "webkit/fileapi/file_system_util.h" #include "webkit/glue/webkit_glue.h" namespace chromeos { -const char CrosMountPointProvider::kLocalName[] = "Local"; -const char CrosMountPointProvider::kLocalDirName[] = "/local/"; - typedef struct { const char* local_root_path; const char* web_root_path; @@ -36,28 +35,12 @@ FixedExposedPaths fixed_exposed_paths[] = { CrosMountPointProvider::CrosMountPointProvider( scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy) - : local_dir_name_(kLocalName), - special_storage_policy_(special_storage_policy) { - - // TODO(zelidrag): There's got to be a better way to generate UUID. - srand(time(NULL)); - std::string virtual_root; - virtual_root.append(base::StringPrintf("%hx%hx-%hx-%hx-%hx-%hx%hx%hx", - static_cast<unsigned short>(rand()), static_cast<unsigned short>(rand()), - static_cast<unsigned short>(rand()), - static_cast<unsigned short>(rand()), - static_cast<unsigned short>(rand()), - static_cast<unsigned short>(rand()), static_cast<unsigned short>(rand()), - static_cast<unsigned short>(rand()))); - - // Create virtual root node. - virtual_root_path_ = FilePath(virtual_root); - base_path_ = virtual_root_path_.Append(local_dir_name_); - + : special_storage_policy_(special_storage_policy), + file_access_permissions_(new FileAccessPermissions()) { for (size_t i = 0; i < arraysize(fixed_exposed_paths); i++) { - mount_point_map_.insert(std::pair<std::string, std::string>( + mount_point_map_.insert(std::pair<std::string, FilePath>( std::string(fixed_exposed_paths[i].web_root_path), - std::string(fixed_exposed_paths[i].local_root_path))); + FilePath(std::string(fixed_exposed_paths[i].local_root_path)))); } } @@ -77,13 +60,13 @@ void CrosMountPointProvider::GetFileSystemRootPath( fileapi::FileSystemType type, bool create, fileapi::FileSystemPathManager::GetRootPathCallback* callback_ptr) { - DCHECK(type == fileapi::kFileSystemTypeLocal); + DCHECK(type == fileapi::kFileSystemTypeExternal); std::string name(GetOriginIdentifierFromURL(origin_url)); name += ':'; - name += CrosMountPointProvider::kLocalName; + name += fileapi::kExternalName; - FilePath root_path = FilePath(CrosMountPointProvider::kLocalDirName); + FilePath root_path = FilePath(fileapi::kExternalDir); callback_ptr->Run(!root_path.empty(), root_path, name); } @@ -94,7 +77,7 @@ FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread( fileapi::FileSystemType type, const FilePath& virtual_path, bool create) { - DCHECK(type == fileapi::kFileSystemTypeLocal); + DCHECK(type == fileapi::kFileSystemTypeExternal); std::vector<FilePath::StringType> components; virtual_path.GetComponents(&components); @@ -108,7 +91,7 @@ FilePath CrosMountPointProvider::GetFileSystemRootPathOnFileThread( return FilePath(); } - return FilePath(iter->second); + return iter->second; } // TODO(zelidrag): Share this code with SandboxMountPointProvider impl. @@ -116,8 +99,53 @@ bool CrosMountPointProvider::IsRestrictedFileName(const FilePath& path) const { return false; } -bool CrosMountPointProvider::IsAccessAllowed(const GURL& origin_url) { - return special_storage_policy_->IsLocalFileSystemAccessAllowed(origin_url); +bool CrosMountPointProvider::IsAccessAllowed(const GURL& origin_url, + fileapi::FileSystemType type, + const FilePath& virtual_path) { + if (type != fileapi::kFileSystemTypeExternal) + return false; + std::string extension_id = origin_url.host(); + // Check first to make sure this extension has fileBrowserHander permissions. + if (!special_storage_policy_->IsFileHandler(extension_id)) + return false; + return file_access_permissions_->HasAccessPermission(extension_id, + virtual_path); +} + +void CrosMountPointProvider::GrantFullAccessToExtension( + const std::string& extension_id) { + DCHECK(special_storage_policy_->IsFileHandler(extension_id)); + if (!special_storage_policy_->IsFileHandler(extension_id)) + return; + for (MountPointMap::const_iterator iter = mount_point_map_.begin(); + iter != mount_point_map_.end(); + ++iter) { + GrantFileAccessToExtension(extension_id, FilePath(iter->first)); + } +} + +void CrosMountPointProvider::GrantFileAccessToExtension( + const std::string& extension_id, const FilePath& virtual_path) { + // All we care about here is access from extensions for now. + DCHECK(special_storage_policy_->IsFileHandler(extension_id)); + if (!special_storage_policy_->IsFileHandler(extension_id)) + return; + file_access_permissions_->GrantAccessPermission(extension_id, virtual_path); +} + +void CrosMountPointProvider::RevokeAccessForExtension( + const std::string& extension_id) { + file_access_permissions_->RevokePermissions(extension_id); +} + +std::vector<FilePath> CrosMountPointProvider::GetRootDirectories() const { + std::vector<FilePath> root_dirs; + for (MountPointMap::const_iterator iter = mount_point_map_.begin(); + iter != mount_point_map_.end(); + ++iter) { + root_dirs.push_back(iter->second.Append(iter->first)); + } + return root_dirs; } } // namespace chromeos diff --git a/webkit/chromeos/fileapi/cros_mount_point_provider.h b/webkit/chromeos/fileapi/cros_mount_point_provider.h index 5ac8f37..23af15f 100644 --- a/webkit/chromeos/fileapi/cros_mount_point_provider.h +++ b/webkit/chromeos/fileapi/cros_mount_point_provider.h @@ -6,51 +6,56 @@ #define WEBKIT_CHROMEOS_FILEAPI_CROS_MOUNT_POINT_PROVIDER_H_ #include <map> -#include <set> #include <string> +#include <vector> +#include "base/file_path.h" #include "webkit/fileapi/file_system_mount_point_provider.h" #include "webkit/quota/special_storage_policy.h" namespace chromeos { +class FileAccessPermissions; + // An interface to provide local filesystem paths. class CrosMountPointProvider - : public fileapi::FileSystemMountPointProvider { + : public fileapi::ExternalFileSystemMountPointProvider { public: CrosMountPointProvider( scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy); virtual ~CrosMountPointProvider(); // fileapi::FileSystemMountPointProvider overrides. - virtual bool IsAccessAllowed(const GURL& origin_url) OVERRIDE; - + virtual bool IsAccessAllowed(const GURL& origin_url, + fileapi::FileSystemType type, + const FilePath& virtual_path) OVERRIDE; virtual void GetFileSystemRootPath( const GURL& origin_url, fileapi::FileSystemType type, bool create, fileapi::FileSystemPathManager::GetRootPathCallback* callback) OVERRIDE; - virtual FilePath GetFileSystemRootPathOnFileThread( const GURL& origin_url, fileapi::FileSystemType type, const FilePath& virtual_path, bool create); - virtual bool IsRestrictedFileName(const FilePath& filename) const OVERRIDE; + virtual std::vector<FilePath> GetRootDirectories() const OVERRIDE; + + // fileapi::ExternalFileSystemMountPointProvider overrides. + virtual void GrantFullAccessToExtension( + const std::string& extension_id) OVERRIDE; + virtual void GrantFileAccessToExtension( + const std::string& extension_id, const FilePath& virtual_path) OVERRIDE; + void RevokeAccessForExtension(const std::string& extension_id) OVERRIDE; private: class GetFileSystemRootPathTask; - typedef std::map<std::string, std::string> MountPointMap; + typedef std::map<std::string, FilePath> MountPointMap; - static const char kLocalDirName[]; - static const char kLocalName[]; - FilePath virtual_root_path_; - FilePath base_path_; - std::string local_dir_name_; MountPointMap mount_point_map_; scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_; - + scoped_ptr<FileAccessPermissions> file_access_permissions_; DISALLOW_COPY_AND_ASSIGN(CrosMountPointProvider); }; diff --git a/webkit/chromeos/fileapi/file_access_permissions.cc b/webkit/chromeos/fileapi/file_access_permissions.cc new file mode 100644 index 0000000..6ab5a04 --- /dev/null +++ b/webkit/chromeos/fileapi/file_access_permissions.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/chromeos/fileapi/file_access_permissions.h" + +#include "base/command_line.h" +#include "base/logging.h" + +namespace chromeos { + +FileAccessPermissions::FileAccessPermissions() {} + +FileAccessPermissions::~FileAccessPermissions() {} + + +void FileAccessPermissions::GrantAccessPermission( + const std::string& extension_id, const FilePath& path) { + base::AutoLock locker(lock_); + PathAccessMap::iterator path_map_iter = path_map_.find(extension_id); + if (path_map_iter == path_map_.end()) { + PathSet path_set; + path_set.insert(path); + path_map_.insert(PathAccessMap::value_type(extension_id, path_set)); + } else { + if (path_map_iter->second.find(path) != path_map_iter->second.end()) + return; + path_map_iter->second.insert(path); + } +} + +bool FileAccessPermissions::HasAccessPermission( + const std::string& extension_id, const FilePath& path) { + base::AutoLock locker(lock_); + PathAccessMap::const_iterator path_map_iter = path_map_.find(extension_id); + if (path_map_iter == path_map_.end()) + return false; + + // Check this file and walk up its directory tree to find if this extension + // has access to it. + FilePath current_path = path.StripTrailingSeparators(); + FilePath last_path; + while (current_path != last_path) { + if (path_map_iter->second.find(current_path) != path_map_iter->second.end()) + return true; + last_path = current_path; + current_path = current_path.DirName(); + } + return false; +} + +void FileAccessPermissions::RevokePermissions( + const std::string& extension_id) { + base::AutoLock locker(lock_); + path_map_.erase(extension_id); +} + +} diff --git a/webkit/chromeos/fileapi/file_access_permissions.h b/webkit/chromeos/fileapi/file_access_permissions.h new file mode 100644 index 0000000..e946634 --- /dev/null +++ b/webkit/chromeos/fileapi/file_access_permissions.h @@ -0,0 +1,44 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_ +#define WEBKIT_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_ +#pragma once + +#include <map> +#include <set> +#include <string> + +#include "base/file_path.h" +#include "base/synchronization/lock.h" + +class Extension; + +namespace chromeos { + +class FileAccessPermissions { + public: + FileAccessPermissions(); + virtual ~FileAccessPermissions(); + + // Grants |extension_id| access to |path|. + void GrantAccessPermission(const std::string& extension_id, + const FilePath& path); + // Checks id |extension_id| has permission to access to |path|. + bool HasAccessPermission(const std::string& extension_id, + const FilePath& path); + // Revokes all file permissions for |extension_id|. + void RevokePermissions(const std::string& extension_id); + + private: + typedef std::set<FilePath> PathSet; + typedef std::map<std::string, PathSet> PathAccessMap; + + base::Lock lock_; // Synchronize all access to path_map_. + PathAccessMap path_map_; +}; + +}; + +#endif // WEBKIT_CHROMEOS_FILEAPI_FILE_ACCESS_PERMISSIONS_H_ diff --git a/webkit/chromeos/fileapi/file_access_permissions_unittest.cc b/webkit/chromeos/fileapi/file_access_permissions_unittest.cc new file mode 100644 index 0000000..b3efbfe --- /dev/null +++ b/webkit/chromeos/fileapi/file_access_permissions_unittest.cc @@ -0,0 +1,67 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/chromeos/fileapi/file_access_permissions.h" +#include "testing/gtest/include/gtest/gtest.h" + + +class FileAccessPermissionsTest : public testing::Test { +}; + +TEST_F(FileAccessPermissionsTest, FileAccessChecks) { +#if defined(OS_WIN) + FilePath good_dir(FILE_PATH_LITERAL("c:\\root\\dir")); + FilePath bad_dir(FILE_PATH_LITERAL("c:\\root")); + FilePath good_file(FILE_PATH_LITERAL("c:\\root\\dir\\good_file.txt")); + FilePath bad_file(FILE_PATH_LITERAL("c:\\root\\dir\\bad_file.txt")); +#elif defined(OS_POSIX) + FilePath good_dir(FILE_PATH_LITERAL("/root/dir")); + FilePath bad_dir(FILE_PATH_LITERAL("/root")); + FilePath good_file(FILE_PATH_LITERAL("/root/dir/good_file.txt")); + FilePath bad_file(FILE_PATH_LITERAL("/root/dir/bad_file.txt")); +#endif + std::string extension1("ddammdhioacbehjngdmkjcjbnfginlla"); + std::string extension2("jkhdjkhkhsdkfhsdkhrterwmtermeter"); + + chromeos::FileAccessPermissions permissions; + // By default extension have no access to any local file. + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); + + // After granting file access to the handler extension for a given file, it + // can only access that file an nothing else. + permissions.GrantAccessPermission(extension1, good_file); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_TRUE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); + + + // After granting file access to the handler extension for a given directory, + // it can access that directory and all files within it. + permissions.GrantAccessPermission(extension2, good_dir); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_TRUE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); + + // After revoking rights for extensions, they should not be able to access + // any file system element anymore. + permissions.RevokePermissions(extension1); + permissions.RevokePermissions(extension2); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension1, bad_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_dir)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, good_file)); + EXPECT_FALSE(permissions.HasAccessPermission(extension2, bad_file)); +} diff --git a/webkit/database/database_tracker_unittest.cc b/webkit/database/database_tracker_unittest.cc index 0ce65d8..4ba3a54 100644 --- a/webkit/database/database_tracker_unittest.cc +++ b/webkit/database/database_tracker_unittest.cc @@ -30,7 +30,7 @@ class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy { return false; } - virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) { + virtual bool IsFileHandler(const std::string& extension_id) { return false; } }; diff --git a/webkit/fileapi/file_system_context_unittest.cc b/webkit/fileapi/file_system_context_unittest.cc index 932ba33..f1fff68 100644 --- a/webkit/fileapi/file_system_context_unittest.cc +++ b/webkit/fileapi/file_system_context_unittest.cc @@ -34,7 +34,7 @@ class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy { return origin == GURL(kTestOrigins[1]); } - virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) { + virtual bool IsFileHandler(const std::string& extension_id) { return false; } }; diff --git a/webkit/fileapi/file_system_mount_point_provider.h b/webkit/fileapi/file_system_mount_point_provider.h index 3210331..e331991 100644 --- a/webkit/fileapi/file_system_mount_point_provider.h +++ b/webkit/fileapi/file_system_mount_point_provider.h @@ -5,6 +5,9 @@ #ifndef WEBKIT_FILEAPI_FILE_SYSTEM_MOUNT_POINT_PROVIDER_H_ #define WEBKIT_FILEAPI_FILE_SYSTEM_MOUNT_POINT_PROVIDER_H_ +#include <string> +#include <vector> + #include "base/file_path.h" #include "googleurl/src/gurl.h" #include "webkit/fileapi/file_system_path_manager.h" @@ -18,8 +21,10 @@ class FileSystemMountPointProvider { public: virtual ~FileSystemMountPointProvider() {} - // Checks if mount point access is allowed from |origin_url|. - virtual bool IsAccessAllowed(const GURL& origin_url) = 0; + // Checks if access to |virtual_path| is allowed from |origin_url|. + virtual bool IsAccessAllowed(const GURL& origin_url, + FileSystemType type, + const FilePath& virtual_path) = 0; // Retrieves the root path for the given |origin_url| and |type|, and // calls the given |callback| with the root path and name. @@ -41,6 +46,27 @@ class FileSystemMountPointProvider { // Checks if a given |name| contains any restricted names/chars in it. // Callable on any thread. virtual bool IsRestrictedFileName(const FilePath& filename) const = 0; + + // Returns the list of top level directories that are exposed by this + // provider. This list is used to set appropriate child process file access + // permissions. + virtual std::vector<FilePath> GetRootDirectories() const = 0; +}; + +// An interface to control external file system access permissions. +class ExternalFileSystemMountPointProvider + : public FileSystemMountPointProvider { + public: + // Grant access to all external file system from extension identified with + // |extension_id|. + virtual void GrantFullAccessToExtension(const std::string& extension_id) = 0; + // Grants access to |virtual_path| from |origin_url|. + virtual void GrantFileAccessToExtension( + const std::string& extension_id, + const FilePath& virtual_path) = 0; + // Revoke file access from extension identified with |extension_id|. + virtual void RevokeAccessForExtension( + const std::string& extension_id) = 0; }; } // namespace fileapi diff --git a/webkit/fileapi/file_system_operation.cc b/webkit/fileapi/file_system_operation.cc index e242e86..15f8955 100644 --- a/webkit/fileapi/file_system_operation.cc +++ b/webkit/fileapi/file_system_operation.cc @@ -626,8 +626,8 @@ bool FileSystemOperation::VerifyFileSystemPathForRead( dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); return false; } - if (!file_system_context()->path_manager()->IsAllowedFileSystemType( - *origin_url, *type)) { + if (!file_system_context()->path_manager()->IsAccessAllowed( + *origin_url, *type, *virtual_path)) { dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); return false; } @@ -663,8 +663,8 @@ bool FileSystemOperation::VerifyFileSystemPathForWrite( dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); return false; } - if (!file_system_context()->path_manager()->IsAllowedFileSystemType( - *origin_url, *type)) { + if (!file_system_context()->path_manager()->IsAccessAllowed( + *origin_url, *type, *virtual_path)) { dispatcher_->DidFail(base::PLATFORM_FILE_ERROR_SECURITY); return false; } diff --git a/webkit/fileapi/file_system_path_manager.cc b/webkit/fileapi/file_system_path_manager.cc index 16fc60b..cefdab8 100644 --- a/webkit/fileapi/file_system_path_manager.cc +++ b/webkit/fileapi/file_system_path_manager.cc @@ -47,7 +47,7 @@ FileSystemPathManager::FileSystemPathManager( file_message_loop, profile_path)) { #if defined(OS_CHROMEOS) - local_provider_.reset( + external_provider_.reset( new chromeos::CrosMountPointProvider(special_storage_policy)); #endif } @@ -64,9 +64,9 @@ void FileSystemPathManager::GetFileSystemRootPath( sandbox_provider_->GetFileSystemRootPath( origin_url, type, create, callback_ptr); break; - case kFileSystemTypeLocal: - if (local_provider_.get()) { - local_provider_->GetFileSystemRootPath( + case kFileSystemTypeExternal: + if (external_provider_.get()) { + external_provider_->GetFileSystemRootPath( origin_url, type, create, callback_ptr); } else { callback_ptr->Run(false, FilePath(), std::string()); @@ -88,9 +88,9 @@ FilePath FileSystemPathManager::GetFileSystemRootPathOnFileThread( return sandbox_provider_->GetFileSystemRootPathOnFileThread( origin_url, type, virtual_path, create); break; - case kFileSystemTypeLocal: - return local_provider_.get() ? - local_provider_->GetFileSystemRootPathOnFileThread( + case kFileSystemTypeExternal: + return external_provider_.get() ? + external_provider_->GetFileSystemRootPathOnFileThread( origin_url, type, virtual_path, create) : FilePath(); case kFileSystemTypeUnknown: @@ -112,9 +112,11 @@ bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const { std::string FileSystemPathManager::GetFileSystemTypeString( fileapi::FileSystemType type) { if (type == fileapi::kFileSystemTypeTemporary) - return fileapi::SandboxMountPointProvider::kTemporaryName; + return fileapi::kTemporaryName; else if (type == fileapi::kFileSystemTypePersistent) - return fileapi::SandboxMountPointProvider::kPersistentName; + return fileapi::kPersistentName; + else if (type == fileapi::kFileSystemTypeExternal) + return fileapi::kExternalName; return std::string(); } @@ -125,9 +127,9 @@ bool FileSystemPathManager::IsRestrictedFileName( case kFileSystemTypeTemporary: case kFileSystemTypePersistent: return sandbox_provider_->IsRestrictedFileName(filename); - case kFileSystemTypeLocal: - return local_provider_.get() ? - local_provider_->IsRestrictedFileName(filename) : true; + case kFileSystemTypeExternal: + return external_provider_.get() ? + external_provider_->IsRestrictedFileName(filename) : true; case kFileSystemTypeUnknown: default: NOTREACHED(); @@ -136,17 +138,17 @@ bool FileSystemPathManager::IsRestrictedFileName( } // Checks if an origin has access to a particular filesystem type. -bool FileSystemPathManager::IsAllowedFileSystemType( - GURL origin, FileSystemType type) { +bool FileSystemPathManager::IsAccessAllowed( + const GURL& origin, FileSystemType type, const FilePath& virtual_path) { switch (type) { case kFileSystemTypeTemporary: case kFileSystemTypePersistent: - if (!sandbox_provider_->IsAccessAllowed(origin)) + if (!sandbox_provider_->IsAccessAllowed(origin, type, virtual_path)) return false; break; - case kFileSystemTypeLocal: - if (!local_provider_.get() || - !local_provider_->IsAccessAllowed(origin)) { + case kFileSystemTypeExternal: + if (!external_provider_.get() || + !external_provider_->IsAccessAllowed(origin, type, virtual_path)) { return false; } break; @@ -164,3 +166,5 @@ COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \ int(fileapi::kFileSystemTypeTemporary), mismatching_enums); COMPILE_ASSERT(int(WebFileSystem::TypePersistent) == \ int(fileapi::kFileSystemTypePersistent), mismatching_enums); +COMPILE_ASSERT(int(WebFileSystem::TypeExternal) == \ + int(fileapi::kFileSystemTypeExternal), mismatching_enums); diff --git a/webkit/fileapi/file_system_path_manager.h b/webkit/fileapi/file_system_path_manager.h index 19718ae..f914a7d 100644 --- a/webkit/fileapi/file_system_path_manager.h +++ b/webkit/fileapi/file_system_path_manager.h @@ -20,7 +20,7 @@ class MessageLoopProxy; namespace fileapi { -class FileSystemMountPointProvider; +class ExternalFileSystemMountPointProvider; class SandboxMountPointProvider; // TODO(kinuko): Probably this module must be called FileSystemPathUtil @@ -81,13 +81,19 @@ class FileSystemPathManager { bool IsRestrictedFileName(FileSystemType type, const FilePath& filename); - // Checks if an origin has access to a particular filesystem type. - bool IsAllowedFileSystemType(GURL origin, FileSystemType type); + // Checks if an origin has access to a particular filesystem type and + // file element represented by |virtual_path|. + bool IsAccessAllowed(const GURL& origin, FileSystemType type, + const FilePath& virtual_path); SandboxMountPointProvider* sandbox_provider() const { return sandbox_provider_.get(); } + ExternalFileSystemMountPointProvider* external_provider() const { + return external_provider_.get(); + } + bool is_incognito() const { return is_incognito_; } @@ -96,7 +102,7 @@ class FileSystemPathManager { const bool is_incognito_; const bool allow_file_access_from_files_; scoped_ptr<SandboxMountPointProvider> sandbox_provider_; - scoped_ptr<FileSystemMountPointProvider> local_provider_; + scoped_ptr<ExternalFileSystemMountPointProvider> external_provider_; DISALLOW_COPY_AND_ASSIGN(FileSystemPathManager); }; diff --git a/webkit/fileapi/file_system_path_manager_unittest.cc b/webkit/fileapi/file_system_path_manager_unittest.cc index 8a99b84..dbdef10 100644 --- a/webkit/fileapi/file_system_path_manager_unittest.cc +++ b/webkit/fileapi/file_system_path_manager_unittest.cc @@ -173,7 +173,7 @@ class TestSpecialStoragePolicy : public quota::SpecialStoragePolicy { return true; } - virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) { + virtual bool IsFileHandler(const std::string& extension_id) { return true; } }; diff --git a/webkit/fileapi/file_system_types.h b/webkit/fileapi/file_system_types.h index 8b7fe01..cfd2cb1 100644 --- a/webkit/fileapi/file_system_types.h +++ b/webkit/fileapi/file_system_types.h @@ -10,7 +10,7 @@ namespace fileapi { enum FileSystemType { kFileSystemTypeTemporary, kFileSystemTypePersistent, - kFileSystemTypeLocal, + kFileSystemTypeExternal, kFileSystemTypeUnknown, }; diff --git a/webkit/fileapi/file_system_util.cc b/webkit/fileapi/file_system_util.cc index 75013da..f3e6278 100644 --- a/webkit/fileapi/file_system_util.cc +++ b/webkit/fileapi/file_system_util.cc @@ -15,9 +15,13 @@ namespace fileapi { -static const char kPersistentDir[] = "/persistent/"; -static const char kTemporaryDir[] = "/temporary/"; -static const char kLocalDir[] = "/local/"; +const char kPersistentDir[] = "/persistent/"; +const char kTemporaryDir[] = "/temporary/"; +const char kExternalDir[] = "/external/"; + +const char kPersistentName[] = "Persistent"; +const char kTemporaryName[] = "Temporary"; +const char kExternalName[] = "External"; bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type, FilePath* file_path) { @@ -77,9 +81,9 @@ bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type, } else if (path.compare(0, strlen(kTemporaryDir), kTemporaryDir) == 0) { file_system_type = kFileSystemTypeTemporary; path = path.substr(strlen(kTemporaryDir)); - } else if (path.compare(0, strlen(kLocalDir), kLocalDir) == 0) { - file_system_type = kFileSystemTypeLocal; - path = path.substr(strlen(kLocalDir)); + } else if (path.compare(0, strlen(kExternalDir), kExternalDir) == 0) { + file_system_type = kFileSystemTypeExternal; + path = path.substr(strlen(kExternalDir)); } else { return false; } @@ -114,8 +118,8 @@ GURL GetFileSystemRootURI( case kFileSystemTypePersistent: path += (kPersistentDir + 1); // We don't want the leading slash. break; - case kFileSystemTypeLocal: - path += (kLocalDir + 1); // We don't want the leading slash. + case kFileSystemTypeExternal: + path += (kExternalDir + 1); // We don't want the leading slash. break; default: NOTREACHED(); diff --git a/webkit/fileapi/file_system_util.h b/webkit/fileapi/file_system_util.h index b858c1b..272e432 100644 --- a/webkit/fileapi/file_system_util.h +++ b/webkit/fileapi/file_system_util.h @@ -13,6 +13,13 @@ class GURL; namespace fileapi { +extern const char kPersistentDir[]; +extern const char kTemporaryDir[]; +extern const char kExternalDir[]; +extern const char kPersistentName[]; +extern const char kTemporaryName[]; +extern const char kExternalName[]; + // The file_path this returns will be using '/' as a path separator, no matter // what platform you're on. bool CrackFileSystemURL(const GURL& url, GURL* origin_url, FileSystemType* type, diff --git a/webkit/fileapi/sandbox_mount_point_provider.cc b/webkit/fileapi/sandbox_mount_point_provider.cc index 5768ed9..5e80296 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.cc +++ b/webkit/fileapi/sandbox_mount_point_provider.cc @@ -111,9 +111,6 @@ namespace fileapi { const FilePath::CharType SandboxMountPointProvider::kFileSystemDirectory[] = FILE_PATH_LITERAL("FileSystem"); -const char SandboxMountPointProvider::kPersistentName[] = "Persistent"; -const char SandboxMountPointProvider::kTemporaryName[] = "Temporary"; - SandboxMountPointProvider::SandboxMountPointProvider( FileSystemPathManager* path_manager, scoped_refptr<base::MessageLoopProxy> file_message_loop, @@ -126,7 +123,11 @@ SandboxMountPointProvider::SandboxMountPointProvider( SandboxMountPointProvider::~SandboxMountPointProvider() { } -bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url) { +bool SandboxMountPointProvider::IsAccessAllowed(const GURL& origin_url, + FileSystemType type, + const FilePath& unused) { + if (type != kFileSystemTypeTemporary && type != kFileSystemTypePersistent) + return false; // We essentially depend on quota to do our access controls. return path_manager_->IsAllowedScheme(origin_url); } @@ -211,6 +212,14 @@ bool SandboxMountPointProvider::IsRestrictedFileName(const FilePath& filename) return false; } +std::vector<FilePath> SandboxMountPointProvider::GetRootDirectories() const { + NOTREACHED(); + // TODO(ericu): Implement this method and check for access permissions as + // fileBrowserPrivate extension API does. We currently have another mechanism, + // but we should switch over. + return std::vector<FilePath>(); +} + void SandboxMountPointProvider::GetFileSystemRootPath( const GURL& origin_url, fileapi::FileSystemType type, bool create, FileSystemPathManager::GetRootPathCallback* callback_ptr) { @@ -278,12 +287,12 @@ std::string SandboxMountPointProvider::OriginEnumerator::Next() { bool SandboxMountPointProvider::OriginEnumerator::HasTemporary() { return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII( - SandboxMountPointProvider::kTemporaryName)); + fileapi::kTemporaryName)); } bool SandboxMountPointProvider::OriginEnumerator::HasPersistent() { return !current_.empty() && file_util::DirectoryExists(current_.AppendASCII( - SandboxMountPointProvider::kPersistentName)); + fileapi::kPersistentName)); } bool SandboxMountPointProvider::GetOriginBasePathAndName( diff --git a/webkit/fileapi/sandbox_mount_point_provider.h b/webkit/fileapi/sandbox_mount_point_provider.h index be85f77..51a9414 100644 --- a/webkit/fileapi/sandbox_mount_point_provider.h +++ b/webkit/fileapi/sandbox_mount_point_provider.h @@ -6,6 +6,7 @@ #define WEBKIT_FILEAPI_SANDBOX_MOUNT_POINT_PROVIDER_H_ #include <string> +#include <vector> #include "base/file_path.h" #include "googleurl/src/gurl.h" @@ -28,8 +29,10 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider { const FilePath& profile_path); virtual ~SandboxMountPointProvider(); - // Checks if mount point access is allowed from |origin_url|. - virtual bool IsAccessAllowed(const GURL& origin_url); + // Checks if access to |virtual_path| is allowed from |origin_url|. + virtual bool IsAccessAllowed(const GURL& origin_url, + FileSystemType type, + const FilePath& virtual_path); // Retrieves the root path for the given |origin_url| and |type|, and // calls the given |callback| with the root path and name. @@ -51,9 +54,6 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider { // The FileSystem directory name. static const FilePath::CharType kFileSystemDirectory[]; - static const char kPersistentName[]; - static const char kTemporaryName[]; - const FilePath& base_path() const { return base_path_; } @@ -61,6 +61,8 @@ class SandboxMountPointProvider : public FileSystemMountPointProvider { // Checks if a given |name| contains any restricted names/chars in it. virtual bool IsRestrictedFileName(const FilePath& filename) const; + virtual std::vector<FilePath> GetRootDirectories() const; + // Returns the origin identifier string, which is used as a part of the // sandboxed path component, for the given |url|. static std::string GetOriginIdentifierFromURL(const GURL& url); diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index b9c79ec..ca25491 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -58,6 +58,9 @@ ['chromeos==1', { 'sources': [ '../chromeos/fileapi/cros_mount_point_provider.cc', + '../chromeos/fileapi/cros_mount_point_provider.h', + '../chromeos/fileapi/file_access_permissions.cc', + '../chromeos/fileapi/file_access_permissions.h', ], }], ], diff --git a/webkit/quota/special_storage_policy.h b/webkit/quota/special_storage_policy.h index e694c4c..d9f1728 100644 --- a/webkit/quota/special_storage_policy.h +++ b/webkit/quota/special_storage_policy.h @@ -5,6 +5,8 @@ #ifndef WEBKIT_QUOTA_SPECIAL_STORAGE_POLICY_H_ #define WEBKIT_QUOTA_SPECIAL_STORAGE_POLICY_H_ +#include <string> + #include "base/memory/ref_counted.h" class GURL; @@ -27,8 +29,9 @@ class SpecialStoragePolicy // Unlimited storage is not subject to 'quotas'. virtual bool IsStorageUnlimited(const GURL& origin) = 0; - // Local file system access allowed via File API. - virtual bool IsLocalFileSystemAccessAllowed(const GURL& origin) = 0; + // Checks if extension identified with |extension_id| is registered as + // file handler. + virtual bool IsFileHandler(const std::string& extension_id) = 0; protected: friend class base::RefCountedThreadSafe<SpecialStoragePolicy>; diff --git a/webkit/tools/test_shell/simple_file_system.cc b/webkit/tools/test_shell/simple_file_system.cc index ff634eeb..6baa1a9 100644 --- a/webkit/tools/test_shell/simple_file_system.cc +++ b/webkit/tools/test_shell/simple_file_system.cc @@ -155,6 +155,8 @@ void SimpleFileSystem::OpenFileSystem( type = fileapi::kFileSystemTypeTemporary; else if (web_filesystem_type == WebFileSystem::TypePersistent) type = fileapi::kFileSystemTypePersistent; + else if (web_filesystem_type == WebFileSystem::TypeExternal) + type = fileapi::kFileSystemTypeExternal; else { // Unknown type filesystem is requested. callbacks->didFail(WebKit::WebFileErrorSecurity); diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi index ddde626..8ce59cc 100644 --- a/webkit/tools/test_shell/test_shell.gypi +++ b/webkit/tools/test_shell/test_shell.gypi @@ -462,6 +462,11 @@ '../../../skia/ext/platform_canvas_unittest.cc', ], }], + ['chromeos==1', { + 'sources': [ + '../../chromeos/fileapi/file_access_permissions_unittest.cc', + ], + }], ['OS=="mac"', { # mac tests load the resources from the built test_shell beside the # test |