Commit 72256f4d authored by Ryan Sturm's avatar Ryan Sturm Committed by Commit Bot

Adding fuzzing to the page load capping threshold

Privacy requested this on the design recently. The idea is that with a
large enough variance, a first party cannot embed a third party to
determine the exact number of bytes in a response.

Bug: 853243
Change-Id: I9a7f851eabc6f99d8aae35dc6398a09263043d0c
Reviewed-on: https://chromium-review.googlesource.com/1102908Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Commit-Queue: Ryan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#567828}
parent 5b371945
......@@ -50,7 +50,7 @@ class PageLoadCappingBrowserTest : public InProcessBrowserTest {
scoped_refptr<base::FieldTrial> trial =
base::FieldTrialList::CreateFieldTrial("TrialName1", "GroupName1");
std::map<std::string, std::string> feature_parameters = {
{"PageCapMiB", "0"}};
{"PageCapMiB", "0"}, {"PageFuzzingKiB", "0"}};
base::FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
"TrialName1", "GroupName1", feature_parameters);
......
......@@ -10,6 +10,7 @@
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/optional.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/data_use_measurement/page_load_capping/chrome_page_load_capping_features.h"
#include "chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.h"
......@@ -31,9 +32,11 @@ const char kPageCap[] = "PageCapMiB";
const char kMediaPageTypical[] = "MediaPageTypicalLargePageMiB";
const char kPageTypical[] = "PageTypicalLargePageMiB";
const char kPageFuzzing[] = "PageFuzzingKiB";
// The page load capping bytes threshold for the page. There are seperate
// thresholds for media and non-media pages. Returns empty optional if the page
// should not be capped.
// thresholds for media and non-media pages. Returns empty optional if the
// page should not be capped.
base::Optional<int64_t> GetPageLoadCappingBytesThreshold(bool media_page_load) {
if (!base::FeatureList::IsEnabled(data_use_measurement::page_load_capping::
features::kDetectingHeavyPages)) {
......@@ -82,6 +85,8 @@ PageCappingPageLoadMetricsObserver::OnCommit(
web_contents_ = navigation_handle->GetWebContents();
page_cap_ = GetPageLoadCappingBytesThreshold(false /* media_page_load */);
url_host_ = navigation_handle->GetURL().host();
fuzzing_offset_ = GetFuzzingOffset();
MaybeCreate();
// TODO(ryansturm) Check a blacklist of eligible pages.
// https://crbug.com/797981
......@@ -107,8 +112,9 @@ void PageCappingPageLoadMetricsObserver::MaybeCreate() {
return;
// If there is no capping threshold, the threshold or the threshold is not
// met, do not show an infobar.
if (!page_cap_ || network_bytes_ < page_cap_.value())
// met, do not show an infobar. Use the fuzzing offset to increase the number
// of bytes needed.
if (!page_cap_ || (network_bytes_ - fuzzing_offset_) < page_cap_.value())
return;
displayed_infobar_ = PageLoadCappingInfoBarDelegate::Create(
......@@ -208,3 +214,20 @@ void PageCappingPageLoadMetricsObserver::WriteToSavings(int64_t bytes_saved) {
->UpdateContentLengths(0, bytes_saved, data_saver_enabled,
data_reduction_proxy::HTTPS, "text/html");
}
int64_t PageCappingPageLoadMetricsObserver::GetFuzzingOffset() const {
if (!base::FeatureList::IsEnabled(data_use_measurement::page_load_capping::
features::kDetectingHeavyPages)) {
return 0;
}
// Default is is 75 KiB.
int cap_kib = 75;
cap_kib = base::GetFieldTrialParamByFeatureAsInt(
data_use_measurement::page_load_capping::features::kDetectingHeavyPages,
kPageFuzzing, cap_kib);
int cap_bytes = cap_kib * 1024;
return base::RandInt(0, cap_bytes);
}
......@@ -36,6 +36,11 @@ class PageCappingPageLoadMetricsObserver
// Returns whether the page's subresource loading is currently paused.
bool IsPausedForTesting() const { return paused_; }
protected:
// Virtual for testing.
// Gets the random offset for the capping threshold.
virtual int64_t GetFuzzingOffset() const;
private:
// page_load_metrics::PageLoadMetricsObserver:
void OnLoadedResource(const page_load_metrics::ExtraRequestCompleteInfo&
......@@ -94,8 +99,11 @@ class PageCappingPageLoadMetricsObserver
// Whether the page's subresource loading is paused.
bool paused_ = false;
// The randomly generated offset from the capping threshold.
int64_t fuzzing_offset_ = 0;
// If non-empty, a group of handles that are pausing subresource loads in the
// renderframes of this page.
// render frames of this page.
std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr> handles_;
base::WeakPtrFactory<PageCappingPageLoadMetricsObserver> weak_factory_;
......
......@@ -30,16 +30,19 @@ class TestPageCappingPageLoadMetricsObserver
: public PageCappingPageLoadMetricsObserver {
public:
using SizeUpdateCallback = base::RepeatingCallback<void(int64_t)>;
explicit TestPageCappingPageLoadMetricsObserver(
const SizeUpdateCallback& callback)
: size_callback_(callback) {}
TestPageCappingPageLoadMetricsObserver(int64_t fuzzing_offset,
const SizeUpdateCallback& callback)
: fuzzing_offset_(fuzzing_offset), size_callback_(callback) {}
~TestPageCappingPageLoadMetricsObserver() override {}
void WriteToSavings(int64_t bytes_saved) override {
size_callback_.Run(bytes_saved);
}
int64_t GetFuzzingOffset() const override { return fuzzing_offset_; }
private:
int64_t fuzzing_offset_;
SizeUpdateCallback size_callback_;
};
......@@ -68,12 +71,14 @@ class PageCappingObserverTest
protected:
void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
auto observer = std::make_unique<TestPageCappingPageLoadMetricsObserver>(
fuzzing_offset_,
base::BindRepeating(&PageCappingObserverTest::UpdateSavings,
base::Unretained(this)));
observer_ = observer.get();
tracker->AddObserver(std::move(observer));
}
int64_t savings_ = 0;
int64_t fuzzing_offset_ = 0;
TestPageCappingPageLoadMetricsObserver* observer_;
};
......@@ -613,3 +618,53 @@ TEST_F(PageCappingObserverTest, DataSavingsHistogramWhenResumed) {
NavigateToUntrackedUrl();
histogram_tester.ExpectTotalCount("HeavyPageCapping.RecordedDataSavings", 0);
}
TEST_F(PageCappingObserverTest, FuzzingOffset) {
std::map<std::string, std::string> feature_parameters = {
{"MediaPageCapMiB", "1"},
{"PageCapMiB", "1"},
{"PageTypicalLargePageMiB", "2"}};
base::test::ScopedFeatureList scoped_feature_list_;
scoped_feature_list_.InitAndEnableFeatureWithParameters(
data_use_measurement::page_load_capping::features::kDetectingHeavyPages,
feature_parameters);
fuzzing_offset_ = 1;
SetUpTest();
base::HistogramTester histogram_tester;
// A resource of 1 MB.
page_load_metrics::ExtraRequestCompleteInfo resource = {
GURL(kTestURL),
net::HostPortPair(),
-1 /* frame_tree_node_id */,
false /* was_cached */,
(1 * 1024 * 1024) /* raw_body_bytes */,
0 /* original_network_content_length */,
nullptr,
content::ResourceType::RESOURCE_TYPE_SCRIPT,
0,
{} /* load_timing_info */};
// This should not trigger an infobar as the non-media cap is not met.
SimulateLoadedResource(resource);
EXPECT_EQ(0u, InfoBarCount());
// A resource of 1 KB.
page_load_metrics::ExtraRequestCompleteInfo resource2 = {
GURL(kTestURL),
net::HostPortPair(),
-1 /* frame_tree_node_id */,
false /* was_cached */,
(1 * 1024) /* raw_body_bytes */,
0 /* original_network_content_length */,
nullptr,
content::ResourceType::RESOURCE_TYPE_SCRIPT,
0,
{} /* load_timing_info */};
// This should trigger an InfoBar as the non-media cap is met.
SimulateLoadedResource(resource2);
EXPECT_EQ(1u, InfoBarCount());
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment