Merge m-c to fx-team. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-07-27 10:44:08 -04:00
commit 5862b8047c
711 changed files with 10282 additions and 12128 deletions

View File

@ -355,10 +355,12 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
AccessibleWrap* accWrap = [self getGeckoAccessible];
if (accWrap) {
Accessible* acc = accWrap->GetChildAt(i);
return acc ? GetNativeFromGeckoAccessible(acc) : nil;
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
Accessible* child = accWrap->GetChildAt(i);
return child ? GetNativeFromGeckoAccessible(child) : nil;
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
ProxyAccessible* child = proxy->ChildAt(i);
return child ? GetNativeFromProxy(child) : nil;
}
return nil;
@ -849,12 +851,14 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
AccessibleWrap* accWrap = [self getGeckoAccessible];
if (!accWrap)
nsIntRect rect;
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
rect = accWrap->Bounds();
else if (ProxyAccessible* proxy = [self getProxyAccessible])
rect = proxy->Bounds();
else
return nil;
nsIntRect rect = accWrap->Bounds();
NSScreen* mainView = [[NSScreen screens] objectAtIndex:0];
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mainView);
NSPoint p = NSMakePoint(static_cast<CGFloat>(rect.x) / scaleFactor,
@ -869,11 +873,14 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
AccessibleWrap* accWrap = [self getGeckoAccessible];
if (!accWrap)
nsIntRect rect;
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
rect = accWrap->Bounds();
else if (ProxyAccessible* proxy = [self getProxyAccessible])
rect = proxy->Bounds();
else
return nil;
nsIntRect rect = accWrap->Bounds();
CGFloat scaleFactor =
nsCocoaUtils::GetBackingScaleFactor([[NSScreen screens] objectAtIndex:0]);
return [NSValue valueWithSize:NSMakeSize(static_cast<CGFloat>(rect.width) / scaleFactor,

View File

@ -1118,9 +1118,6 @@ pref("services.mobileid.server.uri", "https://msisdn.services.mozilla.com");
pref("dom.mapped_arraybuffer.enabled", true);
#endif
// BroadcastChannel API
pref("dom.broadcastChannel.enabled", true);
// SystemUpdate API
pref("dom.system_update.enabled", true);

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -19,7 +19,7 @@
<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="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>

View File

@ -17,10 +17,10 @@
</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="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -19,7 +19,7 @@
<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="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "ade1ef5249cfab921e00ed67b30f3d03c2e24b5e",
"git_revision": "4e3e21a4ba3f188b45623ee2297f21d0791f8667",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "e09bb83fd01a4f6ab6d569c3cf2d8b099f30df55",
"revision": "995162ffe23e554b4de57f72e6341916e2844e92",
"repo_path": "integration/gaia-central"
}

View File

@ -35,6 +35,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
. "$topsrcdir/b2g/config/mozconfigs/common.override"

View File

@ -34,7 +34,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
# Build simulator xpi and phone tweaks for b2g-desktop
FXOS_SIMULATOR=1

View File

@ -35,6 +35,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
. "$topsrcdir/b2g/config/mozconfigs/common.override"

View File

@ -34,7 +34,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
# Build simulator xpi and phone tweaks for b2g-desktop
FXOS_SIMULATOR=1

View File

@ -32,6 +32,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
. "$topsrcdir/b2g/config/mozconfigs/common.override"

View File

@ -30,7 +30,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
# Build simulator xpi and phone tweaks for b2g-desktop
FXOS_SIMULATOR=1

View File

@ -29,6 +29,6 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
. "$topsrcdir/b2g/config/mozconfigs/common.override"

View File

@ -27,7 +27,7 @@ export CXXFLAGS=-DMOZ_ENABLE_JS_DUMP
GAIADIR=$topsrcdir/gaia
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
# Build simulator xpi and phone tweaks for b2g-desktop
FXOS_SIMULATOR=1

View File

@ -17,10 +17,10 @@
</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="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="07c383a786f188904311a37f6062c2cb84c9b61d">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="ade1ef5249cfab921e00ed67b30f3d03c2e24b5e"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="4e3e21a4ba3f188b45623ee2297f21d0791f8667"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="1b587ca868ee75758959c2470a9c35a21299377f"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="5bb657ada461be666c35f419dbe072ed2ce632fc"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -14,10 +14,10 @@
"unpack": true
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
}
]

View File

@ -14,10 +14,10 @@
"unpack": true
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
}
]

View File

@ -17,10 +17,10 @@
"unpack": true
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
}
]

View File

@ -6,10 +6,10 @@
"filename": "mozmake.exe"
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
},
{

View File

@ -8,4 +8,4 @@ ac_add_options --enable-default-toolkit=cairo-gtk2
ac_add_options --enable-application=b2g/dev
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt

View File

@ -24,7 +24,7 @@ ac_add_options --enable-warnings-as-errors
export MOZ_PACKAGE_JSSHELL=1
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt
. "$topsrcdir/build/mozconfig.common.override"
. "$topsrcdir/build/mozconfig.cache"

View File

@ -10,4 +10,4 @@ MOZ_AUTOMATION_SDK=0
ac_add_options --enable-application=b2g/dev
# Include Firefox OS fonts.
MOZTTDIR=$topsrcdir/moztt
MOZTTDIR=$topsrcdir/moz-tt

View File

@ -14,10 +14,10 @@
"unpack": true
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
}
]

View File

@ -17,10 +17,10 @@
"unpack": true
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
}
]

View File

@ -13,10 +13,10 @@
"unpack": true
},
{
"size": 31057326,
"digest": "b844c3e52be493d2cacafa58c4a924b89c9be8d2dcc2a7c71aed58c253d8035fba4d51df309f73e3c4342a1f3c3898a9a25c4815e2112888d1280f43c41c8e51",
"size": 31078810,
"digest": "2dffe4e5419a0c0c9908dc52b01cc07379a42e2aa8481be7a26bb8750b586b95bbac3fe57e64f5d37b43e206516ea70ad938a2e45858fdcf1e28258e70ae8d8c",
"algorithm": "sha512",
"filename": "moztt.tar.bz2",
"filename": "moz-tt.tar.bz2",
"unpack": true
}
]

View File

@ -644,6 +644,7 @@
@RESPATH@/components/AppsService.manifest
@RESPATH@/components/Push.js
@RESPATH@/components/Push.manifest
@RESPATH@/components/PushClient.js
@RESPATH@/components/PushNotificationService.js
@RESPATH@/components/PushServiceLauncher.js

View File

