chromium/chrome/browser/lacros/net/network_settings_translation_unittest.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 "chrome/browser/lacros/net/network_settings_translation.h"

#include "chromeos/crosapi/mojom/network_settings_service.mojom.h"
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "net/base/proxy_server.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

constexpr char kPacUrl[] = "http://pac.pac/";

}  // namespace

namespace chromeos {

TEST(NetworkSettingsTranslationTest, NetProxyToCrosapiProxyDirect) {
  crosapi::mojom::ProxyConfigPtr actual =
      NetProxyToCrosapiProxy(net::ProxyConfigWithAnnotation::CreateDirect());
  EXPECT_TRUE(actual->proxy_settings->is_direct());
}

TEST(NetworkSettingsTranslationTest, NetProxyToCrosapiProxyWpad) {
  crosapi::mojom::ProxyConfigPtr actual =
      NetProxyToCrosapiProxy(net::ProxyConfigWithAnnotation(
          net::ProxyConfig::CreateAutoDetect(), TRAFFIC_ANNOTATION_FOR_TESTS));
  EXPECT_TRUE(actual->proxy_settings->is_wpad());
}

TEST(NetworkSettingsTranslationTest, NetProxyToCrosapiProxyPacNotMandatory) {
  net::ProxyConfig config =
      net::ProxyConfig::CreateFromCustomPacURL(GURL(kPacUrl));

  crosapi::mojom::ProxyConfigPtr actual = NetProxyToCrosapiProxy(
      net::ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
  ASSERT_TRUE(actual->proxy_settings->is_pac());
  EXPECT_EQ(actual->proxy_settings->get_pac()->pac_url, GURL(kPacUrl));
  EXPECT_EQ(actual->proxy_settings->get_pac()->pac_mandatory, false);
}

TEST(NetworkSettingsTranslationTest, NetProxyToCrosapiProxyPacMandatory) {
  net::ProxyConfig config =
      net::ProxyConfig::CreateFromCustomPacURL(GURL(kPacUrl));
  config.set_pac_mandatory(true);

  crosapi::mojom::ProxyConfigPtr actual = NetProxyToCrosapiProxy(
      net::ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
  ASSERT_TRUE(actual->proxy_settings->is_pac());
  EXPECT_EQ(actual->proxy_settings->get_pac()->pac_url, GURL(kPacUrl));
  EXPECT_EQ(actual->proxy_settings->get_pac()->pac_mandatory, true);
}

TEST(NetworkSettingsTranslationTest, NetProxyToCrosapiProxyManual) {
  net::ProxyConfig config;
  config.proxy_rules().ParseFromString(
      "http=http://proxy:80;https=https://secure_proxy:81;socks=socks4://"
      "socks_proxy:82;"
      "http=invalid://proxy2:83;http=direct://proxy3:84;"
      "http=socks5://proxy4:85;");
  config.proxy_rules().bypass_rules.ParseFromString("localhost;google.com;");

  crosapi::mojom::ProxyConfigPtr actual = NetProxyToCrosapiProxy(
      net::ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
  ASSERT_TRUE(actual->proxy_settings->is_manual());
  std::vector<crosapi::mojom::ProxyLocationPtr> proxy_ptr =
      std::move(actual->proxy_settings->get_manual()->http_proxies);
  ASSERT_EQ(proxy_ptr.size(), 2u);
  EXPECT_EQ(proxy_ptr[0]->host, "proxy");
  EXPECT_EQ(proxy_ptr[0]->port, 80);
  EXPECT_EQ(proxy_ptr[0]->scheme, crosapi::mojom::ProxyLocation::Scheme::kHttp);
  EXPECT_EQ(proxy_ptr[1]->host, "proxy4");
  EXPECT_EQ(proxy_ptr[1]->port, 85);
  EXPECT_EQ(proxy_ptr[1]->scheme,
            crosapi::mojom::ProxyLocation::Scheme::kSocks5);

  proxy_ptr =
      std::move(actual->proxy_settings->get_manual()->secure_http_proxies);
  ASSERT_EQ(proxy_ptr.size(), 1u);
  EXPECT_EQ(proxy_ptr[0]->host, "secure_proxy");
  EXPECT_EQ(proxy_ptr[0]->port, 81);
  EXPECT_EQ(proxy_ptr[0]->scheme,
            crosapi::mojom::ProxyLocation::Scheme::kHttps);

  proxy_ptr = std::move(actual->proxy_settings->get_manual()->socks_proxies);
  ASSERT_EQ(proxy_ptr.size(), 1u);
  EXPECT_EQ(proxy_ptr[0]->host, "socks_proxy");
  EXPECT_EQ(proxy_ptr[0]->port, 82);
  EXPECT_EQ(proxy_ptr[0]->scheme,
            crosapi::mojom::ProxyLocation::Scheme::kSocks4);

  const std::vector<std::string> exclude_domains =
      actual->proxy_settings->get_manual()->exclude_domains;
  ASSERT_EQ(exclude_domains.size(), 2u);
  EXPECT_EQ(exclude_domains[0], "localhost");
  EXPECT_EQ(exclude_domains[1], "google.com");
}

TEST(NetworkSettingsTranslationTest,
     NetProxyToCrosapiProxyManualFromSingleProxies) {
  net::ProxyConfig config;
  config.proxy_rules().ParseFromString("proxy:80;");

  crosapi::mojom::ProxyConfigPtr actual = NetProxyToCrosapiProxy(
      net::ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
  ASSERT_TRUE(actual->proxy_settings->is_manual());
  std::vector<crosapi::mojom::ProxyLocationPtr> proxy_ptr =
      std::move(actual->proxy_settings->get_manual()->http_proxies);
  ASSERT_EQ(proxy_ptr.size(), 1u);
  EXPECT_EQ(proxy_ptr[0]->host, "proxy");
  EXPECT_EQ(proxy_ptr[0]->port, 80);

  proxy_ptr =
      std::move(actual->proxy_settings->get_manual()->secure_http_proxies);
  ASSERT_EQ(proxy_ptr.size(), 1u);
  EXPECT_EQ(proxy_ptr[0]->host, "proxy");
  EXPECT_EQ(proxy_ptr[0]->port, 80);

  proxy_ptr = std::move(actual->proxy_settings->get_manual()->socks_proxies);
  ASSERT_EQ(proxy_ptr.size(), 1u);
  EXPECT_EQ(proxy_ptr[0]->host, "proxy");
  EXPECT_EQ(proxy_ptr[0]->port, 80);
}

TEST(NetworkSettingsTranslationTest, NetProxyToCrosapiProxyManualEmptyList) {
  net::ProxyConfig config;
  config.proxy_rules().ParseFromString("");
  crosapi::mojom::ProxyConfigPtr actual = NetProxyToCrosapiProxy(
      net::ProxyConfigWithAnnotation(config, TRAFFIC_ANNOTATION_FOR_TESTS));
  EXPECT_TRUE(actual->proxy_settings->is_direct());
}

TEST(NetworkSettingsTranslationTest, CrosapiProxyToNetProxyDirect) {
  crosapi::mojom::ProxyConfigPtr ptr = crosapi::mojom::ProxyConfig::New();
  crosapi::mojom::ProxySettingsDirectPtr direct =
      crosapi::mojom::ProxySettingsDirect::New();
  ptr->proxy_settings =
      crosapi::mojom::ProxySettings::NewDirect(std::move(direct));

  EXPECT_EQ(CrosapiProxyToNetProxy(std::move(ptr)).value().ToValue(),
            net::ProxyConfig::CreateDirect().ToValue());
}

TEST(NetworkSettingsTranslationTest, CrosapiProxyToNetProxyWpad) {
  crosapi::mojom::ProxyConfigPtr ptr = crosapi::mojom::ProxyConfig::New();
  crosapi::mojom::ProxySettingsWpadPtr wpad =
      crosapi::mojom::ProxySettingsWpad::New();
  ptr->proxy_settings = crosapi::mojom::ProxySettings::NewWpad(std::move(wpad));

  auto actual = CrosapiProxyToNetProxy(std::move(ptr));
  EXPECT_TRUE(actual.value().auto_detect());
}

TEST(NetworkSettingsTranslationTest, CrosapiProxyToNetProxyPac) {
  crosapi::mojom::ProxyConfigPtr ptr = crosapi::mojom::ProxyConfig::New();
  crosapi::mojom::ProxySettingsPacPtr pac =
      crosapi::mojom::ProxySettingsPac::New();
  pac->pac_url = GURL(kPacUrl);
  pac->pac_mandatory = true;
  crosapi::mojom::ProxySettingsPtr proxy =
      crosapi::mojom::ProxySettings::NewPac(pac.Clone());
  ptr->proxy_settings = proxy.Clone();
  auto actual = CrosapiProxyToNetProxy(ptr.Clone());
  EXPECT_FALSE(actual.value().auto_detect());
  EXPECT_EQ(actual.value().pac_url(), GURL(kPacUrl));
  EXPECT_TRUE(actual.value().pac_mandatory());

  pac->pac_mandatory = false;
  proxy->set_pac(std::move(pac));
  ptr->proxy_settings = std::move(proxy);
  actual = CrosapiProxyToNetProxy(std::move(ptr));
  EXPECT_FALSE(actual.value().pac_mandatory());
}

TEST(NetworkSettingsTranslationTest, CrosapiProxyToNetProxyManual) {
  crosapi::mojom::ProxyConfigPtr ptr = crosapi::mojom::ProxyConfig::New();
  crosapi::mojom::ProxySettingsManualPtr manual =
      crosapi::mojom::ProxySettingsManual::New();
  crosapi::mojom::ProxyLocationPtr location =
      crosapi::mojom::ProxyLocation::New();
  location->host = "proxy";
  location->port = 80;
  // Note: Setting the scheme will be reflected in the pac string below. So
  // no need to test those separately after setting. kHttp will map to
  // PROXY in the pac string!
  location->scheme = crosapi::mojom::ProxyLocation::Scheme::kHttp;
  manual->http_proxies.push_back(location.Clone());
  location->host = "secure_proxy";
  location->port = 81;
  location->scheme = crosapi::mojom::ProxyLocation::Scheme::kHttps;
  manual->secure_http_proxies.push_back(location.Clone());
  // Note that the secure_http_proxies may speak HTTP, so test this as well.
  location->host = "secure_proxy2";
  location->port = 82;
  location->scheme = crosapi::mojom::ProxyLocation::Scheme::kHttp;
  manual->secure_http_proxies.push_back(location.Clone());
  location->host = "socks_proxy";
  location->port = 82;
  location->scheme = crosapi::mojom::ProxyLocation::Scheme::kSocks4;
  manual->socks_proxies.push_back(std::move(location));
  manual->exclude_domains = {"localhost", "google.com"};
  ptr->proxy_settings =
      crosapi::mojom::ProxySettings::NewManual(std::move(manual));

  auto actual = CrosapiProxyToNetProxy(std::move(ptr));

  EXPECT_EQ(actual.value().proxy_rules().proxies_for_http.ToDebugString(),
            "PROXY proxy:80");
  EXPECT_EQ(actual.value().proxy_rules().proxies_for_https.ToDebugString(),
            "HTTPS secure_proxy:81;PROXY secure_proxy2:82");
  EXPECT_EQ(actual.value().proxy_rules().fallback_proxies.ToDebugString(),
            "SOCKS socks_proxy:82");
  EXPECT_EQ(actual.value().proxy_rules().bypass_rules.ToString(),
            "localhost;google.com;");
}

}  // namespace chromeos