chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc

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

#include <memory>
#include <utility>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/test_future.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "components/onc/onc_constants.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/testing_pref_service.h"
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "components/user_manager/user_names.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/api/networking_private/networking_private_chromeos.h"
#include "extensions/browser/api/networking_private/networking_private_delegate_factory.h"
#include "extensions/common/switches.h"
#include "extensions/test/extension_test_message_listener.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_switches.h"
#include "chromeos/ash/components/cryptohome/cryptohome_parameters.h"
#include "chromeos/ash/components/dbus/shill/shill_device_client.h"
#include "chromeos/ash/components/dbus/shill/shill_ipconfig_client.h"
#include "chromeos/ash/components/dbus/shill/shill_manager_client.h"
#include "chromeos/ash/components/dbus/shill/shill_profile_client.h"
#include "chromeos/ash/components/dbus/shill/shill_service_client.h"
#include "chromeos/ash/components/dbus/userdataauth/cryptohome_misc_client.h"
#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
#include "chromeos/ash/components/network/managed_network_configuration_handler.h"
#include "chromeos/ash/components/network/network_certificate_handler.h"
#include "chromeos/ash/components/network/network_handler.h"
#include "chromeos/ash/components/network/network_handler_test_helper.h"
#include "chromeos/ash/components/network/network_state.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/onc/network_onc_utils.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/test_controller.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#endif

// This tests the Chrome OS implementation of the networkingPrivate API
// (NetworkingPrivateChromeOS). Note: The test expectations for chromeos, and
// win/mac (NetworkingPrivateServiceClient) are different to reflect the
// different implementations, but should be kept similar where possible.

using testing::_;
using testing::Return;

#if BUILDFLAG(IS_CHROMEOS_ASH)
using ash::ShillDeviceClient;
using ash::ShillIPConfigClient;
using ash::ShillManagerClient;
using ash::ShillProfileClient;
using ash::ShillServiceClient;
using ash::UserDataAuthClient;

using extensions::NetworkingPrivateChromeOS;
using extensions::NetworkingPrivateDelegate;
using extensions::NetworkingPrivateDelegateFactory;
#endif

