diff options
author | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-16 04:01:08 +0000 |
---|---|---|
committer | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-16 04:01:08 +0000 |
commit | b777b3386e10d38944cc717e4192b7858cbdc7fe (patch) | |
tree | 85d37a15e729df855d81e0973d9ed1bb3f90d347 /webkit/chromeos | |
parent | 4b59a325a589190ab95622be4e1b6a70bc02914f (diff) | |
download | chromium_src-b777b3386e10d38944cc717e4192b7858cbdc7fe.zip chromium_src-b777b3386e10d38944cc717e4192b7858cbdc7fe.tar.gz chromium_src-b777b3386e10d38944cc717e4192b7858cbdc7fe.tar.bz2 |
File API changes needed for safely passing user selected file entities from the file browser component extension to a 3rd party extension.
BUG=chromium-os:11996
TEST=FileAccessPermissionsTest.FileAccessChecks
Review URL: http://codereview.chromium.org/6810037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81860 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/chromeos')
5 files changed, 245 insertions, 43 deletions
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)); +} |