import changes from `dev' branch of rmottola/Arctic-Fox:

- missing bit of 989499 and some other files (23b0597ba6)
- Bug 1233666 - Remove hacks for getting frame pointer for x86/x64 gcc. r=glandium (bfe8f59916)
- Bug 1176266: In TimeStamp_posix.cpp, check for XP_LINUX instead of LINUX, and add missing #include, to allow strrchr usage. r=BenWa (56c725cffa)
- Bug 1167230 - Don't pack ProfileEntry on ARM. r=shu (89f880e0cb)
- Bug 1209779 - Ensure that all null elements are written when streaming profiler JSON; r=shu (2bae5addc6)
- missing bit of Bug 1141712 - Make LUL (55f1276545)
- Bug 1061800 - Add breakpad ids to profiler in Linux. r=BenWa (994fd1a941)
- Bug 829621 - Compute the breakpad-id for OS X. r=BenWa. (e129580174)
- missing of  Bug 938157 - Lightweight CFI/EXIDX (b355dc3140)
- Bug 1193838 - Allow ProfileGatherer to gather profiles from exiting processes. r=BenWa (5ab1a6a3c9)
- align some missing stuff (5ebecd2364)
- align some missing stuff (b8ff7aa361)
- Bug 1164315 - Update key fingerprint for bitbucket.org; r=me (c1a3fbd930)
- Bug 1178955 - Refactor config path selection; r=smacleod (89552bb0ac)
- Bug 1195445 - Update host key fingerprint for bugzilla.mozilla.org (3783541088)
- Bug 1218903 - Update bmo fingerprint. r=fubar, a=Tomcat (5b836fc585)
- Bug 1178955 - Print config path on failure; r=smacleod (f5499f3771)
- Bug 1185113 - Support setting more secure file permissions; r=smacleod (7dbf6b22fd)
- Bug 1184229 - Detect multiple version-control-tools repos in Mercurial config; r=smacleod (16c24072a9)
- Bug 978514 - mach mercurial-setup: Use mqext from the version-control-tools repo (1fa5765e8a)
- Bug 1178955 - Don't pass config paths to updater; r=smacleod (80fcb05121)
- Bug 1197527 - Don't unnecessarily attempt to create extensions directory in MercurialUpdater; r=gps (9b049c3ff8)
- Bug 1164812 - mach mercurial-setup: Always mark the v-c-t repo as needing update (bd631208bd)
- Bug 1197527 - Always clone version-control-tools in MercurialSetupWizard; r=gps (6990e8f589)
- Bug 1197527 - Consolidate obtaining hg path into mozversioncontrol.get_hg_path; r=gps (e0b029a8e9)
- Bug 1200458 - Skip permission check for .hgrc on Windows in hgsetup wizard. r=gps DONTBUILD (cc5b0d6daf)
- Bug 1168466 - Bump minimum Mercurial version; r=smacleod (7fde47cfbe)
- Bug 1185113 - Clarify language around Bugzilla credentials; r=smacleod (9166fdfbf9)
- Bug 1185112 - Don't prompt for Bugzilla username/password if cookies defined; r=smacleod (cd87c96823)
- Bug 1188931 - Fix hgsetup wizard. r=gps (68a6b46be4)
- Bug 1200461 - Prompt for Bugzilla API Key instead of password; r=smacleod (780fb5d85d)
- Bug 1228580 - ./mach mercurial-setup should use ~ to set up extension paths, not my literal home directory. r=gps (7a0c839880)
- Bug 1231192 - Mark Mercurial 3.5.2 as oldest non-legacy version; r=smacleod (8f69483333)
- Bug 1231192 - Bump some minimum Mercurial version; r=smacleod (916c56a852)
- Bug 1162093 - Add "push-to-try" from version-control-tools to the mercurial setup wizard prompt.;r=gps (d29c7cf63a)
- Bug 1168466 - Prompt to install bundleclone extension; r=smacleod (780ce90a08)
- Bug 1185557 - Print relevant config options; r=smacleod (2f3f7e0161)
- Bug 1231192 - Support clonebundles feature; r=smacleod (dcba1ccd34)
- Bug 1231192 - Offer to install hg wip; r=smacleod (c42ebce5c8)
- Bug 1231192 - Only install host fingerprints if not running secure Python+hg; r=smacleod (3154a2497b)
- Bug 1178955 - Error when semicolon comments are seen; r=smacleod (e1f7081bb6)
- Bug 1231989 - Prompt to install hgwatchman extension; r=ahal (0eddf0c1c8)
- Bug 1178955 - Print line number for parse errors; r=smacleod (5369468cf1)
- Bug 1185557 - Only prompt to install progress on Mercurial <3.5; r=smacleod (401f362265)
- Bug 1232747 - Check for ssl.SSLContext existence; r=dminor (d505b07c5c)
- Bug 1144629 - UnicodeDecodeError in ./mach mercurial-setup. r=gps, r=glandium (611d3ec83e)
- Bug 1216970 - Make the copying more obvious in ProfilerImpl::GetStacktrace. r=froydnj (085625e113)
- Bug 1190466 - tools/rb/find-leakers.pl re-written in Python r=mccr8 (4bfdcad13e)
- Bug 1116478 - Open web content handlers in the proper tab in e10s. r=billm (ff8e11f45e)
- Bug 1213437 - Less data copying when handling structured clones in MessageManager, r=baku (c4e2a13253)
- const-var (69d17f312d)
- Bug 1203090 - Ensure we always use '/' as the starting path separator for the DOM path of the Directorys initially returned by HTMLInputElement.getFilesAndDirectories. r=baku (1325bbc40c)
- Bug 1209975 - Stop using dom::Promise::MaybeRejectBrokenly() in GetDirectoryListingTask. r=baku (2106790950)
- Bug 1209924 - Implement a general filtering mechanism for Directory::GetFilesAndDirectories, and add filtering of sensitive files/directories. r=baku (27b4a26262)
- Force a repaint after DXGI device resets. (bug 1188019, r=bas) (09c999e6e5)
- Bug 1163911 - Make responsive images block the document load event while the load task is queued. r=jst (0ee0e3db79)
- Bug 1166138 - Make img srcset react to resize/viewport changes, r=jdm (91674519e6)
- Bug 1194893 - Pref for default file upload directory. r=smaug (ec6d33d983)
- bug 1116409: switch update server to sha2 cert; update in-tree pinning. r=rstrong,snorp,mfinkle,dkeeler (7c8f631f27)
- bug 1116409: fix cert pinning on backup cert for aus5.mozilla.org. r=typofix (3c690cbc6d)
- Bug 1167048 - Change default font for Thai script from serif to sans-serif. r=smontagu (15dc86c389)
- Bug 1205570 - fix up font prefs for x-math lang group. r=heycam (03f1820752)
- Bug 1071769: Use DrawTargetTiled on B2G. r=Bas (b80ce768f1)
- fix misspatch of 1149343 (541dd7aac8)
- Bug 1199766 - Disable ICE TCP SO gathering via user pref. r=bwc (80cdc9c662)
- Bug 1187472 - only log UDP and TCP candidate gathering failures. r=bwc (bc3dcb02d0)
- Bug 1190615 - Skip non-UDP STUN servers for UDP sockets. r=bwc (a2d1d914b5)
- Bug 1187775 - skip host and reflexive ICE candidates if relay-only. r=bwc (7e2cba1685)
- Bug 1185198 - use port 9 for TCP active candidates. r=bwc (0a89cb199d)
- Bug 1177921 - Fix typo in STUN server name. r=drno (1ad43ced6b)
- Bug 1178349 - Enable ice_unittests on desktop linux on CI. r=bwc (ce5ece8264)
- Bug 1189041 - Add option to only gather addresses for default route. r=bwc (3651f2ff06)
- Bug 1189040: add a whitelist for network interfaces to use with ICE/webrtc r=ekr (6f693af72c)
- Bug 1189198 - don't start STUN transactions with a protocol mis-match. r=mtseng (a3b410e2a8)
- Bug 1208096 - Handle various failure cases for TURN gathering better. r=drno (1d8e173448)
- Bug 1211389 - Make absolutely sure the relay->srflx pointer doesn't dangle. r=drno (d59b0bf08d)
- Bug 1215616: use base address for server rflx ICE candidates r=bwc (89d07331ac)
- Bug 1207451 - removed framing from multi_tcp API. r=bwc (317f40f490)
- Bug 1186590 - Part 1 - Enable interface prioritizer on all platforms. r=drno (036a69fdb3)
- Bug 1194019 - New defaults for gather tests. r=bwc (8343ceab56)
- Bug 1144933: Only check that remote candidate is loopback in TestLoopbackOnlySortOf. r=drno (1f53d824e4)
- Bug 1186590 - Part 2 - Move hard-coded interface priority list into nrinterfaceprioritizer, and simplify some functions. r=drno (9f20fad21b)
- Bug 1152137 - Part 1: Test case. r=ekr (6b50f06d90)
- Bug 1152137 - Part 2: Remove attributes that could not be initted properly instead of just freeing them. r=ekr (ccdf81294a)
- Bug 1200763 - Remove hard-coded STUN IP address from ice_unittest, and do a DNS lookup instead. r=drno (ae54a83363)
- Bug 1208176 - Part 1: Add a couple of interface names. r=drno (b7ead0b476)
- Bug 1208176 - Part 2: Add a one-sided trickle test case to ice_unittest. r=drno (ad6afedb1c)
- Bug 1037618 - Relax candidate verification for TCP. r=bwc (0cad14c89e)
- Bug 1208176 - Part 3: Be forgiving when we see prflx instead of host candidates in ice_unittest. r=drno (50bdec2ba3)
- Bug 1035428: Re-register writeable callback after partially servicing the send queue. r=drno (2fdb7880fa)
- Bug 1135753 - Mark some overridden virtual functions in WebRTC as MOZ_OVERRIDE; r=mt (97f451c97d)
- Bug 950660: Part 4: Bridge TCPSocketChild to nr_socket r=bwc,jdm (654587b321)
- Bug 971357: Log STUN responses at INFO instead of DEBUG. r=ekr (81b500df17)
- Bug 1006809 - update triggered check behavior to RFC 5245. r+bwc r=mjf (31b718b5e5)
- Bug 1208278 - improved STUN request timeout handling. r=bwc (cf470fb12f)
- Bug 1142964 - Fix ICE tiebreaker on Windows. r=bwc (0d2fd78252)
- Bug 1219557 - don't pair candidates from different reserved networks. r=mt r=bwc (24d3e5106c)
- Bug 1220441 - Improve gather trickle ice unit tests. r=bwc r=mjf (96f76c6c8c)
- Bug 1205421 - fix DNS resolution of STUN server in ice_unittest. r=bwc (5d5b153358)
- Bug 1206465 - removed ice_ctx from TestStunTcpServer. r=bwc (9a0df03894)
- ug 1008792 - Check for valid pointer before using. r=bwc (7660fd0a71)
- Bug 1233101 - Use MOZ_LIKELY in js_new etc to help branch prediction; r=terrence (31fb244734)
- Bug 1225565 - Fix module import cycle detection r=shu (370dc26ee8)
- Bug 1225558 - Improve module error messages r=shu (83b6038bb3)
- Bug 1225561 - Don't allow a module to export non-existent local bindings r=shu (41f065891a)
- Bug 1233124 - Remove mis-named duplicate typedefs for rooted import and export entries r=terrence (17a60bdb39)
- Bug 1208464 - Implement proposed ES7 functions Object.values and Object.entries. r=evilpie (615193d0fb)
- Bug 1226549 - added assert check for matches pointer in for prevent null dereference. r=hv1989 (d321ad0385)
- Bug 1232113 - "Make the format specifiers in JS_snprintf() invocations more portable". r=jcoppeard (7c58b79a53)
- Bug 1232446 - Re-enable method calls in SelfHosted code using new anti-content checks. (r=till) (ba7dc22ff8)
- Bug 1232159 - Stop using pseudo-Uint32Array in SelfHosted code. (r=till) (c325f8ff58)
- Bug 1226235 - Print file and line info for failing assert in self-hosted code. r=efaust (4a8d54d38b)
- fix misspatch (fca2efc1f1)
- Bug 1186003 - Switch automated builds to Gtk+3. r=mshal (658ad843b7)
- Bug 1181342 - tooltool manifests and build-clang config for clang 3.6 r=rail (6264b4df68)
- Bug 1181342 - Follow up to use the unpack feature of tooltool instead of setup.sh r=glandium (96bb3b2062)
- Bug 1181255 - Mozconfigs for tsan builds. r=glandium (19250f4cc1)
- Bug 1181255 - Get tsan builds on gtk3. r=glandium (e5ffd1c02f)
- Bug 1187664 - Create a fontconfig cache so that Firefox doesn't have to do it itself when run on build automation. r=mshal (8ce567bd4c)
- Bug 1188780 - Include debug symbols in gtk3 tooltool package. r=mshal (a5b573aa58)
- Bug 1188780: remove setup.sh invocations, as they fail outside the mock environment; r=glandium a=RyanVM (058e306cac)
- Bug 1178513 - Fix non-unified bustage. r=wchen (543d1e5497)
- Bug 1162789 - Add a comment explaining why mForm is not set to null during unlink (eaa2a82048)
- Bug 1189655 - Define MOZ_HAVE_CXX11_CONSTEXPR on VS2015 or later. r=Waldo (2d134e3b41)
- Bug 1231758 - Fix bogus assertion in BCE for Annex B function assignment. (r=jorendorff) (701b2530b9)
- Bug 1233100 - Ensure that derived constructor bad return value errors are thrown before leaving the containing block. (r=shu) (52f5bcf0a5)
- Bug 1232022, 1232449 - Address forgotten review nits and fix bogus error message. (rs=Waldo) (dfd9d5e388)
- Bug 1233121 - Refactor ObjectBox tracing r=terrence (876a140535)
- Bug 1231647 - Check for duplicate exported let and const in modules r=shu (99f53ad443)
This commit is contained in:
2023-06-22 10:38:22 +08:00
parent 2121ac8f2e
commit 7adb8133f5
167 changed files with 5997 additions and 1465 deletions
+1 -1
View File
@@ -562,7 +562,7 @@ pref("app.update.incompatible.mode", 0);
pref("app.update.staging.enabled", true);
pref("app.update.service.enabled", true);
pref("app.update.url", "https://aus4.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%PRODUCT_DEVICE%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
pref("app.update.url", "https://aus5.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%PRODUCT_DEVICE%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
pref("app.update.channel", "@MOZ_UPDATE_CHANNEL@");
// Interval at which update manifest is fetched. In units of seconds.
@@ -0,0 +1,11 @@
ac_add_options --with-google-oauth-api-keyfile=/builds/google-oauth-api.key
. $topsrcdir/build/unix/mozconfig.tsan
export PKG_CONFIG_LIBDIR=/usr/lib64/pkgconfig:/usr/share/pkgconfig
. $topsrcdir/build/unix/mozconfig.gtk
# Need this to prevent name conflicts with the normal nightly build packages
export MOZ_PKG_SPECIAL=tsan
. "$topsrcdir/build/mozconfig.common.override"
@@ -7,6 +7,13 @@
"unpack": true
},
{
"size": 11179576,
"digest": "91567ce8e2bb8ab0ebc60c31e90731d88a1ea889fb71bcf55c735746a60fa7610b7e040ea3d8f727b6f692ae3ee703d6f3b30cdbd76fdf5617f77d9c38aa20ed",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
@@ -7,6 +7,13 @@
"unpack": true
},
{
"size": 12057960,
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"unpack": true
},
{
"size": 167175,
"digest": "0b71a936edf5bd70cf274aaa5d7abc8f77fe8e7b5593a208f805cc9436fac646b9c4f0b43c2b10de63ff3da671497d35536077ecbc72dba7f8159a38b580f831",
"algorithm": "sha512",
@@ -0,0 +1,19 @@
[
{
"clang_version": "r241773"
},
{
"size": 89690541,
"digest": "470d258d9785a120fcba65eee90daa632a42affa0f97f57d70fc8285bd76bcc27d4d0d70b6c37577ab271a04c843b6269425391a8d6df1967718dba26dd3a73d",
"algorithm": "sha512",
"filename": "clang.tar.bz2",
"unpack": true
},
{
"size": 12057960,
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"unpack": true
}
]
+8
View File
@@ -0,0 +1,8 @@
{
"llvm_revision": "241773",
"llvm_repo": "http://llvm.org/svn/llvm-project/llvm/branches/release_36",
"clang_repo": "http://llvm.org/svn/llvm-project/cfe/branches/release_36",
"compiler_repo": "http://llvm.org/svn/llvm-project/compiler-rt/branches/release_36",
"patches": {
}
}
+146
View File
@@ -0,0 +1,146 @@
#!/bin/bash
# Use "build-gtk.sh" or "build-gtk.sh 64" to build a 64-bits tarball for tooltool.
# Use "build-gtk.sh 32" to build a 32-bits tarball for tooltool.
# Mock environments used:
# - 64-bits:
# https://s3.amazonaws.com/mozilla-releng-mock-archive/67b65e51eb091fba7941a04d249343924a3ee653
# + libxml2-devel.x86_64 gettext.x86_64 libjpeg-devel.x86_64
# - 32-bits:
# https://s3.amazonaws.com/mozilla-releng-mock-archive/58d76c6acca148a1aedcbec7fc1b8212e12807b4
# + libxml2-devel.i686 gettext.i686 libjpeg-devel.i686
set -e
pkg_config_version=0.28
fontconfig_version=2.8.0
libffi_version=3.0.13
glib_version=2.34.3
gdk_pixbuf_version=2.26.5
pixman_version=0.20.2
cairo_version=1.10.2
pango_version=1.30.1
atk_version=2.2.0
gtk__version=3.4.4
pkg_config_url=http://pkgconfig.freedesktop.org/releases/pkg-config-${pkg_config_version}.tar.gz
fontconfig_url=http://www.freedesktop.org/software/fontconfig/release/fontconfig-${fontconfig_version}.tar.gz
libffi_url=ftp://sourceware.org/pub/libffi/libffi-${libffi_version}.tar.gz
glib_url=http://ftp.gnome.org/pub/gnome/sources/glib/${glib_version%.*}/glib-${glib_version}.tar.xz
gdk_pixbuf_url=http://ftp.gnome.org/pub/gnome/sources/gdk-pixbuf/${gdk_pixbuf_version%.*}/gdk-pixbuf-${gdk_pixbuf_version}.tar.xz
pixman_url=http://cairographics.org/releases/pixman-${pixman_version}.tar.gz
cairo_url=http://cairographics.org/releases/cairo-${cairo_version}.tar.gz
pango_url=http://ftp.gnome.org/pub/GNOME/sources/pango/${pango_version%.*}/pango-${pango_version}.tar.xz
atk_url=http://ftp.gnome.org/pub/GNOME/sources/atk/${atk_version%.*}/atk-${atk_version}.tar.xz
gtk__url=http://ftp.gnome.org/pub/gnome/sources/gtk+/${gtk__version%.*}/gtk+-${gtk__version}.tar.xz
cwd=$(pwd)
root_dir=$(mktemp -d)
cd $root_dir
if test -z $TMPDIR; then
TMPDIR=/tmp/
fi
make_flags=-j12
build() {
name=$1
shift
pkg=$(echo $name | tr '+-' '__')
version=$(eval echo \$${pkg}_version)
url=$(eval echo \$${pkg}_url)
wget -c -P $TMPDIR $url
tar -axf $TMPDIR/$name-$version.tar.*
mkdir -p build/$name
cd build/$name
eval ../../$name-$version/configure --disable-static $* $configure_args
make $make_flags
make install DESTDIR=$root_dir/gtk3
find $root_dir/gtk3 -name \*.la -delete
cd ../..
}
case "$1" in
32)
configure_args='--host=i686-pc-linux --build=i686-pc-linux CC="gcc -m32" CXX="g++ -m32"'
lib=lib
;;
*)
configure_args=
lib=lib64
;;
esac
export PKG_CONFIG_LIBDIR=/usr/$lib/pkgconfig:/usr/share/pkgconfig
# The pkg-config version in the mock images is buggy is how it handles
# PKG_CONFIG_SYSROOT_DIR. So we need our own.
build pkg-config
ln -sf /usr/include $root_dir/gtk3/usr/
ln -sf /usr/$lib $root_dir/gtk3/usr/
if [ "$lib" = lib64 ]; then
ln -s lib $root_dir/gtk3/usr/local/lib64
fi
export PKG_CONFIG_PATH=$root_dir/gtk3/usr/local/lib/pkgconfig
export PKG_CONFIG_SYSROOT_DIR=$root_dir/gtk3
export LD_LIBRARY_PATH=$root_dir/gtk3/usr/local/lib
export PATH=$root_dir/gtk3/usr/local/bin:${PATH}
build fontconfig
build libffi
build glib
build gdk-pixbuf --without-libtiff
build pixman --disable-gtk
build cairo --enable-tee
build pango
build atk
make_flags="$make_flags GLIB_COMPILE_SCHEMAS=glib-compile-schemas"
build gtk+
rm -rf $root_dir/gtk3/usr/local/share/gtk-doc
rm -rf $root_dir/gtk3/usr/local/share/locale
# mock build environment doesn't have fonts in /usr/share/fonts, but
# has some in /usr/share/X11/fonts. Add this directory to the
# fontconfig configuration without changing the gtk3 tooltool package.
cat << EOF > $root_dir/gtk3/usr/local/etc/fonts/local.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/usr/share/X11/fonts</dir>
</fontconfig>
EOF
cat <<EOF > $root_dir/gtk3/setup.sh
#!/bin/sh
cd \$(dirname \$0)
# pango expects absolute paths in pango.modules, and TOOLTOOL_DIR may vary...
LD_LIBRARY_PATH=./usr/local/lib \
PANGO_SYSCONFDIR=./usr/local/etc \
PANGO_LIBDIR=./usr/local/lib \
./usr/local/bin/pango-querymodules > ./usr/local/etc/pango/pango.modules
# same with gdb-pixbuf and loaders.cache
LD_LIBRARY_PATH=./usr/local/lib \
GDK_PIXBUF_MODULE_FILE=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache \
GDK_PIXBUF_MODULEDIR=./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders \
./usr/local/bin/gdk-pixbuf-query-loaders > ./usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache
# The fontconfig version in the tooltool package has known uses of
# uninitialized memory when creating its cache, and while most users
# will already have an existing cache, running Firefox on automation
# will create it. Combined with valgrind, this generates irrelevant
# errors.
# So create the fontconfig cache beforehand.
./usr/local/bin/fc-cache
EOF
chmod +x $root_dir/gtk3/setup.sh
cd $cwd
tar -C $root_dir -Jcf gtk3.tar.xz gtk3
+34
View File
@@ -0,0 +1,34 @@
MOZ_AUTOMATION_L10N_CHECK=0
. "$topsrcdir/build/mozconfig.common"
# Use Clang as specified in manifest
export CC="$topsrcdir/clang/bin/clang"
export CXX="$topsrcdir/clang/bin/clang++"
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
# Mandatory flag for TSan
export CFLAGS="-fsanitize=thread"
export CXXFLAGS="-fsanitize=thread"
export LDFLAGS="-fsanitize=thread"
# Enable TSan specific code and build workarounds
ac_add_options --enable-thread-sanitizer
# The ThreadSanitizer is not compatible with sanboxing
# (see bug 1182565)
ac_add_options --disable-sandbox
# These are required by TSan
ac_add_options --disable-jemalloc
ac_add_options --disable-crashreporter
ac_add_options --disable-elf-hack
ac_add_options --enable-pie
# Keep symbols to symbolize TSan traces
ac_add_options --disable-install-strip
# -gline-tables-only results in significantly smaller binaries.
ac_add_options --enable-debug-symbols="-gline-tables-only"
# Avoid dependency on libstdc++ 4.7
ac_add_options --enable-stdcxx-compat
+1
View File
@@ -25,6 +25,7 @@ XPIDL_SOURCES += [
'nsIImageLoadingContent.idl',
'nsIMessageManager.idl',
'nsIObjectLoadingContent.idl',
'nsIRemoteWindowContext.idl',
'nsIScriptChannel.idl',
'nsIScriptLoaderObserver.idl',
'nsISelection.idl',
+15
View File
@@ -0,0 +1,15 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIURI;
[scriptable, builtinclass, uuid(94f4a92b-752e-4fd9-8345-11b069ca19f3)]
interface nsIRemoteWindowContext : nsISupports
{
void openURI(in nsIURI aURI, in uint32_t aFlags);
};
+3 -1
View File
@@ -930,7 +930,9 @@ DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
fs = MakeOrReuseFileSystem(dirname, fs, window);
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
RefPtr<Directory> directory = new Directory(fs, basename);
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
filesAndDirsSeq[i].SetAsDirectory() = directory;
} else {
filesAndDirsSeq[i].SetAsFile() = mFiles->Item(i);
}
+7 -1
View File
@@ -242,7 +242,7 @@ Directory::GetFilesAndDirectories()
nsString realPath;
ErrorResult rv;
RefPtr<GetDirectoryListingTask> task =
new GetDirectoryListingTask(mFileSystem, mPath, rv);
new GetDirectoryListingTask(mFileSystem, mPath, mFilters, rv);
if (NS_WARN_IF(rv.Failed())) {
return nullptr;
}
@@ -251,6 +251,12 @@ Directory::GetFilesAndDirectories()
return task->GetPromise();
}
void
Directory::SetContentFilters(const nsAString& aFilters)
{
mFilters = aFilters;
}
FileSystemBase*
Directory::GetFileSystem() const
{
+26
View File
@@ -87,6 +87,31 @@ public:
// =========== End WebIDL bindings.============
/**
* Sets a semi-colon separated list of filters to filter-in or filter-out
* certain types of files when the contents of this directory are requested
* via a GetFilesAndDirectories() call.
*
* Currently supported keywords:
*
* * filter-out-sensitive
* This keyword filters out files or directories that we don't wish to
* make available to Web content because we are concerned that there is
* a risk that users may unwittingly give Web content access to them
* and suffer undesirable consequences. The details of what is
* filtered out can be found in GetDirectoryListingTask::Work.
*
* In future, we will likely support filtering based on filename extensions
* (for example, aFilters could be "*.jpg; *.jpeg; *.gif"), but that isn't
* supported yet. Once supported, files that don't match a specified
* extension (if any are specified) would be filtered out. This
* functionality would allow us to apply the 'accept' attribute from
* <input type=file directory accept="..."> to the results of a directory
* picker operation.
*/
void
SetContentFilters(const nsAString& aFilters);
FileSystemBase*
GetFileSystem() const;
private:
@@ -108,6 +133,7 @@ private:
RefPtr<FileSystemBase> mFileSystem;
nsString mPath;
nsString mFilters;
};
} // namespace dom
+41 -7
View File
@@ -6,9 +6,9 @@
#include "GetDirectoryListingTask.h"
#include "HTMLSplitOnSpacesTokenizer.h"
#include "js/Value.h"
#include "mozilla/dom/Directory.h"
#include "mozilla/dom/DOMError.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemUtils.h"
@@ -23,9 +23,11 @@ namespace dom {
GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
const nsAString& aTargetPath,
const nsAString& aFilters,
ErrorResult& aRv)
: FileSystemTaskBase(aFileSystem)
, mTargetRealPath(aTargetPath)
, mFilters(aFilters)
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
@@ -41,12 +43,13 @@ GetDirectoryListingTask::GetDirectoryListingTask(FileSystemBase* aFileSystem,
const FileSystemGetDirectoryListingParams& aParam,
FileSystemRequestParent* aParent)
: FileSystemTaskBase(aFileSystem, aParam, aParent)
, mTargetRealPath(aParam.realPath())
, mFilters(aParam.filters())
{
MOZ_ASSERT(XRE_IsParentProcess(),
"Only call from parent process!");
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
MOZ_ASSERT(aFileSystem);
mTargetRealPath = aParam.realPath();
}
GetDirectoryListingTask::~GetDirectoryListingTask()
@@ -66,7 +69,8 @@ FileSystemParams
GetDirectoryListingTask::GetRequestParams(const nsString& aFileSystem) const
{
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
return FileSystemGetDirectoryListingParams(aFileSystem, mTargetRealPath);
return FileSystemGetDirectoryListingParams(aFileSystem, mTargetRealPath,
mFilters);
}
FileSystemResponseValue
@@ -156,6 +160,20 @@ GetDirectoryListingTask::Work()
return rv;
}
bool filterOutSensitive = false;
{
HTMLSplitOnSpacesTokenizer tokenizer(mFilters, ';');
nsAutoString token;
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
if (token.EqualsLiteral("filter-out-sensitive")) {
filterOutSensitive = true;
} else {
MOZ_CRASH("Unrecognized filter");
}
}
}
for (;;) {
bool hasMore = false;
if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
@@ -180,6 +198,21 @@ GetDirectoryListingTask::Work()
!(isFile || isDir)) {
continue;
}
if (filterOutSensitive) {
bool isHidden;
if (NS_WARN_IF(NS_FAILED(currFile->IsHidden(&isHidden))) || isHidden) {
continue;
}
nsAutoString leafName;
if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) {
continue;
}
if (leafName[0] == char16_t('.')) {
continue;
}
}
BlobImplFile* impl = new BlobImplFile(currFile);
impl->LookupAndCacheIsDirectory();
mTargetBlobImpls.AppendElement(impl);
@@ -197,9 +230,7 @@ GetDirectoryListingTask::HandlerCallback()
}
if (HasError()) {
RefPtr<DOMError> domError = new DOMError(mFileSystem->GetWindow(),
mErrorValue);
mPromise->MaybeRejectBrokenly(domError);
mPromise->MaybeReject(mErrorValue);
mPromise = nullptr;
return;
}
@@ -229,7 +260,10 @@ GetDirectoryListingTask::HandlerCallback()
MOZ_ASSERT(exist);
}
#endif
listing[i].SetAsDirectory() = new Directory(mFileSystem, path);
RefPtr<Directory> directory = new Directory(mFileSystem, path);
// Propogate mFilter onto sub-Directory object:
directory->SetContentFilters(mFilters);
listing[i].SetAsDirectory() = directory;
} else {
listing[i].SetAsFile() = File::Create(mFileSystem->GetWindow(), mTargetBlobImpls[i]);
}
+2
View File
@@ -23,6 +23,7 @@ public:
// If aDirectoryOnly is set, we should ensure that the target is a directory.
GetDirectoryListingTask(FileSystemBase* aFileSystem,
const nsAString& aTargetPath,
const nsAString& aFilters,
ErrorResult& aRv);
GetDirectoryListingTask(FileSystemBase* aFileSystem,
const FileSystemGetDirectoryListingParams& aParam,
@@ -55,6 +56,7 @@ protected:
private:
RefPtr<Promise> mPromise;
nsString mTargetRealPath;
nsString mFilters;
// We cannot store File or Directory objects bacause this object is created
// on a different thread and File and Directory are not thread-safe.
+3 -3
View File
@@ -27,7 +27,7 @@ NS_NewHTMLExtAppElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
already_AddRefed<mozilla::dom::NodeInfo> aarni = ni.forget();
if (!permissionManager) {
return new HTMLUnknownElement(aarni);
return new mozilla::dom::HTMLUnknownElement(aarni);
}
uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
@@ -35,10 +35,10 @@ NS_NewHTMLExtAppElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
"external-app",
&perm);
if (perm != nsIPermissionManager::ALLOW_ACTION) {
return new HTMLUnknownElement(aarni);
return new mozilla::dom::HTMLUnknownElement(aarni);
}
return new HTMLExtAppElement(aarni);
return new mozilla::dom::HTMLExtAppElement(aarni);
}
namespace mozilla {
+3
View File
@@ -121,6 +121,9 @@ HTMLFormControlsCollection::FlushPendingNotifications()
NS_IMPL_CYCLE_COLLECTION_CLASS(HTMLFormControlsCollection)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(HTMLFormControlsCollection)
// Note: We intentionally don't set tmp->mForm to nullptr here, since doing
// so may result in crashes because of inconsistent null-checking after the
// object gets unlinked.
tmp->Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+61 -32
View File
@@ -80,27 +80,35 @@ namespace dom {
class ImageLoadTask : public nsRunnable
{
public:
explicit ImageLoadTask(HTMLImageElement *aElement) :
mElement(aElement)
{}
ImageLoadTask(HTMLImageElement *aElement, bool aAlwaysLoad)
: mElement(aElement)
, mAlwaysLoad(aAlwaysLoad)
{
mDocument = aElement->OwnerDoc();
mDocument->BlockOnload();
}
NS_IMETHOD Run()
{
if (mElement->mPendingImageLoadTask == this) {
mElement->mPendingImageLoadTask = nullptr;
mElement->LoadSelectedImage(true, true);
mElement->LoadSelectedImage(true, true, mAlwaysLoad);
}
mDocument->UnblockOnload(false);
return NS_OK;
}
private:
~ImageLoadTask() {}
RefPtr<HTMLImageElement> mElement;
nsCOMPtr<nsIDocument> mDocument;
bool mAlwaysLoad;
};
HTMLImageElement::HTMLImageElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsGenericHTMLElement(aNodeInfo)
, mForm(nullptr)
, mInDocResponsiveContent(false)
{
// We start out broken
AddStatesSilently(NS_EVENT_STATE_BROKEN);
@@ -422,7 +430,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
mResponsiveSelector->Content() == this) {
mResponsiveSelector->SetDefaultSource(NullString());
}
QueueImageLoadTask();
QueueImageLoadTask(true);
} else {
// Bug 1076583 - We still behave synchronously in the non-responsive case
CancelImageRequests(aNotify);
@@ -442,7 +450,7 @@ HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
if (InResponsiveMode()) {
// per spec, full selection runs when this changes, even though
// it doesn't directly affect the source selection
QueueImageLoadTask();
QueueImageLoadTask(true);
} else {
// Bug 1076583 - We still use the older synchronous algorithm in
// non-responsive mode. Force a new load of the image with the
@@ -542,7 +550,7 @@ HTMLImageElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
mResponsiveSelector->Content() == this) {
mResponsiveSelector->SetDefaultSource(aValue);
}
QueueImageLoadTask();
QueueImageLoadTask(true);
} else if (aNotify) {
// If aNotify is false, we are coming from the parser or some such place;
// we'll get bound after all the attributes have been set, so we'll do the
@@ -585,13 +593,15 @@ HTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
UpdateFormOwner();
}
bool addedToPicture = aParent && aParent->IsHTMLElement(nsGkAtoms::picture) &&
HTMLPictureElement::IsPictureEnabled();
if (addedToPicture) {
if (aDocument) {
if (HaveSrcsetOrInPicture()) {
if (aDocument && !mInDocResponsiveContent) {
aDocument->AddResponsiveContent(this);
mInDocResponsiveContent = true;
}
QueueImageLoadTask();
bool forceLoadEvent = HTMLPictureElement::IsPictureEnabled() &&
aParent && aParent->IsHTMLElement(nsGkAtoms::picture);
QueueImageLoadTask(forceLoadEvent);
} else if (!InResponsiveMode() &&
HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
// We skip loading when our attributes were set from parser land,
@@ -632,17 +642,22 @@ HTMLImageElement::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
if (mInDocResponsiveContent) {
nsIDocument* doc = GetOurOwnerDoc();
MOZ_ASSERT(doc);
if (doc) {
doc->RemoveResponsiveContent(this);
mInDocResponsiveContent = false;
}
}
if (GetParent() &&
GetParent()->IsHTMLElement(nsGkAtoms::picture) &&
HTMLPictureElement::IsPictureEnabled()) {
nsIDocument* doc = GetOurOwnerDoc();
if (doc) {
doc->RemoveResponsiveContent(this);
}
// Being removed from picture re-triggers selection, even if we
// weren't using a <source> peer
if (aNullParent) {
QueueImageLoadTask();
QueueImageLoadTask(true);
}
}
@@ -686,7 +701,7 @@ HTMLImageElement::MaybeLoadImage()
// Note, check LoadingEnabled() after LoadImage call.
LoadSelectedImage(false, true);
LoadSelectedImage(false, true, false);
if (!LoadingEnabled()) {
CancelImageRequests(true);
@@ -886,7 +901,7 @@ HTMLImageElement::ClearForm(bool aRemoveFromForm)
}
void
HTMLImageElement::QueueImageLoadTask()
HTMLImageElement::QueueImageLoadTask(bool aAlwaysLoad)
{
// If loading is temporarily disabled, we don't want to queue tasks
// that may then run when loading is re-enabled.
@@ -894,7 +909,7 @@ HTMLImageElement::QueueImageLoadTask()
return;
}
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this);
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this, aAlwaysLoad);
// The task checks this to determine if it was the last
// queued event, and so earlier tasks are implicitly canceled.
mPendingImageLoadTask = task;
@@ -928,7 +943,7 @@ HTMLImageElement::InResponsiveMode()
}
nsresult
HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad)
{
nsresult rv = NS_ERROR_FAILURE;
@@ -936,7 +951,9 @@ HTMLImageElement::LoadSelectedImage(bool aForce, bool aNotify)
// In responsive mode we generally want to re-run the full
// selection algorithm whenever starting a new load, per
// spec. This also causes us to re-resolve the URI as appropriate.
UpdateResponsiveSource();
if (!UpdateResponsiveSource() && !aAlwaysLoad) {
return NS_OK;
}
}
if (mResponsiveSelector) {
@@ -989,9 +1006,17 @@ HTMLImageElement::PictureSourceSrcsetChanged(nsIContent *aSourceNode,
mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue);
}
if (!mInDocResponsiveContent) {
nsIDocument* doc = GetOurOwnerDoc();
if (doc) {
doc->AddResponsiveContent(this);
mInDocResponsiveContent = true;
}
}
// This always triggers the image update steps per the spec, even if
// we are not using this source.
QueueImageLoadTask();
QueueImageLoadTask(true);
}
void
@@ -1018,7 +1043,7 @@ HTMLImageElement::PictureSourceSizesChanged(nsIContent *aSourceNode,
// This always triggers the image update steps per the spec, even if
// we are not using this source.
QueueImageLoadTask();
QueueImageLoadTask(true);
}
void
@@ -1034,7 +1059,7 @@ HTMLImageElement::PictureSourceMediaOrTypeChanged(nsIContent *aSourceNode,
// This always triggers the image update steps per the spec, even if
// we are not switching to/from this source
QueueImageLoadTask();
QueueImageLoadTask(true);
}
void
@@ -1044,7 +1069,7 @@ HTMLImageElement::PictureSourceAdded(nsIContent *aSourceNode)
return;
}
QueueImageLoadTask();
QueueImageLoadTask(true);
}
void
@@ -1054,15 +1079,17 @@ HTMLImageElement::PictureSourceRemoved(nsIContent *aSourceNode)
return;
}
QueueImageLoadTask();
QueueImageLoadTask(true);
}
void
bool
HTMLImageElement::UpdateResponsiveSource()
{
bool hadSelector = !!mResponsiveSelector;
if (!IsSrcsetEnabled()) {
mResponsiveSelector = nullptr;
return;
return hadSelector;
}
nsIContent *currentSource =
@@ -1082,7 +1109,7 @@ HTMLImageElement::UpdateResponsiveSource()
if (candidateSource == currentSource) {
// found no better source before current, re-run selection on
// that and keep it if it's still usable.
mResponsiveSelector->SelectImage(true);
bool changed = mResponsiveSelector->SelectImage(true);
if (mResponsiveSelector->NumCandidates()) {
bool isUsableCandidate = true;
@@ -1094,7 +1121,7 @@ HTMLImageElement::UpdateResponsiveSource()
}
if (isUsableCandidate) {
break;
return changed;
}
}
@@ -1123,6 +1150,8 @@ HTMLImageElement::UpdateResponsiveSource()
// Ran out of siblings without finding ourself, e.g. XBL magic.
mResponsiveSelector = nullptr;
}
return !hadSelector || mResponsiveSelector;
}
/*static */ bool
@@ -1295,7 +1324,7 @@ HTMLImageElement::DestroyContent()
void
HTMLImageElement::MediaFeatureValuesChanged()
{
QueueImageLoadTask();
QueueImageLoadTask(false);
}
void
+6 -3
View File
@@ -280,7 +280,7 @@ protected:
// algorithm (InResponsiveMode()) -- synchronous actions when just
// using img.src will bypass this, and update source and kick off
// image load synchronously.
void QueueImageLoadTask();
void QueueImageLoadTask(bool aAlwaysLoad);
// True if we have a srcset attribute or a <picture> parent, regardless of if
// any valid responsive sources were parsed from either.
@@ -292,7 +292,7 @@ protected:
// Resolve and load the current mResponsiveSelector (responsive mode) or src
// attr image.
nsresult LoadSelectedImage(bool aForce, bool aNotify);
nsresult LoadSelectedImage(bool aForce, bool aNotify, bool aAlwaysLoad);
// True if this string represents a type we would support on <source type>
static bool SupportedPictureSourceType(const nsAString& aType);
@@ -321,7 +321,9 @@ protected:
// the existing mResponsiveSelector, meaning you need to update its
// parameters as appropriate before calling (or null it out to force
// recreation)
void UpdateResponsiveSource();
//
// Returns true if the source has changed, and false otherwise.
bool UpdateResponsiveSource();
// Given a <source> node that is a previous sibling *or* ourselves, try to
// create a ResponsiveSelector.
@@ -362,6 +364,7 @@ private:
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
nsRuleData* aData);
bool mInDocResponsiveContent;
nsCOMPtr<nsIRunnable> mPendingImageLoadTask;
};
+27 -15
View File
@@ -295,20 +295,25 @@ NS_IMPL_ISUPPORTS(UploadLastDir::ContentPrefCallback, nsIContentPrefCallback2)
NS_IMETHODIMP
UploadLastDir::ContentPrefCallback::HandleCompletion(uint16_t aReason)
{
nsCOMPtr<nsIFile> localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
NS_ENSURE_STATE(localFile);
nsCOMPtr<nsIFile> localFile;
nsAutoString prefStr;
if (aReason == nsIContentPrefCallback2::COMPLETE_ERROR ||
!mResult) {
// Default to "desktop" directory for each platform
nsCOMPtr<nsIFile> homeDir;
NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(homeDir));
localFile = do_QueryInterface(homeDir);
} else {
nsAutoString prefStr;
nsCOMPtr<nsIVariant> pref;
mResult->GetValue(getter_AddRefs(pref));
pref->GetAsAString(prefStr);
if (aReason == nsIContentPrefCallback2::COMPLETE_ERROR || !mResult) {
prefStr = Preferences::GetString("dom.input.fallbackUploadDir");
if (prefStr.IsEmpty()) {
// If no custom directory was set through the pref, default to
// "desktop" directory for each platform.
NS_GetSpecialDirectory(NS_OS_DESKTOP_DIR, getter_AddRefs(localFile));
}
}
if (!localFile) {
if (prefStr.IsEmpty() && mResult) {
nsCOMPtr<nsIVariant> pref;
mResult->GetValue(getter_AddRefs(pref));
pref->GetAsAString(prefStr);
}
localFile = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
localFile->InitWithPath(prefStr);
}
@@ -4899,10 +4904,17 @@ HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
}
int32_t leafSeparatorIndex = path.RFind(FILE_PATH_SEPARATOR);
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
fs = MakeOrReuseFileSystem(dirname, fs, window);
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
nsAutoString dompath(NS_LITERAL_STRING(FILESYSTEM_DOM_PATH_SEPARATOR));
dompath.Append(Substring(path, leafSeparatorIndex + 1));
RefPtr<Directory> directory = new Directory(fs, dompath);
// In future we could refactor SetFilePickerFiltersFromAccept to return a
// semicolon separated list of file extensions and include that in the
// filter string passed here.
directory->SetContentFilters(NS_LITERAL_STRING("filter-out-sensitive"));
filesAndDirsSeq[i].SetAsDirectory() = directory;
} else {
// This file was directly selected by the user, so don't filter it.
filesAndDirsSeq[i].SetAsFile() = filesAndDirs[i];
}
}
+1 -1
View File
@@ -70,7 +70,7 @@ static MOZ_CONSTEXPR nsAttrValue::EnumTable kKindTable[] = {
};
// The default value for kKindTable is "subtitles"
static MOZ_CONSTEXPR const char* kKindTableDefaultString = kKindTable->tag;
static MOZ_CONSTEXPR const char* kKindTableDefaultString = kKindTable[0].tag;
/** HTMLTrackElement */
HTMLTrackElement::HTMLTrackElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
Binary file not shown.

After

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

+24 -26
View File
@@ -197,6 +197,9 @@ support-files =
file_ignoreuserfocus.html
simpleFileOpener.js
file_mozaudiochannel.html
file_bug1166138_1x.png
file_bug1166138_2x.png
file_bug1166138_def.png
[test_a_text.html]
[test_anchor_href_cache_invalidation.html]
@@ -289,7 +292,7 @@ skip-if = toolkit == 'android'
[test_bug518122.html]
[test_bug519987.html]
[test_bug523771.html]
skip-if = buildapp == 'b2g' || e10s # b2g(onload of iframe not firing, because submit not working?) b2g-debug(onload of iframe not firing, because submit not working?) b2g-desktop(onload of iframe not firing, because submit not working?)
skip-if = buildapp == 'b2g' # b2g(onload of iframe not firing, because submit not working?) b2g-debug(onload of iframe not firing, because submit not working?) b2g-desktop(onload of iframe not firing, because submit not working?)
[test_bug529819.html]
[test_bug529859.html]
[test_bug535043.html]
@@ -313,7 +316,7 @@ skip-if = toolkit == 'android' #TIMED_OUT
[test_bug560112.html]
[test_bug561634.html]
[test_bug561636.html]
skip-if = buildapp == 'b2g' || e10s # b2g(observerservice not working) b2g-debug(observerservice not working) b2g-desktop(observerservice not working)
skip-if = buildapp == 'b2g' # b2g(observerservice not working) b2g-debug(observerservice not working) b2g-desktop(observerservice not working)
[test_bug561640.html]
[test_bug564001.html]
[test_bug566046.html]
@@ -338,10 +341,9 @@ skip-if = buildapp == 'b2g' || e10s # b2g(observerservice not working) b2g-debug
[test_bug592802.html]
[test_bug593689.html]
[test_bug595429.html]
skip-if = e10s
[test_bug595447.html]
[test_bug595449.html]
skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
[test_bug596350.html]
[test_bug596511.html]
[test_bug598643.html]
@@ -362,7 +364,7 @@ skip-if = buildapp == 'mulet' # TC: Bug 1144079 - Re-enable Mulet mochitests and
[test_bug612730.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-debug(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-desktop(form control not selected/checked with synthesizeMouse, also fails on Android)
[test_bug613113.html]
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
[test_bug613722.html]
[test_bug613979.html]
[test_bug615595.html]
@@ -370,29 +372,22 @@ skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-debug(form control not selected/checked with synthesizeMouse, also fails on Android) b2g-desktop(form control not selected/checked with synthesizeMouse, also fails on Android)
[test_bug617528.html]
[test_bug618948.html]
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
[test_bug619278.html]
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
[test_bug622558.html]
skip-if = e10s
[test_bug622597.html]
skip-if = buildapp == 'b2g' || e10s # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
skip-if = buildapp == 'b2g' # b2g(bug 587671, need an invalidformsubmit observer) b2g-debug(bug 587671, need an invalidformsubmit observer) b2g-desktop(bug 587671, need an invalidformsubmit observer)
[test_bug623291.html]
skip-if = e10s
[test_bug6296.html]
skip-if = e10s
[test_bug629801.html]
skip-if = e10s
[test_bug633058.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug636336.html]
skip-if = e10s
[test_bug641219.html]
skip-if = e10s
[test_bug643051.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug646157.html]
skip-if = e10s
[test_bug649134.html]
# This extra subdirectory is needed due to the nature of this test.
# With the bug, the test loads the base URL of the bug649134/file_*.sjs
@@ -444,7 +439,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
[test_bug839913.html]
[test_bug840877.html]
[test_bug841466.html]
skip-if = (toolkit == 'gonk' && debug) || e10s #debug-only failure
skip-if = (toolkit == 'gonk' && debug) #debug-only failure
[test_bug845057.html]
[test_bug869040.html]
[test_bug870787.html]
@@ -486,11 +481,11 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #time out on b2g desktop spec
[test_iframe_sandbox_navigation2.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #time out on b2g desktop specific
[test_iframe_sandbox_plugins.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
[test_iframe_sandbox_popups.html]
skip-if = buildapp == 'b2g' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_iframe_sandbox_popups_inheritance.html]
skip-if = buildapp == 'b2g' || e10s # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
skip-if = buildapp == 'b2g' || e10s || toolkit == 'android' # b2g(multiple concurrent window.open()s fail on B2G) b2g-debug(multiple concurrent window.open()s fail on B2G) b2g-desktop(Bug 931116, b2g desktop specific, initial triage) android(bug 939642)
[test_iframe_sandbox_redirect.html]
[test_iframe_sandbox_refresh.html]
[test_iframe_sandbox_same_origin.html]
@@ -511,12 +506,12 @@ skip-if = toolkit == 'gonk' # nested imports fail on b2g emulator
[test_meta_attributes_reflection.html]
[test_mod_attributes_reflection.html]
[test_mozaudiochannel.html]
skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Perma-orange on debug emulator) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(Perma-orange on debug emulator) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
[test_named_options.html]
[test_nested_invalid_fieldsets.html]
[test_object_attributes_reflection.html]
[test_object_plugin_nav.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #TIMED_OUT # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' # b2g(plugins not supported) b2g-debug(plugins not supported) b2g-desktop(plugins not supported)
[test_ol_attributes_reflection.html]
[test_option_defaultSelected.html]
[test_option_selected_state.html]
@@ -541,9 +536,9 @@ skip-if = (toolkit == 'gonk' && debug)
[test_bug1823.html]
[test_bug57600.html]
[test_bug196523.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
[test_bug199692.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' || e10s #bug 811644 #Bug 931116, b2g desktop specific, initial triage
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit == 'android' #bug 811644 #Bug 931116, b2g desktop specific, initial triage
[test_bug172261.html]
[test_bug255820.html]
[test_bug259332.html]
@@ -592,7 +587,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
skip-if = buildapp == 'b2g' || e10s
[test_bug765780.html]
[test_bug871161.html]
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
support-files = file_bug871161-1.html file_bug871161-2.html
[test_bug1013316.html]
[test_hash_encoded.html]
@@ -600,7 +595,10 @@ support-files = file_bug871161-1.html file_bug871161-2.html
[test_window_open_close.html]
skip-if = buildapp == 'b2g' # bug 1129014
[test_img_complete.html]
[test_extapp.html]
[test_viewport_resize.html]
[test_extapp.html]
[test_image_clone_load.html]
[test_bug1203668.html]
[test_bug1166138.html]
[test_filepicker_default_directory.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android'
+130
View File
@@ -0,0 +1,130 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1166138
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1166138</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1166138">Mozilla Bug 1166138</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<img srcset="file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x"
src="file_bug1166138_def.png"
onload="onLoad()">
<script type="application/javascript">
var img1x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_1x.png";
var img2x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_2x.png";
var imgdef = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_def.png";
var onLoadCallback = null;
var done = false;
var startPromise = new Promise((a) => {
onLoadCallback = () => {
var image = document.querySelector('img');
// If we aren't starting at 2x scale, resize to 2x scale, and wait for a load
if (image.currentSrc != img2x) {
onLoadCallback = a;
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
} else {
a();
}
};
});
// if aLoad is true, waits for a load event. Otherwise, spins the event loop twice to
// ensure that no events were queued to be fired.
function spin(aLoad) {
if (aLoad) {
return new Promise((a) => {
ok(!onLoadCallback, "Shouldn't be an existing callback");
onLoadCallback = a;
});
} else {
return new Promise((a) => SimpleTest.executeSoon(() => SimpleTest.executeSoon(a)));
}
}
function onLoad() {
if (done) return;
ok(onLoadCallback, "Expected a load event");
if (onLoadCallback) {
var cb = onLoadCallback;
onLoadCallback = null;
cb();
}
}
add_task(function* () {
yield startPromise;
var image = document.querySelector('img');
is(image.currentSrc, img2x, "initial scale must be 2x");
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
yield spin(true);
is(image.currentSrc, img1x, "pre-existing img tag to 1x");
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
yield spin(true);
is(image.currentSrc, img2x, "pre-existing img tag to 2x");
// Try removing & re-adding the image
document.body.removeChild(image);
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
yield spin(false); // No load should occur because the element is unbound
document.body.appendChild(image);
yield spin(true);
is(image.currentSrc, img1x, "remove and re-add tag after changing to 1x");
document.body.removeChild(image);
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
yield spin(false); // No load should occur because the element is unbound
document.body.appendChild(image);
yield spin(true);
is(image.currentSrc, img2x, "remove and re-add tag after changing to 2x");
// get rid of the srcset attribute! It should become the default
image.removeAttribute('srcset');
yield spin(true);
is(image.currentSrc, imgdef, "remove srcset attribute");
// Setting srcset again should return it to the correct value
image.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x");
yield spin(true);
is(image.currentSrc, img2x, "restore srcset attribute");
// Create a new image
var newImage = document.createElement('img');
// Switch load listening over to newImage
newImage.addEventListener('load', onLoad);
image.removeEventListener('load', onLoad);
document.body.appendChild(newImage);
yield spin(false); // no load event should fire - as the image has no attributes
is(newImage.currentSrc, "", "New element with no attributes");
newImage.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x");
yield spin(true);
is(newImage.currentSrc, img2x, "Adding srcset attribute");
SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
yield spin(true);
is(newImage.currentSrc, img1x, "new image after switching to 1x");
is(image.currentSrc, img1x, "old image after switching to 1x");
// Clear the listener
done = true;
});
</script>
</body>
</html>
@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1194893
-->
<head>
<title>Test for filepicker default directory</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1194893">Mozilla Bug 1194893</a>
<div id="content">
<input type="file" id="f">
</div>
<pre id="text">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
const { Cc: Cc, Ci: Ci } = SpecialPowers;
// Platform-independent directory names are #define'd in xpcom/io/nsDirectoryServiceDefs.h
var defaultUploadDirectory = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("Desk", Ci.nsIFile);
// When we want to test an upload directory other than the default, we need to
// get a valid directory in a platform-independent way. Since NS_OS_DESKTOP_DIR
// may fallback to NS_OS_HOME_DIR, let's use NS_OS_TMP_DIR.
var customUploadDirectory = Cc["@mozilla.org/file/directory_service;1"]
.getService(Ci.nsIDirectoryService)
.QueryInterface(Ci.nsIProperties)
.get("TmpD", Ci.nsIFile);
// Useful for debugging
//info("defaultUploadDirectory" + defaultUploadDirectory.path);
//info("customUploadDirectory" + customUploadDirectory.path);
var MockFilePicker = SpecialPowers.MockFilePicker;
MockFilePicker.init(window);
// need to show the MockFilePicker so .displayDirectory gets set
var f = document.getElementById("f");
f.focus();
var testIndex = 0;
var tests = [
["", defaultUploadDirectory.path],
[customUploadDirectory.path, customUploadDirectory.path]
]
MockFilePicker.showCallback = function(filepicker) {
info(SpecialPowers.wrap(MockFilePicker).displayDirectory.path);
is(SpecialPowers.wrap(MockFilePicker).displayDirectory.path,
tests[testIndex][1]);
if (++testIndex == tests.length) {
MockFilePicker.cleanup();
SimpleTest.finish();
} else {
launchNextTest();
}
}
function launchNextTest() {
SpecialPowers.pushPrefEnv(
{ 'set': [
['dom.input.fallbackUploadDir', tests[testIndex][0]],
]},
function () {
f.click();
});
}
launchNextTest();
</script>
</pre>
</body>
</html>
+9
View File
@@ -2963,6 +2963,15 @@ ContentChild::RecvShutdown()
GetIPCChannel()->SetAbortOnError(false);
#ifdef MOZ_ENABLE_PROFILER_SPS
if (profiler_is_active()) {
// We're shutting down while we were profiling. Send the
// profile up to the parent so that we don't lose this
// information.
Unused << RecvGatherProfile();
}
#endif
// Ignore errors here. If this fails, the parent will kill us after a
// timeout.
Unused << SendFinishShutdown();
+54 -2
View File
@@ -134,6 +134,7 @@
#include "nsIMutable.h"
#include "nsIObserverService.h"
#include "nsIPresShell.h"
#include "nsIRemoteWindowContext.h"
#include "nsIScriptError.h"
#include "nsIScriptSecurityManager.h"
#include "nsISiteSecurityService.h"
@@ -1686,6 +1687,47 @@ StaticAutoPtr<LinkedList<SystemMessageHandledListener> >
NS_IMPL_ISUPPORTS(SystemMessageHandledListener,
nsITimerCallback)
class RemoteWindowContext final : public nsIRemoteWindowContext
, public nsIInterfaceRequestor
{
public:
explicit RemoteWindowContext(TabParent* aTabParent)
: mTabParent(aTabParent)
{
}
NS_DECL_ISUPPORTS
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIREMOTEWINDOWCONTEXT
private:
~RemoteWindowContext();
RefPtr<TabParent> mTabParent;
};
NS_IMPL_ISUPPORTS(RemoteWindowContext, nsIRemoteWindowContext, nsIInterfaceRequestor)
RemoteWindowContext::~RemoteWindowContext()
{
}
NS_IMETHODIMP
RemoteWindowContext::GetInterface(const nsIID& aIID, void** aSink)
{
return QueryInterface(aIID, aSink);
}
NS_IMETHODIMP
RemoteWindowContext::OpenURI(nsIURI* aURI, uint32_t aFlags)
{
URIParams uri;
SerializeURI(aURI, uri);
Unused << mTabParent->SendOpenURI(uri, aFlags);
return NS_OK;
}
} // namespace
void
@@ -2089,6 +2131,12 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
mConsoleService = nullptr;
#ifdef MOZ_ENABLE_PROFILER_SPS
if (mGatherer && !mProfile.IsEmpty()) {
mGatherer->OOPExitProfile(mProfile);
}
#endif
if (obs) {
RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
@@ -4314,7 +4362,8 @@ ContentParent::RecvAccumulateMixedContentHSTS(const URIParams& aURI, const bool&
}
bool
ContentParent::RecvLoadURIExternal(const URIParams& uri)
ContentParent::RecvLoadURIExternal(const URIParams& uri,
PBrowserParent* windowContext)
{
nsCOMPtr<nsIExternalProtocolService> extProtService(do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID));
if (!extProtService) {
@@ -4324,7 +4373,10 @@ ContentParent::RecvLoadURIExternal(const URIParams& uri)
if (!ourURI) {
return false;
}
extProtService->LoadURI(ourURI, nullptr);
RefPtr<RemoteWindowContext> context =
new RemoteWindowContext(static_cast<TabParent*>(windowContext));
extProtService->LoadURI(ourURI, context);
return true;
}
+2 -1
View File
@@ -795,7 +795,8 @@ private:
virtual bool RecvOpenNotificationSettings(const IPC::Principal& aPrincipal) override;
virtual bool RecvLoadURIExternal(const URIParams& uri) override;
virtual bool RecvLoadURIExternal(const URIParams& uri,
PBrowserParent* windowContext) override;
virtual bool RecvSyncMessage(const nsString& aMsg,
const ClonedMessageData& aData,
+2
View File
@@ -554,6 +554,8 @@ child:
LoadURL(nsCString uri, BrowserConfiguration config, ShowInfo info);
OpenURI(URIParams uri, uint32_t flags);
CacheFileDescriptor(nsString path, FileDescriptor fd);
UpdateDimensions(CSSRect rect, CSSSize size, nsSizeMode sizeMode,
+11 -1
View File
@@ -278,6 +278,16 @@ struct FileSystemGetDirectoryListingParams
{
nsString filesystem;
nsString realPath;
// 'filters' could be an array rather than a semicolon separated string
// (we'd then use InfallibleTArray<nsString> internally), but that is
// wasteful. E10s requires us to pass the filters over as a string anyway,
// so avoiding using an array avoids serialization on the side passing the
// filters. Since an nsString can share its buffer when copied,
// using that instead of InfallibleTArray<nsString> makes copying the filters
// around in any given process a bit more efficient too, since copying a
// single nsString is cheaper than copying InfallibleTArray member data and
// each nsString that it contains.
nsString filters;
};
struct FileSystemGetFileOrDirectoryParams
@@ -836,7 +846,7 @@ parent:
async VisitURI(URIParams uri, OptionalURIParams referrer, uint32_t flags);
async SetURITitle(URIParams uri, nsString title);
async LoadURIExternal(URIParams uri);
async LoadURIExternal(URIParams uri, PBrowser windowContext);
// PrefService message
sync ReadPrefsArray() returns (PrefSetting[] prefs);
+32 -41
View File
@@ -28,21 +28,19 @@ namespace ipc {
bool
StructuredCloneData::Copy(const StructuredCloneData& aData)
{
if (!aData.mData) {
if (!aData.Data()) {
return true;
}
uint64_t* data = static_cast<uint64_t*>(js_malloc(aData.mDataLength));
if (!data) {
return false;
if (aData.SharedData()) {
mSharedData = aData.SharedData();
} else {
mSharedData =
SharedJSAllocatedData::CreateFromExternalData(aData.Data(),
aData.DataLength());
NS_ENSURE_TRUE(mSharedData, false);
}
memcpy(data, aData.mData, aData.mDataLength);
mData = data;
mDataLength = aData.mDataLength;
mDataOwned = eJSAllocated;
MOZ_ASSERT(BlobImpls().IsEmpty());
BlobImpls().AppendElements(aData.BlobImpls());
@@ -56,12 +54,12 @@ StructuredCloneData::Read(JSContext* aCx,
JS::MutableHandle<JS::Value> aValue,
ErrorResult &aRv)
{
MOZ_ASSERT(mData);
MOZ_ASSERT(Data());
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
MOZ_ASSERT(global);
ReadFromBuffer(global, aCx, mData, mDataLength, aValue, aRv);
ReadFromBuffer(global, aCx, Data(), DataLength(), aValue, aRv);
}
void
@@ -69,26 +67,28 @@ StructuredCloneData::Write(JSContext* aCx,
JS::Handle<JS::Value> aValue,
ErrorResult &aRv)
{
MOZ_ASSERT(!mData);
MOZ_ASSERT(!Data());
StructuredCloneHolder::Write(aCx, aValue, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
mBuffer->steal(&mData, &mDataLength);
uint64_t* data = nullptr;
size_t dataLength = 0;
mBuffer->steal(&data, &dataLength);
mBuffer = nullptr;
mDataOwned = eJSAllocated;
mSharedData = new SharedJSAllocatedData(data, dataLength);
}
void
StructuredCloneData::WriteIPCParams(IPC::Message* aMsg) const
{
WriteParam(aMsg, mDataLength);
WriteParam(aMsg, DataLength());
if (mDataLength) {
if (DataLength()) {
// Structured clone data must be 64-bit aligned.
aMsg->WriteBytes(mData, mDataLength, sizeof(uint64_t));
aMsg->WriteBytes(Data(), DataLength(), sizeof(uint64_t));
}
}
@@ -96,31 +96,29 @@ bool
StructuredCloneData::ReadIPCParams(const IPC::Message* aMsg,
void** aIter)
{
MOZ_ASSERT(!mData);
MOZ_ASSERT(!Data());
if (!ReadParam(aMsg, aIter, &mDataLength)) {
size_t dataLength = 0;
if (!ReadParam(aMsg, aIter, &dataLength)) {
return false;
}
if (!mDataLength) {
if (!dataLength) {
return true;
}
uint64_t* dataBuffer = nullptr;
const char** buffer =
const_cast<const char**>(reinterpret_cast<char**>(&mData));
const_cast<const char**>(reinterpret_cast<char**>(&dataBuffer));
// Structured clone data must be 64-bit aligned.
if (!aMsg->ReadBytes(aIter, buffer, mDataLength, sizeof(uint64_t))) {
if (!aMsg->ReadBytes(aIter, buffer, dataLength, sizeof(uint64_t))) {
return false;
}
uint64_t* data = static_cast<uint64_t*>(js_malloc(mDataLength));
if (!data) {
return false;
}
mSharedData = SharedJSAllocatedData::CreateFromExternalData(dataBuffer,
dataLength);
NS_ENSURE_TRUE(mSharedData, false);
memcpy(data, mData, mDataLength);
mData = data;
mDataOwned = eJSAllocated;
return true;
}
@@ -128,17 +126,10 @@ bool
StructuredCloneData::CopyExternalData(const void* aData,
size_t aDataLength)
{
MOZ_ASSERT(!mData);
uint64_t* data = static_cast<uint64_t*>(js_malloc(aDataLength));
if (!data) {
return false;
}
memcpy(data, aData, aDataLength);
mData = data;
mDataLength = aDataLength;
mDataOwned = eJSAllocated;
MOZ_ASSERT(!Data());
mSharedData = SharedJSAllocatedData::CreateFromExternalData(aData,
aDataLength);
NS_ENSURE_TRUE(mSharedData, false);
return true;
}
+65 -18
View File
@@ -7,7 +7,10 @@
#ifndef mozilla_dom_ipc_StructuredCloneData_h
#define mozilla_dom_ipc_StructuredCloneData_h
#include <algorithm>
#include "mozilla/RefPtr.h"
#include "mozilla/dom/StructuredCloneHolder.h"
#include "nsISupportsImpl.h"
namespace IPC {
class Message;
@@ -17,6 +20,51 @@ namespace mozilla {
namespace dom {
namespace ipc {
class SharedJSAllocatedData final
{
public:
SharedJSAllocatedData(uint64_t* aData, size_t aDataLength)
: mData(aData), mDataLength(aDataLength)
{
MOZ_ASSERT(mData);
}
static already_AddRefed<SharedJSAllocatedData>
CreateFromExternalData(const void* aData, size_t aDataLength)
{
uint64_t* data = Allocate64bitSafely(aDataLength);
if (!data) {
return nullptr;
}
memcpy(data, aData, aDataLength);
RefPtr<SharedJSAllocatedData> sharedData =
new SharedJSAllocatedData(data, aDataLength);
return sharedData.forget();
}
NS_INLINE_DECL_REFCOUNTING(SharedJSAllocatedData)
uint64_t* Data() const { return mData; }
size_t DataLength() const { return mDataLength; }
private:
~SharedJSAllocatedData()
{
js_free(mData);
}
static uint64_t*
Allocate64bitSafely(size_t aSize)
{
// Structured cloning requires 64-bit aligment.
return static_cast<uint64_t*>(js_malloc(std::max(sizeof(uint64_t), aSize)));
}
uint64_t* mData;
size_t mDataLength;
};
class StructuredCloneData : public StructuredCloneHolder
{
public:
@@ -24,18 +72,15 @@ public:
: StructuredCloneHolder(StructuredCloneHolder::CloningSupported,
StructuredCloneHolder::TransferringNotSupported,
StructuredCloneHolder::DifferentProcess)
, mData(nullptr)
, mDataLength(0)
, mDataOwned(eNone)
, mExternalData(nullptr)
, mExternalDataLength(0)
{}
StructuredCloneData(const StructuredCloneData&) = delete;
~StructuredCloneData()
{
if (mDataOwned == eJSAllocated) {
js_free(mData);
}
MOZ_ASSERT(!(mExternalData && mSharedData));
}
StructuredCloneData&
@@ -63,22 +108,26 @@ public:
void UseExternalData(uint64_t* aData, size_t aDataLength)
{
MOZ_ASSERT(!mData);
mData = aData;
mDataLength = aDataLength;
MOZ_ASSERT(mDataOwned == eNone);
MOZ_ASSERT(!Data());
mExternalData = aData;
mExternalDataLength = aDataLength;
}
bool CopyExternalData(const void* aData, size_t aDataLength);
uint64_t* Data() const
{
return mData;
return mSharedData ? mSharedData->Data() : mExternalData;
}
size_t DataLength() const
{
return mDataLength;
return mSharedData ? mSharedData->DataLength() : mExternalDataLength;
}
SharedJSAllocatedData* SharedData() const
{
return mSharedData;
}
// For IPC serialization
@@ -86,12 +135,10 @@ public:
bool ReadIPCParams(const IPC::Message* aMessage, void** aIter);
private:
uint64_t* mData;
size_t mDataLength;
enum {
eNone,
eJSAllocated,
} mDataOwned;
uint64_t* MOZ_NON_OWNING_REF mExternalData;
size_t mExternalDataLength;
RefPtr<SharedJSAllocatedData> mSharedData;
};
} // namespace ipc
+27
View File
@@ -23,6 +23,7 @@
#include "mozilla/plugins/PluginWidgetChild.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/ipc/DocumentRendererChild.h"
#include "mozilla/ipc/URIUtils.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
@@ -101,6 +102,7 @@
#include "nsIAppsService.h"
#include "nsNetUtil.h"
#include "nsIPermissionManager.h"
#include "nsIURILoader.h"
#include "nsIScriptError.h"
#include "mozilla/EventForwards.h"
#include "nsDeviceContext.h"
@@ -1262,6 +1264,31 @@ TabChild::RecvLoadURL(const nsCString& aURI,
return true;
}
bool
TabChild::RecvOpenURI(const URIParams& aURI, const uint32_t& aFlags)
{
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
nsCOMPtr<nsIChannel> channel;
nsresult rv =
NS_NewChannel(getter_AddRefs(channel),
uri,
nsContentUtils::GetSystemPrincipal(),
nsILoadInfo::SEC_NORMAL,
nsIContentPolicy::TYPE_DOCUMENT);
if (NS_WARN_IF(NS_FAILED(rv))) {
return true;
}
nsCOMPtr<nsIURILoader> loader = do_GetService("@mozilla.org/uriloader;1");
if (NS_WARN_IF(!loader)) {
return true;
}
nsCOMPtr<nsIInterfaceRequestor> context(do_QueryInterface(WebNavigation()));
loader->OpenURI(channel, aFlags, context);
return true;
}
bool
TabChild::RecvCacheFileDescriptor(const nsString& aPath,
const FileDescriptor& aFileDescriptor)
+2
View File
@@ -300,6 +300,8 @@ public:
virtual bool RecvLoadURL(const nsCString& aURI,
const BrowserConfiguration& aConfiguration,
const ShowInfo& aInfo) override;
virtual bool RecvOpenURI(const URIParams& aURI,
const uint32_t& aFlags) override;
virtual bool RecvCacheFileDescriptor(const nsString& aPath,
const FileDescriptor& aFileDescriptor)
override;
+2 -2
View File
@@ -7,9 +7,9 @@
// This script is run when the preallocated process starts. It is injected as
// a frame script.
const BrowserElementIsPreloaded = true;
var BrowserElementIsPreloaded = true;
const DoPreloadPostfork = function(aCallback) {
var DoPreloadPostfork = function(aCallback) {
Services.obs.addObserver({
_callback: aCallback,
+2
View File
@@ -118,6 +118,8 @@ skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video suppo
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_promiseSendOnly.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_relayOnly.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_callbacks.html]
skip-if = toolkit == 'gonk' || buildapp == 'mulet' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
[test_peerConnection_replaceTrack.html]
+8 -11
View File
@@ -1266,18 +1266,15 @@ PeerConnectionWrapper.prototype = {
* resolves when connected, rejects on failure
*/
waitForIceConnected : function() {
return new Promise((resolve, reject) => {
var iceConnectedChanged = () => {
if (this.isIceConnected()) {
delete this.ice_connection_callbacks.waitForIceConnected;
resolve();
} else if (! this.isIceConnectionPending()) {
delete this.ice_connection_callbacks.waitForIceConnected;
resolve();
}
return new Promise((resolve, reject) =>
this.ice_connection_callbacks.waitForIceConnected = () => {
if (this.isIceConnected()) {
delete this.ice_connection_callbacks.waitForIceConnected;
resolve();
} else if (!this.isIceConnectionPending()) {
delete this.ice_connection_callbacks.waitForIceConnected;
reject(new Error('ICE failed'));
}
this.ice_connection_callbacks.waitForIceConnected = iceConnectedChanged;
});
},
@@ -0,0 +1,61 @@
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
createHTML({
bug: "1187775",
title: "peer connection ICE fails on relay-only without TURN"
});
function PC_LOCAL_NO_CANDIDATES(test) {
var isnt = can => is(can, null, "No candidates: " + JSON.stringify(can));
test.pcLocal._pc.addEventListener("icecandidate", e => isnt(e.candidate));
}
function PC_BOTH_WAIT_FOR_ICE_FAILED(test) {
var isFail = (f, reason, msg) =>
f().then(() => { throw new Error(msg + " must fail"); },
e => is(e.message, reason, msg + " must fail with: " + e.message));
return Promise.all([
isFail(() => waitForIceConnected(test, test.pcLocal), "ICE failed", "Local ICE"),
isFail(() => waitForIceConnected(test, test.pcRemote), "ICE failed", "Remote ICE")
])
.then(() => ok(true, "ICE on both sides must fail."));
}
var pushPrefs = (...p) => new Promise(r => SpecialPowers.pushPrefEnv({set: p}, r));
var test;
runNetworkTest(options =>
pushPrefs(['media.peerconnection.ice.stun_client_maximum_transmits', 3],
['media.peerconnection.ice.trickle_grace_period', 5000]).then(() => {
options = options || {};
options.config_local = options.config_local || {};
var servers = options.config_local.iceServers || [];
// remove any turn servers
options.config_local.iceServers = servers.filter(server =>
server.urls.every(u => !u.toLowerCase().startsWith('turn')));
// Here's the setting we're testing. Comment out and this test should fail:
options.config_local.iceTransportPolicy = "relay";
test = new PeerConnectionTest(options);
test.setMediaConstraints([{audio: true}, {video: true}],
[{audio: true}, {video: true}]);
test.chain.remove("PC_LOCAL_SETUP_ICE_LOGGER"); // Needed to suppress failing
test.chain.remove("PC_REMOTE_SETUP_ICE_LOGGER"); // on ICE-failure.
test.chain.insertAfter("PC_LOCAL_SETUP_ICE_HANDLER", PC_LOCAL_NO_CANDIDATES);
test.chain.replace("PC_LOCAL_WAIT_FOR_ICE_CONNECTED", PC_BOTH_WAIT_FOR_ICE_FAILED);
test.chain.removeAfter("PC_BOTH_WAIT_FOR_ICE_FAILED");
test.run();
}));
</script>
</pre>
</body>
</html>
+1 -2
View File
@@ -3153,8 +3153,7 @@ PluginProfilerObserver::Observe(nsISupports *aSubject,
} else if (!strcmp(aTopic, "profiler-stopped")) {
mPmp->StopProfiler();
} else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
RefPtr<ProfileGatherer> gatherer = static_cast<ProfileGatherer*>(aSubject);
mPmp->GatherAsyncProfile(gatherer);
mPmp->GatherAsyncProfile();
} else if (!strcmp(aTopic, "profiler-subprocess")) {
nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
mPmp->GatheredAsyncProfile(pse);
@@ -33,8 +33,9 @@
if (expectingLoads > 0) {
expectingLoads--;
}
if (!expectingLoads && !expectingErrors) {
if (!expectingLoads && !expectingErrors && afterExpectCallback) {
setTimeout(afterExpectCallback, 0);
afterExpectCallback = null;
}
}
function onImgError() {
@@ -42,8 +43,9 @@
if (expectingErrors > 0) {
expectingErrors--;
}
if (!expectingLoads && !expectingErrors) {
if (!expectingLoads && !expectingErrors && afterExpectCallback) {
setTimeout(afterExpectCallback, 0);
afterExpectCallback = null;
}
}
function expectEvents(loads, errors, callback) {
@@ -150,7 +152,7 @@
expectEvents(0, 0, nextTest);
});
// Re-binding image to document should be a no-op
// re-binding the image to the document should be a no-op
tests.push(function () {
info("test 8");
document.body.appendChild(img);
@@ -167,19 +169,20 @@
expectEvents(1, 0, function() {
is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request");
SpecialPowers.pushPrefEnv({'set': [ ["layout.css.devPixelsPerPx", "2.0"] ] },
function() {
// We don't currently dynamically switch, but doing so is
// up to the UA so we may in the future. In which case
// this test needs to be changed.
is(img.currentSrc, testPNG50, "Should now have testPNG50 as current request");
// The preference change will trigger a load, as the image will change
SpecialPowers.pushPrefEnv({'set': [ ["layout.css.devPixelsPerPx", "2.0"] ] });
expectEvents(1, 0, function() {
is(img.currentSrc, testPNG200, "Should now have testPNG200 as current request");
img.src = img.src;
is(img.currentSrc, testPNG50, "Should still have testPNG50 as current request");
is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
// img.src = img.src is special-cased by the spec. It should always
// trigger an load event
expectEvents(1, 0, function() {
is(img.currentSrc, testPNG200, "Should now have testPNG200 as current request");
nextTest();
is(img.currentSrc, testPNG200, "Should still have testPNG200 as current request");
expectEvents(0, 0, nextTest);
});
});
})
});
});
@@ -206,6 +209,10 @@
(tests.shift())();
}, 0);
} else {
// Remove the event listeners to prevent the prefenv being popped from
// causing test failures.
img.removeEventListener("load", onImgLoad);
img.removeEventListener("error", onImgError);
SimpleTest.finish();
}
}
+1
View File
@@ -27,6 +27,7 @@ FONT_PREF_LANG(Gujarati, "x-gujr", x_gujr),
FONT_PREF_LANG(Gurmukhi, "x-guru", x_guru),
FONT_PREF_LANG(Khmer, "x-khmr", x_khmr),
FONT_PREF_LANG(Malayalam, "x-mlym", x_mlym),
FONT_PREF_LANG(Mathematics, "x-math", x_math),
FONT_PREF_LANG(Oriya, "x-orya", x_orya),
FONT_PREF_LANG(Telugu, "x-telu", x_telu),
FONT_PREF_LANG(Kannada, "x-knda", x_knda),
+6
View File
@@ -605,6 +605,12 @@ public:
virtual void FlushContentDrawing() {}
// If a device reset has occurred, update the necessary platform backend
// bits.
virtual bool UpdateForDeviceReset() {
return false;
}
/**
* Helper method, creates a draw target for a specific Azure backend.
* Used by CreateOffscreenDrawTarget.
+24
View File
@@ -1195,6 +1195,30 @@ gfxWindowsPlatform::DidRenderingDeviceReset(DeviceResetReason* aResetReason)
return false;
}
BOOL CALLBACK
InvalidateWindowForDeviceReset(HWND aWnd, LPARAM aMsg)
{
RedrawWindow(aWnd, nullptr, nullptr,
RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_FRAME);
return TRUE;
}
bool
gfxWindowsPlatform::UpdateForDeviceReset()
{
if (!DidRenderingDeviceReset()) {
return false;
}
// Trigger an ::OnPaint for each window.
::EnumThreadWindows(GetCurrentThreadId(),
InvalidateWindowForDeviceReset,
0);
gfxCriticalNote << "Detected rendering device reset on refresh";
return true;
}
void
gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size)
{
+2 -1
View File
@@ -213,7 +213,8 @@ public:
*/
virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags) override;
virtual bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;
bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;
bool UpdateForDeviceReset() override;
mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) override;
+4 -4
View File
@@ -302,14 +302,14 @@ static inline char* js_strdup(const char* s)
* Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
* or the build will break.
*/
#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
#define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS) \
template <class T, typename... Args> \
QUALIFIERS T * \
NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
void* memory = ALLOCATOR(sizeof(T)); \
return memory \
? new(memory) T(mozilla::Forward<Args>(args)...) \
: nullptr; \
return MOZ_LIKELY(memory) \
? new(memory) T(mozilla::Forward<Args>(args)...) \
: nullptr; \
}
/*
+7 -7
View File
@@ -14,7 +14,7 @@ function ModuleGetExportedNames(exportStarSet = [])
let module = this;
// Step 2
if (module in exportStarSet)
if (callFunction(ArrayIncludes, exportStarSet, module))
return [];
// Step 3
@@ -47,7 +47,7 @@ function ModuleGetExportedNames(exportStarSet = [])
exportStarSet);
for (let j = 0; j < starNames.length; j++) {
let n = starNames[j];
if (n !== "default" && !(n in exportedNames))
if (n !== "default" && !callFunction(ArrayIncludes, exportedNames, n))
_DefineDataProperty(exportedNames, namesCount++, n);
}
}
@@ -104,7 +104,7 @@ function ModuleResolveExport(exportName, resolveSet = [], exportStarSet = [])
}
// Step 7
if (module in exportStarSet)
if (callFunction(ArrayIncludes, exportStarSet, module))
return null;
// Step 8
@@ -214,9 +214,9 @@ function ModuleDeclarationInstantiation()
let e = indirectExportEntries[i];
let resolution = callFunction(module.resolveExport, module, e.exportName);
if (resolution === null)
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT);
ThrowSyntaxError(JSMSG_MISSING_INDIRECT_EXPORT, e.exportName);
if (resolution === "ambiguous")
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT);
ThrowSyntaxError(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, e.exportName);
}
// Step 12
@@ -231,9 +231,9 @@ function ModuleDeclarationInstantiation()
let resolution = callFunction(importedModule.resolveExport, importedModule,
imp.importName);
if (resolution === null)
ThrowSyntaxError(JSMSG_MISSING_IMPORT);
ThrowSyntaxError(JSMSG_MISSING_IMPORT, imp.importName);
if (resolution === "ambiguous")
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT);
ThrowSyntaxError(JSMSG_AMBIGUOUS_IMPORT, imp.importName);
CreateImportBinding(env, imp.localName, resolution.module, resolution.bindingName);
}
}
+35 -24
View File
@@ -16,9 +16,6 @@
using namespace js;
using namespace js::frontend;
typedef JS::Rooted<ImportEntryObject*> RootedImportEntry;
typedef JS::Rooted<ExportEntryObject*> RootedExportEntry;
template<typename T, Value ValueGetter(T* obj)>
static bool
ModuleValueGetterImpl(JSContext* cx, const CallArgs& args)
@@ -121,7 +118,7 @@ ImportEntryObject::create(JSContext* cx,
if (!obj)
return nullptr;
RootedImportEntry self(cx, &obj->as<ImportEntryObject>());
RootedImportEntryObject self(cx, &obj->as<ImportEntryObject>());
self->initReservedSlot(ModuleRequestSlot, StringValue(moduleRequest));
self->initReservedSlot(ImportNameSlot, StringValue(importName));
self->initReservedSlot(LocalNameSlot, StringValue(localName));
@@ -194,7 +191,7 @@ ExportEntryObject::create(JSContext* cx,
if (!obj)
return nullptr;
RootedExportEntry self(cx, &obj->as<ExportEntryObject>());
RootedExportEntryObject self(cx, &obj->as<ExportEntryObject>());
self->initReservedSlot(ExportNameSlot, StringOrNullValue(maybeExportName));
self->initReservedSlot(ModuleRequestSlot, StringOrNullValue(maybeModuleRequest));
self->initReservedSlot(ImportNameSlot, StringOrNullValue(maybeImportName));
@@ -896,8 +893,9 @@ js::InitModuleClasses(JSContext* cx, HandleObject obj)
///////////////////////////////////////////////////////////////////////////
// ModuleBuilder
ModuleBuilder::ModuleBuilder(JSContext* cx)
ModuleBuilder::ModuleBuilder(JSContext* cx, HandleModuleObject module)
: cx_(cx),
module_(cx, module),
requestedModules_(cx, AtomVector(cx)),
importedBoundNames_(cx, AtomVector(cx)),
importEntries_(cx, ImportEntryVector(cx)),
@@ -908,7 +906,7 @@ ModuleBuilder::ModuleBuilder(JSContext* cx)
{}
bool
ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject module)
ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode)
{
MOZ_ASSERT(moduleNode->isKind(PNK_MODULE));
@@ -940,21 +938,21 @@ ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject
}
for (const auto& e : exportEntries_) {
RootedExportEntry exp(cx_, e);
RootedExportEntryObject exp(cx_, e);
if (!exp->moduleRequest()) {
RootedImportEntry importEntry(cx_, importEntryFor(exp->localName()));
RootedImportEntryObject importEntry(cx_, importEntryFor(exp->localName()));
if (!importEntry) {
if (!localExportEntries_.append(exp))
if (!appendLocalExportEntry(exp))
return false;
} else {
if (importEntry->importName() == cx_->names().star) {
if (!localExportEntries_.append(exp))
if (!appendLocalExportEntry(exp))
return false;
} else {
RootedAtom exportName(cx_, exp->exportName());
RootedAtom moduleRequest(cx_, importEntry->moduleRequest());
RootedAtom importName(cx_, importEntry->importName());
RootedExportEntry exportEntry(cx_);
RootedExportEntryObject exportEntry(cx_);
exportEntry = ExportEntryObject::create(cx_,
exportName,
moduleRequest,
@@ -994,7 +992,7 @@ ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject
if (!starExportEntries)
return false;
module->initImportExportData(requestedModules,
module_->initImportExportData(requestedModules,
importEntries,
localExportEntries,
indirectExportEntries,
@@ -1003,6 +1001,19 @@ ModuleBuilder::buildAndInit(frontend::ParseNode* moduleNode, HandleModuleObject
return true;
}
bool
ModuleBuilder::appendLocalExportEntry(HandleExportEntryObject exp)
{
if (!module_->initialEnvironment().lookup(cx_, AtomToId(exp->localName()))) {
JSAutoByteString str;
str.encodeLatin1(cx_, exp->localName());
JS_ReportErrorNumber(cx_, GetErrorMessage, nullptr, JSMSG_MISSING_EXPORT, str.ptr());
return false;
}
return localExportEntries_.append(exp);
}
bool
ModuleBuilder::processImport(frontend::ParseNode* pn)
{
@@ -1025,7 +1036,7 @@ ModuleBuilder::processImport(frontend::ParseNode* pn)
if (!importedBoundNames_.append(localName))
return false;
RootedImportEntry importEntry(cx_);
RootedImportEntryObject importEntry(cx_);
importEntry = ImportEntryObject::create(cx_, module, importName, localName);
if (!importEntry || !importEntries_.append(importEntry))
return false;
@@ -1049,7 +1060,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
MOZ_ASSERT(spec->isKind(PNK_EXPORT_SPEC));
RootedAtom localName(cx_, spec->pn_left->pn_atom);
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
if (!appendLocalExportEntry(exportName, localName))
if (!appendExportEntry(exportName, localName))
return false;
}
break;
@@ -1058,7 +1069,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
RootedFunction func(cx_, kid->pn_funbox->function());
RootedAtom localName(cx_, func->atom());
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
if (!appendLocalExportEntry(exportName, localName))
if (!appendExportEntry(exportName, localName))
return false;
break;
}
@@ -1068,7 +1079,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
MOZ_ASSERT(cls.names());
RootedAtom localName(cx_, cls.names()->innerBinding()->pn_atom);
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
if (!appendLocalExportEntry(exportName, localName))
if (!appendExportEntry(exportName, localName))
return false;
break;
}
@@ -1083,7 +1094,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
MOZ_ASSERT(var->isKind(PNK_NAME));
RootedAtom localName(cx_, var->pn_atom);
RootedAtom exportName(cx_, isDefault ? cx_->names().default_ : localName.get());
if (!appendLocalExportEntry(exportName, localName))
if (!appendExportEntry(exportName, localName))
return false;
}
break;
@@ -1093,7 +1104,7 @@ ModuleBuilder::processExport(frontend::ParseNode* pn)
MOZ_ASSERT(isDefault);
RootedAtom localName(cx_, cx_->names().starDefaultStar);
RootedAtom exportName(cx_, cx_->names().default_);
if (!appendLocalExportEntry(exportName, localName))
if (!appendExportEntry(exportName, localName))
return false;
break;
}
@@ -1115,12 +1126,12 @@ ModuleBuilder::processExportFrom(frontend::ParseNode* pn)
if (spec->isKind(PNK_EXPORT_SPEC)) {
RootedAtom bindingName(cx_, spec->pn_left->pn_atom);
RootedAtom exportName(cx_, spec->pn_right->pn_atom);
if (!appendIndirectExportEntry(exportName, module, bindingName))
if (!appendExportFromEntry(exportName, module, bindingName))
return false;
} else {
MOZ_ASSERT(spec->isKind(PNK_EXPORT_BATCH_SPEC));
RootedAtom importName(cx_, cx_->names().star);
if (!appendIndirectExportEntry(nullptr, module, importName))
if (!appendExportFromEntry(nullptr, module, importName))
return false;
}
}
@@ -1139,7 +1150,7 @@ ModuleBuilder::importEntryFor(JSAtom* localName)
}
bool
ModuleBuilder::appendLocalExportEntry(HandleAtom exportName, HandleAtom localName)
ModuleBuilder::appendExportEntry(HandleAtom exportName, HandleAtom localName)
{
Rooted<ExportEntryObject*> exportEntry(cx_);
exportEntry = ExportEntryObject::create(cx_, exportName, nullptr, nullptr, localName);
@@ -1147,8 +1158,8 @@ ModuleBuilder::appendLocalExportEntry(HandleAtom exportName, HandleAtom localNam
}
bool
ModuleBuilder::appendIndirectExportEntry(HandleAtom exportName, HandleAtom moduleRequest,
HandleAtom importName)
ModuleBuilder::appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
HandleAtom importName)
{
Rooted<ExportEntryObject*> exportEntry(cx_);
exportEntry = ExportEntryObject::create(cx_, exportName, moduleRequest, importName, nullptr);
+14 -6
View File
@@ -54,6 +54,9 @@ class ImportEntryObject : public NativeObject
JSAtom* localName();
};
typedef Rooted<ImportEntryObject*> RootedImportEntryObject;
typedef Handle<ImportEntryObject*> HandleImportEntryObject;
class ExportEntryObject : public NativeObject
{
public:
@@ -80,6 +83,9 @@ class ExportEntryObject : public NativeObject
JSAtom* localName();
};
typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
typedef Handle<ExportEntryObject*> HandleExportEntryObject;
class IndirectBindingMap
{
public:
@@ -268,9 +274,9 @@ class ModuleObject : public NativeObject
class MOZ_STACK_CLASS ModuleBuilder
{
public:
explicit ModuleBuilder(JSContext* cx);
explicit ModuleBuilder(JSContext* cx, HandleModuleObject module);
bool buildAndInit(frontend::ParseNode* pn, HandleModuleObject module);
bool buildAndInit(frontend::ParseNode* pn);
private:
using AtomVector = TraceableVector<JSAtom*>;
@@ -281,8 +287,8 @@ class MOZ_STACK_CLASS ModuleBuilder
using RootedExportEntryVector = JS::Rooted<ExportEntryVector> ;
JSContext* cx_;
RootedModuleObject module_;
RootedAtomVector requestedModules_;
RootedAtomVector importedBoundNames_;
RootedImportEntryVector importEntries_;
RootedExportEntryVector exportEntries_;
@@ -296,12 +302,14 @@ class MOZ_STACK_CLASS ModuleBuilder
ImportEntryObject* importEntryFor(JSAtom* localName);
bool appendLocalExportEntry(HandleAtom exportName, HandleAtom localName);
bool appendIndirectExportEntry(HandleAtom exportName, HandleAtom moduleRequest,
HandleAtom importName);
bool appendExportEntry(HandleAtom exportName, HandleAtom localName);
bool appendExportFromEntry(HandleAtom exportName, HandleAtom moduleRequest,
HandleAtom importName);
bool maybeAppendRequestedModule(HandleAtom module);
bool appendLocalExportEntry(HandleExportEntryObject exp);
template <typename T>
ArrayObject* createArray(const TraceableVector<T>& vector);
};
+4
View File
@@ -1010,6 +1010,10 @@ static const JSFunctionSpec object_static_methods[] = {
JS_FN("setPrototypeOf", obj_setPrototypeOf, 2, 0),
JS_FN("getOwnPropertyDescriptor", obj_getOwnPropertyDescriptor,2, 0),
JS_FN("keys", obj_keys, 1, 0),
#ifndef RELEASE_BUILD
JS_SELF_HOSTED_FN("values", "ObjectValues", 1, JSPROP_DEFINE_LATE),
JS_SELF_HOSTED_FN("entries", "ObjectEntries", 1, JSPROP_DEFINE_LATE),
#endif
JS_FN("is", obj_is, 2, 0),
JS_FN("defineProperty", obj_defineProperty, 3, 0),
JS_FN("defineProperties", obj_defineProperties, 2, 0),
+45
View File
@@ -134,3 +134,48 @@ function ObjectLookupGetter(name) {
} while (object !== null);
}
// Draft proposal http://tc39.github.io/proposal-object-values-entries/#Object.values
function ObjectValues(O) {
// Steps 1-2.
var object = ToObject(O);
// Steps 3-4.
// EnumerableOwnProperties is inlined here.
var keys = OwnPropertyKeys(object, JSITER_OWNONLY | JSITER_HIDDEN);
var values = [];
var valuesCount = 0;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!callFunction(std_Object_propertyIsEnumerable, object, key))
continue;
var value = object[key];
_DefineDataProperty(values, valuesCount++, value);
}
// Step 5.
return values;
}
// Draft proposal http://tc39.github.io/proposal-object-values-entries/#Object.entries
function ObjectEntries(O) {
// Steps 1-2.
var object = ToObject(O);
// Steps 3-4.
// EnumerableOwnProperties is inlined here.
var keys = OwnPropertyKeys(object, JSITER_OWNONLY | JSITER_HIDDEN);
var entries = [];
var entriesCount = 0;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (!callFunction(std_Object_propertyIsEnumerable, object, key))
continue;
var value = object[key];
_DefineDataProperty(entries, entriesCount++, [key, value]);
}
// Step 5.
return entries;
}
+1
View File
@@ -927,6 +927,7 @@ js::ExecuteRegExp(JSContext* cx, HandleObject regexp, HandleString string,
return RegExpRunStatus_Error;
} else if (reobj->needUpdateLastIndex()) {
/* Steps 18.a-b. */
MOZ_ASSERT(matches && !matches->empty());
if (!SetLastIndex(cx, reobj, (*matches)[0].limit))
return RegExpRunStatus_Error;
}
+2 -2
View File
@@ -298,8 +298,8 @@ GC(JSContext* cx, unsigned argc, Value* vp)
char buf[256] = { '\0' };
#ifndef JS_MORE_DETERMINISTIC
JS_snprintf(buf, sizeof(buf), "before %lu, after %lu\n",
(unsigned long)preBytes, (unsigned long)cx->runtime()->gc.usage.gcBytes());
JS_snprintf(buf, sizeof(buf), "before %" PRIuSIZE ", after %" PRIuSIZE "\n",
preBytes, cx->runtime()->gc.usage.gcBytes());
#endif
JSString* str = JS_NewStringCopyZ(cx, buf);
if (!str)
+9 -5
View File
@@ -650,14 +650,14 @@ function ArrayShorthand(...dims) {
if (!IsObject(this) || !ObjectIsTypeDescr(this))
ThrowTypeError(JSMSG_TYPEDOBJECT_BAD_ARGS);
var T = GetTypedObjectModule();
var AT = GetTypedObjectModule().ArrayType;
if (dims.length == 0)
ThrowTypeError(JSMSG_TYPEDOBJECT_BAD_ARGS);
var accum = this;
for (var i = dims.length - 1; i >= 0; i--)
accum = new T.ArrayType(accum, dims[i]);
accum = new AT(accum, dims[i]);
return accum;
}
@@ -1059,7 +1059,11 @@ function MapTypedSeqImpl(inArray, depth, outputType, func) {
}
function DoMapTypedSeqDepthN() {
var indices = new Uint32Array(depth);
// Simulate Uint32Array(depth) with a dumber (and more accessible)
// datastructure.
var indices = new List();
for (var i = 0; i < depth; i++)
callFunction(std_Array_push, indices, 0);
for (var i = 0; i < totalLength; i++) {
// Prepare input element and out pointer
@@ -1156,9 +1160,9 @@ function FilterTypedSeqImpl(array, func) {
inOffset += size;
}
var T = GetTypedObjectModule();
var AT = GetTypedObjectModule().ArrayType;
var resultType = new T.ArrayType(elementType, count);
var resultType = new AT(elementType, count);
var result = new resultType();
for (var i = 0, j = 0; i < array.length; i++) {
if (GET_BIT(flags, i))
+1 -1
View File
@@ -27,7 +27,7 @@
// Assertions, defined here instead of in the header above to make `assert`
// invisible to C++.
#ifdef DEBUG
#define assert(b, info) if (!(b)) AssertionFailed(info)
#define assert(b, info) if (!(b)) AssertionFailed(__FILE__ + ":" + __LINE__ + ": " + info)
#else
#define assert(b, info) // Elided assertion.
#endif
@@ -135,9 +135,6 @@ var ignoreFunctions = {
"JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoSuppressGCAnalysis instead
"uint8 NS_IsMainThread()" : true,
// Bug 1056410 - devirtualization prevents the standard nsISupports::Release heuristic from working
"uint32 nsXPConnect::Release()" : true,
// Has an indirect call under it by the name "__f", which seemed too
// generic to ignore by itself.
"void* std::_Locale_impl::~_Locale_impl(int32)" : true,
@@ -10,8 +10,8 @@
"unpack": true
},
{
"size": 4431740,
"digest": "68fc56b0fb0cdba629b95683d6649ff76b00dccf97af90960c3d7716f6108b2162ffd5ffcd5c3a60a21b28674df688fe4dabc67345e2da35ec5abeae3d48c8e3",
"size": 12057960,
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
"algorithm": "sha512",
"filename": "gtk3.tar.xz",
"unpack": true
+2 -2
View File
@@ -601,8 +601,8 @@ ModuleObject* BytecodeCompiler::compileModule()
return nullptr;
}
ModuleBuilder builder(cx->asJSContext());
if (!builder.buildAndInit(pn, module))
ModuleBuilder builder(cx->asJSContext(), module);
if (!builder.buildAndInit(pn))
return nullptr;
parser->handler.freeTree(pn);
+61 -18
View File
@@ -4413,13 +4413,25 @@ BytecodeEmitter::emitVariables(ParseNode* pn, VarEmitOption emitOption)
* i' to be hoisted out of the loop.
*/
MOZ_ASSERT(binding->isOp(JSOP_NOP));
MOZ_ASSERT(emitOption != DefineVars && emitOption != AnnexB);
MOZ_ASSERT(emitOption != DefineVars);
MOZ_ASSERT_IF(emitOption == AnnexB, binding->pn_left->isKind(PNK_NAME));
/*
* To allow the front end to rewrite var f = x; as f = x; when a
* function f(){} precedes the var, detect simple name assignment
* here and initialize the name.
*/
// To allow the front end to rewrite |var f = x;| as |f = x;| when a
// |function f(){}| precedes the var, detect simple name assignment
// here and initialize the name.
//
// There is a corner case where a function declaration synthesizes
// an Annex B declaration, which in turn gets rewritten later as a
// simple assignment due to hoisted function declaration of the
// same name. For example,
//
// {
// // Synthesizes an Annex B declaration because no 'f' binding
// // yet exists. This later gets rewritten as an assignment when
// // the outer function 'f' gets hoisted.
// function f() {}
// }
// function f() {}
if (binding->pn_left->isKind(PNK_NAME)) {
if (!emitSingleVariable(pn, binding->pn_left, binding->pn_right, emitOption))
return false;
@@ -6728,6 +6740,16 @@ BytecodeEmitter::emitReturn(ParseNode* pn)
if (!emit1((isGenerator || isDerivedClassConstructor) ? JSOP_SETRVAL : JSOP_RETURN))
return false;
// Make sure that we emit this before popping the blocks in prepareForNonLocalJump,
// to ensure that the error is thrown while the scope-chain is still intact.
if (isDerivedClassConstructor) {
BindingIter bi = Bindings::thisBinding(cx, script);
if (!emitLoadFromTopScope(bi))
return false;
if (!emit1(JSOP_CHECKRETURN))
return false;
}
NonLocalExitScope nle(this);
if (!nle.prepareForNonLocalJump(nullptr))
@@ -6745,11 +6767,6 @@ BytecodeEmitter::emitReturn(ParseNode* pn)
return false;
} else if (isDerivedClassConstructor) {
MOZ_ASSERT(code()[top] == JSOP_SETRVAL);
BindingIter bi = Bindings::thisBinding(cx, script);
if (!emitLoadFromTopScope(bi))
return false;
if (!emit1(JSOP_CHECKRETURN))
return false;
if (!emit1(JSOP_RETRVAL))
return false;
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != offset()) {
@@ -7145,6 +7162,18 @@ BytecodeEmitter::emitDeleteExpression(ParseNode* node)
return emit1(JSOP_TRUE);
}
bool
BytecodeEmitter::emitDebugOnlyCheckSelfHosted()
{
#ifdef DEBUG
if (emitterMode == BytecodeEmitter::SelfHosting) {
if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
return false;
}
#endif
return true;
}
bool
BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
{
@@ -7157,22 +7186,27 @@ BytecodeEmitter::emitSelfHostedCallFunction(ParseNode* pn)
//
// argc is set to the amount of actually emitted args and the
// emitting of args below is disabled by setting emitArgs to false.
ParseNode* pn2 = pn->pn_head;
const char* errorName = pn2->name() == cx->names().callFunction ?
"callFunction" : "callContentFunction";
if (pn->pn_count < 3) {
reportError(pn, JSMSG_MORE_ARGS_NEEDED, "callFunction", "1", "s");
reportError(pn, JSMSG_MORE_ARGS_NEEDED, errorName, "2", "s");
return false;
}
if (pn->getOp() != JSOP_CALL) {
reportError(pn, JSMSG_NOT_CONSTRUCTOR, errorName);
return false;
}
ParseNode* pn2 = pn->pn_head;
ParseNode* funNode = pn2->pn_next;
if (!emitTree(funNode))
return false;
#ifdef DEBUG
if (pn2->name() != cx->names().callContentFunction) {
if (!emit1(JSOP_DEBUGCHECKSELFHOSTED))
if (!emitDebugOnlyCheckSelfHosted())
return false;
}
#endif
ParseNode* thisArg = funNode->pn_next;
if (!emitTree(thisArg))
@@ -7272,8 +7306,9 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
// We shouldn't see foo(bar) = x in self-hosted code.
MOZ_ASSERT(!(pn->pn_xflags & PNX_SETCALL));
// Calls to "forceInterpreter", "callFunction" or "resumeGenerator"
// in self-hosted code generate inline bytecode.
// Calls to "forceInterpreter", "callFunction",
// "callContentFunction", or "resumeGenerator" in self-hosted
// code generate inline bytecode.
if (pn2->name() == cx->names().callFunction ||
pn2->name() == cx->names().callContentFunction)
{
@@ -7296,6 +7331,10 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
if (!emitPropOp(pn2, callop ? JSOP_CALLPROP : JSOP_GETPROP))
return false;
}
if (!emitDebugOnlyCheckSelfHosted())
return false;
break;
case PNK_ELEM:
if (pn2->as<PropertyByValue>().isSuper()) {
@@ -7309,6 +7348,10 @@ BytecodeEmitter::emitCallOrNew(ParseNode* pn)
return false;
}
}
if (!emitDebugOnlyCheckSelfHosted())
return false;
break;
case PNK_FUNCTION:
/*
+1
View File
@@ -608,6 +608,7 @@ struct BytecodeEmitter
bool emitConditionalExpression(ConditionalExpression& conditional);
bool emitCallOrNew(ParseNode* pn);
bool emitDebugOnlyCheckSelfHosted();
bool emitSelfHostedCallFunction(ParseNode* pn);
bool emitSelfHostedResumeGenerator(ParseNode* pn);
bool emitSelfHostedForceInterpreter(ParseNode* pn);
+25 -15
View File
@@ -1163,22 +1163,32 @@ ObjectBox::asModuleBox()
return static_cast<ModuleBox*>(this);
}
/* static */ void
ObjectBox::TraceList(JSTracer* trc, ObjectBox* listHead)
{
for (ObjectBox* box = listHead; box; box = box->traceLink)
box->trace(trc);
}
void
ObjectBox::trace(JSTracer* trc)
{
ObjectBox* box = this;
while (box) {
TraceRoot(trc, &box->object, "parser.object");
if (box->isFunctionBox()) {
FunctionBox* funbox = box->asFunctionBox();
funbox->bindings.trace(trc);
if (funbox->enclosingStaticScope_)
TraceRoot(trc, &funbox->enclosingStaticScope_, "funbox-enclosingStaticScope");
} else if (box->isModuleBox()) {
ModuleBox* modulebox = box->asModuleBox();
modulebox->bindings.trace(trc);
modulebox->exportNames.trace(trc);
}
box = box->traceLink;
}
TraceRoot(trc, &object, "parser.object");
}
void
FunctionBox::trace(JSTracer* trc)
{
ObjectBox::trace(trc);
bindings.trace(trc);
if (enclosingStaticScope_)
TraceRoot(trc, &enclosingStaticScope_, "funbox-enclosingStaticScope");
}
void
ModuleBox::trace(JSTracer* trc)
{
ObjectBox::trace(trc);
bindings.trace(trc);
exportNames.trace(trc);
}
+3 -1
View File
@@ -1722,7 +1722,9 @@ class ObjectBox
FunctionBox* asFunctionBox();
bool isModuleBox() { return object->is<ModuleObject>(); }
ModuleBox* asModuleBox();
void trace(JSTracer* trc);
virtual void trace(JSTracer* trc);
static void TraceList(JSTracer* trc, ObjectBox* listHead);
protected:
friend struct CGObjectList;
+31 -17
View File
@@ -855,7 +855,7 @@ template <typename ParseHandler>
void
Parser<ParseHandler>::trace(JSTracer* trc)
{
traceListHead->trace(trc);
ObjectBox::TraceList(trc, traceListHead);
}
void
@@ -5050,8 +5050,32 @@ template<>
bool
Parser<SyntaxParseHandler>::addExportName(JSAtom* exportName)
{
JS_ALWAYS_FALSE(abortIfSyntaxParser());
return SyntaxParseHandler::NodeFailure;
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
}
template<>
bool
Parser<FullParseHandler>::addExportNamesForDeclaration(ParseNode* node)
{
MOZ_ASSERT(node->isArity(PN_LIST));
for (ParseNode* binding = node->pn_head; binding; binding = binding->pn_next) {
if (binding->isKind(PNK_ASSIGN))
binding = binding->pn_left;
MOZ_ASSERT(binding->isKind(PNK_NAME));
if (!addExportName(binding->pn_atom))
return false;
}
return true;
}
template<>
bool
Parser<SyntaxParseHandler>::addExportNamesForDeclaration(Node node)
{
MOZ_ALWAYS_FALSE(abortIfSyntaxParser());
return false;
}
template<>
@@ -5228,15 +5252,8 @@ Parser<FullParseHandler>::exportDeclaration()
return null();
if (!MatchOrInsertSemicolonAfterExpression(tokenStream))
return null();
MOZ_ASSERT(kid->isArity(PN_LIST));
for (ParseNode* var = kid->pn_head; var; var = var->pn_next) {
if (var->isKind(PNK_ASSIGN))
var = var->pn_left;
MOZ_ASSERT(var->isKind(PNK_NAME));
if (!addExportName(var->pn_atom))
return null();
}
if (!addExportNamesForDeclaration(kid))
return null();
break;
case TOK_DEFAULT: {
@@ -5280,6 +5297,8 @@ Parser<FullParseHandler>::exportDeclaration()
kid = lexicalDeclaration(YieldIsName, tt == TOK_CONST);
if (!kid)
return null();
if (!addExportNamesForDeclaration(kid))
return null();
break;
default:
@@ -8922,11 +8941,6 @@ Parser<ParseHandler>::memberExpr(YieldHandling yieldHandling, TripledotHandling
return handler.newSetThis(thisName, nextMember);
}
if (options().selfHostingMode && handler.isPropertyAccess(lhs)) {
report(ParseError, false, null(), JSMSG_SELFHOSTED_METHOD_CALL);
return null();
}
nextMember = tt == TOK_LP ? handler.newCall() : handler.newTaggedTemplate();
if (!nextMember)
return null();
+1
View File
@@ -761,6 +761,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
Node newBoundImportForCurrentName();
bool namedImportsOrNamespaceImport(TokenKind tt, Node importSpecSet);
bool addExportName(JSAtom* exportName);
bool addExportNamesForDeclaration(Node node);
enum ClassContext { ClassStatement, ClassExpression };
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext, DefaultHandling defaultHandling);
+4
View File
@@ -427,6 +427,8 @@ class FunctionBox : public ObjectBox, public SharedContext
isDerivedClassConstructor() ||
isGenerator();
}
void trace(JSTracer* trc) override;
};
class ModuleBox : public ObjectBox, public SharedContext
@@ -442,6 +444,8 @@ class ModuleBox : public ObjectBox, public SharedContext
ObjectBox* toObjectBox() override { return this; }
ModuleObject* module() const { return &object->as<ModuleObject>(); }
JSObject* staticScope() const override { return module(); }
void trace(JSTracer* trc) override;
};
inline FunctionBox*
+2
View File
@@ -0,0 +1,2 @@
export * from 'module1.js';
export * from 'module1a.js';
+1
View File
@@ -0,0 +1 @@
export const a = 2;
@@ -0,0 +1 @@
export * from 'recursiveStarExport.js';
@@ -0,0 +1,13 @@
Function.prototype.prototype = function() {}
var type = TypedObject.uint8.array(4).array(4);
var x = new type([
[, , , 0],
[, , , 0],
[, , , 0],
[, , , 0]
]);
x.map(2, function(y) {
return 0;
});
@@ -0,0 +1,2 @@
// |jit-test| module; error: SyntaxError
import { a } from "ambiguous.js";
@@ -0,0 +1,2 @@
// |jit-test| module; error: SyntaxError
export { a } from "ambiguous.js";
@@ -7,15 +7,26 @@ function testSyntaxError(source) {
}, SyntaxError);
}
// SyntexError due to duplicate exports
testSyntaxError("export var v; export var v;");
testSyntaxError("export var x, y, z; export var y;");
testSyntaxError("export let v; var w; export {w as v};");
testSyntaxError("export const v; var w; export {w as v};");
testSyntaxError("export var v; let w; export {w as v};");
testSyntaxError("export var v; const w; export {w as v};");
testSyntaxError("export default 1; export default 2;");
testSyntaxError("export var default; export default 1;");
testSyntaxError("export var default; export default function() {};");
testSyntaxError("export var default; export default function foo() {};");
testSyntaxError("export var default; export default export class { constructor() {} };");
testSyntaxError("export var default; export default export class foo { constructor() {} };");
testSyntaxError("export default 1; export default function() {};");
testSyntaxError("export default 1; export default function foo() {};");
testSyntaxError("var v; export {v}; export {v};");
testSyntaxError("var v, x; export {v}; export {x as v};");
testSyntaxError("export default 1; export default export class { constructor() {} };");
testSyntaxError("export default 1; export default export class foo { constructor() {} };");
// SyntaxError due to redeclared binding
testSyntaxError("export let v; export let v;");
testSyntaxError("export let x, y, z; export let y;");
testSyntaxError("export const v = 0; export const v = 0;");
testSyntaxError("export const x = 0, y = 0, z = 0; export const y = 0;");
testSyntaxError("export var v; export let v;");
testSyntaxError("export var v; export const v = 0;");
testSyntaxError("export let v; export const v;");
@@ -0,0 +1,2 @@
// |jit-test| module; error: SyntaxError
import { foo } from "module1.js";
@@ -0,0 +1,2 @@
// |jit-test| module; error: SyntaxError
export { foo } from "module1.js";
@@ -0,0 +1,2 @@
// |jit-test| module;
import * as ns from "recursiveStarExport.js";
@@ -0,0 +1,2 @@
// |jit-test| module; error: SyntaxError: local binding for export 'b' not found
export { b };
+5 -5
View File
@@ -317,7 +317,6 @@ MSG_DEF(JSMSG_RESERVED_ID, 1, JSEXN_SYNTAXERR, "{0} is a reserved id
MSG_DEF(JSMSG_REST_WITH_DEFAULT, 0, JSEXN_SYNTAXERR, "rest parameter may not have a default")
MSG_DEF(JSMSG_SELFHOSTED_TOP_LEVEL_LEXICAL, 1, JSEXN_SYNTAXERR, "self-hosted code cannot contain top-level {0} declarations")
MSG_DEF(JSMSG_SELFHOSTED_UNBOUND_NAME, 0, JSEXN_TYPEERR, "self-hosted code may not contain unbound name lookups")
MSG_DEF(JSMSG_SELFHOSTED_METHOD_CALL, 0, JSEXN_SYNTAXERR, "self-hosted code may not contain direct method calls")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 0, JSEXN_SYNTAXERR, "missing ; before statement")
@@ -526,8 +525,9 @@ MSG_DEF(JSMSG_REINIT_THIS, 0, JSEXN_REFERENCEERR, "super() called twice in
// Modules
MSG_DEF(JSMSG_BAD_DEFAULT_EXPORT, 0, JSEXN_SYNTAXERR, "default export cannot be provided by export *")
MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "indirect export not found")
MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 0, JSEXN_SYNTAXERR, "ambiguous indirect export")
MSG_DEF(JSMSG_MISSING_IMPORT, 0, JSEXN_SYNTAXERR, "import not found")
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 0, JSEXN_SYNTAXERR, "ambiguous import")
MSG_DEF(JSMSG_MISSING_INDIRECT_EXPORT, 1, JSEXN_SYNTAXERR, "indirect export '{0}' not found")
MSG_DEF(JSMSG_AMBIGUOUS_INDIRECT_EXPORT, 1, JSEXN_SYNTAXERR, "ambiguous indirect export '{0}'")
MSG_DEF(JSMSG_MISSING_IMPORT, 1, JSEXN_SYNTAXERR, "import '{0}' not found")
MSG_DEF(JSMSG_AMBIGUOUS_IMPORT, 1, JSEXN_SYNTAXERR, "ambiguous import '{0}'")
MSG_DEF(JSMSG_MISSING_NAMESPACE_EXPORT, 0, JSEXN_SYNTAXERR, "export not found for namespace")
MSG_DEF(JSMSG_MISSING_EXPORT, 1, JSEXN_SYNTAXERR, "local binding for export '{0}' not found")
+2 -1
View File
@@ -2124,9 +2124,10 @@ TryNotes(JSContext* cx, HandleScript script, Sprinter* sp)
Sprint(sp, "\nException table:\nkind stack start end\n");
do {
MOZ_ASSERT(tn->kind < ArrayLength(TryNoteNames));
uint8_t startOff = script->pcToOffset(script->main()) + tn->start;
Sprint(sp, " %-7s %6u %8u %8u\n",
TryNoteNames[tn->kind], tn->stackDepth,
tn->start, tn->start + tn->length);
startOff, startOff + tn->length);
} while (++tn != tnlimit);
return true;
}
@@ -0,0 +1,16 @@
class base {}
class derived extends base {
constructor() {
try {
return;
} catch (e) {
try {
return;
} catch (e) {}
}
}
}
assertThrowsInstanceOf(() => new derived, ReferenceError);
if (typeof reportCompare === 'function')
reportCompare(0,0,"OK");
+94
View File
@@ -0,0 +1,94 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
if ("entries" in Object) {
assertEq(Object.entries.length, 1);
var o, entries;
o = { a: 3, b: 2 };
entries = Object.entries(o);
assertDeepEq(entries, [["a", 3], ["b", 2]]);
o = { get a() { return 17; }, b: 2 };
entries = Object.entries(o),
assertDeepEq(entries, [["a", 17], ["b", 2]]);
o = { __iterator__: function() { return Iterator({a: 2, b: 3}); } };
entries = Object.entries(o);
assertDeepEq(entries, [["__iterator__", o.__iterator__]]);
o = { a: 1, b: 2 };
delete o.a;
o.a = 3;
entries = Object.entries(o);
assertDeepEq(entries, [["b", 2], ["a", 3]]);
o = [0, 1, 2];
entries = Object.entries(o);
assertDeepEq(entries, [["0", 0], ["1", 1], ["2", 2]]);
o = /./.exec("abc");
entries = Object.entries(o);
assertDeepEq(entries, [["0", "a"], ["index", 0], ["input", "abc"]]);
o = { a: 1, b: 2, c: 3 };
delete o.b;
o.b = 5;
entries = Object.entries(o);
assertDeepEq(entries, [["a", 1], ["c", 3], ["b", 5]]);
function f() { }
f.prototype.p = 1;
o = new f();
o.g = 1;
entries = Object.entries(o);
assertDeepEq(entries, [["g", 1]]);
var o = {get a() {delete this.b; return 1}, b: 2, c: 3};
entries = Object.entries(o);
assertDeepEq(entries, [["a", 1], ["c", 3]]);
assertThrowsInstanceOf(() => Object.entries(), TypeError);
assertThrowsInstanceOf(() => Object.entries(undefined), TypeError);
assertThrowsInstanceOf(() => Object.entries(null), TypeError);
assertDeepEq(Object.entries(1), []);
assertDeepEq(Object.entries(true), []);
if (typeof Symbol === "function")
assertDeepEq(Object.entries(Symbol("foo")), []);
assertDeepEq(Object.entries("foo"), [["0", "f"], ["1", "o"], ["2", "o"]]);
entries = Object.entries({
get a(){
Object.defineProperty(this, "b", {enumerable: false});
return "A";
},
b: "B"
});
assertDeepEq(entries, [["a", "A"]]);
let ownKeysCallCount = 0;
let getOwnPropertyDescriptorCalls = [];
let target = { a: 1, b: 2, c: 3 };
o = new Proxy(target, {
ownKeys() {
ownKeysCallCount++;
return ["c", "a"];
},
getOwnPropertyDescriptor(target, key) {
getOwnPropertyDescriptorCalls.push(key);
return Object.getOwnPropertyDescriptor(target, key);
}
});
entries = Object.entries(o);
assertEq(ownKeysCallCount, 1);
assertDeepEq(entries, [["c", 3], ["a", 1]]);
assertDeepEq(getOwnPropertyDescriptorCalls, ["c", "a"]);
}
if (typeof reportCompare === "function")
reportCompare(true, true);
View File
+94
View File
@@ -0,0 +1,94 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
if ("values" in Object) {
assertEq(Object.values.length, 1);
var o, values;
o = { a: 3, b: 2 };
values = Object.values(o);
assertDeepEq(values, [3, 2]);
o = { get a() { return 17; }, b: 2 };
values = Object.values(o),
assertDeepEq(values, [17, 2]);
o = { __iterator__: function() { return Iterator({a: 2, b: 3}); } };
values = Object.values(o);
assertDeepEq(values, [o.__iterator__]);
o = { a: 1, b: 2 };
delete o.a;
o.a = 3;
values = Object.values(o);
assertDeepEq(values, [2, 3]);
o = [0, 1, 2];
values = Object.values(o);
assertDeepEq(values, [0, 1, 2]);
o = /./.exec("abc");
values = Object.values(o);
assertDeepEq(values, ["a", 0, "abc"]);
o = { a: 1, b: 2, c: 3 };
delete o.b;
o.b = 5;
values = Object.values(o);
assertDeepEq(values, [1, 3, 5]);
function f() { }
f.prototype.p = 1;
o = new f();
o.g = 1;
values = Object.values(o);
assertDeepEq(values, [1]);
var o = {get a() {delete this.b; return 1}, b: 2, c: 3};
values = Object.values(o);
assertDeepEq(values, [1, 3]);
assertThrowsInstanceOf(() => Object.values(), TypeError);
assertThrowsInstanceOf(() => Object.values(undefined), TypeError);
assertThrowsInstanceOf(() => Object.values(null), TypeError);
assertDeepEq(Object.values(1), []);
assertDeepEq(Object.values(true), []);
if (typeof Symbol === "function")
assertDeepEq(Object.values(Symbol("foo")), []);
assertDeepEq(Object.values("foo"), ["f", "o", "o"]);
values = Object.values({
get a(){
Object.defineProperty(this, "b", {enumerable: false});
return "A";
},
b: "B"
});
assertDeepEq(values, ["A"]);
let ownKeysCallCount = 0;
let getOwnPropertyDescriptorCalls = [];
let target = { a: 1, b: 2, c: 3 };
o = new Proxy(target, {
ownKeys() {
ownKeysCallCount++;
return ["c", "a"];
},
getOwnPropertyDescriptor(target, key) {
getOwnPropertyDescriptorCalls.push(key);
return Object.getOwnPropertyDescriptor(target, key);
}
});
values = Object.values(o);
assertEq(ownKeysCallCount, 1);
assertDeepEq(values, [3, 1]);
assertDeepEq(getOwnPropertyDescriptorCalls, ["c", "a"]);
}
if (typeof reportCompare === "function")
reportCompare(true, true);
-1
View File
@@ -416,7 +416,6 @@ GlobalObject::initSelfHostingBuiltins(JSContext* cx, Handle<GlobalObject*> globa
return InitBareBuiltinCtor(cx, global, JSProto_Array) &&
InitBareBuiltinCtor(cx, global, JSProto_TypedArray) &&
InitBareBuiltinCtor(cx, global, JSProto_Uint8Array) &&
InitBareBuiltinCtor(cx, global, JSProto_Uint32Array) &&
InitBareWeakMapCtor(cx, global) &&
InitStopIterationClass(cx, global) &&
InitSelfHostingCollectionIteratorFunctions(cx, global) &&
+1 -1
View File
@@ -179,7 +179,7 @@ bool
js::Debug_CheckSelfHosted(JSContext* cx, HandleValue fun)
{
#ifndef DEBUG
MOZ_CRASH("Self hosted checks should only be done in Debug builds");
MOZ_CRASH("self-hosted checks should only be done in Debug builds");
#endif
MOZ_ASSERT(fun.isObject());
+1 -1
View File
@@ -29,7 +29,7 @@ namespace js {
*
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 325;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 327;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
+2
View File
@@ -1628,6 +1628,8 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
AutoRestore<TimeStamp> restoreTickStart(mTickStart);
mTickStart = TimeStamp::Now();
gfxPlatform::GetPlatform()->UpdateForDeviceReset();
/*
* The timer holds a reference to |this| while calling |Notify|.
* However, implementations of |WillRefresh| are permitted to destroy
+2
View File
@@ -4,6 +4,8 @@
# 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("/ipc/chromium/chromium-config.mozbuild")
EXPORTS.mtransport += [
'../dtlsidentity.h',
'../m_cpp_utils.h',
-4
View File
@@ -63,7 +63,6 @@ if CONFIG['OS_TARGET'] in ['Darwin', 'DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD'
]
elif CONFIG['OS_TARGET'] == 'Linux':
DEFINES['LINUX'] = True
DEFINES['USE_INTERFACE_PRIORITIZER'] = True
LOCAL_INCLUDES += [
'/media/mtransport/third_party/nrappkit/src/port/linux/include',
]
@@ -81,9 +80,6 @@ elif CONFIG['OS_TARGET'] == 'WINNT':
'/media/mtransport/third_party/nrappkit/src/port/win32/include',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
DEFINES['USE_INTERFACE_PRIORITIZER'] = True
for var in ('HAVE_STRDUP', 'NR_SOCKET_IS_VOID_PTR'):
DEFINES[var] = True
+2
View File
@@ -4,6 +4,8 @@
# 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("/ipc/chromium/chromium-config.mozbuild")
DIRS += [
'/media/mtransport/third_party',
'/media/mtransport/build',
+616 -98
View File
@@ -106,6 +106,54 @@ nrappkit copyright:
#include "nsXPCOM.h"
#include "nsXULAppAPI.h"
#include "runnable_utils.h"
#include "mozilla/SyncRunnable.h"
#include "nsTArray.h"
#include "mozilla/dom/TCPSocketBinding.h"
#include "nsITCPSocketCallback.h"
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
// csi_platform.h deep in nrappkit defines LOG_INFO and LOG_WARNING
#ifdef LOG_INFO
#define LOG_TEMP_INFO LOG_INFO
#undef LOG_INFO
#endif
#ifdef LOG_WARNING
#define LOG_TEMP_WARNING LOG_WARNING
#undef LOG_WARNING
#endif
#if defined(LOG_DEBUG)
#define LOG_TEMP_DEBUG LOG_DEBUG
#undef LOG_DEBUG
#endif
#undef strlcpy
// TCPSocketChild.h doesn't include TypedArray.h
namespace mozilla {
namespace dom {
class ArrayBuffer;
}
}
#include "mozilla/dom/network/TCPSocketChild.h"
#ifdef LOG_TEMP_INFO
#define LOG_INFO LOG_TEMP_INFO
#endif
#ifdef LOG_TEMP_WARNING
#define LOG_WARNING LOG_TEMP_WARNING
#endif
#ifdef LOG_TEMP_DEBUG
#define LOG_DEBUG LOG_TEMP_DEBUG
#endif
#ifdef XP_WIN
#ifdef LOG_DEBUG
#undef LOG_DEBUG
#endif
// cloned from csi_platform.h. Win32 doesn't like how we hide symbols
#define LOG_DEBUG 7
#endif
#endif
extern "C" {
#include "nr_api.h"
@@ -205,6 +253,31 @@ static void ClearSingletonOnShutdown()
}
#endif
static nsIThread* GetIOThreadAndAddUse_s()
{
// Always runs on STS thread!
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
// We need to safely release this on shutdown to avoid leaks
if (!sThread) {
sThread = new SingletonThreadHolder(NS_LITERAL_CSTRING("mtransport"));
NS_DispatchToMainThread(mozilla::WrapRunnableNM(&ClearSingletonOnShutdown));
}
// Mark that we're using the shared thread and need it to stick around
sThread->AddUse();
return sThread->GetThread();
#else
static nsCOMPtr<nsIThread> sThread;
if (!sThread) {
(void) NS_NewNamedThread("mtransport", getter_AddRefs(sThread));
}
return sThread;
#endif
}
NrSocketIpc::NrSocketIpc(nsIEventTarget *aThread)
: io_thread_(aThread)
{}
static TimeStamp nr_socket_short_term_violation_time;
static TimeStamp nr_socket_long_term_violation_time;
@@ -736,7 +809,7 @@ int NrSocket::connect(nr_transport_addr *addr) {
ASSERT_ON_THREAD(ststhread_);
int r,_status;
PRNetAddr naddr;
int32_t status;
int32_t connect_status, getsockname_status;
if ((r=nr_transport_addr_to_praddr(addr, &naddr)))
ABORT(r);
@@ -747,13 +820,28 @@ int NrSocket::connect(nr_transport_addr *addr) {
// Note: this just means we tried to connect, not that we
// are actually live.
connect_invoked_ = true;
status = PR_Connect(fd_, &naddr, PR_INTERVAL_NO_WAIT);
connect_status = PR_Connect(fd_, &naddr, PR_INTERVAL_NO_WAIT);
if (connect_status != PR_SUCCESS) {
if (PR_GetError() != PR_IN_PROGRESS_ERROR)
ABORT(R_IO_ERROR);
}
if (status != PR_SUCCESS) {
if (PR_GetError() == PR_IN_PROGRESS_ERROR)
ABORT(R_WOULDBLOCK);
// If our local address is wildcard, then fill in the
// address now.
if(nr_transport_addr_is_wildcard(&my_addr_)){
getsockname_status = PR_GetSockName(fd_, &naddr);
if (getsockname_status != PR_SUCCESS){
r_log(LOG_GENERIC, LOG_CRIT, "Couldn't get sock name for socket");
ABORT(R_INTERNAL);
}
ABORT(R_IO_ERROR);
if((r=nr_praddr_to_transport_addr(&naddr,&my_addr_,addr->protocol,1)))
ABORT(r);
}
// Now return the WOULDBLOCK if needed.
if (connect_status != PR_SUCCESS) {
ABORT(R_WOULDBLOCK);
}
_status=0;
@@ -907,10 +995,10 @@ abort:
return(_status);
}
NS_IMPL_ISUPPORTS(NrSocketIpcProxy, nsIUDPSocketInternal)
NS_IMPL_ISUPPORTS(NrUdpSocketIpcProxy, nsIUDPSocketInternal)
nsresult
NrSocketIpcProxy::Init(const RefPtr<NrSocketIpc>& socket)
NrUdpSocketIpcProxy::Init(const RefPtr<NrUdpSocketIpc>& socket)
{
nsresult rv;
sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
@@ -923,7 +1011,7 @@ NrSocketIpcProxy::Init(const RefPtr<NrSocketIpc>& socket)
return NS_OK;
}
NrSocketIpcProxy::~NrSocketIpcProxy()
NrUdpSocketIpcProxy::~NrUdpSocketIpcProxy()
{
// Send our ref to STS to be released
RUN_ON_THREAD(sts_thread_,
@@ -933,39 +1021,39 @@ NrSocketIpcProxy::~NrSocketIpcProxy()
// IUDPSocketInternal interfaces
// callback while error happened in UDP socket operation
NS_IMETHODIMP NrSocketIpcProxy::CallListenerError(const nsACString &message,
const nsACString &filename,
uint32_t line_number) {
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerError(const nsACString &message,
const nsACString &filename,
uint32_t line_number) {
return socket_->CallListenerError(message, filename, line_number);
}
// callback while receiving UDP packet
NS_IMETHODIMP NrSocketIpcProxy::CallListenerReceivedData(const nsACString &host,
uint16_t port,
const uint8_t *data,
uint32_t data_length) {
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerReceivedData(const nsACString &host,
uint16_t port,
const uint8_t *data,
uint32_t data_length) {
return socket_->CallListenerReceivedData(host, port, data, data_length);
}
// callback while UDP socket is opened
NS_IMETHODIMP NrSocketIpcProxy::CallListenerOpened() {
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerOpened() {
return socket_->CallListenerOpened();
}
// callback while UDP socket is closed
NS_IMETHODIMP NrSocketIpcProxy::CallListenerClosed() {
NS_IMETHODIMP NrUdpSocketIpcProxy::CallListenerClosed() {
return socket_->CallListenerClosed();
}
// NrSocketIpc Implementation
NrSocketIpc::NrSocketIpc()
: err_(false),
state_(NR_INIT),
io_thread_(GetIOThreadAndAddUse_s()),
monitor_("NrSocketIpc") {
// NrUdpSocketIpc Implementation
NrUdpSocketIpc::NrUdpSocketIpc()
: NrSocketIpc(GetIOThreadAndAddUse_s()),
monitor_("NrUdpSocketIpc"),
err_(false),
state_(NR_INIT) {
}
NrSocketIpc::~NrSocketIpc()
NrUdpSocketIpc::~NrUdpSocketIpc()
{
// also guarantees socket_child_ is released from the io_thread, and
// tells the SingletonThreadHolder we're done with it
@@ -973,40 +1061,18 @@ NrSocketIpc::~NrSocketIpc()
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
// close(), but transfer the socket_child_ reference to die as well
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnableNM(&NrSocketIpc::release_child_i,
mozilla::WrapRunnableNM(&NrUdpSocketIpc::release_child_i,
socket_child_.forget().take(),
sts_thread_),
NS_DISPATCH_NORMAL);
#endif
}
/* static */
nsIThread* NrSocketIpc::GetIOThreadAndAddUse_s()
{
// Always runs on STS thread!
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
// We need to safely release this on shutdown to avoid leaks
if (!sThread) {
sThread = new SingletonThreadHolder(NS_LITERAL_CSTRING("mtransport"));
NS_DispatchToMainThread(mozilla::WrapRunnableNM(&ClearSingletonOnShutdown));
}
// Mark that we're using the shared thread and need it to stick around
sThread->AddUse();
return sThread->GetThread();
#else
static nsCOMPtr<nsIThread> sThread;
if (!sThread) {
(void) NS_NewNamedThread("mtransport", getter_AddRefs(sThread));
}
return sThread;
#endif
}
// IUDPSocketInternal interfaces
// callback while error happened in UDP socket operation
NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &message,
const nsACString &filename,
uint32_t line_number) {
NS_IMETHODIMP NrUdpSocketIpc::CallListenerError(const nsACString &message,
const nsACString &filename,
uint32_t line_number) {
ASSERT_ON_THREAD(io_thread_);
r_log(LOG_GENERIC, LOG_ERR, "UDP socket error:%s at %s:%d",
@@ -1020,10 +1086,10 @@ NS_IMETHODIMP NrSocketIpc::CallListenerError(const nsACString &message,
}
// callback while receiving UDP packet
NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &host,
uint16_t port,
const uint8_t *data,
uint32_t data_length) {
NS_IMETHODIMP NrUdpSocketIpc::CallListenerReceivedData(const nsACString &host,
uint16_t port,
const uint8_t *data,
uint32_t data_length) {
ASSERT_ON_THREAD(io_thread_);
PRNetAddr addr;
@@ -1050,15 +1116,15 @@ NS_IMETHODIMP NrSocketIpc::CallListenerReceivedData(const nsACString &host,
RefPtr<nr_udp_message> msg(new nr_udp_message(addr, buf));
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
&NrSocketIpc::recv_callback_s,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::recv_callback_s,
msg),
NS_DISPATCH_NORMAL);
return NS_OK;
}
// callback while UDP socket is opened
NS_IMETHODIMP NrSocketIpc::CallListenerOpened() {
NS_IMETHODIMP NrUdpSocketIpc::CallListenerOpened() {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
@@ -1112,7 +1178,7 @@ NS_IMETHODIMP NrSocketIpc::CallListenerOpened() {
}
// callback while UDP socket is closed
NS_IMETHODIMP NrSocketIpc::CallListenerClosed() {
NS_IMETHODIMP NrUdpSocketIpc::CallListenerClosed() {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
@@ -1123,8 +1189,10 @@ NS_IMETHODIMP NrSocketIpc::CallListenerClosed() {
return NS_OK;
}
// nr_socket public APIs
int NrSocketIpc::create(nr_transport_addr *addr) {
//
// NrSocketBase methods.
//
int NrUdpSocketIpc::create(nr_transport_addr *addr) {
ASSERT_ON_THREAD(sts_thread_);
int r, _status;
@@ -1138,12 +1206,6 @@ int NrSocketIpc::create(nr_transport_addr *addr) {
ABORT(R_INTERNAL);
}
// Bug 950660: Remote TCP socket is not supported yet.
if (NS_WARN_IF(addr->protocol != IPPROTO_UDP)) {
MOZ_ASSERT(false, "NrSocket over TCP is not e10s ready, see Bug 950660");
ABORT(R_INTERNAL);
}
sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Failed to get STS thread");
@@ -1154,7 +1216,7 @@ int NrSocketIpc::create(nr_transport_addr *addr) {
ABORT(r);
}
// wildcard address will be resolved at NrSocketIpc::CallListenerVoid
// wildcard address will be resolved at NrUdpSocketIpc::CallListenerVoid
if ((r=nr_transport_addr_copy(&my_addr_, addr))) {
ABORT(r);
}
@@ -1162,8 +1224,8 @@ int NrSocketIpc::create(nr_transport_addr *addr) {
state_ = NR_CONNECTING;
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
&NrSocketIpc::create_i,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::create_i,
host, static_cast<uint16_t>(port)),
NS_DISPATCH_NORMAL);
@@ -1181,7 +1243,7 @@ abort:
return(_status);
}
int NrSocketIpc::sendto(const void *msg, size_t len, int flags,
int NrUdpSocketIpc::sendto(const void *msg, size_t len, int flags,
nr_transport_addr *to) {
ASSERT_ON_THREAD(sts_thread_);
@@ -1205,22 +1267,22 @@ int NrSocketIpc::sendto(const void *msg, size_t len, int flags,
nsAutoPtr<DataBuffer> buf(new DataBuffer(static_cast<const uint8_t*>(msg), len));
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
&NrSocketIpc::sendto_i,
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::sendto_i,
addr, buf),
NS_DISPATCH_NORMAL);
return 0;
}
void NrSocketIpc::close() {
void NrUdpSocketIpc::close() {
ASSERT_ON_THREAD(sts_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
state_ = NR_CLOSING;
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrSocketIpc>(this),
&NrSocketIpc::close_i),
mozilla::WrapRunnable(RefPtr<NrUdpSocketIpc>(this),
&NrUdpSocketIpc::close_i),
NS_DISPATCH_NORMAL);
//remove all enqueued messages
@@ -1228,7 +1290,7 @@ void NrSocketIpc::close() {
std::swap(received_msgs_, empty);
}
int NrSocketIpc::recvfrom(void *buf, size_t maxlen, size_t *len, int flags,
int NrUdpSocketIpc::recvfrom(void *buf, size_t maxlen, size_t *len, int flags,
nr_transport_addr *from) {
ASSERT_ON_THREAD(sts_thread_);
@@ -1272,7 +1334,7 @@ abort:
return(_status);
}
int NrSocketIpc::getaddr(nr_transport_addr *addrp) {
int NrUdpSocketIpc::getaddr(nr_transport_addr *addrp) {
ASSERT_ON_THREAD(sts_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
@@ -1284,38 +1346,39 @@ int NrSocketIpc::getaddr(nr_transport_addr *addrp) {
return nr_transport_addr_copy(addrp, &my_addr_);
}
int NrSocketIpc::connect(nr_transport_addr *addr) {
int NrUdpSocketIpc::connect(nr_transport_addr *addr) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrSocketIpc::write(const void *msg, size_t len, size_t *written) {
int NrUdpSocketIpc::write(const void *msg, size_t len, size_t *written) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
int NrUdpSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrSocketIpc::listen(int backlog) {
int NrUdpSocketIpc::listen(int backlog) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) {
int NrUdpSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
// IO thread executors
void NrSocketIpc::create_i(const nsACString &host, const uint16_t port) {
void NrUdpSocketIpc::create_i(const nsACString &host, const uint16_t port) {
ASSERT_ON_THREAD(io_thread_);
nsresult rv;
nsCOMPtr<nsIUDPSocketChild> socketChild = do_CreateInstance("@mozilla.org/udp-socket-child;1", &rv);
if (NS_FAILED(rv)) {
ReentrantMonitorAutoEnter mon(monitor_);
err_ = true;
MOZ_ASSERT(false, "Failed to create UDPSocketChild");
return;
@@ -1332,7 +1395,7 @@ void NrSocketIpc::create_i(const nsACString &host, const uint16_t port) {
socketChild = nullptr;
}
RefPtr<NrSocketIpcProxy> proxy(new NrSocketIpcProxy);
RefPtr<NrUdpSocketIpcProxy> proxy(new NrUdpSocketIpcProxy);
rv = proxy->Init(this);
if (NS_FAILED(rv)) {
err_ = true;
@@ -1351,17 +1414,16 @@ void NrSocketIpc::create_i(const nsACString &host, const uint16_t port) {
}
}
void NrSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
void NrUdpSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf) {
ASSERT_ON_THREAD(io_thread_);
ReentrantMonitorAutoEnter mon(monitor_);
if (!socket_child_) {
MOZ_ASSERT(false);
err_ = true;
return;
}
ReentrantMonitorAutoEnter mon(monitor_);
if (NS_FAILED(socket_child_->SendWithAddress(&addr,
buf->data(),
buf->len()))) {
@@ -1369,7 +1431,7 @@ void NrSocketIpc::sendto_i(const net::NetAddr &addr, nsAutoPtr<DataBuffer> buf)
}
}
void NrSocketIpc::close_i() {
void NrUdpSocketIpc::close_i() {
ASSERT_ON_THREAD(io_thread_);
if (socket_child_) {
@@ -1381,8 +1443,8 @@ void NrSocketIpc::close_i() {
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
// close(), but transfer the socket_child_ reference to die as well
// static
void NrSocketIpc::release_child_i(nsIUDPSocketChild* aChild,
nsCOMPtr<nsIEventTarget> sts_thread) {
void NrUdpSocketIpc::release_child_i(nsIUDPSocketChild* aChild,
nsCOMPtr<nsIEventTarget> sts_thread) {
RefPtr<nsIUDPSocketChild> socket_child_ref =
already_AddRefed<nsIUDPSocketChild>(aChild);
if (socket_child_ref) {
@@ -1390,16 +1452,16 @@ void NrSocketIpc::release_child_i(nsIUDPSocketChild* aChild,
}
// Tell SingletonThreadHolder we're done with it
RUN_ON_THREAD(sts_thread,
mozilla::WrapRunnableNM(&NrSocketIpc::release_use_s),
mozilla::WrapRunnableNM(&NrUdpSocketIpc::release_use_s),
NS_DISPATCH_NORMAL);
}
void NrSocketIpc::release_use_s() {
void NrUdpSocketIpc::release_use_s() {
sThread->ReleaseUse();
}
#endif
void NrSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) {
void NrUdpSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) {
ASSERT_ON_THREAD(sts_thread_);
{
@@ -1417,6 +1479,448 @@ void NrSocketIpc::recv_callback_s(RefPtr<nr_udp_message> msg) {
}
}
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
// TCPSocket.
class NrTcpSocketIpc::TcpSocketReadyRunner: public nsRunnable
{
public:
explicit TcpSocketReadyRunner(NrTcpSocketIpc *sck)
: socket_(sck) {}
NS_IMETHODIMP Run() {
socket_->maybe_post_socket_ready();
return NS_OK;
}
private:
RefPtr<NrTcpSocketIpc> socket_;
};
NS_IMPL_ISUPPORTS(NrTcpSocketIpc,
nsITCPSocketCallback)
NrTcpSocketIpc::NrTcpSocketIpc(nsIThread* aThread)
: NrSocketIpc(static_cast<nsIEventTarget*>(aThread)),
mirror_state_(NR_INIT),
state_(NR_INIT),
buffered_bytes_(0),
tracking_number_(0) {
}
NrTcpSocketIpc::~NrTcpSocketIpc()
{
// also guarantees socket_child_ is released from the io_thread
// close(), but transfer the socket_child_ reference to die as well
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnableNM(&NrTcpSocketIpc::release_child_i,
socket_child_.forget().take(),
sts_thread_),
NS_DISPATCH_NORMAL);
}
//
// nsITCPSocketCallback methods
//
NS_IMETHODIMP NrTcpSocketIpc::UpdateReadyState(uint32_t aReadyState) {
NrSocketIpcState temp = NR_INIT;
switch (static_cast<dom::TCPReadyState>(aReadyState)) {
case dom::TCPReadyState::Connecting:
temp = NR_CONNECTING;
break;
case dom::TCPReadyState::Open:
temp = NR_CONNECTED;
break;
case dom::TCPReadyState::Closing:
temp = NR_CLOSING;
break;
case dom::TCPReadyState::Closed:
temp = NR_CLOSED;
break;
default:
MOZ_ASSERT(false, "Invalid ReadyState");
return NS_OK;
}
if (mirror_state_ != temp) {
mirror_state_ = temp;
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::update_state_s,
temp),
NS_DISPATCH_NORMAL);
}
return NS_OK;
}
NS_IMETHODIMP NrTcpSocketIpc::UpdateBufferedAmount(uint32_t buffered_amount,
uint32_t tracking_number) {
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::message_sent_s,
buffered_amount,
tracking_number),
NS_DISPATCH_NORMAL);
return NS_OK;
}
NS_IMETHODIMP NrTcpSocketIpc::FireDataArrayEvent(const nsAString& aType,
const InfallibleTArray<uint8_t>& buffer) {
// Called when we received data.
uint8_t *buf = const_cast<uint8_t*>(buffer.Elements());
nsAutoPtr<DataBuffer> data_buf(new DataBuffer(buf, buffer.Length()));
RefPtr<nr_tcp_message> msg = new nr_tcp_message(data_buf);
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::recv_message_s,
msg),
NS_DISPATCH_NORMAL);
return NS_OK;
}
NS_IMETHODIMP NrTcpSocketIpc::FireErrorEvent(const nsAString &type,
const nsAString &name) {
r_log(LOG_GENERIC, LOG_ERR,
"Error from TCPSocketChild: type: %s, name: %s",
NS_LossyConvertUTF16toASCII(type).get(), NS_LossyConvertUTF16toASCII(name).get());
socket_child_ = nullptr;
mirror_state_ = NR_CLOSED;
RUN_ON_THREAD(sts_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::update_state_s,
NR_CLOSED),
NS_DISPATCH_NORMAL);
return NS_OK;
}
// methods of nsITCPSocketCallback that we are not going to implement.
NS_IMETHODIMP NrTcpSocketIpc::FireDataEvent(JSContext* aCx,
const nsAString &type,
const JS::HandleValue data) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP NrTcpSocketIpc::FireDataStringEvent(const nsAString &type,
const nsACString &data) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP NrTcpSocketIpc::FireEvent(const nsAString &type) {
// XXX support type.mData == 'close' at least
return NS_ERROR_NOT_IMPLEMENTED;
}
//
// NrSocketBase methods.
//
int NrTcpSocketIpc::create(nr_transport_addr *addr) {
int r, _status;
nsresult rv;
int32_t port;
nsCString host;
if (state_ != NR_INIT) {
ABORT(R_INTERNAL);
}
sts_thread_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false, "Failed to get STS thread");
ABORT(R_INTERNAL);
}
// Sanity check
if ((r=nr_transport_addr_get_addrstring_and_port(addr, &host, &port))) {
ABORT(r);
}
if ((r=nr_transport_addr_copy(&my_addr_, addr))) {
ABORT(r);
}
_status = 0;
abort:
return(_status);
}
int NrTcpSocketIpc::sendto(const void *msg, size_t len,
int flags, nr_transport_addr *to) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrTcpSocketIpc::recvfrom(void * buf, size_t maxlen,
size_t *len, int flags,
nr_transport_addr *from) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrTcpSocketIpc::getaddr(nr_transport_addr *addrp) {
ASSERT_ON_THREAD(sts_thread_);
return nr_transport_addr_copy(addrp, &my_addr_);
}
void NrTcpSocketIpc::close() {
ASSERT_ON_THREAD(sts_thread_);
if (state_ == NR_CLOSED || state_ == NR_CLOSING) {
return;
}
state_ = NR_CLOSING;
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::close_i),
NS_DISPATCH_NORMAL);
//remove all enqueued messages
std::queue<RefPtr<nr_tcp_message>> empty;
std::swap(msg_queue_, empty);
}
int NrTcpSocketIpc::connect(nr_transport_addr *addr) {
nsCString remote_addr, local_addr;
int32_t remote_port, local_port;
int r, _status;
if ((r=nr_transport_addr_get_addrstring_and_port(addr,
&remote_addr,
&remote_port))) {
ABORT(r);
}
if ((r=nr_transport_addr_get_addrstring_and_port(&my_addr_,
&local_addr,
&local_port))) {
MOZ_ASSERT(false); // shouldn't fail as it was sanity-checked in ::create()
ABORT(r);
}
state_ = mirror_state_ = NR_CONNECTING;
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::connect_i,
remote_addr,
static_cast<uint16_t>(remote_port),
local_addr,
static_cast<uint16_t>(local_port)),
NS_DISPATCH_NORMAL);
// Make caller wait for ready to write.
_status = R_WOULDBLOCK;
abort:
return _status;
}
int NrTcpSocketIpc::write(const void *msg, size_t len, size_t *written) {
ASSERT_ON_THREAD(sts_thread_);
int _status = 0;
if (state_ != NR_CONNECTED) {
ABORT(R_FAILED);
}
if (buffered_bytes_ + len >= nsITCPSocketCallback::BUFFER_SIZE) {
ABORT(R_WOULDBLOCK);
}
buffered_bytes_ += len;
{
InfallibleTArray<uint8_t>* arr = new InfallibleTArray<uint8_t>();
arr->AppendElements(static_cast<const uint8_t*>(msg), len);
// keep track of un-acknowleged writes by tracking number.
writes_in_flight_.push_back(len);
RUN_ON_THREAD(io_thread_,
mozilla::WrapRunnable(RefPtr<NrTcpSocketIpc>(this),
&NrTcpSocketIpc::write_i,
nsAutoPtr<InfallibleTArray<uint8_t>>(arr),
++tracking_number_),
NS_DISPATCH_NORMAL);
}
*written = len;
abort:
return _status;
}
int NrTcpSocketIpc::read(void* buf, size_t maxlen, size_t *len) {
int _status = 0;
if (state_ != NR_CONNECTED) {
ABORT(R_FAILED);
}
if (msg_queue_.size() == 0) {
ABORT(R_WOULDBLOCK);
}
{
RefPtr<nr_tcp_message> msg(msg_queue_.front());
size_t consumed_len = std::min(maxlen, msg->unread_bytes());
memcpy(buf, msg->reading_pointer(), consumed_len);
if (consumed_len < msg->unread_bytes()) {
// There is still something left in buffer.
msg->read_bytes += consumed_len;
} else {
msg_queue_.pop();
}
*len = consumed_len;
}
abort:
return _status;
}
int NrTcpSocketIpc::listen(int backlog) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
int NrTcpSocketIpc::accept(nr_transport_addr *addrp, nr_socket **sockp) {
MOZ_ASSERT(false);
return R_INTERNAL;
}
void NrTcpSocketIpc::connect_i(const nsACString &remote_addr,
uint16_t remote_port,
const nsACString &local_addr,
uint16_t local_port) {
ASSERT_ON_THREAD(io_thread_);
mirror_state_ = NR_CONNECTING;
dom::TCPSocketChild* child = new dom::TCPSocketChild(NS_ConvertUTF8toUTF16(remote_addr), remote_port);
socket_child_ = child;
// XXX remove remote!
socket_child_->SendWindowlessOpenBind(this,
remote_addr, remote_port,
local_addr, local_port,
/* use ssl */ false);
}
void NrTcpSocketIpc::write_i(nsAutoPtr<InfallibleTArray<uint8_t>> arr,
uint32_t tracking_number) {
ASSERT_ON_THREAD(io_thread_);
if (!socket_child_) {
return;
}
socket_child_->SendSendArray(*arr, tracking_number);
}
void NrTcpSocketIpc::close_i() {
ASSERT_ON_THREAD(io_thread_);
mirror_state_ = NR_CLOSING;
if (!socket_child_) {
return;
}
socket_child_->SendClose();
}
// close(), but transfer the socket_child_ reference to die as well
// static
void NrTcpSocketIpc::release_child_i(dom::TCPSocketChild* aChild,
nsCOMPtr<nsIEventTarget> sts_thread) {
RefPtr<dom::TCPSocketChild> socket_child_ref =
already_AddRefed<dom::TCPSocketChild>(aChild);
if (socket_child_ref) {
socket_child_ref->SendClose();
}
// io_thread_ is MainThread, so no use to release
}
void NrTcpSocketIpc::message_sent_s(uint32_t buffered_amount,
uint32_t tracking_number) {
ASSERT_ON_THREAD(sts_thread_);
size_t num_unacked_writes = tracking_number_ - tracking_number;
while (writes_in_flight_.size() > num_unacked_writes) {
writes_in_flight_.pop_front();
}
for (size_t unacked_write_len : writes_in_flight_) {
buffered_amount += unacked_write_len;
}
r_log(LOG_GENERIC, LOG_ERR,
"UpdateBufferedAmount: (tracking %u): %u, waiting: %s",
tracking_number, buffered_amount,
(poll_flags() & PR_POLL_WRITE) ? "yes" : "no");
buffered_bytes_ = buffered_amount;
maybe_post_socket_ready();
}
void NrTcpSocketIpc::recv_message_s(nr_tcp_message *msg) {
ASSERT_ON_THREAD(sts_thread_);
msg_queue_.push(msg);
maybe_post_socket_ready();
}
void NrTcpSocketIpc::update_state_s(NrSocketIpcState next_state) {
ASSERT_ON_THREAD(sts_thread_);
// only allow valid transitions
switch (state_) {
case NR_CONNECTING:
if (next_state == NR_CONNECTED) {
state_ = NR_CONNECTED;
maybe_post_socket_ready();
} else {
state_ = next_state; // all states are valid from CONNECTING
}
break;
case NR_CONNECTED:
if (next_state != NR_CONNECTING) {
state_ = next_state;
}
break;
case NR_CLOSING:
if (next_state == NR_CLOSED) {
state_ = next_state;
}
break;
case NR_CLOSED:
break;
default:
MOZ_CRASH("update_state_s while in illegal state");
}
}
void NrTcpSocketIpc::maybe_post_socket_ready() {
bool has_event = false;
if (state_ == NR_CONNECTED) {
if (poll_flags() & PR_POLL_WRITE) {
// This effectively polls via the event loop until the
// NR_ASYNC_WAIT_WRITE is no longer armed.
if (buffered_bytes_ < nsITCPSocketCallback::BUFFER_SIZE) {
r_log(LOG_GENERIC, LOG_INFO, "Firing write callback (%u)",
(uint32_t)buffered_bytes_);
fire_callback(NR_ASYNC_WAIT_WRITE);
has_event = true;
}
}
if (poll_flags() & PR_POLL_READ) {
if (msg_queue_.size()) {
r_log(LOG_GENERIC, LOG_INFO, "Firing read callback (%u)",
(uint32_t)msg_queue_.size());
fire_callback(NR_ASYNC_WAIT_READ);
has_event = true;
}
}
}
// If any event has been posted, we post a runnable to see
// if the events have to be posted again.
if (has_event) {
RefPtr<TcpSocketReadyRunner> runnable = new TcpSocketReadyRunner(this);
NS_DispatchToCurrentThread(runnable);
}
}
#endif
} // close namespace
@@ -1457,16 +1961,30 @@ static nr_socket_vtbl nr_socket_local_vtbl={
int nr_socket_local_create(void *obj, nr_transport_addr *addr, nr_socket **sockp) {
RefPtr<NrSocketBase> sock;
int r, _status;
// create IPC bridge for content process
if (XRE_IsParentProcess()) {
sock = new NrSocket();
} else {
sock = new NrSocketIpc();
switch (addr->protocol) {
case IPPROTO_UDP:
sock = new NrUdpSocketIpc();
break;
case IPPROTO_TCP:
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
{
nsCOMPtr<nsIThread> main_thread;
NS_GetMainThread(getter_AddRefs(main_thread));
sock = new NrTcpSocketIpc(main_thread.get());
}
#else
ABORT(R_REJECTED);
#endif
break;
}
}
int r, _status;
r = sock->create(addr);
if (r)
ABORT(r);
+122 -14
View File
@@ -61,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsITCPSocketCallback.h"
#include "databuffer.h"
#include "m_cpp_utils.h"
#include "mozilla/ReentrantMonitor.h"
@@ -72,6 +73,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
typedef struct nr_socket_vtbl_ nr_socket_vtbl;
typedef struct nr_socket_ nr_socket;
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
namespace mozilla {
namespace dom {
class TCPSocketChild;
}
}
#endif
namespace mozilla {
namespace net {
@@ -209,7 +218,22 @@ public:
NR_CLOSED,
};
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrSocketIpc)
NrSocketIpc(nsIEventTarget* aThread);
protected:
nsCOMPtr<nsIEventTarget> sts_thread_;
// Note: for UDP PBackground, this is a thread held by SingletonThreadHolder.
// For TCP PNecko, this is MainThread (and TCPSocket requires MainThread currently)
const nsCOMPtr<nsIEventTarget> io_thread_;
virtual ~NrSocketIpc() {};
private:
DISALLOW_COPY_ASSIGN(NrSocketIpc);
};
class NrUdpSocketIpc : public NrSocketIpc {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrUdpSocketIpc, override)
NS_IMETHODIMP CallListenerError(const nsACString &message,
const nsACString &filename,
@@ -221,7 +245,7 @@ public:
NS_IMETHODIMP CallListenerOpened();
NS_IMETHODIMP CallListenerClosed();
NrSocketIpc();
NrUdpSocketIpc();
// Implementations of the NrSocketBase APIs
virtual int create(nr_transport_addr *addr) override;
@@ -239,11 +263,9 @@ public:
virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
private:
virtual ~NrSocketIpc();
virtual ~NrUdpSocketIpc();
DISALLOW_COPY_ASSIGN(NrSocketIpc);
static nsIThread* GetIOThreadAndAddUse_s();
DISALLOW_COPY_ASSIGN(NrUdpSocketIpc);
// Main or private thread executors of the NrSocketBase APIs
void create_i(const nsACString &host, const uint16_t port);
@@ -256,32 +278,118 @@ private:
// STS thread executor
void recv_callback_s(RefPtr<nr_udp_message> msg);
ReentrantMonitor monitor_; // protects err_and state_
bool err_;
NrSocketIpcState state_;
std::queue<RefPtr<nr_udp_message> > received_msgs_;
std::queue<RefPtr<nr_udp_message>> received_msgs_;
RefPtr<nsIUDPSocketChild> socket_child_; // only accessed from the io_thread
nsCOMPtr<nsIEventTarget> sts_thread_;
const nsCOMPtr<nsIEventTarget> io_thread_;
ReentrantMonitor monitor_;
};
// The socket child holds onto one of these, which just passes callbacks
// through and makes sure the ref to the NrSocketIpc is released on STS.
class NrSocketIpcProxy : public nsIUDPSocketInternal {
class NrUdpSocketIpcProxy : public nsIUDPSocketInternal {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIUDPSOCKETINTERNAL
nsresult Init(const RefPtr<NrSocketIpc>& socket);
nsresult Init(const RefPtr<NrUdpSocketIpc>& socket);
private:
virtual ~NrSocketIpcProxy();
virtual ~NrUdpSocketIpcProxy();
RefPtr<NrSocketIpc> socket_;
RefPtr<NrUdpSocketIpc> socket_;
nsCOMPtr<nsIEventTarget> sts_thread_;
};
struct nr_tcp_message {
explicit nr_tcp_message(nsAutoPtr<DataBuffer> &data)
: read_bytes(0)
, data(data) {
}
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nr_tcp_message);
const uint8_t *reading_pointer() const {
return data->data() + read_bytes;
}
size_t unread_bytes() const {
return data->len() - read_bytes;
}
size_t read_bytes;
private:
~nr_tcp_message() {}
DISALLOW_COPY_ASSIGN(nr_tcp_message);
nsAutoPtr<DataBuffer> data;
};
#if defined(MOZILLA_INTERNAL_API) && !defined(MOZILLA_XPCOMRT_API)
class NrTcpSocketIpc : public NrSocketIpc,
public nsITCPSocketCallback {
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITCPSOCKETCALLBACK
explicit NrTcpSocketIpc(nsIThread* aThread);
// Implementations of the NrSocketBase APIs
virtual int create(nr_transport_addr *addr) override;
virtual int sendto(const void *msg, size_t len,
int flags, nr_transport_addr *to) override;
virtual int recvfrom(void * buf, size_t maxlen,
size_t *len, int flags,
nr_transport_addr *from) override;
virtual int getaddr(nr_transport_addr *addrp) override;
virtual void close() override;
virtual int connect(nr_transport_addr *addr) override;
virtual int write(const void *msg, size_t len, size_t *written) override;
virtual int read(void* buf, size_t maxlen, size_t *len) override;
virtual int listen(int backlog) override;
virtual int accept(nr_transport_addr *addrp, nr_socket **sockp) override;
private:
class TcpSocketReadyRunner;
DISALLOW_COPY_ASSIGN(NrTcpSocketIpc);
virtual ~NrTcpSocketIpc();
// Main thread executors of the NrSocketBase APIs
void connect_i(const nsACString &remote_addr,
uint16_t remote_port,
const nsACString &local_addr,
uint16_t local_port);
void write_i(nsAutoPtr<InfallibleTArray<uint8_t>> buf,
uint32_t tracking_number);
void close_i();
static void release_child_i(dom::TCPSocketChild* aChild, nsCOMPtr<nsIEventTarget> ststhread);
// STS thread executor
void message_sent_s(uint32_t bufferedAmount, uint32_t tracking_number);
void recv_message_s(nr_tcp_message *msg);
void update_state_s(NrSocketIpcState next_state);
void maybe_post_socket_ready();
// Accessed from UpdateReadyState (not sts_thread) to avoid sending
// runnables when not needed
NrSocketIpcState mirror_state_;
// variables that can only be accessed on STS.
NrSocketIpcState state_;
std::queue<RefPtr<nr_tcp_message>> msg_queue_;
uint32_t buffered_bytes_;
uint32_t tracking_number_;
std::deque<size_t> writes_in_flight_;
// main thread.
RefPtr<dom::TCPSocketChild> socket_child_;
};
#endif
int nr_netaddr_to_transport_addr(const net::NetAddr *netaddr,
nr_transport_addr *addr,
int protocol);
+25 -34
View File
@@ -380,13 +380,12 @@ void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx,
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
bool offerer,
bool set_interface_priorities,
bool allow_loopback,
bool tcp_enabled,
bool allow_link_local,
bool hide_non_default,
Policy policy) {
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);
RefPtr<NrIceCtx> ctx = new NrIceCtx(name, offerer, policy);
// Initialize the crypto callbacks and logging stuff
if (!initialized) {
@@ -406,37 +405,11 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_HOST_TCP, 125);
NR_reg_set_uchar((char *)NR_ICE_REG_PREF_TYPE_RELAYED_TCP, 0);
if (set_interface_priorities) {
NR_reg_set_uchar((char *)"ice.pref.interface.rl0", 255);
NR_reg_set_uchar((char *)"ice.pref.interface.wi0", 254);
NR_reg_set_uchar((char *)"ice.pref.interface.lo0", 253);
NR_reg_set_uchar((char *)"ice.pref.interface.en1", 252);
NR_reg_set_uchar((char *)"ice.pref.interface.en0", 251);
NR_reg_set_uchar((char *)"ice.pref.interface.eth0", 252);
NR_reg_set_uchar((char *)"ice.pref.interface.eth1", 251);
NR_reg_set_uchar((char *)"ice.pref.interface.eth2", 249);
NR_reg_set_uchar((char *)"ice.pref.interface.ppp", 250);
NR_reg_set_uchar((char *)"ice.pref.interface.ppp0", 249);
NR_reg_set_uchar((char *)"ice.pref.interface.en2", 248);
NR_reg_set_uchar((char *)"ice.pref.interface.en3", 247);
NR_reg_set_uchar((char *)"ice.pref.interface.em0", 251);
NR_reg_set_uchar((char *)"ice.pref.interface.em1", 252);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet0", 240);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet1", 241);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet3", 239);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet4", 238);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet5", 237);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet6", 236);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet7", 235);
NR_reg_set_uchar((char *)"ice.pref.interface.vmnet8", 234);
NR_reg_set_uchar((char *)"ice.pref.interface.virbr0", 233);
NR_reg_set_uchar((char *)"ice.pref.interface.wlan0", 232);
}
int32_t stun_client_maximum_transmits = 7;
int32_t ice_trickle_grace_period = 5000;
int32_t ice_tcp_so_sock_count = 3;
int32_t ice_tcp_listen_backlog = 10;
nsAutoCString force_net_interface;
#ifndef MOZILLA_XPCOMRT_API
nsresult res;
nsCOMPtr<nsIPrefService> prefs =
@@ -457,6 +430,9 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
branch->GetIntPref(
"media.peerconnection.ice.tcp_listen_backlog",
&ice_tcp_listen_backlog);
branch->GetCharPref(
"media.peerconnection.ice.force_interface",
getter_Copies(force_net_interface));
}
}
#endif
@@ -466,8 +442,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
ice_trickle_grace_period);
NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
ice_tcp_so_sock_count);
NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_SO_SOCK_COUNT,
ice_tcp_so_sock_count);
NR_reg_set_int4((char *)NR_ICE_REG_ICE_TCP_LISTEN_BACKLOG,
ice_tcp_listen_backlog);
@@ -480,6 +454,11 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
if (allow_link_local) {
NR_reg_set_char((char *)NR_STUN_REG_PREF_ALLOW_LINK_LOCAL_ADDRS, 1);
}
if (force_net_interface.Length() > 0) {
// Stupid cast.... but needed
const nsCString& flat = PromiseFlatCString(static_cast<nsACString&>(force_net_interface));
NR_reg_set_string((char *)NR_ICE_REG_PREF_FORCE_INTERFACE_NAME, const_cast<char*>(flat.get()));
}
}
// Create the ICE context
@@ -488,6 +467,12 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
UINT4 flags = offerer ? NR_ICE_CTX_FLAGS_OFFERER:
NR_ICE_CTX_FLAGS_ANSWERER;
flags |= NR_ICE_CTX_FLAGS_AGGRESSIVE_NOMINATION;
if (policy == ICE_POLICY_RELAY) {
flags |= NR_ICE_CTX_FLAGS_RELAY_ONLY;
}
if (hide_non_default)
flags |= NR_ICE_CTX_FLAGS_ONLY_DEFAULT_ADDRS;
r = nr_ice_ctx_create(const_cast<char *>(name.c_str()), flags,
&ctx->ctx_);
@@ -496,7 +481,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
return nullptr;
}
#ifdef USE_INTERFACE_PRIORITIZER
nr_interface_prioritizer *prioritizer = CreateInterfacePrioritizer();
if (!prioritizer) {
MOZ_MTLOG(LogLevel::Error, "Couldn't create interface prioritizer.");
@@ -508,7 +492,6 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
MOZ_MTLOG(LogLevel::Error, "Couldn't set interface prioritizer.");
return nullptr;
}
#endif // USE_INTERFACE_PRIORITIZER
if (ctx->generating_trickle()) {
r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx);
@@ -727,6 +710,9 @@ abort:
nsresult NrIceCtx::StartGathering() {
ASSERT_ON_THREAD(sts_target_);
if (policy_ == ICE_POLICY_NONE) {
return NS_OK;
}
SetGatheringState(ICE_CTX_GATHER_STARTED);
// This might start gathering for the first time, or again after
// renegotiation, or might do nothing at all if gathering has already
@@ -801,6 +787,11 @@ nsresult NrIceCtx::ParseGlobalAttributes(std::vector<std::string> attrs) {
nsresult NrIceCtx::StartChecks() {
int r;
if (policy_ == ICE_POLICY_NONE) {
MOZ_MTLOG(ML_ERROR, "Couldn't start peer checks because policy == none");
SetConnectionState(ICE_CTX_FAILED);
return NS_ERROR_FAILURE;
}
r=nr_ice_peer_ctx_pair_candidates(peer_);
if (r) {
MOZ_MTLOG(ML_ERROR, "Couldn't pair candidates on "
+2 -1
View File
@@ -213,12 +213,13 @@ class NrIceCtx {
ICE_POLICY_ALL
};
// TODO(ekr@rtfm.com): Too many bools here. Bug 1193437.
static RefPtr<NrIceCtx> Create(const std::string& name,
bool offerer,
bool set_interface_priorities = true,
bool allow_loopback = false,
bool tcp_enabled = true,
bool allow_link_local = false,
bool hide_non_default = false,
Policy policy = ICE_POLICY_ALL);
// Deinitialize all ICE global state. Used only for testing.
+31 -2
View File
@@ -307,15 +307,44 @@ nsresult NrIceMediaStream::GetCandidatePairs(std::vector<NrIceCandidatePair>*
return NS_ERROR_FAILURE;
}
nr_ice_cand_pair *p1;
nr_ice_cand_pair *p1, *p2;
out_pairs->clear();
TAILQ_FOREACH(p1, &peer_stream->check_list, entry) {
TAILQ_FOREACH(p1, &peer_stream->check_list, check_queue_entry) {
MOZ_ASSERT(p1);
MOZ_ASSERT(p1->local);
MOZ_ASSERT(p1->remote);
NrIceCandidatePair pair;
p2 = TAILQ_FIRST(&peer_stream->check_list);
while (p2) {
if (p1 == p2) {
/* Don't compare with our self. */
p2=TAILQ_NEXT(p2, check_queue_entry);
continue;
}
if (strncmp(p1->codeword,p2->codeword,sizeof(p1->codeword))==0) {
/* In case of duplicate pairs we only report the one winning pair */
if (
((p2->remote->component && (p2->remote->component->active == p2)) &&
!(p1->remote->component && (p1->remote->component->active == p1))) ||
((p2->peer_nominated || p2->nominated) &&
!(p1->peer_nominated || p1->nominated)) ||
(p2->priority > p1->priority) ||
((p2->state == NR_ICE_PAIR_STATE_SUCCEEDED) &&
(p1->state != NR_ICE_PAIR_STATE_SUCCEEDED))
) {
/* p2 is a better pair. */
break;
}
}
p2=TAILQ_NEXT(p2, check_queue_entry);
}
if (p2) {
/* p2 points to a duplicate but better pair so skip this one */
continue;
}
switch (p1->state) {
case NR_ICE_PAIR_STATE_FROZEN:
pair.state = NrIceCandidatePair::State::STATE_FROZEN;
+1 -1
View File
@@ -154,7 +154,7 @@ int NrIceResolver::resolve(nr_resolver_resource *resource,
if (resource->transport_protocol != IPPROTO_UDP &&
resource->transport_protocol != IPPROTO_TCP) {
MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are is supported.");
MOZ_MTLOG(ML_ERROR, "Only UDP and TCP are supported.");
ABORT(R_NOT_FOUND);
}
pr = new PendingResolution(sts_thread_,
+4 -4
View File
@@ -71,6 +71,10 @@ class NrIceResolver
void DestroyResolver();
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceResolver)
int resolve(nr_resolver_resource *resource,
int (*cb)(void *cb_arg, nr_transport_addr *addr),
void *cb_arg, void **handle);
private:
// Implementations of vtbl functions
static int destroy(void **objp);
@@ -80,10 +84,6 @@ class NrIceResolver
static void resolve_cb(NR_SOCKET s, int how, void *cb_arg);
static int cancel(void *obj, void *handle);
int resolve(nr_resolver_resource *resource,
int (*cb)(void *cb_arg, nr_transport_addr *addr),
void *cb_arg, void **handle);
class PendingResolution : public nsIDNSListener
{
public:
+75 -4
View File
@@ -1,9 +1,11 @@
/* 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 <algorithm>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "logging.h"
#include "nrinterfaceprioritizer.h"
#include "nsCOMPtr.h"
@@ -15,20 +17,32 @@ namespace {
class LocalAddress {
public:
LocalAddress()
: key_(),
: ifname_(),
addr_(),
key_(),
is_vpn_(-1),
estimated_speed_(-1),
type_preference_(-1),
ip_version_(-1) {}
bool Init(const nr_local_addr& local_addr) {
ifname_ = local_addr.addr.ifname;
char buf[MAXIFNAME + 41];
int r = nr_transport_addr_fmt_ifname_addr_string(&local_addr.addr, buf, sizeof(buf));
if (r) {
MOZ_MTLOG(ML_ERROR, "Error formatting interface address string.");
MOZ_MTLOG(ML_ERROR, "Error formatting interface key.");
return false;
}
key_ = buf;
r = nr_transport_addr_get_addrstring(&local_addr.addr, buf, sizeof(buf));
if (r) {
MOZ_MTLOG(ML_ERROR, "Error formatting address string.");
return false;
}
addr_ = buf;
is_vpn_ = (local_addr.interface.type & NR_INTERFACE_TYPE_VPN) != 0 ? 1 : 0;
estimated_speed_ = local_addr.interface.estimated_speed;
type_preference_ = GetNetworkTypePreference(local_addr.interface.type);
@@ -56,13 +70,28 @@ public:
return estimated_speed_ > rhs.estimated_speed_;
}
// See if our hard-coded pref list helps us.
auto thisindex = std::find(interface_preference_list().begin(),
interface_preference_list().end(),
ifname_);
auto rhsindex = std::find(interface_preference_list().begin(),
interface_preference_list().end(),
rhs.ifname_);
if (thisindex != rhsindex) {
return thisindex < rhsindex;
}
// Prefer IPV6 over IPV4
if (ip_version_ != rhs.ip_version_) {
return ip_version_ > rhs.ip_version_;
}
// All things above are the same, we can at least sort with key.
return key_ < rhs.key_;
// Now we start getting into arbitrary stuff
if (ifname_ != rhs.ifname_) {
return ifname_ < rhs.ifname_;
}
return addr_ < rhs.addr_;
}
const std::string& GetKey() const {
@@ -85,6 +114,48 @@ private:
return 4;
}
// TODO(bug 895790): Once we can get useful interface properties on Darwin,
// we should remove this stuff.
static const std::vector<std::string>& interface_preference_list()
{
static std::vector<std::string> list(build_interface_preference_list());
return list;
}
static std::vector<std::string> build_interface_preference_list()
{
std::vector<std::string> result;
result.push_back("rl0");
result.push_back("wi0");
result.push_back("en0");
result.push_back("enp2s0");
result.push_back("enp3s0");
result.push_back("en1");
result.push_back("en2");
result.push_back("en3");
result.push_back("eth0");
result.push_back("eth1");
result.push_back("eth2");
result.push_back("em1");
result.push_back("em0");
result.push_back("ppp");
result.push_back("ppp0");
result.push_back("vmnet1");
result.push_back("vmnet0");
result.push_back("vmnet3");
result.push_back("vmnet4");
result.push_back("vmnet5");
result.push_back("vmnet6");
result.push_back("vmnet7");
result.push_back("vmnet8");
result.push_back("virbr0");
result.push_back("wlan0");
result.push_back("lo0");
return result;
}
std::string ifname_;
std::string addr_;
std::string key_;
int is_vpn_;
int estimated_speed_;
+1
View File
@@ -7,6 +7,7 @@
Library('mtransport_standalone')
include('../common.build')
include("/ipc/chromium/chromium-config.mozbuild")
# These files cannot be built in unified mode because of the redefinition of
# getLogModule, UNIMPLEMENTED, nr_socket_long_term_violation_time,

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