File: disconnect_tethering_request_sender_impl.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 4,772 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 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_request_sender_impl.h"

#include <memory>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "chromeos/ash/components/multidevice/logging/logging.h"
#include "chromeos/ash/components/tether/tether_host_fetcher.h"

namespace ash::tether {

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

// static
std::unique_ptr<DisconnectTetheringRequestSender>
DisconnectTetheringRequestSenderImpl::Factory::Create(
    raw_ptr<HostConnection::Factory> host_connection_factory,
    TetherHostFetcher* tether_host_fetcher) {
  if (factory_instance_) {
    return factory_instance_->CreateInstance(host_connection_factory,
                                             tether_host_fetcher);
  }

  return base::WrapUnique(new DisconnectTetheringRequestSenderImpl(
      host_connection_factory, tether_host_fetcher));
}

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

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

DisconnectTetheringRequestSenderImpl::DisconnectTetheringRequestSenderImpl(
    raw_ptr<HostConnection::Factory> host_connection_factory,
    TetherHostFetcher* tether_host_fetcher)
    : host_connection_factory_(host_connection_factory),
      tether_host_fetcher_(tether_host_fetcher) {}

DisconnectTetheringRequestSenderImpl::~DisconnectTetheringRequestSenderImpl() {
  for (auto const& entry : device_id_to_operation_map_) {
    entry.second->RemoveObserver(this);
  }
}

void DisconnectTetheringRequestSenderImpl::SendDisconnectRequestToDevice(
    const std::string& device_id) {
  if (base::Contains(device_id_to_operation_map_, device_id)) {
    return;
  }

  std::optional<multidevice::RemoteDeviceRef> tether_host =
      tether_host_fetcher_->GetTetherHost();

  if (!tether_host || tether_host->GetDeviceId() != device_id) {
    PA_LOG(ERROR) << "Could not fetch device with ID "
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id)
                  << ". Unable to send DisconnectTetheringRequest.";
    return;
  }

  PA_LOG(VERBOSE) << "Attempting to send DisconnectTetheringRequest to device "
                  << "with ID "
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id);

  std::unique_ptr<DisconnectTetheringOperation> disconnect_tethering_operation =
      DisconnectTetheringOperation::Factory::Create(TetherHost(*tether_host),
                                                    host_connection_factory_);

  // Add to the map.
  device_id_to_operation_map_.emplace(
      device_id, std::move(disconnect_tethering_operation));

  // Start the operation; OnOperationFinished() will be called when finished.
  device_id_to_operation_map_.at(device_id)->AddObserver(this);
  device_id_to_operation_map_.at(device_id)->Initialize();
}

bool DisconnectTetheringRequestSenderImpl::HasPendingRequests() {
  return !device_id_to_operation_map_.empty();
}

void DisconnectTetheringRequestSenderImpl::OnOperationFinished(
    const std::string& device_id,
    bool success) {
  if (success) {
    PA_LOG(VERBOSE) << "Successfully sent DisconnectTetheringRequest to device "
                    << "with ID "
                    << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                           device_id);
  } else {
    PA_LOG(ERROR) << "Failed to send DisconnectTetheringRequest to device "
                  << "with ID "
                  << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(
                         device_id);
  }

  bool had_pending_requests = HasPendingRequests();

  if (base::Contains(device_id_to_operation_map_, device_id)) {
    // Regardless of success/failure, unregister as a listener and delete the
    // operation.
    device_id_to_operation_map_.at(device_id)->RemoveObserver(this);
    device_id_to_operation_map_.erase(device_id);
  } else {
    PA_LOG(ERROR)
        << "Operation finished, but device with ID "
        << multidevice::RemoteDeviceRef::TruncateDeviceIdForLogs(device_id)
        << " was not being tracked by DisconnectTetheringRequestSender.";
  }

  // If there were pending requests but now there are none, notify the
  // Observers.
  if (had_pending_requests && !HasPendingRequests()) {
    NotifyPendingDisconnectRequestsComplete();
  }
}

}  // namespace ash::tether