mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 06:45:42 +00:00
Merge mozilla-central to fx-team
This commit is contained in:
commit
8a86055b89
@ -12,6 +12,7 @@
|
|||||||
#include "nsMai.h"
|
#include "nsMai.h"
|
||||||
#include "nsIAccessibleTypes.h"
|
#include "nsIAccessibleTypes.h"
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
|
#include "ProxyAccessible.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::a11y;
|
using namespace mozilla::a11y;
|
||||||
@ -23,15 +24,19 @@ static void
|
|||||||
getImagePositionCB(AtkImage* aImage, gint* aAccX, gint* aAccY,
|
getImagePositionCB(AtkImage* aImage, gint* aAccX, gint* aAccY,
|
||||||
AtkCoordType aCoordType)
|
AtkCoordType aCoordType)
|
||||||
{
|
{
|
||||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
|
nsIntPoint pos;
|
||||||
if (!accWrap || !accWrap->IsImage())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ImageAccessible* image = accWrap->AsImage();
|
|
||||||
uint32_t geckoCoordType = (aCoordType == ATK_XY_WINDOW) ?
|
uint32_t geckoCoordType = (aCoordType == ATK_XY_WINDOW) ?
|
||||||
nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE :
|
nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE :
|
||||||
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
|
nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
|
||||||
nsIntPoint pos = image->Position(geckoCoordType);
|
|
||||||
|
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
|
||||||
|
if (accWrap && accWrap->IsImage()) {
|
||||||
|
ImageAccessible* image = accWrap->AsImage();
|
||||||
|
pos = image->Position(geckoCoordType);
|
||||||
|
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aImage))) {
|
||||||
|
pos = proxy->ImagePosition(geckoCoordType);
|
||||||
|
}
|
||||||
|
|
||||||
*aAccX = pos.x;
|
*aAccX = pos.x;
|
||||||
*aAccY = pos.y;
|
*aAccY = pos.y;
|
||||||
}
|
}
|
||||||
@ -45,11 +50,14 @@ getImageDescriptionCB(AtkImage* aImage)
|
|||||||
static void
|
static void
|
||||||
getImageSizeCB(AtkImage* aImage, gint* aAccWidth, gint* aAccHeight)
|
getImageSizeCB(AtkImage* aImage, gint* aAccWidth, gint* aAccHeight)
|
||||||
{
|
{
|
||||||
|
nsIntSize size;
|
||||||
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
|
AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImage));
|
||||||
if (!accWrap || !accWrap->IsImage())
|
if (accWrap && accWrap->IsImage()) {
|
||||||
return;
|
size = accWrap->AsImage()->Size();
|
||||||
|
} else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aImage))) {
|
||||||
|
size = proxy->ImageSize();
|
||||||
|
}
|
||||||
|
|
||||||
nsIntSize size = accWrap->AsImage()->Size();
|
|
||||||
*aAccWidth = size.width;
|
*aAccWidth = size.width;
|
||||||
*aAccHeight = size.height;
|
*aAccHeight = size.height;
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "ProxyAccessible.h"
|
#include "ProxyAccessible.h"
|
||||||
#include "Relation.h"
|
#include "Relation.h"
|
||||||
#include "HyperTextAccessible-inl.h"
|
#include "HyperTextAccessible-inl.h"
|
||||||
|
#include "ImageAccessible.h"
|
||||||
#include "nsIPersistentProperties2.h"
|
#include "nsIPersistentProperties2.h"
|
||||||
#include "nsISimpleEnumerator.h"
|
#include "nsISimpleEnumerator.h"
|
||||||
|
|
||||||
@ -46,19 +47,26 @@ SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Accessible*
|
Accessible*
|
||||||
DocAccessibleChild::IdToAccessible(const uint64_t& aID)
|
DocAccessibleChild::IdToAccessible(const uint64_t& aID) const
|
||||||
{
|
{
|
||||||
return mDoc->GetAccessibleByUniqueID(reinterpret_cast<void*>(aID));
|
return mDoc->GetAccessibleByUniqueID(reinterpret_cast<void*>(aID));
|
||||||
}
|
}
|
||||||
|
|
||||||
HyperTextAccessible*
|
HyperTextAccessible*
|
||||||
DocAccessibleChild::IdToHyperTextAccessible(const uint64_t& aID)
|
DocAccessibleChild::IdToHyperTextAccessible(const uint64_t& aID) const
|
||||||
{
|
{
|
||||||
Accessible* acc = IdToAccessible(aID);
|
Accessible* acc = IdToAccessible(aID);
|
||||||
MOZ_ASSERT(!acc || acc->IsHyperText());
|
MOZ_ASSERT(!acc || acc->IsHyperText());
|
||||||
return acc ? acc->AsHyperText() : nullptr;
|
return acc ? acc->AsHyperText() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageAccessible*
|
||||||
|
DocAccessibleChild::IdToImageAccessible(const uint64_t& aID) const
|
||||||
|
{
|
||||||
|
Accessible* acc = IdToAccessible(aID);
|
||||||
|
return (acc && acc->IsImage()) ? acc->AsImage() : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DocAccessibleChild::ShowEvent(AccShowEvent* aShowEvent)
|
DocAccessibleChild::ShowEvent(AccShowEvent* aShowEvent)
|
||||||
{
|
{
|
||||||
@ -584,5 +592,31 @@ DocAccessibleChild::RecvPasteText(const uint64_t& aID,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DocAccessibleChild::RecvImagePosition(const uint64_t& aID,
|
||||||
|
const uint32_t& aCoordType,
|
||||||
|
nsIntPoint* aRetVal)
|
||||||
|
{
|
||||||
|
ImageAccessible* acc = IdToImageAccessible(aID);
|
||||||
|
if (acc) {
|
||||||
|
*aRetVal = acc->Position(aCoordType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
DocAccessibleChild::RecvImageSize(const uint64_t& aID,
|
||||||
|
nsIntSize* aRetVal)
|
||||||
|
{
|
||||||
|
|
||||||
|
ImageAccessible* acc = IdToImageAccessible(aID);
|
||||||
|
if (acc) {
|
||||||
|
*aRetVal = acc->Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ namespace mozilla {
|
|||||||
namespace a11y {
|
namespace a11y {
|
||||||
class Accessible;
|
class Accessible;
|
||||||
class HyperTextAccessible;
|
class HyperTextAccessible;
|
||||||
|
class ImageAccessible;
|
||||||
|
|
||||||
class AccShowEvent;
|
class AccShowEvent;
|
||||||
|
|
||||||
@ -34,9 +35,6 @@ public:
|
|||||||
MOZ_COUNT_DTOR(DocAccessibleChild);
|
MOZ_COUNT_DTOR(DocAccessibleChild);
|
||||||
}
|
}
|
||||||
|
|
||||||
Accessible* IdToAccessible(const uint64_t& aID);
|
|
||||||
HyperTextAccessible* IdToHyperTextAccessible(const uint64_t& aID);
|
|
||||||
|
|
||||||
void ShowEvent(AccShowEvent* aShowEvent);
|
void ShowEvent(AccShowEvent* aShowEvent);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -184,7 +182,19 @@ public:
|
|||||||
virtual bool RecvPasteText(const uint64_t& aID,
|
virtual bool RecvPasteText(const uint64_t& aID,
|
||||||
const int32_t& aPosition) override;
|
const int32_t& aPosition) override;
|
||||||
|
|
||||||
|
virtual bool RecvImagePosition(const uint64_t& aID,
|
||||||
|
const uint32_t& aCoordType,
|
||||||
|
nsIntPoint* aRetVal) override;
|
||||||
|
|
||||||
|
virtual bool RecvImageSize(const uint64_t& aID,
|
||||||
|
nsIntSize* aRetVal) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
Accessible* IdToAccessible(const uint64_t& aID) const;
|
||||||
|
HyperTextAccessible* IdToHyperTextAccessible(const uint64_t& aID) const;
|
||||||
|
ImageAccessible* IdToImageAccessible(const uint64_t& aID) const;
|
||||||
|
|
||||||
bool PersistentPropertiesToArray(nsIPersistentProperties* aProps,
|
bool PersistentPropertiesToArray(nsIPersistentProperties* aProps,
|
||||||
nsTArray<Attribute>* aAttributes);
|
nsTArray<Attribute>* aAttributes);
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ include protocol PContent;
|
|||||||
|
|
||||||
include "mozilla/GfxMessageUtils.h";
|
include "mozilla/GfxMessageUtils.h";
|
||||||
|
|
||||||
|
using struct nsIntPoint from "nsRect.h";
|
||||||
|
using struct nsIntSize from "nsRect.h";
|
||||||
using struct nsIntRect from "nsRect.h";
|
using struct nsIntRect from "nsRect.h";
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -121,6 +123,9 @@ child:
|
|||||||
prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
|
prio(high) sync CutText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
|
||||||
prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
|
prio(high) sync DeleteText(uint64_t aID, int32_t aStartPos, int32_t aEndPos);
|
||||||
prio(high) sync PasteText(uint64_t aID, int32_t aPosition);
|
prio(high) sync PasteText(uint64_t aID, int32_t aPosition);
|
||||||
|
|
||||||
|
prio(high) sync ImagePosition(uint64_t aID, uint32_t aCoordType) returns(nsIntPoint aRetVal);
|
||||||
|
prio(high) sync ImageSize(uint64_t aID) returns(nsIntSize aRetVal);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -363,5 +363,21 @@ ProxyAccessible::PasteText(int32_t aPosition)
|
|||||||
unused << mDoc->SendPasteText(mID, aPosition);
|
unused << mDoc->SendPasteText(mID, aPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIntPoint
|
||||||
|
ProxyAccessible::ImagePosition(uint32_t aCoordType)
|
||||||
|
{
|
||||||
|
nsIntPoint retVal;
|
||||||
|
unused << mDoc->SendImagePosition(mID, aCoordType, &retVal);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIntSize
|
||||||
|
ProxyAccessible::ImageSize()
|
||||||
|
{
|
||||||
|
nsIntSize retVal;
|
||||||
|
unused << mDoc->SendImageSize(mID, &retVal);
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,10 @@ public:
|
|||||||
|
|
||||||
void PasteText(int32_t aPosition);
|
void PasteText(int32_t aPosition);
|
||||||
|
|
||||||
|
nsIntPoint ImagePosition(uint32_t aCoordType);
|
||||||
|
|
||||||
|
nsIntSize ImageSize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allow the platform to store a pointers worth of data on us.
|
* Allow the platform to store a pointers worth of data on us.
|
||||||
*/
|
*/
|
||||||
|
@ -26,6 +26,24 @@ if CONFIG['ACCESSIBILITY']:
|
|||||||
'../generic',
|
'../generic',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if CONFIG['MOZ_ENABLE_GTK']:
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'/accessible/atk',
|
||||||
|
]
|
||||||
|
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'/accessible/windows/ia2',
|
||||||
|
'/accessible/windows/msaa',
|
||||||
|
]
|
||||||
|
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'/accessible/mac',
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'/accessible/other',
|
||||||
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
||||||
include('/ipc/chromium/chromium-config.mozbuild')
|
include('/ipc/chromium/chromium-config.mozbuild')
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "9b6f3024e4d0e62dd057231f4b14abe1782932ab",
|
"git_revision": "8eac260ee81a8aca05770d18c5736536d44ee7a7",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "4c2751f5fc24ffad381aae2c50b160cba0f33d36",
|
"revision": "1400d176ecef76d06b012fb082c246eb17d1d30f",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="b685e3aab4fde7624d78993877a8f7910f2a5f06"/>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="9b6f3024e4d0e62dd057231f4b14abe1782932ab"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="8eac260ee81a8aca05770d18c5736536d44ee7a7"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="86cd7486d8e50eaac8ef6fe2f51f09d25194577b"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
|
@ -315,8 +315,10 @@ function assert_records(expected, desc) {
|
|||||||
assert_records([{ added: [firstPlayer], changed: [], removed: [] }],
|
assert_records([{ added: [firstPlayer], changed: [], removed: [] }],
|
||||||
"records after transition start");
|
"records after transition start");
|
||||||
|
|
||||||
// Wait a bit longer for the transition to take effect.
|
// Wait for the AnimationPlayer to get going, then seek well into
|
||||||
|
// the transition.
|
||||||
yield await_frame();
|
yield await_frame();
|
||||||
|
firstPlayer.currentTime = 50000;
|
||||||
|
|
||||||
// Reverse the transition by setting the background-color back to its
|
// Reverse the transition by setting the background-color back to its
|
||||||
// original value.
|
// original value.
|
||||||
@ -328,6 +330,9 @@ function assert_records(expected, desc) {
|
|||||||
|
|
||||||
var secondPlayer = players[0];
|
var secondPlayer = players[0];
|
||||||
|
|
||||||
|
ok(firstPlayer != secondPlayer,
|
||||||
|
"second AnimationPlayer should be different from the first");
|
||||||
|
|
||||||
// Wait for the single MutationRecord for the removal of the original
|
// Wait for the single MutationRecord for the removal of the original
|
||||||
// AnimationPlayer and the addition of the new AnimationPlayer to
|
// AnimationPlayer and the addition of the new AnimationPlayer to
|
||||||
// be delivered.
|
// be delivered.
|
||||||
@ -365,8 +370,10 @@ function assert_records(expected, desc) {
|
|||||||
assert_records([{ added: players, changed: [], removed: [] }],
|
assert_records([{ added: players, changed: [], removed: [] }],
|
||||||
"records after transition starts");
|
"records after transition starts");
|
||||||
|
|
||||||
// Wait for the AnimationPlayers to get going.
|
// Wait for the AnimationPlayers to get going, then seek well into
|
||||||
|
// the transitions.
|
||||||
yield await_frame();
|
yield await_frame();
|
||||||
|
players.forEach(p => p.currentTime = 50000);
|
||||||
|
|
||||||
is(players.filter(p => p.playState == "running").length, 3, "number of running AnimationPlayers");
|
is(players.filter(p => p.playState == "running").length, 3, "number of running AnimationPlayers");
|
||||||
|
|
||||||
|
60
dom/cache/AutoUtils.cpp
vendored
60
dom/cache/AutoUtils.cpp
vendored
@ -7,6 +7,7 @@
|
|||||||
#include "mozilla/dom/cache/AutoUtils.h"
|
#include "mozilla/dom/cache/AutoUtils.h"
|
||||||
|
|
||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
|
#include "mozilla/dom/cache/CachePushStreamChild.h"
|
||||||
#include "mozilla/dom/cache/CacheStreamControlParent.h"
|
#include "mozilla/dom/cache/CacheStreamControlParent.h"
|
||||||
#include "mozilla/dom/cache/ReadStream.h"
|
#include "mozilla/dom/cache/ReadStream.h"
|
||||||
#include "mozilla/dom/cache/SavedTypes.h"
|
#include "mozilla/dom/cache/SavedTypes.h"
|
||||||
@ -19,6 +20,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using mozilla::unused;
|
using mozilla::unused;
|
||||||
|
using mozilla::dom::cache::CachePushStreamChild;
|
||||||
using mozilla::dom::cache::PCacheReadStream;
|
using mozilla::dom::cache::PCacheReadStream;
|
||||||
using mozilla::dom::cache::PCacheReadStreamOrVoid;
|
using mozilla::dom::cache::PCacheReadStreamOrVoid;
|
||||||
using mozilla::ipc::FileDescriptor;
|
using mozilla::ipc::FileDescriptor;
|
||||||
@ -28,8 +30,8 @@ using mozilla::ipc::OptionalFileDescriptorSet;
|
|||||||
|
|
||||||
enum CleanupAction
|
enum CleanupAction
|
||||||
{
|
{
|
||||||
ForgetFds,
|
Forget,
|
||||||
DeleteFds
|
Delete
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -46,7 +48,7 @@ CleanupChildFds(PCacheReadStream& aReadStream, CleanupAction aAction)
|
|||||||
static_cast<FileDescriptorSetChild*>(aReadStream.fds().get_PFileDescriptorSetChild());
|
static_cast<FileDescriptorSetChild*>(aReadStream.fds().get_PFileDescriptorSetChild());
|
||||||
MOZ_ASSERT(fdSetActor);
|
MOZ_ASSERT(fdSetActor);
|
||||||
|
|
||||||
if (aAction == DeleteFds) {
|
if (aAction == Delete) {
|
||||||
unused << fdSetActor->Send__delete__(fdSetActor);
|
unused << fdSetActor->Send__delete__(fdSetActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,13 +59,39 @@ CleanupChildFds(PCacheReadStream& aReadStream, CleanupAction aAction)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CleanupChildFds(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
|
CleanupChildPushStream(PCacheReadStream& aReadStream, CleanupAction aAction)
|
||||||
|
{
|
||||||
|
if (!aReadStream.pushStreamChild()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto pushStream =
|
||||||
|
static_cast<CachePushStreamChild*>(aReadStream.pushStreamChild());
|
||||||
|
|
||||||
|
if (aAction == Delete) {
|
||||||
|
pushStream->StartDestroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we send the stream, then we need to start it before forgetting about it.
|
||||||
|
pushStream->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CleanupChild(PCacheReadStream& aReadStream, CleanupAction aAction)
|
||||||
|
{
|
||||||
|
CleanupChildFds(aReadStream, aAction);
|
||||||
|
CleanupChildPushStream(aReadStream, aAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CleanupChild(PCacheReadStreamOrVoid& aReadStreamOrVoid, CleanupAction aAction)
|
||||||
{
|
{
|
||||||
if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
|
if (aReadStreamOrVoid.type() == PCacheReadStreamOrVoid::Tvoid_t) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CleanupChildFds(aReadStreamOrVoid.get_PCacheReadStream(), aAction);
|
CleanupChild(aReadStreamOrVoid.get_PCacheReadStream(), aAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -80,7 +108,7 @@ CleanupParentFds(PCacheReadStream& aReadStream, CleanupAction aAction)
|
|||||||
static_cast<FileDescriptorSetParent*>(aReadStream.fds().get_PFileDescriptorSetParent());
|
static_cast<FileDescriptorSetParent*>(aReadStream.fds().get_PFileDescriptorSetParent());
|
||||||
MOZ_ASSERT(fdSetActor);
|
MOZ_ASSERT(fdSetActor);
|
||||||
|
|
||||||
if (aAction == DeleteFds) {
|
if (aAction == Delete) {
|
||||||
unused << fdSetActor->Send__delete__(fdSetActor);
|
unused << fdSetActor->Send__delete__(fdSetActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,8 +161,8 @@ AutoChildRequest::~AutoChildRequest()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CleanupAction action = mSent ? ForgetFds : DeleteFds;
|
CleanupAction action = mSent ? Forget : Delete;
|
||||||
CleanupChildFds(mRequestOrVoid.get_PCacheRequest().body(), action);
|
CleanupChild(mRequestOrVoid.get_PCacheRequest().body(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -173,9 +201,9 @@ AutoChildRequestList::AutoChildRequestList(TypeUtils* aTypeUtils,
|
|||||||
|
|
||||||
AutoChildRequestList::~AutoChildRequestList()
|
AutoChildRequestList::~AutoChildRequestList()
|
||||||
{
|
{
|
||||||
CleanupAction action = mSent ? ForgetFds : DeleteFds;
|
CleanupAction action = mSent ? Forget : Delete;
|
||||||
for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
|
for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
|
||||||
CleanupChildFds(mRequestList[i].body(), action);
|
CleanupChild(mRequestList[i].body(), action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,9 +251,9 @@ AutoChildRequestResponse::AutoChildRequestResponse(TypeUtils* aTypeUtils)
|
|||||||
|
|
||||||
AutoChildRequestResponse::~AutoChildRequestResponse()
|
AutoChildRequestResponse::~AutoChildRequestResponse()
|
||||||
{
|
{
|
||||||
CleanupAction action = mSent ? ForgetFds : DeleteFds;
|
CleanupAction action = mSent ? Forget : Delete;
|
||||||
CleanupChildFds(mRequestResponse.request().body(), action);
|
CleanupChild(mRequestResponse.request().body(), action);
|
||||||
CleanupChildFds(mRequestResponse.response().body(), action);
|
CleanupChild(mRequestResponse.response().body(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -311,7 +339,7 @@ AutoParentRequestList::AutoParentRequestList(PBackgroundParent* aManager,
|
|||||||
|
|
||||||
AutoParentRequestList::~AutoParentRequestList()
|
AutoParentRequestList::~AutoParentRequestList()
|
||||||
{
|
{
|
||||||
CleanupAction action = mSent ? ForgetFds : DeleteFds;
|
CleanupAction action = mSent ? Forget : Delete;
|
||||||
for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
|
for (uint32_t i = 0; i < mRequestList.Length(); ++i) {
|
||||||
CleanupParentFds(mRequestList[i].body(), action);
|
CleanupParentFds(mRequestList[i].body(), action);
|
||||||
}
|
}
|
||||||
@ -355,7 +383,7 @@ AutoParentResponseList::AutoParentResponseList(PBackgroundParent* aManager,
|
|||||||
|
|
||||||
AutoParentResponseList::~AutoParentResponseList()
|
AutoParentResponseList::~AutoParentResponseList()
|
||||||
{
|
{
|
||||||
CleanupAction action = mSent ? ForgetFds : DeleteFds;
|
CleanupAction action = mSent ? Forget : Delete;
|
||||||
for (uint32_t i = 0; i < mResponseList.Length(); ++i) {
|
for (uint32_t i = 0; i < mResponseList.Length(); ++i) {
|
||||||
CleanupParentFds(mResponseList[i].body(), action);
|
CleanupParentFds(mResponseList[i].body(), action);
|
||||||
}
|
}
|
||||||
@ -402,7 +430,7 @@ AutoParentResponseOrVoid::~AutoParentResponseOrVoid()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
CleanupAction action = mSent ? ForgetFds : DeleteFds;
|
CleanupAction action = mSent ? Forget : Delete;
|
||||||
CleanupParentFds(mResponseOrVoid.get_PCacheResponse().body(), action);
|
CleanupParentFds(mResponseOrVoid.get_PCacheResponse().body(), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
dom/cache/Cache.cpp
vendored
13
dom/cache/Cache.cpp
vendored
@ -14,6 +14,7 @@
|
|||||||
#include "mozilla/dom/CacheBinding.h"
|
#include "mozilla/dom/CacheBinding.h"
|
||||||
#include "mozilla/dom/cache/AutoUtils.h"
|
#include "mozilla/dom/cache/AutoUtils.h"
|
||||||
#include "mozilla/dom/cache/CacheChild.h"
|
#include "mozilla/dom/cache/CacheChild.h"
|
||||||
|
#include "mozilla/dom/cache/CachePushStreamChild.h"
|
||||||
#include "mozilla/dom/cache/ReadStream.h"
|
#include "mozilla/dom/cache/ReadStream.h"
|
||||||
#include "mozilla/dom/cache/TypeUtils.h"
|
#include "mozilla/dom/cache/TypeUtils.h"
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
@ -526,6 +527,18 @@ Cache::AssertOwningThread() const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CachePushStreamChild*
|
||||||
|
Cache::CreatePushStream(nsIAsyncInputStream* aStream)
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(Cache);
|
||||||
|
MOZ_ASSERT(mActor);
|
||||||
|
MOZ_ASSERT(aStream);
|
||||||
|
auto actor = mActor->SendPCachePushStreamConstructor(
|
||||||
|
new CachePushStreamChild(mActor->GetFeature(), aStream));
|
||||||
|
MOZ_ASSERT(actor);
|
||||||
|
return static_cast<CachePushStreamChild*>(actor);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Cache::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
Cache::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||||
{
|
{
|
||||||
|
7
dom/cache/Cache.h
vendored
7
dom/cache/Cache.h
vendored
@ -39,8 +39,8 @@ class PCacheResponse;
|
|||||||
class PCacheResponseOrVoid;
|
class PCacheResponseOrVoid;
|
||||||
|
|
||||||
class Cache final : public PromiseNativeHandler
|
class Cache final : public PromiseNativeHandler
|
||||||
, public nsWrapperCache
|
, public nsWrapperCache
|
||||||
, public TypeUtils
|
, public TypeUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Cache(nsIGlobalObject* aGlobal, CacheChild* aActor);
|
Cache(nsIGlobalObject* aGlobal, CacheChild* aActor);
|
||||||
@ -97,6 +97,9 @@ public:
|
|||||||
virtual void AssertOwningThread() const override;
|
virtual void AssertOwningThread() const override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual CachePushStreamChild*
|
||||||
|
CreatePushStream(nsIAsyncInputStream* aStream) override;
|
||||||
|
|
||||||
// PromiseNativeHandler methods
|
// PromiseNativeHandler methods
|
||||||
virtual void
|
virtual void
|
||||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||||
|
15
dom/cache/CacheChild.cpp
vendored
15
dom/cache/CacheChild.cpp
vendored
@ -9,6 +9,7 @@
|
|||||||
#include "mozilla/unused.h"
|
#include "mozilla/unused.h"
|
||||||
#include "mozilla/dom/cache/ActorUtils.h"
|
#include "mozilla/dom/cache/ActorUtils.h"
|
||||||
#include "mozilla/dom/cache/Cache.h"
|
#include "mozilla/dom/cache/Cache.h"
|
||||||
|
#include "mozilla/dom/cache/PCachePushStreamChild.h"
|
||||||
#include "mozilla/dom/cache/StreamUtils.h"
|
#include "mozilla/dom/cache/StreamUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -94,6 +95,20 @@ CacheChild::ActorDestroy(ActorDestroyReason aReason)
|
|||||||
RemoveFeature();
|
RemoveFeature();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCachePushStreamChild*
|
||||||
|
CacheChild::AllocPCachePushStreamChild()
|
||||||
|
{
|
||||||
|
MOZ_CRASH("CachePushStreamChild should be manually constructed.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CacheChild::DeallocPCachePushStreamChild(PCachePushStreamChild* aActor)
|
||||||
|
{
|
||||||
|
delete aActor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CacheChild::RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
|
CacheChild::RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
|
||||||
const PCacheResponseOrVoid& aResponse)
|
const PCacheResponseOrVoid& aResponse)
|
||||||
|
8
dom/cache/CacheChild.h
vendored
8
dom/cache/CacheChild.h
vendored
@ -17,7 +17,7 @@ namespace cache {
|
|||||||
class Cache;
|
class Cache;
|
||||||
|
|
||||||
class CacheChild final : public PCacheChild
|
class CacheChild final : public PCacheChild
|
||||||
, public ActorChild
|
, public ActorChild
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CacheChild();
|
CacheChild();
|
||||||
@ -41,6 +41,12 @@ private:
|
|||||||
virtual void
|
virtual void
|
||||||
ActorDestroy(ActorDestroyReason aReason) override;
|
ActorDestroy(ActorDestroyReason aReason) override;
|
||||||
|
|
||||||
|
virtual PCachePushStreamChild*
|
||||||
|
AllocPCachePushStreamChild() override;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
DeallocPCachePushStreamChild(PCachePushStreamChild* aActor) override;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
|
RecvMatchResponse(const RequestId& requestId, const nsresult& aRv,
|
||||||
const PCacheResponseOrVoid& aResponse) override;
|
const PCacheResponseOrVoid& aResponse) override;
|
||||||
|
30
dom/cache/CacheParent.cpp
vendored
30
dom/cache/CacheParent.cpp
vendored
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "mozilla/DebugOnly.h"
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/dom/cache/AutoUtils.h"
|
#include "mozilla/dom/cache/AutoUtils.h"
|
||||||
|
#include "mozilla/dom/cache/CachePushStreamParent.h"
|
||||||
#include "mozilla/dom/cache/CacheStreamControlParent.h"
|
#include "mozilla/dom/cache/CacheStreamControlParent.h"
|
||||||
#include "mozilla/dom/cache/ReadStream.h"
|
#include "mozilla/dom/cache/ReadStream.h"
|
||||||
#include "mozilla/dom/cache/SavedTypes.h"
|
#include "mozilla/dom/cache/SavedTypes.h"
|
||||||
@ -61,6 +62,19 @@ CacheParent::ActorDestroy(ActorDestroyReason aReason)
|
|||||||
mManager = nullptr;
|
mManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCachePushStreamParent*
|
||||||
|
CacheParent::AllocPCachePushStreamParent()
|
||||||
|
{
|
||||||
|
return CachePushStreamParent::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CacheParent::DeallocPCachePushStreamParent(PCachePushStreamParent* aActor)
|
||||||
|
{
|
||||||
|
delete aActor;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CacheParent::RecvTeardown()
|
CacheParent::RecvTeardown()
|
||||||
{
|
{
|
||||||
@ -259,13 +273,27 @@ CacheParent::DeserializeCacheStream(const PCacheReadStreamOrVoid& aStreamOrVoid)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIInputStream> stream;
|
||||||
const PCacheReadStream& readStream = aStreamOrVoid.get_PCacheReadStream();
|
const PCacheReadStream& readStream = aStreamOrVoid.get_PCacheReadStream();
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> stream = ReadStream::Create(readStream);
|
// Option 1: A push stream actor was sent for nsPipe data
|
||||||
|
if (readStream.pushStreamParent()) {
|
||||||
|
MOZ_ASSERT(!readStream.controlParent());
|
||||||
|
CachePushStreamParent* pushStream =
|
||||||
|
static_cast<CachePushStreamParent*>(readStream.pushStreamParent());
|
||||||
|
stream = pushStream->TakeReader();
|
||||||
|
MOZ_ASSERT(stream);
|
||||||
|
return stream.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Option 2: One of our own ReadStreams was passed back to us with a stream
|
||||||
|
// control actor.
|
||||||
|
stream = ReadStream::Create(readStream);
|
||||||
if (stream) {
|
if (stream) {
|
||||||
return stream.forget();
|
return stream.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option 3: A stream was serialized using normal methods.
|
||||||
nsAutoTArray<FileDescriptor, 4> fds;
|
nsAutoTArray<FileDescriptor, 4> fds;
|
||||||
if (readStream.fds().type() ==
|
if (readStream.fds().type() ==
|
||||||
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
|
OptionalFileDescriptorSet::TPFileDescriptorSetChild) {
|
||||||
|
6
dom/cache/CacheParent.h
vendored
6
dom/cache/CacheParent.h
vendored
@ -22,8 +22,8 @@ namespace cache {
|
|||||||
struct SavedResponse;
|
struct SavedResponse;
|
||||||
|
|
||||||
class CacheParent final : public PCacheParent
|
class CacheParent final : public PCacheParent
|
||||||
, public Manager::Listener
|
, public Manager::Listener
|
||||||
, public FetchPut::Listener
|
, public FetchPut::Listener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CacheParent(cache::Manager* aManager, CacheId aCacheId);
|
CacheParent(cache::Manager* aManager, CacheId aCacheId);
|
||||||
@ -32,6 +32,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
// PCacheParent method
|
// PCacheParent method
|
||||||
virtual void ActorDestroy(ActorDestroyReason aReason) override;
|
virtual void ActorDestroy(ActorDestroyReason aReason) override;
|
||||||
|
virtual PCachePushStreamParent* AllocPCachePushStreamParent() override;
|
||||||
|
virtual bool DeallocPCachePushStreamParent(PCachePushStreamParent* aActor) override;
|
||||||
virtual bool RecvTeardown() override;
|
virtual bool RecvTeardown() override;
|
||||||
virtual bool
|
virtual bool
|
||||||
RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest,
|
RecvMatch(const RequestId& aRequestId, const PCacheRequest& aRequest,
|
||||||
|
259
dom/cache/CachePushStreamChild.cpp
vendored
Normal file
259
dom/cache/CachePushStreamChild.cpp
vendored
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
/* -*- 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 "mozilla/dom/cache/CachePushStreamChild.h"
|
||||||
|
|
||||||
|
#include "mozilla/unused.h"
|
||||||
|
#include "nsIAsyncInputStream.h"
|
||||||
|
#include "nsICancelableRunnable.h"
|
||||||
|
#include "nsIThread.h"
|
||||||
|
#include "nsStreamUtils.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace cache {
|
||||||
|
|
||||||
|
class CachePushStreamChild::Callback final : public nsIInputStreamCallback
|
||||||
|
, public nsICancelableRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit Callback(CachePushStreamChild* aActor)
|
||||||
|
: mActor(aActor)
|
||||||
|
, mOwningThread(NS_GetCurrentThread())
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
OnInputStreamReady(nsIAsyncInputStream* aStream) override
|
||||||
|
{
|
||||||
|
// any thread
|
||||||
|
if (mOwningThread == NS_GetCurrentThread()) {
|
||||||
|
return Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this fails, then it means the owning thread is a Worker that has
|
||||||
|
// been shutdown. Its ok to lose the event in this case because the
|
||||||
|
// CachePushStreamChild listens for this event through the Feature.
|
||||||
|
nsresult rv = mOwningThread->Dispatch(this, nsIThread::DISPATCH_NORMAL);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("Failed to dispatch stream readable event to owning thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
Run() override
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mOwningThread == NS_GetCurrentThread());
|
||||||
|
if (mActor) {
|
||||||
|
mActor->OnStreamReady(this);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD
|
||||||
|
Cancel() override
|
||||||
|
{
|
||||||
|
// Cancel() gets called when the Worker thread is being shutdown. We have
|
||||||
|
// nothing to do here because CachePushStreamChild handles this case via
|
||||||
|
// the Feature.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClearActor()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mOwningThread == NS_GetCurrentThread());
|
||||||
|
MOZ_ASSERT(mActor);
|
||||||
|
mActor = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~Callback()
|
||||||
|
{
|
||||||
|
// called on any thread
|
||||||
|
|
||||||
|
// ClearActor() should be called before the Callback is destroyed
|
||||||
|
MOZ_ASSERT(!mActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
CachePushStreamChild* mActor;
|
||||||
|
nsCOMPtr<nsIThread> mOwningThread;
|
||||||
|
|
||||||
|
NS_DECL_THREADSAFE_ISUPPORTS
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(CachePushStreamChild::Callback, nsIInputStreamCallback,
|
||||||
|
nsIRunnable,
|
||||||
|
nsICancelableRunnable);
|
||||||
|
|
||||||
|
CachePushStreamChild::CachePushStreamChild(Feature* aFeature,
|
||||||
|
nsIAsyncInputStream* aStream)
|
||||||
|
: mStream(aStream)
|
||||||
|
, mClosed(false)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mStream);
|
||||||
|
MOZ_ASSERT_IF(!NS_IsMainThread(), aFeature);
|
||||||
|
SetFeature(aFeature);
|
||||||
|
}
|
||||||
|
|
||||||
|
CachePushStreamChild::~CachePushStreamChild()
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(CachePushStreamChild);
|
||||||
|
MOZ_ASSERT(mClosed);
|
||||||
|
MOZ_ASSERT(!mCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::Start()
|
||||||
|
{
|
||||||
|
DoRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::StartDestroy()
|
||||||
|
{
|
||||||
|
// called if we are running on a Worker and the thread gets shutdown
|
||||||
|
OnEnd(NS_ERROR_ABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::ActorDestroy(ActorDestroyReason aReason)
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(CachePushStreamChild);
|
||||||
|
|
||||||
|
// If the parent side runs into a problem then the actor will be destroyed.
|
||||||
|
// In this case we have not run OnEnd(), so still need to close the input
|
||||||
|
// stream.
|
||||||
|
if (!mClosed) {
|
||||||
|
mStream->CloseWithStatus(NS_ERROR_ABORT);
|
||||||
|
mClosed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCallback) {
|
||||||
|
mCallback->ClearActor();
|
||||||
|
mCallback = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveFeature();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::DoRead()
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(CachePushStreamChild);
|
||||||
|
MOZ_ASSERT(!mClosed);
|
||||||
|
MOZ_ASSERT(!mCallback);
|
||||||
|
|
||||||
|
// The input stream (likely a pipe) probably uses a segment size of
|
||||||
|
// 4kb. If there is data already buffered it would be nice to aggregate
|
||||||
|
// multiple segments into a single IPC call. Conversely, don't send too
|
||||||
|
// too large of a buffer in a single call to avoid spiking memory.
|
||||||
|
static const uint64_t kMaxBytesPerMessage = 32 * 1024;
|
||||||
|
static_assert(kMaxBytesPerMessage <= static_cast<uint64_t>(UINT32_MAX),
|
||||||
|
"kMaxBytesPerMessage must cleanly cast to uint32_t");
|
||||||
|
|
||||||
|
while (!mClosed) {
|
||||||
|
// Use non-auto here as we're unlikely to hit stack storage with the
|
||||||
|
// sizes we are sending. Also, it would be nice to avoid another copy
|
||||||
|
// to the IPC layer which we avoid if we use COW strings. Unfortunately
|
||||||
|
// IPC does not seem to support passing dependent storage types.
|
||||||
|
nsCString buffer;
|
||||||
|
|
||||||
|
uint64_t available = 0;
|
||||||
|
nsresult rv = mStream->Available(&available);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
OnEnd(rv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (available == 0) {
|
||||||
|
Wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t expectedBytes =
|
||||||
|
static_cast<uint32_t>(std::min(available, kMaxBytesPerMessage));
|
||||||
|
|
||||||
|
buffer.SetLength(expectedBytes);
|
||||||
|
|
||||||
|
uint32_t bytesRead = 0;
|
||||||
|
rv = mStream->Read(buffer.BeginWriting(), buffer.Length(), &bytesRead);
|
||||||
|
buffer.SetLength(bytesRead);
|
||||||
|
|
||||||
|
// If we read any data from the stream, send it across.
|
||||||
|
if (!buffer.IsEmpty()) {
|
||||||
|
unused << SendBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||||
|
Wait();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any other error or zero-byte read indicates end-of-stream
|
||||||
|
if (NS_FAILED(rv) || buffer.IsEmpty()) {
|
||||||
|
OnEnd(rv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::Wait()
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(CachePushStreamChild);
|
||||||
|
MOZ_ASSERT(!mClosed);
|
||||||
|
MOZ_ASSERT(!mCallback);
|
||||||
|
|
||||||
|
// Set mCallback immediately instead of waiting for success. Its possible
|
||||||
|
// AsyncWait() will callback synchronously.
|
||||||
|
mCallback = new Callback(this);
|
||||||
|
nsresult rv = mStream->AsyncWait(mCallback, 0, 0, nullptr);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
OnEnd(rv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::OnStreamReady(Callback* aCallback)
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(CachePushStreamChild);
|
||||||
|
MOZ_ASSERT(mCallback);
|
||||||
|
MOZ_ASSERT(aCallback == mCallback);
|
||||||
|
mCallback->ClearActor();
|
||||||
|
mCallback = nullptr;
|
||||||
|
DoRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamChild::OnEnd(nsresult aRv)
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(CachePushStreamChild);
|
||||||
|
MOZ_ASSERT(aRv != NS_BASE_STREAM_WOULD_BLOCK);
|
||||||
|
|
||||||
|
if (mClosed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mClosed = true;
|
||||||
|
|
||||||
|
mStream->CloseWithStatus(aRv);
|
||||||
|
|
||||||
|
if (aRv == NS_BASE_STREAM_CLOSED) {
|
||||||
|
aRv = NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will trigger an ActorDestroy() from the parent side
|
||||||
|
unused << SendClose(aRv);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cache
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
57
dom/cache/CachePushStreamChild.h
vendored
Normal file
57
dom/cache/CachePushStreamChild.h
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/* -*- 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_dom_cache_CachePushStreamChild_h
|
||||||
|
#define mozilla_dom_cache_CachePushStreamChild_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/cache/ActorChild.h"
|
||||||
|
#include "mozilla/dom/cache/PCachePushStreamChild.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
|
class nsIAsyncInputStream;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace cache {
|
||||||
|
|
||||||
|
class CachePushStreamChild final : public PCachePushStreamChild
|
||||||
|
, public ActorChild
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CachePushStreamChild(Feature* aFeature, nsIAsyncInputStream* aStream);
|
||||||
|
~CachePushStreamChild();
|
||||||
|
|
||||||
|
virtual void StartDestroy() override;
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Callback;
|
||||||
|
|
||||||
|
// PCachePushStreamChild methods
|
||||||
|
virtual void
|
||||||
|
ActorDestroy(ActorDestroyReason aReason) override;
|
||||||
|
|
||||||
|
void DoRead();
|
||||||
|
|
||||||
|
void Wait();
|
||||||
|
|
||||||
|
void OnStreamReady(Callback* aCallback);
|
||||||
|
|
||||||
|
void OnEnd(nsresult aRv);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAsyncInputStream> mStream;
|
||||||
|
nsRefPtr<Callback> mCallback;
|
||||||
|
bool mClosed;
|
||||||
|
|
||||||
|
NS_DECL_OWNINGTHREAD
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cache
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_cache_CachePushStreamChild_h
|
97
dom/cache/CachePushStreamParent.cpp
vendored
Normal file
97
dom/cache/CachePushStreamParent.cpp
vendored
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/* -*- 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 "mozilla/dom/cache/CachePushStreamParent.h"
|
||||||
|
|
||||||
|
#include "mozilla/unused.h"
|
||||||
|
#include "nsIAsyncInputStream.h"
|
||||||
|
#include "nsIAsyncOutputStream.h"
|
||||||
|
#include "nsIPipe.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace cache {
|
||||||
|
|
||||||
|
// static
|
||||||
|
CachePushStreamParent*
|
||||||
|
CachePushStreamParent::Create()
|
||||||
|
{
|
||||||
|
// use async versions for both reader and writer even though we are
|
||||||
|
// opening the writer as an infinite stream. We want to be able to
|
||||||
|
// use CloseWithStatus() to communicate errors through the pipe.
|
||||||
|
nsCOMPtr<nsIAsyncInputStream> reader;
|
||||||
|
nsCOMPtr<nsIAsyncOutputStream> writer;
|
||||||
|
|
||||||
|
// Use an "infinite" pipe because we cannot apply back-pressure through
|
||||||
|
// the async IPC layer at the moment. Blocking the IPC worker thread
|
||||||
|
// is not desirable, either.
|
||||||
|
nsresult rv = NS_NewPipe2(getter_AddRefs(reader),
|
||||||
|
getter_AddRefs(writer),
|
||||||
|
true, true, // non-blocking
|
||||||
|
0, // segment size
|
||||||
|
UINT32_MAX); // "infinite" pipe
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CachePushStreamParent(reader, writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
CachePushStreamParent::~CachePushStreamParent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<nsIInputStream>
|
||||||
|
CachePushStreamParent::TakeReader()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mReader);
|
||||||
|
return mReader.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CachePushStreamParent::ActorDestroy(ActorDestroyReason aReason)
|
||||||
|
{
|
||||||
|
// If we were gracefully closed we should have gotten RecvClose(). In
|
||||||
|
// that case, the writer will already be closed and this will have no
|
||||||
|
// effect. This just aborts the writer in the case where the child process
|
||||||
|
// crashes.
|
||||||
|
mWriter->CloseWithStatus(NS_ERROR_ABORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CachePushStreamParent::RecvBuffer(const nsCString& aBuffer)
|
||||||
|
{
|
||||||
|
uint32_t numWritten = 0;
|
||||||
|
|
||||||
|
// This should only fail if we hit an OOM condition.
|
||||||
|
nsresult rv = mWriter->Write(aBuffer.get(), aBuffer.Length(), &numWritten);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
RecvClose(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
CachePushStreamParent::RecvClose(const nsresult& aRv)
|
||||||
|
{
|
||||||
|
mWriter->CloseWithStatus(aRv);
|
||||||
|
unused << Send__delete__(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CachePushStreamParent::CachePushStreamParent(nsIAsyncInputStream* aReader,
|
||||||
|
nsIAsyncOutputStream* aWriter)
|
||||||
|
: mReader(aReader)
|
||||||
|
, mWriter(aWriter)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mReader);
|
||||||
|
MOZ_ASSERT(mWriter);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cache
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
55
dom/cache/CachePushStreamParent.h
vendored
Normal file
55
dom/cache/CachePushStreamParent.h
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* -*- 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_dom_cache_CachePushStreamParent_h
|
||||||
|
#define mozilla_dom_cache_CachePushStreamParent_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/cache/PCachePushStreamParent.h"
|
||||||
|
|
||||||
|
class nsIAsyncInputStream;
|
||||||
|
class nsIAsyncOutputStream;
|
||||||
|
class nsIInputStream;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace cache {
|
||||||
|
|
||||||
|
class CachePushStreamParent final : public PCachePushStreamParent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CachePushStreamParent*
|
||||||
|
Create();
|
||||||
|
|
||||||
|
~CachePushStreamParent();
|
||||||
|
|
||||||
|
already_AddRefed<nsIInputStream>
|
||||||
|
TakeReader();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CachePushStreamParent(nsIAsyncInputStream* aReader,
|
||||||
|
nsIAsyncOutputStream* aWriter);
|
||||||
|
|
||||||
|
// PCachePushStreamParent methods
|
||||||
|
virtual void
|
||||||
|
ActorDestroy(ActorDestroyReason aReason) override;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
RecvBuffer(const nsCString& aBuffer) override;
|
||||||
|
|
||||||
|
virtual bool
|
||||||
|
RecvClose(const nsresult& aRv) override;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAsyncInputStream> mReader;
|
||||||
|
nsCOMPtr<nsIAsyncOutputStream> mWriter;
|
||||||
|
|
||||||
|
NS_DECL_OWNINGTHREAD
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cache
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_dom_cache_CachePushStreamParent_h
|
7
dom/cache/CacheStorage.cpp
vendored
7
dom/cache/CacheStorage.cpp
vendored
@ -516,6 +516,13 @@ CacheStorage::AssertOwningThread() const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CachePushStreamChild*
|
||||||
|
CacheStorage::CreatePushStream(nsIAsyncInputStream* aStream)
|
||||||
|
{
|
||||||
|
// This is true because CacheStorage always uses IgnoreBody for requests.
|
||||||
|
MOZ_CRASH("CacheStorage should never create a push stream.");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CacheStorage::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
CacheStorage::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue)
|
||||||
{
|
{
|
||||||
|
9
dom/cache/CacheStorage.h
vendored
9
dom/cache/CacheStorage.h
vendored
@ -44,9 +44,9 @@ class Feature;
|
|||||||
class PCacheResponseOrVoid;
|
class PCacheResponseOrVoid;
|
||||||
|
|
||||||
class CacheStorage final : public nsIIPCBackgroundChildCreateCallback
|
class CacheStorage final : public nsIIPCBackgroundChildCreateCallback
|
||||||
, public nsWrapperCache
|
, public nsWrapperCache
|
||||||
, public TypeUtils
|
, public TypeUtils
|
||||||
, public PromiseNativeHandler
|
, public PromiseNativeHandler
|
||||||
{
|
{
|
||||||
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
|
typedef mozilla::ipc::PBackgroundChild PBackgroundChild;
|
||||||
|
|
||||||
@ -97,6 +97,9 @@ public:
|
|||||||
virtual void AssertOwningThread() const override;
|
virtual void AssertOwningThread() const override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual CachePushStreamChild*
|
||||||
|
CreatePushStream(nsIAsyncInputStream* aStream) override;
|
||||||
|
|
||||||
// PromiseNativeHandler methods
|
// PromiseNativeHandler methods
|
||||||
virtual void
|
virtual void
|
||||||
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override;
|
||||||
|
3
dom/cache/CacheStorageChild.h
vendored
3
dom/cache/CacheStorageChild.h
vendored
@ -20,7 +20,7 @@ class PCacheChild;
|
|||||||
class Feature;
|
class Feature;
|
||||||
|
|
||||||
class CacheStorageChild final : public PCacheStorageChild
|
class CacheStorageChild final : public PCacheStorageChild
|
||||||
, public ActorChild
|
, public ActorChild
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CacheStorageChild(CacheStorage* aListener, Feature* aFeature);
|
CacheStorageChild(CacheStorage* aListener, Feature* aFeature);
|
||||||
@ -41,6 +41,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
// PCacheStorageChild methods
|
// PCacheStorageChild methods
|
||||||
virtual void ActorDestroy(ActorDestroyReason aReason) override;
|
virtual void ActorDestroy(ActorDestroyReason aReason) override;
|
||||||
|
|
||||||
virtual bool RecvMatchResponse(const RequestId& aRequestId,
|
virtual bool RecvMatchResponse(const RequestId& aRequestId,
|
||||||
const nsresult& aRv,
|
const nsresult& aRv,
|
||||||
const PCacheResponseOrVoid& response) override;
|
const PCacheResponseOrVoid& response) override;
|
||||||
|
4
dom/cache/CacheStorageParent.h
vendored
4
dom/cache/CacheStorageParent.h
vendored
@ -23,8 +23,8 @@ class CacheStreamControlParent;
|
|||||||
class ManagerId;
|
class ManagerId;
|
||||||
|
|
||||||
class CacheStorageParent final : public PCacheStorageParent
|
class CacheStorageParent final : public PCacheStorageParent
|
||||||
, public PrincipalVerifier::Listener
|
, public PrincipalVerifier::Listener
|
||||||
, public Manager::Listener
|
, public Manager::Listener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CacheStorageParent(PBackgroundParent* aManagingActor, Namespace aNamespace,
|
CacheStorageParent(PBackgroundParent* aManagingActor, Namespace aNamespace,
|
||||||
|
4
dom/cache/CacheStreamControlChild.h
vendored
4
dom/cache/CacheStreamControlChild.h
vendored
@ -19,8 +19,8 @@ namespace cache {
|
|||||||
class ReadStream;
|
class ReadStream;
|
||||||
|
|
||||||
class CacheStreamControlChild final : public PCacheStreamControlChild
|
class CacheStreamControlChild final : public PCacheStreamControlChild
|
||||||
, public StreamControl
|
, public StreamControl
|
||||||
, public ActorChild
|
, public ActorChild
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CacheStreamControlChild();
|
CacheStreamControlChild();
|
||||||
|
4
dom/cache/CacheStreamControlParent.h
vendored
4
dom/cache/CacheStreamControlParent.h
vendored
@ -18,8 +18,8 @@ namespace cache {
|
|||||||
class ReadStream;
|
class ReadStream;
|
||||||
class StreamList;
|
class StreamList;
|
||||||
|
|
||||||
class CacheStreamControlParent : public PCacheStreamControlParent
|
class CacheStreamControlParent final : public PCacheStreamControlParent
|
||||||
, public StreamControl
|
, public StreamControl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CacheStreamControlParent();
|
CacheStreamControlParent();
|
||||||
|
2
dom/cache/Context.cpp
vendored
2
dom/cache/Context.cpp
vendored
@ -320,7 +320,7 @@ Context::QuotaInitRunnable::Run()
|
|||||||
// runnable executes the Action on the appropriate threads while the Context
|
// runnable executes the Action on the appropriate threads while the Context
|
||||||
// is initialized.
|
// is initialized.
|
||||||
class Context::ActionRunnable final : public nsIRunnable
|
class Context::ActionRunnable final : public nsIRunnable
|
||||||
, public Action::Resolver
|
, public Action::Resolver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ActionRunnable(Context* aContext, nsIEventTarget* aTarget, Action* aAction,
|
ActionRunnable(Context* aContext, nsIEventTarget* aTarget, Action* aAction,
|
||||||
|
6
dom/cache/FetchPut.cpp
vendored
6
dom/cache/FetchPut.cpp
vendored
@ -458,6 +458,12 @@ FetchPut::AssertOwningThread() const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CachePushStreamChild*
|
||||||
|
FetchPut::CreatePushStream(nsIAsyncInputStream* aStream)
|
||||||
|
{
|
||||||
|
MOZ_CRASH("FetchPut should never create a push stream!");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace cache
|
} // namespace cache
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
5
dom/cache/FetchPut.h
vendored
5
dom/cache/FetchPut.h
vendored
@ -30,7 +30,7 @@ class Response;
|
|||||||
namespace cache {
|
namespace cache {
|
||||||
|
|
||||||
class FetchPut final : public Manager::Listener
|
class FetchPut final : public Manager::Listener
|
||||||
, public TypeUtils
|
, public TypeUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::pair<nsRefPtr<Request>, nsRefPtr<Response>> PutPair;
|
typedef std::pair<nsRefPtr<Request>, nsRefPtr<Response>> PutPair;
|
||||||
@ -94,6 +94,9 @@ private:
|
|||||||
virtual void AssertOwningThread() const override;
|
virtual void AssertOwningThread() const override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual CachePushStreamChild*
|
||||||
|
CreatePushStream(nsIAsyncInputStream* aStream) override;
|
||||||
|
|
||||||
Listener* mListener;
|
Listener* mListener;
|
||||||
nsRefPtr<Manager> mManager;
|
nsRefPtr<Manager> mManager;
|
||||||
const RequestId mRequestId;
|
const RequestId mRequestId;
|
||||||
|
3
dom/cache/PCache.ipdl
vendored
3
dom/cache/PCache.ipdl
vendored
@ -3,6 +3,7 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
include protocol PBackground;
|
include protocol PBackground;
|
||||||
|
include protocol PCachePushStream;
|
||||||
include PCacheTypes;
|
include PCacheTypes;
|
||||||
include protocol PFileDescriptorSet;
|
include protocol PFileDescriptorSet;
|
||||||
|
|
||||||
@ -19,8 +20,10 @@ namespace cache {
|
|||||||
protocol PCache
|
protocol PCache
|
||||||
{
|
{
|
||||||
manager PBackground;
|
manager PBackground;
|
||||||
|
manages PCachePushStream;
|
||||||
|
|
||||||
parent:
|
parent:
|
||||||
|
PCachePushStream();
|
||||||
Teardown();
|
Teardown();
|
||||||
Match(RequestId requestId, PCacheRequest request, PCacheQueryParams params);
|
Match(RequestId requestId, PCacheRequest request, PCacheQueryParams params);
|
||||||
MatchAll(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params);
|
MatchAll(RequestId requestId, PCacheRequestOrVoid request, PCacheQueryParams params);
|
||||||
|
28
dom/cache/PCachePushStream.ipdl
vendored
Normal file
28
dom/cache/PCachePushStream.ipdl
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* 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 protocol PCache;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
namespace cache {
|
||||||
|
|
||||||
|
protocol PCachePushStream
|
||||||
|
{
|
||||||
|
manager PCache;
|
||||||
|
|
||||||
|
parent:
|
||||||
|
Buffer(nsCString aBuffer);
|
||||||
|
Close(nsresult aRv);
|
||||||
|
|
||||||
|
child:
|
||||||
|
// Stream is always destroyed from the parent side. This occurs if the
|
||||||
|
// parent encounters an error while writing to its pipe or if the child
|
||||||
|
// signals the stream should close by SendClose().
|
||||||
|
__delete__();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cache
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
2
dom/cache/PCacheTypes.ipdlh
vendored
2
dom/cache/PCacheTypes.ipdlh
vendored
@ -2,6 +2,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 protocol PCachePushStream;
|
||||||
include protocol PCacheStreamControl;
|
include protocol PCacheStreamControl;
|
||||||
include PHeaders;
|
include PHeaders;
|
||||||
include InputStreamParams;
|
include InputStreamParams;
|
||||||
@ -32,6 +33,7 @@ struct PCacheReadStream
|
|||||||
OptionalInputStreamParams params;
|
OptionalInputStreamParams params;
|
||||||
OptionalFileDescriptorSet fds;
|
OptionalFileDescriptorSet fds;
|
||||||
nullable PCacheStreamControl control;
|
nullable PCacheStreamControl control;
|
||||||
|
nullable PCachePushStream pushStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
union PCacheReadStreamOrVoid
|
union PCacheReadStreamOrVoid
|
||||||
|
8
dom/cache/ReadStream.cpp
vendored
8
dom/cache/ReadStream.cpp
vendored
@ -210,6 +210,11 @@ ReadStream::Inner::Serialize(PCacheReadStream* aReadStreamOut)
|
|||||||
MOZ_ASSERT(mState == Open);
|
MOZ_ASSERT(mState == Open);
|
||||||
MOZ_ASSERT(mControl);
|
MOZ_ASSERT(mControl);
|
||||||
|
|
||||||
|
// If we are sending a ReadStream, then we never want to set the
|
||||||
|
// pushStream actors at the same time.
|
||||||
|
aReadStreamOut->pushStreamChild() = nullptr;
|
||||||
|
aReadStreamOut->pushStreamParent() = nullptr;
|
||||||
|
|
||||||
aReadStreamOut->id() = mId;
|
aReadStreamOut->id() = mId;
|
||||||
mControl->SerializeControl(aReadStreamOut);
|
mControl->SerializeControl(aReadStreamOut);
|
||||||
|
|
||||||
@ -406,6 +411,9 @@ ReadStream::Create(const PCacheReadStream& aReadStream)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!aReadStream.pushStreamChild());
|
||||||
|
MOZ_ASSERT(!aReadStream.pushStreamParent());
|
||||||
|
|
||||||
// Control is guaranteed to survive this method as ActorDestroy() cannot
|
// Control is guaranteed to survive this method as ActorDestroy() cannot
|
||||||
// run on this thread until we complete.
|
// run on this thread until we complete.
|
||||||
StreamControl* control;
|
StreamControl* control;
|
||||||
|
2
dom/cache/StreamList.h
vendored
2
dom/cache/StreamList.h
vendored
@ -21,7 +21,7 @@ class CacheStreamControlParent;
|
|||||||
class Context;
|
class Context;
|
||||||
class Manager;
|
class Manager;
|
||||||
|
|
||||||
class StreamList
|
class StreamList final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StreamList(Manager* aManager, Context* aContext);
|
StreamList(Manager* aManager, Context* aContext);
|
||||||
|
106
dom/cache/TypeUtils.cpp
vendored
106
dom/cache/TypeUtils.cpp
vendored
@ -11,6 +11,7 @@
|
|||||||
#include "mozilla/dom/InternalRequest.h"
|
#include "mozilla/dom/InternalRequest.h"
|
||||||
#include "mozilla/dom/Request.h"
|
#include "mozilla/dom/Request.h"
|
||||||
#include "mozilla/dom/Response.h"
|
#include "mozilla/dom/Response.h"
|
||||||
|
#include "mozilla/dom/cache/CachePushStreamChild.h"
|
||||||
#include "mozilla/dom/cache/PCacheTypes.h"
|
#include "mozilla/dom/cache/PCacheTypes.h"
|
||||||
#include "mozilla/dom/cache/ReadStream.h"
|
#include "mozilla/dom/cache/ReadStream.h"
|
||||||
#include "mozilla/ipc/BackgroundChild.h"
|
#include "mozilla/ipc/BackgroundChild.h"
|
||||||
@ -29,6 +30,13 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
using mozilla::ErrorResult;
|
using mozilla::ErrorResult;
|
||||||
|
using mozilla::unused;
|
||||||
|
using mozilla::void_t;
|
||||||
|
using mozilla::dom::cache::PCacheReadStream;
|
||||||
|
using mozilla::ipc::BackgroundChild;
|
||||||
|
using mozilla::ipc::FileDescriptor;
|
||||||
|
using mozilla::ipc::PBackgroundChild;
|
||||||
|
using mozilla::ipc::PFileDescriptorSetChild;
|
||||||
|
|
||||||
// Utility function to remove the fragment from a URL, check its scheme, and optionally
|
// Utility function to remove the fragment from a URL, check its scheme, and optionally
|
||||||
// provide a URL without the query. We're not using nsIURL or URL to do this because
|
// provide a URL without the query. We're not using nsIURL or URL to do this because
|
||||||
@ -96,6 +104,31 @@ ProcessURL(nsAString& aUrl, bool* aSchemeValidOut,
|
|||||||
*aUrlWithoutQueryOut = Substring(aUrl, 0, queryPos - 1);
|
*aUrlWithoutQueryOut = Substring(aUrl, 0, queryPos - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SerializeNormalStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut)
|
||||||
|
{
|
||||||
|
nsAutoTArray<FileDescriptor, 4> fds;
|
||||||
|
SerializeInputStream(aStream, aReadStreamOut.params(), fds);
|
||||||
|
|
||||||
|
PFileDescriptorSetChild* fdSet = nullptr;
|
||||||
|
if (!fds.IsEmpty()) {
|
||||||
|
// We should not be serializing until we have an actor ready
|
||||||
|
PBackgroundChild* manager = BackgroundChild::GetForCurrentThread();
|
||||||
|
MOZ_ASSERT(manager);
|
||||||
|
|
||||||
|
fdSet = manager->SendPFileDescriptorSetConstructor(fds[0]);
|
||||||
|
for (uint32_t i = 1; i < fds.Length(); ++i) {
|
||||||
|
unused << fdSet->SendAddFileDescriptor(fds[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fdSet) {
|
||||||
|
aReadStreamOut.fds() = fdSet;
|
||||||
|
} else {
|
||||||
|
aReadStreamOut.fds() = void_t();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -413,64 +446,61 @@ TypeUtils::SerializeCacheStream(nsIInputStream* aStream,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option 1: Send a cache-specific ReadStream if we can.
|
||||||
nsRefPtr<ReadStream> controlled = do_QueryObject(aStream);
|
nsRefPtr<ReadStream> controlled = do_QueryObject(aStream);
|
||||||
if (controlled) {
|
if (controlled) {
|
||||||
controlled->Serialize(aStreamOut);
|
controlled->Serialize(aStreamOut);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement CrossProcessPipe if we cannot directly serialize (bug 1110814)
|
|
||||||
nsCOMPtr<nsIIPCSerializableInputStream> serial = do_QueryInterface(aStream);
|
|
||||||
if (!serial) {
|
|
||||||
aRv.Throw(NS_ERROR_FAILURE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PCacheReadStream readStream;
|
PCacheReadStream readStream;
|
||||||
readStream.controlChild() = nullptr;
|
readStream.controlChild() = nullptr;
|
||||||
readStream.controlParent() = nullptr;
|
readStream.controlParent() = nullptr;
|
||||||
|
readStream.pushStreamChild() = nullptr;
|
||||||
|
readStream.pushStreamParent() = nullptr;
|
||||||
|
|
||||||
nsAutoTArray<FileDescriptor, 4> fds;
|
// Option 2: Do normal stream serialization if its supported.
|
||||||
SerializeInputStream(aStream, readStream.params(), fds);
|
nsCOMPtr<nsIIPCSerializableInputStream> serial = do_QueryInterface(aStream);
|
||||||
|
if (serial) {
|
||||||
|
SerializeNormalStream(aStream, readStream);
|
||||||
|
|
||||||
PFileDescriptorSetChild* fdSet = nullptr;
|
// Option 3: As a last resort push data across manually. Should only be
|
||||||
if (!fds.IsEmpty()) {
|
// needed for nsPipe input stream. Only works for async,
|
||||||
// We should not be serializing until we have an actor ready
|
// non-blocking streams.
|
||||||
PBackgroundChild* manager = BackgroundChild::GetForCurrentThread();
|
|
||||||
MOZ_ASSERT(manager);
|
|
||||||
|
|
||||||
fdSet = manager->SendPFileDescriptorSetConstructor(fds[0]);
|
|
||||||
for (uint32_t i = 1; i < fds.Length(); ++i) {
|
|
||||||
unused << fdSet->SendAddFileDescriptor(fds[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fdSet) {
|
|
||||||
readStream.fds() = fdSet;
|
|
||||||
} else {
|
} else {
|
||||||
readStream.fds() = void_t();
|
SerializePushStream(aStream, readStream, aRv);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
*aStreamOut = readStream;
|
*aStreamOut = readStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIThread*
|
void
|
||||||
TypeUtils::GetStreamThread()
|
TypeUtils::SerializePushStream(nsIInputStream* aStream,
|
||||||
|
PCacheReadStream& aReadStreamOut,
|
||||||
|
ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
AssertOwningThread();
|
nsCOMPtr<nsIAsyncInputStream> asyncStream = do_QueryInterface(aStream);
|
||||||
|
if (NS_WARN_IF(!asyncStream)) {
|
||||||
if (!mStreamThread) {
|
aRv = NS_ERROR_FAILURE;
|
||||||
// Named threads only allow 16 bytes for their names. Try to make
|
return;
|
||||||
// it meaningful...
|
|
||||||
// TODO: use a thread pool or singleton thread here (bug 1119864)
|
|
||||||
nsresult rv = NS_NewNamedThread("DOMCacheTypeU",
|
|
||||||
getter_AddRefs(mStreamThread));
|
|
||||||
if (NS_FAILED(rv) || !mStreamThread) {
|
|
||||||
MOZ_CRASH("Failed to create DOM Cache serialization thread.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mStreamThread;
|
bool nonBlocking = false;
|
||||||
|
aRv = asyncStream->IsNonBlocking(&nonBlocking);
|
||||||
|
if (NS_WARN_IF(aRv.Failed())) { return; }
|
||||||
|
if (NS_WARN_IF(!nonBlocking)) {
|
||||||
|
aRv = NS_ERROR_FAILURE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aReadStreamOut.pushStreamChild() = CreatePushStream(asyncStream);
|
||||||
|
MOZ_ASSERT(aReadStreamOut.pushStreamChild());
|
||||||
|
aReadStreamOut.params() = void_t();
|
||||||
|
aReadStreamOut.fds() = void_t();
|
||||||
|
|
||||||
|
// CachePushStreamChild::Start() must be called after sending the stream
|
||||||
|
// across to the parent side.
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace cache
|
} // namespace cache
|
||||||
|
13
dom/cache/TypeUtils.h
vendored
13
dom/cache/TypeUtils.h
vendored
@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/dom/BindingUtils.h"
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
|
|
||||||
class nsIGlobalObject;
|
class nsIGlobalObject;
|
||||||
|
class nsIAsyncInputStream;
|
||||||
class nsIInputStream;
|
class nsIInputStream;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -28,7 +28,9 @@ class Response;
|
|||||||
|
|
||||||
namespace cache {
|
namespace cache {
|
||||||
|
|
||||||
|
class CachePushStreamChild;
|
||||||
class PCacheQueryParams;
|
class PCacheQueryParams;
|
||||||
|
class PCacheReadStream;
|
||||||
class PCacheReadStreamOrVoid;
|
class PCacheReadStreamOrVoid;
|
||||||
class PCacheRequest;
|
class PCacheRequest;
|
||||||
class PCacheResponse;
|
class PCacheResponse;
|
||||||
@ -63,6 +65,9 @@ public:
|
|||||||
inline void AssertOwningThread() const { }
|
inline void AssertOwningThread() const { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
virtual CachePushStreamChild*
|
||||||
|
CreatePushStream(nsIAsyncInputStream* aStream) = 0;
|
||||||
|
|
||||||
already_AddRefed<InternalRequest>
|
already_AddRefed<InternalRequest>
|
||||||
ToInternalRequest(const RequestOrUSVString& aIn, BodyAction aBodyAction,
|
ToInternalRequest(const RequestOrUSVString& aIn, BodyAction aBodyAction,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
@ -107,9 +112,9 @@ private:
|
|||||||
SerializeCacheStream(nsIInputStream* aStream, PCacheReadStreamOrVoid* aStreamOut,
|
SerializeCacheStream(nsIInputStream* aStream, PCacheReadStreamOrVoid* aStreamOut,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
|
||||||
nsIThread* GetStreamThread();
|
void
|
||||||
|
SerializePushStream(nsIInputStream* aStream, PCacheReadStream& aReadStreamOut,
|
||||||
nsCOMPtr<nsIThread> mStreamThread;
|
ErrorResult& aRv);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace cache
|
} // namespace cache
|
||||||
|
5
dom/cache/moz.build
vendored
5
dom/cache/moz.build
vendored
@ -12,6 +12,8 @@ EXPORTS.mozilla.dom.cache += [
|
|||||||
'Cache.h',
|
'Cache.h',
|
||||||
'CacheChild.h',
|
'CacheChild.h',
|
||||||
'CacheParent.h',
|
'CacheParent.h',
|
||||||
|
'CachePushStreamChild.h',
|
||||||
|
'CachePushStreamParent.h',
|
||||||
'CacheStorage.h',
|
'CacheStorage.h',
|
||||||
'CacheStorageChild.h',
|
'CacheStorageChild.h',
|
||||||
'CacheStorageParent.h',
|
'CacheStorageParent.h',
|
||||||
@ -44,6 +46,8 @@ UNIFIED_SOURCES += [
|
|||||||
'Cache.cpp',
|
'Cache.cpp',
|
||||||
'CacheChild.cpp',
|
'CacheChild.cpp',
|
||||||
'CacheParent.cpp',
|
'CacheParent.cpp',
|
||||||
|
'CachePushStreamChild.cpp',
|
||||||
|
'CachePushStreamParent.cpp',
|
||||||
'CacheStorage.cpp',
|
'CacheStorage.cpp',
|
||||||
'CacheStorageChild.cpp',
|
'CacheStorageChild.cpp',
|
||||||
'CacheStorageParent.cpp',
|
'CacheStorageParent.cpp',
|
||||||
@ -69,6 +73,7 @@ UNIFIED_SOURCES += [
|
|||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
'CacheInitData.ipdlh',
|
'CacheInitData.ipdlh',
|
||||||
'PCache.ipdl',
|
'PCache.ipdl',
|
||||||
|
'PCachePushStream.ipdl',
|
||||||
'PCacheStorage.ipdl',
|
'PCacheStorage.ipdl',
|
||||||
'PCacheStreamControl.ipdl',
|
'PCacheStreamControl.ipdl',
|
||||||
'PCacheTypes.ipdlh',
|
'PCacheTypes.ipdlh',
|
||||||
|
2
dom/cache/test/mochitest/mochitest.ini
vendored
2
dom/cache/test/mochitest/mochitest.ini
vendored
@ -16,6 +16,7 @@ support-files =
|
|||||||
vary.sjs
|
vary.sjs
|
||||||
test_caches.js
|
test_caches.js
|
||||||
test_cache_keys.js
|
test_cache_keys.js
|
||||||
|
test_cache_put.js
|
||||||
|
|
||||||
[test_cache.html]
|
[test_cache.html]
|
||||||
[test_cache_add.html]
|
[test_cache_add.html]
|
||||||
@ -25,3 +26,4 @@ support-files =
|
|||||||
[test_cache_match_vary.html]
|
[test_cache_match_vary.html]
|
||||||
[test_caches.html]
|
[test_caches.html]
|
||||||
[test_cache_keys.html]
|
[test_cache_keys.html]
|
||||||
|
[test_cache_put.html]
|
||||||
|
20
dom/cache/test/mochitest/test_cache_put.html
vendored
Normal file
20
dom/cache/test/mochitest/test_cache_put.html
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!-- Any copyright is dedicated to the Public Domain.
|
||||||
|
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Validate Interfaces Exposed to Workers</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="driver.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="frame"></iframe>
|
||||||
|
<script class="testbody" type="text/javascript">
|
||||||
|
runTests("test_cache_put.js")
|
||||||
|
.then(function() {
|
||||||
|
SimpleTest.finish();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
26
dom/cache/test/mochitest/test_cache_put.js
vendored
Normal file
26
dom/cache/test/mochitest/test_cache_put.js
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
var url = 'test_cache.js';
|
||||||
|
var cache;
|
||||||
|
var fetchResponse;
|
||||||
|
Promise.all([fetch(url),
|
||||||
|
caches.open('putter' + context)]).then(function(results) {
|
||||||
|
fetchResponse = results[0];
|
||||||
|
cache = results[1];
|
||||||
|
return cache.put(url, fetchResponse.clone());
|
||||||
|
}).then(function(result) {
|
||||||
|
is(undefined, result, 'Successful put() should resolve undefined');
|
||||||
|
return cache.match(url);
|
||||||
|
}).then(function(response) {
|
||||||
|
ok(response, 'match() should find resppnse that was previously put()');
|
||||||
|
ok(response.url.endsWith(url), 'matched response should match original url');
|
||||||
|
return Promise.all([fetchResponse.text(),
|
||||||
|
response.text()]);
|
||||||
|
}).then(function(results) {
|
||||||
|
// suppress large assert spam unless its relevent
|
||||||
|
if (results[0] !== results[1]) {
|
||||||
|
is(results[0], results[1], 'stored response body should match original');
|
||||||
|
}
|
||||||
|
return caches.delete('putter' + context);
|
||||||
|
}).then(function(deleted) {
|
||||||
|
ok(deleted, "The cache should be deleted successfully");
|
||||||
|
testDone();
|
||||||
|
});
|
@ -4218,6 +4218,13 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_EME
|
||||||
|
if (video->ContainsRestrictedContent()) {
|
||||||
|
error.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint16_t readyState;
|
uint16_t readyState;
|
||||||
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
|
if (NS_SUCCEEDED(video->GetReadyState(&readyState)) &&
|
||||||
readyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA) {
|
readyState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA) {
|
||||||
|
@ -671,14 +671,6 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
|||||||
NS_WARNING("Failed to visit all headers.");
|
NS_WARNING("Failed to visit all headers.");
|
||||||
}
|
}
|
||||||
|
|
||||||
mResponse = BeginAndGetFilteredResponse(response);
|
|
||||||
|
|
||||||
nsCOMPtr<nsISupports> securityInfo;
|
|
||||||
rv = channel->GetSecurityInfo(getter_AddRefs(securityInfo));
|
|
||||||
if (securityInfo) {
|
|
||||||
mResponse->SetSecurityInfo(securityInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We open a pipe so that we can immediately set the pipe's read end as the
|
// We open a pipe so that we can immediately set the pipe's read end as the
|
||||||
// response's body. Setting the segment size to UINT32_MAX means that the
|
// response's body. Setting the segment size to UINT32_MAX means that the
|
||||||
// pipe has infinite space. The nsIChannel will continue to buffer data in
|
// pipe has infinite space. The nsIChannel will continue to buffer data in
|
||||||
@ -697,8 +689,17 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
|||||||
// Cancel request.
|
// Cancel request.
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
response->SetBody(pipeInputStream);
|
||||||
|
|
||||||
mResponse->SetBody(pipeInputStream);
|
nsCOMPtr<nsISupports> securityInfo;
|
||||||
|
rv = channel->GetSecurityInfo(getter_AddRefs(securityInfo));
|
||||||
|
if (securityInfo) {
|
||||||
|
response->SetSecurityInfo(securityInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resolves fetch() promise which may trigger code running in a worker. Make
|
||||||
|
// sure the Response is fully initialized before calling this.
|
||||||
|
mResponse = BeginAndGetFilteredResponse(response);
|
||||||
|
|
||||||
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
|
nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
@ -3066,7 +3066,7 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||||||
nsAutoPtr<const MetadataTags> aTags)
|
nsAutoPtr<const MetadataTags> aTags)
|
||||||
{
|
{
|
||||||
mMediaInfo = *aInfo;
|
mMediaInfo = *aInfo;
|
||||||
mIsEncrypted = aInfo->mIsEncrypted;
|
mIsEncrypted = aInfo->IsEncrypted();
|
||||||
mTags = aTags.forget();
|
mTags = aTags.forget();
|
||||||
mLoadedDataFired = false;
|
mLoadedDataFired = false;
|
||||||
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_METADATA);
|
||||||
@ -3086,6 +3086,16 @@ void HTMLMediaElement::MetadataLoaded(const MediaInfo* aInfo,
|
|||||||
ProcessMediaFragmentURI();
|
ProcessMediaFragmentURI();
|
||||||
mDecoder->SetFragmentEndTime(mFragmentEnd);
|
mDecoder->SetFragmentEndTime(mFragmentEnd);
|
||||||
}
|
}
|
||||||
|
if (mIsEncrypted) {
|
||||||
|
if (!mMediaSource) {
|
||||||
|
DecodeError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_EME
|
||||||
|
DispatchEncrypted(aInfo->mCrypto.mInitData, aInfo->mCrypto.mType);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Expose the tracks to JS directly.
|
// Expose the tracks to JS directly.
|
||||||
for (OutputMediaStream& out : mOutputStreams) {
|
for (OutputMediaStream& out : mOutputStreams) {
|
||||||
|
@ -571,6 +571,11 @@ child:
|
|||||||
int32_t aModifiers,
|
int32_t aModifiers,
|
||||||
bool aPreventDefault);
|
bool aPreventDefault);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APZ notification for mouse scroll testing events.
|
||||||
|
*/
|
||||||
|
MouseScrollTestEvent(ViewID aScrollId, nsString aEvent);
|
||||||
|
|
||||||
CompositionEvent(WidgetCompositionEvent event);
|
CompositionEvent(WidgetCompositionEvent event);
|
||||||
|
|
||||||
SelectionEvent(WidgetSelectionEvent event);
|
SelectionEvent(WidgetSelectionEvent event);
|
||||||
|
@ -2199,6 +2199,13 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TabChild::RecvMouseScrollTestEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
|
||||||
|
{
|
||||||
|
APZCCallbackHelper::NotifyMozMouseScrollEvent(aScrollId, aEvent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static Touch*
|
static Touch*
|
||||||
GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId)
|
GetTouchForIdentifier(const WidgetTouchEvent& aEvent, int32_t aId)
|
||||||
{
|
{
|
||||||
|
@ -365,6 +365,8 @@ public:
|
|||||||
const int32_t& aCharCode,
|
const int32_t& aCharCode,
|
||||||
const int32_t& aModifiers,
|
const int32_t& aModifiers,
|
||||||
const bool& aPreventDefault) override;
|
const bool& aPreventDefault) override;
|
||||||
|
virtual bool RecvMouseScrollTestEvent(const FrameMetrics::ViewID& aScrollId,
|
||||||
|
const nsString& aEvent) override;
|
||||||
virtual bool RecvCompositionEvent(const mozilla::WidgetCompositionEvent& event) override;
|
virtual bool RecvCompositionEvent(const mozilla::WidgetCompositionEvent& event) override;
|
||||||
virtual bool RecvSelectionEvent(const mozilla::WidgetSelectionEvent& event) override;
|
virtual bool RecvSelectionEvent(const mozilla::WidgetSelectionEvent& event) override;
|
||||||
virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture) override;
|
virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture) override;
|
||||||
|
@ -973,6 +973,14 @@ void TabParent::NotifyAPZStateChange(ViewID aViewId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TabParent::NotifyMouseScrollTestEvent(const ViewID& aScrollId, const nsString& aEvent)
|
||||||
|
{
|
||||||
|
if (!mIsDestroyed) {
|
||||||
|
unused << SendMouseScrollTestEvent(aScrollId, aEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TabParent::Activate()
|
TabParent::Activate()
|
||||||
{
|
{
|
||||||
|
@ -242,6 +242,7 @@ public:
|
|||||||
void NotifyAPZStateChange(ViewID aViewId,
|
void NotifyAPZStateChange(ViewID aViewId,
|
||||||
APZStateChange aChange,
|
APZStateChange aChange,
|
||||||
int aArg);
|
int aArg);
|
||||||
|
void NotifyMouseScrollTestEvent(const ViewID& aScrollId, const nsString& aEvent);
|
||||||
void Activate();
|
void Activate();
|
||||||
void Deactivate();
|
void Deactivate();
|
||||||
|
|
||||||
|
@ -1282,6 +1282,7 @@ static const char* const gMachineStateStr[] = {
|
|||||||
"NONE",
|
"NONE",
|
||||||
"DECODING_METADATA",
|
"DECODING_METADATA",
|
||||||
"WAIT_FOR_RESOURCES",
|
"WAIT_FOR_RESOURCES",
|
||||||
|
"WAIT_FOR_CDM",
|
||||||
"DECODING_FIRSTFRAME",
|
"DECODING_FIRSTFRAME",
|
||||||
"DORMANT",
|
"DORMANT",
|
||||||
"DECODING",
|
"DECODING",
|
||||||
@ -1582,13 +1583,19 @@ void MediaDecoderStateMachine::DoNotifyWaitingForResourcesStatusChanged()
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
|
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
|
||||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
if (mState != DECODER_STATE_WAIT_FOR_RESOURCES) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DECODER_LOG("DoNotifyWaitingForResourcesStatusChanged");
|
DECODER_LOG("DoNotifyWaitingForResourcesStatusChanged");
|
||||||
// The reader is no longer waiting for resources (say a hardware decoder),
|
|
||||||
// we can now proceed to decode metadata.
|
if (mState == DECODER_STATE_WAIT_FOR_RESOURCES) {
|
||||||
SetState(DECODER_STATE_DECODING_NONE);
|
// The reader is no longer waiting for resources (say a hardware decoder),
|
||||||
|
// we can now proceed to decode metadata.
|
||||||
|
SetState(DECODER_STATE_DECODING_NONE);
|
||||||
|
} else if (mState == DECODER_STATE_WAIT_FOR_CDM &&
|
||||||
|
!mReader->IsWaitingOnCDMResource()) {
|
||||||
|
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
|
||||||
|
EnqueueDecodeFirstFrameTask();
|
||||||
|
}
|
||||||
|
|
||||||
ScheduleStateMachine();
|
ScheduleStateMachine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2269,6 +2276,13 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mState == DECODER_STATE_DECODING_METADATA) {
|
if (mState == DECODER_STATE_DECODING_METADATA) {
|
||||||
|
if (mReader->IsWaitingOnCDMResource()) {
|
||||||
|
// Metadata parsing was successful but we're still waiting for CDM caps
|
||||||
|
// to become available so that we can build the correct decryptor/decoder.
|
||||||
|
SetState(DECODER_STATE_WAIT_FOR_CDM);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
|
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
|
||||||
res = EnqueueDecodeFirstFrameTask();
|
res = EnqueueDecodeFirstFrameTask();
|
||||||
if (NS_FAILED(res)) {
|
if (NS_FAILED(res)) {
|
||||||
@ -2678,6 +2692,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case DECODER_STATE_WAIT_FOR_CDM:
|
||||||
case DECODER_STATE_WAIT_FOR_RESOURCES: {
|
case DECODER_STATE_WAIT_FOR_RESOURCES: {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ public:
|
|||||||
DECODER_STATE_DECODING_NONE,
|
DECODER_STATE_DECODING_NONE,
|
||||||
DECODER_STATE_DECODING_METADATA,
|
DECODER_STATE_DECODING_METADATA,
|
||||||
DECODER_STATE_WAIT_FOR_RESOURCES,
|
DECODER_STATE_WAIT_FOR_RESOURCES,
|
||||||
|
DECODER_STATE_WAIT_FOR_CDM,
|
||||||
DECODER_STATE_DECODING_FIRSTFRAME,
|
DECODER_STATE_DECODING_FIRSTFRAME,
|
||||||
DECODER_STATE_DORMANT,
|
DECODER_STATE_DORMANT,
|
||||||
DECODER_STATE_DECODING,
|
DECODER_STATE_DECODING,
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
#include "ImageTypes.h"
|
#include "ImageTypes.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
#include "StreamBuffer.h" // for TrackID
|
#include "StreamBuffer.h" // for TrackID
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -102,10 +103,22 @@ public:
|
|||||||
TrackInfo mTrackInfo;
|
TrackInfo mTrackInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EncryptionInfo {
|
||||||
|
public:
|
||||||
|
EncryptionInfo() : mIsEncrypted(false) {}
|
||||||
|
|
||||||
|
// Encryption type to be passed to JS. Usually `cenc'.
|
||||||
|
nsString mType;
|
||||||
|
|
||||||
|
// Encryption data.
|
||||||
|
nsTArray<uint8_t> mInitData;
|
||||||
|
|
||||||
|
// True if the stream has encryption metadata
|
||||||
|
bool mIsEncrypted;
|
||||||
|
};
|
||||||
|
|
||||||
class MediaInfo {
|
class MediaInfo {
|
||||||
public:
|
public:
|
||||||
MediaInfo() : mIsEncrypted(false) {}
|
|
||||||
|
|
||||||
bool HasVideo() const
|
bool HasVideo() const
|
||||||
{
|
{
|
||||||
return mVideo.mHasVideo;
|
return mVideo.mHasVideo;
|
||||||
@ -116,16 +129,21 @@ public:
|
|||||||
return mAudio.mHasAudio;
|
return mAudio.mHasAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsEncrypted() const
|
||||||
|
{
|
||||||
|
return mCrypto.mIsEncrypted;
|
||||||
|
}
|
||||||
|
|
||||||
bool HasValidMedia() const
|
bool HasValidMedia() const
|
||||||
{
|
{
|
||||||
return HasVideo() || HasAudio();
|
return HasVideo() || HasAudio();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mIsEncrypted;
|
|
||||||
|
|
||||||
// TODO: Store VideoInfo and AudioIndo in arrays to support multi-tracks.
|
// TODO: Store VideoInfo and AudioIndo in arrays to support multi-tracks.
|
||||||
VideoInfo mVideo;
|
VideoInfo mVideo;
|
||||||
AudioInfo mAudio;
|
AudioInfo mAudio;
|
||||||
|
|
||||||
|
EncryptionInfo mCrypto;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -2213,6 +2213,7 @@ MediaStream::RunAfterPendingUpdates(already_AddRefed<nsIRunnable> aRunnable)
|
|||||||
// runnable will run in finite time.
|
// runnable will run in finite time.
|
||||||
if (!(graph->mRealtime || graph->mNonRealtimeProcessing)) {
|
if (!(graph->mRealtime || graph->mNonRealtimeProcessing)) {
|
||||||
runnable->Run();
|
runnable->Run();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Message : public ControlMessage {
|
class Message : public ControlMessage {
|
||||||
|
@ -265,12 +265,6 @@ AVCCDecoderModule::Startup()
|
|||||||
return mPDM->Startup();
|
return mPDM->Startup();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
AVCCDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
return mPDM->Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder>
|
already_AddRefed<MediaDataDecoder>
|
||||||
AVCCDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
AVCCDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
|
@ -28,7 +28,6 @@ public:
|
|||||||
virtual ~AVCCDecoderModule();
|
virtual ~AVCCDecoderModule();
|
||||||
|
|
||||||
virtual nsresult Startup() override;
|
virtual nsresult Startup() override;
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
@ -206,11 +206,6 @@ private:
|
|||||||
class BlankDecoderModule : public PlatformDecoderModule {
|
class BlankDecoderModule : public PlatformDecoderModule {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Called when the decoders have shutdown. Main thread only.
|
|
||||||
virtual nsresult Shutdown() override {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode thread.
|
// Decode thread.
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
@ -156,6 +156,7 @@ MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
|
|||||||
, mDemuxerInitialized(false)
|
, mDemuxerInitialized(false)
|
||||||
, mFoundSPSForTelemetry(false)
|
, mFoundSPSForTelemetry(false)
|
||||||
, mIsEncrypted(false)
|
, mIsEncrypted(false)
|
||||||
|
, mAreDecodersSetup(false)
|
||||||
, mIndexReady(false)
|
, mIndexReady(false)
|
||||||
, mDemuxerMonitor("MP4 Demuxer")
|
, mDemuxerMonitor("MP4 Demuxer")
|
||||||
#if defined(MP4_READER_DORMANT_HEURISTIC)
|
#if defined(MP4_READER_DORMANT_HEURISTIC)
|
||||||
@ -204,10 +205,7 @@ MP4Reader::Shutdown()
|
|||||||
// Dispose of the queued sample before shutting down the demuxer
|
// Dispose of the queued sample before shutting down the demuxer
|
||||||
mQueuedVideoSample = nullptr;
|
mQueuedVideoSample = nullptr;
|
||||||
|
|
||||||
if (mPlatform) {
|
mPlatform = nullptr;
|
||||||
mPlatform->Shutdown();
|
|
||||||
mPlatform = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return MediaDecoderReader::Shutdown();
|
return MediaDecoderReader::Shutdown();
|
||||||
}
|
}
|
||||||
@ -266,41 +264,13 @@ MP4Reader::Init(MediaDecoderReader* aCloneDonor)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_EME
|
|
||||||
class DispatchKeyNeededEvent : public nsRunnable {
|
|
||||||
public:
|
|
||||||
DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
|
|
||||||
nsTArray<uint8_t>& aInitData,
|
|
||||||
const nsString& aInitDataType)
|
|
||||||
: mDecoder(aDecoder)
|
|
||||||
, mInitData(aInitData)
|
|
||||||
, mInitDataType(aInitDataType)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
NS_IMETHOD Run() {
|
|
||||||
// Note: Null check the owner, as the decoder could have been shutdown
|
|
||||||
// since this event was dispatched.
|
|
||||||
MediaDecoderOwner* owner = mDecoder->GetOwner();
|
|
||||||
if (owner) {
|
|
||||||
owner->DispatchEncrypted(mInitData, mInitDataType);
|
|
||||||
}
|
|
||||||
mDecoder = nullptr;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
nsRefPtr<AbstractMediaDecoder> mDecoder;
|
|
||||||
nsTArray<uint8_t> mInitData;
|
|
||||||
nsString mInitDataType;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void MP4Reader::RequestCodecResource() {
|
void MP4Reader::RequestCodecResource() {
|
||||||
if (mVideo.mDecoder) {
|
if (mVideo.mDecoder) {
|
||||||
mVideo.mDecoder->AllocateMediaResources();
|
mVideo.mDecoder->AllocateMediaResources();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MP4Reader::IsWaitingOnCodecResource() {
|
bool MP4Reader::IsWaitingMediaResources() {
|
||||||
return mVideo.mDecoder && mVideo.mDecoder->IsWaitingMediaResources();
|
return mVideo.mDecoder && mVideo.mDecoder->IsWaitingMediaResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,15 +300,6 @@ bool MP4Reader::IsWaitingOnCDMResource() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MP4Reader::IsWaitingMediaResources()
|
|
||||||
{
|
|
||||||
// IsWaitingOnCDMResource() *must* come first, because we don't know whether
|
|
||||||
// we can create a decoder until the CDM is initialized and it has told us
|
|
||||||
// whether *it* will decode, or whether we need to create a PDM to do the
|
|
||||||
// decoding
|
|
||||||
return IsWaitingOnCDMResource() || IsWaitingOnCodecResource();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MP4Reader::ExtractCryptoInitData(nsTArray<uint8_t>& aInitData)
|
MP4Reader::ExtractCryptoInitData(nsTArray<uint8_t>& aInitData)
|
||||||
{
|
{
|
||||||
@ -407,7 +368,7 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||||||
{
|
{
|
||||||
MonitorAutoUnlock unlock(mDemuxerMonitor);
|
MonitorAutoUnlock unlock(mDemuxerMonitor);
|
||||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
mInfo.mIsEncrypted = mIsEncrypted = mCrypto.valid;
|
mInfo.mCrypto.mIsEncrypted = mIsEncrypted = mCrypto.valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remember that we've initialized the demuxer, so that if we're decoding
|
// Remember that we've initialized the demuxer, so that if we're decoding
|
||||||
@ -420,90 +381,18 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCrypto.valid) {
|
|
||||||
#ifdef MOZ_EME
|
|
||||||
// We have encrypted audio or video. We'll need a CDM to decrypt and
|
|
||||||
// possibly decode this. Wait until we've received a CDM from the
|
|
||||||
// JavaScript player app. Note: we still go through the motions here
|
|
||||||
// even if EME is disabled, so that if script tries and fails to create
|
|
||||||
// a CDM, we can detect that and notify chrome and show some UI explaining
|
|
||||||
// that we failed due to EME being disabled.
|
|
||||||
nsRefPtr<CDMProxy> proxy;
|
|
||||||
nsTArray<uint8_t> initData;
|
|
||||||
ExtractCryptoInitData(initData);
|
|
||||||
if (initData.Length() == 0) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
if (!mInitDataEncountered.Contains(initData)) {
|
|
||||||
mInitDataEncountered.AppendElement(initData);
|
|
||||||
NS_DispatchToMainThread(new DispatchKeyNeededEvent(mDecoder, initData, NS_LITERAL_STRING("cenc")));
|
|
||||||
}
|
|
||||||
if (IsWaitingMediaResources()) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(!IsWaitingMediaResources());
|
|
||||||
|
|
||||||
{
|
|
||||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
|
||||||
proxy = mDecoder->GetCDMProxy();
|
|
||||||
}
|
|
||||||
MOZ_ASSERT(proxy);
|
|
||||||
|
|
||||||
mPlatform = PlatformDecoderModule::CreateCDMWrapper(proxy,
|
|
||||||
HasAudio(),
|
|
||||||
HasVideo());
|
|
||||||
NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE);
|
|
||||||
#else
|
|
||||||
// EME not supported.
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
mPlatform = PlatformDecoderModule::Create();
|
|
||||||
NS_ENSURE_TRUE(mPlatform, NS_ERROR_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HasAudio()) {
|
if (HasAudio()) {
|
||||||
const AudioDecoderConfig& audio = mDemuxer->AudioConfig();
|
const AudioDecoderConfig& audio = mDemuxer->AudioConfig();
|
||||||
if (mInfo.mAudio.mHasAudio && !IsSupportedAudioMimeType(audio.mime_type)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
mInfo.mAudio.mRate = audio.samples_per_second;
|
mInfo.mAudio.mRate = audio.samples_per_second;
|
||||||
mInfo.mAudio.mChannels = audio.channel_count;
|
mInfo.mAudio.mChannels = audio.channel_count;
|
||||||
mAudio.mCallback = new DecoderCallback(this, kAudio);
|
mAudio.mCallback = new DecoderCallback(this, kAudio);
|
||||||
mAudio.mDecoder = mPlatform->CreateAudioDecoder(audio,
|
|
||||||
mAudio.mTaskQueue,
|
|
||||||
mAudio.mCallback);
|
|
||||||
NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, NS_ERROR_FAILURE);
|
|
||||||
nsresult rv = mAudio.mDecoder->Init();
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasVideo()) {
|
if (HasVideo()) {
|
||||||
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
|
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
|
||||||
if (mInfo.mVideo.mHasVideo && !IsSupportedVideoMimeType(video.mime_type)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
mInfo.mVideo.mDisplay =
|
mInfo.mVideo.mDisplay =
|
||||||
nsIntSize(video.display_width, video.display_height);
|
nsIntSize(video.display_width, video.display_height);
|
||||||
mVideo.mCallback = new DecoderCallback(this, kVideo);
|
mVideo.mCallback = new DecoderCallback(this, kVideo);
|
||||||
if (mSharedDecoderManager && mPlatform->SupportsSharedDecoders(video)) {
|
|
||||||
mVideo.mDecoder =
|
|
||||||
mSharedDecoderManager->CreateVideoDecoder(mPlatform,
|
|
||||||
video,
|
|
||||||
mLayersBackendType,
|
|
||||||
mDecoder->GetImageContainer(),
|
|
||||||
mVideo.mTaskQueue,
|
|
||||||
mVideo.mCallback);
|
|
||||||
} else {
|
|
||||||
mVideo.mDecoder = mPlatform->CreateVideoDecoder(video,
|
|
||||||
mLayersBackendType,
|
|
||||||
mDecoder->GetImageContainer(),
|
|
||||||
mVideo.mTaskQueue,
|
|
||||||
mVideo.mCallback);
|
|
||||||
}
|
|
||||||
NS_ENSURE_TRUE(mVideo.mDecoder != nullptr, NS_ERROR_FAILURE);
|
|
||||||
nsresult rv = mVideo.mDecoder->Init();
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// Collect telemetry from h264 AVCC SPS.
|
// Collect telemetry from h264 AVCC SPS.
|
||||||
if (!mFoundSPSForTelemetry) {
|
if (!mFoundSPSForTelemetry) {
|
||||||
@ -511,6 +400,17 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mIsEncrypted) {
|
||||||
|
nsTArray<uint8_t> initData;
|
||||||
|
ExtractCryptoInitData(initData);
|
||||||
|
if (initData.Length() == 0) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mInfo.mCrypto.mInitData = initData;
|
||||||
|
mInfo.mCrypto.mType = NS_LITERAL_STRING("cenc");
|
||||||
|
}
|
||||||
|
|
||||||
// Get the duration, and report it to the decoder if we have it.
|
// Get the duration, and report it to the decoder if we have it.
|
||||||
Microseconds duration;
|
Microseconds duration;
|
||||||
{
|
{
|
||||||
@ -525,12 +425,96 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo,
|
|||||||
*aInfo = mInfo;
|
*aInfo = mInfo;
|
||||||
*aTags = nullptr;
|
*aTags = nullptr;
|
||||||
|
|
||||||
|
if (!IsWaitingMediaResources() && !IsWaitingOnCDMResource()) {
|
||||||
|
NS_ENSURE_TRUE(EnsureDecodersSetup(), NS_ERROR_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
MonitorAutoLock mon(mDemuxerMonitor);
|
MonitorAutoLock mon(mDemuxerMonitor);
|
||||||
UpdateIndex();
|
UpdateIndex();
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MP4Reader::EnsureDecodersSetup()
|
||||||
|
{
|
||||||
|
if (mAreDecodersSetup) {
|
||||||
|
return !!mPlatform;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mIsEncrypted) {
|
||||||
|
#ifdef MOZ_EME
|
||||||
|
// We have encrypted audio or video. We'll need a CDM to decrypt and
|
||||||
|
// possibly decode this. Wait until we've received a CDM from the
|
||||||
|
// JavaScript player app. Note: we still go through the motions here
|
||||||
|
// even if EME is disabled, so that if script tries and fails to create
|
||||||
|
// a CDM, we can detect that and notify chrome and show some UI explaining
|
||||||
|
// that we failed due to EME being disabled.
|
||||||
|
nsRefPtr<CDMProxy> proxy;
|
||||||
|
if (IsWaitingMediaResources()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(!IsWaitingMediaResources());
|
||||||
|
|
||||||
|
{
|
||||||
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
|
proxy = mDecoder->GetCDMProxy();
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(proxy);
|
||||||
|
|
||||||
|
mPlatform = PlatformDecoderModule::CreateCDMWrapper(proxy,
|
||||||
|
HasAudio(),
|
||||||
|
HasVideo());
|
||||||
|
NS_ENSURE_TRUE(mPlatform, false);
|
||||||
|
#else
|
||||||
|
// EME not supported.
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
mPlatform = PlatformDecoderModule::Create();
|
||||||
|
NS_ENSURE_TRUE(mPlatform, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasAudio()) {
|
||||||
|
NS_ENSURE_TRUE(IsSupportedAudioMimeType(mDemuxer->AudioConfig().mime_type),
|
||||||
|
false);
|
||||||
|
|
||||||
|
mAudio.mDecoder = mPlatform->CreateAudioDecoder(mDemuxer->AudioConfig(),
|
||||||
|
mAudio.mTaskQueue,
|
||||||
|
mAudio.mCallback);
|
||||||
|
NS_ENSURE_TRUE(mAudio.mDecoder != nullptr, false);
|
||||||
|
nsresult rv = mAudio.mDecoder->Init();
|
||||||
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasVideo()) {
|
||||||
|
NS_ENSURE_TRUE(IsSupportedVideoMimeType(mDemuxer->VideoConfig().mime_type),
|
||||||
|
false);
|
||||||
|
|
||||||
|
if (mSharedDecoderManager && mPlatform->SupportsSharedDecoders(mDemuxer->VideoConfig())) {
|
||||||
|
mVideo.mDecoder =
|
||||||
|
mSharedDecoderManager->CreateVideoDecoder(mPlatform,
|
||||||
|
mDemuxer->VideoConfig(),
|
||||||
|
mLayersBackendType,
|
||||||
|
mDecoder->GetImageContainer(),
|
||||||
|
mVideo.mTaskQueue,
|
||||||
|
mVideo.mCallback);
|
||||||
|
} else {
|
||||||
|
mVideo.mDecoder = mPlatform->CreateVideoDecoder(mDemuxer->VideoConfig(),
|
||||||
|
mLayersBackendType,
|
||||||
|
mDecoder->GetImageContainer(),
|
||||||
|
mVideo.mTaskQueue,
|
||||||
|
mVideo.mCallback);
|
||||||
|
}
|
||||||
|
NS_ENSURE_TRUE(mVideo.mDecoder != nullptr, false);
|
||||||
|
nsresult rv = mVideo.mDecoder->Init();
|
||||||
|
NS_ENSURE_SUCCESS(rv, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mAreDecodersSetup = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MP4Reader::ReadUpdatedMetadata(MediaInfo* aInfo)
|
MP4Reader::ReadUpdatedMetadata(MediaInfo* aInfo)
|
||||||
{
|
{
|
||||||
@ -579,10 +563,10 @@ void
|
|||||||
MP4Reader::DisableHardwareAcceleration()
|
MP4Reader::DisableHardwareAcceleration()
|
||||||
{
|
{
|
||||||
if (HasVideo() && mSharedDecoderManager) {
|
if (HasVideo() && mSharedDecoderManager) {
|
||||||
mPlatform->DisableHardwareAcceleration();
|
mSharedDecoderManager->DisableHardwareAcceleration();
|
||||||
|
|
||||||
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
|
const VideoDecoderConfig& video = mDemuxer->VideoConfig();
|
||||||
if (!mSharedDecoderManager->Recreate(mPlatform, video, mLayersBackendType, mDecoder->GetImageContainer())) {
|
if (!mSharedDecoderManager->Recreate(video, mLayersBackendType, mDecoder->GetImageContainer())) {
|
||||||
MonitorAutoLock mon(mVideo.mMonitor);
|
MonitorAutoLock mon(mVideo.mMonitor);
|
||||||
mVideo.mError = true;
|
mVideo.mError = true;
|
||||||
if (mVideo.HasPromise()) {
|
if (mVideo.HasPromise()) {
|
||||||
@ -618,6 +602,11 @@ MP4Reader::RequestVideoData(bool aSkipToNextKeyframe,
|
|||||||
MOZ_ASSERT(GetTaskQueue()->IsCurrentThreadIn());
|
MOZ_ASSERT(GetTaskQueue()->IsCurrentThreadIn());
|
||||||
VLOG("skip=%d time=%lld", aSkipToNextKeyframe, aTimeThreshold);
|
VLOG("skip=%d time=%lld", aSkipToNextKeyframe, aTimeThreshold);
|
||||||
|
|
||||||
|
if (!EnsureDecodersSetup()) {
|
||||||
|
NS_WARNING("Error constructing MP4 decoders");
|
||||||
|
return VideoDataPromise::CreateAndReject(DECODE_ERROR, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
if (mShutdown) {
|
if (mShutdown) {
|
||||||
NS_WARNING("RequestVideoData on shutdown MP4Reader!");
|
NS_WARNING("RequestVideoData on shutdown MP4Reader!");
|
||||||
return VideoDataPromise::CreateAndReject(CANCELED, __func__);
|
return VideoDataPromise::CreateAndReject(CANCELED, __func__);
|
||||||
@ -653,6 +642,12 @@ MP4Reader::RequestAudioData()
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(GetTaskQueue()->IsCurrentThreadIn());
|
MOZ_ASSERT(GetTaskQueue()->IsCurrentThreadIn());
|
||||||
VLOG("");
|
VLOG("");
|
||||||
|
|
||||||
|
if (!EnsureDecodersSetup()) {
|
||||||
|
NS_WARNING("Error constructing MP4 decoders");
|
||||||
|
return AudioDataPromise::CreateAndReject(DECODE_ERROR, __func__);
|
||||||
|
}
|
||||||
|
|
||||||
if (mShutdown) {
|
if (mShutdown) {
|
||||||
NS_WARNING("RequestAudioData on shutdown MP4Reader!");
|
NS_WARNING("RequestAudioData on shutdown MP4Reader!");
|
||||||
return AudioDataPromise::CreateAndReject(CANCELED, __func__);
|
return AudioDataPromise::CreateAndReject(CANCELED, __func__);
|
||||||
|
@ -103,6 +103,8 @@ private:
|
|||||||
bool InitDemuxer();
|
bool InitDemuxer();
|
||||||
void ReturnOutput(MediaData* aData, TrackType aTrack);
|
void ReturnOutput(MediaData* aData, TrackType aTrack);
|
||||||
|
|
||||||
|
bool EnsureDecodersSetup();
|
||||||
|
|
||||||
// Sends input to decoder for aTrack, and output to the state machine,
|
// Sends input to decoder for aTrack, and output to the state machine,
|
||||||
// if necessary.
|
// if necessary.
|
||||||
void Update(TrackType aTrack);
|
void Update(TrackType aTrack);
|
||||||
@ -135,7 +137,6 @@ private:
|
|||||||
bool IsSupportedVideoMimeType(const char* aMimeType);
|
bool IsSupportedVideoMimeType(const char* aMimeType);
|
||||||
void NotifyResourcesStatusChanged();
|
void NotifyResourcesStatusChanged();
|
||||||
void RequestCodecResource();
|
void RequestCodecResource();
|
||||||
bool IsWaitingOnCodecResource();
|
|
||||||
virtual bool IsWaitingOnCDMResource() override;
|
virtual bool IsWaitingOnCDMResource() override;
|
||||||
|
|
||||||
Microseconds GetNextKeyframeTime();
|
Microseconds GetNextKeyframeTime();
|
||||||
@ -285,6 +286,8 @@ private:
|
|||||||
// Synchronized by decoder monitor.
|
// Synchronized by decoder monitor.
|
||||||
bool mIsEncrypted;
|
bool mIsEncrypted;
|
||||||
|
|
||||||
|
bool mAreDecodersSetup;
|
||||||
|
|
||||||
bool mIndexReady;
|
bool mIndexReady;
|
||||||
Monitor mDemuxerMonitor;
|
Monitor mDemuxerMonitor;
|
||||||
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
|
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
|
||||||
|
@ -86,13 +86,6 @@ public:
|
|||||||
bool aHasVideo);
|
bool aHasVideo);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Called to shutdown the decoder module and cleanup state. The PDM
|
|
||||||
// is deleted immediately after Shutdown() is called. Shutdown() is
|
|
||||||
// called after Shutdown() has been called on all MediaDataDecoders
|
|
||||||
// created from this PlatformDecoderModule.
|
|
||||||
// This is called on the decode task queue.
|
|
||||||
virtual nsresult Shutdown() = 0;
|
|
||||||
|
|
||||||
// Creates an H.264 decoder. The layers backend is passed in so that
|
// Creates an H.264 decoder. The layers backend is passed in so that
|
||||||
// decoders can determine whether hardware accelerated decoding can be used.
|
// decoders can determine whether hardware accelerated decoding can be used.
|
||||||
// Asynchronous decoding of video should be done in runnables dispatched
|
// Asynchronous decoding of video should be done in runnables dispatched
|
||||||
|
@ -12,7 +12,10 @@ namespace mozilla {
|
|||||||
class SharedDecoderCallback : public MediaDataDecoderCallback
|
class SharedDecoderCallback : public MediaDataDecoderCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit SharedDecoderCallback(SharedDecoderManager* aManager) : mManager(aManager) {}
|
explicit SharedDecoderCallback(SharedDecoderManager* aManager)
|
||||||
|
: mManager(aManager)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
virtual void Output(MediaData* aData) override
|
virtual void Output(MediaData* aData) override
|
||||||
{
|
{
|
||||||
@ -66,25 +69,34 @@ SharedDecoderManager::SharedDecoderManager()
|
|||||||
mCallback = new SharedDecoderCallback(this);
|
mCallback = new SharedDecoderCallback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedDecoderManager::~SharedDecoderManager() {}
|
SharedDecoderManager::~SharedDecoderManager()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder>
|
already_AddRefed<MediaDataDecoder>
|
||||||
SharedDecoderManager::CreateVideoDecoder(
|
SharedDecoderManager::CreateVideoDecoder(
|
||||||
PlatformDecoderModule* aPDM,
|
PlatformDecoderModule* aPDM,
|
||||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend, layers::ImageContainer* aImageContainer,
|
layers::LayersBackend aLayersBackend,
|
||||||
FlushableMediaTaskQueue* aVideoTaskQueue, MediaDataDecoderCallback* aCallback)
|
layers::ImageContainer* aImageContainer,
|
||||||
|
FlushableMediaTaskQueue* aVideoTaskQueue,
|
||||||
|
MediaDataDecoderCallback* aCallback)
|
||||||
{
|
{
|
||||||
if (!mDecoder) {
|
if (!mDecoder) {
|
||||||
// We use the manager's task queue for the decoder, rather than the one
|
// We use the manager's task queue for the decoder, rather than the one
|
||||||
// passed in, so that none of the objects sharing the decoder can shutdown
|
// passed in, so that none of the objects sharing the decoder can shutdown
|
||||||
// the task queue while we're potentially still using it for a *different*
|
// the task queue while we're potentially still using it for a *different*
|
||||||
// object also sharing the decoder.
|
// object also sharing the decoder.
|
||||||
mDecoder = aPDM->CreateVideoDecoder(
|
mDecoder = aPDM->CreateVideoDecoder(aConfig,
|
||||||
aConfig, aLayersBackend, aImageContainer, mTaskQueue, mCallback);
|
aLayersBackend,
|
||||||
|
aImageContainer,
|
||||||
|
mTaskQueue,
|
||||||
|
mCallback);
|
||||||
if (!mDecoder) {
|
if (!mDecoder) {
|
||||||
|
mPDM = nullptr;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
mPDM = aPDM;
|
||||||
nsresult rv = mDecoder->Init();
|
nsresult rv = mDecoder->Init();
|
||||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||||
}
|
}
|
||||||
@ -93,15 +105,25 @@ SharedDecoderManager::CreateVideoDecoder(
|
|||||||
return proxy.forget();
|
return proxy.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SharedDecoderManager::DisableHardwareAcceleration()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mPDM);
|
||||||
|
mPDM->DisableHardwareAcceleration();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SharedDecoderManager::Recreate(PlatformDecoderModule* aPDM,
|
SharedDecoderManager::Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
layers::ImageContainer* aImageContainer)
|
layers::ImageContainer* aImageContainer)
|
||||||
{
|
{
|
||||||
mDecoder->Flush();
|
mDecoder->Flush();
|
||||||
mDecoder->Shutdown();
|
mDecoder->Shutdown();
|
||||||
mDecoder = aPDM->CreateVideoDecoder(aConfig, aLayersBackend, aImageContainer, mTaskQueue, mCallback);
|
mDecoder = mPDM->CreateVideoDecoder(aConfig,
|
||||||
|
aLayersBackend,
|
||||||
|
aImageContainer,
|
||||||
|
mTaskQueue,
|
||||||
|
mCallback);
|
||||||
if (!mDecoder) {
|
if (!mDecoder) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -168,6 +190,7 @@ SharedDecoderManager::Shutdown()
|
|||||||
mDecoder->Shutdown();
|
mDecoder->Shutdown();
|
||||||
mDecoder = nullptr;
|
mDecoder = nullptr;
|
||||||
}
|
}
|
||||||
|
mPDM = nullptr;
|
||||||
if (mTaskQueue) {
|
if (mTaskQueue) {
|
||||||
mTaskQueue->BeginShutdown();
|
mTaskQueue->BeginShutdown();
|
||||||
mTaskQueue->AwaitShutdownAndIdle();
|
mTaskQueue->AwaitShutdownAndIdle();
|
||||||
@ -175,13 +198,17 @@ SharedDecoderManager::Shutdown()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedDecoderProxy::SharedDecoderProxy(
|
SharedDecoderProxy::SharedDecoderProxy(SharedDecoderManager* aManager,
|
||||||
SharedDecoderManager* aManager, MediaDataDecoderCallback* aCallback)
|
MediaDataDecoderCallback* aCallback)
|
||||||
: mManager(aManager), mCallback(aCallback)
|
: mManager(aManager)
|
||||||
|
, mCallback(aCallback)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedDecoderProxy::~SharedDecoderProxy() { Shutdown(); }
|
SharedDecoderProxy::~SharedDecoderProxy()
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
SharedDecoderProxy::Init()
|
SharedDecoderProxy::Init()
|
||||||
|
@ -28,7 +28,8 @@ public:
|
|||||||
PlatformDecoderModule* aPDM,
|
PlatformDecoderModule* aPDM,
|
||||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
layers::ImageContainer* aImageContainer, FlushableMediaTaskQueue* aVideoTaskQueue,
|
layers::ImageContainer* aImageContainer,
|
||||||
|
FlushableMediaTaskQueue* aVideoTaskQueue,
|
||||||
MediaDataDecoderCallback* aCallback);
|
MediaDataDecoderCallback* aCallback);
|
||||||
|
|
||||||
void SetReader(MediaDecoderReader* aReader);
|
void SetReader(MediaDecoderReader* aReader);
|
||||||
@ -40,15 +41,16 @@ public:
|
|||||||
friend class SharedDecoderProxy;
|
friend class SharedDecoderProxy;
|
||||||
friend class SharedDecoderCallback;
|
friend class SharedDecoderCallback;
|
||||||
|
|
||||||
bool Recreate(PlatformDecoderModule* aPDM,
|
void DisableHardwareAcceleration();
|
||||||
const mp4_demuxer::VideoDecoderConfig& aConfig,
|
bool Recreate(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
layers::ImageContainer* aImageContainer);
|
layers::ImageContainer* aImageContainer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual ~SharedDecoderManager();
|
virtual ~SharedDecoderManager();
|
||||||
void DrainComplete();
|
void DrainComplete();
|
||||||
|
|
||||||
|
nsRefPtr<PlatformDecoderModule> mPDM;
|
||||||
nsRefPtr<MediaDataDecoder> mDecoder;
|
nsRefPtr<MediaDataDecoder> mDecoder;
|
||||||
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
|
nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
|
||||||
SharedDecoderProxy* mActiveProxy;
|
SharedDecoderProxy* mActiveProxy;
|
||||||
|
@ -299,12 +299,6 @@ AndroidDecoderModule::CreateAudioDecoder(const mp4_demuxer::AudioDecoderConfig&
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
nsresult AndroidDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
|
MediaCodecDataDecoder::MediaCodecDataDecoder(MediaData::Type aType,
|
||||||
const char* aMimeType,
|
const char* aMimeType,
|
||||||
MediaFormat::Param aFormat,
|
MediaFormat::Param aFormat,
|
||||||
|
@ -19,8 +19,6 @@ typedef std::queue<mp4_demuxer::MP4Sample*> SampleQueue;
|
|||||||
|
|
||||||
class AndroidDecoderModule : public PlatformDecoderModule {
|
class AndroidDecoderModule : public PlatformDecoderModule {
|
||||||
public:
|
public:
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
|
@ -36,12 +36,46 @@ bool AppleDecoderModule::sIsVTHWAvailable = false;
|
|||||||
bool AppleDecoderModule::sIsVDAAvailable = false;
|
bool AppleDecoderModule::sIsVDAAvailable = false;
|
||||||
bool AppleDecoderModule::sForceVDA = false;
|
bool AppleDecoderModule::sForceVDA = false;
|
||||||
|
|
||||||
|
class LinkTask : public nsRunnable {
|
||||||
|
public:
|
||||||
|
NS_IMETHOD Run() override {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||||
|
MOZ_ASSERT(AppleDecoderModule::sInitialized);
|
||||||
|
if (AppleDecoderModule::sIsVDAAvailable) {
|
||||||
|
AppleVDALinker::Link();
|
||||||
|
}
|
||||||
|
if (AppleDecoderModule::sIsVTAvailable) {
|
||||||
|
AppleVTLinker::Link();
|
||||||
|
AppleCMLinker::Link();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnlinkTask : public nsRunnable {
|
||||||
|
public:
|
||||||
|
NS_IMETHOD Run() override {
|
||||||
|
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||||
|
MOZ_ASSERT(AppleDecoderModule::sInitialized);
|
||||||
|
if (AppleDecoderModule::sIsVDAAvailable) {
|
||||||
|
AppleVDALinker::Unlink();
|
||||||
|
}
|
||||||
|
if (AppleDecoderModule::sIsVTAvailable) {
|
||||||
|
AppleVTLinker::Unlink();
|
||||||
|
AppleCMLinker::Unlink();
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
AppleDecoderModule::AppleDecoderModule()
|
AppleDecoderModule::AppleDecoderModule()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
AppleDecoderModule::~AppleDecoderModule()
|
AppleDecoderModule::~AppleDecoderModule()
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIRunnable> task(new UnlinkTask());
|
||||||
|
NS_DispatchToMainThread(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
@ -104,22 +138,6 @@ AppleDecoderModule::CanDecode()
|
|||||||
return (sIsVDAAvailable || sIsVTAvailable) ? NS_OK : NS_ERROR_NO_INTERFACE;
|
return (sIsVDAAvailable || sIsVTAvailable) ? NS_OK : NS_ERROR_NO_INTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
class LinkTask : public nsRunnable {
|
|
||||||
public:
|
|
||||||
NS_IMETHOD Run() override {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
|
||||||
MOZ_ASSERT(AppleDecoderModule::sInitialized);
|
|
||||||
if (AppleDecoderModule::sIsVDAAvailable) {
|
|
||||||
AppleVDALinker::Link();
|
|
||||||
}
|
|
||||||
if (AppleDecoderModule::sIsVTAvailable) {
|
|
||||||
AppleVTLinker::Link();
|
|
||||||
AppleCMLinker::Link();
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
AppleDecoderModule::Startup()
|
AppleDecoderModule::Startup()
|
||||||
{
|
{
|
||||||
@ -133,30 +151,6 @@ AppleDecoderModule::Startup()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnlinkTask : public nsRunnable {
|
|
||||||
public:
|
|
||||||
NS_IMETHOD Run() override {
|
|
||||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
|
||||||
MOZ_ASSERT(AppleDecoderModule::sInitialized);
|
|
||||||
if (AppleDecoderModule::sIsVDAAvailable) {
|
|
||||||
AppleVDALinker::Unlink();
|
|
||||||
}
|
|
||||||
if (AppleDecoderModule::sIsVTAvailable) {
|
|
||||||
AppleVTLinker::Unlink();
|
|
||||||
AppleCMLinker::Unlink();
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
nsresult
|
|
||||||
AppleDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIRunnable> task(new UnlinkTask());
|
|
||||||
NS_DispatchToMainThread(task);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder>
|
already_AddRefed<MediaDataDecoder>
|
||||||
AppleDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
AppleDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
|
@ -18,10 +18,6 @@ public:
|
|||||||
|
|
||||||
virtual nsresult Startup() override;
|
virtual nsresult Startup() override;
|
||||||
|
|
||||||
// Called when the decoders have shutdown. Main thread only.
|
|
||||||
// Does this really need to be main thread only????
|
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
// Decode thread.
|
// Decode thread.
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
@ -94,7 +94,11 @@ AppleVDALinker::Unlink()
|
|||||||
MOZ_ASSERT(sRefCount > 0, "Unbalanced Unlink()");
|
MOZ_ASSERT(sRefCount > 0, "Unbalanced Unlink()");
|
||||||
--sRefCount;
|
--sRefCount;
|
||||||
if (sLink && sRefCount < 1) {
|
if (sLink && sRefCount < 1) {
|
||||||
LOG("Unlinking VideoToolbox framework.");
|
LOG("Unlinking VideoDecodeAcceleration framework.");
|
||||||
|
#define LINK_FUNC(func) \
|
||||||
|
func = nullptr;
|
||||||
|
#include "AppleVDAFunctions.h"
|
||||||
|
#undef LINK_FUNC
|
||||||
dlclose(sLink);
|
dlclose(sLink);
|
||||||
sLink = nullptr;
|
sLink = nullptr;
|
||||||
skPropWidth = nullptr;
|
skPropWidth = nullptr;
|
||||||
|
@ -98,6 +98,10 @@ AppleVTLinker::Unlink()
|
|||||||
--sRefCount;
|
--sRefCount;
|
||||||
if (sLink && sRefCount < 1) {
|
if (sLink && sRefCount < 1) {
|
||||||
LOG("Unlinking VideoToolbox framework.");
|
LOG("Unlinking VideoToolbox framework.");
|
||||||
|
#define LINK_FUNC(func) \
|
||||||
|
func = nullptr;
|
||||||
|
#include "AppleVTFunctions.h"
|
||||||
|
#undef LINK_FUNC
|
||||||
dlclose(sLink);
|
dlclose(sLink);
|
||||||
sLink = nullptr;
|
sLink = nullptr;
|
||||||
skPropEnableHWAccel = nullptr;
|
skPropEnableHWAccel = nullptr;
|
||||||
|
@ -208,15 +208,6 @@ EMEDecoderModule::~EMEDecoderModule()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
EMEDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
if (mPDM) {
|
|
||||||
return mPDM->Shutdown();
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static already_AddRefed<MediaDataDecoderProxy>
|
static already_AddRefed<MediaDataDecoderProxy>
|
||||||
CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableMediaTaskQueue* aTaskQueue)
|
CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, FlushableMediaTaskQueue* aTaskQueue)
|
||||||
{
|
{
|
||||||
|
@ -28,9 +28,6 @@ public:
|
|||||||
|
|
||||||
virtual ~EMEDecoderModule();
|
virtual ~EMEDecoderModule();
|
||||||
|
|
||||||
// Called when the decoders have shutdown. Main thread only.
|
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
// Decode thread.
|
// Decode thread.
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
@ -28,8 +28,6 @@ public:
|
|||||||
FFmpegDecoderModule() {}
|
FFmpegDecoderModule() {}
|
||||||
virtual ~FFmpegDecoderModule() {}
|
virtual ~FFmpegDecoderModule() {}
|
||||||
|
|
||||||
virtual nsresult Shutdown() override { return NS_OK; }
|
|
||||||
|
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
|
@ -21,12 +21,6 @@ GMPDecoderModule::~GMPDecoderModule()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
GMPDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static already_AddRefed<MediaDataDecoderProxy>
|
static already_AddRefed<MediaDataDecoderProxy>
|
||||||
CreateDecoderWrapper(MediaDataDecoderCallback* aCallback)
|
CreateDecoderWrapper(MediaDataDecoderCallback* aCallback)
|
||||||
{
|
{
|
||||||
|
@ -17,9 +17,6 @@ public:
|
|||||||
|
|
||||||
virtual ~GMPDecoderModule();
|
virtual ~GMPDecoderModule();
|
||||||
|
|
||||||
// Called when the decoders have shutdown. Main thread only.
|
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
// Decode thread.
|
// Decode thread.
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
@ -26,12 +26,6 @@ GonkDecoderModule::Init()
|
|||||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
GonkDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder>
|
already_AddRefed<MediaDataDecoder>
|
||||||
GonkDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
GonkDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
mozilla::layers::LayersBackend aLayersBackend,
|
mozilla::layers::LayersBackend aLayersBackend,
|
||||||
|
@ -16,9 +16,6 @@ public:
|
|||||||
GonkDecoderModule();
|
GonkDecoderModule();
|
||||||
virtual ~GonkDecoderModule();
|
virtual ~GonkDecoderModule();
|
||||||
|
|
||||||
// Called when the decoders have shutdown.
|
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
// Decode thread.
|
// Decode thread.
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
|
@ -28,6 +28,8 @@ WMFDecoderModule::WMFDecoderModule()
|
|||||||
|
|
||||||
WMFDecoderModule::~WMFDecoderModule()
|
WMFDecoderModule::~WMFDecoderModule()
|
||||||
{
|
{
|
||||||
|
DebugOnly<HRESULT> hr = wmf::MFShutdown();
|
||||||
|
NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
@ -58,14 +60,6 @@ WMFDecoderModule::Startup()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
WMFDecoderModule::Shutdown()
|
|
||||||
{
|
|
||||||
DebugOnly<HRESULT> hr = wmf::MFShutdown();
|
|
||||||
NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
already_AddRefed<MediaDataDecoder>
|
already_AddRefed<MediaDataDecoder>
|
||||||
WMFDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
WMFDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
|
@ -19,9 +19,6 @@ public:
|
|||||||
// Initializes the module, loads required dynamic libraries, etc.
|
// Initializes the module, loads required dynamic libraries, etc.
|
||||||
virtual nsresult Startup() override;
|
virtual nsresult Startup() override;
|
||||||
|
|
||||||
// Called when the decoders have shutdown.
|
|
||||||
virtual nsresult Shutdown() override;
|
|
||||||
|
|
||||||
virtual already_AddRefed<MediaDataDecoder>
|
virtual already_AddRefed<MediaDataDecoder>
|
||||||
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
|
||||||
layers::LayersBackend aLayersBackend,
|
layers::LayersBackend aLayersBackend,
|
||||||
|
@ -665,10 +665,11 @@ GeckoMediaPluginService::LoadFromEnvironment()
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GeckoMediaPluginService::PathRunnable::Run()
|
GeckoMediaPluginService::PathRunnable::Run()
|
||||||
{
|
{
|
||||||
if (mAdd) {
|
if (mOperation == ADD) {
|
||||||
mService->AddOnGMPThread(mPath);
|
mService->AddOnGMPThread(mPath);
|
||||||
} else {
|
} else {
|
||||||
mService->RemoveOnGMPThread(mPath);
|
mService->RemoveOnGMPThread(mPath,
|
||||||
|
mOperation == REMOVE_AND_DELETE_FROM_DISK);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -677,14 +678,26 @@ NS_IMETHODIMP
|
|||||||
GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory)
|
GeckoMediaPluginService::AddPluginDirectory(const nsAString& aDirectory)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
return GMPDispatch(new PathRunnable(this, aDirectory, true));
|
return GMPDispatch(new PathRunnable(this, aDirectory,
|
||||||
|
PathRunnable::EOperation::ADD));
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
|
GeckoMediaPluginService::RemovePluginDirectory(const nsAString& aDirectory)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
return GMPDispatch(new PathRunnable(this, aDirectory, false));
|
return GMPDispatch(new PathRunnable(this, aDirectory,
|
||||||
|
PathRunnable::EOperation::REMOVE));
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
GeckoMediaPluginService::RemoveAndDeletePluginDirectory(
|
||||||
|
const nsAString& aDirectory)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
return GMPDispatch(
|
||||||
|
new PathRunnable(this, aDirectory,
|
||||||
|
PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK));
|
||||||
}
|
}
|
||||||
|
|
||||||
class DummyRunnable : public nsRunnable {
|
class DummyRunnable : public nsRunnable {
|
||||||
@ -915,7 +928,8 @@ GeckoMediaPluginService::AddOnGMPThread(const nsAString& aDirectory)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
|
GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory,
|
||||||
|
const bool aDeleteFromDisk)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
|
||||||
LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get()));
|
LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get()));
|
||||||
@ -931,7 +945,11 @@ GeckoMediaPluginService::RemoveOnGMPThread(const nsAString& aDirectory)
|
|||||||
nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
|
nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
|
||||||
bool equals;
|
bool equals;
|
||||||
if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) {
|
if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) {
|
||||||
|
mPlugins[i]->AbortAsyncShutdown();
|
||||||
mPlugins[i]->CloseActive(true);
|
mPlugins[i]->CloseActive(true);
|
||||||
|
if (aDeleteFromDisk) {
|
||||||
|
pluginpath->Remove(true);
|
||||||
|
}
|
||||||
mPlugins.RemoveElementAt(i);
|
mPlugins.RemoveElementAt(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,9 @@ private:
|
|||||||
void LoadFromEnvironment();
|
void LoadFromEnvironment();
|
||||||
void ProcessPossiblePlugin(nsIFile* aDir);
|
void ProcessPossiblePlugin(nsIFile* aDir);
|
||||||
|
|
||||||
void AddOnGMPThread(const nsAString& aSearchDir);
|
void AddOnGMPThread(const nsAString& aDirectory);
|
||||||
void RemoveOnGMPThread(const nsAString& aSearchDir);
|
void RemoveOnGMPThread(const nsAString& aDirectory,
|
||||||
|
const bool aDeleteFromDisk);
|
||||||
|
|
||||||
nsresult SetAsyncShutdownTimeout();
|
nsresult SetAsyncShutdownTimeout();
|
||||||
|
|
||||||
@ -96,11 +97,17 @@ private:
|
|||||||
class PathRunnable : public nsRunnable
|
class PathRunnable : public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PathRunnable(GeckoMediaPluginService* service, const nsAString& path,
|
enum EOperation {
|
||||||
bool add)
|
ADD,
|
||||||
: mService(service)
|
REMOVE,
|
||||||
, mPath(path)
|
REMOVE_AND_DELETE_FROM_DISK,
|
||||||
, mAdd(add)
|
};
|
||||||
|
|
||||||
|
PathRunnable(GeckoMediaPluginService* aService, const nsAString& aPath,
|
||||||
|
EOperation aOperation)
|
||||||
|
: mService(aService)
|
||||||
|
, mPath(aPath)
|
||||||
|
, mOperation(aOperation)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
NS_DECL_NSIRUNNABLE
|
NS_DECL_NSIRUNNABLE
|
||||||
@ -108,7 +115,7 @@ private:
|
|||||||
private:
|
private:
|
||||||
nsRefPtr<GeckoMediaPluginService> mService;
|
nsRefPtr<GeckoMediaPluginService> mService;
|
||||||
nsString mPath;
|
nsString mPath;
|
||||||
bool mAdd;
|
EOperation mOperation;
|
||||||
};
|
};
|
||||||
|
|
||||||
Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
|
Mutex mMutex; // Protects mGMPThread and mShuttingDown and mPlugins
|
||||||
|
@ -26,7 +26,7 @@ class GMPVideoHost;
|
|||||||
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
|
[ptr] native GMPDecryptorProxy(GMPDecryptorProxy);
|
||||||
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
|
[ptr] native GMPAudioDecoderProxy(GMPAudioDecoderProxy);
|
||||||
|
|
||||||
[scriptable, uuid(56cc105f-dd27-4752-83e0-371908edba04)]
|
[scriptable, uuid(f71e6e57-5175-4cf3-8cc2-629273a75b67)]
|
||||||
interface mozIGeckoMediaPluginService : nsISupports
|
interface mozIGeckoMediaPluginService : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -97,6 +97,12 @@ interface mozIGeckoMediaPluginService : nsISupports
|
|||||||
*/
|
*/
|
||||||
void removePluginDirectory(in AString directory);
|
void removePluginDirectory(in AString directory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a directory for gecko media plugins and delete it from disk.
|
||||||
|
* @note Main-thread API.
|
||||||
|
*/
|
||||||
|
void removeAndDeletePluginDirectory(in AString directory);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
|
* Gets the NodeId for a (origin, urlbarOrigin, isInprivateBrowsing) tuple.
|
||||||
*/
|
*/
|
||||||
|
@ -93,6 +93,25 @@ MediaSourceReader::IsWaitingMediaResources()
|
|||||||
return !mHasEssentialTrackBuffers;
|
return !mHasEssentialTrackBuffers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MediaSourceReader::IsWaitingOnCDMResource()
|
||||||
|
{
|
||||||
|
#ifdef MOZ_EME
|
||||||
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
|
MOZ_ASSERT(!IsWaitingMediaResources());
|
||||||
|
|
||||||
|
for (auto& trackBuffer : mTrackBuffers) {
|
||||||
|
if (trackBuffer->IsWaitingOnCDMResource()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mInfo.IsEncrypted() && !mCDMProxy;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
MediaSourceReader::SizeOfVideoQueueInFrames()
|
MediaSourceReader::SizeOfVideoQueueInFrames()
|
||||||
{
|
{
|
||||||
@ -1020,6 +1039,22 @@ MediaSourceReader::MaybeNotifyHaveData()
|
|||||||
IsSeeking(), haveAudio, haveVideo);
|
IsSeeking(), haveAudio, haveVideo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
CombineEncryptionData(EncryptionInfo& aTo, const EncryptionInfo& aFrom)
|
||||||
|
{
|
||||||
|
if (!aFrom.mIsEncrypted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aTo.mIsEncrypted = true;
|
||||||
|
|
||||||
|
if (!aTo.mType.IsEmpty() && !aTo.mType.Equals(aFrom.mType)) {
|
||||||
|
NS_WARNING("mismatched encryption types");
|
||||||
|
}
|
||||||
|
|
||||||
|
aTo.mType = aFrom.mType;
|
||||||
|
aTo.mInitData.AppendElements(aFrom.mInitData);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
||||||
{
|
{
|
||||||
@ -1043,7 +1078,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
|||||||
const MediaInfo& info = GetAudioReader()->GetMediaInfo();
|
const MediaInfo& info = GetAudioReader()->GetMediaInfo();
|
||||||
MOZ_ASSERT(info.HasAudio());
|
MOZ_ASSERT(info.HasAudio());
|
||||||
mInfo.mAudio = info.mAudio;
|
mInfo.mAudio = info.mAudio;
|
||||||
mInfo.mIsEncrypted = mInfo.mIsEncrypted || info.mIsEncrypted;
|
CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
|
||||||
MSE_DEBUG("audio reader=%p duration=%lld",
|
MSE_DEBUG("audio reader=%p duration=%lld",
|
||||||
mAudioSourceDecoder.get(),
|
mAudioSourceDecoder.get(),
|
||||||
mAudioSourceDecoder->GetReader()->GetDecoder()->GetMediaDuration());
|
mAudioSourceDecoder->GetReader()->GetDecoder()->GetMediaDuration());
|
||||||
@ -1056,7 +1091,7 @@ MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
|
|||||||
const MediaInfo& info = GetVideoReader()->GetMediaInfo();
|
const MediaInfo& info = GetVideoReader()->GetMediaInfo();
|
||||||
MOZ_ASSERT(info.HasVideo());
|
MOZ_ASSERT(info.HasVideo());
|
||||||
mInfo.mVideo = info.mVideo;
|
mInfo.mVideo = info.mVideo;
|
||||||
mInfo.mIsEncrypted = mInfo.mIsEncrypted || info.mIsEncrypted;
|
CombineEncryptionData(mInfo.mCrypto, info.mCrypto);
|
||||||
MSE_DEBUG("video reader=%p duration=%lld",
|
MSE_DEBUG("video reader=%p duration=%lld",
|
||||||
GetVideoReader(),
|
GetVideoReader(),
|
||||||
GetVideoReader()->GetDecoder()->GetMediaDuration());
|
GetVideoReader()->GetDecoder()->GetMediaDuration());
|
||||||
|
@ -45,6 +45,7 @@ public:
|
|||||||
void PrepareInitialization();
|
void PrepareInitialization();
|
||||||
|
|
||||||
bool IsWaitingMediaResources() override;
|
bool IsWaitingMediaResources() override;
|
||||||
|
bool IsWaitingOnCDMResource() override;
|
||||||
|
|
||||||
nsRefPtr<AudioDataPromise> RequestAudioData() override;
|
nsRefPtr<AudioDataPromise> RequestAudioData() override;
|
||||||
nsRefPtr<VideoDataPromise>
|
nsRefPtr<VideoDataPromise>
|
||||||
|
@ -47,6 +47,7 @@ TrackBuffer::TrackBuffer(MediaSourceDecoder* aParentDecoder, const nsACString& a
|
|||||||
, mLastStartTimestamp(0)
|
, mLastStartTimestamp(0)
|
||||||
, mLastTimestampOffset(0)
|
, mLastTimestampOffset(0)
|
||||||
, mAdjustedTimestamp(0)
|
, mAdjustedTimestamp(0)
|
||||||
|
, mIsWaitingOnCDM(false)
|
||||||
, mShutdown(false)
|
, mShutdown(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(TrackBuffer);
|
MOZ_COUNT_CTOR(TrackBuffer);
|
||||||
@ -588,6 +589,7 @@ TrackBuffer::InitializeDecoder(SourceBufferDecoder* aDecoder)
|
|||||||
|
|
||||||
if (mCurrentDecoder != aDecoder) {
|
if (mCurrentDecoder != aDecoder) {
|
||||||
MSE_DEBUG("append was cancelled. Aborting initialization.");
|
MSE_DEBUG("append was cancelled. Aborting initialization.");
|
||||||
|
RemoveDecoder(aDecoder);
|
||||||
// If we reached this point, the SourceBuffer would have disconnected
|
// If we reached this point, the SourceBuffer would have disconnected
|
||||||
// the promise. So no need to reject it.
|
// the promise. So no need to reject it.
|
||||||
return;
|
return;
|
||||||
@ -641,12 +643,12 @@ TrackBuffer::InitializeDecoder(SourceBufferDecoder* aDecoder)
|
|||||||
}
|
}
|
||||||
if (mCurrentDecoder != aDecoder) {
|
if (mCurrentDecoder != aDecoder) {
|
||||||
MSE_DEBUG("append was cancelled. Aborting initialization.");
|
MSE_DEBUG("append was cancelled. Aborting initialization.");
|
||||||
|
RemoveDecoder(aDecoder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && reader->IsWaitingOnCDMResource()) {
|
if (NS_SUCCEEDED(rv) && reader->IsWaitingOnCDMResource()) {
|
||||||
mWaitingDecoders.AppendElement(aDecoder);
|
mIsWaitingOnCDM = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aDecoder->SetTaskQueue(nullptr);
|
aDecoder->SetTaskQueue(nullptr);
|
||||||
@ -693,6 +695,7 @@ TrackBuffer::CompleteInitializeDecoder(SourceBufferDecoder* aDecoder)
|
|||||||
MSE_DEBUG("append was cancelled. Aborting initialization.");
|
MSE_DEBUG("append was cancelled. Aborting initialization.");
|
||||||
// If we reached this point, the SourceBuffer would have disconnected
|
// If we reached this point, the SourceBuffer would have disconnected
|
||||||
// the promise. So no need to reject it.
|
// the promise. So no need to reject it.
|
||||||
|
RemoveDecoder(aDecoder);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -807,6 +810,12 @@ TrackBuffer::IsReady()
|
|||||||
return mInfo.HasAudio() || mInfo.HasVideo();
|
return mInfo.HasAudio() || mInfo.HasVideo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TrackBuffer::IsWaitingOnCDMResource()
|
||||||
|
{
|
||||||
|
return mIsWaitingOnCDM;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
TrackBuffer::ContainsTime(int64_t aTime, int64_t aTolerance)
|
TrackBuffer::ContainsTime(int64_t aTime, int64_t aTolerance)
|
||||||
{
|
{
|
||||||
@ -875,21 +884,12 @@ TrackBuffer::SetCDMProxy(CDMProxy* aProxy)
|
|||||||
{
|
{
|
||||||
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
|
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
|
for (auto& decoder : mDecoders) {
|
||||||
nsresult rv = mDecoders[i]->SetCDMProxy(aProxy);
|
decoder->SetCDMProxy(aProxy);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < mWaitingDecoders.Length(); ++i) {
|
mIsWaitingOnCDM = false;
|
||||||
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
mParentDecoder->NotifyWaitingForResourcesStatusChanged();
|
||||||
caps.CallOnMainThreadWhenCapsAvailable(
|
|
||||||
NS_NewRunnableMethodWithArg<SourceBufferDecoder*>(this,
|
|
||||||
&TrackBuffer::QueueInitializeDecoder,
|
|
||||||
mWaitingDecoders[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
mWaitingDecoders.Clear();
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,6 +76,8 @@ public:
|
|||||||
// segment has successfully initialized by setting mHas{Audio,Video}..
|
// segment has successfully initialized by setting mHas{Audio,Video}..
|
||||||
bool IsReady();
|
bool IsReady();
|
||||||
|
|
||||||
|
bool IsWaitingOnCDMResource();
|
||||||
|
|
||||||
// Returns true if any of the decoders managed by this track buffer
|
// Returns true if any of the decoders managed by this track buffer
|
||||||
// contain aTime in their buffered ranges.
|
// contain aTime in their buffered ranges.
|
||||||
bool ContainsTime(int64_t aTime, int64_t aTolerance);
|
bool ContainsTime(int64_t aTime, int64_t aTolerance);
|
||||||
@ -185,10 +187,6 @@ private:
|
|||||||
// Access protected by mParentDecoder's monitor.
|
// Access protected by mParentDecoder's monitor.
|
||||||
nsTArray<nsRefPtr<SourceBufferDecoder>> mInitializedDecoders;
|
nsTArray<nsRefPtr<SourceBufferDecoder>> mInitializedDecoders;
|
||||||
|
|
||||||
// Decoders which are waiting on a Content Decryption Module to be able to
|
|
||||||
// finish ReadMetadata.
|
|
||||||
nsTArray<nsRefPtr<SourceBufferDecoder>> mWaitingDecoders;
|
|
||||||
|
|
||||||
// The decoder that the owning SourceBuffer is currently appending data to.
|
// The decoder that the owning SourceBuffer is currently appending data to.
|
||||||
// Modified on the main thread only.
|
// Modified on the main thread only.
|
||||||
nsRefPtr<SourceBufferDecoder> mCurrentDecoder;
|
nsRefPtr<SourceBufferDecoder> mCurrentDecoder;
|
||||||
@ -206,6 +204,9 @@ private:
|
|||||||
int64_t mLastTimestampOffset;
|
int64_t mLastTimestampOffset;
|
||||||
int64_t mAdjustedTimestamp;
|
int64_t mAdjustedTimestamp;
|
||||||
|
|
||||||
|
// True if at least one of our decoders has encrypted content.
|
||||||
|
bool mIsWaitingOnCDM;
|
||||||
|
|
||||||
// Set when the first decoder used by this TrackBuffer is initialized.
|
// Set when the first decoder used by this TrackBuffer is initialized.
|
||||||
// Protected by mParentDecoder's monitor.
|
// Protected by mParentDecoder's monitor.
|
||||||
MediaInfo mInfo;
|
MediaInfo mInfo;
|
||||||
|
@ -370,8 +370,6 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
|
|||||||
skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
|
skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
|
||||||
[test_dormant_playback.html]
|
[test_dormant_playback.html]
|
||||||
skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'gonk')
|
skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'gonk')
|
||||||
[test_eme_access_control.html]
|
|
||||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # bug 1043403, bug 1057908
|
|
||||||
[test_eme_canvas_blocked.html]
|
[test_eme_canvas_blocked.html]
|
||||||
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s || (os == 'win' && !debug) # bug 1043403, bug 1057908, bug 1140675
|
skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s || (os == 'win' && !debug) # bug 1043403, bug 1057908, bug 1140675
|
||||||
[test_eme_non_mse_fails.html]
|
[test_eme_non_mse_fails.html]
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
<!DOCTYPE HTML>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Test EME blocked cross-origin</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">
|
|
||||||
<script class="testbody" type="text/javascript">
|
|
||||||
var manager = new MediaTestManager;
|
|
||||||
|
|
||||||
function TestNoCORS(test, token)
|
|
||||||
{
|
|
||||||
var token = token + "_nocors";
|
|
||||||
|
|
||||||
manager.started(token);
|
|
||||||
|
|
||||||
var v = document.createElement("video");
|
|
||||||
|
|
||||||
v.addEventListener("encrypted", function(ev) {
|
|
||||||
is(ev.initDataType, "", "initDataType should be empty for CORS cross-origin media");
|
|
||||||
is(ev.initData, null, "initData should be null for CORS cross-origin media");
|
|
||||||
|
|
||||||
manager.finished(token);
|
|
||||||
});
|
|
||||||
|
|
||||||
v.addEventListener("error", function() {
|
|
||||||
ok(false, "Should not receive error loading cross-origin media without crossorigin attribute");
|
|
||||||
});
|
|
||||||
|
|
||||||
v.src = test.uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
function TestCORSFailure(test, token)
|
|
||||||
{
|
|
||||||
var token = token + "_corsfail";
|
|
||||||
|
|
||||||
manager.started(token);
|
|
||||||
|
|
||||||
var v = document.createElement("video");
|
|
||||||
v.crossOrigin = true;
|
|
||||||
|
|
||||||
v.addEventListener("error", function(ev) {
|
|
||||||
ok(true, "Should get error loading cross-origin media");
|
|
||||||
manager.finished(token);
|
|
||||||
});
|
|
||||||
|
|
||||||
v.addEventListener("encrypted", function() {
|
|
||||||
ok(false, "Should not receive encrypted event loading cross-origin media");
|
|
||||||
});
|
|
||||||
|
|
||||||
v.src = test.uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
function TestCORSSuccess(test, token)
|
|
||||||
{
|
|
||||||
var token = token + "_corsok";
|
|
||||||
|
|
||||||
manager.started(token);
|
|
||||||
|
|
||||||
var v = document.createElement("video");
|
|
||||||
v.crossOrigin = true;
|
|
||||||
|
|
||||||
v.addEventListener("error", function(ev) {
|
|
||||||
ok(false, "Should not get error loading cross-origin media");
|
|
||||||
});
|
|
||||||
|
|
||||||
v.addEventListener("encrypted", function(ev) {
|
|
||||||
ok(ev.initData.byteLength > 0, "Should get encryption initData loading cross-origin media");
|
|
||||||
is(ev.initDataType, "cenc", "Should get correct encryption initDataType loading cross-origin media");
|
|
||||||
manager.finished(token);
|
|
||||||
});
|
|
||||||
|
|
||||||
v.src = test.uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
function startTest(test, token)
|
|
||||||
{
|
|
||||||
test.uri = "http://test1.mochi.test:8888/tests/dom/media/test/" + test.name;
|
|
||||||
TestNoCORS(test, token);
|
|
||||||
TestCORSFailure(test, token);
|
|
||||||
|
|
||||||
test.uri = "http://test1.mochi.test:8888/tests/dom/media/test/allowed.sjs?" + test.name;
|
|
||||||
TestCORSSuccess(test, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
function beginTest() {
|
|
||||||
manager.runTests(gEMETests.filter(t => t.crossOrigin), startTest);
|
|
||||||
}
|
|
||||||
|
|
||||||
var prefs = [
|
|
||||||
[ "media.mediasource.enabled", true ],
|
|
||||||
[ "media.mediasource.whitelist", false ],
|
|
||||||
[ "media.mediasource.mp4.enabled", true ],
|
|
||||||
];
|
|
||||||
|
|
||||||
if (/Linux/.test(navigator.userAgent) ||
|
|
||||||
!document.createElement('video').canPlayType("video/mp4")) {
|
|
||||||
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
|
|
||||||
prefs.push([ "media.fragmented-mp4.exposed", true ]);
|
|
||||||
prefs.push([ "media.fragmented-mp4.use-blank-decoder", true ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTest.waitForExplicitFinish();
|
|
||||||
SpecialPowers.pushPrefEnv({ "set" : prefs }, beginTest);
|
|
||||||
</script>
|
|
||||||
</pre>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -40,17 +40,19 @@ function TestSetMediaKeys(test, token)
|
|||||||
|
|
||||||
var v = document.createElement("video");
|
var v = document.createElement("video");
|
||||||
|
|
||||||
// XXX the encrypted event should never fire here after bug 1134434
|
|
||||||
v.addEventListener("encrypted", function() {
|
v.addEventListener("encrypted", function() {
|
||||||
DoSetMediaKeys(v)
|
ok(false, token + " should not fire encrypted event");
|
||||||
|
});
|
||||||
|
|
||||||
.then(function() {
|
var loadedMetadata = false;
|
||||||
ok(false, token + " expected setMediaKeys to fail.");
|
v.addEventListener("loadedmetadata", function() {
|
||||||
manager.finished(token);
|
loadedMetadata = true;
|
||||||
}, function(err) {
|
});
|
||||||
is(err.name, "NotSupportedError", token + " should return correct error");
|
|
||||||
manager.finished(token);
|
v.addEventListener("error", function() {
|
||||||
});
|
ok(true, token + " expected error event");
|
||||||
|
ok(loadedMetadata, token + " expected loadedmetadata to have fired");
|
||||||
|
manager.finished(token);
|
||||||
});
|
});
|
||||||
|
|
||||||
v.src = test.name;
|
v.src = test.name;
|
||||||
|
@ -244,6 +244,9 @@ RespondWithHandler::ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValu
|
|||||||
if (NS_WARN_IF(!stsThread)) {
|
if (NS_WARN_IF(!stsThread)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXXnsm, Fix for Bug 1141332 means that if we decide to make this
|
||||||
|
// streaming at some point, we'll need a different solution to that bug.
|
||||||
rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096,
|
rv = NS_AsyncCopy(body, responseBody, stsThread, NS_ASYNCCOPY_VIA_READSEGMENTS, 4096,
|
||||||
RespondWithCopyComplete, closure.forget());
|
RespondWithCopyComplete, closure.forget());
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
17
dom/workers/test/serviceworkers/fetch/deliver-gzip.sjs
Normal file
17
dom/workers/test/serviceworkers/fetch/deliver-gzip.sjs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
function handleRequest(request, response) {
|
||||||
|
// The string "hello" repeated 10 times followed by newline. Compressed using gzip.
|
||||||
|
var bytes = [0x1f, 0x8b, 0x08, 0x08, 0x4d, 0xe2, 0xf9, 0x54, 0x00, 0x03, 0x68,
|
||||||
|
0x65, 0x6c, 0x6c, 0x6f, 0x00, 0xcb, 0x48, 0xcd, 0xc9, 0xc9, 0xcf,
|
||||||
|
0x20, 0x85, 0xe0, 0x02, 0x00, 0xf5, 0x4b, 0x38, 0xcf, 0x33, 0x00,
|
||||||
|
0x00, 0x00];
|
||||||
|
|
||||||
|
response.setHeader("Content-Encoding", "gzip", false);
|
||||||
|
response.setHeader("Content-Length", "" + bytes.length, false);
|
||||||
|
response.setHeader("Content-Type", "text/plain", false);
|
||||||
|
|
||||||
|
var bos = Components.classes["@mozilla.org/binaryoutputstream;1"]
|
||||||
|
.createInstance(Components.interfaces.nsIBinaryOutputStream);
|
||||||
|
bos.setOutputStream(response.bodyOutputStream);
|
||||||
|
|
||||||
|
bos.writeByteArray(bytes, bytes.length);
|
||||||
|
}
|
@ -71,3 +71,35 @@ fetch('headers.txt', function(xhr) {
|
|||||||
my_ok(xhr.responseText == "1", "request header checks should have passed");
|
my_ok(xhr.responseText == "1", "request header checks should have passed");
|
||||||
finish();
|
finish();
|
||||||
}, null, [["X-Test1", "header1"], ["X-Test2", "header2"]]);
|
}, null, [["X-Test1", "header1"], ["X-Test2", "header2"]]);
|
||||||
|
|
||||||
|
var expectedUncompressedResponse = "";
|
||||||
|
for (var i = 0; i < 10; ++i) {
|
||||||
|
expectedUncompressedResponse += "hello";
|
||||||
|
}
|
||||||
|
expectedUncompressedResponse += "\n";
|
||||||
|
|
||||||
|
// ServiceWorker does not intercept, at which point the network request should
|
||||||
|
// be correctly decoded.
|
||||||
|
fetch('deliver-gzip.sjs', function(xhr) {
|
||||||
|
my_ok(xhr.status == 200, "network gzip load should be successful");
|
||||||
|
my_ok(xhr.responseText == expectedUncompressedResponse, "network gzip load should have synthesized response.");
|
||||||
|
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "network Content-Encoding should be gzip.");
|
||||||
|
my_ok(xhr.getResponseHeader("Content-Length") == "35", "network Content-Length should be of original gzipped file.");
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('hello.gz', function(xhr) {
|
||||||
|
my_ok(xhr.status == 200, "gzip load should be successful");
|
||||||
|
my_ok(xhr.responseText == expectedUncompressedResponse, "gzip load should have synthesized response.");
|
||||||
|
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "Content-Encoding should be gzip.");
|
||||||
|
my_ok(xhr.getResponseHeader("Content-Length") == "35", "Content-Length should be of original gzipped file.");
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('hello-after-extracting.gz', function(xhr) {
|
||||||
|
my_ok(xhr.status == 200, "gzip load should be successful");
|
||||||
|
my_ok(xhr.responseText == expectedUncompressedResponse, "gzip load should have synthesized response.");
|
||||||
|
my_ok(xhr.getResponseHeader("Content-Encoding") == "gzip", "Content-Encoding should be gzip.");
|
||||||
|
my_ok(xhr.getResponseHeader("Content-Length") == "35", "Content-Length should be of original gzipped file.");
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
@ -96,4 +96,23 @@ onfetch = function(ev) {
|
|||||||
new Response("check_intercepted_script();", {})
|
new Response("check_intercepted_script();", {})
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (ev.request.url.contains("deliver-gzip")) {
|
||||||
|
// Don't handle the request, this will make Necko perform a network request, at
|
||||||
|
// which point SetApplyConversion must be re-enabled, otherwise the request
|
||||||
|
// will fail.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ev.request.url.contains("hello.gz")) {
|
||||||
|
ev.respondWith(fetch("fetch/deliver-gzip.sjs"));
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ev.request.url.contains("hello-after-extracting.gz")) {
|
||||||
|
ev.respondWith(fetch("fetch/deliver-gzip.sjs").then(function(res) {
|
||||||
|
return res.text().then(function(body) {
|
||||||
|
return new Response(body, { status: res.status, statusText: res.statusText, headers: res.headers });
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ support-files =
|
|||||||
fetch/index.html
|
fetch/index.html
|
||||||
fetch/fetch_worker_script.js
|
fetch/fetch_worker_script.js
|
||||||
fetch/fetch_tests.js
|
fetch/fetch_tests.js
|
||||||
|
fetch/deliver-gzip.sjs
|
||||||
fetch/https/index.html
|
fetch/https/index.html
|
||||||
fetch/https/register.html
|
fetch/https/register.html
|
||||||
fetch/https/unregister.html
|
fetch/https/unregister.html
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user