@ -1,7 +1,5 @@
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
@ -35,18 +33,14 @@ function promiseInitContentBlocklistSvc(aBrowser)
* @returns a Promise that resolves to true after the time has elapsed
*/
function waitForMs(aMs) {
let deferred = Promise.defer();
let startTime = Date.now();
setTimeout(done, aMs);
function done() {
deferred.resolve(true);
}
return deferred.promise;
return new Promise((resolve) => {
setTimeout(done, aMs);
function done() {
resolve(true);
}
});
}
// DOM Promise fails for unknown reasons here, so we're using
// resource://gre/modules/Promise.jsm.
function waitForEvent(subject, eventName, checkFn, useCapture, useUntrusted) {
return new Promise((resolve, reject) => {
subject.addEventListener(eventName, function listener(event) {
@ -84,33 +78,33 @@ function waitForEvent(subject, eventName, checkFn, useCapture, useUntrusted) {
* @rejects if a valid load event is not received within a meaningful interval
*/
function promiseTabLoadEvent(tab, url, eventType="load") {
let deferred = Promise.defer();
info("Wait tab event: " + eventType);
return new Promise((resolve, reject) => {
info("Wait tab event: " + eventType);
function handle(event) {
if (event.originalTarget != tab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank" ||
(url && event.target.location.href != url)) {
info("Skipping spurious '" + eventType + "'' event" +
" for " + event.target.location.href);
return;
function handle(event) {
if (event.originalTarget != tab.linkedBrowser.contentDocument ||
event.target.location.href == "about:blank" ||
(url && event.target.location.href != url)) {
info("Skipping spurious '" + eventType + "'' event" +
" for " + event.target.location.href);
return;
}
clearTimeout(timeout);
tab.linkedBrowser.removeEventListener(eventType, handle, true);
info("Tab event received: " + eventType);
resolve(event);
}
clearTimeout(timeout);
tab.linkedBrowser.removeEventListener(eventType, handle, true);
info("Tab event received: " + eventType);
deferred.resolve(event);
}
let timeout = setTimeout(() => {
tab.linkedBrowser.removeEventListener(eventType, handle, true);
deferred.reject(new Error("Timed out while waiting for a '" + eventType + "'' event"));
}, 30000);
let timeout = setTimeout(() => {
tab.linkedBrowser.removeEventListener(eventType, handle, true);
reject(new Error("Timed out while waiting for a '" + eventType + "'' event"));
}, 30000);
tab.linkedBrowser.addEventListener(eventType, handle, true, true);
if (url) {
tab.linkedBrowser.loadURI(url);
}
return deferred.promise;
tab.linkedBrowser.addEventListener(eventType, handle, true, true);
if (url) {
tab.linkedBrowser.loadURI(url);
}
});
}
function waitForCondition(condition, nextTest, errorMsg, aTries, aWait) {
@ -139,11 +133,11 @@ function waitForCondition(condition, nextTest, errorMsg, aTries, aWait) {
// Waits for a conditional function defined by the caller to return true.
function promiseForCondition(aConditionFn, aMessage, aTries, aWait) {
let deferred = Promise.defer();
waitForCondition(aConditionFn, deferred.resolve,
(aMessage || "Condition didn't pass."),
aTries, aWait);
return deferred.promise;
return new Promise((resolve) => {
waitForCondition(aConditionFn, resolve,
(aMessage || "Condition didn't pass."),
aTries, aWait);
});
}
// Returns the chrome side nsIPluginTag for this plugin
@ -298,17 +292,15 @@ function resetBlocklist() {
// Insure there's a popup notification present. This test does not indicate
// open state. aBrowser can be undefined.
function promisePopupNotification(aName, aBrowser) {
let deferred = Promise.defer();
return new Promise((resolve) => {
waitForCondition(() => PopupNotifications.getNotification(aName, aBrowser),
() => {
ok(!!PopupNotifications.getNotification(aName, aBrowser),
aName + " notification appeared");
waitForCondition(() => PopupNotifications.getNotification(aName, aBrowser),
() => {
ok(!!PopupNotifications.getNotification(aName, aBrowser),
aName + " notification appeared");
deferred.resolve();
}, "timeout waiting for popup notification " + aName);
return deferred.promise;
resolve();
}, "timeout waiting for popup notification " + aName);
});
}
/**
@ -361,9 +353,9 @@ function waitForNotificationBar(notificationID, browser, callback) {
}
function promiseForNotificationBar(notificationID, browser) {
let deferred = Promise.defer();
waitForNotificationBar(notificationID, browser, deferred.resolve);
return deferred.promise;
return new Promise((resolve) => {
waitForNotificationBar(notificationID, browser, resolve);
});
}
/**
@ -386,9 +378,9 @@ function waitForNotificationShown(notification, callback) {
}
function promiseForNotificationShown(notification) {
let deferred = Promise.defer();
waitForNotificationShown(notification, deferred.resolve);
return deferred.promise;
return new Promise((resolve) => {
waitForNotificationShown(notification, resolve);
});
}
/**

View File

@ -558,6 +558,7 @@
@RESPATH@/components/AlarmsManager.manifest
@RESPATH@/components/Push.js
@RESPATH@/components/Push.manifest
@RESPATH@/components/PushClient.js
@RESPATH@/components/PushNotificationService.js
@RESPATH@/components/SlowScriptDebug.manifest

View File

@ -1,6 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
@ -56,7 +57,6 @@ private:
ScopeChecker(Scope scope_) :
scope(scope_) {}
virtual void run(const MatchFinder::MatchResult &Result);
void noteInferred(QualType T, DiagnosticsEngine &Diag);
private:
Scope scope;
};
@ -64,7 +64,6 @@ private:
class NonHeapClassChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
void noteInferred(QualType T, DiagnosticsEngine &Diag);
};
class ArithmeticArgChecker : public MatchFinder::MatchCallback {
@ -97,6 +96,16 @@ private:
virtual void run(const MatchFinder::MatchResult &Result);
};
class NeedsNoVTableTypeChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
};
class NonMemMovableChecker : public MatchFinder::MatchCallback {
public:
virtual void run(const MatchFinder::MatchResult &Result);
};
ScopeChecker stackClassChecker;
ScopeChecker globalClassChecker;
NonHeapClassChecker nonheapClassChecker;
@ -106,6 +115,8 @@ private:
NoAddRefReleaseOnReturnChecker noAddRefReleaseOnReturnChecker;
RefCountedInsideLambdaChecker refCountedInsideLambdaChecker;
ExplicitOperatorBoolChecker explicitOperatorBoolChecker;
NeedsNoVTableTypeChecker needsNoVTableTypeChecker;
NonMemMovableChecker nonMemMovableChecker;
MatchFinder astMatcher;
};
@ -217,6 +228,51 @@ bool isInterestingDeclForImplicitConversion(const Decl *decl) {
}
class CustomTypeAnnotation {
enum ReasonKind {
RK_None,
RK_Direct,
RK_ArrayElement,
RK_BaseClass,
RK_Field,
};
struct AnnotationReason {
QualType Type;
ReasonKind Kind;
const FieldDecl *Field;
bool valid() const { return Kind != RK_None; }
};
typedef DenseMap<void *, AnnotationReason> ReasonCache;
const char *Spelling;
const char *Pretty;
ReasonCache Cache;
public:
CustomTypeAnnotation(const char *Spelling, const char *Pretty)
: Spelling(Spelling), Pretty(Pretty) {};
// Checks if this custom annotation "effectively affects" the given type.
bool hasEffectiveAnnotation(QualType T) {
return directAnnotationReason(T).valid();
}
void dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc);
private:
bool hasLiteralAnnotation(QualType T) const;
AnnotationReason directAnnotationReason(QualType T);
};
static CustomTypeAnnotation StackClass =
CustomTypeAnnotation("moz_stack_class", "stack");
static CustomTypeAnnotation GlobalClass =
CustomTypeAnnotation("moz_global_class", "global");
static CustomTypeAnnotation NonHeapClass =
CustomTypeAnnotation("moz_nonheap_class", "non-heap");
static CustomTypeAnnotation MustUse =
CustomTypeAnnotation("moz_must_use", "must-use");
class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
DiagnosticsEngine &Diag;
const CompilerInstance &CI;
@ -232,29 +288,29 @@ public:
TraverseDecl(ctx.getTranslationUnitDecl());
}
static bool hasCustomAnnotation(const Decl *d, const char *spelling) {
AnnotateAttr *attr = d->getAttr<AnnotateAttr>();
if (!attr)
return false;
static bool hasCustomAnnotation(const Decl *D, const char *Spelling) {
iterator_range<specific_attr_iterator<AnnotateAttr> > Attrs =
D->specific_attrs<AnnotateAttr>();
return attr->getAnnotation() == spelling;
for (AnnotateAttr *Attr : Attrs) {
if (Attr->getAnnotation() == Spelling) {
return true;
}
}
return false;
}
void HandleUnusedExprResult(const Stmt *stmt) {
const Expr* E = dyn_cast_or_null<Expr>(stmt);
if (E) {
// XXX It would be nice if we could use getAsTagDecl,
// but our version of clang is too old.
// (getAsTagDecl would also cover enums etc.)
QualType T = E->getType();
CXXRecordDecl *decl = T->getAsCXXRecordDecl();
if (decl) {
decl = decl->getDefinition();
if (decl && hasCustomAnnotation(decl, "moz_must_use")) {
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "Unused MOZ_MUST_USE value of type %0");
Diag.Report(E->getLocStart(), errorID) << T;
}
if (MustUse.hasEffectiveAnnotation(T)) {
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "Unused value of must-use type %0");
Diag.Report(E->getLocStart(), errorID) << T;
MustUse.dumpAnnotationReason(Diag, T, E->getLocStart());
}
}
}
@ -378,102 +434,6 @@ public:
}
};
/**
* Where classes may be allocated. Regular classes can be allocated anywhere,
* non-heap classes on the stack or as static variables, and stack classes only
* on the stack. Note that stack classes subsumes non-heap classes.
*/
enum ClassAllocationNature {
RegularClass = 0,
NonHeapClass = 1,
StackClass = 2,
GlobalClass = 3
};
/// A cached data of whether classes are stack classes, non-heap classes, or
/// neither.
DenseMap<const CXXRecordDecl *,
std::pair<const Decl *, ClassAllocationNature> > inferredAllocCauses;
ClassAllocationNature getClassAttrs(QualType T);
ClassAllocationNature getClassAttrs(CXXRecordDecl *D) {
// Normalize so that D points to the definition if it exists. If it doesn't,
// then we can't allocate it anyways.
if (!D->hasDefinition())
return RegularClass;
D = D->getDefinition();
// Base class: anyone with this annotation is obviously a stack class
if (MozChecker::hasCustomAnnotation(D, "moz_stack_class"))
return StackClass;
// Base class: anyone with this annotation is obviously a global class
if (MozChecker::hasCustomAnnotation(D, "moz_global_class"))
return GlobalClass;
// See if we cached the result.
DenseMap<const CXXRecordDecl *,
std::pair<const Decl *, ClassAllocationNature> >::iterator it =
inferredAllocCauses.find(D);
if (it != inferredAllocCauses.end()) {
return it->second.second;
}
// Continue looking, we might be a stack class yet. Even if we're a nonheap
// class, it might be possible that we've inferred to be a stack class.
ClassAllocationNature type = RegularClass;
if (MozChecker::hasCustomAnnotation(D, "moz_nonheap_class")) {
type = NonHeapClass;
}
inferredAllocCauses.insert(std::make_pair(D,
std::make_pair((const Decl *)0, type)));
// Look through all base cases to figure out if the parent is a stack class or
// a non-heap class. Since we might later infer to also be a stack class, keep
// going.
for (CXXRecordDecl::base_class_iterator base = D->bases_begin(),
e = D->bases_end(); base != e; ++base) {
ClassAllocationNature super = getClassAttrs(base->getType());
if (super == StackClass) {
inferredAllocCauses[D] = std::make_pair(
base->getType()->getAsCXXRecordDecl(), StackClass);
return StackClass;
} else if (super == GlobalClass) {
inferredAllocCauses[D] = std::make_pair(
base->getType()->getAsCXXRecordDecl(), GlobalClass);
return GlobalClass;
} else if (super == NonHeapClass) {
inferredAllocCauses[D] = std::make_pair(
base->getType()->getAsCXXRecordDecl(), NonHeapClass);
type = NonHeapClass;
}
}
// Maybe it has a member which is a stack class.
for (RecordDecl::field_iterator field = D->field_begin(), e = D->field_end();
field != e; ++field) {
ClassAllocationNature fieldType = getClassAttrs(field->getType());
if (fieldType == StackClass) {
inferredAllocCauses[D] = std::make_pair(*field, StackClass);
return StackClass;
} else if (fieldType == GlobalClass) {
inferredAllocCauses[D] = std::make_pair(*field, GlobalClass);
return GlobalClass;
} else if (fieldType == NonHeapClass) {
inferredAllocCauses[D] = std::make_pair(*field, NonHeapClass);
type = NonHeapClass;
}
}
return type;
}
ClassAllocationNature getClassAttrs(QualType T) {
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
return clazz ? getClassAttrs(clazz) : RegularClass;
}
/// A cached data of whether classes are refcounted or not.
typedef DenseMap<const CXXRecordDecl *,
std::pair<const Decl *, bool> > RefCountedMap;
@ -527,7 +487,88 @@ bool isClassRefCounted(QualType T) {
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
return clazz ? isClassRefCounted(clazz) : RegularClass;
return clazz ? isClassRefCounted(clazz) : false;
}
/// A cached data of whether classes are memmovable, and if not, what declaration
/// makes them non-movable
typedef DenseMap<const CXXRecordDecl *, const CXXRecordDecl *> InferredMovability;
InferredMovability inferredMovability;
bool isClassNonMemMovable(QualType T);
const CXXRecordDecl* isClassNonMemMovableWorker(QualType T);
const CXXRecordDecl* isClassNonMemMovableWorker(const CXXRecordDecl *D) {
// If we have a definition, then we want to standardize our reference to point
// to the definition node. If we don't have a definition, that means that either
// we only have a forward declaration of the type in our file, or we are being
// passed a template argument which is not used, and thus never instantiated by
// clang.
// As the argument isn't used, we can't memmove it (as we don't know it's size),
// which means not reporting an error is OK.
if (!D->hasDefinition()) {
return 0;
}
D = D->getDefinition();
// Are we explicitly marked as non-memmovable class?
if (MozChecker::hasCustomAnnotation(D, "moz_non_memmovable")) {
return D;
}
// Look through all base cases to figure out if the parent is a non-memmovable class.
for (CXXRecordDecl::base_class_const_iterator base = D->bases_begin();
base != D->bases_end(); ++base) {
const CXXRecordDecl *result = isClassNonMemMovableWorker(base->getType());
if (result) {
return result;
}
}
// Look through all members to figure out if a member is a non-memmovable class.
for (RecordDecl::field_iterator field = D->field_begin(), e = D->field_end();
field != e; ++field) {
const CXXRecordDecl *result = isClassNonMemMovableWorker(field->getType());
if (result) {
return result;
}
}
return 0;
}
const CXXRecordDecl* isClassNonMemMovableWorker(QualType T) {
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
const CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
return clazz ? isClassNonMemMovableWorker(clazz) : 0;
}
bool isClassNonMemMovable(const CXXRecordDecl *D) {
InferredMovability::iterator it =
inferredMovability.find(D);
if (it != inferredMovability.end())
return !!it->second;
const CXXRecordDecl *result = isClassNonMemMovableWorker(D);
inferredMovability.insert(std::make_pair(D, result));
return !!result;
}
bool isClassNonMemMovable(QualType T) {
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
const CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
return clazz ? isClassNonMemMovable(clazz) : false;
}
const CXXRecordDecl* findWhyClassIsNonMemMovable(QualType T) {
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
InferredMovability::iterator it =
inferredMovability.find(clazz);
assert(it != inferredMovability.end());
return it->second;
}
template<class T>
@ -540,6 +581,13 @@ bool IsInSystemHeader(const ASTContext &AC, const T &D) {
return SourceManager.isInSystemHeader(ExpansionLoc);
}
bool typeHasVTable(QualType T) {
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
CXXRecordDecl* offender = T->getAsCXXRecordDecl();
return offender && offender->hasDefinition() && offender->isDynamicClass();
}
}
namespace clang {
@ -548,19 +596,19 @@ namespace ast_matchers {
/// This matcher will match any class with the stack class assertion or an
/// array of such classes.
AST_MATCHER(QualType, stackClassAggregate) {
return getClassAttrs(Node) == StackClass;
return StackClass.hasEffectiveAnnotation(Node);
}
/// This matcher will match any class with the global class assertion or an
/// array of such classes.
AST_MATCHER(QualType, globalClassAggregate) {
return getClassAttrs(Node) == GlobalClass;
return GlobalClass.hasEffectiveAnnotation(Node);
}
/// This matcher will match any class with the stack class assertion or an
/// array of such classes.
AST_MATCHER(QualType, nonheapClassAggregate) {
return getClassAttrs(Node) == NonHeapClass;
return NonHeapClass.hasEffectiveAnnotation(Node);
}
/// This matcher will match any function declaration that is declared as a heap
@ -694,11 +742,126 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
#endif
AST_MATCHER(QualType, hasVTable) {
return typeHasVTable(Node);
}
AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) {
return MozChecker::hasCustomAnnotation(&Node, "moz_needs_no_vtable_type");
}
/// This matcher will select classes which are non-memmovable
AST_MATCHER(QualType, isNonMemMovable) {
return isClassNonMemMovable(Node);
}
/// This matcher will select classes which require a memmovable template arg
AST_MATCHER(CXXRecordDecl, needsMemMovable) {
return MozChecker::hasCustomAnnotation(&Node, "moz_needs_memmovable_type");
}
}
}
namespace {
void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc) {
unsigned InheritsID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "%1 is a %0 type because it inherits from a %0 type %2");
unsigned MemberID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "%1 is a %0 type because member %2 is a %0 type %3");
unsigned ArrayID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "%1 is a %0 type because it is an array of %0 type %2");
unsigned TemplID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "%1 is a %0 type because it has a template argument %0 type %2");
AnnotationReason Reason = directAnnotationReason(T);
for (;;) {
switch (Reason.Kind) {
case RK_ArrayElement:
Diag.Report(Loc, ArrayID)
<< Pretty << T << Reason.Type;
break;
case RK_BaseClass:
{
const CXXRecordDecl *Decl = T->getAsCXXRecordDecl();
assert(Decl && "This type should be a C++ class");
Diag.Report(Decl->getLocation(), InheritsID)
<< Pretty << T << Reason.Type;
break;
}
case RK_Field:
Diag.Report(Reason.Field->getLocation(), MemberID)
<< Pretty << T << Reason.Field << Reason.Type;
break;
default:
return;
}
T = Reason.Type;
Reason = directAnnotationReason(T);
}
}
bool CustomTypeAnnotation::hasLiteralAnnotation(QualType T) const {
if (const TagDecl *D = T->getAsTagDecl()) {
return MozChecker::hasCustomAnnotation(D, Spelling);
}
return false;
}
CustomTypeAnnotation::AnnotationReason CustomTypeAnnotation::directAnnotationReason(QualType T) {
if (hasLiteralAnnotation(T)) {
AnnotationReason Reason = { T, RK_Direct, nullptr };
return Reason;
}
// Check if we have a cached answer
void *Key = T.getAsOpaquePtr();
ReasonCache::iterator Cached = Cache.find(T.getAsOpaquePtr());
if (Cached != Cache.end()) {
return Cached->second;
}
// Check if we have a type which we can recurse into
if (const ArrayType *Array = T->getAsArrayTypeUnsafe()) {
if (hasEffectiveAnnotation(Array->getElementType())) {
AnnotationReason Reason = { Array->getElementType(), RK_ArrayElement, nullptr };
Cache[Key] = Reason;
return Reason;
}
}
// Recurse into base classes
if (const CXXRecordDecl *Decl = T->getAsCXXRecordDecl()) {
if (Decl->hasDefinition()) {
Decl = Decl->getDefinition();
for (const CXXBaseSpecifier &Base : Decl->bases()) {
if (hasEffectiveAnnotation(Base.getType())) {
AnnotationReason Reason = { Base.getType(), RK_BaseClass, nullptr };
Cache[Key] = Reason;
return Reason;
}
}
// Recurse into members
for (const FieldDecl *Field : Decl->fields()) {
if (hasEffectiveAnnotation(Field->getType())) {
AnnotationReason Reason = { Field->getType(), RK_Field, Field };
Cache[Key] = Reason;
return Reason;
}
}
}
}
AnnotationReason Reason = { QualType(), RK_None, nullptr };
Cache[Key] = Reason;
return Reason;
}
bool isPlacementNew(const CXXNewExpr *expr) {
// Regular new expressions aren't placement new
if (expr->getNumPlacementArgs() == 0)
@ -816,6 +979,18 @@ DiagnosticsMatcher::DiagnosticsMatcher()
astMatcher.addMatcher(methodDecl(anyOf(hasName("operator bool"),
hasName("operator _Bool"))).bind("node"),
&explicitOperatorBoolChecker);
astMatcher.addMatcher(classTemplateSpecializationDecl(
allOf(hasAnyTemplateArgument(refersToType(hasVTable())),
hasNeedsNoVTableTypeAttr())).bind("node"),
&needsNoVTableTypeChecker);
// Handle non-mem-movable template specializations
astMatcher.addMatcher(classTemplateSpecializationDecl(
allOf(needsMemMovable(),
hasAnyTemplateArgument(refersToType(isNonMemMovable())))
).bind("specialization"),
&nonMemMovableChecker);
}
void DiagnosticsMatcher::ScopeChecker::run(
@ -825,7 +1000,9 @@ void DiagnosticsMatcher::ScopeChecker::run(
DiagnosticIDs::Error, "variable of type %0 only valid on the stack");
unsigned globalID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "variable of type %0 only valid as global");
unsigned errorID = (scope == eGlobal) ? globalID : stackID;
SourceLocation Loc;
QualType T;
if (const VarDecl *d = Result.Nodes.getNodeAs<VarDecl>("node")) {
if (scope == eLocal) {
// Ignore the match if it's a local variable.
@ -840,56 +1017,29 @@ void DiagnosticsMatcher::ScopeChecker::run(
return;
}
Diag.Report(d->getLocation(), errorID) << d->getType();
noteInferred(d->getType(), Diag);
Loc = d->getLocation();
T = d->getType();
} else if (const CXXNewExpr *expr =
Result.Nodes.getNodeAs<CXXNewExpr>("node")) {
// If it's placement new, then this match doesn't count.
if (scope == eLocal && isPlacementNew(expr))
return;
Diag.Report(expr->getStartLoc(), errorID) << expr->getAllocatedType();
noteInferred(expr->getAllocatedType(), Diag);
Loc = expr->getStartLoc();
T = expr->getAllocatedType();
} else if (const CallExpr *expr =
Result.Nodes.getNodeAs<CallExpr>("node")) {
QualType badType = GetCallReturnType(expr)->getPointeeType();
Diag.Report(expr->getLocStart(), errorID) << badType;
noteInferred(badType, Diag);
}
}
void DiagnosticsMatcher::ScopeChecker::noteInferred(QualType T,
DiagnosticsEngine &Diag) {
unsigned inheritsID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note,
"%0 is a %2 class because it inherits from a %2 class %1");
unsigned memberID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note,
"%0 is a %3 class because member %1 is a %3 class %2");
const char* attribute = (scope == eGlobal) ?
"moz_global_class" : "moz_stack_class";
const char* type = (scope == eGlobal) ?
"global" : "stack";
// Find the CXXRecordDecl that is the local/global class of interest
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
// Direct result, we're done.
if (MozChecker::hasCustomAnnotation(clazz, attribute))
return;
const Decl *cause = inferredAllocCauses[clazz].first;
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(cause)) {
Diag.Report(clazz->getLocation(), inheritsID) <<
T << CRD->getDeclName() << type;
} else if (const FieldDecl *FD = dyn_cast<FieldDecl>(cause)) {
Diag.Report(FD->getLocation(), memberID) <<
T << FD << FD->getType() << type;
Loc = expr->getLocStart();
T = GetCallReturnType(expr)->getPointeeType();
}
// Recursively follow this back.
noteInferred(cast<ValueDecl>(cause)->getType(), Diag);
if (scope == eLocal) {
Diag.Report(Loc, stackID) << T;
StackClass.dumpAnnotationReason(Diag, T, Loc);
} else if (scope == eGlobal) {
Diag.Report(Loc, globalID) << T;
GlobalClass.dumpAnnotationReason(Diag, T, Loc);
}
}
void DiagnosticsMatcher::NonHeapClassChecker::run(
@ -897,46 +1047,22 @@ void DiagnosticsMatcher::NonHeapClassChecker::run(
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned stackID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "variable of type %0 is not valid on the heap");
SourceLocation Loc;
QualType T;
if (const CXXNewExpr *expr = Result.Nodes.getNodeAs<CXXNewExpr>("node")) {
// If it's placement new, then this match doesn't count.
if (isPlacementNew(expr))
return;
Diag.Report(expr->getStartLoc(), stackID) << expr->getAllocatedType();
noteInferred(expr->getAllocatedType(), Diag);
Loc = expr->getLocStart();
T = expr->getAllocatedType();
} else if (const CallExpr *expr = Result.Nodes.getNodeAs<CallExpr>("node")) {
QualType badType = GetCallReturnType(expr)->getPointeeType();
Diag.Report(expr->getLocStart(), stackID) << badType;
noteInferred(badType, Diag);
Loc = expr->getLocStart();
T = GetCallReturnType(expr)->getPointeeType();
}
}
void DiagnosticsMatcher::NonHeapClassChecker::noteInferred(QualType T,
DiagnosticsEngine &Diag) {
unsigned inheritsID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note,
"%0 is a non-heap class because it inherits from a non-heap class %1");
unsigned memberID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note,
"%0 is a non-heap class because member %1 is a non-heap class %2");
// Find the CXXRecordDecl that is the stack class of interest
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
T = arrTy->getElementType();
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
// Direct result, we're done.
if (MozChecker::hasCustomAnnotation(clazz, "moz_nonheap_class"))
return;
const Decl *cause = inferredAllocCauses[clazz].first;
if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(cause)) {
Diag.Report(clazz->getLocation(), inheritsID) << T << CRD->getDeclName();
} else if (const FieldDecl *FD = dyn_cast<FieldDecl>(cause)) {
Diag.Report(FD->getLocation(), memberID) << T << FD << FD->getType();
}
// Recursively follow this back.
noteInferred(cast<ValueDecl>(cause)->getType(), Diag);
Diag.Report(Loc, stackID) << T;
NonHeapClass.dumpAnnotationReason(Diag, T, Loc);
}
void DiagnosticsMatcher::ArithmeticArgChecker::run(
@ -1047,6 +1173,72 @@ void DiagnosticsMatcher::ExplicitOperatorBoolChecker::run(
}
}
void DiagnosticsMatcher::NeedsNoVTableTypeChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "%0 cannot be instantiated because %1 has a VTable");
unsigned noteID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "bad instantiation of %0 requested here");
const ClassTemplateSpecializationDecl *specialization =
Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("node");
// Get the offending template argument
QualType offender;
const TemplateArgumentList &args =
specialization->getTemplateInstantiationArgs();
for (unsigned i = 0; i < args.size(); ++i) {
offender = args[i].getAsType();
if (typeHasVTable(offender)) {
break;
}
}
Diag.Report(specialization->getLocStart(), errorID) << specialization << offender;
Diag.Report(specialization->getPointOfInstantiation(), noteID) << specialization;
}
void DiagnosticsMatcher::NonMemMovableChecker::run(
const MatchFinder::MatchResult &Result) {
DiagnosticsEngine &Diag = Result.Context->getDiagnostics();
unsigned errorID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Error, "Cannot instantiate %0 with non-memmovable template argument %1");
unsigned note1ID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "instantiation of %0 requested here");
unsigned note2ID = Diag.getDiagnosticIDs()->getCustomDiagID(
DiagnosticIDs::Note, "%0 is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on %1");
unsigned note3ID = Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Note, "%0");
// Get the specialization
const ClassTemplateSpecializationDecl *specialization =
Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("specialization");
SourceLocation requestLoc = specialization->getPointOfInstantiation();
const CXXRecordDecl *templ =
specialization->getSpecializedTemplate()->getTemplatedDecl();
// Report an error for every template argument which is non-memmovable
const TemplateArgumentList &args =
specialization->getTemplateInstantiationArgs();
for (unsigned i = 0; i < args.size(); ++i) {
QualType argType = args[i].getAsType();
if (isClassNonMemMovable(args[i].getAsType())) {
const CXXRecordDecl *reason = findWhyClassIsNonMemMovable(argType);
Diag.Report(specialization->getLocation(), errorID)
<< specialization << argType;
// XXX It would be really nice if we could get the instantiation stack information
// from Sema such that we could print a full template instantiation stack, however,
// it seems as though that information is thrown out by the time we get here so we
// can only report one level of template specialization (which in many cases won't
// be useful)
Diag.Report(requestLoc, note1ID)
<< specialization;
Diag.Report(reason->getLocation(), note2ID)
<< argType << reason;
}
}
}
class MozCheckAction : public PluginASTAction {
public:
ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, StringRef fileName) override {

View File

@ -16,9 +16,9 @@ void gobble(void *) { }
void misuseGlobalClass(int len) {
Global notValid; // expected-error {{variable of type 'Global' only valid as global}}
Global alsoNotValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}}
Global alsoNotValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} expected-note {{'Global [2]' is a global type because it is an array of global type 'Global'}}
static Global valid; // expected-error {{variable of type 'Global' only valid as global}}
static Global alsoValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}}
static Global alsoValid[2]; // expected-error {{variable of type 'Global [2]' only valid as global}} expected-note {{'Global [2]' is a global type because it is an array of global type 'Global'}}
gobble(&valid);
gobble(&notValid);
@ -35,7 +35,7 @@ void misuseGlobalClass(int len) {
Global valid;
struct RandomClass {
Global nonstaticMember; // expected-note {{'RandomClass' is a global class because member 'nonstaticMember' is a global class 'Global'}}
Global nonstaticMember; // expected-note {{'RandomClass' is a global type because member 'nonstaticMember' is a global type 'Global'}}
static Global staticMember;
};
struct MOZ_GLOBAL_CLASS RandomGlobalClass {
@ -43,7 +43,7 @@ struct MOZ_GLOBAL_CLASS RandomGlobalClass {
static Global staticMember;
};
struct BadInherit : Global {}; // expected-note {{'BadInherit' is a global class because it inherits from a global class 'Global'}}
struct BadInherit : Global {}; // expected-note {{'BadInherit' is a global type because it inherits from a global type 'Global'}}
struct MOZ_GLOBAL_CLASS GoodInherit : Global {};
void misuseGlobalClassEvenMore(int len) {

View File

@ -0,0 +1,17 @@
#define MOZ_MUST_USE __attribute__((annotate("moz_must_use")))
#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
class MOZ_MUST_USE MOZ_STACK_CLASS TestClass {};
TestClass foo; // expected-error {{variable of type 'TestClass' only valid on the stack}}
TestClass f()
{
TestClass bar;
return bar;
}
void g()
{
f(); // expected-error {{Unused value of must-use type 'TestClass'}}
}

View File

@ -20,42 +20,42 @@ void use(MayUse&&);
void use(bool);
void foo() {
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMustUsePointer();
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMayUse();
producesMayUsePointer();
producesMayUseRef();
{
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMustUsePointer();
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMayUse();
producesMayUsePointer();
producesMayUseRef();
}
if (true) {
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMustUsePointer();
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMayUse();
producesMayUsePointer();
producesMayUseRef();
} else {
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMustUsePointer();
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMayUse();
producesMayUsePointer();
producesMayUseRef();
}
if(true) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
else producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
if(true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
else producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
if(true) producesMustUsePointer();
else producesMustUsePointer();
if(true) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
else producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
if(true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
else producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
if(true) producesMayUse();
else producesMayUse();
if(true) producesMayUsePointer();
@ -63,18 +63,18 @@ void foo() {
if(true) producesMayUseRef();
else producesMayUseRef();
while (true) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
while (true) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
while (true) producesMustUsePointer();
while (true) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
while (true) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
while (true) producesMayUse();
while (true) producesMayUsePointer();
while (true) producesMayUseRef();
do producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
do producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
while (true);
do producesMustUsePointer();
while (true);
do producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
do producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
while (true);
do producesMayUse();
while (true);
@ -83,48 +83,48 @@ void foo() {
do producesMayUseRef();
while (true);
for (;;) producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
for (;;) producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
for (;;) producesMustUsePointer();
for (;;) producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
for (;;) producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
for (;;) producesMayUse();
for (;;) producesMayUsePointer();
for (;;) producesMayUseRef();
for (producesMustUse();;); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
for (producesMustUse();;); // expected-error {{Unused value of must-use type 'MustUse'}}
for (producesMustUsePointer();;);
for (producesMustUseRef();;); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
for (producesMustUseRef();;); // expected-error {{Unused value of must-use type 'MustUse'}}
for (producesMayUse();;);
for (producesMayUsePointer();;);
for (producesMayUseRef();;);
for (;;producesMustUse()); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
for (;;producesMustUse()); // expected-error {{Unused value of must-use type 'MustUse'}}
for (;;producesMustUsePointer());
for (;;producesMustUseRef()); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
for (;;producesMustUseRef()); // expected-error {{Unused value of must-use type 'MustUse'}}
for (;;producesMayUse());
for (;;producesMayUsePointer());
for (;;producesMayUseRef());
use((producesMustUse(), false)); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
use((producesMustUse(), false)); // expected-error {{Unused value of must-use type 'MustUse'}}
use((producesMustUsePointer(), false));
use((producesMustUseRef(), false)); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
use((producesMustUseRef(), false)); // expected-error {{Unused value of must-use type 'MustUse'}}
use((producesMayUse(), false));
use((producesMayUsePointer(), false));
use((producesMayUseRef(), false));
switch (1) {
case 1:
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMustUsePointer();
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMayUse();
producesMayUsePointer();
producesMayUseRef();
case 2:
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
case 3:
producesMustUsePointer();
case 4:
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
case 5:
producesMayUse();
case 6:
@ -132,9 +132,9 @@ void foo() {
case 7:
producesMayUseRef();
default:
producesMustUse(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUse(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMustUsePointer();
producesMustUseRef(); // expected-error {{Unused MOZ_MUST_USE value of type 'MustUse'}}
producesMustUseRef(); // expected-error {{Unused value of must-use type 'MustUse'}}
producesMayUse();
producesMayUsePointer();
producesMayUseRef();

View File

@ -0,0 +1,94 @@
#define MOZ_NEEDS_NO_VTABLE_TYPE __attribute__((annotate("moz_needs_no_vtable_type")))
template <class T>
struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer { // expected-error {{'PickyConsumer<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer<G>' cannot be instantiated because 'G' has a VTable}}
T *m;
};
template <class T>
struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_A { // expected-error {{'PickyConsumer_A<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_A<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_A<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_A<G>' cannot be instantiated because 'G' has a VTable}}
T *m;
};
template <class T>
struct PickyConsumerWrapper {
PickyConsumer_A<T> m; // expected-note {{bad instantiation of 'PickyConsumer_A<B>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<E>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<F>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_A<G>' requested here}}
};
template <class T>
struct MOZ_NEEDS_NO_VTABLE_TYPE PickyConsumer_B { // expected-error {{'PickyConsumer_B<B>' cannot be instantiated because 'B' has a VTable}} expected-error {{'PickyConsumer_B<E>' cannot be instantiated because 'E' has a VTable}} expected-error {{'PickyConsumer_B<F>' cannot be instantiated because 'F' has a VTable}} expected-error {{'PickyConsumer_B<G>' cannot be instantiated because 'G' has a VTable}}
T *m;
};
template <class T>
struct PickyConsumerSubclass : PickyConsumer_B<T> {}; // expected-note {{bad instantiation of 'PickyConsumer_B<B>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<E>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<F>' requested here}} expected-note {{bad instantiation of 'PickyConsumer_B<G>' requested here}}
template <class T>
struct NonPickyConsumer {
T *m;
};
struct A {};
struct B : virtual A {};
struct C : A {};
struct D {
void d();
};
struct E {
virtual void e();
};
struct F : E {
virtual void e() final;
};
struct G {
virtual void e() = 0;
};
void f() {
{
PickyConsumer<A> a1;
PickyConsumerWrapper<A> a2;
PickyConsumerSubclass<A> a3;
NonPickyConsumer<A> a4;
}
{
PickyConsumer<B> a1; // expected-note {{bad instantiation of 'PickyConsumer<B>' requested here}}
PickyConsumerWrapper<B> a2;
PickyConsumerSubclass<B> a3;
NonPickyConsumer<B> a4;
}
{
PickyConsumer<C> a1;
PickyConsumerWrapper<C> a2;
PickyConsumerSubclass<C> a3;
NonPickyConsumer<C> a4;
}
{
PickyConsumer<D> a1;
PickyConsumerWrapper<D> a2;
PickyConsumerSubclass<D> a3;
NonPickyConsumer<D> a4;
}
{
PickyConsumer<E> a1; // expected-note {{bad instantiation of 'PickyConsumer<E>' requested here}}
PickyConsumerWrapper<E> a2;
PickyConsumerSubclass<E> a3;
NonPickyConsumer<E> a4;
}
{
PickyConsumer<F> a1; // expected-note {{bad instantiation of 'PickyConsumer<F>' requested here}}
PickyConsumerWrapper<F> a2;
PickyConsumerSubclass<F> a3;
NonPickyConsumer<F> a4;
}
{
PickyConsumer<G> a1; // expected-note {{bad instantiation of 'PickyConsumer<G>' requested here}}
PickyConsumerWrapper<G> a2;
PickyConsumerSubclass<G> a3;
NonPickyConsumer<G> a4;
}
}

View File

@ -36,7 +36,7 @@ void misuseNonHeapClass(int len) {
NonHeap validStatic;
struct RandomClass {
NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap class because member 'nonstaticMember' is a non-heap class 'NonHeap'}}
NonHeap nonstaticMember; // expected-note {{'RandomClass' is a non-heap type because member 'nonstaticMember' is a non-heap type 'NonHeap'}}
static NonHeap staticMember;
};
struct MOZ_NONHEAP_CLASS RandomNonHeapClass {
@ -44,7 +44,7 @@ struct MOZ_NONHEAP_CLASS RandomNonHeapClass {
static NonHeap staticMember;
};
struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap class because it inherits from a non-heap class 'NonHeap'}}
struct BadInherit : NonHeap {}; // expected-note {{'BadInherit' is a non-heap type because it inherits from a non-heap type 'NonHeap'}}
struct MOZ_NONHEAP_CLASS GoodInherit : NonHeap {};
void useStuffWrongly() {
@ -52,11 +52,11 @@ void useStuffWrongly() {
gobble(new RandomClass); // expected-error {{variable of type 'RandomClass' is not valid on the heap}}
}
// Stack class overrides non-heap classes.
// Stack class overrides non-heap typees.
struct MOZ_STACK_CLASS StackClass {};
struct MOZ_NONHEAP_CLASS InferredStackClass : GoodInherit {
NonHeap nonstaticMember;
StackClass stackClass; // expected-note {{'InferredStackClass' is a stack class because member 'stackClass' is a stack class 'StackClass'}}
StackClass stackClass; // expected-note {{'InferredStackClass' is a stack type because member 'stackClass' is a stack type 'StackClass'}}
};
InferredStackClass global; // expected-error {{variable of type 'InferredStackClass' only valid on the stack}}

View File

@ -0,0 +1,812 @@
#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
/*
These are a bunch of structs with variable levels of memmovability.
They will be used as template parameters to the various NeedyTemplates
*/
struct MOZ_NON_MEMMOVABLE NonMovable {}; // expected-note-re + {{'{{.*}}' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'NonMovable'}}
struct Movable {};
// Subclasses
struct S_NonMovable : NonMovable {};
struct S_Movable : Movable {};
// Members
struct W_NonMovable {
NonMovable m;
};
struct W_Movable {
Movable m;
};
// Wrapped Subclasses
struct WS_NonMovable {
S_NonMovable m;
};
struct WS_Movable {
S_Movable m;
};
// Combinations of the above
struct SW_NonMovable : W_NonMovable {};
struct SW_Movable : W_Movable {};
struct SWS_NonMovable : WS_NonMovable {};
struct SWS_Movable : WS_Movable {};
// Basic templated wrapper
template <class T>
struct Template_Inline {
T m;
};
template <class T>
struct Template_Ref {
T* m;
};
template <class T>
struct Template_Unused {};
template <class T>
struct MOZ_NON_MEMMOVABLE Template_NonMovable {}; // expected-note-re + {{'{{.*}}' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'Template_NonMovable<{{.*}}>'}}
/*
These tests take the following form:
DECLARATIONS => Declarations of the templates which are either marked with MOZ_NEEDS_MEMMOVABLE_TYPE
or which instantiate a MOZ_NEEDS_MEMMOVABLE_TYPE through some mechanism.
BAD N => Instantiations of the wrapper template with each of the non-memmovable types.
The prefix S_ means subclass, W_ means wrapped. Each of these rows should produce an error
on the NeedyTemplate in question, and a note at the instantiation location of that template.
Unfortunately, on every case more complicated than bad1, the instantiation location is
within another template. Thus, the notes are expected on the template in question which
actually instantiates the MOZ_NEEDS_MEMMOVABLE_TYPE template.
GOOD N => Instantiations of the wrapper template with each of the memmovable types.
This is meant as a sanity check to ensure that we don't reject valid instantiations of
templates.
Note 1: Each set uses it's own types to ensure that they don't re-use each-other's template specializations.
If they did, then some of the error messages would not be emitted (as error messages are emitted for template
specializations, rather than for variable declarations)
Note 2: Every instance of NeedyTemplate contains a member of type T. This is to ensure that T is actually
instantiated (if T is a template) by clang. If T isn't instantiated, then we can't actually tell if it is
NON_MEMMOVABLE. (This is OK in practice, as you cannot memmove a type which you don't know the size of).
Note 3: There are a set of tests for specializations of NeedyTemplate at the bottom. For each set of tests,
these tests contribute two expected errors to the templates.
*/
//
// 1 - Unwrapped MOZ_NEEDS_MEMMOVABLE_TYPE
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate1 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate1<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
void bad1() {
NeedyTemplate1<NonMovable> a1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<S_NonMovable> a2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<W_NonMovable> a3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<WS_NonMovable> a4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<SW_NonMovable> a5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<SWS_NonMovable> a6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_Inline<NonMovable> > b1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_Inline<S_NonMovable> > b2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_Inline<W_NonMovable> > b3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_Inline<WS_NonMovable> > b4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_Inline<SW_NonMovable> > b5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_Inline<SWS_NonMovable> > b6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<NonMovable> > c1; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<S_NonMovable> > c2; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<W_NonMovable> > c3; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<WS_NonMovable> > c4; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<SW_NonMovable> > c5; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<SWS_NonMovable> > c6; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<Movable> > c7; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<S_Movable> > c8; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<W_Movable> > c9; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<WS_Movable> > c10; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<SW_Movable> > c11; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
NeedyTemplate1<Template_NonMovable<SWS_Movable> > c12; // expected-note-re {{instantiation of 'NeedyTemplate1<{{.*}}>' requested here}}
}
void good1() {
NeedyTemplate1<Movable> a1;
NeedyTemplate1<S_Movable> a2;
NeedyTemplate1<W_Movable> a3;
NeedyTemplate1<WS_Movable> a4;
NeedyTemplate1<SW_Movable> a5;
NeedyTemplate1<SWS_Movable> a6;
NeedyTemplate1<Template_Inline<Movable> > b1;
NeedyTemplate1<Template_Inline<S_Movable> > b2;
NeedyTemplate1<Template_Inline<W_Movable> > b3;
NeedyTemplate1<Template_Inline<WS_Movable> > b4;
NeedyTemplate1<Template_Inline<SW_Movable> > b5;
NeedyTemplate1<Template_Inline<SWS_Movable> > b6;
NeedyTemplate1<Template_Unused<Movable> > c1;
NeedyTemplate1<Template_Unused<S_Movable> > c2;
NeedyTemplate1<Template_Unused<W_Movable> > c3;
NeedyTemplate1<Template_Unused<WS_Movable> > c4;
NeedyTemplate1<Template_Unused<SW_Movable> > c5;
NeedyTemplate1<Template_Unused<SWS_Movable> > c6;
NeedyTemplate1<Template_Unused<NonMovable> > c7;
NeedyTemplate1<Template_Unused<S_NonMovable> > c8;
NeedyTemplate1<Template_Unused<W_NonMovable> > c9;
NeedyTemplate1<Template_Unused<WS_NonMovable> > c10;
NeedyTemplate1<Template_Unused<SW_NonMovable> > c11;
NeedyTemplate1<Template_Unused<SWS_NonMovable> > c12;
NeedyTemplate1<Template_Ref<Movable> > d1;
NeedyTemplate1<Template_Ref<S_Movable> > d2;
NeedyTemplate1<Template_Ref<W_Movable> > d3;
NeedyTemplate1<Template_Ref<WS_Movable> > d4;
NeedyTemplate1<Template_Ref<SW_Movable> > d5;
NeedyTemplate1<Template_Ref<SWS_Movable> > d6;
NeedyTemplate1<Template_Ref<NonMovable> > d7;
NeedyTemplate1<Template_Ref<S_NonMovable> > d8;
NeedyTemplate1<Template_Ref<W_NonMovable> > d9;
NeedyTemplate1<Template_Ref<WS_NonMovable> > d10;
NeedyTemplate1<Template_Ref<SW_NonMovable> > d11;
NeedyTemplate1<Template_Ref<SWS_NonMovable> > d12;
}
//
// 2 - Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate2 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate2<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T>
struct S_NeedyTemplate2 : NeedyTemplate2<T> {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate2<{{.*}}>' requested here}}
void bad2() {
S_NeedyTemplate2<NonMovable> a1;
S_NeedyTemplate2<S_NonMovable> a2;
S_NeedyTemplate2<W_NonMovable> a3;
S_NeedyTemplate2<WS_NonMovable> a4;
S_NeedyTemplate2<SW_NonMovable> a5;
S_NeedyTemplate2<SWS_NonMovable> a6;
S_NeedyTemplate2<Template_Inline<NonMovable> > b1;
S_NeedyTemplate2<Template_Inline<S_NonMovable> > b2;
S_NeedyTemplate2<Template_Inline<W_NonMovable> > b3;
S_NeedyTemplate2<Template_Inline<WS_NonMovable> > b4;
S_NeedyTemplate2<Template_Inline<SW_NonMovable> > b5;
S_NeedyTemplate2<Template_Inline<SWS_NonMovable> > b6;
S_NeedyTemplate2<Template_NonMovable<NonMovable> > c1;
S_NeedyTemplate2<Template_NonMovable<S_NonMovable> > c2;
S_NeedyTemplate2<Template_NonMovable<W_NonMovable> > c3;
S_NeedyTemplate2<Template_NonMovable<WS_NonMovable> > c4;
S_NeedyTemplate2<Template_NonMovable<SW_NonMovable> > c5;
S_NeedyTemplate2<Template_NonMovable<SWS_NonMovable> > c6;
S_NeedyTemplate2<Template_NonMovable<Movable> > c7;
S_NeedyTemplate2<Template_NonMovable<S_Movable> > c8;
S_NeedyTemplate2<Template_NonMovable<W_Movable> > c9;
S_NeedyTemplate2<Template_NonMovable<WS_Movable> > c10;
S_NeedyTemplate2<Template_NonMovable<SW_Movable> > c11;
S_NeedyTemplate2<Template_NonMovable<SWS_Movable> > c12;
}
void good2() {
S_NeedyTemplate2<Movable> a1;
S_NeedyTemplate2<S_Movable> a2;
S_NeedyTemplate2<W_Movable> a3;
S_NeedyTemplate2<WS_Movable> a4;
S_NeedyTemplate2<SW_Movable> a5;
S_NeedyTemplate2<SWS_Movable> a6;
S_NeedyTemplate2<Template_Inline<Movable> > b1;
S_NeedyTemplate2<Template_Inline<S_Movable> > b2;
S_NeedyTemplate2<Template_Inline<W_Movable> > b3;
S_NeedyTemplate2<Template_Inline<WS_Movable> > b4;
S_NeedyTemplate2<Template_Inline<SW_Movable> > b5;
S_NeedyTemplate2<Template_Inline<SWS_Movable> > b6;
S_NeedyTemplate2<Template_Unused<Movable> > c1;
S_NeedyTemplate2<Template_Unused<S_Movable> > c2;
S_NeedyTemplate2<Template_Unused<W_Movable> > c3;
S_NeedyTemplate2<Template_Unused<WS_Movable> > c4;
S_NeedyTemplate2<Template_Unused<SW_Movable> > c5;
S_NeedyTemplate2<Template_Unused<SWS_Movable> > c6;
S_NeedyTemplate2<Template_Unused<NonMovable> > c7;
S_NeedyTemplate2<Template_Unused<S_NonMovable> > c8;
S_NeedyTemplate2<Template_Unused<W_NonMovable> > c9;
S_NeedyTemplate2<Template_Unused<WS_NonMovable> > c10;
S_NeedyTemplate2<Template_Unused<SW_NonMovable> > c11;
S_NeedyTemplate2<Template_Unused<SWS_NonMovable> > c12;
S_NeedyTemplate2<Template_Ref<Movable> > d1;
S_NeedyTemplate2<Template_Ref<S_Movable> > d2;
S_NeedyTemplate2<Template_Ref<W_Movable> > d3;
S_NeedyTemplate2<Template_Ref<WS_Movable> > d4;
S_NeedyTemplate2<Template_Ref<SW_Movable> > d5;
S_NeedyTemplate2<Template_Ref<SWS_Movable> > d6;
S_NeedyTemplate2<Template_Ref<NonMovable> > d7;
S_NeedyTemplate2<Template_Ref<S_NonMovable> > d8;
S_NeedyTemplate2<Template_Ref<W_NonMovable> > d9;
S_NeedyTemplate2<Template_Ref<WS_NonMovable> > d10;
S_NeedyTemplate2<Template_Ref<SW_NonMovable> > d11;
S_NeedyTemplate2<Template_Ref<SWS_NonMovable> > d12;
}
//
// 3 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate3 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate3<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T>
struct W_NeedyTemplate3 {
NeedyTemplate3<T> m; // expected-note-re 26 {{instantiation of 'NeedyTemplate3<{{.*}}>' requested here}}
};
void bad3() {
W_NeedyTemplate3<NonMovable> a1;
W_NeedyTemplate3<S_NonMovable> a2;
W_NeedyTemplate3<W_NonMovable> a3;
W_NeedyTemplate3<WS_NonMovable> a4;
W_NeedyTemplate3<SW_NonMovable> a5;
W_NeedyTemplate3<SWS_NonMovable> a6;
W_NeedyTemplate3<Template_Inline<NonMovable> > b1;
W_NeedyTemplate3<Template_Inline<S_NonMovable> > b2;
W_NeedyTemplate3<Template_Inline<W_NonMovable> > b3;
W_NeedyTemplate3<Template_Inline<WS_NonMovable> > b4;
W_NeedyTemplate3<Template_Inline<SW_NonMovable> > b5;
W_NeedyTemplate3<Template_Inline<SWS_NonMovable> > b6;
W_NeedyTemplate3<Template_NonMovable<NonMovable> > c1;
W_NeedyTemplate3<Template_NonMovable<S_NonMovable> > c2;
W_NeedyTemplate3<Template_NonMovable<W_NonMovable> > c3;
W_NeedyTemplate3<Template_NonMovable<WS_NonMovable> > c4;
W_NeedyTemplate3<Template_NonMovable<SW_NonMovable> > c5;
W_NeedyTemplate3<Template_NonMovable<SWS_NonMovable> > c6;
W_NeedyTemplate3<Template_NonMovable<Movable> > c7;
W_NeedyTemplate3<Template_NonMovable<S_Movable> > c8;
W_NeedyTemplate3<Template_NonMovable<W_Movable> > c9;
W_NeedyTemplate3<Template_NonMovable<WS_Movable> > c10;
W_NeedyTemplate3<Template_NonMovable<SW_Movable> > c11;
W_NeedyTemplate3<Template_NonMovable<SWS_Movable> > c12;
}
void good3() {
W_NeedyTemplate3<Movable> a1;
W_NeedyTemplate3<S_Movable> a2;
W_NeedyTemplate3<W_Movable> a3;
W_NeedyTemplate3<WS_Movable> a4;
W_NeedyTemplate3<SW_Movable> a5;
W_NeedyTemplate3<SWS_Movable> a6;
W_NeedyTemplate3<Template_Inline<Movable> > b1;
W_NeedyTemplate3<Template_Inline<S_Movable> > b2;
W_NeedyTemplate3<Template_Inline<W_Movable> > b3;
W_NeedyTemplate3<Template_Inline<WS_Movable> > b4;
W_NeedyTemplate3<Template_Inline<SW_Movable> > b5;
W_NeedyTemplate3<Template_Inline<SWS_Movable> > b6;
W_NeedyTemplate3<Template_Unused<Movable> > c1;
W_NeedyTemplate3<Template_Unused<S_Movable> > c2;
W_NeedyTemplate3<Template_Unused<W_Movable> > c3;
W_NeedyTemplate3<Template_Unused<WS_Movable> > c4;
W_NeedyTemplate3<Template_Unused<SW_Movable> > c5;
W_NeedyTemplate3<Template_Unused<SWS_Movable> > c6;
W_NeedyTemplate3<Template_Unused<NonMovable> > c7;
W_NeedyTemplate3<Template_Unused<S_NonMovable> > c8;
W_NeedyTemplate3<Template_Unused<W_NonMovable> > c9;
W_NeedyTemplate3<Template_Unused<WS_NonMovable> > c10;
W_NeedyTemplate3<Template_Unused<SW_NonMovable> > c11;
W_NeedyTemplate3<Template_Unused<SWS_NonMovable> > c12;
W_NeedyTemplate3<Template_Ref<Movable> > d1;
W_NeedyTemplate3<Template_Ref<S_Movable> > d2;
W_NeedyTemplate3<Template_Ref<W_Movable> > d3;
W_NeedyTemplate3<Template_Ref<WS_Movable> > d4;
W_NeedyTemplate3<Template_Ref<SW_Movable> > d5;
W_NeedyTemplate3<Template_Ref<SWS_Movable> > d6;
W_NeedyTemplate3<Template_Ref<NonMovable> > d7;
W_NeedyTemplate3<Template_Ref<S_NonMovable> > d8;
W_NeedyTemplate3<Template_Ref<W_NonMovable> > d9;
W_NeedyTemplate3<Template_Ref<WS_NonMovable> > d10;
W_NeedyTemplate3<Template_Ref<SW_NonMovable> > d11;
W_NeedyTemplate3<Template_Ref<SWS_NonMovable> > d12;
}
//
// 4 - Wrapped Subclassed MOZ_NEEDS_MEMMOVABLE_TYPE
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate4 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate4<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T>
struct S_NeedyTemplate4 : NeedyTemplate4<T> {}; // expected-note-re 26 {{instantiation of 'NeedyTemplate4<{{.*}}>' requested here}}
template <class T>
struct WS_NeedyTemplate4 {
S_NeedyTemplate4<T> m;
};
void bad4() {
WS_NeedyTemplate4<NonMovable> a1;
WS_NeedyTemplate4<S_NonMovable> a2;
WS_NeedyTemplate4<W_NonMovable> a3;
WS_NeedyTemplate4<WS_NonMovable> a4;
WS_NeedyTemplate4<SW_NonMovable> a5;
WS_NeedyTemplate4<SWS_NonMovable> a6;
WS_NeedyTemplate4<Template_Inline<NonMovable> > b1;
WS_NeedyTemplate4<Template_Inline<S_NonMovable> > b2;
WS_NeedyTemplate4<Template_Inline<W_NonMovable> > b3;
WS_NeedyTemplate4<Template_Inline<WS_NonMovable> > b4;
WS_NeedyTemplate4<Template_Inline<SW_NonMovable> > b5;
WS_NeedyTemplate4<Template_Inline<SWS_NonMovable> > b6;
WS_NeedyTemplate4<Template_NonMovable<NonMovable> > c1;
WS_NeedyTemplate4<Template_NonMovable<S_NonMovable> > c2;
WS_NeedyTemplate4<Template_NonMovable<W_NonMovable> > c3;
WS_NeedyTemplate4<Template_NonMovable<WS_NonMovable> > c4;
WS_NeedyTemplate4<Template_NonMovable<SW_NonMovable> > c5;
WS_NeedyTemplate4<Template_NonMovable<SWS_NonMovable> > c6;
WS_NeedyTemplate4<Template_NonMovable<Movable> > c7;
WS_NeedyTemplate4<Template_NonMovable<S_Movable> > c8;
WS_NeedyTemplate4<Template_NonMovable<W_Movable> > c9;
WS_NeedyTemplate4<Template_NonMovable<WS_Movable> > c10;
WS_NeedyTemplate4<Template_NonMovable<SW_Movable> > c11;
WS_NeedyTemplate4<Template_NonMovable<SWS_Movable> > c12;
}
void good4() {
WS_NeedyTemplate4<Movable> a1;
WS_NeedyTemplate4<S_Movable> a2;
WS_NeedyTemplate4<W_Movable> a3;
WS_NeedyTemplate4<WS_Movable> a4;
WS_NeedyTemplate4<SW_Movable> a5;
WS_NeedyTemplate4<SWS_Movable> a6;
WS_NeedyTemplate4<Template_Inline<Movable> > b1;
WS_NeedyTemplate4<Template_Inline<S_Movable> > b2;
WS_NeedyTemplate4<Template_Inline<W_Movable> > b3;
WS_NeedyTemplate4<Template_Inline<WS_Movable> > b4;
WS_NeedyTemplate4<Template_Inline<SW_Movable> > b5;
WS_NeedyTemplate4<Template_Inline<SWS_Movable> > b6;
WS_NeedyTemplate4<Template_Unused<Movable> > c1;
WS_NeedyTemplate4<Template_Unused<S_Movable> > c2;
WS_NeedyTemplate4<Template_Unused<W_Movable> > c3;
WS_NeedyTemplate4<Template_Unused<WS_Movable> > c4;
WS_NeedyTemplate4<Template_Unused<SW_Movable> > c5;
WS_NeedyTemplate4<Template_Unused<SWS_Movable> > c6;
WS_NeedyTemplate4<Template_Unused<NonMovable> > c7;
WS_NeedyTemplate4<Template_Unused<S_NonMovable> > c8;
WS_NeedyTemplate4<Template_Unused<W_NonMovable> > c9;
WS_NeedyTemplate4<Template_Unused<WS_NonMovable> > c10;
WS_NeedyTemplate4<Template_Unused<SW_NonMovable> > c11;
WS_NeedyTemplate4<Template_Unused<SWS_NonMovable> > c12;
WS_NeedyTemplate4<Template_Ref<Movable> > d1;
WS_NeedyTemplate4<Template_Ref<S_Movable> > d2;
WS_NeedyTemplate4<Template_Ref<W_Movable> > d3;
WS_NeedyTemplate4<Template_Ref<WS_Movable> > d4;
WS_NeedyTemplate4<Template_Ref<SW_Movable> > d5;
WS_NeedyTemplate4<Template_Ref<SWS_Movable> > d6;
WS_NeedyTemplate4<Template_Ref<NonMovable> > d7;
WS_NeedyTemplate4<Template_Ref<S_NonMovable> > d8;
WS_NeedyTemplate4<Template_Ref<W_NonMovable> > d9;
WS_NeedyTemplate4<Template_Ref<WS_NonMovable> > d10;
WS_NeedyTemplate4<Template_Ref<SW_NonMovable> > d11;
WS_NeedyTemplate4<Template_Ref<SWS_NonMovable> > d12;
}
//
// 5 - Subclassed Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate5 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate5<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T>
struct W_NeedyTemplate5 {
NeedyTemplate5<T> m; // expected-note-re 26 {{instantiation of 'NeedyTemplate5<{{.*}}>' requested here}}
};
template <class T>
struct SW_NeedyTemplate5 : W_NeedyTemplate5<T> {};
void bad5() {
SW_NeedyTemplate5<NonMovable> a1;
SW_NeedyTemplate5<S_NonMovable> a2;
SW_NeedyTemplate5<W_NonMovable> a3;
SW_NeedyTemplate5<WS_NonMovable> a4;
SW_NeedyTemplate5<SW_NonMovable> a5;
SW_NeedyTemplate5<SWS_NonMovable> a6;
SW_NeedyTemplate5<Template_Inline<NonMovable> > b1;
SW_NeedyTemplate5<Template_Inline<S_NonMovable> > b2;
SW_NeedyTemplate5<Template_Inline<W_NonMovable> > b3;
SW_NeedyTemplate5<Template_Inline<WS_NonMovable> > b4;
SW_NeedyTemplate5<Template_Inline<SW_NonMovable> > b5;
SW_NeedyTemplate5<Template_Inline<SWS_NonMovable> > b6;
SW_NeedyTemplate5<Template_NonMovable<NonMovable> > c1;
SW_NeedyTemplate5<Template_NonMovable<S_NonMovable> > c2;
SW_NeedyTemplate5<Template_NonMovable<W_NonMovable> > c3;
SW_NeedyTemplate5<Template_NonMovable<WS_NonMovable> > c4;
SW_NeedyTemplate5<Template_NonMovable<SW_NonMovable> > c5;
SW_NeedyTemplate5<Template_NonMovable<SWS_NonMovable> > c6;
SW_NeedyTemplate5<Template_NonMovable<Movable> > c7;
SW_NeedyTemplate5<Template_NonMovable<S_Movable> > c8;
SW_NeedyTemplate5<Template_NonMovable<W_Movable> > c9;
SW_NeedyTemplate5<Template_NonMovable<WS_Movable> > c10;
SW_NeedyTemplate5<Template_NonMovable<SW_Movable> > c11;
SW_NeedyTemplate5<Template_NonMovable<SWS_Movable> > c12;
}
void good5() {
SW_NeedyTemplate5<Movable> a1;
SW_NeedyTemplate5<S_Movable> a2;
SW_NeedyTemplate5<W_Movable> a3;
SW_NeedyTemplate5<WS_Movable> a4;
SW_NeedyTemplate5<SW_Movable> a5;
SW_NeedyTemplate5<SWS_Movable> a6;
SW_NeedyTemplate5<Template_Inline<Movable> > b1;
SW_NeedyTemplate5<Template_Inline<S_Movable> > b2;
SW_NeedyTemplate5<Template_Inline<W_Movable> > b3;
SW_NeedyTemplate5<Template_Inline<WS_Movable> > b4;
SW_NeedyTemplate5<Template_Inline<SW_Movable> > b5;
SW_NeedyTemplate5<Template_Inline<SWS_Movable> > b6;
SW_NeedyTemplate5<Template_Unused<Movable> > c1;
SW_NeedyTemplate5<Template_Unused<S_Movable> > c2;
SW_NeedyTemplate5<Template_Unused<W_Movable> > c3;
SW_NeedyTemplate5<Template_Unused<WS_Movable> > c4;
SW_NeedyTemplate5<Template_Unused<SW_Movable> > c5;
SW_NeedyTemplate5<Template_Unused<SWS_Movable> > c6;
SW_NeedyTemplate5<Template_Unused<NonMovable> > c7;
SW_NeedyTemplate5<Template_Unused<S_NonMovable> > c8;
SW_NeedyTemplate5<Template_Unused<W_NonMovable> > c9;
SW_NeedyTemplate5<Template_Unused<WS_NonMovable> > c10;
SW_NeedyTemplate5<Template_Unused<SW_NonMovable> > c11;
SW_NeedyTemplate5<Template_Unused<SWS_NonMovable> > c12;
SW_NeedyTemplate5<Template_Ref<Movable> > d1;
SW_NeedyTemplate5<Template_Ref<S_Movable> > d2;
SW_NeedyTemplate5<Template_Ref<W_Movable> > d3;
SW_NeedyTemplate5<Template_Ref<WS_Movable> > d4;
SW_NeedyTemplate5<Template_Ref<SW_Movable> > d5;
SW_NeedyTemplate5<Template_Ref<SWS_Movable> > d6;
SW_NeedyTemplate5<Template_Ref<NonMovable> > d7;
SW_NeedyTemplate5<Template_Ref<S_NonMovable> > d8;
SW_NeedyTemplate5<Template_Ref<W_NonMovable> > d9;
SW_NeedyTemplate5<Template_Ref<WS_NonMovable> > d10;
SW_NeedyTemplate5<Template_Ref<SW_NonMovable> > d11;
SW_NeedyTemplate5<Template_Ref<SWS_NonMovable> > d12;
}
//
// 6 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated with default template argument
//
// Note: This has an extra error, because it also includes a test with the default template argument.
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate6 {T m;}; // expected-error-re 27 {{Cannot instantiate 'NeedyTemplate6<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T>
struct W_NeedyTemplate6 {
NeedyTemplate6<T> m; // expected-note-re 27 {{instantiation of 'NeedyTemplate6<{{.*}}>' requested here}}
};
template <class T>
struct SW_NeedyTemplate6 : W_NeedyTemplate6<T> {};
// We create a different NonMovable type here, as NeedyTemplate6 will already be instantiated with NonMovable
struct MOZ_NON_MEMMOVABLE NonMovable2 {}; // expected-note {{'NonMovable2' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'NonMovable2'}}
template <class T = NonMovable2>
struct Defaulted_SW_NeedyTemplate6 {
SW_NeedyTemplate6<T> m;
};
void bad6() {
Defaulted_SW_NeedyTemplate6<NonMovable> a1;
Defaulted_SW_NeedyTemplate6<S_NonMovable> a2;
Defaulted_SW_NeedyTemplate6<W_NonMovable> a3;
Defaulted_SW_NeedyTemplate6<WS_NonMovable> a4;
Defaulted_SW_NeedyTemplate6<SW_NonMovable> a5;
Defaulted_SW_NeedyTemplate6<SWS_NonMovable> a6;
Defaulted_SW_NeedyTemplate6<Template_Inline<NonMovable> > b1;
Defaulted_SW_NeedyTemplate6<Template_Inline<S_NonMovable> > b2;
Defaulted_SW_NeedyTemplate6<Template_Inline<W_NonMovable> > b3;
Defaulted_SW_NeedyTemplate6<Template_Inline<WS_NonMovable> > b4;
Defaulted_SW_NeedyTemplate6<Template_Inline<SW_NonMovable> > b5;
Defaulted_SW_NeedyTemplate6<Template_Inline<SWS_NonMovable> > b6;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<NonMovable> > c1;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<S_NonMovable> > c2;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<W_NonMovable> > c3;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<WS_NonMovable> > c4;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<SW_NonMovable> > c5;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<SWS_NonMovable> > c6;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<Movable> > c7;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<S_Movable> > c8;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<W_Movable> > c9;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<WS_Movable> > c10;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<SW_Movable> > c11;
Defaulted_SW_NeedyTemplate6<Template_NonMovable<SWS_Movable> > c12;
Defaulted_SW_NeedyTemplate6<> c13;
}
void good6() {
Defaulted_SW_NeedyTemplate6<Movable> a1;
Defaulted_SW_NeedyTemplate6<S_Movable> a2;
Defaulted_SW_NeedyTemplate6<W_Movable> a3;
Defaulted_SW_NeedyTemplate6<WS_Movable> a4;
Defaulted_SW_NeedyTemplate6<SW_Movable> a5;
Defaulted_SW_NeedyTemplate6<SWS_Movable> a6;
Defaulted_SW_NeedyTemplate6<Template_Inline<Movable> > b1;
Defaulted_SW_NeedyTemplate6<Template_Inline<S_Movable> > b2;
Defaulted_SW_NeedyTemplate6<Template_Inline<W_Movable> > b3;
Defaulted_SW_NeedyTemplate6<Template_Inline<WS_Movable> > b4;
Defaulted_SW_NeedyTemplate6<Template_Inline<SW_Movable> > b5;
Defaulted_SW_NeedyTemplate6<Template_Inline<SWS_Movable> > b6;
Defaulted_SW_NeedyTemplate6<Template_Unused<Movable> > c1;
Defaulted_SW_NeedyTemplate6<Template_Unused<S_Movable> > c2;
Defaulted_SW_NeedyTemplate6<Template_Unused<W_Movable> > c3;
Defaulted_SW_NeedyTemplate6<Template_Unused<WS_Movable> > c4;
Defaulted_SW_NeedyTemplate6<Template_Unused<SW_Movable> > c5;
Defaulted_SW_NeedyTemplate6<Template_Unused<SWS_Movable> > c6;
Defaulted_SW_NeedyTemplate6<Template_Unused<NonMovable> > c7;
Defaulted_SW_NeedyTemplate6<Template_Unused<S_NonMovable> > c8;
Defaulted_SW_NeedyTemplate6<Template_Unused<W_NonMovable> > c9;
Defaulted_SW_NeedyTemplate6<Template_Unused<WS_NonMovable> > c10;
Defaulted_SW_NeedyTemplate6<Template_Unused<SW_NonMovable> > c11;
Defaulted_SW_NeedyTemplate6<Template_Unused<SWS_NonMovable> > c12;
Defaulted_SW_NeedyTemplate6<Template_Ref<Movable> > d1;
Defaulted_SW_NeedyTemplate6<Template_Ref<S_Movable> > d2;
Defaulted_SW_NeedyTemplate6<Template_Ref<W_Movable> > d3;
Defaulted_SW_NeedyTemplate6<Template_Ref<WS_Movable> > d4;
Defaulted_SW_NeedyTemplate6<Template_Ref<SW_Movable> > d5;
Defaulted_SW_NeedyTemplate6<Template_Ref<SWS_Movable> > d6;
Defaulted_SW_NeedyTemplate6<Template_Ref<NonMovable> > d7;
Defaulted_SW_NeedyTemplate6<Template_Ref<S_NonMovable> > d8;
Defaulted_SW_NeedyTemplate6<Template_Ref<W_NonMovable> > d9;
Defaulted_SW_NeedyTemplate6<Template_Ref<WS_NonMovable> > d10;
Defaulted_SW_NeedyTemplate6<Template_Ref<SW_NonMovable> > d11;
Defaulted_SW_NeedyTemplate6<Template_Ref<SWS_NonMovable> > d12;
}
//
// 7 - MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate7 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate7<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T, class Q = NeedyTemplate7<T> >
struct Defaulted_Templated_NeedyTemplate7 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate7<{{.*}}>' requested here}}
void bad7() {
Defaulted_Templated_NeedyTemplate7<NonMovable> a1;
Defaulted_Templated_NeedyTemplate7<S_NonMovable> a2;
Defaulted_Templated_NeedyTemplate7<W_NonMovable> a3;
Defaulted_Templated_NeedyTemplate7<WS_NonMovable> a4;
Defaulted_Templated_NeedyTemplate7<SW_NonMovable> a5;
Defaulted_Templated_NeedyTemplate7<SWS_NonMovable> a6;
Defaulted_Templated_NeedyTemplate7<Template_Inline<NonMovable> > b1;
Defaulted_Templated_NeedyTemplate7<Template_Inline<S_NonMovable> > b2;
Defaulted_Templated_NeedyTemplate7<Template_Inline<W_NonMovable> > b3;
Defaulted_Templated_NeedyTemplate7<Template_Inline<WS_NonMovable> > b4;
Defaulted_Templated_NeedyTemplate7<Template_Inline<SW_NonMovable> > b5;
Defaulted_Templated_NeedyTemplate7<Template_Inline<SWS_NonMovable> > b6;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<NonMovable> > c1;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<S_NonMovable> > c2;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<W_NonMovable> > c3;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<WS_NonMovable> > c4;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SW_NonMovable> > c5;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SWS_NonMovable> > c6;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<Movable> > c7;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<S_Movable> > c8;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<W_Movable> > c9;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<WS_Movable> > c10;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SW_Movable> > c11;
Defaulted_Templated_NeedyTemplate7<Template_NonMovable<SWS_Movable> > c12;
}
void good7() {
Defaulted_Templated_NeedyTemplate7<Movable> a1;
Defaulted_Templated_NeedyTemplate7<S_Movable> a2;
Defaulted_Templated_NeedyTemplate7<W_Movable> a3;
Defaulted_Templated_NeedyTemplate7<WS_Movable> a4;
Defaulted_Templated_NeedyTemplate7<SW_Movable> a5;
Defaulted_Templated_NeedyTemplate7<SWS_Movable> a6;
Defaulted_Templated_NeedyTemplate7<Template_Inline<Movable> > b1;
Defaulted_Templated_NeedyTemplate7<Template_Inline<S_Movable> > b2;
Defaulted_Templated_NeedyTemplate7<Template_Inline<W_Movable> > b3;
Defaulted_Templated_NeedyTemplate7<Template_Inline<WS_Movable> > b4;
Defaulted_Templated_NeedyTemplate7<Template_Inline<SW_Movable> > b5;
Defaulted_Templated_NeedyTemplate7<Template_Inline<SWS_Movable> > b6;
Defaulted_Templated_NeedyTemplate7<Template_Unused<Movable> > c1;
Defaulted_Templated_NeedyTemplate7<Template_Unused<S_Movable> > c2;
Defaulted_Templated_NeedyTemplate7<Template_Unused<W_Movable> > c3;
Defaulted_Templated_NeedyTemplate7<Template_Unused<WS_Movable> > c4;
Defaulted_Templated_NeedyTemplate7<Template_Unused<SW_Movable> > c5;
Defaulted_Templated_NeedyTemplate7<Template_Unused<SWS_Movable> > c6;
Defaulted_Templated_NeedyTemplate7<Template_Unused<NonMovable> > c7;
Defaulted_Templated_NeedyTemplate7<Template_Unused<S_NonMovable> > c8;
Defaulted_Templated_NeedyTemplate7<Template_Unused<W_NonMovable> > c9;
Defaulted_Templated_NeedyTemplate7<Template_Unused<WS_NonMovable> > c10;
Defaulted_Templated_NeedyTemplate7<Template_Unused<SW_NonMovable> > c11;
Defaulted_Templated_NeedyTemplate7<Template_Unused<SWS_NonMovable> > c12;
Defaulted_Templated_NeedyTemplate7<Template_Ref<Movable> > d1;
Defaulted_Templated_NeedyTemplate7<Template_Ref<S_Movable> > d2;
Defaulted_Templated_NeedyTemplate7<Template_Ref<W_Movable> > d3;
Defaulted_Templated_NeedyTemplate7<Template_Ref<WS_Movable> > d4;
Defaulted_Templated_NeedyTemplate7<Template_Ref<SW_Movable> > d5;
Defaulted_Templated_NeedyTemplate7<Template_Ref<SWS_Movable> > d6;
Defaulted_Templated_NeedyTemplate7<Template_Ref<NonMovable> > d7;
Defaulted_Templated_NeedyTemplate7<Template_Ref<S_NonMovable> > d8;
Defaulted_Templated_NeedyTemplate7<Template_Ref<W_NonMovable> > d9;
Defaulted_Templated_NeedyTemplate7<Template_Ref<WS_NonMovable> > d10;
Defaulted_Templated_NeedyTemplate7<Template_Ref<SW_NonMovable> > d11;
Defaulted_Templated_NeedyTemplate7<Template_Ref<SWS_NonMovable> > d12;
}
//
// 8 - Wrapped MOZ_NEEDS_MEMMOVABLE_TYPE instantiated as default template argument
//
template <class T>
struct MOZ_NEEDS_MEMMOVABLE_TYPE NeedyTemplate8 {T m;}; // expected-error-re 26 {{Cannot instantiate 'NeedyTemplate8<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
template <class T, class Q = NeedyTemplate8<T> >
struct Defaulted_Templated_NeedyTemplate8 {Q m;}; // expected-note-re 26 {{instantiation of 'NeedyTemplate8<{{.*}}>' requested here}}
template <class T>
struct W_Defaulted_Templated_NeedyTemplate8 {
Defaulted_Templated_NeedyTemplate8<T> m;
};
void bad8() {
W_Defaulted_Templated_NeedyTemplate8<NonMovable> a1;
W_Defaulted_Templated_NeedyTemplate8<S_NonMovable> a2;
W_Defaulted_Templated_NeedyTemplate8<W_NonMovable> a3;
W_Defaulted_Templated_NeedyTemplate8<WS_NonMovable> a4;
W_Defaulted_Templated_NeedyTemplate8<SW_NonMovable> a5;
W_Defaulted_Templated_NeedyTemplate8<SWS_NonMovable> a6;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<NonMovable> > b1;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<S_NonMovable> > b2;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<W_NonMovable> > b3;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<WS_NonMovable> > b4;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SW_NonMovable> > b5;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SWS_NonMovable> > b6;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<NonMovable> > c1;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<S_NonMovable> > c2;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<W_NonMovable> > c3;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<WS_NonMovable> > c4;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SW_NonMovable> > c5;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SWS_NonMovable> > c6;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<Movable> > c7;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<S_Movable> > c8;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<W_Movable> > c9;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<WS_Movable> > c10;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SW_Movable> > c11;
W_Defaulted_Templated_NeedyTemplate8<Template_NonMovable<SWS_Movable> > c12;
}
void good8() {
W_Defaulted_Templated_NeedyTemplate8<Movable> a1;
W_Defaulted_Templated_NeedyTemplate8<S_Movable> a2;
W_Defaulted_Templated_NeedyTemplate8<W_Movable> a3;
W_Defaulted_Templated_NeedyTemplate8<WS_Movable> a4;
W_Defaulted_Templated_NeedyTemplate8<SW_Movable> a5;
W_Defaulted_Templated_NeedyTemplate8<SWS_Movable> a6;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<Movable> > b1;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<S_Movable> > b2;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<W_Movable> > b3;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<WS_Movable> > b4;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SW_Movable> > b5;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SWS_Movable> > b6;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<Movable> > c1;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<S_Movable> > c2;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<W_Movable> > c3;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<WS_Movable> > c4;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SW_Movable> > c5;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SWS_Movable> > c6;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<NonMovable> > c7;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<S_NonMovable> > c8;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<W_NonMovable> > c9;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<WS_NonMovable> > c10;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SW_NonMovable> > c11;
W_Defaulted_Templated_NeedyTemplate8<Template_Unused<SWS_NonMovable> > c12;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<Movable> > d1;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<S_Movable> > d2;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<W_Movable> > d3;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<WS_Movable> > d4;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SW_Movable> > d5;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SWS_Movable> > d6;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<NonMovable> > d7;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<S_NonMovable> > d8;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<W_NonMovable> > d9;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<WS_NonMovable> > d10;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SW_NonMovable> > d11;
W_Defaulted_Templated_NeedyTemplate8<Template_Ref<SWS_NonMovable> > d12;
}
/*
SpecializedNonMovable is a non-movable class which has an explicit specialization of NeedyTemplate
for it. Instantiations of NeedyTemplateN<SpecializedNonMovable> should be legal as the explicit
specialization isn't annotated with MOZ_NEEDS_MEMMOVABLE_TYPE.
However, as it is MOZ_NON_MEMMOVABLE, derived classes and members shouldn't be able to be used to
instantiate NeedyTemplate.
*/
struct MOZ_NON_MEMMOVABLE SpecializedNonMovable {}; // expected-note 8 {{'S_SpecializedNonMovable' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'SpecializedNonMovable'}} expected-note 8 {{'Template_Inline<SpecializedNonMovable>' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'SpecializedNonMovable'}}
struct S_SpecializedNonMovable : SpecializedNonMovable {};
// Specialize all of the NeedyTemplates with SpecializedNonMovable.
template <>
struct NeedyTemplate1<SpecializedNonMovable> {};
template <>
struct NeedyTemplate2<SpecializedNonMovable> {};
template <>
struct NeedyTemplate3<SpecializedNonMovable> {};
template <>
struct NeedyTemplate4<SpecializedNonMovable> {};
template <>
struct NeedyTemplate5<SpecializedNonMovable> {};
template <>
struct NeedyTemplate6<SpecializedNonMovable> {};
template <>
struct NeedyTemplate7<SpecializedNonMovable> {};
template <>
struct NeedyTemplate8<SpecializedNonMovable> {};
void specialization() {
/*
SpecializedNonMovable has a specialization for every variant of NeedyTemplate,
so these templates are valid, even though SpecializedNonMovable isn't
memmovable
*/
NeedyTemplate1<SpecializedNonMovable> a1;
S_NeedyTemplate2<SpecializedNonMovable> a2;
W_NeedyTemplate3<SpecializedNonMovable> a3;
WS_NeedyTemplate4<SpecializedNonMovable> a4;
SW_NeedyTemplate5<SpecializedNonMovable> a5;
Defaulted_SW_NeedyTemplate6<SpecializedNonMovable> a6;
Defaulted_Templated_NeedyTemplate7<SpecializedNonMovable> a7;
W_Defaulted_Templated_NeedyTemplate8<SpecializedNonMovable> a8;
/*
These entries contain an element which is SpecializedNonMovable, and are non-movable
as there is no valid specialization, and their member is non-memmovable
*/
NeedyTemplate1<Template_Inline<SpecializedNonMovable> > b1; // expected-note {{instantiation of 'NeedyTemplate1<Template_Inline<SpecializedNonMovable> >' requested here}}
S_NeedyTemplate2<Template_Inline<SpecializedNonMovable> > b2;
W_NeedyTemplate3<Template_Inline<SpecializedNonMovable> > b3;
WS_NeedyTemplate4<Template_Inline<SpecializedNonMovable> > b4;
SW_NeedyTemplate5<Template_Inline<SpecializedNonMovable> > b5;
Defaulted_SW_NeedyTemplate6<Template_Inline<SpecializedNonMovable> > b6;
Defaulted_Templated_NeedyTemplate7<Template_Inline<SpecializedNonMovable> > b7;
W_Defaulted_Templated_NeedyTemplate8<Template_Inline<SpecializedNonMovable> > b8;
/*
The subclass of SpecializedNonMovable, is also non-memmovable,
as there is no valid specialization.
*/
NeedyTemplate1<S_SpecializedNonMovable> c1; // expected-note {{instantiation of 'NeedyTemplate1<S_SpecializedNonMovable>' requested here}}
S_NeedyTemplate2<S_SpecializedNonMovable> c2;
W_NeedyTemplate3<S_SpecializedNonMovable> c3;
WS_NeedyTemplate4<S_SpecializedNonMovable> c4;
SW_NeedyTemplate5<S_SpecializedNonMovable> c5;
Defaulted_SW_NeedyTemplate6<S_SpecializedNonMovable> c6;
Defaulted_Templated_NeedyTemplate7<S_SpecializedNonMovable> c7;
W_Defaulted_Templated_NeedyTemplate8<S_SpecializedNonMovable> c8;
}

View File

@ -18,7 +18,7 @@ void misuseStackClass(int len) {
Stack valid;
Stack alsoValid[2];
static Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}}
static Stack alsoNotValid[2]; // expected-error {{variable of type 'Stack [2]' only valid on the stack}}
static Stack alsoNotValid[2]; // expected-error {{variable of type 'Stack [2]' only valid on the stack}} expected-note {{'Stack [2]' is a stack type because it is an array of stack type 'Stack'}}
gobble(&valid);
gobble(&notValid);
@ -35,7 +35,7 @@ void misuseStackClass(int len) {
Stack notValid; // expected-error {{variable of type 'Stack' only valid on the stack}}
struct RandomClass {
Stack nonstaticMember; // expected-note {{'RandomClass' is a stack class because member 'nonstaticMember' is a stack class 'Stack'}}
Stack nonstaticMember; // expected-note {{'RandomClass' is a stack type because member 'nonstaticMember' is a stack type 'Stack'}}
static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}}
};
struct MOZ_STACK_CLASS RandomStackClass {
@ -43,7 +43,7 @@ struct MOZ_STACK_CLASS RandomStackClass {
static Stack staticMember; // expected-error {{variable of type 'Stack' only valid on the stack}}
};
struct BadInherit : Stack {}; // expected-note {{'BadInherit' is a stack class because it inherits from a stack class 'Stack'}}
struct BadInherit : Stack {}; // expected-note {{'BadInherit' is a stack type because it inherits from a stack type 'Stack'}}
struct MOZ_STACK_CLASS GoodInherit : Stack {};
BadInherit moreInvalid; // expected-error {{variable of type 'BadInherit' only valid on the stack}}

View File

@ -9,13 +9,16 @@ SOURCES += [
'TestCustomHeap.cpp',
'TestExplicitOperatorBool.cpp',
'TestGlobalClass.cpp',
'TestMultipleAnnotations.cpp',
'TestMustOverride.cpp',
'TestMustUse.cpp',
'TestNANTestingExpr.cpp',
'TestNANTestingExprC.c',
'TestNeedsNoVTableType.cpp',
'TestNoAddRefReleaseOnReturn.cpp',
'TestNoArithmeticExprInArgument.cpp',
'TestNonHeapClass.cpp',
'TestNonMemMovable.cpp',
'TestNoRefcountedInsideLambdas.cpp',
'TestStackClass.cpp',
'TestTrivialCtorDtor.cpp',

View File

@ -109,6 +109,7 @@ class MachCommands(MachCommandBase):
'--show-possibly-lost=no',
'--track-origins=yes',
'--trace-children=yes',
'-v', # Enable verbosity to get the list of used suppressions
]
for s in suppressions:

View File

@ -1710,20 +1710,22 @@ nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
}
uint32_t loadType = LOAD_NORMAL;
nsCOMPtr<nsIPrincipal> requestingPrincipal;
if (aLoadInfo) {
nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
(void)aLoadInfo->GetLoadType(&lt);
// Get the appropriate LoadType from nsIDocShellLoadInfo type
loadType = ConvertDocShellLoadInfoToLoadType(lt);
nsCOMPtr<nsISupports> owner;
aLoadInfo->GetOwner(getter_AddRefs(owner));
requestingPrincipal = do_QueryInterface(owner);
}
NS_ENSURE_SUCCESS(Stop(nsIWebNavigation::STOP_NETWORK), NS_ERROR_FAILURE);
mLoadType = loadType;
nsCOMPtr<nsISupports> owner;
aLoadInfo->GetOwner(getter_AddRefs(owner));
nsCOMPtr<nsIPrincipal> requestingPrincipal = do_QueryInterface(owner);
if (!requestingPrincipal) {
requestingPrincipal = nsContentUtils::GetSystemPrincipal();
}

View File

@ -2728,8 +2728,52 @@ Navigator::RequestMediaKeySystemAccess(const nsAString& aKeySystem,
const Optional<Sequence<MediaKeySystemOptions>>& aOptions,
ErrorResult& aRv)
{
nsAutoCString logMsg;
logMsg.AppendPrintf("Navigator::RequestMediaKeySystemAccess(keySystem='%s' options=[",
NS_ConvertUTF16toUTF8(aKeySystem).get());
if (aOptions.WasPassed()) {
const Sequence<MediaKeySystemOptions>& options = aOptions.Value();
for (size_t i = 0; i < options.Length(); i++) {
const MediaKeySystemOptions& op = options[i];
if (i > 0) {
logMsg.AppendLiteral(",");
}
logMsg.AppendLiteral("{");
logMsg.AppendPrintf("stateful='%s'",
MediaKeysRequirementValues::strings[(size_t)op.mStateful].value);
logMsg.AppendPrintf(", uniqueIdentifier='%s'",
MediaKeysRequirementValues::strings[(size_t)op.mUniqueidentifier].value);
if (!op.mAudioCapability.IsEmpty()) {
logMsg.AppendPrintf(", audioCapability='%s'",
NS_ConvertUTF16toUTF8(op.mAudioCapability).get());
}
if (!op.mAudioType.IsEmpty()) {
logMsg.AppendPrintf(", audioType='%s'",
NS_ConvertUTF16toUTF8(op.mAudioType).get());
}
if (!op.mInitDataType.IsEmpty()) {
logMsg.AppendPrintf(", initDataType='%s'",
NS_ConvertUTF16toUTF8(op.mInitDataType).get());
}
if (!op.mVideoCapability.IsEmpty()) {
logMsg.AppendPrintf(", videoCapability='%s'",
NS_ConvertUTF16toUTF8(op.mVideoCapability).get());
}
if (!op.mVideoType.IsEmpty()) {
logMsg.AppendPrintf(", videoType='%s'",
NS_ConvertUTF16toUTF8(op.mVideoType).get());
}
logMsg.AppendLiteral("}");
}
}
logMsg.AppendPrintf("])");
EME_LOG(logMsg.get());
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
nsRefPtr<DetailedPromise> promise = DetailedPromise::Create(go, aRv);
nsRefPtr<DetailedPromise> promise = DetailedPromise::Create(go, aRv,
NS_LITERAL_CSTRING("navigator.requestMediaKeySystemAccess"));
if (aRv.Failed()) {
return nullptr;
}

View File

@ -9,11 +9,13 @@
#include "mozilla/dom/MimeTypeArrayBinding.h"
#include "mozilla/dom/MimeTypeBinding.h"
#include "nsIDOMNavigator.h"
#include "nsPIDOMWindow.h"
#include "nsPluginArray.h"
#include "nsIMIMEService.h"
#include "nsIMIMEInfo.h"
#include "Navigator.h"
#include "nsServiceManagerUtils.h"
#include "nsPluginTags.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -216,19 +218,22 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsMimeType, Release)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsMimeType, mWindow, mPluginElement)
nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, nsPluginElement* aPluginElement,
uint32_t aPluginTagMimeIndex, const nsAString& aType)
nsMimeType::nsMimeType(nsPIDOMWindow* aWindow,
nsPluginElement* aPluginElement,
const nsAString& aType,
const nsAString& aDescription,
const nsAString& aExtension)
: mWindow(aWindow),
mPluginElement(aPluginElement),
mPluginTagMimeIndex(aPluginTagMimeIndex),
mType(aType)
mType(aType),
mDescription(aDescription),
mExtension(aExtension)
{
}
nsMimeType::nsMimeType(nsPIDOMWindow* aWindow, const nsAString& aType)
: mWindow(aWindow),
mPluginElement(nullptr),
mPluginTagMimeIndex(0),
mType(aType)
{
}
@ -251,14 +256,9 @@ nsMimeType::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
}
void
nsMimeType::GetDescription(nsString& retval) const
nsMimeType::GetDescription(nsString& aRetval) const
{
retval.Truncate();
if (mPluginElement) {
CopyUTF8toUTF16(mPluginElement->PluginTag()->
mMimeDescriptions[mPluginTagMimeIndex], retval);
}
aRetval = mDescription;
}
nsPluginElement*
@ -269,14 +269,9 @@ nsMimeType::GetEnabledPlugin() const
}
void
nsMimeType::GetSuffixes(nsString& retval) const
nsMimeType::GetSuffixes(nsString& aRetval) const
{
retval.Truncate();
if (mPluginElement) {
CopyUTF8toUTF16(mPluginElement->PluginTag()->
mExtensions[mPluginTagMimeIndex], retval);
}
aRetval = mExtension;
}
void

View File

@ -58,8 +58,11 @@ public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsMimeType)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsMimeType)
nsMimeType(nsPIDOMWindow* aWindow, nsPluginElement* aPluginElement,
uint32_t aPluginTagMimeIndex, const nsAString& aMimeType);
nsMimeType(nsPIDOMWindow* aWindow,
nsPluginElement* aPluginElement,
const nsAString& aType,
const nsAString& aDescription,
const nsAString& aExtension);
nsMimeType(nsPIDOMWindow* aWindow, const nsAString& aMimeType);
nsPIDOMWindow* GetParentObject() const;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
@ -85,8 +88,9 @@ protected:
// mimetype array. We rely on the cycle collector to break this
// cycle.
nsRefPtr<nsPluginElement> mPluginElement;
uint32_t mPluginTagMimeIndex;
nsString mType;
nsString mDescription;
nsString mExtension;
};
#endif /* nsMimeTypeArray_h___ */

View File

@ -130,7 +130,7 @@ nsPluginArray::Refresh(bool aReloadDocuments)
// that plugins did not change and was not reloaded
if (pluginHost->ReloadPlugins() ==
NS_ERROR_PLUGINS_PLUGINSNOTCHANGED) {
nsTArray<nsRefPtr<nsPluginTag> > newPluginTags;
nsTArray<nsCOMPtr<nsIInternalPluginTag> > newPluginTags;
pluginHost->GetPlugins(newPluginTags);
// Check if the number of plugins we know about are different from
@ -279,7 +279,7 @@ operator<(const nsRefPtr<nsPluginElement>& lhs,
const nsRefPtr<nsPluginElement>& rhs)
{
// Sort plugins alphabetically by name.
return lhs->PluginTag()->mName < rhs->PluginTag()->mName;
return lhs->PluginTag()->Name() < rhs->PluginTag()->Name();
}
void
@ -296,14 +296,13 @@ nsPluginArray::EnsurePlugins()
return;
}
nsTArray<nsRefPtr<nsPluginTag> > pluginTags;
nsTArray<nsCOMPtr<nsIInternalPluginTag> > pluginTags;
pluginHost->GetPlugins(pluginTags);
// need to wrap each of these with a nsPluginElement, which is
// scriptable.
for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
nsPluginTag* pluginTag = pluginTags[i];
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTag));
mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
}
// Alphabetize the enumeration order of non-hidden plugins to reduce
@ -323,7 +322,7 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginElement, mWindow, mMimeTypes)
nsPluginElement::nsPluginElement(nsPIDOMWindow* aWindow,
nsPluginTag* aPluginTag)
nsIInternalPluginTag* aPluginTag)
: mWindow(aWindow),
mPluginTag(aPluginTag)
{
@ -349,25 +348,25 @@ nsPluginElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
void
nsPluginElement::GetDescription(nsString& retval) const
{
CopyUTF8toUTF16(mPluginTag->mDescription, retval);
CopyUTF8toUTF16(mPluginTag->Description(), retval);
}
void
nsPluginElement::GetFilename(nsString& retval) const
{
CopyUTF8toUTF16(mPluginTag->mFileName, retval);
CopyUTF8toUTF16(mPluginTag->FileName(), retval);
}
void
nsPluginElement::GetVersion(nsString& retval) const
{
CopyUTF8toUTF16(mPluginTag->mVersion, retval);
CopyUTF8toUTF16(mPluginTag->Version(), retval);
}
void
nsPluginElement::GetName(nsString& retval) const
{
CopyUTF8toUTF16(mPluginTag->mName, retval);
CopyUTF8toUTF16(mPluginTag->Name(), retval);
}
nsMimeType*
@ -452,8 +451,18 @@ nsPluginElement::EnsurePluginMimeTypes()
return;
}
for (uint32_t i = 0; i < mPluginTag->mMimeTypes.Length(); ++i) {
NS_ConvertUTF8toUTF16 type(mPluginTag->mMimeTypes[i]);
mMimeTypes.AppendElement(new nsMimeType(mWindow, this, i, type));
if (mPluginTag->MimeTypes().Length() != mPluginTag->MimeDescriptions().Length() ||
mPluginTag->MimeTypes().Length() != mPluginTag->Extensions().Length()) {
MOZ_ASSERT(false, "mime type arrays expected to be the same length");
return;
}
for (uint32_t i = 0; i < mPluginTag->MimeTypes().Length(); ++i) {
NS_ConvertUTF8toUTF16 type(mPluginTag->MimeTypes()[i]);
NS_ConvertUTF8toUTF16 description(mPluginTag->MimeDescriptions()[i]);
NS_ConvertUTF8toUTF16 extension(mPluginTag->Extensions()[i]);
mMimeTypes.AppendElement(new nsMimeType(mWindow, this, type, description,
extension));
}
}

