blob: 11fad4126a178c43ce92778e0702a693ad238b97 [file] [log] [blame]
// Copyright 2023 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/enterprise/data_controls/attributes_condition.h"
#include <vector>
#include "base/json/json_reader.h"
#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace data_controls {
namespace {
constexpr char kGoogleUrl[] = "https://google.com";
constexpr char kChromiumUrl[] = "https://chromium.org";
base::Value CreateDict(const std::string& value) {
auto dict = base::JSONReader::Read(value, base::JSON_ALLOW_TRAILING_COMMAS);
EXPECT_TRUE(dict.has_value());
return std::move(dict.value());
}
} // namespace
TEST(AttributesConditionTest, InvalidInputs) {
// Invalid JSON types are rejected.
ASSERT_FALSE(AttributesCondition::Create(base::Value("some string")));
ASSERT_FALSE(AttributesCondition::Create(base::Value(12345)));
ASSERT_FALSE(AttributesCondition::Create(base::Value(99.999)));
ASSERT_FALSE(AttributesCondition::Create(
base::Value(std::vector<char>({1, 2, 3, 4, 5}))));
// Invalid dictionaries are rejected.
ASSERT_FALSE(AttributesCondition::Create(base::Value::Dict()));
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"foo": 1})")));
// Dictionaries with correct keys but wrong schema for values are rejected
ASSERT_FALSE(AttributesCondition::Create(
CreateDict(R"({"urls": "https://foo.com"})")));
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"urls": 1})")));
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"urls": 99.999})")));
#if BUILDFLAG(IS_CHROMEOS)
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"urls": "https://foo.com",
"components": "ARC"})")));
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"urls": 1,
"components": "ARC"})")));
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"urls": 99.999,
"components": "ARC"})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"components": "ARC"})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"components": 12345})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"components": 99.999})")));
#endif // BUILDFLAG(IS_CHROMEOS)
// Dictionaries with valid schemas but invalid URL patterns or components are
// rejected.
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"urls": ["http://:port"]})")));
ASSERT_FALSE(AttributesCondition::Create(
CreateDict(R"({"urls": ["http://?query"]})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"urls": ["https://"]})")));
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"urls": ["//"]})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"urls": ["a", 1]})")));
#if BUILDFLAG(IS_CHROMEOS)
ASSERT_FALSE(AttributesCondition::Create(CreateDict(R"({"urls": ["a", 1],
"components": ["ARC"]})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"components": ["1", "a"]})")));
ASSERT_FALSE(
AttributesCondition::Create(CreateDict(R"({"components": ["5.5"]})")));
#endif // BUILDFLAG(IS_CHROMEOS)
}
TEST(AttributesConditionTest, AnyURL) {
auto any_url = AttributesCondition::Create(CreateDict(R"({"urls": ["*"]})"));
ASSERT_TRUE(any_url);
for (const char* url : {kGoogleUrl, kChromiumUrl}) {
ActionContext context = {.url = GURL(url)};
ASSERT_TRUE(any_url->IsTriggered(context));
}
}
TEST(AttributesConditionTest, SpecificURL) {
auto google_url =
AttributesCondition::Create(CreateDict(R"({"urls": ["google.com"]})"));
auto chromium_url =
AttributesCondition::Create(CreateDict(R"({"urls": ["chromium.org"]})"));
ASSERT_TRUE(google_url);
ASSERT_TRUE(chromium_url);
ASSERT_TRUE(google_url->IsTriggered({.url = GURL(kGoogleUrl)}));
ASSERT_TRUE(chromium_url->IsTriggered({.url = GURL(kChromiumUrl)}));
ASSERT_FALSE(google_url->IsTriggered({.url = GURL(kChromiumUrl)}));
ASSERT_FALSE(chromium_url->IsTriggered({.url = GURL(kGoogleUrl)}));
}
#if BUILDFLAG(IS_CHROMEOS)
TEST(AttributesConditionTest, AllComponents) {
auto any_component = AttributesCondition::Create(CreateDict(R"(
{
"components": ["ARC", "CROSTINI", "PLUGIN_VM", "USB", "DRIVE",
"ONEDRIVE"]
})"));
ASSERT_TRUE(any_component);
for (Component component : kAllComponents) {
ActionContext context = {.component = component};
ASSERT_TRUE(any_component->IsTriggered(context));
}
}
TEST(AttributesConditionTest, OneComponent) {
for (Component condition_component : kAllComponents) {
constexpr char kTemplate[] = R"({"components": ["%s"]})";
auto one_component =
AttributesCondition::Create(CreateDict(base::StringPrintf(
kTemplate, GetComponentMapping(condition_component).c_str())));
for (Component context_component : kAllComponents) {
ActionContext context = {.component = context_component};
if (context_component == condition_component) {
ASSERT_TRUE(one_component->IsTriggered(context));
} else {
ASSERT_FALSE(one_component->IsTriggered(context));
}
}
}
}
TEST(AttributesConditionTest, URLAndAllComponents) {
auto any_component_or_url = AttributesCondition::Create(CreateDict(R"(
{
"urls": ["*"],
"components": ["ARC", "CROSTINI", "PLUGIN_VM", "USB", "DRIVE",
"ONEDRIVE"]
})"));
ASSERT_TRUE(any_component_or_url);
for (Component component : kAllComponents) {
for (const char* url : {kGoogleUrl, kChromiumUrl}) {
ActionContext context = {.url = GURL(url), .component = component};
ASSERT_TRUE(any_component_or_url->IsTriggered(context));
}
}
}
TEST(AttributesConditionTest, URLAndOneComponent) {
for (Component condition_component : kAllComponents) {
constexpr char kTemplate[] =
R"({"urls": ["google.com"], "components": ["%s"]})";
auto google_and_one_component =
AttributesCondition::Create(CreateDict(base::StringPrintf(
kTemplate, GetComponentMapping(condition_component).c_str())));
ASSERT_TRUE(google_and_one_component);
for (Component context_component : kAllComponents) {
for (const char* url : {kGoogleUrl, kChromiumUrl}) {
ActionContext context = {.url = GURL(url),
.component = context_component};
if (context_component == condition_component && url == kGoogleUrl) {
ASSERT_TRUE(google_and_one_component->IsTriggered(context))
<< "Expected " << GetComponentMapping(context_component)
<< " to trigger for " << url;
} else {
ASSERT_FALSE(google_and_one_component->IsTriggered(context))
<< "Expected " << GetComponentMapping(context_component)
<< " to not trigger for " << url;
}
}
}
}
}
#endif // BUILDFLAG(IS_CHROMEOS)
} // namespace data_controls