Commit 02995c14 authored by Ryan Sturm's avatar Ryan Sturm Committed by Commit Bot

Dismiss the heavy page capping UI when network has stopped

This CL adds logic to dismiss the heavy page capping InfoBar after 8
seconds of no requests being finished on the page. The actual time is
field trial configurable. This also adds a browser test to check this
behavior.

Bug: 888817
Change-Id: I7332918b4590f2f8cd70db365af8dce60f26956c
Reviewed-on: https://chromium-review.googlesource.com/1242173Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Reviewed-by: default avatarTarun Bansal <tbansal@chromium.org>
Commit-Queue: Ryan Sturm <ryansturm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#594831}
parent d6699ff3
......@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
......@@ -25,6 +26,7 @@
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_delegate.h"
#include "components/infobars/core/infobar_manager.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browsing_data_remover.h"
......@@ -44,6 +46,26 @@ namespace {
const base::FilePath::CharType kDocRoot[] =
FILE_PATH_LITERAL("chrome/test/data/data_use_measurement");
const char kImagePrefix[] = "/image";
class TestInfoBarObserver : public infobars::InfoBarManager::Observer {
public:
explicit TestInfoBarObserver(base::RunLoop* run_loop) : run_loop_(run_loop) {}
~TestInfoBarObserver() override {}
void OnInfoBarAdded(infobars::InfoBar* infobar) override {}
void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override {
run_loop_->QuitWhenIdle();
}
void OnInfoBarReplaced(infobars::InfoBar* old_infobar,
infobars::InfoBar* new_infobar) override {}
void OnManagerShuttingDown(infobars::InfoBarManager* manager) override {
NOTREACHED();
}
private:
base::RunLoop* run_loop_;
};
} // namespace
class PageLoadCappingBrowserTest : public InProcessBrowserTest {
......@@ -51,8 +73,10 @@ class PageLoadCappingBrowserTest : public InProcessBrowserTest {
PageLoadCappingBrowserTest()
: https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
~PageLoadCappingBrowserTest() override {}
void PostToSelf() {
EXPECT_FALSE(waiting_);
EXPECT_FALSE(waiting_for_infobar_event_ || waiting_for_request_);
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
run_loop.QuitClosure());
......@@ -60,10 +84,22 @@ class PageLoadCappingBrowserTest : public InProcessBrowserTest {
}
void WaitForRequest() {
EXPECT_FALSE(waiting_);
waiting_ = true;
EXPECT_FALSE(waiting_for_infobar_event_ || waiting_for_request_);
waiting_for_request_ = true;
run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
run_loop_.reset();
}
void WaitForInfoBarRemoved() {
EXPECT_FALSE(waiting_for_infobar_event_ || waiting_for_request_);
waiting_for_infobar_event_ = true;
run_loop_ = std::make_unique<base::RunLoop>();
TestInfoBarObserver test_observer(run_loop_.get());
InfoBarService::FromWebContents(contents())->AddObserver(&test_observer);
run_loop_->Run();
InfoBarService::FromWebContents(contents())->RemoveObserver(&test_observer);
waiting_for_infobar_event_ = false;
run_loop_.reset();
}
......@@ -115,7 +151,10 @@ class PageLoadCappingBrowserTest : public InProcessBrowserTest {
std::map<std::string, std::string> feature_parameters = {
{"PageCapMiB", "0"},
{"PageFuzzingKiB", "0"},
{"OptOutStoreDisabled", "true"}};
{"OptOutStoreDisabled", "true"},
{"InfoBarTimeoutInMilliseconds", "500000"}};
ChangeParams(&feature_parameters);
base::FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
"TrialName1", "GroupName1", feature_parameters);
......@@ -134,6 +173,8 @@ class PageLoadCappingBrowserTest : public InProcessBrowserTest {
InProcessBrowserTest::SetUp();
}
virtual void ChangeParams(std::map<std::string, std::string>* params) {}
std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
const net::test_server::HttpRequest& request) {
// Check if this matches the image requests from the test suite.
......@@ -149,16 +190,17 @@ class PageLoadCappingBrowserTest : public InProcessBrowserTest {
std::unique_ptr<net::test_server::BasicHttpResponse> not_found_response =
std::make_unique<net::test_server::BasicHttpResponse>();
not_found_response->set_code(net::HTTP_NOT_FOUND);
if (waiting_) {
if (waiting_for_request_) {
run_loop_->QuitWhenIdle();
waiting_ = false;
waiting_for_request_ = false;
}
return not_found_response;
}
net::EmbeddedTestServer https_test_server_;
size_t images_attempted_ = 0u;
bool waiting_ = false;
bool waiting_for_request_ = false;
bool waiting_for_infobar_event_ = false;
std::unique_ptr<base::RunLoop> run_loop_;
base::test::ScopedFeatureList scoped_feature_list_;
......@@ -429,3 +471,42 @@ IN_PROC_BROWSER_TEST_F(PageLoadCappingBrowserTest, DataSaverOffTest) {
EXPECT_EQ(0u, InfoBarCount());
}
class PageLoadCappingBrowserTestDismissAfterNetworkUse
: public PageLoadCappingBrowserTest {
public:
PageLoadCappingBrowserTestDismissAfterNetworkUse() {}
~PageLoadCappingBrowserTestDismissAfterNetworkUse() override {}
void ChangeParams(std::map<std::string, std::string>* params) override {
(*params)["InfoBarTimeoutInMilliseconds"] = "50";
}
};
IN_PROC_BROWSER_TEST_F(PageLoadCappingBrowserTestDismissAfterNetworkUse,
TestInfoBarDismiss) {
// Verifies the InfoBar dismisses shortly (5ms) after the last resource is
// loaded.
EnableDataSaver(true);
base::HistogramTester histogram_tester;
// Load a page and ignore the InfoBar.
NavigateToHeavyPage();
// Verify the InfoBar was shown (it might be dismissed already by the
// InfoBarTimeout logic).
histogram_tester.ExpectBucketCount("HeavyPageCapping.InfoBarInteraction", 0,
1);
bool is_dismissed = histogram_tester.GetBucketCount(
"HeavyPageCapping.InfoBarInteraction", 3) > 0;
if (!is_dismissed) {
ASSERT_EQ(1u, InfoBarCount());
WaitForInfoBarRemoved();
}
histogram_tester.ExpectBucketCount("HeavyPageCapping.InfoBarInteraction", 3,
1);
ASSERT_EQ(0u, InfoBarCount());
}
......@@ -6,6 +6,7 @@
#include <memory>
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "chrome/browser/android/android_theme_resources.h"
......@@ -29,7 +30,9 @@ class ResumeDelegate : public PageLoadCappingInfoBarDelegate {
// |pause_callback| will either pause subresource loading or resume it based
// on the passed in bool.
explicit ResumeDelegate(const PauseCallback& pause_callback)
: pause_callback_(pause_callback) {}
: pause_callback_(pause_callback) {
DCHECK(!pause_callback_.is_null());
}
~ResumeDelegate() override = default;
private:
......@@ -42,8 +45,6 @@ class ResumeDelegate : public PageLoadCappingInfoBarDelegate {
}
bool LinkClicked(WindowOpenDisposition disposition) override {
RecordInteractionUMA(InfoBarInteraction::kResumedPage);
if (pause_callback_.is_null())
return true;
// Pass false to resume subresource loading.
pause_callback_.Run(false);
return true;
......@@ -51,7 +52,7 @@ class ResumeDelegate : public PageLoadCappingInfoBarDelegate {
// |pause_callback| will either pause subresource loading or resume it based
// on the passed in bool.
PauseCallback pause_callback_;
const PauseCallback pause_callback_;
DISALLOW_COPY_AND_ASSIGN(ResumeDelegate);
};
......@@ -59,14 +60,26 @@ class ResumeDelegate : public PageLoadCappingInfoBarDelegate {
// The infobar that allows the user to pause resoruce loading on the page.
class PauseDelegate : public PageLoadCappingInfoBarDelegate {
public:
// This object is destroyed wqhen the page is terminated, and methods related
// to functionality of the infobar (E.g., LinkClicked()), are not called from
// This object is destroyed when the page is terminated, and methods related
// to functionality of the InfoBar (E.g., LinkClicked()), are not called from
// page destructors. This object is also destroyed on all non-same page
// navigations.
// |pause_callback| is a callback that will pause subresource loading on the
// page.
explicit PauseDelegate(const PauseCallback& pause_callback)
: pause_callback_(pause_callback) {}
// |time_to_expire_callback| is used to get the earliest time at which the
// page is considered to have stopped using data.
explicit PauseDelegate(const PauseCallback& pause_callback,
const TimeToExpireCallback& time_to_expire_callback)
: pause_callback_(pause_callback),
time_to_expire_callback_(time_to_expire_callback),
weak_factory_(this) {
// When creating the InfoBar, it should not already be expired.
DCHECK(!time_to_expire_callback_.is_null());
DCHECK(!pause_callback_.is_null());
base::TimeDelta time_to_expire;
time_to_expire_callback_.Run(&time_to_expire);
RunDelayedCheck(time_to_expire);
}
~PauseDelegate() override = default;
private:
......@@ -81,10 +94,9 @@ class PauseDelegate : public PageLoadCappingInfoBarDelegate {
bool LinkClicked(WindowOpenDisposition disposition) override {
RecordInteractionUMA(InfoBarInteraction::kPausedPage);
if (!pause_callback_.is_null()) {
// Pause subresouce loading on the page.
pause_callback_.Run(true);
}
auto* infobar_manager = infobar()->owner();
// |this| will be gone after this call.
......@@ -95,10 +107,41 @@ class PauseDelegate : public PageLoadCappingInfoBarDelegate {
return false;
}
private:
void RunDelayedCheck(base::TimeDelta time_to_expire) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&PauseDelegate::ExpireIfNecessary,
weak_factory_.GetWeakPtr()),
time_to_expire);
}
void ExpireIfNecessary() {
base::TimeDelta time_to_expire;
time_to_expire_callback_.Run(&time_to_expire);
// When the owner of |time_to_expire_callback_| is deleted, or it returns a
// TimeDelta of 0, the InfoBar should be deleted. Otherwise, re-evaluate
// after |time_to_expire|.
if (time_to_expire > base::TimeDelta()) {
RunDelayedCheck(time_to_expire);
return;
}
RecordInteractionUMA(InfoBarInteraction::kDismissedByNetworkStopped);
auto* infobar_manager = infobar()->owner();
// |this| will be gone after this call.
infobar_manager->RemoveInfoBar(infobar());
}
// |pause_callback| will either pause subresource loading or resume it based
// on the passed in bool.
PauseCallback pause_callback_;
const PauseCallback pause_callback_;
// Used to get the earliest time at which the page is considered to have
// stopped using data.
const TimeToExpireCallback time_to_expire_callback_;
base::WeakPtrFactory<PauseDelegate> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PauseDelegate);
};
......@@ -108,12 +151,14 @@ class PauseDelegate : public PageLoadCappingInfoBarDelegate {
// static
bool PageLoadCappingInfoBarDelegate::Create(
content::WebContents* web_contents,
const PauseCallback& pause_callback) {
const PauseCallback& pause_callback,
const TimeToExpireCallback& time_to_expire_callback) {
auto* infobar_service = InfoBarService::FromWebContents(web_contents);
RecordInteractionUMA(InfoBarInteraction::kShowedInfoBar);
// WrapUnique is used to allow for a private constructor.
return infobar_service->AddInfoBar(infobar_service->CreateConfirmInfoBar(
std::make_unique<PauseDelegate>(pause_callback)));
return infobar_service->AddInfoBar(
infobar_service->CreateConfirmInfoBar(std::make_unique<PauseDelegate>(
pause_callback, time_to_expire_callback)));
}
PageLoadCappingInfoBarDelegate::~PageLoadCappingInfoBarDelegate() = default;
......
......@@ -34,10 +34,21 @@ class PageLoadCappingInfoBarDelegate : public ConfirmInfoBarDelegate {
// resumed based on |pause|.
using PauseCallback = base::RepeatingCallback<void(bool pause)>;
// A callback used to get the earliest possible time (offset from now) that
// the InfoBar could be dismissed based on lack of network usage.
// |time_to_expire| must be passed in as TimeDelta initialized to 0 to handle
// the case of the underlying weak pointer being destroyed.
using TimeToExpireCallback =
base::RepeatingCallback<void(base::TimeDelta* time_to_expire)>;
// Creates an InfoBar for page load capping. Returns whether the InfoBar was
// created. |web_contents| is the WebContents that caused the data usage.
// |pause_callback| is used to pause and unpause the resource loading of the
// page. |time_to_expire_callback| is used to get the earliest time at which
// the page is considered to have stopped using data.
static bool Create(content::WebContents* web_contents,
const PauseCallback& set_handles_callback);
const PauseCallback& pause_callback,
const TimeToExpireCallback& time_to_expire_callback);
~PageLoadCappingInfoBarDelegate() override;
......@@ -47,7 +58,8 @@ class PageLoadCappingInfoBarDelegate : public ConfirmInfoBarDelegate {
kShowedInfoBar = 0,
kPausedPage = 1,
kResumedPage = 2,
kMaxValue = kResumedPage,
kDismissedByNetworkStopped = 3,
kMaxValue = kDismissedByNetworkStopped,
};
protected:
......
......@@ -4,6 +4,7 @@
#include "chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.h"
#include "base/bind_helpers.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/infobars/mock_infobar_service.h"
......@@ -61,7 +62,8 @@ TEST_F(PageLoadCappingInfoBarDelegateTest, ClickingCreatesNewInfobar) {
web_contents(),
base::BindRepeating(
&PageLoadCappingInfoBarDelegateTest::PauseSubresourceLoading,
base::Unretained(this))));
base::Unretained(this)),
base::DoNothing()));
histogram_tester.ExpectUniqueSample(
"HeavyPageCapping.InfoBarInteraction",
PageLoadCappingInfoBarDelegate::InfoBarInteraction::kShowedInfoBar, 1);
......
......@@ -414,7 +414,7 @@ void InfoBarUiTest::ShowUi(const std::string& name) {
case IBD::PAGE_LOAD_CAPPING_INFOBAR_DELEGATE:
PageLoadCappingInfoBarDelegate::Create(
GetWebContents(), PageLoadCappingInfoBarDelegate::PauseCallback());
GetWebContents(), base::DoNothing(), base::DoNothing());
break;
case IBD::BLOATED_RENDERER_INFOBAR_DELEGATE:
......
......@@ -12,6 +12,7 @@
#include "base/optional.h"
#include "base/rand_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/default_tick_clock.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_blacklist.h"
#include "chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.h"
......@@ -39,6 +40,8 @@ const char kPageTypical[] = "PageTypicalLargePageMiB";
const char kPageFuzzing[] = "PageFuzzingKiB";
const char kInfoBarTimeoutInMilliseconds[] = "InfoBarTimeoutInMilliseconds";
// 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.
......@@ -77,10 +80,18 @@ int64_t GetEstimatedSavings(int64_t network_bytes,
return std::max<int64_t>((typical_size - network_bytes), 0);
}
base::TimeDelta GetPageLoadCappingTimeout() {
return base::TimeDelta::FromMilliseconds(
base::GetFieldTrialParamByFeatureAsInt(
data_use_measurement::page_load_capping::features::
kDetectingHeavyPages,
kInfoBarTimeoutInMilliseconds, 8000));
}
} // namespace
PageCappingPageLoadMetricsObserver::PageCappingPageLoadMetricsObserver()
: weak_factory_(this) {}
: clock_(base::DefaultTickClock::GetInstance()), weak_factory_(this) {}
PageCappingPageLoadMetricsObserver::~PageCappingPageLoadMetricsObserver() {}
page_load_metrics::PageLoadMetricsObserver::ObservePolicy
......@@ -101,6 +112,7 @@ PageCappingPageLoadMetricsObserver::OnCommit(
void PageCappingPageLoadMetricsObserver::OnLoadedResource(
const page_load_metrics::ExtraRequestCompleteInfo&
extra_request_complete_info) {
last_request_complete_time_ = clock_->NowTicks();
if (extra_request_complete_info.was_cached)
return;
network_bytes_ += extra_request_complete_info.raw_body_bytes;
......@@ -116,21 +128,25 @@ void PageCappingPageLoadMetricsObserver::MaybeCreate() {
if (!web_contents_)
return;
// If there is no capping threshold, the threshold or the threshold is not
// met, do not show an InfoBar. Use the fuzzing offset to increase the number
// of bytes needed.
// If there is no capping threshold or the threshold is not 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;
if (IsBlacklisted())
return;
if (PageLoadCappingInfoBarDelegate::Create(
// Set the state preemptively in case one of the callbacks is called
// synchronously, if the InfoBar is not created, set it back.
page_capping_state_ = PageCappingState::kInfoBarShown;
if (!PageLoadCappingInfoBarDelegate::Create(
web_contents_,
base::BindRepeating(
&PageCappingPageLoadMetricsObserver::PauseSubresourceLoading,
weak_factory_.GetWeakPtr()))) {
page_capping_state_ = PageCappingState::kInfoBarShown;
weak_factory_.GetWeakPtr()),
base::BindRepeating(&PageCappingPageLoadMetricsObserver::TimeToExpire,
weak_factory_.GetWeakPtr()))) {
page_capping_state_ = PageCappingState::kInfoBarNotShown;
}
}
......@@ -333,3 +349,22 @@ PageCappingPageLoadMetricsObserver::GetPageLoadCappingBlacklist() const {
return page_capping_service->page_load_capping_blacklist();
}
void PageCappingPageLoadMetricsObserver::TimeToExpire(
base::TimeDelta* time_to_expire) const {
DCHECK(time_to_expire);
DCHECK_EQ(*time_to_expire, base::TimeDelta());
DCHECK_EQ(PageCappingState::kInfoBarShown, page_capping_state_);
DCHECK(last_request_complete_time_);
auto expiration_time =
(last_request_complete_time_.value() + GetPageLoadCappingTimeout());
if (expiration_time < clock_->NowTicks())
return;
*time_to_expire = expiration_time - clock_->NowTicks();
}
void PageCappingPageLoadMetricsObserver::SetTickClockForTesting(
base::TickClock* clock) {
clock_ = clock;
}
......@@ -5,12 +5,15 @@
#ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_PAGE_CAPPING_PAGE_LOAD_METRICS_OBSERVER_H_
#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_PAGE_CAPPING_PAGE_LOAD_METRICS_OBSERVER_H_
#include <memory>
#include <vector>
#include <stdint.h>
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
......@@ -39,6 +42,10 @@ class PageCappingPageLoadMetricsObserver
// Returns whether the page's subresource loading is currently paused.
bool IsPausedForTesting() const;
// Tests can change the behavior of clock for testing time between resource
// loads.
void SetTickClockForTesting(base::TickClock* clock);
// The current state of the page.
// This class operates as a state machine going from each of the below states
// in order. This is recorded to UKM, so the enum should not be changed.
......@@ -112,6 +119,15 @@ class PageCappingPageLoadMetricsObserver
// load resources. https://crbug.com/835895
void PauseSubresourceLoading(bool paused);
// Sets |time_to_expire| to the earliest time duration that the page load is
// considered not to be using data anymore. |time_to_expire| must be passed in
// as TimeDelta initialized to 0 to handle the case of the underlying weak
// pointer being destroyed.
// If |time_to_expire| is returned as 0, the consumer should treat the page as
// not using data anymore, and does not need to wait any longer to consider
// the page stopped with respect to data use..
void TimeToExpire(base::TimeDelta* time_to_expire) const;
// The current bytes threshold of the capping page triggering.
base::Optional<int64_t> page_cap_;
......@@ -149,6 +165,11 @@ class PageCappingPageLoadMetricsObserver
// render frames of this page.
std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr> handles_;
base::Optional<base::TimeTicks> last_request_complete_time_;
// Default clock unless SetClockForTesting is called.
const base::TickClock* clock_;
base::WeakPtrFactory<PageCappingPageLoadMetricsObserver> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PageCappingPageLoadMetricsObserver);
......
......@@ -10,6 +10,7 @@
#include "base/callback.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/default_clock.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_blacklist.h"
......@@ -52,12 +53,17 @@ class TestPageCappingPageLoadMetricsObserver
: public PageCappingPageLoadMetricsObserver {
public:
using SizeUpdateCallback = base::RepeatingCallback<void(int64_t)>;
TestPageCappingPageLoadMetricsObserver(int64_t fuzzing_offset,
PageLoadCappingBlacklist* blacklist,
const SizeUpdateCallback& callback)
TestPageCappingPageLoadMetricsObserver(
int64_t fuzzing_offset,
PageLoadCappingBlacklist* blacklist,
std::unique_ptr<base::SimpleTestTickClock> simple_test_tick_clock,
const SizeUpdateCallback& callback)
: fuzzing_offset_(fuzzing_offset),
blacklist_(blacklist),
size_callback_(callback) {}
simple_test_tick_clock_(std::move(simple_test_tick_clock)),
size_callback_(callback) {
SetTickClockForTesting(simple_test_tick_clock_.get());
}
~TestPageCappingPageLoadMetricsObserver() override {}
void WriteToSavings(int64_t bytes_saved) override {
......@@ -73,6 +79,7 @@ class TestPageCappingPageLoadMetricsObserver
private:
int64_t fuzzing_offset_;
PageLoadCappingBlacklist* blacklist_;
std::unique_ptr<base::SimpleTestTickClock> simple_test_tick_clock_;
SizeUpdateCallback size_callback_;
};
......@@ -126,9 +133,11 @@ class PageCappingObserverTest
void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override {
auto observer = std::make_unique<TestPageCappingPageLoadMetricsObserver>(
fuzzing_offset_, test_blacklist_.get(),
std::make_unique<base::SimpleTestTickClock>(),
base::BindRepeating(&PageCappingObserverTest::UpdateSavings,
base::Unretained(this)));
observer_ = observer.get();
// Keep the clock frozen.
tracker->AddObserver(std::move(observer));
}
......
......@@ -24191,6 +24191,9 @@ Called by update_gpu_driver_bug_workaround_entries.py.-->
<int value="2" label="Resumed">
The user clicked the InfoBar again resuming subresource loading.
</int>
<int value="3" label="Network Usage Stopped">
The InfoBar was dismissed because the network usage on the page stopped.
</int>
</enum>
<enum name="HIDContinueScenarioType">
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