This commit is contained in:
Wes Kocher 2015-10-08 14:36:57 -07:00
Родитель 484a185c31 599117d547
Коммит e046a644c8
130 изменённых файлов: 2019 добавлений и 829 удалений

Просмотреть файл

@ -547,8 +547,9 @@ GroupPos
ARIARowAccessible::GroupPosition()
{
int32_t count = 0, index = 0;
if (nsCoreUtils::GetUIntAttr(nsAccUtils::TableFor(this)->GetContent(),
nsGkAtoms::aria_rowcount, &count) &&
Accessible* table = nsAccUtils::TableFor(this);
if (table && nsCoreUtils::GetUIntAttr(table->GetContent(),
nsGkAtoms::aria_rowcount, &count) &&
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) {
return GroupPos(0, index, count);
}

Просмотреть файл

@ -128,7 +128,10 @@ var LogShake = {
"/proc/version": LogParser.prettyPrintArray,
"/proc/vmallocinfo": LogParser.prettyPrintArray,
"/proc/vmstat": LogParser.prettyPrintArray,
"/system/b2g/application.ini": LogParser.prettyPrintArray
"/system/b2g/application.ini": LogParser.prettyPrintArray,
"/cache/recovery/last_install": LogParser.prettyPrintArray,
"/cache/recovery/last_kmsg": LogParser.prettyPrintArray,
"/cache/recovery/last_log": LogParser.prettyPrintArray
},
/**

Просмотреть файл

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -19,8 +19,8 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="065f6361461030d32c6dc08d716b013bfadab1d9"/>

Просмотреть файл

@ -17,8 +17,8 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>

Просмотреть файл

@ -15,9 +15,9 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -15,9 +15,9 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -19,8 +19,8 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="065f6361461030d32c6dc08d716b013bfadab1d9"/>

Просмотреть файл

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "4973f57cd8f9a62a95f783a24eac32da2bde99fc",
"git_revision": "e698df503ff700eb5782e3d50c6eb753567d3451",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "c728de03bc96ef160fd5a662b3efcd5cf2c2b844",
"revision": "bd073200a776c714b8160a38c77f980b19fd97c2",
"repo_path": "integration/gaia-central"
}

Просмотреть файл

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -18,8 +18,8 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f004530b30a63c08a16d82536858600446b2abf5"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>

Просмотреть файл

@ -15,10 +15,10 @@
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4973f57cd8f9a62a95f783a24eac32da2bde99fc"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="e698df503ff700eb5782e3d50c6eb753567d3451"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7e0fe55ac52323eace5a6119ab2b911fc4f64495"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="7938df689aa87769fad3f2cf9097fb4ecb106a43"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="31a7849fe9a8b743d6f5e5facc212f0ef9d57499"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>

Просмотреть файл

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = os == 'android' || buildapp == 'b2g' || os == 'mac'
support-files =
head.js
context.html

Просмотреть файл

@ -103,6 +103,8 @@ SEARCH_PATHS = [
'testing/mozbase/mozdevice',
'testing/mozbase/mozfile',
'testing/mozbase/mozhttpd',
'testing/mozbase/mozinfo',
'testing/mozbase/mozinstall',
'testing/mozbase/mozleak',
'testing/mozbase/mozlog',
'testing/mozbase/moznetwork',
@ -110,7 +112,6 @@ SEARCH_PATHS = [
'testing/mozbase/mozprofile',
'testing/mozbase/mozrunner',
'testing/mozbase/mozsystemmonitor',
'testing/mozbase/mozinfo',
'testing/mozbase/mozscreenshot',
'testing/mozbase/moztest',
'testing/mozbase/mozversion',

Просмотреть файл

@ -212,11 +212,10 @@ var testcases = [ {
protocolChange: true
}, {
input: "[::1][100",
fixedURI: "http://[::1][100/",
alternateURI: "http://[::1][100/",
fixedURI: null,
alternateURI: null,
keywordLookup: true,
protocolChange: true,
affectedByDNSForSingleHosts: true,
protocolChange: true
}, {
input: "[::1]]",
keywordLookup: true,
@ -503,13 +502,14 @@ if (Services.appinfo.OS.toLowerCase().startsWith("win")) {
fixedURI: "file:////mozilla",
protocolChange: true,
});
// \ is an invalid character in the hostname until bug 652186 is implemented
testcases.push({
input: "mozilla\\",
fixedURI: "http://mozilla\\/",
alternateURI: "http://www.mozilla/",
// fixedURI: "http://mozilla\\/",
// alternateURI: "http://www.mozilla/",
keywordLookup: true,
protocolChange: true,
affectedByDNSForSingleHosts: true,
// affectedByDNSForSingleHosts: true,
});
}

Просмотреть файл

@ -84,11 +84,10 @@ MP3Demuxer::IsSeekable() const {
}
void
MP3Demuxer::NotifyDataArrived(uint32_t aLength, int64_t aOffset) {
MP3Demuxer::NotifyDataArrived() {
// TODO: bug 1169485.
NS_WARNING("Unimplemented function NotifyDataArrived");
MP3DEMUXER_LOGV("NotifyDataArrived(%u, %" PRId64 ") mOffset=%" PRId64,
aLength, aOffset, mTrackDemuxer->GetResourceOffset());
MP3DEMUXER_LOGV("NotifyDataArrived()");
}
void

Просмотреть файл

@ -25,7 +25,7 @@ public:
already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
bool IsSeekable() const override;
void NotifyDataArrived(uint32_t aLength, int64_t aOffset) override;
void NotifyDataArrived() override;
void NotifyDataRemoved() override;
// Do not shift the calculated buffered range by the start time of the first
// decoded frame. The mac MP3 decoder will buffer some samples and the first

Просмотреть файл

@ -77,15 +77,17 @@ public:
return nullptr;
}
// Notifies the demuxer that the underlying resource has received more data.
// Notifies the demuxer that the underlying resource has received more data
// since the demuxer was initialized.
// The demuxer can use this mechanism to inform all track demuxers that new
// data is available.
virtual void NotifyDataArrived(uint32_t aLength, int64_t aOffset) { }
// data is available and to refresh its buffered range.
virtual void NotifyDataArrived() { }
// Notifies the demuxer that the underlying resource has had data removed.
// Notifies the demuxer that the underlying resource has had data removed
// since the demuxer was initialized.
// The demuxer can use this mechanism to inform all track demuxers to update
// its TimeIntervals.
// This will be called should the demuxer be used with MediaSource.
// its buffered range.
// This will be called should the demuxer be used with MediaSourceResource.
virtual void NotifyDataRemoved() { }
// Indicate to MediaFormatReader if it should compute the start time

Просмотреть файл

@ -1603,7 +1603,7 @@ MediaFormatReader::NotifyDemuxer(uint32_t aLength, int64_t aOffset)
}
if (aLength || aOffset) {
mDemuxer->NotifyDataArrived(aLength, aOffset);
mDemuxer->NotifyDataArrived();
} else {
mDemuxer->NotifyDataRemoved();
}

Просмотреть файл

@ -186,7 +186,7 @@ MP4Demuxer::IsSeekable() const
}
void
MP4Demuxer::NotifyDataArrived(uint32_t aLength, int64_t aOffset)
MP4Demuxer::NotifyDataArrived()
{
for (uint32_t i = 0; i < mDemuxers.Length(); i++) {
mDemuxers[i]->NotifyDataArrived();

Просмотреть файл

@ -40,7 +40,7 @@ public:
virtual UniquePtr<EncryptionInfo> GetCrypto() override;
virtual void NotifyDataArrived(uint32_t aLength, int64_t aOffset) override;
virtual void NotifyDataArrived() override;
virtual void NotifyDataRemoved() override;

Просмотреть файл

@ -53,7 +53,7 @@ MediaSourceDemuxer::AttemptInit()
return p;
}
void MediaSourceDemuxer::NotifyDataArrived(uint32_t aLength, int64_t aOffset)
void MediaSourceDemuxer::NotifyDataArrived()
{
nsRefPtr<MediaSourceDemuxer> self = this;
nsCOMPtr<nsIRunnable> task =

Просмотреть файл

@ -42,7 +42,7 @@ public:
bool ShouldComputeStartTime() const override { return false; }
void NotifyDataArrived(uint32_t aLength, int64_t aOffset) override;
void NotifyDataArrived() override;
/* interface for TrackBuffersManager */
void AttachSourceBuffer(TrackBuffersManager* aSourceBuffer);

Просмотреть файл

@ -876,10 +876,8 @@ void
TrackBuffersManager::AppendDataToCurrentInputBuffer(MediaByteBuffer* aData)
{
MOZ_ASSERT(mCurrentInputBuffer);
int64_t offset = mCurrentInputBuffer->GetLength();
mCurrentInputBuffer->AppendData(aData);
// A MediaByteBuffer has a maximum size of 2GiB.
mInputDemuxer->NotifyDataArrived(uint32_t(aData->Length()), offset);
mInputDemuxer->NotifyDataArrived();
}
void

Просмотреть файл

@ -14,7 +14,6 @@
#include <android/log.h>
#define MCP_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "MediaCodecProxy", __VA_ARGS__)
#define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll
namespace android {
@ -571,7 +570,8 @@ bool MediaCodecProxy::UpdateOutputBuffers()
}
status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
int64_t aTimestampUsecs, uint64_t aflags)
int64_t aTimestampUsecs, uint64_t aflags,
int64_t aTimeoutUs)
{
// Read Lock for mCodec
{
@ -583,9 +583,11 @@ status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
}
size_t index;
status_t err = dequeueInputBuffer(&index, TIMEOUT_DEQUEUE_INPUTBUFFER_MS);
status_t err = dequeueInputBuffer(&index, aTimeoutUs);
if (err != OK) {
MCP_LOG("dequeueInputBuffer returned %d", err);
if (err != -EAGAIN) {
MCP_LOG("dequeueInputBuffer returned %d", err);
}
return err;
}

Просмотреть файл

@ -129,7 +129,7 @@ public:
// If aData is null, will notify decoder input EOS
status_t Input(const uint8_t* aData, uint32_t aDataSize,
int64_t aTimestampUsecs, uint64_t flags);
int64_t aTimestampUsecs, uint64_t flags, int64_t aTimeoutUs = 0);
status_t Output(MediaBuffer** aBuffer, int64_t aTimeoutUs);
bool Prepare();
void ReleaseMediaResources();

Просмотреть файл

