Skip to content

Commit

Permalink
Add ForceLoadAtTop DocumentPolicy
Browse files Browse the repository at this point in the history
Add a document policy that lets pages opt out of scrolling that
automatically happens on page load. This provides an opt-out to the
Scroll To Text feature (see bug and [1]), but also applies to fragment
scrolls and scroll restoration.

With the DocumentPolicy feature[2] enabled, pages can opt out of these
types of scrolling by adding the HTTP header:
Document-Policy: force-load-at-top

[1] WICG/scroll-to-text-fragment#80
[2] https://github.com/w3c/webappsec-feature-policy/blob/master/document-policy-explainer.md

Bug: 1047900
Change-Id: Iebba7fd24fa2e362bfa4a8f77903763b5d95b787
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2073138
Commit-Queue: Nick Burris <nburris@chromium.org>
Reviewed-by: Ian Clelland <iclelland@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Reviewed-by: David Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748465}
  • Loading branch information
Nick Burris authored and Commit Bot committed Mar 10, 2020
1 parent cbd4502 commit 3c290e0
Show file tree
Hide file tree
Showing 7 changed files with 351 additions and 18 deletions.
322 changes: 312 additions & 10 deletions content/browser/navigation_browsertest.cc

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions third_party/blink/common/feature_policy/document_policy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ bool DocumentPolicy::IsFeatureSupported(
switch (feature) {
case mojom::DocumentPolicyFeature::kFontDisplay:
case mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages:
case mojom::DocumentPolicyFeature::kForceLoadAtTop:
return true;
default:
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ enum DocumentPolicyFeature {
kFontDisplay = 1,
// When disallowed, these policies require images to have a reasonable byte-to-pixel ratio.
kUnoptimizedLosslessImages = 2,
// Controls whether the browser should allow navigations that cause the page to scroll.
kForceLoadAtTop = 3,
// Don't change assigned numbers of any item, and don't reuse removed slots.
// Add new features at the end of the enum.
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// which gets parsed from the header or the policy attribute.
document_policy_name: {},
value_name: {},
// value type allowed in mojom::PolicyValueType which is defined in
// value type allowed in mojom::PolicyValueType which is defined in
// third_party/blink/public/mojom/feature_policy/policy_value.mojom.
value_type: {},
// valid c++ expression strings, e.g. true/false, 1.0, -1.
Expand Down Expand Up @@ -46,5 +46,16 @@
default_value: "max",
depends_on: ["UnoptimizedImagePolicies"],
},
{
// The ForceLoadAtTop policy lets pages opt-out of scrolling that
// automatically happens on page load. This includes fragment scrolls,
// text fragment scrolls (i.e. this provides an opt-out for the Scroll To
// Text feature), and scroll restoration.
name: "ForceLoadAtTop",
document_policy_name: "force-load-at-top",
value_name: "",
value_type: "Bool",
default_value: "false",
},
],
}
8 changes: 8 additions & 0 deletions third_party/blink/renderer/core/loader/document_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ DocumentLoader::DocumentLoader(
frame_policy_ = params_->frame_policy.value_or(FramePolicy());

document_policy_ = CreateDocumentPolicy();

// If the document is blocked by document policy, there won't be content
// in the sub-frametree, thus no need to initialize required_policy for
// subtree.
Expand Down Expand Up @@ -1488,6 +1489,13 @@ void DocumentLoader::InstallNewDocument(
if (!RuntimeEnabledFeatures::DocumentPolicyEnabled(owner_document))
document_policy_ = DocumentPolicy::FeatureState{};

if (document_policy_.contains(
mojom::blink::DocumentPolicyFeature::kForceLoadAtTop)) {
navigation_scroll_allowed_ =
!(document_policy_[mojom::blink::DocumentPolicyFeature::kForceLoadAtTop]
.BoolValue());
}

DocumentInit init =
DocumentInit::Create()
.WithDocumentLoader(this)
Expand Down
5 changes: 5 additions & 0 deletions third_party/blink/renderer/core/loader/document_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,8 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
return last_same_document_navigation_was_browser_initiated_;
}

bool NavigationScrollAllowed() const { return navigation_scroll_allowed_; }

protected:
Vector<KURL> redirect_chain_;

Expand Down Expand Up @@ -551,6 +553,9 @@ class CORE_EXPORT DocumentLoader : public GarbageCollected<DocumentLoader>,
// Whether this load request is a result of a browser initiated same-document
// navigation.
bool last_same_document_navigation_was_browser_initiated_ = false;

// Whether the document can be scrolled on load
bool navigation_scroll_allowed_ = true;
};

DECLARE_WEAK_IDENTIFIER_MAP(DocumentLoader);
Expand Down
18 changes: 11 additions & 7 deletions third_party/blink/renderer/core/loader/frame_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,8 @@ void FrameLoader::CommitDocumentLoader(
void FrameLoader::RestoreScrollPositionAndViewState() {
if (!frame_->GetPage() || !GetDocumentLoader() ||
!GetDocumentLoader()->GetHistoryItem() ||
!GetDocumentLoader()->GetHistoryItem()->GetViewState()) {
!GetDocumentLoader()->GetHistoryItem()->GetViewState() ||
!GetDocumentLoader()->NavigationScrollAllowed()) {
return;
}
RestoreScrollPositionAndViewState(
Expand Down Expand Up @@ -1307,12 +1308,15 @@ void FrameLoader::ProcessFragment(const KURL& url,
// restoration type is manual, then we should not override it unless this
// is a same document reload.
bool should_scroll_to_fragment =
(load_start_type == kNavigationWithinSameDocument &&
!IsBackForwardLoadType(frame_load_type)) ||
(!GetDocumentLoader()->GetInitialScrollState().did_restore_from_history &&
!(GetDocumentLoader()->GetHistoryItem() &&
GetDocumentLoader()->GetHistoryItem()->ScrollRestorationType() ==
kScrollRestorationManual));
GetDocumentLoader()->NavigationScrollAllowed() &&
((load_start_type == kNavigationWithinSameDocument &&
!IsBackForwardLoadType(frame_load_type)) ||
(!GetDocumentLoader()
->GetInitialScrollState()
.did_restore_from_history &&
!(GetDocumentLoader()->GetHistoryItem() &&
GetDocumentLoader()->GetHistoryItem()->ScrollRestorationType() ==
kScrollRestorationManual)));

view->ProcessUrlFragment(url,
load_start_type == kNavigationWithinSameDocument,
Expand Down

0 comments on commit 3c290e0

Please sign in to comment.