namespace {

const char kCellular1ServicePath[] = "stub_cellular1";
const char kCellularDevicePath[] = "/device/stub_cellular_device1";
const char kEthernetDevicePath[] = "/device/stub_ethernet_device";
const char kIPConfigPath[] = "/ipconfig/ipconfig1";
const char kUser1ProfilePath[] = "/profile/user1/shill";
const char kWifi1ServicePath[] = "stub_wifi1";
const char kWifi2ServicePath[] = "stub_wifi2";
const char kWifiDevicePath[] = "/device/stub_wifi_device1";

class NetworkingPrivateChromeOSApiTestBase
    : public extensions::ExtensionApiTest {
 public:
  // From extensions::ExtensionApiTest
  void SetUpCommandLine(base::CommandLine* command_line) override {
    extensions::ExtensionApiTest::SetUpCommandLine(command_line);
    // Allowlist the extension ID of the test extension.
    command_line->AppendSwitchASCII(
        extensions::switches::kAllowlistedExtensionID,
        "epcifkihnkjgphfkloaaleeakhpmgdmn");
  }

  bool RunNetworkingSubtest(const std::string& test) {
    const std::string arg =
        base::StringPrintf("{\"test\": \"%s\"}", test.c_str());
    return RunExtensionTest(
        "networking_private/chromeos",
        {.custom_arg = arg.c_str(), .launch_as_platform_app = true});
  }

  void ConfigFakeNetwork() {
    ClearDevices();
    ClearServices();

    std::string userhash = GetSanitizedActiveUsername();

    // Sends a notification about the added profile.
    AddProfile(kUser1ProfilePath, userhash);

    // Add IPConfigs
    base::Value::Dict ipconfig;
    ipconfig.Set(shill::kAddressProperty, "0.0.0.0");
    ipconfig.Set(shill::kGatewayProperty, "0.0.0.1");
    ipconfig.Set(shill::kPrefixlenProperty, 0);
    ipconfig.Set(shill::kMethodProperty, shill::kTypeIPv4);
    AddIPConfig(kIPConfigPath, std::move(ipconfig));

    // Add Devices
    AddDevice(kEthernetDevicePath, shill::kTypeEthernet,
              "stub_ethernet_device1");

    AddDevice(kWifiDevicePath, shill::kTypeWifi, "stub_wifi_device1");
    base::Value::List wifi_ip_configs;
    wifi_ip_configs.Append(kIPConfigPath);
    SetDeviceProperty(kWifiDevicePath, shill::kIPConfigsProperty,
                      base::Value(std::move(wifi_ip_configs)));
    SetDeviceProperty(kWifiDevicePath, shill::kAddressProperty,
                      base::Value("001122aabbcc"));

    // Add Services
    AddService("stub_ethernet", "eth0", shill::kTypeEthernet,
               shill::kStateOnline);
    SetServiceProperty("stub_ethernet", shill::kProfileProperty,
                       base::Value(GetSharedProfilePath()));
    AddServiceToProfile(GetSharedProfilePath(), "stub_ethernet");

    AddService(kWifi1ServicePath, "wifi1", shill::kTypeWifi,
               shill::kStateOnline);
    SetServiceProperty(kWifi1ServicePath, shill::kSecurityClassProperty,
                       base::Value(shill::kSecurityClassWep));
    SetServiceProperty(kWifi1ServicePath, shill::kWifiBSsid,
                       base::Value("00:01:02:03:04:05"));
    SetServiceProperty(kWifi1ServicePath, shill::kSignalStrengthProperty,
                       base::Value(40));
    SetServiceProperty(kWifi1ServicePath, shill::kProfileProperty,
                       base::Value(kUser1ProfilePath));
    SetServiceProperty(kWifi1ServicePath, shill::kConnectableProperty,
                       base::Value(true));
    SetServiceProperty(kWifi1ServicePath, shill::kDeviceProperty,
                       base::Value(kWifiDevicePath));
    base::Value::Dict static_ipconfig;
    static_ipconfig.Set(shill::kAddressProperty, "1.2.3.4");
    static_ipconfig.Set(shill::kGatewayProperty, "0.0.0.0");
    static_ipconfig.Set(shill::kPrefixlenProperty, 1);
    SetServiceProperty(kWifi1ServicePath, shill::kStaticIPConfigProperty,
                       base::Value(std::move(static_ipconfig)));
    base::Value::List frequencies1;
    frequencies1.Append(2400);
    SetServiceProperty(kWifi1ServicePath, shill::kWifiFrequencyListProperty,
                       base::Value(std::move(frequencies1)));
    SetServiceProperty(kWifi1ServicePath, shill::kWifiFrequency,
                       base::Value(2400));
    AddServiceToProfile(kUser1ProfilePath, kWifi1ServicePath);

    AddService(kWifi2ServicePath, "wifi2_PSK", shill::kTypeWifi,
               shill::kStateIdle);
    SetServiceProperty(kWifi2ServicePath, shill::kSecurityClassProperty,
                       base::Value(shill::kSecurityClassPsk));
    SetServiceProperty(kWifi2ServicePath, shill::kSignalStrengthProperty,
                       base::Value(80));
    SetServiceProperty(kWifi2ServicePath, shill::kConnectableProperty,
                       base::Value(true));

    base::Value::List frequencies2;
    frequencies2.Append(2400);
    frequencies2.Append(5000);
    SetServiceProperty(kWifi2ServicePath, shill::kWifiFrequencyListProperty,
                       base::Value(std::move(frequencies2)));
    SetServiceProperty(kWifi2ServicePath, shill::kWifiFrequency,
                       base::Value(5000));
    SetServiceProperty(kWifi2ServicePath, shill::kProfileProperty,
                       base::Value(kUser1ProfilePath));
    AddServiceToProfile(kUser1ProfilePath, kWifi2ServicePath);

    AddService("stub_vpn1", "vpn1", shill::kTypeVPN, shill::kStateOnline);
    SetServiceProperty("stub_vpn1", shill::kProviderTypeProperty,
                       base::Value(shill::kProviderOpenVpn));
    AddServiceToProfile(kUser1ProfilePath, "stub_vpn1");

    AddService("stub_vpn2", "vpn2", shill::kTypeVPN, shill::kStateIdle);
    SetServiceProperty("stub_vpn2", shill::kProviderTypeProperty,
                       base::Value(shill::kProviderThirdPartyVpn));
    SetServiceProperty("stub_vpn2", shill::kProviderHostProperty,
                       base::Value("third_party_provider_extension_id"));
    AddServiceToProfile(kUser1ProfilePath, "stub_vpn2");
  }

  virtual void SetupCellular() {
    // Add a Cellular GSM Device.
    AddDevice(kCellularDevicePath, shill::kTypeCellular,
              "stub_cellular_device1");
    base::Value::Dict home_provider;
    home_provider.Set("name", "Cellular1_Provider");
    home_provider.Set("code", "000000");
    home_provider.Set("country", "us");
    SetDeviceProperty(kCellularDevicePath, shill::kHomeProviderProperty,
                      base::Value(std::move(home_provider)));
    SetDeviceProperty(kCellularDevicePath, shill::kTechnologyFamilyProperty,
                      base::Value(shill::kNetworkTechnologyGsm));
    SetDeviceProperty(kCellularDevicePath, shill::kMeidProperty,
                      base::Value("test_meid"));
    SetDeviceProperty(kCellularDevicePath, shill::kImeiProperty,
                      base::Value("test_imei"));
    SetDeviceProperty(kCellularDevicePath, shill::kIccidProperty,
                      base::Value("test_iccid"));
    SetDeviceProperty(kCellularDevicePath, shill::kEsnProperty,
                      base::Value("test_esn"));
    SetDeviceProperty(kCellularDevicePath, shill::kMdnProperty,
                      base::Value("test_mdn"));
    SetDeviceProperty(kCellularDevicePath, shill::kMinProperty,
                      base::Value("test_min"));
    SetDeviceProperty(kCellularDevicePath, shill::kModelIdProperty,
                      base::Value("test_model_id"));
    SetSimLocked(kCellularDevicePath, false);

    // Add the Cellular Service.
    AddService(kCellular1ServicePath, "cellular1", shill::kTypeCellular,
               shill::kStateIdle);
    SetServiceProperty(kCellular1ServicePath,
                       shill::kCellularAllowRoamingProperty,
                       base::Value(false));
    SetServiceProperty(kCellular1ServicePath, shill::kAutoConnectProperty,
                       base::Value(true));
    SetServiceProperty(kCellular1ServicePath, shill::kIccidProperty,
                       base::Value("test_iccid"));
    SetServiceProperty(kCellular1ServicePath, shill::kNetworkTechnologyProperty,
                       base::Value(shill::kNetworkTechnologyGsm));
    SetServiceProperty(kCellular1ServicePath, shill::kActivationStateProperty,
                       base::Value(shill::kActivationStateNotActivated));
    SetServiceProperty(kCellular1ServicePath, shill::kRoamingStateProperty,
                       base::Value(shill::kRoamingStateHome));

    AddServiceToProfile(kUser1ProfilePath, kCellular1ServicePath);
  }

  virtual std::string GetSanitizedActiveUsername() = 0;

  virtual void AddDevice(const std::string& device_path,
                         const std::string& type,
                         const std::string& name) = 0;
  virtual void SetDeviceProperty(const std::string& device_path,
                                 const std::string& name,
                                 const base::Value& value) = 0;
  virtual void SetSimLocked(const std::string& device_path, bool enabled) = 0;
  virtual void ClearDevices() = 0;
  virtual void AddService(const std::string& service_path,
                          const std::string& name,
                          const std::string& type,
                          const std::string& state) = 0;
  virtual void ClearServices() = 0;
  virtual void SetServiceProperty(const std::string& service_path,
                                  const std::string& property,
                                  const base::Value& value) = 0;
  virtual void AddProfile(const std::string& profile_path,
                          const std::string& userhash) = 0;

  virtual void AddServiceToProfile(const std::string& profile_path,
                                   const std::string& service_path) = 0;
  virtual std::string GetSharedProfilePath() = 0;
  virtual void AddIPConfig(const std::string& ip_config_path,
                           base::Value::Dict properties) = 0;
};

#if BUILDFLAG(IS_CHROMEOS_ASH)
class UIDelegateStub : public NetworkingPrivateDelegate::UIDelegate {
 public:
  static int s_show_account_details_called_;

