import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1212720 - Part 1: Implement Document.getAnimations(). r=heycam, r=smaug (8c3951b318)
- Bug 1212720 - Part 2: Tests for document.getAnimations. r=heycam (8e6660abe1)
- Bug 1212720 - Part 3: Remove AnimationTimeline.getAnimations. r=heycam, r=smaug (a663e7e79b)
- Bug 1212720 - Part 4: Remove all cancelAllAnimationsOnEnd. It is not needed any more. r=bbirtles (8c9b92f2d4)
- Bug 1218258 - Fix -Wimplicit-fallthrough warnings in toolkit/components/downloads. r=paolo (1962eee4fc)
- Bug 1218258 - Fix -Wshadow warnings in toolkit/components/downloads. r=paolo (6cf1d464bb)
- Bug 1212323: P1. Use a 640x360 SPS to test for HW decoding support. r=cpearce (ed67910d9c)
- Bug 1212323: P2. Have IsVideoAccelerated return a Promise. r=cpearce (824e543945)
- Bug 1240365 - FileReader should use the global scope correctly in ChromeWorkers, r=smaug, r=khuey (bf40380947)
- Bug 1239210 - Don't process WebIDL files when not compiling; r=glandium (5a55f23b2e)
This commit is contained in:
2023-11-08 16:50:37 +08:00
parent 19b122873d
commit 0ccb78c213
27 changed files with 280 additions and 191 deletions
-42
View File
@@ -34,48 +34,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationTimeline)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
void
AnimationTimeline::GetAnimations(AnimationSequence& aAnimations)
{
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mWindow);
if (mWindow) {
nsIDocument* doc = window->GetDoc();
if (doc) {
doc->FlushPendingNotifications(Flush_Style);
}
}
aAnimations.SetCapacity(mAnimations.Count());
for (Animation* animation = mAnimationOrder.getFirst(); animation;
animation = animation->getNext()) {
// Skip animations which are no longer relevant or which have been
// associated with another timeline. These animations will be removed
// on the next tick.
if (!animation->IsRelevant() || animation->GetTimeline() != this) {
continue;
}
// Bug 1174575: Until we implement a suitable PseudoElement interface we
// don't have anything to return for the |target| attribute of
// KeyframeEffect(ReadOnly) objects that refer to pseudo-elements.
// Rather than return some half-baked version of these objects (e.g.
// we a null effect attribute) we simply don't provide access to animations
// whose effect refers to a pseudo-element until we can support them
// properly.
Element* target;
nsCSSPseudoElements::Type pseudoType;
animation->GetEffect()->GetTarget(target, pseudoType);
if (pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
aAnimations.AppendElement(animation);
}
}
// Sort animations by priority
aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
}
void
AnimationTimeline::NotifyAnimationUpdated(Animation& aAnimation)
{
-3
View File
@@ -51,11 +51,8 @@ public:
nsIGlobalObject* GetParentObject() const { return mWindow; }
typedef nsTArray<RefPtr<Animation>> AnimationSequence;
// AnimationTimeline methods
virtual Nullable<TimeDuration> GetCurrentTime() const = 0;
void GetAnimations(AnimationSequence& aAnimations);
// Wrapper functions for AnimationTimeline DOM methods when called from
// script.
@@ -24,7 +24,7 @@
'use strict';
test(function(t) {
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'getAnimations returns an empty sequence for a document'
+ ' with no animations');
}, 'getAnimations for non-animated content');
@@ -34,17 +34,17 @@ test(function(t) {
// Add an animation
div.style.animation = 'animLeft 100s';
assert_equals(document.timeline.getAnimations().length, 1,
assert_equals(document.getAnimations().length, 1,
'getAnimations returns a running CSS Animation');
// Add another animation
div.style.animation = 'animLeft 100s, animTop 100s';
assert_equals(document.timeline.getAnimations().length, 2,
assert_equals(document.getAnimations().length, 2,
'getAnimations returns two running CSS Animations');
// Remove both
div.style.animation = '';
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'getAnimations returns no running CSS Animations');
}, 'getAnimations for CSS Animations');
@@ -53,7 +53,7 @@ test(function(t) {
div.style.animation = 'animLeft 100s, animTop 100s, animRight 100s, ' +
'animBottom 100s';
var animations = document.timeline.getAnimations();
var animations = document.getAnimations();
assert_equals(animations.length, 4,
'getAnimations returns all running CSS Animations');
assert_equals(animations[0].animationName, 'animLeft',
@@ -72,7 +72,7 @@ test(function(t) {
var div3 = addDiv(t, { style: 'animation: animLeft 100s' });
var div4 = addDiv(t, { style: 'animation: animLeft 100s' });
var animations = document.timeline.getAnimations();
var animations = document.getAnimations();
assert_equals(animations.length, 4,
'getAnimations returns all running CSS Animations');
assert_equals(animations[0].effect.target, div1,
@@ -95,7 +95,7 @@ test(function(t) {
// Which should give: 2, 1, 4, 3
div2.appendChild(div1);
div2.appendChild(div4);
animations = document.timeline.getAnimations();
animations = document.getAnimations();
assert_equals(animations[0].effect.target, div2,
'Order of first animation returned after tree surgery');
assert_equals(animations[1].effect.target, div1,
@@ -114,7 +114,7 @@ test(function(t) {
var expectedResults = [ [ div1, 'animLeft' ],
[ div1, 'animTop' ],
[ div2, 'animBottom' ] ];
var animations = document.timeline.getAnimations();
var animations = document.getAnimations();
assert_equals(animations.length, expectedResults.length,
'getAnimations returns all running CSS Animations');
animations.forEach(function(anim, i) {
@@ -132,7 +132,7 @@ test(function(t) {
[ div1, 'animLeft' ],
[ div1, 'animRight' ],
[ div1, 'animTop' ] ];
animations = document.timeline.getAnimations();
animations = document.getAnimations();
assert_equals(animations.length, expectedResults.length,
'getAnimations returns all running CSS Animations after ' +
'making changes');
@@ -145,10 +145,8 @@ test(function(t) {
}, 'Order of CSS Animations - across and within elements');
test(function(t) {
cancelAllAnimationsOnEnd(t);
var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
var animLeft = document.timeline.getAnimations()[0];
var animLeft = document.getAnimations()[0];
assert_equals(animLeft.animationName, 'animLeft',
'Originally, animLeft animation comes first');
@@ -156,7 +154,7 @@ test(function(t) {
div.style.animation = 'animTop 100s';
animLeft.play();
var animations = document.timeline.getAnimations();
var animations = document.getAnimations();
assert_equals(animations.length, 2,
'getAnimations returns markup-bound and free animations');
assert_equals(animations[0].animationName, 'animTop',
@@ -165,18 +163,16 @@ test(function(t) {
}, 'Order of CSS Animations - markup-bound vs free animations');
test(function(t) {
cancelAllAnimationsOnEnd(t);
var div = addDiv(t, { style: 'animation: animLeft 100s, animTop 100s' });
var animLeft = document.timeline.getAnimations()[0];
var animTop = document.timeline.getAnimations()[1];
var animLeft = document.getAnimations()[0];
var animTop = document.getAnimations()[1];
// Disassociate both animations from markup and restart in opposite order
div.style.animation = '';
animTop.play();
animLeft.play();
var animations = document.timeline.getAnimations();
var animations = document.getAnimations();
assert_equals(animations.length, 2,
'getAnimations returns free animations');
assert_equals(animations[0], animTop,
@@ -187,7 +183,7 @@ test(function(t) {
// Restarting an animation should have no effect
animTop.cancel();
animTop.play();
assert_equals(document.timeline.getAnimations()[0], animTop,
assert_equals(document.getAnimations()[0], animTop,
'After restarting, the ordering of free animations' +
' does not change');
}, 'Order of CSS Animations - free animations');
@@ -204,7 +200,7 @@ test(function(t) {
flushComputedStyle(div);
// Although the transition was added later, it should come first in the list
var animations = document.timeline.getAnimations();
var animations = document.getAnimations();
assert_equals(animations.length, 2,
'Both CSS animations and transitions are returned');
assert_class_string(animations[0], 'CSSTransition', 'Transition comes first');
@@ -214,38 +210,36 @@ test(function(t) {
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s forwards' });
div.getAnimations()[0].finish();
assert_equals(document.timeline.getAnimations().length, 1,
assert_equals(document.getAnimations().length, 1,
'Forwards-filling CSS animations are returned');
}, 'Finished but filling CSS Animations are returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s' });
div.getAnimations()[0].finish();
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'Non-filling finished CSS animations are not returned');
}, 'Finished but not filling CSS Animations are not returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s 100s' });
assert_equals(document.timeline.getAnimations().length, 1,
assert_equals(document.getAnimations().length, 1,
'Yet-to-start CSS animations are returned');
}, 'Yet-to-start CSS Animations are returned');
test(function(t) {
var div = addDiv(t, { style: 'animation: animLeft 100s' });
div.getAnimations()[0].cancel();
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'CSS animations cancelled by the API are not returned');
}, 'CSS Animations cancelled via the API are not returned');
test(function(t) {
cancelAllAnimationsOnEnd(t);
var div = addDiv(t, { style: 'animation: animLeft 100s' });
var anim = div.getAnimations()[0];
anim.cancel();
anim.play();
assert_equals(document.timeline.getAnimations().length, 1,
assert_equals(document.getAnimations().length, 1,
'CSS animations cancelled and restarted by the API are ' +
'returned');
}, 'CSS Animations cancelled and restarted via the API are returned');
@@ -256,7 +250,7 @@ test(function(t) {
// but we haven't implemented a PseudoElement interface to use as
// animation's target (bug 1174575) so we simply don't return these animations
// until we can support them properly.
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'CSS animations on pseudo elements are not returned');
}, 'CSS Animations targetting pseudo-elements are not returned');
@@ -9,7 +9,7 @@ setup({explicit_done: true});
SpecialPowers.pushPrefEnv(
{ "set": [["dom.animations-api.core.enabled", true]]},
function() {
window.open("file_timeline-get-animations.html");
window.open("file_document-get-animations.html");
});
</script>
</html>
@@ -6,7 +6,7 @@
'use strict';
test(function(t) {
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'getAnimations returns an empty sequence for a document'
+ ' with no animations');
}, 'getAnimations for non-animated content');
@@ -22,12 +22,12 @@ test(function(t) {
div.style.transition = 'all 100s';
div.style.left = '100px';
div.style.top = '100px';
assert_equals(document.timeline.getAnimations().length, 2,
assert_equals(document.getAnimations().length, 2,
'getAnimations returns two running CSS Transitions');
// Remove both
div.style.transitionProperty = 'none';
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'getAnimations returns no running CSS Transitions');
}, 'getAnimations for CSS Transitions');
@@ -39,7 +39,7 @@ async_test(function(t) {
var animations = div.getAnimations();
assert_equals(animations.length, 1, 'Got transition');
animations[0].finished.then(t.step_func(function() {
assert_equals(document.timeline.getAnimations().length, 0,
assert_equals(document.getAnimations().length, 0,
'No animations returned');
t.done();
}));
@@ -9,7 +9,7 @@ setup({explicit_done: true});
SpecialPowers.pushPrefEnv(
{ "set": [["dom.animations-api.core.enabled", true]]},
function() {
window.open("file_timeline-get-animations.html");
window.open("file_document-get-animations.html");
});
</script>
</html>
+8 -8
View File
@@ -32,15 +32,15 @@ support-files = css-animations/file_animation-reverse.html
support-files = css-animations/file_animation-starttime.html
[css-animations/test_cssanimation-animationname.html]
support-files = css-animations/file_cssanimation-animationname.html
[css-animations/test_keyframeeffect-getframes.html]
support-files = css-animations/file_keyframeeffect-getframes.html
[css-animations/test_document-get-animations.html]
support-files = css-animations/file_document-get-animations.html
[css-animations/test_effect-target.html]
support-files = css-animations/file_effect-target.html
[css-animations/test_element-get-animations.html]
skip-if = buildapp == 'mulet'
support-files = css-animations/file_element-get-animations.html
[css-animations/test_timeline-get-animations.html]
support-files = css-animations/file_timeline-get-animations.html
[css-animations/test_keyframeeffect-getframes.html]
support-files = css-animations/file_keyframeeffect-getframes.html
[css-transitions/test_animation-cancel.html]
support-files = css-transitions/file_animation-cancel.html
[css-transitions/test_animation-computed-timing.html]
@@ -57,15 +57,15 @@ support-files = css-transitions/file_animation-ready.html
support-files = css-transitions/file_animation-starttime.html
[css-transitions/test_csstransition-transitionproperty.html]
support-files = css-transitions/file_csstransition-transitionproperty.html
[css-transitions/test_keyframeeffect-getframes.html]
support-files = css-transitions/file_keyframeeffect-getframes.html
[css-transitions/test_document-get-animations.html]
support-files = css-transitions/file_document-get-animations.html
[css-transitions/test_effect-target.html]
support-files = css-transitions/file_effect-target.html
[css-transitions/test_element-get-animations.html]
skip-if = buildapp == 'mulet'
support-files = css-transitions/file_element-get-animations.html
[css-transitions/test_timeline-get-animations.html]
support-files = css-transitions/file_timeline-get-animations.html
[css-transitions/test_keyframeeffect-getframes.html]
support-files = css-transitions/file_keyframeeffect-getframes.html
[document-timeline/test_document-timeline.html]
support-files = document-timeline/file_document-timeline.html
[document-timeline/test_request_animation_frame.html]
-12
View File
@@ -17,18 +17,6 @@ function addDiv(t) {
return div;
}
/**
* Some tests cause animations to continue to exist even after their target
* element has been removed from the document tree. To ensure that these
* animations do not impact other tests we should cancel them when the test
* is complete.
*/
function cancelAllAnimationsOnEnd(t) {
t.add_cleanup(function() {
document.timeline.getAnimations().forEach(animation => animation.cancel());
});
}
/**
* Promise wrapper for requestAnimationFrame.
*/
+7 -2
View File
@@ -3378,6 +3378,13 @@ Element::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
doc->FlushPendingNotifications(Flush_Style);
}
GetAnimationsUnsorted(aAnimations);
aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
}
void
Element::GetAnimationsUnsorted(nsTArray<RefPtr<Animation>>& aAnimations)
{
EffectSet* effects = EffectSet::GetEffectSet(this,
nsCSSPseudoElements::ePseudo_NotPseudoElement);
if (!effects) {
@@ -3395,8 +3402,6 @@ Element::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
"effect set");
aAnimations.AppendElement(animation);
}
aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
}
NS_IMETHODIMP
+2
View File
@@ -852,7 +852,9 @@ public:
{
}
// Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
void GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations);
void GetAnimationsUnsorted(nsTArray<RefPtr<Animation>>& aAnimations);
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
+7 -25
View File
@@ -98,9 +98,9 @@ FileReader::RootResultArrayBuffer()
//FileReader constructors/initializers
FileReader::FileReader(nsPIDOMWindow* aWindow,
FileReader::FileReader(nsIGlobalObject* aGlobal,
WorkerPrivate* aWorkerPrivate)
: DOMEventTargetHelper(aWindow)
: DOMEventTargetHelper(aGlobal)
, mFileData(nullptr)
, mDataLen(0)
, mDataFormat(FILE_AS_BINARY)
@@ -114,8 +114,8 @@ FileReader::FileReader(nsPIDOMWindow* aWindow,
, mBusyCount(0)
, mWorkerPrivate(aWorkerPrivate)
{
MOZ_ASSERT_IF(!NS_IsMainThread(), mWorkerPrivate && !aWindow);
MOZ_ASSERT_IF(NS_IsMainThread(), !mWorkerPrivate);
MOZ_ASSERT(aGlobal);
MOZ_ASSERT(NS_IsMainThread() == !mWorkerPrivate);
SetDOMStringToNull(mResult);
}
@@ -128,8 +128,7 @@ FileReader::~FileReader()
/* static */ already_AddRefed<FileReader>
FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
{
// The owner can be null when this object is used by chrome code.
nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aGlobal.GetAsSupports());
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
WorkerPrivate* workerPrivate = nullptr;
if (!NS_IsMainThread()) {
@@ -138,14 +137,7 @@ FileReader::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
MOZ_ASSERT(workerPrivate);
}
RefPtr<FileReader> fileReader = new FileReader(owner, workerPrivate);
if (!owner && nsContentUtils::ThreadsafeIsCallerChrome()) {
// Instead of grabbing some random global from the context stack,
// let's use the default one (junk scope) for now.
// We should move away from this Init...
fileReader->BindToOwner(xpc::NativeGlobal(xpc::PrivilegedJunkScope()));
}
RefPtr<FileReader> fileReader = new FileReader(global, workerPrivate);
return fileReader.forget();
}
@@ -242,17 +234,7 @@ FileReader::DoOnLoadEnd(nsresult aStatus,
switch (mDataFormat) {
case FILE_AS_ARRAYBUFFER: {
AutoJSAPI jsapi;
nsCOMPtr<nsIGlobalObject> globalObject;
if (NS_IsMainThread()) {
globalObject = do_QueryInterface(GetParentObject());
} else {
MOZ_ASSERT(mWorkerPrivate);
MOZ_ASSERT(mBusyCount);
globalObject = mWorkerPrivate->GlobalScope();
}
if (!globalObject || !jsapi.Init(globalObject)) {
if (!jsapi.Init(GetParentObject())) {
FreeFileData();
return NS_ERROR_FAILURE;
}
+1 -1
View File
@@ -46,7 +46,7 @@ class FileReader final : public DOMEventTargetHelper,
friend class FileReaderDecreaseBusyCounter;
public:
FileReader(nsPIDOMWindow* aWindow,
FileReader(nsIGlobalObject* aGlobal,
workers::WorkerPrivate* aWorkerPrivate);
NS_DECL_ISUPPORTS_INHERITED
+19 -16
View File
@@ -107,6 +107,7 @@
#include "HTMLImageElement.h"
#include "mozilla/css/ImageLoader.h"
#include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
#include "mozilla/dom/Promise.h"
#ifdef XP_WIN
#undef GetClassName
@@ -2269,28 +2270,30 @@ nsDOMWindowUtils::GetLayerManagerRemote(bool* retval)
}
NS_IMETHODIMP
nsDOMWindowUtils::GetSupportsHardwareH264Decoding(nsAString& aRetval)
nsDOMWindowUtils::GetSupportsHardwareH264Decoding(JS::MutableHandle<JS::Value> aPromise)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(window);
NS_ENSURE_STATE(parentObject);
#ifdef MOZ_FMP4
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget)
return NS_ERROR_FAILURE;
NS_ENSURE_STATE(widget);
LayerManager *mgr = widget->GetLayerManager();
if (!mgr)
return NS_ERROR_FAILURE;
nsCString failureReason;
if (MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), failureReason)) {
aRetval.AssignLiteral("Yes");
} else {
aRetval.AssignLiteral("No; ");
AppendUTF8toUTF16(failureReason, aRetval);
}
NS_ENSURE_STATE(mgr);
RefPtr<Promise> promise =
MP4Decoder::IsVideoAccelerated(mgr->GetCompositorBackendType(), parentObject);
NS_ENSURE_STATE(promise);
aPromise.setObject(*promise->GetWrapper());
#else
aRetval.AssignLiteral("No; Compiled without MP4 support.");
ErrorResult rv;
RefPtr<Promise> promise = Promise::Create(parentObject, rv);
if (rv.Failed()) {
return rv.StealNSResult();
}
promise.MaybeResolve(NS_LITERAL_STRING("No; Compiled without MP4 support."));
aPromise.setObject(*promise->GetWrapper());
#endif
return NS_OK;
}
+28
View File
@@ -10,10 +10,12 @@
#include "nsDocument.h"
#include "nsIDocumentInlines.h"
#include "mozilla/AnimationComparator.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/BinarySearch.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/EffectSet.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Likely.h"
@@ -3156,6 +3158,32 @@ nsDocument::Timeline()
return mDocumentTimeline;
}
void
nsDocument::GetAnimations(nsTArray<RefPtr<Animation>>& aAnimations)
{
FlushPendingNotifications(Flush_Style);
// Bug 1174575: Until we implement a suitable PseudoElement interface we
// don't have anything to return for the |target| attribute of
// KeyframeEffect(ReadOnly) objects that refer to pseudo-elements.
// Rather than return some half-baked version of these objects (e.g.
// we a null effect attribute) we simply don't provide access to animations
// whose effect refers to a pseudo-element until we can support them
// properly.
for (nsIContent* node = nsINode::GetFirstChild();
node;
node = node->GetNextNode(this)) {
if (!node->IsElement()) {
continue;
}
node->AsElement()->GetAnimationsUnsorted(aAnimations);
}
// Sort animations by priority
aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
}
/* Return true if the document is in the focused top-level window, and is an
* ancestor of the focused DOMWindow. */
NS_IMETHODIMP
+2
View File
@@ -759,6 +759,8 @@ public:
static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
virtual mozilla::dom::DocumentTimeline* Timeline() override;
virtual void GetAnimations(
nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override;
virtual nsresult SetSubDocumentFor(Element* aContent,
nsIDocument* aSubDoc) override;
+4
View File
@@ -104,6 +104,7 @@ class Rule;
} // namespace css
namespace dom {
class Animation;
class AnonymousContent;
class Attr;
class BoxObject;
@@ -2201,6 +2202,9 @@ public:
virtual mozilla::dom::DocumentTimeline* Timeline() = 0;
virtual void GetAnimations(
nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) = 0;
nsresult ScheduleFrameRequestCallback(mozilla::dom::FrameRequestCallback& aCallback,
int32_t *aHandle);
void CancelFrameRequestCallback(int32_t aHandle);
+4
View File
@@ -4,6 +4,8 @@
webidl_base := $(topsrcdir)/dom/webidl
ifdef COMPILE_ENVIRONMENT
# Generated by moz.build
include webidlsrcs.mk
@@ -55,6 +57,8 @@ codegen.pp: $(codegen_dependencies)
compiletests:
$(call SUBMAKE,libs,test)
endif
GARBAGE += \
codegen.pp \
codegen.json \
+5 -4
View File
@@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(ca6a458c-82e7-4979-886e-6d214eac6f0b)]
[scriptable, uuid(46b44e33-13c2-4eb3-bf80-76a4e0857ccc)]
interface nsIDOMWindowUtils : nsISupports {
/**
@@ -1327,11 +1327,12 @@ interface nsIDOMWindowUtils : nsISupports {
readonly attribute boolean layerManagerRemote;
/**
* True if we can initialize a hardware-backed h264 decoder for a simple
* test video, does not mean that all h264 video decoding will be done
* Returns a Promise that will be resolved with a string once the capabilities
* of the h264 decoder have been determined.
* Success does not mean that all h264 video decoding will be done
* in hardware.
*/
readonly attribute AString supportsHardwareH264Decoding;
readonly attribute jsval supportsHardwareH264Decoding;
/**
* Record (and return) frame-intervals for frames which were presented
+81 -18
View File
@@ -188,23 +188,46 @@ MP4Decoder::IsEnabled()
return Preferences::GetBool("media.mp4.enabled");
}
// sTestH264ExtraData represents the content of the avcC atom found in
// an AVC1 h264 video. It contains the H264 SPS and PPS NAL.
// the structure of the avcC atom is as follow:
// write(0x1); // version, always 1
// write(sps[0].data[1]); // profile
// write(sps[0].data[2]); // compatibility
// write(sps[0].data[3]); // level
// write(0xFC | 3); // reserved (6 bits), NULA length size - 1 (2 bits)
// write(0xE0 | 1); // reserved (3 bits), num of SPS (5 bits)
// write_word(sps[0].size); // 2 bytes for length of SPS
// for(size_t i=0 ; i < sps[0].size ; ++i)
// write(sps[0].data[i]); // data of SPS
// write(&b, pps.size()); // num of PPS
// for(size_t i=0 ; i < pps.size() ; ++i) {
// write_word(pps[i].size); // 2 bytes for length of PPS
// for(size_t j=0 ; j < pps[i].size ; ++j)
// write(pps[i].data[j]); // data of PPS
// }
// }
// here we have a h264 Baseline, 640x360
// We use a 640x360 extradata, as some video framework (Apple VT) will never
// attempt to use hardware decoding for small videos.
static const uint8_t sTestH264ExtraData[] = {
0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64,
0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03,
0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96,
0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0
0x01, 0x42, 0xc0, 0x1e, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x42,
0xc0, 0x1e, 0xbb, 0x40, 0x50, 0x17, 0xfc, 0xb8, 0x08, 0x80,
0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, 0xb5, 0x07, 0x8b, 0x17,
0x50, 0x01, 0x00, 0x04, 0x68, 0xce, 0x32, 0xc8
};
static already_AddRefed<MediaDataDecoder>
CreateTestH264Decoder(layers::LayersBackend aBackend,
VideoInfo& aConfig)
VideoInfo& aConfig,
FlushableTaskQueue* aTaskQueue)
{
aConfig.mMimeType = "video/avc";
aConfig.mId = 1;
aConfig.mDuration = 40000;
aConfig.mMediaTime = 0;
aConfig.mDisplay = nsIntSize(64, 64);
aConfig.mImage = nsIntRect(0, 0, 64, 64);
aConfig.mDisplay = nsIntSize(640, 360);
aConfig.mImage = nsIntRect(0, 0, 640, 360);
aConfig.mExtraData = new MediaByteBuffer();
aConfig.mExtraData->AppendElements(sTestH264ExtraData,
MOZ_ARRAY_LENGTH(sTestH264ExtraData));
@@ -213,23 +236,63 @@ CreateTestH264Decoder(layers::LayersBackend aBackend,
RefPtr<PDMFactory> platform = new PDMFactory();
RefPtr<MediaDataDecoder> decoder(
platform->CreateDecoder(aConfig, nullptr, nullptr, aBackend, nullptr));
platform->CreateDecoder(aConfig, aTaskQueue, nullptr, aBackend, nullptr));
return decoder.forget();
}
/* static */ bool
MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsACString& aFailureReason)
/* static */ already_AddRefed<dom::Promise>
MP4Decoder::IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent)
{
VideoInfo config;
RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config));
if (!decoder) {
aFailureReason.AssignLiteral("Failed to create H264 decoder");
return false;
MOZ_ASSERT(NS_IsMainThread());
ErrorResult rv;
RefPtr<dom::Promise> promise;
promise = dom::Promise::Create(aParent, rv);
if (rv.Failed()) {
rv.SuppressException();
return nullptr;
}
bool result = decoder->IsHardwareAccelerated(aFailureReason);
decoder->Shutdown();
return result;
RefPtr<FlushableTaskQueue> taskQueue =
new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
VideoInfo config;
RefPtr<MediaDataDecoder> decoder(CreateTestH264Decoder(aBackend, config, taskQueue));
if (!decoder) {
taskQueue->BeginShutdown();
taskQueue->AwaitShutdownAndIdle();
promise->MaybeResolve(NS_LITERAL_STRING("No; Failed to create H264 decoder"));
return promise.forget();
}
decoder->Init()
->Then(AbstractThread::MainThread(), __func__,
[promise, decoder, taskQueue] (TrackInfo::TrackType aTrack) {
nsCString failureReason;
bool ok = decoder->IsHardwareAccelerated(failureReason);
nsAutoString result;
if (ok) {
result.AssignLiteral("Yes");
} else {
result.AssignLiteral("No");
if (failureReason.Length()) {
result.AppendLiteral("; ");
AppendUTF8toUTF16(failureReason, result);
}
}
decoder->Shutdown();
taskQueue->BeginShutdown();
taskQueue->AwaitShutdownAndIdle();
promise->MaybeResolve(result);
},
[promise, decoder, taskQueue] (MediaDataDecoder::DecoderFailureReason aResult) {
decoder->Shutdown();
taskQueue->BeginShutdown();
taskQueue->AwaitShutdownAndIdle();
promise->MaybeResolve(NS_LITERAL_STRING("No; Failed to initialize H264 decoder"));
});
return promise.forget();
}
void
+3 -1
View File
@@ -8,6 +8,7 @@
#include "MediaDecoder.h"
#include "MediaFormatReader.h"
#include "mozilla/dom/Promise.h"
namespace mozilla {
@@ -38,7 +39,8 @@ public:
// Returns true if the MP4 backend is preffed on.
static bool IsEnabled();
static bool IsVideoAccelerated(layers::LayersBackend aBackend, nsACString& aReason);
static already_AddRefed<dom::Promise>
IsVideoAccelerated(layers::LayersBackend aBackend, nsIGlobalObject* aParent);
void GetMozDebugReaderData(nsAString& aString) override;
-1
View File
@@ -14,5 +14,4 @@
interface AnimationTimeline {
[BinaryName="currentTimeAsDouble"]
readonly attribute double? currentTime;
sequence<Animation> getAnimations ();
};
+2
View File
@@ -310,6 +310,8 @@ partial interface Document {
partial interface Document {
[Func="nsDocument::IsWebAnimationsEnabled"]
readonly attribute DocumentTimeline timeline;
[Func="nsDocument::IsWebAnimationsEnabled"]
sequence<Animation> getAnimations();
};
// Mozilla extensions of various sorts
@@ -0,0 +1,8 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
self.onmessage = function(msg) {
var fr = new FileReader();
self.postMessage("OK");
};
@@ -0,0 +1,40 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
Components.utils.import("resource://gre/modules/Promise.jsm");
// Worker must be loaded from a chrome:// uri, not a file://
// uri, so we first need to load it.
var WORKER_SOURCE_URI = "chrome://workers/content/worker_fileReader.js";
do_load_manifest("data/chrome.manifest");
function run_test() {
run_next_test();
}
function talk_with_worker(worker) {
let deferred = Promise.defer();
worker.onmessage = function(event) {
let success = true;
if (event.data == "OK") {
deferred.resolve();
} else {
success = false;
deferred.reject(event);
}
do_check_true(success);
worker.terminate();
};
worker.onerror = function(event) {
let error = new Error(event.message, event.filename, event.lineno);
worker.terminate();
deferred.reject(error);
};
worker.postMessage("START");
return deferred.promise;
}
add_task(function test_chrome_worker() {
return talk_with_worker(new ChromeWorker(WORKER_SOURCE_URI));
});
+2
View File
@@ -4,6 +4,8 @@ tail =
skip-if = toolkit == 'android' || toolkit == 'gonk'
support-files =
data/worker.js
data/worker_fileReader.js
data/chrome.manifest
[test_workers.js]
[test_fileReader.js]
@@ -593,7 +593,7 @@ PendingLookup::GenerateWhitelistStringsForChain(
aChain.element(i).certificate().size(), getter_AddRefs(issuer));
NS_ENSURE_SUCCESS(rv, rv);
nsresult rv = GenerateWhitelistStringsForPair(signer, issuer);
rv = GenerateWhitelistStringsForPair(signer, issuer);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
@@ -703,24 +703,24 @@ PendingLookup::DoLookupInternal()
nsresult rv = mQuery->GetSourceURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
nsCString spec;
rv = GetStrippedSpec(uri, spec);
nsCString sourceSpec;
rv = GetStrippedSpec(uri, sourceSpec);
NS_ENSURE_SUCCESS(rv, rv);
mAnylistSpecs.AppendElement(spec);
mAnylistSpecs.AppendElement(sourceSpec);
ClientDownloadRequest_Resource* resource = mRequest.add_resources();
resource->set_url(spec.get());
resource->set_url(sourceSpec.get());
resource->set_type(ClientDownloadRequest::DOWNLOAD_URL);
nsCOMPtr<nsIURI> referrer = nullptr;
rv = mQuery->GetReferrerURI(getter_AddRefs(referrer));
if (referrer) {
nsCString spec;
rv = GetStrippedSpec(referrer, spec);
nsCString referrerSpec;
rv = GetStrippedSpec(referrer, referrerSpec);
NS_ENSURE_SUCCESS(rv, rv);
mAnylistSpecs.AppendElement(spec);
resource->set_referrer(spec.get());
mAnylistSpecs.AppendElement(referrerSpec);
resource->set_referrer(referrerSpec.get());
}
nsCOMPtr<nsIArray> redirects;
rv = mQuery->GetRedirects(getter_AddRefs(redirects));
@@ -787,11 +787,11 @@ PendingLookup::ParseCertificates(nsIArray* aSigArray)
NS_ENSURE_SUCCESS(rv, rv);
while (hasMoreChains) {
nsCOMPtr<nsISupports> supports;
rv = chains->GetNext(getter_AddRefs(supports));
nsCOMPtr<nsISupports> chainSupports;
rv = chains->GetNext(getter_AddRefs(chainSupports));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIX509CertList> certList = do_QueryInterface(supports, &rv);
nsCOMPtr<nsIX509CertList> certList = do_QueryInterface(chainSupports, &rv);
NS_ENSURE_SUCCESS(rv, rv);
safe_browsing::ClientDownloadRequest_CertificateChain* certChain =
@@ -804,11 +804,11 @@ PendingLookup::ParseCertificates(nsIArray* aSigArray)
bool hasMoreCerts = false;
rv = chainElt->HasMoreElements(&hasMoreCerts);
while (hasMoreCerts) {
nsCOMPtr<nsISupports> supports;
rv = chainElt->GetNext(getter_AddRefs(supports));
nsCOMPtr<nsISupports> certSupports;
rv = chainElt->GetNext(getter_AddRefs(certSupports));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIX509Cert> cert = do_QueryInterface(supports, &rv);
nsCOMPtr<nsIX509Cert> cert = do_QueryInterface(certSupports, &rv);
NS_ENSURE_SUCCESS(rv, rv);
uint8_t* data = nullptr;
@@ -494,6 +494,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to the next upgrade
MOZ_FALLTHROUGH;
case 2: // Add referrer column to the database
{
@@ -508,6 +509,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to the next upgrade
MOZ_FALLTHROUGH;
case 3: // This version adds a column to the database (entityID)
{
@@ -522,6 +524,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to the next upgrade
MOZ_FALLTHROUGH;
case 4: // This version adds a column to the database (tempPath)
{
@@ -536,6 +539,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to the next upgrade
MOZ_FALLTHROUGH;
case 5: // This version adds two columns for tracking transfer progress
{
@@ -555,6 +559,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to the next upgrade
MOZ_FALLTHROUGH;
case 6: // This version adds three columns to DB (MIME type related info)
{
@@ -579,6 +584,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to next upgrade
MOZ_FALLTHROUGH;
case 7: // This version adds a column to remember to auto-resume downloads
{
@@ -593,6 +599,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to the next upgrade
MOZ_FALLTHROUGH;
// Warning: schema versions >=8 must take into account that they can
// be operating on schemas from unknown, future versions that have
@@ -627,6 +634,7 @@ nsDownloadManager::InitFileDB()
// Extra sanity checking for developers
#ifndef DEBUG
MOZ_FALLTHROUGH;
case DM_SCHEMA_VERSION:
#endif
break;
@@ -643,6 +651,7 @@ nsDownloadManager::InitFileDB()
NS_ENSURE_SUCCESS(rv, rv);
}
// Fallthrough to downgrade check
MOZ_FALLTHROUGH;
// Downgrading
// If columns have been added to the table, we can still use the ones we
@@ -1265,17 +1274,17 @@ nsDownloadManager::GetDownloadFromDB(mozIStorageConnection* aDBConn,
if (dl->mGUID.IsEmpty()) {
rv = GenerateGUID(dl->mGUID);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStorageStatement> stmt;
nsCOMPtr<mozIStorageStatement> updateStmt;
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
"UPDATE moz_downloads SET guid = :guid "
"WHERE id = :id"),
getter_AddRefs(stmt));
getter_AddRefs(updateStmt));
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("guid"), dl->mGUID);
rv = updateStmt->BindUTF8StringByName(NS_LITERAL_CSTRING("guid"), dl->mGUID);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), dl->mID);
rv = updateStmt->BindInt64ByName(NS_LITERAL_CSTRING("id"), dl->mID);
NS_ENSURE_SUCCESS(rv, rv);
rv = stmt->Execute();
rv = updateStmt->Execute();
NS_ENSURE_SUCCESS(rv, rv);
}
@@ -1480,9 +1489,6 @@ nsDownloadManager::GetUserDownloadsDirectory(nsIFile **aResult)
case 0: // Desktop
{
nsCOMPtr<nsIFile> downloadDir;
nsCOMPtr<nsIProperties> dirService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = dirService->Get(NS_OS_DESKTOP_DIR,
NS_GET_IID(nsIFile),
getter_AddRefs(downloadDir));
@@ -1804,7 +1810,6 @@ nsDownloadManager::RetryDownload(const nsACString& aGUID)
return RetryDownload(dl);
}
NS_IMETHODIMP
nsDownloadManager::RetryDownload(uint32_t aID)
{