@ -389,9 +389,8 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
picture.height = (frame.Y.mHeight * mPicture.height) / mInitialFrame.height;
}
MOZ_ASSERT(mStreamSource);
// This is the approximate byte position in the stream.
int64_t pos = mStreamSource->Tell();
int64_t pos = mStreamSource ? mStreamSource->Tell() : 0;
nsRefPtr<VideoData> v;
if (!frame.mGraphicBuffer) {
@ -492,9 +491,8 @@ bool MediaOmxReader::DecodeAudioData()
MOZ_ASSERT(OnTaskQueue());
EnsureActive();
MOZ_ASSERT(mStreamSource);
// This is the approximate byte position in the stream.
int64_t pos = mStreamSource->Tell();
int64_t pos = mStreamSource ? mStreamSource->Tell() : 0;
// Read next frame
MPAPI::AudioFrame source;

Просмотреть файл

@ -21,12 +21,14 @@
#include "MediaData.h"
#include "MediaInfo.h"
#define CODECCONFIG_TIMEOUT_US 10000LL
#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
#include <android/log.h>
#define GADM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkAudioDecoderManager", __VA_ARGS__)
extern PRLogModuleInfo* GetPDMLog();
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
#define READ_OUTPUT_BUFFER_TIMEOUT_US 3000
using namespace android;
typedef android::MediaCodecProxy MediaCodecProxy;
@ -34,18 +36,15 @@ typedef android::MediaCodecProxy MediaCodecProxy;
namespace mozilla {
GonkAudioDecoderManager::GonkAudioDecoderManager(const AudioInfo& aConfig)
: mLastDecodedTime(0)
, mAudioChannels(aConfig.mChannels)
: mAudioChannels(aConfig.mChannels)
, mAudioRate(aConfig.mRate)
, mAudioProfile(aConfig.mProfile)
, mAudioBuffer(nullptr)
, mMonitor("GonkAudioDecoderManager")
{
MOZ_COUNT_CTOR(GonkAudioDecoderManager);
MOZ_ASSERT(mAudioChannels);
mCodecSpecificData = aConfig.mCodecSpecificConfig;
mMimeType = aConfig.mMimeType;
}
GonkAudioDecoderManager::~GonkAudioDecoderManager()
@ -54,9 +53,9 @@ GonkAudioDecoderManager::~GonkAudioDecoderManager()
}
nsRefPtr<MediaDataDecoder::InitPromise>
GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
GonkAudioDecoderManager::Init()
{
if (InitMediaCodecProxy(aCallback)) {
if (InitMediaCodecProxy()) {
return InitPromise::CreateAndResolve(TrackType::kAudioTrack, __func__);
} else {
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
@ -64,18 +63,14 @@ GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
}
bool
GonkAudioDecoderManager::InitMediaCodecProxy(MediaDataDecoderCallback* aCallback)
GonkAudioDecoderManager::InitMediaCodecProxy()
{
status_t rv = OK;
if (mLooper != nullptr) {
if (!InitLoopers(MediaData::AUDIO_DATA)) {
return false;
}
// Create ALooper
mLooper = new ALooper;
mLooper->setName("GonkAudioDecoderManager");
mLooper->start();
mDecoder = MediaCodecProxy::CreateByType(mLooper, mMimeType.get(), false, nullptr);
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, nullptr);
if (!mDecoder.get()) {
return false;
}
@ -99,7 +94,8 @@ GonkAudioDecoderManager::InitMediaCodecProxy(MediaDataDecoderCallback* aCallback
if (mMimeType.EqualsLiteral("audio/mp4a-latm")) {
rv = mDecoder->Input(mCodecSpecificData->Elements(), mCodecSpecificData->Length(), 0,
android::MediaCodec::BUFFER_FLAG_CODECCONFIG);
android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
CODECCONFIG_TIMEOUT_US);
}
if (rv == OK) {
@ -110,52 +106,6 @@ GonkAudioDecoderManager::InitMediaCodecProxy(MediaDataDecoderCallback* aCallback
}
}
bool
GonkAudioDecoderManager::HasQueuedSample()
{
MonitorAutoLock mon(mMonitor);
return mQueueSample.Length();
}
nsresult
GonkAudioDecoderManager::Input(MediaRawData* aSample)
{
MonitorAutoLock mon(mMonitor);
nsRefPtr<MediaRawData> sample;
if (aSample) {
sample = aSample;
} else {
// It means EOS with empty sample.
sample = new MediaRawData();
}
mQueueSample.AppendElement(sample);
status_t rv;
while (mQueueSample.Length()) {
nsRefPtr<MediaRawData> data = mQueueSample.ElementAt(0);
{
MonitorAutoUnlock mon_exit(mMonitor);
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
data->Size(),
data->mTime,
0);
}
if (rv == OK) {
mQueueSample.RemoveElementAt(0);
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
// buffer on time.
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
nsresult
GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
if (!(mAudioBuffer != nullptr && mAudioBuffer->data() != nullptr)) {
@ -175,13 +125,13 @@ GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
return NS_ERROR_NOT_AVAILABLE;
}
if (mLastDecodedTime > timeUs) {
if (mLastTime > timeUs) {
ReleaseAudioBuffer();
GADM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
MOZ_ASSERT(false);
return NS_ERROR_NOT_AVAILABLE;
}
mLastDecodedTime = timeUs;
mLastTime = timeUs;
const uint8_t *data = static_cast<const uint8_t*>(mAudioBuffer->data());
size_t dataOffset = mAudioBuffer->range_offset();
@ -207,23 +157,6 @@ GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
return NS_OK;
}
nsresult
GonkAudioDecoderManager::Flush()
{
{
MonitorAutoLock mon(mMonitor);
mQueueSample.Clear();
}
mLastDecodedTime = 0;
if (mDecoder->flush() != OK) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult
GonkAudioDecoderManager::Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutData)

Просмотреть файл

@ -13,7 +13,6 @@
using namespace android;
namespace android {
struct MOZ_EXPORT ALooper;
class MOZ_EXPORT MediaBuffer;
} // namespace android
@ -24,44 +23,26 @@ typedef android::MediaCodecProxy MediaCodecProxy;
public:
GonkAudioDecoderManager(const AudioInfo& aConfig);
virtual ~GonkAudioDecoderManager() override;
virtual ~GonkAudioDecoderManager();
nsRefPtr<InitPromise> Init(MediaDataDecoderCallback* aCallback) override;
nsresult Input(MediaRawData* aSample) override;
nsRefPtr<InitPromise> Init() override;
nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) override;
nsresult Flush() override;
bool HasQueuedSample() override;
private:
bool InitMediaCodecProxy(MediaDataDecoderCallback* aCallback);
bool InitMediaCodecProxy();
nsresult CreateAudioData(int64_t aStreamOffset,
AudioData** aOutData);
void ReleaseAudioBuffer();
int64_t mLastDecodedTime;
uint32_t mAudioChannels;
uint32_t mAudioRate;
const uint32_t mAudioProfile;
MediaDataDecoderCallback* mReaderCallback;
android::MediaBuffer* mAudioBuffer;
android::sp<ALooper> mLooper;
// This monitor protects mQueueSample.
Monitor mMonitor;
// An queue with the MP4 samples which are waiting to be sent into OMX.
// If an element is an empty MP4Sample, that menas EOS. There should not
// any sample be queued after EOS.
nsTArray<nsRefPtr<MediaRawData>> mQueueSample;
};
} // namespace mozilla

Просмотреть файл

@ -8,9 +8,13 @@
#include "nsTArray.h"
#include "MediaCodecProxy.h"
#include <stagefright/foundation/ADebug.h>
#include "mozilla/Logging.h"
#include <android/log.h>
#define GMDD_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkMediaDataDecoder", __VA_ARGS__)
#define INPUT_TIMEOUT_US 0LL // Don't wait for buffer if none is available.
#define MIN_QUEUED_SAMPLES 2
extern PRLogModuleInfo* GetPDMLog();
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
@ -19,6 +23,103 @@ using namespace android;
namespace mozilla {
bool
GonkDecoderManager::InitLoopers(MediaData::Type aType)
{
MOZ_ASSERT(mDecodeLooper.get() == nullptr && mTaskLooper.get() == nullptr);
MOZ_ASSERT(aType == MediaData::VIDEO_DATA || aType == MediaData::AUDIO_DATA);
const char* suffix = (aType == MediaData::VIDEO_DATA ? "video" : "audio");
mDecodeLooper = new ALooper;
android::AString name("MediaCodecProxy/");
name.append(suffix);
mDecodeLooper->setName(name.c_str());
mTaskLooper = new ALooper;
name.setTo("GonkDecoderManager/");
name.append(suffix);
mTaskLooper->setName(name.c_str());
mTaskLooper->registerHandler(this);
return mDecodeLooper->start() == OK && mTaskLooper->start() == OK;
}
nsresult
GonkDecoderManager::Input(MediaRawData* aSample)
{
nsRefPtr<MediaRawData> sample;
if (aSample) {
sample = aSample;
} else {
// It means EOS with empty sample.
sample = new MediaRawData();
}
{
MutexAutoLock lock(mMutex);
mQueuedSamples.AppendElement(sample);
}
sp<AMessage> input = new AMessage(kNotifyProcessInput, id());
if (!aSample) {
input->setInt32("input-eos", 1);
}
input->post();
return NS_OK;
}
int32_t
GonkDecoderManager::ProcessQueuedSamples()
{
MutexAutoLock lock(mMutex);
status_t rv;
while (mQueuedSamples.Length()) {
nsRefPtr<MediaRawData> data = mQueuedSamples.ElementAt(0);
{
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
data->Size(),
data->mTime,
0,
INPUT_TIMEOUT_US);
}
if (rv == OK) {
mQueuedSamples.RemoveElementAt(0);
mWaitOutput.AppendElement(data->mOffset);
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
// buffer on time.
break;
} else {
return rv;
}
}
return mQueuedSamples.Length();
}
nsresult
GonkDecoderManager::Flush()
{
if (mDecoder == nullptr) {
GMDD_LOG("Decoder is not initialized");
return NS_ERROR_UNEXPECTED;
}
{
MutexAutoLock lock(mMutex);
mQueuedSamples.Clear();
}
mLastTime = 0;
MonitorAutoLock lock(mFlushMonitor);
mIsFlushing = true;
sp<AMessage> flush = new AMessage(kNotifyProcessFlush, id());
flush->post();
while (mIsFlushing) {
lock.Wait();
}
return NS_OK;
}
nsresult
GonkDecoderManager::Shutdown()
{
@ -33,16 +134,135 @@ GonkDecoderManager::Shutdown()
return NS_OK;
}
bool
GonkDecoderManager::HasQueuedSample()
{
MutexAutoLock lock(mMutex);
return mQueuedSamples.Length();
}
void
GonkDecoderManager::ProcessInput(bool aEndOfStream)
{
status_t rv = ProcessQueuedSamples();
if (rv >= 0) {
if (!aEndOfStream && rv <= MIN_QUEUED_SAMPLES) {
mDecodeCallback->InputExhausted();
}
if (mToDo.get() == nullptr) {
mToDo = new AMessage(kNotifyDecoderActivity, id());
if (aEndOfStream) {
mToDo->setInt32("input-eos", 1);
}
mDecoder->requestActivityNotification(mToDo);
}
} else {
GMDD_LOG("input processed: error#%d", rv);
mDecodeCallback->Error();
}
}
void
GonkDecoderManager::ProcessFlush()
{
MonitorAutoLock lock(mFlushMonitor);
mWaitOutput.Clear();
if (mDecoder->flush() != OK) {
GMDD_LOG("flush error");
mDecodeCallback->Error();
}
mIsFlushing = false;
lock.NotifyAll();
}
void
GonkDecoderManager::ProcessToDo(bool aEndOfStream)
{
MOZ_ASSERT(mToDo.get() != nullptr);
mToDo.clear();
if (HasQueuedSample()) {
status_t pendingInput = ProcessQueuedSamples();
if (pendingInput < 0) {
mDecodeCallback->Error();
return;
}
if (!aEndOfStream && pendingInput <= MIN_QUEUED_SAMPLES) {
mDecodeCallback->InputExhausted();
}
}
nsresult rv = NS_OK;
while (mWaitOutput.Length() > 0) {
nsRefPtr<MediaData> output;
int64_t offset = mWaitOutput.ElementAt(0);
rv = Output(offset, output);
if (rv == NS_OK) {
mWaitOutput.RemoveElementAt(0);
mDecodeCallback->Output(output);
} else if (rv == NS_ERROR_ABORT) {
GMDD_LOG("eos output");
mWaitOutput.RemoveElementAt(0);
MOZ_ASSERT(mQueuedSamples.IsEmpty());
MOZ_ASSERT(mWaitOutput.IsEmpty());
// EOS
if (output) {
mDecodeCallback->Output(output);
}
mDecodeCallback->DrainComplete();
return;
} else if (rv == NS_ERROR_NOT_AVAILABLE) {
break;
} else {
mDecodeCallback->Error();
return;
}
}
if (HasQueuedSample() || mWaitOutput.Length() > 0) {
mToDo = new AMessage(kNotifyDecoderActivity, id());
mDecoder->requestActivityNotification(mToDo);
}
}
void
GonkDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
{
switch (aMessage->what()) {
case kNotifyProcessInput:
{
int32_t eos = 0;
ProcessInput(aMessage->findInt32("input-eos", &eos) && eos);
break;
}
case kNotifyProcessFlush:
{
ProcessFlush();
break;
}
case kNotifyDecoderActivity:
{
int32_t eos = 0;
ProcessToDo(aMessage->findInt32("input-eos", &eos) && eos);
break;
}
default:
{
TRESPASS();
break;
}
}
}
GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
FlushableTaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback)
: mTaskQueue(aTaskQueue)
, mCallback(aCallback)
, mManager(aManager)
, mSignaledEOS(false)
, mDrainComplete(false)
{
MOZ_COUNT_CTOR(GonkMediaDataDecoder);
mManager->SetDecodeCallback(aCallback);
}
GonkMediaDataDecoder::~GonkMediaDataDecoder()
@ -53,9 +273,7 @@ GonkMediaDataDecoder::~GonkMediaDataDecoder()
nsRefPtr<MediaDataDecoder::InitPromise>
GonkMediaDataDecoder::Init()
{
mDrainComplete = false;
return mManager->Init(mCallback);
return mManager->Init();
}
nsresult
@ -73,79 +291,10 @@ GonkMediaDataDecoder::Shutdown()
nsresult
GonkMediaDataDecoder::Input(MediaRawData* aSample)
{
nsCOMPtr<nsIRunnable> runnable(
NS_NewRunnableMethodWithArg<nsRefPtr<MediaRawData>>(
this,
&GonkMediaDataDecoder::ProcessDecode,
nsRefPtr<MediaRawData>(aSample)));
mTaskQueue->Dispatch(runnable.forget());
mManager->Input(aSample);
return NS_OK;
}
void
GonkMediaDataDecoder::ProcessDecode(MediaRawData* aSample)
{
nsresult rv = mManager->Input(aSample);
if (rv != NS_OK) {
NS_WARNING("GonkMediaDataDecoder failed to input data");
GMDD_LOG("Failed to input data err: %d",int(rv));
mCallback->Error();
return;
}
if (aSample) {
mLastStreamOffset = aSample->mOffset;
}
ProcessOutput();
}
void
GonkMediaDataDecoder::ProcessOutput()
{
nsRefPtr<MediaData> output;
nsresult rv = NS_ERROR_ABORT;
while (!mDrainComplete) {
// There are samples in queue, try to send them into decoder when EOS.
if (mSignaledEOS && mManager->HasQueuedSample()) {
GMDD_LOG("ProcessOutput: drain all input samples");
rv = mManager->Input(nullptr);
}
rv = mManager->Output(mLastStreamOffset, output);
if (rv == NS_OK) {
mCallback->Output(output);
continue;
} else if (rv == NS_ERROR_NOT_AVAILABLE && mSignaledEOS) {
// Try to get more frames before getting EOS frame
continue;
}
else {
break;
}
}
if (rv == NS_ERROR_NOT_AVAILABLE && !mSignaledEOS) {
mCallback->InputExhausted();
return;
}
if (rv != NS_OK) {
NS_WARNING("GonkMediaDataDecoder failed to output data");
GMDD_LOG("Failed to output data");
// GonkDecoderManangers report NS_ERROR_ABORT when EOS is reached.
if (rv == NS_ERROR_ABORT) {
if (output) {
mCallback->Output(output);
}
mCallback->DrainComplete();
MOZ_ASSERT_IF(mSignaledEOS, !mManager->HasQueuedSample());
mSignaledEOS = false;
mDrainComplete = true;
return;
}
GMDD_LOG("Callback error!");
mCallback->Error();
}
}
nsresult
GonkMediaDataDecoder::Flush()
{
@ -154,25 +303,13 @@ GonkMediaDataDecoder::Flush()
// it's executing at all. Note the MP4Reader ignores all output while
// flushing.
mTaskQueue->Flush();
mDrainComplete = false;
return mManager->Flush();
}
void
GonkMediaDataDecoder::ProcessDrain()
{
// Notify decoder input EOS by sending a null data.
ProcessDecode(nullptr);
mSignaledEOS = true;
ProcessOutput();
}
nsresult
GonkMediaDataDecoder::Drain()
{
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethod(this, &GonkMediaDataDecoder::ProcessDrain);
mTaskQueue->Dispatch(runnable.forget());
mManager->Input(nullptr);
return NS_OK;
}

Просмотреть файл

@ -7,8 +7,10 @@
#if !defined(GonkMediaDataDecoder_h_)
#define GonkMediaDataDecoder_h_
#include "PlatformDecoderModule.h"
#include <stagefright/foundation/AHandler.h>
namespace android {
struct ALooper;
class MediaCodecProxy;
} // namespace android
@ -16,7 +18,7 @@ namespace mozilla {
class MediaRawData;
// Manage the data flow from inputting encoded data and outputting decode data.
class GonkDecoderManager {
class GonkDecoderManager : public android::AHandler {
public:
typedef TrackInfo::TrackType TrackType;
typedef MediaDataDecoder::InitPromise InitPromise;
@ -24,39 +26,99 @@ public:
virtual ~GonkDecoderManager() {}
virtual nsRefPtr<InitPromise> Init(MediaDataDecoderCallback* aCallback) = 0;
virtual nsRefPtr<InitPromise> Init() = 0;
// Add samples into OMX decoder or queue them if decoder is out of input buffer.
virtual nsresult Input(MediaRawData* aSample) = 0;
// Produces decoded output, it blocks until output can be produced or a timeout
// is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
// if there's not enough data to produce more output. If this returns a failure
// code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
// MP4Reader.
// The overrided class should follow the same behaviour.
virtual nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) = 0;
// Asynchronously send sample into mDecoder. If out of input buffer, aSample
// will be queued for later re-send.
nsresult Input(MediaRawData* aSample);
// Flush the queued sample.
virtual nsresult Flush() = 0;
nsresult Flush();
// Shutdown decoder and rejects the init promise.
nsresult Shutdown();
// True if sample is queued.
virtual bool HasQueuedSample() = 0;
bool HasQueuedSample();
// Set callback for decoder events, such as requesting more input,
// returning output, or reporting error.
void SetDecodeCallback(MediaDataDecoderCallback* aCallback)
{
mDecodeCallback = aCallback;
}
protected:
GonkDecoderManager()
: mMutex("GonkDecoderManager")
, mLastTime(0)
, mFlushMonitor("GonkDecoderManager::Flush")
, mIsFlushing(false)
, mDecodeCallback(nullptr)
{}
bool InitLoopers(MediaData::Type aType);
void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
// Produces decoded output. It returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
// when output is not produced yet.
// If this returns a failure code other than NS_ERROR_NOT_AVAILABLE, an error
// will be reported through mDecodeCallback.
virtual nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) = 0;
// Send queued samples to OMX. It returns how many samples are still in
// queue after processing, or negtive error code if failed.
int32_t ProcessQueuedSamples();
void ProcessInput(bool aEndOfStream);
void ProcessFlush();
void ProcessToDo(bool aEndOfStream);
nsRefPtr<MediaByteBuffer> mCodecSpecificData;
nsAutoCString mMimeType;
// MediaCodedc's wrapper that performs the decoding.
android::sp<android::MediaCodecProxy> mDecoder;
// Looper for mDecoder to run on.
android::sp<android::ALooper> mDecodeLooper;
// Looper to run decode tasks such as processing input, output, flush, and
// recycling output buffers.
android::sp<android::ALooper> mTaskLooper;
enum {
// Decoder will send this to indicate internal state change such as input or
// output buffers availability. Used to run pending input & output tasks.
kNotifyDecoderActivity = 'nda ',
// Signal the decoder to flush.
kNotifyProcessFlush = 'npf ',
// Used to process queued samples when there is new input.
kNotifyProcessInput = 'npi ',
};
MozPromiseHolder<InitPromise> mInitPromise;
Mutex mMutex; // Protects mQueuedSamples.
// A queue that stores the samples waiting to be sent to mDecoder.
// Empty element means EOS and there shouldn't be any sample be queued after it.
// Samples are queued in caller's thread and dequeued in mTaskLooper.
nsTArray<nsRefPtr<MediaRawData>> mQueuedSamples;
int64_t mLastTime; // The last decoded frame presentation time.
Monitor mFlushMonitor; // Waits for flushing to complete.
bool mIsFlushing;
// Remembers the notification that is currently waiting for the decoder event
// to avoid requesting more than one notification at the time, which is
// forbidden by mDecoder.
android::sp<android::AMessage> mToDo;
// Stores the offset of every output that needs to be read from mDecoder.
nsTArray<int64_t> mWaitOutput;
MediaDataDecoderCallback* mDecodeCallback; // Reports decoder output or error.
};
// Samples are decoded using the GonkDecoder (MediaCodec)
@ -83,33 +145,9 @@ public:
nsresult Shutdown() override;
private:
// Called on the task queue. Inserts the sample into the decoder, and
// extracts output if available, if aSample is null, it means there is
// no data from source, it will notify the decoder EOS and flush all the
// decoded frames.
void ProcessDecode(MediaRawData* aSample);
// Called on the task queue. Extracts output if available, and delivers
// it to the reader. Called after ProcessDecode() and ProcessDrain().
void ProcessOutput();
// Called on the task queue. Orders the Gonk to drain, and then extracts
// all available output.
void ProcessDrain();
RefPtr<FlushableTaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback;
nsAutoPtr<GonkDecoderManager> mManager;
// The last offset into the media resource that was passed into Input().
// This is used to approximate the decoder's position in the media resource.
int64_t mLastStreamOffset;
// Set it ture when there is no input data
bool mSignaledEOS;
// Set if there is no more output data from decoder
bool mDrainComplete;
android::sp<GonkDecoderManager> mManager;
};
} // namespace mozilla