View File

@ -11,11 +11,11 @@
#include "nsWeakReference.h"
#include "nsIObserver.h"
#include "nsWrapperCache.h"
#include "nsPluginTags.h"
#include "nsPIDOMWindow.h"
class nsPluginElement;
class nsMimeType;
class nsIInternalPluginTag;
class nsPluginArray final : public nsIObserver,
public nsSupportsWeakReference,
@ -70,12 +70,12 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsPluginElement)
nsPluginElement(nsPIDOMWindow* aWindow, nsPluginTag* aPluginTag);
nsPluginElement(nsPIDOMWindow* aWindow, nsIInternalPluginTag* aPluginTag);
nsPIDOMWindow* GetParentObject() const;
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
nsPluginTag* PluginTag() const
nsIInternalPluginTag* PluginTag() const
{
return mPluginTag;
}
@ -102,7 +102,7 @@ protected:
void EnsurePluginMimeTypes();
nsCOMPtr<nsPIDOMWindow> mWindow;
nsRefPtr<nsPluginTag> mPluginTag;
nsCOMPtr<nsIInternalPluginTag> mPluginTag;
nsTArray<nsRefPtr<nsMimeType> > mMimeTypes;
};

View File

@ -960,6 +960,25 @@ DOMInterfaces = {
'workers': True
},
'PushManager': [{
'workers': False,
'headerFile': 'mozilla/dom/PushManager.h',
'nativeType': 'mozilla::dom::PushManager',
}, {
'workers': True,
'headerFile': 'mozilla/dom/PushManager.h',
'nativeType': 'mozilla::dom::WorkerPushManager',
}],
'PushSubscription': [{
'workers': False,
'headerFile': 'mozilla/dom/PushManager.h',
}, {
'workers': True,
'headerFile': 'mozilla/dom/PushManager.h',
'nativeType': 'mozilla::dom::WorkerPushSubscription',
}],
'Range': {
'nativeType': 'nsRange',
'binaryNames': {

View File

@ -115,11 +115,8 @@ static bool sIsFirstTimeToggleOffBt(false);
#ifndef MOZ_B2G_BT_API_V1
static bool sAdapterEnabled(false);
// Use a static hash table to keep the name of remote device during the pairing
// procedure. In this manner, BT service and adapter can get the name of paired
// device name when bond state changed.
// The hash Key is BD address, the Value is remote BD name.
static nsDataHashtable<nsStringHashKey, nsString> sPairingNameTable;
// Static hash table to map device name from address
static nsDataHashtable<nsStringHashKey, nsString> sDeviceNameMap;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeAdapterStateRunnableArray;
static nsTArray<nsRefPtr<BluetoothReplyRunnable> > sChangeDiscoveryRunnableArray;
@ -1896,7 +1893,7 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
sFetchUuidsRunnableArray.Clear();
sBondingRunnableArray.Clear();
sUnbondingRunnableArray.Clear();
sPairingNameTable.Clear();
sDeviceNameMap.Clear();
// Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., it should
// be connectable and non-discoverable.
@ -2178,7 +2175,8 @@ BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", nsString(aBdAddr));
nsString bdAddr(aBdAddr);
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", bdAddr);
for (int i = 0; i < aNumProperties; ++i) {
@ -2187,6 +2185,9 @@ BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
if (p.mType == PROPERTY_BDNAME) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", p.mString);
// Update <address, name> mapping
sDeviceNameMap.Remove(bdAddr);
sDeviceNameMap.Put(bdAddr, p.mString);
} else if (p.mType == PROPERTY_CLASS_OF_DEVICE) {
uint32_t cod = p.mUint32;
BT_APPEND_NAMED_VALUE(propertiesArray, "Cod", cod);
@ -2382,19 +2383,19 @@ BluetoothServiceBluedroid::DeviceFoundNotification(
#ifndef MOZ_B2G_BT_API_V1
MOZ_ASSERT(NS_IsMainThread());
BluetoothValue propertyValue;
InfallibleTArray<BluetoothNamedValue> propertiesArray;
nsString bdAddr, bdName;
for (int i = 0; i < aNumProperties; i++) {
const BluetoothProperty& p = aProperties[i];
if (p.mType == PROPERTY_BDADDR) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Address", p.mString);
bdAddr = p.mString;
} else if (p.mType == PROPERTY_BDNAME) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", p.mString);
bdName = p.mString;
} else if (p.mType == PROPERTY_CLASS_OF_DEVICE) {
BT_APPEND_NAMED_VALUE(propertiesArray, "Cod", p.mUint32);
@ -2423,6 +2424,10 @@ BluetoothServiceBluedroid::DeviceFoundNotification(
}
}
// Update <address, name> mapping
sDeviceNameMap.Remove(bdAddr);
sDeviceNameMap.Put(bdAddr, bdName);
DistributeSignal(NS_LITERAL_STRING("DeviceFound"),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
@ -2515,14 +2520,23 @@ BluetoothServiceBluedroid::PinRequestNotification(const nsAString& aRemoteBdAddr
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
BT_APPEND_NAMED_VALUE(propertiesArray, "name", nsString(aBdName));
// If |aBdName| is empty, get device name from |sDeviceNameMap|;
// Otherwise update <address, name> mapping with |aBdName|
nsString bdAddr(aRemoteBdAddr);
nsString bdName(aBdName);
if (bdName.IsEmpty()) {
sDeviceNameMap.Get(bdAddr, &bdName);
} else {
sDeviceNameMap.Remove(bdAddr);
sDeviceNameMap.Put(bdAddr, bdName);
}
BT_APPEND_NAMED_VALUE(propertiesArray, "address", bdAddr);
BT_APPEND_NAMED_VALUE(propertiesArray, "name", bdName);
BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", EmptyString());
BT_APPEND_NAMED_VALUE(propertiesArray, "type",
NS_LITERAL_STRING(PAIRING_REQ_TYPE_ENTERPINCODE));
sPairingNameTable.Put(nsString(aRemoteBdAddr), nsString(aBdName));
DistributeSignal(NS_LITERAL_STRING("PairingRequest"),
NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
BluetoothValue(propertiesArray));
@ -2551,8 +2565,17 @@ BluetoothServiceBluedroid::SspRequestNotification(
#ifndef MOZ_B2G_BT_API_V1
InfallibleTArray<BluetoothNamedValue> propertiesArray;
nsAutoString passkey;
nsAutoString pairingType;
// If |aBdName| is empty, get device name from |sDeviceNameMap|;
// Otherwise update <address, name> mapping with |aBdName|
nsString bdAddr(aRemoteBdAddr);
nsString bdName(aBdName);
if (bdName.IsEmpty()) {
sDeviceNameMap.Get(bdAddr, &bdName);
} else {
sDeviceNameMap.Remove(bdAddr);
sDeviceNameMap.Put(bdAddr, bdName);
}
/**
* Assign pairing request type and passkey based on the pairing variant.
@ -2562,6 +2585,8 @@ BluetoothServiceBluedroid::SspRequestNotification(
* PAIRING_REQ_TYPE_DISPLAYPASSKEY
* 2) empty string: PAIRING_REQ_TYPE_CONSENT
*/
nsAutoString passkey;
nsAutoString pairingType;
switch (aPairingVariant) {
case SSP_VARIANT_PASSKEY_CONFIRMATION:
pairingType.AssignLiteral(PAIRING_REQ_TYPE_CONFIRMATION);
@ -2579,13 +2604,11 @@ BluetoothServiceBluedroid::SspRequestNotification(
return;
}
BT_APPEND_NAMED_VALUE(propertiesArray, "address", nsString(aRemoteBdAddr));
BT_APPEND_NAMED_VALUE(propertiesArray, "name", nsString(aBdName));
BT_APPEND_NAMED_VALUE(propertiesArray, "address", bdAddr);
BT_APPEND_NAMED_VALUE(propertiesArray, "name", bdName);
BT_APPEND_NAMED_VALUE(propertiesArray, "passkey", passkey);
BT_APPEND_NAMED_VALUE(propertiesArray, "type", pairingType);
sPairingNameTable.Put(nsString(aRemoteBdAddr), nsString(aBdName));
DistributeSignal(NS_LITERAL_STRING("PairingRequest"),
NS_LITERAL_STRING(KEY_PAIRING_LISTENER),
BluetoothValue(propertiesArray));
@ -2642,16 +2665,13 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
return;
}
// Retrieve and remove pairing device name from hash table
nsString deviceName;
bool nameExists = sPairingNameTable.Get(aRemoteBdAddr, &deviceName);
if (nameExists) {
sPairingNameTable.Remove(aRemoteBdAddr);
}
// Query pairing device name from hash table
nsString remoteBdAddr(aRemoteBdAddr);
nsString remotebdName;
sDeviceNameMap.Get(remoteBdAddr, &remotebdName);
// Update bonded address array and append pairing device name
InfallibleTArray<BluetoothNamedValue> propertiesArray;
nsString remoteBdAddr = nsString(aRemoteBdAddr);
if (!bonded) {
sAdapterBondedAddressArray.RemoveElement(remoteBdAddr);
} else {
@ -2659,21 +2679,17 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
sAdapterBondedAddressArray.AppendElement(remoteBdAddr);
}
// We don't assert |!deviceName.IsEmpty()| here since empty string is
// also a valid name. According to Bluetooth Core Spec. v3.0 - Sec. 6.22,
// We don't assert |!remotebdName.IsEmpty()| since empty string is also
// valid, according to Bluetooth Core Spec. v3.0 - Sec. 6.22:
// "a valid Bluetooth name is a UTF-8 encoding string which is up to 248
// bytes in length."
// Furthermore, we don't assert |nameExists| here since it's expected to be
// 'false' if remote device is using "SSP just works without user
// interaction" or "legacy pairing with auto-pairing".
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", deviceName);
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", remotebdName);
}
// Notify device of attribute changed
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
DistributeSignal(NS_LITERAL_STRING("PropertyChanged"),
aRemoteBdAddr,
remoteBdAddr,
BluetoothValue(propertiesArray));
// Notify adapter of device paired/unpaired

View File

@ -12,7 +12,6 @@
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/Preferences.h"
#include "WorkerPrivate.h"
#include "WorkerRunnable.h"
@ -299,50 +298,8 @@ private:
}
};
class PrefEnabledRunnable final : public WorkerMainThreadRunnable
{
public:
explicit PrefEnabledRunnable(WorkerPrivate* aWorkerPrivate)
: WorkerMainThreadRunnable(aWorkerPrivate)
, mEnabled(false)
{ }
bool MainThreadRun() override
{
AssertIsOnMainThread();
mEnabled = Preferences::GetBool("dom.broadcastChannel.enabled", false);
return true;
}
bool IsEnabled() const
{
return mEnabled;
}
private:
bool mEnabled;
};
} // namespace
/* static */ bool
BroadcastChannel::IsEnabled(JSContext* aCx, JSObject* aGlobal)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.broadcastChannel.enabled", false);
}
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
nsRefPtr<PrefEnabledRunnable> runnable =
new PrefEnabledRunnable(workerPrivate);
runnable->Dispatch(workerPrivate->GetJSContext());
return runnable->IsEnabled();
}
BroadcastChannel::BroadcastChannel(nsPIDOMWindow* aWindow,
const PrincipalInfo& aPrincipalInfo,
const nsACString& aOrigin,

View File

@ -47,8 +47,6 @@ public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BroadcastChannel,
DOMEventTargetHelper)
static bool IsEnabled(JSContext* aCx, JSObject* aGlobal);
virtual JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;

