blob: d1d6748b800e5eebe4e2f0ea79f2d95b187940a5 [file]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/lite_video/lite_video_user_blocklist.h"
#include <map>
#include <memory>
#include <string>
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_delegate.h"
#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_item.h"
#include "components/blocklist/opt_out_blocklist/opt_out_store.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_navigation_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace lite_video {
namespace {
// Empty mock class to test the LiteVideoUserBlocklist.
class EmptyOptOutBlocklistDelegate : public blocklist::OptOutBlocklistDelegate {
public:
EmptyOptOutBlocklistDelegate() = default;
};
class TestLiteVideoUserBlocklist : public LiteVideoUserBlocklist {
public:
TestLiteVideoUserBlocklist(
std::unique_ptr<blocklist::OptOutStore> opt_out_store,
base::Clock* clock,
blocklist::OptOutBlocklistDelegate* blocklist_delegate)
: LiteVideoUserBlocklist(std::move(opt_out_store),
clock,
blocklist_delegate) {}
~TestLiteVideoUserBlocklist() override = default;
bool ShouldUseSessionPolicy(base::TimeDelta* duration,
size_t* history,
int* threshold) const override {
return LiteVideoUserBlocklist::ShouldUseSessionPolicy(duration, history,
threshold);
}
bool ShouldUsePersistentPolicy(base::TimeDelta* duration,
size_t* history,
int* threshold) const override {
return LiteVideoUserBlocklist::ShouldUsePersistentPolicy(duration, history,
threshold);
}
bool ShouldUseHostPolicy(base::TimeDelta* duration,
size_t* history,
int* threshold,
size_t* max_hosts) const override {
return LiteVideoUserBlocklist::ShouldUseHostPolicy(duration, history,
threshold, max_hosts);
}
bool ShouldUseTypePolicy(base::TimeDelta* duration,
size_t* history,
int* threshold) const override {
return LiteVideoUserBlocklist::ShouldUseTypePolicy(duration, history,
threshold);
}
blocklist::BlocklistData::AllowedTypesAndVersions GetAllowedTypes()
const override {
return LiteVideoUserBlocklist::GetAllowedTypes();
}
};
class LiteVideoUserBlocklistTest : public ChromeRenderViewHostTestHarness {
public:
void SetUp() override {
content::RenderViewHostTestHarness::SetUp();
ConfigBlocklistWithParams({});
}
// Sets up a new blocklist with the given |params|.
void ConfigBlocklistWithParams(
const std::map<std::string, std::string>& params) {
scoped_feature_list_.Reset();
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kLiteVideo, params);
blocklist_ = std::make_unique<TestLiteVideoUserBlocklist>(
nullptr, &test_clock_, &blocklist_delegate_);
}
void ConfigBlocklistParamsForTesting() {
int max_user_blocklist_hosts = 1;
int user_blocklist_opt_out_history_threshold = 1;
ConfigBlocklistWithParams(
{{"user_blocklist_opt_out_history_threshold",
base::NumberToString(user_blocklist_opt_out_history_threshold)},
{"max_user_blocklist_hosts",
base::NumberToString(max_user_blocklist_hosts)}});
}
void SeedBlocklist(const std::string& key, LiteVideoBlocklistType type) {
blocklist_->AddEntry(key, true, static_cast<int>(type));
}
LiteVideoBlocklistReason CheckBlocklistForSubframeNavigation(
const GURL& mainframe_url,
const GURL& subframe_url) {
// Needed so that a mainframe navigation exists.
NavigateAndCommit(mainframe_url);
content::RenderFrameHostTester* rfh_tester =
content::RenderFrameHostTester::For(main_rfh());
content::RenderFrameHost* subframe = rfh_tester->AppendChild("subframe");
content::MockNavigationHandle navigation_handle(subframe_url, subframe);
return blocklist_->IsLiteVideoAllowedOnNavigation(&navigation_handle);
}
LiteVideoBlocklistReason CheckBlocklistForMainframeNavigation(
const GURL& url) {
// Needed so that a mainframe navigation exists.
NavigateAndCommit(url);
content::MockNavigationHandle navigation_handle(url, main_rfh());
return blocklist_->IsLiteVideoAllowedOnNavigation(&navigation_handle);
}
void TearDown() override { content::RenderViewHostTestHarness::TearDown(); }
TestLiteVideoUserBlocklist* blocklist() { return blocklist_.get(); }
base::SimpleTestClock* test_clock() { return &test_clock_; }
private:
EmptyOptOutBlocklistDelegate blocklist_delegate_;
base::test::ScopedFeatureList scoped_feature_list_;
base::SimpleTestClock test_clock_;
std::unique_ptr<TestLiteVideoUserBlocklist> blocklist_;
};
TEST_F(LiteVideoUserBlocklistTest, NavigationNotEligibile) {
GURL url("chrome://about");
EXPECT_EQ(CheckBlocklistForMainframeNavigation(url),
LiteVideoBlocklistReason::kNavigationNotEligibile);
}
TEST_F(LiteVideoUserBlocklistTest, NavigationBlocklistedByNavigationBlocklist) {
ConfigBlocklistParamsForTesting();
GURL url("https://test.com");
content::MockNavigationHandle nav_handle;
nav_handle.set_url(url);
blocklist()->AddNavigationToBlocklist(&nav_handle, true);
EXPECT_EQ(CheckBlocklistForMainframeNavigation(url),
LiteVideoBlocklistReason::kNavigationBlocklisted);
}
TEST_F(LiteVideoUserBlocklistTest, NavigationUnblocklistedByNavigation) {
ConfigBlocklistParamsForTesting();
GURL url("https://test.com");
content::MockNavigationHandle nav_handle;
nav_handle.set_url(url);
blocklist()->AddNavigationToBlocklist(&nav_handle, true);
test_clock()->Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(CheckBlocklistForMainframeNavigation(url),
LiteVideoBlocklistReason::kNavigationBlocklisted);
blocklist()->AddNavigationToBlocklist(&nav_handle, false);
test_clock()->Advance(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(CheckBlocklistForMainframeNavigation(url),
LiteVideoBlocklistReason::kAllowed);
}
TEST_F(LiteVideoUserBlocklistTest,
MainframeNavigationBlocklistedByRebufferBlocklist) {
ConfigBlocklistParamsForTesting();
GURL url("https://test.com");
blocklist()->AddRebufferToBlocklist(url, base::nullopt, true);
EXPECT_EQ(CheckBlocklistForMainframeNavigation(url),
LiteVideoBlocklistReason::kRebufferingBlocklisted);
}
TEST_F(LiteVideoUserBlocklistTest, MainframeNavigationAllowed) {
ConfigBlocklistParamsForTesting();
GURL url("https://test.com");
EXPECT_EQ(CheckBlocklistForMainframeNavigation(url),
LiteVideoBlocklistReason::kAllowed);
}
TEST_F(LiteVideoUserBlocklistTest,
SubframeNavigationBlocklistedByRebufferBlocklist) {
ConfigBlocklistParamsForTesting();
GURL mainframe_url("https://test.com");
GURL subframe_url("https://subframe.com");
blocklist()->AddRebufferToBlocklist(mainframe_url, subframe_url, true);
EXPECT_EQ(CheckBlocklistForSubframeNavigation(mainframe_url, subframe_url),
LiteVideoBlocklistReason::kRebufferingBlocklisted);
}
TEST_F(LiteVideoUserBlocklistTest, SubframeNavigationAllowed) {
ConfigBlocklistParamsForTesting();
GURL mainframe_url("https://test.com");
GURL subframe_url("https://subframe.com");
EXPECT_EQ(CheckBlocklistForSubframeNavigation(mainframe_url, subframe_url),
LiteVideoBlocklistReason::kAllowed);
}
TEST_F(LiteVideoUserBlocklistTest, DefaultParams) {
base::TimeDelta duration;
size_t history = 0;
int threshold = 0;
size_t max_hosts = 0;
EXPECT_TRUE(blocklist()->ShouldUseHostPolicy(&duration, &history, &threshold,
&max_hosts));
EXPECT_EQ(base::TimeDelta::FromDays(1), duration);
EXPECT_EQ(5u, history);
EXPECT_EQ(5, threshold);
EXPECT_EQ(50u, max_hosts);
EXPECT_FALSE(blocklist()->ShouldUseTypePolicy(nullptr, nullptr, nullptr));
blocklist::BlocklistData::AllowedTypesAndVersions types =
blocklist()->GetAllowedTypes();
EXPECT_EQ(2u, types.size());
auto iter = types.find(
static_cast<int>(LiteVideoBlocklistType::kNavigationBlocklist));
EXPECT_NE(iter, types.end());
EXPECT_EQ(0, iter->second);
iter =
types.find(static_cast<int>(LiteVideoBlocklistType::kRebufferBlocklist));
EXPECT_NE(iter, types.end());
EXPECT_EQ(0, iter->second);
}
} // namespace
} // namespace lite_video