Просмотреть файл

@ -17,17 +17,15 @@
#include "stagefright/MediaBuffer.h"
#include "stagefright/MetaData.h"
#include "stagefright/MediaErrors.h"
#include <stagefright/foundation/ADebug.h>
#include <stagefright/foundation/AMessage.h>
#include <stagefright/foundation/AString.h>
#include <stagefright/foundation/ALooper.h>
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "mozilla/layers/GrallocTextureClient.h"
#include "mozilla/layers/TextureClient.h"
#include <cutils/properties.h>
#define READ_OUTPUT_BUFFER_TIMEOUT_US 3000
#define CODECCONFIG_TIMEOUT_US 10000LL
#define READ_OUTPUT_BUFFER_TIMEOUT_US 0LL
#include <android/log.h>
#define GVDM_LOG(...) __android_log_print(ANDROID_LOG_DEBUG, "GonkVideoDecoderManager", __VA_ARGS__)
@ -44,12 +42,9 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
mozilla::layers::ImageContainer* aImageContainer,
const VideoInfo& aConfig)
: mImageContainer(aImageContainer)
, mReaderCallback(nullptr)
, mLastDecodedTime(0)
, mColorConverterBufferSize(0)
, mNativeWindow(nullptr)
, mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock")
, mMonitor("GonkVideoDecoderManager")
{
MOZ_COUNT_CTOR(GonkVideoDecoderManager);
mMimeType = aConfig.mMimeType;
@ -64,7 +59,6 @@ GonkVideoDecoderManager::GonkVideoDecoderManager(
nsIntSize frameSize(mVideoWidth, mVideoHeight);
mPicture = pictureRect;
mInitialFrame = frameSize;
mHandler = new MessageHandler(this);
mVideoListener = new VideoResourceListener(this);
}
@ -76,7 +70,7 @@ GonkVideoDecoderManager::~GonkVideoDecoderManager()
}
nsRefPtr<MediaDataDecoder::InitPromise>
GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
GonkVideoDecoderManager::Init()
{
nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
@ -101,26 +95,19 @@ GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
}
mReaderCallback = aCallback;
mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
MOZ_ASSERT(mReaderTaskQueue);
if (mLooper.get() != nullptr) {
if (mDecodeLooper.get() != nullptr) {
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
}
// Create ALooper
mLooper = new ALooper;
mManagerLooper = new ALooper;
mManagerLooper->setName("GonkVideoDecoderManager");
// Register AMessage handler to ALooper.
mManagerLooper->registerHandler(mHandler);
// Start ALooper thread.
if (mLooper->start() != OK || mManagerLooper->start() != OK ) {
if (!InitLoopers(MediaData::VIDEO_DATA)) {
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
}
nsRefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
mDecoder = MediaCodecProxy::CreateByType(mLooper, mMimeType.get(), false, mVideoListener);
mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false, mVideoListener);
mDecoder->AsyncAskMediaCodec();
uint32_t capability = MediaCodecProxy::kEmptyCapability;
@ -132,52 +119,6 @@ GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
return p;
}
nsresult
GonkVideoDecoderManager::Input(MediaRawData* aSample)
{
MonitorAutoLock mon(mMonitor);
nsRefPtr<MediaRawData> sample;
if (!aSample) {
// It means EOS with empty sample.
sample = new MediaRawData();
} else {
sample = aSample;
}
mQueueSample.AppendElement(sample);
status_t rv;
while (mQueueSample.Length()) {
nsRefPtr<MediaRawData> data = mQueueSample.ElementAt(0);
{
MonitorAutoUnlock mon_unlock(mMonitor);
rv = mDecoder->Input(reinterpret_cast<const uint8_t*>(data->Data()),
data->Size(),
data->mTime,
0);
}
if (rv == OK) {
mQueueSample.RemoveElementAt(0);
} else if (rv == -EAGAIN || rv == -ETIMEDOUT) {
// In most cases, EAGAIN or ETIMEOUT are safe because OMX can't fill
// buffer on time.
return NS_OK;
} else {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
bool
GonkVideoDecoderManager::HasQueuedSample()
{
MonitorAutoLock mon(mMonitor);
return mQueueSample.Length();
}
nsresult
GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
{
@ -197,12 +138,12 @@ GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
return NS_ERROR_UNEXPECTED;
}
if (mLastDecodedTime > timeUs) {
if (mLastTime > timeUs) {
ReleaseVideoBuffer();
GVDM_LOG("Output decoded sample time is revert. time=%lld", timeUs);
return NS_ERROR_NOT_AVAILABLE;
}
mLastDecodedTime = timeUs;
mLastTime = timeUs;
if (mVideoBuffer->range_length() == 0) {
// Some decoders may return spurious empty buffers that we just want to ignore
@ -367,27 +308,6 @@ GonkVideoDecoderManager::SetVideoFormat()
return false;
}
nsresult
GonkVideoDecoderManager::Flush()
{
if (mDecoder == nullptr) {
GVDM_LOG("Decoder is not inited");
return NS_ERROR_UNEXPECTED;
}
{
MonitorAutoLock mon(mMonitor);
mQueueSample.Clear();
}
mLastDecodedTime = 0;
if (mDecoder->flush() != OK) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
// Blocks until decoded sample is produced by the deoder.
nsresult
GonkVideoDecoderManager::Output(int64_t aStreamOffset,
@ -497,7 +417,8 @@ GonkVideoDecoderManager::codecReserved()
if (mMimeType.EqualsLiteral("video/mp4v-es")) {
rv = mDecoder->Input(mCodecSpecificData->Elements(),
mCodecSpecificData->Length(), 0,
android::MediaCodec::BUFFER_FLAG_CODECCONFIG);
android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
CODECCONFIG_TIMEOUT_US);
}
if (rv != OK) {
@ -516,7 +437,7 @@ GonkVideoDecoderManager::codecCanceled()
mInitPromise.RejectIfExists(DecoderFailureReason::CANCELED, __func__);
}
// Called on GonkVideoDecoderManager::mManagerLooper thread.
// Called on GonkDecoderManager::mTaskLooper thread.
void
GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
{
@ -528,26 +449,10 @@ GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
}
default:
TRESPASS();
{
GonkDecoderManager::onMessageReceived(aMessage);
break;
}
}
GonkVideoDecoderManager::MessageHandler::MessageHandler(GonkVideoDecoderManager *aManager)
: mManager(aManager)
{
}
GonkVideoDecoderManager::MessageHandler::~MessageHandler()
{
mManager = nullptr;
}
void
GonkVideoDecoderManager::MessageHandler::onMessageReceived(const android::sp<android::AMessage> &aMessage)
{
if (mManager != nullptr) {
mManager->onMessageReceived(aMessage);
}
}
}
@ -652,7 +557,7 @@ void GonkVideoDecoderManager::PostReleaseVideoBuffer(
}
}
sp<AMessage> notify =
new AMessage(kNotifyPostReleaseBuffer, mHandler->id());
new AMessage(kNotifyPostReleaseBuffer, id());
notify->post();
}

Просмотреть файл

@ -7,13 +7,11 @@
#if !defined(GonkVideoDecoderManager_h_)
#define GonkVideoDecoderManager_h_
#include <set>
#include "nsRect.h"
#include "GonkMediaDataDecoder.h"
#include "mozilla/RefPtr.h"
#include "I420ColorConverterHelper.h"
#include "MediaCodecProxy.h"
#include <stagefright/foundation/AHandler.h>
#include "GonkNativeWindow.h"
#include "GonkNativeWindowClient.h"
#include "mozilla/layers/FenceUtils.h"
@ -22,7 +20,6 @@
using namespace android;
namespace android {
struct ALooper;
class MediaBuffer;
struct MOZ_EXPORT AString;
class GonkNativeWindow;
@ -42,19 +39,13 @@ public:
GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
const VideoInfo& aConfig);
virtual ~GonkVideoDecoderManager() override;
virtual ~GonkVideoDecoderManager();
nsRefPtr<InitPromise> Init(MediaDataDecoderCallback* aCallback) override;
nsresult Input(MediaRawData* aSample) override;
nsRefPtr<InitPromise> Init() override;
nsresult Output(int64_t aStreamOffset,
nsRefPtr<MediaData>& aOutput) override;
nsresult Flush() override;
bool HasQueuedSample() override;
static void RecycleCallback(TextureClient* aClient, void* aClosure);
private:
@ -70,23 +61,8 @@ private:
int32_t mCropRight = 0;
int32_t mCropBottom = 0;
};
class MessageHandler : public android::AHandler
{
public:
MessageHandler(GonkVideoDecoderManager *aManager);
~MessageHandler();
void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
private:
// Forbidden
MessageHandler() = delete;
MessageHandler(const MessageHandler &rhs) = delete;
const MessageHandler &operator=(const MessageHandler &rhs) = delete;
GonkVideoDecoderManager *mManager;
};
friend class MessageHandler;
void onMessageReceived(const android::sp<android::AMessage> &aMessage) override;
class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
{
@ -119,7 +95,6 @@ private:
// For codec resource management
void codecReserved();
void codecCanceled();
void onMessageReceived(const sp<AMessage> &aMessage);
void ReleaseAllPendingVideoBuffers();
void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer,
@ -136,16 +111,10 @@ private:
android::MediaBuffer* mVideoBuffer;
MediaDataDecoderCallback* mReaderCallback;
MediaInfo mInfo;
android::sp<VideoResourceListener> mVideoListener;
android::sp<MessageHandler> mHandler;
android::sp<ALooper> mLooper;
android::sp<ALooper> mManagerLooper;
FrameInfo mFrameInfo;
int64_t mLastDecodedTime; // The last decoded frame presentation time.
// color converter
android::I420ColorConverterHelper mColorConverter;
nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
@ -168,17 +137,9 @@ private:
// The lock protects mPendingReleaseItems.
Mutex mPendingReleaseItemsLock;
// This monitor protects mQueueSample.
Monitor mMonitor;
// This TaskQueue should be the same one in mReaderCallback->OnReaderTaskQueue().
// This TaskQueue should be the same one in mDecodeCallback->OnReaderTaskQueue().
// It is for codec resource mangement, decoding task should not dispatch to it.
nsRefPtr<TaskQueue> mReaderTaskQueue;
// An queue with the MP4 samples which are waiting to be sent into OMX.
// If an element is an empty MP4Sample, that menas EOS. There should not
// any sample be queued after EOS.
nsTArray<nsRefPtr<MediaRawData>> mQueueSample;
};
} // namespace mozilla

Просмотреть файл

@ -230,26 +230,34 @@ public:
aOutput->AllocateChannels(channelCount);
for (uint32_t i = 0; i < channelCount; ++i) {
float* scaledSample = (float *)(aInput.mChannelData[i]);
AudioBlockInPlaceScale(scaledSample, aInput.mVolume);
const float* inputBuffer = static_cast<const float*>(scaledSample);
const float* inputSamples;
float scaledInput[WEBAUDIO_BLOCK_SIZE];
if (aInput.mVolume != 1.0f) {
AudioBlockCopyChannelWithScale(
static_cast<const float*>(aInput.mChannelData[i]),
aInput.mVolume,
scaledInput);
inputSamples = scaledInput;
} else {
inputSamples = static_cast<const float*>(aInput.mChannelData[i]);
}
float* outputBuffer = aOutput->ChannelFloatsForWrite(i);
float* sampleBuffer;
switch (mType) {
case OverSampleType::None:
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::None);
ProcessCurve<1>(inputBuffer, outputBuffer);
ProcessCurve<1>(inputSamples, outputBuffer);
break;
case OverSampleType::_2x:
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::_2x);
sampleBuffer = mResampler.UpSample(i, inputBuffer, 2);
sampleBuffer = mResampler.UpSample(i, inputSamples, 2);
ProcessCurve<2>(sampleBuffer, sampleBuffer);
mResampler.DownSample(i, outputBuffer, 2);
break;
case OverSampleType::_4x:
mResampler.Reset(channelCount, aStream->SampleRate(), OverSampleType::_4x);
sampleBuffer = mResampler.UpSample(i, inputBuffer, 4);
sampleBuffer = mResampler.UpSample(i, inputSamples, 4);
ProcessCurve<4>(sampleBuffer, sampleBuffer);
mResampler.DownSample(i, outputBuffer, 4);
break;

Просмотреть файл

@ -172,6 +172,7 @@ skip-if = (toolkit == 'gonk' && !debug) || android_version == '10' || android_ve
[test_stereoPanningWithGain.html]
[test_waveDecoder.html]
[test_waveShaper.html]
[test_waveShaperGain.html]
[test_waveShaperNoCurve.html]
[test_waveShaperPassThrough.html]
[test_waveShaperInvalidLengthCurve.html]

Просмотреть файл

