Skip to content

Commit

Permalink
Add mechanism to auto mount file systems in response to a URL request.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vandebo@chromium.org committed Mar 19, 2014
1 parent d8911ef commit dc89523
Show file tree
Hide file tree
Showing 27 changed files with 396 additions and 32 deletions.
4 changes: 4 additions & 0 deletions chrome/browser/chrome_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions chrome/browser/chrome_content_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/chromeos/drive/file_system_util_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
10 changes: 10 additions & 0 deletions chrome/browser/media_galleries/fileapi/media_file_system_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ namespace base {
class SequencedTaskRunner;
}

namespace net {
class URLRequest;
}

class MediaPathFilter;

class DeviceMediaAsyncFileUtil;
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions content/browser/fileapi/browser_file_system_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(),
Expand All @@ -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));

Expand Down
18 changes: 10 additions & 8 deletions content/browser/fileapi/file_system_context_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
121 changes: 116 additions & 5 deletions content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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

Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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));
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Loading

0 comments on commit dc89523

Please sign in to comment.