View File

@ -1,11 +0,0 @@
onmessage = function() {
var exists = true;
try {
var bc = new BroadcastChannel('foobar');
} catch(e) {
exists = false;
}
postMessage({ exists: exists });
}

View File

@ -1,7 +1,6 @@
[DEFAULT]
support-files =
iframe_broadcastchannel.html
broadcastchannel_pref_worker.js
broadcastchannel_sharedWorker.js
broadcastchannel_worker.js
broadcastchannel_worker_alive.js
@ -17,7 +16,6 @@ support-files =
[test_broadcastchannel_basic.html]
[test_broadcastchannel_close.html]
[test_broadcastchannel_self.html]
[test_broadcastchannel_pref.html]
[test_broadcastchannel_sharedWorker.html]
[test_broadcastchannel_worker.html]
[test_broadcastchannel_worker_alive.html]

View File

@ -130,7 +130,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>

View File

@ -55,7 +55,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>

View File

@ -54,7 +54,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>

View File

@ -84,8 +84,7 @@ var steps = [
},
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true],
["network.disable.ipc.security", true],
SpecialPowers.pushPrefEnv({"set": [["network.disable.ipc.security", true],
["browser.pagethumbnails.capturing_disabled", true],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.browser_frames.oop_by_default", false],

View File

@ -84,8 +84,7 @@ var steps = [
},
function() {
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true],
["network.disable.ipc.security", true],
SpecialPowers.pushPrefEnv({"set": [["network.disable.ipc.security", true],
["browser.pagethumbnails.capturing_disabled", true],
["dom.mozBrowserFramesEnabled", true],
["dom.ipc.browser_frames.oop_by_default", false],

View File

@ -1,72 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test for BroadcastChannel</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<div id="content"></div>
<script type="application/javascript">
function testNoPref() {
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", false]]}, function() {
ok(!("BroadcastChannel" in window), "BroadcastChannel should not exist");
runTests();
});
}
function testPref() {
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, function() {
ok("BroadcastChannel" in window, "BroadcastChannel should exist");
runTests();
});
}
function testNoPrefWorker() {
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", false]]}, function() {
var worker = new Worker("broadcastchannel_pref_worker.js");
worker.onmessage = function(event) {
ok(!event.data.exists, "BroadcastChannel should not exist in workers");
runTests();
}
worker.postMessage('go!');
});
}
function testPrefWorker() {
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, function() {
var worker = new Worker("broadcastchannel_pref_worker.js");
worker.onmessage = function(event) {
ok(event.data.exists, "BroadcastChannel should exist in workers");
runTests();
}
worker.postMessage('go!');
});
}
var tests = [
testNoPref,
testPref,
testNoPrefWorker,
testPrefWorker
];
function runTests() {
if (tests.length == 0) {
SimpleTest.finish();
return;
}
var test = tests.shift();
test();
}
SimpleTest.waitForExplicitFinish();
runTests();
</script>
</body>
</html>

