Commit 7e995b26 authored by Sam McNally's avatar Sam McNally Committed by Commit Bot

Add a fake DriveFS launcher client.

Using DriveFS requires building and deploying ChromeOS. Add a client for
the fake DriveFS launcher to allow the use of a real DriveFS from a
ChromeOS chroot to be used with a target_os="chromeos" build of chrome.
This connects to the fake DriveFS launcher using mojo over a unix domain
socket named by a command-line flag, using the launcher to create
DriveFS instances.

Bug: 848126
Change-Id: I22dcca154d41bda196dd7c1782bb503f6bcba5b1
Reviewed-on: https://chromium-review.googlesource.com/1098434Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Sam McNally <sammc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567513}
parent 05a8dcc9
......@@ -116,6 +116,7 @@
#include "chromeos/chromeos_paths.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/components/drivefs/drive_file_stream_service_provider_delegate.h"
#include "chromeos/components/drivefs/fake_drivefs_launcher_client.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/cryptohome/homedir_methods.h"
......@@ -600,6 +601,18 @@ int ChromeBrowserMainPartsChromeos::PreEarlyInitialization() {
dbus_pre_early_init_ = std::make_unique<internal::DBusPreEarlyInit>();
if (!base::SysInfo::IsRunningOnChromeOS() &&
parsed_command_line().HasSwitch(
switches::kFakeDriveFsLauncherChrootPath) &&
parsed_command_line().HasSwitch(
switches::kFakeDriveFsLauncherSocketPath)) {
drivefs::FakeDriveFsLauncherClient::Init(
parsed_command_line().GetSwitchValuePath(
switches::kFakeDriveFsLauncherChrootPath),
parsed_command_line().GetSwitchValuePath(
switches::kFakeDriveFsLauncherSocketPath));
}
return ChromeBrowserMainPartsLinux::PreEarlyInitialization();
}
......
......@@ -414,6 +414,17 @@ const char kEnterpriseEnrollmentInitialModulus[] =
const char kEnterpriseEnrollmentModulusLimit[] =
"enterprise-enrollment-modulus-limit";
// An absolute path to the chroot hosting the DriveFS to use. This is only used
// when running on Linux, i.e. when IsRunningOnChromeOS() returns false.
const char kFakeDriveFsLauncherChrootPath[] =
"fake-drivefs-launcher-chroot-path";
// A relative path to socket to communicat with the fake DriveFS launcher within
// the chroot specified by kFakeDriveFsLauncherChrootPath. This is only used
// when running on Linux, i.e. when IsRunningOnChromeOS() returns false.
const char kFakeDriveFsLauncherSocketPath[] =
"fake-drivefs-launcher-socket-path";
// Passed to Chrome the first time that it's run after the system boots.
// Not passed on restart after sign out.
const char kFirstExecAfterBoot[] = "first-exec-after-boot";
......
......@@ -120,6 +120,8 @@ CHROMEOS_EXPORT extern const char kEnterpriseEnableZeroTouchEnrollment[];
CHROMEOS_EXPORT extern const char kEnterpriseEnrollmentInitialModulus[];
CHROMEOS_EXPORT extern const char kEnterpriseEnrollmentModulusLimit[];
CHROMEOS_EXPORT extern const char kFirstExecAfterBoot[];
CHROMEOS_EXPORT extern const char kFakeDriveFsLauncherChrootPath[];
CHROMEOS_EXPORT extern const char kFakeDriveFsLauncherSocketPath[];
CHROMEOS_EXPORT extern const char kForceFirstRunUI[];
CHROMEOS_EXPORT extern const char kForceHappinessTrackingSystem[];
CHROMEOS_EXPORT extern const char kForceLoginManagerInTests[];
......
......@@ -11,6 +11,8 @@ component("drivefs") {
"drivefs_host.cc",
"drivefs_host.h",
"drivefs_host_observer.h",
"fake_drivefs_launcher_client.cc",
"fake_drivefs_launcher_client.h",
"pending_connection_manager.cc",
"pending_connection_manager.h",
]
......
......@@ -82,13 +82,6 @@ class DriveFsHost::MountState : public mojom::DriveFsDelegate,
host_->profile_path_.Append(kDataPath)
.Append(host_->delegate_->GetAccountId().GetAccountIdKey())
.value()});
chromeos::disks::DiskMountManager::GetInstance()->MountPath(
source_path_, "",
base::StrCat(
{"drivefs-", host_->delegate_->GetAccountId().GetAccountIdKey()}),
{datadir_option}, chromeos::MOUNT_TYPE_NETWORK_STORAGE,
chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
auto bootstrap =
mojo::MakeProxy(mojo_connection_delegate_->InitializeMojoConnection());
mojom::DriveFsDelegatePtr delegate;
......@@ -102,6 +95,13 @@ class DriveFsHost::MountState : public mojom::DriveFsDelegate,
pending_token_,
base::BindOnce(&DriveFsHost::MountState::AcceptMojoConnection,
base::Unretained(this)));
chromeos::disks::DiskMountManager::GetInstance()->MountPath(
source_path_, "",
base::StrCat(
{"drivefs-", host_->delegate_->GetAccountId().GetAccountIdKey()}),
{datadir_option}, chromeos::MOUNT_TYPE_NETWORK_STORAGE,
chromeos::MOUNT_ACCESS_MODE_READ_WRITE);
}
~MountState() override {
......
// 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_launcher_client.h"
#include <utility>
#include <vector>
#include "base/strings/strcat.h"
#include "base/sys_info.h"
#include "base/task_scheduler/post_task.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cros_disks_client.h"
#include "mojo/edk/embedder/embedder.h"
#include "mojo/edk/embedder/named_platform_handle.h"
#include "mojo/edk/embedder/named_platform_handle_utils.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "url/gurl.h"
namespace drivefs {
namespace {
void ConnectAsync(mojom::FakeDriveFsLauncherRequest request,
mojo::edk::NamedPlatformHandle os_pipe) {
mojo::edk::ScopedInternalPlatformHandle os_pipe_handle =
mojo::edk::CreateClientHandle(os_pipe);
if (!os_pipe_handle.is_valid()) {
return;
}
mojo::OutgoingInvitation invitation;
mojo::FuseMessagePipes(invitation.AttachMessagePipe("drivefs-launcher"),
request.PassMessagePipe());
mojo::OutgoingInvitation::Send(
std::move(invitation), base::kNullProcessHandle,
mojo::PlatformChannelEndpoint(mojo::PlatformHandle(
base::ScopedFD(os_pipe_handle.release().handle))));
}
} // namespace
// static
void FakeDriveFsLauncherClient::Init(const base::FilePath& chroot_path,
const base::FilePath& socket_path) {
DCHECK(!base::SysInfo::IsRunningOnChromeOS());
DCHECK(chroot_path.IsAbsolute());
DCHECK(!socket_path.IsAbsolute());
static base::NoDestructor<FakeDriveFsLauncherClient>
fake_drivefs_launcher_client(chroot_path, socket_path);
}
FakeDriveFsLauncherClient::FakeDriveFsLauncherClient(
const base::FilePath& chroot_path,
const base::FilePath& socket_path)
: chroot_path_(chroot_path),
socket_path_(chroot_path_.Append(socket_path)) {
mojo::edk::NamedPlatformHandle os_pipe(socket_path_.value());
base::PostTaskWithTraits(
FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
base::BindOnce(&ConnectAsync, mojo::MakeRequest(&launcher_), os_pipe));
chromeos::DBusThreadManager* dbus_thread_manager =
chromeos::DBusThreadManager::Get();
static_cast<chromeos::FakeCrosDisksClient*>(
dbus_thread_manager->GetCrosDisksClient())
->SetCustomMountPointCallback(
base::BindRepeating(&FakeDriveFsLauncherClient::MaybeMountDriveFs,
base::Unretained(this)));
}
FakeDriveFsLauncherClient::~FakeDriveFsLauncherClient() = default;
base::FilePath FakeDriveFsLauncherClient::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 {};
}
const auto identity = base::FilePath(source_url.path()).BaseName().value();
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;
}
}
const std::string datadir = base::StrCat({"drivefs-", datadir_suffix});
mojo::PlatformChannel channel;
PendingConnectionManager::Get().OpenIpcChannel(
identity, channel.TakeLocalEndpoint().TakePlatformHandle().TakeFD());
launcher_->LaunchDriveFs(
base::FilePath("/tmp").Append(datadir),
base::FilePath("/media/fuse").Append(datadir),
mojo::WrapPlatformHandle(
channel.TakeRemoteEndpoint().TakePlatformHandle()));
return chroot_path_.Append("media/fuse").Append(datadir);
}
} // 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_LAUNCHER_CLIENT_H_
#define CHROMEOS_COMPONENTS_DRIVEFS_FAKE_DRIVEFS_LAUNCHER_CLIENT_H_
#include "base/component_export.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/no_destructor.h"
#include "chromeos/components/drivefs/mojom/fake_drivefs_launcher.mojom.h"
namespace drivefs {
class FakeDriveFsLauncherClient {
public:
COMPONENT_EXPORT(DRIVEFS)
static void Init(const base::FilePath& socket_path,
const base::FilePath& chroot_path);
private:
friend class base::NoDestructor<FakeDriveFsLauncherClient>;
FakeDriveFsLauncherClient(const base::FilePath& chroot_path,
const base::FilePath& socket_path);
~FakeDriveFsLauncherClient();
base::FilePath MaybeMountDriveFs(
const std::string& source_path,
const std::vector<std::string>& mount_options);
const base::FilePath chroot_path_;
const base::FilePath socket_path_;
mojom::FakeDriveFsLauncherPtr launcher_;
DISALLOW_COPY_AND_ASSIGN(FakeDriveFsLauncherClient);
};
} // namespace drivefs
#endif // CHROMEOS_COMPONENTS_DRIVEFS_FAKE_DRIVEFS_LAUNCHER_CLIENT_H_
......@@ -7,6 +7,7 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom_component("mojom") {
sources = [
"drivefs.mojom",
"fake_drivefs_launcher.mojom",
]
public_deps = [
......
// 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.
module drivefs.mojom;
import "mojo/public/mojom/base/file_path.mojom";
// This file tracks platform/drivefs/mojom/fake_drivefs_launcher.mojom.
// Changes should be made there first and then replicated here.
interface FakeDriveFsLauncher {
// Launch a DriveFS, using |datadir_path| for its data, mounting at
// |mount_path|, using |mojo_socket_handle| to communicate with chrome.
LaunchDriveFs(mojo_base.mojom.FilePath datadir_path,
mojo_base.mojom.FilePath mount_path,
handle mojo_socket_handle);
};
......@@ -21,7 +21,8 @@ namespace {
// Performs fake mounting by creating a directory with a dummy file.
MountError PerformFakeMount(const std::string& source_path,
const base::FilePath& mounted_path) {
const base::FilePath& mounted_path,
MountType type) {
if (mounted_path.empty())
return MOUNT_ERROR_INVALID_ARGUMENT;
......@@ -31,6 +32,11 @@ MountError PerformFakeMount(const std::string& source_path,
return MOUNT_ERROR_DIRECTORY_CREATION_FAILED;
}
// Fake network mounts are responsible for populating their mount paths so
// don't need a dummy file.
if (type == MOUNT_TYPE_NETWORK_STORAGE)
return MOUNT_ERROR_NONE;
// Put a dummy file.
const base::FilePath dummy_file_path =
mounted_path.Append("SUCCESSFULLY_PERFORMED_FAKE_MOUNT.txt");
......@@ -111,7 +117,7 @@ void FakeCrosDisksClient::Mount(const std::string& source_path,
base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&PerformFakeMount, source_path, mounted_path),
base::BindOnce(&PerformFakeMount, source_path, mounted_path, type),
base::BindOnce(&FakeCrosDisksClient::DidMount,
weak_ptr_factory_.GetWeakPtr(), source_path, type,
mounted_path, std::move(callback)));
......
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