// Copyright 2018 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 "third_party/blink/renderer/core/loader/previews_resource_loading_hints.h" #include #include #include "base/test/metrics/histogram_tester.h" #include "components/ukm/test_ukm_recorder.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/loader/frame_loader.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/platform/geometry/int_size.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h" #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { namespace { class PreviewsResourceLoadingHintsTest : public PageTestBase { public: PreviewsResourceLoadingHintsTest() { dummy_page_holder_ = DummyPageHolder::Create(IntSize(1, 1)); } protected: std::unique_ptr dummy_page_holder_; }; TEST_F(PreviewsResourceLoadingHintsTest, NoPatterns) { std::vector subresources_to_block; PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create( dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(), subresources_to_block); EXPECT_TRUE(hints->AllowLoad(KURL("https://www.example.com/"), ResourceLoadPriority::kHighest)); } TEST_F(PreviewsResourceLoadingHintsTest, OnePattern) { std::vector subresources_to_block; subresources_to_block.push_back("foo.jpg"); PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create( dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(), subresources_to_block); const struct { KURL url; bool allow_load_expected; } tests[] = { {KURL("https://www.example.com/"), true}, {KURL("https://www.example.com/foo.js"), true}, {KURL("https://www.example.com/foo.jpg"), false}, {KURL("https://www.example.com/pages/foo.jpg"), false}, {KURL("https://www.example.com/foobar.jpg"), true}, {KURL("https://www.example.com/barfoo.jpg"), false}, {KURL("http://www.example.com/foo.jpg"), false}, {KURL("http://www.example.com/foo.jpg?q=alpha"), false}, {KURL("http://www.example.com/bar.jpg?q=foo.jpg"), true}, {KURL("http://www.example.com/bar.jpg?q=foo.jpg#foo.jpg"), true}, }; for (const auto& test : tests) { base::HistogramTester histogram_tester; EXPECT_EQ(test.allow_load_expected, hints->AllowLoad(test.url, ResourceLoadPriority::kHighest)); histogram_tester.ExpectUniqueSample( "ResourceLoadingHints.ResourceLoadingBlocked", !test.allow_load_expected, 1); if (!test.allow_load_expected) { histogram_tester.ExpectUniqueSample( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Blocked", ResourceLoadPriority::kHighest, 1); histogram_tester.ExpectTotalCount( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Allowed", 0); } else { histogram_tester.ExpectTotalCount( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Blocked", 0); histogram_tester.ExpectUniqueSample( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Allowed", ResourceLoadPriority::kHighest, 1); } } } TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatterns) { std::vector subresources_to_block; subresources_to_block.push_back(".example1.com/foo.jpg"); subresources_to_block.push_back(".example1.com/bar.jpg"); subresources_to_block.push_back(".example2.com/baz.jpg"); PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create( dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(), subresources_to_block); const struct { KURL url; bool allow_load_expected; } tests[] = { {KURL("https://www.example1.com/"), true}, {KURL("https://www.example1.com/foo.js"), true}, {KURL("https://www.example1.com/foo.jpg"), false}, {KURL("https://www.example1.com/pages/foo.jpg"), true}, {KURL("https://www.example1.com/foobar.jpg"), true}, {KURL("https://www.example1.com/barfoo.jpg"), true}, {KURL("http://www.example1.com/foo.jpg"), false}, {KURL("http://www.example1.com/bar.jpg"), false}, {KURL("http://www.example2.com/baz.jpg"), false}, {KURL("http://www.example2.com/pages/baz.jpg"), true}, {KURL("http://www.example2.com/baz.html"), true}, }; for (const auto& test : tests) { EXPECT_EQ(test.allow_load_expected, hints->AllowLoad(test.url, ResourceLoadPriority::kHighest)); } } TEST_F(PreviewsResourceLoadingHintsTest, OnePatternHistogramChecker) { std::vector subresources_to_block; subresources_to_block.push_back("foo.jpg"); PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create( dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(), subresources_to_block); const struct { KURL url; bool allow_load_expected; ResourceLoadPriority resource_load_priority; } tests[] = { {KURL("https://www.example.com/foo.js"), true, ResourceLoadPriority::kLow}, {KURL("https://www.example.com/foo.jpg"), false, ResourceLoadPriority::kLow}, {KURL("https://www.example.com/foo.js"), true, ResourceLoadPriority::kMedium}, {KURL("https://www.example.com/foo.jpg"), false, ResourceLoadPriority::kMedium}, }; for (const auto& test : tests) { base::HistogramTester histogram_tester; EXPECT_EQ(test.allow_load_expected, hints->AllowLoad(test.url, test.resource_load_priority)); histogram_tester.ExpectUniqueSample( "ResourceLoadingHints.ResourceLoadingBlocked", !test.allow_load_expected, 1); if (!test.allow_load_expected) { histogram_tester.ExpectUniqueSample( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Blocked", test.resource_load_priority, 1); histogram_tester.ExpectTotalCount( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Allowed", 0); } else { histogram_tester.ExpectTotalCount( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Blocked", 0); histogram_tester.ExpectUniqueSample( "ResourceLoadingHints.ResourceLoadingBlocked.ResourceLoadPriority." "Allowed", test.resource_load_priority, 1); } } } TEST_F(PreviewsResourceLoadingHintsTest, MultiplePatternUKMChecker) { std::vector subresources_to_block; subresources_to_block.push_back(".example1.com/low_1.jpg"); subresources_to_block.push_back(".example1.com/very_low_1.jpg"); subresources_to_block.push_back(".example1.com/very_high_1.jpg"); subresources_to_block.push_back(".example1.com/medium_1_and_medium_4.jpg"); subresources_to_block.push_back(".example1.com/unused_1.jpg"); subresources_to_block.push_back(".example2.com/medium_2.jpg"); subresources_to_block.push_back(".example2.com/unused_2.jpg"); subresources_to_block.push_back(".example3.com/unused_3.jpg"); subresources_to_block.push_back(".example3.com/very_low_2_and_medium_3.jpg"); PreviewsResourceLoadingHints* hints = PreviewsResourceLoadingHints::Create( dummy_page_holder_->GetDocument(), ukm::UkmRecorder::GetNewSourceID(), subresources_to_block); const struct { KURL url; ResourceLoadPriority resource_load_priority; } resources_to_load[] = { {KURL("https://www.example1.com/"), ResourceLoadPriority::kHigh}, {KURL("https://www.example1.com/foo.js"), ResourceLoadPriority::kLow}, {KURL("https://www.example1.com/very_low_1.jpg"), ResourceLoadPriority::kVeryLow}, {KURL("https://www.example1.com/low_1.jpg"), ResourceLoadPriority::kLow}, {KURL("https://www.example1.com/very_high_1.jpg"), ResourceLoadPriority::kVeryHigh}, {KURL("https://www.example1.com/pages/foo.jpg"), ResourceLoadPriority::kVeryLow}, {KURL("https://www.example1.com/foobar.jpg"), ResourceLoadPriority::kVeryHigh}, {KURL("https://www.example1.com/barfoo.jpg"), ResourceLoadPriority::kVeryHigh}, {KURL("http://www.example1.com/foo.jpg"), ResourceLoadPriority::kLow}, {KURL("http://www.example1.com/medium_1_and_medium_4.jpg"), ResourceLoadPriority::kMedium}, {KURL("http://www.example2.com/medium_2.jpg"), ResourceLoadPriority::kMedium}, {KURL("http://www.example2.com/pages/baz.jpg"), ResourceLoadPriority::kLow}, {KURL("http://www.example2.com/baz.html"), ResourceLoadPriority::kVeryHigh}, {KURL("http://www.example3.com/very_low_2_and_medium_3.jpg"), ResourceLoadPriority::kVeryLow}, {KURL("http://www.example3.com/very_low_2_and_medium_3.jpg"), ResourceLoadPriority::kMedium}, {KURL("http://www.example1.com/medium_1_and_medium_4.jpg"), ResourceLoadPriority::kMedium}, }; for (const auto& resource_to_load : resources_to_load) { hints->AllowLoad(resource_to_load.url, resource_to_load.resource_load_priority); } ukm::TestAutoSetUkmRecorder test_ukm_recorder; hints->RecordUKM(&test_ukm_recorder); using UkmEntry = ukm::builders::PreviewsResourceLoadingHints; auto entries = test_ukm_recorder.GetEntriesByName(UkmEntry::kEntryName); ASSERT_EQ(1u, entries.size()); const auto* entry = entries[0]; test_ukm_recorder.ExpectEntryMetric( entry, UkmEntry::kpatterns_to_block_totalName, 9); test_ukm_recorder.ExpectEntryMetric(entry, UkmEntry::kpatterns_to_block_usedName, 6); test_ukm_recorder.ExpectEntryMetric( entry, UkmEntry::kblocked_very_low_priorityName, 2); test_ukm_recorder.ExpectEntryMetric(entry, UkmEntry::kblocked_low_priorityName, 1); test_ukm_recorder.ExpectEntryMetric( entry, UkmEntry::kblocked_medium_priorityName, 4); test_ukm_recorder.ExpectEntryMetric(entry, UkmEntry::kblocked_high_priorityName, 0); test_ukm_recorder.ExpectEntryMetric( entry, UkmEntry::kblocked_very_high_priorityName, 1); } } // namespace } // namespace blink