View File

@ -109,7 +109,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>

View File

@ -30,7 +30,7 @@ function runTest() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
runTest();
</script>
</body>

View File

@ -44,8 +44,7 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true],
["dom.workers.sharedWorkers.enabled", true]]}, runTests);
SpecialPowers.pushPrefEnv({"set": [["dom.workers.sharedWorkers.enabled", true]]}, runTests);
</script>
</pre>

View File

@ -54,7 +54,7 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTests);
runTests();
</script>
</pre>

View File

@ -48,7 +48,7 @@ function runTests() {
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTests);
runTests();
</script>
</pre>

View File

@ -41,7 +41,15 @@ if (!('BrowserElementIsPreloaded' in this)) {
} catch (e) {
}
}
}
if(Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
// general content apps
if (isTopBrowserElement(docShell)) {
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
}
} else {
// rocketbar in system app and other in-process case (ex. B2G desktop client)
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
}

View File

@ -8,6 +8,8 @@
dump("###################################### BrowserElementCopyPaste.js loaded\n");
let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
let CopyPasteAssistent = {
COMMAND_MAP: {
'cut': 'cmd_cut',
@ -81,6 +83,13 @@ let CopyPasteAssistent = {
detail.rect.left += currentRect.left;
detail.rect.right += currentRect.left;
currentWindow = currentWindow.realFrameElement.ownerDocument.defaultView;
let targetDocShell = currentWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation);
if(targetDocShell.isBrowserOrApp) {
break;
}
}
sendAsyncMsg('caretstatechanged', detail);

View File

@ -5031,21 +5031,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
return NS_ERROR_DOM_SYNTAX_ERR;
}
IntRect srcRect(0, 0, mWidth, mHeight);
IntRect destRect(aX, aY, aWidth, aHeight);
IntRect srcReadRect = srcRect.Intersect(destRect);
RefPtr<DataSourceSurface> readback;
DataSourceSurface::MappedSurface rawData;
if (!srcReadRect.IsEmpty() && !mZero) {
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (snapshot) {
readback = snapshot->GetDataSurface();
}
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
JS::Rooted<JSObject*> darray(aCx, JS_NewUint8ClampedArray(aCx, len.value()));
if (!darray) {
return NS_ERROR_OUT_OF_MEMORY;
@ -5056,6 +5041,21 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
return NS_OK;
}
IntRect srcRect(0, 0, mWidth, mHeight);
IntRect destRect(aX, aY, aWidth, aHeight);
IntRect srcReadRect = srcRect.Intersect(destRect);
RefPtr<DataSourceSurface> readback;
DataSourceSurface::MappedSurface rawData;
if (!srcReadRect.IsEmpty()) {
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (snapshot) {
readback = snapshot->GetDataSurface();
}
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
IntRect dstWriteRect = srcReadRect;
dstWriteRect.MoveBy(-aX, -aY);
@ -5074,10 +5074,6 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
srcStride = aWidth * 4;
}
// NOTE! dst is the same as src, and this relies on reading
// from src and advancing that ptr before writing to dst.
// NOTE! I'm not sure that it is, I think this comment might have been
// inherited from Thebes canvas and is no longer true
uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
if (mOpaque) {

View File

@ -804,6 +804,15 @@ pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Premultiply, float
dst[2] = src[2] * scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGB32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
dst[0] = src[0] * scaleFactor;
dst[1] = src[1] * scaleFactor;
dst[2] = src[2] * scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
{
@ -826,11 +835,11 @@ pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Premultiply, floa
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGBA32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
dst[0] = src[0] * scaleFactor;
dst[1] = src[1] * scaleFactor;
dst[2] = src[2] * scaleFactor;
dst[3] = src[3];
float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
dst[0] = src[0] * scaleFactor;
dst[1] = src[1] * scaleFactor;
dst[2] = src[2] * scaleFactor;
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
@ -845,6 +854,12 @@ pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Premultiply, float,
dst[0] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::A32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
dst[0] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
{
@ -858,6 +873,13 @@ pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Premultiply, float,
dst[0] = src[0] * scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::R32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
dst[0] = src[0] * scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::None, float, float>(const float* __restrict src, float* __restrict dst)
{
@ -873,6 +895,14 @@ pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Premultiply, float,
dst[1] = scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RA32F, WebGLTexelPremultiplicationOp::Unpremultiply, float, float>(const float* __restrict src, float* __restrict dst)
{
float scaleFactor = src[3] ? 1.0f / src[3] : 1.0f;
dst[0] = src[0] * scaleFactor;
dst[1] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
@ -890,6 +920,16 @@ pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Premultiply, uint1
dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGB16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float unpackedAlpha = unpackFromFloat16(src[3]);
float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
@ -909,6 +949,17 @@ pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Premultiply, uint
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RGBA16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float unpackedAlpha = unpackFromFloat16(src[3]);
float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
dst[1] = packToFloat16(unpackFromFloat16(src[1]) * scaleFactor);
dst[2] = packToFloat16(unpackFromFloat16(src[2]) * scaleFactor);
dst[3] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
@ -921,6 +972,12 @@ pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_
dst[0] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::A16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
dst[0] = src[3];
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
@ -934,6 +991,14 @@ pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Premultiply, uint16_
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::R16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float unpackedAlpha = unpackFromFloat16(src[3]);
float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::None, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
@ -949,6 +1014,15 @@ pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Premultiply, uint16
dst[1] = scaleFactor;
}
template<> MOZ_ALWAYS_INLINE void
pack<WebGLTexelFormat::RA16F, WebGLTexelPremultiplicationOp::Unpremultiply, uint16_t, uint16_t>(const uint16_t* __restrict src, uint16_t* __restrict dst)
{
float unpackedAlpha = unpackFromFloat16(src[3]);
float scaleFactor = unpackedAlpha ? 1.0f / unpackedAlpha : 1.0f;
dst[0] = packToFloat16(unpackFromFloat16(src[0]) * scaleFactor);
dst[1] = src[3];
}
/****** END CODE SHARED WITH WEBKIT ******/
template<typename SrcType, typename DstType> MOZ_ALWAYS_INLINE void

View File

@ -4561,7 +4561,8 @@ HTMLMediaElement::SetMediaKeys(mozilla::dom::MediaKeys* aMediaKeys,
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
nsRefPtr<DetailedPromise> promise = DetailedPromise::Create(global, aRv);
nsRefPtr<DetailedPromise> promise = DetailedPromise::Create(global, aRv,
NS_LITERAL_CSTRING("HTMLMediaElement.setMediaKeys"));
if (aRv.Failed()) {
return nullptr;
}

View File

@ -203,26 +203,6 @@ HTMLTrackElement::LoadResource()
mChannel = nullptr;
}
rv = nsContentUtils::GetSecurityManager()->
CheckLoadURIWithPrincipal(NodePrincipal(), uri,
nsIScriptSecurityManager::STANDARD);
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_INTERNAL_TRACK,
uri,
NodePrincipal(),
static_cast<Element*>(this),
NS_LITERAL_CSTRING("text/vtt"), // mime type
nullptr, // extra
&shouldLoad,
nsContentUtils::GetContentPolicy(),
nsContentUtils::GetSecurityManager());
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
if (NS_CP_REJECTED(shouldLoad)) {
return;
}
// We may already have a TextTrack at this point if GetTrack() has already
// been called. This happens, for instance, if script tries to get the
// TextTrack before its mTrackElement has been bound to the DOM tree.
@ -235,7 +215,7 @@ HTMLTrackElement::LoadResource()
rv = NS_NewChannel(getter_AddRefs(channel),
uri,
static_cast<Element*>(this),
nsILoadInfo::SEC_NORMAL,
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS,
nsIContentPolicy::TYPE_INTERNAL_TRACK,
loadGroup);
@ -247,7 +227,7 @@ HTMLTrackElement::LoadResource()
channel->SetNotificationCallbacks(mListener);
LOG(LogLevel::Debug, ("opening webvtt channel"));
rv = channel->AsyncOpen(mListener, nullptr);
rv = channel->AsyncOpen2(mListener);
NS_ENSURE_TRUE_VOID(NS_SUCCEEDED(rv));
mChannel = channel;

View File

@ -5,6 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
XPIDL_SOURCES += [
'nsIPushClient.idl',
'nsIPushNotificationService.idl',
'nsIPushObserverNotification.idl',
]

View File

@ -0,0 +1,53 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIPrincipal;
/**
* Satisfies contracts similar to the Push API specification.
*
* If status is not NS_OK, endpoint should be ignored. When subscribing to
* a new endpoint, endpoint will be a valid URL on success, when querying for
* the presence of an existing subscription, this will be an empty string if
* the calling {scope+principal} does not currently have an associated
* endpoint.
*/
[scriptable, uuid(0bcac389-a3ac-44a4-97fb-b50e41a46146)]
interface nsIPushEndpointCallback : nsISupports
{
void onPushEndpoint(in nsresult status, in DOMString endpoint);
};
/**
* Satisfies contracts similar to the Push API specification.
*
* If status is not NS_OK, there was a problem unsubscribing and success should
* be ignored. success is true if unsubscribing was successful and false if
* there was no subscription.
*/
[scriptable, uuid(9522934d-e844-4f2f-81e8-48c3947b44de)]
interface nsIUnsubscribeResultCallback : nsISupports
{
void onUnsubscribe(in nsresult status, in bool success);
};
/**
* Provides an XPIDL component to interact with the PushService from content
* processes. Unlike PushManager, this has no relationship to the DOM and is
* not exposed to web content. This was added to allow ServiceWorkers to use
* it by dispatching appropriate runnables to the main thread.
*/
[scriptable, uuid(6622d599-439e-4ad1-af32-c941bd2b9968)]
interface nsIPushClient : nsISupports
{
void subscribe(in DOMString scope, in nsIPrincipal principal, in nsIPushEndpointCallback callback);
void unsubscribe(in DOMString scope, in nsIPrincipal principal, in nsIUnsubscribeResultCallback callback);
void getSubscription(in DOMString scope, in nsIPrincipal principal, in nsIPushEndpointCallback callback);
};

View File

@ -1121,12 +1121,15 @@ ContentParent::RecvGetBlocklistState(const uint32_t& aPluginId,
nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
if (!pluginHost) {
NS_WARNING("Plugin host not found");
return false;
}
nsPluginTag* tag = pluginHost->PluginWithId(aPluginId);
if (!tag) {
return false;
// Default state is blocked anyway
NS_WARNING("Plugin tag not found. This should never happen, but to avoid a crash we're forcibly blocking it");
return true;
}
return NS_SUCCEEDED(tag->GetBlocklistState(aState));

View File

@ -750,7 +750,7 @@ HangMonitoredProcess::GetPluginName(nsACString& aPluginName)
return NS_ERROR_UNEXPECTED;
}
aPluginName = tag->mName;
aPluginName = tag->Name();
return NS_OK;
}

View File

@ -11,5 +11,4 @@ toolkit.jar:
content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js)
* content/global/BrowserElementPanningAPZDisabled.js (../browser-element/BrowserElementPanningAPZDisabled.js)
content/global/manifestMessages.js (manifestMessages.js)
content/global/PushServiceChildPreload.js (../push/PushServiceChildPreload.js)
content/global/preload.js (preload.js)

View File

@ -217,6 +217,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mDecodeToSeekTarget(false),
mCurrentTimeBeforeSeek(0),
mCorruptFrames(30),
mDecodingFirstFrame(true),
mDisabledHardwareAcceleration(false),
mDecodingFrozenAtStateDecoding(false),
mSentLoadedMetadataEvent(false),
@ -441,7 +442,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
HaveEnoughDecodedVideo());
return IsVideoDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(mState == DECODER_STATE_DECODING_FIRSTFRAME &&
(IsDecodingFirstFrame() &&
IsVideoDecoding() && VideoQueue().GetSize() == 0) ||
(!mMinimizePreroll && !HaveEnoughDecodedVideo()));
}
@ -451,7 +452,7 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
if (IsDecodingFirstFrame()) {
return false;
}
MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
@ -508,7 +509,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
return IsAudioDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(mState == DECODER_STATE_DECODING_FIRSTFRAME &&
(IsDecodingFirstFrame() &&
IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(!mMinimizePreroll &&
!HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate) &&
@ -560,12 +561,6 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
(audio ? audio->mDiscontinuity : 0));
switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: {
Push(audio);
MaybeFinishDecodeFirstFrame();
return;
}
case DECODER_STATE_BUFFERING: {
// If we're buffering, this may be the sample we need to stop buffering.
// Save it and schedule the state machine.
@ -576,6 +571,9 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
case DECODER_STATE_DECODING: {
Push(audio);
if (MaybeFinishDecodeFirstFrame()) {
return;
}
if (mIsAudioPrerolling && DonePrerollingAudio()) {
StopPrerollingAudio();
}
@ -781,13 +779,11 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
StopPrerollingVideo();
}
switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: {
MaybeFinishDecodeFirstFrame();
return;
}
case DECODER_STATE_BUFFERING:
case DECODER_STATE_DECODING: {
if (MaybeFinishDecodeFirstFrame()) {
return;
}
CheckIfDecodeComplete();
mDecoder->GetReentrantMonitor().NotifyAll();
// Tell AudioSink to wake up for audio queue is finished.
@ -821,18 +817,26 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
}
}
void
bool
MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if ((IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
if (!IsDecodingFirstFrame() ||
(IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(IsVideoDecoding() && VideoQueue().GetSize() == 0)) {
return;
return false;
}
if (NS_FAILED(FinishDecodeFirstFrame())) {
DecodeError();
FinishDecodeFirstFrame();
if (!mQueuedSeek.Exists()) {
return false;
}
// We can now complete the pending seek.
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
return true;
}
void
@ -852,12 +856,6 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
(video ? video->mDiscontinuity : 0));
switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: {
Push(video);
MaybeFinishDecodeFirstFrame();
return;
}
case DECODER_STATE_BUFFERING: {
// If we're buffering, this may be the sample we need to stop buffering.
// Save it and schedule the state machine.
@ -868,6 +866,9 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
case DECODER_STATE_DECODING: {
Push(video);
if (MaybeFinishDecodeFirstFrame()) {
return;
}
if (mIsVideoPrerolling && DonePrerollingVideo()) {
StopPrerollingVideo();
}
@ -892,7 +893,8 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
return;
}
TimeDuration decodeTime = TimeStamp::Now() - mVideoDecodeStartTime;
if (THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
if (!IsDecodingFirstFrame() &&
THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
!HasLowUndecodedData())
{
mLowAudioThresholdUsecs =
@ -1144,7 +1146,6 @@ static const char* const gMachineStateStr[] = {
"DECODING_METADATA",
"WAIT_FOR_RESOURCES",
"WAIT_FOR_CDM",
"DECODING_FIRSTFRAME",
"DORMANT",
"DECODING",
"SEEKING",
@ -1274,6 +1275,7 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
mDecodingFrozenAtStateDecoding = true;
ScheduleStateMachine();
mCurrentPosition = 0;
mDecodingFirstFrame = true;
SetState(DECODER_STATE_DECODING_NONE);
mDecoder->GetReentrantMonitor().NotifyAll();
}
@ -1319,11 +1321,32 @@ void MediaDecoderStateMachine::StartDecoding()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState == DECODER_STATE_DECODING) {
if (mState == DECODER_STATE_DECODING && !mDecodingFirstFrame) {
return;
}
SetState(DECODER_STATE_DECODING);
if (mDecodingFirstFrame &&
(IsRealTime() || mSentFirstFrameLoadedEvent)) {
if (IsRealTime()) {
FinishDecodeFirstFrame();
} else {
// We're resuming from dormant state, so we don't need to request
// the first samples in order to determine the media start time,
// we have the start time from last time we loaded.
// FinishDecodeFirstFrame will be launched upon completion of the seek when
// we have data ready to play.
MOZ_ASSERT(mQueuedSeek.Exists() && mSentFirstFrameLoadedEvent,
"Return from dormant must have queued seek");
}
if (mQueuedSeek.Exists()) {
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
return;
}
}
mDecodeStartTime = TimeStamp::Now();
CheckIfDecodeComplete();
@ -1353,8 +1376,7 @@ void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
ScheduleStateMachine();
} else if (mState == DECODER_STATE_WAIT_FOR_CDM &&
!mReader->IsWaitingOnCDMResource()) {
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
EnqueueDecodeFirstFrameTask();
StartDecoding();
}
}
@ -1454,7 +1476,8 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
"We should have got duration already");
if (mState < DECODER_STATE_DECODING) {
if (mState < DECODER_STATE_DECODING ||
(IsDecodingFirstFrame() && !mReader->ForceZeroStartTime())) {
DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
mQueuedSeek.RejectIfExists(__func__);
mQueuedSeek.mTarget = aTarget;
@ -1484,19 +1507,6 @@ void MediaDecoderStateMachine::StopAudioThread()
mAudioSinkPromise.DisconnectIfExists();
}
nsresult
MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
nsCOMPtr<nsIRunnable> task(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame));
OwnerThread()->Dispatch(task.forget());
return NS_OK;
}
void
MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
{
@ -1504,7 +1514,6 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
AssertCurrentThreadInMonitor();
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return;
@ -1653,7 +1662,6 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
IsAudioDecoding(), AudioRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return NS_OK;
@ -1725,7 +1733,6 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
IsVideoDecoding(), VideoRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return NS_OK;
@ -1862,7 +1869,7 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME,
NS_ASSERTION(mState >= DECODER_STATE_DECODING && !IsDecodingFirstFrame(),
"Must have loaded first frame for mBuffered to be valid");
// If we don't have a duration, mBuffered is probably not going to have
@ -1993,8 +2000,8 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
return;
}
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
EnqueueDecodeFirstFrameTask();
StartDecoding();
ScheduleStateMachine();
}
@ -2045,60 +2052,19 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
mSentFirstFrameLoadedEvent = true;
}
bool
MediaDecoderStateMachine::IsDecodingFirstFrame()
{
return mState == DECODER_STATE_DECODING && mDecodingFirstFrame;
}
void
MediaDecoderStateMachine::CallDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState != DECODER_STATE_DECODING_FIRSTFRAME) {
return;
}
if (NS_FAILED(DecodeFirstFrame())) {
DECODER_WARN("Decode failed to start, shutting down decoder");
DecodeError();
}
}
nsresult
MediaDecoderStateMachine::DecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
DECODER_LOG("DecodeFirstFrame started");
if (IsRealTime()) {
nsresult res = FinishDecodeFirstFrame();
NS_ENSURE_SUCCESS(res, res);
} else if (mSentFirstFrameLoadedEvent) {
// We're resuming from dormant state, so we don't need to request
// the first samples in order to determine the media start time,
// we have the start time from last time we loaded.
nsresult res = FinishDecodeFirstFrame();
NS_ENSURE_SUCCESS(res, res);
} else {
if (HasAudio()) {
RequestAudioData();
}
if (HasVideo()) {
RequestVideoData();
}
}
return NS_OK;
}
nsresult
MediaDecoderStateMachine::FinishDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
DECODER_LOG("FinishDecodeFirstFrame");
if (IsShutdown()) {
return NS_ERROR_FAILURE;
}
if (!IsRealTime() && !mSentFirstFrameLoadedEvent) {
RenderVideoFrames(1);
}
@ -2112,7 +2078,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
"transportSeekable=%d, mediaSeekable=%d",
Duration().ToMicroseconds(), mDecoder->IsTransportSeekable(), mDecoder->IsMediaSeekable());
if (HasAudio() && !HasVideo()) {
if (HasAudio() && !HasVideo() && !mSentFirstFrameLoadedEvent) {
// We're playing audio only. We don't need to worry about slow video
// decodes causing audio underruns, so don't buffer so much audio in
// order to reduce memory usage.
@ -2133,16 +2099,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
}
EnqueueFirstFrameLoadedEvent();
if (mQueuedSeek.Exists()) {
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
} else if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
// StartDecoding() will also check if decode is completed.
StartDecoding();
}
return NS_OK;
mDecodingFirstFrame = false;
}
void
@ -2175,6 +2132,12 @@ MediaDecoderStateMachine::SeekCompleted()
}
mPlayDuration = newCurrentTime;
if (mDecodingFirstFrame) {
// We were resuming from dormant, or initiated a seek early.
// We can fire loadeddata now.
FinishDecodeFirstFrame();
}
// Change state to DECODING or COMPLETED now. SeekingStopped will
// call MediaDecoderStateMachine::Seek to reset our state to SEEKING
// if we need to seek again.
@ -2338,12 +2301,12 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
return NS_OK;
}
case DECODER_STATE_DECODING_FIRSTFRAME: {
// DECODER_STATE_DECODING_FIRSTFRAME will be started by OnMetadataRead.
return NS_OK;
}
case DECODER_STATE_DECODING: {
if (IsDecodingFirstFrame()) {
// We haven't completed decoding our first frames, we can't start
// playback yet.
return NS_OK;
}
if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying())
{
// We're playing, but the element/decoder is in paused state. Stop
@ -2890,7 +2853,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus()
MediaDecoderOwner::NextFrameStatus status;
const char* statusString;
if (mState <= DECODER_STATE_DECODING_FIRSTFRAME) {
if (mState <= DECODER_STATE_WAIT_FOR_CDM || IsDecodingFirstFrame()) {
status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
statusString = "NEXT_FRAME_UNAVAILABLE";
} else if (IsBuffering()) {

View File

@ -138,7 +138,6 @@ public:
DECODER_STATE_DECODING_METADATA,
DECODER_STATE_WAIT_FOR_RESOURCES,
DECODER_STATE_WAIT_FOR_CDM,
DECODER_STATE_DECODING_FIRSTFRAME,
DECODER_STATE_DORMANT,
DECODER_STATE_DECODING,
DECODER_STATE_SEEKING,
@ -407,8 +406,6 @@ protected:
MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
nsresult FinishDecodeFirstFrame();
// True if our buffers of decoded audio are not full, and we should
// decode more.
bool NeedToDecodeAudio();
@ -555,11 +552,6 @@ protected:
void EnqueueFirstFrameLoadedEvent();
// Dispatches a task to the state machine thread to begin decoding content.
// This is threadsafe and can be called on any thread.
// The decoder monitor must be held.
nsresult EnqueueDecodeFirstFrameTask();
// Clears any previous seeking state and initiates a new see on the decoder.
// The decoder monitor must be held.
void InitiateSeek();
@ -617,16 +609,14 @@ protected:
void OnMetadataRead(MetadataHolder* aMetadata);
void OnMetadataNotRead(ReadMetadataFailureReason aReason);
// Initiate first content decoding. Called on the state machine thread.
// The decoder monitor must be held with exactly one lock count.
nsresult DecodeFirstFrame();
// Wraps the call to DecodeFirstFrame(), signals a DecodeError() on failure.
void CallDecodeFirstFrame();
// Checks whether we're finished decoding first audio and/or video packets,
// and switches to DECODING state if so.
void MaybeFinishDecodeFirstFrame();
// Checks whether we're finished decoding first audio and/or video packets.
// If so will trigger firing loadeddata event.
// If there are any queued seek, will change state to DECODER_STATE_SEEKING
// and return true.
bool MaybeFinishDecodeFirstFrame();
// Return true if we are currently decoding the first frames.
bool IsDecodingFirstFrame();
void FinishDecodeFirstFrame();
// Seeks to mSeekTarget. Called on the decode thread. The decoder monitor
// must be held with exactly one lock count.
@ -1262,6 +1252,10 @@ private:
mozilla::RollingMean<uint32_t, uint32_t> mCorruptFrames;
// True if we need to call FinishDecodeFirstFrame() upon frame decoding
// successeeding.
bool mDecodingFirstFrame;
bool mDisabledHardwareAcceleration;
// mDecodingFrozenAtStateDecoding: turn on/off at

View File

@ -715,6 +715,7 @@ MediaFormatReader::NotifyDrainComplete(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
LOG("%s", TrackTypeToStr(aTrack));
if (!decoder.mOutputRequested) {
LOG("MediaFormatReader called DrainComplete() before flushing, ignoring.");
return;
@ -983,6 +984,11 @@ MediaFormatReader::DrainDecoder(TrackType aTrack)
return;
}
decoder.mOutputRequested = true;
if (decoder.mNumSamplesInput == decoder.mNumSamplesOutput) {
// No frames to drain.
NotifyDrainComplete(aTrack);
return;
}
decoder.mDecoder->Drain();
decoder.mDraining = true;
LOG("Requesting %s decoder to drain", TrackTypeToStr(aTrack));

View File

@ -6,12 +6,15 @@
#include "DetailedPromise.h"
#include "mozilla/dom/DOMException.h"
#include "nsPrintfCString.h"
namespace mozilla {
namespace dom {
DetailedPromise::DetailedPromise(nsIGlobalObject* aGlobal)
DetailedPromise::DetailedPromise(nsIGlobalObject* aGlobal,
const nsACString& aName)
: Promise(aGlobal)
, mName(aName)
, mResponded(false)
{
}
@ -21,25 +24,16 @@ DetailedPromise::~DetailedPromise()
MOZ_ASSERT(mResponded == IsPending());
}
static void
LogToConsole(const nsAString& aMsg)
{
nsCOMPtr<nsIConsoleService> console(
do_GetService("@mozilla.org/consoleservice;1"));
if (!console) {
NS_WARNING("Failed to log message to console.");
return;
}
nsAutoString msg(aMsg);
console->LogStringMessage(msg.get());
}
void
DetailedPromise::MaybeReject(nsresult aArg, const nsACString& aReason)
{
nsPrintfCString msg("%s promise rejected 0x%x '%s'", mName.get(), aArg,
PromiseFlatCString(aReason).get());
EME_LOG(msg.get());
mResponded = true;
LogToConsole(NS_ConvertUTF8toUTF16(aReason));
LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg));
nsRefPtr<DOMException> exception =
DOMException::Create(aArg, aReason);
@ -53,9 +47,11 @@ DetailedPromise::MaybeReject(ErrorResult&, const nsACString& aReason)
}
/* static */ already_AddRefed<DetailedPromise>
DetailedPromise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
DetailedPromise::Create(nsIGlobalObject* aGlobal,
ErrorResult& aRv,
const nsACString& aName)
{
nsRefPtr<DetailedPromise> promise = new DetailedPromise(aGlobal);
nsRefPtr<DetailedPromise> promise = new DetailedPromise(aGlobal, aName);
promise->CreateWrapper(aRv);
return aRv.Failed() ? nullptr : promise.forget();
}

View File

@ -8,6 +8,7 @@
#define __DetailedPromise_h__
#include "mozilla/dom/Promise.h"
#include "EMEUtils.h"
namespace mozilla {
namespace dom {
@ -21,11 +22,12 @@ class DetailedPromise : public Promise
{
public:
static already_AddRefed<DetailedPromise>
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv, const nsACString& aName);
template <typename T>
void MaybeResolve(const T& aArg)
{
EME_LOG("%s promise resolved", mName.get());
mResponded = true;
Promise::MaybeResolve<T>(aArg);
}
@ -37,9 +39,10 @@ public:
void MaybeReject(ErrorResult&, const nsACString& aReason);
private:
explicit DetailedPromise(nsIGlobalObject* aGlobal);
explicit DetailedPromise(nsIGlobalObject* aGlobal, const nsACString& aName);
virtual ~DetailedPromise();
nsCString mName;
bool mResponded;
};

View File

@ -5,6 +5,8 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/EMEUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIConsoleService.h"
namespace mozilla {
@ -109,4 +111,17 @@ ParseKeySystem(const nsAString& aInputKeySystem,
return false;
}
void
LogToBrowserConsole(const nsAString& aMsg)
{
nsCOMPtr<nsIConsoleService> console(
do_GetService("@mozilla.org/consoleservice;1"));
if (!console) {
NS_WARNING("Failed to log message to console.");
return;
}
nsAutoString msg(aMsg);
console->LogStringMessage(msg.get());
}
} // namespace mozilla

View File

@ -51,6 +51,9 @@ bool ParseKeySystem(const nsAString& aKeySystem,
nsAString& aOutKeySystem,
int32_t& aOutMinCDMVersion);
void
LogToBrowserConsole(const nsAString& aMsg);
} // namespace mozilla
#endif // EME_LOG_H_

View File

@ -60,7 +60,7 @@ MediaKeySession::MediaKeySession(JSContext* aCx,
if (aRv.Failed()) {
return;
}
mClosed = MakePromise(aRv);
mClosed = MakePromise(aRv, NS_LITERAL_CSTRING("MediaKeys.createSession"));
}
void MediaKeySession::SetSessionId(const nsAString& aSessionId)
@ -169,7 +169,8 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
const ArrayBufferViewOrArrayBuffer& aInitData,
ErrorResult& aRv)
{
nsRefPtr<DetailedPromise> promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeySession.generateRequest")));
if (aRv.Failed()) {
return nullptr;
}
@ -226,7 +227,8 @@ MediaKeySession::GenerateRequest(const nsAString& aInitDataType,
already_AddRefed<Promise>
MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
{
nsRefPtr<DetailedPromise> promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeySession.load")));
if (aRv.Failed()) {
return nullptr;
}
@ -269,7 +271,8 @@ MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
already_AddRefed<Promise>
MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv)
{
nsRefPtr<DetailedPromise> promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeySession.update")));
if (aRv.Failed()) {
return nullptr;
}
@ -320,7 +323,8 @@ MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResu
already_AddRefed<Promise>
MediaKeySession::Close(ErrorResult& aRv)
{
nsRefPtr<DetailedPromise> promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeySession.close")));
if (aRv.Failed()) {
return nullptr;
}
@ -362,7 +366,8 @@ MediaKeySession::IsClosed() const
already_AddRefed<Promise>
MediaKeySession::Remove(ErrorResult& aRv)
{
nsRefPtr<DetailedPromise> promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeySession.remove")));
if (aRv.Failed()) {
return nullptr;
}
@ -447,7 +452,7 @@ MediaKeySession::Token() const
}
already_AddRefed<DetailedPromise>
MediaKeySession::MakePromise(ErrorResult& aRv)
MediaKeySession::MakePromise(ErrorResult& aRv, const nsACString& aName)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
@ -455,7 +460,7 @@ MediaKeySession::MakePromise(ErrorResult& aRv)
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
return DetailedPromise::Create(global, aRv);
return DetailedPromise::Create(global, aRv, aName);
}
} // namespace dom

View File

@ -98,7 +98,8 @@ private:
~MediaKeySession();
void UpdateKeyStatusMap();
already_AddRefed<DetailedPromise> MakePromise(ErrorResult& aRv);
already_AddRefed<DetailedPromise> MakePromise(ErrorResult& aRv,
const nsACString& aName);
nsRefPtr<DetailedPromise> mClosed;

View File

@ -13,6 +13,7 @@
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#endif
#include "nsPrintfCString.h"
namespace mozilla {
namespace dom {
@ -106,7 +107,17 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
}
nsAutoCString message;
MediaKeySystemStatus status = MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion, message);
MediaKeySystemStatus status =
MediaKeySystemAccess::GetKeySystemStatus(keySystem, minCdmVersion, message);
nsPrintfCString msg("MediaKeySystemAccess::GetKeySystemStatus(%s, minVer=%d) "
"result=%s msg='%s'",
NS_ConvertUTF16toUTF8(keySystem).get(),
minCdmVersion,
MediaKeySystemStatusValues::strings[(size_t)status].value,
message.get());
LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg));
if ((status == MediaKeySystemStatus::Cdm_not_installed ||
status == MediaKeySystemStatus::Cdm_insufficient_version) &&
keySystem.EqualsLiteral("com.adobe.primetime")) {
@ -139,8 +150,7 @@ MediaKeySystemAccessManager::Request(DetailedPromise* aPromise,
// chrome, so we can show some UI to explain how the user can rectify
// the situation.
MediaKeySystemAccess::NotifyObservers(mWindow, keySystem, status);
aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
NS_LITERAL_CSTRING("The key system has been disabled by the user"));
aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, message);
return;
}
aPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR,

View File

@ -147,8 +147,8 @@ MediaKeys::GetKeySystem(nsString& retval) const
already_AddRefed<DetailedPromise>
MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv)
{
nsRefPtr<DetailedPromise>
promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeys.setServerCertificate")));
if (aRv.Failed()) {
return nullptr;
}
@ -172,7 +172,7 @@ MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, Error
}
already_AddRefed<DetailedPromise>
MediaKeys::MakePromise(ErrorResult& aRv)
MediaKeys::MakePromise(ErrorResult& aRv, const nsACString& aName)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
if (!global) {
@ -180,7 +180,7 @@ MediaKeys::MakePromise(ErrorResult& aRv)
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
return DetailedPromise::Create(global, aRv);
return DetailedPromise::Create(global, aRv, aName);
}
PromiseId
@ -295,8 +295,8 @@ MediaKeys::ResolvePromise(PromiseId aId)
already_AddRefed<DetailedPromise>
MediaKeys::Init(ErrorResult& aRv)
{
nsRefPtr<DetailedPromise>
promise(MakePromise(aRv));
nsRefPtr<DetailedPromise> promise(MakePromise(aRv,
NS_LITERAL_CSTRING("MediaKeys::Init()")));
if (aRv.Failed()) {
return nullptr;
}

View File

@ -99,7 +99,8 @@ public:
CDMProxy* GetCDMProxy() { return mProxy; }
// Makes a new promise, or nullptr on failure.
already_AddRefed<DetailedPromise> MakePromise(ErrorResult& aRv);
already_AddRefed<DetailedPromise> MakePromise(ErrorResult& aRv,
const nsACString& aName);
// Stores promise in mPromises, returning an ID that can be used to retrieve
// it later. The ID is passed to the CDM, so that it can signal specific
// promises to be resolved.

View File

@ -28,6 +28,8 @@ GMPAudioDecoderParent::GMPAudioDecoderParent(GMPContentParent* aPlugin)
: mIsOpen(false)
, mShuttingDown(false)
, mActorDestroyed(false)
, mIsAwaitingResetComplete(false)
, mIsAwaitingDrainComplete(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
{
@ -109,6 +111,8 @@ GMPAudioDecoderParent::Reset()
return NS_ERROR_FAILURE;
}
mIsAwaitingResetComplete = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
@ -127,6 +131,8 @@ GMPAudioDecoderParent::Drain()
return NS_ERROR_FAILURE;
}
mIsAwaitingDrainComplete = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
@ -138,6 +144,11 @@ GMPAudioDecoderParent::Close()
LOGD(("%s: %p", __FUNCTION__, this));
MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread());
// Ensure if we've received a Close while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the close. This seems unlikely to happen, but better to be careful.
UnblockResetAndDrain();
// Consumer is done with us; we can shut down. No more callbacks should
// be made to mCallback. Note: do this before Shutdown()!
mCallback = nullptr;
@ -163,6 +174,11 @@ GMPAudioDecoderParent::Shutdown()
}
mShuttingDown = true;
// Ensure if we've received a shutdown while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the shutdown.
UnblockResetAndDrain();
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
@ -183,6 +199,12 @@ GMPAudioDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
{
mIsOpen = false;
mActorDestroyed = true;
// Ensure if we've received a destroy while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the error.
UnblockResetAndDrain();
if (mCallback) {
// May call Close() (and Shutdown()) immediately or with a delay
mCallback->Terminated();
@ -230,6 +252,11 @@ GMPAudioDecoderParent::RecvDrainComplete()
return false;
}
if (!mIsAwaitingDrainComplete) {
return true;
}
mIsAwaitingDrainComplete = false;
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->DrainComplete();
@ -243,6 +270,11 @@ GMPAudioDecoderParent::RecvResetComplete()
return false;
}
if (!mIsAwaitingResetComplete) {
return true;
}
mIsAwaitingResetComplete = false;
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->ResetComplete();
@ -256,6 +288,11 @@ GMPAudioDecoderParent::RecvError(const GMPErr& aError)
return false;
}
// Ensure if we've received an error while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the error.
UnblockResetAndDrain();
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->Error(aError);
@ -281,5 +318,23 @@ GMPAudioDecoderParent::Recv__delete__()
return true;
}
void
GMPAudioDecoderParent::UnblockResetAndDrain()
{
if (!mCallback) {
MOZ_ASSERT(!mIsAwaitingResetComplete);
MOZ_ASSERT(!mIsAwaitingDrainComplete);
return;
}
if (mIsAwaitingResetComplete) {
mIsAwaitingResetComplete = false;
mCallback->ResetComplete();
}
if (mIsAwaitingDrainComplete) {
mIsAwaitingDrainComplete = false;
mCallback->DrainComplete();
}
}
} // namespace gmp
} // namespace mozilla

