diff options
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 12 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 9 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_dispatcher_host.cc | 34 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_dispatcher_host.h | 11 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_host_context.cc | 119 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_host_context.h | 29 | ||||
-rw-r--r-- | chrome/browser/file_system/file_system_host_context_unittest.cc | 3 | ||||
-rw-r--r-- | webkit/fileapi/file_system_quota.cc | 35 | ||||
-rw-r--r-- | webkit/fileapi/file_system_quota.h | 42 | ||||
-rw-r--r-- | webkit/fileapi/file_system_quota_unittest.cc | 146 | ||||
-rw-r--r-- | webkit/fileapi/webkit_fileapi.gypi | 2 | ||||
-rw-r--r-- | webkit/glue/webkit_glue.cc | 4 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_shell.gypi | 1 |
13 files changed, 434 insertions, 13 deletions
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 286a283..457be14 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -1168,6 +1168,12 @@ void ExtensionsService::GrantUnlimitedStorage(Extension* extension) { &ChromeAppCacheService::SetOriginQuotaInMemory, origin, kint64max)); + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod( + profile_->GetFileSystemHostContext(), + &FileSystemHostContext::SetOriginQuotaUnlimited, + origin)); } } } @@ -1197,6 +1203,12 @@ void ExtensionsService::RevokeUnlimitedStorage(Extension* extension) { profile_->GetAppCacheService(), &ChromeAppCacheService::ResetOriginQuotaInMemory, origin)); + ChromeThread::PostTask( + ChromeThread::IO, FROM_HERE, + NewRunnableMethod( + profile_->GetFileSystemHostContext(), + &FileSystemHostContext::ResetOriginQuotaUnlimited, + origin)); } } } diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc index 7d6733d..7a1c384 100644 --- a/chrome/browser/extensions/extensions_service_unittest.cc +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -23,6 +23,7 @@ #include "base/version.h" #include "chrome/browser/appcache/chrome_appcache_service.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/file_system/file_system_host_context.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_creator.h" #include "chrome/browser/extensions/extension_error_reporter.h" @@ -257,9 +258,17 @@ class ExtensionTestingProfile : public TestingProfile { return appcache_service_; } + virtual FileSystemHostContext* GetFileSystemHostContext() { + if (!file_system_host_context_) + file_system_host_context_ = new FileSystemHostContext( + GetPath(), IsOffTheRecord()); + return file_system_host_context_; + } + private: ExtensionsService* service_; scoped_refptr<ChromeAppCacheService> appcache_service_; + scoped_refptr<FileSystemHostContext> file_system_host_context_; }; // Our message loop may be used in tests which require it to be an IO loop. diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc index b2e9cb6..28ffe03 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.cc +++ b/chrome/browser/file_system/file_system_dispatcher_host.cc @@ -18,6 +18,9 @@ #include "chrome/common/render_messages_params.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_context.h" +#include "webkit/fileapi/file_system_quota.h" + +using fileapi::FileSystemQuota; // A class to hold an ongoing openFileSystem completion task. struct OpenFileSystemCompletionTask { @@ -157,7 +160,8 @@ void FileSystemDispatcherHost::OnOpenFileSystem( void FileSystemDispatcherHost::OnMove( int request_id, const FilePath& src_path, const FilePath& dest_path) { if (!CheckValidFileSystemPath(src_path, request_id) || - !CheckValidFileSystemPath(dest_path, request_id)) + !CheckValidFileSystemPath(dest_path, request_id) || + !CheckQuotaForPath(dest_path, FileSystemQuota::kUnknownSize, request_id)) return; GetNewOperation(request_id)->Move(src_path, dest_path); @@ -166,7 +170,8 @@ void FileSystemDispatcherHost::OnMove( void FileSystemDispatcherHost::OnCopy( int request_id, const FilePath& src_path, const FilePath& dest_path) { if (!CheckValidFileSystemPath(src_path, request_id) || - !CheckValidFileSystemPath(dest_path, request_id)) + !CheckValidFileSystemPath(dest_path, request_id) || + !CheckQuotaForPath(dest_path, FileSystemQuota::kUnknownSize, request_id)) return; GetNewOperation(request_id)->Copy(src_path, dest_path); @@ -189,7 +194,8 @@ void FileSystemDispatcherHost::OnReadMetadata( void FileSystemDispatcherHost::OnCreate( int request_id, const FilePath& path, bool exclusive, bool is_directory, bool recursive) { - if (!CheckValidFileSystemPath(path, request_id)) + if (!CheckValidFileSystemPath(path, request_id) || + !CheckQuotaForPath(path, 0L, request_id)) return; if (is_directory) GetNewOperation(request_id)->CreateDirectory(path, exclusive, recursive); @@ -219,7 +225,8 @@ void FileSystemDispatcherHost::OnWrite( const FilePath& path, const GURL& blob_url, int64 offset) { - if (!CheckValidFileSystemPath(path, request_id)) + if (!CheckValidFileSystemPath(path, request_id) || + !CheckQuotaForPath(path, FileSystemQuota::kUnknownSize, request_id)) return; GetNewOperation(request_id)->Write( request_context_, path, blob_url, offset); @@ -281,6 +288,25 @@ bool FileSystemDispatcherHost::CheckValidFileSystemPath( return true; } +bool FileSystemDispatcherHost::CheckQuotaForPath( + const FilePath& path, int64 growth, int request_id) { + GURL origin_url; + if (!context_->GetOriginFromPath(path, &origin_url)) { + // Appears to be an ill-formed path or for an unallowed scheme. + Send(new ViewMsg_FileSystem_DidFail( + request_id, base::PLATFORM_FILE_ERROR_SECURITY)); + return false; + } + // TODO(kinuko): For operations with kUnknownSize we'll eventually + // need to resolve what amount of size it's going to write. + if (!context_->CheckOriginQuota(origin_url, growth)) { + Send(new ViewMsg_FileSystem_DidFail( + request_id, base::PLATFORM_FILE_ERROR_NO_SPACE)); + return false; + } + return true; +} + fileapi::FileSystemOperation* FileSystemDispatcherHost::GetNewOperation( int request_id) { BrowserFileSystemCallbackDispatcher* dispatcher = diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h index 201ade6..33e6011 100644 --- a/chrome/browser/file_system/file_system_dispatcher_host.h +++ b/chrome/browser/file_system/file_system_dispatcher_host.h @@ -80,10 +80,17 @@ class FileSystemDispatcherHost fileapi::FileSystemOperation* GetNewOperation(int request_id); // Checks the validity of a given |path|. Returns true if the given |path| - // is valid as a path for FileSystem API. Otherwise it sends back a - // security error code to the dispatcher and returns false. + // is valid as a path for FileSystem API. Otherwise it sends back + // PLATFORM_FILE_ERROR_SECURITY to the dispatcher and returns false. bool CheckValidFileSystemPath(const FilePath& path, int request_id); + // Checks the quota for the given |path|. This method only performs a + // in-memory quick check and returns immediately. + // Returns true if the given |path| will be able to grow by |growth|. + // Otherwise it sends back PLATFORM_FILE_ERROR_NO_SPACE to the dispatcher + // and returns false. + bool CheckQuotaForPath(const FilePath& path, int64 growth, int request_id); + // The sender to be used for sending out IPC messages. IPC::Message::Sender* message_sender_; diff --git a/chrome/browser/file_system/file_system_host_context.cc b/chrome/browser/file_system/file_system_host_context.cc index f0cea3b..e7b1f5c 100644 --- a/chrome/browser/file_system/file_system_host_context.cc +++ b/chrome/browser/file_system/file_system_host_context.cc @@ -4,13 +4,23 @@ #include "chrome/browser/file_system/file_system_host_context.h" +#include "base/command_line.h" #include "base/file_util.h" #include "base/logging.h" +#include "base/string_util.h" #include "base/utf_string_conversions.h" +#include "chrome/common/chrome_switches.h" #include "googleurl/src/gurl.h" #include "third_party/WebKit/WebKit/chromium/public/WebCString.h" #include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h" #include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h" +#include "webkit/glue/webkit_glue.h" + +// We use some of WebKit types for conversions between storage identifiers +// and origin URLs. +using WebKit::WebFileSystem; +using WebKit::WebSecurityOrigin; +using WebKit::WebString; const FilePath::CharType FileSystemHostContext::kFileSystemDirectory[] = FILE_PATH_LITERAL("FileSystem"); @@ -18,10 +28,27 @@ const FilePath::CharType FileSystemHostContext::kFileSystemDirectory[] = const char FileSystemHostContext::kPersistentName[] = "Persistent"; const char FileSystemHostContext::kTemporaryName[] = "Temporary"; +namespace { + +static inline std::string FilePathStringToASCII( + const FilePath::StringType& path_string) { +#if defined(OS_WIN) + return WideToASCII(path_string); +#elif defined(OS_POSIX) + return path_string; +#endif +} + +} // anonymous namespace + FileSystemHostContext::FileSystemHostContext( const FilePath& data_path, bool is_incognito) : base_path_(data_path.Append(kFileSystemDirectory)), - is_incognito_(is_incognito) { + is_incognito_(is_incognito), + quota_manager_(new fileapi::FileSystemQuota()) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + allow_file_access_from_files_ = command_line.HasSwitch( + switches::kAllowFileAccessFromFiles); } bool FileSystemHostContext::GetFileSystemRootPath( @@ -30,6 +57,10 @@ bool FileSystemHostContext::GetFileSystemRootPath( // TODO(kinuko): should return an isolated temporary file system space. if (is_incognito_) return false; + + if (!IsAllowedScheme(origin_url)) + return false; + std::string storage_identifier = GetStorageIdentifierFromURL(origin_url); switch (type) { case fileapi::kFileSystemTypeTemporary: @@ -54,7 +85,87 @@ bool FileSystemHostContext::GetFileSystemRootPath( bool FileSystemHostContext::CheckValidFileSystemPath( const FilePath& path) const { // Any paths that includes parent references are considered invalid. - return !path.ReferencesParent() && base_path_.IsParent(path); + if (path.ReferencesParent()) + return false; + + // The path should be a child of the profile FileSystem path. + FilePath relative; + if (!base_path_.AppendRelativePath(path, &relative)) + return false; + + // The relative path from the profile FileSystem path should at least + // contains two components, one for storage identifier and the other for type. + std::vector<FilePath::StringType> components; + relative.GetComponents(&components); + if (components.size() < 2) + return false; + + // The second component of the relative path to the root directory + // must be kPersistent or kTemporary. + if (!IsStringASCII(components[1])) + return false; + std::string ascii_type_component = FilePathStringToASCII(components[1]); + if (ascii_type_component != kPersistentName && + ascii_type_component != kTemporaryName) + return false; + + return true; +} + +bool FileSystemHostContext::GetOriginFromPath( + const FilePath& path, GURL* origin_url) { + DCHECK(origin_url); + FilePath relative; + if (!base_path_.AppendRelativePath(path, &relative)) { + // The path should be a child of the profile's FileSystem path. + return false; + } + std::vector<FilePath::StringType> components; + relative.GetComponents(&components); + if (components.size() < 2) { + // The relative path should at least contain storage identifier and type. + return false; + } + WebSecurityOrigin web_security_origin = + WebSecurityOrigin::createFromDatabaseIdentifier( + webkit_glue::FilePathStringToWebString(components[0])); + *origin_url = GURL(web_security_origin.toString()); + + // We need this work-around for file:/// URIs as + // createFromDatabaseIdentifier returns empty origin_url for them. + if (allow_file_access_from_files_ && origin_url->spec().empty() && + components[0].find(FILE_PATH_LITERAL("file")) == 0) { + *origin_url = GURL("file:///"); + return true; + } + + return IsAllowedScheme(*origin_url); +} + +bool FileSystemHostContext::IsAllowedScheme(const GURL& url) const { + // Basically we only accept http or https. We allow file:// URLs + // only if --allow-file-access-from-files flag is given. + return url.SchemeIs("http") || url.SchemeIs("https") || + (url.SchemeIsFile() && allow_file_access_from_files_); +} + +bool FileSystemHostContext::CheckOriginQuota(const GURL& url, int64 growth) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + // If allow-file-access-from-files flag is explicitly given and the scheme + // is file, always return true. + if (url.SchemeIsFile() && allow_file_access_from_files_) + return true; + return quota_manager_->CheckOriginQuota(url, growth); +} + +void FileSystemHostContext::SetOriginQuotaUnlimited(const GURL& url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + quota_manager_->SetOriginQuotaUnlimited(url); +} + +void FileSystemHostContext::ResetOriginQuotaUnlimited(const GURL& url) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + quota_manager_->ResetOriginQuotaUnlimited(url); } std::string FileSystemHostContext::GetStorageIdentifierFromURL( @@ -64,7 +175,7 @@ std::string FileSystemHostContext::GetStorageIdentifierFromURL( return web_security_origin.databaseIdentifier().utf8(); } -COMPILE_ASSERT(int(WebKit::WebFileSystem::TypeTemporary) == \ +COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \ int(fileapi::kFileSystemTypeTemporary), mismatching_enums); -COMPILE_ASSERT(int(WebKit::WebFileSystem::TypePersistent) == \ +COMPILE_ASSERT(int(WebFileSystem::TypePersistent) == \ int(fileapi::kFileSystemTypePersistent), mismatching_enums); diff --git a/chrome/browser/file_system/file_system_host_context.h b/chrome/browser/file_system/file_system_host_context.h index e651a43..a1141c0 100644 --- a/chrome/browser/file_system/file_system_host_context.h +++ b/chrome/browser/file_system/file_system_host_context.h @@ -6,8 +6,11 @@ #define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_ #include "base/file_path.h" +#include "base/gtest_prod_util.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" +#include "chrome/browser/chrome_thread.h" +#include "webkit/fileapi/file_system_quota.h" #include "webkit/fileapi/file_system_types.h" class GURL; @@ -15,7 +18,8 @@ class GURL; // This is owned by profile and shared by all the FileSystemDispatcherHost // that shared by the same profile. class FileSystemHostContext - : public base::RefCountedThreadSafe<FileSystemHostContext> { + : public base::RefCountedThreadSafe<FileSystemHostContext, + BrowserThread::DeleteOnIOThread> { public: FileSystemHostContext(const FilePath& data_path, bool is_incognito); const FilePath& base_path() const { return base_path_; } @@ -32,8 +36,19 @@ class FileSystemHostContext // Check if the given |path| is in the FileSystem base directory. bool CheckValidFileSystemPath(const FilePath& path) const; - // Returns the storage identifier string for the given |url|. - static std::string GetStorageIdentifierFromURL(const GURL& url); + // Retrieves the origin URL for the given |path| and populates + // |origin_url|. It returns false when the given |path| is not a + // valid filesystem path. + bool GetOriginFromPath(const FilePath& path, GURL* origin_url); + + // Returns true if the given |url|'s scheme is allowed to access + // filesystem. + bool IsAllowedScheme(const GURL& url) const; + + // Quota related methods. + bool CheckOriginQuota(const GURL& url, int64 growth); + void SetOriginQuotaUnlimited(const GURL& url); + void ResetOriginQuotaUnlimited(const GURL& url); // The FileSystem directory name. static const FilePath::CharType kFileSystemDirectory[]; @@ -42,8 +57,16 @@ class FileSystemHostContext static const char kTemporaryName[]; private: + // Returns the storage identifier string for the given |url|. + static std::string GetStorageIdentifierFromURL(const GURL& url); + const FilePath base_path_; const bool is_incognito_; + bool allow_file_access_from_files_; + + scoped_ptr<fileapi::FileSystemQuota> quota_manager_; + + FRIEND_TEST_ALL_PREFIXES(FileSystemHostContextTest, GetOriginFromPath); DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemHostContext); }; diff --git a/chrome/browser/file_system/file_system_host_context_unittest.cc b/chrome/browser/file_system/file_system_host_context_unittest.cc index 3837e00..f91bb04 100644 --- a/chrome/browser/file_system/file_system_host_context_unittest.cc +++ b/chrome/browser/file_system/file_system_host_context_unittest.cc @@ -37,6 +37,9 @@ const struct RootPathTest { false, "" }, { fileapi::kFileSystemTypePersistent, true, "http://host:4/", false, "" }, + // We disallow file:// URIs to access filesystem. + { fileapi::kFileSystemTypeTemporary, false, "file:///some/path", false, "" }, + { fileapi::kFileSystemTypePersistent, false, "file:///some/path", false, "" }, }; const struct CheckValidPathTest { diff --git a/webkit/fileapi/file_system_quota.cc b/webkit/fileapi/file_system_quota.cc new file mode 100644 index 0000000..eb69beb --- /dev/null +++ b/webkit/fileapi/file_system_quota.cc @@ -0,0 +1,35 @@ +// Copyright (c) 2010 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/file_system_quota.h" + +#include "base/file_path.h" +#include "base/file_util_proxy.h" +#include "base/ref_counted.h" +#include "base/scoped_callback_factory.h" + +namespace fileapi { + +const int64 FileSystemQuota::kUnknownSize = -1; + +bool FileSystemQuota::CheckOriginQuota(const GURL& origin, int64) { + return CheckIfOriginGrantedUnlimitedQuota(origin); +} + +void FileSystemQuota::SetOriginQuotaUnlimited(const GURL& origin) { + DCHECK(origin == origin.GetOrigin()); + unlimited_quota_origins_.insert(origin); +} + +void FileSystemQuota::ResetOriginQuotaUnlimited(const GURL& origin) { + DCHECK(origin == origin.GetOrigin()); + unlimited_quota_origins_.erase(origin); +} + +bool FileSystemQuota::CheckIfOriginGrantedUnlimitedQuota(const GURL& origin) { + std::set<GURL>::const_iterator found = unlimited_quota_origins_.find(origin); + return (found != unlimited_quota_origins_.end()); +} + +} // namespace fileapi diff --git a/webkit/fileapi/file_system_quota.h b/webkit/fileapi/file_system_quota.h new file mode 100644 index 0000000..80888ed1 --- /dev/null +++ b/webkit/fileapi/file_system_quota.h @@ -0,0 +1,42 @@ +// Copyright (c) 2010 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_FILE_SYSTEM_QUOTA_H_ +#define WEBKIT_FILEAPI_FILE_SYSTEM_QUOTA_H_ + +#include <set> + +#include "base/basictypes.h" +#include "googleurl/src/gurl.h" + +namespace fileapi { + +// A quota manager for FileSystem. For now it has little implementation +// and just allows unlimited quota for apps. +class FileSystemQuota { + public: + FileSystemQuota() { } + static const int64 kUnknownSize; + + // Checks if the origin can grow its usage by |growth| bytes. + // This only performs in-memory check and returns immediately. + // For now it just returns false for any origins (regardless of the size) + // that are not in the in-memory unlimited_quota_origins map. + bool CheckOriginQuota(const GURL& origin, int64 growth); + + // Maintains origins in memory that are allowed to have unlimited quota. + void SetOriginQuotaUnlimited(const GURL& origin); + void ResetOriginQuotaUnlimited(const GURL& origin); + bool CheckIfOriginGrantedUnlimitedQuota(const GURL& origin); + + private: + // For some extensions/apps we allow unlimited quota. + std::set<GURL> unlimited_quota_origins_; + + DISALLOW_COPY_AND_ASSIGN(FileSystemQuota); +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_FILE_SYSTEM_QUOTA_H_ diff --git a/webkit/fileapi/file_system_quota_unittest.cc b/webkit/fileapi/file_system_quota_unittest.cc new file mode 100644 index 0000000..0c505cd --- /dev/null +++ b/webkit/fileapi/file_system_quota_unittest.cc @@ -0,0 +1,146 @@ +// Copyright (c) 2010 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/file_system_quota.h" + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" +#include "base/string_number_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" + +using namespace fileapi; + +class FileSystemQuotaTest : public testing::Test { + public: + FileSystemQuotaTest() { } + + void SetUp() { + quota_.reset(new FileSystemQuota); + } + + FileSystemQuota* quota() const { return quota_.get(); } + + protected: + scoped_ptr<FileSystemQuota> quota_; + DISALLOW_COPY_AND_ASSIGN(FileSystemQuotaTest); +}; + +namespace { + +static const char* const kTestOrigins[] = { + "https://a.com/", + "http://b.com/", + "http://c.com:1/", + "file:///", +}; + +} // anonymous namespace + +TEST_F(FileSystemQuotaTest, CheckOriginQuotaNotAllowed) { + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + SCOPED_TRACE(testing::Message() << "CheckOriginQuotaNotAllowed #" + << i << " " << kTestOrigins[i]); + // Should fail no matter how much size is requested. + EXPECT_FALSE(quota()->CheckOriginQuota(GURL(kTestOrigins[i]), -1)); + EXPECT_FALSE(quota()->CheckOriginQuota(GURL(kTestOrigins[i]), 0)); + EXPECT_FALSE(quota()->CheckOriginQuota(GURL(kTestOrigins[i]), 100)); + } +} + +TEST_F(FileSystemQuotaTest, CheckOriginQuotaUnlimited) { + // Tests if SetOriginQuotaUnlimited and ResetOriginQuotaUnlimited + // are working as expected. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + SCOPED_TRACE(testing::Message() << "CheckOriginQuotaUnlimited #" + << i << " " << kTestOrigins[i]); + GURL url(kTestOrigins[i]); + EXPECT_FALSE(quota()->CheckIfOriginGrantedUnlimitedQuota(url)); + EXPECT_FALSE(quota()->CheckOriginQuota(url, 0)); + + quota()->SetOriginQuotaUnlimited(url); + EXPECT_TRUE(quota()->CheckIfOriginGrantedUnlimitedQuota(url)); + EXPECT_TRUE(quota()->CheckOriginQuota(url, -1)); + EXPECT_TRUE(quota()->CheckOriginQuota(url, 0)); + EXPECT_TRUE(quota()->CheckOriginQuota(url, 100)); + + quota()->ResetOriginQuotaUnlimited(url); + EXPECT_FALSE(quota()->CheckIfOriginGrantedUnlimitedQuota(url)); + EXPECT_FALSE(quota()->CheckOriginQuota(url, -1)); + EXPECT_FALSE(quota()->CheckOriginQuota(url, 0)); + EXPECT_FALSE(quota()->CheckOriginQuota(url, 100)); + } +} + +TEST_F(FileSystemQuotaTest, CheckOriginQuotaWithMixedSet) { + // Tests setting unlimited quota for some urls doesn't affect + // other urls. + GURL test_url1("http://foo.bar.com/"); + GURL test_url2("http://example.com/"); + quota()->SetOriginQuotaUnlimited(test_url1); + quota()->SetOriginQuotaUnlimited(test_url2); + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + SCOPED_TRACE(testing::Message() << "CheckOriginQuotaMixedSet #" + << i << " " << kTestOrigins[i]); + GURL url(kTestOrigins[i]); + EXPECT_FALSE(quota()->CheckOriginQuota(url, 0)); + EXPECT_FALSE(quota()->CheckIfOriginGrantedUnlimitedQuota(url)); + } +} + +TEST_F(FileSystemQuotaTest, CheckOriginQuotaMixedWithDifferentScheme) { + // Tests setting unlimited quota for urls doesn't affect + // pages in the same hosts but with different scheme. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + GURL url(kTestOrigins[i]); + if (url.SchemeIsFile()) + continue; + DCHECK(url == url.GetOrigin()); + std::string new_scheme = "https"; + if (url.SchemeIsSecure()) + new_scheme = "http"; + else + DCHECK(url.SchemeIs("http")); + std::string new_url_string = new_scheme + "://" + url.host(); + if (url.has_port()) + new_url_string += ":" + url.port(); + quota()->SetOriginQuotaUnlimited(GURL(new_url_string)); + } + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + SCOPED_TRACE(testing::Message() + << "CheckOriginQuotaMixedWithDifferentScheme #" + << i << " " << kTestOrigins[i]); + GURL url(kTestOrigins[i]); + EXPECT_FALSE(quota()->CheckOriginQuota(url, 0)); + EXPECT_FALSE(quota()->CheckIfOriginGrantedUnlimitedQuota(url)); + } +} + +TEST_F(FileSystemQuotaTest, CheckOriginQuotaMixedWithDifferentPort) { + // Tests setting unlimited quota for urls doesn't affect + // pages in the same scheme/hosts but with different port number. + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + GURL url(kTestOrigins[i]); + if (url.SchemeIsFile()) + continue; + DCHECK(url == url.GetOrigin()); + int port = 81; + if (url.has_port()) + port = url.IntPort() + 1; + GURL new_url(url.scheme() + "://" + url.host() + ":" + + base::IntToString(port)); + quota()->SetOriginQuotaUnlimited(new_url); + } + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestOrigins); ++i) { + SCOPED_TRACE(testing::Message() + << "CheckOriginQuotaMixedWithDifferentPort #" + << i << " " << kTestOrigins[i]); + GURL url(kTestOrigins[i]); + EXPECT_FALSE(quota()->CheckOriginQuota(url, 0)); + EXPECT_FALSE(quota()->CheckIfOriginGrantedUnlimitedQuota(url)); + } +} diff --git a/webkit/fileapi/webkit_fileapi.gypi b/webkit/fileapi/webkit_fileapi.gypi index a795da4..f01e9db 100644 --- a/webkit/fileapi/webkit_fileapi.gypi +++ b/webkit/fileapi/webkit_fileapi.gypi @@ -17,6 +17,8 @@ 'file_system_callback_dispatcher.h', 'file_system_operation.cc', 'file_system_operation.h', + 'file_system_quota.cc', + 'file_system_quota.h', 'file_system_types.h', 'file_writer_delegate.cc', 'file_writer_delegate.h', diff --git a/webkit/glue/webkit_glue.cc b/webkit/glue/webkit_glue.cc index f7f60aa..a58ff1b 100644 --- a/webkit/glue/webkit_glue.cc +++ b/webkit/glue/webkit_glue.cc @@ -330,6 +330,10 @@ WebKit::WebFileError PlatformFileErrorToWebFileError( return WebKit::WebFileErrorInvalidState; case base::PLATFORM_FILE_ERROR_ABORT: return WebKit::WebFileErrorAbort; + case base::PLATFORM_FILE_ERROR_SECURITY: + return WebKit::WebFileErrorSecurity; + case base::PLATFORM_FILE_ERROR_NO_SPACE: + return WebKit::WebFileErrorQuotaExceeded; default: return WebKit::WebFileErrorInvalidModification; } diff --git a/webkit/tools/test_shell/test_shell.gypi b/webkit/tools/test_shell/test_shell.gypi index d9efb30..4ac1faa 100644 --- a/webkit/tools/test_shell/test_shell.gypi +++ b/webkit/tools/test_shell/test_shell.gypi @@ -376,6 +376,7 @@ '../../database/database_util_unittest.cc', '../../database/quota_table_unittest.cc', '../../fileapi/file_system_operation_unittest.cc', + '../../fileapi/file_system_quota_unittest.cc', '../../glue/bookmarklet_unittest.cc', '../../glue/context_menu_unittest.cc', '../../glue/cpp_bound_class_unittest.cc', |