Commit db032cf0 authored by Kevin Ellis's avatar Kevin Ellis Committed by Chromium LUCI CQ

Test for persistent execution context during Animatable::animate.

Prior to the patch, the validity of the execution context was only
checked on entry to the method; however, the execution context can
be invalidated during the course of parsing keyframes or options.
The parsing of options is upstream of Animatable::animate and caught by
the existing check, but invalidation during keyframe parsing could fall
through triggering a crash.

Bug: 1161739
Change-Id: Ic0fc927d1d6ce902592bf92261fd4c506e96afac
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2636213
Commit-Queue: Kevin Ellis <kevers@chromium.org>
Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844622}
parent 710bae69
...@@ -73,6 +73,11 @@ Animation* Animatable::animate( ...@@ -73,6 +73,11 @@ Animation* Animatable::animate(
if (exception_state.HadException()) if (exception_state.HadException())
return nullptr; return nullptr;
// Creation of the keyframe effect parses JavaScript, which could result
// in destruction of the execution context. Recheck that it is still valid.
if (!element->GetExecutionContext())
return nullptr;
ReportFeaturePolicyViolationsIfNecessary(*element->GetExecutionContext(), ReportFeaturePolicyViolationsIfNecessary(*element->GetExecutionContext(),
*effect->Model()); *effect->Model());
if (!options.IsKeyframeAnimationOptions()) if (!options.IsKeyframeAnimationOptions())
...@@ -90,6 +95,9 @@ Animation* Animatable::animate( ...@@ -90,6 +95,9 @@ Animation* Animatable::animate(
nullptr, exception_state); nullptr, exception_state);
} }
if (!animation)
return nullptr;
animation->setId(options_dict->id()); animation->setId(options_dict->id());
return animation; return animation;
} }
......
<!DOCTYPE html>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<body></body>
<script>
test(function() {
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const element = iframe.contentDocument.createElement("div");
const keyframes = [];
keyframes.__defineGetter__(0,()=>{
document.body.removeChild(iframe);
return { transform: 'translate3D(0, -300px, 0)' };
});
const animation = element.animate(keyframes, {
duration: 3000,
iterations: Infinity,
timeline: null
});
assert_equals(animation, null);
}, "Check that removing a parent iframe during keyframe parsing " +
"doesn't crash");
test(function() {
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const element = iframe.contentDocument.createElement("div");
const options = {
iterations: Infinity,
timeline: null
};
let getterCalled = false;
options.__defineGetter__('duration', () => {
document.body.removeChild(iframe);
getterCalled = true;
return 3000;
});
assert_false(getterCalled);
const animation = element.animate(
{ transform: 'translate3D(0, -300px, 0)' }, options);
assert_true(getterCalled);
assert_equals(animation, null);
}, "Check that removing a parent iframe during options parsing " +
"doesn't crash");
</script>
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