@ -0,0 +1,51 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Test that WaveShaperNode doesn't corrupt its inputs when the gain is !=
1.0 (bug 1203616)</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var samplerate = 44100;
var context = new OfflineAudioContext(1, 44100, samplerate);
var dc = context.createBufferSource();
var buffer = context.createBuffer(1, 1, samplerate);
buffer.getChannelData(0)[0] = 1.0;
dc.buffer = buffer;
var gain = context.createGain();
var ws2 = context.createWaveShaper();
var ws = [];
// No-op waveshaper curves.
for (var i = 0; i < 2; i++) {
ws[i] = context.createWaveShaper();
var curve = new Float32Array(2);
curve[0] = -1.0;
curve[1] = 1.0;
ws[i].curve = curve;
ws[i].connect(context.destination);
gain.connect(ws[i]);
}
dc.connect(gain);
dc.start();
gain.gain.value = 0.5;
context.startRendering().then(buffer => {
document.querySelector("pre").innerHTML = buffer.getChannelData(0)[0];
ok(buffer.getChannelData(0)[0] == 1.0, "Volume was handled properly");
SimpleTest.finish();
});
</script>
<pre>
</pre>
</body>

Просмотреть файл

@ -462,9 +462,9 @@ WebMDemuxer::EnsureUpToDateIndex()
}
void
WebMDemuxer::NotifyDataArrived(uint32_t aLength, int64_t aOffset)
WebMDemuxer::NotifyDataArrived()
{
WEBM_DEBUG("length: %ld offset: %ld", aLength, aOffset);
WEBM_DEBUG("");
mNeedReIndex = true;
}

Просмотреть файл

@ -129,7 +129,7 @@ private:
void Cleanup();
void InitBufferedState();
nsresult ReadMetadata();
void NotifyDataArrived(uint32_t aLength, int64_t aOffset) override;
void NotifyDataArrived() override;
void NotifyDataRemoved() override;
void EnsureUpToDateIndex();
media::TimeIntervals GetBuffered();

Просмотреть файл

@ -168,7 +168,7 @@ PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
nsRefPtr<PresentationSession> session =
PresentationSession::Create(GetOwner(), aSessionId,
PresentationSessionState::Disconnected);
PresentationSessionState::Closed);
if (NS_WARN_IF(!session)) {
return NS_ERROR_NOT_AVAILABLE;
}

Просмотреть файл

@ -429,7 +429,7 @@ PresentationService::SendSessionMessage(const nsAString& aSessionId,
}
NS_IMETHODIMP
PresentationService::Terminate(const nsAString& aSessionId)
PresentationService::CloseSession(const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aSessionId.IsEmpty());
@ -439,7 +439,21 @@ PresentationService::Terminate(const nsAString& aSessionId)
return NS_ERROR_NOT_AVAILABLE;
}
return info->Close(NS_OK);
return info->Close(NS_OK, nsIPresentationSessionListener::STATE_CLOSED);
}
NS_IMETHODIMP
PresentationService::TerminateSession(const nsAString& aSessionId)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aSessionId.IsEmpty());
nsRefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId);
if (NS_WARN_IF(!info)) {
return NS_ERROR_NOT_AVAILABLE;
}
return info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED);
}
NS_IMETHODIMP
@ -495,7 +509,7 @@ PresentationService::UnregisterSessionListener(const nsAString& aSessionId)
nsRefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId);
if (info) {
NS_WARN_IF(NS_FAILED(info->Close(NS_OK)));
NS_WARN_IF(NS_FAILED(info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED)));
UntrackSessionInfo(aSessionId);
return info->SetListener(nullptr);
}

Просмотреть файл

