Skip to content

Commit

Permalink
view-transition: Implement more opt-in CSSOM
Browse files Browse the repository at this point in the history
This CL implements the @view-transitions rule's navigation trigger
setter so that it may be used from JavaScript.

Bug: 1463966
Change-Id: Ia506cb8ae9c997da91837df7c8515cc57bd036cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4938961
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Commit-Queue: David Bokan <bokan@chromium.org>
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1211548}
  • Loading branch information
bokand authored and Chromium LUCI CQ committed Oct 18, 2023
1 parent 5beee05 commit a8ce39d
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 18 deletions.
39 changes: 36 additions & 3 deletions third_party/blink/renderer/core/css/css_view_transitions_rule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@

#include "third_party/blink/renderer/core/css/css_view_transitions_rule.h"

#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_rule.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/style_rule_view_transitions.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"

namespace blink {
Expand Down Expand Up @@ -41,9 +49,34 @@ String CSSViewTransitionsRule::navigationTrigger() const {
return String();
}

void CSSViewTransitionsRule::setNavigationTrigger(const ExecutionContext*,
const String&) {
// TODO(crbug.com/1463966): Implement
void CSSViewTransitionsRule::setNavigationTrigger(
const ExecutionContext* execution_context,
const String& text) {
CSSStyleSheet* style_sheet = parentStyleSheet();
auto& context = *MakeGarbageCollected<CSSParserContext>(
ParserContext(execution_context->GetSecureContextMode()), style_sheet);
CSSTokenizer tokenizer(text);
auto tokens = tokenizer.TokenizeToEOF();
CSSParserTokenRange token_range(tokens);
AtRuleDescriptorID descriptor_id = AtRuleDescriptorID::NavigationTrigger;
CSSValue* new_value =
AtRuleDescriptorParser::ParseAtViewTransitionsDescriptor(
descriptor_id, token_range, context);
if (!new_value) {
return;
}

const auto* id = DynamicTo<CSSIdentifierValue>(new_value);
if (!id || (id->GetValueID() != CSSValueID::kCrossDocumentSameOrigin &&
id->GetValueID() != CSSValueID::kNone)) {
return;
}

view_transitions_rule_->SetNavigationTrigger(new_value);

if (Document* document = style_sheet->OwnerDocument()) {
document->GetStyleEngine().UpdateViewTransitionsOptIn();
}
}

void CSSViewTransitionsRule::Reattach(StyleRuleBase* rule) {
Expand Down
32 changes: 18 additions & 14 deletions third_party/blink/renderer/core/css/style_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,23 @@ RuleSet* StyleEngine::DefaultViewTransitionStyle() const {
CSSDefaultStyleSheets::ScreenEval());
}

void StyleEngine::UpdateViewTransitionsOptIn() {
bool cross_document_enabled = false;

// TODO(https://crbug.com/1463966): This will likely need to change to a
// CSSValueList if we want to support multiple tokens as a trigger.
if (view_transitions_rule_) {
if (const CSSValue* value =
view_transitions_rule_->GetNavigationTrigger()) {
cross_document_enabled = To<CSSIdentifierValue>(value)->GetValueID() ==
CSSValueID::kCrossDocumentSameOrigin;
}
}

ViewTransitionSupplement::From(GetDocument())
->OnViewTransitionsStyleUpdated(cross_document_enabled);
}

bool StyleEngine::HasRulesForId(const AtomicString& id) const {
DCHECK(global_rule_set_);
return global_rule_set_->GetRuleFeatureSet().HasSelectorForId(id);
Expand Down Expand Up @@ -3019,20 +3036,7 @@ void StyleEngine::AddViewTransitionsRules(
}
}

bool cross_document_enabled = false;

// TODO(https://crbug.com/1463966): This will likely need to change to a
// CSSValueList if we want to support multiple tokens as a trigger.
if (view_transitions_rule_) {
if (const CSSValue* value =
view_transitions_rule_->GetNavigationTrigger()) {
cross_document_enabled = To<CSSIdentifierValue>(value)->GetValueID() ==
CSSValueID::kCrossDocumentSameOrigin;
}
}

ViewTransitionSupplement::From(GetDocument())
->OnViewTransitionsStyleUpdated(cross_document_enabled);
UpdateViewTransitionsOptIn();
}

void StyleEngine::AddFontPaletteValuesRules(const RuleSet& rule_set) {
Expand Down
1 change: 1 addition & 0 deletions third_party/blink/renderer/core/css/style_engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
const char* NameInHeapSnapshot() const override { return "StyleEngine"; }

RuleSet* DefaultViewTransitionStyle() const;
void UpdateViewTransitionsOptIn();

const ActiveStyleSheetVector& ActiveUserStyleSheets() const {
return active_user_style_sheets_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "base/auto_reset.h"
#include "base/memory/values_equivalent.h"
#include "third_party/blink/renderer/core/css/cascade_layer.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"

namespace blink {
Expand All @@ -26,6 +27,10 @@ const CSSValue* StyleRuleViewTransitions::GetNavigationTrigger() const {
return navigation_trigger_.Get();
}

void StyleRuleViewTransitions::SetNavigationTrigger(const CSSValue* new_value) {
navigation_trigger_ = new_value;
}

void StyleRuleViewTransitions::TraceAfterDispatch(
blink::Visitor* visitor) const {
visitor->Trace(layer_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_RULE_VIEW_TRANSITIONS_H_

#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/parser/at_rule_descriptors.h"
#include "third_party/blink/renderer/core/css/style_rule.h"

namespace blink {
Expand All @@ -18,6 +17,7 @@ class CORE_EXPORT StyleRuleViewTransitions : public StyleRuleBase {
~StyleRuleViewTransitions();

const CSSValue* GetNavigationTrigger() const;
void SetNavigationTrigger(const CSSValue* new_value);

StyleRuleViewTransitions* Copy() const {
return MakeGarbageCollected<StyleRuleViewTransitions>(*this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,31 @@
assert_equals(rule.cssText, "@view-transitions { }");
});
}, "navigation-trigger with !important flag should fail to parse.");

test(function () {
resetStateAndTest(() => {
document.styleSheets[0].insertRule(`
@view-transitions {
navigation-trigger: none;
}
`);
let rule = document.styleSheets[0].cssRules[0];
rule.navigationTrigger = "cross-document-same-origin";
assert_equals(rule.navigationTrigger, "cross-document-same-origin");
});
}, "navigation-trigger attribute can be set.");

test(function () {
resetStateAndTest(() => {
document.styleSheets[0].insertRule(`
@view-transitions {
navigation-trigger: none;
}
`);
let rule = document.styleSheets[0].cssRules[0];
rule.navigationTrigger = "foo";
assert_equals(rule.navigationTrigger, "none");
});
}, "navigation-trigger doesn't set invalid token.");

</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!DOCTYPE html>
<title>View Transitions: @view-transitions opt-in programmatically.</title>
<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
<link rel="author" href="mailto:bokan@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
@view-transitions {
navigation-trigger: none;
}
</style>
<script>
function optIn() {
document.styleSheets[0].cssRules[0].navigationTrigger = 'cross-document-same-origin';
}
const params = new URLSearchParams(location.search);
const is_new_page = params.has('new');

if (!is_new_page) {
onload = () => requestAnimationFrame(() => requestAnimationFrame(() => {
optIn();
location.replace(location.href + '?new');
}));
} else {
promise_test(() => {
optIn();
return new Promise((resolve) => {
addEventListener('pagereveal', resolve);
}).then(event => {
assert_not_equals(event.viewTransition, null,
"ViewTransition must be triggered.");
});
});
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<title>View Transitions: @view-transitions opt-out programmatically.</title>
<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
<link rel="author" href="mailto:bokan@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
@view-transitions {
navigation-trigger: cross-document-same-origin;
}
</style>
<script>
const params = new URLSearchParams(location.search);
const is_new_page = params.has('new');

if (!is_new_page) {
onload = () => requestAnimationFrame(() => requestAnimationFrame(() => {
document.styleSheets[0].rules[0].navigationTrigger = 'none';
location.replace(location.href + '?new');
}));
} else {
promise_test(() => {
return new Promise((resolve) => {
addEventListener('pagereveal', resolve);
}).then(event => {
assert_equals(event.viewTransition, null,
"ViewTransition must not be triggered.");
});
});
}
</script>

0 comments on commit a8ce39d

Please sign in to comment.