Commit f9c54ec3 authored by haozhe's avatar haozhe Committed by Commit Bot

Support getAnimations() for ShadowRoot

This patch makes Webanimation to support getAnimations() whose target
element is a shadow root on which this method is called.

Spec: https://drafts.csswg.org/web-animations/#extensions-to-the-documentorshadowroot-interface-mixin

Bug: 1046916
Change-Id: Ibb201fe3a8a21f3852d4f5135ce344238b1476c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2051768
Commit-Queue: Hao Sheng <haozhes@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Reviewed-by: default avatarKevin Ellis <kevers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#749222}
parent 68f2e87b
......@@ -2525,6 +2525,8 @@ enum WebFeature {
kQuicTransport = 3184,
kQuicTransportStreamApis = 3185,
kQuicTransportDatagramApis = 3186,
kV8Document_GetAnimations_Method = 3187,
kV8ShadowRoot_GetAnimations_Method = 3188,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
......
......@@ -105,7 +105,8 @@ HeapVector<Member<Animation>> Animatable::getAnimations(
return animations;
for (const auto& animation :
element->GetDocument().GetDocumentAnimations().getAnimations()) {
element->GetDocument().GetDocumentAnimations().getAnimations(
element->GetTreeScope())) {
DCHECK(animation->effect());
// TODO(gtsteel) make this use the idl properties
Element* target = To<KeyframeEffect>(animation->effect())->EffectTarget();
......
......@@ -19,10 +19,6 @@ class DocumentAnimation {
static DocumentTimeline* timeline(Document& document) {
return &document.Timeline();
}
static HeapVector<Member<Animation>> getAnimations(Document& document) {
return document.GetDocumentAnimations().getAnimations();
}
};
} // namespace blink
......
......@@ -9,6 +9,4 @@
RuntimeEnabled=WebAnimationsAPI
] partial interface Document {
readonly attribute DocumentTimeline timeline;
sequence<Animation> getAnimations();
};
......@@ -121,7 +121,8 @@ void DocumentAnimations::UpdateAnimations(
timeline->ScheduleNextService();
}
HeapVector<Member<Animation>> DocumentAnimations::getAnimations() {
HeapVector<Member<Animation>> DocumentAnimations::getAnimations(
const TreeScope& tree_scope) {
// This method implements the Document::getAnimations method defined in the
// web-animations-1 spec.
// https://drafts.csswg.org/web-animations-1/#dom-document-getanimations
......@@ -130,9 +131,9 @@ HeapVector<Member<Animation>> DocumentAnimations::getAnimations() {
document_->UpdateStyleAndLayoutTree();
HeapVector<Member<Animation>> animations;
if (document_->GetPage())
animations = document_->GetPage()->Animator().GetAnimations(document_);
animations = document_->GetPage()->Animator().GetAnimations(tree_scope);
else
GetAnimationsTargetingDocument(document_, animations);
GetAnimationsTargetingTreeScope(animations, tree_scope);
std::sort(animations.begin(), animations.end(), CompareAnimations);
return animations;
......@@ -143,9 +144,9 @@ void DocumentAnimations::Trace(Visitor* visitor) {
visitor->Trace(timelines_);
}
void DocumentAnimations::GetAnimationsTargetingDocument(
Document* document_,
HeapVector<Member<Animation>>& animations) {
void DocumentAnimations::GetAnimationsTargetingTreeScope(
HeapVector<Member<Animation>>& animations,
const TreeScope& tree_scope) {
// This method follows the timelines in a given docmuent and append all the
// animations to the reference animations.
for (auto& timeline : timelines_) {
......@@ -156,13 +157,12 @@ void DocumentAnimations::GetAnimationsTargetingDocument(
!animation->effect()->IsInEffect())) {
continue;
}
if (auto* effect = DynamicTo<KeyframeEffect>(animation->effect())) {
Element* target = effect->target();
if (!target || !target->isConnected() ||
document_ != target->GetDocument()) {
continue;
}
}
auto* effect = DynamicTo<KeyframeEffect>(animation->effect());
Element* target = effect->target();
if (!target || !target->isConnected())
continue;
if (&tree_scope != &target->GetTreeScope())
continue;
animations.push_back(animation);
}
}
......
......@@ -51,8 +51,8 @@ class CORE_EXPORT DocumentAnimations final
void UpdateAnimationTimingForAnimationFrame();
bool NeedsAnimationTimingUpdate();
void UpdateAnimationTimingIfNeeded();
void GetAnimationsTargetingDocument(Document*,
HeapVector<Member<Animation>>&);
void GetAnimationsTargetingTreeScope(HeapVector<Member<Animation>>&,
const TreeScope&);
// Updates existing animations as part of generating a new (document
// lifecycle) frame. Note that this considers and updates state for
......@@ -61,7 +61,7 @@ class CORE_EXPORT DocumentAnimations final
DocumentLifecycle::LifecycleState required_lifecycle_state,
const PaintArtifactCompositor* paint_artifact_compositor);
HeapVector<Member<Animation>> getAnimations();
HeapVector<Member<Animation>> getAnimations(const TreeScope&);
void Trace(Visitor*);
private:
......
......@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_OR_SHADOW_ROOT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_OR_SHADOW_ROOT_H_
#include "third_party/blink/renderer/core/animation/document_animation.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
......@@ -50,6 +51,15 @@ class DocumentOrShadowRoot {
return tree_scope.GetSelection();
}
static HeapVector<Member<Animation>> getAnimations(Document& document) {
return document.GetDocumentAnimations().getAnimations(document);
}
static HeapVector<Member<Animation>> getAnimations(ShadowRoot& shadow_root) {
return shadow_root.GetDocument().GetDocumentAnimations().getAnimations(
shadow_root);
}
static Element* elementFromPoint(TreeScope& tree_scope, double x, double y) {
return tree_scope.ElementFromPoint(x, y);
}
......
......@@ -10,6 +10,9 @@
// Selection API
// https://w3c.github.io/selection-api/#extensions-to-document-interface
[Affects=Nothing] Selection? getSelection();
// Web-Animation-API
//https://drafts.csswg.org/web-animations/#extensions-to-the-documentorshadowroot-interface-mixin
[RuntimeEnabled=WebAnimationsAPI, Measure] sequence<Animation> getAnimations();
// CSSOM View Module
// https://drafts.csswg.org/cssom-view/#extensions-to-the-document-interface
Element? elementFromPoint(double x, double y);
......
......@@ -182,13 +182,13 @@ void PageAnimator::UpdateHitTestOcclusionData(LocalFrame& root_frame) {
}
}
HeapVector<Member<Animation>> PageAnimator::GetAnimations(Document* document_) {
HeapVector<Member<Animation>> PageAnimator::GetAnimations(
const TreeScope& tree_scope) {
HeapVector<Member<Animation>> animations;
DocumentsVector documents = GetAllDocuments(page_->MainFrame());
for (auto& document : documents) {
document->GetDocumentAnimations().GetAnimationsTargetingDocument(
document_, animations);
document->GetDocumentAnimations().GetAnimationsTargetingTreeScope(
animations, tree_scope);
}
return animations;
}
......
......@@ -17,6 +17,7 @@ namespace blink {
class LocalFrame;
class Page;
class TreeScope;
class CORE_EXPORT PageAnimator final : public GarbageCollected<PageAnimator> {
public:
......@@ -44,7 +45,7 @@ class CORE_EXPORT PageAnimator final : public GarbageCollected<PageAnimator> {
void UpdateLifecycleToLayoutClean(LocalFrame& root_frame,
DocumentUpdateReason reason);
AnimationClock& Clock() { return animation_clock_; }
HeapVector<Member<Animation>> GetAnimations(Document*);
HeapVector<Member<Animation>> GetAnimations(const TreeScope&);
private:
void UpdateHitTestOcclusionData(LocalFrame& root_frame);
......
......@@ -78,7 +78,8 @@ TEST_P(ValidationMessageOverlayDelegateTest,
To<LocalFrame>(delegate_ptr->GetPageForTesting()->MainFrame())
->GetDocument();
HeapVector<Member<Animation>> animations =
internal_document->GetDocumentAnimations().getAnimations();
internal_document->GetDocumentAnimations().getAnimations(
*internal_document);
ASSERT_FALSE(animations.IsEmpty());
for (const auto& animation : animations) {
......
This is a testharness.js-based test.
PASS Document.getAnimations() returns an empty sequence for non-animated content
PASS Document.getAnimations() returns script-generated animations
PASS Document.getAnimations() returns script-generated animations in the order they were created
PASS Document.getAnimations() does not return a disconnected node
PASS Document.getAnimations() does not return an animation with a null target
PASS Document.getAnimations() returns animations on elements inside same-origin iframes
PASS iframe.contentDocument.getAnimations() returns animations on elements inside same-origin Document
FAIL ShadowRoot.getAnimations() return all animations in the shadow tree div.shadowRoot.getAnimations is not a function
FAIL Document.getAnimations() does NOT return animations in shadow trees assert_array_equals: getAnimations() called on Document does not return animations from shadow trees lengths differ, expected array [] length 0, got [object "[object Animation]"] length 1
PASS Document.getAnimations() triggers a style change event
Harness: the test ran to completion.
......@@ -188,6 +188,20 @@ test(t => {
);
}, 'Document.getAnimations() does NOT return animations in shadow trees');
test(t => {
const div = createDiv(t);
const shadow = div.attachShadow({ mode: 'open' });
div.animate(gKeyFrames, 100 * MS_PER_SEC)
assert_array_equals(
div.shadowRoot.getAnimations(),
[],
'getAnimations() called on ShadowRoot does not return animations from'
+ ' Document'
);
}, 'ShadowRoot.getAnimations() does NOT return animations in parent document');
promise_test(async t => {
const div = createDiv(t);
const watcher = EventWatcher(t, div, 'transitionrun');
......
......@@ -8035,6 +8035,7 @@ interface ShadowRoot : DocumentFragment
method constructor
method elementFromPoint
method elementsFromPoint
method getAnimations
method getSelection
setter adoptedStyleSheets
setter fullscreenElement
......
......@@ -26784,6 +26784,8 @@ Called by update_use_counter_feature_enum.py.-->
<int value="3184" label="QuicTransport"/>
<int value="3185" label="QuicTransportStreamApis"/>
<int value="3186" label="QuicTransportDatagramApis"/>
<int value="3187" label="V8Document_GetAnimations_Method"/>
<int value="3188" label="V8ShadowRoot_GetAnimations_Method"/>
</enum>
<enum name="FeaturePolicyAllowlistType">
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