@ -142,31 +142,44 @@ PresentationSession::Send(const nsAString& aData,
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
return;
}
rv = service->SendSessionMessage(mId, stream);
if(NS_WARN_IF(NS_FAILED(rv))) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
}
}
void
PresentationSession::Close()
PresentationSession::Close(ErrorResult& aRv)
{
// Closing does nothing if the session is already terminated.
if (NS_WARN_IF(mState == PresentationSessionState::Terminated)) {
// It only works when the state is CONNECTED.
if (NS_WARN_IF(mState != PresentationSessionState::Connected)) {
return;
}
// TODO Bug 1210340 - Support close semantics.
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
void
PresentationSession::Terminate(ErrorResult& aRv)
{
// It only works when the state is CONNECTED.
if (NS_WARN_IF(mState != PresentationSessionState::Connected)) {
return;
}
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if(NS_WARN_IF(!service)) {
aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
return;
}
NS_WARN_IF(NS_FAILED(service->Terminate(mId)));
NS_WARN_IF(NS_FAILED(service->TerminateSession(mId)));
}
NS_IMETHODIMP
@ -182,8 +195,8 @@ PresentationSession::NotifyStateChange(const nsAString& aSessionId,
case nsIPresentationSessionListener::STATE_CONNECTED:
state = PresentationSessionState::Connected;
break;
case nsIPresentationSessionListener::STATE_DISCONNECTED:
state = PresentationSessionState::Disconnected;
case nsIPresentationSessionListener::STATE_CLOSED:
state = PresentationSessionState::Closed;
break;
case nsIPresentationSessionListener::STATE_TERMINATED:
state = PresentationSessionState::Terminated;

Просмотреть файл

@ -23,10 +23,9 @@ public:
DOMEventTargetHelper)
NS_DECL_NSIPRESENTATIONSESSIONLISTENER
static already_AddRefed<PresentationSession>
Create(nsPIDOMWindow* aWindow,
const nsAString& aId,
PresentationSessionState aState);
static already_AddRefed<PresentationSession> Create(nsPIDOMWindow* aWindow,
const nsAString& aId,
PresentationSessionState aState);
virtual void DisconnectFromOwner() override;
@ -38,9 +37,12 @@ public:
PresentationSessionState State() const;
void Send(const nsAString& aData, ErrorResult& aRv);
void Send(const nsAString& aData,
ErrorResult& aRv);
void Close();
void Close(ErrorResult& aRv);
void Terminate(ErrorResult& aRv);
IMPL_EVENT_HANDLER(statechange);
IMPL_EVENT_HANDLER(message);

Просмотреть файл

@ -174,10 +174,7 @@ PresentationSessionInfo::SetListener(nsIPresentationSessionListener* aListener)
// The transport might become ready, or might become un-ready again, before
// the listener has registered. So notify the listener of the state change.
uint16_t state = IsSessionReady() ?
nsIPresentationSessionListener::STATE_CONNECTED :
nsIPresentationSessionListener::STATE_DISCONNECTED;
return mListener->NotifyStateChange(mSessionId, state);
return mListener->NotifyStateChange(mSessionId, mState);
}
return NS_OK;
@ -198,23 +195,15 @@ PresentationSessionInfo::Send(nsIInputStream* aData)
}
nsresult
PresentationSessionInfo::Close(nsresult aReason)
PresentationSessionInfo::Close(nsresult aReason,
uint32_t aState)
{
// The session is disconnected and it's a normal close. Simply change the
// state to TERMINATED.
if (!IsSessionReady() && NS_SUCCEEDED(aReason)) {
if (mListener) {
// Notify the listener and the service will untrack the session info after
// the listener calls |UnregisterSessionListener|.
nsresult rv = mListener->NotifyStateChange(mSessionId,
nsIPresentationSessionListener::STATE_TERMINATED);
NS_WARN_IF(NS_FAILED(rv));
} else {
// Directly untrack the session info from the service.
NS_WARN_IF(NS_FAILED(UntrackFromService()));
}
if (NS_WARN_IF(!IsSessionReady())) {
return NS_ERROR_DOM_INVALID_STATE_ERR;
}
SetState(aState);
Shutdown(aReason);
return NS_OK;
}
@ -222,12 +211,7 @@ PresentationSessionInfo::Close(nsresult aReason)
nsresult
PresentationSessionInfo::ReplySuccess()
{
if (mListener) {
// Notify session state change.
nsresult rv = mListener->NotifyStateChange(mSessionId,
nsIPresentationSessionListener::STATE_CONNECTED);
NS_WARN_IF(NS_FAILED(rv));
}
SetState(nsIPresentationSessionListener::STATE_CONNECTED);
if (mCallback) {
NS_WARN_IF(NS_FAILED(mCallback->NotifySuccess()));
@ -308,17 +292,14 @@ PresentationSessionInfo::NotifyTransportClosed(nsresult aReason)
// Unset |mIsTransportReady| here so it won't affect |IsSessionReady()| above.
mIsTransportReady = false;
if (mState == nsIPresentationSessionListener::STATE_CONNECTED) {
// The transport channel is closed unexpectedly (not caused by a |Close| call).
SetState(nsIPresentationSessionListener::STATE_CLOSED);
}
Shutdown(aReason);
uint16_t state = (NS_WARN_IF(NS_FAILED(aReason))) ?
nsIPresentationSessionListener::STATE_DISCONNECTED :
nsIPresentationSessionListener::STATE_TERMINATED;
if (mListener) {
// It happens after the session is ready. Notify session state change.
// If the new state is TERMINATED. the service will untrack the session info
// after the listener calls |UnregisterSessionListener|.
return mListener->NotifyStateChange(mSessionId, state);
} else if (state == nsIPresentationSessionListener::STATE_TERMINATED) {
if (mState == nsIPresentationSessionListener::STATE_TERMINATED) {
// Directly untrack the session info from the service.
return UntrackFromService();
}
@ -509,12 +490,9 @@ PresentationControllingInfo::NotifyClosed(nsresult aReason)
SetControlChannel(nullptr);
if (NS_WARN_IF(NS_FAILED(aReason))) {
if (mListener) {
// The presentation session instance at receiver side may already exist.
// Change the state to TERMINATED since it never succeeds.
return mListener->NotifyStateChange(mSessionId,
nsIPresentationSessionListener::STATE_TERMINATED);
}
// The presentation session instance may already exist.
// Change the state to TERMINATED since it never succeeds.
SetState(nsIPresentationSessionListener::STATE_TERMINATED);
// Reply error for an abnormal close.
return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
@ -566,11 +544,8 @@ PresentationControllingInfo::OnStopListening(nsIServerSocket* aServerSocket,
return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
}
// It happens after the session is ready. Notify session state change.
if (mListener) {
return mListener->NotifyStateChange(mSessionId,
nsIPresentationSessionListener::STATE_DISCONNECTED);
}
// It happens after the session is ready. Change the state to CLOSED.
SetState(nsIPresentationSessionListener::STATE_CLOSED);
return NS_OK;
}
@ -775,12 +750,9 @@ PresentationPresentingInfo::NotifyClosed(nsresult aReason)
SetControlChannel(nullptr);
if (NS_WARN_IF(NS_FAILED(aReason))) {
if (mListener) {
// The presentation session instance at receiver side may already exist.
// Change the state to TERMINATED since it never succeeds.
return mListener->NotifyStateChange(mSessionId,
nsIPresentationSessionListener::STATE_TERMINATED);
}
// The presentation session instance may already exist.
// Change the state to TERMINATED since it never succeeds.
SetState(nsIPresentationSessionListener::STATE_TERMINATED);
// Reply error for an abnormal close.
return ReplyError(NS_ERROR_DOM_OPERATION_ERR);

Просмотреть файл

@ -39,6 +39,7 @@ public:
, mSessionId(aSessionId)
, mIsResponderReady(false)
, mIsTransportReady(false)
, mState(nsIPresentationSessionListener::STATE_CLOSED)
, mCallback(aCallback)
{
MOZ_ASSERT(!mUrl.IsEmpty());
@ -89,7 +90,8 @@ public:
nsresult Send(nsIInputStream* aData);
nsresult Close(nsresult aReason);
nsresult Close(nsresult aReason,
uint32_t aState);
nsresult ReplyError(nsresult aReason);
@ -112,10 +114,26 @@ protected:
virtual nsresult UntrackFromService();
void SetState(uint32_t aState)
{
if (mState == aState) {
return;
}
mState = aState;
// Notify session state change.
if (mListener) {
nsresult rv = mListener->NotifyStateChange(mSessionId, mState);
NS_WARN_IF(NS_FAILED(rv));
}
}
nsString mUrl;
nsString mSessionId;
bool mIsResponderReady;
bool mIsTransportReady;
uint32_t mState; // CONNECTED, CLOSED, TERMINATED
nsCOMPtr<nsIPresentationServiceCallback> mCallback;
nsCOMPtr<nsIPresentationSessionListener> mListener;
nsCOMPtr<nsIPresentationDevice> mDevice;

Просмотреть файл

@ -13,11 +13,11 @@ interface nsIPresentationAvailabilityListener : nsISupports
void notifyAvailableChange(in bool available);
};
[scriptable, uuid(3b9ae71f-2905-4969-9117-101627c1c2ea)]
[scriptable, uuid(7dd48df8-8f8c-48c7-ac37-7b9fd1acf2f8)]
interface nsIPresentationSessionListener : nsISupports
{
const unsigned short STATE_CONNECTED = 0;
const unsigned short STATE_DISCONNECTED = 1;
const unsigned short STATE_CLOSED = 1;
const unsigned short STATE_TERMINATED = 2;
/*

Просмотреть файл

@ -33,7 +33,7 @@ interface nsIPresentationServiceCallback : nsISupports
void notifyError(in nsresult error);
};
[scriptable, uuid(5a254519-45c3-4229-9b16-f58c05b78fc6)]
[scriptable, uuid(c177a13a-bf1a-48bf-8032-d415c3343c46)]
interface nsIPresentationService : nsISupports
{
/*
@ -62,12 +62,19 @@ interface nsIPresentationService : nsISupports
void sendSessionMessage(in DOMString sessionId,
in nsIInputStream stream);
/*
* Close the session.
*
* @param sessionId: An ID to identify presentation session.
*/
void closeSession(in DOMString sessionId);
/*
* Terminate the session.
*
* @param sessionId: An ID to identify presentation session.
*/
void terminate(in DOMString sessionId);
void terminateSession(in DOMString sessionId);
/*
* Register an availability listener. Must be called from the main thread.

Просмотреть файл

@ -25,7 +25,12 @@ struct SendSessionMessageRequest
InputStreamParams data;
};
struct TerminateRequest
struct CloseSessionRequest
{
nsString sessionId;
};
struct TerminateSessionRequest
{
nsString sessionId;
};
@ -34,7 +39,8 @@ union PresentationIPCRequest
{
StartSessionRequest;
SendSessionMessageRequest;
TerminateRequest;
CloseSessionRequest;
TerminateSessionRequest;
};
sync protocol PPresentation

Просмотреть файл

@ -71,11 +71,19 @@ PresentationIPCService::SendSessionMessage(const nsAString& aSessionId,
}
NS_IMETHODIMP
PresentationIPCService::Terminate(const nsAString& aSessionId)
PresentationIPCService::CloseSession(const nsAString& aSessionId)
{
MOZ_ASSERT(!aSessionId.IsEmpty());
return SendRequest(nullptr, TerminateRequest(nsAutoString(aSessionId)));
return SendRequest(nullptr, CloseSessionRequest(nsAutoString(aSessionId)));
}
NS_IMETHODIMP
PresentationIPCService::TerminateSession(const nsAString& aSessionId)
{
MOZ_ASSERT(!aSessionId.IsEmpty());
return SendRequest(nullptr, TerminateSessionRequest(nsAutoString(aSessionId)));
}
nsresult

Просмотреть файл

@ -74,8 +74,11 @@ PresentationParent::RecvPPresentationRequestConstructor(
case PresentationIPCRequest::TSendSessionMessageRequest:
rv = actor->DoRequest(aRequest.get_SendSessionMessageRequest());
break;
case PresentationIPCRequest::TTerminateRequest:
rv = actor->DoRequest(aRequest.get_TerminateRequest());
case PresentationIPCRequest::TCloseSessionRequest:
rv = actor->DoRequest(aRequest.get_CloseSessionRequest());
break;
case PresentationIPCRequest::TTerminateSessionRequest:
rv = actor->DoRequest(aRequest.get_TerminateSessionRequest());
break;
default:
MOZ_CRASH("Unknown PresentationIPCRequest type");
@ -278,7 +281,7 @@ PresentationRequestParent::DoRequest(const SendSessionMessageRequest& aRequest)
}
nsresult
PresentationRequestParent::DoRequest(const TerminateRequest& aRequest)
PresentationRequestParent::DoRequest(const CloseSessionRequest& aRequest)
{
MOZ_ASSERT(mService);
@ -289,7 +292,26 @@ PresentationRequestParent::DoRequest(const TerminateRequest& aRequest)
return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
}
nsresult rv = mService->Terminate(aRequest.sessionId());
nsresult rv = mService->CloseSession(aRequest.sessionId());
if (NS_WARN_IF(NS_FAILED(rv))) {
return NotifyError(rv);
}
return NotifySuccess();
}
nsresult
PresentationRequestParent::DoRequest(const TerminateSessionRequest& aRequest)
{
MOZ_ASSERT(mService);
// Validate the accessibility (primarily for receiver side) so that a
// compromised child process can't fake the ID.
if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
IsSessionAccessible(aRequest.sessionId(), OtherPid()))) {
return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
}
nsresult rv = mService->TerminateSession(aRequest.sessionId());
if (NS_WARN_IF(NS_FAILED(rv))) {
return NotifyError(rv);
}

Просмотреть файл

@ -89,7 +89,9 @@ private:
nsresult DoRequest(const SendSessionMessageRequest& aRequest);
nsresult DoRequest(const TerminateRequest& aRequest);
nsresult DoRequest(const CloseSessionRequest& aRequest);
nsresult DoRequest(const TerminateSessionRequest& aRequest);
bool mActorDestroyed;
nsCOMPtr<nsIPresentationService> mService;

Просмотреть файл

@ -42,12 +42,12 @@ function testSessionAvailable() {
session = aSession;
ok(session.id, "Session ID should be set: " + session.id);
is(session.state, "disconnected", "Session state at receiver side should be disconnected by default.");
is(session.state, "closed", "Session state at receiver side should be closed by default.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when getting the session: " + aError);
teardown();
finish();
aReject();
}
);
@ -81,7 +81,7 @@ function testIncomingMessage() {
});
}
function testCloseSession() {
function testTerminateSession() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
@ -89,14 +89,14 @@ function testCloseSession() {
aResolve();
};
session.close();
session.terminate();
});
}
testSessionAvailable().
then(testSessionReady).
then(testIncomingMessage).
then(testCloseSession).
then(testTerminateSession).
then(finish);
</script>

Просмотреть файл

@ -42,12 +42,12 @@ function testSessionAvailable() {
session = aSession;
ok(session.id, "Session ID should be set: " + session.id);
is(session.state, "disconnected", "Session state at receiver side should be disconnected by default.");
is(session.state, "closed", "Session state at receiver side should be closed by default.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when getting the session: " + aError);
teardown();
finish();
aReject();
}
);
@ -81,7 +81,7 @@ function testIncomingMessage() {
});
}
function testCloseSession() {
function testTerminateSession() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
@ -89,14 +89,14 @@ function testCloseSession() {
aResolve();
};
session.close();
session.terminate();
});
}
testSessionAvailable().
then(testSessionReady).
then(testIncomingMessage).
then(testCloseSession).
then(testTerminateSession).
then(finish);
</script>

Просмотреть файл

@ -42,12 +42,12 @@ function testSessionAvailable() {
session = aSession;
ok(session.id, "Session ID should be set: " + session.id);
is(session.state, "disconnected", "Session state at receiver side should be disconnected by default.");
is(session.state, "closed", "Session state at receiver side should be closed by default.");
aResolve();
},
function(aError) {
ok(false, "Error occurred when getting the session: " + aError);
teardown();
finish();
aReject();
}
);

Просмотреть файл

@ -148,7 +148,7 @@ function testIncomingMessage() {
});
}
function testCloseSession() {
function testTerminateSession() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
@ -161,7 +161,7 @@ function testCloseSession() {
aResolve();
};
session.close();
session.terminate();
});
}
@ -182,7 +182,7 @@ function runTests() {
then(testStartSession).
then(testSend).
then(testIncomingMessage).
then(testCloseSession).
then(testTerminateSession).
then(teardown);
}

Просмотреть файл

@ -97,7 +97,7 @@ function testStartSession() {
});
}
function testCloseSession() {
function testTerminateSession() {
return new Promise(function(aResolve, aReject) {
gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
@ -110,7 +110,7 @@ function testCloseSession() {
aResolve();
};
session.close();
session.terminate();
});
}
@ -130,7 +130,7 @@ function runTests() {
testSetup().
then(testStartSession).
then(testCloseSession).
then(testTerminateSession).
then(teardown);
}

Просмотреть файл

@ -113,7 +113,7 @@ function testSessionDisconnection() {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "disconnected", "Session should be disconnected.");
is(session.state, "closed", "Session should be closed.");
aResolve();
};
@ -121,18 +121,6 @@ function testSessionDisconnection() {
});
}
function testCloseSession() {
return new Promise(function(aResolve, aReject) {
session.onstatechange = function() {
session.onstatechange = null;
is(session.state, "terminated", "Session should be terminated.");
aResolve();
};
session.close();
});
}
function teardown() {
gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
@ -149,7 +137,6 @@ function runTests() {
testSetup().
then(testStartSession).
then(testSessionDisconnection).
then(testCloseSession).
then(teardown);
}

Просмотреть файл

@ -1,3 +1,2 @@
component {94b065ad-d45a-436a-b394-6dabc3cf110f} TVSimulatorService.js
contract @mozilla.org/tv/simulatorservice;1 {94b065ad-d45a-436a-b394-6dabc3cf110f}
TVSimulatorService @mozilla.org/tv/simulatorservice;1

Просмотреть файл

@ -10,10 +10,10 @@ enum PresentationSessionState
"connected",
// Existing presentation, but the communication channel is inactive.
"disconnected",
"closed",
// The presentation is nonexistent anymore. It could be terminated manually,
// or either requesting page or presenting page is no longer available.
// or either controlling or receiving browsing context is no longer available.
"terminated"
};
@ -27,27 +27,24 @@ interface PresentationSession : EventTarget {
readonly attribute DOMString id;
/*
* Please refer to PresentationSessionStateEvent.webidl for the declaration of
* PresentationSessionState.
*
* @value "connected", "disconnected", or "terminated".
* @value "connected", "closed", or "terminated".
*/
readonly attribute PresentationSessionState state;
/*
* It is called when session state changes. New state is dispatched with the
* event.
* It is called when session state changes.
*/
attribute EventHandler onstatechange;
/*
* After a communication channel has been established between the requesting
* page and the presenting page, send() is called to send message out, and the
* event handler "onmessage" will be invoked on the remote side.
* After a communication channel has been established between the controlling
* and receiving context, this function is called to send message out, and the
* event handler "onmessage" will be invoked at the remote side.
*
* This function only works when state equals "connected".
* This function only works when the state is "connected".
*
* @data: String literal-only for current implementation.
* TODO bug 1148307 Implement PresentationSessionTransport with DataChannel to
* support other binary types.
*/
[Throws]
void send(DOMString data);
@ -58,12 +55,21 @@ interface PresentationSession : EventTarget {
attribute EventHandler onmessage;
/*
* Both the requesting page and the presenting page can close the session by
* calling terminate(). Then, the session is destroyed and its state is
* truned into "terminated". After getting into the state of "terminated",
* resumeSession() is incapable of re-establishing the connection.
* Both the controlling and receving browsing context can close the session.
* Then, the session state should turn into "closed".
*
* This function does nothing if the state has already been "terminated".
* This function only works when the state is not "connected".
*/
void close();
// TODO Bug 1210340 - Support close semantics.
// [Throws]
// void close();
/*
* Both the controlling and receving browsing context can terminate the session.
* Then the session state should turn into "terminated".
*
* This function only works when the state is not "connected".
*/
[Throws]
void terminate();
};

Просмотреть файл

@ -2315,30 +2315,6 @@ nsPermissionManager::RemovePermissionsForApp(uint32_t aAppId, bool aBrowserOnly)
ENSURE_NOT_CHILD_PROCESS;
NS_ENSURE_ARG(aAppId != nsIScriptSecurityManager::NO_APP_ID);
// We begin by removing all the permissions from the DB.
// After clearing the DB, we call AddInternal() to make sure that all
// processes are aware of this change and the representation of the DB in
// memory is updated.
// We have to get all permissions associated with an application first
// because removing entries from the permissions table while iterating over
// it is dangerous.
nsAutoCString sql;
sql.AppendLiteral("DELETE FROM moz_perms WHERE appId=");
sql.AppendInt(aAppId);
if (aBrowserOnly) {
sql.AppendLiteral(" AND isInBrowserElement=1");
}
nsCOMPtr<mozIStorageAsyncStatement> removeStmt;
nsresult rv = mDBConn->CreateAsyncStatement(sql, getter_AddRefs(removeStmt));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStoragePendingStatement> pending;
rv = removeStmt->ExecuteAsync(nullptr, getter_AddRefs(pending));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMArray<nsIPermission> permissions;
for (auto iter = mPermissionTable.Iter(); !iter.Done(); iter.Next()) {
PermissionHashKey* entry = iter.Get();

Просмотреть файл

@ -0,0 +1,96 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function run_test() {
// initialize the permission manager service
let ssm = Services.scriptSecurityManager;
let pm = Services.perms;
function mkPrin(uri, appId, inBrowser) {
return ssm.createCodebasePrincipal(Services.io.newURI(uri, null, null),
{appId: appId, inBrowser: inBrowser});
}
function checkPerms(perms) {
perms.forEach((perm) => {
// Look up the expected permission
do_check_eq(pm.getPermissionObject(mkPrin(perm[0], perm[1], perm[2]),
perm[3], true).capability,
perm[4], "Permission is expected in the permission database");
});
// Count the entries
let count = 0;
let enumerator = Services.perms.enumerator;
while (enumerator.hasMoreElements()) { enumerator.getNext(); count++; }
do_check_eq(count, perms.length, "There should be the right number of permissions in the DB");
}
checkPerms([]);
let permissions = [
['http://google.com', 1001, false, 'a', 1],
['http://google.com', 1001, false, 'b', 1],
['http://mozilla.com', 1001, false, 'b', 1],
['http://mozilla.com', 1001, false, 'a', 1],
['http://google.com', 1001, true, 'a', 1],
['http://google.com', 1001, true, 'b', 1],
['http://mozilla.com', 1001, true, 'b', 1],
['http://mozilla.com', 1001, true, 'a', 1],
['http://google.com', 1011, false, 'a', 1],
['http://google.com', 1011, false, 'b', 1],
['http://mozilla.com', 1011, false, 'b', 1],
['http://mozilla.com', 1011, false, 'a', 1],
];
permissions.forEach((perm) => {
pm.addFromPrincipal(mkPrin(perm[0], perm[1], perm[2]), perm[3], perm[4]);
});
checkPerms(permissions);
let remove_false_perms = [
['http://google.com', 1011, false, 'a', 1],
['http://google.com', 1011, false, 'b', 1],
['http://mozilla.com', 1011, false, 'b', 1],
['http://mozilla.com', 1011, false, 'a', 1],
];
pm.removePermissionsForApp(1001, false);
checkPerms(remove_false_perms);
let restore = [
['http://google.com', 1001, false, 'a', 1],
['http://google.com', 1001, false, 'b', 1],
['http://mozilla.com', 1001, false, 'b', 1],
['http://mozilla.com', 1001, false, 'a', 1],
['http://google.com', 1001, true, 'a', 1],
['http://google.com', 1001, true, 'b', 1],
['http://mozilla.com', 1001, true, 'b', 1],
['http://mozilla.com', 1001, true, 'a', 1],
];
restore.forEach((perm) => {
pm.addFromPrincipal(mkPrin(perm[0], perm[1], perm[2]), perm[3], perm[4]);
});
checkPerms(permissions);
let remove_true_perms = [
['http://google.com', 1001, false, 'a', 1],
['http://google.com', 1001, false, 'b', 1],
['http://mozilla.com', 1001, false, 'b', 1],
['http://mozilla.com', 1001, false, 'a', 1],
['http://google.com', 1011, false, 'a', 1],
['http://google.com', 1011, false, 'b', 1],
['http://mozilla.com', 1011, false, 'b', 1],
['http://mozilla.com', 1011, false, 'a', 1],
];
pm.removePermissionsForApp(1001, true);
checkPerms(remove_true_perms);
}

Просмотреть файл

@ -26,6 +26,7 @@ skip-if = true # Bug 863738
[test_permmanager_notifications.js]
[test_permmanager_removeall.js]
[test_permmanager_removesince.js]
[test_permmanager_removeforapp.js]
[test_permmanager_load_invalid_entries.js]
skip-if = debug == true
[test_permmanager_idn.js]

Просмотреть файл

@ -536,6 +536,27 @@ IsTransferFilterType(FilterType aType)
}
}
static bool
HasUnboundedOutputRegion(FilterType aType)
{
if (IsTransferFilterType(aType)) {
return true;
}
switch (aType) {
case FilterType::COLOR_MATRIX:
case FilterType::POINT_DIFFUSE:
case FilterType::SPOT_DIFFUSE:
case FilterType::DISTANT_DIFFUSE:
case FilterType::POINT_SPECULAR:
case FilterType::SPOT_SPECULAR:
case FilterType::DISTANT_SPECULAR:
return true;
default:
return false;
}
}
/* static */
already_AddRefed<FilterNode>
FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType)
@ -556,7 +577,7 @@ FilterNodeD2D1::Create(ID2D1DeviceContext *aDC, FilterType aType)
RefPtr<FilterNodeD2D1> filter = new FilterNodeD2D1(effect, aType);
if (IsTransferFilterType(aType) || aType == FilterType::COLOR_MATRIX) {
if (HasUnboundedOutputRegion(aType)) {
// These filters can produce non-transparent output from transparent
// input pixels, and we want them to have an unbounded output region.
filter = new FilterNodeExtendInputAdapterD2D1(aDC, filter, aType);

Просмотреть файл

@ -3340,7 +3340,7 @@ template<typename LightType, typename LightingType>
IntRect
FilterNodeLightingSoftware<LightType, LightingType>::GetOutputRectInRect(const IntRect& aRect)
{
return GetInputRectInRect(IN_LIGHTING_IN, aRect);
return aRect;
}
Point3D
@ -3482,7 +3482,7 @@ FilterNodeLightingSoftware<LightType, LightingType>::DoRender(const IntRect& aRe
RefPtr<DataSourceSurface> input =
GetInputDataSourceSurface(IN_LIGHTING_IN, srcRect, CAN_HANDLE_A8,
EDGE_MODE_DUPLICATE);
EDGE_MODE_NONE);
if (!input) {
return nullptr;

Просмотреть файл

@ -435,12 +435,14 @@ public:
DebugGLGraphicBuffer(void *layerRef,
GLenum target,
GLuint name,
const LayerRenderState &aState)
const LayerRenderState &aState,
bool aIsMask)
: DebugGLData(Packet::TEXTURE),
mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
mTarget(target),
mName(name),
mState(aState)
mState(aState),
mIsMask(aIsMask)
{
}
@ -457,6 +459,7 @@ public:
tp->set_layerref(mLayerRef);
tp->set_name(mName);
tp->set_target(mTarget);
tp->set_ismask(mIsMask);
int pFormat = buffer->getPixelFormat();
if (HAL_PIXEL_FORMAT_RGBA_8888 != pFormat &&
@ -513,6 +516,7 @@ private:
GLenum mTarget;
GLuint mName;
const LayerRenderState &mState;
bool mIsMask;
Packet mPacket;
};
#endif
@ -523,13 +527,15 @@ public:
void* layerRef,
GLenum target,
GLuint name,
DataSourceSurface* img)
DataSourceSurface* img,
bool aIsMask)
: DebugGLData(Packet::TEXTURE),
mLayerRef(reinterpret_cast<uint64_t>(layerRef)),
mTarget(target),
mName(name),
mContextAddress(reinterpret_cast<intptr_t>(cx)),
mDatasize(0)
mDatasize(0),
mIsMask(aIsMask)
{
// pre-packing
// DataSourceSurface may have locked buffer,
@ -552,6 +558,7 @@ private:
tp->set_target(mTarget);
tp->set_dataformat(LOCAL_GL_RGBA);
tp->set_glcontext(static_cast<uint64_t>(mContextAddress));
tp->set_ismask(mIsMask);
if (aImage) {
tp->set_width(aImage->GetSize().width);
@ -590,6 +597,7 @@ protected:
GLuint mName;
intptr_t mContextAddress;
uint32_t mDatasize;
bool mIsMask;
// Packet data
Packet mPacket;
@ -872,9 +880,11 @@ NS_IMPL_ISUPPORTS(DebugDataSender::SendTask, nsIRunnable);
* 2. SendEffectChain
* 1. SendTexturedEffect
* -> SendTextureSource
* 2. SendYCbCrEffect
* 2. SendMaskEffect
* -> SendTextureSource
* 3. SendColor
* 3. SendYCbCrEffect
* -> SendTextureSource
* 4. SendColor
*/
class SenderHelper
{
@ -895,7 +905,7 @@ public:
static bool GetLayersTreeSendable() {return sLayersTreeSendable;}
static void ClearTextureIdList();
static void ClearSentTextureIds();
// Sender private functions
@ -907,58 +917,52 @@ private:
static void SendTextureSource(GLContext* aGLContext,
void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
bool aFlipY);
bool aFlipY,
bool aIsMask);
#ifdef MOZ_WIDGET_GONK
static bool SendGraphicBuffer(void* aLayerRef,
static bool SendGraphicBuffer(GLContext* aGLContext,
void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
const TexturedEffect* aEffect);
const TexturedEffect* aEffect,
bool aIsMask);
#endif
static void SendTexturedEffect(GLContext* aGLContext,
void* aLayerRef,
const TexturedEffect* aEffect);
static void SendMaskEffect(GLContext* aGLContext,
void* aLayerRef,
const EffectMask* aEffect);
static void SendYCbCrEffect(GLContext* aGLContext,
void* aLayerRef,
const EffectYCbCr* aEffect);
static GLuint GetTextureID(GLContext* aGLContext,
TextureSourceOGL* aSource);
static bool IsTextureIdContainsInList(GLuint aTextureId);
static bool HasTextureIdBeenSent(GLuint aTextureId);
// Data fields
private:
static bool sLayersTreeSendable;
static bool sLayersBufferSendable;
static std::list<GLuint> sTextureIdList;
static std::vector<GLuint> sSentTextureIds;
};
bool SenderHelper::sLayersTreeSendable = true;
bool SenderHelper::sLayersBufferSendable = true;
std::list<GLuint> SenderHelper::sTextureIdList;
std::vector<GLuint> SenderHelper::sSentTextureIds;
// ----------------------------------------------
// SenderHelper implementation
// ----------------------------------------------
void
SenderHelper::ClearTextureIdList()
SenderHelper::ClearSentTextureIds()
{
std::list<GLuint>::iterator it;
while (!sTextureIdList.empty()) {
it = sTextureIdList.begin();
sTextureIdList.erase(it);
}
sSentTextureIds.clear();
}
bool
SenderHelper::IsTextureIdContainsInList(GLuint aTextureId)
SenderHelper::HasTextureIdBeenSent(GLuint aTextureId)
{
for (std::list<GLuint>::iterator it = sTextureIdList.begin();
it != sTextureIdList.end(); ++it) {
if (*it == aTextureId) {
return true;
}
}
return false;
return std::find(sSentTextureIds.begin(), sSentTextureIds.end(), aTextureId) != sSentTextureIds.end();
}
void
@ -1035,13 +1039,17 @@ void
SenderHelper::SendTextureSource(GLContext* aGLContext,
void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
bool aFlipY)
bool aFlipY,
bool aIsMask)
{
MOZ_ASSERT(aGLContext);
if (!aGLContext) {
return;
}
GLuint texID = GetTextureID(aGLContext, aSource);
if (HasTextureIdBeenSent(texID)) {
return;
}
GLenum textureTarget = aSource->GetTextureTarget();
ShaderConfigOGL config = ShaderConfigFromTargetAndFormat(textureTarget,
@ -1058,26 +1066,31 @@ SenderHelper::SendTextureSource(GLContext* aGLContext,
shaderConfig, aFlipY);
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLTextureData(aGLContext, aLayerRef, textureTarget,
aTexID, img));
texID, img, aIsMask));
sTextureIdList.push_back(aTexID);
gLayerScopeManager.CurrentSession().mTexIDs.push_back(aTexID);
sSentTextureIds.push_back(texID);
gLayerScopeManager.CurrentSession().mTexIDs.push_back(texID);
}
#ifdef MOZ_WIDGET_GONK
bool
SenderHelper::SendGraphicBuffer(void* aLayerRef,
SenderHelper::SendGraphicBuffer(GLContext* aGLContext,
void* aLayerRef,
TextureSourceOGL* aSource,
GLuint aTexID,
const TexturedEffect* aEffect) {
const TexturedEffect* aEffect,
bool aIsMask) {
GLuint texID = GetTextureID(aGLContext, aSource);
if (HasTextureIdBeenSent(texID)) {
return false;
}
if (!aEffect->mState.mSurface.get()) {
return false;
}
GLenum target = aSource->GetTextureTarget();
mozilla::UniquePtr<DebugGLGraphicBuffer> package =
MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, aTexID, aEffect->mState);
MakeUnique<DebugGLGraphicBuffer>(aLayerRef, target, texID, aEffect->mState, aIsMask);
// The texure content in this TexureHost is not altered,
// we don't need to send it again.
@ -1089,9 +1102,9 @@ SenderHelper::SendGraphicBuffer(void* aLayerRef,
// Transfer ownership to SocketManager.
gLayerScopeManager.GetSocketManager()->AppendDebugData(package.release());
sTextureIdList.push_back(aTexID);
sSentTextureIds.push_back(texID);
gLayerScopeManager.CurrentSession().mTexIDs.push_back(aTexID);
gLayerScopeManager.CurrentSession().mTexIDs.push_back(texID);
gLayerScopeManager.GetContentMonitor()->ClearChangedHost(aEffect->mState.mTexture);
return true;
@ -1108,19 +1121,27 @@ SenderHelper::SendTexturedEffect(GLContext* aGLContext,
return;
}
GLuint texID = GetTextureID(aGLContext, source);
if (IsTextureIdContainsInList(texID)) {
return;
}
#ifdef MOZ_WIDGET_GONK
if (SendGraphicBuffer(aLayerRef, source, texID, aEffect)) {
if (SendGraphicBuffer(aGLContext, aLayerRef, source, aEffect, false)) {
return;
}
#endif
// Fallback texture sending path.
// Render to texture and read pixels back.
SendTextureSource(aGLContext, aLayerRef, source, texID, false);
SendTextureSource(aGLContext, aLayerRef, source, false, false);
}
void
SenderHelper::SendMaskEffect(GLContext* aGLContext,
void* aLayerRef,
const EffectMask* aEffect)
{
TextureSourceOGL* source = aEffect->mMaskTexture->AsSourceOGL();
if (!source) {
return;
}
SendTextureSource(aGLContext, aLayerRef, source, false, true);
}
void
@ -1137,20 +1158,9 @@ SenderHelper::SendYCbCrEffect(GLContext* aGLContext,
TextureSourceOGL* sourceCb = sourceYCbCr->GetSubSource(Cb)->AsSourceOGL();
TextureSourceOGL* sourceCr = sourceYCbCr->GetSubSource(Cr)->AsSourceOGL();
GLuint texID = GetTextureID(aGLContext, sourceY);
if (!IsTextureIdContainsInList(texID)) {
SendTextureSource(aGLContext, aLayerRef, sourceY, texID, false);
}
texID = GetTextureID(aGLContext, sourceCb);
if (!IsTextureIdContainsInList(texID)) {
SendTextureSource(aGLContext, aLayerRef, sourceCb, texID, false);
}
texID = GetTextureID(aGLContext, sourceCr);
if (!IsTextureIdContainsInList(texID)) {
SendTextureSource(aGLContext, aLayerRef, sourceCr, texID, false);
}
SendTextureSource(aGLContext, aLayerRef, sourceY, false, false);
SendTextureSource(aGLContext, aLayerRef, sourceCb, false, false);
SendTextureSource(aGLContext, aLayerRef, sourceCr, false, false);
}
void
@ -1188,8 +1198,11 @@ SenderHelper::SendEffectChain(GLContext* aGLContext,
break;
}
//const Effect* secondaryEffect = aEffectChain.mSecondaryEffects[EffectTypes::MASK];
// TODO:
if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
const EffectMask* effectMask =
static_cast<const EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
SendMaskEffect(aGLContext, aEffectChain.mLayerRef, effectMask);
}
}
void
@ -1872,7 +1885,7 @@ LayerScopeAutoFrame::BeginFrame(int64_t aFrameStamp)
if (!LayerScope::CheckSendable()) {
return;
}
SenderHelper::ClearTextureIdList();
SenderHelper::ClearSentTextureIds();
gLayerScopeManager.GetSocketManager()->AppendDebugData(
new DebugGLFrameStatusData(Packet::FRAMESTART, aFrameStamp));

Просмотреть файл

@ -53,6 +53,10 @@ TextureClientDIB::BorrowDrawTarget()
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(mSurface, mSize);
}
if (!mDrawTarget) {
gfxCriticalNote << "DIB failed draw target surface " << mSize << ", " << (int)mIsLocked << ", " << IsAllocated();
}
return mDrawTarget;
}

