mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
Merge m-c to fx-team. a=merge
This commit is contained in:
commit
5862b8047c
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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 -->
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"/>
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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 -->
|
||||
|
@ -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"/>
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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
|
||||
},
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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(¬Valid);
|
||||
@ -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) {
|
||||
|
17
build/clang-plugin/tests/TestMultipleAnnotations.cpp
Normal file
17
build/clang-plugin/tests/TestMultipleAnnotations.cpp
Normal 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'}}
|
||||
}
|
@ -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();
|
||||
|
94
build/clang-plugin/tests/TestNeedsNoVTableType.cpp
Normal file
94
build/clang-plugin/tests/TestNeedsNoVTableType.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -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}}
|
||||
|
812
build/clang-plugin/tests/TestNonMemMovable.cpp
Normal file
812
build/clang-plugin/tests/TestNonMemMovable.cpp
Normal 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;
|
||||
}
|
@ -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(¬Valid);
|
||||
@ -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}}
|
||||
|
@ -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',
|
||||
|
@ -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:
|
||||
|
@ -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(<);
|
||||
// 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();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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___ */
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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': {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
onmessage = function() {
|
||||
var exists = true;
|
||||
try {
|
||||
var bc = new BroadcastChannel('foobar');
|
||||
} catch(e) {
|
||||
exists = false;
|
||||
}
|
||||
|
||||
postMessage({ exists: exists });
|
||||
}
|
||||
|
@ -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]
|
||||
|
@ -130,7 +130,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -55,7 +55,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -54,7 +54,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -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],
|
||||
|
@ -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],
|
||||
|
@ -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>
|
@ -109,7 +109,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -30,7 +30,7 @@ function runTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTest);
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -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>
|
||||
|
@ -54,7 +54,7 @@ function runTests() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -48,7 +48,7 @@ function runTests() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.broadcastChannel.enabled", true]]}, runTests);
|
||||
runTests();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -5,6 +5,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIPushClient.idl',
|
||||
'nsIPushNotificationService.idl',
|
||||
'nsIPushObserverNotification.idl',
|
||||
]
|
||||
|
53
dom/interfaces/push/nsIPushClient.idl
Normal file
53
dom/interfaces/push/nsIPushClient.idl
Normal 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);
|
||||
};
|
@ -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));
|
||||
|
@ -750,7 +750,7 @@ HangMonitoredProcess::GetPluginName(nsACString& aPluginName)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
aPluginName = tag->mName;
|
||||
aPluginName = tag->Name();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -95,6 +95,7 @@ H264Converter::Drain()
|
||||
if (mDecoder) {
|
||||
return mDecoder->Drain();
|
||||
}
|
||||
mCallback->DrainComplete();
|
||||
return mLastError;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user