blob: a7b4b3208eb955f4c66e50243a9d732e35d8bbd8 [file] [log] [blame]
// 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 "components/arc/appfuse/arc_appfuse_bridge.h"
#include <utility>
#include "base/bind.h"
#include "base/memory/singleton.h"
#include "chromeos/dbus/arc_appfuse_provider_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "components/arc/arc_bridge_service.h"
#include "components/arc/arc_browser_context_keyed_service_factory_base.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include <sys/epoll.h>
namespace arc {
namespace {
// Singleton factory for ArcAppfuseBridge.
class ArcAppfuseBridgeFactory
: public internal::ArcBrowserContextKeyedServiceFactoryBase<
ArcAppfuseBridge,
ArcAppfuseBridgeFactory> {
public:
// Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
static constexpr const char* kName = "ArcAppfuseBridgeFactory";
static ArcAppfuseBridgeFactory* GetInstance() {
return base::Singleton<ArcAppfuseBridgeFactory>::get();
}
private:
friend base::DefaultSingletonTraits<ArcAppfuseBridgeFactory>;
ArcAppfuseBridgeFactory() = default;
~ArcAppfuseBridgeFactory() override = default;
};
void RunWithScopedHandle(base::OnceCallback<void(mojo::ScopedHandle)> callback,
base::Optional<base::ScopedFD> fd) {
if (!fd || !fd.value().is_valid()) {
LOG(ERROR) << "Invalid FD: fd.has_value() = " << fd.has_value();
std::move(callback).Run(mojo::ScopedHandle());
return;
}
mojo::ScopedHandle wrapped_handle =
mojo::WrapPlatformHandle(mojo::PlatformHandle(std::move(fd.value())));
if (!wrapped_handle.is_valid()) {
LOG(ERROR) << "Failed to wrap handle";
std::move(callback).Run(mojo::ScopedHandle());
return;
}
std::move(callback).Run(std::move(wrapped_handle));
}
} // namespace
// static
ArcAppfuseBridge* ArcAppfuseBridge::GetForBrowserContext(
content::BrowserContext* context) {
return ArcAppfuseBridgeFactory::GetForBrowserContext(context);
}
ArcAppfuseBridge::ArcAppfuseBridge(content::BrowserContext* context,
ArcBridgeService* bridge_service)
: arc_bridge_service_(bridge_service) {
arc_bridge_service_->appfuse()->SetHost(this);
}
ArcAppfuseBridge::~ArcAppfuseBridge() {
arc_bridge_service_->appfuse()->SetHost(nullptr);
}
void ArcAppfuseBridge::Mount(uint32_t uid,
int32_t mount_id,
MountCallback callback) {
// This is always safe because DBusThreadManager outlives ArcServiceLauncher.
chromeos::DBusThreadManager::Get()->GetArcAppfuseProviderClient()->Mount(
uid, mount_id, base::BindOnce(&RunWithScopedHandle, std::move(callback)));
}
void ArcAppfuseBridge::Unmount(uint32_t uid,
int32_t mount_id,
UnmountCallback callback) {
chromeos::DBusThreadManager::Get()->GetArcAppfuseProviderClient()->Unmount(
uid, mount_id, std::move(callback));
}
void ArcAppfuseBridge::OpenFile(uint32_t uid,
int32_t mount_id,
int32_t file_id,
int32_t flags,
OpenFileCallback callback) {
chromeos::DBusThreadManager::Get()->GetArcAppfuseProviderClient()->OpenFile(
uid, mount_id, file_id, flags,
base::BindOnce(&RunWithScopedHandle, std::move(callback)));
}
} // namespace arc