View File

@ -53,9 +53,13 @@ private:
virtual bool RecvShutdown() override;
virtual bool Recv__delete__() override;
void UnblockResetAndDrain();
bool mIsOpen;
bool mShuttingDown;
bool mActorDestroyed;
bool mIsAwaitingResetComplete;
bool mIsAwaitingDrainComplete;
nsRefPtr<GMPContentParent> mPlugin;
GMPAudioDecoderCallbackProxy* mCallback;
};

View File

@ -43,6 +43,8 @@ GMPVideoDecoderParent::GMPVideoDecoderParent(GMPContentParent* aPlugin)
, mIsOpen(false)
, mShuttingDown(false)
, mActorDestroyed(false)
, mIsAwaitingResetComplete(false)
, mIsAwaitingDrainComplete(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
, mVideoHost(this)
@ -67,6 +69,12 @@ GMPVideoDecoderParent::Close()
{
LOGD(("%s: %p", __FUNCTION__, this));
MOZ_ASSERT(!mPlugin || mPlugin->GMPThread() == NS_GetCurrentThread());
// Ensure if we've received a Close while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the close. This seems unlikely to happen, but better to be careful.
UnblockResetAndDrain();
// Consumer is done with us; we can shut down. No more callbacks should
// be made to mCallback. Note: do this before Shutdown()!
mCallback = nullptr;
@ -161,6 +169,8 @@ GMPVideoDecoderParent::Reset()
return NS_ERROR_FAILURE;
}
mIsAwaitingResetComplete = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
@ -179,6 +189,8 @@ GMPVideoDecoderParent::Drain()
return NS_ERROR_FAILURE;
}
mIsAwaitingDrainComplete = true;
// Async IPC, we don't have access to a return value.
return NS_OK;
}
@ -207,6 +219,11 @@ GMPVideoDecoderParent::Shutdown()
}
mShuttingDown = true;
// Ensure if we've received a shutdown while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the shutdown.
UnblockResetAndDrain();
// Notify client we're gone! Won't occur after Close()
if (mCallback) {
mCallback->Terminated();
@ -229,6 +246,11 @@ GMPVideoDecoderParent::ActorDestroy(ActorDestroyReason aWhy)
mActorDestroyed = true;
mVideoHost.DoneWithAPI();
// Ensure if we've received a destroy while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the error.
UnblockResetAndDrain();
if (mCallback) {
// May call Close() (and Shutdown()) immediately or with a delay
mCallback->Terminated();
@ -307,6 +329,11 @@ GMPVideoDecoderParent::RecvDrainComplete()
return false;
}
if (!mIsAwaitingDrainComplete) {
return true;
}
mIsAwaitingDrainComplete = false;
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->DrainComplete();
@ -320,6 +347,11 @@ GMPVideoDecoderParent::RecvResetComplete()
return false;
}
if (!mIsAwaitingResetComplete) {
return true;
}
mIsAwaitingResetComplete = false;
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->ResetComplete();
@ -333,6 +365,11 @@ GMPVideoDecoderParent::RecvError(const GMPErr& aError)
return false;
}
// Ensure if we've received an error while waiting for a ResetComplete
// or DrainComplete notification, we'll unblock the caller before processing
// the error.
UnblockResetAndDrain();
// Ignore any return code. It is OK for this to fail without killing the process.
mCallback->Error(aError);
@ -387,5 +424,23 @@ GMPVideoDecoderParent::Recv__delete__()
return true;
}
void
GMPVideoDecoderParent::UnblockResetAndDrain()
{
if (!mCallback) {
MOZ_ASSERT(!mIsAwaitingResetComplete);
MOZ_ASSERT(!mIsAwaitingDrainComplete);
return;
}
if (mIsAwaitingResetComplete) {
mIsAwaitingResetComplete = false;
mCallback->ResetComplete();
}
if (mIsAwaitingDrainComplete) {
mIsAwaitingDrainComplete = false;
mCallback->DrainComplete();
}
}
} // namespace gmp
} // namespace mozilla

