chromium/components/embedder_support/user_agent_utils_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 "components/embedder_support/user_agent_utils.h"

#include <string>
#include <vector>

#include "base/command_line.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "base/version.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "components/embedder_support/pref_names.h"
#include "components/embedder_support/switches.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/version_info/version_info.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/user_agent/user_agent_brand_version_type.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/re2/src/re2/re2.h"

#if BUILDFLAG(IS_POSIX)
#include <sys/utsname.h>
#endif

#if BUILDFLAG(IS_WIN)
#include <windows.foundation.metadata.h>
#include <wrl.h>

#include "base/win/core_winrt_util.h"
#include "base/win/hstring_reference.h"
#include "base/win/scoped_hstring.h"
#include "base/win/scoped_winrt_initializer.h"
#endif  // BUILDFLAG(IS_WIN)

namespace embedder_support {

namespace {

// A regular expression that matches Chrome/{major_version}.{minor_version} in
// the User-Agent string, where the first capture is the {major_version} and the
// second capture is the {minor_version}.
static constexpr char kChromeProductVersionRegex[] =;

#if BUILDFLAG(IS_ANDROID)
const char kAndroid[] =
    "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) "
    "Chrome/%s.0.0.0 "
    "%sSafari/537.36";
#else
const char kDesktop[] =;
#endif  // BUILDFLAG(IS_ANDROID)

void CheckUserAgentStringOrdering(bool mobile_device) {}

#if BUILDFLAG(IS_WIN)

// On Windows, the client hint sec-ch-ua-platform-version should be
// the highest supported version of the UniversalApiContract.
void VerifyWinPlatformVersion(std::string version) {
  base::win::ScopedWinrtInitializer scoped_winrt_initializer;
  ASSERT_TRUE(scoped_winrt_initializer.Succeeded());

  base::win::HStringReference api_info_class_name(
      RuntimeClass_Windows_Foundation_Metadata_ApiInformation);

  Microsoft::WRL::ComPtr<
      ABI::Windows::Foundation::Metadata::IApiInformationStatics>
      api;
  HRESULT result = base::win::RoGetActivationFactory(api_info_class_name.Get(),
                                                     IID_PPV_ARGS(&api));
  ASSERT_EQ(result, S_OK);

  base::win::HStringReference universal_contract_name(
      L"Windows.Foundation.UniversalApiContract");

  std::vector<std::string> version_parts = base::SplitString(
      version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);

  EXPECT_EQ(version_parts[2], "0");

  int major_version;
  base::StringToInt(version_parts[0], &major_version);

  // If this check fails, our highest known UniversalApiContract version
  // needs to be updated.
  EXPECT_LE(major_version,
            GetHighestKnownUniversalApiContractVersionForTesting());

  int minor_version;
  base::StringToInt(version_parts[1], &minor_version);

  boolean is_supported = false;
  // Verify that the major and minor versions are supported.
  result = api->IsApiContractPresentByMajor(universal_contract_name.Get(),
                                            major_version, &is_supported);
  EXPECT_EQ(result, S_OK);
  EXPECT_TRUE(is_supported)
      << " expected major version " << major_version << " to be supported.";
  result = api->IsApiContractPresentByMajorAndMinor(
      universal_contract_name.Get(), major_version, minor_version,
      &is_supported);
  EXPECT_EQ(result, S_OK);
  EXPECT_TRUE(is_supported)
      << " expected major version " << major_version << " and minor version "
      << minor_version << " to be supported.";

  // Verify that the next highest value is not supported.
  result = api->IsApiContractPresentByMajorAndMinor(
      universal_contract_name.Get(), major_version, minor_version + 1,
      &is_supported);
  EXPECT_EQ(result, S_OK);
  EXPECT_FALSE(is_supported) << " expected minor version " << minor_version + 1
                             << " to not be supported with a major version of "
                             << major_version << ".";
  result = api->IsApiContractPresentByMajor(universal_contract_name.Get(),
                                            major_version + 1, &is_supported);
  EXPECT_EQ(result, S_OK);
  EXPECT_FALSE(is_supported) << " expected major version " << major_version + 1
                             << " to not be supported.";
}

#endif  // BUILDFLAG(IS_WIN)

bool ContainsBrandVersion(const blink::UserAgentBrandList& brand_list,
                          const blink::UserAgentBrandVersion brand_version) {}

}  // namespace

class UserAgentUtilsTest : public testing::Test,
                           public testing::WithParamInterface<bool> {};

TEST_F(UserAgentUtilsTest, UserAgentStringOrdering) {}

TEST_F(UserAgentUtilsTest, CustomUserAgent) {}

TEST_F(UserAgentUtilsTest, InvalidCustomUserAgent) {}

TEST_F(UserAgentUtilsTest, UserAgentStringReduced) {}

TEST_F(UserAgentUtilsTest, UserAgentStringFull) {}

TEST_F(UserAgentUtilsTest, ReduceUserAgentPlatformOsCpu) {}

#if BUILDFLAG(IS_ANDROID)
TEST_F(UserAgentUtilsTest, ReduceUserAgentAndroidVersionDeviceModel) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitWithFeatures(
      {blink::features::kReduceUserAgentMinorVersion,
       blink::features::kReduceUserAgentAndroidVersionDeviceModel},
      {});
  // Verify the correct user agent is returned when the UseMobileUserAgent
  // command line flag is present.
  const char* const kArguments[] = {"chrome"};
  base::test::ScopedCommandLine scoped_command_line;
  base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
  command_line->InitFromArgv(1, kArguments);

