chromium/chromeos/ash/components/tether/disconnect_tethering_operation.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/ash/components/tether/disconnect_tethering_operation.h"

#include <memory>

#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/default_clock.h"
#include "chromeos/ash/components/multidevice/logging/logging.h"
#include "chromeos/ash/components/tether/message_wrapper.h"
#include "chromeos/ash/components/tether/proto/tether.pb.h"

namespace ash::tether {

// static
DisconnectTetheringOperation::Factory*
    DisconnectTetheringOperation::Factory::factory_instance_ = nullptr;

// static
std::unique_ptr<DisconnectTetheringOperation>
DisconnectTetheringOperation::Factory::Create(
    const TetherHost& tether_host,
    raw_ptr<HostConnection::Factory> host_connection_factory) {
  if (factory_instance_) {
    return factory_instance_->CreateInstance(tether_host,
                                             host_connection_factory);
  }

  return base::WrapUnique(
      new DisconnectTetheringOperation(tether_host, host_connection_factory));
}

// static
void DisconnectTetheringOperation::Factory::SetFactoryForTesting(
    Factory* factory) {
  factory_instance_ = factory;
}

DisconnectTetheringOperation::Factory::~Factory() = default;

DisconnectTetheringOperation::DisconnectTetheringOperation(
    const TetherHost& tether_host,
    raw_ptr<HostConnection::Factory> host_connection_factory)
    : MessageTransferOperation(
          tether_host,
          HostConnection::Factory::ConnectionPriority::kHigh,
          host_connection_factory),
      has_sent_message_(false),
      clock_(base::DefaultClock::GetInstance()) {}

DisconnectTetheringOperation::~DisconnectTetheringOperation() = default;

void DisconnectTetheringOperation::AddObserver(Observer* observer) {
  observer_list_.AddObserver(observer);
}

void DisconnectTetheringOperation::RemoveObserver(Observer* observer) {
  observer_list_.RemoveObserver(observer);
}

void DisconnectTetheringOperation::NotifyObserversOperationFinished(
    bool success) {
  for (auto& observer : observer_list_) {
    observer.OnOperationFinished(GetDeviceId(/*truncate_for_logs=*/false),
                                 success);
  }
}

void DisconnectTetheringOperation::OnDeviceAuthenticated() {
  SendMessage(std::make_unique<MessageWrapper>(DisconnectTetheringRequest()),
              base::BindOnce(&DisconnectTetheringOperation::OnMessageSent,
                             weak_ptr_factory_.GetWeakPtr()));
  disconnect_start_time_ = clock_->Now();
}

void DisconnectTetheringOperation::OnOperationFinished() {
  NotifyObserversOperationFinished(has_sent_message_);
}

MessageType DisconnectTetheringOperation::GetMessageTypeForConnection() {
  return MessageType::DISCONNECT_TETHERING_REQUEST;
}

void DisconnectTetheringOperation::OnMessageSent() {
  has_sent_message_ = true;

  DCHECK(!disconnect_start_time_.is_null());
  UMA_HISTOGRAM_TIMES(
      "InstantTethering.Performance.DisconnectTetheringRequestDuration",
      clock_->Now() - disconnect_start_time_);
  disconnect_start_time_ = base::Time();

  StopOperation();
}

void DisconnectTetheringOperation::SetClockForTest(
    base::Clock* clock_for_test) {
  clock_ = clock_for_test;
}

}  // namespace ash::tether