View File

@ -79,9 +79,13 @@ private:
Shmem* aMem) override;
virtual bool Recv__delete__() override;
void UnblockResetAndDrain();
bool mIsOpen;
bool mShuttingDown;
bool mActorDestroyed;
bool mIsAwaitingResetComplete;
bool mIsAwaitingDrainComplete;
nsRefPtr<GMPContentParent> mPlugin;
GMPVideoDecoderCallbackProxy* mCallback;
GMPVideoHostImpl mVideoHost;

View File

@ -95,6 +95,7 @@ H264Converter::Drain()
if (mDecoder) {
return mDecoder->Drain();
}
mCallback->DrainComplete();
return mLastError;
}

View File

@ -13,8 +13,6 @@
#include "mozilla/dom/nsSpeechTask.h"
#include "mozilla/Preferences.h"
#include <sphelper.h>
namespace mozilla {
namespace dom {
@ -226,9 +224,19 @@ SapiService::RegisterVoices()
return false;
}
nsRefPtr<ISpObjectTokenCategory> category;
if (FAILED(CoCreateInstance(CLSID_SpObjectTokenCategory, nullptr, CLSCTX_ALL,
IID_ISpObjectTokenCategory,
getter_AddRefs(category)))) {
return false;
}
if (FAILED(category->SetId(SPCAT_VOICES, FALSE))) {
return false;
}
nsRefPtr<IEnumSpObjectTokens> voiceTokens;
if (FAILED(SpEnumTokens(SPCAT_VOICES, nullptr, nullptr,
getter_AddRefs(voiceTokens)))) {
if (FAILED(category->EnumTokens(nullptr, nullptr,
getter_AddRefs(voiceTokens)))) {
return false;
}
@ -238,11 +246,6 @@ SapiService::RegisterVoices()
break;
}
WCHAR* description = nullptr;
if (FAILED(SpGetDescription(voiceToken, &description))) {
continue;
}
nsRefPtr<ISpDataKey> attributes;
if (FAILED(voiceToken->OpenKey(L"Attributes",
getter_AddRefs(attributes)))) {
@ -258,9 +261,15 @@ SapiService::RegisterVoices()
// name.
nsAutoString hexLcid;
LCID lcid = wcstol(language, nullptr, 16);
CoTaskMemFree(language);
nsAutoString locale;
nsWin32Locale::GetXPLocale(lcid, locale);
WCHAR* description = nullptr;
if (FAILED(voiceToken->GetStringValue(nullptr, &description))) {
continue;
}
nsAutoString uri;
uri.AssignLiteral("urn:moz-tts:sapi:");
uri.Append(description);
@ -269,6 +278,7 @@ SapiService::RegisterVoices()
rv = registry->AddVoice(this, uri, nsDependentString(description), locale,
true);
CoTaskMemFree(description);
if (NS_FAILED(rv)) {
continue;
}

View File

@ -36,11 +36,11 @@ interface nsIClearSiteDataCallback : nsISupports
void callback(in nsresult rv);
};
[scriptable, uuid(2bed7533-50e3-45dd-9e47-102e2c6f5ea8)]
[scriptable, uuid(50677599-323f-4c7d-a450-307bdb7acbf0)]
interface nsIPluginHost : nsISupports
{
/**
* Causes the plugins directory to be searched again for new plugin
* Causes the plugins directory to be searched again for new plugin
* libraries.
*/
void reloadPlugins();
@ -64,6 +64,7 @@ interface nsIPluginHost : nsISupports
*/
const uint32_t EXCLUDE_NONE = 0;
const uint32_t EXCLUDE_DISABLED = 1 << 0;
const uint32_t EXCLUDE_FAKE = 1 << 1;
/*
* Clear site data for a given plugin.
@ -127,6 +128,9 @@ interface nsIPluginHost : nsISupports
* passed to the permission manager to see whether the plugin is allowed to
* run, for example. This will typically be based on the plugin's "nice name"
* and its blocklist state.
*
* @mimeType The MIME type we're interested in.
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
*/
ACString getPermissionStringForType(in AUTF8String mimeType,
[optional] in uint32_t excludeFlags);
@ -136,6 +140,12 @@ interface nsIPluginHost : nsISupports
* enabled and disabled/blocklisted plugins, but an enabled plugin will
* always be returned if available.
*
* A fake plugin tag, if one exists and is available, will be returned in
* preference to NPAPI plugin tags unless excluded by the excludeFlags.
*
* @mimeType The MIME type we're interested in.
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
*
* @throws NS_ERROR_NOT_AVAILABLE if no plugin is available for this MIME
* type.
*/
@ -145,16 +155,45 @@ interface nsIPluginHost : nsISupports
/**
* Get the nsIPluginTag enabled state for this MIME type. See
* nsIPluginTag.enabledState.
*
* @mimeType The MIME type we're interested in.
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
*/
unsigned long getStateForType(in AUTF8String mimeType,
[optional] in uint32_t excludeFlags);
/**
* Get the blocklist state for a MIME type. See nsIPluginTag.blocklistState.
*
* @mimeType The MIME type we're interested in.
* @excludeFlags Set of the EXCLUDE_* flags above, defaulting to EXCLUDE_NONE.
*/
uint32_t getBlocklistStateForType(in AUTF8String aMimeType,
[optional] in uint32_t excludeFlags);
/**
* Create a fake plugin tag, register it, and return it. The argument is a
* FakePluginTagInit dictionary. See documentation in
* FakePluginTagInit.webidl for what it should look like. Will throw
* NS_ERROR_UNEXPECTED if there is already a fake plugin registered with the
* given handler URI.
*/
[implicit_jscontext]
nsIFakePluginTag registerFakePlugin(in jsval initDictionary);
/**
* Get a reference to an existing fake plugin tag for the given MIME type, if
* any. Can return null.
*/
nsIFakePluginTag getFakePlugin(in AUTF8String mimeType);
/**
* Unregister a fake plugin. The argument can be the .handlerURI.spec of an
* existing nsIFakePluginTag, or just a known handler URI string that was
* passed in the FakePluginTagInit when registering.
*/
void unregisterFakePlugin(in AUTF8String handlerURI);
/**
* Returns true if plugins with the given mimetype will run out of process.
*/

View File

@ -5,7 +5,9 @@
#include "nsISupports.idl"
[scriptable, uuid(32563b21-3c5e-4864-baaa-4e49b90b64f2)]
interface nsIURI;
[scriptable, uuid(5daa99d5-265a-4397-b429-c943803e2619)]
interface nsIPluginTag : nsISupports
{
// enabledState is stored as one of the following as an integer in prefs,
@ -26,6 +28,8 @@ interface nsIPluginTag : nsISupports
/**
* true only if this plugin is "hardblocked" and cannot be enabled.
*/
// FIXME-jsplugins QI to fakePluginTag possible
// FIXME-jsplugins implement missing + tests (whatever that means)
readonly attribute boolean blocklisted;
/**
@ -55,3 +59,17 @@ interface nsIPluginTag : nsISupports
[retval, array, size_is(aCount)]
out wstring aResults);
};
/**
* An interface representing a "fake" plugin: one implemented in JavaScript, not
* as a NPAPI plug-in. See nsIPluginHost.registerFakePlugin and the
* documentation for the FakePluginTagInit dictionary.
*/
[scriptable, uuid(6d22c968-226d-4156-b230-da6ad6bbf6e8)]
interface nsIFakePluginTag : nsIPluginTag
{
// The URI that should be loaded into the tag (as a frame) to handle the
// plugin. Note that the original data/src value for the plugin is not loaded
// and will need to be requested by the handler via XHR or similar if desired.
readonly attribute nsIURI handlerURI;
};

View File

@ -1673,8 +1673,8 @@ nsNPAPIPluginInstance::CarbonNPAPIFailure()
static bool
GetJavaVersionFromMimetype(nsPluginTag* pluginTag, nsCString& version)
{
for (uint32_t i = 0; i < pluginTag->mMimeTypes.Length(); ++i) {
nsCString type = pluginTag->mMimeTypes[i];
for (uint32_t i = 0; i < pluginTag->MimeTypes().Length(); ++i) {
nsCString type = pluginTag->MimeTypes()[i];
nsAutoCString jpi("application/x-java-applet;jpi-version=");
int32_t idx = type.Find(jpi, false, 0, -1);

View File

@ -52,6 +52,7 @@
#include "nsICategoryManager.h"
#include "nsPluginStreamListenerPeer.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/FakePluginTagInitBinding.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/plugins/PluginAsyncSurrogate.h"
#include "mozilla/plugins/PluginBridge.h"
@ -119,6 +120,7 @@ using namespace mozilla;
using mozilla::TimeStamp;
using mozilla::plugins::PluginTag;
using mozilla::plugins::PluginAsyncSurrogate;
using mozilla::dom::FakePluginTagInit;
// Null out a strong ref to a linked list iteratively to avoid
// exhausting the stack (bug 486349).
@ -230,7 +232,7 @@ nsInvalidPluginTag::~nsInvalidPluginTag()
// Helper to check for a MIME in a comma-delimited preference
static bool
IsTypeInList(nsCString &aMimeType, nsCString aTypeList)
IsTypeInList(const nsCString& aMimeType, nsCString aTypeList)
{
nsAutoCString searchStr;
searchStr.Assign(',');
@ -998,7 +1000,7 @@ nsPluginHost::TrySetUpPluginInstance(const nsACString &aMimeType,
#if defined(MOZ_WIDGET_ANDROID) && defined(MOZ_CRASHREPORTER)
if (pluginTag->mIsFlashPlugin) {
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FlashVersion"), pluginTag->mVersion);
CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("FlashVersion"), pluginTag->Version());
}
#endif
@ -1049,7 +1051,22 @@ nsPluginHost::HavePluginForType(const nsACString & aMimeType,
PluginFilter aFilter)
{
bool checkEnabled = aFilter & eExcludeDisabled;
return FindNativePluginForType(aMimeType, checkEnabled);
bool allowFake = !(aFilter & eExcludeFake);
return FindPluginForType(aMimeType, allowFake, checkEnabled);
}
nsIInternalPluginTag*
nsPluginHost::FindPluginForType(const nsACString& aMimeType,
bool aIncludeFake, bool aCheckEnabled)
{
if (aIncludeFake) {
nsFakePluginTag* fakeTag = FindFakePluginForType(aMimeType, aCheckEnabled);
if (fakeTag) {
return fakeTag;
}
}
return FindNativePluginForType(aMimeType, aCheckEnabled);
}
NS_IMETHODIMP
@ -1057,21 +1074,22 @@ nsPluginHost::GetPluginTagForType(const nsACString& aMimeType,
uint32_t aExcludeFlags,
nsIPluginTag** aResult)
{
bool includeFake = !(aExcludeFlags & eExcludeFake);
bool includeDisabled = !(aExcludeFlags & eExcludeDisabled);
nsPluginTag *tag = FindNativePluginForType(aMimeType, true);
// Prefer enabled, but select disabled if none is found
if (includeDisabled && !tag) {
tag = FindNativePluginForType(aMimeType, false);
// First look for an enabled plugin.
nsRefPtr<nsIInternalPluginTag> tag = FindPluginForType(aMimeType, includeFake,
true);
if (!tag && includeDisabled) {
tag = FindPluginForType(aMimeType, includeFake, false);
}
if (!tag) {
return NS_ERROR_NOT_AVAILABLE;
if (tag) {
tag.forget(aResult);
return NS_OK;
}
NS_ADDREF(*aResult = tag);
return NS_OK;
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
@ -1152,17 +1170,28 @@ nsPluginHost::HavePluginForExtension(const nsACString & aExtension,
PluginFilter aFilter)
{
bool checkEnabled = aFilter & eExcludeDisabled;
return FindNativePluginForExtension(aExtension, aMimeType, checkEnabled);
bool allowFake = !(aFilter & eExcludeFake);
return FindNativePluginForExtension(aExtension, aMimeType, checkEnabled) ||
(allowFake &&
FindFakePluginForExtension(aExtension, aMimeType, checkEnabled));
}
void
nsPluginHost::GetPlugins(nsTArray<nsRefPtr<nsPluginTag> >& aPluginArray,
nsPluginHost::GetPlugins(nsTArray<nsCOMPtr<nsIInternalPluginTag>>& aPluginArray,
bool aIncludeDisabled)
{
aPluginArray.Clear();
LoadPlugins();
// Append fake plugins, then normal plugins.
uint32_t numFake = mFakePlugins.Length();
for (uint32_t i = 0; i < numFake; i++) {
aPluginArray.AppendElement(mFakePlugins[i]);
}
// Regular plugins
nsPluginTag* plugin = mPlugins;
while (plugin != nullptr) {
if (plugin->IsEnabled() || aIncludeDisabled) {
@ -1172,12 +1201,14 @@ nsPluginHost::GetPlugins(nsTArray<nsRefPtr<nsPluginTag> >& aPluginArray,
}
}
// FIXME-jsplugins Check users for order of fake v non-fake
NS_IMETHODIMP
nsPluginHost::GetPluginTags(uint32_t* aPluginCount, nsIPluginTag*** aResults)
{
LoadPlugins();
uint32_t count = 0;
uint32_t fakeCount = mFakePlugins.Length();
nsRefPtr<nsPluginTag> plugin = mPlugins;
while (plugin != nullptr) {
count++;
@ -1185,11 +1216,11 @@ nsPluginHost::GetPluginTags(uint32_t* aPluginCount, nsIPluginTag*** aResults)
}
*aResults = static_cast<nsIPluginTag**>
(moz_xmalloc(count * sizeof(**aResults)));
(moz_xmalloc((fakeCount + count) * sizeof(**aResults)));
if (!*aResults)
return NS_ERROR_OUT_OF_MEMORY;
*aPluginCount = count;
*aPluginCount = count + fakeCount;
plugin = mPlugins;
for (uint32_t i = 0; i < count; i++) {
@ -1198,6 +1229,11 @@ nsPluginHost::GetPluginTags(uint32_t* aPluginCount, nsIPluginTag*** aResults)
plugin = plugin->mNext;
}
for (uint32_t i = 0; i < fakeCount; i++) {
(*aResults)[i + count] = static_cast<nsIInternalPluginTag*>(mFakePlugins[i]);
NS_ADDREF((*aResults)[i + count]);
}
return NS_OK;
}
@ -1217,7 +1253,7 @@ nsPluginHost::FindPreferredPlugin(const InfallibleTArray<nsPluginTag*>& matches)
nsPluginTag *preferredPlugin = matches[0];
for (unsigned int i = 1; i < matches.Length(); i++) {
if (mozilla::Version(matches[i]->mVersion.get()) > preferredPlugin->mVersion.get()) {
if (mozilla::Version(matches[i]->Version().get()) > preferredPlugin->Version().get()) {
preferredPlugin = matches[i];
}
}
@ -1225,6 +1261,47 @@ nsPluginHost::FindPreferredPlugin(const InfallibleTArray<nsPluginTag*>& matches)
return preferredPlugin;
}
nsFakePluginTag*
nsPluginHost::FindFakePluginForExtension(const nsACString & aExtension,
/* out */ nsACString & aMimeType,
bool aCheckEnabled)
{
if (aExtension.IsEmpty()) {
return nullptr;
}
int32_t numFakePlugins = mFakePlugins.Length();
for (int32_t i = 0; i < numFakePlugins; i++) {
nsFakePluginTag *plugin = mFakePlugins[i];
bool active;
if ((!aCheckEnabled ||
(NS_SUCCEEDED(plugin->GetActive(&active)) && active)) &&
plugin->HasExtension(aExtension, aMimeType)) {
return plugin;
}
}
return nullptr;
}
nsFakePluginTag*
nsPluginHost::FindFakePluginForType(const nsACString & aMimeType,
bool aCheckEnabled)
{
int32_t numFakePlugins = mFakePlugins.Length();
for (int32_t i = 0; i < numFakePlugins; i++) {
nsFakePluginTag *plugin = mFakePlugins[i];
bool active;
if ((!aCheckEnabled ||
(NS_SUCCEEDED(plugin->GetActive(&active)) && active)) &&
plugin->HasMimeType(aMimeType)) {
return plugin;
}
}
return nullptr;
}
nsPluginTag*
nsPluginHost::FindNativePluginForType(const nsACString & aMimeType,
bool aCheckEnabled)
@ -1411,12 +1488,12 @@ nsresult nsPluginHost::GetPlugin(const nsACString &aMimeType,
rv = NS_OK;
PLUGIN_LOG(PLUGIN_LOG_BASIC,
("nsPluginHost::GetPlugin Begin mime=%s, plugin=%s\n",
PromiseFlatCString(aMimeType).get(), pluginTag->mFileName.get()));
PromiseFlatCString(aMimeType).get(), pluginTag->FileName().get()));
#ifdef DEBUG
if (!pluginTag->mFileName.IsEmpty())
if (!pluginTag->FileName().IsEmpty())
printf("For %s found plugin %s\n",
PromiseFlatCString(aMimeType).get(), pluginTag->mFileName.get());
PromiseFlatCString(aMimeType).get(), pluginTag->FileName().get());
#endif
rv = EnsurePluginLoaded(pluginTag);
@ -1431,7 +1508,7 @@ nsresult nsPluginHost::GetPlugin(const nsACString &aMimeType,
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHost::GetPlugin End mime=%s, rv=%d, plugin=%p name=%s\n",
PromiseFlatCString(aMimeType).get(), rv, *aPlugin,
(pluginTag ? pluginTag->mFileName.get() : "(not found)")));
(pluginTag ? pluginTag->FileName().get() : "(not found)")));
return rv;
}
@ -1531,6 +1608,50 @@ nsPluginHost::EnumerateSiteData(const nsACString& domain,
return NS_OK;
}
NS_IMETHODIMP
nsPluginHost::RegisterFakePlugin(JS::Handle<JS::Value> aInitDictionary,
JSContext* aCx,
nsIFakePluginTag **aResult)
{
FakePluginTagInit initDictionary;
if (!initDictionary.Init(aCx, aInitDictionary)) {
return NS_ERROR_FAILURE;
}
nsRefPtr<nsFakePluginTag> newTag;
nsresult rv = nsFakePluginTag::Create(initDictionary, getter_AddRefs(newTag));
NS_ENSURE_SUCCESS(rv, rv);
for (auto existingTag : mFakePlugins) {
if (newTag->HandlerURIMatches(existingTag->HandlerURI())) {
return NS_ERROR_UNEXPECTED;
}
}
mFakePlugins.AppendElement(newTag);
// FIXME-jsplugins do we need to register with the category manager here? For
// shumway, for now, probably not.
newTag.forget(aResult);
return NS_OK;
}
NS_IMETHODIMP
nsPluginHost::UnregisterFakePlugin(const nsACString& aHandlerURI)
{
nsCOMPtr<nsIURI> handlerURI;
nsresult rv = NS_NewURI(getter_AddRefs(handlerURI), aHandlerURI);
NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0; i < mFakePlugins.Length(); ++i) {
if (mFakePlugins[i]->HandlerURIMatches(handlerURI)) {
mFakePlugins.RemoveElementAt(i);
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsPluginHost::RegisterPlayPreviewMimeType(const nsACString& mimeType,
bool ignoreCTP,
@ -1583,6 +1704,21 @@ nsPluginHost::GetPlayPreviewInfo(const nsACString& mimeType,
return NS_ERROR_NOT_AVAILABLE;
}
// FIXME-jsplugins Is this method actually needed?
NS_IMETHODIMP
nsPluginHost::GetFakePlugin(const nsACString & aMimeType,
nsIFakePluginTag** aResult)
{
nsRefPtr<nsFakePluginTag> result = FindFakePluginForType(aMimeType, false);
if (result) {
result.forget(aResult);
return NS_OK;
}
*aResult = nullptr;
return NS_ERROR_NOT_AVAILABLE;
}
#define ClearDataFromSitesClosure_CID {0x9fb21761, 0x2403, 0x41ad, {0x9e, 0xfd, 0x36, 0x7e, 0xc4, 0x4f, 0xa4, 0x5e}}
@ -1649,6 +1785,7 @@ NS_INTERFACE_MAP_BEGIN(ClearDataFromSitesClosure)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIClearSiteDataCallback)
NS_INTERFACE_MAP_END
// FIXME-jsplugins what should this do for fake plugins?
NS_IMETHODIMP
nsPluginHost::ClearSiteData(nsIPluginTag* plugin, const nsACString& domain,
uint64_t flags, int64_t maxAge, nsIClearSiteDataCallback* callbackFunc)
@ -1836,15 +1973,24 @@ nsPluginHost::GetSpecialType(const nsACString & aMIMEType)
bool
nsPluginHost::IsLiveTag(nsIPluginTag* aPluginTag)
{
nsCOMPtr<nsIInternalPluginTag> internalTag(do_QueryInterface(aPluginTag));
uint32_t fakeCount = mFakePlugins.Length();
for (uint32_t i = 0; i < fakeCount; i++) {
if (mFakePlugins[i] == internalTag) {
return true;
}
}
nsPluginTag* tag;
for (tag = mPlugins; tag; tag = tag->mNext) {
if (tag == aPluginTag) {
if (tag == internalTag) {
return true;
}
}
return false;
}
// FIXME-jsplugins what should happen with jsplugins here, if anything?
nsPluginTag*
nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag)
{
@ -1856,6 +2002,8 @@ nsPluginHost::HaveSamePlugin(const nsPluginTag* aPluginTag)
return nullptr;
}
// Don't have to worry about fake plugins here, since this is only used during
// the plugin directory scan, which doesn't pick up fake plugins.
nsPluginTag*
nsPluginHost::FirstPluginWithPath(const nsCString& path)
{
@ -1970,7 +2118,7 @@ nsPluginHost::ShouldAddPlugin(nsPluginTag* aPluginTag)
#if defined(XP_WIN) && (defined(__x86_64__) || defined(_M_X64))
// On 64-bit windows, the only plugin we should load is flash. Use library
// filename and MIME type to check.
if (StringBeginsWith(aPluginTag->mFileName, NS_LITERAL_CSTRING("NPSWF"), nsCaseInsensitiveCStringComparator()) &&
if (StringBeginsWith(aPluginTag->FileName(), NS_LITERAL_CSTRING("NPSWF"), nsCaseInsensitiveCStringComparator()) &&
(aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash")) ||
aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash-test")))) {
return true;
@ -1983,7 +2131,7 @@ nsPluginHost::ShouldAddPlugin(nsPluginTag* aPluginTag)
}
#ifdef PLUGIN_LOGGING
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("ShouldAddPlugin : Ignoring non-flash plugin library %s\n", aPluginTag->mFileName.get()));
("ShouldAddPlugin : Ignoring non-flash plugin library %s\n", aPluginTag->FileName().get()));
#endif // PLUGIN_LOGGING
return false;
#else
@ -2003,9 +2151,9 @@ nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag)
if (aPluginTag->IsActive()) {
nsAdoptingCString disableFullPage =
Preferences::GetCString(kPrefDisableFullPage);
for (uint32_t i = 0; i < aPluginTag->mMimeTypes.Length(); i++) {
if (!IsTypeInList(aPluginTag->mMimeTypes[i], disableFullPage)) {
RegisterWithCategoryManager(aPluginTag->mMimeTypes[i],
for (uint32_t i = 0; i < aPluginTag->MimeTypes().Length(); i++) {
if (!IsTypeInList(aPluginTag->MimeTypes()[i], disableFullPage)) {
RegisterWithCategoryManager(aPluginTag->MimeTypes()[i],
ePluginRegister);
}
}
@ -2590,11 +2738,23 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
return;
}
nsTArray<nsRefPtr<nsPluginTag>> plugins;
nsTArray<nsCOMPtr<nsIInternalPluginTag>> plugins;
GetPlugins(plugins, true);
for (size_t i = 0; i < plugins.Length(); i++) {
nsRefPtr<nsPluginTag> tag = plugins[i];
nsCOMPtr<nsIInternalPluginTag> basetag = plugins[i];
nsCOMPtr<nsIFakePluginTag> faketag = do_QueryInterface(basetag);
if (faketag) {
/// FIXME-jsplugins - We need to make content processes properly
/// aware of jsplugins (and add a nsIInternalPluginTag->AsNative() to
/// avoid this hacky static cast)
continue;
}
/// FIXME-jsplugins - We need to cleanup the various plugintag classes
/// to be more sane and avoid this dance
nsPluginTag *tag = static_cast<nsPluginTag *>(basetag.get());
if (!nsNPAPIPlugin::RunPluginOOP(tag)) {
// Don't expose non-OOP plugins to content processes since we have no way
@ -2603,20 +2763,21 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
}
aPlugins->AppendElement(PluginTag(tag->mId,
tag->mName,
tag->mDescription,
tag->mMimeTypes,
tag->mMimeDescriptions,
tag->mExtensions,
tag->Name(),
tag->Description(),
tag->MimeTypes(),
tag->MimeDescriptions(),
tag->Extensions(),
tag->mIsJavaPlugin,
tag->mIsFlashPlugin,
tag->mFileName,
tag->mVersion,
tag->FileName(),
tag->Version(),
tag->mLastModifiedTime,
tag->IsFromExtension()));
}
}
// This function is not relevant for fake plugins.
void
nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
{
@ -2634,18 +2795,18 @@ nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
// Update types with category manager
nsAdoptingCString disableFullPage =
Preferences::GetCString(kPrefDisableFullPage);
for (uint32_t i = 0; i < aPluginTag->mMimeTypes.Length(); i++) {
for (uint32_t i = 0; i < aPluginTag->MimeTypes().Length(); i++) {
nsRegisterType shouldRegister;
if (IsTypeInList(aPluginTag->mMimeTypes[i], disableFullPage)) {
if (IsTypeInList(aPluginTag->MimeTypes()[i], disableFullPage)) {
shouldRegister = ePluginUnregister;
} else {
nsPluginTag *plugin = FindNativePluginForType(aPluginTag->mMimeTypes[i],
nsPluginTag *plugin = FindNativePluginForType(aPluginTag->MimeTypes()[i],
true);
shouldRegister = plugin ? ePluginRegister : ePluginUnregister;
}
RegisterWithCategoryManager(aPluginTag->mMimeTypes[i], shouldRegister);
RegisterWithCategoryManager(aPluginTag->MimeTypes()[i], shouldRegister);
}
nsCOMPtr<nsIObserverService> obsService =
@ -2666,7 +2827,7 @@ nsPluginHost::IsTypeWhitelisted(const char *aMimeType)
}
void
nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType,
nsPluginHost::RegisterWithCategoryManager(const nsCString& aMimeType,
nsRegisterType aType)
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
@ -2690,6 +2851,15 @@ nsPluginHost::RegisterWithCategoryManager(nsCString &aMimeType,
mOverrideInternalTypes,
nullptr);
} else {
if (aType == ePluginMaybeUnregister) {
// Bail out if this type is still used by an enabled plugin
if (HavePluginForType(aMimeType)) {
return;
}
} else {
MOZ_ASSERT(aType == ePluginUnregister, "Unknown nsRegisterType");
}
// Only delete the entry if a plugin registered for it
nsXPIDLCString value;
nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers",
@ -2768,13 +2938,13 @@ nsPluginHost::WritePluginInfo()
// filename & fullpath are on separate line
// because they can contain field delimiter char
PR_fprintf(fd, "%s%c%c\n%s%c%c\n%s%c%c\n",
(tag->mFileName.get()),
(tag->FileName().get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
PLUGIN_REGISTRY_END_OF_LINE_MARKER,
(tag->mFullPath.get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
PLUGIN_REGISTRY_END_OF_LINE_MARKER,
(tag->mVersion.get()),
(tag->Version().get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
@ -2792,23 +2962,23 @@ nsPluginHost::WritePluginInfo()
//description, name & mtypecount are on separate line
PR_fprintf(fd, "%s%c%c\n%s%c%c\n%d\n",
(tag->mDescription.get()),
(tag->Description().get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
PLUGIN_REGISTRY_END_OF_LINE_MARKER,
(tag->mName.get()),
(tag->Name().get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
PLUGIN_REGISTRY_END_OF_LINE_MARKER,
tag->mMimeTypes.Length());
tag->MimeTypes().Length());
// Add in each mimetype this plugin supports
for (uint32_t i = 0; i < tag->mMimeTypes.Length(); i++) {
for (uint32_t i = 0; i < tag->MimeTypes().Length(); i++) {
PR_fprintf(fd, "%d%c%s%c%s%c%s%c%c\n",
i,PLUGIN_REGISTRY_FIELD_DELIMITER,
(tag->mMimeTypes[i].get()),
(tag->MimeTypes()[i].get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
(tag->mMimeDescriptions[i].get()),
(tag->MimeDescriptions()[i].get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
(tag->mExtensions[i].get()),
(tag->Extensions()[i].get()),
PLUGIN_REGISTRY_FIELD_DELIMITER,
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
}
@ -3153,7 +3323,7 @@ nsPluginHost::ReadPluginInfo()
}
MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC,
("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->mFileName.get()));
("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->FileName().get()));
if (!ShouldAddPlugin(tag)) {
continue;
@ -3881,7 +4051,7 @@ nsPluginHost::GetPluginName(nsNPAPIPluginInstance *aPluginInstance,
if (!plugin)
return NS_ERROR_FAILURE;
*aPluginName = TagForPlugin(plugin)->mName.get();
*aPluginName = TagForPlugin(plugin)->Name().get();
return NS_OK;
}

Some files were not shown because too many files have changed in this diff Show More