Commit e00bfd52 authored by Anand K. Mistry's avatar Anand K. Mistry Committed by Commit Bot

Move PendingConnectionManager to a separate component.

This class will be used by smbfs to establish a Mojo channel to Chrome.

BUG=939235

Change-Id: Idc0bc822e4839325ba32f204a06cd5fe4a92e012
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1833017
Commit-Queue: Anand Mistry <amistry@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarSergei Datsenko <dats@chromium.org>
Cr-Commit-Position: refs/heads/master@{#710220}
parent a6a2f4ce
......@@ -90,6 +90,7 @@ source_set("chromeos") {
"//chromeos/components/account_manager",
"//chromeos/components/drivefs",
"//chromeos/components/drivefs/mojom",
"//chromeos/components/mojo_bootstrap",
"//chromeos/components/multidevice",
"//chromeos/components/multidevice/logging",
"//chromeos/components/power",
......
......@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include "dbus/message.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
......@@ -47,8 +47,8 @@ void DriveFileStreamServiceProvider::HandleOpenIpcChannel(
method_call, DBUS_ERROR_INVALID_ARGS, "Second argument is not FD."));
return;
}
if (!drivefs::PendingConnectionManager::Get().OpenIpcChannel(id,
std::move(fd))) {
if (!mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
id, std::move(fd))) {
response_sender.Run(dbus::ErrorResponse::FromMethodCall(
method_call, DBUS_ERROR_FAILED, "Failed to open IPC"));
return;
......
......@@ -19,6 +19,7 @@ test("chromeos_components_unittests") {
"//chromeos:chromeos_buildflags",
"//chromeos/components/account_manager:unit_tests",
"//chromeos/components/drivefs:unit_tests",
"//chromeos/components/mojo_bootstrap:unit_tests",
"//chromeos/components/multidevice:unit_tests",
"//chromeos/components/nearby:unit_tests",
"//chromeos/components/power:unit_tests",
......
......@@ -20,12 +20,11 @@ component("drivefs") {
"drivefs_util.h",
"fake_drivefs_launcher_client.cc",
"fake_drivefs_launcher_client.h",
"pending_connection_manager.cc",
"pending_connection_manager.h",
]
deps = [
"//base",
"//chromeos/components/drivefs/mojom",
"//chromeos/components/mojo_bootstrap",
"//chromeos/constants",
"//chromeos/dbus",
"//chromeos/disks",
......@@ -66,7 +65,6 @@ source_set("unit_tests") {
"drivefs_host_unittest.cc",
"drivefs_search_unittest.cc",
"drivefs_session_unittest.cc",
"pending_connection_manager_unittest.cc",
]
deps = [
......@@ -75,6 +73,7 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//chromeos/components/drivefs/mojom",
"//chromeos/components/mojo_bootstrap",
"//chromeos/disks:test_support",
"//components/account_id",
"//components/drive",
......
......@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/platform/platform_channel_endpoint.h"
......@@ -20,7 +20,7 @@ DriveFsBootstrapListener::DriveFsBootstrapListener()
: bootstrap_(invitation_.AttachMessagePipe("drivefs-bootstrap"),
mojom::DriveFsBootstrap::Version_),
pending_token_(base::UnguessableToken::Create()) {
PendingConnectionManager::Get().ExpectOpenIpcChannel(
mojo_bootstrap::PendingConnectionManager::Get().ExpectOpenIpcChannel(
pending_token_,
base::BindOnce(&DriveFsBootstrapListener::AcceptMojoConnection,
base::Unretained(this)));
......@@ -28,8 +28,8 @@ DriveFsBootstrapListener::DriveFsBootstrapListener()
DriveFsBootstrapListener::~DriveFsBootstrapListener() {
if (pending_token_) {
PendingConnectionManager::Get().CancelExpectedOpenIpcChannel(
pending_token_);
mojo_bootstrap::PendingConnectionManager::Get()
.CancelExpectedOpenIpcChannel(pending_token_);
pending_token_ = {};
}
}
......
......@@ -12,7 +12,7 @@
#include "base/test/task_environment.h"
#include "chromeos/components/drivefs/mojom/drivefs.mojom-test-utils.h"
#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
......@@ -91,8 +91,8 @@ class DriveFsBootstrapTest : public testing::Test,
}
void WaitForConnection(const base::UnguessableToken& token) {
ASSERT_TRUE(
PendingConnectionManager::Get().OpenIpcChannel(token.ToString(), {}));
ASSERT_TRUE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token.ToString(), {}));
base::RunLoop run_loop;
bootstrap_receiver_.set_disconnect_handler(run_loop.QuitClosure());
run_loop.Run();
......@@ -121,8 +121,8 @@ TEST_F(DriveFsBootstrapTest, Listen_Connect_Disconnect) {
EXPECT_CALL(*this, OnDisconnect());
receiver_.reset();
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(
PendingConnectionManager::Get().OpenIpcChannel(token.ToString(), {}));
ASSERT_FALSE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token.ToString(), {}));
}
TEST_F(DriveFsBootstrapTest, Listen_Connect_DisconnectDelegate) {
......@@ -132,8 +132,8 @@ TEST_F(DriveFsBootstrapTest, Listen_Connect_DisconnectDelegate) {
EXPECT_CALL(*this, OnDisconnect());
delegate_.reset();
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(
PendingConnectionManager::Get().OpenIpcChannel(token.ToString(), {}));
ASSERT_FALSE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token.ToString(), {}));
}
TEST_F(DriveFsBootstrapTest, Listen_Connect_Destroy) {
......@@ -143,8 +143,8 @@ TEST_F(DriveFsBootstrapTest, Listen_Connect_Destroy) {
EXPECT_CALL(*this, OnDisconnect()).Times(0);
connection_.reset();
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(
PendingConnectionManager::Get().OpenIpcChannel(token.ToString(), {}));
ASSERT_FALSE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token.ToString(), {}));
}
TEST_F(DriveFsBootstrapTest, Listen_Destroy) {
......@@ -152,8 +152,8 @@ TEST_F(DriveFsBootstrapTest, Listen_Destroy) {
auto token = ListenForConnection();
connection_.reset();
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(
PendingConnectionManager::Get().OpenIpcChannel(token.ToString(), {}));
ASSERT_FALSE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token.ToString(), {}));
}
TEST_F(DriveFsBootstrapTest, Listen_DisconnectDelegate) {
......
......@@ -22,7 +22,7 @@
#include "chromeos/components/drivefs/fake_drivefs.h"
#include "chromeos/components/drivefs/mojom/drivefs.mojom-test-utils.h"
#include "chromeos/components/drivefs/mojom/drivefs.mojom.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include "chromeos/disks/mock_disk_mount_manager.h"
#include "components/drive/drive_notification_manager.h"
#include "components/drive/drive_notification_observer.h"
......@@ -342,7 +342,8 @@ class DriveFsHostTest : public ::testing::Test, public mojom::DriveFsBootstrap {
token_ = StartMount();
DispatchMountSuccessEvent(token_);
ASSERT_TRUE(PendingConnectionManager::Get().OpenIpcChannel(token_, {}));
ASSERT_TRUE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token_, {}));
{
base::RunLoop run_loop;
bootstrap_receiver_.set_disconnect_handler(run_loop.QuitClosure());
......@@ -488,7 +489,8 @@ TEST_F(DriveFsHostTest, OnMountFailedFromDbus) {
run_loop.Run();
ASSERT_FALSE(host_->IsMounted());
EXPECT_FALSE(PendingConnectionManager::Get().OpenIpcChannel(token, {}));
EXPECT_FALSE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token, {}));
}
TEST_F(DriveFsHostTest, DestroyBeforeMojoConnection) {
......@@ -498,7 +500,8 @@ TEST_F(DriveFsHostTest, DestroyBeforeMojoConnection) {
chromeos::UNMOUNT_OPTIONS_LAZY, _));
host_.reset();
EXPECT_FALSE(PendingConnectionManager::Get().OpenIpcChannel(token, {}));
EXPECT_FALSE(mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
token, {}));
}
TEST_F(DriveFsHostTest, MountWhileAlreadyMounted) {
......
......@@ -11,7 +11,7 @@
#include "base/strings/strcat.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "chromeos/components/drivefs/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_cros_disks_client.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
......@@ -96,7 +96,7 @@ base::FilePath FakeDriveFsLauncherClient::MaybeMountDriveFs(
}
const std::string datadir = base::StrCat({"drivefs-", datadir_suffix});
mojo::PlatformChannel channel;
PendingConnectionManager::Get().OpenIpcChannel(
mojo_bootstrap::PendingConnectionManager::Get().OpenIpcChannel(
identity, channel.TakeLocalEndpoint().TakePlatformHandle().TakeFD());
launcher_->LaunchDriveFs(
base::FilePath("/tmp").Append(datadir),
......
// 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_PENDING_CONNECTION_MANAGER_H_
#define CHROMEOS_COMPONENTS_DRIVEFS_PENDING_CONNECTION_MANAGER_H_
#include <string>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/unguessable_token.h"
namespace drivefs {
class PendingConnectionManagerTest;
class COMPONENT_EXPORT(DRIVEFS) PendingConnectionManager {
public:
using OpenIpcChannelCallback = base::OnceCallback<void(base::ScopedFD)>;
static PendingConnectionManager& Get();
bool OpenIpcChannel(const std::string& identity, base::ScopedFD ipc_channel);
void ExpectOpenIpcChannel(base::UnguessableToken token,
OpenIpcChannelCallback handler);
void CancelExpectedOpenIpcChannel(base::UnguessableToken token);
private:
friend class base::NoDestructor<PendingConnectionManager>;
friend class PendingConnectionManagerTest;
PendingConnectionManager();
~PendingConnectionManager();
base::flat_map<std::string, OpenIpcChannelCallback>
open_ipc_channel_callbacks_;
DISALLOW_COPY_AND_ASSIGN(PendingConnectionManager);
};
} // namespace drivefs
#endif // CHROMEOS_COMPONENTS_DRIVEFS_PENDING_CONNECTION_MANAGER_H_
# Copyright 2019 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.
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
component("mojo_bootstrap") {
sources = [
"pending_connection_manager.cc",
"pending_connection_manager.h",
]
deps = [
"//base",
]
defines = [ "IS_MOJO_BOOTSTRAP_IMPL" ]
}
source_set("unit_tests") {
testonly = true
sources = [
"pending_connection_manager_unittest.cc",
]
deps = [
":mojo_bootstrap",
"//base/test:test_support",
"//testing/gtest",
]
}
amistry@chromium.org
dats@chromium.org
slangley@chromium.org
# COMPONENT: OS>Systems
chromeos/components/mojo_bootstrap
==================================
This directory contains classes that are useful to establish a Mojo
connection with a Chrome OS service.
In general, any class that is used by more than one Chrome OS service to
establish a Mojo connection should be moved here.
// Copyright 2018 The Chromium Authors. All rights reserved.
// Copyright 2019 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/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include <utility>
#include "base/logging.h"
namespace drivefs {
namespace mojo_bootstrap {
// static
PendingConnectionManager& PendingConnectionManager::Get() {
......@@ -16,15 +16,15 @@ PendingConnectionManager& PendingConnectionManager::Get() {
return *connection_manager;
}
bool PendingConnectionManager::OpenIpcChannel(const std::string& identity,
base::ScopedFD ipc_channel) {
auto it = open_ipc_channel_callbacks_.find(identity);
bool PendingConnectionManager::OpenIpcChannel(const std::string& token,
base::ScopedFD fd) {
auto it = open_ipc_channel_callbacks_.find(token);
if (it == open_ipc_channel_callbacks_.end()) {
return false;
}
OpenIpcChannelCallback callback = std::move(it->second);
open_ipc_channel_callbacks_.erase(it);
std::move(callback).Run(std::move(ipc_channel));
std::move(callback).Run(std::move(fd));
return true;
}
......@@ -44,4 +44,4 @@ void PendingConnectionManager::CancelExpectedOpenIpcChannel(
PendingConnectionManager::PendingConnectionManager() = default;
PendingConnectionManager::~PendingConnectionManager() = default;
} // namespace drivefs
} // namespace mojo_bootstrap
// Copyright 2019 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_MOJO_BOOTSTRAP_PENDING_CONNECTION_MANAGER_H_
#define CHROMEOS_COMPONENTS_MOJO_BOOTSTRAP_PENDING_CONNECTION_MANAGER_H_
#include <string>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/component_export.h"
#include "base/containers/flat_map.h"
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/unguessable_token.h"
namespace mojo_bootstrap {
class PendingConnectionManagerTest;
// PendingConnectionManager is used to wait for a unix domain socket to be used
// for bootstrapping a Mojo connection. The typical use case is where a system
// service is started by Chrome, but only text arguments can be passed to the
// service startup. An example of this are filesystems mounted by cros-disks,
// where only an array of strings can be passed as options to the Mount() D-Bus
// method. This class is NOT needed if a socket end can be passed to the system
// service directly.
//
// To use this class:
// 1. Create and export a D-Bus service in Chrome containing a single method
// which is passed a string and FD. (eg. org.chromium.DriveFileStream).
// This method simply calls PendingConnectionManager::OpenIpcChannel().
// 2. Create an UnguessableToken and pass the string serialisation to the system
// service. Use PendingConnectionManager::ExpectOpenIpcChannel() to wait for
// an FD.
// 3. In the system service, create a socketpair() and pass one end over the
// D-Bus method created in step 1, along with the token.
//
// Sample usage:
// --- Chrome ---
// class MyClass {
// private:
// const base::UnguessableToken token_;
// mojo::OutgoingInvitation invitation_;
// };
//
// MyClass::MyClass() : token_(base::UnguessableToken::Create()) {}
//
// void MyClass::StartService() {
// // Use this message pipe to bind an InterfacePtr<> to the Mojo service.
// mojo::ScopedMessagePipeHandle bootstrap_handle =
// invitation_.AttachMessagePipe("myservice-bootstrap");
//
// base::UnguessableToken token = base::UnguessableToken::Create();
// PendingConnectionManager::Get().ExpectOpenIpcChannel(
// token_, base::BindOnce(&MyClass::AcceptConnection,
// base::Unretained(this)));
// StartMySystemService(token_.ToString());
// }
//
// void MyClass::AcceptConnection(base::ScopedFD handle) {
// mojo::OutgoingInvitation::Send(
// std::move(invitation_), base::kNullProcessHandle,
// mojo::PlatformChannelEndpoint(
// mojo::PlatformHandle(std::move(handle))));
// }
//
// void MyClass::MyExportedDbusConnectMethod(
// dbus::MethodCall* method_call,
// dbus::ExportedObject::ResponseSender response_sender) {
// std::string token = // Pop token passed to StartMySystemService()
// base::ScopedFD fd = // Pop FD
// CHECK(PendingConnectionManager::Get().OpenIpcChannel(
// token, std::move(fd)));
// }
//
// --- System Service ---
// // Returns an InterfaceRequest<> that can be used to bind the Mojo service
// // implementation.
// mojom::MyServiceRequest MyService::BootstrapMojo() {
// mojo::edk::PlatformChannelPair channel;
// org::chromium::MyChromeServiceProxy dbus_proxy(bus_, kServiceName);
// brillo::ErrorPtr error;
// CHECK(dbus_proxy.MyExportedDbusConnectMethod(
// token_, channel.PassClientHandle().get().handle, &error));
// mojo::edk::SetParentPipeHandle(channel.PassServerHandle());
//
// mojom::MyServiceRequest request;
// request.Bind(mojo::edk::CreateChildMessagePipe("myservice-bootstrap"));
// return request;
// }
class COMPONENT_EXPORT(MOJO_BOOTSTRAP) PendingConnectionManager {
public:
using OpenIpcChannelCallback = base::OnceCallback<void(base::ScopedFD)>;
static PendingConnectionManager& Get();
// Responds to a file descriptor request for |token| with |fd|. |token| is the
// UnguessableToken::ToString() representation of the |token| parameter to
// ExpectOpenIpcChannel().
bool OpenIpcChannel(const std::string& token, base::ScopedFD ipc_channel);
// Registers a callback that is run when a file descriptor is received for
// |token|.
void ExpectOpenIpcChannel(base::UnguessableToken token,
OpenIpcChannelCallback handler);
// Cancels the pending callback for |token|.
void CancelExpectedOpenIpcChannel(base::UnguessableToken token);
private:
friend class base::NoDestructor<PendingConnectionManager>;
friend class PendingConnectionManagerTest;
PendingConnectionManager();
~PendingConnectionManager();
base::flat_map<std::string, OpenIpcChannelCallback>
open_ipc_channel_callbacks_;
DISALLOW_COPY_AND_ASSIGN(PendingConnectionManager);
};
} // namespace mojo_bootstrap
#endif // CHROMEOS_COMPONENTS_MOJO_BOOTSTRAP_PENDING_CONNECTION_MANAGER_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Copyright 2019 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/pending_connection_manager.h"
#include "chromeos/components/mojo_bootstrap/pending_connection_manager.h"
#include "base/test/bind_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace drivefs {
namespace mojo_bootstrap {
class PendingConnectionManagerTest : public testing::Test {
protected:
......@@ -41,4 +41,4 @@ TEST_F(PendingConnectionManagerTest, UnexpectedConnection) {
}
} // namespace
} // namespace drivefs
} // namespace mojo_bootstrap
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