  // Verify the mobile deviceModel and androidVersion in the user agent string
  // is reduced when not using a mobile user agent.
  ASSERT_FALSE(command_line->HasSwitch(switches::kUseMobileUserAgent));
  {
    std::string buffer = GetUserAgent();
    EXPECT_EQ("Linux; Android 10; K", GetUserAgentPlatformOsCpu(buffer));
    std::string device_compat = "";
    EXPECT_EQ(buffer,
              base::StringPrintf(kAndroid,
                                 version_info::GetMajorVersionNumber().c_str(),
                                 device_compat.c_str()));
  }

  // Verify the mobile deviceModel and androidVersion in the user agent string
  // is reduced when using a mobile user agent.
  command_line->AppendSwitch(switches::kUseMobileUserAgent);
  ASSERT_TRUE(command_line->HasSwitch(switches::kUseMobileUserAgent));
  {
    std::string buffer = GetUserAgent();
    EXPECT_EQ("Linux; Android 10; K", GetUserAgentPlatformOsCpu(buffer));
    std::string device_compat = "Mobile ";
    EXPECT_EQ(buffer,
              base::StringPrintf(kAndroid,
                                 version_info::GetMajorVersionNumber().c_str(),
                                 device_compat.c_str()));
  }
}
#endif

TEST_F(UserAgentUtilsTest, UserAgentMetadata) {}

TEST_F(UserAgentUtilsTest, UserAgentMetadataXR) {}

TEST_F(UserAgentUtilsTest, GenerateBrandVersionListUnbranded) {}

TEST_F(UserAgentUtilsTest, GenerateBrandVersionListUnbrandedVerifySeedChanges) {}

TEST_F(UserAgentUtilsTest, GenerateBrandVersionListWithGreaseBrandOverride) {}

TEST_F(UserAgentUtilsTest,
       GenerateBrandVersionListWithGreaseBrandAndVersionOverride) {}

TEST_F(UserAgentUtilsTest, GenerateBrandVersionListWithGreaseVersionOverride) {}

TEST_F(UserAgentUtilsTest, GenerateBrandVersionListWithBrand) {}

TEST_F(UserAgentUtilsTest, GenerateBrandVersionListInvalidSeed) {}

TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionOldAlgorithm) {}

TEST_F(UserAgentUtilsTest,
       GetGreasedUserAgentBrandVersionOldAlgorithmIgnoresBrandOverrides) {}

TEST_F(UserAgentUtilsTest,
       GetGreasedUserAgentBrandVersionOldAlgorithmIgnoresVersionOverrides) {}

TEST_F(
    UserAgentUtilsTest,
    GetGreasedUserAgentBrandVersionOldAlgorithmIgnoresBrandAndVersionOverrides) {}

// Tests to ensure the new algorithm works and is still overridable.
TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionNewAlgorithm) {}

TEST_F(UserAgentUtilsTest,
       GetGreasedUserAgentBrandVersionNewAlgorithmBrandOverride) {}

TEST_F(UserAgentUtilsTest,
       GetGreasedUserAgentBrandVersionNewAlgorithmVersionOverride) {}

TEST_F(UserAgentUtilsTest,
       GetGreasedUserAgentBrandVersionNewAlgorithmBrandAndVersionOverride) {}

TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionFullVersions) {}

TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionEnterpriseOverride) {}

TEST_F(
    UserAgentUtilsTest,
    GetGreasedUserAgentBrandVersionEnterpriseOverrideSupersedesOtherOverrides) {}

TEST_F(UserAgentUtilsTest, GetGreasedUserAgentBrandVersionNoLeadingWhitespace) {}

TEST_F(UserAgentUtilsTest, GetProductAndVersion) {}

TEST_F(UserAgentUtilsTest, GetUserAgent) {}

TEST_F(UserAgentUtilsTest, HeadlessUserAgent) {}

}  // namespace embedder_support