Просмотреть файл

@ -424,7 +424,7 @@ TextureClientD3D11::BorrowDrawTarget()
mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture10, mFormat);
}
if (!mDrawTarget) {
gfxWarning() << "Invalid draw target for borrowing";
gfxCriticalNote << "Invalid draw target for borrowing D3D11 " << (int)mFormat;
}
return mDrawTarget;
}

Просмотреть файл

@ -541,6 +541,7 @@ TextureClientD3D9::BorrowDrawTarget()
MOZ_ASSERT(mIsLocked && mD3D9Surface);
if (!mIsLocked || !mD3D9Surface) {
NS_WARNING("Calling BorrowDrawTarget on an Unlocked TextureClient");
gfxCriticalNote << "BorrowDrawTarget on an Unlocked TextureClient";
return nullptr;
}
@ -552,10 +553,14 @@ TextureClientD3D9::BorrowDrawTarget()
nsRefPtr<gfxASurface> surface = new gfxWindowsSurface(mD3D9Surface);
if (!surface || surface->CairoStatus()) {
NS_WARNING("Could not create surface for d3d9 surface");
gfxCriticalNote << "Failed creation on D3D9";
return nullptr;
}
mDrawTarget =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surface, mSize);
if (!mDrawTarget) {
gfxCriticalNote << "Bad draw target creation for surface D3D9 " << mSize;
}
} else {
// gfxWindowsSurface don't support transparency so we can't use the d3d9
// windows surface optimization.
@ -569,6 +574,9 @@ TextureClientD3D9::BorrowDrawTarget()
mDrawTarget =
gfxPlatform::GetPlatform()->CreateDrawTargetForData((uint8_t*)rect.pBits, mSize,
rect.Pitch, mFormat);
if (!mDrawTarget) {
gfxCriticalNote << "Bad draw target creation for data D3D9 " << mSize << ", " << (int)mFormat;
}
mLockRect = true;
}

Просмотреть файл