 private:
  // UIDelegate
  void ShowAccountDetails(const std::string& guid) const override {
    ++s_show_account_details_called_;
  }
};

// static
int UIDelegateStub::s_show_account_details_called_ = 0;

class NetworkingPrivateChromeOSApiTestAsh
    : public NetworkingPrivateChromeOSApiTestBase {
 public:
  NetworkingPrivateChromeOSApiTestAsh() = default;

  NetworkingPrivateChromeOSApiTestAsh(
      const NetworkingPrivateChromeOSApiTestAsh&) = delete;
  NetworkingPrivateChromeOSApiTestAsh& operator=(
      const NetworkingPrivateChromeOSApiTestAsh&) = delete;

  static std::unique_ptr<KeyedService> CreateNetworkingPrivateDelegate(
      content::BrowserContext* context) {
    std::unique_ptr<NetworkingPrivateDelegate> result(
        new NetworkingPrivateChromeOS(context));
    std::unique_ptr<NetworkingPrivateDelegate::UIDelegate> ui_delegate(
        new UIDelegateStub);
    result->set_ui_delegate(std::move(ui_delegate));
    return result;
  }

  void SetupTether() {
    ash::NetworkStateHandler* network_state_handler =
        ash::NetworkHandler::Get()->network_state_handler();
    network_state_handler->SetTetherTechnologyState(
        ash::NetworkStateHandler::TechnologyState::TECHNOLOGY_ENABLED);
    network_state_handler->AddTetherNetworkState(
        "tetherGuid1", "tetherName1", "tetherCarrier1",
        50 /* battery_percentage */, 75 /* signal_strength */,
        true /* has_connected_to_host */);
    network_state_handler->AddTetherNetworkState(
        "tetherGuid2", "tetherName2", "tetherCarrier2",
        75 /* battery_percentage */, 100 /* signal_strength */,
        false /* has_connected_to_host */);
  }

  ShillServiceClient::TestInterface* service_test() {
    return network_handler_test_helper_->service_test();
  }
  ShillProfileClient::TestInterface* profile_test() {
    return network_handler_test_helper_->profile_test();
  }
  ShillDeviceClient::TestInterface* device_test() {
    return network_handler_test_helper_->device_test();
  }
  ShillManagerClient::TestInterface* manager_test() {
    return network_handler_test_helper_->manager_test();
  }

  // extensions::ExtensionApiTest overrides:

  void SetUpInProcessBrowserTestFixture() override {
    provider_.SetDefaultReturns(
        /*is_initialization_complete_return=*/true,
        /*is_first_policy_load_complete_return=*/true);
    policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);

    extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture();
  }

