blob: b73b2e04b210385596763999aa871dd582cae7af [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_disconnector_impl.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "chromeos/components/multidevice/logging/logging.h"
namespace chromeos {
namespace secure_channel {
// static
SecureChannelDisconnectorImpl::Factory*
SecureChannelDisconnectorImpl::Factory::test_factory_ = nullptr;
// static
SecureChannelDisconnectorImpl::Factory*
SecureChannelDisconnectorImpl::Factory::Get() {
if (test_factory_)
return test_factory_;
static base::NoDestructor<Factory> factory;
return factory.get();
}
// static
void SecureChannelDisconnectorImpl::Factory::SetFactoryForTesting(
Factory* test_factory) {
test_factory_ = test_factory;
}
SecureChannelDisconnectorImpl::Factory::~Factory() = default;
std::unique_ptr<SecureChannelDisconnector>
SecureChannelDisconnectorImpl::Factory::BuildInstance() {
return base::WrapUnique(new SecureChannelDisconnectorImpl());
}
SecureChannelDisconnectorImpl::SecureChannelDisconnectorImpl() = default;
SecureChannelDisconnectorImpl::~SecureChannelDisconnectorImpl() = default;
void SecureChannelDisconnectorImpl::DisconnectSecureChannel(
std::unique_ptr<SecureChannel> channel_to_disconnect) {
// If |channel_to_disconnect| was already DISCONNECTING, this function is a
// no-op. If |channel_to_disconnecting| was CONNECTING, this function
// immediately causes the channel to switch to DISCONNECTED. Both of these
// cases trigger an early return below.
channel_to_disconnect->Disconnect();
if (channel_to_disconnect->status() == SecureChannel::Status::DISCONNECTED) {
return;
}
// If no early return occurred, |channel_to_disconnect| is now DISCONNECTING.
DCHECK_EQ(SecureChannel::Status::DISCONNECTING,
channel_to_disconnect->status());
// Observe |channel_to_disconnect| so that we can be alerted when it does
// eventually transition to DISCONNECTED.
channel_to_disconnect->AddObserver(this);
disconnecting_channels_.insert(std::move(channel_to_disconnect));
}
void SecureChannelDisconnectorImpl::OnSecureChannelStatusChanged(
SecureChannel* secure_channel,
const SecureChannel::Status& old_status,
const SecureChannel::Status& new_status) {
if (new_status != SecureChannel::Status::DISCONNECTED)
return;
for (auto it = disconnecting_channels_.begin();
it != disconnecting_channels_.end(); ++it) {
if (secure_channel == it->get()) {
(*it)->RemoveObserver(this);
disconnecting_channels_.erase(it);
return;
}
}
PA_LOG(ERROR) << "SecureChannelDisconnectorImpl::"
<< "OnSecureChannelStatusChanged(): Channel was disconnected, "
<< "but it was not being tracked.";
NOTREACHED();
}
} // namespace secure_channel
} // namespace chromeos