mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to fx-team, a=merge
This commit is contained in:
commit
8dfdddf741
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee",
|
"git_revision": "89602d6ae53ecf4129b35a84e49d25b9fd37bc39",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "d74e738cd626558fb9dc289500ad28ae29deab03",
|
"revision": "ea9b9cc69315e86bf7198ec0d57a267e64345b32",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
<!--
|
<!--
|
||||||
B2G repositories for all targets
|
B2G repositories for all targets
|
||||||
-->
|
-->
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="619766a1ce78d50fb8a3b5a9e0821c335a0ed7ee"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="89602d6ae53ecf4129b35a84e49d25b9fd37bc39"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="35dccb3127db8f39f20b985ad312d2cd44780669"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="99c333dab00ed79baff9e1cf76b320aee8e1c123"/>
|
||||||
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
<project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
|
||||||
|
@ -494,7 +494,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="learnMoreContainer">
|
<div id="learnMoreContainer">
|
||||||
<p><a href="https://support.mozilla.org/kb/tls-error-reports" id="learnMoreLink" target="new">&errorReporting.learnMore;</a></p>
|
<p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new">&errorReporting.learnMore;</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="buttonContainer">
|
<div id="buttonContainer">
|
||||||
|
@ -272,7 +272,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p id="badStsCertExplanation">&certerror.whatShouldIDo.badStsCertExplanation;</p>
|
<p id="badStsCertExplanation">&certerror.whatShouldIDo.badStsCertExplanation;</p>
|
||||||
<div>
|
<div>
|
||||||
<p><a href="https://support.mozilla.org/kb/tls-error-reports" id="learnMoreLink" target="new">&certerror.learnMore;</a></p>
|
<p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new">&certerror.learnMore;</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="buttonContainer">
|
<div id="buttonContainer">
|
||||||
|
@ -463,14 +463,19 @@ endif
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef SYMBOLS_FILE
|
ifdef SYMBOLS_FILE
|
||||||
|
ifeq ($(OS_TARGET),WINNT)
|
||||||
|
ifndef GNU_CC
|
||||||
|
EXTRA_DSO_LDOPTS += -DEF:$(call normalizepath,$(SYMBOLS_FILE))
|
||||||
|
else
|
||||||
|
EXTRA_DSO_LDOPTS += $(call normalizepath,$(SYMBOLS_FILE))
|
||||||
|
endif
|
||||||
|
else
|
||||||
ifdef GCC_USE_GNU_LD
|
ifdef GCC_USE_GNU_LD
|
||||||
EXTRA_DSO_LDOPTS += -Wl,--version-script,$(SYMBOLS_FILE)
|
EXTRA_DSO_LDOPTS += -Wl,--version-script,$(SYMBOLS_FILE)
|
||||||
else
|
else
|
||||||
ifeq ($(OS_TARGET),Darwin)
|
ifeq ($(OS_TARGET),Darwin)
|
||||||
EXTRA_DSO_LDOPTS += -Wl,-exported_symbols_list,$(SYMBOLS_FILE)
|
EXTRA_DSO_LDOPTS += -Wl,-exported_symbols_list,$(SYMBOLS_FILE)
|
||||||
endif
|
endif
|
||||||
ifeq ($(OS_TARGET),WINNT)
|
|
||||||
EXTRA_DSO_LDOPTS += -DEF:$(call normalizepath,$(SYMBOLS_FILE))
|
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
EXTRA_DEPS += $(SYMBOLS_FILE)
|
EXTRA_DEPS += $(SYMBOLS_FILE)
|
||||||
|
12
configure.in
12
configure.in
@ -75,7 +75,7 @@ GNOMEUI_VERSION=2.2.0
|
|||||||
GCONF_VERSION=1.2.1
|
GCONF_VERSION=1.2.1
|
||||||
STARTUP_NOTIFICATION_VERSION=0.8
|
STARTUP_NOTIFICATION_VERSION=0.8
|
||||||
DBUS_VERSION=0.60
|
DBUS_VERSION=0.60
|
||||||
SQLITE_VERSION=3.10.1
|
SQLITE_VERSION=3.10.2
|
||||||
|
|
||||||
MSMANIFEST_TOOL=
|
MSMANIFEST_TOOL=
|
||||||
|
|
||||||
@ -3746,7 +3746,7 @@ if test -n "$MOZ_FMP4"; then
|
|||||||
else
|
else
|
||||||
MOZ_FMP4=
|
MOZ_FMP4=
|
||||||
fi
|
fi
|
||||||
MOZ_FFMPEG=1
|
MOZ_FFMPEG=
|
||||||
MOZ_WEBRTC=1
|
MOZ_WEBRTC=1
|
||||||
MOZ_PEERCONNECTION=
|
MOZ_PEERCONNECTION=
|
||||||
MOZ_SRTP=
|
MOZ_SRTP=
|
||||||
@ -5226,6 +5226,14 @@ fi;
|
|||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
dnl FFmpeg H264/AAC Decoding Support
|
dnl FFmpeg H264/AAC Decoding Support
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
|
case "$OS_TARGET" in
|
||||||
|
WINNT|Android)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
MOZ_FFMPEG=1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
MOZ_ARG_DISABLE_BOOL(ffmpeg,
|
MOZ_ARG_DISABLE_BOOL(ffmpeg,
|
||||||
[ --disable-ffmpeg Disable FFmpeg for fragmented H264/AAC decoding],
|
[ --disable-ffmpeg Disable FFmpeg for fragmented H264/AAC decoding],
|
||||||
MOZ_FFMPEG=,
|
MOZ_FFMPEG=,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
** This file is an amalgamation of many separate C source files from SQLite
|
** This file is an amalgamation of many separate C source files from SQLite
|
||||||
** version 3.10.1. By combining all the individual C code files into this
|
** version 3.10.2. By combining all the individual C code files into this
|
||||||
** single large file, the entire code can be compiled as a single translation
|
** single large file, the entire code can be compiled as a single translation
|
||||||
** unit. This allows many compilers to do optimizations that would not be
|
** unit. This allows many compilers to do optimizations that would not be
|
||||||
** possible if the files were compiled separately. Performance improvements
|
** possible if the files were compiled separately. Performance improvements
|
||||||
@ -325,9 +325,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.10.1"
|
#define SQLITE_VERSION "3.10.2"
|
||||||
#define SQLITE_VERSION_NUMBER 3010001
|
#define SQLITE_VERSION_NUMBER 3010002
|
||||||
#define SQLITE_SOURCE_ID "2016-01-13 21:41:56 254419c36766225ca542ae873ed38255e3fb8588"
|
#define SQLITE_SOURCE_ID "2016-01-20 15:27:19 17efb4209f97fb4971656086b138599a91a75ff9"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
@ -49045,7 +49045,7 @@ SQLITE_PRIVATE int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory
|
|||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
sqlite3WalExclusiveMode(pPager->pWal, 1);
|
(void)sqlite3WalExclusiveMode(pPager->pWal, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab the write lock on the log file. If successful, upgrade to
|
/* Grab the write lock on the log file. If successful, upgrade to
|
||||||
@ -50115,7 +50115,11 @@ SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager *pPager){
|
|||||||
** This will be either the rollback journal or the WAL file.
|
** This will be either the rollback journal or the WAL file.
|
||||||
*/
|
*/
|
||||||
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
|
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager *pPager){
|
||||||
|
#if SQLITE_OMIT_WAL
|
||||||
|
return pPager->jfd;
|
||||||
|
#else
|
||||||
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
|
return pPager->pWal ? sqlite3WalFile(pPager->pWal) : pPager->jfd;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -100279,7 +100283,7 @@ static int patternCompare(
|
|||||||
}
|
}
|
||||||
c2 = Utf8Read(zString);
|
c2 = Utf8Read(zString);
|
||||||
if( c==c2 ) continue;
|
if( c==c2 ) continue;
|
||||||
if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
|
if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
|
||||||
@ -135026,7 +135030,6 @@ static int openDatabase(
|
|||||||
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
|
sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
|
||||||
|
|
||||||
opendb_out:
|
opendb_out:
|
||||||
sqlite3_free(zOpen);
|
|
||||||
if( db ){
|
if( db ){
|
||||||
assert( db->mutex!=0 || isThreadsafe==0
|
assert( db->mutex!=0 || isThreadsafe==0
|
||||||
|| sqlite3GlobalConfig.bFullMutex==0 );
|
|| sqlite3GlobalConfig.bFullMutex==0 );
|
||||||
@ -135063,6 +135066,7 @@ opendb_out:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
sqlite3_free(zOpen);
|
||||||
return rc & 0xff;
|
return rc & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182280,7 +182284,7 @@ static void fts5SourceIdFunc(
|
|||||||
sqlite3_value **apVal /* Function arguments */
|
sqlite3_value **apVal /* Function arguments */
|
||||||
){
|
){
|
||||||
assert( nArg==0 );
|
assert( nArg==0 );
|
||||||
sqlite3_result_text(pCtx, "fts5: 2016-01-13 21:41:56 254419c36766225ca542ae873ed38255e3fb8588", -1, SQLITE_TRANSIENT);
|
sqlite3_result_text(pCtx, "fts5: 2016-01-20 15:27:19 17efb4209f97fb4971656086b138599a91a75ff9", -1, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fts5Init(sqlite3 *db){
|
static int fts5Init(sqlite3 *db){
|
||||||
|
@ -111,9 +111,9 @@ extern "C" {
|
|||||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
||||||
** [sqlite_version()] and [sqlite_source_id()].
|
** [sqlite_version()] and [sqlite_source_id()].
|
||||||
*/
|
*/
|
||||||
#define SQLITE_VERSION "3.10.1"
|
#define SQLITE_VERSION "3.10.2"
|
||||||
#define SQLITE_VERSION_NUMBER 3010001
|
#define SQLITE_VERSION_NUMBER 3010002
|
||||||
#define SQLITE_SOURCE_ID "2016-01-13 21:41:56 254419c36766225ca542ae873ed38255e3fb8588"
|
#define SQLITE_SOURCE_ID "2016-01-20 15:27:19 17efb4209f97fb4971656086b138599a91a75ff9"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** CAPI3REF: Run-Time Library Version Numbers
|
** CAPI3REF: Run-Time Library Version Numbers
|
||||||
|
@ -31,7 +31,7 @@ class nsDOMNavigationTiming;
|
|||||||
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
|
[ptr] native nsDOMNavigationTimingPtr(nsDOMNavigationTiming);
|
||||||
[ref] native nsIContentViewerTArray(nsTArray<nsCOMPtr<nsIContentViewer> >);
|
[ref] native nsIContentViewerTArray(nsTArray<nsCOMPtr<nsIContentViewer> >);
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(91b6c1f3-fc5f-43a9-88f4-9286bd19387f)]
|
[scriptable, builtinclass, uuid(2da17016-7851-4a45-a7a8-00b360e01595)]
|
||||||
interface nsIContentViewer : nsISupports
|
interface nsIContentViewer : nsISupports
|
||||||
{
|
{
|
||||||
[noscript] void init(in nsIWidgetPtr aParentWidget,
|
[noscript] void init(in nsIWidgetPtr aParentWidget,
|
||||||
@ -229,6 +229,18 @@ interface nsIContentViewer : nsISupports
|
|||||||
*/
|
*/
|
||||||
[noscript] void appendSubtree(in nsIContentViewerTArray array);
|
[noscript] void appendSubtree(in nsIContentViewerTArray array);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the refresh driver to discontinue painting until further
|
||||||
|
* notice.
|
||||||
|
*/
|
||||||
|
void pausePainting();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct the refresh driver to resume painting after a previous call to
|
||||||
|
* pausePainting().
|
||||||
|
*/
|
||||||
|
void resumePainting();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Render the document as if being viewed on a device with the specified
|
* Render the document as if being viewed on a device with the specified
|
||||||
* media type. This will cause a reflow.
|
* media type. This will cause a reflow.
|
||||||
|
@ -27,6 +27,7 @@ support-files =
|
|||||||
file_bug234628-9-child.html
|
file_bug234628-9-child.html
|
||||||
file_bug234628-9.html
|
file_bug234628-9.html
|
||||||
file_bug420605.html
|
file_bug420605.html
|
||||||
|
file_bug422543_script.js
|
||||||
file_bug503832.html
|
file_bug503832.html
|
||||||
file_bug655270.html
|
file_bug655270.html
|
||||||
file_bug670318.html
|
file_bug670318.html
|
||||||
@ -59,13 +60,10 @@ support-files =
|
|||||||
[browser_bug234628-8.js]
|
[browser_bug234628-8.js]
|
||||||
[browser_bug234628-9.js]
|
[browser_bug234628-9.js]
|
||||||
[browser_bug349769.js]
|
[browser_bug349769.js]
|
||||||
skip-if = e10s # Bug ?????? - test touches content (newBrowser.contentDocument.nodePrincipal)
|
|
||||||
[browser_bug388121-1.js]
|
[browser_bug388121-1.js]
|
||||||
skip-if = e10s # Bug ?????? - test touches content (newBrowser.contentDocument.nodePrincipal)
|
|
||||||
[browser_bug388121-2.js]
|
[browser_bug388121-2.js]
|
||||||
[browser_bug420605.js]
|
[browser_bug420605.js]
|
||||||
[browser_bug422543.js]
|
[browser_bug422543.js]
|
||||||
skip-if = e10s # Bug 1220927 - Test tries to do addSHistoryListener on content.
|
|
||||||
[browser_bug441169.js]
|
[browser_bug441169.js]
|
||||||
skip-if = buildapp == 'mulet'
|
skip-if = buildapp == 'mulet'
|
||||||
[browser_bug503832.js]
|
[browser_bug503832.js]
|
||||||
@ -74,7 +72,6 @@ skip-if = buildapp == 'mulet'
|
|||||||
[browser_bug655270.js]
|
[browser_bug655270.js]
|
||||||
[browser_bug655273.js]
|
[browser_bug655273.js]
|
||||||
[browser_bug670318.js]
|
[browser_bug670318.js]
|
||||||
skip-if = e10s # Bug 1220927 - Test tries to do addSHistoryListener on content.
|
|
||||||
[browser_bug673467.js]
|
[browser_bug673467.js]
|
||||||
[browser_bug852909.js]
|
[browser_bug852909.js]
|
||||||
[browser_bug92473.js]
|
[browser_bug92473.js]
|
||||||
|
@ -1,44 +1,47 @@
|
|||||||
function test() {
|
add_task(function* test() {
|
||||||
waitForExplicitFinish();
|
|
||||||
|
|
||||||
var newTab;
|
|
||||||
var newBrowser;
|
|
||||||
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
||||||
var iteration = 1;
|
|
||||||
const uris = [undefined, "about:blank"];
|
const uris = [undefined, "about:blank"];
|
||||||
var uri;
|
|
||||||
|
|
||||||
function testLoad(event) {
|
function checkContentProcess(uri) {
|
||||||
newBrowser.removeEventListener("load", testLoad, true);
|
yield ContentTask.spawn(newBrowser, uri, function* (uri) {
|
||||||
is (event.target, newBrowser.contentDocument, "Unexpected target");
|
var prin = content.document.nodePrincipal;
|
||||||
var prin = newBrowser.contentDocument.nodePrincipal;
|
isnot(prin, null, "Loaded principal must not be null when adding " + uri);
|
||||||
isnot(prin, null, "Loaded principal must not be null when adding " + uri);
|
isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
|
||||||
isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
|
|
||||||
is(secMan.isSystemPrincipal(prin), false,
|
|
||||||
"Loaded principal must not be system when loading " + uri);
|
|
||||||
gBrowser.removeTab(newTab);
|
|
||||||
|
|
||||||
if (iteration == uris.length) {
|
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||||
finish();
|
.getService(Ci.nsIScriptSecurityManager);
|
||||||
} else {
|
is(secMan.isSystemPrincipal(prin), false,
|
||||||
++iteration;
|
"Loaded principal must not be system when loading " + uri);
|
||||||
doTest();
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function doTest() {
|
for (var uri of uris) {
|
||||||
uri = uris[iteration - 1];
|
yield BrowserTestUtils.withNewTab({ gBrowser }, function* (newBrowser) {
|
||||||
newTab = gBrowser.addTab(uri);
|
yield BrowserTestUtils.loadURI(newBrowser, uri);
|
||||||
newBrowser = gBrowser.getBrowserForTab(newTab);
|
|
||||||
newBrowser.addEventListener("load", testLoad, true);
|
|
||||||
var prin = newBrowser.contentDocument.nodePrincipal;
|
|
||||||
isnot(prin, null, "Forced principal must not be null when loading " + uri);
|
|
||||||
isnot(prin, undefined,
|
|
||||||
"Forced principal must not be undefined when loading " + uri);
|
|
||||||
is(secMan.isSystemPrincipal(prin), false,
|
|
||||||
"Forced principal must not be system when loading " + uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
doTest();
|
var prin = newBrowser.contentPrincipal;
|
||||||
}
|
isnot(prin, null, "Forced principal must not be null when loading " + uri);
|
||||||
|
isnot(prin, undefined,
|
||||||
|
"Forced principal must not be undefined when loading " + uri);
|
||||||
|
is(secMan.isSystemPrincipal(prin), false,
|
||||||
|
"Forced principal must not be system when loading " + uri);
|
||||||
|
|
||||||
|
// Belt-and-suspenders e10s check: make sure that the same checks hold
|
||||||
|
// true in the content process.
|
||||||
|
checkContentProcess(uri);
|
||||||
|
|
||||||
|
yield BrowserTestUtils.browserLoaded(newBrowser);
|
||||||
|
|
||||||
|
prin = newBrowser.contentPrincipal;
|
||||||
|
isnot(prin, null, "Loaded principal must not be null when adding " + uri);
|
||||||
|
isnot(prin, undefined, "Loaded principal must not be undefined when loading " + uri);
|
||||||
|
is(secMan.isSystemPrincipal(prin), false,
|
||||||
|
"Loaded principal must not be system when loading " + uri);
|
||||||
|
|
||||||
|
// Belt-and-suspenders e10s check: make sure that the same checks hold
|
||||||
|
// true in the content process.
|
||||||
|
checkContentProcess(uri);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@ -1,26 +1,15 @@
|
|||||||
function test() {
|
add_task(function* test() {
|
||||||
waitForExplicitFinish();
|
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, function* (newBrowser) {
|
||||||
|
yield ContentTask.spawn(newBrowser, null, function* () {
|
||||||
|
var prin = content.document.nodePrincipal;
|
||||||
|
isnot(prin, null, "Loaded principal must not be null");
|
||||||
|
isnot(prin, undefined, "Loaded principal must not be undefined");
|
||||||
|
|
||||||
var newTab;
|
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]
|
||||||
var newBrowser;
|
.getService(Ci.nsIScriptSecurityManager);
|
||||||
const secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
|
is(secMan.isSystemPrincipal(prin), false,
|
||||||
|
"Loaded principal must not be system");
|
||||||
function testLoad(event) {
|
});
|
||||||
newBrowser.removeEventListener("load", testLoad, true);
|
});
|
||||||
is (event.target, newBrowser.contentDocument, "Unexpected target");
|
});
|
||||||
var prin = newBrowser.contentDocument.nodePrincipal;
|
|
||||||
isnot(prin, null, "Loaded principal must not be null");
|
|
||||||
isnot(prin, undefined, "Loaded principal must not be undefined");
|
|
||||||
is(secMan.isSystemPrincipal(prin), false,
|
|
||||||
"Loaded principal must not be system");
|
|
||||||
gBrowser.removeTab(newTab);
|
|
||||||
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
newTab = gBrowser.addTab();
|
|
||||||
newBrowser = gBrowser.getBrowserForTab(newTab);
|
|
||||||
newBrowser.contentWindow.location.href = "about:blank"
|
|
||||||
newBrowser.addEventListener("load", testLoad, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,174 +1,116 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
add_task(function* runTests() {
|
||||||
|
|
||||||
function SHistoryListener() {
|
|
||||||
}
|
|
||||||
|
|
||||||
SHistoryListener.prototype = {
|
|
||||||
retval: true,
|
|
||||||
last: "initial",
|
|
||||||
|
|
||||||
OnHistoryNewEntry: function (aNewURI) {
|
|
||||||
this.last = "newentry";
|
|
||||||
},
|
|
||||||
|
|
||||||
OnHistoryGoBack: function (aBackURI) {
|
|
||||||
this.last = "goback";
|
|
||||||
return this.retval;
|
|
||||||
},
|
|
||||||
|
|
||||||
OnHistoryGoForward: function (aForwardURI) {
|
|
||||||
this.last = "goforward";
|
|
||||||
return this.retval;
|
|
||||||
},
|
|
||||||
|
|
||||||
OnHistoryGotoIndex: function (aIndex, aGotoURI) {
|
|
||||||
this.last = "gotoindex";
|
|
||||||
return this.retval;
|
|
||||||
},
|
|
||||||
|
|
||||||
OnHistoryPurge: function (aNumEntries) {
|
|
||||||
this.last = "purge";
|
|
||||||
return this.retval;
|
|
||||||
},
|
|
||||||
|
|
||||||
OnHistoryReload: function (aReloadURI, aReloadFlags) {
|
|
||||||
this.last = "reload";
|
|
||||||
return this.retval;
|
|
||||||
},
|
|
||||||
|
|
||||||
OnHistoryReplaceEntry: function (aIndex) {},
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
|
|
||||||
Ci.nsISupportsWeakReference])
|
|
||||||
};
|
|
||||||
|
|
||||||
var gFirstListener = new SHistoryListener();
|
|
||||||
var gSecondListener = new SHistoryListener();
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
TestRunner.run();
|
|
||||||
}
|
|
||||||
|
|
||||||
function runTests() {
|
|
||||||
yield setup();
|
yield setup();
|
||||||
let browser = gBrowser.selectedBrowser;
|
let browser = gBrowser.selectedBrowser;
|
||||||
checkListeners("initial", "listeners initialized");
|
// Now that we're set up, initialize our frame script.
|
||||||
|
yield checkListeners("initial", "listeners initialized");
|
||||||
|
|
||||||
// Check if all history listeners are always notified.
|
// Check if all history listeners are always notified.
|
||||||
info("# part 1");
|
info("# part 1");
|
||||||
browser.loadURI("http://www.example.com/");
|
yield whenPageShown(browser, () => browser.loadURI("http://www.example.com/"));
|
||||||
yield whenPageShown(browser);
|
yield checkListeners("newentry", "shistory has a new entry");
|
||||||
checkListeners("newentry", "shistory has a new entry");
|
|
||||||
ok(browser.canGoBack, "we can go back");
|
ok(browser.canGoBack, "we can go back");
|
||||||
|
|
||||||
browser.goBack();
|
yield whenPageShown(browser, () => browser.goBack());
|
||||||
yield whenPageShown(browser);
|
yield checkListeners("goback", "back to the first shentry");
|
||||||
checkListeners("goback", "back to the first shentry");
|
|
||||||
ok(browser.canGoForward, "we can go forward");
|
ok(browser.canGoForward, "we can go forward");
|
||||||
|
|
||||||
browser.goForward();
|
yield whenPageShown(browser, () => browser.goForward());
|
||||||
yield whenPageShown(browser);
|
yield checkListeners("goforward", "forward to the second shentry");
|
||||||
checkListeners("goforward", "forward to the second shentry");
|
|
||||||
|
|
||||||
browser.reload();
|
yield whenPageShown(browser, () => browser.reload());
|
||||||
yield whenPageShown(browser);
|
yield checkListeners("reload", "current shentry reloaded");
|
||||||
checkListeners("reload", "current shentry reloaded");
|
|
||||||
|
|
||||||
browser.gotoIndex(0);
|
yield whenPageShown(browser, () => browser.gotoIndex(0));
|
||||||
yield whenPageShown(browser);
|
yield checkListeners("gotoindex", "back to the first index");
|
||||||
checkListeners("gotoindex", "back to the first index");
|
|
||||||
|
|
||||||
// Check nsISHistoryInternal.notifyOnHistoryReload
|
// Check nsISHistoryInternal.notifyOnHistoryReload
|
||||||
info("# part 2");
|
info("# part 2");
|
||||||
ok(notifyReload(), "reloading has not been canceled");
|
ok((yield notifyReload()), "reloading has not been canceled");
|
||||||
checkListeners("reload", "saw the reload notification");
|
yield checkListeners("reload", "saw the reload notification");
|
||||||
|
|
||||||
// Let the first listener cancel the reload action.
|
// Let the first listener cancel the reload action.
|
||||||
info("# part 3");
|
info("# part 3");
|
||||||
resetListeners();
|
yield resetListeners();
|
||||||
gFirstListener.retval = false;
|
yield setListenerRetval(0, false);
|
||||||
ok(!notifyReload(), "reloading has been canceled");
|
ok(!(yield notifyReload()), "reloading has been canceled");
|
||||||
checkListeners("reload", "saw the reload notification");
|
yield checkListeners("reload", "saw the reload notification");
|
||||||
|
|
||||||
// Let both listeners cancel the reload action.
|
// Let both listeners cancel the reload action.
|
||||||
info("# part 4");
|
info("# part 4");
|
||||||
resetListeners();
|
yield resetListeners();
|
||||||
gSecondListener.retval = false;
|
yield setListenerRetval(1, false);
|
||||||
ok(!notifyReload(), "reloading has been canceled");
|
ok(!(yield notifyReload()), "reloading has been canceled");
|
||||||
checkListeners("reload", "saw the reload notification");
|
yield checkListeners("reload", "saw the reload notification");
|
||||||
|
|
||||||
// Let the second listener cancel the reload action.
|
// Let the second listener cancel the reload action.
|
||||||
info("# part 5");
|
info("# part 5");
|
||||||
resetListeners();
|
yield resetListeners();
|
||||||
gFirstListener.retval = true;
|
yield setListenerRetval(0, true);
|
||||||
ok(!notifyReload(), "reloading has been canceled");
|
ok(!(yield notifyReload()), "reloading has been canceled");
|
||||||
checkListeners("reload", "saw the reload notification");
|
yield checkListeners("reload", "saw the reload notification");
|
||||||
}
|
});
|
||||||
|
|
||||||
function checkListeners(aLast, aMessage) {
|
function listenOnce(message, arg = {}) {
|
||||||
is(gFirstListener.last, aLast, aMessage);
|
return new Promise(resolve => {
|
||||||
is(gSecondListener.last, aLast, aMessage);
|
let mm = gBrowser.selectedBrowser.messageManager;
|
||||||
}
|
mm.addMessageListener(message + ":return", function listener(msg) {
|
||||||
|
mm.removeMessageListener(message + ":return", listener);
|
||||||
function resetListeners() {
|
resolve(msg.data);
|
||||||
gFirstListener.last = gSecondListener.last = "initial";
|
|
||||||
}
|
|
||||||
|
|
||||||
function notifyReload() {
|
|
||||||
let browser = gBrowser.selectedBrowser;
|
|
||||||
let shistory = browser.docShell.sessionHistory;
|
|
||||||
shistory.QueryInterface(Ci.nsISHistoryInternal);
|
|
||||||
return shistory.notifyOnHistoryReload(browser.currentURI, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setup(aCallback) {
|
|
||||||
let tab = gBrowser.selectedTab = gBrowser.addTab("about:mozilla");
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
registerCleanupFunction(function () { gBrowser.removeTab(tab); });
|
|
||||||
|
|
||||||
whenPageShown(browser, function () {
|
|
||||||
gFirstListener = new SHistoryListener();
|
|
||||||
gSecondListener = new SHistoryListener();
|
|
||||||
|
|
||||||
let shistory = browser.docShell.sessionHistory;
|
|
||||||
shistory.addSHistoryListener(gFirstListener);
|
|
||||||
shistory.addSHistoryListener(gSecondListener);
|
|
||||||
|
|
||||||
registerCleanupFunction(function () {
|
|
||||||
shistory.removeSHistoryListener(gFirstListener);
|
|
||||||
shistory.removeSHistoryListener(gSecondListener);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
(aCallback || TestRunner.next)();
|
mm.sendAsyncMessage(message, arg);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function whenPageShown(aBrowser, aCallback) {
|
function checkListeners(aLast, aMessage) {
|
||||||
aBrowser.addEventListener("pageshow", function onLoad() {
|
return listenOnce("bug422543:getListenerStatus").then((listenerStatuses) => {
|
||||||
aBrowser.removeEventListener("pageshow", onLoad, true);
|
is(listenerStatuses[0], aLast, aMessage);
|
||||||
executeSoon(aCallback || TestRunner.next);
|
is(listenerStatuses[1], aLast, aMessage);
|
||||||
}, true);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var TestRunner = {
|
function resetListeners() {
|
||||||
run: function () {
|
return listenOnce("bug422543:resetListeners");
|
||||||
waitForExplicitFinish();
|
}
|
||||||
this._iter = runTests();
|
|
||||||
this.next();
|
|
||||||
},
|
|
||||||
|
|
||||||
next: function () {
|
function notifyReload() {
|
||||||
try {
|
return listenOnce("bug422543:notifyReload").then(({ rval }) => {
|
||||||
TestRunner._iter.next();
|
return rval;
|
||||||
} catch (e if e instanceof StopIteration) {
|
});
|
||||||
TestRunner.finish();
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
finish: function () {
|
function setListenerRetval(num, val) {
|
||||||
finish();
|
return listenOnce("bug422543:setRetval", { num, val });
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
function setup() {
|
||||||
|
return BrowserTestUtils.openNewForegroundTab(gBrowser,
|
||||||
|
"http://mochi.test:8888")
|
||||||
|
.then(function (tab) {
|
||||||
|
let browser = tab.linkedBrowser;
|
||||||
|
registerCleanupFunction(function* () {
|
||||||
|
yield listenOnce("bug422543:cleanup");
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.messageManager
|
||||||
|
.loadFrameScript(getRootDirectory(gTestPath) + "file_bug422543_script.js", false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function whenPageShown(aBrowser, aNavigation) {
|
||||||
|
let listener = ContentTask.spawn(aBrowser, null, function () {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
addEventListener("pageshow", function onLoad() {
|
||||||
|
removeEventListener("pageshow", onLoad, true);
|
||||||
|
resolve();
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
aNavigation();
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
@ -10,51 +10,53 @@
|
|||||||
|
|
||||||
const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
|
const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
|
||||||
|
|
||||||
function test() {
|
add_task(function* test() {
|
||||||
waitForExplicitFinish();
|
yield BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" },
|
||||||
|
function* (browser) {
|
||||||
|
yield ContentTask.spawn(browser, URL, function* (URL) {
|
||||||
|
let history = docShell.sessionHistory;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
let count = 0, historyListenerRemoved = false;
|
let testDone = {};
|
||||||
|
testDone.promise = new Promise(resolve => { testDone.resolve = resolve; });
|
||||||
|
|
||||||
let listener = {
|
let listener = {
|
||||||
OnHistoryNewEntry: function (aNewURI) {
|
OnHistoryNewEntry: function (aNewURI) {
|
||||||
if (aNewURI.spec == URL && 5 == ++count) {
|
if (aNewURI.spec == URL && 5 == ++count) {
|
||||||
browser.addEventListener("load", function onLoad() {
|
addEventListener("load", function onLoad() {
|
||||||
browser.removeEventListener("load", onLoad, true);
|
removeEventListener("load", onLoad, true);
|
||||||
|
|
||||||
ok(history.index < history.count, "history.index is valid");
|
ok(history.index < history.count, "history.index is valid");
|
||||||
finish();
|
testDone.resolve();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
history.removeSHistoryListener(listener);
|
history.removeSHistoryListener(listener);
|
||||||
historyListenerRemoved = true;
|
content.setTimeout(() => { content.location.reload(); }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
executeSoon(function () { BrowserReload(); });
|
return true;
|
||||||
}
|
},
|
||||||
|
|
||||||
return true;
|
OnHistoryReload: () => true,
|
||||||
},
|
OnHistoryGoBack: () => true,
|
||||||
|
OnHistoryGoForward: () => true,
|
||||||
|
OnHistoryGotoIndex: () => true,
|
||||||
|
OnHistoryPurge: () => true,
|
||||||
|
OnHistoryReplaceEntry: () => {
|
||||||
|
// The initial load of about:blank causes a transient entry to be
|
||||||
|
// created, so our first navigation to a real page is a replace
|
||||||
|
// instead of a new entry.
|
||||||
|
++count;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
OnHistoryReload: () => true,
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
|
||||||
OnHistoryGoBack: () => true,
|
Ci.nsISupportsWeakReference])
|
||||||
OnHistoryGoForward: () => true,
|
};
|
||||||
OnHistoryGotoIndex: () => true,
|
|
||||||
OnHistoryPurge: () => true,
|
|
||||||
OnHistoryReplaceEntry: () => true,
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
|
history.addSHistoryListener(listener);
|
||||||
Ci.nsISupportsWeakReference])
|
content.location = URL;
|
||||||
};
|
yield testDone.promise;
|
||||||
|
});
|
||||||
let tab = gBrowser.loadOneTab(URL, {inBackground: false});
|
|
||||||
let browser = tab.linkedBrowser;
|
|
||||||
let history = browser.sessionHistory;
|
|
||||||
|
|
||||||
history.addSHistoryListener(listener);
|
|
||||||
|
|
||||||
registerCleanupFunction(function () {
|
|
||||||
gBrowser.removeTab(tab);
|
|
||||||
|
|
||||||
if (!historyListenerRemoved)
|
|
||||||
history.removeSHistoryListener(listener);
|
|
||||||
});
|
});
|
||||||
}
|
});
|
||||||
|
98
docshell/test/browser/file_bug422543_script.js
Normal file
98
docshell/test/browser/file_bug422543_script.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
const { utils: Cu, interfaces: Ci } = Components;
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
function SHistoryListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
SHistoryListener.prototype = {
|
||||||
|
retval: true,
|
||||||
|
last: "initial",
|
||||||
|
|
||||||
|
OnHistoryNewEntry: function (aNewURI) {
|
||||||
|
this.last = "newentry";
|
||||||
|
},
|
||||||
|
|
||||||
|
OnHistoryGoBack: function (aBackURI) {
|
||||||
|
this.last = "goback";
|
||||||
|
return this.retval;
|
||||||
|
},
|
||||||
|
|
||||||
|
OnHistoryGoForward: function (aForwardURI) {
|
||||||
|
this.last = "goforward";
|
||||||
|
return this.retval;
|
||||||
|
},
|
||||||
|
|
||||||
|
OnHistoryGotoIndex: function (aIndex, aGotoURI) {
|
||||||
|
this.last = "gotoindex";
|
||||||
|
return this.retval;
|
||||||
|
},
|
||||||
|
|
||||||
|
OnHistoryPurge: function (aNumEntries) {
|
||||||
|
this.last = "purge";
|
||||||
|
return this.retval;
|
||||||
|
},
|
||||||
|
|
||||||
|
OnHistoryReload: function (aReloadURI, aReloadFlags) {
|
||||||
|
this.last = "reload";
|
||||||
|
return this.retval;
|
||||||
|
},
|
||||||
|
|
||||||
|
OnHistoryReplaceEntry: function (aIndex) {},
|
||||||
|
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
|
||||||
|
Ci.nsISupportsWeakReference])
|
||||||
|
};
|
||||||
|
|
||||||
|
let testAPI = {
|
||||||
|
shistory: null,
|
||||||
|
listeners: [ new SHistoryListener(),
|
||||||
|
new SHistoryListener() ],
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.shistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
|
||||||
|
for (let listener of this.listeners) {
|
||||||
|
this.shistory.addSHistoryListener(listener);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
for (let listener of this.listeners) {
|
||||||
|
this.shistory.removeSHistoryListener(listener);
|
||||||
|
}
|
||||||
|
this.shistory = null;
|
||||||
|
sendAsyncMessage("bug422543:cleanup:return", {});
|
||||||
|
},
|
||||||
|
|
||||||
|
getListenerStatus() {
|
||||||
|
sendAsyncMessage("bug422543:getListenerStatus:return",
|
||||||
|
this.listeners.map(l => l.last));
|
||||||
|
},
|
||||||
|
|
||||||
|
resetListeners() {
|
||||||
|
for (let listener of this.listeners) {
|
||||||
|
listener.last = "initial";
|
||||||
|
}
|
||||||
|
|
||||||
|
sendAsyncMessage("bug422543:resetListeners:return", {});
|
||||||
|
},
|
||||||
|
|
||||||
|
notifyReload() {
|
||||||
|
let internal = this.shistory.QueryInterface(Ci.nsISHistoryInternal);
|
||||||
|
let rval =
|
||||||
|
internal.notifyOnHistoryReload(content.document.documentURIObject, 0);
|
||||||
|
sendAsyncMessage("bug422543:notifyReload:return", { rval });
|
||||||
|
},
|
||||||
|
|
||||||
|
setRetval({ num, val }) {
|
||||||
|
this.listeners[num].retval = val;
|
||||||
|
sendAsyncMessage("bug422543:setRetval:return", {});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
addMessageListener("bug422543:cleanup", () => { testAPI.cleanup(); });
|
||||||
|
addMessageListener("bug422543:getListenerStatus", () => { testAPI.getListenerStatus(); });
|
||||||
|
addMessageListener("bug422543:notifyReload", () => { testAPI.notifyReload(); });
|
||||||
|
addMessageListener("bug422543:resetListeners", () => { testAPI.resetListeners(); });
|
||||||
|
addMessageListener("bug422543:setRetval", (msg) => { testAPI.setRetval(msg.data); });
|
||||||
|
|
||||||
|
testAPI.init();
|
@ -4,7 +4,7 @@
|
|||||||
function load() {
|
function load() {
|
||||||
function next() {
|
function next() {
|
||||||
if (count < 5)
|
if (count < 5)
|
||||||
iframe.src = 'data:text/html,iframe ' + (++count);
|
iframe.src = 'data:text/html;charset=utf-8,iframe ' + (++count);
|
||||||
}
|
}
|
||||||
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
@ -8,5 +8,4 @@ support-files =
|
|||||||
bug343515_pg3_2.html
|
bug343515_pg3_2.html
|
||||||
|
|
||||||
[browser_bug343515.js]
|
[browser_bug343515.js]
|
||||||
skip-if = e10s # Bug ?????? - test directly touches content (tries to QI the content window)
|
|
||||||
[browser_test-content-chromeflags.js]
|
[browser_test-content-chromeflags.js]
|
||||||
|
@ -4,14 +4,6 @@
|
|||||||
var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
|
var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/";
|
||||||
var ctx = {};
|
var ctx = {};
|
||||||
|
|
||||||
// Helper function to check if a window is active
|
|
||||||
function isActive(aWindow) {
|
|
||||||
var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIWebNavigation)
|
|
||||||
.QueryInterface(Ci.nsIDocShell);
|
|
||||||
return docshell.isActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to wait until the page from each testcase is fully loaded,
|
// We need to wait until the page from each testcase is fully loaded,
|
||||||
// including all of its descendant iframes. To do that we manually count
|
// including all of its descendant iframes. To do that we manually count
|
||||||
// how many load events should happen on that page (one for the toplevel doc
|
// how many load events should happen on that page (one for the toplevel doc
|
||||||
@ -34,6 +26,12 @@ function oneShotListener(aElem, aType, aCallback) {
|
|||||||
nShotsListener(aElem, aType, aCallback, 1);
|
nShotsListener(aElem, aType, aCallback, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function waitForPageshow(aBrowser, callback) {
|
||||||
|
return ContentTask.spawn(aBrowser, null, function* () {
|
||||||
|
yield ContentTaskUtils.waitForEvent(this, "pageshow");
|
||||||
|
}).then(callback);
|
||||||
|
}
|
||||||
|
|
||||||
// Entry point from Mochikit
|
// Entry point from Mochikit
|
||||||
function test() {
|
function test() {
|
||||||
|
|
||||||
@ -49,15 +47,13 @@ function step1() {
|
|||||||
// Get a handle on the initial tab
|
// Get a handle on the initial tab
|
||||||
ctx.tab0 = gBrowser.selectedTab;
|
ctx.tab0 = gBrowser.selectedTab;
|
||||||
ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
|
ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0);
|
||||||
ctx.tab0Window = ctx.tab0Browser.contentWindow;
|
|
||||||
|
|
||||||
// Our current tab should be active
|
// Our current tab should be active
|
||||||
ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start");
|
ok(ctx.tab0Browser.docShellIsActive, "Tab 0 should be active at test start");
|
||||||
|
|
||||||
// Open a New Tab
|
// Open a New Tab
|
||||||
ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
|
ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html");
|
||||||
ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
|
ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
|
||||||
ctx.tab1Window = ctx.tab1Browser.contentWindow;
|
|
||||||
oneShotListener(ctx.tab1Browser, "load", step2);
|
oneShotListener(ctx.tab1Browser, "load", step2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,24 +62,23 @@ function step2() {
|
|||||||
"Got expected tab 1 url in step 2");
|
"Got expected tab 1 url in step 2");
|
||||||
|
|
||||||
// Our current tab should still be active
|
// Our current tab should still be active
|
||||||
ok(isActive(ctx.tab0Window), "Tab 0 should still be active");
|
ok(ctx.tab0Browser.docShellIsActive, "Tab 0 should still be active");
|
||||||
ok(!isActive(ctx.tab1Window), "Tab 1 should not be active");
|
ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should not be active");
|
||||||
|
|
||||||
// Switch to tab 1
|
// Switch to tab 1
|
||||||
gBrowser.selectedTab = ctx.tab1;
|
BrowserTestUtils.switchTab(gBrowser, ctx.tab1).then(() => {
|
||||||
|
// Tab 1 should now be active
|
||||||
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
|
ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
|
||||||
|
|
||||||
// Tab 1 should now be active
|
// Open another tab
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
|
||||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
|
||||||
|
|
||||||
// Open another tab
|
// bug343515_pg2.html consists of a page with two iframes,
|
||||||
ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html");
|
// which will therefore generate 3 load events.
|
||||||
ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
|
nShotsListener(ctx.tab2Browser, "load", step3, 3);
|
||||||
ctx.tab2Window = ctx.tab2Browser.contentWindow;
|
});
|
||||||
|
|
||||||
// bug343515_pg2.html consists of a page with two iframes,
|
|
||||||
// which will therefore generate 3 load events.
|
|
||||||
nShotsListener(ctx.tab2Browser, "load", step3, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function step3() {
|
function step3() {
|
||||||
@ -91,115 +86,169 @@ function step3() {
|
|||||||
"Got expected tab 2 url in step 3");
|
"Got expected tab 2 url in step 3");
|
||||||
|
|
||||||
// Tab 0 should be inactive, Tab 1 should be active
|
// Tab 0 should be inactive, Tab 1 should be active
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
|
||||||
|
|
||||||
// Tab 2's window _and_ its iframes should be inactive
|
// Tab 2's window _and_ its iframes should be inactive
|
||||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
|
||||||
is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
|
ContentTask.spawn(ctx.tab2Browser, null, function* () {
|
||||||
for (var i = 0; i < ctx.tab2Window.frames.length; i++)
|
is(content.frames.length, 2, "Tab 2 should have 2 iframes");
|
||||||
info("step 3, frame " + i + " info: " + ctx.tab2Window.frames[i].location);
|
for (var i = 0; i < content.frames.length; i++) {
|
||||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
info("step 3, frame " + i + " info: " + content.frames[i].location);
|
||||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
|
|
||||||
// Navigate tab 2 to a different page
|
ok(!docShell.isActive, `Tab2 iframe ${i} should be inactive`);
|
||||||
ctx.tab2Window.location = testPath + "bug343515_pg3.html";
|
}
|
||||||
|
}).then(() => {
|
||||||
|
// Navigate tab 2 to a different page
|
||||||
|
ctx.tab2Browser.loadURI(testPath + "bug343515_pg3.html");
|
||||||
|
|
||||||
// bug343515_pg3.html consists of a page with two iframes, one of which
|
// bug343515_pg3.html consists of a page with two iframes, one of which
|
||||||
// contains another iframe, so there'll be a total of 4 load events
|
// contains another iframe, so there'll be a total of 4 load events
|
||||||
nShotsListener(ctx.tab2Browser, "load", step4, 4);
|
nShotsListener(ctx.tab2Browser, "load", step4, 4);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function step4() {
|
function step4() {
|
||||||
|
function checkTab2Active(expected) {
|
||||||
|
return ContentTask.spawn(ctx.tab2Browser, expected, function* (expected) {
|
||||||
|
function isActive(aWindow) {
|
||||||
|
var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
|
return docshell.isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
let active = expected ? "active" : "inactive";
|
||||||
|
is(content.frames.length, 2, "Tab 2 should have 2 iframes");
|
||||||
|
for (var i = 0; i < content.frames.length; i++)
|
||||||
|
info("step 4, frame " + i + " info: " + content.frames[i].location);
|
||||||
|
is(content.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
|
||||||
|
is(isActive(content.frames[0]), expected, `Tab2 iframe 0 should be ${active}`);
|
||||||
|
is(isActive(content.frames[0].frames[0]), expected,
|
||||||
|
`Tab2 iframe 0 subiframe 0 should be ${active}`);
|
||||||
|
is(isActive(content.frames[1]), expected, `Tab2 iframe 1 should be ${active}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec,
|
is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec,
|
||||||
"Got expected tab 2 url in step 4");
|
"Got expected tab 2 url in step 4");
|
||||||
|
|
||||||
// Tab 0 should be inactive, Tab 1 should be active
|
// Tab 0 should be inactive, Tab 1 should be active
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
|
||||||
|
|
||||||
// Tab2 and all descendants should be inactive
|
// Tab2 and all descendants should be inactive
|
||||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
checkTab2Active(false).then(() => {
|
||||||
is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes");
|
// Switch to Tab 2
|
||||||
for (var i = 0; i < ctx.tab2Window.frames.length; i++)
|
return BrowserTestUtils.switchTab(gBrowser, ctx.tab2);
|
||||||
info("step 4, frame " + i + " info: " + ctx.tab2Window.frames[i].location);
|
}).then(() => {
|
||||||
is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes");
|
// Check everything
|
||||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
|
ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should be inactive");
|
||||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
ok(ctx.tab2Browser.docShellIsActive, "Tab 2 should be active");
|
||||||
|
|
||||||
// Switch to Tab 2
|
|
||||||
gBrowser.selectedTab = ctx.tab2;
|
|
||||||
|
|
||||||
// Check everything
|
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
|
||||||
ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
|
|
||||||
ok(isActive(ctx.tab2Window), "Tab 2 should be active");
|
|
||||||
ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
|
|
||||||
ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active");
|
|
||||||
ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
|
|
||||||
|
|
||||||
// Go back
|
|
||||||
oneShotListener(ctx.tab2Browser, "pageshow", step5);
|
|
||||||
ctx.tab2Browser.goBack();
|
|
||||||
|
|
||||||
|
return checkTab2Active(true);
|
||||||
|
}).then(() => {
|
||||||
|
// Go back
|
||||||
|
waitForPageshow(ctx.tab2Browser, step5);
|
||||||
|
ctx.tab2Browser.goBack();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function step5() {
|
function step5() {
|
||||||
// Check everything
|
// Check everything
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive");
|
ok(!ctx.tab1Browser.docShellIsActive, "Tab 1 should be inactive");
|
||||||
ok(isActive(ctx.tab2Window), "Tab 2 should be active");
|
ok(ctx.tab2Browser.docShellIsActive, "Tab 2 should be active");
|
||||||
ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active");
|
ContentTask.spawn(ctx.tab2Browser, null, function* () {
|
||||||
ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active");
|
for (var i = 0; i < content.frames.length; i++) {
|
||||||
|
let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
|
|
||||||
// Switch to tab 1
|
ok(docShell.isActive, `Tab2 iframe ${i} should be active`);
|
||||||
gBrowser.selectedTab = ctx.tab1;
|
}
|
||||||
|
}).then(() => {
|
||||||
|
// Switch to tab 1
|
||||||
|
return BrowserTestUtils.switchTab(gBrowser, ctx.tab1);
|
||||||
|
}).then(() => {
|
||||||
|
// Navigate to page 3
|
||||||
|
ctx.tab1Browser.loadURI(testPath + "bug343515_pg3.html");
|
||||||
|
|
||||||
// Navigate to page 3
|
// bug343515_pg3.html consists of a page with two iframes, one of which
|
||||||
ctx.tab1Window.location = testPath + "bug343515_pg3.html";
|
// contains another iframe, so there'll be a total of 4 load events
|
||||||
|
nShotsListener(ctx.tab1Browser, "load", step6, 4);
|
||||||
// bug343515_pg3.html consists of a page with two iframes, one of which
|
});
|
||||||
// contains another iframe, so there'll be a total of 4 load events
|
|
||||||
nShotsListener(ctx.tab1Browser, "load", step6, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function step6() {
|
function step6() {
|
||||||
|
|
||||||
// Check everything
|
// Check everything
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
|
||||||
ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
|
ContentTask.spawn(ctx.tab1Browser, null, function* () {
|
||||||
ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
function isActive(aWindow) {
|
||||||
ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
|
var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
return docshell.isActive;
|
||||||
|
}
|
||||||
|
|
||||||
// Go forward on tab 2
|
ok(isActive(content.frames[0]), "Tab1 iframe 0 should be active");
|
||||||
oneShotListener(ctx.tab2Browser, "pageshow", step7);
|
ok(isActive(content.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
||||||
var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor)
|
ok(isActive(content.frames[1]), "Tab1 iframe 1 should be active");
|
||||||
.getInterface(Ci.nsIWebNavigation);
|
}).then(() => {
|
||||||
tab2docshell.goForward();
|
ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
|
||||||
|
return ContentTask.spawn(ctx.tab2Browser, null, function* () {
|
||||||
|
for (var i = 0; i < content.frames.length; i++) {
|
||||||
|
let docshell = content.frames[i].QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
|
|
||||||
|
ok(!docShell.isActive, `Tab2 iframe ${i} should be inactive`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then(() => {
|
||||||
|
// Go forward on tab 2
|
||||||
|
waitForPageshow(ctx.tab2Browser, step7);
|
||||||
|
ctx.tab2Browser.goForward();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function step7() {
|
function step7() {
|
||||||
|
function checkBrowser(browser, tabNum, active) {
|
||||||
|
return ContentTask.spawn(browser, { tabNum, active },
|
||||||
|
function* ({ tabNum, active }) {
|
||||||
|
function isActive(aWindow) {
|
||||||
|
var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||||
|
.getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShell);
|
||||||
|
return docshell.isActive;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.tab2Window = ctx.tab2Browser.contentWindow;
|
let activestr = active ? "active" : "inactive";
|
||||||
|
is(isActive(content.frames[0]), active,
|
||||||
|
`Tab${tabNum} iframe 0 should be ${activestr}`);
|
||||||
|
is(isActive(content.frames[0].frames[0]), active,
|
||||||
|
`Tab${tabNum} iframe 0 subiframe 0 should be ${activestr}`);
|
||||||
|
is(isActive(content.frames[1]), active,
|
||||||
|
`Tab${tabNum} iframe 1 should be ${activestr}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Check everything
|
// Check everything
|
||||||
ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive");
|
ok(!ctx.tab0Browser.docShellIsActive, "Tab 0 should be inactive");
|
||||||
ok(isActive(ctx.tab1Window), "Tab 1 should be active");
|
ok(ctx.tab1Browser.docShellIsActive, "Tab 1 should be active");
|
||||||
ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active");
|
checkBrowser(ctx.tab1Browser, 1, true).then(() => {
|
||||||
ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active");
|
ok(!ctx.tab2Browser.docShellIsActive, "Tab 2 should be inactive");
|
||||||
ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active");
|
return checkBrowser(ctx.tab2Browser, 2, false);
|
||||||
ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive");
|
}).then(() => {
|
||||||
ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive");
|
// That's probably enough
|
||||||
ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive");
|
allDone();
|
||||||
ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive");
|
});
|
||||||
|
|
||||||
// That's probably enough
|
|
||||||
allDone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function allDone() {
|
function allDone() {
|
||||||
|
@ -685,7 +685,8 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(Console)
|
|||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Console)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Console)
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
Console::Console(nsPIDOMWindow* aWindow)
|
Console::Console(nsPIDOMWindow* aWindow)
|
||||||
@ -709,7 +710,7 @@ Console::Console(nsPIDOMWindow* aWindow)
|
|||||||
if (NS_IsMainThread()) {
|
if (NS_IsMainThread()) {
|
||||||
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
|
||||||
if (obs) {
|
if (obs) {
|
||||||
obs->AddObserver(this, "inner-window-destroyed", false);
|
obs->AddObserver(this, "inner-window-destroyed", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
#include "nsWrapperCache.h"
|
#include "nsWrapperCache.h"
|
||||||
#include "nsDOMNavigationTiming.h"
|
#include "nsDOMNavigationTiming.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
@ -29,12 +30,13 @@ struct ConsoleStackEntry;
|
|||||||
|
|
||||||
class Console final : public nsIObserver
|
class Console final : public nsIObserver
|
||||||
, public nsWrapperCache
|
, public nsWrapperCache
|
||||||
|
, public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
~Console();
|
~Console();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Console)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console, nsIObserver)
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
explicit Console(nsPIDOMWindow* aWindow);
|
explicit Console(nsPIDOMWindow* aWindow);
|
||||||
|
@ -67,9 +67,6 @@ GetSriLog()
|
|||||||
return gSriPRLog;
|
return gSriPRLog;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The nsScriptLoadRequest is passed as the context to necko, and thus
|
|
||||||
// it needs to be threadsafe. Necko won't do anything with this
|
|
||||||
// context, but it will AddRef and Release it on other threads.
|
|
||||||
NS_IMPL_ISUPPORTS0(nsScriptLoadRequest)
|
NS_IMPL_ISUPPORTS0(nsScriptLoadRequest)
|
||||||
|
|
||||||
nsScriptLoadRequestList::~nsScriptLoadRequestList()
|
nsScriptLoadRequestList::~nsScriptLoadRequestList()
|
||||||
|
@ -82,7 +82,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_DECL_THREADSAFE_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
void FireScriptAvailable(nsresult aResult)
|
void FireScriptAvailable(nsresult aResult)
|
||||||
{
|
{
|
||||||
|
@ -228,6 +228,10 @@ BluetoothA2dpManager::InitA2dpInterface(BluetoothProfileResultHandler* aRes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BluetoothA2dpManager::~BluetoothA2dpManager()
|
BluetoothA2dpManager::~BluetoothA2dpManager()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothA2dpManager::Uninit()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
NS_ENSURE_TRUE_VOID(obs);
|
NS_ENSURE_TRUE_VOID(obs);
|
||||||
@ -273,9 +277,9 @@ BluetoothA2dpManager::Get()
|
|||||||
// If we're in shutdown, don't create a new instance
|
// If we're in shutdown, don't create a new instance
|
||||||
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
||||||
|
|
||||||
// Create a new instance, register, and return
|
// Create a new instance and return
|
||||||
BluetoothA2dpManager* manager = new BluetoothA2dpManager();
|
sBluetoothA2dpManager = new BluetoothA2dpManager();
|
||||||
sBluetoothA2dpManager = manager;
|
|
||||||
return sBluetoothA2dpManager;
|
return sBluetoothA2dpManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,6 +301,9 @@ public:
|
|||||||
sBtA2dpInterface->SetNotificationHandler(nullptr);
|
sBtA2dpInterface->SetNotificationHandler(nullptr);
|
||||||
sBtA2dpInterface = nullptr;
|
sBtA2dpInterface = nullptr;
|
||||||
|
|
||||||
|
sBluetoothA2dpManager->Uninit();
|
||||||
|
sBluetoothA2dpManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(NS_ERROR_FAILURE);
|
mRes->OnError(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
@ -309,6 +316,9 @@ public:
|
|||||||
sBtA2dpInterface->SetNotificationHandler(nullptr);
|
sBtA2dpInterface->SetNotificationHandler(nullptr);
|
||||||
sBtA2dpInterface = nullptr;
|
sBtA2dpInterface = nullptr;
|
||||||
|
|
||||||
|
sBluetoothA2dpManager->Uninit();
|
||||||
|
sBluetoothA2dpManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->Deinit();
|
mRes->Deinit();
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ private:
|
|||||||
|
|
||||||
BluetoothA2dpManager();
|
BluetoothA2dpManager();
|
||||||
|
|
||||||
|
void Uninit();
|
||||||
void HandleShutdown();
|
void HandleShutdown();
|
||||||
void NotifyConnectionStatusChanged();
|
void NotifyConnectionStatusChanged();
|
||||||
|
|
||||||
|
@ -268,6 +268,10 @@ BluetoothAvrcpManager::InitAvrcpInterface(BluetoothProfileResultHandler* aRes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BluetoothAvrcpManager::~BluetoothAvrcpManager()
|
BluetoothAvrcpManager::~BluetoothAvrcpManager()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothAvrcpManager::Uninit()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
NS_ENSURE_TRUE_VOID(obs);
|
NS_ENSURE_TRUE_VOID(obs);
|
||||||
@ -294,9 +298,9 @@ BluetoothAvrcpManager::Get()
|
|||||||
// If we're in shutdown, don't create a new instance
|
// If we're in shutdown, don't create a new instance
|
||||||
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
||||||
|
|
||||||
// Create a new instance, register, and return
|
// Create a new instance and return
|
||||||
BluetoothAvrcpManager* manager = new BluetoothAvrcpManager();
|
sBluetoothAvrcpManager = new BluetoothAvrcpManager();
|
||||||
sBluetoothAvrcpManager = manager;
|
|
||||||
return sBluetoothAvrcpManager;
|
return sBluetoothAvrcpManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +322,9 @@ public:
|
|||||||
sBtAvrcpInterface->SetNotificationHandler(nullptr);
|
sBtAvrcpInterface->SetNotificationHandler(nullptr);
|
||||||
sBtAvrcpInterface = nullptr;
|
sBtAvrcpInterface = nullptr;
|
||||||
|
|
||||||
|
sBluetoothAvrcpManager->Uninit();
|
||||||
|
sBluetoothAvrcpManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(NS_ERROR_FAILURE);
|
mRes->OnError(NS_ERROR_FAILURE);
|
||||||
}
|
}
|
||||||
@ -330,6 +337,9 @@ public:
|
|||||||
sBtAvrcpInterface->SetNotificationHandler(nullptr);
|
sBtAvrcpInterface->SetNotificationHandler(nullptr);
|
||||||
sBtAvrcpInterface = nullptr;
|
sBtAvrcpInterface = nullptr;
|
||||||
|
|
||||||
|
sBluetoothAvrcpManager->Uninit();
|
||||||
|
sBluetoothAvrcpManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->Deinit();
|
mRes->Deinit();
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ private:
|
|||||||
|
|
||||||
BluetoothAvrcpManager();
|
BluetoothAvrcpManager();
|
||||||
|
|
||||||
|
void Uninit();
|
||||||
void HandleShutdown();
|
void HandleShutdown();
|
||||||
void NotifyConnectionStatusChanged();
|
void NotifyConnectionStatusChanged();
|
||||||
|
|
||||||
|
@ -389,26 +389,39 @@ BluetoothGattManager::Get()
|
|||||||
NS_ENSURE_FALSE(mInShutdown, nullptr);
|
NS_ENSURE_FALSE(mInShutdown, nullptr);
|
||||||
|
|
||||||
// Create a new instance, register, and return
|
// Create a new instance, register, and return
|
||||||
BluetoothGattManager* manager = new BluetoothGattManager();
|
RefPtr<BluetoothGattManager> manager = new BluetoothGattManager();
|
||||||
NS_ENSURE_TRUE(manager->Init(), nullptr);
|
NS_ENSURE_SUCCESS(manager->Init(), nullptr);
|
||||||
|
|
||||||
sBluetoothGattManager = manager;
|
sBluetoothGattManager = manager;
|
||||||
|
|
||||||
return sBluetoothGattManager;
|
return sBluetoothGattManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
nsresult
|
||||||
BluetoothGattManager::Init()
|
BluetoothGattManager::Init()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
NS_ENSURE_TRUE(obs, false);
|
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
|
auto rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
BT_WARNING("Failed to add observers!");
|
BT_WARNING("Failed to add observers!");
|
||||||
return false;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothGattManager::Uninit()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
|
NS_ENSURE_TRUE_VOID(obs);
|
||||||
|
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
|
||||||
|
BT_WARNING("Failed to remove shutdown observer!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BluetoothGattManager::RegisterModuleResultHandler final
|
class BluetoothGattManager::RegisterModuleResultHandler final
|
||||||
@ -569,6 +582,11 @@ public:
|
|||||||
|
|
||||||
sBluetoothGattInterface->SetNotificationHandler(nullptr);
|
sBluetoothGattInterface->SetNotificationHandler(nullptr);
|
||||||
sBluetoothGattInterface = nullptr;
|
sBluetoothGattInterface = nullptr;
|
||||||
|
sClients = nullptr;
|
||||||
|
sServers = nullptr;
|
||||||
|
|
||||||
|
sBluetoothGattManager->Uninit();
|
||||||
|
sBluetoothGattManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(NS_ERROR_FAILURE);
|
mRes->OnError(NS_ERROR_FAILURE);
|
||||||
@ -584,6 +602,9 @@ public:
|
|||||||
sClients = nullptr;
|
sClients = nullptr;
|
||||||
sServers = nullptr;
|
sServers = nullptr;
|
||||||
|
|
||||||
|
sBluetoothGattManager->Uninit();
|
||||||
|
sBluetoothGattManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->Deinit();
|
mRes->Deinit();
|
||||||
}
|
}
|
||||||
@ -4090,13 +4111,7 @@ BluetoothGattManager::BluetoothGattManager()
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
BluetoothGattManager::~BluetoothGattManager()
|
BluetoothGattManager::~BluetoothGattManager()
|
||||||
{
|
{ }
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
NS_ENSURE_TRUE_VOID(obs);
|
|
||||||
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
|
|
||||||
BT_WARNING("Failed to remove shutdown observer!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
BluetoothGattManager::Observe(nsISupports* aSubject,
|
BluetoothGattManager::Observe(nsISupports* aSubject,
|
||||||
|
@ -216,8 +216,9 @@ private:
|
|||||||
class ServerSendIndicationResultHandler;
|
class ServerSendIndicationResultHandler;
|
||||||
|
|
||||||
BluetoothGattManager();
|
BluetoothGattManager();
|
||||||
bool Init();
|
|
||||||
|
|
||||||
|
nsresult Init();
|
||||||
|
void Uninit();
|
||||||
void HandleShutdown();
|
void HandleShutdown();
|
||||||
|
|
||||||
void RegisterClientNotification(BluetoothGattStatus aStatus,
|
void RegisterClientNotification(BluetoothGattStatus aStatus,
|
||||||
|
@ -84,6 +84,8 @@ BluetoothMapSmsManager::HandleShutdown()
|
|||||||
|
|
||||||
sInShutdown = true;
|
sInShutdown = true;
|
||||||
Disconnect(nullptr);
|
Disconnect(nullptr);
|
||||||
|
Uninit();
|
||||||
|
|
||||||
sMapSmsManager = nullptr;
|
sMapSmsManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,27 +100,19 @@ BluetoothMapSmsManager::BluetoothMapSmsManager()
|
|||||||
}
|
}
|
||||||
|
|
||||||
BluetoothMapSmsManager::~BluetoothMapSmsManager()
|
BluetoothMapSmsManager::~BluetoothMapSmsManager()
|
||||||
{
|
{ }
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
if (NS_WARN_IF(!obs)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_WARN_IF(NS_FAILED(
|
nsresult
|
||||||
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
BluetoothMapSmsManager::Init()
|
BluetoothMapSmsManager::Init()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
if (NS_WARN_IF(!obs)) {
|
if (NS_WARN_IF(!obs)) {
|
||||||
return false;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(
|
auto rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return false;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,7 +124,64 @@ BluetoothMapSmsManager::Init()
|
|||||||
* absence of read events when device boots up.
|
* absence of read events when device boots up.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return true;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothMapSmsManager::Uninit()
|
||||||
|
{
|
||||||
|
if (mMasServerSocket) {
|
||||||
|
mMasServerSocket->SetObserver(nullptr);
|
||||||
|
|
||||||
|
if (mMasServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mMasServerSocket->Close();
|
||||||
|
}
|
||||||
|
mMasServerSocket = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMasSocket) {
|
||||||
|
mMasSocket->SetObserver(nullptr);
|
||||||
|
|
||||||
|
if (mMasSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mMasSocket->Close();
|
||||||
|
}
|
||||||
|
mMasSocket = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
|
if (NS_WARN_IF(!obs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_WARN_IF(NS_FAILED(
|
||||||
|
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothMapSmsManager::InitMapSmsInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothMapSmsManager::DeinitMapSmsInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (sMapSmsManager) {
|
||||||
|
sMapSmsManager->Uninit();
|
||||||
|
sMapSmsManager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Deinit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
@ -150,8 +201,8 @@ BluetoothMapSmsManager::Get()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new instance, register, and return
|
// Create a new instance, register, and return
|
||||||
BluetoothMapSmsManager *manager = new BluetoothMapSmsManager();
|
RefPtr<BluetoothMapSmsManager> manager = new BluetoothMapSmsManager();
|
||||||
if (NS_WARN_IF(!manager->Init())) {
|
if (NS_WARN_IF(NS_FAILED(manager->Init()))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,10 +226,11 @@ BluetoothMapSmsManager::Listen()
|
|||||||
* BT stops; otherwise no more read events would be received even if
|
* BT stops; otherwise no more read events would be received even if
|
||||||
* BT restarts.
|
* BT restarts.
|
||||||
*/
|
*/
|
||||||
if (mMasServerSocket) {
|
if (mMasServerSocket &&
|
||||||
|
mMasServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
mMasServerSocket->Close();
|
mMasServerSocket->Close();
|
||||||
mMasServerSocket = nullptr;
|
|
||||||
}
|
}
|
||||||
|
mMasServerSocket = nullptr;
|
||||||
|
|
||||||
mMasServerSocket = new BluetoothSocket(this);
|
mMasServerSocket = new BluetoothSocket(this);
|
||||||
|
|
||||||
@ -1510,7 +1562,17 @@ BluetoothMapSmsManager::OnSocketConnectError(BluetoothSocket* aSocket)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MAS socket connection error
|
// MAS socket connection error
|
||||||
|
|
||||||
|
if (mMasServerSocket &&
|
||||||
|
mMasServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mMasServerSocket->Close();
|
||||||
|
}
|
||||||
mMasServerSocket = nullptr;
|
mMasServerSocket = nullptr;
|
||||||
|
|
||||||
|
if (mMasSocket &&
|
||||||
|
mMasSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mMasSocket->Close();
|
||||||
|
}
|
||||||
mMasSocket = nullptr;
|
mMasSocket = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1541,6 +1603,7 @@ BluetoothMapSmsManager::OnSocketDisconnect(BluetoothSocket* aSocket)
|
|||||||
// MAS socket is disconnected
|
// MAS socket is disconnected
|
||||||
AfterMapSmsDisconnected();
|
AfterMapSmsDisconnected();
|
||||||
mDeviceAddress.Clear();
|
mDeviceAddress.Clear();
|
||||||
|
|
||||||
mMasSocket = nullptr;
|
mMasSocket = nullptr;
|
||||||
|
|
||||||
Listen();
|
Listen();
|
||||||
|
@ -86,7 +86,10 @@ public:
|
|||||||
// By defualt SMS/MMS is default supported
|
// By defualt SMS/MMS is default supported
|
||||||
static const int SDP_SMS_MMS_INSTANCE_ID = 0;
|
static const int SDP_SMS_MMS_INSTANCE_ID = 0;
|
||||||
|
|
||||||
|
static void InitMapSmsInterface(BluetoothProfileResultHandler* aRes);
|
||||||
|
static void DeinitMapSmsInterface(BluetoothProfileResultHandler* aRes);
|
||||||
static BluetoothMapSmsManager* Get();
|
static BluetoothMapSmsManager* Get();
|
||||||
|
|
||||||
bool Listen();
|
bool Listen();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,7 +197,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BluetoothMapSmsManager();
|
BluetoothMapSmsManager();
|
||||||
bool Init();
|
|
||||||
|
nsresult Init();
|
||||||
|
void Uninit();
|
||||||
void HandleShutdown();
|
void HandleShutdown();
|
||||||
|
|
||||||
void ReplyToConnect();
|
void ReplyToConnect();
|
||||||
|
@ -214,31 +214,24 @@ BluetoothOppManager::BluetoothOppManager() : mConnected(false)
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
BluetoothOppManager::~BluetoothOppManager()
|
BluetoothOppManager::~BluetoothOppManager()
|
||||||
{
|
{ }
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
NS_ENSURE_TRUE_VOID(obs);
|
|
||||||
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
|
|
||||||
BT_WARNING("Failed to remove shutdown observer!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_FAILED(obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED))) {
|
nsresult
|
||||||
BT_WARNING("Failed to remove volume observer!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
BluetoothOppManager::Init()
|
BluetoothOppManager::Init()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
NS_ENSURE_TRUE(obs, false);
|
NS_ENSURE_TRUE(obs, NS_ERROR_NOT_AVAILABLE);
|
||||||
if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
|
|
||||||
|
auto rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
BT_WARNING("Failed to add shutdown observer!");
|
BT_WARNING("Failed to add shutdown observer!");
|
||||||
return false;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_FAILED(obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false))) {
|
rv = obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
BT_WARNING("Failed to add ns volume observer!");
|
BT_WARNING("Failed to add ns volume observer!");
|
||||||
return false;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -250,7 +243,67 @@ BluetoothOppManager::Init()
|
|||||||
* absence of read events when device boots up.
|
* absence of read events when device boots up.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return true;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothOppManager::Uninit()
|
||||||
|
{
|
||||||
|
if (mServerSocket) {
|
||||||
|
mServerSocket->SetObserver(nullptr);
|
||||||
|
|
||||||
|
if (mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mServerSocket->Close();
|
||||||
|
}
|
||||||
|
mServerSocket = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSocket) {
|
||||||
|
mSocket->SetObserver(nullptr);
|
||||||
|
|
||||||
|
if (mSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mSocket->Close();
|
||||||
|
}
|
||||||
|
mSocket = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
|
NS_ENSURE_TRUE_VOID(obs);
|
||||||
|
|
||||||
|
if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
|
||||||
|
BT_WARNING("Failed to remove shutdown observer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED))) {
|
||||||
|
BT_WARNING("Failed to remove volume observer!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothOppManager::InitOppInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothOppManager::DeinitOppInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (sBluetoothOppManager) {
|
||||||
|
sBluetoothOppManager->Uninit();
|
||||||
|
sBluetoothOppManager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Deinit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
@ -268,10 +321,11 @@ BluetoothOppManager::Get()
|
|||||||
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
NS_ENSURE_FALSE(sInShutdown, nullptr);
|
||||||
|
|
||||||
// Create a new instance, register, and return
|
// Create a new instance, register, and return
|
||||||
BluetoothOppManager *manager = new BluetoothOppManager();
|
RefPtr<BluetoothOppManager> manager = new BluetoothOppManager();
|
||||||
NS_ENSURE_TRUE(manager->Init(), nullptr);
|
NS_ENSURE_SUCCESS(manager->Init(), nullptr);
|
||||||
|
|
||||||
sBluetoothOppManager = manager;
|
sBluetoothOppManager = manager;
|
||||||
|
|
||||||
return sBluetoothOppManager;
|
return sBluetoothOppManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,10 +335,11 @@ BluetoothOppManager::ConnectInternal(const BluetoothAddress& aDeviceAddress)
|
|||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
// Stop listening because currently we only support one connection at a time.
|
// Stop listening because currently we only support one connection at a time.
|
||||||
if (mServerSocket) {
|
if (mServerSocket &&
|
||||||
|
mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
mServerSocket->Close();
|
mServerSocket->Close();
|
||||||
mServerSocket = nullptr;
|
|
||||||
}
|
}
|
||||||
|
mServerSocket = nullptr;
|
||||||
|
|
||||||
mIsServer = false;
|
mIsServer = false;
|
||||||
|
|
||||||
@ -310,6 +365,8 @@ BluetoothOppManager::HandleShutdown()
|
|||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
sInShutdown = true;
|
sInShutdown = true;
|
||||||
Disconnect(nullptr);
|
Disconnect(nullptr);
|
||||||
|
Uninit();
|
||||||
|
|
||||||
sBluetoothOppManager = nullptr;
|
sBluetoothOppManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,10 +413,11 @@ BluetoothOppManager::Listen()
|
|||||||
* BT stops; otherwise no more read events would be received even if
|
* BT stops; otherwise no more read events would be received even if
|
||||||
* BT restarts.
|
* BT restarts.
|
||||||
*/
|
*/
|
||||||
if (mServerSocket) {
|
if (mServerSocket &&
|
||||||
|
mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
mServerSocket->Close();
|
mServerSocket->Close();
|
||||||
mServerSocket = nullptr;
|
|
||||||
}
|
}
|
||||||
|
mServerSocket = nullptr;
|
||||||
|
|
||||||
mServerSocket = new BluetoothSocket(this);
|
mServerSocket = new BluetoothSocket(this);
|
||||||
|
|
||||||
@ -1526,7 +1584,16 @@ BluetoothOppManager::OnSocketConnectError(BluetoothSocket* aSocket)
|
|||||||
{
|
{
|
||||||
BT_LOGR("[%s]", (mIsServer)? "server" : "client");
|
BT_LOGR("[%s]", (mIsServer)? "server" : "client");
|
||||||
|
|
||||||
|
if (mServerSocket &&
|
||||||
|
mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mServerSocket->Close();
|
||||||
|
}
|
||||||
mServerSocket = nullptr;
|
mServerSocket = nullptr;
|
||||||
|
|
||||||
|
if (mSocket &&
|
||||||
|
mSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mSocket->Close();
|
||||||
|
}
|
||||||
mSocket = nullptr;
|
mSocket = nullptr;
|
||||||
|
|
||||||
if (!mIsServer) {
|
if (!mIsServer) {
|
||||||
@ -1576,7 +1643,8 @@ BluetoothOppManager::OnSocketDisconnect(BluetoothSocket* aSocket)
|
|||||||
mDeviceAddress.Clear();
|
mDeviceAddress.Clear();
|
||||||
mSuccessFlag = false;
|
mSuccessFlag = false;
|
||||||
|
|
||||||
mSocket = nullptr;
|
mSocket = nullptr; // should already be closed
|
||||||
|
|
||||||
// Listen as a server if there's no more batch to process
|
// Listen as a server if there's no more batch to process
|
||||||
if (!ProcessNextBatch()) {
|
if (!ProcessNextBatch()) {
|
||||||
Listen();
|
Listen();
|
||||||
|
@ -40,6 +40,7 @@ class BluetoothOppManager : public BluetoothSocketObserver
|
|||||||
class SendSocketDataTask;
|
class SendSocketDataTask;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BT_DECL_PROFILE_MGR_BASE
|
BT_DECL_PROFILE_MGR_BASE
|
||||||
BT_DECL_SOCKET_OBSERVER
|
BT_DECL_SOCKET_OBSERVER
|
||||||
virtual void GetName(nsACString& aName)
|
virtual void GetName(nsACString& aName)
|
||||||
@ -49,7 +50,10 @@ public:
|
|||||||
|
|
||||||
static const int MAX_PACKET_LENGTH = 0xFFFE;
|
static const int MAX_PACKET_LENGTH = 0xFFFE;
|
||||||
|
|
||||||
|
static void InitOppInterface(BluetoothProfileResultHandler* aRes);
|
||||||
|
static void DeinitOppInterface(BluetoothProfileResultHandler* aRes);
|
||||||
static BluetoothOppManager* Get();
|
static BluetoothOppManager* Get();
|
||||||
|
|
||||||
void ClientDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
|
void ClientDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
|
||||||
void ServerDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
|
void ServerDataHandler(mozilla::ipc::UnixSocketBuffer* aMessage);
|
||||||
|
|
||||||
@ -75,7 +79,8 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BluetoothOppManager();
|
BluetoothOppManager();
|
||||||
bool Init();
|
nsresult Init();
|
||||||
|
void Uninit();
|
||||||
void HandleShutdown();
|
void HandleShutdown();
|
||||||
void HandleVolumeStateChanged(nsISupports* aSubject);
|
void HandleVolumeStateChanged(nsISupports* aSubject);
|
||||||
|
|
||||||
|
@ -94,6 +94,8 @@ BluetoothPbapManager::HandleShutdown()
|
|||||||
|
|
||||||
sInShutdown = true;
|
sInShutdown = true;
|
||||||
Disconnect(nullptr);
|
Disconnect(nullptr);
|
||||||
|
Uninit();
|
||||||
|
|
||||||
sPbapManager = nullptr;
|
sPbapManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,27 +107,19 @@ BluetoothPbapManager::BluetoothPbapManager() : mPhonebookSizeRequired(false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
BluetoothPbapManager::~BluetoothPbapManager()
|
BluetoothPbapManager::~BluetoothPbapManager()
|
||||||
{
|
{ }
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
|
||||||
if (NS_WARN_IF(!obs)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_WARN_IF(NS_FAILED(
|
nsresult
|
||||||
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
BluetoothPbapManager::Init()
|
BluetoothPbapManager::Init()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
if (NS_WARN_IF(!obs)) {
|
if (NS_WARN_IF(!obs)) {
|
||||||
return false;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(
|
auto rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false)))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return false;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,7 +131,64 @@ BluetoothPbapManager::Init()
|
|||||||
* absence of read events when device boots up.
|
* absence of read events when device boots up.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return true;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothPbapManager::Uninit()
|
||||||
|
{
|
||||||
|
if (mServerSocket) {
|
||||||
|
mServerSocket->SetObserver(nullptr);
|
||||||
|
|
||||||
|
if (mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mServerSocket->Close();
|
||||||
|
}
|
||||||
|
mServerSocket = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSocket) {
|
||||||
|
mSocket->SetObserver(nullptr);
|
||||||
|
|
||||||
|
if (mSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mSocket->Close();
|
||||||
|
}
|
||||||
|
mSocket = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||||
|
if (NS_WARN_IF(!obs)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_WARN_IF(NS_FAILED(
|
||||||
|
obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothPbapManager::InitPbapInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothPbapManager::DeinitPbapInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (sPbapManager) {
|
||||||
|
sPbapManager->Uninit();
|
||||||
|
sPbapManager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Deinit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
@ -157,8 +208,8 @@ BluetoothPbapManager::Get()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new instance, register, and return
|
// Create a new instance, register, and return
|
||||||
BluetoothPbapManager *manager = new BluetoothPbapManager();
|
RefPtr<BluetoothPbapManager> manager = new BluetoothPbapManager();
|
||||||
if (NS_WARN_IF(!manager->Init())) {
|
if (NS_WARN_IF(NS_FAILED(manager->Init()))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,10 +232,11 @@ BluetoothPbapManager::Listen()
|
|||||||
* BT stops; otherwise no more read events would be received even if
|
* BT stops; otherwise no more read events would be received even if
|
||||||
* BT restarts.
|
* BT restarts.
|
||||||
*/
|
*/
|
||||||
if (mServerSocket) {
|
if (mServerSocket &&
|
||||||
|
mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
mServerSocket->Close();
|
mServerSocket->Close();
|
||||||
mServerSocket = nullptr;
|
|
||||||
}
|
}
|
||||||
|
mServerSocket = nullptr;
|
||||||
|
|
||||||
mServerSocket = new BluetoothSocket(this);
|
mServerSocket = new BluetoothSocket(this);
|
||||||
|
|
||||||
@ -1131,7 +1183,16 @@ BluetoothPbapManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
|
|||||||
void
|
void
|
||||||
BluetoothPbapManager::OnSocketConnectError(BluetoothSocket* aSocket)
|
BluetoothPbapManager::OnSocketConnectError(BluetoothSocket* aSocket)
|
||||||
{
|
{
|
||||||
|
if (mServerSocket &&
|
||||||
|
mServerSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mServerSocket->Close();
|
||||||
|
}
|
||||||
mServerSocket = nullptr;
|
mServerSocket = nullptr;
|
||||||
|
|
||||||
|
if (mSocket &&
|
||||||
|
mSocket->GetConnectionStatus() != SOCKET_DISCONNECTED) {
|
||||||
|
mSocket->Close();
|
||||||
|
}
|
||||||
mSocket = nullptr;
|
mSocket = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1147,7 +1208,8 @@ BluetoothPbapManager::OnSocketDisconnect(BluetoothSocket* aSocket)
|
|||||||
|
|
||||||
AfterPbapDisconnected();
|
AfterPbapDisconnected();
|
||||||
mDeviceAddress.Clear();
|
mDeviceAddress.Clear();
|
||||||
mSocket = nullptr;
|
|
||||||
|
mSocket = nullptr; // should already be closed
|
||||||
|
|
||||||
Listen();
|
Listen();
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,10 @@ public:
|
|||||||
static const int MAX_PACKET_LENGTH = 0xFFFE;
|
static const int MAX_PACKET_LENGTH = 0xFFFE;
|
||||||
static const int DIGEST_LENGTH = 16;
|
static const int DIGEST_LENGTH = 16;
|
||||||
|
|
||||||
|
static void InitPbapInterface(BluetoothProfileResultHandler* aRes);
|
||||||
|
static void DeinitPbapInterface(BluetoothProfileResultHandler* aRes);
|
||||||
static BluetoothPbapManager* Get();
|
static BluetoothPbapManager* Get();
|
||||||
|
|
||||||
bool Listen();
|
bool Listen();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,7 +149,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BluetoothPbapManager();
|
BluetoothPbapManager();
|
||||||
bool Init();
|
|
||||||
|
nsresult Init();
|
||||||
|
void Uninit();
|
||||||
void HandleShutdown();
|
void HandleShutdown();
|
||||||
|
|
||||||
void ReplyToConnect(const nsAString& aPassword = EmptyString());
|
void ReplyToConnect(const nsAString& aPassword = EmptyString());
|
||||||
|
@ -138,6 +138,10 @@ public:
|
|||||||
void Init() override
|
void Init() override
|
||||||
{
|
{
|
||||||
static void (* const sInitManager[])(BluetoothProfileResultHandler*) = {
|
static void (* const sInitManager[])(BluetoothProfileResultHandler*) = {
|
||||||
|
BluetoothMapSmsManager::InitMapSmsInterface,
|
||||||
|
BluetoothOppManager::InitOppInterface,
|
||||||
|
BluetoothPbapManager::InitPbapInterface,
|
||||||
|
BluetoothHidManager::InitHidInterface,
|
||||||
BluetoothHfpManager::InitHfpInterface,
|
BluetoothHfpManager::InitHfpInterface,
|
||||||
BluetoothA2dpManager::InitA2dpInterface,
|
BluetoothA2dpManager::InitA2dpInterface,
|
||||||
BluetoothAvrcpManager::InitAvrcpInterface,
|
BluetoothAvrcpManager::InitAvrcpInterface,
|
||||||
@ -280,14 +284,15 @@ BluetoothServiceBluedroid::StopInternal(BluetoothReplyRunnable* aRunnable)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
static BluetoothProfileManagerBase* sProfiles[] = {
|
BluetoothProfileManagerBase* sProfiles[] = {
|
||||||
BluetoothHfpManager::Get(),
|
// BluetoothGattManager not handled here
|
||||||
BluetoothAvrcpManager::Get(),
|
BluetoothAvrcpManager::Get(),
|
||||||
BluetoothA2dpManager::Get(),
|
BluetoothA2dpManager::Get(),
|
||||||
BluetoothOppManager::Get(),
|
BluetoothHfpManager::Get(),
|
||||||
|
BluetoothHidManager::Get(),
|
||||||
BluetoothPbapManager::Get(),
|
BluetoothPbapManager::Get(),
|
||||||
BluetoothMapSmsManager::Get(),
|
BluetoothOppManager::Get(),
|
||||||
BluetoothHidManager::Get()
|
BluetoothMapSmsManager::Get()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Disconnect all connected profiles
|
// Disconnect all connected profiles
|
||||||
@ -2037,7 +2042,11 @@ BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState)
|
|||||||
BluetoothGattManager::DeinitGattInterface,
|
BluetoothGattManager::DeinitGattInterface,
|
||||||
BluetoothAvrcpManager::DeinitAvrcpInterface,
|
BluetoothAvrcpManager::DeinitAvrcpInterface,
|
||||||
BluetoothA2dpManager::DeinitA2dpInterface,
|
BluetoothA2dpManager::DeinitA2dpInterface,
|
||||||
BluetoothHfpManager::DeinitHfpInterface
|
BluetoothHfpManager::DeinitHfpInterface,
|
||||||
|
BluetoothHidManager::DeinitHidInterface,
|
||||||
|
BluetoothPbapManager::DeinitPbapInterface,
|
||||||
|
BluetoothOppManager::DeinitOppInterface,
|
||||||
|
BluetoothMapSmsManager::DeinitMapSmsInterface
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return error if BluetoothService is unavailable
|
// Return error if BluetoothService is unavailable
|
||||||
|
@ -20,24 +20,6 @@ using namespace mozilla::ipc;
|
|||||||
USING_BLUETOOTH_NAMESPACE
|
USING_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
static const size_t MAX_READ_SIZE = 1 << 16;
|
static const size_t MAX_READ_SIZE = 1 << 16;
|
||||||
static BluetoothSocketInterface* sBluetoothSocketInterface;
|
|
||||||
|
|
||||||
// helper functions
|
|
||||||
static bool
|
|
||||||
EnsureBluetoothSocketHalLoad()
|
|
||||||
{
|
|
||||||
if (sBluetoothSocketInterface) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothInterface* btInf = BluetoothInterface::GetInstance();
|
|
||||||
NS_ENSURE_TRUE(btInf, false);
|
|
||||||
|
|
||||||
sBluetoothSocketInterface = btInf->GetBluetoothSocketInterface();
|
|
||||||
NS_ENSURE_TRUE(sBluetoothSocketInterface, false);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class mozilla::dom::bluetooth::DroidSocketImpl
|
class mozilla::dom::bluetooth::DroidSocketImpl
|
||||||
: public mozilla::ipc::UnixFdWatcher
|
: public mozilla::ipc::UnixFdWatcher
|
||||||
@ -429,24 +411,20 @@ private:
|
|||||||
class InvokeAcceptTask final : public SocketTask<DroidSocketImpl>
|
class InvokeAcceptTask final : public SocketTask<DroidSocketImpl>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InvokeAcceptTask(DroidSocketImpl* aImpl, int aFd)
|
InvokeAcceptTask(DroidSocketImpl* aImpl, int aListenFd)
|
||||||
: SocketTask<DroidSocketImpl>(aImpl)
|
: SocketTask<DroidSocketImpl>(aImpl)
|
||||||
, mFd(aFd)
|
, mListenFd(aListenFd)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void Run() override
|
void Run() override
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(GetIO()->IsConsumerThread());
|
MOZ_ASSERT(GetIO()->IsConsumerThread());
|
||||||
MOZ_ASSERT(sBluetoothSocketInterface);
|
|
||||||
|
|
||||||
BluetoothSocketResultHandler* res = new AcceptResultHandler(GetIO());
|
GetIO()->mConsumer->Accept(mListenFd, new AcceptResultHandler(GetIO()));
|
||||||
GetIO()->mConsumer->SetCurrentResultHandler(res);
|
|
||||||
|
|
||||||
sBluetoothSocketInterface->Accept(mFd, res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mFd;
|
int mListenFd;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -581,22 +559,27 @@ DroidSocketImpl::DiscardBuffer()
|
|||||||
//
|
//
|
||||||
|
|
||||||
BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver)
|
BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver)
|
||||||
: mObserver(aObserver)
|
: mSocketInterface(nullptr)
|
||||||
|
, mObserver(aObserver)
|
||||||
, mCurrentRes(nullptr)
|
, mCurrentRes(nullptr)
|
||||||
, mImpl(nullptr)
|
, mImpl(nullptr)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aObserver);
|
|
||||||
|
|
||||||
MOZ_COUNT_CTOR_INHERITED(BluetoothSocket, DataSocket);
|
MOZ_COUNT_CTOR_INHERITED(BluetoothSocket, DataSocket);
|
||||||
|
|
||||||
EnsureBluetoothSocketHalLoad();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BluetoothSocket::~BluetoothSocket()
|
BluetoothSocket::~BluetoothSocket()
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(!mImpl); // Socket is closed
|
||||||
|
|
||||||
MOZ_COUNT_DTOR_INHERITED(BluetoothSocket, DataSocket);
|
MOZ_COUNT_DTOR_INHERITED(BluetoothSocket, DataSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothSocket::SetObserver(BluetoothSocketObserver* aObserver)
|
||||||
|
{
|
||||||
|
mObserver = aObserver;
|
||||||
|
}
|
||||||
|
|
||||||
class ConnectSocketResultHandler final : public BluetoothSocketResultHandler
|
class ConnectSocketResultHandler final : public BluetoothSocketResultHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -655,6 +638,11 @@ BluetoothSocket::Connect(const BluetoothAddress& aDeviceAddress,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(!mImpl);
|
MOZ_ASSERT(!mImpl);
|
||||||
|
|
||||||
|
auto rv = LoadSocketInterface();
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
SetConnectionStatus(SOCKET_CONNECTING);
|
SetConnectionStatus(SOCKET_CONNECTING);
|
||||||
|
|
||||||
mImpl = new DroidSocketImpl(aConsumerLoop, aIOLoop, this);
|
mImpl = new DroidSocketImpl(aConsumerLoop, aIOLoop, this);
|
||||||
@ -662,7 +650,7 @@ BluetoothSocket::Connect(const BluetoothAddress& aDeviceAddress,
|
|||||||
BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
|
BluetoothSocketResultHandler* res = new ConnectSocketResultHandler(mImpl);
|
||||||
SetCurrentResultHandler(res);
|
SetCurrentResultHandler(res);
|
||||||
|
|
||||||
sBluetoothSocketInterface->Connect(
|
mSocketInterface->Connect(
|
||||||
aDeviceAddress, aType,
|
aDeviceAddress, aType,
|
||||||
aServiceUuid, aChannel,
|
aServiceUuid, aChannel,
|
||||||
aEncrypt, aAuth, res);
|
aEncrypt, aAuth, res);
|
||||||
@ -719,8 +707,13 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(!mImpl);
|
MOZ_ASSERT(!mImpl);
|
||||||
|
|
||||||
|
auto rv = LoadSocketInterface();
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
BluetoothServiceName serviceName;
|
BluetoothServiceName serviceName;
|
||||||
nsresult rv = StringToServiceName(aServiceName, serviceName);
|
rv = StringToServiceName(aServiceName, serviceName);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -732,7 +725,7 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||||||
BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
|
BluetoothSocketResultHandler* res = new ListenResultHandler(mImpl);
|
||||||
SetCurrentResultHandler(res);
|
SetCurrentResultHandler(res);
|
||||||
|
|
||||||
sBluetoothSocketInterface->Listen(
|
mSocketInterface->Listen(
|
||||||
aType,
|
aType,
|
||||||
serviceName, aServiceUuid, aChannel,
|
serviceName, aServiceUuid, aChannel,
|
||||||
aEncrypt, aAuth, res);
|
aEncrypt, aAuth, res);
|
||||||
@ -751,12 +744,26 @@ BluetoothSocket::Listen(const nsAString& aServiceName,
|
|||||||
MessageLoop::current(), XRE_GetIOMessageLoop());
|
MessageLoop::current(), XRE_GetIOMessageLoop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
BluetoothSocket::Accept(int aListenFd, BluetoothSocketResultHandler* aRes)
|
||||||
|
{
|
||||||
|
auto rv = LoadSocketInterface();
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetCurrentResultHandler(aRes);
|
||||||
|
mSocketInterface->Accept(aListenFd, aRes);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
|
BluetoothSocket::ReceiveSocketData(nsAutoPtr<UnixSocketBuffer>& aBuffer)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mObserver);
|
if (mObserver) {
|
||||||
|
mObserver->ReceiveSocketData(this, aBuffer);
|
||||||
mObserver->ReceiveSocketData(this, aBuffer);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// |DataSocket|
|
// |DataSocket|
|
||||||
@ -778,50 +785,86 @@ BluetoothSocket::SendSocketData(UnixSocketIOBuffer* aBuffer)
|
|||||||
void
|
void
|
||||||
BluetoothSocket::Close()
|
BluetoothSocket::Close()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(sBluetoothSocketInterface);
|
|
||||||
|
|
||||||
if (!mImpl) {
|
if (!mImpl) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(mImpl->IsConsumerThread());
|
|
||||||
|
|
||||||
// Stop any watching |SocketMessageWatcher|
|
|
||||||
if (mCurrentRes) {
|
|
||||||
sBluetoothSocketInterface->Close(mCurrentRes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// From this point on, we consider mImpl as being deleted.
|
|
||||||
// We sever the relationship here so any future calls to listen or connect
|
|
||||||
// will create a new implementation.
|
|
||||||
mImpl->ShutdownOnConsumerThread();
|
|
||||||
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
|
|
||||||
mImpl = nullptr;
|
|
||||||
|
|
||||||
NotifyDisconnect();
|
NotifyDisconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothSocket::OnConnectSuccess()
|
BluetoothSocket::OnConnectSuccess()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mObserver);
|
|
||||||
|
|
||||||
SetCurrentResultHandler(nullptr);
|
SetCurrentResultHandler(nullptr);
|
||||||
mObserver->OnSocketConnectSuccess(this);
|
|
||||||
|
if (mObserver) {
|
||||||
|
mObserver->OnSocketConnectSuccess(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothSocket::OnConnectError()
|
BluetoothSocket::OnConnectError()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mObserver);
|
auto observer = mObserver;
|
||||||
|
|
||||||
SetCurrentResultHandler(nullptr);
|
Cleanup();
|
||||||
mObserver->OnSocketConnectError(this);
|
|
||||||
|
if (observer) {
|
||||||
|
observer->OnSocketConnectError(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
BluetoothSocket::OnDisconnect()
|
BluetoothSocket::OnDisconnect()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mObserver);
|
auto observer = mObserver;
|
||||||
mObserver->OnSocketDisconnect(this);
|
|
||||||
|
Cleanup();
|
||||||
|
|
||||||
|
if (observer) {
|
||||||
|
observer->OnSocketDisconnect(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
BluetoothSocket::LoadSocketInterface()
|
||||||
|
{
|
||||||
|
if (mSocketInterface) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto interface = BluetoothInterface::GetInstance();
|
||||||
|
NS_ENSURE_TRUE(!!interface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
auto socketInterface = interface->GetBluetoothSocketInterface();
|
||||||
|
NS_ENSURE_TRUE(!!socketInterface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
mSocketInterface = socketInterface;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BluetoothSocket::Cleanup()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mSocketInterface);
|
||||||
|
MOZ_ASSERT(mImpl);
|
||||||
|
MOZ_ASSERT(mImpl->IsConsumerThread());
|
||||||
|
|
||||||
|
// Stop any watching |SocketMessageWatcher|
|
||||||
|
if (mCurrentRes) {
|
||||||
|
mSocketInterface->Close(mCurrentRes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// From this point on, we consider mImpl as being deleted. We
|
||||||
|
// sever the relationship here so any future calls to listen
|
||||||
|
// or connect will create a new implementation.
|
||||||
|
mImpl->ShutdownOnConsumerThread();
|
||||||
|
mImpl->GetIOLoop()->PostTask(FROM_HERE, new SocketIOShutdownTask(mImpl));
|
||||||
|
mImpl = nullptr;
|
||||||
|
|
||||||
|
mSocketInterface = nullptr;
|
||||||
|
mObserver = nullptr;
|
||||||
|
mCurrentRes = nullptr;
|
||||||
|
mDeviceAddress.Clear();
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ class MessageLoop;
|
|||||||
|
|
||||||
BEGIN_BLUETOOTH_NAMESPACE
|
BEGIN_BLUETOOTH_NAMESPACE
|
||||||
|
|
||||||
|
class BluetoothSocketInterface;
|
||||||
class BluetoothSocketObserver;
|
class BluetoothSocketObserver;
|
||||||
class BluetoothSocketResultHandler;
|
class BluetoothSocketResultHandler;
|
||||||
class DroidSocketImpl;
|
class DroidSocketImpl;
|
||||||
@ -24,6 +25,8 @@ public:
|
|||||||
BluetoothSocket(BluetoothSocketObserver* aObserver);
|
BluetoothSocket(BluetoothSocketObserver* aObserver);
|
||||||
~BluetoothSocket();
|
~BluetoothSocket();
|
||||||
|
|
||||||
|
void SetObserver(BluetoothSocketObserver* aObserver);
|
||||||
|
|
||||||
nsresult Connect(const BluetoothAddress& aDeviceAddress,
|
nsresult Connect(const BluetoothAddress& aDeviceAddress,
|
||||||
const BluetoothUuid& aServiceUuid,
|
const BluetoothUuid& aServiceUuid,
|
||||||
BluetoothSocketType aType,
|
BluetoothSocketType aType,
|
||||||
@ -52,6 +55,8 @@ public:
|
|||||||
int aChannel,
|
int aChannel,
|
||||||
bool aAuth, bool aEncrypt);
|
bool aAuth, bool aEncrypt);
|
||||||
|
|
||||||
|
nsresult Accept(int aListenFd, BluetoothSocketResultHandler* aRes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to be called whenever data is received. This is only called on the
|
* Method to be called whenever data is received. This is only called on the
|
||||||
* consumer thread.
|
* consumer thread.
|
||||||
@ -70,11 +75,6 @@ public:
|
|||||||
mDeviceAddress = aDeviceAddress;
|
mDeviceAddress = aDeviceAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SetCurrentResultHandler(BluetoothSocketResultHandler* aRes)
|
|
||||||
{
|
|
||||||
mCurrentRes = aRes;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Methods for |DataSocket|
|
// Methods for |DataSocket|
|
||||||
//
|
//
|
||||||
|
|
||||||
@ -90,6 +90,15 @@ public:
|
|||||||
void OnDisconnect() override;
|
void OnDisconnect() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
nsresult LoadSocketInterface();
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
inline void SetCurrentResultHandler(BluetoothSocketResultHandler* aRes)
|
||||||
|
{
|
||||||
|
mCurrentRes = aRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
BluetoothSocketInterface* mSocketInterface;
|
||||||
BluetoothSocketObserver* mObserver;
|
BluetoothSocketObserver* mObserver;
|
||||||
BluetoothSocketResultHandler* mCurrentRes;
|
BluetoothSocketResultHandler* mCurrentRes;
|
||||||
DroidSocketImpl* mImpl;
|
DroidSocketImpl* mImpl;
|
||||||
|
@ -176,6 +176,8 @@ BluetoothHfpManager::DeinitHfpInterface(BluetoothProfileResultHandler* aRes)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
sBluetoothHfpManager = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO:
|
* TODO:
|
||||||
* Implement DeinitHfpInterface() for applications that want to create SCO
|
* Implement DeinitHfpInterface() for applications that want to create SCO
|
||||||
|
@ -446,6 +446,7 @@ public:
|
|||||||
|
|
||||||
sBluetoothHfpInterface->SetNotificationHandler(nullptr);
|
sBluetoothHfpInterface->SetNotificationHandler(nullptr);
|
||||||
sBluetoothHfpInterface = nullptr;
|
sBluetoothHfpInterface = nullptr;
|
||||||
|
sBluetoothHfpManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->OnError(NS_ERROR_FAILURE);
|
mRes->OnError(NS_ERROR_FAILURE);
|
||||||
@ -458,6 +459,7 @@ public:
|
|||||||
|
|
||||||
sBluetoothHfpInterface->SetNotificationHandler(nullptr);
|
sBluetoothHfpInterface->SetNotificationHandler(nullptr);
|
||||||
sBluetoothHfpInterface = nullptr;
|
sBluetoothHfpInterface = nullptr;
|
||||||
|
sBluetoothHfpManager = nullptr;
|
||||||
|
|
||||||
if (mRes) {
|
if (mRes) {
|
||||||
mRes->Deinit();
|
mRes->Deinit();
|
||||||
|
@ -78,6 +78,30 @@ BluetoothHidManager::~BluetoothHidManager()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothHidManager::InitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
BluetoothHidManager::DeinitHidInterface(BluetoothProfileResultHandler* aRes)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
sBluetoothHidManager = nullptr;
|
||||||
|
|
||||||
|
if (aRes) {
|
||||||
|
aRes->Deinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
BluetoothHidManager*
|
BluetoothHidManager*
|
||||||
BluetoothHidManager::Get()
|
BluetoothHidManager::Get()
|
||||||
|
@ -22,6 +22,8 @@ public:
|
|||||||
aName.AssignLiteral("HID");
|
aName.AssignLiteral("HID");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void InitHidInterface(BluetoothProfileResultHandler* aRes);
|
||||||
|
static void DeinitHidInterface(BluetoothProfileResultHandler* aRes);
|
||||||
static BluetoothHidManager* Get();
|
static BluetoothHidManager* Get();
|
||||||
|
|
||||||
// HID-specific functions
|
// HID-specific functions
|
||||||
|
@ -258,7 +258,7 @@ WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY
|
|||||||
static bool
|
static bool
|
||||||
ValidateTextureLayerAttachment(GLenum attachment)
|
ValidateTextureLayerAttachment(GLenum attachment)
|
||||||
{
|
{
|
||||||
if (LOCAL_GL_COLOR_ATTACHMENT0 < attachment &&
|
if (LOCAL_GL_COLOR_ATTACHMENT0 <= attachment &&
|
||||||
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
|
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
@ -293,15 +293,23 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
|
|||||||
"texture object.");
|
"texture object.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level < 0)
|
if (layer < 0)
|
||||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
|
return ErrorInvalidValue("framebufferTextureLayer: layer must be >= 0.");
|
||||||
|
|
||||||
|
if (level < 0)
|
||||||
|
return ErrorInvalidValue("framebufferTextureLayer: level must be >= 0.");
|
||||||
|
|
||||||
switch (texture->Target().get()) {
|
switch (texture->Target().get()) {
|
||||||
case LOCAL_GL_TEXTURE_3D:
|
case LOCAL_GL_TEXTURE_3D:
|
||||||
if (uint32_t(layer) >= mImplMax3DTextureSize) {
|
if (uint32_t(layer) >= mImplMax3DTextureSize) {
|
||||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
||||||
"MAX_3D_TEXTURE_SIZE");
|
"MAX_3D_TEXTURE_SIZE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uint32_t(level) > FloorLog2(mImplMax3DTextureSize)) {
|
||||||
|
return ErrorInvalidValue("framebufferTextureLayer: layer mube be <= "
|
||||||
|
"log2(MAX_3D_TEXTURE_SIZE");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
case LOCAL_GL_TEXTURE_2D_ARRAY:
|
||||||
@ -309,6 +317,11 @@ WebGL2Context::FramebufferTextureLayer(GLenum target, GLenum attachment,
|
|||||||
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
return ErrorInvalidValue("framebufferTextureLayer: layer must be < "
|
||||||
"MAX_ARRAY_TEXTURE_LAYERS");
|
"MAX_ARRAY_TEXTURE_LAYERS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uint32_t(level) > FloorLog2(mImplMaxTextureSize)) {
|
||||||
|
return ErrorInvalidValue("framebufferTextureLayer: layer mube be <= "
|
||||||
|
"log2(MAX_TEXTURE_SIZE");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -52,21 +52,42 @@ bool WebGL2Context::ValidateClearBuffer(const char* info, GLenum buffer, GLint d
|
|||||||
void
|
void
|
||||||
WebGL2Context::ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value)
|
WebGL2Context::ClearBufferiv_base(GLenum buffer, GLint drawbuffer, const GLint* value)
|
||||||
{
|
{
|
||||||
|
const char funcName[] = "clearBufferiv";
|
||||||
|
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
if (mBoundDrawFramebuffer) {
|
||||||
|
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gl->fClearBufferiv(buffer, drawbuffer, value);
|
gl->fClearBufferiv(buffer, drawbuffer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGL2Context::ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value)
|
WebGL2Context::ClearBufferuiv_base(GLenum buffer, GLint drawbuffer, const GLuint* value)
|
||||||
{
|
{
|
||||||
|
const char funcName[] = "clearBufferuiv";
|
||||||
|
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
if (mBoundDrawFramebuffer) {
|
||||||
|
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gl->fClearBufferuiv(buffer, drawbuffer, value);
|
gl->fClearBufferuiv(buffer, drawbuffer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGL2Context::ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value)
|
WebGL2Context::ClearBufferfv_base(GLenum buffer, GLint drawbuffer, const GLfloat* value)
|
||||||
{
|
{
|
||||||
|
const char funcName[] = "clearBufferfv";
|
||||||
|
|
||||||
MakeContextCurrent();
|
MakeContextCurrent();
|
||||||
|
if (mBoundDrawFramebuffer) {
|
||||||
|
if (!mBoundDrawFramebuffer->ValidateAndInitAttachments(funcName))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gl->fClearBufferfv(buffer, drawbuffer, value);
|
gl->fClearBufferfv(buffer, drawbuffer, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,8 @@ WebGL2Context::DeleteSampler(WebGLSampler* sampler)
|
|||||||
for (int n = 0; n < mGLMaxTextureUnits; n++) {
|
for (int n = 0; n < mGLMaxTextureUnits; n++) {
|
||||||
if (mBoundSamplers[n] == sampler) {
|
if (mBoundSamplers[n] == sampler) {
|
||||||
mBoundSamplers[n] = nullptr;
|
mBoundSamplers[n] = nullptr;
|
||||||
|
|
||||||
|
InvalidateResolveCacheForTextureWithTexUnit(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,6 +90,7 @@ WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
|
|||||||
return ErrorInvalidOperation("bindSampler: binding deleted sampler");
|
return ErrorInvalidOperation("bindSampler: binding deleted sampler");
|
||||||
|
|
||||||
WebGLContextUnchecked::BindSampler(unit, sampler);
|
WebGLContextUnchecked::BindSampler(unit, sampler);
|
||||||
|
InvalidateResolveCacheForTextureWithTexUnit(unit);
|
||||||
|
|
||||||
mBoundSamplers[unit] = sampler;
|
mBoundSamplers[unit] = sampler;
|
||||||
}
|
}
|
||||||
@ -104,6 +107,7 @@ WebGL2Context::SamplerParameteri(WebGLSampler* sampler, GLenum pname, GLint para
|
|||||||
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri"))
|
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameteri"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sampler->SamplerParameter1i(pname, param);
|
||||||
WebGLContextUnchecked::SamplerParameteri(sampler, pname, param);
|
WebGLContextUnchecked::SamplerParameteri(sampler, pname, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +128,7 @@ WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom
|
|||||||
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv"))
|
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameteriv"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sampler->SamplerParameter1i(pname, param.Data()[0]);
|
||||||
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data());
|
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,6 +148,7 @@ WebGL2Context::SamplerParameteriv(WebGLSampler* sampler, GLenum pname, const dom
|
|||||||
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv"))
|
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameteriv"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sampler->SamplerParameter1i(pname, param[0]);
|
||||||
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements());
|
WebGLContextUnchecked::SamplerParameteriv(sampler, pname, param.Elements());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,6 +164,7 @@ WebGL2Context::SamplerParameterf(WebGLSampler* sampler, GLenum pname, GLfloat pa
|
|||||||
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf"))
|
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param), "samplerParameterf"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sampler->SamplerParameter1f(pname, param);
|
||||||
WebGLContextUnchecked::SamplerParameterf(sampler, pname, param);
|
WebGLContextUnchecked::SamplerParameterf(sampler, pname, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +185,7 @@ WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom
|
|||||||
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv"))
|
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param.Data()[0]), "samplerParameterfv"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sampler->SamplerParameter1f(pname, param.Data()[0]);
|
||||||
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data());
|
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Data());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,6 +205,7 @@ WebGL2Context::SamplerParameterfv(WebGLSampler* sampler, GLenum pname, const dom
|
|||||||
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv"))
|
if (!ValidateSamplerParameterParams(pname, WebGLIntOrFloat(param[0]), "samplerParameterfv"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
sampler->SamplerParameter1f(pname, param[0]);
|
||||||
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements());
|
WebGLContextUnchecked::SamplerParameterfv(sampler, pname, param.Elements());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +332,8 @@ public:
|
|||||||
return ActiveBoundTextureForTarget(texTarget);
|
return ActiveBoundTextureForTarget(texTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
|
||||||
|
|
||||||
already_AddRefed<Layer>
|
already_AddRefed<Layer>
|
||||||
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
|
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
|
||||||
LayerManager* manager) override;
|
LayerManager* manager) override;
|
||||||
|
@ -1316,15 +1316,50 @@ WebGLContext::DoReadPixelsAndConvert(GLint x, GLint y, GLsizei width, GLsizei he
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
IsFormatAndTypeUnpackable(GLenum format, GLenum type)
|
IsFormatAndTypeUnpackable(GLenum format, GLenum type, bool isWebGL2)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LOCAL_GL_UNSIGNED_BYTE:
|
case LOCAL_GL_UNSIGNED_BYTE:
|
||||||
|
switch (format) {
|
||||||
|
case LOCAL_GL_LUMINANCE:
|
||||||
|
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||||
|
if (!isWebGL2)
|
||||||
|
return false;
|
||||||
|
case LOCAL_GL_ALPHA:
|
||||||
|
case LOCAL_GL_RED:
|
||||||
|
case LOCAL_GL_RED_INTEGER:
|
||||||
|
case LOCAL_GL_RG:
|
||||||
|
case LOCAL_GL_RG_INTEGER:
|
||||||
|
case LOCAL_GL_RGB:
|
||||||
|
case LOCAL_GL_RGB_INTEGER:
|
||||||
|
case LOCAL_GL_RGBA:
|
||||||
|
case LOCAL_GL_RGBA_INTEGER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LOCAL_GL_BYTE:
|
||||||
|
switch (format) {
|
||||||
|
case LOCAL_GL_RED:
|
||||||
|
case LOCAL_GL_RED_INTEGER:
|
||||||
|
case LOCAL_GL_RG:
|
||||||
|
case LOCAL_GL_RG_INTEGER:
|
||||||
|
case LOCAL_GL_RGB:
|
||||||
|
case LOCAL_GL_RGB_INTEGER:
|
||||||
|
case LOCAL_GL_RGBA:
|
||||||
|
case LOCAL_GL_RGBA_INTEGER:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
case LOCAL_GL_FLOAT:
|
case LOCAL_GL_FLOAT:
|
||||||
case LOCAL_GL_HALF_FLOAT:
|
case LOCAL_GL_HALF_FLOAT:
|
||||||
case LOCAL_GL_HALF_FLOAT_OES:
|
case LOCAL_GL_HALF_FLOAT_OES:
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case LOCAL_GL_ALPHA:
|
case LOCAL_GL_RED:
|
||||||
|
case LOCAL_GL_RG:
|
||||||
case LOCAL_GL_RGB:
|
case LOCAL_GL_RGB:
|
||||||
case LOCAL_GL_RGBA:
|
case LOCAL_GL_RGBA:
|
||||||
return true;
|
return true;
|
||||||
@ -1348,14 +1383,28 @@ static bool
|
|||||||
IsIntegerFormatAndTypeUnpackable(GLenum format, GLenum type)
|
IsIntegerFormatAndTypeUnpackable(GLenum format, GLenum type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case LOCAL_GL_UNSIGNED_SHORT:
|
||||||
|
case LOCAL_GL_SHORT:
|
||||||
case LOCAL_GL_UNSIGNED_INT:
|
case LOCAL_GL_UNSIGNED_INT:
|
||||||
case LOCAL_GL_INT:
|
case LOCAL_GL_INT:
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
case LOCAL_GL_RED_INTEGER:
|
||||||
|
case LOCAL_GL_RG_INTEGER:
|
||||||
|
case LOCAL_GL_RGB_INTEGER:
|
||||||
case LOCAL_GL_RGBA_INTEGER:
|
case LOCAL_GL_RGBA_INTEGER:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||||
|
return format == LOCAL_GL_RGBA ||
|
||||||
|
format == LOCAL_GL_RGBA_INTEGER;
|
||||||
|
|
||||||
|
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
|
||||||
|
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
|
||||||
|
return format == LOCAL_GL_RGB;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1418,7 +1467,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||||||
return ErrorInvalidValue("readPixels: null destination buffer");
|
return ErrorInvalidValue("readPixels: null destination buffer");
|
||||||
|
|
||||||
if (!(IsWebGL2() && IsIntegerFormatAndTypeUnpackable(format, type)) &&
|
if (!(IsWebGL2() && IsIntegerFormatAndTypeUnpackable(format, type)) &&
|
||||||
!IsFormatAndTypeUnpackable(format, type)) {
|
!IsFormatAndTypeUnpackable(format, type, IsWebGL2())) {
|
||||||
return ErrorInvalidEnum("readPixels: Bad format or type.");
|
return ErrorInvalidEnum("readPixels: Bad format or type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1427,9 +1476,18 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||||||
// Check the format param
|
// Check the format param
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case LOCAL_GL_ALPHA:
|
case LOCAL_GL_ALPHA:
|
||||||
|
case LOCAL_GL_LUMINANCE:
|
||||||
|
case LOCAL_GL_RED:
|
||||||
|
case LOCAL_GL_RED_INTEGER:
|
||||||
channels = 1;
|
channels = 1;
|
||||||
break;
|
break;
|
||||||
|
case LOCAL_GL_LUMINANCE_ALPHA:
|
||||||
|
case LOCAL_GL_RG:
|
||||||
|
case LOCAL_GL_RG_INTEGER:
|
||||||
|
channels = 2;
|
||||||
|
break;
|
||||||
case LOCAL_GL_RGB:
|
case LOCAL_GL_RGB:
|
||||||
|
case LOCAL_GL_RGB_INTEGER:
|
||||||
channels = 3;
|
channels = 3;
|
||||||
break;
|
break;
|
||||||
case LOCAL_GL_RGBA:
|
case LOCAL_GL_RGBA:
|
||||||
@ -1445,11 +1503,22 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||||||
int bytesPerPixel;
|
int bytesPerPixel;
|
||||||
int requiredDataType;
|
int requiredDataType;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case LOCAL_GL_BYTE:
|
||||||
|
bytesPerPixel = 1*channels;
|
||||||
|
requiredDataType = js::Scalar::Int8;
|
||||||
|
break;
|
||||||
|
|
||||||
case LOCAL_GL_UNSIGNED_BYTE:
|
case LOCAL_GL_UNSIGNED_BYTE:
|
||||||
bytesPerPixel = 1*channels;
|
bytesPerPixel = 1*channels;
|
||||||
requiredDataType = js::Scalar::Uint8;
|
requiredDataType = js::Scalar::Uint8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_SHORT:
|
||||||
|
bytesPerPixel = 2*channels;
|
||||||
|
requiredDataType = js::Scalar::Int16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_UNSIGNED_SHORT:
|
||||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||||
@ -1457,13 +1526,21 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||||||
requiredDataType = js::Scalar::Uint16;
|
requiredDataType = js::Scalar::Uint16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LOCAL_GL_UNSIGNED_INT:
|
case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||||
|
case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
|
||||||
|
case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
|
||||||
|
case LOCAL_GL_UNSIGNED_INT_24_8:
|
||||||
bytesPerPixel = 4;
|
bytesPerPixel = 4;
|
||||||
requiredDataType = js::Scalar::Uint32;
|
requiredDataType = js::Scalar::Uint32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_UNSIGNED_INT:
|
||||||
|
bytesPerPixel = 4*channels;
|
||||||
|
requiredDataType = js::Scalar::Uint32;
|
||||||
|
break;
|
||||||
|
|
||||||
case LOCAL_GL_INT:
|
case LOCAL_GL_INT:
|
||||||
bytesPerPixel = 4;
|
bytesPerPixel = 4*channels;
|
||||||
requiredDataType = js::Scalar::Int32;
|
requiredDataType = js::Scalar::Int32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1524,14 +1601,28 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||||||
if (!ValidateCurFBForRead("readPixels", &srcFormat, &srcWidth, &srcHeight))
|
if (!ValidateCurFBForRead("readPixels", &srcFormat, &srcWidth, &srcHeight))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto srcType = srcFormat->format->componentType;
|
|
||||||
const bool isSrcTypeFloat = (srcType == webgl::ComponentType::Float);
|
|
||||||
|
|
||||||
// Check the format and type params to assure they are an acceptable pair (as per spec)
|
// Check the format and type params to assure they are an acceptable pair (as per spec)
|
||||||
|
auto srcType = srcFormat->format->componentType;
|
||||||
const GLenum mainReadFormat = LOCAL_GL_RGBA;
|
GLenum mainReadFormat;
|
||||||
const GLenum mainReadType = isSrcTypeFloat ? LOCAL_GL_FLOAT
|
GLenum mainReadType;
|
||||||
: LOCAL_GL_UNSIGNED_BYTE;
|
switch (srcType) {
|
||||||
|
case webgl::ComponentType::Float:
|
||||||
|
mainReadFormat = LOCAL_GL_RGBA;
|
||||||
|
mainReadType = LOCAL_GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case webgl::ComponentType::UInt:
|
||||||
|
mainReadFormat = LOCAL_GL_RGBA_INTEGER;
|
||||||
|
mainReadType = LOCAL_GL_UNSIGNED_INT;
|
||||||
|
break;
|
||||||
|
case webgl::ComponentType::Int:
|
||||||
|
mainReadFormat = LOCAL_GL_RGBA_INTEGER;
|
||||||
|
mainReadType = LOCAL_GL_INT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mainReadFormat = LOCAL_GL_RGBA;
|
||||||
|
mainReadType = LOCAL_GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum auxReadFormat = mainReadFormat;
|
GLenum auxReadFormat = mainReadFormat;
|
||||||
GLenum auxReadType = mainReadType;
|
GLenum auxReadType = mainReadType;
|
||||||
@ -1547,7 +1638,18 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum
|
|||||||
|
|
||||||
const bool mainMatches = (format == mainReadFormat && type == mainReadType);
|
const bool mainMatches = (format == mainReadFormat && type == mainReadType);
|
||||||
const bool auxMatches = (format == auxReadFormat && type == auxReadType);
|
const bool auxMatches = (format == auxReadFormat && type == auxReadType);
|
||||||
const bool isValid = mainMatches || auxMatches;
|
bool isValid = mainMatches || auxMatches;
|
||||||
|
|
||||||
|
// OpenGL ES 3.0.4 p194 - When the internal format of the rendering surface is
|
||||||
|
// RGB10_A2, a third combination of format RGBA and type UNSIGNED_INT_2_10_10_10_REV
|
||||||
|
// is accepted.
|
||||||
|
if (srcFormat->format->effectiveFormat == webgl::EffectiveFormat::RGB10_A2 &&
|
||||||
|
format == LOCAL_GL_RGBA &&
|
||||||
|
type == LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV)
|
||||||
|
{
|
||||||
|
isValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isValid)
|
if (!isValid)
|
||||||
return ErrorInvalidOperation("readPixels: Invalid format/type pair");
|
return ErrorInvalidOperation("readPixels: Invalid format/type pair");
|
||||||
|
|
||||||
|
@ -310,6 +310,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
|||||||
} else {
|
} else {
|
||||||
i = LOCAL_GL_UNSIGNED_BYTE;
|
i = LOCAL_GL_UNSIGNED_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return JS::NumberValue(uint32_t(i));
|
return JS::NumberValue(uint32_t(i));
|
||||||
}
|
}
|
||||||
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
|
case LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT: {
|
||||||
@ -330,6 +331,14 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
|||||||
} else {
|
} else {
|
||||||
i = LOCAL_GL_RGBA;
|
i = LOCAL_GL_RGBA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenGL ES 3.0.4 p112 Table 3.2 shows that read format SRGB_ALPHA is
|
||||||
|
// not supported. And if internal format of fbo is SRGB8_ALPHA8, then
|
||||||
|
// IMPLEMENTATION_COLOR_READ_FORMAT is SRGB_ALPHA which is not supported
|
||||||
|
// by ReadPixels. So, just return RGBA here.
|
||||||
|
if (i == LOCAL_GL_SRGB_ALPHA)
|
||||||
|
i = LOCAL_GL_RGBA;
|
||||||
|
|
||||||
return JS::NumberValue(uint32_t(i));
|
return JS::NumberValue(uint32_t(i));
|
||||||
}
|
}
|
||||||
// int
|
// int
|
||||||
|
@ -187,6 +187,19 @@ WebGLContext::IsTexParamValid(GLenum pname) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebGLContext::InvalidateResolveCacheForTextureWithTexUnit(const GLuint texUnit)
|
||||||
|
{
|
||||||
|
if (mBound2DTextures[texUnit])
|
||||||
|
mBound2DTextures[texUnit]->InvalidateResolveCache();
|
||||||
|
if (mBoundCubeMapTextures[texUnit])
|
||||||
|
mBoundCubeMapTextures[texUnit]->InvalidateResolveCache();
|
||||||
|
if (mBound3DTextures[texUnit])
|
||||||
|
mBound3DTextures[texUnit]->InvalidateResolveCache();
|
||||||
|
if (mBound2DArrayTextures[texUnit])
|
||||||
|
mBound2DArrayTextures[texUnit]->InvalidateResolveCache();
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// GL calls
|
// GL calls
|
||||||
|
|
||||||
|
@ -989,7 +989,13 @@ WebGLFramebuffer::ValidateAndInitAttachments(const char* funcName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear!
|
// Clear!
|
||||||
mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
|
{
|
||||||
|
// This FB maybe bind to GL_READ_FRAMEBUFFER and glClear only
|
||||||
|
// clear GL_DRAW_FRAMEBUFFER. So bind FB to GL_DRAW_FRAMEBUFFER
|
||||||
|
// here.
|
||||||
|
gl::ScopedBindFramebuffer autoFB(mContext->gl, mGLName);
|
||||||
|
mContext->ForceClearFramebufferWithDefaultValues(clearBits, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (hasDrawBuffers) {
|
if (hasDrawBuffers) {
|
||||||
fnDrawBuffers(mDrawBuffers);
|
fnDrawBuffers(mDrawBuffers);
|
||||||
|
@ -14,6 +14,15 @@ namespace mozilla {
|
|||||||
WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler)
|
WebGLSampler::WebGLSampler(WebGLContext* webgl, GLuint sampler)
|
||||||
: WebGLContextBoundObject(webgl)
|
: WebGLContextBoundObject(webgl)
|
||||||
, mGLName(sampler)
|
, mGLName(sampler)
|
||||||
|
, mMinFilter(LOCAL_GL_NEAREST_MIPMAP_LINEAR)
|
||||||
|
, mMagFilter(LOCAL_GL_LINEAR)
|
||||||
|
, mWrapS(LOCAL_GL_REPEAT)
|
||||||
|
, mWrapT(LOCAL_GL_REPEAT)
|
||||||
|
, mWrapR(LOCAL_GL_REPEAT)
|
||||||
|
, mMinLod(-1000)
|
||||||
|
, mMaxLod(1000)
|
||||||
|
, mCompareMode(LOCAL_GL_NONE)
|
||||||
|
, mCompareFunc(LOCAL_GL_LEQUAL)
|
||||||
{
|
{
|
||||||
mContext->mSamplers.insertBack(this);
|
mContext->mSamplers.insertBack(this);
|
||||||
}
|
}
|
||||||
@ -44,6 +53,72 @@ WebGLSampler::WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto)
|
|||||||
return dom::WebGLSamplerBinding::Wrap(cx, this, givenProto);
|
return dom::WebGLSamplerBinding::Wrap(cx, this, givenProto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebGLSampler::SamplerParameter1i(GLenum pname, GLint param)
|
||||||
|
{
|
||||||
|
switch (pname) {
|
||||||
|
case LOCAL_GL_TEXTURE_MIN_FILTER:
|
||||||
|
mMinFilter = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_MAG_FILTER:
|
||||||
|
mMagFilter = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_WRAP_S:
|
||||||
|
mWrapS = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_WRAP_T:
|
||||||
|
mWrapT = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_WRAP_R:
|
||||||
|
mWrapR = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_COMPARE_MODE:
|
||||||
|
mCompareMode = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_COMPARE_FUNC:
|
||||||
|
mCompareFunc = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Unhandled pname");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
|
||||||
|
if (this == mContext->mBoundSamplers[i])
|
||||||
|
mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebGLSampler::SamplerParameter1f(GLenum pname, GLfloat param)
|
||||||
|
{
|
||||||
|
switch (pname) {
|
||||||
|
case LOCAL_GL_TEXTURE_MIN_LOD:
|
||||||
|
mMinLod = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOCAL_GL_TEXTURE_MAX_LOD:
|
||||||
|
mMaxLod = param;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Unhandled pname");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < mContext->mBoundSamplers.Length(); ++i) {
|
||||||
|
if (this == mContext->mBoundSamplers[i])
|
||||||
|
mContext->InvalidateResolveCacheForTextureWithTexUnit(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLSampler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLSampler, AddRef)
|
||||||
|
@ -19,6 +19,7 @@ class WebGLSampler final
|
|||||||
, public WebGLContextBoundObject
|
, public WebGLContextBoundObject
|
||||||
{
|
{
|
||||||
friend class WebGLContext2;
|
friend class WebGLContext2;
|
||||||
|
friend class WebGLTexture;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit WebGLSampler(WebGLContext* webgl, GLuint sampler);
|
explicit WebGLSampler(WebGLContext* webgl, GLuint sampler);
|
||||||
@ -30,11 +31,24 @@ public:
|
|||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> givenProto) override;
|
||||||
|
|
||||||
|
void SamplerParameter1i(GLenum pname, GLint param);
|
||||||
|
void SamplerParameter1f(GLenum pname, GLfloat param);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLSampler)
|
||||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(WebGLSampler)
|
||||||
|
|
||||||
|
TexMinFilter mMinFilter;
|
||||||
|
TexMagFilter mMagFilter;
|
||||||
|
TexWrap mWrapS;
|
||||||
|
TexWrap mWrapT;
|
||||||
|
TexWrap mWrapR;
|
||||||
|
GLint mMinLod;
|
||||||
|
GLint mMaxLod;
|
||||||
|
TexCompareMode mCompareMode;
|
||||||
|
TexCompareFunc mCompareFunc;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~WebGLSampler();
|
~WebGLSampler();
|
||||||
};
|
};
|
||||||
|
@ -269,6 +269,22 @@ STRONG_GLENUM_BEGIN(TexWrap)
|
|||||||
STRONG_GLENUM_VALUE(MIRRORED_REPEAT),
|
STRONG_GLENUM_VALUE(MIRRORED_REPEAT),
|
||||||
STRONG_GLENUM_END(TexWrap)
|
STRONG_GLENUM_END(TexWrap)
|
||||||
|
|
||||||
|
STRONG_GLENUM_BEGIN(TexCompareMode)
|
||||||
|
STRONG_GLENUM_VALUE(NONE),
|
||||||
|
STRONG_GLENUM_VALUE(COMPARE_REF_TO_TEXTURE),
|
||||||
|
STRONG_GLENUM_END(TexCompareMode)
|
||||||
|
|
||||||
|
STRONG_GLENUM_BEGIN(TexCompareFunc)
|
||||||
|
STRONG_GLENUM_VALUE(LEQUAL),
|
||||||
|
STRONG_GLENUM_VALUE(GEQUAL),
|
||||||
|
STRONG_GLENUM_VALUE(LESS),
|
||||||
|
STRONG_GLENUM_VALUE(GREATER),
|
||||||
|
STRONG_GLENUM_VALUE(EQUAL),
|
||||||
|
STRONG_GLENUM_VALUE(NOTEQUAL),
|
||||||
|
STRONG_GLENUM_VALUE(ALWAYS),
|
||||||
|
STRONG_GLENUM_VALUE(NEVER),
|
||||||
|
STRONG_GLENUM_END(TexCompareFunc)
|
||||||
|
|
||||||
STRONG_GLENUM_BEGIN(TexFormat)
|
STRONG_GLENUM_BEGIN(TexFormat)
|
||||||
STRONG_GLENUM_VALUE(NONE), // 0x0000
|
STRONG_GLENUM_VALUE(NONE), // 0x0000
|
||||||
STRONG_GLENUM_VALUE(DEPTH_COMPONENT), // 0x1902
|
STRONG_GLENUM_VALUE(DEPTH_COMPONENT), // 0x1902
|
||||||
|
@ -190,12 +190,12 @@ WebGLTexture::SetImageInfosAtLevel(uint32_t level, const ImageInfo& newInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebGLTexture::IsMipmapComplete() const
|
WebGLTexture::IsMipmapComplete(uint32_t texUnit) const
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(DoesMinFilterRequireMipmap());
|
MOZ_ASSERT(DoesMinFilterRequireMipmap());
|
||||||
// GLES 3.0.4, p161
|
// GLES 3.0.4, p161
|
||||||
|
|
||||||
const uint32_t maxLevel = MaxEffectiveMipmapLevel();
|
const uint32_t maxLevel = MaxEffectiveMipmapLevel(texUnit);
|
||||||
|
|
||||||
// "* `level_base <= level_max`"
|
// "* `level_base <= level_max`"
|
||||||
if (mBaseMipmapLevel > maxLevel)
|
if (mBaseMipmapLevel > maxLevel)
|
||||||
@ -290,7 +290,7 @@ WebGLTexture::IsCubeComplete() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebGLTexture::IsComplete(const char** const out_reason) const
|
WebGLTexture::IsComplete(uint32_t texUnit, const char** const out_reason) const
|
||||||
{
|
{
|
||||||
// Texture completeness is established at GLES 3.0.4, p160-161.
|
// Texture completeness is established at GLES 3.0.4, p160-161.
|
||||||
// "[A] texture is complete unless any of the following conditions hold true:"
|
// "[A] texture is complete unless any of the following conditions hold true:"
|
||||||
@ -315,19 +315,23 @@ WebGLTexture::IsComplete(const char** const out_reason) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
|
||||||
|
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
|
||||||
|
TexMagFilter magFilter = sampler ? sampler->mMagFilter : mMagFilter;
|
||||||
|
|
||||||
// "* The minification filter requires a mipmap (is neither NEAREST nor LINEAR) and
|
// "* The minification filter requires a mipmap (is neither NEAREST nor LINEAR) and
|
||||||
// the texture is not mipmap complete."
|
// the texture is not mipmap complete."
|
||||||
const bool requiresMipmap = (mMinFilter != LOCAL_GL_NEAREST &&
|
const bool requiresMipmap = (minFilter != LOCAL_GL_NEAREST &&
|
||||||
mMinFilter != LOCAL_GL_LINEAR);
|
minFilter != LOCAL_GL_LINEAR);
|
||||||
if (requiresMipmap && !IsMipmapComplete()) {
|
if (requiresMipmap && !IsMipmapComplete(texUnit)) {
|
||||||
*out_reason = "Because the minification filter requires mipmapping, the texture"
|
*out_reason = "Because the minification filter requires mipmapping, the texture"
|
||||||
" must be \"mipmap complete\".";
|
" must be \"mipmap complete\".";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool isMinFilteringNearest = (mMinFilter == LOCAL_GL_NEAREST ||
|
const bool isMinFilteringNearest = (minFilter == LOCAL_GL_NEAREST ||
|
||||||
mMinFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
|
minFilter == LOCAL_GL_NEAREST_MIPMAP_NEAREST);
|
||||||
const bool isMagFilteringNearest = (mMagFilter == LOCAL_GL_NEAREST);
|
const bool isMagFilteringNearest = (magFilter == LOCAL_GL_NEAREST);
|
||||||
const bool isFilteringNearestOnly = (isMinFilteringNearest && isMagFilteringNearest);
|
const bool isFilteringNearestOnly = (isMinFilteringNearest && isMagFilteringNearest);
|
||||||
if (!isFilteringNearestOnly) {
|
if (!isFilteringNearestOnly) {
|
||||||
auto formatUsage = baseImageInfo.mFormat;
|
auto formatUsage = baseImageInfo.mFormat;
|
||||||
@ -394,9 +398,11 @@ WebGLTexture::IsComplete(const char** const out_reason) const
|
|||||||
// non-power-of-two images, and either the texture wrap mode is not
|
// non-power-of-two images, and either the texture wrap mode is not
|
||||||
// CLAMP_TO_EDGE, or the minification filter is neither NEAREST nor LINEAR."
|
// CLAMP_TO_EDGE, or the minification filter is neither NEAREST nor LINEAR."
|
||||||
if (!baseImageInfo.IsPowerOfTwo()) {
|
if (!baseImageInfo.IsPowerOfTwo()) {
|
||||||
|
TexWrap wrapS = sampler ? sampler->mWrapS : mWrapS;
|
||||||
|
TexWrap wrapT = sampler ? sampler->mWrapT : mWrapT;
|
||||||
// "either the texture wrap mode is not CLAMP_TO_EDGE"
|
// "either the texture wrap mode is not CLAMP_TO_EDGE"
|
||||||
if (mWrapS != LOCAL_GL_CLAMP_TO_EDGE ||
|
if (wrapS != LOCAL_GL_CLAMP_TO_EDGE ||
|
||||||
mWrapT != LOCAL_GL_CLAMP_TO_EDGE)
|
wrapT != LOCAL_GL_CLAMP_TO_EDGE)
|
||||||
{
|
{
|
||||||
*out_reason = "Non-power-of-two textures must have a wrap mode of"
|
*out_reason = "Non-power-of-two textures must have a wrap mode of"
|
||||||
" CLAMP_TO_EDGE.";
|
" CLAMP_TO_EDGE.";
|
||||||
@ -421,10 +427,12 @@ WebGLTexture::IsComplete(const char** const out_reason) const
|
|||||||
|
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
WebGLTexture::MaxEffectiveMipmapLevel() const
|
WebGLTexture::MaxEffectiveMipmapLevel(uint32_t texUnit) const
|
||||||
{
|
{
|
||||||
if (mMinFilter == LOCAL_GL_NEAREST ||
|
WebGLSampler* sampler = mContext->mBoundSamplers[texUnit];
|
||||||
mMinFilter == LOCAL_GL_LINEAR)
|
TexMinFilter minFilter = sampler ? sampler->mMinFilter : mMinFilter;
|
||||||
|
if (minFilter == LOCAL_GL_NEAREST ||
|
||||||
|
minFilter == LOCAL_GL_LINEAR)
|
||||||
{
|
{
|
||||||
// No mips used.
|
// No mips used.
|
||||||
return mBaseMipmapLevel;
|
return mBaseMipmapLevel;
|
||||||
@ -442,7 +450,7 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
|
|||||||
FakeBlackType* const out_fakeBlack)
|
FakeBlackType* const out_fakeBlack)
|
||||||
{
|
{
|
||||||
const char* incompleteReason;
|
const char* incompleteReason;
|
||||||
if (!IsComplete(&incompleteReason)) {
|
if (!IsComplete(texUnit, &incompleteReason)) {
|
||||||
if (incompleteReason) {
|
if (incompleteReason) {
|
||||||
mContext->GenerateWarning("%s: Active texture %u for target 0x%04x is"
|
mContext->GenerateWarning("%s: Active texture %u for target 0x%04x is"
|
||||||
" 'incomplete', and will be rendered as"
|
" 'incomplete', and will be rendered as"
|
||||||
@ -458,7 +466,7 @@ WebGLTexture::GetFakeBlackType(const char* funcName, uint32_t texUnit,
|
|||||||
bool hasUninitializedData = false;
|
bool hasUninitializedData = false;
|
||||||
bool hasInitializedData = false;
|
bool hasInitializedData = false;
|
||||||
|
|
||||||
const auto maxLevel = MaxEffectiveMipmapLevel();
|
const auto maxLevel = MaxEffectiveMipmapLevel(texUnit);
|
||||||
MOZ_ASSERT(mBaseMipmapLevel <= maxLevel);
|
MOZ_ASSERT(mBaseMipmapLevel <= maxLevel);
|
||||||
for (uint32_t level = mBaseMipmapLevel; level <= maxLevel; level++) {
|
for (uint32_t level = mBaseMipmapLevel; level <= maxLevel; level++) {
|
||||||
for (uint8_t face = 0; face < mFaceCount; face++) {
|
for (uint8_t face = 0; face < mFaceCount; face++) {
|
||||||
@ -734,6 +742,12 @@ WebGLTexture::GenerateMipmap(TexTarget texTarget)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!baseImageInfo.mFormat->isRenderable || !baseImageInfo.mFormat->isFilterable) {
|
||||||
|
mContext->ErrorInvalidOperation("generateMipmap: Texture at base level is not"
|
||||||
|
" color-renderable or texture-filterable.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Done with validation. Do the operation.
|
// Done with validation. Do the operation.
|
||||||
|
|
||||||
mContext->MakeContextCurrent();
|
mContext->MakeContextCurrent();
|
||||||
|
@ -284,7 +284,7 @@ protected:
|
|||||||
|
|
||||||
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
|
void PopulateMipChain(uint32_t baseLevel, uint32_t maxLevel);
|
||||||
|
|
||||||
uint32_t MaxEffectiveMipmapLevel() const;
|
uint32_t MaxEffectiveMipmapLevel(uint32_t texUnit) const;
|
||||||
|
|
||||||
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
|
static uint8_t FaceForTarget(TexImageTarget texImageTarget) {
|
||||||
GLenum rawTexImageTarget = texImageTarget.get();
|
GLenum rawTexImageTarget = texImageTarget.get();
|
||||||
@ -369,11 +369,11 @@ public:
|
|||||||
|
|
||||||
bool AreAllLevel0ImageInfosEqual() const;
|
bool AreAllLevel0ImageInfosEqual() const;
|
||||||
|
|
||||||
bool IsMipmapComplete() const;
|
bool IsMipmapComplete(uint32_t texUnit) const;
|
||||||
|
|
||||||
bool IsCubeComplete() const;
|
bool IsCubeComplete() const;
|
||||||
|
|
||||||
bool IsComplete(const char** const out_reason) const;
|
bool IsComplete(uint32_t texUnit, const char** const out_reason) const;
|
||||||
|
|
||||||
bool IsMipmapCubeComplete() const;
|
bool IsMipmapCubeComplete() const;
|
||||||
|
|
||||||
|
@ -11265,22 +11265,7 @@ isPixel(ctx, 50,25, 0,255,0,255, 0);
|
|||||||
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
isPixel(ctx, 1,1, 0,255,0,255, 0);
|
||||||
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
isPixel(ctx, 98,1, 0,255,0,255, 0);
|
||||||
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
isPixel(ctx, 1,48, 0,255,0,255, 0);
|
||||||
// Fails on Linux with Azure/Cairo only
|
isPixel(ctx, 20,48, 0,255,0,255, 0);
|
||||||
// The arc is drawn badly due to Cairo limitations, the error only becomes
|
|
||||||
// apparent on Linux because of anti-aliasing, probably due to X.
|
|
||||||
// The limitation is that Cairo draws arcs by stroking perpendicular to the arc,
|
|
||||||
// and at very large stroke thicknesses, this becomes a fan. Where exactly the
|
|
||||||
// 'blades' of the fan appear seems to depend on exactly how the arc is defined
|
|
||||||
// and the platform. So if the blades of the fan are where pixels are tested it
|
|
||||||
// passes the test, if the testing pixels fall in between the blades, then we fail.
|
|
||||||
// With Thebes/Cairo, we were rendering wrong, but got lucky with the test, now
|
|
||||||
// we are not so lucky.
|
|
||||||
// Bug 764125
|
|
||||||
if (IsAzureCairo() && IsLinux()) {
|
|
||||||
todo_isPixel(ctx, 20,48, 0,255,0,255, 0);
|
|
||||||
} else {
|
|
||||||
isPixel(ctx, 20,48, 0,255,0,255, 0);
|
|
||||||
}
|
|
||||||
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
isPixel(ctx, 98,48, 0,255,0,255, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2121,7 +2121,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
|
|||||||
mElementInTreeState(ELEMENT_NOT_INTREE),
|
mElementInTreeState(ELEMENT_NOT_INTREE),
|
||||||
mHasUserInteraction(false),
|
mHasUserInteraction(false),
|
||||||
mFirstFrameLoaded(false),
|
mFirstFrameLoaded(false),
|
||||||
mDefaultPlaybackStartPosition(0.0)
|
mDefaultPlaybackStartPosition(0.0),
|
||||||
|
mIsAudioTrackAudible(false)
|
||||||
{
|
{
|
||||||
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
|
mAudioChannel = AudioChannelService::GetDefaultAudioChannel();
|
||||||
|
|
||||||
@ -5177,5 +5178,14 @@ HTMLMediaElement::IsCurrentlyPlaying() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLMediaElement::NotifyAudibleStateChanged(bool aAudible)
|
||||||
|
{
|
||||||
|
if (mIsAudioTrackAudible != aAudible) {
|
||||||
|
mIsAudioTrackAudible = aAudible;
|
||||||
|
// To do ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -397,6 +397,9 @@ public:
|
|||||||
// when the connection between Rtsp server and client gets lost.
|
// when the connection between Rtsp server and client gets lost.
|
||||||
virtual void ResetConnectionState() final override;
|
virtual void ResetConnectionState() final override;
|
||||||
|
|
||||||
|
// Called by media decoder when the audible state changed.
|
||||||
|
virtual void NotifyAudibleStateChanged(bool aAudible) final override;
|
||||||
|
|
||||||
// XPCOM GetPreload() is OK
|
// XPCOM GetPreload() is OK
|
||||||
void SetPreload(const nsAString& aValue, ErrorResult& aRv)
|
void SetPreload(const nsAString& aValue, ErrorResult& aRv)
|
||||||
{
|
{
|
||||||
@ -1525,6 +1528,9 @@ private:
|
|||||||
// initially be set to zero seconds. This time is used to allow the element to
|
// initially be set to zero seconds. This time is used to allow the element to
|
||||||
// be seeked even before the media is loaded.
|
// be seeked even before the media is loaded.
|
||||||
double mDefaultPlaybackStartPosition;
|
double mDefaultPlaybackStartPosition;
|
||||||
|
|
||||||
|
// True if the audio track is producing audible sound.
|
||||||
|
bool mIsAudioTrackAudible;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
@ -1934,6 +1934,21 @@ nsTextEditorState::SetValue(const nsAString& aValue, uint32_t aFlags)
|
|||||||
// be set later with the updated mValueBeingSet.
|
// be set later with the updated mValueBeingSet.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (NS_WARN_IF(!mBoundFrame)) {
|
||||||
|
// We're not sure if this case is possible.
|
||||||
|
} else {
|
||||||
|
// If setting value won't change current value, we shouldn't commit
|
||||||
|
// composition for compatibility with the other browsers.
|
||||||
|
nsAutoString currentValue;
|
||||||
|
mBoundFrame->GetText(currentValue);
|
||||||
|
if (newValue == currentValue) {
|
||||||
|
// Note that in this case, we shouldn't fire any events with setting
|
||||||
|
// value because event handlers may try to set value recursively but
|
||||||
|
// we cannot commit composition at that time due to unsafe to run
|
||||||
|
// script (see below).
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
// If there is composition, need to commit composition first because
|
// If there is composition, need to commit composition first because
|
||||||
// other browsers do that.
|
// other browsers do that.
|
||||||
// NOTE: We don't need to block nested calls of this because input nor
|
// NOTE: We don't need to block nested calls of this because input nor
|
||||||
|
@ -54,6 +54,23 @@ AudioData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioData::IsAudible() const
|
||||||
|
{
|
||||||
|
if (!mAudioData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t frame = 0; frame < mFrames; ++frame) {
|
||||||
|
for (uint32_t channel = 0; channel < mChannels; ++channel) {
|
||||||
|
if (mAudioData[frame * mChannels + channel] != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
already_AddRefed<AudioData>
|
already_AddRefed<AudioData>
|
||||||
AudioData::TransferAndUpdateTimestampAndDuration(AudioData* aOther,
|
AudioData::TransferAndUpdateTimestampAndDuration(AudioData* aOther,
|
||||||
|
@ -149,6 +149,10 @@ public:
|
|||||||
// If mAudioBuffer is null, creates it from mAudioData.
|
// If mAudioBuffer is null, creates it from mAudioData.
|
||||||
void EnsureAudioBuffer();
|
void EnsureAudioBuffer();
|
||||||
|
|
||||||
|
// To check whether mAudioData has audible signal, it's used to distinguish
|
||||||
|
// the audiable data and silent data.
|
||||||
|
bool IsAudible() const;
|
||||||
|
|
||||||
const uint32_t mChannels;
|
const uint32_t mChannels;
|
||||||
const uint32_t mRate;
|
const uint32_t mRate;
|
||||||
// At least one of mAudioBuffer/mAudioData must be non-null.
|
// At least one of mAudioBuffer/mAudioData must be non-null.
|
||||||
|
@ -532,6 +532,8 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
|||||||
"MediaDecoder::mStateMachineDuration (Mirror)")
|
"MediaDecoder::mStateMachineDuration (Mirror)")
|
||||||
, mPlaybackPosition(AbstractThread::MainThread(), 0,
|
, mPlaybackPosition(AbstractThread::MainThread(), 0,
|
||||||
"MediaDecoder::mPlaybackPosition (Mirror)")
|
"MediaDecoder::mPlaybackPosition (Mirror)")
|
||||||
|
, mIsAudioDataAudible(AbstractThread::MainThread(), false,
|
||||||
|
"MediaDecoder::mIsAudioDataAudible (Mirror)")
|
||||||
, mVolume(AbstractThread::MainThread(), 0.0,
|
, mVolume(AbstractThread::MainThread(), 0.0,
|
||||||
"MediaDecoder::mVolume (Canonical)")
|
"MediaDecoder::mVolume (Canonical)")
|
||||||
, mPlaybackRate(AbstractThread::MainThread(), 1.0,
|
, mPlaybackRate(AbstractThread::MainThread(), 1.0,
|
||||||
@ -592,6 +594,8 @@ MediaDecoder::MediaDecoder(MediaDecoderOwner* aOwner)
|
|||||||
// mIgnoreProgressData
|
// mIgnoreProgressData
|
||||||
mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::SeekingChanged);
|
mWatchManager.Watch(mLogicallySeeking, &MediaDecoder::SeekingChanged);
|
||||||
|
|
||||||
|
mWatchManager.Watch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
|
||||||
|
|
||||||
MediaShutdownManager::Instance().Register(this);
|
MediaShutdownManager::Instance().Register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,6 +627,8 @@ MediaDecoder::Shutdown()
|
|||||||
mOnSeekingStart.Disconnect();
|
mOnSeekingStart.Disconnect();
|
||||||
mOnMediaNotSeekable.Disconnect();
|
mOnMediaNotSeekable.Disconnect();
|
||||||
|
|
||||||
|
mWatchManager.Unwatch(mIsAudioDataAudible, &MediaDecoder::NotifyAudibleStateChanged);
|
||||||
|
|
||||||
shutdown = mDecoderStateMachine->BeginShutdown()
|
shutdown = mDecoderStateMachine->BeginShutdown()
|
||||||
->Then(AbstractThread::MainThread(), __func__, this,
|
->Then(AbstractThread::MainThread(), __func__, this,
|
||||||
&MediaDecoder::FinishShutdown,
|
&MediaDecoder::FinishShutdown,
|
||||||
@ -1473,6 +1479,7 @@ MediaDecoder::SetStateMachine(MediaDecoderStateMachine* aStateMachine)
|
|||||||
mNextFrameStatus.Connect(mDecoderStateMachine->CanonicalNextFrameStatus());
|
mNextFrameStatus.Connect(mDecoderStateMachine->CanonicalNextFrameStatus());
|
||||||
mCurrentPosition.Connect(mDecoderStateMachine->CanonicalCurrentPosition());
|
mCurrentPosition.Connect(mDecoderStateMachine->CanonicalCurrentPosition());
|
||||||
mPlaybackPosition.Connect(mDecoderStateMachine->CanonicalPlaybackOffset());
|
mPlaybackPosition.Connect(mDecoderStateMachine->CanonicalPlaybackOffset());
|
||||||
|
mIsAudioDataAudible.Connect(mDecoderStateMachine->CanonicalIsAudioDataAudible());
|
||||||
} else {
|
} else {
|
||||||
mStateMachineDuration.DisconnectIfConnected();
|
mStateMachineDuration.DisconnectIfConnected();
|
||||||
mBuffered.DisconnectIfConnected();
|
mBuffered.DisconnectIfConnected();
|
||||||
@ -1480,6 +1487,7 @@ MediaDecoder::SetStateMachine(MediaDecoderStateMachine* aStateMachine)
|
|||||||
mNextFrameStatus.DisconnectIfConnected();
|
mNextFrameStatus.DisconnectIfConnected();
|
||||||
mCurrentPosition.DisconnectIfConnected();
|
mCurrentPosition.DisconnectIfConnected();
|
||||||
mPlaybackPosition.DisconnectIfConnected();
|
mPlaybackPosition.DisconnectIfConnected();
|
||||||
|
mIsAudioDataAudible.DisconnectIfConnected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1831,6 +1839,13 @@ MediaDecoder::NextFrameBufferedStatus()
|
|||||||
: MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
|
: MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoder::NotifyAudibleStateChanged()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mShuttingDown);
|
||||||
|
mOwner->NotifyAudibleStateChanged(mIsAudioDataAudible);
|
||||||
|
}
|
||||||
|
|
||||||
MediaMemoryTracker::MediaMemoryTracker()
|
MediaMemoryTracker::MediaMemoryTracker()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -777,6 +777,9 @@ protected:
|
|||||||
// start playing back again.
|
// start playing back again.
|
||||||
Mirror<int64_t> mPlaybackPosition;
|
Mirror<int64_t> mPlaybackPosition;
|
||||||
|
|
||||||
|
// Used to distiguish whether the audio is producing sound.
|
||||||
|
Mirror<bool> mIsAudioDataAudible;
|
||||||
|
|
||||||
// Volume of playback. 0.0 = muted. 1.0 = full volume.
|
// Volume of playback. 0.0 = muted. 1.0 = full volume.
|
||||||
Canonical<double> mVolume;
|
Canonical<double> mVolume;
|
||||||
|
|
||||||
@ -872,6 +875,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Notify owner when the audible state changed
|
||||||
|
void NotifyAudibleStateChanged();
|
||||||
|
|
||||||
/* Functions called by ResourceCallback */
|
/* Functions called by ResourceCallback */
|
||||||
|
|
||||||
// A media stream is assumed to be infinite if the metadata doesn't
|
// A media stream is assumed to be infinite if the metadata doesn't
|
||||||
|
@ -130,6 +130,9 @@ public:
|
|||||||
// when the connection between Rtsp server and client gets lost.
|
// when the connection between Rtsp server and client gets lost.
|
||||||
virtual void ResetConnectionState() = 0;
|
virtual void ResetConnectionState() = 0;
|
||||||
|
|
||||||
|
// Called by media decoder when the audible state changed
|
||||||
|
virtual void NotifyAudibleStateChanged(bool aAudible) = 0;
|
||||||
|
|
||||||
#ifdef MOZ_EME
|
#ifdef MOZ_EME
|
||||||
// Dispatches a "encrypted" event to the HTMLMediaElement, with the
|
// Dispatches a "encrypted" event to the HTMLMediaElement, with the
|
||||||
// provided init data. Actual dispatch may be delayed until HAVE_METADATA.
|
// provided init data. Actual dispatch may be delayed until HAVE_METADATA.
|
||||||
|
@ -116,6 +116,11 @@ static const int AUDIO_DURATION_USECS = 40000;
|
|||||||
// increase it by more.
|
// increase it by more.
|
||||||
static const int THRESHOLD_FACTOR = 2;
|
static const int THRESHOLD_FACTOR = 2;
|
||||||
|
|
||||||
|
// When the continuous silent data is over this threshold, means the a/v does
|
||||||
|
// not produce any sound. This time is decided by UX suggestion, see
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1235612#c18
|
||||||
|
static const uint32_t SILENT_DATA_THRESHOLD_USECS = 10000000;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// If we have less than this much undecoded data available, we'll consider
|
// If we have less than this much undecoded data available, we'll consider
|
||||||
@ -236,6 +241,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||||||
mOutputStreamManager(new OutputStreamManager()),
|
mOutputStreamManager(new OutputStreamManager()),
|
||||||
mResource(aDecoder->GetResource()),
|
mResource(aDecoder->GetResource()),
|
||||||
mAudioOffloading(false),
|
mAudioOffloading(false),
|
||||||
|
mSilentDataDuration(0),
|
||||||
mBuffered(mTaskQueue, TimeIntervals(),
|
mBuffered(mTaskQueue, TimeIntervals(),
|
||||||
"MediaDecoderStateMachine::mBuffered (Mirror)"),
|
"MediaDecoderStateMachine::mBuffered (Mirror)"),
|
||||||
mEstimatedDuration(mTaskQueue, NullableTimeUnit(),
|
mEstimatedDuration(mTaskQueue, NullableTimeUnit(),
|
||||||
@ -272,7 +278,9 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
|||||||
mCurrentPosition(mTaskQueue, 0,
|
mCurrentPosition(mTaskQueue, 0,
|
||||||
"MediaDecoderStateMachine::mCurrentPosition (Canonical)"),
|
"MediaDecoderStateMachine::mCurrentPosition (Canonical)"),
|
||||||
mPlaybackOffset(mTaskQueue, 0,
|
mPlaybackOffset(mTaskQueue, 0,
|
||||||
"MediaDecoderStateMachine::mPlaybackOffset (Canonical)")
|
"MediaDecoderStateMachine::mPlaybackOffset (Canonical)"),
|
||||||
|
mIsAudioDataAudible(mTaskQueue, false,
|
||||||
|
"MediaDecoderStateMachine::mIsAudioDataAudible (Canonical)")
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
|
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
|
||||||
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
|
||||||
@ -709,14 +717,36 @@ MediaDecoderStateMachine::PushFront(MediaData* aSample, MediaData::Type aSampleT
|
|||||||
UpdateNextFrameStatus();
|
UpdateNextFrameStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoderStateMachine::CheckIsAudible(const MediaData* aSample)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(OnTaskQueue());
|
||||||
|
MOZ_ASSERT(aSample->mType == MediaData::AUDIO_DATA);
|
||||||
|
|
||||||
|
const AudioData* data = aSample->As<AudioData>();
|
||||||
|
bool isAudible = data->IsAudible();
|
||||||
|
if (isAudible && !mIsAudioDataAudible) {
|
||||||
|
mIsAudioDataAudible = true;
|
||||||
|
mSilentDataDuration = 0;
|
||||||
|
} else if (isAudible && mIsAudioDataAudible) {
|
||||||
|
mSilentDataDuration += data->mDuration;
|
||||||
|
if (mSilentDataDuration > SILENT_DATA_THRESHOLD_USECS) {
|
||||||
|
mIsAudioDataAudible = false;
|
||||||
|
mSilentDataDuration = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MediaDecoderStateMachine::OnAudioPopped(const RefPtr<MediaData>& aSample)
|
MediaDecoderStateMachine::OnAudioPopped(const RefPtr<MediaData>& aSample)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(OnTaskQueue());
|
MOZ_ASSERT(OnTaskQueue());
|
||||||
|
|
||||||
mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
|
mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
|
||||||
UpdateNextFrameStatus();
|
UpdateNextFrameStatus();
|
||||||
DispatchAudioDecodeTaskIfNeeded();
|
DispatchAudioDecodeTaskIfNeeded();
|
||||||
MaybeStartBuffering();
|
MaybeStartBuffering();
|
||||||
|
CheckIsAudible(aSample);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2168,6 +2198,7 @@ MediaDecoderStateMachine::FinishShutdown()
|
|||||||
mNextFrameStatus.DisconnectAll();
|
mNextFrameStatus.DisconnectAll();
|
||||||
mCurrentPosition.DisconnectAll();
|
mCurrentPosition.DisconnectAll();
|
||||||
mPlaybackOffset.DisconnectAll();
|
mPlaybackOffset.DisconnectAll();
|
||||||
|
mIsAudioDataAudible.DisconnectAll();
|
||||||
|
|
||||||
// Shut down the watch manager before shutting down our task queue.
|
// Shut down the watch manager before shutting down our task queue.
|
||||||
mWatchManager.Shutdown();
|
mWatchManager.Shutdown();
|
||||||
|
@ -405,6 +405,7 @@ protected:
|
|||||||
void OnAudioPopped(const RefPtr<MediaData>& aSample);
|
void OnAudioPopped(const RefPtr<MediaData>& aSample);
|
||||||
void OnVideoPopped(const RefPtr<MediaData>& aSample);
|
void OnVideoPopped(const RefPtr<MediaData>& aSample);
|
||||||
|
|
||||||
|
void CheckIsAudible(const MediaData* aSample);
|
||||||
void VolumeChanged();
|
void VolumeChanged();
|
||||||
void LogicalPlaybackRateChanged();
|
void LogicalPlaybackRateChanged();
|
||||||
void PreservesPitchChanged();
|
void PreservesPitchChanged();
|
||||||
@ -1195,6 +1196,9 @@ private:
|
|||||||
// Playback will not start when audio is offloading.
|
// Playback will not start when audio is offloading.
|
||||||
bool mAudioOffloading;
|
bool mAudioOffloading;
|
||||||
|
|
||||||
|
// Duration of the continuous silent data.
|
||||||
|
uint32_t mSilentDataDuration;
|
||||||
|
|
||||||
#ifdef MOZ_EME
|
#ifdef MOZ_EME
|
||||||
void OnCDMProxyReady(RefPtr<CDMProxy> aProxy);
|
void OnCDMProxyReady(RefPtr<CDMProxy> aProxy);
|
||||||
void OnCDMProxyNotReady();
|
void OnCDMProxyNotReady();
|
||||||
@ -1263,6 +1267,9 @@ private:
|
|||||||
// Current playback position in the stream in bytes.
|
// Current playback position in the stream in bytes.
|
||||||
Canonical<int64_t> mPlaybackOffset;
|
Canonical<int64_t> mPlaybackOffset;
|
||||||
|
|
||||||
|
// Used to distiguish whether the audio is producing sound.
|
||||||
|
Canonical<bool> mIsAudioDataAudible;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
|
AbstractCanonical<media::TimeIntervals>* CanonicalBuffered() {
|
||||||
return mReader->CanonicalBuffered();
|
return mReader->CanonicalBuffered();
|
||||||
@ -1282,6 +1289,9 @@ public:
|
|||||||
AbstractCanonical<int64_t>* CanonicalPlaybackOffset() {
|
AbstractCanonical<int64_t>* CanonicalPlaybackOffset() {
|
||||||
return &mPlaybackOffset;
|
return &mPlaybackOffset;
|
||||||
}
|
}
|
||||||
|
AbstractCanonical<bool>* CanonicalIsAudioDataAudible() {
|
||||||
|
return &mIsAudioDataAudible;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void ResetConnectionState() override {}
|
void ResetConnectionState() override {}
|
||||||
|
void NotifyAudibleStateChanged(bool aAudible) override {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
#include "WMFDecoderModule.h"
|
#include "WMFDecoderModule.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_FFVPX
|
||||||
|
#include "FFVPXRuntimeLinker.h"
|
||||||
|
#endif
|
||||||
#ifdef MOZ_FFMPEG
|
#ifdef MOZ_FFMPEG
|
||||||
#include "FFmpegRuntimeLinker.h"
|
#include "FFmpegRuntimeLinker.h"
|
||||||
#endif
|
#endif
|
||||||
@ -53,6 +56,10 @@ bool PDMFactory::sAndroidMCDecoderEnabled = false;
|
|||||||
bool PDMFactory::sAndroidMCDecoderPreferred = false;
|
bool PDMFactory::sAndroidMCDecoderPreferred = false;
|
||||||
#endif
|
#endif
|
||||||
bool PDMFactory::sGMPDecoderEnabled = false;
|
bool PDMFactory::sGMPDecoderEnabled = false;
|
||||||
|
#ifdef MOZ_FFVPX
|
||||||
|
bool PDMFactory::sFFVPXDecoderEnabled = false;
|
||||||
|
using namespace ffvpx;
|
||||||
|
#endif
|
||||||
#ifdef MOZ_FFMPEG
|
#ifdef MOZ_FFMPEG
|
||||||
bool PDMFactory::sFFmpegDecoderEnabled = false;
|
bool PDMFactory::sFFmpegDecoderEnabled = false;
|
||||||
#endif
|
#endif
|
||||||
@ -94,6 +101,10 @@ PDMFactory::Init()
|
|||||||
Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
|
Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
|
||||||
"media.ffmpeg.enabled", false);
|
"media.ffmpeg.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_FFVPX
|
||||||
|
Preferences::AddBoolVarCache(&sFFVPXDecoderEnabled,
|
||||||
|
"media.ffvpx.enabled", false);
|
||||||
|
#endif
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
Preferences::AddBoolVarCache(&sWMFDecoderEnabled,
|
Preferences::AddBoolVarCache(&sWMFDecoderEnabled,
|
||||||
"media.wmf.enabled", false);
|
"media.wmf.enabled", false);
|
||||||
@ -112,6 +123,9 @@ PDMFactory::Init()
|
|||||||
#ifdef MOZ_APPLEMEDIA
|
#ifdef MOZ_APPLEMEDIA
|
||||||
AppleDecoderModule::Init();
|
AppleDecoderModule::Init();
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_FFVPX
|
||||||
|
FFVPXRuntimeLinker::Link();
|
||||||
|
#endif
|
||||||
#ifdef MOZ_FFMPEG
|
#ifdef MOZ_FFMPEG
|
||||||
FFmpegRuntimeLinker::Link();
|
FFmpegRuntimeLinker::Link();
|
||||||
#endif
|
#endif
|
||||||
@ -262,6 +276,12 @@ PDMFactory::CreatePDMs()
|
|||||||
StartupPDM(m);
|
StartupPDM(m);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_FFVPX
|
||||||
|
if (sFFVPXDecoderEnabled) {
|
||||||
|
m = FFVPXRuntimeLinker::CreateDecoderModule();
|
||||||
|
StartupPDM(m);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef MOZ_FFMPEG
|
#ifdef MOZ_FFMPEG
|
||||||
if (sFFmpegDecoderEnabled) {
|
if (sFFmpegDecoderEnabled) {
|
||||||
m = FFmpegRuntimeLinker::CreateDecoderModule();
|
m = FFmpegRuntimeLinker::CreateDecoderModule();
|
||||||
|
@ -73,6 +73,9 @@ private:
|
|||||||
static bool sAndroidMCDecoderEnabled;
|
static bool sAndroidMCDecoderEnabled;
|
||||||
#endif
|
#endif
|
||||||
static bool sGMPDecoderEnabled;
|
static bool sGMPDecoderEnabled;
|
||||||
|
#ifdef MOZ_FFVPX
|
||||||
|
static bool sFFVPXDecoderEnabled;
|
||||||
|
#endif
|
||||||
#ifdef MOZ_FFMPEG
|
#ifdef MOZ_FFMPEG
|
||||||
static bool sFFmpegDecoderEnabled;
|
static bool sFFmpegDecoderEnabled;
|
||||||
#endif
|
#endif
|
||||||
|
@ -101,7 +101,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
av_init_packet(&packet);
|
AV_CALL(av_init_packet(&packet));
|
||||||
|
|
||||||
packet.data = const_cast<uint8_t*>(aSample->Data());
|
packet.data = const_cast<uint8_t*>(aSample->Data());
|
||||||
packet.size = aSample->Size();
|
packet.size = aSample->Size();
|
||||||
@ -118,7 +118,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
|||||||
while (packet.size > 0) {
|
while (packet.size > 0) {
|
||||||
int decoded;
|
int decoded;
|
||||||
int bytesConsumed =
|
int bytesConsumed =
|
||||||
avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet);
|
AV_CALL(avcodec_decode_audio4(mCodecContext, mFrame, &decoded, &packet));
|
||||||
|
|
||||||
if (bytesConsumed < 0) {
|
if (bytesConsumed < 0) {
|
||||||
NS_WARNING("FFmpeg audio decoder error.");
|
NS_WARNING("FFmpeg audio decoder error.");
|
||||||
|
@ -54,7 +54,7 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
|||||||
|
|
||||||
StaticMutexAutoLock mon(sMonitor);
|
StaticMutexAutoLock mon(sMonitor);
|
||||||
|
|
||||||
if (!(mCodecContext = avcodec_alloc_context3(codec))) {
|
if (!(mCodecContext = AV_CALL(avcodec_alloc_context3(codec)))) {
|
||||||
NS_WARNING("Couldn't init ffmpeg context");
|
NS_WARNING("Couldn't init ffmpeg context");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
@ -77,10 +77,10 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
|||||||
mCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
|
mCodecContext->flags |= CODEC_FLAG_EMU_EDGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (avcodec_open2(mCodecContext, codec, nullptr) < 0) {
|
if (AV_CALL(avcodec_open2(mCodecContext, codec, nullptr)) < 0) {
|
||||||
NS_WARNING("Couldn't initialise ffmpeg decoder");
|
NS_WARNING("Couldn't initialise ffmpeg decoder");
|
||||||
avcodec_close(mCodecContext);
|
AV_CALL(avcodec_close(mCodecContext));
|
||||||
av_freep(&mCodecContext);
|
AV_CALL(av_freep(&mCodecContext));
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessFlush()
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
if (mCodecContext) {
|
if (mCodecContext) {
|
||||||
avcodec_flush_buffers(mCodecContext);
|
AV_CALL(avcodec_flush_buffers(mCodecContext));
|
||||||
}
|
}
|
||||||
MonitorAutoLock mon(mMonitor);
|
MonitorAutoLock mon(mMonitor);
|
||||||
mIsFlushing = false;
|
mIsFlushing = false;
|
||||||
@ -154,12 +154,12 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown()
|
|||||||
StaticMutexAutoLock mon(sMonitor);
|
StaticMutexAutoLock mon(sMonitor);
|
||||||
|
|
||||||
if (sFFmpegInitDone && mCodecContext) {
|
if (sFFmpegInitDone && mCodecContext) {
|
||||||
avcodec_close(mCodecContext);
|
AV_CALL(avcodec_close(mCodecContext));
|
||||||
av_freep(&mCodecContext);
|
AV_CALL(av_freep(&mCodecContext));
|
||||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||||
av_frame_free(&mFrame);
|
AV_CALL(av_frame_free(&mFrame));
|
||||||
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
||||||
avcodec_free_frame(&mFrame);
|
AV_CALL(avcodec_free_frame(&mFrame));
|
||||||
#else
|
#else
|
||||||
delete mFrame;
|
delete mFrame;
|
||||||
mFrame = nullptr;
|
mFrame = nullptr;
|
||||||
@ -173,20 +173,20 @@ FFmpegDataDecoder<LIBAV_VER>::PrepareFrame()
|
|||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||||
if (mFrame) {
|
if (mFrame) {
|
||||||
av_frame_unref(mFrame);
|
AV_CALL(av_frame_unref(mFrame));
|
||||||
} else {
|
} else {
|
||||||
mFrame = av_frame_alloc();
|
mFrame = AV_CALL(av_frame_alloc());
|
||||||
}
|
}
|
||||||
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
#elif LIBAVCODEC_VERSION_MAJOR == 54
|
||||||
if (mFrame) {
|
if (mFrame) {
|
||||||
avcodec_get_frame_defaults(mFrame);
|
AV_CALL(avcodec_get_frame_defaults(mFrame));
|
||||||
} else {
|
} else {
|
||||||
mFrame = avcodec_alloc_frame();
|
mFrame = AV_CALL(avcodec_alloc_frame());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
delete mFrame;
|
delete mFrame;
|
||||||
mFrame = new AVFrame;
|
mFrame = new AVFrame;
|
||||||
avcodec_get_frame_defaults(mFrame);
|
AV_CALL(avcodec_get_frame_defaults(mFrame));
|
||||||
#endif
|
#endif
|
||||||
return mFrame;
|
return mFrame;
|
||||||
}
|
}
|
||||||
@ -196,13 +196,13 @@ FFmpegDataDecoder<LIBAV_VER>::FindAVCodec(AVCodecID aCodec)
|
|||||||
{
|
{
|
||||||
StaticMutexAutoLock mon(sMonitor);
|
StaticMutexAutoLock mon(sMonitor);
|
||||||
if (!sFFmpegInitDone) {
|
if (!sFFmpegInitDone) {
|
||||||
avcodec_register_all();
|
AV_CALL(avcodec_register_all());
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
av_log_set_level(AV_LOG_DEBUG);
|
AV_CALL(av_log_set_level(AV_LOG_DEBUG));
|
||||||
#endif
|
#endif
|
||||||
sFFmpegInitDone = true;
|
sFFmpegInitDone = true;
|
||||||
}
|
}
|
||||||
return avcodec_find_decoder(aCodec);
|
return AV_CALL(avcodec_find_decoder(aCodec));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "PlatformDecoderModule.h"
|
#include "PlatformDecoderModule.h"
|
||||||
#include "FFmpegAudioDecoder.h"
|
#include "FFmpegAudioDecoder.h"
|
||||||
#include "FFmpegH264Decoder.h"
|
#include "FFmpegVideoDecoder.h"
|
||||||
|
|
||||||
namespace mozilla
|
namespace mozilla
|
||||||
{
|
{
|
||||||
@ -37,8 +37,8 @@ public:
|
|||||||
MediaDataDecoderCallback* aCallback) override
|
MediaDataDecoderCallback* aCallback) override
|
||||||
{
|
{
|
||||||
RefPtr<MediaDataDecoder> decoder =
|
RefPtr<MediaDataDecoder> decoder =
|
||||||
new FFmpegH264Decoder<V>(aVideoTaskQueue, aCallback, aConfig,
|
new FFmpegVideoDecoder<V>(aVideoTaskQueue, aCallback, aConfig,
|
||||||
aImageContainer);
|
aImageContainer);
|
||||||
return decoder.forget();
|
return decoder.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,15 +47,23 @@ public:
|
|||||||
FlushableTaskQueue* aAudioTaskQueue,
|
FlushableTaskQueue* aAudioTaskQueue,
|
||||||
MediaDataDecoderCallback* aCallback) override
|
MediaDataDecoderCallback* aCallback) override
|
||||||
{
|
{
|
||||||
|
#ifdef USING_MOZFFVPX
|
||||||
|
return nullptr;
|
||||||
|
#else
|
||||||
RefPtr<MediaDataDecoder> decoder =
|
RefPtr<MediaDataDecoder> decoder =
|
||||||
new FFmpegAudioDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
|
new FFmpegAudioDecoder<V>(aAudioTaskQueue, aCallback, aConfig);
|
||||||
return decoder.forget();
|
return decoder.forget();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SupportsMimeType(const nsACString& aMimeType) const override
|
bool SupportsMimeType(const nsACString& aMimeType) const override
|
||||||
{
|
{
|
||||||
|
#ifdef USING_MOZFFVPX
|
||||||
|
AVCodecID audioCodec = AV_CODEC_ID_NONE;
|
||||||
|
#else
|
||||||
AVCodecID audioCodec = FFmpegAudioDecoder<V>::GetCodecId(aMimeType);
|
AVCodecID audioCodec = FFmpegAudioDecoder<V>::GetCodecId(aMimeType);
|
||||||
AVCodecID videoCodec = FFmpegH264Decoder<V>::GetCodecId(aMimeType);
|
#endif
|
||||||
|
AVCodecID videoCodec = FFmpegVideoDecoder<V>::GetCodecId(aMimeType);
|
||||||
if (audioCodec == AV_CODEC_ID_NONE && videoCodec == AV_CODEC_ID_NONE) {
|
if (audioCodec == AV_CODEC_ID_NONE && videoCodec == AV_CODEC_ID_NONE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,29 @@ extern "C" {
|
|||||||
typedef CodecID AVCodecID;
|
typedef CodecID AVCodecID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef FFVPX_VERSION
|
||||||
|
enum { LIBAV_VER = FFVPX_VERSION };
|
||||||
|
#else
|
||||||
enum { LIBAV_VER = LIBAVCODEC_VERSION_MAJOR };
|
enum { LIBAV_VER = LIBAVCODEC_VERSION_MAJOR };
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
#ifdef USING_MOZFFVPX
|
||||||
|
namespace ffvpx {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define AV_FUNC(func, ver) extern decltype(func)* func;
|
#define AV_FUNC(func, ver) extern decltype(func)* func;
|
||||||
#include "FFmpegFunctionList.h"
|
#include "FFmpegFunctionList.h"
|
||||||
#undef AV_FUNC
|
#undef AV_FUNC
|
||||||
|
|
||||||
|
#ifdef USING_MOZFFVPX
|
||||||
|
} // namespace ffvpx
|
||||||
|
#define AV_CALL(func) mozilla::ffvpx::func
|
||||||
|
#else
|
||||||
|
#define AV_CALL(func) mozilla::func
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __FFmpegLibs_h__
|
#endif // __FFmpegLibs_h__
|
||||||
|
@ -7,18 +7,9 @@
|
|||||||
#include "FFmpegRuntimeLinker.h"
|
#include "FFmpegRuntimeLinker.h"
|
||||||
#include "mozilla/ArrayUtils.h"
|
#include "mozilla/ArrayUtils.h"
|
||||||
#include "FFmpegLog.h"
|
#include "FFmpegLog.h"
|
||||||
#include "mozilla/Preferences.h"
|
|
||||||
#include "mozilla/Types.h"
|
#include "mozilla/Types.h"
|
||||||
#include "nsIFile.h"
|
|
||||||
#include "nsXPCOMPrivate.h" // for XUL_DLL
|
|
||||||
#include "prmem.h"
|
|
||||||
#include "prlink.h"
|
#include "prlink.h"
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
|
||||||
#include "libavcodec/avcodec.h"
|
|
||||||
#include "libavutil/avutil.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace mozilla
|
namespace mozilla
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -77,7 +68,6 @@ FFmpegRuntimeLinker::Link()
|
|||||||
if (sLinkStatus) {
|
if (sLinkStatus) {
|
||||||
return sLinkStatus == LinkStatus_SUCCEEDED;
|
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
|
for (size_t i = 0; i < ArrayLength(sLibs); i++) {
|
||||||
@ -100,54 +90,6 @@ FFmpegRuntimeLinker::Link()
|
|||||||
}
|
}
|
||||||
FFMPEG_LOG(" ]\n");
|
FFMPEG_LOG(" ]\n");
|
||||||
|
|
||||||
#ifdef MOZ_FFVPX
|
|
||||||
// We retrieve the path of the XUL library as this is where mozavcodec and
|
|
||||||
// mozavutil libs are located.
|
|
||||||
char* path =
|
|
||||||
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFmpegRuntimeLinker::Link);
|
|
||||||
if (!path) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
nsCOMPtr<nsIFile> xulFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
|
||||||
if (!xulFile ||
|
|
||||||
NS_FAILED(xulFile->InitWithNativePath(nsDependentCString(path)))) {
|
|
||||||
PR_Free(path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
PR_Free(path);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> rootDir;
|
|
||||||
if (NS_FAILED(xulFile->GetParent(getter_AddRefs(rootDir))) || !rootDir) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
nsAutoCString rootPath;
|
|
||||||
if (NS_FAILED(rootDir->GetNativePath(rootPath))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* libname = NULL;
|
|
||||||
/* Get the platform-dependent library name of the module */
|
|
||||||
libname = PR_GetLibraryName(rootPath.get(), "mozavutil");
|
|
||||||
if (!libname) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sLinkedUtilLib = MozAVLink(libname);
|
|
||||||
PR_FreeLibraryName(libname);
|
|
||||||
libname = PR_GetLibraryName(rootPath.get(), "mozavcodec");
|
|
||||||
if (!libname) {
|
|
||||||
Unlink();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sLinkedLib = MozAVLink(libname);
|
|
||||||
PR_FreeLibraryName(libname);
|
|
||||||
if (sLinkedLib && sLinkedUtilLib) {
|
|
||||||
if (Bind("mozavcodec")) {
|
|
||||||
sLinkStatus = LinkStatus_SUCCEEDED;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Unlink();
|
Unlink();
|
||||||
|
|
||||||
sLinkStatus = LinkStatus_FAILED;
|
sLinkStatus = LinkStatus_FAILED;
|
||||||
@ -218,12 +160,10 @@ FFmpegRuntimeLinker::CreateDecoderModule()
|
|||||||
|
|
||||||
RefPtr<PlatformDecoderModule> module;
|
RefPtr<PlatformDecoderModule> module;
|
||||||
switch (major) {
|
switch (major) {
|
||||||
#ifndef XP_WIN
|
|
||||||
case 53: module = FFmpegDecoderModule<53>::Create(); break;
|
case 53: module = FFmpegDecoderModule<53>::Create(); break;
|
||||||
case 54: module = FFmpegDecoderModule<54>::Create(); break;
|
case 54: module = FFmpegDecoderModule<54>::Create(); break;
|
||||||
case 55:
|
case 55:
|
||||||
case 56: module = FFmpegDecoderModule<55>::Create(); break;
|
case 56: module = FFmpegDecoderModule<55>::Create(); break;
|
||||||
#endif
|
|
||||||
case 57: module = FFmpegDecoderModule<57>::Create(); break;
|
case 57: module = FFmpegDecoderModule<57>::Create(); break;
|
||||||
default: module = nullptr;
|
default: module = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
#include "MediaInfo.h"
|
#include "MediaInfo.h"
|
||||||
|
|
||||||
#include "FFmpegH264Decoder.h"
|
#include "FFmpegVideoDecoder.h"
|
||||||
#include "FFmpegLog.h"
|
#include "FFmpegLog.h"
|
||||||
#include "mozilla/PodOperations.h"
|
#include "mozilla/PodOperations.h"
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ ChoosePixelFormat(AVCodecContext* aCodecContext, const AVPixelFormat* aFormats)
|
|||||||
return AV_PIX_FMT_NONE;
|
return AV_PIX_FMT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext()
|
FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext()
|
||||||
: mNumFaultyPts(0)
|
: mNumFaultyPts(0)
|
||||||
, mNumFaultyDts(0)
|
, mNumFaultyDts(0)
|
||||||
, mLastPts(INT64_MIN)
|
, mLastPts(INT64_MIN)
|
||||||
@ -68,7 +68,7 @@ FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::PtsCorrectionContext()
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::GuessCorrectPts(int64_t aPts, int64_t aDts)
|
FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::GuessCorrectPts(int64_t aPts, int64_t aDts)
|
||||||
{
|
{
|
||||||
int64_t pts = AV_NOPTS_VALUE;
|
int64_t pts = AV_NOPTS_VALUE;
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::GuessCorrectPts(int64_t aPts
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::Reset()
|
FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::Reset()
|
||||||
{
|
{
|
||||||
mNumFaultyPts = 0;
|
mNumFaultyPts = 0;
|
||||||
mNumFaultyDts = 0;
|
mNumFaultyDts = 0;
|
||||||
@ -98,7 +98,7 @@ FFmpegH264Decoder<LIBAV_VER>::PtsCorrectionContext::Reset()
|
|||||||
mLastDts = INT64_MIN;
|
mLastDts = INT64_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
|
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(
|
||||||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||||
const VideoInfo& aConfig,
|
const VideoInfo& aConfig,
|
||||||
ImageContainer* aImageContainer)
|
ImageContainer* aImageContainer)
|
||||||
@ -108,14 +108,14 @@ FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
|
|||||||
, mImage(aConfig.mImage)
|
, mImage(aConfig.mImage)
|
||||||
, mCodecParser(nullptr)
|
, mCodecParser(nullptr)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(FFmpegH264Decoder);
|
MOZ_COUNT_CTOR(FFmpegVideoDecoder);
|
||||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||||
mExtraData = new MediaByteBuffer;
|
mExtraData = new MediaByteBuffer;
|
||||||
mExtraData->AppendElements(*aConfig.mExtraData);
|
mExtraData->AppendElements(*aConfig.mExtraData);
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<MediaDataDecoder::InitPromise>
|
RefPtr<MediaDataDecoder::InitPromise>
|
||||||
FFmpegH264Decoder<LIBAV_VER>::Init()
|
FFmpegVideoDecoder<LIBAV_VER>::Init()
|
||||||
{
|
{
|
||||||
if (NS_FAILED(InitDecoder())) {
|
if (NS_FAILED(InitDecoder())) {
|
||||||
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
|
||||||
@ -125,7 +125,7 @@ FFmpegH264Decoder<LIBAV_VER>::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFmpegH264Decoder<LIBAV_VER>::InitCodecContext()
|
FFmpegVideoDecoder<LIBAV_VER>::InitCodecContext()
|
||||||
{
|
{
|
||||||
mCodecContext->width = mImage.width;
|
mCodecContext->width = mImage.width;
|
||||||
mCodecContext->height = mImage.height;
|
mCodecContext->height = mImage.height;
|
||||||
@ -151,14 +151,14 @@ FFmpegH264Decoder<LIBAV_VER>::InitCodecContext()
|
|||||||
// FFmpeg will call back to this to negotiate a video pixel format.
|
// FFmpeg will call back to this to negotiate a video pixel format.
|
||||||
mCodecContext->get_format = ChoosePixelFormat;
|
mCodecContext->get_format = ChoosePixelFormat;
|
||||||
|
|
||||||
mCodecParser = av_parser_init(mCodecID);
|
mCodecParser = AV_CALL(av_parser_init(mCodecID));
|
||||||
if (mCodecParser) {
|
if (mCodecParser) {
|
||||||
mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
|
mCodecParser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
|
FFmpegVideoDecoder<LIBAV_VER>::DecodeResult
|
||||||
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
|
|
||||||
@ -175,10 +175,10 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
|||||||
while (inputSize) {
|
while (inputSize) {
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
int size;
|
int size;
|
||||||
int len = av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
int len = AV_CALL(av_parser_parse2(mCodecParser, mCodecContext, &data, &size,
|
||||||
inputData, inputSize,
|
inputData, inputSize,
|
||||||
aSample->mTime, aSample->mTimecode,
|
aSample->mTime, aSample->mTimecode,
|
||||||
aSample->mOffset);
|
aSample->mOffset));
|
||||||
if (size_t(len) > inputSize) {
|
if (size_t(len) > inputSize) {
|
||||||
mCallback->Error();
|
mCallback->Error();
|
||||||
return DecodeResult::DECODE_ERROR;
|
return DecodeResult::DECODE_ERROR;
|
||||||
@ -203,14 +203,14 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
|||||||
return DoDecodeFrame(aSample, inputData, inputSize);
|
return DoDecodeFrame(aSample, inputData, inputSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
|
FFmpegVideoDecoder<LIBAV_VER>::DecodeResult
|
||||||
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
FFmpegVideoDecoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||||
uint8_t* aData, int aSize)
|
uint8_t* aData, int aSize)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
|
|
||||||
AVPacket packet;
|
AVPacket packet;
|
||||||
av_init_packet(&packet);
|
AV_CALL(av_init_packet(&packet));
|
||||||
|
|
||||||
packet.data = aData;
|
packet.data = aData;
|
||||||
packet.size = aSize;
|
packet.size = aSize;
|
||||||
@ -237,7 +237,7 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
|||||||
|
|
||||||
int decoded;
|
int decoded;
|
||||||
int bytesConsumed =
|
int bytesConsumed =
|
||||||
avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet);
|
AV_CALL(avcodec_decode_video2(mCodecContext, mFrame, &decoded, &packet));
|
||||||
|
|
||||||
FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d "
|
FFMPEG_LOG("DoDecodeFrame:decode_video: rv=%d decoded=%d "
|
||||||
"(Input: pts(%lld) dts(%lld) Output: pts(%lld) "
|
"(Input: pts(%lld) dts(%lld) Output: pts(%lld) "
|
||||||
@ -317,7 +317,7 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(MediaRawData* aSample)
|
FFmpegVideoDecoder<LIBAV_VER>::DecodeFrame(MediaRawData* aSample)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
|
|
||||||
@ -328,11 +328,11 @@ FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(MediaRawData* aSample)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
FFmpegH264Decoder<LIBAV_VER>::Input(MediaRawData* aSample)
|
FFmpegVideoDecoder<LIBAV_VER>::Input(MediaRawData* aSample)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIRunnable> runnable(
|
nsCOMPtr<nsIRunnable> runnable(
|
||||||
NS_NewRunnableMethodWithArg<RefPtr<MediaRawData>>(
|
NS_NewRunnableMethodWithArg<RefPtr<MediaRawData>>(
|
||||||
this, &FFmpegH264Decoder<LIBAV_VER>::DecodeFrame,
|
this, &FFmpegVideoDecoder<LIBAV_VER>::DecodeFrame,
|
||||||
RefPtr<MediaRawData>(aSample)));
|
RefPtr<MediaRawData>(aSample)));
|
||||||
mTaskQueue->Dispatch(runnable.forget());
|
mTaskQueue->Dispatch(runnable.forget());
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ FFmpegH264Decoder<LIBAV_VER>::Input(MediaRawData* aSample)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFmpegH264Decoder<LIBAV_VER>::ProcessDrain()
|
FFmpegVideoDecoder<LIBAV_VER>::ProcessDrain()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||||
RefPtr<MediaRawData> empty(new MediaRawData());
|
RefPtr<MediaRawData> empty(new MediaRawData());
|
||||||
@ -350,24 +350,24 @@ FFmpegH264Decoder<LIBAV_VER>::ProcessDrain()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FFmpegH264Decoder<LIBAV_VER>::ProcessFlush()
|
FFmpegVideoDecoder<LIBAV_VER>::ProcessFlush()
|
||||||
{
|
{
|
||||||
mPtsContext.Reset();
|
mPtsContext.Reset();
|
||||||
mDurationMap.Clear();
|
mDurationMap.Clear();
|
||||||
FFmpegDataDecoder::ProcessFlush();
|
FFmpegDataDecoder::ProcessFlush();
|
||||||
}
|
}
|
||||||
|
|
||||||
FFmpegH264Decoder<LIBAV_VER>::~FFmpegH264Decoder()
|
FFmpegVideoDecoder<LIBAV_VER>::~FFmpegVideoDecoder()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(FFmpegH264Decoder);
|
MOZ_COUNT_DTOR(FFmpegVideoDecoder);
|
||||||
if (mCodecParser) {
|
if (mCodecParser) {
|
||||||
av_parser_close(mCodecParser);
|
AV_CALL(av_parser_close(mCodecParser));
|
||||||
mCodecParser = nullptr;
|
mCodecParser = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AVCodecID
|
AVCodecID
|
||||||
FFmpegH264Decoder<LIBAV_VER>::GetCodecId(const nsACString& aMimeType)
|
FFmpegVideoDecoder<LIBAV_VER>::GetCodecId(const nsACString& aMimeType)
|
||||||
{
|
{
|
||||||
if (aMimeType.EqualsLiteral("video/avc") || aMimeType.EqualsLiteral("video/mp4")) {
|
if (aMimeType.EqualsLiteral("video/avc") || aMimeType.EqualsLiteral("video/mp4")) {
|
||||||
return AV_CODEC_ID_H264;
|
return AV_CODEC_ID_H264;
|
@ -4,8 +4,8 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef __FFmpegH264Decoder_h__
|
#ifndef __FFmpegVideoDecoder_h__
|
||||||
#define __FFmpegH264Decoder_h__
|
#define __FFmpegVideoDecoder_h__
|
||||||
|
|
||||||
#include "FFmpegDataDecoder.h"
|
#include "FFmpegDataDecoder.h"
|
||||||
#include "mozilla/Pair.h"
|
#include "mozilla/Pair.h"
|
||||||
@ -15,12 +15,12 @@ namespace mozilla
|
|||||||
{
|
{
|
||||||
|
|
||||||
template <int V>
|
template <int V>
|
||||||
class FFmpegH264Decoder : public FFmpegDataDecoder<V>
|
class FFmpegVideoDecoder : public FFmpegDataDecoder<V>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
class FFmpegH264Decoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
||||||
{
|
{
|
||||||
typedef mozilla::layers::Image Image;
|
typedef mozilla::layers::Image Image;
|
||||||
typedef mozilla::layers::ImageContainer ImageContainer;
|
typedef mozilla::layers::ImageContainer ImageContainer;
|
||||||
@ -32,11 +32,11 @@ class FFmpegH264Decoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FFmpegH264Decoder(FlushableTaskQueue* aTaskQueue,
|
FFmpegVideoDecoder(FlushableTaskQueue* aTaskQueue,
|
||||||
MediaDataDecoderCallback* aCallback,
|
MediaDataDecoderCallback* aCallback,
|
||||||
const VideoInfo& aConfig,
|
const VideoInfo& aConfig,
|
||||||
ImageContainer* aImageContainer);
|
ImageContainer* aImageContainer);
|
||||||
virtual ~FFmpegH264Decoder();
|
virtual ~FFmpegVideoDecoder();
|
||||||
|
|
||||||
RefPtr<InitPromise> Init() override;
|
RefPtr<InitPromise> Init() override;
|
||||||
nsresult Input(MediaRawData* aSample) override;
|
nsresult Input(MediaRawData* aSample) override;
|
||||||
@ -122,4 +122,4 @@ private:
|
|||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // __FFmpegH264Decoder_h__
|
#endif // __FFmpegVideoDecoder_h__
|
@ -8,7 +8,7 @@ UNIFIED_SOURCES += [
|
|||||||
'../FFmpegAudioDecoder.cpp',
|
'../FFmpegAudioDecoder.cpp',
|
||||||
'../FFmpegDataDecoder.cpp',
|
'../FFmpegDataDecoder.cpp',
|
||||||
'../FFmpegDecoderModule.cpp',
|
'../FFmpegDecoderModule.cpp',
|
||||||
'../FFmpegH264Decoder.cpp',
|
'../FFmpegVideoDecoder.cpp',
|
||||||
]
|
]
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'..',
|
'..',
|
||||||
@ -21,9 +21,5 @@ if CONFIG['CLANG_CXX']:
|
|||||||
CXXFLAGS += [
|
CXXFLAGS += [
|
||||||
'-Wno-unknown-attributes',
|
'-Wno-unknown-attributes',
|
||||||
]
|
]
|
||||||
if CONFIG['_MSC_VER']:
|
|
||||||
CXXFLAGS += [
|
|
||||||
'-wd4996', # deprecated declaration
|
|
||||||
]
|
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
162
dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp
Normal file
162
dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* 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 "FFVPXRuntimeLinker.h"
|
||||||
|
#include "FFmpegRuntimeLinker.h"
|
||||||
|
#include "FFmpegLog.h"
|
||||||
|
#include "mozilla/Types.h"
|
||||||
|
#include "nsIFile.h"
|
||||||
|
#include "nsXPCOMPrivate.h" // for XUL_DLL
|
||||||
|
#include "prmem.h"
|
||||||
|
#include "prlink.h"
|
||||||
|
|
||||||
|
#if defined(XP_WIN)
|
||||||
|
#include "libavcodec/avcodec.h"
|
||||||
|
#include "libavutil/avutil.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace mozilla
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int V> class FFmpegDecoderModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static already_AddRefed<PlatformDecoderModule> Create();
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace ffvpx
|
||||||
|
{
|
||||||
|
|
||||||
|
FFVPXRuntimeLinker::LinkStatus FFVPXRuntimeLinker::sLinkStatus =
|
||||||
|
LinkStatus_INIT;
|
||||||
|
|
||||||
|
PRLibrary* FFVPXRuntimeLinker::sLinkedLib = nullptr;
|
||||||
|
PRLibrary* FFVPXRuntimeLinker::sLinkedUtilLib = nullptr;
|
||||||
|
static unsigned (*avcodec_version)() = nullptr;
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define AV_FUNC(func, ver) void (*func)();
|
||||||
|
#define LIBAVCODEC_ALLVERSION
|
||||||
|
#else
|
||||||
|
#define AV_FUNC(func, ver) decltype(func)* func;
|
||||||
|
#endif
|
||||||
|
#include "FFmpegFunctionList.h"
|
||||||
|
#undef AV_FUNC
|
||||||
|
|
||||||
|
static PRLibrary*
|
||||||
|
MozAVLink(const char* aName)
|
||||||
|
{
|
||||||
|
PRLibSpec lspec;
|
||||||
|
lspec.type = PR_LibSpec_Pathname;
|
||||||
|
lspec.value.pathname = aName;
|
||||||
|
return PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
FFVPXRuntimeLinker::Link()
|
||||||
|
{
|
||||||
|
if (sLinkStatus) {
|
||||||
|
return sLinkStatus == LinkStatus_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
// We retrieve the path of the XUL library as this is where mozavcodec and
|
||||||
|
// mozavutil libs are located.
|
||||||
|
char* path =
|
||||||
|
PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Link);
|
||||||
|
if (!path) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIFile> xulFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
|
||||||
|
if (!xulFile ||
|
||||||
|
NS_FAILED(xulFile->InitWithNativePath(nsDependentCString(path)))) {
|
||||||
|
PR_Free(path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PR_Free(path);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIFile> rootDir;
|
||||||
|
if (NS_FAILED(xulFile->GetParent(getter_AddRefs(rootDir))) || !rootDir) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsAutoCString rootPath;
|
||||||
|
if (NS_FAILED(rootDir->GetNativePath(rootPath))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* libname = NULL;
|
||||||
|
/* Get the platform-dependent library name of the module */
|
||||||
|
libname = PR_GetLibraryName(rootPath.get(), "mozavutil");
|
||||||
|
if (!libname) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sLinkedUtilLib = MozAVLink(libname);
|
||||||
|
PR_FreeLibraryName(libname);
|
||||||
|
libname = PR_GetLibraryName(rootPath.get(), "mozavcodec");
|
||||||
|
if (libname) {
|
||||||
|
sLinkedLib = MozAVLink(libname);
|
||||||
|
PR_FreeLibraryName(libname);
|
||||||
|
if (sLinkedLib && sLinkedUtilLib) {
|
||||||
|
if (Bind("mozavcodec")) {
|
||||||
|
sLinkStatus = LinkStatus_SUCCEEDED;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Unlink();
|
||||||
|
|
||||||
|
sLinkStatus = LinkStatus_FAILED;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
FFVPXRuntimeLinker::Bind(const char* aLibName)
|
||||||
|
{
|
||||||
|
int version = AV_FUNC_57;
|
||||||
|
|
||||||
|
#define AV_FUNC(func, ver) \
|
||||||
|
if ((ver) & version) { \
|
||||||
|
if (!(func = (decltype(func))PR_FindSymbol(((ver) & AV_FUNC_AVUTIL_MASK) ? sLinkedUtilLib : sLinkedLib, #func))) { \
|
||||||
|
FFMPEG_LOG("Couldn't load function " #func " from %s.", aLibName); \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
func = (decltype(func))nullptr; \
|
||||||
|
}
|
||||||
|
#include "FFmpegFunctionList.h"
|
||||||
|
#undef AV_FUNC
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ already_AddRefed<PlatformDecoderModule>
|
||||||
|
FFVPXRuntimeLinker::CreateDecoderModule()
|
||||||
|
{
|
||||||
|
if (!Link()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return FFmpegDecoderModule<FFVPX_VERSION>::Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
FFVPXRuntimeLinker::Unlink()
|
||||||
|
{
|
||||||
|
if (sLinkedUtilLib && sLinkedUtilLib != sLinkedLib) {
|
||||||
|
PR_UnloadLibrary(sLinkedUtilLib);
|
||||||
|
}
|
||||||
|
if (sLinkedLib) {
|
||||||
|
PR_UnloadLibrary(sLinkedLib);
|
||||||
|
sLinkedLib = nullptr;
|
||||||
|
sLinkStatus = LinkStatus_INIT;
|
||||||
|
avcodec_version = nullptr;
|
||||||
|
}
|
||||||
|
sLinkedUtilLib = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef LIBAVCODEC_ALLVERSION
|
||||||
|
} // namespace ffvpx
|
||||||
|
} // namespace mozilla
|
43
dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.h
Normal file
43
dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef __FFVPXRuntimeLinker_h__
|
||||||
|
#define __FFVPXRuntimeLinker_h__
|
||||||
|
|
||||||
|
#include "PlatformDecoderModule.h"
|
||||||
|
|
||||||
|
struct PRLibrary;
|
||||||
|
|
||||||
|
namespace mozilla
|
||||||
|
{
|
||||||
|
namespace ffvpx
|
||||||
|
{
|
||||||
|
|
||||||
|
class FFVPXRuntimeLinker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool Link();
|
||||||
|
static void Unlink();
|
||||||
|
static already_AddRefed<PlatformDecoderModule> CreateDecoderModule();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PRLibrary* sLinkedLib;
|
||||||
|
static PRLibrary* sLinkedUtilLib;
|
||||||
|
static enum LinkStatus {
|
||||||
|
LinkStatus_INIT = 0,
|
||||||
|
LinkStatus_FAILED,
|
||||||
|
LinkStatus_SUCCEEDED
|
||||||
|
} sLinkStatus;
|
||||||
|
|
||||||
|
static bool Bind(const char* aLibName);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __FFVPXRuntimeLinker_h__ */
|
44
dom/media/platforms/ffmpeg/ffvpx/moz.build
Normal file
44
dom/media/platforms/ffmpeg/ffvpx/moz.build
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||||
|
# vim: set filetype=python:
|
||||||
|
# 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/.
|
||||||
|
|
||||||
|
LOCAL_INCLUDES += ['/xpcom/build']
|
||||||
|
EXPORTS += [
|
||||||
|
'FFVPXRuntimeLinker.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
UNIFIED_SOURCES += [
|
||||||
|
'../FFmpegDataDecoder.cpp',
|
||||||
|
'../FFmpegDecoderModule.cpp',
|
||||||
|
'../FFmpegVideoDecoder.cpp',
|
||||||
|
]
|
||||||
|
SOURCES += [
|
||||||
|
'FFVPXRuntimeLinker.cpp',
|
||||||
|
]
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'..',
|
||||||
|
'../ffmpeg57/include',
|
||||||
|
]
|
||||||
|
|
||||||
|
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||||
|
LOCAL_INCLUDES += [
|
||||||
|
'../ffmpeg57/include',
|
||||||
|
]
|
||||||
|
|
||||||
|
if CONFIG['GNU_CXX']:
|
||||||
|
CXXFLAGS += [ '-Wno-deprecated-declarations' ]
|
||||||
|
if CONFIG['CLANG_CXX']:
|
||||||
|
CXXFLAGS += [
|
||||||
|
'-Wno-unknown-attributes',
|
||||||
|
]
|
||||||
|
if CONFIG['_MSC_VER']:
|
||||||
|
CXXFLAGS += [
|
||||||
|
'-wd4996', # deprecated declaration
|
||||||
|
]
|
||||||
|
|
||||||
|
DEFINES['FFVPX_VERSION'] = 46465650
|
||||||
|
DEFINES['USING_MOZFFVPX'] = True
|
||||||
|
|
||||||
|
FINAL_LIBRARY = 'xul'
|
@ -8,7 +8,7 @@ UNIFIED_SOURCES += [
|
|||||||
'../FFmpegAudioDecoder.cpp',
|
'../FFmpegAudioDecoder.cpp',
|
||||||
'../FFmpegDataDecoder.cpp',
|
'../FFmpegDataDecoder.cpp',
|
||||||
'../FFmpegDecoderModule.cpp',
|
'../FFmpegDecoderModule.cpp',
|
||||||
'../FFmpegH264Decoder.cpp',
|
'../FFmpegVideoDecoder.cpp',
|
||||||
]
|
]
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'..',
|
'..',
|
||||||
|
@ -8,7 +8,7 @@ UNIFIED_SOURCES += [
|
|||||||
'../FFmpegAudioDecoder.cpp',
|
'../FFmpegAudioDecoder.cpp',
|
||||||
'../FFmpegDataDecoder.cpp',
|
'../FFmpegDataDecoder.cpp',
|
||||||
'../FFmpegDecoderModule.cpp',
|
'../FFmpegDecoderModule.cpp',
|
||||||
'../FFmpegH264Decoder.cpp',
|
'../FFmpegVideoDecoder.cpp',
|
||||||
]
|
]
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'..',
|
'..',
|
||||||
|
@ -8,7 +8,7 @@ UNIFIED_SOURCES += [
|
|||||||
'../FFmpegAudioDecoder.cpp',
|
'../FFmpegAudioDecoder.cpp',
|
||||||
'../FFmpegDataDecoder.cpp',
|
'../FFmpegDataDecoder.cpp',
|
||||||
'../FFmpegDecoderModule.cpp',
|
'../FFmpegDecoderModule.cpp',
|
||||||
'../FFmpegH264Decoder.cpp',
|
'../FFmpegVideoDecoder.cpp',
|
||||||
]
|
]
|
||||||
LOCAL_INCLUDES += [
|
LOCAL_INCLUDES += [
|
||||||
'..',
|
'..',
|
||||||
@ -21,9 +21,5 @@ if CONFIG['CLANG_CXX']:
|
|||||||
CXXFLAGS += [
|
CXXFLAGS += [
|
||||||
'-Wno-unknown-attributes',
|
'-Wno-unknown-attributes',
|
||||||
]
|
]
|
||||||
if CONFIG['_MSC_VER']:
|
|
||||||
CXXFLAGS += [
|
|
||||||
'-wd4996', # deprecated declaration
|
|
||||||
]
|
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
@ -38,26 +38,22 @@ if CONFIG['MOZ_WMF']:
|
|||||||
if CONFIG['MOZ_EME']:
|
if CONFIG['MOZ_EME']:
|
||||||
DIRS += ['agnostic/eme']
|
DIRS += ['agnostic/eme']
|
||||||
|
|
||||||
|
if CONFIG['MOZ_FFVPX']:
|
||||||
|
DIRS += [
|
||||||
|
'ffmpeg/ffvpx',
|
||||||
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_FFMPEG']:
|
if CONFIG['MOZ_FFMPEG']:
|
||||||
LOCAL_INCLUDES += ['/xpcom/build']
|
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'ffmpeg/FFmpegRuntimeLinker.h',
|
'ffmpeg/FFmpegRuntimeLinker.h',
|
||||||
]
|
]
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
'ffmpeg/FFmpegRuntimeLinker.cpp',
|
'ffmpeg/FFmpegRuntimeLinker.cpp',
|
||||||
]
|
]
|
||||||
if CONFIG['OS_ARCH'] != 'WINNT':
|
|
||||||
DIRS += [
|
|
||||||
'ffmpeg/libav53',
|
|
||||||
'ffmpeg/libav54',
|
|
||||||
'ffmpeg/libav55',
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
LOCAL_INCLUDES += [
|
|
||||||
'ffmpeg/ffmpeg57/include',
|
|
||||||
]
|
|
||||||
|
|
||||||
DIRS += [
|
DIRS += [
|
||||||
|
'ffmpeg/libav53',
|
||||||
|
'ffmpeg/libav54',
|
||||||
|
'ffmpeg/libav55',
|
||||||
'ffmpeg/ffmpeg57',
|
'ffmpeg/ffmpeg57',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ const kSmsDeletedObserverTopic = "sms-deleted";
|
|||||||
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
||||||
const kNetworkConnStateChangedTopic = "network-connection-state-changed";
|
const kNetworkConnStateChangedTopic = "network-connection-state-changed";
|
||||||
|
|
||||||
const kPrefRilRadioDisabled = "ril.radio.disabled";
|
|
||||||
const kPrefMmsDebuggingEnabled = "mms.debugging.enabled";
|
const kPrefMmsDebuggingEnabled = "mms.debugging.enabled";
|
||||||
|
|
||||||
// HTTP status codes:
|
// HTTP status codes:
|
||||||
@ -194,18 +193,12 @@ function getDefaultServiceId() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return Radio disabled state.
|
* Return radio disabled state.
|
||||||
*/
|
*/
|
||||||
function getRadioDisabledState() {
|
function isRadioOff(aServiceId) {
|
||||||
let state;
|
let connection = gMobileConnectionService.getItemByServiceId(aServiceId);
|
||||||
try {
|
return connection.radioState
|
||||||
state = Services.prefs.getBoolPref(kPrefRilRadioDisabled);
|
!== Ci.nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED;
|
||||||
} catch (e) {
|
|
||||||
if (DEBUG) debug("Getting preference 'ril.radio.disabled' fails.");
|
|
||||||
state = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -422,7 +415,7 @@ MmsConnection.prototype = {
|
|||||||
this.pendingCallbacks.push(callback);
|
this.pendingCallbacks.push(callback);
|
||||||
|
|
||||||
let errorStatus;
|
let errorStatus;
|
||||||
if (getRadioDisabledState()) {
|
if (isRadioOff(this.serviceId)) {
|
||||||
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
||||||
errorStatus = _HTTP_STATUS_RADIO_DISABLED;
|
errorStatus = _HTTP_STATUS_RADIO_DISABLED;
|
||||||
} else if (this.getCardState() != Ci.nsIIcc.CARD_STATE_READY) {
|
} else if (this.getCardState() != Ci.nsIIcc.CARD_STATE_READY) {
|
||||||
@ -993,7 +986,8 @@ function CancellableTransaction(cancellableId, serviceId) {
|
|||||||
this.isCancelled = false;
|
this.isCancelled = false;
|
||||||
}
|
}
|
||||||
CancellableTransaction.prototype = {
|
CancellableTransaction.prototype = {
|
||||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
||||||
|
Ci.nsIMobileConnectionListener]),
|
||||||
|
|
||||||
// The timer for retrying sending or retrieving process.
|
// The timer for retrying sending or retrieving process.
|
||||||
timer: null,
|
timer: null,
|
||||||
@ -1010,8 +1004,9 @@ CancellableTransaction.prototype = {
|
|||||||
if (!this.isObserversAdded) {
|
if (!this.isObserversAdded) {
|
||||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||||
Services.obs.addObserver(this, kSmsDeletedObserverTopic, false);
|
Services.obs.addObserver(this, kSmsDeletedObserverTopic, false);
|
||||||
Services.prefs.addObserver(kPrefRilRadioDisabled, this, false);
|
|
||||||
Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
|
Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
|
||||||
|
gMobileConnectionService
|
||||||
|
.getItemByServiceId(this.serviceId).registerListener(this);
|
||||||
this.isObserversAdded = true;
|
this.isObserversAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,8 +1018,9 @@ CancellableTransaction.prototype = {
|
|||||||
if (this.isObserversAdded) {
|
if (this.isObserversAdded) {
|
||||||
Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||||
Services.obs.removeObserver(this, kSmsDeletedObserverTopic);
|
Services.obs.removeObserver(this, kSmsDeletedObserverTopic);
|
||||||
Services.prefs.removeObserver(kPrefRilRadioDisabled, this);
|
|
||||||
Services.prefs.removeObserver(kPrefDefaultServiceId, this);
|
Services.prefs.removeObserver(kPrefDefaultServiceId, this);
|
||||||
|
gMobileConnectionService
|
||||||
|
.getItemByServiceId(this.serviceId).unregisterListener(this);
|
||||||
this.isObserversAdded = false;
|
this.isObserversAdded = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1080,18 +1076,35 @@ CancellableTransaction.prototype = {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: {
|
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID: {
|
||||||
if (data == kPrefRilRadioDisabled) {
|
if (data === kPrefDefaultServiceId &&
|
||||||
if (getRadioDisabledState()) {
|
|
||||||
this.cancelRunning(_MMS_ERROR_RADIO_DISABLED);
|
|
||||||
}
|
|
||||||
} else if (data === kPrefDefaultServiceId &&
|
|
||||||
this.serviceId != getDefaultServiceId()) {
|
this.serviceId != getDefaultServiceId()) {
|
||||||
this.cancelRunning(_MMS_ERROR_SIM_CARD_CHANGED);
|
this.cancelRunning(_MMS_ERROR_SIM_CARD_CHANGED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
// nsIMobileConnectionListener
|
||||||
|
|
||||||
|
notifyVoiceChanged: function() {},
|
||||||
|
notifyDataChanged: function() {},
|
||||||
|
notifyDataError: function(message) {},
|
||||||
|
notifyCFStateChanged: function(action, reason, number, timeSeconds, serviceClass) {},
|
||||||
|
notifyEmergencyCbModeChanged: function(active, timeoutMs) {},
|
||||||
|
notifyOtaStatusChanged: function(status) {},
|
||||||
|
|
||||||
|
notifyRadioStateChanged: function() {
|
||||||
|
if (isRadioOff(this.serviceId)) {
|
||||||
|
this.cancelRunning(_MMS_ERROR_RADIO_DISABLED);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
notifyClirModeChanged: function(mode) {},
|
||||||
|
notifyLastKnownNetworkChanged: function() {},
|
||||||
|
notifyLastKnownHomeNetworkChanged: function() {},
|
||||||
|
notifyNetworkSelectionModeChanged: function() {},
|
||||||
|
notifyDeviceIdentitiesChanged: function() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2388,7 +2401,7 @@ MmsService.prototype = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check radio state in prior to default service Id.
|
// Check radio state in prior to default service Id.
|
||||||
if (getRadioDisabledState()) {
|
if (isRadioOff(aServiceId)) {
|
||||||
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
|
||||||
sendTransactionCb(mmsMessage,
|
sendTransactionCb(mmsMessage,
|
||||||
Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR,
|
Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR,
|
||||||
@ -2502,7 +2515,13 @@ MmsService.prototype = {
|
|||||||
// Hence, for manual retrieving, instead of checking radio state later
|
// Hence, for manual retrieving, instead of checking radio state later
|
||||||
// in MmsConnection.acquire(), We have to check radio state in prior to
|
// in MmsConnection.acquire(), We have to check radio state in prior to
|
||||||
// iccId to return the error correctly.
|
// iccId to return the error correctly.
|
||||||
if (getRadioDisabledState()) {
|
let numRadioInterfaces = gMobileConnectionService.numItems;
|
||||||
|
let isAllRadioOff = true;
|
||||||
|
for (let serviceId = 0; serviceId < numRadioInterfaces; serviceId++) {
|
||||||
|
isAllRadioOff &= isRadioOff(serviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAllRadioOff) {
|
||||||
if (DEBUG) debug("Error! Radio is disabled when retrieving MMS.");
|
if (DEBUG) debug("Error! Radio is disabled when retrieving MMS.");
|
||||||
aRequest.notifyGetMessageFailed(
|
aRequest.notifyGetMessageFailed(
|
||||||
Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR);
|
Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR);
|
||||||
|
@ -663,3 +663,60 @@ function runIfMultiSIM(aTest) {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to enable/disable connection radio state.
|
||||||
|
*
|
||||||
|
* @param aConnection
|
||||||
|
* connection to enable / disable
|
||||||
|
* @param aEnabled
|
||||||
|
* True to enable the radio.
|
||||||
|
* @return a Promise object.
|
||||||
|
*/
|
||||||
|
function setRadioEnabled(aConnection, aEnabled) {
|
||||||
|
log("setRadioEnabled to " + aEnabled);
|
||||||
|
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
let finalState = (aEnabled) ? "enabled" : "disabled";
|
||||||
|
if (aConnection.radioState == finalState) {
|
||||||
|
return deferred.resolve(aConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
aConnection.onradiostatechange = function() {
|
||||||
|
log("Received 'radiostatechange', radioState: " + aConnection.radioState);
|
||||||
|
|
||||||
|
if (aConnection.radioState == finalState) {
|
||||||
|
deferred.resolve(aConnection);
|
||||||
|
aConnection.onradiostatechange = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let req = aConnection.setRadioEnabled(aEnabled);
|
||||||
|
|
||||||
|
req.onsuccess = function() {
|
||||||
|
log("setRadioEnabled success");
|
||||||
|
};
|
||||||
|
|
||||||
|
req.onerror = function() {
|
||||||
|
ok(false, "setRadioEnabled should not fail");
|
||||||
|
deferred.reject();
|
||||||
|
};
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to enable/disable all connections radio state.
|
||||||
|
*
|
||||||
|
* @param aEnabled
|
||||||
|
* True to enable the radio.
|
||||||
|
* @return a Promise object.
|
||||||
|
*/
|
||||||
|
function setAllRadioEnabled(aEnabled) {
|
||||||
|
let promises = []
|
||||||
|
for (let i = 0; i < window.navigator.mozMobileConnections.length; ++i) {
|
||||||
|
promises.push(ensureMobileConnection(i)
|
||||||
|
.then((connection) => setRadioEnabled(connection, aEnabled)));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
MARIONETTE_TIMEOUT = 60000;
|
MARIONETTE_TIMEOUT = 60000;
|
||||||
|
|
||||||
// We apply "chrome" context to be more flexible to
|
// We apply "chrome" context to be more flexible to
|
||||||
// specify the content of M-Notification.ind such as iccId
|
// specify the content of M-Notification.ind such as iccId
|
||||||
// for different kinds of testing.
|
// for different kinds of testing.
|
||||||
@ -17,11 +18,17 @@ var gMobileMessageDatabaseService =
|
|||||||
.getService(Ci.nsIGonkMobileMessageDatabaseService);
|
.getService(Ci.nsIGonkMobileMessageDatabaseService);
|
||||||
|
|
||||||
var gUuidGenerator =
|
var gUuidGenerator =
|
||||||
Cc["@mozilla.org/uuid-generator;1"]
|
Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
|
||||||
.getService(Ci.nsIUUIDGenerator);
|
|
||||||
|
|
||||||
var gMmsService = Cc["@mozilla.org/mms/gonkmmsservice;1"]
|
var gMmsService =
|
||||||
.getService(Ci.nsIMmsService);
|
Cc["@mozilla.org/mms/gonkmmsservice;1"].getService(Ci.nsIMmsService);
|
||||||
|
|
||||||
|
var gMobileConnectionService =
|
||||||
|
Cc["@mozilla.org/mobileconnection/mobileconnectionservice;1"]
|
||||||
|
.getService(Ci.nsIMobileConnectionService);
|
||||||
|
|
||||||
|
var gIccService =
|
||||||
|
Cc["@mozilla.org/icc/gonkiccservice;1"].getService(Ci.nsIIccService);
|
||||||
|
|
||||||
function saveMmsNotification() {
|
function saveMmsNotification() {
|
||||||
log("saveMmsNotification()");
|
log("saveMmsNotification()");
|
||||||
@ -101,23 +108,111 @@ function retrieveMmsWithFailure(aId) {
|
|||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function testRetrieve(aCause, aInit, aCleanup) {
|
function testRetrieve(aCause) {
|
||||||
log("testRetrieve: aCause = " + aCause);
|
log("testRetrieve: aCause = " + aCause);
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => { if (aInit) aInit(); })
|
|
||||||
.then(saveMmsNotification)
|
.then(saveMmsNotification)
|
||||||
.then((message) => retrieveMmsWithFailure(message.id))
|
.then((message) => retrieveMmsWithFailure(message.id))
|
||||||
.then((response) => verifyErrorCause(response, aCause))
|
.then((response) => verifyErrorCause(response, aCause));
|
||||||
.then(() => { if (aCleanup) aCleanup(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var setRadioDisabled = function(aDisabled) {
|
function setRadioEnabled(aConnection, aEnabled) {
|
||||||
log("set ril.radio.disabled to " + aDisabled);
|
let deferred = Promise.defer();
|
||||||
Services.prefs.setBoolPref("ril.radio.disabled", aDisabled);
|
let finalState = (aEnabled) ?
|
||||||
};
|
Ci.nsIMobileConnection.MOBILE_RADIO_STATE_ENABLED :
|
||||||
|
Ci.nsIMobileConnection.MOBILE_RADIO_STATE_DISABLED;
|
||||||
|
|
||||||
testRetrieve(Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR,
|
if (aConnection.radioState == finalState) {
|
||||||
setRadioDisabled.bind(null, true),
|
return deferred.resolve(aConnection);
|
||||||
setRadioDisabled.bind(null, false))
|
}
|
||||||
|
let listener = {
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionListener]),
|
||||||
|
notifyVoiceChanged: function() {},
|
||||||
|
notifyDataChanged: function() {},
|
||||||
|
notifyDataError: function(message) {},
|
||||||
|
notifyCFStateChanged: function(action, reason, number, timeSeconds, serviceClass) {},
|
||||||
|
notifyEmergencyCbModeChanged: function(active, timeoutMs) {},
|
||||||
|
notifyOtaStatusChanged: function(status) {},
|
||||||
|
notifyRadioStateChanged: function() {
|
||||||
|
log("setRadioEnabled state changed to " + aConnection.radioState);
|
||||||
|
if (aConnection.radioState == finalState) {
|
||||||
|
aConnection.unregisterListener(listener);
|
||||||
|
deferred.resolve(aConnection);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notifyClirModeChanged: function(mode) {},
|
||||||
|
notifyLastKnownNetworkChanged: function() {},
|
||||||
|
notifyLastKnownHomeNetworkChanged: function() {},
|
||||||
|
notifyNetworkSelectionModeChanged: function() {},
|
||||||
|
notifyDeviceIdentitiesChanged: function() {}
|
||||||
|
};
|
||||||
|
let callback = {
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionCallback]),
|
||||||
|
notifySuccess() {},
|
||||||
|
notifySuccessWithBoolean(result) {},
|
||||||
|
notifyGetNetworksSuccess(count, networks) {},
|
||||||
|
notifyGetCallForwardingSuccess(count, results) {},
|
||||||
|
notifyGetCallBarringSuccess(program, enabled, serviceClass) {},
|
||||||
|
notifyGetCallWaitingSuccess(serviceClass) {},
|
||||||
|
notifyGetClirStatusSuccess(n, m) {},
|
||||||
|
notifyGetPreferredNetworkTypeSuccess(type) {},
|
||||||
|
notifyGetRoamingPreferenceSuccess(mode) {},
|
||||||
|
notifyError(name) {
|
||||||
|
log("setRadioEnabled reject");
|
||||||
|
aConnection.unregisterListener(listener);
|
||||||
|
deferred.reject();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
aConnection.registerListener(listener);
|
||||||
|
aConnection.setRadioEnabled(aEnabled, callback);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAllRadioEnabled(aEnabled) {
|
||||||
|
log("setAllRadioEnabled connection number = " +
|
||||||
|
gMobileConnectionService.numItems);
|
||||||
|
|
||||||
|
let promises = [];
|
||||||
|
for (let i = 0; i < gMobileConnectionService.numItems; ++i) {
|
||||||
|
promises.push(setRadioEnabled(
|
||||||
|
gMobileConnectionService.getItemByServiceId(i), aEnabled));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitIccReady(aIcc) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
if (aIcc.cardState == Ci.nsIIcc.CARD_STATE_READY) {
|
||||||
|
return deferred.resolve(aIcc);
|
||||||
|
}
|
||||||
|
let listener = {
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccListener]),
|
||||||
|
notifyStkCommand(aStkProactiveCmd) {},
|
||||||
|
notifyStkSessionEnd() {},
|
||||||
|
notifyCardStateChanged() {
|
||||||
|
if (aIcc.cardState == Ci.nsIIcc.CARD_STATE_READY) {
|
||||||
|
aIcc.unregisterListener(listener);
|
||||||
|
deferred.resolve(aIcc);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notifyIccInfoChanged() {}
|
||||||
|
};
|
||||||
|
aIcc.registerListener(listener);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitAllIccReady() {
|
||||||
|
let promises = [];
|
||||||
|
for (let i = 0; i < gMobileConnectionService.numItems; ++i) {
|
||||||
|
let icc = gIccService.getIccByServiceId(i);
|
||||||
|
promises.push(waitIccReady(icc));
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAllRadioEnabled(false)
|
||||||
|
.then(() => testRetrieve(Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR))
|
||||||
|
.then(() => setAllRadioEnabled(true))
|
||||||
|
.then(() => waitAllIccReady())
|
||||||
.then(() => testRetrieve(Ci.nsIMobileMessageCallback.SIM_NOT_MATCHED_ERROR))
|
.then(() => testRetrieve(Ci.nsIMobileMessageCallback.SIM_NOT_MATCHED_ERROR))
|
||||||
.then(finish);
|
.then(finish);
|
||||||
|
@ -4,8 +4,6 @@
|
|||||||
MARIONETTE_TIMEOUT = 60000;
|
MARIONETTE_TIMEOUT = 60000;
|
||||||
MARIONETTE_HEAD_JS = 'head.js';
|
MARIONETTE_HEAD_JS = 'head.js';
|
||||||
|
|
||||||
const kPrefRilRadioDisabled = "ril.radio.disabled";
|
|
||||||
|
|
||||||
function testSendFailed(aCause, aServiceId) {
|
function testSendFailed(aCause, aServiceId) {
|
||||||
log("testSendFailed, aCause: " + aCause + ", aServiceId: " + aServiceId);
|
log("testSendFailed, aCause: " + aCause + ", aServiceId: " + aServiceId);
|
||||||
let sendParameters;
|
let sendParameters;
|
||||||
@ -44,13 +42,9 @@ function testSendFailed(aCause, aServiceId) {
|
|||||||
|
|
||||||
startTestCommon(function testCaseMain() {
|
startTestCommon(function testCaseMain() {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
.then(() => {
|
.then(() => setAllRadioEnabled(false))
|
||||||
SpecialPowers.setBoolPref(kPrefRilRadioDisabled, true);
|
.then(() => testSendFailed("RadioDisabledError"), 0)
|
||||||
})
|
.then(() => setAllRadioEnabled(true))
|
||||||
.then(() => testSendFailed("RadioDisabledError"))
|
|
||||||
.then(() => {
|
|
||||||
SpecialPowers.setBoolPref(kPrefRilRadioDisabled, false);
|
|
||||||
})
|
|
||||||
.then(() => runIfMultiSIM(
|
.then(() => runIfMultiSIM(
|
||||||
() => testSendFailed("NonActiveSimCardError", 1)));
|
() => testSendFailed("NonActiveSimCardError", 1)));
|
||||||
});
|
});
|
||||||
|
@ -4,79 +4,6 @@
|
|||||||
MARIONETTE_TIMEOUT = 60000;
|
MARIONETTE_TIMEOUT = 60000;
|
||||||
MARIONETTE_HEAD_JS = 'head.js';
|
MARIONETTE_HEAD_JS = 'head.js';
|
||||||
|
|
||||||
const kPrefRilRadioDisabled = "ril.radio.disabled";
|
|
||||||
|
|
||||||
var connection;
|
|
||||||
function ensureMobileConnection() {
|
|
||||||
let deferred = Promise.defer();
|
|
||||||
|
|
||||||
let permissions = [{
|
|
||||||
"type": "mobileconnection",
|
|
||||||
"allow": true,
|
|
||||||
"context": document,
|
|
||||||
}];
|
|
||||||
SpecialPowers.pushPermissions(permissions, function() {
|
|
||||||
ok(true, "permissions pushed: " + JSON.stringify(permissions));
|
|
||||||
|
|
||||||
connection = window.navigator.mozMobileConnections[0];
|
|
||||||
if (connection) {
|
|
||||||
log("navigator.mozMobileConnections[0] is instance of " + connection.constructor);
|
|
||||||
} else {
|
|
||||||
log("navigator.mozMobileConnections[0] is undefined.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connection instanceof MozMobileConnection) {
|
|
||||||
deferred.resolve(connection);
|
|
||||||
} else {
|
|
||||||
deferred.reject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitRadioState(state) {
|
|
||||||
let deferred = Promise.defer();
|
|
||||||
|
|
||||||
waitFor(function() {
|
|
||||||
deferred.resolve();
|
|
||||||
}, function() {
|
|
||||||
return connection.radioState == state;
|
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setRadioEnabled(enabled) {
|
|
||||||
log("setRadioEnabled to " + enabled);
|
|
||||||
|
|
||||||
let deferred = Promise.defer();
|
|
||||||
|
|
||||||
let finalState = (enabled) ? "enabled" : "disabled";
|
|
||||||
connection.onradiostatechange = function() {
|
|
||||||
let state = connection.radioState;
|
|
||||||
log("Received 'radiostatechange' event, radioState: " + state);
|
|
||||||
|
|
||||||
if (state == finalState) {
|
|
||||||
deferred.resolve();
|
|
||||||
connection.onradiostatechange = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let req = connection.setRadioEnabled(enabled);
|
|
||||||
|
|
||||||
req.onsuccess = function() {
|
|
||||||
log("setRadioEnabled success");
|
|
||||||
};
|
|
||||||
|
|
||||||
req.onerror = function() {
|
|
||||||
ok(false, "setRadioEnabled should not fail");
|
|
||||||
deferred.reject();
|
|
||||||
};
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
}
|
|
||||||
|
|
||||||
function testSendFailed(aCause) {
|
function testSendFailed(aCause) {
|
||||||
log("testSendFailed, aCause: " + aCause);
|
log("testSendFailed, aCause: " + aCause);
|
||||||
|
|
||||||
@ -98,8 +25,7 @@ function testSendFailed(aCause) {
|
|||||||
|
|
||||||
startTestCommon(function testCaseMain() {
|
startTestCommon(function testCaseMain() {
|
||||||
return ensureMobileConnection()
|
return ensureMobileConnection()
|
||||||
.then(() => waitRadioState("enabled"))
|
.then(() => setRadioEnabled(mobileConnection, false))
|
||||||
.then(() => setRadioEnabled(false))
|
|
||||||
.then(() => testSendFailed("RadioDisabledError"))
|
.then(() => testSendFailed("RadioDisabledError"))
|
||||||
.then(() => setRadioEnabled(true));
|
.then(() => setRadioEnabled(mobileConnection, true));
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
en_US-mozilla Hunspell Dictionary
|
en_US-mozilla Hunspell Dictionary
|
||||||
Generated from SCOWL Version 2015.08.24
|
Generated from SCOWL Version 2016.01.19
|
||||||
Sun Jan 10 15:07:17 EST 2016
|
Thu Jan 21 14:36:28 EST 2016
|
||||||
|
|
||||||
http://wordlist.sourceforge.net
|
http://wordlist.sourceforge.net
|
||||||
|
|
||||||
@ -24,9 +24,12 @@ The normal (non-large) dictionaries correspond to SCOWL size 60 and,
|
|||||||
to encourage consistent spelling, generally only include one spelling
|
to encourage consistent spelling, generally only include one spelling
|
||||||
variant for a word. The large dictionaries correspond to SCOWL size
|
variant for a word. The large dictionaries correspond to SCOWL size
|
||||||
70 and may include multiple spelling for a word when both variants are
|
70 and may include multiple spelling for a word when both variants are
|
||||||
considered almost equal. Also, the general quality of the larger
|
considered almost equal. The larger dictionaries however (1) have not
|
||||||
dictionaries may also be less as they are not as carefully checked for
|
been as carefully checked for errors as the normal dictionaries and
|
||||||
errors as the normal dictionaries.
|
thus may contain misspelled or invalid words; and (2) contain
|
||||||
|
uncommon, yet valid, words that might cause problems as they are
|
||||||
|
likely to be misspellings of more common words (for example, "ort" and
|
||||||
|
"calender").
|
||||||
|
|
||||||
To get an idea of the difference in size, here are 25 random words
|
To get an idea of the difference in size, here are 25 random words
|
||||||
only found in the large dictionary for American English:
|
only found in the large dictionary for American English:
|
||||||
@ -42,7 +45,7 @@ basis. If you find them useful please send me a quick email at
|
|||||||
kevina@gnu.org.
|
kevina@gnu.org.
|
||||||
|
|
||||||
If none of these dictionaries suite you (for example, maybe you want
|
If none of these dictionaries suite you (for example, maybe you want
|
||||||
the larger dictionary but only use spelling of a word) additional
|
the normal dictionary that also includes common variants) additional
|
||||||
dictionaries can be generated at http://app.aspell.net/create or by
|
dictionaries can be generated at http://app.aspell.net/create or by
|
||||||
modifying speller/make-hunspell-dict in SCOWL. Please do let me know
|
modifying speller/make-hunspell-dict in SCOWL. Please do let me know
|
||||||
if you end up publishing a customized dictionary.
|
if you end up publishing a customized dictionary.
|
||||||
@ -57,11 +60,16 @@ kevina@gnu.org or to the wordlist-devel mailing lists
|
|||||||
have specific issues with any of these dictionaries please file a bug
|
have specific issues with any of these dictionaries please file a bug
|
||||||
report at https://github.com/kevina/wordlist/issues.
|
report at https://github.com/kevina/wordlist/issues.
|
||||||
|
|
||||||
IMPORTANT CHANGES FROM 2015.02.15:
|
IMPORTANT CHANGES INTRODUCED IN 2015.04.24:
|
||||||
|
|
||||||
The dictionaries are now in UTF-8 format instead of ISO-8859-1. This
|
The dictionaries are now in UTF-8 format instead of ISO-8859-1. This
|
||||||
was required to handle smart quotes correctly.
|
was required to handle smart quotes correctly.
|
||||||
|
|
||||||
|
IMPORTANT CHANGES INTRODUCED IN 2016.01.19:
|
||||||
|
|
||||||
|
"SET UTF8" was changes to "SET UTF-8" in the affix file as some
|
||||||
|
versions of Hunspell do not recognize "UTF8".
|
||||||
|
|
||||||
ADDITIONAL NOTES:
|
ADDITIONAL NOTES:
|
||||||
|
|
||||||
The NOSUGGEST flag was added to certain taboo words. While I made an
|
The NOSUGGEST flag was added to certain taboo words. While I made an
|
||||||
@ -311,4 +319,4 @@ from the Ispell distribution they are under the Ispell copyright:
|
|||||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
Build Date: Sun Jan 10 15:07:17 EST 2016
|
Build Date: Thu Jan 21 14:36:28 EST 2016
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user