#include "content/browser/interest_group/data_decoder_manager.h"
#include <memory>
#include <optional>
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
namespace {
class DataDecoderManagerTest : public testing::Test {
public:
DataDecoderManagerTest() = default;
~DataDecoderManagerTest() override = default;
protected:
void ValidateDecoder(data_decoder::DataDecoder& data_decoder) {
base::test::TestFuture<data_decoder::DataDecoder::ValueOrError> future;
data_decoder.ParseCbor({0x64, 0x74, 0x65, 0x73, 0x74},
future.GetCallback());
const auto& result = future.Get();
ASSERT_TRUE(result.has_value());
EXPECT_EQ(result.value(), "test");
}
const url::Origin kOrigin1 =
url::Origin::Create(GURL("https://origin1.test"));
const url::Origin kOrigin2 =
url::Origin::Create(GURL("https://origin2.test"));
base::TimeDelta kTinyTime = base::Milliseconds(1);
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
DataDecoderManager manager_;
};
TEST_F(DataDecoderManagerTest, CreateAndDestroyHandle) {
for (base::TimeDelta delay :
{base::Seconds(0), DataDecoderManager::kIdleTimeout - kTinyTime,
DataDecoderManager::kIdleTimeout, base::Hours(1)}) {
auto handle = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
task_environment_.FastForwardBy(delay);
ValidateDecoder(handle->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
handle.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout -
kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
task_environment_.FastForwardBy(kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2),
std::nullopt);
}
}
TEST_F(DataDecoderManagerTest, MultipleHandles) {
auto handle1 = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle1->data_decoder());
auto handle2 = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 2u);
EXPECT_EQ(&handle1->data_decoder(), &handle2->data_decoder());
ValidateDecoder(handle2->data_decoder());
handle1.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle2->data_decoder());
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle2->data_decoder());
auto* raw_decoder = &handle2->data_decoder();
handle2.reset();
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout - kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
auto handle3 = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_EQ(&handle3->data_decoder(), raw_decoder);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle3->data_decoder());
raw_decoder = nullptr;
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle3->data_decoder());
handle3.reset();
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout - kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
task_environment_.FastForwardBy(kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2),
std::nullopt);
}
TEST_F(DataDecoderManagerTest, MultipleDataDecoders) {
auto handle1 = manager_.GetHandle(kOrigin1, kOrigin1);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 1u);
ValidateDecoder(handle1->data_decoder());
auto handle2 = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_NE(&handle1->data_decoder(), &handle2->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
ValidateDecoder(handle2->data_decoder());
auto handle3 = manager_.GetHandle(kOrigin2, kOrigin1);
EXPECT_NE(&handle1->data_decoder(), &handle3->data_decoder());
EXPECT_NE(&handle2->data_decoder(), &handle3->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 3u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 1u);
ValidateDecoder(handle3->data_decoder());
auto handle4 = manager_.GetHandle(kOrigin2, kOrigin2);
EXPECT_NE(&handle1->data_decoder(), &handle4->data_decoder());
EXPECT_NE(&handle2->data_decoder(), &handle4->data_decoder());
EXPECT_NE(&handle3->data_decoder(), &handle4->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 1u);
ValidateDecoder(handle4->data_decoder());
auto handle1_2 = manager_.GetHandle(kOrigin1, kOrigin1);
EXPECT_EQ(&handle1->data_decoder(), &handle1_2->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 1u);
auto handle2_2 = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_EQ(&handle2->data_decoder(), &handle2_2->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 1u);
auto handle3_2 = manager_.GetHandle(kOrigin2, kOrigin1);
EXPECT_EQ(&handle3->data_decoder(), &handle3_2->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 1u);
auto handle4_2 = manager_.GetHandle(kOrigin2, kOrigin2);
EXPECT_EQ(&handle4->data_decoder(), &handle4_2->data_decoder());
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 2u);
handle1.reset();
handle1_2.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 2u);
handle2.reset();
handle2_2.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 2u);
handle3.reset();
handle3_2.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 2u);
handle4.reset();
handle4_2.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2), 0u);
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout - kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 4u);
task_environment_.FastForwardBy(kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1),
std::nullopt);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2),
std::nullopt);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin1),
std::nullopt);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin2, kOrigin2),
std::nullopt);
}
TEST_F(DataDecoderManagerTest, OverlappingCleanupTimers) {
const base::TimeDelta kHalfTimeout = DataDecoderManager::kIdleTimeout / 2;
auto handle1 = manager_.GetHandle(kOrigin1, kOrigin1);
auto handle2 = manager_.GetHandle(kOrigin1, kOrigin2);
EXPECT_EQ(manager_.NumDecodersForTesting(), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
handle1.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 1u);
task_environment_.FastForwardBy(kHalfTimeout);
handle2.reset();
EXPECT_EQ(manager_.NumDecodersForTesting(), 2u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout -
kHalfTimeout - kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 2u);
task_environment_.FastForwardBy(kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1),
std::nullopt);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2), 0u);
task_environment_.FastForwardBy(DataDecoderManager::kIdleTimeout - kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 1u);
task_environment_.FastForwardBy(kTinyTime);
EXPECT_EQ(manager_.NumDecodersForTesting(), 0u);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin1),
std::nullopt);
EXPECT_EQ(manager_.GetHandleCountForTesting(kOrigin1, kOrigin2),
std::nullopt);
}
}
}