blob: 740d70ac90ce87b4ed8b15a163a8559ddad2602f [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/browsing_topics/header_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/web_contents_tester.h"
#include "content/test/test_render_view_host.h"
namespace content {
namespace {
class TopicsInterceptingContentBrowserClient : public ContentBrowserClient {
public:
bool HandleTopicsWebApi(
const url::Origin& context_origin,
content::RenderFrameHost* main_frame,
browsing_topics::ApiCallerSource caller_source,
bool get_topics,
bool observe,
std::vector<blink::mojom::EpochTopicPtr>& topics) override {
handle_topics_web_api_called_ = true;
last_get_topics_param_ = get_topics;
last_observe_param_ = observe;
return true;
}
bool handle_topics_web_api_called() const {
return handle_topics_web_api_called_;
}
bool last_get_topics_param() const { return last_get_topics_param_; }
bool last_observe_param() const { return last_observe_param_; }
private:
bool handle_topics_web_api_called_ = false;
bool last_get_topics_param_ = false;
bool last_observe_param_ = false;
};
} // namespace
class BrowsingTopicsUtilTest : public RenderViewHostTestHarness {
public:
void SetUp() override {
content::RenderViewHostTestHarness::SetUp();
original_client_ = content::SetBrowserClientForTesting(&browser_client_);
GURL url("https://foo.com");
auto simulator =
NavigationSimulator::CreateBrowserInitiated(url, web_contents());
simulator->Commit();
}
void TearDown() override {
SetBrowserClientForTesting(original_client_);
content::RenderViewHostTestHarness::TearDown();
}
const TopicsInterceptingContentBrowserClient& browser_client() const {
return browser_client_;
}
private:
TopicsInterceptingContentBrowserClient browser_client_;
raw_ptr<ContentBrowserClient> original_client_ = nullptr;
};
TEST_F(BrowsingTopicsUtilTest, DeriveTopicsHeaderValue_EmptyTopics) {
std::vector<blink::mojom::EpochTopicPtr> topics;
std::string header_value = DeriveTopicsHeaderValue(topics);
EXPECT_TRUE(header_value.empty());
}
TEST_F(BrowsingTopicsUtilTest, DeriveTopicsHeaderValue_OneTopic) {
std::vector<blink::mojom::EpochTopicPtr> topics;
blink::mojom::EpochTopicPtr topic0 = blink::mojom::EpochTopic::New();
topic0->topic = 1;
topic0->config_version = "chrome.1";
topic0->taxonomy_version = "1";
topic0->model_version = "2";
topic0->version = "chrome.1:1:2";
topics.push_back(std::move(topic0));
std::string header_value = DeriveTopicsHeaderValue(topics);
EXPECT_EQ(
header_value,
"1;version=\"chrome.1:1:2\";config_version=\"chrome.1\";model_version="
"\"2\";taxonomy_version=\"1\"");
}
TEST_F(BrowsingTopicsUtilTest, DeriveTopicsHeaderValue_TwoTopics) {
std::vector<blink::mojom::EpochTopicPtr> topics;
{
blink::mojom::EpochTopicPtr topic = blink::mojom::EpochTopic::New();
topic->topic = 1;
topic->config_version = "chrome.1";
topic->taxonomy_version = "1";
topic->model_version = "2";
topic->version = "chrome.1:1:2";
topics.push_back(std::move(topic));
}
{
blink::mojom::EpochTopicPtr topic = blink::mojom::EpochTopic::New();
topic->topic = 2;
topic->config_version = "chrome.1";
topic->taxonomy_version = "3";
topic->model_version = "4";
topic->version = "chrome.1:3:4";
topics.push_back(std::move(topic));
}
std::string header_value = DeriveTopicsHeaderValue(topics);
EXPECT_EQ(header_value,
"1;version=\"chrome.1:1:2\";config_version=\"chrome.1\";model_"
"version=\"2\";taxonomy_version=\"1\", "
"2;version=\"chrome.1:3:4\";config_version=\"chrome.1\";model_"
"version=\"4\";taxonomy_version=\"3\"");
}
TEST_F(BrowsingTopicsUtilTest,
HandleTopicsEligibleResponse_NoObserveTopicsHeader) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate("HTTP/1.1 200 OK\r\n");
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
*web_contents()->GetPrimaryMainFrame(),
browsing_topics::ApiCallerSource::kFetch);
EXPECT_FALSE(browser_client().handle_topics_web_api_called());
}
TEST_F(BrowsingTopicsUtilTest,
HandleTopicsEligibleResponse_TrueValueObserveTopicsHeader) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\r\n"
"Observe-Browsing-Topics: ?1\r\n");
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
*web_contents()->GetPrimaryMainFrame(),
browsing_topics::ApiCallerSource::kFetch);
EXPECT_TRUE(browser_client().handle_topics_web_api_called());
EXPECT_FALSE(browser_client().last_get_topics_param());
EXPECT_TRUE(browser_client().last_observe_param());
}
TEST_F(BrowsingTopicsUtilTest,
HandleTopicsEligibleResponse_FalseValueObserveTopicsHeader) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\r\n"
"Observe-Browsing-Topics: ?0\r\n");
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
*web_contents()->GetPrimaryMainFrame(),
browsing_topics::ApiCallerSource::kFetch);
EXPECT_FALSE(browser_client().handle_topics_web_api_called());
}
TEST_F(BrowsingTopicsUtilTest,
HandleTopicsEligibleResponse_NotBooleanObserveTopicsHeader) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\r\n"
"Observe-Browsing-Topics: 1\r\n");
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
*web_contents()->GetPrimaryMainFrame(),
browsing_topics::ApiCallerSource::kFetch);
EXPECT_FALSE(browser_client().handle_topics_web_api_called());
}
TEST_F(BrowsingTopicsUtilTest,
HandleTopicsEligibleResponse_InvalidObserveTopicsHeader) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\r\n"
"Observe-Browsing-Topics: !!!\r\n");
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
*web_contents()->GetPrimaryMainFrame(),
browsing_topics::ApiCallerSource::kFetch);
EXPECT_FALSE(browser_client().handle_topics_web_api_called());
}
TEST_F(
BrowsingTopicsUtilTest,
HandleTopicsEligibleResponse_MultipleObserveTopicsHeader_InvalidNormalizedHeader) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\r\n"
"Observe-Browsing-Topics: ?1\r\n"
"Observe-Browsing-Topics: ?1\r\n");
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
*web_contents()->GetPrimaryMainFrame(),
browsing_topics::ApiCallerSource::kFetch);
EXPECT_FALSE(browser_client().handle_topics_web_api_called());
}
TEST_F(BrowsingTopicsUtilTest, HandleTopicsEligibleResponse_InactiveFrame) {
scoped_refptr<net::HttpResponseHeaders> headers =
net::HttpResponseHeaders::TryToCreate(
"HTTP/1.1 200 OK\r\n"
"Observe-Browsing-Topics: ?1\r\n");
RenderFrameHostImpl& rfh =
static_cast<RenderFrameHostImpl&>(*web_contents()->GetPrimaryMainFrame());
rfh.SetLifecycleState(
RenderFrameHostImpl::LifecycleStateImpl::kReadyToBeDeleted);
HandleTopicsEligibleResponse(
*headers, /*caller_origin=*/url::Origin::Create(GURL("https://bar.com")),
rfh, browsing_topics::ApiCallerSource::kFetch);
EXPECT_FALSE(browser_client().handle_topics_web_api_called());
}
} // namespace content