  void SetUpOnMainThread() override {
    extensions::ExtensionApiTest::SetUpOnMainThread();
    content::RunAllPendingInMessageLoop();

    NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory(
        profile(), base::BindRepeating(&CreateNetworkingPrivateDelegate));

    network_handler_test_helper_ =
        std::make_unique<ash::NetworkHandlerTestHelper>();

    ConfigFakeNetwork();

    PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry());
    PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry());
    network_handler_test_helper_->RegisterPrefs(user_prefs_.registry(),
                                                local_state_.registry());

    network_handler_test_helper_->InitializePrefs(&user_prefs_, &local_state_);

    base::RunLoop().RunUntilIdle();
  }

  void TearDownOnMainThread() override { network_handler_test_helper_.reset(); }

  // NetworkingPrivateChromeOSApiTestBase overrides:

  void SetUpCommandLine(base::CommandLine* command_line) override {
    NetworkingPrivateChromeOSApiTestBase::SetUpCommandLine(command_line);

    // TODO(pneubeck): Remove the following hack, once the NetworkingPrivateAPI
    // uses the ProfileHelper to obtain the userhash crbug/238623.
    cryptohome::AccountIdentifier login_user;
    login_user.set_account_id(user_manager::CanonicalizeUserID(
        command_line->GetSwitchValueNative(ash::switches::kLoginUser)));
    const std::string sanitized_user =
        UserDataAuthClient::GetStubSanitizedUsername(login_user);
    command_line->AppendSwitchASCII(ash::switches::kLoginProfile,
                                    sanitized_user);
  }

  std::string GetSanitizedActiveUsername() override {
    user_manager::UserManager* user_manager = user_manager::UserManager::Get();
    user_manager::User* user = user_manager->GetActiveUser();
    CHECK(user);
    std::string userhash;
    ::user_data_auth::GetSanitizedUsernameRequest request;
    request.set_username(
        cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId())
            .account_id());
    ash::CryptohomeMiscClient::Get()->GetSanitizedUsername(
        request,
        base::BindOnce(
            [](std::string* out,
               std::optional<::user_data_auth::GetSanitizedUsernameReply>
                   result) {
              CHECK(result.has_value());
              *out = result->sanitized_username();
            },
            &userhash));
    base::RunLoop().RunUntilIdle();
    CHECK(!userhash.empty());
    return userhash;
  }

  void SetupCellular() override {
    UIDelegateStub::s_show_account_details_called_ = 0;
    NetworkingPrivateChromeOSApiTestBase::SetupCellular();
    base::RunLoop().RunUntilIdle();
  }

  void AddDevice(const std::string& device_path,
                 const std::string& type,
                 const std::string& name) override {
    device_test()->AddDevice(device_path, type, name);
  }

  void ClearDevices() override { device_test()->ClearDevices(); }

  void SetDeviceProperty(const std::string& device_path,
                         const std::string& name,
                         const base::Value& value) override {
    device_test()->SetDeviceProperty(device_path, name, value,
                                     /*notify_changed=*/true);
  }

  void SetSimLocked(const std::string& device_path, bool enabled) override {
    device_test()->SetSimLocked(device_path, enabled);
  }

  void AddService(const std::string& service_path,
                  const std::string& name,
                  const std::string& type,
                  const std::string& state) override {
    service_test()->AddService(service_path, service_path + "_guid", name, type,
                               state, true /* add_to_visible */);
  }

  void ClearServices() override { service_test()->ClearServices(); }

  void SetServiceProperty(const std::string& service_path,
                          const std::string& property,
                          const base::Value& value) override {
    service_test()->SetServiceProperty(service_path, property, value);
  }

  void AddIPConfig(const std::string& ip_config_path,
                   base::Value::Dict properties) override {
    network_handler_test_helper_->ip_config_test()->AddIPConfig(
        ip_config_path, std::move(properties));
  }

  void AddProfile(const std::string& profile_path,
                  const std::string& userhash) override {
    profile_test()->AddProfile(profile_path, userhash);
  }

  void AddServiceToProfile(const std::string& profile_path,
                           const std::string& service_path) override {
    profile_test()->AddService(profile_path, service_path);
  }

  std::string GetSharedProfilePath() override {
    return ShillProfileClient::GetSharedProfilePath();
  }

 protected:
  std::unique_ptr<ash::NetworkHandlerTestHelper> network_handler_test_helper_;
  testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_;
  sync_preferences::TestingPrefServiceSyncable user_prefs_;
  TestingPrefServiceSimple local_state_;
};
#else
class NetworkingPrivateChromeOSApiTestLacros
    : public NetworkingPrivateChromeOSApiTestBase {
 public:
  NetworkingPrivateChromeOSApiTestLacros() {}

  NetworkingPrivateChromeOSApiTestLacros(
      const NetworkingPrivateChromeOSApiTestLacros&) = delete;
  NetworkingPrivateChromeOSApiTestLacros& operator=(
      const NetworkingPrivateChromeOSApiTestLacros&) = delete;

  bool SetUpAsh() {
    auto* service = chromeos::LacrosService::Get();
    if (!service->IsAvailable<crosapi::mojom::TestController>() ||
        service->GetInterfaceVersion<crosapi::mojom::TestController>() <
            static_cast<int>(crosapi::mojom::TestController::MethodMinVersions::
                                 kBindShillClientTestInterfaceMinVersion)) {
      LOG(ERROR) << "Unsupported ash version.";
      return false;
    }

    base::test::TestFuture<void> future;
    service->GetRemote<crosapi::mojom::TestController>()
        ->BindShillClientTestInterface(shill_test_.BindNewPipeAndPassReceiver(),
                                       future.GetCallback());
    EXPECT_TRUE(future.Wait());

    ConfigFakeNetwork();

    return true;
  }

  // NetworkingPrivateChromeOSApiTestBase overrides

  std::string GetSanitizedActiveUsername() override {
    auto* service = chromeos::LacrosService::Get();
    if (!service->IsAvailable<crosapi::mojom::TestController>() ||
        service->GetInterfaceVersion<crosapi::mojom::TestController>() <
            static_cast<int>(crosapi::mojom::TestController::MethodMinVersions::
                                 kGetSanitizedActiveUsernameMinVersion)) {
      LOG(ERROR) << "Unsupported ash version.";
      return "";
    }

    base::test::TestFuture<const std::string&> future;
    service->GetRemote<crosapi::mojom::TestController>()
        ->GetSanitizedActiveUsername(future.GetCallback());
    return future.Take();
  }

  void AddDevice(const std::string& device_path,
                 const std::string& type,
                 const std::string& name) override {
    base::test::TestFuture<void> future;
    shill_test_->AddDevice(device_path, type, name, future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void SetDeviceProperty(const std::string& device_path,
                         const std::string& name,
                         const base::Value& value) override {
    base::test::TestFuture<void> future;
    shill_test_->SetDeviceProperty(device_path, name, value.Clone(),
                                   /*notify_changed=*/true,
                                   future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void SetSimLocked(const std::string& device_path, bool enabled) override {
    base::test::TestFuture<void> future;
    shill_test_->SetSimLocked(device_path, enabled, future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void ClearDevices() override {
    base::test::TestFuture<void> future;
    shill_test_->ClearDevices(future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void AddService(const std::string& service_path,
                  const std::string& name,
                  const std::string& type,
                  const std::string& state) override {
    base::test::TestFuture<void> future;
    shill_test_->AddService(service_path, service_path + "_guid", name, type,
                            state, true /* add_to_visible */,
                            future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void ClearServices() override {
    base::test::TestFuture<void> future;
    shill_test_->ClearServices(future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void SetServiceProperty(const std::string& service_path,
                          const std::string& property,
                          const base::Value& value) override {
    base::test::TestFuture<void> future;
    shill_test_->SetServiceProperty(service_path, property, value.Clone(),
                                    future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void AddIPConfig(const std::string& ip_config_path,
                   base::Value::Dict properties) override {
    base::test::TestFuture<void> future;
    shill_test_->AddIPConfig(ip_config_path, base::Value(std::move(properties)),
                             future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void AddProfile(const std::string& profile_path,
                  const std::string& userhash) override {
    base::test::TestFuture<void> future;
    shill_test_->AddProfile(profile_path, userhash, future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  void AddServiceToProfile(const std::string& profile_path,
                           const std::string& service_path) override {
    base::test::TestFuture<void> future;
    shill_test_->AddServiceToProfile(profile_path, service_path,
                                     future.GetCallback());
    ASSERT_TRUE(future.Wait());
  }

  std::string GetSharedProfilePath() override {
    // TODO(crbug.com/): get this information from Ash
    const char kSharedProfilePath[] = "/profile/default";
    return kSharedProfilePath;
  }

 protected:
  mojo::Remote<crosapi::mojom::ShillClientTestInterface> shill_test_;
};
#endif

#if BUILDFLAG(IS_CHROMEOS_LACROS)
using NetworkingPrivateChromeOSApiTest = NetworkingPrivateChromeOSApiTestLacros;
#else
using NetworkingPrivateChromeOSApiTest = NetworkingPrivateChromeOSApiTestAsh;
#endif

// Place each subtest into a separate browser test so that the stub networking
// library state is reset for each subtest run. This way they won't affect each
// other.

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartConnect) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("startConnect")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartDisconnect) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("startDisconnect")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartActivate) {
  SetupCellular();
  EXPECT_TRUE(RunNetworkingSubtest("startActivate")) << message_;
  EXPECT_EQ(1, UIDelegateStub::s_show_account_details_called_);
}
#endif

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       StartConnectNonexistent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("startConnectNonexistent")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       StartDisconnectNonexistent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("startDisconnectNonexistent")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       StartGetPropertiesNonexistent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("startGetPropertiesNonexistent"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetNetworks) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  // Hide stub_wifi2.
  SetServiceProperty(kWifi2ServicePath, shill::kVisibleProperty,
                     base::Value(false));
  // Add a couple of additional networks that are not configured (saved).
  AddService("stub_wifi3", "wifi3", shill::kTypeWifi, shill::kStateIdle);
  AddService("stub_wifi4", "wifi4", shill::kTypeWifi, shill::kStateIdle);
  content::RunAllPendingInMessageLoop();

  EXPECT_TRUE(RunNetworkingSubtest("getNetworks")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetVisibleNetworks) {
  EXPECT_TRUE(RunNetworkingSubtest("getVisibleNetworks")) << message_;
}
#endif

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       GetVisibleNetworksWifi) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("getVisibleNetworksWifi")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, EnabledNetworkTypes) {
  EXPECT_TRUE(RunNetworkingSubtest("enabledNetworkTypesDisable")) << message_;
  EXPECT_TRUE(RunNetworkingSubtest("enabledNetworkTypesEnable")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetDeviceStates) {
  SetupCellular();
  manager_test()->RemoveTechnology("cellular");
  manager_test()->AddTechnology("cellular", false /* disabled */);
  manager_test()->SetTechnologyInitializing("cellular", true);
  EXPECT_TRUE(RunNetworkingSubtest("getDeviceStates")) << message_;
}
#endif

#if BUILDFLAG(IS_CHROMEOS_LACROS)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       GetDeviceStatesLacros) {
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
  EXPECT_TRUE(RunNetworkingSubtest("getDeviceStatesLacros")) << message_;
}
#endif

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, RequestNetworkScan) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("requestNetworkScan")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       RequestNetworkScanCellular) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  SetupCellular();
  EXPECT_TRUE(RunNetworkingSubtest("requestNetworkScanCellular")) << message_;
}

// Properties are filtered and translated through
// ShillToONCTranslator::TranslateWiFiWithState
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetProperties) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("getProperties")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       GetCellularProperties) {
  SetupCellular();
  EXPECT_TRUE(RunNetworkingSubtest("getPropertiesCellular")) << message_;
}
#endif

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetState) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("getState")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetStateNonExistent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("getStateNonExistent")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       SetCellularProperties) {
  SetupCellular();
  EXPECT_TRUE(RunNetworkingSubtest("setCellularProperties")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, SetWiFiProperties) {
  EXPECT_TRUE(RunNetworkingSubtest("setWiFiProperties")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, SetVPNProperties) {
  EXPECT_TRUE(RunNetworkingSubtest("setVPNProperties")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, CreateNetwork) {
  EXPECT_TRUE(RunNetworkingSubtest("createNetwork")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       CreateNetworkForPolicyControlledNetwork) {
  constexpr char kUserPolicyBlob[] =
      R"({
           "NetworkConfigurations": [{
             "GUID": "stub_wifi2",
             "Type": "WiFi",
             "Name": "My WiFi Network",
             "WiFi": {
               "HexSSID": "77696669325F50534B",
               "Passphrase": "passphrase",
               "Recommended": [ "AutoConnect", "Passphrase" ],
               "Security": "WPA-PSK"
             }
           }],
           "Certificates": [],
           "Type": "UnencryptedConfiguration"
         })";

  policy::PolicyMap policy;
  policy.Set(policy::key::kOpenNetworkConfiguration,
             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
             policy::POLICY_SOURCE_CLOUD, base::Value(kUserPolicyBlob),
             nullptr);
  provider_.UpdateChromePolicy(policy);

  content::RunAllPendingInMessageLoop();

  EXPECT_TRUE(RunNetworkingSubtest("createNetworkForPolicyControlledNetwork"));
}
#endif

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, ForgetNetwork) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("forgetNetwork")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       ForgetPolicyControlledNetwork) {
  constexpr char kUserPolicyBlob[] =
      R"({
           "NetworkConfigurations": [{
             "GUID": "stub_wifi2",
             "Type": "WiFi",
             "Name": "My WiFi Network",
             "WiFi": {
               "HexSSID": "77696669325F50534B",
               "Passphrase": "passphrase",
               "Recommended": [ "AutoConnect", "Passphrase" ],
               "Security": "WPA-PSK"
             }
           }],
           "Certificates": [],
           "Type": "UnencryptedConfiguration"
         })";

  policy::PolicyMap policy;
  policy.Set(policy::key::kOpenNetworkConfiguration,
             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
             policy::POLICY_SOURCE_CLOUD, base::Value(kUserPolicyBlob),
             nullptr);
  provider_.UpdateChromePolicy(policy);

  content::RunAllPendingInMessageLoop();

  EXPECT_TRUE(RunNetworkingSubtest("forgetPolicyControlledNetwork"));
}

// TODO(stevenjb): Find a better way to set this up on Chrome OS.
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetManagedProperties) {
  constexpr char kUidataBlob[] =
      R"({
        "user_settings": {
          "WiFi": {"Passphrase": "FAKE_CREDENTIAL_VPaJDV9x"}
        }
      })";
  service_test()->SetServiceProperty(kWifi2ServicePath, shill::kUIDataProperty,
                                     base::Value(kUidataBlob));
  service_test()->SetServiceProperty(
      kWifi2ServicePath, shill::kAutoConnectProperty, base::Value(false));

  // Update the profile entry.
  profile_test()->AddService(kUser1ProfilePath, kWifi2ServicePath);

  content::RunAllPendingInMessageLoop();

  constexpr char kUserPolicyBlob[] = R"({
      "NetworkConfigurations": [
          { "GUID": "stub_wifi2",
            "Type": "WiFi",
            "Name": "My WiFi Network",
            "ProxySettings":{
                "Type": "Direct"
            },
            "WiFi": {
              "HexSSID": "77696669325F50534B",
              "Passphrase": "passphrase",
              "Recommended": [ "AutoConnect", "Passphrase" ],
              "Security": "WPA-PSK" }
          }
        ],
        "Certificates": [],
        "Type": "UnencryptedConfiguration"
      })";

  policy::PolicyMap policy;
  policy.Set(policy::key::kOpenNetworkConfiguration,
             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
             policy::POLICY_SOURCE_CLOUD, base::Value(kUserPolicyBlob),
             nullptr);
  provider_.UpdateChromePolicy(policy);

  content::RunAllPendingInMessageLoop();

  EXPECT_TRUE(RunNetworkingSubtest("getManagedProperties")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetErrorState) {
  ash::NetworkHandler::Get()->network_state_handler()->SetErrorForTest(
      kWifi1ServicePath, "TestErrorState");
  EXPECT_TRUE(RunNetworkingSubtest("getErrorState")) << message_;
}
#endif

