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

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chromeos/ash/components/network/network_type_pattern.h"

#include <stddef.h>

#include "base/notreached.h"
#include "chromeos/ash/components/network/network_event_log.h"
#include "chromeos/ash/components/network/tether_constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace ash {

namespace {

const char kPatternDefault[] = "PatternDefault";
const char kPatternWireless[] = "PatternWireless";
const char kPatternMobile[] = "PatternMobile";
const char kPatternNonVirtual[] = "PatternNonVirtual";
const char kPatternPhysical[] = "PatternPhysical";

enum NetworkTypeBitFlag {
  kNetworkTypeNone = 0,
  kNetworkTypeEthernet = 1 << 0,
  kNetworkTypeWifi = 1 << 1,
  kNetworkTypeCellular = 1 << 2,
  kNetworkTypeVPN = 1 << 3,
  kNetworkTypeEthernetEap = 1 << 4,
  kNetworkTypeTether = 1 << 5
};

struct ShillToBitFlagEntry {
  const char* shill_network_type;
  NetworkTypeBitFlag bit_flag;
} shill_type_to_flag[] = {{shill::kTypeEthernet, kNetworkTypeEthernet},
                          {shill::kTypeEthernetEap, kNetworkTypeEthernetEap},
                          {shill::kTypeWifi, kNetworkTypeWifi},
                          {shill::kTypeCellular, kNetworkTypeCellular},
                          {shill::kTypeVPN, kNetworkTypeVPN},
                          {kTypeTether, kNetworkTypeTether}};

NetworkTypeBitFlag ShillNetworkTypeToFlag(const std::string& shill_type) {
  for (size_t i = 0; i < std::size(shill_type_to_flag); ++i) {
    if (shill_type_to_flag[i].shill_network_type == shill_type)
      return shill_type_to_flag[i].bit_flag;
  }
  NET_LOG(ERROR) << "ShillNetworkTypeToFlag unknown type: " << shill_type;
  return kNetworkTypeNone;
}

}  // namespace

// static
NetworkTypePattern NetworkTypePattern::Default() {
  return NetworkTypePattern(~0);
}

// static
NetworkTypePattern NetworkTypePattern::Wireless() {
  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeCellular |
                            kNetworkTypeTether);
}

// static
NetworkTypePattern NetworkTypePattern::Mobile() {
  return NetworkTypePattern(kNetworkTypeCellular | kNetworkTypeTether);
}

// static
NetworkTypePattern NetworkTypePattern::Physical() {
  return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeCellular |
                            kNetworkTypeEthernet);
}

// static
NetworkTypePattern NetworkTypePattern::NonVirtual() {
  return NetworkTypePattern(~(kNetworkTypeVPN | kNetworkTypeEthernetEap));
}

// static
NetworkTypePattern NetworkTypePattern::Ethernet() {
  return NetworkTypePattern(kNetworkTypeEthernet);
}

// static
NetworkTypePattern NetworkTypePattern::EthernetOrEthernetEAP() {
  return NetworkTypePattern(kNetworkTypeEthernet | kNetworkTypeEthernetEap);
}

// static
NetworkTypePattern NetworkTypePattern::WiFi() {
  return NetworkTypePattern(kNetworkTypeWifi);
}

// static
NetworkTypePattern NetworkTypePattern::Cellular() {
  return NetworkTypePattern(kNetworkTypeCellular);
}

// static
NetworkTypePattern NetworkTypePattern::VPN() {
  return NetworkTypePattern(kNetworkTypeVPN);
}

// static
NetworkTypePattern NetworkTypePattern::Tether() {
  return NetworkTypePattern(kNetworkTypeTether);
}

// static
NetworkTypePattern NetworkTypePattern::Primitive(
    const std::string& shill_network_type) {
  return NetworkTypePattern(ShillNetworkTypeToFlag(shill_network_type));
}

bool NetworkTypePattern::Equals(const NetworkTypePattern& other) const {
  return pattern_ == other.pattern_;
}

bool NetworkTypePattern::MatchesType(
    const std::string& shill_network_type) const {
  if (shill_network_type.empty()) {
    NET_LOG(ERROR) << "NetworkTypePattern: " << ToDebugString()
                   << ": Can not match empty type.";
    return false;
  }
  return MatchesPattern(Primitive(shill_network_type));
}

bool NetworkTypePattern::MatchesPattern(
    const NetworkTypePattern& other_pattern) const {
  if (Equals(other_pattern))
    return true;

  return pattern_ & other_pattern.pattern_;
}

NetworkTypePattern NetworkTypePattern::operator|(
    const NetworkTypePattern& other) const {
  return NetworkTypePattern(pattern_ | other.pattern_);
}

std::string NetworkTypePattern::ToDebugString() const {
  if (Equals(Default()))
    return kPatternDefault;
  if (Equals(Wireless()))
    return kPatternWireless;
  if (Equals(Mobile()))
    return kPatternMobile;
  if (Equals(Physical()))
    return kPatternPhysical;
  if (Equals(NonVirtual()))
    return kPatternNonVirtual;

  // Note: shill_type_to_flag includes kTypeTether.
  std::string str;
  for (size_t i = 0; i < std::size(shill_type_to_flag); ++i) {
    if (!(pattern_ & shill_type_to_flag[i].bit_flag))
      continue;
    if (!str.empty())
      str += "|";
    str += shill_type_to_flag[i].shill_network_type;
  }
  return str;
}

NetworkTypePattern::NetworkTypePattern(int pattern) : pattern_(pattern) {}

}  // namespace ash