blob: 0b3617bc2b3a6f125ee33a18d7c9e5ff4fab47b2 [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 "chrome/browser/ui/webui/flags/flags_ui_handler.h"
#include "base/test/task_environment.h"
#include "components/webui/flags/flags_storage.h"
#include "components/webui/flags/flags_ui_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/test_web_ui.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class TestFlagStorage : public flags_ui::FlagsStorage {
public:
// Retrieves the flags as a set of strings.
std::set<std::string> GetFlags() const override { return flags_; }
// Stores the |flags| and returns true on success.
bool SetFlags(const std::set<std::string>& flags) override {
flags_ = flags;
return true;
}
// Retrieves the serialized origin list corresponding to
// |internal_entry_name|. Does not check if the return value is well formed.
std::string GetOriginListFlag(
const std::string& internal_entry_name) const override {
if (origin_list_flags_.count(internal_entry_name) == 0) {
return "";
}
return origin_list_flags_.at(internal_entry_name);
}
// Sets the serialized |origin_list_value| corresponding to
// |internal_entry_name|. Does not check if |origin_list_value| is well
// formed.
void SetOriginListFlag(const std::string& internal_entry_name,
const std::string& origin_list_value) override {
origin_list_flags_[internal_entry_name] = origin_list_value;
}
std::string GetStringFlag(
const std::string& internal_entry_name) const override {
return GetOriginListFlag(internal_entry_name);
}
void SetStringFlag(const std::string& internal_entry_name,
const std::string& value) override {
SetOriginListFlag(internal_entry_name, value);
}
// Lands pending changes to disk immediately.
void CommitPendingWrites() override {}
private:
std::set<std::string> flags_;
std::map<std::string, std::string> origin_list_flags_;
};
class TestFlagsUIHandler : public FlagsUIHandler {
public:
// Make public for testing.
using FlagsUIHandler::set_web_ui;
};
class FlagsUIHandlerTest : public testing::Test {
public:
void SetUp() override {
std::unique_ptr<TestFlagStorage> storage =
std::make_unique<TestFlagStorage>();
storage_ = storage.get();
handler_ = std::make_unique<TestFlagsUIHandler>();
handler_->Init(std::move(storage),
flags_ui::FlagAccess::kOwnerAccessToFlags);
handler_->set_web_ui(&web_ui_);
handler_->RegisterMessages();
}
protected:
content::TestWebUI web_ui_;
std::unique_ptr<TestFlagsUIHandler> handler_;
raw_ptr<TestFlagStorage> storage_;
};
TEST_F(FlagsUIHandlerTest, HandlesSetString) {
// Need to use an actual feature name for ChromeOS.
const std::string kTestFeature = "protected-audience-debug-token";
EXPECT_EQ("", storage_->GetStringFlag(kTestFeature));
web_ui_.HandleReceivedMessage(
flags_ui::kSetStringFlag,
base::Value::List().Append(kTestFeature).Append("value"));
EXPECT_EQ("value", storage_->GetStringFlag(kTestFeature));
}
TEST_F(FlagsUIHandlerTest, HandlesSetOriginList) {
// Need to use an actual feature name for ChromeOS.
const std::string kTestFeature = "isolate-origins";
EXPECT_EQ("", storage_->GetOriginListFlag(kTestFeature));
web_ui_.HandleReceivedMessage(
flags_ui::kSetOriginListFlag,
base::Value::List()
.Append(kTestFeature)
.Append("https://foo.com,invalid,http://bar.org"));
EXPECT_EQ("https://foo.com,http://bar.org",
storage_->GetOriginListFlag(kTestFeature));
}
TEST_F(FlagsUIHandlerTest, HandleRequestExperimentalFeatures) {
base::Value::List args;
args.Append("callbackId");
web_ui_.HandleReceivedMessage(flags_ui::kRequestExperimentalFeatures, args);
EXPECT_EQ(1u, web_ui_.call_data().size());
auto& call_data = *(web_ui_.call_data().back());
EXPECT_EQ("cr.webUIResponse", call_data.function_name());
EXPECT_EQ("callbackId", call_data.arg1()->GetString());
EXPECT_TRUE(call_data.arg2()->GetBool());
const base::Value::Dict& response = call_data.arg3()->GetDict();
// Check that entries for both "supported_features" and "unsupported_features"
// exist.
const base::Value::List& supported =
*response.FindList(flags_ui::kSupportedFeatures);
EXPECT_GT(supported.size(), 0u);
const base::Value::List& unsupported =
*response.FindList(flags_ui::kUnsupportedFeatures);
EXPECT_GT(unsupported.size(), 0u);
}
// Tests for chrome://flags/deprecated
TEST_F(FlagsUIHandlerTest, HandleRequestDeprecatedFeatures) {
base::Value::List args;
args.Append("callbackId");
web_ui_.HandleReceivedMessage("requestDeprecatedFeatures", args);
EXPECT_EQ(1u, web_ui_.call_data().size());
auto& call_data = *(web_ui_.call_data().back());
EXPECT_EQ("cr.webUIResponse", call_data.function_name());
EXPECT_EQ("callbackId", call_data.arg1()->GetString());
EXPECT_TRUE(call_data.arg2()->GetBool());
const base::Value::Dict& response = call_data.arg3()->GetDict();
// Check that exactly 1 entry is returned as part of "supported_features".
const base::Value::List& supported =
*response.FindList(flags_ui::kSupportedFeatures);
EXPECT_EQ(1u, supported.size());
const base::Value::Dict& feature = supported[0].GetDict();
const std::string& internal_name = *feature.FindString("internal_name");
EXPECT_EQ("deprecate-unload", internal_name);
// Check that no entry is returned as part of "unsupported_features".
const base::Value::List& unsupported =
*response.FindList(flags_ui::kUnsupportedFeatures);
EXPECT_EQ(0u, unsupported.size());
}
} // namespace