Commit f073a6f6 authored by Sam McNally's avatar Sam McNally Committed by Commit Bot

Reland "Add a FakeDriveFs and change FileManagerBrowserTestBase to use it."

This is a reland of ac0ccdc1 with
FileManagerBrowserTestBase::drive_volume_ null-initialized.

Original change's description:
> Add a FakeDriveFs and change FileManagerBrowserTestBase to use it.
>
> Bug: 848126
> Change-Id: Icb7b5edf28aa61e133aff0f0bf639f06b32adcfa
> Reviewed-on: https://chromium-review.googlesource.com/1088336
> Commit-Queue: Sam McNally <sammc@chromium.org>
> Reviewed-by: Noel Gordon <noel@chromium.org>
> Reviewed-by: Sasha Morrissey <sashab@chromium.org>
> Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#566333}

Bug: 848126
Change-Id: I583fd6ebe92e5f191de93a3b3167a1c50e595a95
Tbr: noel@chromium.org, sashab@chromium.org, xiyuan@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/1098395Reviewed-by: default avatarSam McNally <sammc@chromium.org>
Commit-Queue: Sam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#566691}
parent 0424f1aa
......@@ -5,7 +5,6 @@
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/logging.h"
......@@ -30,7 +29,6 @@
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/components/drivefs/drivefs_host.h"
#include "components/drive/chromeos/file_cache.h"
#include "components/drive/chromeos/file_system.h"
#include "components/drive/chromeos/resource_metadata.h"
......@@ -79,8 +77,6 @@ const base::FilePath::CharType kCacheFileDirectory[] =
const base::FilePath::CharType kTemporaryFileDirectory[] =
FILE_PATH_LITERAL("tmp");
const base::Feature kDriveFs{"DriveFS", base::FEATURE_DISABLED_BY_DEFAULT};
// Returns a user agent string used for communicating with the Drive backend,
// both WAPI and Drive API. The user agent looks like:
//
......@@ -207,6 +203,8 @@ FileError InitializeMetadata(
} // namespace
const base::Feature kDriveFs{"DriveFS", base::FEATURE_DISABLED_BY_DEFAULT};
// Observes drive disable Preference's change.
class DriveIntegrationService::PreferenceWatcher {
public:
......@@ -244,7 +242,10 @@ class DriveIntegrationService::PreferenceWatcher {
class DriveIntegrationService::DriveFsHolder
: public drivefs::DriveFsHost::Delegate {
public:
DriveFsHolder(Profile* profile, base::RepeatingClosure on_drivefs_mounted);
DriveFsHolder(Profile* profile,
base::RepeatingClosure on_drivefs_mounted,
DriveFsMojoConnectionDelegateFactory
test_drivefs_mojo_connection_delegate_factory);
drivefs::DriveFsHost* drivefs_host() { return &drivefs_host_; }
......@@ -254,12 +255,17 @@ class DriveIntegrationService::DriveFsHolder
service_manager::Connector* GetConnector() override;
const AccountId& GetAccountId() override;
void OnMounted(const base::FilePath& path) override;
std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>
CreateMojoConnectionDelegate() override;
Profile* const profile_;
// Invoked when DriveFS mounting is completed.
const base::RepeatingClosure on_drivefs_mounted_;
const DriveFsMojoConnectionDelegateFactory
test_drivefs_mojo_connection_delegate_factory_;
drivefs::DriveFsHost drivefs_host_;
DISALLOW_COPY_AND_ASSIGN(DriveFsHolder);
......@@ -267,9 +273,13 @@ class DriveIntegrationService::DriveFsHolder
DriveIntegrationService::DriveFsHolder::DriveFsHolder(
Profile* profile,
base::RepeatingClosure on_drivefs_mounted)
base::RepeatingClosure on_drivefs_mounted,
DriveFsMojoConnectionDelegateFactory
test_drivefs_mojo_connection_delegate_factory)
: profile_(profile),
on_drivefs_mounted_(std::move(on_drivefs_mounted)),
test_drivefs_mojo_connection_delegate_factory_(
std::move(test_drivefs_mojo_connection_delegate_factory)),
drivefs_host_(profile_->GetPath(), this) {}
net::URLRequestContextGetter*
......@@ -288,6 +298,13 @@ const AccountId& DriveIntegrationService::DriveFsHolder::GetAccountId() {
->GetAccountId();
}
std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>
DriveIntegrationService::DriveFsHolder::CreateMojoConnectionDelegate() {
if (test_drivefs_mojo_connection_delegate_factory_)
return test_drivefs_mojo_connection_delegate_factory_.Run();
return Delegate::CreateMojoConnectionDelegate();
}
void DriveIntegrationService::DriveFsHolder::OnMounted(
const base::FilePath& path) {
on_drivefs_mounted_.Run();
......@@ -299,7 +316,9 @@ DriveIntegrationService::DriveIntegrationService(
DriveServiceInterface* test_drive_service,
const std::string& test_mount_point_name,
const base::FilePath& test_cache_root,
FileSystemInterface* test_file_system)
FileSystemInterface* test_file_system,
DriveFsMojoConnectionDelegateFactory
test_drivefs_mojo_connection_delegate_factory)
: profile_(profile),
state_(NOT_INITIALIZED),
enabled_(false),
......@@ -313,7 +332,8 @@ DriveIntegrationService::DriveIntegrationService(
profile_,
base::BindRepeating(&DriveIntegrationService::
AddDriveMountPointAfterMounted,
base::Unretained(this)))
base::Unretained(this)),
std::move(test_drivefs_mojo_connection_delegate_factory))
: nullptr),
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
......
......@@ -8,10 +8,12 @@
#include <memory>
#include "base/callback.h"
#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chromeos/components/drivefs/drivefs_host.h"
#include "components/drive/drive_notification_observer.h"
#include "components/drive/file_errors.h"
#include "components/drive/file_system_core_util.h"
......@@ -52,6 +54,8 @@ class ResourceMetadata;
class ResourceMetadataStorage;
} // namespace internal
extern const base::Feature kDriveFs;
// Interface for classes that need to observe events from
// DriveIntegrationService. All events are notified on UI thread.
class DriveIntegrationServiceObserver {
......@@ -81,6 +85,8 @@ class DriveIntegrationService : public KeyedService,
public content::NotificationObserver {
public:
class PreferenceWatcher;
using DriveFsMojoConnectionDelegateFactory = base::RepeatingCallback<
std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>()>;
// test_drive_service, test_mount_point_name, test_cache_root and
// test_file_system are used by tests to inject customized instances.
......@@ -94,7 +100,9 @@ class DriveIntegrationService : public KeyedService,
DriveServiceInterface* test_drive_service,
const std::string& test_mount_point_name,
const base::FilePath& test_cache_root,
FileSystemInterface* test_file_system);
FileSystemInterface* test_file_system,
DriveFsMojoConnectionDelegateFactory
test_drivefs_mojo_connection_delegate_factory = {});
~DriveIntegrationService() override;
// KeyedService override:
......
......@@ -32,6 +32,7 @@ class FileManagerBrowserTestBase : public extensions::ExtensionApiTest {
// ExtensionApiTest overrides.
void SetUp() override;
void SetUpCommandLine(base::CommandLine* command_line) override;
bool SetUpUserDataDirectory() override;
void SetUpInProcessBrowserTestFixture() override;
void SetUpOnMainThread() override;
......@@ -74,8 +75,8 @@ class FileManagerBrowserTestBase : public extensions::ExtensionApiTest {
std::string* output);
std::unique_ptr<LocalTestVolume> local_volume_;
std::unique_ptr<DriveTestVolume> drive_volume_;
std::map<Profile*, std::unique_ptr<DriveTestVolume>> drive_volumes_;
DriveTestVolume* drive_volume_ = nullptr;
std::unique_ptr<FakeTestVolume> usb_volume_;
std::unique_ptr<FakeTestVolume> mtp_volume_;
......
......@@ -1752,6 +1752,7 @@ test("browser_tests") {
"//ash/public/interfaces:test_interfaces",
"//chrome/browser/chromeos:arc_test_support",
"//chrome/services/file_util/public/cpp:browser_tests",
"//chromeos/components/drivefs:test_support",
"//components/arc:arc_test_support",
"//components/exo:test_support",
"//components/prefs",
......
......@@ -648,6 +648,7 @@ static_library("test_support_without_gmock") {
":power_manager_proto",
"//components/policy/proto",
"//crypto",
"//url",
]
sources = [
"dbus/fake_cros_disks_client.cc",
......
......@@ -30,6 +30,21 @@ component("drivefs") {
defines = [ "IS_DRIVEFS_IMPL" ]
}
source_set("test_support") {
testonly = true
sources = [
"fake_drivefs.cc",
"fake_drivefs.h",
]
deps = [
":drivefs",
"//base",
"//chromeos",
"//chromeos/components/drivefs/mojom",
"//net",
]
}
source_set("unit_tests") {
testonly = true
sources = [
......
// Copyright 2018 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 "chromeos/components/drivefs/fake_drivefs.h"
#include <utility>
#include <vector>
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cros_disks_client.h"
namespace drivefs {
namespace {
class FakeDriveFsMojoConnectionDelegate
: public drivefs::DriveFsHost::MojoConnectionDelegate {
public:
FakeDriveFsMojoConnectionDelegate(
drivefs::mojom::DriveFsBootstrapPtrInfo bootstrap)
: bootstrap_(std::move(bootstrap)) {}
drivefs::mojom::DriveFsBootstrapPtrInfo InitializeMojoConnection() override {
return std::move(bootstrap_);
}
void AcceptMojoConnection(base::ScopedFD handle) override { NOTREACHED(); }
private:
drivefs::mojom::DriveFsBootstrapPtrInfo bootstrap_;
DISALLOW_COPY_AND_ASSIGN(FakeDriveFsMojoConnectionDelegate);
};
std::vector<std::pair<base::RepeatingCallback<AccountId()>,
base::WeakPtr<FakeDriveFs>>>&
GetRegisteredFakeDriveFsIntances() {
static base::NoDestructor<std::vector<std::pair<
base::RepeatingCallback<AccountId()>, base::WeakPtr<FakeDriveFs>>>>
registered_fake_drivefs_instances;
return *registered_fake_drivefs_instances;
}
base::FilePath MaybeMountDriveFs(
const std::string& source_path,
const std::vector<std::string>& mount_options) {
GURL source_url(source_path);
DCHECK(source_url.is_valid());
if (source_url.scheme() != "drivefs") {
return {};
}
std::string datadir_suffix;
for (const auto& option : mount_options) {
if (base::StartsWith(option, "datadir=", base::CompareCase::SENSITIVE)) {
auto datadir =
base::FilePath(base::StringPiece(option).substr(strlen("datadir=")));
CHECK(datadir.IsAbsolute());
CHECK(!datadir.ReferencesParent());
datadir_suffix = datadir.BaseName().value();
break;
}
}
CHECK(!datadir_suffix.empty());
for (auto& registration : GetRegisteredFakeDriveFsIntances()) {
AccountId account_id = registration.first.Run();
if (registration.second && account_id.HasAccountIdKey() &&
account_id.GetAccountIdKey() == datadir_suffix) {
return registration.second->mount_path();
}
}
NOTREACHED() << datadir_suffix;
return {};
}
} // namespace
struct FakeDriveFs::FileMetadata {
std::string mime_type;
bool pinned = false;
bool hosted = false;
std::string original_name;
};
FakeDriveFs::FakeDriveFs(const base::FilePath& mount_path)
: mount_path_(mount_path),
binding_(this),
bootstrap_binding_(this),
weak_factory_(this) {
CHECK(mount_path.IsAbsolute());
CHECK(!mount_path.ReferencesParent());
}
FakeDriveFs::~FakeDriveFs() = default;
void FakeDriveFs::RegisterMountingForAccountId(
base::RepeatingCallback<AccountId()> account_id_getter) {
chromeos::DBusThreadManager* dbus_thread_manager =
chromeos::DBusThreadManager::Get();
static_cast<chromeos::FakeCrosDisksClient*>(
dbus_thread_manager->GetCrosDisksClient())
->SetCustomMountPointCallback(base::BindRepeating(&MaybeMountDriveFs));
GetRegisteredFakeDriveFsIntances().emplace_back(std::move(account_id_getter),
weak_factory_.GetWeakPtr());
}
std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>
FakeDriveFs::CreateConnectionDelegate() {
drivefs::mojom::DriveFsBootstrapPtrInfo bootstrap;
bootstrap_binding_.Bind(mojo::MakeRequest(&bootstrap));
pending_delegate_request_ = mojo::MakeRequest(&delegate_);
delegate_->OnMounted();
return std::make_unique<FakeDriveFsMojoConnectionDelegate>(
std::move(bootstrap));
}
void FakeDriveFs::SetMetadata(const base::FilePath& path,
const std::string& mime_type,
const std::string& original_name) {
auto& stored_metadata = metadata_[path];
stored_metadata.mime_type = mime_type;
stored_metadata.original_name = original_name;
stored_metadata.hosted = (original_name != path.BaseName().value());
}
void FakeDriveFs::Init(drivefs::mojom::DriveFsConfigurationPtr config,
drivefs::mojom::DriveFsRequest drive_fs_request,
drivefs::mojom::DriveFsDelegatePtr delegate) {
mojo::FuseInterface(std::move(pending_delegate_request_),
delegate.PassInterface());
binding_.Bind(std::move(drive_fs_request));
}
void FakeDriveFs::GetMetadata(const base::FilePath& path,
bool want_thumbnail,
GetMetadataCallback callback) {
base::File::Info info;
if (!base::GetFileInfo(path, &info)) {
std::move(callback).Run(drive::FILE_ERROR_NOT_FOUND, nullptr);
return;
}
auto metadata = drivefs::mojom::FileMetadata::New();
metadata->size = info.size;
metadata->modification_time = info.last_modified;
const auto& stored_metadata = metadata_[path];
metadata->pinned = stored_metadata.pinned;
metadata->content_mime_type = stored_metadata.mime_type;
metadata->hosted = stored_metadata.hosted;
if (!stored_metadata.original_name.empty()) {
base::StringPiece prefix;
if (metadata->hosted) {
prefix = "https://document_alternate_link/";
} else if (info.is_directory) {
prefix = "https://folder_alternate_link/";
} else {
prefix = "https://file_alternate_link/";
}
metadata->alternate_url =
GURL(base::StrCat({prefix, stored_metadata.original_name})).spec();
}
std::move(callback).Run(drive::FILE_ERROR_OK, std::move(metadata));
}
void FakeDriveFs::SetPinned(const base::FilePath& path,
bool pinned,
SetPinnedCallback callback) {
metadata_[path].pinned = pinned;
std::move(callback).Run(drive::FILE_ERROR_OK);
}
} // namespace drivefs
// Copyright 2018 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 CHROMEOS_COMPONENTS_DRIVEFS_FAKE_DRIVEFS_H_
#define CHROMEOS_COMPONENTS_DRIVEFS_FAKE_DRIVEFS_H_
#include <map>
#include <memory>
#include <string>
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/components/drivefs/drivefs_host.h"
#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
class AccountId;
namespace drivefs {
class FakeDriveFs : public drivefs::mojom::DriveFs,
public drivefs::mojom::DriveFsBootstrap {
public:
explicit FakeDriveFs(const base::FilePath& mount_path);
~FakeDriveFs() override;
void RegisterMountingForAccountId(
base::RepeatingCallback<AccountId()> account_id_getter);
std::unique_ptr<drivefs::DriveFsHost::MojoConnectionDelegate>
CreateConnectionDelegate();
void SetMetadata(const base::FilePath& path,
const std::string& mime_type,
const std::string& original_name);
const base::FilePath& mount_path() { return mount_path_; }
private:
struct FileMetadata;
// drivefs::mojom::DriveFsBootstrap:
void Init(drivefs::mojom::DriveFsConfigurationPtr config,
drivefs::mojom::DriveFsRequest drive_fs_request,
drivefs::mojom::DriveFsDelegatePtr delegate) override;
// drivefs::mojom::DriveFs:
void GetMetadata(const base::FilePath& path,
bool want_thumbnail,
GetMetadataCallback callback) override;
void SetPinned(const base::FilePath& path,
bool pinned,
SetPinnedCallback callback) override;
const base::FilePath mount_path_;
std::map<base::FilePath, FileMetadata> metadata_;
mojo::Binding<drivefs::mojom::DriveFs> binding_;
drivefs::mojom::DriveFsDelegatePtr delegate_;
mojo::Binding<drivefs::mojom::DriveFsBootstrap> bootstrap_binding_;
drivefs::mojom::DriveFsDelegateRequest pending_delegate_request_;
base::WeakPtrFactory<FakeDriveFs> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(FakeDriveFs);
};
} // namespace drivefs
#endif // CHROMEOS_COMPONENTS_DRIVEFS_FAKE_DRIVEFS_H_
......@@ -13,6 +13,7 @@
#include "base/single_thread_task_runner.h"
#include "base/task_scheduler/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "url/gurl.h"
namespace chromeos {
......@@ -21,6 +22,9 @@ namespace {
// Performs fake mounting by creating a directory with a dummy file.
MountError PerformFakeMount(const std::string& source_path,
const base::FilePath& mounted_path) {
if (mounted_path.empty())
return MOUNT_ERROR_INVALID_ARGUMENT;
// Just create an empty directory and shows it as the mounted directory.
if (!base::CreateDirectory(mounted_path)) {
DLOG(ERROR) << "Failed to create directory at " << mounted_path.value();
......@@ -78,6 +82,10 @@ void FakeCrosDisksClient::Mount(const std::string& source_path,
MountType type =
source_format.empty() ? MOUNT_TYPE_DEVICE : MOUNT_TYPE_ARCHIVE;
// Network storage source paths are URIs.
if (GURL(source_path).is_valid())
type = MOUNT_TYPE_NETWORK_STORAGE;
base::FilePath mounted_path;
switch (type) {
case MOUNT_TYPE_ARCHIVE:
......@@ -89,9 +97,11 @@ void FakeCrosDisksClient::Mount(const std::string& source_path,
base::FilePath::FromUTF8Unsafe(mount_label));
break;
case MOUNT_TYPE_NETWORK_STORAGE:
// TODO(sammc): Support mounting fake network storage.
NOTREACHED();
return;
if (custom_mount_point_callback_) {
mounted_path =
custom_mount_point_callback_.Run(source_path, mount_options);
}
break;
case MOUNT_TYPE_INVALID:
NOTREACHED();
return;
......@@ -217,4 +227,9 @@ void FakeCrosDisksClient::NotifyRenameCompleted(
observer.OnRenameCompleted(error_code, device_path);
}
void FakeCrosDisksClient::SetCustomMountPointCallback(
FakeCrosDisksClient::CustomMountPointCallback custom_mount_point_callback) {
custom_mount_point_callback_ = std::move(custom_mount_point_callback);
}
} // namespace chromeos
......@@ -21,6 +21,9 @@ namespace chromeos {
// and the user of this class can raise a fake mouse events.
class CHROMEOS_EXPORT FakeCrosDisksClient : public CrosDisksClient {
public:
using CustomMountPointCallback =
base::RepeatingCallback<base::FilePath(const std::string&,
const std::vector<std::string>&)>;
FakeCrosDisksClient();
~FakeCrosDisksClient() override;
......@@ -72,6 +75,9 @@ class CHROMEOS_EXPORT FakeCrosDisksClient : public CrosDisksClient {
void NotifyRenameCompleted(RenameError error_code,
const std::string& device_path);
void SetCustomMountPointCallback(
CustomMountPointCallback custom_mount_point_callback);
// Returns how many times Unmount() was called.
int unmount_call_count() const {
return unmount_call_count_;
......@@ -157,6 +163,7 @@ class CHROMEOS_EXPORT FakeCrosDisksClient : public CrosDisksClient {
std::string last_rename_volume_name_;
bool rename_success_;
std::set<base::FilePath> mounted_paths_;
CustomMountPointCallback custom_mount_point_callback_;
base::WeakPtrFactory<FakeCrosDisksClient> weak_ptr_factory_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment