blob: 11d211d2cd630e5f930edb95d3d13bc78865784c [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/services/secure_channel/secure_channel_initializer.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "chromeos/services/secure_channel/secure_channel_impl.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
namespace chromeos {
namespace secure_channel {
// static
SecureChannelInitializer::Factory*
SecureChannelInitializer::Factory::test_factory_ = nullptr;
// static
SecureChannelInitializer::Factory* SecureChannelInitializer::Factory::Get() {
if (test_factory_)
return test_factory_;
static base::NoDestructor<Factory> factory;
return factory.get();
}
// static
void SecureChannelInitializer::Factory::SetFactoryForTesting(
Factory* test_factory) {
test_factory_ = test_factory;
}
SecureChannelInitializer::Factory::~Factory() = default;
std::unique_ptr<SecureChannelBase>
SecureChannelInitializer::Factory::BuildInstance(
scoped_refptr<base::TaskRunner> task_runner) {
return base::WrapUnique(new SecureChannelInitializer(task_runner));
}
SecureChannelInitializer::ConnectionRequestArgs::ConnectionRequestArgs(
const multidevice::RemoteDevice& device_to_connect,
const multidevice::RemoteDevice& local_device,
const std::string& feature,
ConnectionPriority connection_priority,
mojom::ConnectionDelegatePtr delegate,
bool is_listen_request)
: device_to_connect(device_to_connect),
local_device(local_device),
feature(feature),
connection_priority(connection_priority),
delegate(std::move(delegate)),
is_listen_request(is_listen_request) {}
SecureChannelInitializer::ConnectionRequestArgs::~ConnectionRequestArgs() =
default;
SecureChannelInitializer::SecureChannelInitializer(
scoped_refptr<base::TaskRunner> task_runner)
: weak_ptr_factory_(this) {
PA_LOG(VERBOSE) << "SecureChannelInitializer::SecureChannelInitializer(): "
<< "Fetching Bluetooth adapter. All requests received before "
<< "the adapter is fetched will be queued.";
// device::BluetoothAdapterFactory::SetAdapterForTesting() causes the
// GetAdapter() callback to return synchronously. Thus, post the GetAdapter()
// call as a task to ensure that it is returned asynchronously, even in tests.
task_runner->PostTask(
FROM_HERE,
base::Bind(
device::BluetoothAdapterFactory::GetAdapter,
base::Bind(&SecureChannelInitializer::OnBluetoothAdapterReceived,
weak_ptr_factory_.GetWeakPtr())));
}
SecureChannelInitializer::~SecureChannelInitializer() = default;
void SecureChannelInitializer::ListenForConnectionFromDevice(
const multidevice::RemoteDevice& device_to_connect,
const multidevice::RemoteDevice& local_device,
const std::string& feature,
ConnectionPriority connection_priority,
mojom::ConnectionDelegatePtr delegate) {
if (secure_channel_impl_) {
secure_channel_impl_->ListenForConnectionFromDevice(
device_to_connect, local_device, feature, connection_priority,
std::move(delegate));
return;
}
pending_args_.push(std::make_unique<ConnectionRequestArgs>(
device_to_connect, local_device, feature, connection_priority,
std::move(delegate), true /* is_listen_request */));
}
void SecureChannelInitializer::InitiateConnectionToDevice(
const multidevice::RemoteDevice& device_to_connect,
const multidevice::RemoteDevice& local_device,
const std::string& feature,
ConnectionPriority connection_priority,
mojom::ConnectionDelegatePtr delegate) {
if (secure_channel_impl_) {
secure_channel_impl_->InitiateConnectionToDevice(
device_to_connect, local_device, feature, connection_priority,
std::move(delegate));
return;
}
pending_args_.push(std::make_unique<ConnectionRequestArgs>(
device_to_connect, local_device, feature, connection_priority,
std::move(delegate), false /* is_listen_request */));
}
void SecureChannelInitializer::OnBluetoothAdapterReceived(
scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) {
PA_LOG(VERBOSE) << "SecureChannelInitializer::OnBluetoothAdapterReceived(): "
<< "Bluetooth adapter has been fetched. Passing all queued "
<< "requests to the service.";
secure_channel_impl_ =
SecureChannelImpl::Factory::Get()->BuildInstance(bluetooth_adapter);
while (!pending_args_.empty()) {
std::unique_ptr<ConnectionRequestArgs> args_to_pass =
std::move(pending_args_.front());
pending_args_.pop();
if (args_to_pass->is_listen_request) {
secure_channel_impl_->ListenForConnectionFromDevice(
args_to_pass->device_to_connect, args_to_pass->local_device,
args_to_pass->feature, args_to_pass->connection_priority,
std::move(args_to_pass->delegate));
continue;
}
secure_channel_impl_->InitiateConnectionToDevice(
args_to_pass->device_to_connect, args_to_pass->local_device,
args_to_pass->feature, args_to_pass->connection_priority,
std::move(args_to_pass->delegate));
}
}
} // namespace secure_channel
} // namespace chromeos