// TODO(crbug.com/41496066): This test is flaky.
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       DISABLED_OnNetworksChangedEventConnect) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("onNetworksChangedEventConnect"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       OnNetworksChangedEventDisconnect) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("onNetworksChangedEventDisconnect"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       OnNetworkListChangedEvent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("onNetworkListChangedEvent")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       OnDeviceStateListChangedEvent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  EXPECT_TRUE(RunNetworkingSubtest("onDeviceStateListChangedEvent"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       OnDeviceScanningChangedEvent) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  SetupCellular();
  EXPECT_TRUE(RunNetworkingSubtest("onDeviceScanningChangedEvent")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       OnCertificateListsChangedEvent) {
  ExtensionTestMessageListener listener("eventListenerReady");
  listener.SetOnSatisfied(base::BindOnce([](const std::string& message) {
    ash::NetworkHandler::Get()
        ->network_certificate_handler()
        ->AddAuthorityCertificateForTest("authority_cert");
  }));
  EXPECT_TRUE(RunNetworkingSubtest("onCertificateListsChangedEvent"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       GetCaptivePortalStatus) {
  // Ethernet defaults to online.
  // Set wifi1 to idle with captive portal status mapping 'Offline'.
  // Set wifi2 to redirect-found with captive portal statu smapping 'Portal'.
  SetServiceProperty(kWifi1ServicePath, shill::kStateProperty,
                     base::Value(shill::kStateIdle));
  SetServiceProperty(kWifi2ServicePath, shill::kStateProperty,
                     base::Value(shill::kStateRedirectFound));
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(RunNetworkingSubtest("getCaptivePortalStatus")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       CaptivePortalNotification) {
  // Make wifi1 the default service since captive portal notifications only
  // occur for the default service.
  service_test()->RemoveService("stub_ethernet");
  service_test()->RemoveService("stub_vpn1");

  ExtensionTestMessageListener listener("notifyPortalDetectorObservers");
  listener.SetOnSatisfied(
      base::BindLambdaForTesting([&](const std::string& message) {
        SetServiceProperty(kWifi1ServicePath, shill::kStateProperty,
                           base::Value(shill::kStateRedirectFound));
      }));

  EXPECT_TRUE(RunNetworkingSubtest("captivePortalNotification")) << message_;
}
#endif

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, UnlockCellularSim) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  SetupCellular();
  // Lock the SIM
  SetSimLocked(kCellularDevicePath, true);
  EXPECT_TRUE(RunNetworkingSubtest("unlockCellularSim")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, SetCellularSimState) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  SetupCellular();
  EXPECT_TRUE(RunNetworkingSubtest("setCellularSimState")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       SelectCellularMobileNetwork) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  SetupCellular();
  // Create fake list of found networks.
  base::Value::List found_networks =
      base::Value::List()
          .Append(base::Value::Dict()
                      .Set(shill::kNetworkIdProperty, "network1")
                      .Set(shill::kTechnologyProperty, "GSM")
                      .Set(shill::kStatusProperty, "current"))
          .Append(base::Value::Dict()
                      .Set(shill::kNetworkIdProperty, "network2")
                      .Set(shill::kTechnologyProperty, "GSM")
                      .Set(shill::kStatusProperty, "available"));
  SetDeviceProperty(kCellularDevicePath, shill::kFoundNetworksProperty,
                    base::Value(std::move(found_networks)));
  EXPECT_TRUE(RunNetworkingSubtest("selectCellularMobileNetwork")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, CellularSimPuk) {
#if BUILDFLAG(IS_CHROMEOS_LACROS)
  if (!SetUpAsh()) {
    GTEST_SKIP() << "Unsupported ash version.";
  }
#endif
  SetupCellular();
  // Lock the SIM
  SetSimLocked(kCellularDevicePath, true);
  EXPECT_TRUE(RunNetworkingSubtest("cellularSimPuk")) << message_;
}

#if BUILDFLAG(IS_CHROMEOS_ASH)
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetGlobalPolicy) {
  base::Value::Dict global_config;
  global_config.Set(
      ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
      true);
  global_config.Set(::onc::global_network_config::kAllowOnlyPolicyWiFiToConnect,
                    false);
  global_config.Set("SomeNewGlobalPolicy", false);
  ash::NetworkHandler::Get()
      ->managed_network_configuration_handler()
      ->SetPolicy(::onc::ONC_SOURCE_DEVICE_POLICY,
                  /*userhash=*/std::string(),
                  /*network_configs_onc=*/base::Value::List(), global_config);
  base::RunLoop().RunUntilIdle();

  EXPECT_TRUE(RunNetworkingSubtest("getGlobalPolicy")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       Tether_GetTetherNetworks) {
  SetupTether();
  EXPECT_TRUE(RunNetworkingSubtest("getTetherNetworks")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       Tether_GetTetherNetworkProperties) {
  SetupTether();
  EXPECT_TRUE(RunNetworkingSubtest("getTetherNetworkProperties")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       Tether_GetTetherNetworkManagedProperties) {
  SetupTether();
  EXPECT_TRUE(RunNetworkingSubtest("getTetherNetworkManagedProperties"))
      << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest,
                       Tether_GetTetherNetworkState) {
  SetupTether();
  EXPECT_TRUE(RunNetworkingSubtest("getTetherNetworkState")) << message_;
}

IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, GetCertificateLists) {
  ash::NetworkHandler::Get()
      ->network_certificate_handler()
      ->AddAuthorityCertificateForTest("authority_cert");
  EXPECT_TRUE(RunNetworkingSubtest("getCertificateLists")) << message_;
}

// Tests subset of networking API for the networking API alias - to verify that
// using API methods and event does not cause access exceptions (due to
// missing permissions).
IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, Alias) {
  SetupCellular();
  EXPECT_TRUE(RunExtensionTest("networking_private/alias",
                               {.launch_as_platform_app = true}))
      << message_;
}
#endif

}  // namespace