зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team. a=merge
This commit is contained in:
Коммит
d8044bfc25
|
@ -104,8 +104,8 @@ AccReorderEvent::IsShowHideEventTarget(const Accessible* aTarget) const
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AccHideEvent::
|
AccHideEvent::
|
||||||
AccHideEvent(Accessible* aTarget, nsINode* aTargetNode, bool aNeedsShutdown) :
|
AccHideEvent(Accessible* aTarget, bool aNeedsShutdown) :
|
||||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode),
|
AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget),
|
||||||
mNeedsShutdown(aNeedsShutdown)
|
mNeedsShutdown(aNeedsShutdown)
|
||||||
{
|
{
|
||||||
mNextSibling = mAccessible->NextSibling();
|
mNextSibling = mAccessible->NextSibling();
|
||||||
|
@ -118,8 +118,8 @@ AccHideEvent::
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AccShowEvent::
|
AccShowEvent::
|
||||||
AccShowEvent(Accessible* aTarget, nsINode* aTargetNode) :
|
AccShowEvent(Accessible* aTarget) :
|
||||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget, aTargetNode)
|
AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,8 +212,7 @@ private:
|
||||||
class AccMutationEvent: public AccEvent
|
class AccMutationEvent: public AccEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AccMutationEvent(uint32_t aEventType, Accessible* aTarget,
|
AccMutationEvent(uint32_t aEventType, Accessible* aTarget) :
|
||||||
nsINode* aTargetNode) :
|
|
||||||
AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange)
|
AccEvent(aEventType, aTarget, eAutoDetect, eCoalesceMutationTextChange)
|
||||||
{
|
{
|
||||||
// Don't coalesce these since they are coalesced by reorder event. Coalesce
|
// Don't coalesce these since they are coalesced by reorder event. Coalesce
|
||||||
|
@ -250,8 +249,7 @@ protected:
|
||||||
class AccHideEvent: public AccMutationEvent
|
class AccHideEvent: public AccMutationEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AccHideEvent(Accessible* aTarget, nsINode* aTargetNode,
|
explicit AccHideEvent(Accessible* aTarget, bool aNeedsShutdown = true);
|
||||||
bool aNeedsShutdown = true);
|
|
||||||
|
|
||||||
// Event
|
// Event
|
||||||
static const EventGroup kEventGroup = eHideEvent;
|
static const EventGroup kEventGroup = eHideEvent;
|
||||||
|
@ -281,7 +279,7 @@ protected:
|
||||||
class AccShowEvent: public AccMutationEvent
|
class AccShowEvent: public AccMutationEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AccShowEvent(Accessible* aTarget, nsINode* aTargetNode);
|
explicit AccShowEvent(Accessible* aTarget);
|
||||||
|
|
||||||
// Event
|
// Event
|
||||||
static const EventGroup kEventGroup = eShowEvent;
|
static const EventGroup kEventGroup = eShowEvent;
|
||||||
|
|
|
@ -1511,7 +1511,7 @@ DocAccessible::DoInitialUpdate()
|
||||||
uint32_t childCount = ChildCount();
|
uint32_t childCount = ChildCount();
|
||||||
for (uint32_t i = 0; i < childCount; i++) {
|
for (uint32_t i = 0; i < childCount; i++) {
|
||||||
Accessible* child = GetChildAt(i);
|
Accessible* child = GetChildAt(i);
|
||||||
RefPtr<AccShowEvent> event = new AccShowEvent(child, child->GetContent());
|
RefPtr<AccShowEvent> event = new AccShowEvent(child);
|
||||||
FireDelayedEvent(event);
|
FireDelayedEvent(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1892,7 +1892,6 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
||||||
// this node already then it will be suppressed by this one.
|
// this node already then it will be suppressed by this one.
|
||||||
Accessible* focusedAcc = nullptr;
|
Accessible* focusedAcc = nullptr;
|
||||||
|
|
||||||
nsINode* node = aChild->GetNode();
|
|
||||||
if (aIsInsert) {
|
if (aIsInsert) {
|
||||||
// Create accessible tree for shown accessible.
|
// Create accessible tree for shown accessible.
|
||||||
CacheChildrenInSubtree(aChild, &focusedAcc);
|
CacheChildrenInSubtree(aChild, &focusedAcc);
|
||||||
|
@ -1914,9 +1913,9 @@ DocAccessible::UpdateTreeInternal(Accessible* aChild, bool aIsInsert,
|
||||||
// Fire show/hide event.
|
// Fire show/hide event.
|
||||||
RefPtr<AccMutationEvent> event;
|
RefPtr<AccMutationEvent> event;
|
||||||
if (aIsInsert)
|
if (aIsInsert)
|
||||||
event = new AccShowEvent(aChild, node);
|
event = new AccShowEvent(aChild);
|
||||||
else
|
else
|
||||||
event = new AccHideEvent(aChild, node);
|
event = new AccHideEvent(aChild);
|
||||||
|
|
||||||
FireDelayedEvent(event);
|
FireDelayedEvent(event);
|
||||||
aReorderEvent->AddSubMutationEvent(event);
|
aReorderEvent->AddSubMutationEvent(event);
|
||||||
|
@ -2089,8 +2088,7 @@ DocAccessible::SeizeChild(Accessible* aNewParent, Accessible* aChild,
|
||||||
int32_t oldIdxInParent = aChild->IndexInParent();
|
int32_t oldIdxInParent = aChild->IndexInParent();
|
||||||
|
|
||||||
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(oldParent);
|
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(oldParent);
|
||||||
RefPtr<AccMutationEvent> hideEvent =
|
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
|
||||||
new AccHideEvent(aChild, aChild->GetContent(), false);
|
|
||||||
reorderEvent->AddSubMutationEvent(hideEvent);
|
reorderEvent->AddSubMutationEvent(hideEvent);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -2121,8 +2119,7 @@ DocAccessible::SeizeChild(Accessible* aNewParent, Accessible* aChild,
|
||||||
FireDelayedEvent(reorderEvent);
|
FireDelayedEvent(reorderEvent);
|
||||||
|
|
||||||
reorderEvent = new AccReorderEvent(aNewParent);
|
reorderEvent = new AccReorderEvent(aNewParent);
|
||||||
RefPtr<AccMutationEvent> showEvent =
|
RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);
|
||||||
new AccShowEvent(aChild, aChild->GetContent());
|
|
||||||
reorderEvent->AddSubMutationEvent(showEvent);
|
reorderEvent->AddSubMutationEvent(showEvent);
|
||||||
|
|
||||||
FireDelayedEvent(showEvent);
|
FireDelayedEvent(showEvent);
|
||||||
|
@ -2140,8 +2137,7 @@ DocAccessible::MoveChild(Accessible* aChild, int32_t aIdxInParent)
|
||||||
|
|
||||||
Accessible* parent = aChild->Parent();
|
Accessible* parent = aChild->Parent();
|
||||||
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(parent);
|
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(parent);
|
||||||
RefPtr<AccMutationEvent> hideEvent =
|
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
|
||||||
new AccHideEvent(aChild, aChild->GetContent(), false);
|
|
||||||
reorderEvent->AddSubMutationEvent(hideEvent);
|
reorderEvent->AddSubMutationEvent(hideEvent);
|
||||||
|
|
||||||
AutoTreeMutation mut(parent);
|
AutoTreeMutation mut(parent);
|
||||||
|
@ -2152,8 +2148,7 @@ DocAccessible::MoveChild(Accessible* aChild, int32_t aIdxInParent)
|
||||||
|
|
||||||
FireDelayedEvent(hideEvent);
|
FireDelayedEvent(hideEvent);
|
||||||
|
|
||||||
RefPtr<AccMutationEvent> showEvent =
|
RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);
|
||||||
new AccShowEvent(aChild, aChild->GetContent());
|
|
||||||
reorderEvent->AddSubMutationEvent(showEvent);
|
reorderEvent->AddSubMutationEvent(showEvent);
|
||||||
FireDelayedEvent(showEvent);
|
FireDelayedEvent(showEvent);
|
||||||
|
|
||||||
|
@ -2177,8 +2172,7 @@ DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
|
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
|
||||||
RefPtr<AccMutationEvent> hideEvent =
|
RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(child, false);
|
||||||
new AccHideEvent(child, child->GetContent(), false);
|
|
||||||
reorderEvent->AddSubMutationEvent(hideEvent);
|
reorderEvent->AddSubMutationEvent(hideEvent);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -121,7 +121,7 @@ HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aDoFireEvents) {
|
if (aDoFireEvents) {
|
||||||
RefPtr<AccShowEvent> event = new AccShowEvent(area, areaContent);
|
RefPtr<AccShowEvent> event = new AccShowEvent(area);
|
||||||
mDoc->FireDelayedEvent(event);
|
mDoc->FireDelayedEvent(event);
|
||||||
reorderEvent->AddSubMutationEvent(event);
|
reorderEvent->AddSubMutationEvent(event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ HTMLLIAccessible::UpdateBullet(bool aHasBullet)
|
||||||
document->BindToDocument(mBullet, nullptr);
|
document->BindToDocument(mBullet, nullptr);
|
||||||
InsertChildAt(0, mBullet);
|
InsertChildAt(0, mBullet);
|
||||||
|
|
||||||
RefPtr<AccShowEvent> event = new AccShowEvent(mBullet, mBullet->GetContent());
|
RefPtr<AccShowEvent> event = new AccShowEvent(mBullet);
|
||||||
mDoc->FireDelayedEvent(event);
|
mDoc->FireDelayedEvent(event);
|
||||||
reorderEvent->AddSubMutationEvent(event);
|
reorderEvent->AddSubMutationEvent(event);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "16ebbfb6ce62c14573982b0aa87537ef8f857047",
|
"git_revision": "81c021654c657f6995e5e70ef02ee067d4bfedbd",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "8668ab0c480334a48e1935cce440e33dff23b33a",
|
"revision": "e651f5b571034436b7bc8eb8099033dff5623a20",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="16ebbfb6ce62c14573982b0aa87537ef8f857047"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="81c021654c657f6995e5e70ef02ee067d4bfedbd"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
|
|
@ -1014,8 +1014,6 @@ pref("browser.sessionstore.interval", 15000);
|
||||||
// on which sites to save text data, POSTDATA and cookies
|
// on which sites to save text data, POSTDATA and cookies
|
||||||
// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
|
// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
|
||||||
pref("browser.sessionstore.privacy_level", 0);
|
pref("browser.sessionstore.privacy_level", 0);
|
||||||
// the same as browser.sessionstore.privacy_level, but for saving deferred session data
|
|
||||||
pref("browser.sessionstore.privacy_level_deferred", 1);
|
|
||||||
// how many tabs can be reopened (per window)
|
// how many tabs can be reopened (per window)
|
||||||
pref("browser.sessionstore.max_tabs_undo", 10);
|
pref("browser.sessionstore.max_tabs_undo", 10);
|
||||||
// how many windows can be reopened (per session) - on non-OS X platforms this
|
// how many windows can be reopened (per session) - on non-OS X platforms this
|
||||||
|
@ -1405,8 +1403,8 @@ pref("security.insecure_password.ui.enabled", false);
|
||||||
// 1 = allow MITM for certificate pinning checks.
|
// 1 = allow MITM for certificate pinning checks.
|
||||||
pref("security.cert_pinning.enforcement_level", 1);
|
pref("security.cert_pinning.enforcement_level", 1);
|
||||||
|
|
||||||
// 2 = allow SHA-1 only before 2016-01-01
|
// 0 = allow SHA-1
|
||||||
pref("security.pki.sha1_enforcement_level", 2);
|
pref("security.pki.sha1_enforcement_level", 0);
|
||||||
|
|
||||||
// Required blocklist freshness for OneCRL OCSP bypass
|
// Required blocklist freshness for OneCRL OCSP bypass
|
||||||
// (default is 1.25x extensions.blocklist.interval, or 30 hours)
|
// (default is 1.25x extensions.blocklist.interval, or 30 hours)
|
||||||
|
@ -1502,7 +1500,8 @@ pref("media.eme.apiVisible", true);
|
||||||
|
|
||||||
// Decode using Gecko Media Plugins in <video>, if a system decoder is not
|
// Decode using Gecko Media Plugins in <video>, if a system decoder is not
|
||||||
// availble and the preferred GMP is available.
|
// availble and the preferred GMP is available.
|
||||||
pref("media.gmp.decoder.enabled", true);
|
// NOTE: Disabled until Bug 1236756 is fixed by Adobe.
|
||||||
|
pref("media.gmp.decoder.enabled", false);
|
||||||
|
|
||||||
// If decoding-via-GMP is turned on for <video>, use Adobe's GMP for decoding,
|
// If decoding-via-GMP is turned on for <video>, use Adobe's GMP for decoding,
|
||||||
// if it's available. Note: We won't fallback to another GMP if Adobe's is not
|
// if it's available. Note: We won't fallback to another GMP if Adobe's is not
|
||||||
|
|
|
@ -6132,6 +6132,16 @@
|
||||||
]]>
|
]]>
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="setUserContextId">
|
||||||
|
<parameter name="aUserContextId"/>
|
||||||
|
<body>
|
||||||
|
<![CDATA[
|
||||||
|
this.linkedBrowser.setAttribute("usercontextid", aUserContextId);
|
||||||
|
this.setAttribute("usercontextid", aUserContextId);
|
||||||
|
]]>
|
||||||
|
</body>
|
||||||
|
</method>
|
||||||
</implementation>
|
</implementation>
|
||||||
|
|
||||||
<handlers>
|
<handlers>
|
||||||
|
|
|
@ -80,8 +80,7 @@ add_task(function* test() {
|
||||||
// check each item in the title and validate it meets expectatations
|
// check each item in the title and validate it meets expectatations
|
||||||
for (let part of title) {
|
for (let part of title) {
|
||||||
let [storageMethodName, value] = part.split("=");
|
let [storageMethodName, value] = part.split("=");
|
||||||
let is_f = storageMethodName == "cookie" ? is : todo_is;
|
is(value, expectedContext,
|
||||||
is_f(value, expectedContext,
|
|
||||||
"the title reflects the expected contextual identity of " +
|
"the title reflects the expected contextual identity of " +
|
||||||
expectedContext + " for method " + storageMethodName + ": " + value);
|
expectedContext + " for method " + storageMethodName + ": " + value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivacyLevel",
|
||||||
* |url|.
|
* |url|.
|
||||||
*
|
*
|
||||||
* @param url The URL we want to save data for.
|
* @param url The URL we want to save data for.
|
||||||
* @param isPinned Whether the given |url| is contained in a pinned tab.
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function checkPrivacyLevel(url, isPinned) {
|
function checkPrivacyLevel(url) {
|
||||||
let isHttps = url.startsWith("https:");
|
let isHttps = url.startsWith("https:");
|
||||||
return PrivacyLevel.canSave({isHttps: isHttps, isPinned: isPinned});
|
return PrivacyLevel.canSave({isHttps});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,14 +36,13 @@ this.PrivacyFilter = Object.freeze({
|
||||||
* we're allowed to store.
|
* we're allowed to store.
|
||||||
*
|
*
|
||||||
* @param data The session storage data as collected from a tab.
|
* @param data The session storage data as collected from a tab.
|
||||||
* @param isPinned Whether the tab we collected from is pinned.
|
|
||||||
* @return object
|
* @return object
|
||||||
*/
|
*/
|
||||||
filterSessionStorageData: function (data, isPinned) {
|
filterSessionStorageData: function (data) {
|
||||||
let retval = {};
|
let retval = {};
|
||||||
|
|
||||||
for (let host of Object.keys(data)) {
|
for (let host of Object.keys(data)) {
|
||||||
if (checkPrivacyLevel(host, isPinned)) {
|
if (checkPrivacyLevel(host)) {
|
||||||
retval[host] = data[host];
|
retval[host] = data[host];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,14 +56,13 @@ this.PrivacyFilter = Object.freeze({
|
||||||
* allowed to store.
|
* allowed to store.
|
||||||
*
|
*
|
||||||
* @param data The form data as collected from a tab.
|
* @param data The form data as collected from a tab.
|
||||||
* @param isPinned Whether the tab we collected from is pinned.
|
|
||||||
* @return object
|
* @return object
|
||||||
*/
|
*/
|
||||||
filterFormData: function (data, isPinned) {
|
filterFormData: function (data) {
|
||||||
// If the given form data object has an associated URL that we are not
|
// If the given form data object has an associated URL that we are not
|
||||||
// allowed to store data for, bail out. We explicitly discard data for any
|
// allowed to store data for, bail out. We explicitly discard data for any
|
||||||
// children as well even if storing data for those frames would be allowed.
|
// children as well even if storing data for those frames would be allowed.
|
||||||
if (data.url && !checkPrivacyLevel(data.url, isPinned)) {
|
if (data.url && !checkPrivacyLevel(data.url)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +70,7 @@ this.PrivacyFilter = Object.freeze({
|
||||||
|
|
||||||
for (let key of Object.keys(data)) {
|
for (let key of Object.keys(data)) {
|
||||||
if (key === "children") {
|
if (key === "children") {
|
||||||
let recurse = child => this.filterFormData(child, isPinned);
|
let recurse = child => this.filterFormData(child);
|
||||||
let children = data.children.map(recurse).filter(child => child);
|
let children = data.children.map(recurse).filter(child => child);
|
||||||
|
|
||||||
if (children.length) {
|
if (children.length) {
|
||||||
|
|
|
@ -14,8 +14,7 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
|
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
|
||||||
"@mozilla.org/browser/sessionstartup;1", "nsISessionStartup");
|
"@mozilla.org/browser/sessionstartup;1", "nsISessionStartup");
|
||||||
|
|
||||||
const PREF_NORMAL = "browser.sessionstore.privacy_level";
|
const PREF = "browser.sessionstore.privacy_level";
|
||||||
const PREF_DEFERRED = "browser.sessionstore.privacy_level_deferred";
|
|
||||||
|
|
||||||
// The following constants represent the different possible privacy levels that
|
// The following constants represent the different possible privacy levels that
|
||||||
// can be set by the user and that we need to consider when collecting text
|
// can be set by the user and that we need to consider when collecting text
|
||||||
|
@ -28,25 +27,6 @@ const PRIVACY_ENCRYPTED = 1;
|
||||||
// Collect no data.
|
// Collect no data.
|
||||||
const PRIVACY_FULL = 2;
|
const PRIVACY_FULL = 2;
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the current privacy level as set by the user.
|
|
||||||
*
|
|
||||||
* @param isPinned
|
|
||||||
* Whether to return the privacy level for pinned tabs.
|
|
||||||
* @return {int} The privacy level as read from the user's preferences.
|
|
||||||
*/
|
|
||||||
function getCurrentLevel(isPinned) {
|
|
||||||
let pref = PREF_NORMAL;
|
|
||||||
|
|
||||||
// If we're in the process of quitting and we're not autoresuming the session
|
|
||||||
// then we will use the deferred privacy level for non-pinned tabs.
|
|
||||||
if (!isPinned && Services.startup.shuttingDown && !gSessionStartup.isAutomaticRestoreEnabled()) {
|
|
||||||
pref = PREF_DEFERRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Services.prefs.getIntPref(pref);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The external API as exposed by this module.
|
* The external API as exposed by this module.
|
||||||
*/
|
*/
|
||||||
|
@ -54,14 +34,13 @@ var PrivacyLevel = Object.freeze({
|
||||||
/**
|
/**
|
||||||
* Checks whether we're allowed to save data for a specific site.
|
* Checks whether we're allowed to save data for a specific site.
|
||||||
*
|
*
|
||||||
* @param {isHttps: boolean, isPinned: boolean}
|
* @param {isHttps: boolean}
|
||||||
* An object that must have two properties: 'isHttps' and 'isPinned'.
|
* An object that must have one property: 'isHttps'.
|
||||||
* 'isHttps' tells whether the site us secure communication (HTTPS).
|
* 'isHttps' tells whether the site us secure communication (HTTPS).
|
||||||
* 'isPinned' tells whether the site is loaded in a pinned tab.
|
|
||||||
* @return {bool} Whether we can save data for the specified site.
|
* @return {bool} Whether we can save data for the specified site.
|
||||||
*/
|
*/
|
||||||
canSave: function ({isHttps, isPinned}) {
|
canSave: function ({isHttps}) {
|
||||||
let level = getCurrentLevel(isPinned);
|
let level = Services.prefs.getIntPref(PREF);
|
||||||
|
|
||||||
// Never save any data when full privacy is requested.
|
// Never save any data when full privacy is requested.
|
||||||
if (level == PRIVACY_FULL) {
|
if (level == PRIVACY_FULL) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ var SessionHistoryInternal = {
|
||||||
* The docShell that owns the session history.
|
* The docShell that owns the session history.
|
||||||
*/
|
*/
|
||||||
collect: function (docShell) {
|
collect: function (docShell) {
|
||||||
let data = {entries: []};
|
let data = {entries: [], userContextId: docShell.userContextId };
|
||||||
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
|
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||||
let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
|
let history = webNavigation.sessionHistory.QueryInterface(Ci.nsISHistoryInternal);
|
||||||
|
|
||||||
|
@ -253,6 +253,10 @@ var SessionHistoryInternal = {
|
||||||
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
|
let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
|
||||||
let history = webNavigation.sessionHistory;
|
let history = webNavigation.sessionHistory;
|
||||||
|
|
||||||
|
if ("userContextId" in tabData) {
|
||||||
|
docShell.userContextId = tabData.userContextId;
|
||||||
|
}
|
||||||
|
|
||||||
if (history.count > 0) {
|
if (history.count > 0) {
|
||||||
history.PurgeHistory(history.count);
|
history.PurgeHistory(history.count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3189,6 +3189,10 @@ var SessionStoreInternal = {
|
||||||
tabbrowser.showTab(tab);
|
tabbrowser.showTab(tab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tabData.userContextId) {
|
||||||
|
tab.setUserContextId(tabData.userContextId);
|
||||||
|
}
|
||||||
|
|
||||||
if (!!tabData.muted != browser.audioMuted) {
|
if (!!tabData.muted != browser.audioMuted) {
|
||||||
tab.toggleMuteAudio();
|
tab.toggleMuteAudio();
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,15 +224,19 @@ var TabStateInternal = {
|
||||||
// Filter sensitive data according to the current privacy level.
|
// Filter sensitive data according to the current privacy level.
|
||||||
if (!includePrivateData) {
|
if (!includePrivateData) {
|
||||||
if (key === "storage") {
|
if (key === "storage") {
|
||||||
value = PrivacyFilter.filterSessionStorageData(value, isPinned);
|
value = PrivacyFilter.filterSessionStorageData(value);
|
||||||
} else if (key === "formdata") {
|
} else if (key === "formdata") {
|
||||||
value = PrivacyFilter.filterFormData(value, isPinned);
|
value = PrivacyFilter.filterFormData(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key === "history") {
|
if (key === "history") {
|
||||||
tabData.entries = value.entries;
|
tabData.entries = value.entries;
|
||||||
|
|
||||||
|
if (value.hasOwnProperty("userContextId")) {
|
||||||
|
tabData.userContextId = value.userContextId;
|
||||||
|
}
|
||||||
|
|
||||||
if (value.hasOwnProperty("index")) {
|
if (value.hasOwnProperty("index")) {
|
||||||
tabData.index = value.index;
|
tabData.index = value.index;
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,3 +219,4 @@ skip-if = os == "mac"
|
||||||
run-if = e10s
|
run-if = e10s
|
||||||
[browser_async_window_flushing.js]
|
[browser_async_window_flushing.js]
|
||||||
[browser_forget_async_closings.js]
|
[browser_forget_async_closings.js]
|
||||||
|
[browser_sessionStoreContainer.js]
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
function retrieveUserContextId(browser) {
|
||||||
|
return ContentTask.spawn(browser, null, function* () {
|
||||||
|
return docShell.userContextId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function() {
|
||||||
|
for (let i = 0; i < 3; ++i) {
|
||||||
|
let tab = gBrowser.addTab("about:blank");
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
|
||||||
|
yield promiseBrowserLoaded(browser);
|
||||||
|
yield promiseTabState(tab, { userContextId: i, entries: [{ url: "http://example.com/" }] });
|
||||||
|
|
||||||
|
let userContextId = yield retrieveUserContextId(browser);
|
||||||
|
is(userContextId, i, "The docShell has the correct userContextId");
|
||||||
|
|
||||||
|
yield promiseRemoveTab(tab);
|
||||||
|
}
|
||||||
|
});
|
|
@ -132,6 +132,7 @@ OriginAttributes::CreateSuffix(nsACString& aStr) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mSignedPkg.IsEmpty()) {
|
if (!mSignedPkg.IsEmpty()) {
|
||||||
|
MOZ_RELEASE_ASSERT(mSignedPkg.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
|
||||||
params->Set(NS_LITERAL_STRING("signedPkg"), mSignedPkg);
|
params->Set(NS_LITERAL_STRING("signedPkg"), mSignedPkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10072,6 +10072,11 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're doing a history load, use its scroll restoration state.
|
||||||
|
if (aSHEntry) {
|
||||||
|
aSHEntry->GetScrollRestorationIsManual(&scrollRestorationIsManual);
|
||||||
|
}
|
||||||
|
|
||||||
/* Assign mOSHE to mLSHE. This will either be a new entry created
|
/* Assign mOSHE to mLSHE. This will either be a new entry created
|
||||||
* by OnNewURI() for normal loads or aSHEntry for history loads.
|
* by OnNewURI() for normal loads or aSHEntry for history loads.
|
||||||
*/
|
*/
|
||||||
|
@ -13831,6 +13836,17 @@ nsDocShell::SetIsSignedPackage(const nsAString& aSignedPkg)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocShell::GetUserContextId(uint32_t* aUserContextId)
|
||||||
|
{
|
||||||
|
if (!aUserContextId) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*aUserContextId = mUserContextId;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsDocShell::SetUserContextId(uint32_t aUserContextId)
|
nsDocShell::SetUserContextId(uint32_t aUserContextId)
|
||||||
{
|
{
|
||||||
|
@ -14181,55 +14197,8 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceReques
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class FetchEventDispatcher final : public nsIFetchEventDispatcher
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FetchEventDispatcher(nsIInterceptedChannel* aChannel,
|
|
||||||
nsIRunnable* aContinueRunnable)
|
|
||||||
: mChannel(aChannel)
|
|
||||||
, mContinueRunnable(aContinueRunnable)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
|
||||||
NS_DECL_NSIFETCHEVENTDISPATCHER
|
|
||||||
|
|
||||||
private:
|
|
||||||
~FetchEventDispatcher()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIInterceptedChannel> mChannel;
|
|
||||||
nsCOMPtr<nsIRunnable> mContinueRunnable;
|
|
||||||
};
|
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(FetchEventDispatcher, nsIFetchEventDispatcher)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
FetchEventDispatcher::Dispatch()
|
nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
|
||||||
{
|
|
||||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
||||||
if (!swm) {
|
|
||||||
mChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ErrorResult error;
|
|
||||||
swm->DispatchPreparedFetchEvent(mChannel, mContinueRunnable, error);
|
|
||||||
if (NS_WARN_IF(error.Failed())) {
|
|
||||||
return error.StealNSResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel,
|
|
||||||
nsIFetchEventDispatcher** aFetchDispatcher)
|
|
||||||
{
|
{
|
||||||
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
if (!swm) {
|
if (!swm) {
|
||||||
|
@ -14266,18 +14235,12 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel,
|
||||||
attrs.InheritFromDocShellToDoc(GetOriginAttributes(), uri);
|
attrs.InheritFromDocShellToDoc(GetOriginAttributes(), uri);
|
||||||
|
|
||||||
ErrorResult error;
|
ErrorResult error;
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
swm->DispatchFetchEvent(attrs, doc, mInterceptedDocumentId, aChannel,
|
||||||
swm->PrepareFetchEvent(attrs, doc, mInterceptedDocumentId, aChannel,
|
isReload, isSubresourceLoad, error);
|
||||||
isReload, isSubresourceLoad, error);
|
|
||||||
if (NS_WARN_IF(error.Failed())) {
|
if (NS_WARN_IF(error.Failed())) {
|
||||||
return error.StealNSResult();
|
return error.StealNSResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(runnable);
|
|
||||||
RefPtr<FetchEventDispatcher> dispatcher =
|
|
||||||
new FetchEventDispatcher(aChannel, runnable);
|
|
||||||
dispatcher.forget(aFetchDispatcher);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,7 +232,6 @@ public:
|
||||||
NS_IMETHOD GetUseRemoteTabs(bool*) override;
|
NS_IMETHOD GetUseRemoteTabs(bool*) override;
|
||||||
NS_IMETHOD SetRemoteTabs(bool) override;
|
NS_IMETHOD SetRemoteTabs(bool) override;
|
||||||
NS_IMETHOD GetOriginAttributes(JS::MutableHandle<JS::Value>) override;
|
NS_IMETHOD GetOriginAttributes(JS::MutableHandle<JS::Value>) override;
|
||||||
NS_IMETHOD SetUserContextId(uint32_t);
|
|
||||||
|
|
||||||
// Restores a cached presentation from history (mLSHE).
|
// Restores a cached presentation from history (mLSHE).
|
||||||
// This method swaps out the content viewer and simulates loads for
|
// This method swaps out the content viewer and simulates loads for
|
||||||
|
|
|
@ -43,7 +43,7 @@ interface nsITabParent;
|
||||||
|
|
||||||
typedef unsigned long nsLoadFlags;
|
typedef unsigned long nsLoadFlags;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(811aa3e1-7c4d-45ae-89da-ea1b107c60ed)]
|
[scriptable, builtinclass, uuid(258a8a33-219f-42f8-8fa8-f8f2dcd2358b)]
|
||||||
interface nsIDocShell : nsIDocShellTreeItem
|
interface nsIDocShell : nsIDocShellTreeItem
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -1096,4 +1096,9 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||||
* @see https://html.spec.whatwg.org/#dom-history-scroll-restoration
|
* @see https://html.spec.whatwg.org/#dom-history-scroll-restoration
|
||||||
*/
|
*/
|
||||||
attribute boolean currentScrollRestorationIsManual;
|
attribute boolean currentScrollRestorationIsManual;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets/gets the user context ID for this docshell.
|
||||||
|
*/
|
||||||
|
attribute unsigned long userContextId;
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,6 +82,15 @@
|
||||||
opener.is(window.scrollY, 0, "Shouldn't have scrolled back to the state3's position");
|
opener.is(window.scrollY, 0, "Shouldn't have scrolled back to the state3's position");
|
||||||
opener.is(history.state.state, "state3", "Unexpected state.");
|
opener.is(history.state.state, "state3", "Unexpected state.");
|
||||||
|
|
||||||
|
history.pushState({ state: "state5" }, "state5");
|
||||||
|
history.scrollRestoration = "auto";
|
||||||
|
document.getElementById("bottom").scrollIntoView();
|
||||||
|
opener.isnot(window.scrollY, 0, "Should have scrolled to 'bottom'.");
|
||||||
|
history.back();
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
history.forward();
|
||||||
|
opener.isnot(window.scrollY, 0, "Should have scrolled back to the state5's position");
|
||||||
|
|
||||||
var ifr = document.createElement("iframe");
|
var ifr = document.createElement("iframe");
|
||||||
ifr.src = "data:text/html,";
|
ifr.src = "data:text/html,";
|
||||||
document.body.appendChild(ifr);
|
document.body.appendChild(ifr);
|
||||||
|
|
|
@ -47,7 +47,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||||
[test_popup-navigates-children.html]
|
[test_popup-navigates-children.html]
|
||||||
skip-if = buildapp == 'b2g' # b2g(Needs multiple window.open support, also uses docshelltreenode) b2g-debug(Needs multiple window.open support, also uses docshelltreenode) b2g-desktop(Needs multiple window.open support, also uses docshelltreenode)
|
skip-if = buildapp == 'b2g' # b2g(Needs multiple window.open support, also uses docshelltreenode) b2g-debug(Needs multiple window.open support, also uses docshelltreenode) b2g-desktop(Needs multiple window.open support, also uses docshelltreenode)
|
||||||
[test_reserved.html]
|
[test_reserved.html]
|
||||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || android_version == '10' || android_version == '18' #too slow on Android 2.3 and 4.3 aws only; bug 1030403
|
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || android_version == '10' || android_version == '18' || (e10s && debug && os == 'win') #too slow on Android 2.3 and 4.3 aws only; bug 1030403
|
||||||
[test_sessionhistory.html]
|
[test_sessionhistory.html]
|
||||||
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #RANDOM # b2g-debug(Perma-orange on debug emulator builds) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #RANDOM # b2g-debug(Perma-orange on debug emulator builds) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
|
||||||
[test_sibling-matching-parent.html]
|
[test_sibling-matching-parent.html]
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "AnimValuesStyleRule.h"
|
||||||
|
#include "nsRuleData.h"
|
||||||
|
#include "nsStyleContext.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(AnimValuesStyleRule, nsIStyleRule)
|
||||||
|
|
||||||
|
void
|
||||||
|
AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
|
||||||
|
{
|
||||||
|
nsStyleContext *contextParent = aRuleData->mStyleContext->GetParent();
|
||||||
|
if (contextParent && contextParent->HasPseudoElementData()) {
|
||||||
|
// Don't apply transitions or animations to things inside of
|
||||||
|
// pseudo-elements.
|
||||||
|
// FIXME (Bug 522599): Add tests for this.
|
||||||
|
|
||||||
|
// Prevent structs from being cached on the rule node since we're inside
|
||||||
|
// a pseudo-element, as we could determine cacheability differently
|
||||||
|
// when walking the rule tree for a style context that is not inside
|
||||||
|
// a pseudo-element. Note that nsRuleNode::GetStyle##name_ and GetStyleData
|
||||||
|
// will never look at cached structs when we're animating things inside
|
||||||
|
// a pseduo-element, so that we don't incorrectly return a struct that
|
||||||
|
// is only appropriate for non-pseudo-elements.
|
||||||
|
aRuleData->mConditions.SetUncacheable();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) {
|
||||||
|
PropertyValuePair &cv = mPropertyValuePairs[i];
|
||||||
|
if (aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(
|
||||||
|
nsCSSProps::kSIDTable[cv.mProperty]))
|
||||||
|
{
|
||||||
|
nsCSSValue *prop = aRuleData->ValueFor(cv.mProperty);
|
||||||
|
if (prop->GetUnit() == eCSSUnit_Null) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
bool ok =
|
||||||
|
#endif
|
||||||
|
StyleAnimationValue::UncomputeValue(cv.mProperty, cv.mValue, *prop);
|
||||||
|
MOZ_ASSERT(ok, "could not store computed value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AnimValuesStyleRule::MightMapInheritedStyleData()
|
||||||
|
{
|
||||||
|
return mStyleBits & NS_STYLE_INHERITED_STRUCT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void
|
||||||
|
AnimValuesStyleRule::List(FILE* out, int32_t aIndent) const
|
||||||
|
{
|
||||||
|
nsAutoCString str;
|
||||||
|
for (int32_t index = aIndent; --index >= 0; ) {
|
||||||
|
str.AppendLiteral(" ");
|
||||||
|
}
|
||||||
|
str.AppendLiteral("[anim values] { ");
|
||||||
|
for (uint32_t i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) {
|
||||||
|
const PropertyValuePair &pair = mPropertyValuePairs[i];
|
||||||
|
str.Append(nsCSSProps::GetStringValue(pair.mProperty));
|
||||||
|
str.AppendLiteral(": ");
|
||||||
|
nsAutoString value;
|
||||||
|
StyleAnimationValue::UncomputeValue(pair.mProperty, pair.mValue, value);
|
||||||
|
AppendUTF16toUTF8(value, str);
|
||||||
|
str.AppendLiteral("; ");
|
||||||
|
}
|
||||||
|
str.AppendLiteral("}\n");
|
||||||
|
fprintf_stderr(out, "%s", str.get());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_AnimValuesStyleRule_h
|
||||||
|
#define mozilla_AnimValuesStyleRule_h
|
||||||
|
|
||||||
|
#include "mozilla/StyleAnimationValue.h"
|
||||||
|
#include "nsCSSProperty.h"
|
||||||
|
#include "nsCSSPropertySet.h"
|
||||||
|
#include "nsIStyleRule.h"
|
||||||
|
#include "nsISupportsImpl.h" // For NS_DECL_ISUPPORTS
|
||||||
|
#include "nsRuleNode.h" // For nsCachedStyleData
|
||||||
|
#include "nsTArray.h" // For nsTArray
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A style rule that maps property-StyleAnimationValue pairs.
|
||||||
|
*/
|
||||||
|
class AnimValuesStyleRule final : public nsIStyleRule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnimValuesStyleRule()
|
||||||
|
: mStyleBits(0) {}
|
||||||
|
|
||||||
|
// nsISupports implementation
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
// nsIStyleRule implementation
|
||||||
|
void MapRuleInfoInto(nsRuleData* aRuleData) override;
|
||||||
|
bool MightMapInheritedStyleData() override;
|
||||||
|
#ifdef DEBUG
|
||||||
|
void List(FILE* out = stdout, int32_t aIndent = 0) const override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void AddValue(nsCSSProperty aProperty, StyleAnimationValue &aStartValue)
|
||||||
|
{
|
||||||
|
PropertyValuePair v = { aProperty, aStartValue };
|
||||||
|
mPropertyValuePairs.AppendElement(v);
|
||||||
|
mStyleBits |=
|
||||||
|
nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[aProperty]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Caller must fill in returned value.
|
||||||
|
StyleAnimationValue* AddEmptyValue(nsCSSProperty aProperty)
|
||||||
|
{
|
||||||
|
PropertyValuePair *p = mPropertyValuePairs.AppendElement();
|
||||||
|
p->mProperty = aProperty;
|
||||||
|
mStyleBits |=
|
||||||
|
nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[aProperty]);
|
||||||
|
return &p->mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PropertyValuePair {
|
||||||
|
nsCSSProperty mProperty;
|
||||||
|
StyleAnimationValue mValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AddPropertiesToSet(nsCSSPropertySet& aSet) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0, i_end = mPropertyValuePairs.Length(); i < i_end; ++i) {
|
||||||
|
const PropertyValuePair &cv = mPropertyValuePairs[i];
|
||||||
|
aSet.AddProperty(cv.mProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~AnimValuesStyleRule() {}
|
||||||
|
|
||||||
|
InfallibleTArray<PropertyValuePair> mPropertyValuePairs;
|
||||||
|
uint32_t mStyleBits;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_AnimValuesStyleRule_h
|
|
@ -477,14 +477,12 @@ Animation::Tick()
|
||||||
|
|
||||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||||
|
|
||||||
// FIXME: Detect the no-change case and don't request a restyle at all
|
// Update layers if we are newly finished.
|
||||||
// FIXME: Detect changes to IsPlaying() state and request RestyleType::Layer
|
if (mEffect &&
|
||||||
// so that layers get updated immediately
|
!mEffect->Properties().IsEmpty() &&
|
||||||
AnimationCollection* collection = GetCollection();
|
!mFinishedAtLastComposeStyle &&
|
||||||
if (collection) {
|
PlayState() == AnimationPlayState::Finished) {
|
||||||
collection->RequestRestyle(CanThrottle() ?
|
PostUpdate();
|
||||||
AnimationCollection::RestyleType::Throttled :
|
|
||||||
AnimationCollection::RestyleType::Standard);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,41 +671,6 @@ Animation::HasLowerCompositeOrderThan(const Animation& aOther) const
|
||||||
return mAnimationIndex < aOther.mAnimationIndex;
|
return mAnimationIndex < aOther.mAnimationIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
Animation::CanThrottle() const
|
|
||||||
{
|
|
||||||
// This method answers the question, "Can we get away with NOT updating
|
|
||||||
// style on the main thread for this animation on this tick?"
|
|
||||||
|
|
||||||
// Ignore animations that were never going to have any effect anyway.
|
|
||||||
if (!mEffect || mEffect->Properties().IsEmpty()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finished animations can be throttled unless this is the first
|
|
||||||
// sample since finishing. In that case we need an unthrottled sample
|
|
||||||
// so we can apply the correct end-of-animation behavior on the main
|
|
||||||
// thread (either removing the animation style or applying the fill mode).
|
|
||||||
if (PlayState() == AnimationPlayState::Finished) {
|
|
||||||
return mFinishedAtLastComposeStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should also ignore animations which are not "in effect"--i.e. not
|
|
||||||
// producing an output. This includes animations that are idle or in their
|
|
||||||
// delay phase but with no backwards fill.
|
|
||||||
//
|
|
||||||
// Note that unlike newly-finished animations, we don't need to worry about
|
|
||||||
// special handling for newly-idle animations or animations that are newly
|
|
||||||
// yet-to-start since any operation that would cause that change (e.g. a call
|
|
||||||
// to cancel() on the animation, or seeking its current time) will trigger an
|
|
||||||
// unthrottled sample.
|
|
||||||
if (!IsInEffect()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mEffect->CanThrottle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Animation::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
Animation::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||||
nsCSSPropertySet& aSetProperties,
|
nsCSSPropertySet& aSetProperties,
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/EffectCompositor.h" // For EffectCompositor::CascadeLevel
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
|
||||||
#include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState
|
#include "mozilla/dom/AnimationBinding.h" // for AnimationPlayState
|
||||||
|
@ -285,6 +286,15 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool HasLowerCompositeOrderThan(const Animation& aOther) const;
|
virtual bool HasLowerCompositeOrderThan(const Animation& aOther) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the level at which the effect(s) associated with this Animation
|
||||||
|
* are applied to the CSS cascade.
|
||||||
|
*/
|
||||||
|
virtual EffectCompositor::CascadeLevel CascadeLevel() const
|
||||||
|
{
|
||||||
|
return EffectCompositor::CascadeLevel::Animations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this animation does not currently need to update
|
* Returns true if this animation does not currently need to update
|
||||||
* style on the main thread (e.g. because it is empty, or is
|
* style on the main thread (e.g. because it is empty, or is
|
||||||
|
|
|
@ -7,12 +7,24 @@
|
||||||
#include "EffectCompositor.h"
|
#include "EffectCompositor.h"
|
||||||
|
|
||||||
#include "mozilla/dom/Animation.h"
|
#include "mozilla/dom/Animation.h"
|
||||||
#include "mozilla/dom/KeyframeEffect.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/dom/KeyframeEffect.h" // For KeyframeEffectReadOnly
|
||||||
#include "mozilla/AnimationUtils.h"
|
#include "mozilla/AnimationUtils.h"
|
||||||
#include "mozilla/EffectSet.h"
|
#include "mozilla/EffectSet.h"
|
||||||
|
#include "mozilla/LayerAnimationInfo.h"
|
||||||
|
#include "AnimationCommon.h" // For AnimationCollection
|
||||||
|
#include "nsAnimationManager.h"
|
||||||
|
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent
|
||||||
|
#include "nsCSSPropertySet.h"
|
||||||
|
#include "nsCSSProps.h"
|
||||||
|
#include "nsIPresShell.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
|
#include "nsRuleNode.h" // For nsRuleNode::ComputePropertiesOverridingAnimation
|
||||||
|
#include "nsTArray.h"
|
||||||
|
#include "nsTransitionManager.h"
|
||||||
|
|
||||||
using mozilla::dom::Animation;
|
using mozilla::dom::Animation;
|
||||||
|
using mozilla::dom::Element;
|
||||||
using mozilla::dom::KeyframeEffectReadOnly;
|
using mozilla::dom::KeyframeEffectReadOnly;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
@ -40,6 +52,21 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The animation cascade will almost always be up-to-date by this point
|
||||||
|
// but there are some cases such as when we are restoring the refresh driver
|
||||||
|
// from test control after seeking where it might not be the case.
|
||||||
|
//
|
||||||
|
// Those cases are probably not important but just to be safe, let's make
|
||||||
|
// sure the cascade is up to date since if it *is* up to date, this is
|
||||||
|
// basically a no-op.
|
||||||
|
Maybe<Pair<dom::Element*, nsCSSPseudoElements::Type>> pseudoElement =
|
||||||
|
EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
|
||||||
|
if (pseudoElement) {
|
||||||
|
EffectCompositor::MaybeUpdateCascadeResults(pseudoElement->first(),
|
||||||
|
pseudoElement->second(),
|
||||||
|
aFrame->StyleContext());
|
||||||
|
}
|
||||||
|
|
||||||
if (!nsLayoutUtils::AreAsyncAnimationsEnabled()) {
|
if (!nsLayoutUtils::AreAsyncAnimationsEnabled()) {
|
||||||
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
|
if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
|
||||||
nsCString message;
|
nsCString message;
|
||||||
|
@ -104,4 +131,288 @@ EffectCompositor::GetAnimationsForCompositor(const nsIFrame* aFrame,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
EffectCompositor::MaybeUpdateCascadeResults(Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type
|
||||||
|
aPseudoType,
|
||||||
|
nsStyleContext* aStyleContext)
|
||||||
|
{
|
||||||
|
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||||
|
if (!effects || !effects->CascadeNeedsUpdate()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateCascadeResults(*effects, aElement, aPseudoType, aStyleContext);
|
||||||
|
|
||||||
|
MOZ_ASSERT(!effects->CascadeNeedsUpdate(), "Failed to update cascade state");
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class EffectCompositeOrderComparator {
|
||||||
|
public:
|
||||||
|
bool Equals(const KeyframeEffectReadOnly* a,
|
||||||
|
const KeyframeEffectReadOnly* b) const
|
||||||
|
{
|
||||||
|
return a == b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LessThan(const KeyframeEffectReadOnly* a,
|
||||||
|
const KeyframeEffectReadOnly* b) const
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(a->GetAnimation() && b->GetAnimation());
|
||||||
|
MOZ_ASSERT(
|
||||||
|
Equals(a, b) ||
|
||||||
|
a->GetAnimation()->HasLowerCompositeOrderThan(*b->GetAnimation()) !=
|
||||||
|
b->GetAnimation()->HasLowerCompositeOrderThan(*a->GetAnimation()));
|
||||||
|
return a->GetAnimation()->HasLowerCompositeOrderThan(*b->GetAnimation());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
EffectCompositor::UpdateCascadeResults(Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
nsStyleContext* aStyleContext)
|
||||||
|
{
|
||||||
|
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||||
|
if (!effects) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateCascadeResults(*effects, aElement, aPseudoType, aStyleContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ Maybe<Pair<Element*, nsCSSPseudoElements::Type>>
|
||||||
|
EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
// Always return the same object to benefit from return-value optimization.
|
||||||
|
Maybe<Pair<Element*, nsCSSPseudoElements::Type>> result;
|
||||||
|
|
||||||
|
nsIContent* content = aFrame->GetContent();
|
||||||
|
if (!content) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCSSPseudoElements::Type pseudoType =
|
||||||
|
nsCSSPseudoElements::ePseudo_NotPseudoElement;
|
||||||
|
|
||||||
|
if (aFrame->IsGeneratedContentFrame()) {
|
||||||
|
nsIFrame* parent = aFrame->GetParent();
|
||||||
|
if (parent->IsGeneratedContentFrame()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
nsIAtom* name = content->NodeInfo()->NameAtom();
|
||||||
|
if (name == nsGkAtoms::mozgeneratedcontentbefore) {
|
||||||
|
pseudoType = nsCSSPseudoElements::ePseudo_before;
|
||||||
|
} else if (name == nsGkAtoms::mozgeneratedcontentafter) {
|
||||||
|
pseudoType = nsCSSPseudoElements::ePseudo_after;
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
content = content->GetParent();
|
||||||
|
if (!content) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!content->IsElement()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Some(MakePair(content->AsElement(), pseudoType));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
EffectCompositor::ComposeAnimationRule(dom::Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
CascadeLevel aCascadeLevel,
|
||||||
|
bool& aStyleChanging)
|
||||||
|
{
|
||||||
|
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||||
|
if (!effects) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The caller is responsible for calling MaybeUpdateCascadeResults first.
|
||||||
|
MOZ_ASSERT(!effects->CascadeNeedsUpdate(),
|
||||||
|
"Animation cascade out of date when composing animation rule");
|
||||||
|
|
||||||
|
// Get a list of effects for the current level sorted by composite order.
|
||||||
|
nsTArray<KeyframeEffectReadOnly*> sortedEffectList;
|
||||||
|
for (KeyframeEffectReadOnly* effect : *effects) {
|
||||||
|
MOZ_ASSERT(effect->GetAnimation());
|
||||||
|
if (effect->GetAnimation()->CascadeLevel() == aCascadeLevel) {
|
||||||
|
sortedEffectList.AppendElement(effect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sortedEffectList.Sort(EffectCompositeOrderComparator());
|
||||||
|
|
||||||
|
RefPtr<AnimValuesStyleRule>& animationRule =
|
||||||
|
effects->AnimationRule(aCascadeLevel);
|
||||||
|
animationRule = nullptr;
|
||||||
|
|
||||||
|
// We'll set aStyleChanging to true below if necessary.
|
||||||
|
aStyleChanging = false;
|
||||||
|
|
||||||
|
// If multiple animations specify behavior for the same property the
|
||||||
|
// animation with the *highest* composite order wins.
|
||||||
|
// As a result, we iterate from last animation to first and, if a
|
||||||
|
// property has already been set, we don't change it.
|
||||||
|
nsCSSPropertySet properties;
|
||||||
|
|
||||||
|
for (KeyframeEffectReadOnly* effect : Reversed(sortedEffectList)) {
|
||||||
|
effect->GetAnimation()->ComposeStyle(animationRule, properties,
|
||||||
|
aStyleChanging);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
EffectCompositor::GetOverriddenProperties(nsStyleContext* aStyleContext,
|
||||||
|
EffectSet& aEffectSet,
|
||||||
|
nsCSSPropertySet&
|
||||||
|
aPropertiesOverridden)
|
||||||
|
{
|
||||||
|
nsAutoTArray<nsCSSProperty, LayerAnimationInfo::kRecords> propertiesToTrack;
|
||||||
|
{
|
||||||
|
nsCSSPropertySet propertiesToTrackAsSet;
|
||||||
|
for (KeyframeEffectReadOnly* effect : aEffectSet) {
|
||||||
|
for (const AnimationProperty& property : effect->Properties()) {
|
||||||
|
if (nsCSSProps::PropHasFlags(property.mProperty,
|
||||||
|
CSS_PROPERTY_CAN_ANIMATE_ON_COMPOSITOR) &&
|
||||||
|
!propertiesToTrackAsSet.HasProperty(property.mProperty)) {
|
||||||
|
propertiesToTrackAsSet.AddProperty(property.mProperty);
|
||||||
|
propertiesToTrack.AppendElement(property.mProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Skip iterating over the rest of the effects if we've already
|
||||||
|
// found all the compositor-animatable properties.
|
||||||
|
if (propertiesToTrack.Length() == LayerAnimationInfo::kRecords) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertiesToTrack.IsEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRuleNode::ComputePropertiesOverridingAnimation(propertiesToTrack,
|
||||||
|
aStyleContext,
|
||||||
|
aPropertiesOverridden);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
|
||||||
|
Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
nsStyleContext* aStyleContext)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(EffectSet::GetEffectSet(aElement, aPseudoType) == &aEffectSet,
|
||||||
|
"Effect set should correspond to the specified (pseudo-)element");
|
||||||
|
if (aEffectSet.IsEmpty()) {
|
||||||
|
aEffectSet.MarkCascadeUpdated();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a list of effects sorted by composite order.
|
||||||
|
nsTArray<KeyframeEffectReadOnly*> sortedEffectList;
|
||||||
|
for (KeyframeEffectReadOnly* effect : aEffectSet) {
|
||||||
|
sortedEffectList.AppendElement(effect);
|
||||||
|
}
|
||||||
|
sortedEffectList.Sort(EffectCompositeOrderComparator());
|
||||||
|
|
||||||
|
// Get properties that override the *animations* level of the cascade.
|
||||||
|
//
|
||||||
|
// We only do this for properties that we can animate on the compositor
|
||||||
|
// since we will apply other properties on the main thread where the usual
|
||||||
|
// cascade applies.
|
||||||
|
nsCSSPropertySet overriddenProperties;
|
||||||
|
if (aStyleContext) {
|
||||||
|
GetOverriddenProperties(aStyleContext, aEffectSet, overriddenProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
nsCSSPropertySet animatedProperties;
|
||||||
|
|
||||||
|
// Iterate from highest to lowest composite order.
|
||||||
|
for (KeyframeEffectReadOnly* effect : Reversed(sortedEffectList)) {
|
||||||
|
MOZ_ASSERT(effect->GetAnimation(),
|
||||||
|
"Effects on a target element should have an Animation");
|
||||||
|
bool inEffect = effect->IsInEffect();
|
||||||
|
for (AnimationProperty& prop : effect->Properties()) {
|
||||||
|
|
||||||
|
bool winsInCascade = !animatedProperties.HasProperty(prop.mProperty) &&
|
||||||
|
inEffect;
|
||||||
|
|
||||||
|
// If this property wins in the cascade, add it to the set of animated
|
||||||
|
// properties. We need to do this even if the property is overridden
|
||||||
|
// (in which case we set winsInCascade to false below) since we don't
|
||||||
|
// want to fire transitions on these properties.
|
||||||
|
if (winsInCascade) {
|
||||||
|
animatedProperties.AddProperty(prop.mProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For effects that will be applied to the animations level of the
|
||||||
|
// cascade, we need to check that the property isn't being set by
|
||||||
|
// something with higher priority in the cascade.
|
||||||
|
//
|
||||||
|
// We only do this, however, for properties that can be animated on
|
||||||
|
// the compositor. For properties animated on the main thread the usual
|
||||||
|
// cascade ensures these animations will be correctly overridden.
|
||||||
|
if (winsInCascade &&
|
||||||
|
effect->GetAnimation()->CascadeLevel() == CascadeLevel::Animations &&
|
||||||
|
overriddenProperties.HasProperty(prop.mProperty)) {
|
||||||
|
winsInCascade = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winsInCascade != prop.mWinsInCascade) {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
prop.mWinsInCascade = winsInCascade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aEffectSet.MarkCascadeUpdated();
|
||||||
|
|
||||||
|
// If there is any change in the cascade result, update animations on
|
||||||
|
// layers with the winning animations.
|
||||||
|
nsPresContext* presContext = GetPresContext(aElement);
|
||||||
|
if (changed && presContext) {
|
||||||
|
// We currently unconditionally update both animations and transitions
|
||||||
|
// even if we could, for example, get away with only updating animations.
|
||||||
|
// This is a temporary measure until we unify all animation style updating
|
||||||
|
// under EffectCompositor.
|
||||||
|
AnimationCollection* animations =
|
||||||
|
presContext->AnimationManager()->GetAnimationCollection(aElement,
|
||||||
|
aPseudoType,
|
||||||
|
false);
|
||||||
|
/* don't create */
|
||||||
|
if (animations) {
|
||||||
|
animations->RequestRestyle(AnimationCollection::RestyleType::Layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationCollection* transitions =
|
||||||
|
presContext->TransitionManager()->GetAnimationCollection(aElement,
|
||||||
|
aPseudoType,
|
||||||
|
false);
|
||||||
|
/* don't create */
|
||||||
|
if (transitions) {
|
||||||
|
transitions->RequestRestyle(AnimationCollection::RestyleType::Layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ nsPresContext*
|
||||||
|
EffectCompositor::GetPresContext(Element* aElement)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aElement);
|
||||||
|
nsIPresShell* shell = nsComputedDOMStyle::GetPresShellForContent(aElement);
|
||||||
|
if (!shell) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return shell->GetPresContext();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -7,24 +7,109 @@
|
||||||
#ifndef mozilla_EffectCompositor_h
|
#ifndef mozilla_EffectCompositor_h
|
||||||
#define mozilla_EffectCompositor_h
|
#define mozilla_EffectCompositor_h
|
||||||
|
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/Pair.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "nsCSSProperty.h"
|
||||||
|
#include "nsCSSPseudoElements.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
|
||||||
|
class nsCSSPropertySet;
|
||||||
|
class nsIFrame;
|
||||||
|
class nsPresContext;
|
||||||
|
class nsStyleContext;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class EffectSet;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class Animation;
|
class Animation;
|
||||||
|
class Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
class EffectCompositor
|
class EffectCompositor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Animations can be applied at two different levels in the CSS cascade:
|
||||||
|
enum class CascadeLevel {
|
||||||
|
// The animations sheet (CSS animations, script-generated animations,
|
||||||
|
// and CSS transitions that are no longer tied to CSS markup)
|
||||||
|
Animations,
|
||||||
|
// The transitions sheet (CSS transitions that are tied to CSS markup)
|
||||||
|
Transitions
|
||||||
|
};
|
||||||
|
// We don't define this as part of CascadeLevel as then we'd have to add
|
||||||
|
// explicit checks for the Count enum value everywhere CascadeLevel is used.
|
||||||
|
static const size_t kCascadeLevelCount =
|
||||||
|
static_cast<size_t>(CascadeLevel::Transitions) + 1;
|
||||||
|
|
||||||
static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
|
static bool HasAnimationsForCompositor(const nsIFrame* aFrame,
|
||||||
nsCSSProperty aProperty);
|
nsCSSProperty aProperty);
|
||||||
|
|
||||||
static nsTArray<RefPtr<dom::Animation>>
|
static nsTArray<RefPtr<dom::Animation>>
|
||||||
GetAnimationsForCompositor(const nsIFrame* aFrame,
|
GetAnimationsForCompositor(const nsIFrame* aFrame,
|
||||||
nsCSSProperty aProperty);
|
nsCSSProperty aProperty);
|
||||||
|
|
||||||
|
|
||||||
|
// Update animation cascade results for the specified (pseudo-)element
|
||||||
|
// but only if we have marked the cascade as needing an update due a
|
||||||
|
// the change in the set of effects or a change in one of the effects'
|
||||||
|
// "in effect" state.
|
||||||
|
//
|
||||||
|
// This method does NOT detect if other styles that apply above the
|
||||||
|
// animation level of the cascade have changed.
|
||||||
|
static void
|
||||||
|
MaybeUpdateCascadeResults(dom::Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
nsStyleContext* aStyleContext);
|
||||||
|
|
||||||
|
// Update the mWinsInCascade member for each property in effects targetting
|
||||||
|
// the specified (pseudo-)element.
|
||||||
|
//
|
||||||
|
// This can be expensive so we should only call it if styles that apply
|
||||||
|
// above the animation level of the cascade might have changed. For all
|
||||||
|
// other cases we should call MaybeUpdateCascadeResults.
|
||||||
|
static void
|
||||||
|
UpdateCascadeResults(dom::Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
nsStyleContext* aStyleContext);
|
||||||
|
|
||||||
|
// Helper to fetch the corresponding element and pseudo-type from a frame.
|
||||||
|
//
|
||||||
|
// For frames corresponding to pseudo-elements, the returned element is the
|
||||||
|
// element on which we store the animations (i.e. the EffectSet and/or
|
||||||
|
// AnimationCollection), *not* the generated content.
|
||||||
|
//
|
||||||
|
// Returns an empty result when a suitable element cannot be found including
|
||||||
|
// when the frame represents a pseudo-element on which we do not support
|
||||||
|
// animations.
|
||||||
|
static Maybe<Pair<dom::Element*, nsCSSPseudoElements::Type>>
|
||||||
|
GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame);
|
||||||
|
|
||||||
|
// Rebuilds the animation rule corresponding to |aCascadeLevel| on the
|
||||||
|
// EffectSet associated with the specified (pseudo-)element.
|
||||||
|
static void ComposeAnimationRule(dom::Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
CascadeLevel aCascadeLevel,
|
||||||
|
bool& aStyleChanging);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Get the properties in |aEffectSet| that we are able to animate on the
|
||||||
|
// compositor but which are also specified at a higher level in the cascade
|
||||||
|
// than the animations level in |aStyleContext|.
|
||||||
|
static void
|
||||||
|
GetOverriddenProperties(nsStyleContext* aStyleContext,
|
||||||
|
EffectSet& aEffectSet,
|
||||||
|
nsCSSPropertySet& aPropertiesOverridden);
|
||||||
|
|
||||||
|
static void
|
||||||
|
UpdateCascadeResults(EffectSet& aEffectSet,
|
||||||
|
dom::Element* aElement,
|
||||||
|
nsCSSPseudoElements::Type aPseudoType,
|
||||||
|
nsStyleContext* aStyleContext);
|
||||||
|
|
||||||
|
static nsPresContext* GetPresContext(dom::Element* aElement);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
#include "EffectSet.h"
|
#include "EffectSet.h"
|
||||||
#include "mozilla/dom/Element.h" // For Element
|
#include "mozilla/dom/Element.h" // For Element
|
||||||
|
#include "RestyleManager.h"
|
||||||
#include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
|
#include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
|
||||||
|
#include "nsPresContext.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -106,6 +108,13 @@ EffectSet::GetOrCreateEffectSet(dom::Element* aElement,
|
||||||
return effectSet;
|
return effectSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
EffectSet::UpdateAnimationGeneration(nsPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
mAnimationGeneration =
|
||||||
|
aPresContext->RestyleManager()->GetAnimationGeneration();
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ nsIAtom**
|
/* static */ nsIAtom**
|
||||||
EffectSet::GetEffectSetPropertyAtoms()
|
EffectSet::GetEffectSetPropertyAtoms()
|
||||||
{
|
{
|
||||||
|
@ -143,13 +152,23 @@ EffectSet::GetEffectSetPropertyAtom(nsCSSPseudoElements::Type aPseudoType)
|
||||||
void
|
void
|
||||||
EffectSet::AddEffect(dom::KeyframeEffectReadOnly& aEffect)
|
EffectSet::AddEffect(dom::KeyframeEffectReadOnly& aEffect)
|
||||||
{
|
{
|
||||||
|
if (mEffects.Contains(&aEffect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mEffects.PutEntry(&aEffect);
|
mEffects.PutEntry(&aEffect);
|
||||||
|
MarkCascadeNeedsUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EffectSet::RemoveEffect(dom::KeyframeEffectReadOnly& aEffect)
|
EffectSet::RemoveEffect(dom::KeyframeEffectReadOnly& aEffect)
|
||||||
{
|
{
|
||||||
|
if (!mEffects.Contains(&aEffect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mEffects.RemoveEntry(&aEffect);
|
mEffects.RemoveEntry(&aEffect);
|
||||||
|
MarkCascadeNeedsUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -7,10 +7,15 @@
|
||||||
#ifndef mozilla_EffectSet_h
|
#ifndef mozilla_EffectSet_h
|
||||||
#define mozilla_EffectSet_h
|
#define mozilla_EffectSet_h
|
||||||
|
|
||||||
|
#include "mozilla/AnimValuesStyleRule.h"
|
||||||
|
#include "mozilla/EffectCompositor.h"
|
||||||
|
#include "mozilla/EnumeratedArray.h"
|
||||||
#include "nsCSSPseudoElements.h" // For nsCSSPseudoElements::Type
|
#include "nsCSSPseudoElements.h" // For nsCSSPseudoElements::Type
|
||||||
#include "nsHashKeys.h" // For nsPtrHashKey
|
#include "nsHashKeys.h" // For nsPtrHashKey
|
||||||
#include "nsTHashtable.h" // For nsTHashtable
|
#include "nsTHashtable.h" // For nsTHashtable
|
||||||
|
|
||||||
|
class nsPresContext;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -24,8 +29,10 @@ class EffectSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EffectSet()
|
EffectSet()
|
||||||
|
: mCascadeNeedsUpdate(false)
|
||||||
|
, mAnimationGeneration(0)
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
: mCalledPropertyDtor(false)
|
, mCalledPropertyDtor(false)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(EffectSet);
|
MOZ_COUNT_CTOR(EffectSet);
|
||||||
|
@ -120,6 +127,19 @@ public:
|
||||||
}
|
}
|
||||||
bool IsEmpty() const { return mEffects.IsEmpty(); }
|
bool IsEmpty() const { return mEffects.IsEmpty(); }
|
||||||
|
|
||||||
|
RefPtr<AnimValuesStyleRule>& AnimationRule(EffectCompositor::CascadeLevel
|
||||||
|
aCascadeLevel)
|
||||||
|
{
|
||||||
|
return mAnimationRule[aCascadeLevel];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CascadeNeedsUpdate() const { return mCascadeNeedsUpdate; }
|
||||||
|
void MarkCascadeNeedsUpdate() { mCascadeNeedsUpdate = true; }
|
||||||
|
void MarkCascadeUpdated() { mCascadeNeedsUpdate = false; }
|
||||||
|
|
||||||
|
void UpdateAnimationGeneration(nsPresContext* aPresContext);
|
||||||
|
uint64_t GetAnimationGeneration() const { return mAnimationGeneration; }
|
||||||
|
|
||||||
static nsIAtom** GetEffectSetPropertyAtoms();
|
static nsIAtom** GetEffectSetPropertyAtoms();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -128,6 +148,31 @@ private:
|
||||||
|
|
||||||
OwningEffectSet mEffects;
|
OwningEffectSet mEffects;
|
||||||
|
|
||||||
|
// These style rules contain the style data for currently animating
|
||||||
|
// values. They only match when styling with animation. When we
|
||||||
|
// style without animation, we need to not use them so that we can
|
||||||
|
// detect any new changes; if necessary we restyle immediately
|
||||||
|
// afterwards with animation.
|
||||||
|
EnumeratedArray<EffectCompositor::CascadeLevel,
|
||||||
|
EffectCompositor::CascadeLevel(
|
||||||
|
EffectCompositor::kCascadeLevelCount),
|
||||||
|
RefPtr<AnimValuesStyleRule>> mAnimationRule;
|
||||||
|
|
||||||
|
// Dirty flag to represent when the mWinsInCascade flag on effects in
|
||||||
|
// this set might need to be updated.
|
||||||
|
//
|
||||||
|
// Set to true any time the set of effects is changed or when
|
||||||
|
// one the effects goes in or out of the "in effect" state.
|
||||||
|
bool mCascadeNeedsUpdate;
|
||||||
|
|
||||||
|
// RestyleManager keeps track of the number of animation restyles.
|
||||||
|
// 'mini-flushes' (see nsTransitionManager::UpdateAllThrottledStyles()).
|
||||||
|
// mAnimationGeneration is the sequence number of the last flush where a
|
||||||
|
// transition/animation changed. We keep a similar count on the
|
||||||
|
// corresponding layer so we can check that the layer is up to date with
|
||||||
|
// the animation manager.
|
||||||
|
uint64_t mAnimationGeneration;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool mCalledPropertyDtor;
|
bool mCalledPropertyDtor;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
||||||
#include "nsCSSValue.h"
|
#include "nsCSSValue.h"
|
||||||
#include "nsStyleUtil.h"
|
#include "nsStyleUtil.h"
|
||||||
#include <algorithm> // std::max
|
#include <algorithm> // For std::max
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
||||||
, mTarget(aTarget)
|
, mTarget(aTarget)
|
||||||
, mTiming(aTiming)
|
, mTiming(aTiming)
|
||||||
, mPseudoType(aPseudoType)
|
, mPseudoType(aPseudoType)
|
||||||
|
, mInEffectOnLastAnimationTimingUpdate(false)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
MOZ_ASSERT(aTarget, "null animation target is not yet supported");
|
||||||
}
|
}
|
||||||
|
@ -132,6 +133,56 @@ KeyframeEffectReadOnly::SetTiming(const AnimationTiming& aTiming)
|
||||||
// update our registration with the target element.
|
// update our registration with the target element.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
KeyframeEffectReadOnly::NotifyAnimationTimingUpdated()
|
||||||
|
{
|
||||||
|
UpdateTargetRegistration();
|
||||||
|
|
||||||
|
// If the effect is not relevant it will be removed from the target
|
||||||
|
// element's effect set. However, effects not in the effect set
|
||||||
|
// will not be included in the set of candidate effects for running on
|
||||||
|
// the compositor and hence they won't have their compositor status
|
||||||
|
// updated. As a result, we need to make sure we clear their compositor
|
||||||
|
// status here.
|
||||||
|
bool isRelevant = mAnimation && mAnimation->IsRelevant();
|
||||||
|
if (!isRelevant) {
|
||||||
|
ResetIsRunningOnCompositor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect changes to "in effect" status since we need to recalculate the
|
||||||
|
// animation cascade for this element whenever that changes.
|
||||||
|
bool inEffect = IsInEffect();
|
||||||
|
if (inEffect != mInEffectOnLastAnimationTimingUpdate) {
|
||||||
|
if (mTarget) {
|
||||||
|
EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType);
|
||||||
|
if (effectSet) {
|
||||||
|
effectSet->MarkCascadeNeedsUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mInEffectOnLastAnimationTimingUpdate = inEffect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request restyle if necessary.
|
||||||
|
ComputedTiming computedTiming = GetComputedTiming();
|
||||||
|
AnimationCollection* collection = GetCollection();
|
||||||
|
// Bug 1235002: We should skip requesting a restyle when mProperties is empty.
|
||||||
|
// However, currently we don't properly encapsulate mProperties so we can't
|
||||||
|
// detect when it changes. As a result, if we skip requesting restyles when
|
||||||
|
// mProperties is empty and we play an animation and *then* add properties to
|
||||||
|
// it (as we currently do when building CSS animations), we will fail to
|
||||||
|
// request a restyle at all. Since animations without properties are rare, we
|
||||||
|
// currently just request the restyle regardless of whether mProperties is
|
||||||
|
// empty or not.
|
||||||
|
if (collection &&
|
||||||
|
// Bug 1216843: When we implement iteration composite modes, we need to
|
||||||
|
// also detect if the current iteration has changed.
|
||||||
|
computedTiming.mProgress != mProgressOnLastCompose) {
|
||||||
|
collection->RequestRestyle(CanThrottle() ?
|
||||||
|
AnimationCollection::RestyleType::Throttled :
|
||||||
|
AnimationCollection::RestyleType::Standard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Nullable<TimeDuration>
|
Nullable<TimeDuration>
|
||||||
KeyframeEffectReadOnly::GetLocalTime() const
|
KeyframeEffectReadOnly::GetLocalTime() const
|
||||||
{
|
{
|
||||||
|
@ -376,6 +427,7 @@ KeyframeEffectReadOnly::ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
|
||||||
nsCSSPropertySet& aSetProperties)
|
nsCSSPropertySet& aSetProperties)
|
||||||
{
|
{
|
||||||
ComputedTiming computedTiming = GetComputedTiming();
|
ComputedTiming computedTiming = GetComputedTiming();
|
||||||
|
mProgressOnLastCompose = computedTiming.mProgress;
|
||||||
|
|
||||||
// If the progress is null, we don't have fill data for the current
|
// If the progress is null, we don't have fill data for the current
|
||||||
// time so we shouldn't animate.
|
// time so we shouldn't animate.
|
||||||
|
@ -533,10 +585,6 @@ KeyframeEffectReadOnly::UpdateTargetRegistration()
|
||||||
if (effectSet) {
|
if (effectSet) {
|
||||||
effectSet->RemoveEffect(*this);
|
effectSet->RemoveEffect(*this);
|
||||||
}
|
}
|
||||||
// Any effects not in the effect set will not be included in the set of
|
|
||||||
// candidate effects for running on the compositor and hence they won't
|
|
||||||
// have their compositor status updated so we should do that now.
|
|
||||||
ResetIsRunningOnCompositor();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1776,15 +1824,14 @@ KeyframeEffectReadOnly::OverflowRegionRefreshInterval()
|
||||||
bool
|
bool
|
||||||
KeyframeEffectReadOnly::CanThrottle() const
|
KeyframeEffectReadOnly::CanThrottle() const
|
||||||
{
|
{
|
||||||
// Animation::CanThrottle checks for not in effect animations
|
// Unthrottle if we are not in effect or current. This will be the case when
|
||||||
// before calling this.
|
// our owning animation has finished, is idle, or when we are in the delay
|
||||||
MOZ_ASSERT(IsInEffect(), "Effect should be in effect");
|
// phase (but without a backwards fill). In each case the computed progress
|
||||||
|
// value produced on each tick will be the same so we will skip requesting
|
||||||
// Unthrottle if this animation is not current (i.e. it has passed the end).
|
// unnecessary restyles in NotifyAnimationTimingUpdated. Any calls we *do* get
|
||||||
// In future we may be able to throttle this case too, but we should only get
|
// here will be because of a change in state (e.g. we are newly finished or
|
||||||
// occasional ticks while the animation is in this state so it doesn't matter
|
// newly no longer in effect) in which case we shouldn't throttle the sample.
|
||||||
// too much.
|
if (!IsInEffect() || !IsCurrent()) {
|
||||||
if (!IsCurrent()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1812,14 +1859,15 @@ KeyframeEffectReadOnly::CanThrottle() const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationCollection* collection = GetCollection();
|
EffectSet* effectSet = EffectSet::GetEffectSet(mTarget, mPseudoType);
|
||||||
MOZ_ASSERT(collection,
|
MOZ_ASSERT(effectSet, "CanThrottle should be called on an effect "
|
||||||
"CanThrottle should be called on an effect associated with an animation");
|
"associated with a target element");
|
||||||
layers::Layer* layer =
|
layers::Layer* layer =
|
||||||
FrameLayerBuilder::GetDedicatedLayer(frame, record.mLayerType);
|
FrameLayerBuilder::GetDedicatedLayer(frame, record.mLayerType);
|
||||||
// Unthrottle if the layer needs to be brought up to date with the animation.
|
// Unthrottle if the layer needs to be brought up to date
|
||||||
if (!layer ||
|
if (!layer ||
|
||||||
collection->mAnimationGeneration > layer->GetAnimationGeneration()) {
|
effectSet->GetAnimationGeneration() !=
|
||||||
|
layer->GetAnimationGeneration()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -131,10 +131,7 @@ struct AnimationProperty
|
||||||
// For CSS Animations, which are overridden by !important rules in the
|
// For CSS Animations, which are overridden by !important rules in the
|
||||||
// cascade, we actually determine this from the CSS cascade
|
// cascade, we actually determine this from the CSS cascade
|
||||||
// computations, and then use it for OMTA.
|
// computations, and then use it for OMTA.
|
||||||
// **NOTE**: For CSS animations, we only bother setting mWinsInCascade
|
// **NOTE**: This member is not included when comparing AnimationProperty
|
||||||
// accurately for properties that we can animate on the compositor.
|
|
||||||
// For other properties, we make it always be true.
|
|
||||||
// **NOTE 2**: This member is not included when comparing AnimationProperty
|
|
||||||
// objects for equality.
|
// objects for equality.
|
||||||
bool mWinsInCascade = true;
|
bool mWinsInCascade = true;
|
||||||
|
|
||||||
|
@ -229,7 +226,7 @@ public:
|
||||||
const AnimationTiming& Timing() const { return mTiming; }
|
const AnimationTiming& Timing() const { return mTiming; }
|
||||||
AnimationTiming& Timing() { return mTiming; }
|
AnimationTiming& Timing() { return mTiming; }
|
||||||
void SetTiming(const AnimationTiming& aTiming);
|
void SetTiming(const AnimationTiming& aTiming);
|
||||||
void NotifyAnimationTimingUpdated() { UpdateTargetRegistration(); }
|
void NotifyAnimationTimingUpdated();
|
||||||
|
|
||||||
Nullable<TimeDuration> GetLocalTime() const;
|
Nullable<TimeDuration> GetLocalTime() const;
|
||||||
|
|
||||||
|
@ -293,8 +290,6 @@ public:
|
||||||
bool IsRunningOnCompositor() const;
|
bool IsRunningOnCompositor() const;
|
||||||
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
|
void SetIsRunningOnCompositor(nsCSSProperty aProperty, bool aIsRunning);
|
||||||
|
|
||||||
bool CanThrottle() const;
|
|
||||||
|
|
||||||
// Returns true if this effect, applied to |aFrame|, contains
|
// Returns true if this effect, applied to |aFrame|, contains
|
||||||
// properties that mean we shouldn't run *any* compositor animations on this
|
// properties that mean we shouldn't run *any* compositor animations on this
|
||||||
// element.
|
// element.
|
||||||
|
@ -349,9 +344,19 @@ protected:
|
||||||
|
|
||||||
InfallibleTArray<AnimationProperty> mProperties;
|
InfallibleTArray<AnimationProperty> mProperties;
|
||||||
|
|
||||||
|
// The computed progress last time we composed the style rule. This is
|
||||||
|
// used to detect when the progress is not changing (e.g. due to a step
|
||||||
|
// timing function) so we can avoid unnecessary style updates.
|
||||||
|
Nullable<double> mProgressOnLastCompose;
|
||||||
|
|
||||||
|
// We need to track when we go to or from being "in effect" since
|
||||||
|
// we need to re-evaluate the cascade of animations when that changes.
|
||||||
|
bool mInEffectOnLastAnimationTimingUpdate;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsIFrame* GetAnimationFrame() const;
|
nsIFrame* GetAnimationFrame() const;
|
||||||
|
|
||||||
|
bool CanThrottle() const;
|
||||||
bool CanThrottleTransformChanges(nsIFrame& aFrame) const;
|
bool CanThrottleTransformChanges(nsIFrame& aFrame) const;
|
||||||
|
|
||||||
// Returns true unless Gecko limitations prevent performing transform
|
// Returns true unless Gecko limitations prevent performing transform
|
||||||
|
|
|
@ -18,6 +18,7 @@ EXPORTS.mozilla.dom += [
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
'AnimationComparator.h',
|
'AnimationComparator.h',
|
||||||
'AnimationUtils.h',
|
'AnimationUtils.h',
|
||||||
|
'AnimValuesStyleRule.h',
|
||||||
'ComputedTimingFunction.h',
|
'ComputedTimingFunction.h',
|
||||||
'EffectCompositor.h',
|
'EffectCompositor.h',
|
||||||
'EffectSet.h',
|
'EffectSet.h',
|
||||||
|
@ -29,6 +30,7 @@ UNIFIED_SOURCES += [
|
||||||
'AnimationEffectReadOnly.cpp',
|
'AnimationEffectReadOnly.cpp',
|
||||||
'AnimationTimeline.cpp',
|
'AnimationTimeline.cpp',
|
||||||
'AnimationUtils.cpp',
|
'AnimationUtils.cpp',
|
||||||
|
'AnimValuesStyleRule.cpp',
|
||||||
'ComputedTimingFunction.cpp',
|
'ComputedTimingFunction.cpp',
|
||||||
'DocumentTimeline.cpp',
|
'DocumentTimeline.cpp',
|
||||||
'EffectCompositor.cpp',
|
'EffectCompositor.cpp',
|
||||||
|
@ -39,6 +41,8 @@ UNIFIED_SOURCES += [
|
||||||
|
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'/dom/base',
|
'/dom/base',
|
||||||
|
'/layout/base',
|
||||||
|
'/layout/style',
|
||||||
]
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
|
@ -80,6 +80,12 @@ this.UserCustomizations = {
|
||||||
},
|
},
|
||||||
|
|
||||||
isFromExtension: function(aURI) {
|
isFromExtension: function(aURI) {
|
||||||
|
if (!aURI && Services.prefs.getBoolPref("webextensions.tests")) {
|
||||||
|
// That's the case in mochitests because of the packaging setup:
|
||||||
|
// aURI is expected to be the appURI from the jarChannel but there is
|
||||||
|
// no real app associated to mochitest's jar:remoteopenfile:/// uris.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return this.appId.has(aURI.host);
|
return this.appId.has(aURI.host);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -700,9 +700,9 @@ public:
|
||||||
// (on element that have status pointer capture override
|
// (on element that have status pointer capture override
|
||||||
// or on element that have status pending pointer capture)
|
// or on element that have status pending pointer capture)
|
||||||
if (pointerCaptureInfo->mOverrideContent == this) {
|
if (pointerCaptureInfo->mOverrideContent == this) {
|
||||||
nsIPresShell::ReleasePointerCapturingContent(aPointerId, this);
|
nsIPresShell::ReleasePointerCapturingContent(aPointerId);
|
||||||
} else if (pointerCaptureInfo->mPendingContent == this) {
|
} else if (pointerCaptureInfo->mPendingContent == this) {
|
||||||
nsIPresShell::ReleasePointerCapturingContent(aPointerId, this);
|
nsIPresShell::ReleasePointerCapturingContent(aPointerId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -742,8 +742,7 @@ nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsDOMStyleSheetList::StyleSheetAdded(nsIDocument *aDocument,
|
nsDOMStyleSheetList::StyleSheetAdded(CSSStyleSheet* aStyleSheet,
|
||||||
CSSStyleSheet* aStyleSheet,
|
|
||||||
bool aDocumentSheet)
|
bool aDocumentSheet)
|
||||||
{
|
{
|
||||||
if (aDocumentSheet && -1 != mLength) {
|
if (aDocumentSheet && -1 != mLength) {
|
||||||
|
@ -752,8 +751,7 @@ nsDOMStyleSheetList::StyleSheetAdded(nsIDocument *aDocument,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsDOMStyleSheetList::StyleSheetRemoved(nsIDocument *aDocument,
|
nsDOMStyleSheetList::StyleSheetRemoved(CSSStyleSheet* aStyleSheet,
|
||||||
CSSStyleSheet* aStyleSheet,
|
|
||||||
bool aDocumentSheet)
|
bool aDocumentSheet)
|
||||||
{
|
{
|
||||||
if (aDocumentSheet && -1 != mLength) {
|
if (aDocumentSheet && -1 != mLength) {
|
||||||
|
@ -3666,14 +3664,12 @@ nsDocument::CreateShell(nsPresContext* aContext, nsViewManager* aViewManager,
|
||||||
// Don't add anything here. Add it to |doCreateShell| instead.
|
// Don't add anything here. Add it to |doCreateShell| instead.
|
||||||
// This exists so that subclasses can pass other values for the 4th
|
// This exists so that subclasses can pass other values for the 4th
|
||||||
// parameter some of the time.
|
// parameter some of the time.
|
||||||
return doCreateShell(aContext, aViewManager, aStyleSet,
|
return doCreateShell(aContext, aViewManager, aStyleSet);
|
||||||
eCompatibility_FullStandards);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIPresShell>
|
already_AddRefed<nsIPresShell>
|
||||||
nsDocument::doCreateShell(nsPresContext* aContext,
|
nsDocument::doCreateShell(nsPresContext* aContext,
|
||||||
nsViewManager* aViewManager, nsStyleSet* aStyleSet,
|
nsViewManager* aViewManager, nsStyleSet* aStyleSet)
|
||||||
nsCompatibility aCompatMode)
|
|
||||||
{
|
{
|
||||||
NS_ASSERTION(!mPresShell, "We have a presshell already!");
|
NS_ASSERTION(!mPresShell, "We have a presshell already!");
|
||||||
|
|
||||||
|
@ -3682,7 +3678,7 @@ nsDocument::doCreateShell(nsPresContext* aContext,
|
||||||
FillStyleSet(aStyleSet);
|
FillStyleSet(aStyleSet);
|
||||||
|
|
||||||
RefPtr<PresShell> shell = new PresShell;
|
RefPtr<PresShell> shell = new PresShell;
|
||||||
shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
|
shell->Init(this, aContext, aViewManager, aStyleSet);
|
||||||
|
|
||||||
// Note: we don't hold a ref to the shell (it holds a ref to us)
|
// Note: we don't hold a ref to the shell (it holds a ref to us)
|
||||||
mPresShell = shell;
|
mPresShell = shell;
|
||||||
|
@ -4075,7 +4071,7 @@ nsDocument::AddStyleSheetToStyleSets(CSSStyleSheet* aSheet)
|
||||||
void
|
void
|
||||||
nsDocument::NotifyStyleSheetAdded(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
nsDocument::NotifyStyleSheetAdded(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
||||||
{
|
{
|
||||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (this, aSheet, aDocumentSheet));
|
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetAdded, (aSheet, aDocumentSheet));
|
||||||
|
|
||||||
if (StyleSheetChangeEventsEnabled()) {
|
if (StyleSheetChangeEventsEnabled()) {
|
||||||
DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent,
|
DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent,
|
||||||
|
@ -4088,7 +4084,7 @@ nsDocument::NotifyStyleSheetAdded(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
||||||
void
|
void
|
||||||
nsDocument::NotifyStyleSheetRemoved(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
nsDocument::NotifyStyleSheetRemoved(CSSStyleSheet* aSheet, bool aDocumentSheet)
|
||||||
{
|
{
|
||||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetRemoved, (this, aSheet, aDocumentSheet));
|
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetRemoved, (aSheet, aDocumentSheet));
|
||||||
|
|
||||||
if (StyleSheetChangeEventsEnabled()) {
|
if (StyleSheetChangeEventsEnabled()) {
|
||||||
DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent,
|
DO_STYLESHEET_NOTIFICATION(StyleSheetChangeEvent,
|
||||||
|
@ -4216,8 +4212,7 @@ nsDocument::SetStyleSheetApplicableState(CSSStyleSheet* aSheet,
|
||||||
// that are children of sheets in our style set, as well as some
|
// that are children of sheets in our style set, as well as some
|
||||||
// sheets for nsHTMLEditor.
|
// sheets for nsHTMLEditor.
|
||||||
|
|
||||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetApplicableStateChanged,
|
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleSheetApplicableStateChanged, (aSheet));
|
||||||
(this, aSheet, aApplicable));
|
|
||||||
|
|
||||||
if (StyleSheetChangeEventsEnabled()) {
|
if (StyleSheetChangeEventsEnabled()) {
|
||||||
DO_STYLESHEET_NOTIFICATION(StyleSheetApplicableStateChangeEvent,
|
DO_STYLESHEET_NOTIFICATION(StyleSheetApplicableStateChangeEvent,
|
||||||
|
@ -5140,9 +5135,7 @@ void
|
||||||
nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet,
|
nsDocument::StyleRuleChanged(CSSStyleSheet* aSheet,
|
||||||
css::Rule* aStyleRule)
|
css::Rule* aStyleRule)
|
||||||
{
|
{
|
||||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged,
|
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleChanged, (aSheet));
|
||||||
(this, aSheet,
|
|
||||||
aStyleRule));
|
|
||||||
|
|
||||||
if (StyleSheetChangeEventsEnabled()) {
|
if (StyleSheetChangeEventsEnabled()) {
|
||||||
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
||||||
|
@ -5156,8 +5149,7 @@ void
|
||||||
nsDocument::StyleRuleAdded(CSSStyleSheet* aSheet,
|
nsDocument::StyleRuleAdded(CSSStyleSheet* aSheet,
|
||||||
css::Rule* aStyleRule)
|
css::Rule* aStyleRule)
|
||||||
{
|
{
|
||||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleAdded,
|
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleAdded, (aSheet));
|
||||||
(this, aSheet, aStyleRule));
|
|
||||||
|
|
||||||
if (StyleSheetChangeEventsEnabled()) {
|
if (StyleSheetChangeEventsEnabled()) {
|
||||||
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
||||||
|
@ -5172,8 +5164,7 @@ void
|
||||||
nsDocument::StyleRuleRemoved(CSSStyleSheet* aSheet,
|
nsDocument::StyleRuleRemoved(CSSStyleSheet* aSheet,
|
||||||
css::Rule* aStyleRule)
|
css::Rule* aStyleRule)
|
||||||
{
|
{
|
||||||
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleRemoved,
|
NS_DOCUMENT_NOTIFY_OBSERVERS(StyleRuleRemoved, (aSheet));
|
||||||
(this, aSheet, aStyleRule));
|
|
||||||
|
|
||||||
if (StyleSheetChangeEventsEnabled()) {
|
if (StyleSheetChangeEventsEnabled()) {
|
||||||
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
DO_STYLESHEET_NOTIFICATION(StyleRuleChangeEvent,
|
||||||
|
@ -8758,6 +8749,13 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WEBSPEECH
|
||||||
|
nsGlobalWindow* globalWindow = static_cast<nsGlobalWindow*>(win);
|
||||||
|
if (globalWindow->HasActiveSpeechSynthesis()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1494,8 +1494,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
already_AddRefed<nsIPresShell> doCreateShell(nsPresContext* aContext,
|
already_AddRefed<nsIPresShell> doCreateShell(nsPresContext* aContext,
|
||||||
nsViewManager* aViewManager,
|
nsViewManager* aViewManager,
|
||||||
nsStyleSet* aStyleSet,
|
nsStyleSet* aStyleSet);
|
||||||
nsCompatibility aCompatMode);
|
|
||||||
|
|
||||||
void RemoveDocStyleSheetsFromStyleSets();
|
void RemoveDocStyleSheetsFromStyleSets();
|
||||||
void RemoveStyleSheetsFromStyleSets(
|
void RemoveStyleSheetsFromStyleSets(
|
||||||
|
|
|
@ -3760,6 +3760,19 @@ nsGlobalWindow::GetSpeechSynthesis(ErrorResult& aError)
|
||||||
|
|
||||||
return mSpeechSynthesis;
|
return mSpeechSynthesis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsGlobalWindow::HasActiveSpeechSynthesis()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsInnerWindow());
|
||||||
|
|
||||||
|
if (mSpeechSynthesis) {
|
||||||
|
return !mSpeechSynthesis->HasEmptyQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
already_AddRefed<nsIDOMWindow>
|
already_AddRefed<nsIDOMWindow>
|
||||||
|
|
|
@ -1045,6 +1045,7 @@ public:
|
||||||
#ifdef MOZ_WEBSPEECH
|
#ifdef MOZ_WEBSPEECH
|
||||||
mozilla::dom::SpeechSynthesis*
|
mozilla::dom::SpeechSynthesis*
|
||||||
GetSpeechSynthesis(mozilla::ErrorResult& aError);
|
GetSpeechSynthesis(mozilla::ErrorResult& aError);
|
||||||
|
bool HasActiveSpeechSynthesis();
|
||||||
#endif
|
#endif
|
||||||
already_AddRefed<nsICSSDeclaration>
|
already_AddRefed<nsICSSDeclaration>
|
||||||
GetDefaultComputedStyle(mozilla::dom::Element& aElt,
|
GetDefaultComputedStyle(mozilla::dom::Element& aElt,
|
||||||
|
|
|
@ -94,15 +94,13 @@ public:
|
||||||
* A StyleSheet has just been added to the document. This method is
|
* A StyleSheet has just been added to the document. This method is
|
||||||
* called automatically when a StyleSheet gets added to the
|
* called automatically when a StyleSheet gets added to the
|
||||||
* document, even if the stylesheet is not applicable. The
|
* document, even if the stylesheet is not applicable. The
|
||||||
* notification is passed on to all of the document observers.
|
* notification is passed on to all of the document observers.
|
||||||
*
|
*
|
||||||
* @param aDocument The document being observed
|
|
||||||
* @param aStyleSheet the StyleSheet that has been added
|
* @param aStyleSheet the StyleSheet that has been added
|
||||||
* @param aDocumentSheet True if sheet is in document's style sheet list,
|
* @param aDocumentSheet True if sheet is in document's style sheet list,
|
||||||
* false if sheet is not (i.e., UA or user sheet)
|
* false if sheet is not (i.e., UA or user sheet)
|
||||||
*/
|
*/
|
||||||
virtual void StyleSheetAdded(nsIDocument *aDocument,
|
virtual void StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet,
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,
|
|
||||||
bool aDocumentSheet) = 0;
|
bool aDocumentSheet) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,13 +109,11 @@ public:
|
||||||
* from the document, even if the stylesheet is not applicable. The
|
* from the document, even if the stylesheet is not applicable. The
|
||||||
* notification is passed on to all of the document observers.
|
* notification is passed on to all of the document observers.
|
||||||
*
|
*
|
||||||
* @param aDocument The document being observed
|
|
||||||
* @param aStyleSheet the StyleSheet that has been removed
|
* @param aStyleSheet the StyleSheet that has been removed
|
||||||
* @param aDocumentSheet True if sheet is in document's style sheet list,
|
* @param aDocumentSheet True if sheet is in document's style sheet list,
|
||||||
* false if sheet is not (i.e., UA or user sheet)
|
* false if sheet is not (i.e., UA or user sheet)
|
||||||
*/
|
*/
|
||||||
virtual void StyleSheetRemoved(nsIDocument *aDocument,
|
virtual void StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet,
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,
|
|
||||||
bool aDocumentSheet) = 0;
|
bool aDocumentSheet) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,14 +123,9 @@ public:
|
||||||
* notification to the document. The notification is passed on
|
* notification to the document. The notification is passed on
|
||||||
* to all of the document observers.
|
* to all of the document observers.
|
||||||
*
|
*
|
||||||
* @param aDocument The document being observed
|
|
||||||
* @param aStyleSheet the StyleSheet that has changed state
|
* @param aStyleSheet the StyleSheet that has changed state
|
||||||
* @param aApplicable true if the sheet is applicable, false if
|
|
||||||
* it is not applicable
|
|
||||||
*/
|
*/
|
||||||
virtual void StyleSheetApplicableStateChanged(nsIDocument *aDocument,
|
virtual void StyleSheetApplicableStateChanged(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,
|
|
||||||
bool aApplicable) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A StyleRule has just been modified within a style sheet.
|
* A StyleRule has just been modified within a style sheet.
|
||||||
|
@ -143,13 +134,9 @@ public:
|
||||||
* the document. The notification is passed on to all of
|
* the document. The notification is passed on to all of
|
||||||
* the document observers.
|
* the document observers.
|
||||||
*
|
*
|
||||||
* @param aDocument The document being observed
|
|
||||||
* @param aStyleSheet the StyleSheet that contians the rule
|
* @param aStyleSheet the StyleSheet that contians the rule
|
||||||
* @param aStyleRule The rule being changed.
|
|
||||||
*/
|
*/
|
||||||
virtual void StyleRuleChanged(nsIDocument *aDocument,
|
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,
|
|
||||||
mozilla::css::Rule* aStyleRule) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A StyleRule has just been added to a style sheet.
|
* A StyleRule has just been added to a style sheet.
|
||||||
|
@ -158,13 +145,9 @@ public:
|
||||||
* notification to the document. The notification is passed on
|
* notification to the document. The notification is passed on
|
||||||
* to all of the document observers.
|
* to all of the document observers.
|
||||||
*
|
*
|
||||||
* @param aDocument The document being observed
|
|
||||||
* @param aStyleSheet the StyleSheet that has been modified
|
* @param aStyleSheet the StyleSheet that has been modified
|
||||||
* @param aStyleRule the rule that was added
|
|
||||||
*/
|
*/
|
||||||
virtual void StyleRuleAdded(nsIDocument *aDocument,
|
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,
|
|
||||||
mozilla::css::Rule* aStyleRule) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A StyleRule has just been removed from a style sheet.
|
* A StyleRule has just been removed from a style sheet.
|
||||||
|
@ -173,13 +156,9 @@ public:
|
||||||
* notification to the document. The notification is passed on
|
* notification to the document. The notification is passed on
|
||||||
* to all of the document observers.
|
* to all of the document observers.
|
||||||
*
|
*
|
||||||
* @param aDocument The document being observed
|
|
||||||
* @param aStyleSheet the StyleSheet that has been modified
|
* @param aStyleSheet the StyleSheet that has been modified
|
||||||
* @param aStyleRule the rule that was removed
|
|
||||||
*/
|
*/
|
||||||
virtual void StyleRuleRemoved(nsIDocument *aDocument,
|
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) = 0;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,
|
|
||||||
mozilla::css::Rule* aStyleRule) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
||||||
|
@ -207,35 +186,25 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentObserver, NS_IDOCUMENT_OBSERVER_IID)
|
||||||
mozilla::EventStates aStateMask) override;
|
mozilla::EventStates aStateMask) override;
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED \
|
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED \
|
||||||
virtual void StyleSheetAdded(nsIDocument* aDocument, \
|
virtual void StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
bool aDocumentSheet) override;
|
bool aDocumentSheet) override;
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED \
|
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED \
|
||||||
virtual void StyleSheetRemoved(nsIDocument* aDocument, \
|
virtual void StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
bool aDocumentSheet) override;
|
bool aDocumentSheet) override;
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED \
|
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETAPPLICABLESTATECHANGED \
|
||||||
virtual void StyleSheetApplicableStateChanged( \
|
virtual void StyleSheetApplicableStateChanged( \
|
||||||
nsIDocument* aDocument, \
|
mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
bool aApplicable) override;
|
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED \
|
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULECHANGED \
|
||||||
virtual void StyleRuleChanged(nsIDocument* aDocument, \
|
virtual void StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
mozilla::css::Rule* aStyleRule) override;
|
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED \
|
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEADDED \
|
||||||
virtual void StyleRuleAdded(nsIDocument* aDocument, \
|
virtual void StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
mozilla::css::Rule* aStyleRule) override;
|
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED \
|
#define NS_DECL_NSIDOCUMENTOBSERVER_STYLERULEREMOVED \
|
||||||
virtual void StyleRuleRemoved(nsIDocument* aDocument, \
|
virtual void StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) override;
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
mozilla::css::Rule* aStyleRule) override;
|
|
||||||
|
|
||||||
#define NS_DECL_NSIDOCUMENTOBSERVER \
|
#define NS_DECL_NSIDOCUMENTOBSERVER \
|
||||||
NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE \
|
NS_DECL_NSIDOCUMENTOBSERVER_BEGINUPDATE \
|
||||||
|
@ -293,39 +262,29 @@ NS_IMPL_NSIMUTATIONOBSERVER_CONTENT(_class)
|
||||||
|
|
||||||
#define NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(_class) \
|
#define NS_IMPL_NSIDOCUMENTOBSERVER_STYLE_STUB(_class) \
|
||||||
void \
|
void \
|
||||||
_class::StyleSheetAdded(nsIDocument* aDocument, \
|
_class::StyleSheetAdded(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
bool aDocumentSheet) \
|
bool aDocumentSheet) \
|
||||||
{ \
|
{ \
|
||||||
} \
|
} \
|
||||||
void \
|
void \
|
||||||
_class::StyleSheetRemoved(nsIDocument* aDocument, \
|
_class::StyleSheetRemoved(mozilla::CSSStyleSheet* aStyleSheet, \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
bool aDocumentSheet) \
|
bool aDocumentSheet) \
|
||||||
{ \
|
{ \
|
||||||
} \
|
} \
|
||||||
void \
|
void \
|
||||||
_class::StyleSheetApplicableStateChanged(nsIDocument* aDocument, \
|
_class::StyleSheetApplicableStateChanged(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet,\
|
|
||||||
bool aApplicable) \
|
|
||||||
{ \
|
{ \
|
||||||
} \
|
} \
|
||||||
void \
|
void \
|
||||||
_class::StyleRuleChanged(nsIDocument* aDocument, \
|
_class::StyleRuleChanged(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
mozilla::css::Rule* aStyleRule) \
|
|
||||||
{ \
|
{ \
|
||||||
} \
|
} \
|
||||||
void \
|
void \
|
||||||
_class::StyleRuleAdded(nsIDocument* aDocument, \
|
_class::StyleRuleAdded(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
mozilla::css::Rule* aStyleRule) \
|
|
||||||
{ \
|
{ \
|
||||||
} \
|
} \
|
||||||
void \
|
void \
|
||||||
_class::StyleRuleRemoved(nsIDocument* aDocument, \
|
_class::StyleRuleRemoved(mozilla::CSSStyleSheet* aStyleSheet) \
|
||||||
mozilla::CSSStyleSheet* aStyleSheet, \
|
|
||||||
mozilla::css::Rule* aStyleRule) \
|
|
||||||
{ \
|
{ \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
browserElementTestHelpers.setEnabledPref(true);
|
||||||
|
browserElementTestHelpers.addPermission();
|
||||||
|
|
||||||
|
var fileURL = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_ActiveStateChangeOnChangingMutedOrVolume.html';
|
||||||
|
var generator = runTests();
|
||||||
|
var testFrame;
|
||||||
|
var ac;
|
||||||
|
|
||||||
|
function assert(aVal, aMessage) {
|
||||||
|
return (!aVal) ? error(aMessage) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(aMessage) {
|
||||||
|
ok(false, "Error : " + aMessage);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function continueTest() {
|
||||||
|
try {
|
||||||
|
generator.next();
|
||||||
|
} catch (e if e instanceof StopIteration) {
|
||||||
|
error("Stop test because of exception!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish() {
|
||||||
|
document.body.removeChild(testFrame);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCommand(aArg) {
|
||||||
|
assert(!!ac, "Audio channel doesn't exist!");
|
||||||
|
info("# Command = " + aArg);
|
||||||
|
|
||||||
|
testFrame.src = fileURL + '#' + aArg;
|
||||||
|
var expectedActive = false;
|
||||||
|
switch (aArg) {
|
||||||
|
case 'play':
|
||||||
|
case 'unmute':
|
||||||
|
case 'volume-1':
|
||||||
|
expectedActive = true;
|
||||||
|
break;
|
||||||
|
case 'pause':
|
||||||
|
case 'mute':
|
||||||
|
case 'volume-0':
|
||||||
|
expectedActive = false;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
error("Undefined command!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ac.onactivestatechanged = () => {
|
||||||
|
ac.onactivestatechanged = null;
|
||||||
|
ac.isActive().onsuccess = (e) => {
|
||||||
|
is(expectedActive, e.target.result,
|
||||||
|
"Correct active state = " + expectedActive);
|
||||||
|
continueTest();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
setCommand('play');
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
setCommand('mute');
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
setCommand('unmute');
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
setCommand('volume-0');
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
setCommand('volume-1');
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
setCommand('pause');
|
||||||
|
yield undefined;
|
||||||
|
|
||||||
|
finish();
|
||||||
|
yield undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTestFrame() {
|
||||||
|
testFrame = document.createElement('iframe');
|
||||||
|
testFrame.setAttribute('mozbrowser', 'true');
|
||||||
|
testFrame.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||||
|
testFrame.src = fileURL;
|
||||||
|
|
||||||
|
function loadend() {
|
||||||
|
testFrame.removeEventListener('mozbrowserloadend', loadend);
|
||||||
|
ok("allowedAudioChannels" in testFrame, "allowedAudioChannels exist");
|
||||||
|
var channels = testFrame.allowedAudioChannels;
|
||||||
|
is(channels.length, 1, "1 audio channel by default");
|
||||||
|
|
||||||
|
ac = channels[0];
|
||||||
|
|
||||||
|
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
|
||||||
|
ok("isActive" in ac, "isActive exists");
|
||||||
|
ok("onactivestatechanged" in ac, "onactivestatechanged exists");
|
||||||
|
|
||||||
|
generator.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
function alertError(e) {
|
||||||
|
testFrame.removeEventListener('mozbrowsershowmodalprompt', alertError);
|
||||||
|
var message = e.detail.message
|
||||||
|
error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
testFrame.addEventListener('mozbrowserloadend', loadend);
|
||||||
|
testFrame.addEventListener('mozbrowsershowmodalprompt', alertError);
|
||||||
|
document.body.appendChild(testFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('testready', function() {
|
||||||
|
SpecialPowers.pushPrefEnv({'set': [["b2g.system_manifest_url", "http://mochi.test:8888/manifest.webapp"]]},
|
||||||
|
function() {
|
||||||
|
SimpleTest.executeSoon(setupTestFrame);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -182,60 +182,7 @@ function audio() {
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
function audioMutedByDefault() {
|
var tests = [ noaudio, audio ];
|
||||||
info("Test : audio-muted-by-default");
|
|
||||||
SpecialPowers.pushPrefEnv(
|
|
||||||
{'set': [["dom.audiochannel.mutedByDefault", true]]}, function () {
|
|
||||||
var iframe = document.createElement('iframe');
|
|
||||||
iframe.setAttribute('mozbrowser', 'true');
|
|
||||||
iframe.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
|
||||||
iframe.src = 'http://example.org/tests/dom/browser-element/mochitest/file_processingAudioSample.html';
|
|
||||||
|
|
||||||
function audio_loadend_MutedByDefault() {
|
|
||||||
ok("allowedAudioChannels" in iframe, "allowedAudioChannels exist");
|
|
||||||
var channels = iframe.allowedAudioChannels;
|
|
||||||
is(channels.length, 1, "1 audio channel by default");
|
|
||||||
|
|
||||||
var ac = channels[0];
|
|
||||||
|
|
||||||
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
|
|
||||||
ok("getMuted" in ac, "ac.getMuted exists");
|
|
||||||
ok("setMuted" in ac, "ac.setMuted exists");
|
|
||||||
|
|
||||||
ac.onactivestatechanged = function() {
|
|
||||||
ok(true, "activestatechanged event received.");
|
|
||||||
ac.onactivestatechanged = null;
|
|
||||||
|
|
||||||
new Promise(function(r, rr) {
|
|
||||||
ac.getMuted().onsuccess = function(e) {
|
|
||||||
is(e.target.result, true, "Muted channel by default");
|
|
||||||
r();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(function() {
|
|
||||||
ac.setMuted(false).onsuccess = function(e) {
|
|
||||||
ok(true, "Unmuted the channel.");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var complete = false;
|
|
||||||
iframe.addEventListener("mozbrowsershowmodalprompt", function (e) {
|
|
||||||
is(e.detail.message, "playback-success", "Audio playback success!");
|
|
||||||
if (!complete) {
|
|
||||||
document.body.removeChild(iframe);
|
|
||||||
SpecialPowers.popPrefEnv(runTests);
|
|
||||||
complete = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe.addEventListener('mozbrowserloadend', audio_loadend_MutedByDefault);
|
|
||||||
document.body.appendChild(iframe);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var tests = [ noaudio, audio, audioMutedByDefault ];
|
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
if (tests.length == 0) {
|
if (tests.length == 0) {
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
browserElementTestHelpers.setEnabledPref(true);
|
||||||
|
browserElementTestHelpers.addPermission();
|
||||||
|
|
||||||
|
var fileURL = 'http://example.org/tests/dom/browser-element/mochitest/file_browserElement_AudioChannelMutedByDefault.html';
|
||||||
|
var testFrame;
|
||||||
|
var ac;
|
||||||
|
|
||||||
|
function alertListener(e) {
|
||||||
|
var message = e.detail.message
|
||||||
|
if (/^OK/.exec(message)) {
|
||||||
|
ok(true, "Message from file : " + message);
|
||||||
|
} else if (/^KO/.exec(message)) {
|
||||||
|
error(message);
|
||||||
|
} else if (/DONE/.exec(message)) {
|
||||||
|
ok(true, "Audio playback success!");
|
||||||
|
finish();
|
||||||
|
} else {
|
||||||
|
error("Undefined event.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert(aVal, aMessage) {
|
||||||
|
return (!aVal) ? error(aMessage) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function error(aMessage) {
|
||||||
|
ok(false, "Error : " + aMessage);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish() {
|
||||||
|
testFrame.removeEventListener('mozbrowsershowmodalprompt', alertListener);
|
||||||
|
document.body.removeChild(testFrame);
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCommand(aArg) {
|
||||||
|
assert(!!ac, "Audio channel doesn't exist!");
|
||||||
|
info("# Command = " + aArg);
|
||||||
|
testFrame.src = fileURL + '#' + aArg;
|
||||||
|
|
||||||
|
switch (aArg) {
|
||||||
|
case 'play':
|
||||||
|
ac.onactivestatechanged = () => {
|
||||||
|
ac.onactivestatechanged = null;
|
||||||
|
ok(true, "activestatechanged event received.");
|
||||||
|
|
||||||
|
new Promise(function(r, rr) {
|
||||||
|
ac.getMuted().onsuccess = function(e) {
|
||||||
|
is(e.target.result, true, "Muted channel by default");
|
||||||
|
r();
|
||||||
|
}
|
||||||
|
}).then(function() {
|
||||||
|
ac.setMuted(false).onsuccess = function(e) {
|
||||||
|
ok(true, "Unmuted the channel.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
error("Undefined command!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTests() {
|
||||||
|
setCommand('play');
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTestFrame() {
|
||||||
|
testFrame = document.createElement('iframe');
|
||||||
|
testFrame.setAttribute('mozbrowser', 'true');
|
||||||
|
testFrame.setAttribute('mozapp', 'http://example.org/manifest.webapp');
|
||||||
|
testFrame.src = fileURL;
|
||||||
|
|
||||||
|
function loadend() {
|
||||||
|
testFrame.removeEventListener('mozbrowserloadend', loadend);
|
||||||
|
ok("allowedAudioChannels" in testFrame, "allowedAudioChannels exist");
|
||||||
|
var channels = testFrame.allowedAudioChannels;
|
||||||
|
is(channels.length, 1, "1 audio channel by default");
|
||||||
|
|
||||||
|
ac = channels[0];
|
||||||
|
ok(ac instanceof BrowserElementAudioChannel, "Correct class");
|
||||||
|
ok("getMuted" in ac, "ac.getMuted exists");
|
||||||
|
ok("setMuted" in ac, "ac.setMuted exists");
|
||||||
|
ok("onactivestatechanged" in ac, "onactivestatechanged exists");
|
||||||
|
|
||||||
|
runTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Set EventListeners.");
|
||||||
|
testFrame.addEventListener('mozbrowsershowmodalprompt', alertListener);
|
||||||
|
testFrame.addEventListener('mozbrowserloadend', loadend);
|
||||||
|
document.body.appendChild(testFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('testready', function() {
|
||||||
|
SpecialPowers.pushPrefEnv({'set': [["b2g.system_manifest_url", "http://mochi.test:8888/manifest.webapp"],
|
||||||
|
["dom.audiochannel.mutedByDefault", true]]},
|
||||||
|
function() {
|
||||||
|
SimpleTest.executeSoon(setupTestFrame);
|
||||||
|
});
|
||||||
|
});
|
|
@ -47,6 +47,20 @@ function registerPage(aEvent) {
|
||||||
ioService.newURI(manifestURI, null, null));
|
ioService.newURI(manifestURI, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uninstallApp() {
|
||||||
|
if (app) {
|
||||||
|
var request = navigator.mozApps.mgmt.uninstall(app);
|
||||||
|
app = null;
|
||||||
|
request.onerror = () => {
|
||||||
|
error("Uninstall app failed!");
|
||||||
|
};
|
||||||
|
request.onsuccess = () => {
|
||||||
|
is(request.result, manifestURI, "App uninstalled.");
|
||||||
|
runNextTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function runTest(aEnable) {
|
function runTest(aEnable) {
|
||||||
var request = navigator.mozApps.install(manifestURI, {});
|
var request = navigator.mozApps.install(manifestURI, {});
|
||||||
request.onerror = () => {
|
request.onerror = () => {
|
||||||
|
@ -63,9 +77,10 @@ function runTest(aEnable) {
|
||||||
iframe.setAttribute('remote', aEnable);
|
iframe.setAttribute('remote', aEnable);
|
||||||
iframe.setAttribute('mozapp', manifestURI);
|
iframe.setAttribute('mozapp', manifestURI);
|
||||||
iframe.src = srcURI;
|
iframe.src = srcURI;
|
||||||
document.body.appendChild(iframe);
|
|
||||||
|
|
||||||
iframe.addEventListener('mozbrowserloadend', () => {
|
function loadend() {
|
||||||
|
iframe.removeEventListener('mozbrowserloadend', loadend);
|
||||||
|
iframe.addEventListener("mozbrowsershowmodalprompt", getInterruption);
|
||||||
var channels = iframe.allowedAudioChannels;
|
var channels = iframe.allowedAudioChannels;
|
||||||
is(channels.length, 1, "1 audio channel by default");
|
is(channels.length, 1, "1 audio channel by default");
|
||||||
|
|
||||||
|
@ -76,23 +91,19 @@ function runTest(aEnable) {
|
||||||
var message = "audiochannel-interruption-begin";
|
var message = "audiochannel-interruption-begin";
|
||||||
registerPage(message);
|
registerPage(message);
|
||||||
ac.notifyChannel(message);
|
ac.notifyChannel(message);
|
||||||
iframe.addEventListener("mozbrowsershowmodalprompt", function (e) {
|
|
||||||
|
function getInterruption(e) {
|
||||||
|
e.target.removeEventListener("mozbrowsershowmodalprompt", getInterruption);
|
||||||
is(e.detail.message, message,
|
is(e.detail.message, message,
|
||||||
"App got audiochannel-interruption-begin.");
|
"App got audiochannel-interruption-begin.");
|
||||||
|
|
||||||
if (app) {
|
document.body.removeChild(iframe);
|
||||||
request = navigator.mozApps.mgmt.uninstall(app);
|
uninstallApp();
|
||||||
app = null;
|
}
|
||||||
request.onerror = () => {
|
};
|
||||||
error("Uninstall app failed!");
|
|
||||||
};
|
iframe.addEventListener("mozbrowserloadend", loadend);
|
||||||
request.onsuccess = () => {
|
document.body.appendChild(iframe);
|
||||||
is(request.result, manifestURI, "App uninstalled.");
|
|
||||||
runNextTest();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
var audio = new Audio();
|
||||||
|
audio.src = "audio.ogg";
|
||||||
|
audio.loop = true;
|
||||||
|
|
||||||
|
function runCommands()
|
||||||
|
{
|
||||||
|
switch(location.hash) {
|
||||||
|
case '#play':
|
||||||
|
audio.play();
|
||||||
|
break;
|
||||||
|
case '#mute':
|
||||||
|
audio.muted = true;
|
||||||
|
break;
|
||||||
|
case '#unmute':
|
||||||
|
audio.muted = false;
|
||||||
|
break;
|
||||||
|
case '#volume-0':
|
||||||
|
audio.volume = 0.0;
|
||||||
|
break;
|
||||||
|
case '#volume-1':
|
||||||
|
audio.volume = 1.0;
|
||||||
|
break;
|
||||||
|
case '#pause':
|
||||||
|
audio.pause();
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
alert("Undefined command!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('hashchange', runCommands);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,65 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
var audio = new Audio("audio.ogg");
|
||||||
|
var context = new AudioContext();
|
||||||
|
var node = context.createMediaElementSource(audio);
|
||||||
|
var sp = context.createScriptProcessor(2048, 1);
|
||||||
|
node.connect(sp);
|
||||||
|
var expectedSamplesCount;
|
||||||
|
var nonzeroSamplesCount = 0;
|
||||||
|
var isStarted = false;
|
||||||
|
|
||||||
|
function ok(aVal, aMsg) {
|
||||||
|
alert((!!aVal ? "OK" : "KO") + ", " + aMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish() {
|
||||||
|
audio.onended = null;
|
||||||
|
audio.pause();
|
||||||
|
alert("DONE");
|
||||||
|
}
|
||||||
|
|
||||||
|
function processSamples(e) {
|
||||||
|
var buf = e.inputBuffer.getChannelData(0);
|
||||||
|
for (var i = 0; i < buf.length; ++i) {
|
||||||
|
if (buf[i] != 0) {
|
||||||
|
if (!isStarted) {
|
||||||
|
isStarted = true;
|
||||||
|
ok(true, "Start process audio sample.");
|
||||||
|
}
|
||||||
|
nonzeroSamplesCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nonzeroSamplesCount >= expectedSamplesCount) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
audio.oncanplaythrough = function() {
|
||||||
|
var testDuration = audio.duration > 1.0 ? 1.0 : audio.duration * 0.5;
|
||||||
|
expectedSamplesCount = Math.floor(testDuration * context.sampleRate);
|
||||||
|
sp.onaudioprocess = processSamples;
|
||||||
|
};
|
||||||
|
|
||||||
|
function runCommands()
|
||||||
|
{
|
||||||
|
switch(location.hash) {
|
||||||
|
case '#play':
|
||||||
|
ok(true, "Audio starts playing.")
|
||||||
|
audio.play();
|
||||||
|
audio.onended = () => {
|
||||||
|
audio.onended = null;
|
||||||
|
ok(false, "Audio shouldn't go ended in this test!")
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
ok(false, "Undefined command!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('hashchange', runCommands);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,45 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
<script>
|
|
||||||
var audio = new Audio("audio.ogg");
|
|
||||||
var context = new AudioContext();
|
|
||||||
var node = context.createMediaElementSource(audio);
|
|
||||||
var sp = context.createScriptProcessor(2048, 1);
|
|
||||||
node.connect(sp);
|
|
||||||
var expectedSamplesCount;
|
|
||||||
var nonzeroSamplesCount = 0;
|
|
||||||
var complete = false;
|
|
||||||
var iterationCount = 0;
|
|
||||||
|
|
||||||
function processSamples(e) {
|
|
||||||
if (complete) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start playing the audio until the AudioContext is connected and running.
|
|
||||||
if (iterationCount++ == 0) {
|
|
||||||
audio.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf = e.inputBuffer.getChannelData(0);
|
|
||||||
for (var i = 0; i < buf.length; ++i) {
|
|
||||||
if (buf[i] != 0) {
|
|
||||||
nonzeroSamplesCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nonzeroSamplesCount >= expectedSamplesCount && !complete) {
|
|
||||||
alert("playback-success");
|
|
||||||
complete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
audio.oncanplaythrough = function() {
|
|
||||||
var testDuration = audio.duration > 2.0 ? 2.0 : audio.duration;
|
|
||||||
expectedSamplesCount = Math.floor(testDuration * context.sampleRate) ;
|
|
||||||
sp.onaudioprocess = processSamples;
|
|
||||||
};
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -27,6 +27,7 @@ skip-if = toolkit=='gonk'
|
||||||
skip-if = (toolkit == 'gonk' && !debug)
|
skip-if = (toolkit == 'gonk' && !debug)
|
||||||
[test_browserElement_oop_AppWindowNamespace.html]
|
[test_browserElement_oop_AppWindowNamespace.html]
|
||||||
skip-if = (toolkit == 'gonk' && !debug)
|
skip-if = (toolkit == 'gonk' && !debug)
|
||||||
|
[test_browserElement_oop_AudioChannelMutedByDefault.html]
|
||||||
[test_browserElement_oop_Auth.html]
|
[test_browserElement_oop_Auth.html]
|
||||||
skip-if = (toolkit == 'gonk' && !debug)
|
skip-if = (toolkit == 'gonk' && !debug)
|
||||||
[test_browserElement_oop_BackForward.html]
|
[test_browserElement_oop_BackForward.html]
|
||||||
|
@ -124,3 +125,4 @@ disabled = bug 924771
|
||||||
[test_browserElement_oop_getWebManifest.html]
|
[test_browserElement_oop_getWebManifest.html]
|
||||||
[test_browserElement_oop_OpenWindowEmpty.html]
|
[test_browserElement_oop_OpenWindowEmpty.html]
|
||||||
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
|
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
|
||||||
|
[test_browserElement_oop_ActiveStateChangeOnChangingMutedOrVolume.html]
|
||||||
|
|
|
@ -5,11 +5,13 @@ support-files =
|
||||||
../../../dom/media/test/short-video.ogv
|
../../../dom/media/test/short-video.ogv
|
||||||
async.js
|
async.js
|
||||||
browserElementTestHelpers.js
|
browserElementTestHelpers.js
|
||||||
|
browserElement_ActiveStateChangeOnChangingMutedOrVolume.js
|
||||||
browserElement_Alert.js
|
browserElement_Alert.js
|
||||||
browserElement_AlertInFrame.js
|
browserElement_AlertInFrame.js
|
||||||
browserElement_AllowEmbedAppsInNestedOOIframe.js
|
browserElement_AllowEmbedAppsInNestedOOIframe.js
|
||||||
browserElement_AppFramePermission.js
|
browserElement_AppFramePermission.js
|
||||||
browserElement_AppWindowNamespace.js
|
browserElement_AppWindowNamespace.js
|
||||||
|
browserElement_AudioChannelMutedByDefault.js
|
||||||
browserElement_AudioPlayback.js
|
browserElement_AudioPlayback.js
|
||||||
browserElement_Auth.js
|
browserElement_Auth.js
|
||||||
browserElement_BackForward.js
|
browserElement_BackForward.js
|
||||||
|
@ -84,12 +86,14 @@ support-files =
|
||||||
browserElement_GetContentDimensions.js
|
browserElement_GetContentDimensions.js
|
||||||
browserElement_AudioChannel.js
|
browserElement_AudioChannel.js
|
||||||
browserElement_AudioChannel_nested.js
|
browserElement_AudioChannel_nested.js
|
||||||
|
file_browserElement_ActiveStateChangeOnChangingMutedOrVolume.html
|
||||||
file_browserElement_AlertInFrame.html
|
file_browserElement_AlertInFrame.html
|
||||||
file_browserElement_AlertInFrame_Inner.html
|
file_browserElement_AlertInFrame_Inner.html
|
||||||
file_browserElement_AllowEmbedAppsInNestedOOIframe.html
|
file_browserElement_AllowEmbedAppsInNestedOOIframe.html
|
||||||
file_browserElement_AppFramePermission.html
|
file_browserElement_AppFramePermission.html
|
||||||
file_browserElement_AppWindowNamespace.html
|
file_browserElement_AppWindowNamespace.html
|
||||||
file_browserElement_AudioChannel_nested.html
|
file_browserElement_AudioChannel_nested.html
|
||||||
|
file_browserElement_AudioChannelMutedByDefault.html
|
||||||
file_browserElement_Viewmode.html
|
file_browserElement_Viewmode.html
|
||||||
file_browserElement_ThemeColor.html
|
file_browserElement_ThemeColor.html
|
||||||
file_browserElement_BrowserWindowNamespace.html
|
file_browserElement_BrowserWindowNamespace.html
|
||||||
|
@ -143,7 +147,6 @@ support-files =
|
||||||
file_web_manifest.html
|
file_web_manifest.html
|
||||||
file_web_manifest.json
|
file_web_manifest.json
|
||||||
file_illegal_web_manifest.html
|
file_illegal_web_manifest.html
|
||||||
file_processingAudioSample.html
|
|
||||||
noaudio.webm
|
noaudio.webm
|
||||||
|
|
||||||
# Note: browserElementTestHelpers.js looks at the test's filename to determine
|
# Note: browserElementTestHelpers.js looks at the test's filename to determine
|
||||||
|
@ -162,6 +165,8 @@ skip-if = buildapp == 'b2g'
|
||||||
skip-if = toolkit == 'android' || buildapp == 'b2g'
|
skip-if = toolkit == 'android' || buildapp == 'b2g'
|
||||||
[test_browserElement_inproc_AppWindowNamespace.html]
|
[test_browserElement_inproc_AppWindowNamespace.html]
|
||||||
skip-if = toolkit == 'android' || buildapp == 'b2g' # android(TIMED_OUT, bug 783509) androidx86(TIMED_OUT, bug 783509)
|
skip-if = toolkit == 'android' || buildapp == 'b2g' # android(TIMED_OUT, bug 783509) androidx86(TIMED_OUT, bug 783509)
|
||||||
|
[test_browserElement_inproc_AudioChannelMutedByDefault.html]
|
||||||
|
skip-if = toolkit == 'android'
|
||||||
[test_browserElement_inproc_AudioPlayback.html]
|
[test_browserElement_inproc_AudioPlayback.html]
|
||||||
[test_browserElement_inproc_Auth.html]
|
[test_browserElement_inproc_Auth.html]
|
||||||
skip-if = buildapp == 'b2g'
|
skip-if = buildapp == 'b2g'
|
||||||
|
@ -258,3 +263,4 @@ disabled = bug 774100
|
||||||
[test_browserElement_inproc_getStructuredData.html]
|
[test_browserElement_inproc_getStructuredData.html]
|
||||||
[test_browserElement_inproc_OpenWindowEmpty.html]
|
[test_browserElement_inproc_OpenWindowEmpty.html]
|
||||||
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
|
skip-if = (toolkit == 'gonk') # Test doesn't work on B2G emulator
|
||||||
|
[test_browserElement_inproc_ActiveStateChangeOnChangingMutedOrVolume.html]
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test ActiveStateChangeOnChangingMutedOrVolume</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript;version=1.7" src="browserElement_ActiveStateChangeOnChangingMutedOrVolume.js">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Bug 1235535 - Audio Channel Muted-By-Default.</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript;version=1.7" src="browserElement_AudioChannelMutedByDefault.js">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test ActiveStateChangeOnChangingMutedOrVolume</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript;version=1.7" src="browserElement_ActiveStateChangeOnChangingMutedOrVolume.js">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Bug 1235535 - Audio Channel Muted-By-Default.</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script type="application/javascript;version=1.7" src="browserElement_AudioChannelMutedByDefault.js">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -32,6 +32,7 @@ support-files =
|
||||||
[test_cache_overwrite.html]
|
[test_cache_overwrite.html]
|
||||||
[test_cache_match_vary.html]
|
[test_cache_match_vary.html]
|
||||||
[test_caches.html]
|
[test_caches.html]
|
||||||
|
skip-if = e10s && debug && os == 'win'
|
||||||
[test_cache_keys.html]
|
[test_cache_keys.html]
|
||||||
[test_cache_put.html]
|
[test_cache_put.html]
|
||||||
[test_cache_requestCache.html]
|
[test_cache_requestCache.html]
|
||||||
|
|
|
@ -599,6 +599,7 @@ WebGLProgram::GetProgramParameter(GLenum pname) const
|
||||||
if (mContext->IsWebGL2()) {
|
if (mContext->IsWebGL2()) {
|
||||||
switch (pname) {
|
switch (pname) {
|
||||||
case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS:
|
case LOCAL_GL_ACTIVE_UNIFORM_BLOCKS:
|
||||||
|
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
|
||||||
return JS::Int32Value(GetProgramiv(gl, mGLName, pname));
|
return JS::Int32Value(GetProgramiv(gl, mGLName, pname));
|
||||||
|
|
||||||
case LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS:
|
case LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS:
|
||||||
|
|
|
@ -259,20 +259,28 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk')
|
||||||
[test_mozDashOffset.html]
|
[test_mozDashOffset.html]
|
||||||
[test_mozGetAsFile.html]
|
[test_mozGetAsFile.html]
|
||||||
[test_strokeText_throw.html]
|
[test_strokeText_throw.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
[test_toBlob.html]
|
[test_toBlob.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win') # bug 1236257
|
||||||
[test_toDataURL_alpha.html]
|
[test_toDataURL_alpha.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
[test_toDataURL_lowercase_ascii.html]
|
[test_toDataURL_lowercase_ascii.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
[test_toDataURL_parameters.html]
|
[test_toDataURL_parameters.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
[test_windingRuleUndefined.html]
|
[test_windingRuleUndefined.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
[test_2d.fillText.gradient.html]
|
[test_2d.fillText.gradient.html]
|
||||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
|
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
|
||||||
[test_2d_composite_canvaspattern_setTransform.html]
|
[test_2d_composite_canvaspattern_setTransform.html]
|
||||||
[test_createPattern_broken.html]
|
[test_createPattern_broken.html]
|
||||||
[test_setlinedash.html]
|
[test_setlinedash.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
[test_filter.html]
|
[test_filter.html]
|
||||||
[test_offscreencanvas_toblob.html]
|
[test_offscreencanvas_toblob.html]
|
||||||
tags = offscreencanvas
|
tags = offscreencanvas
|
||||||
[test_offscreencanvas_toimagebitmap.html]
|
[test_offscreencanvas_toimagebitmap.html]
|
||||||
|
skip-if = (e10s && debug && os == 'win')
|
||||||
tags = offscreencanvas
|
tags = offscreencanvas
|
||||||
[test_offscreencanvas_basic_webgl.html]
|
[test_offscreencanvas_basic_webgl.html]
|
||||||
tags = offscreencanvas
|
tags = offscreencanvas
|
||||||
|
|
|
@ -87,7 +87,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(1 failure out of 615,
|
||||||
[test_bug605242.html]
|
[test_bug605242.html]
|
||||||
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||||
[test_bug607464.html]
|
[test_bug607464.html]
|
||||||
skip-if = buildapp == 'b2g' || toolkit == 'android' #CRASH_DUMP, RANDOM
|
skip-if = buildapp == 'b2g' || toolkit == 'android' || (e10s && os == 'win') #CRASH_DUMP, RANDOM
|
||||||
[test_bug613634.html]
|
[test_bug613634.html]
|
||||||
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||||
[test_bug615597.html]
|
[test_bug615597.html]
|
||||||
|
|
|
@ -170,7 +170,7 @@ addLoadEvent(doTest);
|
||||||
</script>
|
</script>
|
||||||
</pre>
|
</pre>
|
||||||
<div id="parent">
|
<div id="parent">
|
||||||
<span id="testTarget" style="padding: 5px; border: 1px solid black;">testTarget</span>
|
<span id="testTarget" style="margin-left: 200px; padding: 5px; border: 1px solid black;">testTarget</span>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4842,20 +4842,8 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (mMediaKeys == aMediaKeys) {
|
|
||||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
// We only support EME for MSE content by default.
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
if (aMediaKeys && aMediaKeys->IsBoundToMediaElement()) {
|
|
||||||
promise->MaybeReject(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR,
|
|
||||||
NS_LITERAL_CSTRING("MediaKeys object is already bound to another HTMLMediaElement"));
|
|
||||||
return promise.forget();
|
|
||||||
}
|
|
||||||
if (mMediaKeys) {
|
|
||||||
// Existing MediaKeys object. Shut it down.
|
|
||||||
mMediaKeys->Shutdown();
|
|
||||||
mMediaKeys = nullptr;
|
|
||||||
}
|
|
||||||
if (mDecoder &&
|
if (mDecoder &&
|
||||||
!mMediaSource &&
|
!mMediaSource &&
|
||||||
Preferences::GetBool("media.eme.mse-only", true)) {
|
Preferences::GetBool("media.eme.mse-only", true)) {
|
||||||
|
@ -4865,19 +4853,92 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
mMediaKeys = aMediaKeys;
|
// 1. If mediaKeys and the mediaKeys attribute are the same object,
|
||||||
|
// return a resolved promise.
|
||||||
|
if (mMediaKeys == aMediaKeys) {
|
||||||
|
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: Our attaching code is synchronous, so we can skip the following steps.
|
||||||
|
|
||||||
|
// 2. If this object's attaching media keys value is true, return a
|
||||||
|
// promise rejected with a new DOMException whose name is InvalidStateError.
|
||||||
|
// 3. Let this object's attaching media keys value be true.
|
||||||
|
// 4. Let promise be a new promise.
|
||||||
|
// 5. Run the following steps in parallel:
|
||||||
|
|
||||||
|
// 5.1 If mediaKeys is not null, CDM instance represented by mediaKeys is
|
||||||
|
// already in use by another media element, and the user agent is unable
|
||||||
|
// to use it with this element, let this object's attaching media keys
|
||||||
|
// value be false and reject promise with a new DOMException whose name
|
||||||
|
// is QuotaExceededError.
|
||||||
|
if (aMediaKeys && aMediaKeys->IsBoundToMediaElement()) {
|
||||||
|
promise->MaybeReject(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR,
|
||||||
|
NS_LITERAL_CSTRING("MediaKeys object is already bound to another HTMLMediaElement"));
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.2 If the mediaKeys attribute is not null, run the following steps:
|
||||||
if (mMediaKeys) {
|
if (mMediaKeys) {
|
||||||
if (NS_FAILED(mMediaKeys->Bind(this))) {
|
// 5.2.1 If the user agent or CDM do not support removing the association,
|
||||||
|
// let this object's attaching media keys value be false and reject promise
|
||||||
|
// with a new DOMException whose name is NotSupportedError.
|
||||||
|
|
||||||
|
// 5.2.2 If the association cannot currently be removed, let this object's
|
||||||
|
// attaching media keys value be false and reject promise with a new
|
||||||
|
// DOMException whose name is InvalidStateError.
|
||||||
|
if (mDecoder) {
|
||||||
|
// We don't support swapping out the MediaKeys once we've started to
|
||||||
|
// setup the playback pipeline. Note this also means we don't need to worry
|
||||||
|
// about handling disassociating the MediaKeys from the MediaDecoder.
|
||||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||||
NS_LITERAL_CSTRING("Failed to bind MediaKeys object to HTMLMediaElement"));
|
NS_LITERAL_CSTRING("Can't change MediaKeys on HTMLMediaElement after load has started"));
|
||||||
mMediaKeys = nullptr;
|
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5.2.3 Stop using the CDM instance represented by the mediaKeys attribute
|
||||||
|
// to decrypt media data and remove the association with the media element.
|
||||||
|
mMediaKeys->Unbind();
|
||||||
|
mMediaKeys = nullptr;
|
||||||
|
|
||||||
|
// 5.2.4 If the preceding step failed, let this object's attaching media
|
||||||
|
// keys value be false and reject promise with a new DOMException whose
|
||||||
|
// name is the appropriate error name.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.3. If mediaKeys is not null, run the following steps:
|
||||||
|
if (aMediaKeys) {
|
||||||
|
// 5.3.1 Associate the CDM instance represented by mediaKeys with the
|
||||||
|
// media element for decrypting media data.
|
||||||
|
if (NS_FAILED(aMediaKeys->Bind(this))) {
|
||||||
|
// 5.3.2 If the preceding step failed, run the following steps:
|
||||||
|
// 5.3.2.1 Set the mediaKeys attribute to null.
|
||||||
|
mMediaKeys = nullptr;
|
||||||
|
// 5.3.2.2 Let this object's attaching media keys value be false.
|
||||||
|
// 5.3.2.3 Reject promise with a new DOMException whose name is
|
||||||
|
// the appropriate error name.
|
||||||
|
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,
|
||||||
|
NS_LITERAL_CSTRING("Failed to bind MediaKeys object to HTMLMediaElement"));
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
// 5.3.3 Queue a task to run the "Attempt to Resume Playback If Necessary"
|
||||||
|
// algorithm on the media element.
|
||||||
|
// Note: Setting the CDMProxy on the MediaDecoder will unblock playback.
|
||||||
if (mDecoder) {
|
if (mDecoder) {
|
||||||
mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
|
mDecoder->SetCDMProxy(aMediaKeys->GetCDMProxy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 5.4 Set the mediaKeys attribute to mediaKeys.
|
||||||
|
mMediaKeys = aMediaKeys;
|
||||||
|
|
||||||
|
// 5.5 Let this object's attaching media keys value be false.
|
||||||
|
|
||||||
|
// 5.6 Resolve promise.
|
||||||
promise->MaybeResolve(JS::UndefinedHandleValue);
|
promise->MaybeResolve(JS::UndefinedHandleValue);
|
||||||
|
|
||||||
|
// 6. Return promise.
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,7 @@ nsHTMLDocument::CreateShell(nsPresContext* aContext,
|
||||||
nsViewManager* aViewManager,
|
nsViewManager* aViewManager,
|
||||||
nsStyleSet* aStyleSet)
|
nsStyleSet* aStyleSet)
|
||||||
{
|
{
|
||||||
return doCreateShell(aContext, aViewManager, aStyleSet, mCompatMode);
|
return doCreateShell(aContext, aViewManager, aStyleSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -593,13 +593,14 @@ support-files = file_bug871161-1.html file_bug871161-2.html
|
||||||
[test_hash_encoded.html]
|
[test_hash_encoded.html]
|
||||||
[test_bug1081037.html]
|
[test_bug1081037.html]
|
||||||
[test_window_open_close.html]
|
[test_window_open_close.html]
|
||||||
skip-if = buildapp == 'b2g' # bug 1129014
|
skip-if = buildapp == 'b2g' || (e10s && debug && os == 'win') # bug 1129014
|
||||||
[test_img_complete.html]
|
[test_img_complete.html]
|
||||||
[test_viewport_resize.html]
|
[test_viewport_resize.html]
|
||||||
[test_extapp.html]
|
[test_extapp.html]
|
||||||
[test_image_clone_load.html]
|
[test_image_clone_load.html]
|
||||||
[test_bug1203668.html]
|
[test_bug1203668.html]
|
||||||
[test_bug1166138.html]
|
[test_bug1166138.html]
|
||||||
|
[test_bug1230665.html]
|
||||||
[test_filepicker_default_directory.html]
|
[test_filepicker_default_directory.html]
|
||||||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
|
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
|
||||||
[test_bug1233598.html]
|
[test_bug1233598.html]
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 1230665</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
SimpleTest.waitForFocus(function() {
|
||||||
|
document.getElementById("flexbutton1").focus();
|
||||||
|
synthesizeKey("VK_TAB", { });
|
||||||
|
var e = document.getElementById("flexbutton2");
|
||||||
|
is(document.activeElement, e, "focus in flexbutton2 after TAB");
|
||||||
|
|
||||||
|
document.getElementById("gridbutton1").focus();
|
||||||
|
synthesizeKey("VK_TAB", { });
|
||||||
|
e = document.getElementById("gridbutton2");
|
||||||
|
is(document.activeElement, e, "focus in gridbutton2 after TAB");
|
||||||
|
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div tabindex="0" style="display:flex">
|
||||||
|
<button id="flexbutton1"></button>
|
||||||
|
text <!-- this text will force a :-moz-anonymous-flex-item frame -->
|
||||||
|
<div style="">
|
||||||
|
<button id="flexbutton2"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div tabindex="0" style="display:grid">
|
||||||
|
<button id="gridbutton1"></button>
|
||||||
|
text <!-- this text will force a :-moz-anonymous-grid-item frame -->
|
||||||
|
<div style="">
|
||||||
|
<button id="gridbutton2"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -172,6 +172,6 @@ PEExpectedVariableName=Expected identifier for variable name but found '%1$S'.
|
||||||
PEExpectedVariableFallback=Expected variable reference fallback after ','.
|
PEExpectedVariableFallback=Expected variable reference fallback after ','.
|
||||||
PEExpectedVariableCommaOrCloseParen=Expected ',' or ')' after variable name in variable reference but found '%1$S'.
|
PEExpectedVariableCommaOrCloseParen=Expected ',' or ')' after variable name in variable reference but found '%1$S'.
|
||||||
PESubgridNotSupported=Support for the 'subgrid' keyword of CSS Grid is not enabled.
|
PESubgridNotSupported=Support for the 'subgrid' keyword of CSS Grid is not enabled.
|
||||||
PEMoreThanOneGridRepeatAutoFillInNameList=Only one repeat(auto-fill, ...) is allowed in a name list for a subgrid.
|
PEMoreThanOneGridRepeatAutoFillInNameList=Only one repeat(auto-fill, …) is allowed in a name list for a subgrid.
|
||||||
PEMoreThanOneGridRepeatAutoFillFitInTrackList=Only one repeat(auto-fill, ...) or repeat(auto-fit, ...) is allowed in a track list.
|
PEMoreThanOneGridRepeatAutoFillFitInTrackList=Only one repeat(auto-fill, …) or repeat(auto-fit, …) is allowed in a track list.
|
||||||
PEMoreThanOneGridRepeatTrackSize=Only one track size is allowed inside repeat(auto-fit/auto-fill, ...).
|
PEMoreThanOneGridRepeatTrackSize=Only one track size is allowed inside repeat(auto-fit/auto-fill, …).
|
||||||
|
|
|
@ -504,5 +504,12 @@ MediaKeys::Bind(HTMLMediaElement* aElement)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaKeys::Unbind()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
mElement = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -55,6 +55,7 @@ public:
|
||||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
nsresult Bind(HTMLMediaElement* aElement);
|
nsresult Bind(HTMLMediaElement* aElement);
|
||||||
|
void Unbind();
|
||||||
|
|
||||||
// Javascript: readonly attribute DOMString keySystem;
|
// Javascript: readonly attribute DOMString keySystem;
|
||||||
void GetKeySystem(nsString& retval) const;
|
void GetKeySystem(nsString& retval) const;
|
||||||
|
|
|
@ -10,10 +10,13 @@
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
// "test.webm" contains 8 SimpleBlocks in a single Cluster with the following attributes
|
// "test.webm" contains 8 SimpleBlocks in a single Cluster. The blocks with
|
||||||
static const uint64_t gTimecodes[] = { 66000000, 160000000, 100000000, 133000000,
|
// timecodes 100000000 and are 133000000 skipped by WebMBufferedParser
|
||||||
166000000, 200000000, 233000000, 320000000 };
|
// because they occur after a block with timecode 160000000 and the parser
|
||||||
static const int64_t gEndOffsets[] = { 501, 772, 930, 1085, 1244, 1380, 1543, 2015 };
|
// expects in-order timecodes per the WebM spec. The remaining 6
|
||||||
|
// SimpleBlocks have the following attributes:
|
||||||
|
static const uint64_t gTimecodes[] = { 66000000, 160000000, 166000000, 200000000, 233000000, 320000000 };
|
||||||
|
static const int64_t gEndOffsets[] = { 501, 772, 1244, 1380, 1543, 2015 };
|
||||||
|
|
||||||
TEST(WebMBuffered, BasicTests)
|
TEST(WebMBuffered, BasicTests)
|
||||||
{
|
{
|
||||||
|
@ -66,7 +69,7 @@ TEST(WebMBuffered, RealData)
|
||||||
|
|
||||||
nsTArray<WebMTimeDataOffset> mapping;
|
nsTArray<WebMTimeDataOffset> mapping;
|
||||||
parser.Append(webmData.Elements(), webmData.Length(), mapping, dummy);
|
parser.Append(webmData.Elements(), webmData.Length(), mapping, dummy);
|
||||||
EXPECT_EQ(mapping.Length(), 8u);
|
EXPECT_EQ(mapping.Length(), 6u);
|
||||||
EXPECT_EQ(parser.mStartOffset, 0);
|
EXPECT_EQ(parser.mStartOffset, 0);
|
||||||
EXPECT_EQ(parser.mCurrentOffset, int64_t(webmData.Length()));
|
EXPECT_EQ(parser.mCurrentOffset, int64_t(webmData.Length()));
|
||||||
EXPECT_EQ(parser.GetTimecodeScale(), 500000u);
|
EXPECT_EQ(parser.GetTimecodeScale(), 500000u);
|
||||||
|
@ -95,7 +98,7 @@ TEST(WebMBuffered, RealDataAppend)
|
||||||
EXPECT_EQ(parser.mCurrentOffset, int64_t(offset));
|
EXPECT_EQ(parser.mCurrentOffset, int64_t(offset));
|
||||||
if (mapping.Length() != arrayEntries) {
|
if (mapping.Length() != arrayEntries) {
|
||||||
arrayEntries = mapping.Length();
|
arrayEntries = mapping.Length();
|
||||||
ASSERT_LE(arrayEntries, 8u);
|
ASSERT_LE(arrayEntries, 6u);
|
||||||
uint32_t i = arrayEntries - 1;
|
uint32_t i = arrayEntries - 1;
|
||||||
EXPECT_EQ(mapping[i].mEndOffset, gEndOffsets[i]);
|
EXPECT_EQ(mapping[i].mEndOffset, gEndOffsets[i]);
|
||||||
EXPECT_EQ(mapping[i].mSyncOffset, 361);
|
EXPECT_EQ(mapping[i].mSyncOffset, 361);
|
||||||
|
@ -103,7 +106,7 @@ TEST(WebMBuffered, RealDataAppend)
|
||||||
EXPECT_EQ(parser.GetTimecodeScale(), 500000u);
|
EXPECT_EQ(parser.GetTimecodeScale(), 500000u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(mapping.Length(), 8u);
|
EXPECT_EQ(mapping.Length(), 6u);
|
||||||
EXPECT_EQ(parser.mStartOffset, 0);
|
EXPECT_EQ(parser.mStartOffset, 0);
|
||||||
EXPECT_EQ(parser.mCurrentOffset, int64_t(webmData.Length()));
|
EXPECT_EQ(parser.mCurrentOffset, int64_t(webmData.Length()));
|
||||||
EXPECT_EQ(parser.GetTimecodeScale(), 500000u);
|
EXPECT_EQ(parser.GetTimecodeScale(), 500000u);
|
||||||
|
|
|
@ -623,6 +623,8 @@ skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'go
|
||||||
[test_eme_session_callable_value.html]
|
[test_eme_session_callable_value.html]
|
||||||
[test_eme_canvas_blocked.html]
|
[test_eme_canvas_blocked.html]
|
||||||
skip-if = toolkit == 'android' # bug 1149374
|
skip-if = toolkit == 'android' # bug 1149374
|
||||||
|
[test_eme_detach_media_keys.html]
|
||||||
|
skip-if = toolkit == 'android' # bug 1149374
|
||||||
[test_eme_initDataTypes.html]
|
[test_eme_initDataTypes.html]
|
||||||
skip-if = toolkit == 'android' # bug 1149374
|
skip-if = toolkit == 'android' # bug 1149374
|
||||||
[test_eme_non_mse_fails.html]
|
[test_eme_non_mse_fails.html]
|
||||||
|
@ -846,7 +848,9 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
|
||||||
[test_VideoPlaybackQuality_disabled.html]
|
[test_VideoPlaybackQuality_disabled.html]
|
||||||
[test_volume.html]
|
[test_volume.html]
|
||||||
[test_vttparser.html]
|
[test_vttparser.html]
|
||||||
|
skip-if = e10s && debug && os == 'win'
|
||||||
[test_webvtt_disabled.html]
|
[test_webvtt_disabled.html]
|
||||||
|
skip-if = e10s && debug && os == 'win'
|
||||||
|
|
||||||
# The tests below contain backend-specific tests. Write backend independent
|
# The tests below contain backend-specific tests. Write backend independent
|
||||||
# tests rather than adding to this list.
|
# tests rather than adding to this list.
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test Encrypted Media Extensions</title>
|
||||||
|
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||||
|
<script type="text/javascript" src="manifest.js"></script>
|
||||||
|
<script type="text/javascript" src="eme.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<video id="v" controls></video>
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
const keysystem = 'org.w3.clearkey';
|
||||||
|
|
||||||
|
function createAndSet() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
var m;
|
||||||
|
navigator.requestMediaKeySystemAccess(keysystem, [{initDataType: 'cenc'}])
|
||||||
|
.then(function (access) {
|
||||||
|
return access.createMediaKeys();
|
||||||
|
}).then(function (mediaKeys) {
|
||||||
|
m = mediaKeys;
|
||||||
|
return document.getElementById("v").setMediaKeys(mediaKeys);
|
||||||
|
}).then(function() {
|
||||||
|
resolve(m);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
|
||||||
|
var m1,m2;
|
||||||
|
|
||||||
|
// Test that if we create and set two MediaKeys on one video element,
|
||||||
|
// that if the first MediaKeys we set on the media elemnt is still usable
|
||||||
|
// after the second MediaKeys has been set on the media element.
|
||||||
|
SetupEMEPref(() => {
|
||||||
|
createAndSet().then((m) => {
|
||||||
|
m1 = m; // Stash MediaKeys.
|
||||||
|
return createAndSet();
|
||||||
|
})
|
||||||
|
.then((m) => {
|
||||||
|
m2 = m;
|
||||||
|
is(document.getElementById("v").mediaKeys, m2, "Should have set MediaKeys on media element");
|
||||||
|
ok(document.getElementById("v").mediaKeys != m1, "First MediaKeys should no longer be set on media element");
|
||||||
|
var s = m1.createSession("temporary");
|
||||||
|
return s.generateRequest("webm", StringToArrayBuffer(atob('YAYeAX5Hfod+V9ANHtANHg==')));
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ok(true, "Was able to generateRequest using second CDM");
|
||||||
|
SimpleTest.finish();
|
||||||
|
}, () => {
|
||||||
|
ok(false, "Was *NOT* able to generateRequest using second CDM");
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -9,8 +9,12 @@
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#define WEBM_DEBUG(arg, ...) MOZ_LOG(gWebMDemuxerLog, mozilla::LogLevel::Debug, ("WebMBufferedParser(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
extern LazyLogModule gWebMDemuxerLog;
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
VIntLength(unsigned char aFirstByte, uint32_t* aMask)
|
VIntLength(unsigned char aFirstByte, uint32_t* aMask)
|
||||||
{
|
{
|
||||||
|
@ -183,9 +187,20 @@ void WebMBufferedParser::Append(const unsigned char* aBuffer, uint32_t aLength,
|
||||||
MOZ_ASSERT(mGotTimecodeScale);
|
MOZ_ASSERT(mGotTimecodeScale);
|
||||||
uint64_t absTimecode = mClusterTimecode + mBlockTimecode;
|
uint64_t absTimecode = mClusterTimecode + mBlockTimecode;
|
||||||
absTimecode *= mTimecodeScale;
|
absTimecode *= mTimecodeScale;
|
||||||
WebMTimeDataOffset entry(endOffset, absTimecode, mLastInitStartOffset,
|
// Avoid creating an entry if the timecode is out of order
|
||||||
mClusterOffset, mClusterEndOffset);
|
// (invalid according to the WebM specification) so that
|
||||||
aMapping.InsertElementAt(idx, entry);
|
// ordering invariants of aMapping are not violated.
|
||||||
|
if (idx == 0 ||
|
||||||
|
aMapping[idx - 1].mTimecode <= absTimecode ||
|
||||||
|
(idx + 1 < aMapping.Length() &&
|
||||||
|
aMapping[idx + 1].mTimecode >= absTimecode)) {
|
||||||
|
WebMTimeDataOffset entry(endOffset, absTimecode, mLastInitStartOffset,
|
||||||
|
mClusterOffset, mClusterEndOffset);
|
||||||
|
aMapping.InsertElementAt(idx, entry);
|
||||||
|
} else {
|
||||||
|
WEBM_DEBUG("Out of order timecode %llu in Cluster at %lld ignored",
|
||||||
|
absTimecode, mClusterOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,6 +317,7 @@ bool WebMBufferedState::CalculateBufferedForRange(int64_t aStartOffset, int64_t
|
||||||
"Must have found greatest WebMTimeDataOffset for end");
|
"Must have found greatest WebMTimeDataOffset for end");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mTimeMapping[end].mTimecode >= mTimeMapping[end - 1].mTimecode);
|
||||||
uint64_t frameDuration = mTimeMapping[end].mTimecode - mTimeMapping[end - 1].mTimecode;
|
uint64_t frameDuration = mTimeMapping[end].mTimecode - mTimeMapping[end - 1].mTimecode;
|
||||||
*aStartTime = mTimeMapping[start].mTimecode;
|
*aStartTime = mTimeMapping[start].mTimecode;
|
||||||
*aEndTime = mTimeMapping[end].mTimecode + frameDuration;
|
*aEndTime = mTimeMapping[end].mTimecode + frameDuration;
|
||||||
|
@ -478,3 +494,6 @@ WebMBufferedState::GetNextKeyframeTime(uint64_t aTime, uint64_t* aKeyframeTime)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#undef WEBM_DEBUG
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsSpeechTask.h"
|
#include "nsSpeechTask.h"
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
|
|
||||||
|
@ -55,7 +56,9 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechSynthesis)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SpeechSynthesis)
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechSynthesis)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(SpeechSynthesis)
|
||||||
|
@ -64,8 +67,16 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(SpeechSynthesis)
|
||||||
SpeechSynthesis::SpeechSynthesis(nsPIDOMWindow* aParent)
|
SpeechSynthesis::SpeechSynthesis(nsPIDOMWindow* aParent)
|
||||||
: mParent(aParent)
|
: mParent(aParent)
|
||||||
, mHoldQueue(false)
|
, mHoldQueue(false)
|
||||||
|
, mInnerID(aParent->WindowID())
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aParent->IsInnerWindow());
|
MOZ_ASSERT(aParent->IsInnerWindow());
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||||
|
if (obs) {
|
||||||
|
obs->AddObserver(this, "inner-window-destroyed", true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeechSynthesis::~SpeechSynthesis()
|
SpeechSynthesis::~SpeechSynthesis()
|
||||||
|
@ -118,6 +129,12 @@ SpeechSynthesis::Paused() const
|
||||||
(!mSpeechQueue.IsEmpty() && mSpeechQueue.ElementAt(0)->IsPaused());
|
(!mSpeechQueue.IsEmpty() && mSpeechQueue.ElementAt(0)->IsPaused());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SpeechSynthesis::HasEmptyQueue() const
|
||||||
|
{
|
||||||
|
return mSpeechQueue.Length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SpeechSynthesis::Speak(SpeechSynthesisUtterance& aUtterance)
|
SpeechSynthesis::Speak(SpeechSynthesisUtterance& aUtterance)
|
||||||
{
|
{
|
||||||
|
@ -239,6 +256,8 @@ SpeechSynthesis::GetVoices(nsTArray< RefPtr<SpeechSynthesisVoice> >& aResult)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsISupports* voiceParent = NS_ISUPPORTS_CAST(nsIObserver*, this);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < voiceCount; i++) {
|
for (uint32_t i = 0; i < voiceCount; i++) {
|
||||||
nsAutoString uri;
|
nsAutoString uri;
|
||||||
rv = nsSynthVoiceRegistry::GetInstance()->GetVoice(i, uri);
|
rv = nsSynthVoiceRegistry::GetInstance()->GetVoice(i, uri);
|
||||||
|
@ -251,7 +270,7 @@ SpeechSynthesis::GetVoices(nsTArray< RefPtr<SpeechSynthesisVoice> >& aResult)
|
||||||
SpeechSynthesisVoice* voice = mVoiceCache.GetWeak(uri);
|
SpeechSynthesisVoice* voice = mVoiceCache.GetWeak(uri);
|
||||||
|
|
||||||
if (!voice) {
|
if (!voice) {
|
||||||
voice = new SpeechSynthesisVoice(this, uri);
|
voice = new SpeechSynthesisVoice(voiceParent, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
aResult.AppendElement(voice);
|
aResult.AppendElement(voice);
|
||||||
|
@ -275,5 +294,36 @@ SpeechSynthesis::ForceEnd()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SpeechSynthesis::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
|
const char16_t* aData)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (strcmp(aTopic, "inner-window-destroyed")) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
|
||||||
|
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
uint64_t innerID;
|
||||||
|
nsresult rv = wrapper->GetData(&innerID);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (innerID == mInnerID) {
|
||||||
|
if (mCurrentTask) {
|
||||||
|
mCurrentTask->Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||||
|
if (obs) {
|
||||||
|
obs->RemoveObserver(this, "inner-window-destroyed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
#define mozilla_dom_SpeechSynthesis_h
|
#define mozilla_dom_SpeechSynthesis_h
|
||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsString.h"
|
#include "nsIObserver.h"
|
||||||
#include "nsWrapperCache.h"
|
|
||||||
#include "nsRefPtrHashtable.h"
|
#include "nsRefPtrHashtable.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
#include "js/TypeDecls.h"
|
#include "js/TypeDecls.h"
|
||||||
|
|
||||||
#include "SpeechSynthesisUtterance.h"
|
#include "SpeechSynthesisUtterance.h"
|
||||||
|
@ -23,14 +25,17 @@ namespace dom {
|
||||||
|
|
||||||
class nsSpeechTask;
|
class nsSpeechTask;
|
||||||
|
|
||||||
class SpeechSynthesis final : public nsISupports,
|
class SpeechSynthesis final : public nsIObserver
|
||||||
public nsWrapperCache
|
, public nsWrapperCache
|
||||||
|
, public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SpeechSynthesis(nsPIDOMWindow* aParent);
|
explicit SpeechSynthesis(nsPIDOMWindow* aParent);
|
||||||
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(SpeechSynthesis)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(SpeechSynthesis,
|
||||||
|
nsIObserver)
|
||||||
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
nsIDOMWindow* GetParentObject() const;
|
nsIDOMWindow* GetParentObject() const;
|
||||||
|
|
||||||
|
@ -42,6 +47,8 @@ public:
|
||||||
|
|
||||||
bool Paused() const;
|
bool Paused() const;
|
||||||
|
|
||||||
|
bool HasEmptyQueue() const;
|
||||||
|
|
||||||
void Speak(SpeechSynthesisUtterance& aUtterance);
|
void Speak(SpeechSynthesisUtterance& aUtterance);
|
||||||
|
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
@ -70,6 +77,8 @@ private:
|
||||||
nsRefPtrHashtable<nsStringHashKey, SpeechSynthesisVoice> mVoiceCache;
|
nsRefPtrHashtable<nsStringHashKey, SpeechSynthesisVoice> mVoiceCache;
|
||||||
|
|
||||||
bool mHoldQueue;
|
bool mHoldQueue;
|
||||||
|
|
||||||
|
uint64_t mInnerID;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -82,7 +82,11 @@ SpeechSynthesisRequestParent::SpeechSynthesisRequestParent(SpeechTaskParent* aTa
|
||||||
|
|
||||||
SpeechSynthesisRequestParent::~SpeechSynthesisRequestParent()
|
SpeechSynthesisRequestParent::~SpeechSynthesisRequestParent()
|
||||||
{
|
{
|
||||||
|
if (mTask) {
|
||||||
|
mTask->mActor = nullptr;
|
||||||
|
// If we still have a task, cancel it.
|
||||||
|
mTask->Cancel();
|
||||||
|
}
|
||||||
MOZ_COUNT_DTOR(SpeechSynthesisRequestParent);
|
MOZ_COUNT_DTOR(SpeechSynthesisRequestParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +161,11 @@ SpeechTaskParent::DispatchStartImpl(const nsAString& aUri)
|
||||||
nsresult
|
nsresult
|
||||||
SpeechTaskParent::DispatchEndImpl(float aElapsedTime, uint32_t aCharIndex)
|
SpeechTaskParent::DispatchEndImpl(float aElapsedTime, uint32_t aCharIndex)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mActor);
|
if (!mActor) {
|
||||||
|
// Child is already gone.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if(NS_WARN_IF(!(mActor->SendOnEnd(false, aElapsedTime, aCharIndex)))) {
|
if(NS_WARN_IF(!(mActor->SendOnEnd(false, aElapsedTime, aCharIndex)))) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,11 +498,17 @@ nsSpeechTask::DispatchResumeImpl(float aElapsedTime, uint32_t aCharIndex)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSpeechTask::DispatchError(float aElapsedTime, uint32_t aCharIndex)
|
nsSpeechTask::DispatchError(float aElapsedTime, uint32_t aCharIndex)
|
||||||
{
|
{
|
||||||
|
LOG(LogLevel::Debug, ("nsSpeechTask::DispatchError"));
|
||||||
|
|
||||||
if (!mIndirectAudio) {
|
if (!mIndirectAudio) {
|
||||||
NS_WARNING("Can't call DispatchError() from a direct audio speech service");
|
NS_WARNING("Can't call DispatchError() from a direct audio speech service");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mPreCanceled) {
|
||||||
|
nsSynthVoiceRegistry::GetInstance()->SpeakNext();
|
||||||
|
}
|
||||||
|
|
||||||
return DispatchErrorImpl(aElapsedTime, aCharIndex);
|
return DispatchErrorImpl(aElapsedTime, aCharIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,6 +520,10 @@ nsSpeechTask::DispatchErrorImpl(float aElapsedTime, uint32_t aCharIndex)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSpeechSynthesis) {
|
||||||
|
mSpeechSynthesis->OnEnd(this);
|
||||||
|
}
|
||||||
|
|
||||||
mUtterance->mState = SpeechSynthesisUtterance::STATE_ENDED;
|
mUtterance->mState = SpeechSynthesisUtterance::STATE_ENDED;
|
||||||
mUtterance->DispatchSpeechSynthesisEvent(NS_LITERAL_STRING("error"),
|
mUtterance->DispatchSpeechSynthesisEvent(NS_LITERAL_STRING("error"),
|
||||||
aCharIndex, aElapsedTime,
|
aCharIndex, aElapsedTime,
|
||||||
|
|
|
@ -14,8 +14,6 @@ function synthTestQueue(aTestArgs, aEndFunc) {
|
||||||
is(e.target, utterances.shift(), "Target matches utterances");
|
is(e.target, utterances.shift(), "Target matches utterances");
|
||||||
ok(!speechSynthesis.speaking, "speechSynthesis is not speaking.");
|
ok(!speechSynthesis.speaking, "speechSynthesis is not speaking.");
|
||||||
|
|
||||||
isnot(e.eventType, 'error', "Error in utterance");
|
|
||||||
|
|
||||||
if (utterances.length) {
|
if (utterances.length) {
|
||||||
ok(speechSynthesis.pending, "other utterances queued");
|
ok(speechSynthesis.pending, "other utterances queued");
|
||||||
} else {
|
} else {
|
||||||
|
@ -38,10 +36,12 @@ function synthTestQueue(aTestArgs, aEndFunc) {
|
||||||
u.addEventListener('end', onend_handler);
|
u.addEventListener('end', onend_handler);
|
||||||
u.addEventListener('error', onend_handler);
|
u.addEventListener('error', onend_handler);
|
||||||
|
|
||||||
u.addEventListener(
|
u.addEventListener('error',
|
||||||
'error', function onerror_handler(e) {
|
(function (expectedError) {
|
||||||
ok(false, "Error in speech utterance '" + e.target.text + "'");
|
return function onerror_handler(e) {
|
||||||
});
|
ok(expectedError, "Error in speech utterance '" + e.target.text + "'");
|
||||||
|
};
|
||||||
|
})(aTestArgs[i][1] ? aTestArgs[i][1].err : false));
|
||||||
|
|
||||||
utterances.push(u);
|
utterances.push(u);
|
||||||
win.speechSynthesis.speak(u);
|
win.speechSynthesis.speak(u);
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<script type="application/javascript">
|
||||||
|
var frameUnloaded = function() {
|
||||||
|
var u = new SpeechSynthesisUtterance('hi');
|
||||||
|
u.addEventListener('end', function () {
|
||||||
|
parent.ok(true, 'Successfully spoke utterance from new frame.');
|
||||||
|
parent.onDone();
|
||||||
|
});
|
||||||
|
speechSynthesis.speak(u);
|
||||||
|
}
|
||||||
|
addEventListener('pageshow', function onshow(evt) {
|
||||||
|
var u = new SpeechSynthesisUtterance('hello');
|
||||||
|
u.lang = 'it-IT-noend';
|
||||||
|
u.addEventListener('start', function() {
|
||||||
|
location =
|
||||||
|
'data:text/html,<html><body onpageshow="' +
|
||||||
|
frameUnloaded.toSource() + '()"></body></html>';
|
||||||
|
});
|
||||||
|
speechSynthesis.speak(u);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -28,7 +28,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1226015
|
||||||
|
|
||||||
function testFunc(done_cb) {
|
function testFunc(done_cb) {
|
||||||
var utterance = new SpeechSynthesisUtterance();
|
var utterance = new SpeechSynthesisUtterance();
|
||||||
utterance.lang = 'it-IT-error';
|
utterance.lang = 'it-IT-failatstart';
|
||||||
|
|
||||||
speechSynthesis.speak(utterance);
|
speechSynthesis.speak(utterance);
|
||||||
speechSynthesis.cancel();
|
speechSynthesis.cancel();
|
||||||
|
|
|
@ -30,9 +30,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=525444
|
||||||
var langUriMap = {};
|
var langUriMap = {};
|
||||||
|
|
||||||
for (var voice of speechSynthesis.getVoices()) {
|
for (var voice of speechSynthesis.getVoices()) {
|
||||||
if (voice.voiceURI.indexOf('urn:moz-tts:fake-direct') < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
langUriMap[voice.lang] = voice.voiceURI;
|
langUriMap[voice.lang] = voice.voiceURI;
|
||||||
ok(true, voice.lang + ' ' + voice.voiceURI + ' ' + voice.default);
|
ok(true, voice.lang + ' ' + voice.voiceURI + ' ' + voice.default);
|
||||||
is(voice.default, voice.lang == 'en-JM', 'Only Jamaican voice should be default');
|
is(voice.default, voice.lang == 'en-JM', 'Only Jamaican voice should be default');
|
||||||
|
@ -43,6 +40,7 @@ ok(langUriMap['en-GB'], 'No English-British voice');
|
||||||
ok(langUriMap['en-CA'], 'No English-Canadian voice');
|
ok(langUriMap['en-CA'], 'No English-Canadian voice');
|
||||||
ok(langUriMap['fr-CA'], 'No French-Canadian voice');
|
ok(langUriMap['fr-CA'], 'No French-Canadian voice');
|
||||||
ok(langUriMap['es-MX'], 'No Spanish-Mexican voice');
|
ok(langUriMap['es-MX'], 'No Spanish-Mexican voice');
|
||||||
|
ok(langUriMap['it-IT-fail'], 'No Failing Italian voice');
|
||||||
|
|
||||||
function testFunc(done_cb) {
|
function testFunc(done_cb) {
|
||||||
synthTestQueue(
|
synthTestQueue(
|
||||||
|
@ -53,6 +51,8 @@ function testFunc(done_cb) {
|
||||||
{ uri: langUriMap['fr-CA'], rate: 0.5, pitch: 0.75}],
|
{ uri: langUriMap['fr-CA'], rate: 0.5, pitch: 0.75}],
|
||||||
[{text: "How are you doing?", args: { lang: "en-GB" } },
|
[{text: "How are you doing?", args: { lang: "en-GB" } },
|
||||||
{ rate: 1, pitch: 1, uri: langUriMap['en-GB']}],
|
{ rate: 1, pitch: 1, uri: langUriMap['en-GB']}],
|
||||||
|
[{text: "Come stai?", args: { lang: "it-IT-fail" } },
|
||||||
|
{ rate: 1, pitch: 1, uri: langUriMap['it-IT-fail'], err: true }],
|
||||||
[{text: "¡hasta mañana!", args: { lang: "es-MX" } },
|
[{text: "¡hasta mañana!", args: { lang: "es-MX" } },
|
||||||
{ uri: langUriMap['es-MX'] }]],
|
{ uri: langUriMap['es-MX'] }]],
|
||||||
function () {
|
function () {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
tags=msg
|
tags=msg
|
||||||
support-files =
|
support-files =
|
||||||
common.js
|
common.js
|
||||||
|
file_bfcache_frame.html
|
||||||
file_setup.html
|
file_setup.html
|
||||||
file_speech_queue.html
|
file_speech_queue.html
|
||||||
file_speech_simple.html
|
file_speech_simple.html
|
||||||
|
@ -21,3 +22,4 @@ support-files =
|
||||||
[test_global_queue.html]
|
[test_global_queue.html]
|
||||||
[test_global_queue_cancel.html]
|
[test_global_queue_cancel.html]
|
||||||
[test_global_queue_pause.html]
|
[test_global_queue_pause.html]
|
||||||
|
[test_bfcache.html]
|
|
@ -31,7 +31,8 @@ enum VoiceFlags
|
||||||
{
|
{
|
||||||
eSuppressEvents = 1,
|
eSuppressEvents = 1,
|
||||||
eSuppressEnd = 2,
|
eSuppressEnd = 2,
|
||||||
eFailAtStart = 4
|
eFailAtStart = 4,
|
||||||
|
eFail = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VoiceDetails
|
struct VoiceDetails
|
||||||
|
@ -55,7 +56,8 @@ static const VoiceDetails sIndirectVoices[] = {
|
||||||
{"urn:moz-tts:fake-indirect:zanetta", "Zanetta Farussi", "it-IT", false, 0},
|
{"urn:moz-tts:fake-indirect:zanetta", "Zanetta Farussi", "it-IT", false, 0},
|
||||||
{"urn:moz-tts:fake-indirect:margherita", "Margherita Durastanti", "it-IT-noevents-noend", false, eSuppressEvents | eSuppressEnd},
|
{"urn:moz-tts:fake-indirect:margherita", "Margherita Durastanti", "it-IT-noevents-noend", false, eSuppressEvents | eSuppressEnd},
|
||||||
{"urn:moz-tts:fake-indirect:teresa", "Teresa Cornelys", "it-IT-noend", false, eSuppressEnd},
|
{"urn:moz-tts:fake-indirect:teresa", "Teresa Cornelys", "it-IT-noend", false, eSuppressEnd},
|
||||||
{"urn:moz-tts:fake-indirect:cecilia", "Cecilia Bartoli", "it-IT-error", false, eFailAtStart},
|
{"urn:moz-tts:fake-indirect:cecilia", "Cecilia Bartoli", "it-IT-failatstart", false, eFailAtStart},
|
||||||
|
{"urn:moz-tts:fake-indirect:gottardo", "Gottardo Aldighieri", "it-IT-fail", false, eFail},
|
||||||
};
|
};
|
||||||
|
|
||||||
// FakeSynthCallback
|
// FakeSynthCallback
|
||||||
|
@ -238,6 +240,26 @@ FakeIndirectAudioSynth::Speak(const nsAString& aText, const nsAString& aUri,
|
||||||
nsString mText;
|
nsString mText;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DispatchError final : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DispatchError(nsISpeechTask* aTask, const nsAString& aText) :
|
||||||
|
mTask(aTask), mText(aText)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() override
|
||||||
|
{
|
||||||
|
mTask->DispatchError(mText.Length()/2, mText.Length());
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsCOMPtr<nsISpeechTask> mTask;
|
||||||
|
nsString mText;
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
for (uint32_t i = 0; i < ArrayLength(sIndirectVoices); i++) {
|
for (uint32_t i = 0; i < ArrayLength(sIndirectVoices); i++) {
|
||||||
if (aUri.EqualsASCII(sIndirectVoices[i].uri)) {
|
if (aUri.EqualsASCII(sIndirectVoices[i].uri)) {
|
||||||
|
@ -258,7 +280,10 @@ FakeIndirectAudioSynth::Speak(const nsAString& aText, const nsAString& aUri,
|
||||||
nsCOMPtr<nsIRunnable> runnable = new DispatchStart(aTask);
|
nsCOMPtr<nsIRunnable> runnable = new DispatchStart(aTask);
|
||||||
NS_DispatchToMainThread(runnable);
|
NS_DispatchToMainThread(runnable);
|
||||||
|
|
||||||
if ((flags & eSuppressEnd) == 0) {
|
if (flags & eFail) {
|
||||||
|
runnable = new DispatchError(aTask, aText);
|
||||||
|
NS_DispatchToMainThread(runnable);
|
||||||
|
} else if ((flags & eSuppressEnd) == 0) {
|
||||||
runnable = new DispatchEnd(aTask, aText);
|
runnable = new DispatchEnd(aTask, aText);
|
||||||
NS_DispatchToMainThread(runnable);
|
NS_DispatchToMainThread(runnable);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1230533
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 1230533: Test speech is stopped from a window when unloaded</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="common.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1230533">Mozilla Bug 1230533</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<iframe id="testFrame"></iframe>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 525444 **/
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
|
||||||
|
var iframe;
|
||||||
|
|
||||||
|
function onDone() {
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
function doTest() {
|
||||||
|
iframe = document.getElementById("testFrame");
|
||||||
|
iframe.src = "file_bfcache_frame.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
SpecialPowers.pushPrefEnv({ set: [
|
||||||
|
['media.webspeech.synth.enabled', true],
|
||||||
|
['media.webspeech.synth.force_global_queue', true],
|
||||||
|
['browser.sessionhistory.cache_subframes', true],
|
||||||
|
['browser.sessionhistory.max_total_viewers', 10]] }, doTest());
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -304,19 +304,18 @@ PluginPRLibrary::SetBackgroundUnknown(NPP instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PluginPRLibrary::BeginUpdateBackground(NPP instance,
|
PluginPRLibrary::BeginUpdateBackground(NPP instance, const nsIntRect&,
|
||||||
const nsIntRect&, gfxContext** aCtx)
|
DrawTarget** aDrawTarget)
|
||||||
{
|
{
|
||||||
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
|
nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
|
||||||
NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
|
NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
|
||||||
NS_ERROR("Unexpected use of async APIs for in-process plugin.");
|
NS_ERROR("Unexpected use of async APIs for in-process plugin.");
|
||||||
*aCtx = nullptr;
|
*aDrawTarget = nullptr;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PluginPRLibrary::EndUpdateBackground(NPP instance,
|
PluginPRLibrary::EndUpdateBackground(NPP instance, const nsIntRect&)
|
||||||
gfxContext*, const nsIntRect&)
|
|
||||||
{
|
{
|
||||||
NS_RUNTIMEABORT("This should never be called");
|
NS_RUNTIMEABORT("This should never be called");
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
|
@ -117,10 +117,10 @@ public:
|
||||||
virtual nsresult ContentsScaleFactorChanged(NPP aInstance, double aContentsScaleFactor) override;
|
virtual nsresult ContentsScaleFactorChanged(NPP aInstance, double aContentsScaleFactor) override;
|
||||||
#endif
|
#endif
|
||||||
virtual nsresult SetBackgroundUnknown(NPP instance) override;
|
virtual nsresult SetBackgroundUnknown(NPP instance) override;
|
||||||
virtual nsresult BeginUpdateBackground(NPP instance,
|
virtual nsresult BeginUpdateBackground(NPP instance, const nsIntRect&,
|
||||||
const nsIntRect&, gfxContext** aCtx) override;
|
DrawTarget** aDrawTarget) override;
|
||||||
virtual nsresult EndUpdateBackground(NPP instance,
|
virtual nsresult EndUpdateBackground(NPP instance,
|
||||||
gfxContext* aCtx, const nsIntRect&) override;
|
const nsIntRect&) override;
|
||||||
virtual void DidComposite(NPP aInstance) override { }
|
virtual void DidComposite(NPP aInstance) override { }
|
||||||
virtual void GetLibraryPath(nsACString& aPath) { aPath.Assign(mFilePath); }
|
virtual void GetLibraryPath(nsACString& aPath) { aPath.Assign(mFilePath); }
|
||||||
virtual nsresult GetRunID(uint32_t* aRunID) override { return NS_ERROR_NOT_IMPLEMENTED; }
|
virtual nsresult GetRunID(uint32_t* aRunID) override { return NS_ERROR_NOT_IMPLEMENTED; }
|
||||||
|
|
|
@ -1250,7 +1250,7 @@ nsNPAPIPluginInstance::SetBackgroundUnknown()
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
|
nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
|
||||||
gfxContext** aContext)
|
DrawTarget** aDrawTarget)
|
||||||
{
|
{
|
||||||
if (RUNNING != mRunning)
|
if (RUNNING != mRunning)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -1259,12 +1259,11 @@ nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
|
||||||
if (!library)
|
if (!library)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
return library->BeginUpdateBackground(&mNPP, *aRect, aContext);
|
return library->BeginUpdateBackground(&mNPP, *aRect, aDrawTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsNPAPIPluginInstance::EndUpdateBackground(gfxContext* aContext,
|
nsNPAPIPluginInstance::EndUpdateBackground(nsIntRect* aRect)
|
||||||
nsIntRect* aRect)
|
|
||||||
{
|
{
|
||||||
if (RUNNING != mRunning)
|
if (RUNNING != mRunning)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -1273,7 +1272,7 @@ nsNPAPIPluginInstance::EndUpdateBackground(gfxContext* aContext,
|
||||||
if (!library)
|
if (!library)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
return library->EndUpdateBackground(&mNPP, aContext, *aRect);
|
return library->EndUpdateBackground(&mNPP, *aRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
|
|
@ -83,6 +83,8 @@ private:
|
||||||
typedef mozilla::PluginLibrary PluginLibrary;
|
typedef mozilla::PluginLibrary PluginLibrary;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||||
|
|
||||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsNPAPIPluginInstance)
|
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsNPAPIPluginInstance)
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
|
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
|
||||||
|
@ -108,8 +110,8 @@ public:
|
||||||
nsresult NotifyPainted(void);
|
nsresult NotifyPainted(void);
|
||||||
nsresult GetIsOOP(bool* aIsOOP);
|
nsresult GetIsOOP(bool* aIsOOP);
|
||||||
nsresult SetBackgroundUnknown();
|
nsresult SetBackgroundUnknown();
|
||||||
nsresult BeginUpdateBackground(nsIntRect* aRect, gfxContext** aContext);
|
nsresult BeginUpdateBackground(nsIntRect* aRect, DrawTarget** aContext);
|
||||||
nsresult EndUpdateBackground(gfxContext* aContext, nsIntRect* aRect);
|
nsresult EndUpdateBackground(nsIntRect* aRect);
|
||||||
nsresult IsTransparent(bool* isTransparent);
|
nsresult IsTransparent(bool* isTransparent);
|
||||||
nsresult GetFormValue(nsAString& aValue);
|
nsresult GetFormValue(nsAString& aValue);
|
||||||
nsresult PushPopupsEnabledState(bool aEnabled);
|
nsresult PushPopupsEnabledState(bool aEnabled);
|
||||||
|
|
|
@ -268,25 +268,24 @@ nsPluginInstanceOwner::SetBackgroundUnknown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<gfxContext>
|
already_AddRefed<mozilla::gfx::DrawTarget>
|
||||||
nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect)
|
nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect)
|
||||||
{
|
{
|
||||||
nsIntRect rect = aRect;
|
nsIntRect rect = aRect;
|
||||||
RefPtr<gfxContext> ctx;
|
RefPtr<DrawTarget> dt;
|
||||||
if (mInstance &&
|
if (mInstance &&
|
||||||
NS_SUCCEEDED(mInstance->BeginUpdateBackground(&rect, getter_AddRefs(ctx)))) {
|
NS_SUCCEEDED(mInstance->BeginUpdateBackground(&rect, getter_AddRefs(dt)))) {
|
||||||
return ctx.forget();
|
return dt.forget();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsPluginInstanceOwner::EndUpdateBackground(gfxContext* aContext,
|
nsPluginInstanceOwner::EndUpdateBackground(const nsIntRect& aRect)
|
||||||
const nsIntRect& aRect)
|
|
||||||
{
|
{
|
||||||
nsIntRect rect = aRect;
|
nsIntRect rect = aRect;
|
||||||
if (mInstance) {
|
if (mInstance) {
|
||||||
mInstance->EndUpdateBackground(aContext, &rect);
|
mInstance->EndUpdateBackground(&rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,10 @@ class nsPluginDOMContextMenuListener;
|
||||||
class nsPluginFrame;
|
class nsPluginFrame;
|
||||||
class nsDisplayListBuilder;
|
class nsDisplayListBuilder;
|
||||||
|
|
||||||
|
#if defined(MOZ_X11) || defined(ANDROID)
|
||||||
|
class gfxContext;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
class TextComposition;
|
class TextComposition;
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -54,6 +58,8 @@ class nsPluginInstanceOwner final : public nsIPluginInstanceOwner,
|
||||||
public nsSupportsWeakReference
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||||
|
|
||||||
nsPluginInstanceOwner();
|
nsPluginInstanceOwner();
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
@ -236,9 +242,9 @@ public:
|
||||||
// The eventual target of these operations is PluginInstanceParent,
|
// The eventual target of these operations is PluginInstanceParent,
|
||||||
// but it takes several hops to get there.
|
// but it takes several hops to get there.
|
||||||
void SetBackgroundUnknown();
|
void SetBackgroundUnknown();
|
||||||
already_AddRefed<gfxContext> BeginUpdateBackground(const nsIntRect& aRect);
|
already_AddRefed<DrawTarget> BeginUpdateBackground(const nsIntRect& aRect);
|
||||||
void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect);
|
void EndUpdateBackground(const nsIntRect& aRect);
|
||||||
|
|
||||||
bool UseAsyncRendering();
|
bool UseAsyncRendering();
|
||||||
|
|
||||||
already_AddRefed<nsIURI> GetBaseURI() const;
|
already_AddRefed<nsIURI> GetBaseURI() const;
|
||||||
|
|
|
@ -1130,7 +1130,7 @@ PluginInstanceParent::SetBackgroundUnknown()
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
|
PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
|
||||||
gfxContext** aCtx)
|
DrawTarget** aDrawTarget)
|
||||||
{
|
{
|
||||||
PLUGIN_LOG_DEBUG(
|
PLUGIN_LOG_DEBUG(
|
||||||
("[InstanceParent][%p] BeginUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
|
("[InstanceParent][%p] BeginUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
|
||||||
|
@ -1144,7 +1144,7 @@ PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
|
||||||
MOZ_ASSERT(aRect.TopLeft() == nsIntPoint(0, 0),
|
MOZ_ASSERT(aRect.TopLeft() == nsIntPoint(0, 0),
|
||||||
"Expecting rect for whole frame");
|
"Expecting rect for whole frame");
|
||||||
if (!CreateBackground(aRect.Size())) {
|
if (!CreateBackground(aRect.Size())) {
|
||||||
*aCtx = nullptr;
|
*aDrawTarget = nullptr;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1157,15 +1157,13 @@ PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
|
||||||
|
|
||||||
RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
|
RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
|
||||||
CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height));
|
CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height));
|
||||||
RefPtr<gfxContext> ctx = new gfxContext(dt);
|
dt.forget(aDrawTarget);
|
||||||
ctx.forget(aCtx);
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
PluginInstanceParent::EndUpdateBackground(gfxContext* aCtx,
|
PluginInstanceParent::EndUpdateBackground(const nsIntRect& aRect)
|
||||||
const nsIntRect& aRect)
|
|
||||||
{
|
{
|
||||||
PLUGIN_LOG_DEBUG(
|
PLUGIN_LOG_DEBUG(
|
||||||
("[InstanceParent][%p] EndUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
|
("[InstanceParent][%p] EndUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
|
||||||
|
|
|
@ -60,6 +60,8 @@ public:
|
||||||
#endif // defined(XP_WIN)
|
#endif // defined(XP_WIN)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||||
|
|
||||||
PluginInstanceParent(PluginModuleParent* parent,
|
PluginInstanceParent(PluginModuleParent* parent,
|
||||||
NPP npp,
|
NPP npp,
|
||||||
const nsCString& mimeType,
|
const nsCString& mimeType,
|
||||||
|
@ -338,9 +340,8 @@ public:
|
||||||
#endif
|
#endif
|
||||||
nsresult SetBackgroundUnknown();
|
nsresult SetBackgroundUnknown();
|
||||||
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
||||||
gfxContext** aCtx);
|
DrawTarget** aDrawTarget);
|
||||||
nsresult EndUpdateBackground(gfxContext* aCtx,
|
nsresult EndUpdateBackground(const nsIntRect& aRect);
|
||||||
const nsIntRect& aRect);
|
|
||||||
void DidComposite();
|
void DidComposite();
|
||||||
|
|
||||||
bool IsUsingDirectDrawing();
|
bool IsUsingDirectDrawing();
|
||||||
|
|
|
@ -17,11 +17,13 @@
|
||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
|
|
||||||
class gfxContext;
|
|
||||||
class nsCString;
|
class nsCString;
|
||||||
class nsNPAPIPlugin;
|
class nsNPAPIPlugin;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
namespace gfx {
|
||||||
|
class DrawTarget;
|
||||||
|
}
|
||||||
namespace layers {
|
namespace layers {
|
||||||
class Image;
|
class Image;
|
||||||
class ImageContainer;
|
class ImageContainer;
|
||||||
|
@ -43,6 +45,8 @@ namespace mozilla {
|
||||||
class PluginLibrary
|
class PluginLibrary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||||
|
|
||||||
virtual ~PluginLibrary() { }
|
virtual ~PluginLibrary() { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,14 +95,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual nsresult SetBackgroundUnknown(NPP instance) = 0;
|
virtual nsresult SetBackgroundUnknown(NPP instance) = 0;
|
||||||
virtual nsresult BeginUpdateBackground(NPP instance,
|
virtual nsresult BeginUpdateBackground(NPP instance,
|
||||||
const nsIntRect&, gfxContext**) = 0;
|
const nsIntRect&, DrawTarget**) = 0;
|
||||||
virtual nsresult EndUpdateBackground(NPP instance,
|
virtual nsresult EndUpdateBackground(NPP instance, const nsIntRect&) = 0;
|
||||||
gfxContext*, const nsIntRect&) = 0;
|
|
||||||
virtual nsresult GetRunID(uint32_t* aRunID) = 0;
|
virtual nsresult GetRunID(uint32_t* aRunID) = 0;
|
||||||
virtual void SetHasLocalInstance() = 0;
|
virtual void SetHasLocalInstance() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // ifndef mozilla_PluginLibrary_h
|
#endif // ifndef mozilla_PluginLibrary_h
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче