blob: a2b1fab33ec134582472b42a96dccb912ce2892c [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 "chromeos/components/drivefs/drivefs_bootstrap.h"
#include <utility>
#include "base/bind.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
#include "mojo/public/cpp/system/invitation.h"
namespace drivefs {
DriveFsBootstrapListener::DriveFsBootstrapListener()
: bootstrap_(mojo::MakeProxy(mojom::DriveFsBootstrapPtrInfo(
invitation_.AttachMessagePipe("drivefs-bootstrap"),
mojom::DriveFsBootstrap::Version_))),
pending_token_(base::UnguessableToken::Create()) {
PendingConnectionManager::Get().ExpectOpenIpcChannel(
pending_token_,
base::BindOnce(&DriveFsBootstrapListener::AcceptMojoConnection,
base::Unretained(this)));
}
DriveFsBootstrapListener::~DriveFsBootstrapListener() {
if (pending_token_) {
PendingConnectionManager::Get().CancelExpectedOpenIpcChannel(
pending_token_);
pending_token_ = {};
}
}
mojom::DriveFsBootstrapPtr DriveFsBootstrapListener::bootstrap() {
return std::move(bootstrap_);
}
void DriveFsBootstrapListener::AcceptMojoConnection(base::ScopedFD handle) {
DCHECK(pending_token_);
pending_token_ = {};
connected_ = true;
SendInvitationOverPipe(std::move(handle));
}
void DriveFsBootstrapListener::SendInvitationOverPipe(base::ScopedFD handle) {
mojo::OutgoingInvitation::Send(
std::move(invitation_), base::kNullProcessHandle,
mojo::PlatformChannelEndpoint(mojo::PlatformHandle(std::move(handle))));
}
class DriveFsConnectionImpl : public DriveFsConnection {
public:
DriveFsConnectionImpl(
std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
mojom::DriveFsConfigurationPtr config)
: bootstrap_listener_(std::move(bootstrap_listener)),
config_(std::move(config)) {}
~DriveFsConnectionImpl() override = default;
base::UnguessableToken Connect(mojom::DriveFsDelegate* delegate,
base::OnceClosure on_disconnected) override {
delegate_binding_ =
std::make_unique<mojo::Binding<mojom::DriveFsDelegate>>(delegate);
on_disconnected_ = std::move(on_disconnected);
auto bootstrap = bootstrap_listener_->bootstrap();
auto token = bootstrap_listener_->pending_token();
mojom::DriveFsDelegatePtr delegate_ptr;
delegate_binding_->Bind(mojo::MakeRequest(&delegate_ptr));
delegate_binding_->set_connection_error_handler(base::BindOnce(
&DriveFsConnectionImpl::OnMojoConnectionError, base::Unretained(this)));
bootstrap->Init(std::move(config_), mojo::MakeRequest(&drivefs_),
std::move(delegate_ptr));
drivefs_.set_connection_error_handler(base::BindOnce(
&DriveFsConnectionImpl::OnMojoConnectionError, base::Unretained(this)));
return token;
}
mojom::DriveFs& GetDriveFs() override {
CHECK(drivefs_);
return *drivefs_;
}
private:
void OnMojoConnectionError() {
if (on_disconnected_ && bootstrap_listener_->is_connected()) {
std::move(on_disconnected_).Run();
}
}
const std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener_;
mojom::DriveFsConfigurationPtr config_;
std::unique_ptr<mojo::Binding<mojom::DriveFsDelegate>> delegate_binding_;
mojom::DriveFsPtr drivefs_;
base::OnceClosure on_disconnected_;
DISALLOW_COPY_AND_ASSIGN(DriveFsConnectionImpl);
};
std::unique_ptr<DriveFsConnection> DriveFsConnection::Create(
std::unique_ptr<DriveFsBootstrapListener> bootstrap_listener,
mojom::DriveFsConfigurationPtr config) {
return std::make_unique<DriveFsConnectionImpl>(std::move(bootstrap_listener),
std::move(config));
}
} // namespace drivefs