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, ...@@ -625,6 +625,7 @@ Document::Document(const DocumentInit& initializer,
css_target_(nullptr), css_target_(nullptr),
was_discarded_(false), was_discarded_(false),
load_event_progress_(kLoadEventCompleted), load_event_progress_(kLoadEventCompleted),
is_freezing_in_progress_(false),
start_time_(CurrentTime()), start_time_(CurrentTime()),
script_runner_(ScriptRunner::Create(this)), script_runner_(ScriptRunner::Create(this)),
xml_version_("1.0"), xml_version_("1.0"),
...@@ -3521,6 +3522,18 @@ void Document::DispatchUnloadEvents() { ...@@ -3521,6 +3522,18 @@ void Document::DispatchUnloadEvents() {
RemoveAllEventListenersRecursively(); 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() Document::PageDismissalType Document::PageDismissalEventBeingDispatched()
const { const {
switch (load_event_progress_) { switch (load_event_progress_) {
......
...@@ -624,6 +624,8 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -624,6 +624,8 @@ class CORE_EXPORT Document : public ContainerNode,
bool& did_allow_navigation); bool& did_allow_navigation);
void DispatchUnloadEvents(); void DispatchUnloadEvents();
void DispatchFreezeEvent();
enum PageDismissalType { enum PageDismissalType {
kNoDismissal, kNoDismissal,
kBeforeUnloadDismissal, kBeforeUnloadDismissal,
...@@ -730,6 +732,8 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -730,6 +732,8 @@ class CORE_EXPORT Document : public ContainerNode,
void SetReadyState(DocumentReadyState); void SetReadyState(DocumentReadyState);
bool IsLoadCompleted() const; bool IsLoadCompleted() const;
bool IsFreezingInProgress() const { return is_freezing_in_progress_; };
enum ParsingState { kParsing, kInDOMContentLoaded, kFinishedParsing }; enum ParsingState { kParsing, kInDOMContentLoaded, kFinishedParsing };
void SetParsingState(ParsingState); void SetParsingState(ParsingState);
bool Parsing() const { return parsing_state_ == kParsing; } bool Parsing() const { return parsing_state_ == kParsing; }
...@@ -1422,6 +1426,8 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -1422,6 +1426,8 @@ class CORE_EXPORT Document : public ContainerNode,
friend class IgnoreDestructiveWriteCountIncrementer; friend class IgnoreDestructiveWriteCountIncrementer;
friend class ThrowOnDynamicMarkupInsertionCountIncrementer; friend class ThrowOnDynamicMarkupInsertionCountIncrementer;
friend class NthIndexCache; friend class NthIndexCache;
FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest,
DuringOnFreeze);
class NetworkStateObserver; class NetworkStateObserver;
bool IsDocumentFragment() const = bool IsDocumentFragment() const =
...@@ -1531,6 +1537,10 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -1531,6 +1537,10 @@ class CORE_EXPORT Document : public ContainerNode,
// the LocalFrameClient. // the LocalFrameClient.
void ApplyFeaturePolicy(const ParsedFeaturePolicy& declared_policy); void ApplyFeaturePolicy(const ParsedFeaturePolicy& declared_policy);
void SetFreezingInProgress(bool is_freezing_in_progress) {
is_freezing_in_progress_ = is_freezing_in_progress;
};
DocumentLifecycle lifecycle_; DocumentLifecycle lifecycle_;
bool has_nodes_with_placeholder_style_; bool has_nodes_with_placeholder_style_;
...@@ -1650,6 +1660,8 @@ class CORE_EXPORT Document : public ContainerNode, ...@@ -1650,6 +1660,8 @@ class CORE_EXPORT Document : public ContainerNode,
LoadEventProgress load_event_progress_; LoadEventProgress load_event_progress_;
bool is_freezing_in_progress_;
double start_time_; double start_time_;
TraceWrapperMember<ScriptRunner> script_runner_; TraceWrapperMember<ScriptRunner> script_runner_;
......
...@@ -532,13 +532,7 @@ void LocalFrame::DidChangeVisibilityState() { ...@@ -532,13 +532,7 @@ void LocalFrame::DidChangeVisibilityState() {
void LocalFrame::DidFreeze() { void LocalFrame::DidFreeze() {
DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled()); DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled());
if (GetDocument()) { if (GetDocument()) {
const double freeze_event_start = CurrentTimeTicksInSeconds(); GetDocument()->DispatchFreezeEvent();
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);
// TODO(fmeawad): Move the following logic to the page once we have a // TODO(fmeawad): Move the following logic to the page once we have a
// PageResourceCoordinator in Blink. http://crbug.com/838415 // PageResourceCoordinator in Blink. http://crbug.com/838415
if (auto* frame_resource_coordinator = GetFrameResourceCoordinator()) { if (auto* frame_resource_coordinator = GetFrameResourceCoordinator()) {
......
...@@ -1443,4 +1443,24 @@ ResourceLoadPriority FrameFetchContext::ModifyPriorityForExperiments( ...@@ -1443,4 +1443,24 @@ ResourceLoadPriority FrameFetchContext::ModifyPriorityForExperiments(
return ResourceLoadPriority::kLowest; 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 } // namespace blink
...@@ -78,6 +78,14 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext { ...@@ -78,6 +78,14 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
void AddAdditionalRequestHeaders(ResourceRequest&, void AddAdditionalRequestHeaders(ResourceRequest&,
FetchResourceType) override; 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( mojom::FetchCacheMode ResourceRequestCachePolicy(
const ResourceRequest&, const ResourceRequest&,
Resource::Type, Resource::Type,
......
...@@ -213,6 +213,11 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest { ...@@ -213,6 +213,11 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
return CanRequestInternal(SecurityViolationReportingPolicy::kReport); return CanRequestInternal(SecurityViolationReportingPolicy::kReport);
} }
ResourceRequestBlockedReason CanRequestKeepAlive() {
return CanRequestInternal(SecurityViolationReportingPolicy::kReport,
true /* keepalive */);
}
ResourceRequestBlockedReason CanRequestPreload() { ResourceRequestBlockedReason CanRequestPreload() {
return CanRequestInternal( return CanRequestInternal(
SecurityViolationReportingPolicy::kSuppressReporting); SecurityViolationReportingPolicy::kSuppressReporting);
...@@ -250,11 +255,13 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest { ...@@ -250,11 +255,13 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
private: private:
ResourceRequestBlockedReason CanRequestInternal( ResourceRequestBlockedReason CanRequestInternal(
SecurityViolationReportingPolicy reporting_policy) { SecurityViolationReportingPolicy reporting_policy,
bool keepalive = false) {
const KURL input_url("http://example.com/"); const KURL input_url("http://example.com/");
ResourceRequest resource_request(input_url); ResourceRequest resource_request(input_url);
resource_request.SetFetchCredentialsMode( resource_request.SetFetchCredentialsMode(
network::mojom::FetchCredentialsMode::kOmit); network::mojom::FetchCredentialsMode::kOmit);
resource_request.SetKeepalive(keepalive);
ResourceLoaderOptions options; ResourceLoaderOptions options;
return fetch_context->CanRequest( return fetch_context->CanRequest(
Resource::kImage, resource_request, input_url, options, Resource::kImage, resource_request, input_url, options,
...@@ -1307,6 +1314,16 @@ TEST_F(FrameFetchContextSubresourceFilterTest, Allow) { ...@@ -1307,6 +1314,16 @@ TEST_F(FrameFetchContextSubresourceFilterTest, Allow) {
EXPECT_EQ(0, GetFilteredLoadCallCount()); 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) { TEST_F(FrameFetchContextSubresourceFilterTest, WouldDisallow) {
SetFilterPolicy(WebDocumentSubresourceFilter::kWouldDisallow); 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