diff options
author | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-20 22:43:55 +0000 |
---|---|---|
committer | vandebo@chromium.org <vandebo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-20 22:43:55 +0000 |
commit | c79859b8aaf03c6ca791ee98c6e2a9558e070a26 (patch) | |
tree | 82fd2f41155e05d176aea7211a6c277031a1375d | |
parent | 5062a57b9dc728cfff5c922709c37f8dfb984b8e (diff) | |
download | chromium_src-c79859b8aaf03c6ca791ee98c6e2a9558e070a26.zip chromium_src-c79859b8aaf03c6ca791ee98c6e2a9558e070a26.tar.gz chromium_src-c79859b8aaf03c6ca791ee98c6e2a9558e070a26.tar.bz2 |
Revert of Revert of Add mechanism to auto mount file systems in response to a URL request. (https://codereview.chromium.org/206253002/)
Reason for revert:
This revert did not fix the breakage it was suspected of.
Original issue's description:
> Revert of Add mechanism to auto mount file systems in response to a URL request. (https://codereview.chromium.org/195923002/)
>
> Reason for revert:
> Best guess that this broke
> SyncFileSystemApiTest.WriteFileThenGetUsage
> SyncFileSystemApiTest.GetFileStatuses
> MediaGalleriesPlatformAppBrowserTest.MediaGalleriesCopyTo
> on XP Tests(1).
>
> Original issue's description:
> > 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
> >
> > Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=258064
>
> TBR=kinuko@chromium.org,tzik@chromium.org,joi@chromium.org,sky@chromium.org,vandebo@chromium.org
> NOTREECHECKS=true
> NOTRY=true
> BUG=160900
>
> Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=258261
TBR=kinuko@chromium.org,tzik@chromium.org,joi@chromium.org,sky@chromium.org,pneubeck@chromium.org
BUG=160900
Review URL: https://codereview.chromium.org/199903003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258440 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 396 insertions, 32 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 9d3a7c6..bb39d4c 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -2556,6 +2556,10 @@ void ChromeContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem( additional_allowed_schemes->push_back(extensions::kExtensionScheme); } +void ChromeContentBrowserClient::GetURLRequestAutoMountHandlers( + std::vector<fileapi::URLRequestAutoMountHandler>* handlers) { +} + void ChromeContentBrowserClient::GetAdditionalFileSystemBackends( content::BrowserContext* browser_context, const base::FilePath& storage_partition_path, diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index a548b35..da26283 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h @@ -260,6 +260,8 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient { content::WebContents* web_contents) OVERRIDE; virtual void GetAdditionalAllowedSchemesForFileSystem( std::vector<std::string>* additional_schemes) OVERRIDE; + virtual void GetURLRequestAutoMountHandlers( + std::vector<fileapi::URLRequestAutoMountHandler>* handlers) OVERRIDE; virtual void GetAdditionalFileSystemBackends( content::BrowserContext* browser_context, const base::FilePath& storage_partition_path, diff --git a/chrome/browser/chromeos/drive/file_system_util_unittest.cc b/chrome/browser/chromeos/drive/file_system_util_unittest.cc index 89db541..157dfff 100644 --- a/chrome/browser/chromeos/drive/file_system_util_unittest.cc +++ b/chrome/browser/chromeos/drive/file_system_util_unittest.cc @@ -153,6 +153,7 @@ TEST(FileSystemUtilTest, ExtractDrivePathFromFileSystemUrl) { NULL, // special_storage_policy NULL, // quota_manager_proxy, ScopedVector<fileapi::FileSystemBackend>(), + std::vector<fileapi::URLRequestAutoMountHandler>(), temp_dir_.path(), // partition_path content::CreateAllowFileAccessOptions())); diff --git a/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc index d8dbbdf..645beaf 100644 --- a/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc @@ -214,6 +214,7 @@ class IPhotoFileUtilTest : public testing::Test { storage_policy.get(), NULL, additional_providers.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), profile_dir_.path(), content::CreateAllowFileAccessOptions()); } diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc index 7ef4765..43a09be 100644 --- a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc @@ -182,6 +182,7 @@ class ItunesFileUtilTest : public testing::Test { storage_policy.get(), NULL, additional_providers.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), profile_dir_.path(), content::CreateAllowFileAccessOptions()); } diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h index c5f8d99..7dbfbd1 100644 --- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h +++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h @@ -13,6 +13,10 @@ namespace base { class SequencedTaskRunner; } +namespace net { +class URLRequest; +} + class MediaPathFilter; class DeviceMediaAsyncFileUtil; @@ -29,6 +33,12 @@ class MediaFileSystemBackend : public fileapi::FileSystemBackend { static bool CurrentlyOnMediaTaskRunnerThread(); static scoped_refptr<base::SequencedTaskRunner> MediaTaskRunner(); + static bool AttemptAutoMountForURLRequest( + const net::URLRequest* url_request, + const fileapi::FileSystemURL& filesystem_url, + const std::string& storage_domain, + const base::Callback<void(base::File::Error result)>& callback); + // FileSystemBackend implementation. virtual bool CanHandleType(fileapi::FileSystemType type) const OVERRIDE; virtual void Initialize(fileapi::FileSystemContext* context) OVERRIDE; diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc index 93a47c3..0b20d58 100644 --- a/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/native_media_file_util_unittest.cc @@ -133,6 +133,7 @@ class NativeMediaFileUtilTest : public testing::Test { storage_policy.get(), NULL, additional_providers.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), data_dir_.path(), content::CreateAllowFileAccessOptions()); diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc index 3255ad1..c70c2ca 100644 --- a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc +++ b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc @@ -250,6 +250,7 @@ class PicasaFileUtilTest : public testing::Test { storage_policy.get(), NULL, additional_providers.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), profile_dir_.path(), content::CreateAllowFileAccessOptions()); } diff --git a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc index 9608013..2c7a56b 100644 --- a/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc +++ b/chrome/browser/sync_file_system/local/canned_syncable_file_system.cc @@ -254,6 +254,7 @@ void CannedSyncableFileSystem::SetUp(QuotaMode quota_mode) { storage_policy.get(), quota_manager_ ? quota_manager_->proxy() : NULL, additional_backends.Pass(), + std::vector<fileapi::URLRequestAutoMountHandler>(), data_dir_.path(), options); is_filesystem_set_up_ = true; 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); diff --git a/webkit/browser/fileapi/external_mount_points.h b/webkit/browser/fileapi/external_mount_points.h index 9fb3cc3..1748a09 100644 --- a/webkit/browser/fileapi/external_mount_points.h +++ b/webkit/browser/fileapi/external_mount_points.h @@ -21,10 +21,8 @@ class FilePath; } namespace fileapi { -class FileSystemURL; -} -namespace fileapi { +class FileSystemURL; // Manages external filesystem namespaces that are identified by 'mount name' // and are persisted until RevokeFileSystem is called. diff --git a/webkit/browser/fileapi/file_system_context.cc b/webkit/browser/fileapi/file_system_context.cc index c42eadb..067b25b 100644 --- a/webkit/browser/fileapi/file_system_context.cc +++ b/webkit/browser/fileapi/file_system_context.cc @@ -8,6 +8,7 @@ #include "base/single_thread_task_runner.h" #include "base/stl_util.h" #include "base/task_runner_util.h" +#include "net/url_request/url_request.h" #include "url/gurl.h" #include "webkit/browser/blob/file_stream_reader.h" #include "webkit/browser/fileapi/copy_or_move_file_validator.h" @@ -113,6 +114,7 @@ FileSystemContext::FileSystemContext( quota::SpecialStoragePolicy* special_storage_policy, quota::QuotaManagerProxy* quota_manager_proxy, ScopedVector<FileSystemBackend> additional_backends, + const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, const base::FilePath& partition_path, const FileSystemOptions& options) : io_task_runner_(io_task_runner), @@ -133,6 +135,7 @@ FileSystemContext::FileSystemContext( special_storage_policy, options)), additional_backends_(additional_backends.Pass()), + auto_mount_handlers_(auto_mount_handlers), external_mount_points_(external_mount_points), partition_path_(partition_path), is_incognito_(options.is_incognito()), @@ -337,6 +340,22 @@ void FileSystemContext::ResolveURL( callback)); } +void FileSystemContext::AttemptAutoMountForURLRequest( + const net::URLRequest* url_request, + const std::string& storage_domain, + const StatusCallback& callback) { + FileSystemURL filesystem_url(url_request->url()); + if (filesystem_url.type() == kFileSystemTypeExternal) { + for (size_t i = 0; i < auto_mount_handlers_.size(); i++) { + if (auto_mount_handlers_[i].Run(url_request, filesystem_url, + storage_domain, callback)) { + return; + } + } + } + callback.Run(base::File::FILE_ERROR_NOT_FOUND); +} + void FileSystemContext::DeleteFileSystem( const GURL& origin_url, FileSystemType type, diff --git a/webkit/browser/fileapi/file_system_context.h b/webkit/browser/fileapi/file_system_context.h index 62841d1..ba91af7 100644 --- a/webkit/browser/fileapi/file_system_context.h +++ b/webkit/browser/fileapi/file_system_context.h @@ -38,6 +38,10 @@ class QuotaManagerProxy; class SpecialStoragePolicy; } +namespace net { +class URLRequest; +} + namespace webkit_blob { class BlobURLRequestJobTest; class FileStreamReader; @@ -65,6 +69,18 @@ class SandboxFileSystemBackend; struct DefaultContextDeleter; struct FileSystemInfo; +// An auto mount handler will attempt to mount the file system requested in +// |url_request|. If the URL is for this auto mount handler, it returns true +// and calls |callback| when the attempt is complete. If the auto mounter +// does not recognize the URL, it returns false and does not call |callback|. +// Called on the IO thread. +typedef base::Callback<bool( + const net::URLRequest* url_request, + const FileSystemURL& filesystem_url, + const std::string& storage_domain, + const base::Callback<void(base::File::Error result)>& callback)> + URLRequestAutoMountHandler; + // This class keeps and provides a file system context for FileSystem API. // An instance of this class is created and owned by profile. class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext @@ -95,6 +111,10 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext // to serve filesystem requests for non-regular types. // If none is given, this context only handles HTML5 Sandbox FileSystem // and Drag-and-drop Isolated FileSystem requests. + // + // |auto_mount_handlers| are used to resolve calls to + // AttemptAutoMountForURLRequest. Only external filesystems are auto mounted + // when a filesystem: URL request is made. FileSystemContext( base::SingleThreadTaskRunner* io_task_runner, base::SequencedTaskRunner* file_task_runner, @@ -102,6 +122,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext quota::SpecialStoragePolicy* special_storage_policy, quota::QuotaManagerProxy* quota_manager_proxy, ScopedVector<FileSystemBackend> additional_backends, + const std::vector<URLRequestAutoMountHandler>& auto_mount_handlers, const base::FilePath& partition_path, const FileSystemOptions& options); @@ -193,6 +214,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext const FileSystemURL& url, const ResolveURLCallback& callback); + // Attempts to mount the filesystem needed to satisfy |url_request| made + // from |storage_domain|. If an appropriate file system is not found, + // callback will return an error. + void AttemptAutoMountForURLRequest(const net::URLRequest* url_request, + const std::string& storage_domain, + const StatusCallback& callback); + // Deletes the filesystem for the given |origin_url| and |type|. This should // be called on the IO thread. void DeleteFileSystem( @@ -343,6 +371,8 @@ class WEBKIT_STORAGE_BROWSER_EXPORT FileSystemContext scoped_ptr<PluginPrivateFileSystemBackend> plugin_private_backend_; ScopedVector<FileSystemBackend> additional_backends_; + std::vector<URLRequestAutoMountHandler> auto_mount_handlers_; + // Registered file system backends. // The map must be constructed in the constructor since it can be accessed // on multiple threads. diff --git a/webkit/browser/fileapi/file_system_dir_url_request_job.cc b/webkit/browser/fileapi/file_system_dir_url_request_job.cc index b0f1966..fffe739 100644 --- a/webkit/browser/fileapi/file_system_dir_url_request_job.cc +++ b/webkit/browser/fileapi/file_system_dir_url_request_job.cc @@ -35,8 +35,10 @@ namespace fileapi { FileSystemDirURLRequestJob::FileSystemDirURLRequestJob( URLRequest* request, NetworkDelegate* network_delegate, + const std::string& storage_domain, FileSystemContext* file_system_context) : URLRequestJob(request, network_delegate), + storage_domain_(storage_domain), file_system_context_(file_system_context), weak_factory_(this) { } @@ -81,6 +83,14 @@ void FileSystemDirURLRequestJob::StartAsync() { if (!request_) return; url_ = file_system_context_->CrackURL(request_->url()); + if (!url_.is_valid()) { + file_system_context_->AttemptAutoMountForURLRequest( + request_, + storage_domain_, + base::Bind(&FileSystemDirURLRequestJob::DidAttemptAutoMount, + weak_factory_.GetWeakPtr())); + return; + } if (!file_system_context_->CanServeURLRequest(url_)) { // In incognito mode the API is not usable and there should be no data. if (url_.is_valid() && VirtualPath::IsRootPath(url_.virtual_path())) { @@ -99,6 +109,16 @@ void FileSystemDirURLRequestJob::StartAsync() { base::Bind(&FileSystemDirURLRequestJob::DidReadDirectory, this)); } +void FileSystemDirURLRequestJob::DidAttemptAutoMount(base::File::Error result) { + if (result >= 0 && + file_system_context_->CrackURL(request_->url()).is_valid()) { + StartAsync(); + } else { + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, + net::ERR_FILE_NOT_FOUND)); + } +} + void FileSystemDirURLRequestJob::DidReadDirectory( base::File::Error result, const std::vector<DirectoryEntry>& entries, diff --git a/webkit/browser/fileapi/file_system_dir_url_request_job.h b/webkit/browser/fileapi/file_system_dir_url_request_job.h index 7346225..67e9df3 100644 --- a/webkit/browser/fileapi/file_system_dir_url_request_job.h +++ b/webkit/browser/fileapi/file_system_dir_url_request_job.h @@ -28,6 +28,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemDirURLRequestJob FileSystemDirURLRequestJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, + const std::string& storage_domain, FileSystemContext* file_system_context); // URLRequestJob methods: @@ -49,12 +50,14 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemDirURLRequestJob virtual ~FileSystemDirURLRequestJob(); void StartAsync(); + void DidAttemptAutoMount(base::File::Error result); void DidReadDirectory(base::File::Error result, const std::vector<DirectoryEntry>& entries, bool has_more); std::string data_; FileSystemURL url_; + const std::string storage_domain_; FileSystemContext* file_system_context_; base::WeakPtrFactory<FileSystemDirURLRequestJob> weak_factory_; diff --git a/webkit/browser/fileapi/file_system_url_request_job.cc b/webkit/browser/fileapi/file_system_url_request_job.cc index fe445649..8ccc5bb 100644 --- a/webkit/browser/fileapi/file_system_url_request_job.cc +++ b/webkit/browser/fileapi/file_system_url_request_job.cc @@ -57,8 +57,10 @@ static net::HttpResponseHeaders* CreateHttpResponseHeaders() { FileSystemURLRequestJob::FileSystemURLRequestJob( URLRequest* request, NetworkDelegate* network_delegate, + const std::string& storage_domain, FileSystemContext* file_system_context) : URLRequestJob(request, network_delegate), + storage_domain_(storage_domain), file_system_context_(file_system_context), is_directory_(false), remaining_bytes_(0), @@ -157,6 +159,14 @@ void FileSystemURLRequestJob::StartAsync() { return; DCHECK(!reader_.get()); url_ = file_system_context_->CrackURL(request_->url()); + if (!url_.is_valid()) { + file_system_context_->AttemptAutoMountForURLRequest( + request_, + storage_domain_, + base::Bind(&FileSystemURLRequestJob::DidAttemptAutoMount, + weak_factory_.GetWeakPtr())); + return; + } if (!file_system_context_->CanServeURLRequest(url_)) { // In incognito mode the API is not usable and there should be no data. NotifyFailed(net::ERR_FILE_NOT_FOUND); @@ -168,6 +178,15 @@ void FileSystemURLRequestJob::StartAsync() { weak_factory_.GetWeakPtr())); } +void FileSystemURLRequestJob::DidAttemptAutoMount(base::File::Error result) { + if (result >= 0 && + file_system_context_->CrackURL(request_->url()).is_valid()) { + StartAsync(); + } else { + NotifyFailed(net::ERR_FILE_NOT_FOUND); + } +} + void FileSystemURLRequestJob::DidGetMetadata( base::File::Error error_code, const base::File::Info& file_info) { diff --git a/webkit/browser/fileapi/file_system_url_request_job.h b/webkit/browser/fileapi/file_system_url_request_job.h index 8fa766c..29b42a5 100644 --- a/webkit/browser/fileapi/file_system_url_request_job.h +++ b/webkit/browser/fileapi/file_system_url_request_job.h @@ -36,6 +36,7 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemURLRequestJob FileSystemURLRequestJob( net::URLRequest* request, net::NetworkDelegate* network_delegate, + const std::string& storage_domain, FileSystemContext* file_system_context); // URLRequestJob methods: @@ -60,12 +61,13 @@ class WEBKIT_STORAGE_BROWSER_EXPORT_PRIVATE FileSystemURLRequestJob virtual ~FileSystemURLRequestJob(); void StartAsync(); - void DidGetMetadata( - base::File::Error error_code, - const base::File::Info& file_info); + void DidAttemptAutoMount(base::File::Error result); + void DidGetMetadata(base::File::Error error_code, + const base::File::Info& file_info); void DidRead(int result); void NotifyFailed(int rv); + const std::string storage_domain_; FileSystemContext* file_system_context_; scoped_ptr<webkit_blob::FileStreamReader> reader_; FileSystemURL url_; diff --git a/webkit/browser/fileapi/file_system_url_request_job_factory.cc b/webkit/browser/fileapi/file_system_url_request_job_factory.cc index 76ae7c9..3add372 100644 --- a/webkit/browser/fileapi/file_system_url_request_job_factory.cc +++ b/webkit/browser/fileapi/file_system_url_request_job_factory.cc @@ -19,7 +19,8 @@ namespace { class FileSystemProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { public: - explicit FileSystemProtocolHandler(FileSystemContext* context); + FileSystemProtocolHandler(const std::string& storage_domain, + FileSystemContext* context); virtual ~FileSystemProtocolHandler(); virtual net::URLRequestJob* MaybeCreateJob( @@ -27,6 +28,8 @@ class FileSystemProtocolHandler net::NetworkDelegate* network_delegate) const OVERRIDE; private: + const std::string storage_domain_; + // No scoped_refptr because |file_system_context_| is owned by the // ProfileIOData, which also owns this ProtocolHandler. FileSystemContext* const file_system_context_; @@ -35,8 +38,10 @@ class FileSystemProtocolHandler }; FileSystemProtocolHandler::FileSystemProtocolHandler( + const std::string& storage_domain, FileSystemContext* context) - : file_system_context_(context) { + : storage_domain_(storage_domain), + file_system_context_(context) { DCHECK(file_system_context_); } @@ -51,18 +56,18 @@ net::URLRequestJob* FileSystemProtocolHandler::MaybeCreateJob( // redirects back here, by adding a / to the URL. if (!path.empty() && path[path.size() - 1] == '/') { return new FileSystemDirURLRequestJob( - request, network_delegate, file_system_context_); + request, network_delegate, storage_domain_, file_system_context_); } return new FileSystemURLRequestJob( - request, network_delegate, file_system_context_); + request, network_delegate, storage_domain_, file_system_context_); } } // anonymous namespace -net::URLRequestJobFactory::ProtocolHandler* -CreateFileSystemProtocolHandler(FileSystemContext* context) { +net::URLRequestJobFactory::ProtocolHandler* CreateFileSystemProtocolHandler( + const std::string& storage_domain, FileSystemContext* context) { DCHECK(context); - return new FileSystemProtocolHandler(context); + return new FileSystemProtocolHandler(storage_domain, context); } } // namespace fileapi diff --git a/webkit/browser/fileapi/file_system_url_request_job_factory.h b/webkit/browser/fileapi/file_system_url_request_job_factory.h index 5bd3c0f..bcc55dc 100644 --- a/webkit/browser/fileapi/file_system_url_request_job_factory.h +++ b/webkit/browser/fileapi/file_system_url_request_job_factory.h @@ -5,6 +5,8 @@ #ifndef WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_ #define WEBKIT_BROWSER_FILEAPI_FILE_SYSTEM_URL_REQUEST_JOB_FACTORY_H_ +#include <string> + #include "net/url_request/url_request_job_factory.h" #include "webkit/browser/webkit_storage_browser_export.h" @@ -21,7 +23,8 @@ class FileSystemContext; // Currently, this is only used by ProfileIOData which owns |context| and the // ProtocolHandler. WEBKIT_STORAGE_BROWSER_EXPORT net::URLRequestJobFactory::ProtocolHandler* - CreateFileSystemProtocolHandler(FileSystemContext* context); + CreateFileSystemProtocolHandler(const std::string& storage_domain, + FileSystemContext* context); } // namespace fileapi |