diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-19 19:40:31 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-19 19:40:31 +0000 |
commit | dc895236268d5f20f45c3ed86f1f70f65853cd80 (patch) | |
tree | fa69c05cacb50a7f12e3fce8f23fc974ab43039b /content | |
parent | d8911efaf3cd3635a1edcc985c81416bebebd3a7 (diff) | |
download | chromium_src-dc895236268d5f20f45c3ed86f1f70f65853cd80.zip chromium_src-dc895236268d5f20f45c3ed86f1f70f65853cd80.tar.gz chromium_src-dc895236268d5f20f45c3ed86f1f70f65853cd80.tar.bz2 |
Add mechanism to auto mount file systems in response to a URL request.
This code adds a hook for when a file system URL request can not be cracked.
It will allow external media galleries file systems to be lazily created.
BUG=160900
Review URL: https://codereview.chromium.org/195923002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258064 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
9 files changed, 261 insertions, 18 deletions
diff --git a/content/browser/fileapi/browser_file_system_helper.cc b/content/browser/fileapi/browser_file_system_helper.cc index 4ec6259..f7c9183 100644 --- a/content/browser/fileapi/browser_file_system_helper.cc +++ b/content/browser/fileapi/browser_file_system_helper.cc @@ -21,6 +21,7 @@ #include "webkit/browser/fileapi/external_mount_points.h" #include "webkit/browser/fileapi/file_permission_policy.h" #include "webkit/browser/fileapi/file_system_backend.h" +#include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_operation_runner.h" #include "webkit/browser/fileapi/file_system_options.h" #include "webkit/browser/quota/quota_manager.h" @@ -66,6 +67,12 @@ scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext( profile_path, &additional_backends); + // Set up the auto mount handlers for url requests. + std::vector<fileapi::URLRequestAutoMountHandler> + url_request_auto_mount_handlers; + GetContentClient()->browser()->GetURLRequestAutoMountHandlers( + &url_request_auto_mount_handlers); + scoped_refptr<fileapi::FileSystemContext> file_system_context = new fileapi::FileSystemContext( BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get(), @@ -74,6 +81,7 @@ scoped_refptr<fileapi::FileSystemContext> CreateFileSystemContext( browser_context->GetSpecialStoragePolicy(), quota_manager_proxy, additional_backends.Pass(), + url_request_auto_mount_handlers, profile_path, CreateBrowserFileSystemOptions(is_incognito)); diff --git a/content/browser/fileapi/file_system_context_unittest.cc b/content/browser/fileapi/file_system_context_unittest.cc index f989ed7..ad8997d 100644 --- a/content/browser/fileapi/file_system_context_unittest.cc +++ b/content/browser/fileapi/file_system_context_unittest.cc @@ -66,14 +66,16 @@ class FileSystemContextTest : public testing::Test { protected: FileSystemContext* CreateFileSystemContextForTest( fileapi::ExternalMountPoints* external_mount_points) { - return new FileSystemContext(base::MessageLoopProxy::current().get(), - base::MessageLoopProxy::current().get(), - external_mount_points, - storage_policy_.get(), - mock_quota_manager_->proxy(), - ScopedVector<FileSystemBackend>(), - data_dir_.path(), - CreateAllowFileAccessOptions()); + return new FileSystemContext( + base::MessageLoopProxy::current().get(), + base::MessageLoopProxy::current().get(), + external_mount_points, + storage_policy_.get(), + mock_quota_manager_->proxy(), + ScopedVector<FileSystemBackend>(), + std::vector<fileapi::URLRequestAutoMountHandler>(), + data_dir_.path(), + CreateAllowFileAccessOptions()); } // Verifies a *valid* filesystem url has expected values. diff --git a/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc index e17157f..3b4c73f 100644 --- a/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc +++ b/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc @@ -6,15 +6,18 @@ #include <string> +#include "base/file_util.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/format_macros.h" +#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/platform_file.h" #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" +#include "content/public/test/test_file_system_backend.h" #include "content/public/test/test_file_system_context.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" @@ -25,6 +28,7 @@ #include "net/url_request/url_request_test_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/icu/source/i18n/unicode/regex.h" +#include "webkit/browser/fileapi/external_mount_points.h" #include "webkit/browser/fileapi/file_system_context.h" #include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/fileapi/file_system_operation_context.h" @@ -39,8 +43,34 @@ namespace content { namespace { // We always use the TEMPORARY FileSystem in this test. -static const char kFileSystemURLPrefix[] = - "filesystem:http://remote/temporary/"; +const char kFileSystemURLPrefix[] = "filesystem:http://remote/temporary/"; + +const char kValidExternalMountPoint[] = "mnt_name"; + +// An auto mounter that will try to mount anything for |storage_domain| = +// "automount", but will only succeed for the mount point "mnt_name". +bool TestAutoMountForURLRequest( + const net::URLRequest* /*url_request*/, + const fileapi::FileSystemURL& filesystem_url, + const std::string& storage_domain, + const base::Callback<void(base::File::Error result)>& callback) { + if (storage_domain != "automount") + return false; + + std::vector<base::FilePath::StringType> components; + filesystem_url.path().GetComponents(&components); + std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe(); + + if (mount_point == kValidExternalMountPoint) { + fileapi::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + kValidExternalMountPoint, fileapi::kFileSystemTypeTest, + fileapi::FileSystemMountOption(), base::FilePath()); + callback.Run(base::File::FILE_OK); + } else { + callback.Run(base::File::FILE_ERROR_NOT_FOUND); + } + return true; +} } // namespace @@ -77,6 +107,21 @@ class FileSystemDirURLRequestJobTest : public testing::Test { ClearUnusedJob(); } + void SetUpAutoMountContext(base::FilePath* mnt_point) { + *mnt_point = temp_dir_.path().AppendASCII("auto_mount_dir"); + ASSERT_TRUE(base::CreateDirectory(*mnt_point)); + + ScopedVector<fileapi::FileSystemBackend> additional_providers; + additional_providers.push_back(new TestFileSystemBackend( + base::MessageLoopProxy::current().get(), *mnt_point)); + + std::vector<fileapi::URLRequestAutoMountHandler> handlers; + handlers.push_back(base::Bind(&TestAutoMountForURLRequest)); + + file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting( + NULL, additional_providers.Pass(), handlers, temp_dir_.path()); + } + void OnOpenFileSystem(const GURL& root_url, const std::string& name, base::File::Error result) { @@ -90,7 +135,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test { request_ = empty_context_.CreateRequest( url, net::DEFAULT_PRIORITY, delegate_.get(), NULL); job_ = new fileapi::FileSystemDirURLRequestJob( - request_.get(), NULL, file_system_context); + request_.get(), NULL, url.GetOrigin().host(), file_system_context); request_->Start(); ASSERT_TRUE(request_->is_pending()); // verify that we're starting async @@ -158,6 +203,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test { file_info, platform_file_path); } + // If |size| is negative, the reported size is ignored. void VerifyListingEntry(const std::string& entry_line, const std::string& name, const std::string& url, @@ -178,8 +224,10 @@ class FileSystemDirURLRequestJobTest : public testing::Test { EXPECT_EQ(icu::UnicodeString(url.c_str()), match.group(2, status)); EXPECT_EQ(icu::UnicodeString(is_directory ? "1" : "0"), match.group(3, status)); - icu::UnicodeString size_string(FormatBytesUnlocalized(size).c_str()); - EXPECT_EQ(size_string, match.group(4, status)); + if (size >= 0) { + icu::UnicodeString size_string(FormatBytesUnlocalized(size).c_str()); + EXPECT_EQ(size_string, match.group(4, status)); + } base::Time date; icu::UnicodeString date_ustr(match.group(5, status)); @@ -265,6 +313,7 @@ TEST_F(FileSystemDirURLRequestJobTest, DirectoryListing) { EXPECT_TRUE(!!std::getline(in, line)); VerifyListingEntry(line, "baz", "baz", true, 0); + EXPECT_FALSE(!!std::getline(in, line)); } TEST_F(FileSystemDirURLRequestJobTest, InvalidURL) { @@ -321,5 +370,67 @@ TEST_F(FileSystemDirURLRequestJobTest, Incognito) { EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); } +TEST_F(FileSystemDirURLRequestJobTest, AutoMountDirectoryListing) { + base::FilePath mnt_point; + SetUpAutoMountContext(&mnt_point); + ASSERT_TRUE(base::CreateDirectory(mnt_point)); + ASSERT_TRUE(base::CreateDirectory(mnt_point.AppendASCII("foo"))); + ASSERT_EQ(10, + base::WriteFile(mnt_point.AppendASCII("bar"), "1234567890", 10)); + + TestRequest(GURL("filesystem:http://automount/external/mnt_name")); + + ASSERT_FALSE(request_->is_pending()); + EXPECT_EQ(1, delegate_->response_started_count()); + EXPECT_FALSE(delegate_->received_data_before_response()); + EXPECT_GT(delegate_->bytes_received(), 0); + + std::istringstream in(delegate_->data_received()); + std::string line; + EXPECT_TRUE(!!std::getline(in, line)); // |line| contains the temp dir path. + + // Result order is not guaranteed, so sort the results. + std::vector<std::string> listing_entries; + while (!!std::getline(in, line)) + listing_entries.push_back(line); + + ASSERT_EQ(2U, listing_entries.size()); + std::sort(listing_entries.begin(), listing_entries.end()); + VerifyListingEntry(listing_entries[0], "bar", "bar", false, 10); + VerifyListingEntry(listing_entries[1], "foo", "foo", true, -1); + + ASSERT_TRUE( + fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + kValidExternalMountPoint)); +} + +TEST_F(FileSystemDirURLRequestJobTest, AutoMountInvalidRoot) { + base::FilePath mnt_point; + SetUpAutoMountContext(&mnt_point); + TestRequest(GURL("filesystem:http://automount/external/invalid")); + + ASSERT_FALSE(request_->is_pending()); + ASSERT_FALSE(request_->status().is_success()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); + + ASSERT_FALSE( + fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + "invalid")); +} + +TEST_F(FileSystemDirURLRequestJobTest, AutoMountNoHandler) { + base::FilePath mnt_point; + SetUpAutoMountContext(&mnt_point); + TestRequest(GURL("filesystem:http://noauto/external/mnt_name")); + + ASSERT_FALSE(request_->is_pending()); + ASSERT_FALSE(request_->status().is_success()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); + + ASSERT_FALSE( + fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + kValidExternalMountPoint)); +} + } // namespace (anonymous) } // namespace content diff --git a/content/browser/fileapi/file_system_url_request_job_unittest.cc b/content/browser/fileapi/file_system_url_request_job_unittest.cc index 2ddaef6..df444fa 100644 --- a/content/browser/fileapi/file_system_url_request_job_unittest.cc +++ b/content/browser/fileapi/file_system_url_request_job_unittest.cc @@ -11,6 +11,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/format_macros.h" +#include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_proxy.h" @@ -21,6 +22,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "content/public/test/async_file_test_helper.h" +#include "content/public/test/test_file_system_backend.h" #include "content/public/test/test_file_system_context.h" #include "net/base/load_flags.h" #include "net/base/mime_util.h" @@ -53,6 +55,32 @@ void FillBuffer(char* buffer, size_t len) { base::RandBytes(buffer, len); } +const char kValidExternalMountPoint[] = "mnt_name"; + +// An auto mounter that will try to mount anything for |storage_domain| = +// "automount", but will only succeed for the mount point "mnt_name". +bool TestAutoMountForURLRequest( + const net::URLRequest* /*url_request*/, + const fileapi::FileSystemURL& filesystem_url, + const std::string& storage_domain, + const base::Callback<void(base::File::Error result)>& callback) { + if (storage_domain != "automount") + return false; + std::vector<base::FilePath::StringType> components; + filesystem_url.path().GetComponents(&components); + std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe(); + + if (mount_point == kValidExternalMountPoint) { + fileapi::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( + kValidExternalMountPoint, fileapi::kFileSystemTypeTest, + fileapi::FileSystemMountOption(), base::FilePath()); + callback.Run(base::File::FILE_OK); + } else { + callback.Run(base::File::FILE_ERROR_NOT_FOUND); + } + return true; +} + } // namespace class FileSystemURLRequestJobTest : public testing::Test { @@ -90,6 +118,25 @@ class FileSystemURLRequestJobTest : public testing::Test { base::RunLoop().RunUntilIdle(); } + void SetUpAutoMountContext() { + base::FilePath mnt_point = temp_dir_.path().AppendASCII("auto_mount_dir"); + ASSERT_TRUE(base::CreateDirectory(mnt_point)); + + ScopedVector<fileapi::FileSystemBackend> additional_providers; + additional_providers.push_back(new TestFileSystemBackend( + base::MessageLoopProxy::current().get(), mnt_point)); + + std::vector<fileapi::URLRequestAutoMountHandler> handlers; + handlers.push_back(base::Bind(&TestAutoMountForURLRequest)); + + file_system_context_ = CreateFileSystemContextWithAutoMountersForTesting( + NULL, additional_providers.Pass(), handlers, temp_dir_.path()); + + ASSERT_EQ(static_cast<int>(sizeof(kTestFileData)) - 1, + base::WriteFile(mnt_point.AppendASCII("foo"), kTestFileData, + sizeof(kTestFileData) - 1)); + } + void OnOpenFileSystem(const GURL& root_url, const std::string& name, base::File::Error result) { @@ -110,7 +157,7 @@ class FileSystemURLRequestJobTest : public testing::Test { request_->SetExtraRequestHeaders(*headers); ASSERT_TRUE(!job_); job_ = new FileSystemURLRequestJob( - request_.get(), NULL, file_system_context); + request_.get(), NULL, url.GetOrigin().host(), file_system_context); pending_job_ = job_; request_->Start(); @@ -260,7 +307,6 @@ TEST_F(FileSystemURLRequestJobTest, FileTestHalfSpecifiedRange) { EXPECT_TRUE(partial_buffer_string == delegate_->data_received()); } - TEST_F(FileSystemURLRequestJobTest, FileTestMultipleRangesNotSupported) { WriteFile("file1.dat", kTestFileData, arraysize(kTestFileData) - 1); net::HttpRequestHeaders headers; @@ -369,5 +415,49 @@ TEST_F(FileSystemURLRequestJobTest, Incognito) { EXPECT_EQ(200, request_->GetResponseCode()); } +TEST_F(FileSystemURLRequestJobTest, AutoMountFileTest) { + SetUpAutoMountContext(); + TestRequest(GURL("filesystem:http://automount/external/mnt_name/foo")); + + ASSERT_FALSE(request_->is_pending()); + EXPECT_EQ(1, delegate_->response_started_count()); + EXPECT_FALSE(delegate_->received_data_before_response()); + EXPECT_EQ(kTestFileData, delegate_->data_received()); + EXPECT_EQ(200, request_->GetResponseCode()); + std::string cache_control; + request_->GetResponseHeaderByName("cache-control", &cache_control); + EXPECT_EQ("no-cache", cache_control); + + ASSERT_TRUE( + fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + kValidExternalMountPoint)); +} + +TEST_F(FileSystemURLRequestJobTest, AutoMountInvalidRoot) { + SetUpAutoMountContext(); + TestRequest(GURL("filesystem:http://automount/external/invalid/foo")); + + ASSERT_FALSE(request_->is_pending()); + EXPECT_TRUE(delegate_->request_failed()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); + + ASSERT_FALSE( + fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + "invalid")); +} + +TEST_F(FileSystemURLRequestJobTest, AutoMountNoHandler) { + SetUpAutoMountContext(); + TestRequest(GURL("filesystem:http://noauto/external/mnt_name/foo")); + + ASSERT_FALSE(request_->is_pending()); + EXPECT_TRUE(delegate_->request_failed()); + EXPECT_EQ(net::ERR_FILE_NOT_FOUND, request_->status().error()); + + ASSERT_FALSE( + fileapi::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem( + kValidExternalMountPoint)); +} + } // namespace } // namespace content diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc index 66703f3..03fb312 100644 --- a/content/browser/storage_partition_impl_map.cc +++ b/content/browser/storage_partition_impl_map.cc @@ -384,7 +384,8 @@ StoragePartitionImpl* StoragePartitionImplMap::Get( partition->GetFileSystemContext())); protocol_handlers[kFileSystemScheme] = linked_ptr<net::URLRequestJobFactory::ProtocolHandler>( - CreateFileSystemProtocolHandler(partition->GetFileSystemContext())); + CreateFileSystemProtocolHandler(partition_domain, + partition->GetFileSystemContext())); protocol_handlers[kChromeUIScheme] = linked_ptr<net::URLRequestJobFactory::ProtocolHandler>( URLDataManagerBackend::CreateProtocolHandler( diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index a0396ff..01c2eb9 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h @@ -24,6 +24,7 @@ #include "net/url_request/url_request_job_factory.h" #include "third_party/WebKit/public/web/WebNotificationPresenter.h" #include "ui/base/window_open_disposition.h" +#include "webkit/browser/fileapi/file_system_context.h" #include "webkit/common/resource_type.h" #if defined(OS_POSIX) && !defined(OS_MACOSX) @@ -583,6 +584,10 @@ class CONTENT_EXPORT ContentBrowserClient { virtual void GetAdditionalAllowedSchemesForFileSystem( std::vector<std::string>* additional_schemes) {} + // Returns auto mount handlers for URL requests for FileSystem APIs. + virtual void GetURLRequestAutoMountHandlers( + std::vector<fileapi::URLRequestAutoMountHandler>* handlers) {} + // Returns additional file system backends for FileSystem API. // |browser_context| is needed in the additional FileSystemBackends. // It has mount points to create objects returned by additional diff --git a/content/public/test/test_file_system_backend.cc b/content/public/test/test_file_system_backend.cc index b473716..8c37a9e 100644 --- a/content/public/test/test_file_system_backend.cc +++ b/content/public/test/test_file_system_backend.cc @@ -137,7 +137,6 @@ class TestFileSystemBackend::QuotaUtil virtual const fileapi::AccessObserverList* GetAccessObservers( FileSystemType type) const OVERRIDE { - NOTIMPLEMENTED(); return NULL; } diff --git a/content/public/test/test_file_system_context.cc b/content/public/test/test_file_system_context.cc index d09bbd1..aa954de 100644 --- a/content/public/test/test_file_system_context.cc +++ b/content/public/test/test_file_system_context.cc @@ -36,6 +36,25 @@ CreateFileSystemContextWithAdditionalProvidersForTesting( make_scoped_refptr(new quota::MockSpecialStoragePolicy()).get(), quota_manager_proxy, additional_providers.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), + base_path, + CreateAllowFileAccessOptions()); +} + +fileapi::FileSystemContext* +CreateFileSystemContextWithAutoMountersForTesting( + quota::QuotaManagerProxy* quota_manager_proxy, + ScopedVector<fileapi::FileSystemBackend> additional_providers, + const std::vector<fileapi::URLRequestAutoMountHandler>& auto_mounters, + const base::FilePath& base_path) { + return new fileapi::FileSystemContext( + base::MessageLoopProxy::current().get(), + base::MessageLoopProxy::current().get(), + fileapi::ExternalMountPoints::CreateRefCounted().get(), + make_scoped_refptr(new quota::MockSpecialStoragePolicy()).get(), + quota_manager_proxy, + additional_providers.Pass(), + auto_mounters, base_path, CreateAllowFileAccessOptions()); } @@ -51,6 +70,7 @@ fileapi::FileSystemContext* CreateIncognitoFileSystemContextForTesting( make_scoped_refptr(new quota::MockSpecialStoragePolicy()).get(), quota_manager_proxy, additional_providers.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), base_path, CreateIncognitoFileSystemOptions()); } diff --git a/content/public/test/test_file_system_context.h b/content/public/test/test_file_system_context.h index 19a4fc4..8b7c872 100644 --- a/content/public/test/test_file_system_context.h +++ b/content/public/test/test_file_system_context.h @@ -7,6 +7,7 @@ #include "base/files/file_path.h" #include "base/memory/scoped_vector.h" +#include "webkit/browser/fileapi/file_system_context.h" namespace quota { class QuotaManagerProxy; @@ -14,7 +15,6 @@ class SpecialStoragePolicy; } namespace fileapi { -class FileSystemContext; class FileSystemBackend; } @@ -32,6 +32,13 @@ CreateFileSystemContextWithAdditionalProvidersForTesting( ScopedVector<fileapi::FileSystemBackend> additional_providers, const base::FilePath& base_path); +fileapi::FileSystemContext* +CreateFileSystemContextWithAutoMountersForTesting( + quota::QuotaManagerProxy* quota_manager_proxy, + ScopedVector<fileapi::FileSystemBackend> additional_providers, + const std::vector<fileapi::URLRequestAutoMountHandler>& auto_mounters, + const base::FilePath& base_path); + fileapi::FileSystemContext* CreateIncognitoFileSystemContextForTesting( quota::QuotaManagerProxy* quota_manager_proxy, const base::FilePath& base_path); |