@ -648,6 +648,7 @@ const int TexturePacket::kTargetFieldNumber;
const int TexturePacket::kDataformatFieldNumber;
const int TexturePacket::kGlcontextFieldNumber;
const int TexturePacket::kDataFieldNumber;
const int TexturePacket::kIsMaskFieldNumber;
#endif // !_MSC_VER
TexturePacket::TexturePacket()
@ -678,6 +679,7 @@ void TexturePacket::SharedCtor() {
dataformat_ = 0u;
glcontext_ = GOOGLE_ULONGLONG(0);
data_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
ismask_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
@ -732,10 +734,13 @@ void TexturePacket::Clear() {
if (_has_bits_[0 / 32] & 255) {
ZR_(layerref_, glcontext_);
}
if (has_data()) {
if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
data_->clear();
if (_has_bits_[8 / 32] & 768) {
if (has_data()) {
if (data_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) {
data_->clear();
}
}
ismask_ = false;
}
#undef OFFSET_OF_FIELD_
@ -755,7 +760,7 @@ bool TexturePacket::MergePartialFromCodedStream(
&unknown_fields_string);
// @@protoc_insertion_point(parse_start:mozilla.layers.layerscope.TexturePacket)
for (;;) {
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127);
::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383);
tag = p.first;
if (!p.second) goto handle_unusual;
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
@ -887,6 +892,21 @@ bool TexturePacket::MergePartialFromCodedStream(
} else {
goto handle_unusual;
}
if (input->ExpectTag(160)) goto parse_isMask;
break;
}
// optional bool isMask = 20;
case 20: {
if (tag == 160) {
parse_isMask:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
input, &ismask_)));
set_has_ismask();
} else {
goto handle_unusual;
}
if (input->ExpectAtEnd()) goto success;
break;
}
@ -962,6 +982,11 @@ void TexturePacket::SerializeWithCachedSizes(
9, this->data(), output);
}
// optional bool isMask = 20;
if (has_ismask()) {
::google::protobuf::internal::WireFormatLite::WriteBool(20, this->ismask(), output);
}
output->WriteRaw(unknown_fields().data(),
unknown_fields().size());
// @@protoc_insertion_point(serialize_end:mozilla.layers.layerscope.TexturePacket)
@ -1036,6 +1061,11 @@ int TexturePacket::ByteSize() const {
this->data());
}
// optional bool isMask = 20;
if (has_ismask()) {
total_size += 2 + 1;
}
}
total_size += unknown_fields().size();
@ -1082,6 +1112,9 @@ void TexturePacket::MergeFrom(const TexturePacket& from) {
if (from.has_data()) {
set_data(from.data());
}
if (from.has_ismask()) {
set_ismask(from.ismask());
}
}
mutable_unknown_fields()->append(from.unknown_fields());
}
@ -1109,6 +1142,7 @@ void TexturePacket::Swap(TexturePacket* other) {
std::swap(dataformat_, other->dataformat_);
std::swap(glcontext_, other->glcontext_);
std::swap(data_, other->data_);
std::swap(ismask_, other->ismask_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
_unknown_fields_.swap(other->_unknown_fields_);
std::swap(_cached_size_, other->_cached_size_);

Просмотреть файл

@ -460,6 +460,13 @@ class TexturePacket : public ::google::protobuf::MessageLite {
inline ::std::string* release_data();
inline void set_allocated_data(::std::string* data);
// optional bool isMask = 20;
inline bool has_ismask() const;
inline void clear_ismask();
static const int kIsMaskFieldNumber = 20;
inline bool ismask() const;
inline void set_ismask(bool value);
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.TexturePacket)
private:
inline void set_has_layerref();
@ -480,6 +487,8 @@ class TexturePacket : public ::google::protobuf::MessageLite {
inline void clear_has_glcontext();
inline void set_has_data();
inline void clear_has_data();
inline void set_has_ismask();
inline void clear_has_ismask();
::std::string _unknown_fields_;
@ -494,6 +503,7 @@ class TexturePacket : public ::google::protobuf::MessageLite {
::google::protobuf::uint32 dataformat_;
::google::protobuf::uint64 glcontext_;
::std::string* data_;
bool ismask_;
#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER
friend void protobuf_AddDesc_LayerScopePacket_2eproto_impl();
#else
@ -2664,6 +2674,30 @@ inline void TexturePacket::set_allocated_data(::std::string* data) {
// @@protoc_insertion_point(field_set_allocated:mozilla.layers.layerscope.TexturePacket.data)
}
// optional bool isMask = 20;
inline bool TexturePacket::has_ismask() const {
return (_has_bits_[0] & 0x00000200u) != 0;
}
inline void TexturePacket::set_has_ismask() {
_has_bits_[0] |= 0x00000200u;
}
inline void TexturePacket::clear_has_ismask() {
_has_bits_[0] &= ~0x00000200u;
}
inline void TexturePacket::clear_ismask() {
ismask_ = false;
clear_has_ismask();
}
inline bool TexturePacket::ismask() const {
// @@protoc_insertion_point(field_get:mozilla.layers.layerscope.TexturePacket.isMask)
return ismask_;
}
inline void TexturePacket::set_ismask(bool value) {
set_has_ismask();
ismask_ = value;
// @@protoc_insertion_point(field_set:mozilla.layers.layerscope.TexturePacket.isMask)
}
// -------------------------------------------------------------------
// LayersPacket_Layer_Size

Просмотреть файл

@ -20,6 +20,7 @@ message ColorPacket {
}
message TexturePacket {
// Basic info
required uint64 layerref = 1;
optional uint32 width = 2;
optional uint32 height = 3;
@ -29,6 +30,13 @@ message TexturePacket {
optional uint32 dataformat = 7;
optional uint64 glcontext = 8;
optional bytes data = 9;
// Texture effect attributes (10 to 19)
// TODO: reserved for primary textured effect attributes, see Bug 1205521
// Mask effect attributes (20 to 29)
optional bool isMask = 20;
// TODO: reserved for secondary mask effect attributes, see Bug 1205521
}
message LayersPacket {

Просмотреть файл

@ -1232,9 +1232,6 @@ FilterNodeGraphFromDescription(DrawTarget* aDT,
{
const nsTArray<FilterPrimitiveDescription>& primitives = aFilter.mPrimitives;
Rect resultNeededRect(aResultNeededRect);
resultNeededRect.RoundOut();
RefPtr<FilterCachedColorModels> sourceFilters[4];
nsTArray<RefPtr<FilterCachedColorModels> > primitiveFilters;
@ -1407,6 +1404,9 @@ ResultChangeRegionForPrimitive(const FilterPrimitiveDescription& aDescription,
case PrimitiveType::ConvolveMatrix:
{
if (atts.GetUint(eConvolveMatrixEdgeMode) != EDGE_MODE_NONE) {
return aDescription.PrimitiveSubregion();
}
Size kernelUnitLength = atts.GetSize(eConvolveMatrixKernelUnitLength);
IntSize kernelSize = atts.GetIntSize(eConvolveMatrixKernelSize);
IntPoint target = atts.GetIntPoint(eConvolveMatrixTarget);
@ -1603,6 +1603,8 @@ FilterSupport::PostFilterExtentsForPrimitive(const FilterPrimitiveDescription& a
case PrimitiveType::Turbulence:
case PrimitiveType::Image:
case PrimitiveType::DiffuseLighting:
case PrimitiveType::SpecularLighting:
{
return aDescription.PrimitiveSubregion();
}

Просмотреть файл

@ -437,7 +437,8 @@ public:
/**
* Computes the region that changes in the filter output due to a change in
* input.
* input. This is primarily needed when an individual piece of content inside
* a filtered container element changes.
*/
static nsIntRegion
ComputeResultChangeRegion(const FilterDescription& aFilter,

Просмотреть файл

@ -181,15 +181,10 @@ static inline bool ShouldFailWithOOM() { return false; }
namespace js {
MOZ_NORETURN MOZ_COLD void
CrashAtUnhandlableOOM(const char* reason);
/* Disable OOM testing in sections which are not OOM safe. */
struct MOZ_RAII AutoEnterOOMUnsafeRegion
{
void crash(const char* reason) {
CrashAtUnhandlableOOM(reason);
}
MOZ_NORETURN MOZ_COLD void crash(const char* reason);
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
AutoEnterOOMUnsafeRegion()

Просмотреть файл

@ -97,12 +97,12 @@ function ModuleDeclarationInstantiation()
let module = this;
// Step 5
if (module.environment !== undefined)
if (GetModuleEnvironment(module) !== undefined)
return;
// Step 7
CreateModuleEnvironment(module);
let env = module.environment;
let env = GetModuleEnvironment(module);
// Step 8
let requestedModules = module.requestedModules;
@ -131,7 +131,7 @@ function ModuleDeclarationInstantiation()
if (imp.importName === "*") {
// TODO
// let namespace = GetModuleNamespace(importedModule);
// CreateNamespaceBinding(module.environment, imp.localName, namespace);
// CreateNamespaceBinding(env, imp.localName, namespace);
} else {
let resolution = importedModule.resolveExport(imp.importName);
if (resolution === null)

Просмотреть файл

@ -410,8 +410,6 @@ ModuleObject::evaluate(JSContext* cx, MutableHandleValue rval)
return JS_ExecuteScript(cx, script, rval);
}
DEFINE_GETTER_FUNCTIONS(ModuleObject, initialEnvironment, InitialEnvironmentSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, environment, EnvironmentSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, evaluated, EvaluatedSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, requestedModules, RequestedModulesSlot)
DEFINE_GETTER_FUNCTIONS(ModuleObject, importEntries, ImportEntriesSlot)
@ -423,8 +421,6 @@ JSObject*
js::InitModuleClass(JSContext* cx, HandleObject obj)
{
static const JSPropertySpec protoAccessors[] = {
JS_PSG("initialEnvironment", ModuleObject_initialEnvironmentGetter, 0),
JS_PSG("environment", ModuleObject_environmentGetter, 0),
JS_PSG("evaluated", ModuleObject_evaluatedGetter, 0),
JS_PSG("requestedModules", ModuleObject_requestedModulesGetter, 0),
JS_PSG("importEntries", ModuleObject_importEntriesGetter, 0),

Просмотреть файл

@ -2886,6 +2886,80 @@ SetRNGState(JSContext* cx, unsigned argc, Value* vp)
}
#endif
static ModuleEnvironmentObject*
GetModuleEnvironment(JSContext* cx, HandleValue moduleValue)
{
RootedModuleObject module(cx, &moduleValue.toObject().as<ModuleObject>());
// Use the initial environment so that tests can check bindings exists
// before they have been instantiated.
RootedModuleEnvironmentObject env(cx, &module->initialEnvironment());
MOZ_ASSERT(env);
MOZ_ASSERT_IF(module->environment(), module->environment() == env);
return env;
}
static bool
GetModuleEnvironmentNames(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 1) {
JS_ReportError(cx, "Wrong number of arguments");
return false;
}
if (!args[0].isObject() || !args[0].toObject().is<ModuleObject>()) {
JS_ReportError(cx, "First argument should be a ModuleObject");
return false;
}
RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
Rooted<IdVector> ids(cx, IdVector(cx));
if (!JS_Enumerate(cx, env, &ids))
return false;
uint32_t length = ids.length();
RootedArrayObject array(cx, NewDenseFullyAllocatedArray(cx, length));
if (!array)
return false;
array->setDenseInitializedLength(length);
for (uint32_t i = 0; i < length; i++)
array->initDenseElement(i, StringValue(JSID_TO_STRING(ids[i])));
args.rval().setObject(*array);
return true;
}
static bool
GetModuleEnvironmentValue(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 2) {
JS_ReportError(cx, "Wrong number of arguments");
return false;
}
if (!args[0].isObject() || !args[0].toObject().is<ModuleObject>()) {
JS_ReportError(cx, "First argument should be a ModuleObject");
return false;
}
if (!args[1].isString()) {
JS_ReportError(cx, "Second argument should be a string");
return false;
}
RootedModuleEnvironmentObject env(cx, GetModuleEnvironment(cx, args[0]));
RootedString name(cx, args[1].toString());
RootedId id(cx);
if (!JS_StringToId(cx, name, &id))
return false;
return GetProperty(cx, env, env, id, args.rval());
}
static const JSFunctionSpecWithHelp TestingFunctions[] = {
JS_FN_HELP("gc", ::GC, 0, 0,
"gc([obj] | 'compartment' [, 'shrinking'])",
@ -3359,6 +3433,14 @@ gc::ZealModeHelpText),
" Set this compartment's RNG state.\n"),
#endif
JS_FN_HELP("getModuleEnvironmentNames", GetModuleEnvironmentNames, 1, 0,
"getModuleEnvironmentNames(module)",
" Get the list of a module environment's bound names for a specified module.\n"),
JS_FN_HELP("getModuleEnvironmentValue", GetModuleEnvironmentValue, 2, 0,
"getModuleEnvironmentValue(module, name)",
" Get the value of a bound name in a module environment.\n"),
JS_FS_HELP_END
};

Просмотреть файл

@ -952,7 +952,7 @@ Statistics::beginSlice(const ZoneGCStats& zoneStats, JSGCInvocationKind gckind,
SliceData data(budget, reason, PRMJ_Now(), JS_GetCurrentEmbedderTime(), GetPageFaultCount());
if (!slices.append(data)) {
// OOM testing fails if we CrashAtUnhandlableOOM here.
// OOM testing fails if we crash here, so set a flag instead.
aborted = true;
return;
}

Просмотреть файл

@ -1,4 +1,4 @@
// |jit-test| allow-oom
// |jit-test| allow-oom; allow-unhandlable-oom
gcparam("maxBytes", gcparam("gcBytes") + 4*1024);
var max = 400;
function f(b) {

Просмотреть файл

@ -0,0 +1,17 @@
load(libdir + 'oomTest.js');
oomTest(() => {
try {
var max = 400;
function f(b) {
if (b) {
f(b - 1);
} else {
g = {};
}
g.apply(null, arguments);
}
f(max - 1);
} catch(exc0) {}
f();
});

Просмотреть файл

@ -1,13 +1,7 @@
// Exercise ModuleDeclarationInstantiation() operation.
function parseAndInstantiate(source) {
let m = parseModule(source);
m.declarationInstantiation();
return m.environment;
}
function testModuleEnvironment(module, expected) {
var actual = Object.keys(module.environment);
var actual = getModuleEnvironmentNames(module);
assertEq(actual.length, expected.length);
for (var i = 0; i < actual.length; i++) {
assertEq(actual[i], expected[i]);
@ -15,8 +9,9 @@ function testModuleEnvironment(module, expected) {
}
// Check the environment of an empty module.
let e = parseAndInstantiate("");
assertEq(Object.keys(e).length, 0);
let m = parseModule("");
m.declarationInstantiation();
testModuleEnvironment(m, []);
let moduleRepo = new Map();
setModuleResolveHook(function(module, specifier) {
@ -25,8 +20,8 @@ setModuleResolveHook(function(module, specifier) {
throw "Module " + specifier + " not found";
});
a = moduleRepo['a'] = parseModule("var x = 1; export { x };");
b = moduleRepo['b'] = parseModule("import { x as y } from 'a';");
let a = moduleRepo['a'] = parseModule("var x = 1; export { x };");
let b = moduleRepo['b'] = parseModule("import { x as y } from 'a';");
a.declarationInstantiation();
b.declarationInstantiation();

Просмотреть файл

@ -3,13 +3,11 @@ load(libdir + "class.js");
// Test top-level module environment
function testInitialEnvironment(source, expected) {
print(source);
let m = parseModule(source);
let scope = m.initialEnvironment;
let keys = Object.keys(scope);
assertEq(keys.length, expected.length);
let module = parseModule(source);
let names = getModuleEnvironmentNames(module);
assertEq(names.length, expected.length);
expected.forEach(function(name) {
assertEq(name in scope, true);
assertEq(names.includes(name), true);
});
}

Просмотреть файл

@ -26,15 +26,15 @@ assertEq(typeof m.evaluation(), "undefined");
// Check top level variables are initialized by evaluation.
m = parseModule("export var x = 2 + 2;");
assertEq(typeof m.initialEnvironment.x, "undefined");
assertEq(typeof getModuleEnvironmentValue(m, "x"), "undefined");
m.declarationInstantiation();
m.evaluation();
assertEq(m.environment.x, 4);
assertEq(getModuleEnvironmentValue(m, "x"), 4);
m = parseModule("export let x = 2 * 3;");
m.declarationInstantiation();
m.evaluation();
assertEq(m.environment.x, 6);
assertEq(getModuleEnvironmentValue(m, "x"), 6);
// Set up a module to import from.
let a = moduleRepo['a'] =
@ -99,4 +99,5 @@ assertDeepEq(parseAndEvaluate(`import { x as x1, y as y1 } from 'c1';
m = parseModule("import { x } from 'a'; function f() { return x; }")
m.declarationInstantiation();
m.evaluation();
assertEq(m.environment.f(), 1);
let f = getModuleEnvironmentValue(m, "f");
assertEq(f(), 1);

Просмотреть файл

@ -2031,7 +2031,7 @@ SnapshotIterator::maybeRead(const RValueAllocation& a, MaybeReadFallback& fallba
if (fallback.canRecoverResults()) {
if (!initInstructionResults(fallback))
js::CrashAtUnhandlableOOM("Unable to recover allocations.");
MOZ_CRASH("Unable to recover allocations.");
if (allocationReadable(a))
return allocationValue(a);

Просмотреть файл

@ -993,7 +993,7 @@ class BOffImm
{
MOZ_ASSERT((offset & 0x3) == 0);
if (!IsInRange(offset))
CrashAtUnhandlableOOM("BOffImm");
MOZ_CRASH("BOffImm offset out of range");
}
explicit BOffImm()

Просмотреть файл

@ -1199,13 +1199,15 @@ JS::AutoCheckRequestDepth::~AutoCheckRequestDepth()
#endif
#ifdef JS_CRASH_DIAGNOSTICS
void CompartmentChecker::check(InterpreterFrame* fp)
void
CompartmentChecker::check(InterpreterFrame* fp)
{
if (fp)
check(fp->scopeChain());
}
void CompartmentChecker::check(AbstractFramePtr frame)
void
CompartmentChecker::check(AbstractFramePtr frame)
{
if (frame)
check(frame.scopeChain());
@ -1213,7 +1215,7 @@ void CompartmentChecker::check(AbstractFramePtr frame)
#endif
void
js::CrashAtUnhandlableOOM(const char* reason)
AutoEnterOOMUnsafeRegion::crash(const char* reason)
{
char msgbuf[1024];
JS_snprintf(msgbuf, sizeof(msgbuf), "[unhandlable oom] %s", reason);

Просмотреть файл

@ -3548,6 +3548,9 @@ js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFu
if (!dst)
return nullptr;
// Save flags in case we need to undo the early mutations.
const int preservedFlags = fun->flags();
dst->setFunction(fun);
Rooted<LazyScript*> lazy(cx);
if (fun->isInterpretedLazy()) {
@ -3562,6 +3565,7 @@ js::CloneScriptIntoFunction(JSContext* cx, HandleObject enclosingScope, HandleFu
fun->initLazyScript(lazy);
else
fun->setScript(nullptr);
fun->setFlags(preservedFlags);
return nullptr;
}
@ -4023,17 +4027,11 @@ JSScript::argumentsOptimizationFailed(JSContext* cx, HandleScript script)
continue;
AbstractFramePtr frame = i.abstractFramePtr();
if (frame.isFunctionFrame() && frame.script() == script) {
/* We crash on OOM since cleaning up here would be complicated. */
AutoEnterOOMUnsafeRegion oomUnsafe;
ArgumentsObject* argsobj = ArgumentsObject::createExpected(cx, frame);
if (!argsobj) {
/*
* We can't leave stack frames with script->needsArgsObj but no
* arguments object. It is, however, safe to leave frames with
* an arguments object but !script->needsArgsObj.
*/
script->needsArgsObj_ = false;
return false;
}
if (!argsobj)
oomUnsafe.crash("JSScript::argumentsOptimizationFailed");
SetFrameArgumentsObject(cx, frame, script, argsobj);
}
}

Просмотреть файл

@ -1293,6 +1293,23 @@ intrinsic_HostResolveImportedModule(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_GetModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
RootedModuleObject module(cx, &args[0].toObject().as<ModuleObject>());
RootedModuleEnvironmentObject env(cx, module->environment());
args.rval().setUndefined();
if (!env) {
args.rval().setUndefined();
return true;
}
args.rval().setObject(*env);
return true;
}
static bool
intrinsic_CreateModuleEnvironment(JSContext* cx, unsigned argc, Value* vp)
{
@ -1586,7 +1603,8 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("CallModuleMethodIfWrapped",
CallNonGenericSelfhostedMethod<Is<ModuleObject>>, 2, 0),
JS_FN("HostResolveImportedModule", intrinsic_HostResolveImportedModule, 2, 0),
JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 2, 0),
JS_FN("GetModuleEnvironment", intrinsic_GetModuleEnvironment, 1, 0),
JS_FN("CreateModuleEnvironment", intrinsic_CreateModuleEnvironment, 1, 0),
JS_FN("CreateImportBinding", intrinsic_CreateImportBinding, 4, 0),
JS_FN("SetModuleEvaluated", intrinsic_SetModuleEvaluated, 1, 0),
JS_FN("EvaluateModule", intrinsic_EvaluateModule, 1, 0),

Просмотреть файл

@ -734,9 +734,13 @@ JSStructuredCloneWriter::~JSStructuredCloneWriter()
// Free any transferable data left lying around in the buffer
uint64_t* data;
size_t size;
MOZ_ALWAYS_TRUE(extractBuffer(&data, &size));
DiscardTransferables(data, size, callbacks, closure);
js_free(data);
{
AutoEnterOOMUnsafeRegion oomUnsafe;
if (!extractBuffer(&data, &size))
oomUnsafe.crash("Unable to extract clone buffer");
DiscardTransferables(data, size, callbacks, closure);
js_free(data);
}
}
bool

Просмотреть файл

@ -3,5 +3,14 @@
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
<image width='100' height='100' xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAG6SURBVHhe7d3BbcJAGAXhJYXQg32mCV8p2vRAEb4mREoJe/g2GiTf55/hiRu+jTG+P08fxMAXwhHGn4GCYF+FghQEM4DhtJCCYAYwnBZSEMwAhtNCCoIZwHBaSEEwAxhOCykIZgDDaSEFwQxgOC2kIJgBDGfqQh6Px9j3HTtxLZypQZ7P5ziOYy0DGO3UIPf7fWzbhp24Fs7UIGudbtIWBOtSkIJgBjCcFlIQzACG00IKghnAcFpIQTADGE4LKQhmAMNpIQXBDGA4LaQgmAEMp4UUBDOA4bSQgmAGMJwWUhDMAIbTQgqCGcBwWkhBMAMYTgspCGYAw2khBcEMYDgtpCCYAQynhRQEM4DhtJCCYAYwnBZSEMwAhtNCCoIZwHBaSEEwAxhOCykIZgDDaSEFwQxgOC2kIJgBDKeFFAQzgOG0kIJgBjCcFlIQzACG00IKghnAcFrIfw7yfr/H6/XCTlwL5/bBnfY+9d8/47+ua5znuZYFiHZqEOiuZVH6DcHSFaQgmAEMp4UUBDOA4bSQgmAGMJwWUhDMAIbTQgqCGcBwWkhBMAMYTgspCGYAw2khBcEMYDgtBAvyA+wPEw79WuphAAAAAElFTkSuQmCC"/>
<image width='100' height='100'
xlink:href="data:image/png;base64,
iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABmJLR0QA/wD/AP+gvaeTAAAACXBI
WXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3wkbDDIilL5aRAAAAB1pVFh0Q29tbWVudAAAAAAAQ3Jl
YXRlZCB3aXRoIEdJTVBkLmUHAAAA9UlEQVR42u3csRHDIBBFwbPHddADiqmEduhFlSiWelBOSirX
YFsB49lXAMHf4DIeEXGFpqi1Fk8zzFPOGchsAQEiIEAEBIiAABEQIAIiIEAEBIiAAPmgUkosy2LV
H3rd+VitNXrvse+7ZWcASSlFSsmqbggQAQEiIAICRECACAgQAQEiIEAERECACAgQAQEiIEAERECA
CAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAfnHbv3Z+jzP6L1bdRaQdV1j
jGHVWUC2bbOoGwJEQIAIiIAAERAgAgJEQIAIiIAAERAg+qrjOOINBcEbJFN4kugAAAAASUVORK5C
YII="/>
</svg>

До

Ширина:  |  Высота:  |  Размер: 1013 B

После

Ширина:  |  Высота:  |  Размер: 834 B

Просмотреть файл

@ -0,0 +1,11 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" width="600px" height="300px">
<rect x="50" y="50" width="200" height="200" fill="black" />
<rect x="340" y="40" width="220" height="220" fill="grey" />
<rect x="350" y="50" width="200" height="200" fill="white" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 387 B

Просмотреть файл

@ -0,0 +1,30 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<svg xmlns="http://www.w3.org/2000/svg" width="600px" height="300px">
<!-- From https://bugzilla.mozilla.org/show_bug.cgi?id=1203376 -->
<defs>
<!-- the filter lights are intentionally chosen to fill the entire area with
a solid color since we're only testing the extents of the filter region
-->
<filter id="diffuse" x="-50%" y="-50%" width="200%" height="200%">
<!-- gives a black filter region -->
<feDiffuseLighting lighting-color="black">
<feDistantLight />
</feDiffuseLighting>
</filter>
<filter id="specular" x="-50%" y="-50%" width="200%" height="200%">
<!-- gives a white filter region -->
<feSpecularLighting lighting-color="white" specularConstant="100">
<feDistantLight elevation="90"/>
</feSpecularLighting>
</filter>
</defs>
<rect x="100" y="100" width="100" height="100" filter="url(#diffuse)" />
<rect x="340" y="40" width="220" height="220" fill="grey" />
<rect x="400" y="100" width="100" height="100" filter="url(#specular)" />
</svg>

После

Ширина:  |  Высота:  |  Размер: 1.1 KiB

Просмотреть файл

@ -109,10 +109,12 @@ fuzzy(2,500) == feDisplacementMap-colour-01.svg feDisplacementMap-colour-01-ref.
== feTile-large-02.svg feTile-large-02-ref.svg
== feTile-outside-01.svg feTile-outside-01-ref.svg
fuzzy(1,119) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
fuzzy(1,217) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
fuzzy(2,2659) skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.svg
== filter-lighting-region.svg filter-lighting-region-ref.svg
== fePointLight-zoomed-page.svg fePointLight-zoomed-page-ref.svg
== feTurbulence-offset.svg feTurbulence-offset-ref.svg

Просмотреть файл

@ -284,8 +284,6 @@ static void nr_ice_candidate_mark_done(nr_ice_candidate *cand, int state)
* piggybacking on it. Make sure it is marked done too. */
if ((cand->type == RELAYED) && cand->u.relayed.srvflx_candidate) {
nr_ice_candidate *srflx=cand->u.relayed.srvflx_candidate;
/* Calling done_cb can destroy this, make sure it doesn't dangle. */
cand->u.relayed.srvflx_candidate=0;
if (state == NR_ICE_CAND_STATE_INITIALIZED &&
nr_turn_client_get_mapped_address(cand->u.relayed.turn,
&srflx->addr)) {
@ -325,6 +323,8 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp)
case RELAYED:
if (cand->u.relayed.turn_handle)
nr_ice_socket_deregister(cand->isock, cand->u.relayed.turn_handle);
if (cand->u.relayed.srvflx_candidate)
cand->u.relayed.srvflx_candidate->u.srvrflx.relay_candidate=0;
nr_turn_client_ctx_destroy(&cand->u.relayed.turn);
nr_socket_destroy(&cand->u.relayed.turn_sock);
break;
@ -332,6 +332,8 @@ int nr_ice_candidate_destroy(nr_ice_candidate **candp)
case SERVER_REFLEXIVE:
if (cand->u.srvrflx.stun_handle)
nr_ice_socket_deregister(cand->isock, cand->u.srvrflx.stun_handle);
if (cand->u.srvrflx.relay_candidate)
cand->u.srvrflx.relay_candidate->u.relayed.srvflx_candidate=0;
nr_stun_client_ctx_destroy(&cand->u.srvrflx.stun);
break;
default:

Просмотреть файл

@ -76,6 +76,9 @@ struct nr_ice_candidate_ {
struct {
nr_stun_client_ctx *stun;
void *stun_handle;
/* If this is a srflx that is piggybacking on a relay candidate, this is
* a back pointer to that relay candidate. */
nr_ice_candidate *relay_candidate;
} srvrflx;
struct {
nr_turn_client_ctx *turn;

Просмотреть файл

@ -286,7 +286,10 @@ static int nr_ice_component_initialize_udp(struct nr_ice_ctx_ *ctx,nr_ice_compon
isock,turn_sock,RELAYED,0,
&ctx->turn_servers[j].turn_server,component->component_id,&cand))
ABORT(r);
cand->u.relayed.srvflx_candidate=srvflx_cand;
if (srvflx_cand) {
cand->u.relayed.srvflx_candidate=srvflx_cand;
srvflx_cand->u.srvrflx.relay_candidate=cand;
}
cand->u.relayed.server=&ctx->turn_servers[j];
TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
component->candidate_ct++;

Просмотреть файл

@ -21,6 +21,20 @@
#include "nsTraceRefcnt.h"
#endif
#if defined(MOZ_CRASHREPORTER) && defined(MOZILLA_INTERNAL_API) && \
!defined(MOZILLA_EXTERNAL_LINKAGE) && defined(__cplusplus)
# define MOZ_CRASH_CRASHREPORT
namespace CrashReporter {
// This declaration is present here as well as in nsExceptionHandler.h
// nsExceptionHandler.h is not directly included in this file as it includes
// windows.h, which can cause problems when it is imported into some files due
// to the number of macros defined.
// XXX If you change this definition - also change the definition in
// nsExceptionHandler.h
void AnnotateMozCrashReason(const char* aReason);
} // namespace CrashReporter
#endif
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@ -249,7 +263,15 @@ __declspec(noreturn) __inline void MOZ_NoReturn() {}
* corrupted.
*/
#ifndef DEBUG
# define MOZ_CRASH(...) MOZ_REALLY_CRASH()
# ifdef MOZ_CRASH_CRASHREPORT
# define MOZ_CRASH(...) \
do { \
CrashReporter::AnnotateMozCrashReason("MOZ_CRASH(" __VA_ARGS__ ")"); \
MOZ_REALLY_CRASH(); \
} while (0)
# else
# define MOZ_CRASH(...) MOZ_REALLY_CRASH()
# endif
#else
# define MOZ_CRASH(...) \
do { \
@ -509,5 +531,6 @@ struct AssertionConditionType
#endif
#undef MOZ_DUMP_ASSERTION_STACK
#undef MOZ_CRASH_CRASHREPORT
#endif /* mozilla_Assertions_h */

Просмотреть файл

@ -24,7 +24,7 @@ interface nsIVerificationCallback;
* https://wiki.mozilla.org/FirefoxOS/New_security_model/Packaging
*/
[scriptable, uuid(d0a98a69-a215-4cf9-abb3-7a0b9237cd27)]
[scriptable, uuid(cc245638-6a38-4f70-8d77-21c55aabd636)]
interface nsIPackagedAppUtils : nsISupports
{
/**
@ -48,6 +48,12 @@ interface nsIPackagedAppUtils : nsISupports
void checkIntegrity(in ACString aFileName,
in ACString aHashValue,
in nsIVerificationCallback aVerifier);
/**
* The package identifier for signed package. Only available after the
* manifest is verified.
*/
readonly attribute ACString packageIdentifier;
};
/**

Просмотреть файл

@ -422,14 +422,16 @@ nsStandardURL::NormalizeIDN(const nsCSubstring &host, nsCString &result)
}
bool
nsStandardURL::ValidIPv6orHostname(const char *host)
nsStandardURL::ValidIPv6orHostname(const char *host, uint32_t length)
{
if (!host || !*host) {
// Should not be NULL or empty string
if (!host) {
return false;
}
int32_t length = strlen(host);
if (length != strlen(host)) {
// Embedded null
return false;
}
bool openBracket = host[0] == '[';
bool closeBracket = host[length - 1] == ']';
@ -443,8 +445,9 @@ nsStandardURL::ValidIPv6orHostname(const char *host)
return false;
}
if (PL_strchr(host, ':')) {
// Hostnames should not contain a colon
const char *end = host + length;
if (end != net_FindCharInSet(host, end, "\t\n\v\f\r #/:?@[\\]")) {
// % is allowed because we don't do hostname percent decoding yet.
return false;
}
@ -582,6 +585,11 @@ nsStandardURL::BuildNormalizedSpec(const char *spec)
approxLen += encHost.Length();
else
approxLen += mHost.mLen;
if ((useEncHost && !ValidIPv6orHostname(encHost.BeginReading(), encHost.Length())) ||
(!useEncHost && !ValidIPv6orHostname(tempHost.BeginReading(), tempHost.Length()))) {
return NS_ERROR_MALFORMED_URI;
}
}
//
@ -1609,14 +1617,10 @@ nsStandardURL::SetHost(const nsACString &input)
if (strchr(host, ' '))
return NS_ERROR_MALFORMED_URI;
if (!ValidIPv6orHostname(host)) {
return NS_ERROR_MALFORMED_URI;
}
InvalidateCache();
mHostEncoding = eEncoding_ASCII;
int32_t len;
uint32_t len;
nsAutoCString hostBuf;
if (NormalizeIDN(flat, hostBuf)) {
host = hostBuf.get();
@ -1625,6 +1629,10 @@ nsStandardURL::SetHost(const nsACString &input)
else
len = flat.Length();
if (!ValidIPv6orHostname(host, len)) {
return NS_ERROR_MALFORMED_URI;
}
if (mHost.mLen < 0) {
int port_length = 0;
if (mPort != -1) {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше