chromium/chromeos/ash/components/network/fake_stub_cellular_networks_provider.cc

// Copyright 2021 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/network/fake_stub_cellular_networks_provider.h"

#include "base/containers/contains.h"
#include "base/ranges/algorithm.h"
#include "base/uuid.h"
#include "chromeos/ash/components/network/cellular_utils.h"

namespace ash {

FakeStubCellularNetworksProvider::FakeStubCellularNetworksProvider() = default;

FakeStubCellularNetworksProvider::~FakeStubCellularNetworksProvider() = default;

void FakeStubCellularNetworksProvider::AddStub(const std::string& stub_iccid,
                                               const std::string& stub_eid,
                                               bool is_managed) {
  stub_iccid_and_eid_pairs_.emplace(stub_iccid, stub_eid);
  if (is_managed)
    managed_iccids_.insert(stub_iccid);
}

void FakeStubCellularNetworksProvider::RemoveStub(const std::string& stub_iccid,
                                                  const std::string& stub_eid) {
  stub_iccid_and_eid_pairs_.erase(std::make_pair(stub_iccid, stub_eid));
  managed_iccids_.erase(stub_iccid);
}

bool FakeStubCellularNetworksProvider::AddOrRemoveStubCellularNetworks(
    NetworkStateHandler::ManagedStateList& network_list,
    NetworkStateHandler::ManagedStateList& new_stub_networks,
    const DeviceState* device) {
  bool changed = false;

  // Add new stub networks if they do not correspond to an existing Shill-backed
  // network.
  std::vector<IccidEidPair> stubs_to_add =
      GetStubsNotBackedByShill(network_list);
  if (!stubs_to_add.empty()) {
    changed = true;
    for (const IccidEidPair& pair : stubs_to_add) {
      new_stub_networks.push_back(NetworkState::CreateNonShillCellularNetwork(
          pair.first, pair.second, GetGuidForStubIccid(pair.first),
          base::Contains(managed_iccids_, pair.first), device->path()));
      stub_networks_add_count_++;
    }
  }

  // Removing existing stub networks if they are no longer applicable.
  auto network_list_it = network_list.begin();
  while (network_list_it != network_list.end()) {
    const NetworkState* network = (*network_list_it)->AsNetworkState();

    if (!network->IsNonShillCellularNetwork()) {
      ++network_list_it;
      continue;
    }

    std::string iccid = network->iccid();

    // Stub network which corresponds to a removed stub ICCID; remove.
    if (!base::Contains(stub_iccid_and_eid_pairs_, iccid,
                        &IccidEidPair::first)) {
      changed = true;
      network_list_it = network_list.erase(network_list_it);
      continue;
    }

    if (base::ranges::none_of(
            network_list, [&iccid](const std::unique_ptr<ManagedState>& state) {
              const NetworkState* network = state->AsNetworkState();
              return !network->IsNonShillCellularNetwork() &&
                     network->iccid() == iccid;
            })) {
      ++network_list_it;
      continue;
    }

    // Stub network which has been replaced by a non-stub network; remove.
    changed = true;
    network_list_it = network_list.erase(network_list_it);
  }

  return changed;
}

bool FakeStubCellularNetworksProvider::GetStubNetworkMetadata(
    const std::string& iccid,
    const DeviceState* cellular_device,
    std::string* service_path_out,
    std::string* guid_out) {
  if (!base::Contains(stub_iccid_and_eid_pairs_, iccid, &IccidEidPair::first))
    return false;

  *service_path_out = cellular_utils::GenerateStubCellularServicePath(iccid);
  *guid_out = GetGuidForStubIccid(iccid);
  return true;
}

const std::string& FakeStubCellularNetworksProvider::GetGuidForStubIccid(
    const std::string& iccid) {
  std::string& guid = iccid_to_guid_map_[iccid];

  // If we have not yet generated a GUID for this ICCID, generate one.
  if (guid.empty())
    guid = base::Uuid::GenerateRandomV4().AsLowercaseString();

  return guid;
}

std::vector<FakeStubCellularNetworksProvider::IccidEidPair>
FakeStubCellularNetworksProvider::GetStubsNotBackedByShill(
    const NetworkStateHandler::ManagedStateList& network_list) const {
  std::vector<IccidEidPair> not_backed_by_shill;

  for (const IccidEidPair& pair : stub_iccid_and_eid_pairs_) {
    // Only need to add a stub network if the stub ICCID does not match the
    // ICCID of a Shill-backed network.
    if (!base::Contains(network_list, pair.first,
                        [](const std::unique_ptr<ManagedState>& state) {
                          return state->AsNetworkState()->iccid();
                        })) {
      not_backed_by_shill.push_back(pair);
    }
  }

  return not_backed_by_shill;
}

}  // namespace ash