Commit d225483d authored by Fadi Meawad's avatar Fadi Meawad Committed by Commit Bot

[PageLifecycle] Restrict network activities during onfreeze callback

Only fetch(request, {keepalive: true}) is allowed as it is
guaranteed to be delivered even if the renderer gets discarded.

Bug: chromium:838684
Change-Id: I2966a7f9365ff8ab97a4a8cfc20b8df8c3e96561
Reviewed-on: https://chromium-review.googlesource.com/1038343Reviewed-by: default avatarNate Chapin <japhet@chromium.org>
Commit-Queue: Fadi Meawad <fmeawad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558042}
parent aa3626ec
......@@ -625,6 +625,7 @@ Document::Document(const DocumentInit& initializer,
css_target_(nullptr),
was_discarded_(false),
load_event_progress_(kLoadEventCompleted),
is_freezing_in_progress_(false),
start_time_(CurrentTime()),
script_runner_(ScriptRunner::Create(this)),
xml_version_("1.0"),
......@@ -3521,6 +3522,18 @@ void Document::DispatchUnloadEvents() {
RemoveAllEventListenersRecursively();
}
void Document::DispatchFreezeEvent() {
DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled());
const double freeze_event_start = CurrentTimeTicksInSeconds();
SetFreezingInProgress(true);
DispatchEvent(Event::Create(EventTypeNames::freeze));
SetFreezingInProgress(false);
const double freeze_event_end = CurrentTimeTicksInSeconds();
DEFINE_STATIC_LOCAL(CustomCountHistogram, freeze_histogram,
("DocumentEventTiming.FreezeDuration", 0, 10000000, 50));
freeze_histogram.Count((freeze_event_end - freeze_event_start) * 1000000.0);
}
Document::PageDismissalType Document::PageDismissalEventBeingDispatched()
const {
switch (load_event_progress_) {
......
......@@ -624,6 +624,8 @@ class CORE_EXPORT Document : public ContainerNode,
bool& did_allow_navigation);
void DispatchUnloadEvents();
void DispatchFreezeEvent();
enum PageDismissalType {
kNoDismissal,
kBeforeUnloadDismissal,
......@@ -730,6 +732,8 @@ class CORE_EXPORT Document : public ContainerNode,
void SetReadyState(DocumentReadyState);
bool IsLoadCompleted() const;
bool IsFreezingInProgress() const { return is_freezing_in_progress_; };
enum ParsingState { kParsing, kInDOMContentLoaded, kFinishedParsing };
void SetParsingState(ParsingState);
bool Parsing() const { return parsing_state_ == kParsing; }
......@@ -1422,6 +1426,8 @@ class CORE_EXPORT Document : public ContainerNode,
friend class IgnoreDestructiveWriteCountIncrementer;
friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
friend class NthIndexCache;
FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest,
DuringOnFreeze);
class NetworkStateObserver;
bool IsDocumentFragment() const =
......@@ -1531,6 +1537,10 @@ class CORE_EXPORT Document : public ContainerNode,
// the LocalFrameClient.
void ApplyFeaturePolicy(const ParsedFeaturePolicy& declared_policy);
void SetFreezingInProgress(bool is_freezing_in_progress) {
is_freezing_in_progress_ = is_freezing_in_progress;
};
DocumentLifecycle lifecycle_;
bool has_nodes_with_placeholder_style_;
......@@ -1650,6 +1660,8 @@ class CORE_EXPORT Document : public ContainerNode,
LoadEventProgress load_event_progress_;
bool is_freezing_in_progress_;
double start_time_;
TraceWrapperMember<ScriptRunner> script_runner_;
......
......@@ -532,13 +532,7 @@ void LocalFrame::DidChangeVisibilityState() {
void LocalFrame::DidFreeze() {
DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled());
if (GetDocument()) {
const double freeze_event_start = CurrentTimeTicksInSeconds();
GetDocument()->DispatchEvent(Event::Create(EventTypeNames::freeze));
const double freeze_event_end = CurrentTimeTicksInSeconds();
DEFINE_STATIC_LOCAL(
CustomCountHistogram, freeze_histogram,
("DocumentEventTiming.FreezeDuration", 0, 10000000, 50));
freeze_histogram.Count((freeze_event_end - freeze_event_start) * 1000000.0);
GetDocument()->DispatchFreezeEvent();
// TODO(fmeawad): Move the following logic to the page once we have a
// PageResourceCoordinator in Blink. http://crbug.com/838415
if (auto* frame_resource_coordinator = GetFrameResourceCoordinator()) {
......
......@@ -1443,4 +1443,24 @@ ResourceLoadPriority FrameFetchContext::ModifyPriorityForExperiments(
return ResourceLoadPriority::kLowest;
}
ResourceRequestBlockedReason FrameFetchContext::CanRequest(
Resource::Type type,
const ResourceRequest& resource_request,
const KURL& url,
const ResourceLoaderOptions& options,
SecurityViolationReportingPolicy reporting_policy,
FetchParameters::OriginRestriction origin_restriction,
ResourceRequest::RedirectStatus redirect_status) const {
if (document_ && document_->IsFreezingInProgress() &&
!resource_request.GetKeepalive()) {
AddErrorConsoleMessage(
"Only fetch keepalive is allowed during onfreeze: " + url.GetString(),
kJSSource);
return ResourceRequestBlockedReason::kOther;
}
return BaseFetchContext::CanRequest(type, resource_request, url, options,
reporting_policy, origin_restriction,
redirect_status);
}
} // namespace blink
......@@ -78,6 +78,14 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
void AddAdditionalRequestHeaders(ResourceRequest&,
FetchResourceType) override;
ResourceRequestBlockedReason CanRequest(
Resource::Type type,
const ResourceRequest& resource_request,
const KURL& url,
const ResourceLoaderOptions& options,
SecurityViolationReportingPolicy reporting_policy,
FetchParameters::OriginRestriction origin_restriction,
ResourceRequest::RedirectStatus redirect_status) const override;
mojom::FetchCacheMode ResourceRequestCachePolicy(
const ResourceRequest&,
Resource::Type,
......
......@@ -213,6 +213,11 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
return CanRequestInternal(SecurityViolationReportingPolicy::kReport);
}
ResourceRequestBlockedReason CanRequestKeepAlive() {
return CanRequestInternal(SecurityViolationReportingPolicy::kReport,
true /* keepalive */);
}
ResourceRequestBlockedReason CanRequestPreload() {
return CanRequestInternal(
SecurityViolationReportingPolicy::kSuppressReporting);
......@@ -250,11 +255,13 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
private:
ResourceRequestBlockedReason CanRequestInternal(
SecurityViolationReportingPolicy reporting_policy) {
SecurityViolationReportingPolicy reporting_policy,
bool keepalive = false) {
const KURL input_url("http://example.com/");
ResourceRequest resource_request(input_url);
resource_request.SetFetchCredentialsMode(
network::mojom::FetchCredentialsMode::kOmit);
resource_request.SetKeepalive(keepalive);
ResourceLoaderOptions options;
return fetch_context->CanRequest(
Resource::kImage, resource_request, input_url, options,
......@@ -1307,6 +1314,16 @@ TEST_F(FrameFetchContextSubresourceFilterTest, Allow) {
EXPECT_EQ(0, GetFilteredLoadCallCount());
}
TEST_F(FrameFetchContextSubresourceFilterTest, DuringOnFreeze) {
document->SetFreezingInProgress(true);
// Only keepalive requests should succeed during onfreeze.
EXPECT_EQ(ResourceRequestBlockedReason::kOther, CanRequest());
EXPECT_EQ(ResourceRequestBlockedReason::kNone, CanRequestKeepAlive());
document->SetFreezingInProgress(false);
EXPECT_EQ(ResourceRequestBlockedReason::kNone, CanRequest());
EXPECT_EQ(ResourceRequestBlockedReason::kNone, CanRequestKeepAlive());
}
TEST_F(FrameFetchContextSubresourceFilterTest, WouldDisallow) {
SetFilterPolicy(WebDocumentSubresourceFilter::kWouldDisallow);
......
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