diff options
| author | Vladimir Druzenko <vvd@FreeBSD.org> | 2024-07-09 00:36:36 +0000 |
|---|---|---|
| committer | Vladimir Druzenko <vvd@FreeBSD.org> | 2024-07-09 01:07:24 +0000 |
| commit | 3bc831e5ab010280176c17ed8788d040b0bb3201 (patch) | |
| tree | 4abffda6fa5662fb5064b0248812c385e444ae41 | |
| parent | 8abc2496a2a419868f223f13b08691f04acb082f (diff) | |
www/waterfox: resurect removed port before update to new release
This reverts commit 8bbfbba74e2ee5df4b64cbc639847d6419160f67.
PR: 278672
334 files changed, 43550 insertions, 0 deletions
diff --git a/www/Makefile b/www/Makefile index 62750f6b48b6..2e5fefc609a5 100644 --- a/www/Makefile +++ b/www/Makefile @@ -2459,6 +2459,7 @@ SUBDIR += w3mir SUBDIR += wabt SUBDIR += wasm-pack + SUBDIR += waterfox SUBDIR += web2ldap SUBDIR += webalizer SUBDIR += webbrowser diff --git a/www/waterfox/Makefile b/www/waterfox/Makefile new file mode 100644 index 000000000000..4afa9bb2ce3f --- /dev/null +++ b/www/waterfox/Makefile @@ -0,0 +1,77 @@ +# $FreeBSD$ + +PORTNAME= waterfox +DISTVERSION= 56.2.3 +PORTREVISION= 2 +CATEGORIES= www ipv6 + +MAINTAINER= jbeich@FreeBSD.org +COMMENT= Distilled fork of Firefox + +DEPRECATED= Temporary experiment +EXPIRATION_DATE=2018-09-27 + +BUILD_DEPENDS= nspr>=4.16:devel/nspr \ + nss>=3.32.1:security/nss \ + icu>=59.1,1:devel/icu \ + libevent>=2.1.8:devel/libevent \ + harfbuzz>=1.4.7:print/harfbuzz \ + graphite2>=1.3.10:graphics/graphite2 \ + png>=1.6.31:graphics/png \ + libvorbis>=1.3.5,3:audio/libvorbis \ + libvpx>=1.5.0:multimedia/libvpx \ + sqlite3>=3.19.3:databases/sqlite3 \ + ${PYTHON_PKGNAMEPREFIX}sqlite3>0:databases/py-sqlite3@${PY_FLAVOR} \ + v4l_compat>0:multimedia/v4l_compat \ + autoconf-2.13:devel/autoconf213 \ + yasm:devel/yasm \ + zip:archivers/zip +# soundtouch>=1.9.0:audio/soundtouch \ + +LIB_DEPENDS= libv4l2.so:multimedia/libv4l + +USE_GITHUB= yes +GH_ACCOUNT= MrAlex94 +GH_PROJECT= Waterfox + +USE_GECKO= gecko +MOZ_PKGCONFIG_FILES= # empty +USE_MOZILLA= -soundtouch +MOZILLA_NAME= Waterfox + +USE_GL= gl + +WATERFOX_ICON= ${MOZILLA}.png +WATERFOX_ICON_SRC= ${PREFIX}/lib/${MOZILLA}/browser/chrome/icons/default/default256.png +WATERFOX_DESKTOP= ${MOZSRC}/taskcluster/docker/firefox-snap/firefox.desktop +MOZ_OPTIONS= --enable-application=browser \ + --with-app-name=${MOZILLA} \ + --with-app-basename=${MOZILLA_NAME} \ + --with-distribution-id=org.${MOZILLA}project + +OPTIONS_DEFAULT= BUNDLED_CAIRO + +.include "${.CURDIR}/../../www/firefox/Makefile.options" + +# Inconsistent fallback order (libcubeb vs. audio_device) +SNDIO_PREVENTS= ${OPTIONS_MULTI_AUDIO:NSNDIO} + +post-patch: + @${REINPLACE_CMD} -e 's/%u/%U/' -e '/X-MultipleArgs/d' \ + -e 's/firefox/${MOZILLA}/' \ + -e 's/Firefox/${MOZILLA_NAME}/' \ + ${WATERFOX_DESKTOP} + @${REINPLACE_CMD} -e 's|%%LOCALBASE%%|${LOCALBASE}|g' \ + ${WRKSRC}/browser/app/nsBrowserApp.cpp + +pre-configure: + (cd ${WRKSRC} && ${LOCALBASE}/bin/autoconf-2.13) + (cd ${WRKSRC}/js/src/ && ${LOCALBASE}/bin/autoconf-2.13) + +post-install: + ${INSTALL_DATA} ${WATERFOX_DESKTOP} \ + ${STAGEDIR}${PREFIX}/share/applications/${MOZILLA}.desktop + ${MKDIR} ${STAGEDIR}${PREFIX}/share/pixmaps + ${LN} -sf ${WATERFOX_ICON_SRC} ${STAGEDIR}${PREFIX}/share/pixmaps/${WATERFOX_ICON} + +.include <bsd.port.mk> diff --git a/www/waterfox/distinfo b/www/waterfox/distinfo new file mode 100644 index 000000000000..fc8b4ed55cf6 --- /dev/null +++ b/www/waterfox/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1536644593 +SHA256 (MrAlex94-Waterfox-56.2.3_GH0.tar.gz) = 6134501bf3325d3bcd9632405a46f1f1278988e57bf4ca88b61926eb49ef1465 +SIZE (MrAlex94-Waterfox-56.2.3_GH0.tar.gz) = 395126627 diff --git a/www/waterfox/files/patch-addon-search b/www/waterfox/files/patch-addon-search new file mode 100644 index 000000000000..a2fabaa456b7 --- /dev/null +++ b/www/waterfox/files/patch-addon-search @@ -0,0 +1,70 @@ +https://github.com/mozilla/addons/issues/708 +https://github.com/mozilla/addons-frontend/issues/4610 + +diff --git browser/app/profile/firefox.js browser/app/profile/firefox.js +index 75c2c5e435e35..4d8c09c02759b 100644 +--- browser/app/profile/firefox.js ++++ browser/app/profile/firefox.js +@@ -48,12 +48,12 @@ pref("extensions.webextOptionalPermissionPrompts", true); + sticky_pref("extensions.getAddons.cache.enabled", true); + pref("extensions.getAddons.showPane", false); + pref("extensions.getAddons.maxResults", 15); +-pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%"); ++pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=Linux&appVersion=%VERSION%"); + pref("extensions.getAddons.getWithPerformance.url", ""); +-pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%&platform=%OS%&appver=%VERSION%"); +-pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%/%COMPATIBILITY_MODE%?src=firefox"); ++pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%&platform=Linux&appver=%VERSION%"); ++pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/Linux/%VERSION%/%COMPATIBILITY_MODE%?src=firefox"); + pref("extensions.webservice.discoverURL", ""); +-pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/list/recommended/all/%MAX_RESULTS%/%OS%/%VERSION%?src=firefox"); ++pref("extensions.getAddons.recommended.url", "https://services.addons.mozilla.org/%LOCALE%/%APP%/api/%API_VERSION%/list/recommended/all/%MAX_RESULTS%/Linux/%VERSION%?src=firefox"); + pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/"); + pref("extensions.getAddons.themes.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes/?src=firefox"); + +@@ -204,8 +204,8 @@ pref("app.update.service.enabled", true); + // .. etc .. + // + pref("extensions.update.enabled", true); +-pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%"); +-pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%"); ++pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=Linux&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%"); ++pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=Linux&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%"); + pref("extensions.update.interval", 86400); // Check for updates to Extensions and + // Themes every day + // Non-symmetric (not shared by extensions) extension-specific [update] preferences +diff --git toolkit/mozapps/extensions/internal/AddonRepository.jsm toolkit/mozapps/extensions/internal/AddonRepository.jsm +index f70fd8d7e3bd8..81e8cd7764fdf 100644 +--- toolkit/mozapps/extensions/internal/AddonRepository.jsm ++++ toolkit/mozapps/extensions/internal/AddonRepository.jsm +@@ -1179,7 +1179,7 @@ this.AddonRepository = { + let nodes = node.getElementsByTagName("os"); + addon.isPlatformCompatible = Array.some(nodes, function(aNode) { + let text = aNode.textContent.toLowerCase().trim(); +- return text == "all" || text == Services.appinfo.OS.toLowerCase(); ++ return text == "all" || text == "linux" || text == Services.appinfo.OS.toLowerCase(); + }); + break; + case "install": +@@ -1187,7 +1187,7 @@ this.AddonRepository = { + if (node.hasAttribute("os")) { + let os = node.getAttribute("os").trim().toLowerCase(); + // If the os is not ALL and not the current OS then ignore this xpi +- if (os != "all" && os != Services.appinfo.OS.toLowerCase()) ++ if (os != "all" && os != "linux" && os != Services.appinfo.OS.toLowerCase()) + break; + } + +diff --git toolkit/mozapps/extensions/internal/XPIProvider.jsm toolkit/mozapps/extensions/internal/XPIProvider.jsm +index f70fd8d7e3bd8..81e8cd7764fdf 100644 +--- toolkit/mozapps/extensions/internal/XPIProvider.jsm ++++ toolkit/mozapps/extensions/internal/XPIProvider.jsm +@@ -7186,7 +7186,7 @@ AddonInternal.prototype = { + // Something is causing errors in here + try { + for (let platform of this.targetPlatforms) { +- if (platform.os == Services.appinfo.OS) { ++ if (platform.os == "Linux" || platform.os == Services.appinfo.OS) { + if (platform.abi) { + needsABI = true; + if (platform.abi === abi) diff --git a/www/waterfox/files/patch-browser-app-nsBrowserApp.cpp b/www/waterfox/files/patch-browser-app-nsBrowserApp.cpp new file mode 100644 index 000000000000..68cb778b95a7 --- /dev/null +++ b/www/waterfox/files/patch-browser-app-nsBrowserApp.cpp @@ -0,0 +1,12 @@ +--- browser/app/nsBrowserApp.cpp.orig 2016-09-19 16:19:28 UTC ++++ browser/app/nsBrowserApp.cpp +@@ -324,6 +324,9 @@ int main(int argc, char* argv[], char* e + { + mozilla::TimeStamp start = mozilla::TimeStamp::Now(); + ++ setenv("MOZ_GMP_PATH", "%%LOCALBASE%%/lib/browser_plugins/symlinks/gecko", 0); ++ setenv("MOZ_PLUGIN_PATH", "%%LOCALBASE%%/lib/browser_plugins/symlinks/gecko", 0); ++ + #ifdef HAS_DLL_BLOCKLIST + DllBlocklist_Initialize(); + diff --git a/www/waterfox/files/patch-bug1021761 b/www/waterfox/files/patch-bug1021761 new file mode 100644 index 000000000000..f0764a8c4b22 --- /dev/null +++ b/www/waterfox/files/patch-bug1021761 @@ -0,0 +1,1218 @@ +diff --git build/moz.configure/old.configure build/moz.configure/old.configure +index cd6c37cf4c7c..e98dc7973a6a 100644 +--- build/moz.configure/old.configure ++++ build/moz.configure/old.configure +@@ -275,6 +275,7 @@ def old_configure_options(*options): + '--with-nspr-prefix', + '--with-nss-exec-prefix', + '--with-nss-prefix', ++ '--with-oss', + '--with-pthreads', + '--with-qemu-exe', + '--with-sixgill', +diff --git old-configure.in old-configure.in +index dff46614635e..dbbfdb76ab78 100644 +--- old-configure.in ++++ old-configure.in +@@ -3128,6 +3128,67 @@ AC_DEFINE(MOZ_WEBM_ENCODER) + AC_SUBST(MOZ_WEBM_ENCODER) + + dnl ================================== ++dnl = Check OSS availability ++dnl ================================== ++ ++dnl If using Linux, Solaris or BSDs, ensure that OSS is available ++case "$OS_TARGET" in ++Linux|SunOS|DragonFly|FreeBSD|NetBSD|GNU/kFreeBSD) ++ MOZ_OSS=1 ++ ;; ++esac ++ ++MOZ_ARG_WITH_STRING(oss, ++[ --with-oss[=PFX] Enable OpenSoundSystem support [installed at prefix PFX]], ++ OSSPREFIX=$withval) ++ ++if test -n "$OSSPREFIX"; then ++ if test "$OSSPREFIX" != "no"; then ++ MOZ_OSS=1 ++ else ++ MOZ_OSS= ++ fi ++fi ++ ++_SAVE_CFLAGS=$CFLAGS ++_SAVE_LIBS=$LIBS ++if test -n "$MOZ_OSS"; then ++ dnl Prefer 4Front implementation ++ AC_MSG_CHECKING([MOZ_OSS_CFLAGS]) ++ if test "$OSSPREFIX" != "yes"; then ++ oss_conf=${OSSPREFIX%/usr}/etc/oss.conf ++ if test -f "$oss_conf"; then ++ . "$oss_conf" ++ else ++ OSSLIBDIR=$OSSPREFIX/lib/oss ++ fi ++ if test -d "$OSSLIBDIR"; then ++ MOZ_OSS_CFLAGS="$MOZ_OSS_CFLAGS -I$OSSLIBDIR/include" ++ fi ++ fi ++ AC_MSG_RESULT([$MOZ_OSS_CFLAGS]) ++ ++ CFLAGS="$CFLAGS $MOZ_OSS_CFLAGS" ++ MOZ_CHECK_HEADERS(sys/soundcard.h soundcard.h) ++ ++ if test "$ac_cv_header_sys_soundcard_h" != "yes" -a \ ++ "$ac_cv_header_soundcard_h" != "yes"; then ++ AC_MSG_ERROR([Need OSS for Ogg, Wave or WebM decoding on $OS_TARGET. Disable with --without-oss.]) ++ fi ++ ++ dnl Assume NetBSD implementation over SunAudio ++ AC_CHECK_LIB(ossaudio, _oss_ioctl, ++ [AC_DEFINE_UNQUOTED(CUBEB_OSS_DEFAULT_OUTPUT, "/dev/sound") ++ MOZ_OSS_LIBS="$MOZ_OSS_LIBS -lossaudio"]) ++fi ++CFLAGS=$_SAVE_CFLAGS ++LIBS=$_SAVE_LIBS ++ ++AC_SUBST(MOZ_OSS) ++AC_SUBST_LIST(MOZ_OSS_CFLAGS) ++AC_SUBST_LIST(MOZ_OSS_LIBS) ++ ++dnl ================================== + dnl = Check alsa availability on Linux + dnl ================================== + +diff --git dom/media/CubebUtils.cpp dom/media/CubebUtils.cpp +index e10e07e06ade..1fd561bea113 100644 +--- dom/media/CubebUtils.cpp ++++ dom/media/CubebUtils.cpp +@@ -71,7 +71,8 @@ const char* AUDIOSTREAM_BACKEND_ID_STR[] = { + "sndio", + "opensl", + "audiotrack", +- "kai" ++ "kai", ++ "oss", + }; + /* Index for failures to create an audio stream the first time. */ + const int CUBEB_BACKEND_INIT_FAILURE_FIRST = +diff --git media/libcubeb/AUTHORS media/libcubeb/AUTHORS +index 0fde65baad34..f8663c43b475 100644 +--- media/libcubeb/AUTHORS ++++ media/libcubeb/AUTHORS +@@ -4,6 +4,7 @@ Michael Wu <mwu@mozilla.com> + Paul Adenot <paul@paul.cx> + David Richards <drichards@mozilla.com> + Sebastien Alaiwan <sebastien.alaiwan@gmail.com> ++Evgeniy Vodolazskiy <waterlaz@gmail.com> + KO Myung-Hun <komh@chollian.net> + Haakon Sporsheim <haakon.sporsheim@telenordigital.com> + Alex Chronopoulos <achronop@gmail.com> +diff --git media/libcubeb/src/cubeb.c media/libcubeb/src/cubeb.c +index 57bcb4c13652..68be024f4a68 100644 +--- media/libcubeb/src/cubeb.c ++++ media/libcubeb/src/cubeb.c +@@ -54,6 +54,9 @@ int audiotrack_init(cubeb ** context, char const * context_name); + #if defined(USE_KAI) + int kai_init(cubeb ** context, char const * context_name); + #endif ++#if defined(USE_OSS) ++int oss_init(cubeb ** context, char const * context_name); ++#endif + + static int + validate_stream_params(cubeb_stream_params * input_stream_params, +@@ -155,6 +158,10 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_KAI) + init_oneshot = kai_init; + #endif ++ } else if (!strcmp(backend_name, "oss")) { ++#if defined(USE_OSS) ++ init_oneshot = oss_init; ++#endif + } else { + /* Already set */ + } +@@ -196,6 +203,9 @@ cubeb_init(cubeb ** context, char const * context_name, char const * backend_nam + #if defined(USE_KAI) + kai_init, + #endif ++#if defined(USE_OSS) ++ oss_init, ++#endif + }; + int i; + +diff --git media/libcubeb/src/cubeb_alsa.c media/libcubeb/src/cubeb_alsa.c +index 05ad27fef53b..3ea78e994f59 100644 +--- media/libcubeb/src/cubeb_alsa.c ++++ media/libcubeb/src/cubeb_alsa.c +@@ -12,6 +12,7 @@ + #include <sys/time.h> + #include <assert.h> + #include <limits.h> ++#include <dlfcn.h> + #include <poll.h> + #include <unistd.h> + #include <alsa/asoundlib.h> +@@ -25,6 +26,52 @@ + + #define ALSA_PA_PLUGIN "ALSA <-> PulseAudio PCM I/O Plugin" + ++#ifdef DISABLE_LIBASOUND_DLOPEN ++#define WRAP(x) x ++#else ++#define WRAP(x) cubeb_##x ++#define MAKE_TYPEDEF(x) static typeof(x) * cubeb_##x ++MAKE_TYPEDEF(snd_config); ++MAKE_TYPEDEF(snd_config_add); ++MAKE_TYPEDEF(snd_config_copy); ++MAKE_TYPEDEF(snd_config_delete); ++MAKE_TYPEDEF(snd_config_get_id); ++MAKE_TYPEDEF(snd_config_get_string); ++MAKE_TYPEDEF(snd_config_imake_integer); ++MAKE_TYPEDEF(snd_config_search); ++MAKE_TYPEDEF(snd_config_search_definition); ++MAKE_TYPEDEF(snd_lib_error_set_handler); ++MAKE_TYPEDEF(snd_pcm_avail_update); ++MAKE_TYPEDEF(snd_pcm_close); ++MAKE_TYPEDEF(snd_pcm_delay); ++MAKE_TYPEDEF(snd_pcm_drain); ++MAKE_TYPEDEF(snd_pcm_frames_to_bytes); ++MAKE_TYPEDEF(snd_pcm_get_params); ++/* snd_pcm_hw_params_alloca is actually a macro */ ++/* MAKE_TYPEDEF(snd_pcm_hw_params_alloca); */ ++MAKE_TYPEDEF(snd_pcm_hw_params_sizeof); ++#define snd_pcm_hw_params_sizeof cubeb_snd_pcm_hw_params_sizeof ++MAKE_TYPEDEF(snd_pcm_hw_params_any); ++MAKE_TYPEDEF(snd_pcm_hw_params_get_channels_max); ++MAKE_TYPEDEF(snd_pcm_hw_params_get_rate); ++MAKE_TYPEDEF(snd_pcm_hw_params_set_rate_near); ++MAKE_TYPEDEF(snd_pcm_nonblock); ++MAKE_TYPEDEF(snd_pcm_open); ++MAKE_TYPEDEF(snd_pcm_open_lconf); ++MAKE_TYPEDEF(snd_pcm_pause); ++MAKE_TYPEDEF(snd_pcm_poll_descriptors); ++MAKE_TYPEDEF(snd_pcm_poll_descriptors_count); ++MAKE_TYPEDEF(snd_pcm_poll_descriptors_revents); ++MAKE_TYPEDEF(snd_pcm_readi); ++MAKE_TYPEDEF(snd_pcm_recover); ++MAKE_TYPEDEF(snd_pcm_set_params); ++MAKE_TYPEDEF(snd_pcm_start); ++MAKE_TYPEDEF(snd_pcm_state); ++MAKE_TYPEDEF(snd_pcm_writei); ++ ++#undef MAKE_TYPEDEF ++#endif ++ + /* ALSA is not thread-safe. snd_pcm_t instances are individually protected + by the owning cubeb_stream's mutex. snd_pcm_t creation and destruction + is not thread-safe until ALSA 1.0.24 (see alsa-lib.git commit 91c9c8f1), +@@ -65,6 +112,8 @@ struct cubeb { + workaround is not required. */ + snd_config_t * local_config; + int is_pa; ++ ++ void * libasound; + }; + + enum stream_state { +@@ -243,8 +292,8 @@ set_timeout(struct timeval * timeout, unsigned int ms) + static void + stream_buffer_decrement(cubeb_stream * stm, long count) + { +- char * bufremains = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, count); +- memmove(stm->buffer, bufremains, snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes - count)); ++ char * bufremains = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, count); ++ memmove(stm->buffer, bufremains, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes - count)); + stm->bufframes -= count; + } + +@@ -276,9 +325,9 @@ alsa_process_stream(cubeb_stream * stm) + /* Call _poll_descriptors_revents() even if we don't use it + to let underlying plugins clear null events. Otherwise poll() + may wake up again and again, producing unnecessary CPU usage. */ +- snd_pcm_poll_descriptors_revents(stm->pcm, stm->fds, stm->nfds, &revents); ++ WRAP(snd_pcm_poll_descriptors_revents)(stm->pcm, stm->fds, stm->nfds, &revents); + +- avail = snd_pcm_avail_update(stm->pcm); ++ avail = WRAP(snd_pcm_avail_update)(stm->pcm); + + /* Got null event? Bail and wait for another wakeup. */ + if (avail == 0) { +@@ -301,7 +350,7 @@ alsa_process_stream(cubeb_stream * stm) + // TODO: should it be marked as DRAINING? + } + +- got = snd_pcm_readi(stm->pcm, stm->buffer+stm->bufframes, avail); ++ got = WRAP(snd_pcm_readi)(stm->pcm, stm->buffer+stm->bufframes, avail); + + if (got < 0) { + avail = got; // the error handler below will recover us +@@ -345,7 +394,7 @@ alsa_process_stream(cubeb_stream * stm) + (!stm->other_stream || stm->other_stream->bufframes > 0)) { + long got = avail - stm->bufframes; + void * other_buffer = stm->other_stream ? stm->other_stream->buffer : NULL; +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); + + /* Correct read size to the other stream available frames */ + if (stm->other_stream && got > (snd_pcm_sframes_t) stm->other_stream->bufframes) { +@@ -372,8 +421,8 @@ alsa_process_stream(cubeb_stream * stm) + long drain_frames = avail - stm->bufframes; + double drain_time = (double) drain_frames / stm->params.rate; + +- char * buftail = stm->buffer + snd_pcm_frames_to_bytes(stm->pcm, stm->bufframes); +- memset(buftail, 0, snd_pcm_frames_to_bytes(stm->pcm, drain_frames)); ++ char * buftail = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->bufframes); ++ memset(buftail, 0, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, drain_frames)); + stm->bufframes = avail; + + /* Mark as draining, unless we're waiting for capture */ +@@ -400,7 +449,7 @@ alsa_process_stream(cubeb_stream * stm) + } + } + +- wrote = snd_pcm_writei(stm->pcm, stm->buffer, avail); ++ wrote = WRAP(snd_pcm_writei)(stm->pcm, stm->buffer, avail); + if (wrote < 0) { + avail = wrote; // the error handler below will recover us + } else { +@@ -413,13 +462,13 @@ alsa_process_stream(cubeb_stream * stm) + + /* Got some error? Let's try to recover the stream. */ + if (avail < 0) { +- avail = snd_pcm_recover(stm->pcm, avail, 0); ++ avail = WRAP(snd_pcm_recover)(stm->pcm, avail, 0); + + /* Capture pcm must be started after initial setup/recover */ + if (avail >= 0 && + stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- avail = snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ avail = WRAP(snd_pcm_start)(stm->pcm); + } + } + +@@ -535,26 +584,26 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + + slave_def = NULL; + +- r = snd_config_search(root_pcm, "slave", &slave_pcm); ++ r = WRAP(snd_config_search)(root_pcm, "slave", &slave_pcm); + if (r < 0) { + return NULL; + } + +- r = snd_config_get_string(slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_pcm, &string); + if (r >= 0) { +- r = snd_config_search_definition(lconf, "pcm_slave", string, &slave_def); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm_slave", string, &slave_def); + if (r < 0) { + return NULL; + } + } + + do { +- r = snd_config_search(slave_def ? slave_def : slave_pcm, "pcm", &pcm); ++ r = WRAP(snd_config_search)(slave_def ? slave_def : slave_pcm, "pcm", &pcm); + if (r < 0) { + break; + } + +- r = snd_config_get_string(slave_def ? slave_def : slave_pcm, &string); ++ r = WRAP(snd_config_get_string)(slave_def ? slave_def : slave_pcm, &string); + if (r < 0) { + break; + } +@@ -563,7 +612,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm); + if (r < 0) { + break; + } +@@ -572,7 +621,7 @@ get_slave_pcm_node(snd_config_t * lconf, snd_config_t * root_pcm) + } while (0); + + if (slave_def) { +- snd_config_delete(slave_def); ++ WRAP(snd_config_delete)(slave_def); + } + + return NULL; +@@ -595,22 +644,22 @@ init_local_config_with_workaround(char const * pcm_name) + + lconf = NULL; + +- if (snd_config == NULL) { ++ if (*WRAP(snd_config) == NULL) { + return NULL; + } + +- r = snd_config_copy(&lconf, snd_config); ++ r = WRAP(snd_config_copy)(&lconf, *WRAP(snd_config)); + if (r < 0) { + return NULL; + } + + do { +- r = snd_config_search_definition(lconf, "pcm", pcm_name, &pcm_node); ++ r = WRAP(snd_config_search_definition)(lconf, "pcm", pcm_name, &pcm_node); + if (r < 0) { + break; + } + +- r = snd_config_get_id(pcm_node, &string); ++ r = WRAP(snd_config_get_id)(pcm_node, &string); + if (r < 0) { + break; + } +@@ -619,7 +668,7 @@ init_local_config_with_workaround(char const * pcm_name) + if (r < 0 || r > (int) sizeof(node_name)) { + break; + } +- r = snd_config_search(lconf, node_name, &pcm_node); ++ r = WRAP(snd_config_search)(lconf, node_name, &pcm_node); + if (r < 0) { + break; + } +@@ -630,12 +679,12 @@ init_local_config_with_workaround(char const * pcm_name) + } + + /* Fetch the PCM node's type, and bail out if it's not the PulseAudio plugin. */ +- r = snd_config_search(pcm_node, "type", &node); ++ r = WRAP(snd_config_search)(pcm_node, "type", &node); + if (r < 0) { + break; + } + +- r = snd_config_get_string(node, &string); ++ r = WRAP(snd_config_get_string)(node, &string); + if (r < 0) { + break; + } +@@ -646,18 +695,18 @@ init_local_config_with_workaround(char const * pcm_name) + + /* Don't clobber an explicit existing handle_underrun value, set it only + if it doesn't already exist. */ +- r = snd_config_search(pcm_node, "handle_underrun", &node); ++ r = WRAP(snd_config_search)(pcm_node, "handle_underrun", &node); + if (r != -ENOENT) { + break; + } + + /* Disable pcm_pulse's asynchronous underrun handling. */ +- r = snd_config_imake_integer(&node, "handle_underrun", 0); ++ r = WRAP(snd_config_imake_integer)(&node, "handle_underrun", 0); + if (r < 0) { + break; + } + +- r = snd_config_add(pcm_node, node); ++ r = WRAP(snd_config_add)(pcm_node, node); + if (r < 0) { + break; + } +@@ -665,7 +714,7 @@ init_local_config_with_workaround(char const * pcm_name) + return lconf; + } while (0); + +- snd_config_delete(lconf); ++ WRAP(snd_config_delete)(lconf); + + return NULL; + } +@@ -677,9 +726,9 @@ alsa_locked_pcm_open(snd_pcm_t ** pcm, char const * pcm_name, snd_pcm_stream_t s + + pthread_mutex_lock(&cubeb_alsa_mutex); + if (local_config) { +- r = snd_pcm_open_lconf(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); ++ r = WRAP(snd_pcm_open_lconf)(pcm, pcm_name, stream, SND_PCM_NONBLOCK, local_config); + } else { +- r = snd_pcm_open(pcm, pcm_name, stream, SND_PCM_NONBLOCK); ++ r = WRAP(snd_pcm_open)(pcm, pcm_name, stream, SND_PCM_NONBLOCK); + } + pthread_mutex_unlock(&cubeb_alsa_mutex); + +@@ -692,7 +741,7 @@ alsa_locked_pcm_close(snd_pcm_t * pcm) + int r; + + pthread_mutex_lock(&cubeb_alsa_mutex); +- r = snd_pcm_close(pcm); ++ r = WRAP(snd_pcm_close)(pcm); + pthread_mutex_unlock(&cubeb_alsa_mutex); + + return r; +@@ -755,12 +804,65 @@ alsa_init(cubeb ** context, char const * context_name) + pthread_attr_t attr; + snd_pcm_t * dummy; + ++ void * libasound = NULL; ++ ++#ifndef DISABLE_LIBASOUND_DLOPEN ++ libasound = dlopen("libasound.so", RTLD_LAZY); ++ if (!libasound) { ++ return CUBEB_ERROR; ++ } ++ ++#define LOAD(x) do { \ ++ cubeb_##x = dlsym(libasound, #x); \ ++ if (!cubeb_##x) { \ ++ dlclose(libasound); \ ++ return CUBEB_ERROR; \ ++ } \ ++ } while(0) ++ ++ LOAD(snd_config); ++ LOAD(snd_config_add); ++ LOAD(snd_config_copy); ++ LOAD(snd_config_delete); ++ LOAD(snd_config_get_id); ++ LOAD(snd_config_get_string); ++ LOAD(snd_config_imake_integer); ++ LOAD(snd_config_search); ++ LOAD(snd_config_search_definition); ++ LOAD(snd_lib_error_set_handler); ++ LOAD(snd_pcm_avail_update); ++ LOAD(snd_pcm_close); ++ LOAD(snd_pcm_delay); ++ LOAD(snd_pcm_drain); ++ LOAD(snd_pcm_frames_to_bytes); ++ LOAD(snd_pcm_get_params); ++ /* snd_pcm_hw_params_alloca is actually a macro */ ++ /* LOAD(snd_pcm_hw_params_alloca); */ ++ LOAD(snd_pcm_hw_params_sizeof); ++ LOAD(snd_pcm_hw_params_any); ++ LOAD(snd_pcm_hw_params_get_channels_max); ++ LOAD(snd_pcm_hw_params_get_rate); ++ LOAD(snd_pcm_hw_params_set_rate_near); ++ LOAD(snd_pcm_nonblock); ++ LOAD(snd_pcm_open); ++ LOAD(snd_pcm_open_lconf); ++ LOAD(snd_pcm_pause); ++ LOAD(snd_pcm_poll_descriptors); ++ LOAD(snd_pcm_poll_descriptors_count); ++ LOAD(snd_pcm_poll_descriptors_revents); ++ LOAD(snd_pcm_recover); ++ LOAD(snd_pcm_set_params); ++ LOAD(snd_pcm_state); ++ LOAD(snd_pcm_writei); ++ ++#undef LOAD ++#endif + assert(context); + *context = NULL; + + pthread_mutex_lock(&cubeb_alsa_mutex); + if (!cubeb_alsa_error_handler_set) { +- snd_lib_error_set_handler(silent_error_handler); ++ WRAP(snd_lib_error_set_handler)(silent_error_handler); + cubeb_alsa_error_handler_set = 1; + } + pthread_mutex_unlock(&cubeb_alsa_mutex); +@@ -768,6 +870,8 @@ alsa_init(cubeb ** context, char const * context_name) + ctx = calloc(1, sizeof(*ctx)); + assert(ctx); + ++ ctx->libasound = libasound; ++ + ctx->ops = &alsa_ops; + + r = pthread_mutex_init(&ctx->mutex, NULL); +@@ -817,7 +921,7 @@ alsa_init(cubeb ** context, char const * context_name) + config fails with EINVAL, the PA PCM is too old for this workaround. */ + if (r == -EINVAL) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + ctx->local_config = NULL; + } else if (r >= 0) { +@@ -857,9 +961,13 @@ alsa_destroy(cubeb * ctx) + pthread_mutex_destroy(&ctx->mutex); + free(ctx->fds); + ++ if (ctx->libasound) { ++ dlclose(ctx->libasound); ++ } ++ + if (ctx->local_config) { + pthread_mutex_lock(&cubeb_alsa_mutex); +- snd_config_delete(ctx->local_config); ++ WRAP(snd_config_delete)(ctx->local_config); + pthread_mutex_unlock(&cubeb_alsa_mutex); + } + +@@ -939,7 +1047,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR; + } + +- r = snd_pcm_nonblock(stm->pcm, 1); ++ r = WRAP(snd_pcm_nonblock)(stm->pcm, 1); + assert(r == 0); + + latency_us = latency_frames * 1e6 / stm->params.rate; +@@ -952,7 +1060,7 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + latency_us = latency_us < min_latency ? min_latency: latency_us; + } + +- r = snd_pcm_set_params(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, ++ r = WRAP(snd_pcm_set_params)(stm->pcm, format, SND_PCM_ACCESS_RW_INTERLEAVED, + stm->params.channels, stm->params.rate, 1, + latency_us); + if (r < 0) { +@@ -960,20 +1068,20 @@ alsa_stream_init_single(cubeb * ctx, cubeb_stream ** stream, char const * stream + return CUBEB_ERROR_INVALID_FORMAT; + } + +- r = snd_pcm_get_params(stm->pcm, &stm->buffer_size, &period_size); ++ r = WRAP(snd_pcm_get_params)(stm->pcm, &stm->buffer_size, &period_size); + assert(r == 0); + + /* Double internal buffer size to have enough space when waiting for the other side of duplex connection */ + stm->buffer_size *= 2; +- stm->buffer = calloc(1, snd_pcm_frames_to_bytes(stm->pcm, stm->buffer_size)); ++ stm->buffer = calloc(1, WRAP(snd_pcm_frames_to_bytes)(stm->pcm, stm->buffer_size)); + assert(stm->buffer); + +- stm->nfds = snd_pcm_poll_descriptors_count(stm->pcm); ++ stm->nfds = WRAP(snd_pcm_poll_descriptors_count)(stm->pcm); + assert(stm->nfds > 0); + + stm->saved_fds = calloc(stm->nfds, sizeof(struct pollfd)); + assert(stm->saved_fds); +- r = snd_pcm_poll_descriptors(stm->pcm, stm->saved_fds, stm->nfds); ++ r = WRAP(snd_pcm_poll_descriptors)(stm->pcm, stm->saved_fds, stm->nfds); + assert((nfds_t) r == stm->nfds); + + if (alsa_register_stream(ctx, stm) != 0) { +@@ -1048,7 +1156,7 @@ alsa_stream_destroy(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + if (stm->pcm) { + if (stm->state == DRAINING) { +- snd_pcm_drain(stm->pcm); ++ WRAP(snd_pcm_drain)(stm->pcm); + } + alsa_locked_pcm_close(stm->pcm); + stm->pcm = NULL; +@@ -1094,12 +1202,12 @@ alsa_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) + + assert(stm); + +- r = snd_pcm_hw_params_any(stm->pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(stm->pcm, hw_params); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_channels_max(hw_params, max_channels); ++ r = WRAP(snd_pcm_hw_params_get_channels_max)(hw_params, max_channels); + if (r < 0) { + return CUBEB_ERROR; + } +@@ -1120,34 +1228,34 @@ alsa_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate) { + + /* get a pcm, disabling resampling, so we get a rate the + * hardware/dmix/pulse/etc. supports. */ +- r = snd_pcm_open(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); ++ r = WRAP(snd_pcm_open)(&pcm, CUBEB_ALSA_PCM_NAME, SND_PCM_STREAM_PLAYBACK, SND_PCM_NO_AUTO_RESAMPLE); + if (r < 0) { + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_any(pcm, hw_params); ++ r = WRAP(snd_pcm_hw_params_any)(pcm, hw_params); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- r = snd_pcm_hw_params_get_rate(hw_params, rate, &dir); ++ r = WRAP(snd_pcm_hw_params_get_rate)(hw_params, rate, &dir); + if (r >= 0) { + /* There is a default rate: use it. */ +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_OK; + } + + /* Use a common rate, alsa may adjust it based on hw/etc. capabilities. */ + *rate = 44100; + +- r = snd_pcm_hw_params_set_rate_near(pcm, hw_params, rate, NULL); ++ r = WRAP(snd_pcm_hw_params_set_rate_near)(pcm, hw_params, rate, NULL); + if (r < 0) { +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + return CUBEB_ERROR; + } + +- snd_pcm_close(pcm); ++ WRAP(snd_pcm_close)(pcm); + + return CUBEB_OK; + } +@@ -1180,10 +1288,10 @@ alsa_stream_start(cubeb_stream * stm) + pthread_mutex_lock(&stm->mutex); + /* Capture pcm must be started after initial setup/recover */ + if (stm->stream_type == SND_PCM_STREAM_CAPTURE && +- snd_pcm_state(stm->pcm) == SND_PCM_STATE_PREPARED) { +- snd_pcm_start(stm->pcm); ++ WRAP(snd_pcm_state)(stm->pcm) == SND_PCM_STATE_PREPARED) { ++ WRAP(snd_pcm_start)(stm->pcm); + } +- snd_pcm_pause(stm->pcm, 0); ++ WRAP(snd_pcm_pause)(stm->pcm, 0); + gettimeofday(&stm->last_activity, NULL); + pthread_mutex_unlock(&stm->mutex); + +@@ -1223,7 +1331,7 @@ alsa_stream_stop(cubeb_stream * stm) + pthread_mutex_unlock(&ctx->mutex); + + pthread_mutex_lock(&stm->mutex); +- snd_pcm_pause(stm->pcm, 1); ++ WRAP(snd_pcm_pause)(stm->pcm, 1); + pthread_mutex_unlock(&stm->mutex); + + return CUBEB_OK; +@@ -1239,8 +1347,8 @@ alsa_stream_get_position(cubeb_stream * stm, uint64_t * position) + pthread_mutex_lock(&stm->mutex); + + delay = -1; +- if (snd_pcm_state(stm->pcm) != SND_PCM_STATE_RUNNING || +- snd_pcm_delay(stm->pcm, &delay) != 0) { ++ if (WRAP(snd_pcm_state)(stm->pcm) != SND_PCM_STATE_RUNNING || ++ WRAP(snd_pcm_delay)(stm->pcm, &delay) != 0) { + *position = stm->last_position; + pthread_mutex_unlock(&stm->mutex); + return CUBEB_OK; +@@ -1265,7 +1373,7 @@ alsa_stream_get_latency(cubeb_stream * stm, uint32_t * latency) + snd_pcm_sframes_t delay; + /* This function returns the delay in frames until a frame written using + snd_pcm_writei is sent to the DAC. The DAC delay should be < 1ms anyways. */ +- if (snd_pcm_delay(stm->pcm, &delay)) { ++ if (WRAP(snd_pcm_delay)(stm->pcm, &delay)) { + return CUBEB_ERROR; + } + +diff --git media/libcubeb/src/cubeb_oss.c media/libcubeb/src/cubeb_oss.c +new file mode 100644 +index 000000000000..7b0b4f37dbe4 +--- /dev/null ++++ media/libcubeb/src/cubeb_oss.c +@@ -0,0 +1,445 @@ ++/* ++ * Copyright © 2014 Mozilla Foundation ++ * ++ * This program is made available under an ISC-style license. See the ++ * accompanying file LICENSE for details. ++ */ ++#if defined(HAVE_SYS_SOUNDCARD_H) ++#include <sys/soundcard.h> ++#else ++#include <soundcard.h> ++#endif ++#include <unistd.h> ++#include <stdlib.h> ++#include <sys/types.h> ++#include <sys/stat.h> ++#include <fcntl.h> ++#include <sys/ioctl.h> ++#include <errno.h> ++#include <pthread.h> ++#include <stdio.h> ++#include <assert.h> ++ ++#include "cubeb/cubeb.h" ++#include "cubeb-internal.h" ++ ++#ifndef CUBEB_OSS_DEFAULT_OUTPUT ++#define CUBEB_OSS_DEFAULT_OUTPUT "/dev/dsp" ++#endif ++ ++#define OSS_BUFFER_SIZE 1024 ++ ++struct cubeb { ++ struct cubeb_ops const * ops; ++}; ++ ++struct cubeb_stream { ++ cubeb * context; ++ ++ cubeb_data_callback data_callback; ++ cubeb_state_callback state_callback; ++ void * user_ptr; ++ float volume; ++ float panning; ++ ++ pthread_mutex_t state_mutex; ++ pthread_cond_t state_cond; ++ ++ int running; ++ int stopped; ++ int floating; ++ ++ /* These two vars are needed to support old versions of OSS */ ++ unsigned int position_bytes; ++ unsigned int last_position_bytes; ++ ++ uint64_t written_frags; /* The number of fragments written to /dev/dsp */ ++ uint64_t missed_frags; /* fragments output with stopped stream */ ++ ++ cubeb_stream_params params; ++ int fd; ++ pthread_t th; ++}; ++ ++static struct cubeb_ops const oss_ops; ++ ++int oss_init(cubeb ** context, char const * context_name) ++{ ++ cubeb* ctx = (cubeb*)malloc(sizeof(cubeb)); ++ ctx->ops = &oss_ops; ++ *context = ctx; ++ return CUBEB_OK; ++} ++ ++static void oss_destroy(cubeb *ctx) ++{ ++ free(ctx); ++} ++ ++static char const * oss_get_backend_id(cubeb * context) ++{ ++ static char oss_name[] = "oss"; ++ return oss_name; ++} ++ ++static int oss_get_max_channel_count(cubeb * ctx, uint32_t * max_channels) ++{ ++ *max_channels = 2; /* Let's support only stereo for now */ ++ return CUBEB_OK; ++} ++ ++static int oss_get_min_latency(cubeb * context, cubeb_stream_params params, ++ uint32_t * latency_frames) ++{ ++ (void)context; ++ /* 40ms is a big enough number to work ok */ ++ *latency_frames = 40 * params.rate / 1000; ++ return CUBEB_OK; ++} ++ ++static int oss_get_preferred_sample_rate(cubeb *context, uint32_t * rate) ++{ ++ /* 48000 seems a prefered choice for most audio devices ++ * and a good choice for OSS */ ++ *rate = 48000; ++ return CUBEB_OK; ++} ++ ++static void run_state_callback(cubeb_stream *stream, cubeb_state state) ++{ ++ if (stream->state_callback) { ++ stream->state_callback(stream, stream->user_ptr, state); ++ } ++} ++ ++static long run_data_callback(cubeb_stream *stream, void *buffer, long nframes) ++{ ++ long got = 0; ++ pthread_mutex_lock(&stream->state_mutex); ++ if (stream->data_callback && stream->running && !stream->stopped) { ++ pthread_mutex_unlock(&stream->state_mutex); ++ got = stream->data_callback(stream, stream->user_ptr, NULL, buffer, nframes); ++ } else { ++ pthread_mutex_unlock(&stream->state_mutex); ++ } ++ return got; ++} ++ ++static void apply_volume_int(int16_t* buffer, unsigned int n, ++ float volume, float panning) ++{ ++ float left = volume; ++ float right = volume; ++ unsigned int i; ++ int pan[2]; ++ if (panning<0) { ++ right *= (1+panning); ++ } else { ++ left *= (1-panning); ++ } ++ pan[0] = 128.0*left; ++ pan[1] = 128.0*right; ++ for(i=0; i<n; i++){ ++ buffer[i] = ((int)buffer[i])*pan[i%2]/128; ++ } ++} ++ ++static void apply_volume_float(float* buffer, unsigned int n, ++ float volume, float panning) ++{ ++ float left = volume; ++ float right = volume; ++ unsigned int i; ++ float pan[2]; ++ if (panning<0) { ++ right *= (1+panning); ++ } else { ++ left *= (1-panning); ++ } ++ pan[0] = left; ++ pan[1] = right; ++ for(i=0; i<n; i++){ ++ buffer[i] = buffer[i]*pan[i%2]; ++ } ++} ++ ++ ++static void *writer(void *stm) ++{ ++ cubeb_stream* stream = (cubeb_stream*)stm; ++ int16_t buffer[OSS_BUFFER_SIZE]; ++ float f_buffer[OSS_BUFFER_SIZE]; ++ int got; ++ unsigned long i; ++ while (stream->running) { ++ pthread_mutex_lock(&stream->state_mutex); ++ if (stream->stopped) { ++ pthread_mutex_unlock(&stream->state_mutex); ++ run_state_callback(stream, CUBEB_STATE_STOPPED); ++ pthread_mutex_lock(&stream->state_mutex); ++ while (stream->stopped) { ++ pthread_cond_wait(&stream->state_cond, &stream->state_mutex); ++ } ++ pthread_mutex_unlock(&stream->state_mutex); ++ run_state_callback(stream, CUBEB_STATE_STARTED); ++ continue; ++ } ++ pthread_mutex_unlock(&stream->state_mutex); ++ if (stream->floating) { ++ got = run_data_callback(stream, f_buffer, ++ OSS_BUFFER_SIZE/stream->params.channels); ++ apply_volume_float(f_buffer, got*stream->params.channels, ++ stream->volume, stream->panning); ++ for (i=0; i<((unsigned long)got)*stream->params.channels; i++) { ++ /* Clipping is prefered to overflow */ ++ if(f_buffer[i]>=1.0){ ++ f_buffer[i]=1.0; ++ } ++ if(f_buffer[i]<=-1.0){ ++ f_buffer[i]=-1.0; ++ } ++ /* One might think that multipling by 32767.0 is logical but results in clipping */ ++ buffer[i] = f_buffer[i]*32767.0; ++ } ++ } else { ++ got = run_data_callback(stream, buffer, ++ OSS_BUFFER_SIZE/stream->params.channels); ++ apply_volume_int(buffer, got*stream->params.channels, ++ stream->volume, stream->panning); ++ } ++ if (got<0) { ++ run_state_callback(stream, CUBEB_STATE_ERROR); ++ break; ++ } ++ if (!got) { ++ run_state_callback(stream, CUBEB_STATE_DRAINED); ++ } ++ if (got) { ++ size_t i = 0; ++ size_t s = got*stream->params.channels*sizeof(int16_t); ++ while (i < s) { ++ ssize_t n = write(stream->fd, ((char*)buffer) + i, s - i); ++ if (n<=0) { ++ run_state_callback(stream, CUBEB_STATE_ERROR); ++ break; ++ } ++ i+=n; ++ } ++ stream->written_frags+=got; ++ } ++ } ++ return NULL; ++} ++ ++static void oss_try_set_latency(cubeb_stream* stream, unsigned int latency) ++{ ++ unsigned int latency_bytes, n_frag; ++ int frag; ++ /* fragment size of 1024 is a good choice with good chances to be accepted */ ++ unsigned int frag_log=10; /* 2^frag_log = fragment size */ ++ latency_bytes = ++ latency*stream->params.rate*stream->params.channels*sizeof(uint16_t)/1000; ++ n_frag = latency_bytes>>frag_log; ++ frag = (n_frag<<16) | frag_log; ++ /* Even if this fails we wish to continue, not checking for errors */ ++ ioctl(stream->fd, SNDCTL_DSP_SETFRAGMENT, &frag); ++} ++ ++static int oss_stream_init(cubeb * context, cubeb_stream ** stm, ++ char const * stream_name, ++ cubeb_devid input_device, ++ cubeb_stream_params * input_stream_params, ++ cubeb_devid output_device, ++ cubeb_stream_params * output_stream_params, ++ unsigned int latency, ++ cubeb_data_callback data_callback, ++ cubeb_state_callback state_callback, void * user_ptr) ++{ ++ cubeb_stream* stream = (cubeb_stream*)malloc(sizeof(cubeb_stream)); ++ stream->context = context; ++ stream->data_callback = data_callback; ++ stream->state_callback = state_callback; ++ stream->user_ptr = user_ptr; ++ ++ assert(!input_stream_params && "not supported."); ++ if (input_device || output_device) { ++ /* Device selection not yet implemented. */ ++ return CUBEB_ERROR_DEVICE_UNAVAILABLE; ++ } ++ ++ if ((stream->fd = open(CUBEB_OSS_DEFAULT_OUTPUT, O_WRONLY)) == -1) { ++ free(stream); ++ return CUBEB_ERROR; ++ } ++#define SET(what, to) do { unsigned int i = to; \ ++ int j = ioctl(stream->fd, what, &i); \ ++ if (j == -1 || i != to) { \ ++ close(stream->fd); \ ++ free(stream); \ ++ return CUBEB_ERROR_INVALID_FORMAT; } } while (0) ++ ++ stream->params = *output_stream_params; ++ stream->volume = 1.0; ++ stream->panning = 0.0; ++ ++ oss_try_set_latency(stream, latency); ++ ++ stream->floating = 0; ++ SET(SNDCTL_DSP_CHANNELS, stream->params.channels); ++ SET(SNDCTL_DSP_SPEED, stream->params.rate); ++ switch (stream->params.format) { ++ case CUBEB_SAMPLE_S16LE: ++ SET(SNDCTL_DSP_SETFMT, AFMT_S16_LE); ++ break; ++ case CUBEB_SAMPLE_S16BE: ++ SET(SNDCTL_DSP_SETFMT, AFMT_S16_BE); ++ break; ++ case CUBEB_SAMPLE_FLOAT32LE: ++ SET(SNDCTL_DSP_SETFMT, AFMT_S16_NE); ++ stream->floating = 1; ++ break; ++ default: ++ close(stream->fd); ++ free(stream); ++ return CUBEB_ERROR; ++ } ++ ++ ++ pthread_mutex_init(&stream->state_mutex, NULL); ++ pthread_cond_init(&stream->state_cond, NULL); ++ ++ stream->running = 1; ++ stream->stopped = 1; ++ stream->position_bytes = 0; ++ stream->last_position_bytes = 0; ++ stream->written_frags = 0; ++ stream->missed_frags = 0; ++ ++ pthread_create(&stream->th, NULL, writer, (void*)stream); ++ ++ *stm = stream; ++ ++ return CUBEB_OK; ++} ++ ++static void oss_stream_destroy(cubeb_stream * stream) ++{ ++ pthread_mutex_lock(&stream->state_mutex); ++ ++ stream->running = 0; ++ stream->stopped = 0; ++ pthread_cond_signal(&stream->state_cond); ++ ++ pthread_mutex_unlock(&stream->state_mutex); ++ ++ pthread_join(stream->th, NULL); ++ ++ pthread_mutex_destroy(&stream->state_mutex); ++ pthread_cond_destroy(&stream->state_cond); ++ close(stream->fd); ++ free(stream); ++} ++ ++static int oss_stream_get_latency(cubeb_stream * stream, uint32_t * latency) ++{ ++ if (ioctl(stream->fd, SNDCTL_DSP_GETODELAY, latency)==-1) { ++ return CUBEB_ERROR; ++ } ++ /* Convert latency from bytes to frames */ ++ *latency /= stream->params.channels*sizeof(int16_t); ++ return CUBEB_OK; ++} ++ ++ ++static int oss_stream_current_optr(cubeb_stream * stream, uint64_t * position) ++{ ++ count_info ci; ++ /* Unfortunately, this ioctl is only available in OSS 4.x */ ++#ifdef SNDCTL_DSP_CURRENT_OPTR ++ oss_count_t count; ++ if (ioctl(stream->fd, SNDCTL_DSP_CURRENT_OPTR, &count) != -1) { ++ *position = count.samples;// + count.fifo_samples; ++ return CUBEB_OK; ++ } ++#endif ++ /* Fall back to this ioctl in case the previous one fails */ ++ if (ioctl(stream->fd, SNDCTL_DSP_GETOPTR, &ci) == -1) { ++ return CUBEB_ERROR; ++ } ++ /* ci.bytes is only 32 bit and will start to wrap after arithmetic overflow */ ++ stream->position_bytes += ci.bytes - stream->last_position_bytes; ++ stream->last_position_bytes = ci.bytes; ++ *position = stream->position_bytes/stream->params.channels/sizeof(int16_t); ++ return CUBEB_OK; ++} ++ ++static int oss_stream_get_position(cubeb_stream * stream, uint64_t * position) ++{ ++ if ( oss_stream_current_optr(stream, position) == CUBEB_OK ){ ++ *position -= stream->missed_frags; ++ return CUBEB_OK; ++ } ++ /* If no correct method to get position works we resort to this */ ++ *position = stream->written_frags; ++ return CUBEB_OK; ++} ++ ++ ++static int oss_stream_start(cubeb_stream * stream) ++{ ++ pthread_mutex_lock(&stream->state_mutex); ++ if (stream->stopped) { ++ uint64_t ptr; ++ oss_stream_current_optr(stream, &ptr); ++ stream->missed_frags = ptr - stream->written_frags; ++ stream->stopped = 0; ++ pthread_cond_signal(&stream->state_cond); ++ } ++ pthread_mutex_unlock(&stream->state_mutex); ++ return CUBEB_OK; ++} ++ ++static int oss_stream_stop(cubeb_stream * stream) ++{ ++ pthread_mutex_lock(&stream->state_mutex); ++ stream->stopped = 1; ++ pthread_mutex_unlock(&stream->state_mutex); ++ return CUBEB_OK; ++} ++ ++int oss_stream_set_panning(cubeb_stream * stream, float panning) ++{ ++ if (stream->params.channels == 2) { ++ stream->panning=panning; ++ } ++ return CUBEB_OK; ++} ++ ++int oss_stream_set_volume(cubeb_stream * stream, float volume) ++{ ++ stream->volume=volume; ++ return CUBEB_OK; ++} ++ ++static struct cubeb_ops const oss_ops = { ++ .init = oss_init, ++ .get_backend_id = oss_get_backend_id, ++ .get_max_channel_count = oss_get_max_channel_count, ++ .get_min_latency = oss_get_min_latency, ++ .get_preferred_sample_rate = oss_get_preferred_sample_rate, ++ .get_preferred_channel_layout = NULL, ++ .destroy = oss_destroy, ++ .enumerate_devices = NULL, ++ .stream_init = oss_stream_init, ++ .stream_destroy = oss_stream_destroy, ++ .stream_start = oss_stream_start, ++ .stream_stop = oss_stream_stop, ++ .stream_get_position = oss_stream_get_position, ++ .stream_get_latency = oss_stream_get_latency, ++ .stream_set_volume = oss_stream_set_volume, ++ .stream_set_panning = oss_stream_set_panning, ++ .stream_get_current_device = NULL, ++ .stream_device_destroy = NULL, ++ .stream_register_device_changed_callback = NULL, ++ .register_device_collection_changed = NULL ++}; +diff --git media/libcubeb/src/moz.build media/libcubeb/src/moz.build +index fc9c79198e30..57d039d5a0f2 100644 +--- media/libcubeb/src/moz.build ++++ media/libcubeb/src/moz.build +@@ -20,6 +20,12 @@ if CONFIG['MOZ_ALSA']: + ] + DEFINES['USE_ALSA'] = True + ++if CONFIG['MOZ_OSS']: ++ SOURCES += [ ++ 'cubeb_oss.c', ++ ] ++ DEFINES['USE_OSS'] = True ++ + if CONFIG['MOZ_PULSEAUDIO'] or CONFIG['MOZ_JACK']: + SOURCES += [ + 'cubeb_resampler.cpp', +@@ -92,6 +98,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': + '%' + '%s/system/media/wilhelm/include' % CONFIG['ANDROID_SOURCE'], + ] + ++CFLAGS += CONFIG['MOZ_OSS_CFLAGS'] + CFLAGS += CONFIG['MOZ_ALSA_CFLAGS'] + CFLAGS += CONFIG['MOZ_PULSEAUDIO_CFLAGS'] + +diff --git media/libcubeb/gtest/moz.build media/libcubeb/gtest/moz.build +index e99968648554..efbbbf779e11 100644 +--- media/libcubeb/gtest/moz.build ++++ media/libcubeb/gtest/moz.build +@@ -71,7 +71,6 @@ elif CONFIG['OS_TARGET'] == 'OpenBSD': + 'sndio', + ] + else: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] + OS_LIBS += CONFIG['MOZ_PULSEAUDIO_LIBS'] + + if CONFIG['GNU_CXX']: +diff --git media/libcubeb/update.sh media/libcubeb/update.sh +index b139b8f497fd..d1f8a223c6d8 100755 +--- media/libcubeb/update.sh ++++ media/libcubeb/update.sh +@@ -20,6 +20,7 @@ cp $1/src/cubeb_log.h src + cp $1/src/cubeb_mixer.cpp src + cp $1/src/cubeb_mixer.h src + cp $1/src/cubeb_opensl.c src ++cp $1/src/cubeb_oss.c src + cp $1/src/cubeb_osx_run_loop.h src + cp $1/src/cubeb_panner.cpp src + cp $1/src/cubeb_panner.h src +diff --git toolkit/library/moz.build toolkit/library/moz.build +index a61c689c83c3..7764df6f8a6b 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -242,8 +242,8 @@ if CONFIG['MOZ_SYSTEM_LIBVPX']: + if not CONFIG['MOZ_TREE_PIXMAN']: + OS_LIBS += CONFIG['MOZ_PIXMAN_LIBS'] + +-if CONFIG['MOZ_ALSA']: +- OS_LIBS += CONFIG['MOZ_ALSA_LIBS'] ++if CONFIG['MOZ_OSS']: ++ OS_LIBS += CONFIG['MOZ_OSS_LIBS'] + + if CONFIG['HAVE_CLOCK_MONOTONIC']: + OS_LIBS += CONFIG['REALTIME_LIBS'] diff --git a/www/waterfox/files/patch-bug1036008 b/www/waterfox/files/patch-bug1036008 new file mode 100644 index 000000000000..7f50b456c30d --- /dev/null +++ b/www/waterfox/files/patch-bug1036008 @@ -0,0 +1,523 @@ +commit ed18f146242b +Author: Masayuki Nakano <masayuki@d-toybox.com> +Date: Fri Feb 16 15:54:07 2018 +0900 + + Bug 1036008 - Use alternative ASCII capable keyboard layout information to decide keyCode even if the key produces an ASCII punctuation character r=smaug + + Gecko decides keyCode from an ASCII character which is produced by the key + by itself or with Shift on active keyboard layout or alternative ASCII capable + keyboard layout if active keyboard layout isn't ASCII capable. However, we've + ignored alternative ASCII capable keyboard layout's character if both the + key itself and with Shift don't produce ASCII alphabet nor ASCII numeral, + i.e., ASCII punctuation characters are not used in alternative ASCII capable + keyboard layout because of avoiding mapping a keyCode value to 2 or more keys. + + However, setting 0 to keyCode value makes Firefox unusable with some web + applications which are aware of neither KeyboardEvent.key nor + KeyboardEvent.code. So, even if we map same keyCode value to a key, we should + avoid setting keyCode value to 0 as far as possible. + + This patch's approach is, we behave same keyCode value as the alternative ASCII + capable keyCode is selected when computed keyCode value of active keyboard + layout is 0. This means that we will make some language users whose keyboard + layout for their language is not ASCII capable can use global web services + which support US keyboard layout of Firefox since the new keyCode values + are mostly computed with US layout on Windows or actual alternative ASCII + capable keyboard layout on macOS and Linux. In other words, we cannot improve + compatibility with web applications which don't support Firefox by this patch + since our keyCode values are really different from Chrome's. So, unfortunately, + if we'd use exactly same keyCode computation as Chromium, we'd break + compatibility with existing web applications which are aware of Firefox since + it's necessary to check UA name or something before using keyCode values. + + Note that the most important difference between Windows and the others is, + such keyCode value is computed with alternative ASCII capable keyboard + layout on macOS and Linux but only on Windows, it's computed with OEM virtual + keycode. This means that only on Windows, the keyCode value may be different + from actual alternative ASCII capable keyboard layout's keyCode. + + MozReview-Commit-ID: As289r9wp6i + + --HG-- + extra : rebase_source : 66181403dbe8ca8dab893edc8f4eec1991d544d0 +--- + widget/TextEvents.h | 11 ++++++ + widget/WidgetEventImpl.cpp | 36 ++++++++++++++++++++ + widget/cocoa/TextInputHandler.mm | 43 ++++++++++++++---------- + widget/gtk/nsGtkKeyUtils.cpp | 64 ++++++++++++++++++++++++++--------- + widget/gtk/nsGtkKeyUtils.h | 10 ++++++ + widget/tests/test_keycodes.xul | 41 ++++++++++++----------- + widget/windows/KeyboardLayout.cpp | 70 ++++++++++++++++++++++++++++++++++++++- + 7 files changed, 223 insertions(+), 52 deletions(-) + +diff --git widget/TextEvents.h widget/TextEvents.h +index f1a67ecfdf3d..015331e8287d 100644 +--- widget/TextEvents.h ++++ widget/TextEvents.h +@@ -459,6 +459,17 @@ public: + GetDOMCodeName(mCodeNameIndex, aCodeName); + } + ++ /** ++ * GetFallbackKeyCodeOfPunctuationKey() returns a DOM keyCode value for ++ * aCodeNameIndex. This is keyCode value of the key when active keyboard ++ * layout is ANSI (US), JIS or ABNT keyboard layout (the latter 2 layouts ++ * are used only when ANSI doesn't have the key). The result is useful ++ * if the key doesn't produce ASCII character with active keyboard layout ++ * nor with alternative ASCII capable keyboard layout. ++ */ ++ static uint32_t ++ GetFallbackKeyCodeOfPunctuationKey(CodeNameIndex aCodeNameIndex); ++ + bool IsModifierKeyEvent() const + { + return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE; +diff --git widget/WidgetEventImpl.cpp widget/WidgetEventImpl.cpp +index 5415d9889be9..c379e7301b21 100644 +--- widget/WidgetEventImpl.cpp ++++ widget/WidgetEventImpl.cpp +@@ -1183,6 +1183,42 @@ WidgetKeyboardEvent::GetCodeNameIndex(const nsAString& aCodeValue) + return result; + } + ++/* static */ uint32_t ++WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey( ++ CodeNameIndex aCodeNameIndex) ++{ ++ switch (aCodeNameIndex) { ++ case CODE_NAME_INDEX_Semicolon: // VK_OEM_1 on Windows ++ return nsIDOMKeyEvent::DOM_VK_SEMICOLON; ++ case CODE_NAME_INDEX_Equal: // VK_OEM_PLUS on Windows ++ return nsIDOMKeyEvent::DOM_VK_EQUALS; ++ case CODE_NAME_INDEX_Comma: // VK_OEM_COMMA on Windows ++ return nsIDOMKeyEvent::DOM_VK_COMMA; ++ case CODE_NAME_INDEX_Minus: // VK_OEM_MINUS on Windows ++ return nsIDOMKeyEvent::DOM_VK_HYPHEN_MINUS; ++ case CODE_NAME_INDEX_Period: // VK_OEM_PERIOD on Windows ++ return nsIDOMKeyEvent::DOM_VK_PERIOD; ++ case CODE_NAME_INDEX_Slash: // VK_OEM_2 on Windows ++ return nsIDOMKeyEvent::DOM_VK_SLASH; ++ case CODE_NAME_INDEX_Backquote: // VK_OEM_3 on Windows ++ return nsIDOMKeyEvent::DOM_VK_BACK_QUOTE; ++ case CODE_NAME_INDEX_BracketLeft: // VK_OEM_4 on Windows ++ return nsIDOMKeyEvent::DOM_VK_OPEN_BRACKET; ++ case CODE_NAME_INDEX_Backslash: // VK_OEM_5 on Windows ++ return nsIDOMKeyEvent::DOM_VK_BACK_SLASH; ++ case CODE_NAME_INDEX_BracketRight: // VK_OEM_6 on Windows ++ return nsIDOMKeyEvent::DOM_VK_CLOSE_BRACKET; ++ case CODE_NAME_INDEX_Quote: // VK_OEM_7 on Windows ++ return nsIDOMKeyEvent::DOM_VK_QUOTE; ++ case CODE_NAME_INDEX_IntlBackslash: // VK_OEM_5 on Windows (ABNT, etc) ++ case CODE_NAME_INDEX_IntlYen: // VK_OEM_5 on Windows (JIS) ++ case CODE_NAME_INDEX_IntlRo: // VK_OEM_102 on Windows ++ return nsIDOMKeyEvent::DOM_VK_BACK_SLASH; ++ default: ++ return 0; ++ } ++} ++ + /* static */ const char* + WidgetKeyboardEvent::GetCommandStr(Command aCommand) + { +diff --git widget/cocoa/TextInputHandler.mm widget/cocoa/TextInputHandler.mm +index 437d8222ab3b..106ef0e91f52 100644 +--- widget/cocoa/TextInputHandler.mm ++++ widget/cocoa/TextInputHandler.mm +@@ -1410,25 +1410,34 @@ TISInputSourceWrapper::ComputeGeckoKeyCode(UInt32 aNativeKeyCode, + return keyCode; + } + +- // If this is ASCII capable, give up to compute it. +- if (IsASCIICapable()) { +- return 0; ++ if (!IsASCIICapable()) { ++ // Retry with ASCII capable keyboard layout. ++ TISInputSourceWrapper currentKeyboardLayout; ++ currentKeyboardLayout.InitByCurrentASCIICapableKeyboardLayout(); ++ NS_ENSURE_TRUE(mInputSource != currentKeyboardLayout.mInputSource, 0); ++ keyCode = currentKeyboardLayout.ComputeGeckoKeyCode(aNativeKeyCode, aKbType, ++ aCmdIsPressed); ++ // We've returned 0 for long time if keyCode isn't for an alphabet keys or ++ // a numeric key even in alternative ASCII capable keyboard layout because ++ // we decided that we should avoid setting same keyCode value to 2 or ++ // more keys since active keyboard layout may have a key to input the ++ // punctuation with different key. However, setting keyCode to 0 makes ++ // some web applications which are aware of neither KeyboardEvent.key nor ++ // KeyboardEvent.code not work with Firefox when user selects non-ASCII ++ // capable keyboard layout such as Russian and Thai. So, if alternative ++ // ASCII capable keyboard layout has keyCode value for the key, we should ++ // use it. In other words, this behavior does that non-ASCII capable ++ // keyboard layout overrides some keys' keyCode value only if the key ++ // produces ASCII character by itself or with Shift key. ++ if (keyCode) { ++ return keyCode; ++ } + } + +- // Retry with ASCII capable keyboard layout. +- TISInputSourceWrapper currentKeyboardLayout; +- currentKeyboardLayout.InitByCurrentASCIICapableKeyboardLayout(); +- NS_ENSURE_TRUE(mInputSource != currentKeyboardLayout.mInputSource, 0); +- keyCode = currentKeyboardLayout.ComputeGeckoKeyCode(aNativeKeyCode, aKbType, +- aCmdIsPressed); +- +- // However, if keyCode isn't for an alphabet keys or a numeric key, we should +- // ignore it. For example, comma key of Thai layout is same as close-square- +- // bracket key of US layout and an unicode character key of Thai layout is +- // same as comma key of US layout. If we return NS_VK_COMMA for latter key, +- // web application developers cannot distinguish with the former key. +- return ((keyCode >= NS_VK_A && keyCode <= NS_VK_Z) || +- (keyCode >= NS_VK_0 && keyCode <= NS_VK_9)) ? keyCode : 0; ++ // Otherwise, let's decide keyCode value from the native virtual keycode ++ // value on major keyboard layout. ++ CodeNameIndex code = ComputeGeckoCodeNameIndex(aNativeKeyCode, aKbType); ++ return WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(code); + } + + // static +diff --git widget/gtk/nsGtkKeyUtils.cpp widget/gtk/nsGtkKeyUtils.cpp +index bda2c2920248..a336c1ad6c92 100644 +--- widget/gtk/nsGtkKeyUtils.cpp ++++ widget/gtk/nsGtkKeyUtils.cpp +@@ -795,7 +795,7 @@ KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent) + + // If the unmodified character is not an ASCII character, that means we + // couldn't find the hint. We should reset it. +- if (unmodifiedChar > 0x7F) { ++ if (!IsPrintableASCIICharacter(unmodifiedChar)) { + unmodifiedChar = 0; + } + +@@ -814,7 +814,7 @@ KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent) + + // If the shifted unmodified character isn't an ASCII character, we should + // discard it too. +- if (shiftedChar > 0x7F) { ++ if (!IsPrintableASCIICharacter(shiftedChar)) { + shiftedChar = 0; + } + +@@ -822,14 +822,12 @@ KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent) + // look for ASCII alphabet inputtable keyboard layout. If the key + // inputs an ASCII alphabet or an ASCII numeric, we should use it + // for deciding our keyCode. +- // Note that it's important not to use alternative keyboard layout for ASCII +- // alphabet inputabble keyboard layout because the keycode for the key with +- // alternative keyboard layout may conflict with another key on current +- // keyboard layout. ++ uint32_t unmodCharLatin = 0; ++ uint32_t shiftedCharLatin = 0; + if (!keymapWrapper->IsLatinGroup(aGdkKeyEvent->group)) { + gint minGroup = keymapWrapper->GetFirstLatinGroup(); + if (minGroup >= 0) { +- uint32_t unmodCharLatin = ++ unmodCharLatin = + keymapWrapper->GetCharCodeFor(aGdkKeyEvent, baseState, + minGroup); + if (IsBasicLatinLetterOrNumeral(unmodCharLatin)) { +@@ -837,7 +835,13 @@ KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent) + // an ASCII numeric, we should use it for the keyCode. + return WidgetUtils::ComputeKeyCodeFromChar(unmodCharLatin); + } +- uint32_t shiftedCharLatin = ++ // If the unmodified character in the alternative ASCII capable ++ // keyboard layout isn't an ASCII character, that means we couldn't ++ // find the hint. We should reset it. ++ if (!IsPrintableASCIICharacter(unmodCharLatin)) { ++ unmodCharLatin = 0; ++ } ++ shiftedCharLatin = + keymapWrapper->GetCharCodeFor(aGdkKeyEvent, shiftState, + minGroup); + if (IsBasicLatinLetterOrNumeral(shiftedCharLatin)) { +@@ -845,16 +849,46 @@ KeymapWrapper::ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent) + // numeric, we should use it for the keyCode. + return WidgetUtils::ComputeKeyCodeFromChar(shiftedCharLatin); + } ++ // If the shifted unmodified character in the alternative ASCII ++ // capable keyboard layout isn't an ASCII character, we should ++ // discard it too. ++ if (!IsPrintableASCIICharacter(shiftedCharLatin)) { ++ shiftedCharLatin = 0; ++ } + } + } + +- // If unmodified character is in ASCII range, use it. Otherwise, use +- // shifted character. +- if (!unmodifiedChar && !shiftedChar) { +- return 0; +- } +- return WidgetUtils::ComputeKeyCodeFromChar( +- unmodifiedChar ? unmodifiedChar : shiftedChar); ++ // If the key itself or with Shift state on active keyboard layout produces ++ // an ASCII punctuation character, we should decide keyCode value with it. ++ if (unmodifiedChar || shiftedChar) { ++ return WidgetUtils::ComputeKeyCodeFromChar( ++ unmodifiedChar ? unmodifiedChar : shiftedChar); ++ } ++ ++ // If the key itself or with Shift state on alternative ASCII capable ++ // keyboard layout produces an ASCII punctuation character, we should ++ // decide keyCode value with it. Note that We've returned 0 for long ++ // time if keyCode isn't for an alphabet keys or a numeric key even in ++ // alternative ASCII capable keyboard layout because we decided that we ++ // should avoid setting same keyCode value to 2 or more keys since active ++ // keyboard layout may have a key to input the punctuation with different ++ // key. However, setting keyCode to 0 makes some web applications which ++ // are aware of neither KeyboardEvent.key nor KeyboardEvent.code not work ++ // with Firefox when user selects non-ASCII capable keyboard layout such ++ // as Russian and Thai. So, if alternative ASCII capable keyboard layout ++ // has keyCode value for the key, we should use it. In other words, this ++ // behavior means that non-ASCII capable keyboard layout overrides some ++ // keys' keyCode value only if the key produces ASCII character by itself ++ // or with Shift key. ++ if (unmodCharLatin || shiftedCharLatin) { ++ return WidgetUtils::ComputeKeyCodeFromChar( ++ unmodCharLatin ? unmodCharLatin : shiftedCharLatin); ++ } ++ ++ // Otherwise, let's decide keyCode value from the hardware_keycode ++ // value on major keyboard layout. ++ CodeNameIndex code = ComputeDOMCodeNameIndex(aGdkKeyEvent); ++ return WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(code); + } + + KeyNameIndex +diff --git widget/gtk/nsGtkKeyUtils.h widget/gtk/nsGtkKeyUtils.h +index 480d02322752..3dc8a4f6a936 100644 +--- widget/gtk/nsGtkKeyUtils.h ++++ widget/gtk/nsGtkKeyUtils.h +@@ -337,6 +337,16 @@ protected: + */ + static bool IsBasicLatinLetterOrNumeral(uint32_t aCharCode); + ++ /** ++ * IsPrintableASCIICharacter() checks whether the aCharCode is a printable ++ * ASCII character. I.e., returns false if aCharCode is a control ++ * character even in an ASCII character. ++ */ ++ static bool IsPrintableASCIICharacter(uint32_t aCharCode) ++ { ++ return aCharCode >= 0x20 && aCharCode <= 0x7E; ++ } ++ + /** + * GetGDKKeyvalWithoutModifier() returns the keyval for aGdkKeyEvent when + * ignoring the modifier state except NumLock. (NumLock is a key to change +diff --git widget/tests/test_keycodes.xul widget/tests/test_keycodes.xul +index 8a935e74a7f4..db789e8be367 100644 +--- widget/tests/test_keycodes.xul ++++ widget/tests/test_keycodes.xul +@@ -494,7 +494,7 @@ function* runKeyEventTests() + "a", "KeyA", nsIDOMKeyEvent.DOM_VK_A, "a", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_GERMAN, keyCode:MAC_VK_ANSI_LeftBracket, + modifiers: {}, chars:"\u00fc", unmodifiedChars:"\u00fc"}, +- "\u00fc", "BracketLeft", 0, "\u00fc", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "\u00fc", "BracketLeft", nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET, "\u00fc", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_GERMAN, keyCode:MAC_VK_ANSI_Minus, + modifiers: {}, chars:"\u00df", unmodifiedChars:"\u00df"}, + "\u00df", "Minus", nsIDOMKeyEvent.DOM_VK_QUESTION_MARK, "\u00df", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); +@@ -2737,10 +2737,9 @@ function* runKeyEventTests() + yield testKey({layout:KEYBOARD_LAYOUT_THAI, keyCode:MAC_VK_ANSI_Quote, + modifiers:{}, chars:"\u0E07", unmodifiedChars:"\u0E07"}, + "\u0E07", "Quote", nsIDOMKeyEvent.DOM_VK_PERIOD, "\u0E07", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); +- // keycode should be zero if the character of the key on the latest ASCII capable keyboard layout isn't for alphabet + yield testKey({layout:KEYBOARD_LAYOUT_THAI, keyCode:MAC_VK_ANSI_Period, + modifiers:{}, chars:"\u0E43", unmodifiedChars:"\u0E43"}, +- "\u0E43", "Period", 0, "\u0E43", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "\u0E43", "Period", nsIDOMKeyEvent.DOM_VK_PERIOD, "\u0E43", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + // keycode should be DOM_VK_[0-9] if the key on the latest ASCII capable keyboard layout is for numeric + yield testKey({layout:KEYBOARD_LAYOUT_THAI, keyCode:MAC_VK_ANSI_1, + modifiers:{}, chars:"\u0E45", unmodifiedChars:"\u0E45"}, +@@ -4129,12 +4128,14 @@ function* runKeyEventTests() + "\u00E7", "Digit9", nsIDOMKeyEvent.DOM_VK_9, "\u00E7", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + // OEM keys ++ // If the key doesn't cause ASCII character even with or without Shift key, keyCode value should be same as ++ // the key which causes the virtual keycode on ANSI keyboard layout. + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_7, + modifiers:{}, chars:"\u00B2"}, +- "\u00B2", "Backquote", 0, "\u00B2", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "\u00B2", "Backquote", nsIDOMKeyEvent.DOM_VK_QUOTE, "\u00B2", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_7, + modifiers:{shiftKey:1}, chars:""}, +- "", "Backquote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "", "Backquote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_4, + modifiers:{}, chars:")"}, + ")", "Minus", nsIDOMKeyEvent.DOM_VK_CLOSE_PAREN, ")", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); +@@ -4205,10 +4206,10 @@ function* runKeyEventTests() + // OEM keys with ShiftLock + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_7, + modifiers:{capsLockKey:1}, chars:"\u00B2"}, +- "\u00B2", "Backquote", 0, "\u00B2", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "\u00B2", "Backquote", nsIDOMKeyEvent.DOM_VK_QUOTE, "\u00B2", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_7, + modifiers:{capsLockKey:1, shiftKey:1}, chars:""}, +- "", "Backquote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "", "Backquote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_4, + modifiers:{capsLockKey:1}, chars:"\u00B0"}, + "\u00B0", "Minus", nsIDOMKeyEvent.DOM_VK_CLOSE_PAREN, "\u00B0", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); +@@ -4223,10 +4224,10 @@ function* runKeyEventTests() + "=", "Equal", nsIDOMKeyEvent.DOM_VK_EQUALS, "=", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + //yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_6, + // modifiers:{capsLockKey:1}, chars:""}, +- // "Dead", "BracketLeft", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); // Dead-key ++ // "Dead", "BracketLeft", nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); // Dead-key + //yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_6, + // modifiers:{capsLockKey:1, shiftKey:1}, chars:""}, +- // ["\u00A8\u00A8", "\u00A8", "\u00A8", "\u00A8"], "BracketLeft", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); // Dead-key ++ // ["\u00A8\u00A8", "\u00A8", "\u00A8", "\u00A8"], "BracketLeft", nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); // Dead-key + yield testKey({layout:KEYBOARD_LAYOUT_FRENCH, keyCode:WIN_VK_OEM_1, + modifiers:{capsLockKey:1}, chars:"\u00A3"}, + "\u00A3", "BracketRight", nsIDOMKeyEvent.DOM_VK_DOLLAR, "\u00A3", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); +@@ -4496,56 +4497,56 @@ function* runKeyEventTests() + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{}, chars:"\u00B4\u00B4"}, +- ["\u00B4\u00B4", "\u00B4", "\u00B4", "\u00B4"], "Quote", 0, "\u00B4\u00B4", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ ["\u00B4\u00B4", "\u00B4", "\u00B4", "\u00B4"], "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "\u00B4\u00B4", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_A, + modifiers:{}, chars:"\u00E1"}, + ["\u00E1", "\u00E1", "a"], "KeyA", nsIDOMKeyEvent.DOM_VK_A, "\u00E1", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_A, + modifiers:{shiftKey:1}, chars:"\u00C1"}, + ["\u00C1", "\u00C1", "A"], "KeyA", nsIDOMKeyEvent.DOM_VK_A, "\u00C1", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_Q, + modifiers:{}, chars:"\u00B4q"}, + ["\u00B4q", "\u00B4", "q", "q"], "KeyQ", nsIDOMKeyEvent.DOM_VK_Q, "\u00B4q", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{shiftKey:1}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{shiftKey:1}, chars:"\u00A8\u00A8"}, +- ["\u00A8\u00A8", "\u00A8", "\u00A8", "\u00A8"], "Quote", 0, "\u00A8\u00A8", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ ["\u00A8\u00A8", "\u00A8", "\u00A8", "\u00A8"], "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "\u00A8\u00A8", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{shiftKey:1}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_A, + modifiers:{shiftKey:1}, chars:"\u00C4"}, + ["\u00C4", "\u00C4", "A"], "KeyA", nsIDOMKeyEvent.DOM_VK_A, "\u00C4", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{shiftKey:1}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_A, + modifiers:{}, chars:"\u00E4"}, + ["\u00E4", "\u00E4", "a"], "KeyA", nsIDOMKeyEvent.DOM_VK_A, "\u00E4", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_OEM_7, + modifiers:{shiftKey:1}, chars:""}, +- "Dead", "Quote", 0, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); ++ "Dead", "Quote", nsIDOMKeyEvent.DOM_VK_QUOTE, "", SHOULD_DELIVER_KEYDOWN_KEYUP, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); + yield testKey({layout:KEYBOARD_LAYOUT_SPANISH, keyCode:WIN_VK_Q, + modifiers:{shiftKey:1}, chars:"\u00A8Q"}, + ["\u00A8Q", "\u00A8", "Q", "Q"], "KeyQ", nsIDOMKeyEvent.DOM_VK_Q, "\u00A8Q", SHOULD_DELIVER_ALL, KeyboardEvent.DOM_KEY_LOCATION_STANDARD); +diff --git widget/windows/KeyboardLayout.cpp widget/windows/KeyboardLayout.cpp +index e29c0b0655d9..947e914e4bef 100644 +--- widget/windows/KeyboardLayout.cpp ++++ widget/windows/KeyboardLayout.cpp +@@ -4721,7 +4721,75 @@ KeyboardLayout::ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const + uniChars = GetUniCharsAndModifiers(aNativeKeyCode, modKeyState); + if (uniChars.Length() != 1 || + uniChars.CharAt(0) < ' ' || uniChars.CharAt(0) > 0x7F) { +- return 0; ++ // In this case, we've returned 0 in this case for long time because ++ // we decided that we should avoid setting same keyCode value to 2 or ++ // more keys since active keyboard layout may have a key to input the ++ // punctuation with different key. However, setting keyCode to 0 ++ // makes some web applications which are aware of neither ++ // KeyboardEvent.key nor KeyboardEvent.code not work with Firefox ++ // when user selects non-ASCII capable keyboard layout such as ++ // Russian and Thai layout. So, let's decide keyCode value with ++ // major keyboard layout's key which causes the OEM keycode. ++ // Actually, this maps same keyCode value to 2 keys on Russian ++ // keyboard layout. "Period" key causes VK_OEM_PERIOD but inputs ++ // Yu of Cyrillic and "Slash" key causes VK_OEM_2 (same as US ++ // keyboard layout) but inputs "." (period of ASCII). Therefore, ++ // we return DOM_VK_PERIOD which is same as VK_OEM_PERIOD for ++ // "Period" key. On the other hand, we use same keyCode value for ++ // "Slash" key too because it inputs ".". ++ CodeNameIndex code; ++ switch (aNativeKeyCode) { ++ case VK_OEM_1: ++ code = CODE_NAME_INDEX_Semicolon; ++ break; ++ case VK_OEM_PLUS: ++ code = CODE_NAME_INDEX_Equal; ++ break; ++ case VK_OEM_COMMA: ++ code = CODE_NAME_INDEX_Comma; ++ break; ++ case VK_OEM_MINUS: ++ code = CODE_NAME_INDEX_Minus; ++ break; ++ case VK_OEM_PERIOD: ++ code = CODE_NAME_INDEX_Period; ++ break; ++ case VK_OEM_2: ++ code = CODE_NAME_INDEX_Slash; ++ break; ++ case VK_OEM_3: ++ code = CODE_NAME_INDEX_Backquote; ++ break; ++ case VK_OEM_4: ++ code = CODE_NAME_INDEX_BracketLeft; ++ break; ++ case VK_OEM_5: ++ code = CODE_NAME_INDEX_Backslash; ++ break; ++ case VK_OEM_6: ++ code = CODE_NAME_INDEX_BracketRight; ++ break; ++ case VK_OEM_7: ++ code = CODE_NAME_INDEX_Quote; ++ break; ++ case VK_OEM_8: ++ // Use keyCode value for "Backquote" key on UK keyboard layout. ++ code = CODE_NAME_INDEX_Backquote; ++ break; ++ case VK_OEM_102: ++ // Use keyCode value for "IntlBackslash" key. ++ code = CODE_NAME_INDEX_IntlBackslash; ++ break; ++ case VK_ABNT_C1: // "/" of ABNT. ++ // Use keyCode value for "IntlBackslash" key on ABNT keyboard ++ // layout. ++ code = CODE_NAME_INDEX_IntlBackslash; ++ break; ++ default: ++ MOZ_ASSERT_UNREACHABLE("Handle all OEM keycode values"); ++ return 0; ++ } ++ return WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(code); + } + } + return WidgetUtils::ComputeKeyCodeFromChar(uniChars.CharAt(0)); diff --git a/www/waterfox/files/patch-bug1134077 b/www/waterfox/files/patch-bug1134077 new file mode 100644 index 000000000000..ba8b29523d64 --- /dev/null +++ b/www/waterfox/files/patch-bug1134077 @@ -0,0 +1,65 @@ +commit a67756af6ac4 +Author: decltype <mozilla@decltype.org> +Date: Fri Feb 2 18:39:37 2018 +0100 + + Bug 1134077 - X11: Set EWMH property to keep top-level nsWindows composited. r=karlt + + Some compositors such as GNOME mutter use heuristics to unredirect fullscreen + windows in an effort to reduce output latency. This works fine for applications + that take the proper steps to ensure all framebuffer updates happen in the + vblank interval. Since this is not currently the case for Firefox, bypassing + the compositor will lead to frame tearing. + + Set _NET_WM_BYPASS_COMPOSITOR to 2 to opt out of fullscreen unredirection. + + MozReview-Commit-ID: 1xW2VAnbiJw + + --HG-- + extra : rebase_source : 77c4ae490413057d8d9dadf9b155c86ddbbcb4b5 +--- + widget/gtk/mozgtk/mozgtk.c | 1 + + widget/gtk/nsWindow.cpp | 19 +++++++++++++++++++ + 2 files changed, 20 insertions(+) + +diff --git widget/gtk/mozgtk/mozgtk.c widget/gtk/mozgtk/mozgtk.c +index a182d9b278e7..023cd192d522 100644 +--- widget/gtk/mozgtk/mozgtk.c ++++ widget/gtk/mozgtk/mozgtk.c +@@ -52,6 +52,7 @@ STUB(gdk_keyval_to_unicode) + STUB(gdk_pango_context_get) + STUB(gdk_pointer_grab) + STUB(gdk_pointer_ungrab) ++STUB(gdk_property_change) + STUB(gdk_property_get) + STUB(gdk_screen_get_default) + STUB(gdk_screen_get_display) +diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp +index 0e75cc8c5968..b59ac05dd3c4 100644 +--- widget/gtk/nsWindow.cpp ++++ widget/gtk/nsWindow.cpp +@@ -3803,6 +3803,25 @@ nsWindow::Create(nsIWidget* aParent, + cairo_region_destroy(region); + } + } ++ ++#ifdef MOZ_X11 ++ // Set window manager hint to keep fullscreen windows composited. ++ // ++ // If the window were to get unredirected, there could be visible ++ // tearing because Gecko does not align its framebuffer updates with ++ // vblank. ++ if (mIsX11Display) { ++ gulong value = 2; // Opt out of unredirection ++ GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL); ++ gdk_property_change(gtk_widget_get_window(mShell), ++ gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE), ++ cardinal_atom, ++ 32, // format ++ GDK_PROP_MODE_REPLACE, ++ (guchar*)&value, ++ 1); ++ } ++#endif + } + break; + diff --git a/www/waterfox/files/patch-bug1144632 b/www/waterfox/files/patch-bug1144632 new file mode 100644 index 000000000000..fee10b5db317 --- /dev/null +++ b/www/waterfox/files/patch-bug1144632 @@ -0,0 +1,23 @@ +Revert bug 1323303 to unbreak build on big-endian architectures. + +diff --git toolkit/moz.configure toolkit/moz.configure +index 67fcbc39d075..c117fd11a358 100644 +--- toolkit/moz.configure ++++ toolkit/moz.configure +@@ -1032,11 +1032,11 @@ add_old_configure_assignment('NECKO_PROTOCOLS', necko_protocols) + # ============================================================== + option('--disable-skia', help='Disable use of Skia') + +-@depends('--disable-skia') +-def skia(value): +- if not value: +- die('--disable-skia is not supported anymore') +- else: ++@depends('--disable-skia', target) ++def skia(value, target): ++ if value.origin == 'default' and target.endianness == 'big': ++ return None ++ if value: + return True + + set_config('MOZ_ENABLE_SKIA', skia) diff --git a/www/waterfox/files/patch-bug1186967 b/www/waterfox/files/patch-bug1186967 new file mode 100644 index 000000000000..26d304fbd3e9 --- /dev/null +++ b/www/waterfox/files/patch-bug1186967 @@ -0,0 +1,41 @@ +commit 64bb4e051b50 +Author: Martin Stransky <stransky@redhat.com> +Date: Tue Oct 17 09:50:18 2017 +0200 + + Bug 1186967 - ignore double-click on WM without _NET_WM_MOVERESIZE support, r=jhorak + + MozReview-Commit-ID: 2Vs6i5leero + + --HG-- + extra : rebase_source : d8f2bbaf9ef9b2025478f029a68ee7e87e07de79 +--- + widget/gtk/nsWindow.cpp | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp +index eb2f0e5e95cd..955327297ac9 100644 +--- widget/gtk/nsWindow.cpp ++++ widget/gtk/nsWindow.cpp +@@ -6444,6 +6444,22 @@ nsWindow::GetDragInfo(WidgetMouseEvent* aMouseEvent, + return false; + } + ++ if (mIsX11Display) { ++ // Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=789054 ++ // To avoid crashes disable double-click on WM without _NET_WM_MOVERESIZE. ++ // See _should_perform_ewmh_drag() at gdkwindow-x11.c ++ GdkScreen* screen = gdk_window_get_screen(gdk_window); ++ GdkAtom atom = gdk_atom_intern("_NET_WM_MOVERESIZE", FALSE); ++ if (!gdk_x11_screen_supports_net_wm_hint(screen, atom)) { ++ static unsigned int lastTimeStamp = 0; ++ if (lastTimeStamp != aMouseEvent->mTime) { ++ lastTimeStamp = aMouseEvent->mTime; ++ } else { ++ return false; ++ } ++ } ++ } ++ + // FIXME: It would be nice to have the widget position at the time + // of the event, but it's relatively unlikely that the widget has + // moved since the mousedown. (On the other hand, it's quite likely diff --git a/www/waterfox/files/patch-bug1203273 b/www/waterfox/files/patch-bug1203273 new file mode 100644 index 000000000000..31894b5bb011 --- /dev/null +++ b/www/waterfox/files/patch-bug1203273 @@ -0,0 +1,68 @@ +commit 18bd60050c9c +Author: Jon Coppeard <jcoppeard@mozilla.com> +Date: Tue Mar 20 10:19:37 2018 +0000 + + Bug 1203273 - Add a canary to check gray buffers are valid. r=sfink, a=RyanVM + + --HG-- + extra : source : b1dacff4b3744f303f04ad9f53c670608af8b17a +--- + js/src/gc/RootMarking.cpp | 23 ++++++++++++++++++++++- + 1 file changed, 22 insertions(+), 1 deletion(-) + +diff --git js/src/gc/RootMarking.cpp js/src/gc/RootMarking.cpp +index 384edb9fdd2a..a5c408b687b9 100644 +--- js/src/gc/RootMarking.cpp ++++ js/src/gc/RootMarking.cpp +@@ -460,6 +460,7 @@ class BufferGrayRootsTracer final : public JS::CallbackTracer + {} + + bool failed() const { return bufferingGrayRootsFailed; } ++ void setFailed() { bufferingGrayRootsFailed = true; } + + #ifdef DEBUG + TracerKind getTracerKind() const override { return TracerKind::GrayBuffering; } +@@ -477,6 +478,9 @@ js::IsBufferGrayRootsTracer(JSTracer* trc) + } + #endif + ++// A canary value used to check the gray buffer contents are valid. ++static Cell* const GrayBufferCanary = reinterpret_cast<Cell*>(0x47726179); // "Gray" ++ + void + js::gc::GCRuntime::bufferGrayRoots() + { +@@ -490,6 +494,12 @@ js::gc::GCRuntime::bufferGrayRoots() + if (JSTraceDataOp op = grayRootTracer.op) + (*op)(&grayBufferer, grayRootTracer.data); + ++ // Push a canary value onto the end of the list. ++ for (GCZonesIter zone(rt); !zone.done(); zone.next()) { ++ if (!zone->gcGrayRoots().empty() && !zone->gcGrayRoots().append(GrayBufferCanary)) ++ grayBufferer.setFailed(); ++ } ++ + // Propagate the failure flag from the marker to the runtime. + if (grayBufferer.failed()) { + grayBufferState = GrayBufferState::Failed; +@@ -531,8 +541,19 @@ GCRuntime::markBufferedGrayRoots(JS::Zone* zone) + MOZ_ASSERT(grayBufferState == GrayBufferState::Okay); + MOZ_ASSERT(zone->isGCMarkingGray() || zone->isGCCompacting()); + +- for (auto cell : zone->gcGrayRoots()) ++ auto& roots = zone->gcGrayRoots(); ++ if (roots.empty()) ++ return; ++ ++ // Check for and remove canary value. ++ MOZ_RELEASE_ASSERT(roots.length() > 1); ++ MOZ_RELEASE_ASSERT(roots.back() == GrayBufferCanary); ++ roots.popBack(); ++ ++ for (auto cell : zone->gcGrayRoots()) { ++ MOZ_ASSERT(IsCellPointerValid(cell)); + TraceManuallyBarrieredGenericPointerEdge(&marker, &cell, "buffered gray root"); ++ } + } + + void diff --git a/www/waterfox/files/patch-bug1231203 b/www/waterfox/files/patch-bug1231203 new file mode 100644 index 000000000000..7ce1d4e74325 --- /dev/null +++ b/www/waterfox/files/patch-bug1231203 @@ -0,0 +1,203 @@ +commit ef357e507dd1 +Author: David Keeler <dkeeler@mozilla.com> +Date: Thu Feb 8 17:16:03 2018 -0800 + + bug 1231203 - ensure OCSP responses to requests from private contexts aren't cached on disk r=jcj a=ritu + + MozReview-Commit-ID: 374f7hERLee + + --HG-- + extra : source : ee10aee44d26bf6eb3ddc5f54ddbbbb4fdeb4b0d +--- + security/manager/ssl/nsNSSCallbacks.cpp | 12 ++- + security/manager/ssl/tests/unit/head_psm.js | 8 +- + .../ssl/tests/unit/test_ocsp_private_caching.js | 112 +++++++++++++++++++++ + security/manager/ssl/tests/unit/xpcshell.ini | 2 + + 4 files changed, 130 insertions(+), 4 deletions(-) + +diff --git security/manager/ssl/nsNSSCallbacks.cpp security/manager/ssl/nsNSSCallbacks.cpp +index 7288a7f2c725..d3b973362ab1 100644 +--- security/manager/ssl/nsNSSCallbacks.cpp ++++ security/manager/ssl/nsNSSCallbacks.cpp +@@ -119,13 +119,19 @@ nsHTTPDownloadEvent::Run() + chan->SetLoadFlags(nsIRequest::LOAD_ANONYMOUS | + nsIChannel::LOAD_BYPASS_SERVICE_WORKER); + +- // For OCSP requests, only the first party domain aspect of origin attributes +- // is used. This means that OCSP requests are shared across different +- // containers. ++ // For OCSP requests, only the first party domain and private browsing id ++ // aspects of origin attributes are used. This means that: ++ // a) if first party isolation is enabled, OCSP requests will be isolated ++ // according to the first party domain of the original https request ++ // b) OCSP requests are shared across different containers as long as first ++ // party isolation is not enabled and none of the containers are in private ++ // browsing mode. + if (mRequestSession->mOriginAttributes != OriginAttributes()) { + OriginAttributes attrs; + attrs.mFirstPartyDomain = + mRequestSession->mOriginAttributes.mFirstPartyDomain; ++ attrs.mPrivateBrowsingId = ++ mRequestSession->mOriginAttributes.mPrivateBrowsingId; + + nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo(); + if (loadInfo) { +diff --git security/manager/ssl/tests/unit/head_psm.js security/manager/ssl/tests/unit/head_psm.js +index 6e0d41125549..51e2beb7ce1d 100644 +--- security/manager/ssl/tests/unit/head_psm.js ++++ security/manager/ssl/tests/unit/head_psm.js +@@ -609,9 +609,12 @@ function getFailingHttpServer(serverPort, serverIdentities) { + // by which HTTP method the server is expected to be queried. + // expectedResponseTypes is an optional array of OCSP response types to use (see + // GenerateOCSPResponse.cpp). ++// responseHeaderPairs is an optional array of HTTP header (name, value) pairs ++// to set in each response. + function startOCSPResponder(serverPort, identity, nssDBLocation, + expectedCertNames, expectedBasePaths, +- expectedMethods, expectedResponseTypes) { ++ expectedMethods, expectedResponseTypes, ++ responseHeaderPairs = []) { + let ocspResponseGenerationArgs = expectedCertNames.map( + function(expectedNick) { + let responseType = "good"; +@@ -640,6 +643,9 @@ function startOCSPResponder(serverPort, identity, nssDBLocation, + } + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); + aResponse.setHeader("Content-Type", "application/ocsp-response"); ++ for (let headerPair of responseHeaderPairs) { ++ aResponse.setHeader(headerPair[0], headerPair[1]); ++ } + aResponse.write(ocspResponses.shift()); + }); + httpServer.identity.setPrimary("http", identity, serverPort); +diff --git security/manager/ssl/tests/unit/test_ocsp_private_caching.js security/manager/ssl/tests/unit/test_ocsp_private_caching.js +new file mode 100644 +index 000000000000..b61252eb6e6f +--- /dev/null ++++ security/manager/ssl/tests/unit/test_ocsp_private_caching.js +@@ -0,0 +1,112 @@ ++// -*- indent-tabs-mode: nil; js-indent-level: 2 -*- ++// This Source Code Form is subject to the terms of the Mozilla Public ++// License, v. 2.0. If a copy of the MPL was not distributed with this ++// file, You can obtain one at http://mozilla.org/MPL/2.0/. ++ ++"use strict"; ++ ++// In which we connect to a host and encounter OCSP responses with the ++// Cache-Control header set, which Necko will normally cache. We need to ensure ++// that these responses aren't cached to disk when the original https request ++// was in a private context. ++ ++do_get_profile(); // must be called before getting nsIX509CertDB ++const certdb = Cc["@mozilla.org/security/x509certdb;1"] ++ .getService(Ci.nsIX509CertDB); ++ ++const SERVER_PORT = 8888; ++ ++function start_ocsp_responder(expectedCertNames, expectedPaths, ++ expectedMethods) { ++ return startOCSPResponder(SERVER_PORT, "www.example.com", ++ "test_ocsp_fetch_method", expectedCertNames, ++ expectedPaths, expectedMethods); ++} ++ ++function check_cert_err(cert_name, expected_error) { ++ let cert = constructCertFromFile("test_ocsp_fetch_method/" + cert_name + ".pem"); ++ return checkCertErrorGeneric(certdb, cert, expected_error, ++ certificateUsageSSLServer); ++} ++ ++function add_flush_cache() { ++ add_test(() => { ++ // This appears to either fire multiple times or fire once for every ++ // observer that has ever been passed to flush. To prevent multiple calls to ++ // run_next_test, keep track of if this observer has already called it. ++ let observed = false; ++ let observer = { observe: () => { ++ if (!observed) { ++ observed = true; ++ run_next_test(); ++ } ++ } ++ }; ++ Services.cache2.QueryInterface(Ci.nsICacheTesting).flush(observer); ++ }); ++} ++ ++function add_ocsp_necko_cache_test(loadContext, shouldFindEntry) { ++ // Pre-testcase cleanup/setup. ++ add_test(() => { ++ Services.cache2.clear(); ++ run_next_test(); ++ }); ++ add_flush_cache(); ++ ++ let responder; ++ add_test(() => { ++ clearOCSPCache(); ++ clearSessionCache(); ++ responder = startOCSPResponder(SERVER_PORT, "localhost", "ocsp_certs", ++ ["default-ee"], [], [], [], ++ [["Cache-Control", "max-age: 1000"]]); ++ run_next_test(); ++ }); ++ ++ // Prepare a connection that will cause an OCSP request. ++ add_connection_test("ocsp-stapling-none.example.com", PRErrorCodeSuccess, ++ null, null, null, loadContext.originAttributes); ++ ++ add_flush_cache(); ++ ++ // Traverse the cache and ensure the response made it into the cache with the ++ // appropriate properties (private or not private). ++ add_test(() => { ++ let foundEntry = false; ++ let visitor = { ++ onCacheStorageInfo() {}, ++ onCacheEntryInfo(aURI, aIdEnhance, aDataSize, aFetchCount, ++ aLastModifiedTime, aExpirationTime, aPinned, aInfo) { ++ Assert.equal(aURI.spec, "http://localhost:8888/", ++ "expected OCSP request URI should match"); ++ foundEntry = true; ++ }, ++ onCacheEntryVisitCompleted() { ++ Assert.equal(foundEntry, shouldFindEntry, ++ "should only find a cached entry if we're expecting one"); ++ run_next_test(); ++ }, ++ QueryInterface(iid) { ++ if (iid.equals(Ci.nsICacheStorageVisitor)) { ++ return this; ++ } ++ throw Cr.NS_ERROR_NO_INTERFACE; ++ }, ++ }; ++ Services.cache2.asyncVisitAllStorages(visitor, true); ++ }); ++ ++ // Clean up (stop the responder). ++ add_test(() => { ++ responder.stop(run_next_test); ++ }); ++} ++ ++function run_test() { ++ Services.prefs.setIntPref("security.OCSP.enabled", 1); ++ add_tls_server_setup("OCSPStaplingServer", "ocsp_certs"); ++ add_ocsp_necko_cache_test(Services.loadContextInfo.private, false); ++ add_ocsp_necko_cache_test(Services.loadContextInfo.default, true); ++ run_next_test(); ++} +diff --git security/manager/ssl/tests/unit/xpcshell.ini security/manager/ssl/tests/unit/xpcshell.ini +index b85c775514eb..4dbe59ac5e73 100644 +--- security/manager/ssl/tests/unit/xpcshell.ini ++++ security/manager/ssl/tests/unit/xpcshell.ini +@@ -121,6 +121,8 @@ run-sequentially = hardcoded ports + run-sequentially = hardcoded ports + [test_ocsp_must_staple.js] + run-sequentially = hardcoded ports ++[test_ocsp_private_caching.js] ++run-sequentially = hardcoded ports + [test_ocsp_no_hsts_upgrade.js] + run-sequentially = hardcoded ports + [test_ocsp_required.js] diff --git a/www/waterfox/files/patch-bug1246883 b/www/waterfox/files/patch-bug1246883 new file mode 100644 index 000000000000..b515debb9f2b --- /dev/null +++ b/www/waterfox/files/patch-bug1246883 @@ -0,0 +1,56 @@ +commit b175b27efefd +Author: Mantaroh Yoshinaga <mantaroh@gmail.com> +Date: Wed Dec 13 08:58:05 2017 +0900 + + Bug 1246883 - Load UA Stylesheet when printing the SVG document. r=jwatt, a=gchang + + Currently, Gecko load only minimal-xul.css if the document is the SVG[1]. + In the case of printing SVG document, gecko should load ua.css for using style + which related to print. + + This patch will load ua.css when printing the SVG document. + + [1] http://searchfox.org/mozilla-central/rev/67f38de2443e6b613d874fcf4d2cd1f2fc3d5e97/layout/base/nsDocumentViewer.cpp#2472 + + MozReview-Commit-ID: JtdaEvX8QTw + + --HG-- + extra : source : 727a90ad06e715b3a4457b2532e922d22a2469a2 +--- + layout/printing/nsPrintEngine.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git layout/printing/nsPrintEngine.cpp layout/printing/nsPrintEngine.cpp +index f8d8f1077ba5..3ac2211d159d 100644 +--- layout/printing/nsPrintEngine.cpp ++++ layout/printing/nsPrintEngine.cpp +@@ -75,6 +75,7 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro + #include "nsISupportsUtils.h" + #include "nsIScriptContext.h" + #include "nsIDOMDocument.h" ++#include "nsIDocumentObserver.h" + #include "nsISelectionListener.h" + #include "nsISelectionPrivate.h" + #include "nsIDOMRange.h" +@@ -82,6 +83,7 @@ static const char kPrintingPromptService[] = "@mozilla.org/embedcomp/printingpro + #include "nsLayoutCID.h" + #include "nsContentUtils.h" + #include "nsIPresShell.h" ++#include "nsLayoutStylesheetCache.h" + #include "nsLayoutUtils.h" + #include "mozilla/Preferences.h" + +@@ -2267,6 +2269,13 @@ nsPrintEngine::ReflowPrintObject(const UniquePtr<nsPrintObject>& aPO) + + StyleSetHandle styleSet = mDocViewerPrint->CreateStyleSet(aPO->mDocument); + ++ if (aPO->mDocument->IsSVGDocument()) { ++ // The SVG document only loads minimal-xul.css, so it doesn't apply other ++ // styles. We should add ua.css for applying style which related to print. ++ auto cache = nsLayoutStylesheetCache::For(aPO->mDocument->GetStyleBackendType()); ++ styleSet->PrependStyleSheet(SheetType::Agent, cache->UASheet()); ++ } ++ + aPO->mPresShell = aPO->mDocument->CreateShell(aPO->mPresContext, + aPO->mViewManager, styleSet); + if (!aPO->mPresShell) { diff --git a/www/waterfox/files/patch-bug1275062 b/www/waterfox/files/patch-bug1275062 new file mode 100644 index 000000000000..e9183ad9a677 --- /dev/null +++ b/www/waterfox/files/patch-bug1275062 @@ -0,0 +1,344 @@ +commit 7b030826befa +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Sat Jan 27 13:40:58 2018 +0100 + + Bug 1275062 - Introduce a size check of IPC messages for IndexedDB. r=asuth, a=lizzard + + --HG-- + extra : source : ca73f9471eded208cbf1206f22e0fe9f10550497 +--- + dom/indexedDB/ActorsParent.cpp | 78 +++++++++++++++++++++++++++------- + dom/indexedDB/IndexedDatabase.h | 4 ++ + dom/indexedDB/IndexedDatabaseInlines.h | 14 ++++++ + 3 files changed, 80 insertions(+), 16 deletions(-) + +diff --git dom/indexedDB/ActorsParent.cpp dom/indexedDB/ActorsParent.cpp +index b9eb1744b8b6..aef19c8379be 100644 +--- dom/indexedDB/ActorsParent.cpp ++++ dom/indexedDB/ActorsParent.cpp +@@ -8173,7 +8173,7 @@ protected: + + // Subclasses use this override to set the IPDL response value. + virtual void +- GetResponse(RequestResponse& aResponse) = 0; ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) = 0; + + private: + nsresult +@@ -8237,7 +8237,7 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override; ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override; + + void + Cleanup() override; +@@ -8359,7 +8359,7 @@ private: + GetPreprocessParams(PreprocessParams& aParams) override; + + void +- GetResponse(RequestResponse& aResponse) override; ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override; + }; + + class ObjectStoreGetKeyRequestOp final +@@ -8385,7 +8385,7 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override; ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override; + }; + + class ObjectStoreDeleteRequestOp final +@@ -8407,9 +8407,10 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override + { + aResponse = Move(mResponse); ++ *aResponseSize = 0; + } + }; + +@@ -8432,9 +8433,10 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override + { + aResponse = Move(mResponse); ++ *aResponseSize = 0; + } + }; + +@@ -8459,9 +8461,10 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override + { + aResponse = Move(mResponse); ++ *aResponseSize = sizeof(uint64_t); + } + }; + +@@ -8511,7 +8514,7 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override; ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override; + }; + + class IndexGetKeyRequestOp final +@@ -8536,7 +8539,7 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override; ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override; + }; + + class IndexCountRequestOp final +@@ -8561,9 +8564,10 @@ private: + DoDatabaseWork(DatabaseConnection* aConnection) override; + + void +- GetResponse(RequestResponse& aResponse) override ++ GetResponse(RequestResponse& aResponse, size_t* aResponseSize) override + { + aResponse = Move(mResponse); ++ *aResponseSize = sizeof(uint64_t); + } + }; + +@@ -25726,8 +25730,22 @@ NormalTransactionOp::SendSuccessResult() + AssertIsOnOwningThread(); + + if (!IsActorDestroyed()) { ++ static const size_t kMaxIDBMsgOverhead = 1024 * 1024 * 10; // 10MB ++ const uint32_t maximalSizeFromPref = ++ IndexedDatabaseManager::MaxSerializedMsgSize(); ++ MOZ_ASSERT(maximalSizeFromPref > kMaxIDBMsgOverhead); ++ const size_t kMaxMessageSize = maximalSizeFromPref - kMaxIDBMsgOverhead; ++ + RequestResponse response; +- GetResponse(response); ++ size_t responseSize = kMaxMessageSize; ++ GetResponse(response, &responseSize); ++ ++ if (responseSize >= kMaxMessageSize) { ++ nsPrintfCString("The serialized value is too large" ++ " (size=%zu bytes, max=%zu bytes).", ++ responseSize, kMaxMessageSize); ++ return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; ++ } + + MOZ_ASSERT(response.type() != RequestResponse::T__None); + +@@ -26387,14 +26405,17 @@ ObjectStoreAddOrPutRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) + } + + void +-ObjectStoreAddOrPutRequestOp::GetResponse(RequestResponse& aResponse) ++ObjectStoreAddOrPutRequestOp::GetResponse(RequestResponse& aResponse, ++ size_t* aResponseSize) + { + AssertIsOnOwningThread(); + + if (mOverwrite) { + aResponse = ObjectStorePutResponse(mResponse); ++ *aResponseSize = mResponse.GetBuffer().Length(); + } else { + aResponse = ObjectStoreAddResponse(mResponse); ++ *aResponseSize = mResponse.GetBuffer().Length(); + } + } + +@@ -26688,12 +26709,14 @@ ObjectStoreGetRequestOp::GetPreprocessParams(PreprocessParams& aParams) + } + + void +-ObjectStoreGetRequestOp::GetResponse(RequestResponse& aResponse) ++ObjectStoreGetRequestOp::GetResponse(RequestResponse& aResponse, ++ size_t* aResponseSize) + { + MOZ_ASSERT_IF(mLimit, mResponse.Length() <= mLimit); + + if (mGetAll) { + aResponse = ObjectStoreGetAllResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { + FallibleTArray<SerializedStructuredCloneReadInfo> fallibleCloneInfos; +@@ -26706,6 +26729,7 @@ ObjectStoreGetRequestOp::GetResponse(RequestResponse& aResponse) + for (uint32_t count = mResponse.Length(), index = 0; + index < count; + index++) { ++ *aResponseSize += mResponse[index].Size(); + nsresult rv = + ConvertResponse<false>(mResponse[index], fallibleCloneInfos[index]); + if (NS_WARN_IF(NS_FAILED(rv))) { +@@ -26724,11 +26748,13 @@ ObjectStoreGetRequestOp::GetResponse(RequestResponse& aResponse) + } + + aResponse = ObjectStoreGetResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { + SerializedStructuredCloneReadInfo& serializedInfo = + aResponse.get_ObjectStoreGetResponse().cloneInfo(); + ++ *aResponseSize += mResponse[0].Size(); + nsresult rv = ConvertResponse<false>(mResponse[0], serializedInfo); + if (NS_WARN_IF(NS_FAILED(rv))) { + aResponse = rv; +@@ -26834,25 +26860,33 @@ ObjectStoreGetKeyRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) + } + + void +-ObjectStoreGetKeyRequestOp::GetResponse(RequestResponse& aResponse) ++ObjectStoreGetKeyRequestOp::GetResponse(RequestResponse& aResponse, ++ size_t* aResponseSize) + { + MOZ_ASSERT_IF(mLimit, mResponse.Length() <= mLimit); + + if (mGetAll) { + aResponse = ObjectStoreGetAllKeysResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { + nsTArray<Key>& response = + aResponse.get_ObjectStoreGetAllKeysResponse().keys(); ++ + mResponse.SwapElements(response); ++ for (uint32_t i = 0; i < mResponse.Length(); ++i) { ++ *aResponseSize += mResponse[i].GetBuffer().Length(); ++ } + } + + return; + } + + aResponse = ObjectStoreGetKeyResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { ++ *aResponseSize = mResponse[0].GetBuffer().Length(); + aResponse.get_ObjectStoreGetKeyResponse().key() = Move(mResponse[0]); + } + } +@@ -27284,12 +27318,14 @@ IndexGetRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) + } + + void +-IndexGetRequestOp::GetResponse(RequestResponse& aResponse) ++IndexGetRequestOp::GetResponse(RequestResponse& aResponse, ++ size_t* aResponseSize) + { + MOZ_ASSERT_IF(!mGetAll, mResponse.Length() <= 1); + + if (mGetAll) { + aResponse = IndexGetAllResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { + FallibleTArray<SerializedStructuredCloneReadInfo> fallibleCloneInfos; +@@ -27303,6 +27339,7 @@ IndexGetRequestOp::GetResponse(RequestResponse& aResponse) + index < count; + index++) { + StructuredCloneReadInfo& info = mResponse[index]; ++ *aResponseSize += info.Size(); + + SerializedStructuredCloneReadInfo& serializedInfo = + fallibleCloneInfos[index]; +@@ -27335,9 +27372,11 @@ IndexGetRequestOp::GetResponse(RequestResponse& aResponse) + } + + aResponse = IndexGetResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { + StructuredCloneReadInfo& info = mResponse[0]; ++ *aResponseSize += info.Size(); + + SerializedStructuredCloneReadInfo& serializedInfo = + aResponse.get_IndexGetResponse().cloneInfo(); +@@ -27467,23 +27506,30 @@ IndexGetKeyRequestOp::DoDatabaseWork(DatabaseConnection* aConnection) + } + + void +-IndexGetKeyRequestOp::GetResponse(RequestResponse& aResponse) ++IndexGetKeyRequestOp::GetResponse(RequestResponse& aResponse, ++ size_t* aResponseSize) + { + MOZ_ASSERT_IF(!mGetAll, mResponse.Length() <= 1); + + if (mGetAll) { + aResponse = IndexGetAllKeysResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { + mResponse.SwapElements(aResponse.get_IndexGetAllKeysResponse().keys()); ++ for (uint32_t i = 0; i < mResponse.Length(); ++i) { ++ *aResponseSize += mResponse[i].GetBuffer().Length(); ++ } + } + + return; + } + + aResponse = IndexGetKeyResponse(); ++ *aResponseSize = 0; + + if (!mResponse.IsEmpty()) { ++ *aResponseSize = mResponse[0].GetBuffer().Length(); + aResponse.get_IndexGetKeyResponse().key() = Move(mResponse[0]); + } + } +diff --git dom/indexedDB/IndexedDatabase.h dom/indexedDB/IndexedDatabase.h +index b0c4cb877a9c..9165758bcd62 100644 +--- dom/indexedDB/IndexedDatabase.h ++++ dom/indexedDB/IndexedDatabase.h +@@ -83,6 +83,10 @@ struct StructuredCloneReadInfo + // In IndexedDatabaseInlines.h + inline + MOZ_IMPLICIT StructuredCloneReadInfo(SerializedStructuredCloneReadInfo&& aOther); ++ ++ // In IndexedDatabaseInlines.h ++ inline ++ size_t Size() const; + }; + + } // namespace indexedDB +diff --git dom/indexedDB/IndexedDatabaseInlines.h dom/indexedDB/IndexedDatabaseInlines.h +index 830c2f11009d..48cc4f9b3ced 100644 +--- dom/indexedDB/IndexedDatabaseInlines.h ++++ dom/indexedDB/IndexedDatabaseInlines.h +@@ -99,6 +99,20 @@ StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo) + return *this; + } + ++inline size_t ++StructuredCloneReadInfo::Size() const ++{ ++ size_t size = mData.Size(); ++ ++ for (uint32_t i = 0, count = mFiles.Length(); i < count; ++i) { ++ // We don't want to calculate the size of files and so on, because are mainly ++ // file descriptors. ++ size += sizeof(uint64_t); ++ } ++ ++ return size; ++} ++ + } // namespace indexedDB + } // namespace dom + } // namespace mozilla diff --git a/www/waterfox/files/patch-bug1288587 b/www/waterfox/files/patch-bug1288587 new file mode 100644 index 000000000000..e10ef8537a4a --- /dev/null +++ b/www/waterfox/files/patch-bug1288587 @@ -0,0 +1,67 @@ +diff --git a/build/moz.configure/init.configure b/build/moz.configure/init.configure +index 855214a..1e91d51 100644 +--- build/moz.configure/init.configure ++++ build/moz.configure/init.configure +@@ -165,16 +165,17 @@ option(env='PYTHON', nargs=1, help='Python interpreter') + # ============================================================== + @depends('PYTHON', check_build_environment, mozconfig, '--help') + @imports('os') + @imports('sys') + @imports('subprocess') + @imports(_from='mozbuild.configure.util', _import='LineIO') + @imports(_from='mozbuild.virtualenv', _import='VirtualenvManager') + @imports(_from='mozbuild.virtualenv', _import='verify_python_version') ++@imports(_from='__builtin__', _import='KeyError') + @imports('distutils.sysconfig') + def virtualenv_python(env_python, build_env, mozconfig, help): + if help: + return + + python = env_python[0] if env_python else None + + # Ideally we'd rely on the mozconfig injection from mozconfig_options, +@@ -184,16 +185,22 @@ def virtualenv_python(env_python, build_env, mozconfig, help): + if 'PYTHON' in mozconfig['env']['added']: + python = mozconfig['env']['added']['PYTHON'] + elif 'PYTHON' in mozconfig['env']['modified']: + python = mozconfig['env']['modified']['PYTHON'][1] + elif 'PYTHON' in mozconfig['vars']['added']: + python = mozconfig['vars']['added']['PYTHON'] + elif 'PYTHON' in mozconfig['vars']['modified']: + python = mozconfig['vars']['modified']['PYTHON'][1] ++ for i in ('env', 'vars'): ++ for j in ('added', 'modified'): ++ try: ++ del mozconfig[i][j]['PYTHON'] ++ except KeyError: ++ pass + + with LineIO(lambda l: log.error(l)) as out: + verify_python_version(out) + topsrcdir, topobjdir = build_env.topsrcdir, build_env.topobjdir + if topobjdir.endswith('/js/src'): + topobjdir = topobjdir[:-7] + + with LineIO(lambda l: log.info(l)) as out: +@@ -219,17 +226,20 @@ def virtualenv_python(env_python, build_env, mozconfig, help): + log.info('Creating Python environment') + manager.build(python) + + python = normsep(manager.python_path) + + if python != normsep(sys.executable): + log.info('Reexecuting in the virtualenv') + if env_python: +- del os.environ['PYTHON'] ++ try: ++ del os.environ['PYTHON'] ++ except KeyError: ++ pass + # One would prefer to use os.execl, but that's completely borked on + # Windows. + sys.exit(subprocess.call([python] + sys.argv)) + + # We are now in the virtualenv + if not distutils.sysconfig.get_python_lib(): + die('Could not determine python site packages directory') + diff --git a/www/waterfox/files/patch-bug1321069 b/www/waterfox/files/patch-bug1321069 new file mode 100644 index 000000000000..646e530562d3 --- /dev/null +++ b/www/waterfox/files/patch-bug1321069 @@ -0,0 +1,100 @@ +commit a09c25bcc3b4 +Author: Kartikaya Gupta <kgupta@mozilla.com> +Date: Wed May 30 09:49:23 2018 -0400 + + Bug 1321069 - Redirect the end event of a long-tap sequence back to the content window. r=karlt, a=RyanVM + + In the case of a long-tap touch sequence, a new popup window (the + contextmenu) is spawned while the sequence is ongoing. The touch-end of + the sequence ends up getting delivered to the popup window, instead of + the original content window, and that causes the touch-handling + machinery state in the content window to get out of sync with reality. + This patch detects this scenario and redirects the touch events on the + popup window back to the original content window. + + MozReview-Commit-ID: L2vvKLlogRA + + --HG-- + extra : source : 27a160b7025ffaadd7cc1ce326ce8729c2b180a0 +--- + widget/gtk/nsWindow.cpp | 36 +++++++++++++++++++++++++++++++++++- + widget/gtk/nsWindow.h | 3 +++ + 2 files changed, 38 insertions(+), 1 deletion(-) + +diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp +index 54ec8615051f1..18d0ccac4dbd6 100644 +--- widget/gtk/nsWindow.cpp ++++ widget/gtk/nsWindow.cpp +@@ -3455,11 +3455,41 @@ nsWindow::OnDragDataReceivedEvent(GtkWidget *aWidget, + aSelectionData, aInfo, aTime); + } + ++nsWindow* ++nsWindow::GetTransientForWindowIfPopup() ++{ ++ if (mWindowType != eWindowType_popup) { ++ return nullptr; ++ } ++ GtkWindow* toplevel = gtk_window_get_transient_for(GTK_WINDOW(mShell)); ++ if (toplevel) { ++ return get_window_for_gtk_widget(GTK_WIDGET(toplevel)); ++ } ++ return nullptr; ++} ++ ++bool ++nsWindow::IsHandlingTouchSequence(GdkEventSequence* aSequence) ++{ ++ return mHandleTouchEvent && mTouches.Contains(aSequence); ++} ++ + #if GTK_CHECK_VERSION(3,4,0) + gboolean + nsWindow::OnTouchEvent(GdkEventTouch* aEvent) + { + if (!mHandleTouchEvent) { ++ // If a popup window was spawned (e.g. as the result of a long-press) ++ // and touch events got diverted to that window within a touch sequence, ++ // ensure the touch event gets sent to the original window instead. We ++ // keep the checks here very conservative so that we only redirect ++ // events in this specific scenario. ++ nsWindow* targetWindow = GetTransientForWindowIfPopup(); ++ if (targetWindow && ++ targetWindow->IsHandlingTouchSequence(aEvent->sequence)) { ++ return targetWindow->OnTouchEvent(aEvent); ++ } ++ + return FALSE; + } + +@@ -4780,12 +4810,16 @@ nsWindow::GrabPointer(guint32 aTime) + return; + + gint retval; ++ // Note that we need GDK_TOUCH_MASK below to work around a GDK/X11 bug that ++ // causes touch events that would normally be received by this client on ++ // other windows to be discarded during the grab. + retval = gdk_pointer_grab(mGdkWindow, TRUE, + (GdkEventMask)(GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK | +- GDK_POINTER_MOTION_MASK), ++ GDK_POINTER_MOTION_MASK | ++ GDK_TOUCH_MASK), + (GdkWindow *)nullptr, nullptr, aTime); + + if (retval == GDK_GRAB_NOT_VIEWABLE) { +diff --git widget/gtk/nsWindow.h widget/gtk/nsWindow.h +index c28c1749c76dc..33e8c4db7c1c0 100644 +--- widget/gtk/nsWindow.h ++++ widget/gtk/nsWindow.h +@@ -434,6 +434,8 @@ private: + nsIWidgetListener* GetListener(); + bool IsComposited() const; + ++ nsWindow* GetTransientForWindowIfPopup(); ++ bool IsHandlingTouchSequence(GdkEventSequence* aSequence); + + GtkWidget *mShell; + MozContainer *mContainer; diff --git a/www/waterfox/files/patch-bug1321960 b/www/waterfox/files/patch-bug1321960 new file mode 100644 index 000000000000..410894bfbadb --- /dev/null +++ b/www/waterfox/files/patch-bug1321960 @@ -0,0 +1,134 @@ +commit 8721b8f42bc0 +Author: Alexander Surkov <surkov.alexander@gmail.com> +Date: Tue Sep 26 16:25:12 2017 -0400 + + Bug 1321960 - Rename nsIPresShell::mSuppressInterruptibleReflows to mWasLastReflowInterrupted to reflect better its purpose. r=dholbert, a=sledru + + --HG-- + extra : source : c65fce03b9e0a1a7591668f727b846675cffa44a +--- + layout/base/PresShell.cpp | 8 ++++---- + layout/base/nsIPresShell.h | 18 +++++++++++++++++- + layout/base/nsRefreshDriver.cpp | 2 +- + 3 files changed, 22 insertions(+), 6 deletions(-) + +diff --git layout/base/PresShell.cpp layout/base/PresShell.cpp +index 4ca35ffe1466..a1660ac30de7 100644 +--- layout/base/PresShell.cpp ++++ layout/base/PresShell.cpp +@@ -762,7 +762,7 @@ nsIPresShell::nsIPresShell() + , mFrozen(false) + , mIsFirstPaint(false) + , mObservesMutationsForPrint(false) +- , mSuppressInterruptibleReflows(false) ++ , mWasLastReflowInterrupted(false) + , mScrollPositionClampingScrollPortSizeSet(false) + , mNeedLayoutFlush(true) + , mNeedStyleFlush(true) +@@ -4197,7 +4197,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush) + // worry about them. They can't be triggered during reflow, so we should + // be good. + +- if (flushType >= (mSuppressInterruptibleReflows ++ if (flushType >= (SuppressInterruptibleReflows() + ? FlushType::Layout + : FlushType::InterruptibleLayout) && + !mIsDestroying) { +@@ -4232,7 +4232,7 @@ PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush aFlush) + if (!didLayoutFlush && flushType >= FlushType::InterruptibleLayout && + !mIsDestroying) { + // We suppressed this flush either due to it not being safe to flush, +- // or due to mSuppressInterruptibleReflows. Either way, the ++ // or due to SuppressInterruptibleReflows(). Either way, the + // mNeedLayoutFlush flag needs to be re-set. + SetNeedLayoutFlush(); + } +@@ -9484,7 +9484,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible) + // Any FlushPendingNotifications with interruptible reflows + // should be suppressed now. We don't want to do extra reflow work + // before our reflow event happens. +- mSuppressInterruptibleReflows = true; ++ mWasLastReflowInterrupted = true; + MaybeScheduleReflow(); + } + +diff --git layout/base/nsIPresShell.h layout/base/nsIPresShell.h +index 9f65bad1b4d7..885bc0bc699a 100644 +--- layout/base/nsIPresShell.h ++++ layout/base/nsIPresShell.h +@@ -1581,6 +1581,21 @@ public: + mFontSizeInflationEnabledIsDirty = true; + } + ++ /** ++ * Return true if the most recent interruptible reflow was interrupted. ++ */ ++ bool IsReflowInterrupted() const { ++ return mWasLastReflowInterrupted; ++ } ++ ++ /** ++ * Return true if the the interruptible reflows have to be suppressed. ++ * This may happen only if if the most recent reflow was interrupted. ++ */ ++ bool SuppressInterruptibleReflows() const { ++ return mWasLastReflowInterrupted; ++ } ++ + ////////////////////////////////////////////////////////////////////////////// + // Approximate frame visibility tracking public API. + ////////////////////////////////////////////////////////////////////////////// +@@ -1794,7 +1809,8 @@ protected: + bool mIsFirstPaint : 1; + bool mObservesMutationsForPrint : 1; + +- bool mSuppressInterruptibleReflows : 1; ++ // Whether the most recent interruptible reflow was actually interrupted: ++ bool mWasLastReflowInterrupted : 1; + bool mScrollPositionClampingScrollPortSizeSet : 1; + + // True if a layout flush might not be a no-op +diff --git layout/base/nsRefreshDriver.cpp layout/base/nsRefreshDriver.cpp +index 4dbe56952ccf..4ca4783561c6 100644 +--- layout/base/nsRefreshDriver.cpp ++++ layout/base/nsRefreshDriver.cpp +@@ -1949,7 +1949,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime) + + nsCOMPtr<nsIPresShell> shellKungFuDeathGrip(shell); + shell->mObservingLayoutFlushes = false; +- shell->mSuppressInterruptibleReflows = false; ++ shell->mWasLastReflowInterrupted = false; + FlushType flushType = HasPendingAnimations(shell) + ? FlushType::Layout + : FlushType::InterruptibleLayout; +commit 5ee10fd6f2e4 +Author: Alexander Surkov <surkov.alexander@gmail.com> +Date: Tue Sep 26 16:27:02 2017 -0400 + + Bug 1321960 - Let an interrupted reflow finish before processing a11y. r=eeejay, f=dholbert, a=sledru + + --HG-- + extra : source : c845865489652eadaa3f9a12736c1db56c0e6f12 +--- + accessible/base/NotificationController.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git accessible/base/NotificationController.cpp accessible/base/NotificationController.cpp +index d08500458221..8263c7b54d83 100644 +--- accessible/base/NotificationController.cpp ++++ accessible/base/NotificationController.cpp +@@ -601,9 +601,13 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime) + if (!mDocument) + return; + ++ // Wait until an update, we have started, or an interruptible reflow is ++ // finished. + if (mObservingState == eRefreshProcessing || +- mObservingState == eRefreshProcessingForUpdate) ++ mObservingState == eRefreshProcessingForUpdate || ++ mPresShell->IsReflowInterrupted()) { + return; ++ } + + // Any generic notifications should be queued if we're processing content + // insertions or generic notifications. diff --git a/www/waterfox/files/patch-bug1324042 b/www/waterfox/files/patch-bug1324042 new file mode 100644 index 000000000000..d9edf5e153b5 --- /dev/null +++ b/www/waterfox/files/patch-bug1324042 @@ -0,0 +1,33 @@ +commit ac0f7d653b1e +Author: Daniel Holbert <dholbert@cs.stanford.edu> +Date: Sat Feb 10 08:46:49 2018 -0800 + + Bug 1324042: Fix trimmedOffsets arithmetic in GetRenderedText(). r=mats a=abillings + + MozReview-Commit-ID: H4ngU8Juyln + + --HG-- + extra : source : fbf54020043bd09c162530907b2a1091a10f4f92 +--- + layout/generic/nsTextFrame.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git layout/generic/nsTextFrame.cpp layout/generic/nsTextFrame.cpp +index 42891e960eea..f8b49e4d07cf 100644 +--- layout/generic/nsTextFrame.cpp ++++ layout/generic/nsTextFrame.cpp +@@ -10116,9 +10116,13 @@ nsTextFrame::GetRenderedText(uint32_t aStartOffset, + startOffset = aStartOffset; + endOffset = std::min<uint32_t>(INT32_MAX, aEndOffset); + } ++ ++ // If startOffset and/or endOffset are inside of trimmedOffsets' range, ++ // then clamp the edges of trimmedOffsets accordingly. ++ int32_t origTrimmedOffsetsEnd = trimmedOffsets.GetEnd(); + trimmedOffsets.mStart = std::max<uint32_t>(trimmedOffsets.mStart, + startOffset); +- trimmedOffsets.mLength = std::min<uint32_t>(trimmedOffsets.GetEnd(), ++ trimmedOffsets.mLength = std::min<uint32_t>(origTrimmedOffsetsEnd, + endOffset) - trimmedOffsets.mStart; + if (trimmedOffsets.mLength <= 0) { + offsetInRenderedString = nextOffsetInRenderedString; diff --git a/www/waterfox/files/patch-bug1325888 b/www/waterfox/files/patch-bug1325888 new file mode 100644 index 000000000000..39cff975859d --- /dev/null +++ b/www/waterfox/files/patch-bug1325888 @@ -0,0 +1,39 @@ +commit fb631be6ce75 +Author: DimiL <dlee@mozilla.com> +Date: Wed Nov 1 08:40:00 2017 +0800 + + Bug 1325888 - Clear cached completion result when close safebrowsing database. r=francois + + Safebrowsing testcase will close and then re-open database to simulate firefox restart. + This bug happened when DB service already has a previously cached completion result and then + re-open database. In this scenario, if testcase triggers another the same completion request, + we won't cache it because we thought we have it already (See nsUrlClassifierDBServiceWorker::CacheCompletion). + + This causes a testcase assertion when testcase expects the completion + result should be stored in LookupCache. + + MozReview-Commit-ID: 8o57jHv92OH + + --HG-- + extra : rebase_source : 90861060437d6cef860b85dd669d76e74ceec660 +--- + toolkit/components/url-classifier/nsUrlClassifierDBService.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git toolkit/components/url-classifier/nsUrlClassifierDBService.cpp toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +index e1a1be065aaf..a108812a1792 100644 +--- toolkit/components/url-classifier/nsUrlClassifierDBService.cpp ++++ toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +@@ -812,6 +812,12 @@ nsUrlClassifierDBServiceWorker::CloseDb() + mClassifier = nullptr; + } + ++ // Clear last completion result when close db so we will still cache completion ++ // result next time we re-open it. ++ if (mLastResults) { ++ mLastResults->Clear(); ++ } ++ + LOG(("urlclassifier db closed\n")); + + return NS_OK; diff --git a/www/waterfox/files/patch-bug1331209 b/www/waterfox/files/patch-bug1331209 new file mode 100644 index 000000000000..e210d467a5e6 --- /dev/null +++ b/www/waterfox/files/patch-bug1331209 @@ -0,0 +1,571 @@ +commit b7088851d6e8 +Author: Jan Varga <jan.varga@gmail.com> +Date: Sat Nov 4 23:13:20 2017 +0100 + + Bug 1331209 - Part 2: Fix incorrect FailOnNonOwningThread() calls; r=asuth +--- + dom/asmjscache/AsmJSCache.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git dom/asmjscache/AsmJSCache.cpp dom/asmjscache/AsmJSCache.cpp +index 227bf80f2ac4..ec1e3531fb4f 100644 +--- dom/asmjscache/AsmJSCache.cpp ++++ dom/asmjscache/AsmJSCache.cpp +@@ -560,13 +560,13 @@ private: + // If shutdown just started, the QuotaManager may have been deleted. + QuotaManager* qm = QuotaManager::Get(); + if (!qm) { +- FailOnNonOwningThread(); ++ Fail(); + return; + } + + nsresult rv = qm->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { +- FailOnNonOwningThread(); ++ Fail(); + return; + } + } + +commit ea39dafe977a +Author: Jan Varga <jan.varga@gmail.com> +Date: Sat Nov 4 23:13:41 2017 +0100 + + Bug 1331209 - Part 3: Allow sending of the __delete__ message in one direction only; r=asuth +--- + dom/asmjscache/AsmJSCache.cpp | 141 +++++++++++++++++++++++------------ + dom/asmjscache/PAsmJSCacheEntry.ipdl | 20 ++++- + 2 files changed, 111 insertions(+), 50 deletions(-) + +diff --git dom/asmjscache/AsmJSCache.cpp dom/asmjscache/AsmJSCache.cpp +index ec1e3531fb4f..2216149cd762 100644 +--- dom/asmjscache/AsmJSCache.cpp ++++ dom/asmjscache/AsmJSCache.cpp +@@ -445,7 +445,6 @@ public: + mWriteParams(aWriteParams), + mState(eInitial), + mResult(JS::AsmJSCache_InternalError), +- mDeleteReceived(false), + mActorDestroyed(false), + mOpened(false) + { +@@ -493,12 +492,17 @@ private: + { + AssertIsOnOwningThread(); + MOZ_ASSERT(mState == eOpened); ++ MOZ_ASSERT(mResult == JS::AsmJSCache_Success); + + mState = eFinished; + + MOZ_ASSERT(mOpened); + + FinishOnOwningThread(); ++ ++ if (!mActorDestroyed) { ++ Unused << Send__delete__(this, mResult); ++ } + } + + // This method is called upon any failure that prevents the eventual opening +@@ -508,6 +512,7 @@ private: + { + AssertIsOnOwningThread(); + MOZ_ASSERT(mState != eFinished); ++ MOZ_ASSERT(mResult != JS::AsmJSCache_Success); + + mState = eFinished; + +@@ -515,7 +520,7 @@ private: + + FinishOnOwningThread(); + +- if (!mDeleteReceived && !mActorDestroyed) { ++ if (!mActorDestroyed) { + Unused << Send__delete__(this, mResult); + } + } +@@ -579,26 +584,6 @@ private: + DirectoryLockFailed() override; + + // IPDL methods. +- mozilla::ipc::IPCResult +- Recv__delete__(const JS::AsmJSCacheResult& aResult) override +- { +- AssertIsOnOwningThread(); +- MOZ_ASSERT(mState != eFinished); +- MOZ_ASSERT(!mDeleteReceived); +- +- mDeleteReceived = true; +- +- if (mOpened) { +- Close(); +- } else { +- Fail(); +- } +- +- MOZ_ASSERT(mState == eFinished); +- +- return IPC_OK(); +- } +- + void + ActorDestroy(ActorDestroyReason why) override + { +@@ -624,17 +609,59 @@ private: + } + + mozilla::ipc::IPCResult +- RecvSelectCacheFileToRead(const uint32_t& aModuleIndex) override ++ RecvSelectCacheFileToRead(const OpenMetadataForReadResponse& aResponse) ++ override + { + AssertIsOnOwningThread(); + MOZ_ASSERT(mState == eWaitingToOpenCacheFileForRead); + MOZ_ASSERT(mOpenMode == eOpenForRead); ++ MOZ_ASSERT(!mOpened); ++ ++ switch (aResponse.type()) { ++ case OpenMetadataForReadResponse::TAsmJSCacheResult: { ++ MOZ_ASSERT(aResponse.get_AsmJSCacheResult() != JS::AsmJSCache_Success); ++ ++ mResult = aResponse.get_AsmJSCacheResult(); ++ ++ // This ParentRunnable can only be held alive by the IPDL. Fail() ++ // clears that last reference. So we need to add a self reference here. ++ RefPtr<ParentRunnable> kungFuDeathGrip = this; ++ ++ Fail(); ++ ++ break; ++ } ++ ++ case OpenMetadataForReadResponse::Tuint32_t: ++ // A cache entry has been selected to open. ++ mModuleIndex = aResponse.get_uint32_t(); ++ ++ mState = eReadyToOpenCacheFileForRead; ++ ++ DispatchToIOThread(); ++ ++ break; + +- // A cache entry has been selected to open. ++ default: ++ MOZ_CRASH("Should never get here!"); ++ } ++ ++ return IPC_OK(); ++ } ++ ++ mozilla::ipc::IPCResult ++ RecvClose() override ++ { ++ AssertIsOnOwningThread(); ++ MOZ_ASSERT(mState == eOpened); + +- mModuleIndex = aModuleIndex; +- mState = eReadyToOpenCacheFileForRead; +- DispatchToIOThread(); ++ // This ParentRunnable can only be held alive by the IPDL. Close() clears ++ // that last reference. So we need to add a self reference here. ++ RefPtr<ParentRunnable> kungFuDeathGrip = this; ++ ++ Close(); ++ ++ MOZ_ASSERT(mState == eFinished); + + return IPC_OK(); + } +@@ -675,7 +702,6 @@ private: + State mState; + JS::AsmJSCacheResult mResult; + +- bool mDeleteReceived; + bool mActorDestroyed; + bool mOpened; + }; +@@ -1021,10 +1047,6 @@ ParentRunnable::Run() + + mState = eOpened; + +- // The entry is now open. +- MOZ_ASSERT(!mOpened); +- mOpened = true; +- + FileDescriptor::PlatformHandleType handle = + FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFileDesc)); + if (!SendOnOpenCacheFile(mFileSize, FileDescriptor(handle))) { +@@ -1032,6 +1054,12 @@ ParentRunnable::Run() + return NS_OK; + } + ++ // The entry is now open. ++ MOZ_ASSERT(!mOpened); ++ mOpened = true; ++ ++ mResult = JS::AsmJSCache_Success; ++ + return NS_OK; + } + +@@ -1291,15 +1319,16 @@ private: + MOZ_ASSERT(mState == eOpening); + + uint32_t moduleIndex; +- if (!FindHashMatch(aMetadata, mReadParams, &moduleIndex)) { +- Fail(JS::AsmJSCache_InternalError); +- Send__delete__(this, JS::AsmJSCache_InternalError); +- return IPC_OK(); ++ bool ok; ++ if (FindHashMatch(aMetadata, mReadParams, &moduleIndex)) { ++ ok = SendSelectCacheFileToRead(moduleIndex); ++ } else { ++ ok = SendSelectCacheFileToRead(JS::AsmJSCache_InternalError); + } +- +- if (!SendSelectCacheFileToRead(moduleIndex)) { ++ if (!ok) { + return IPC_FAIL_NO_REASON(this); + } ++ + return IPC_OK(); + } + +@@ -1327,9 +1356,20 @@ private: + Recv__delete__(const JS::AsmJSCacheResult& aResult) override + { + MOZ_ASSERT(NS_IsMainThread()); +- MOZ_ASSERT(mState == eOpening); ++ MOZ_ASSERT(mState == eOpening || mState == eFinishing); ++ MOZ_ASSERT_IF(mState == eOpening, aResult != JS::AsmJSCache_Success); ++ MOZ_ASSERT_IF(mState == eFinishing, aResult == JS::AsmJSCache_Success); + +- Fail(aResult); ++ if (mState == eOpening) { ++ Fail(aResult); ++ } else { ++ // Match the AddRef in BlockUntilOpen(). The IPDL still holds an ++ // outstanding ref which will keep 'this' alive until ActorDestroy() ++ // is executed. ++ Release(); ++ ++ mState = eFinished; ++ } + return IPC_OK(); + } + +@@ -1395,6 +1435,7 @@ private: + eOpening, // Waiting for the parent process to respond + eOpened, // Parent process opened the entry and sent it back + eClosing, // Waiting to be dispatched to the main thread to Send__delete__ ++ eFinishing, // Waiting for the parent process to close + eFinished // Terminal state + }; + State mState; +@@ -1454,28 +1495,32 @@ ChildRunnable::Run() + + // Per FileDescriptorHolder::Finish()'s comment, call before + // releasing the directory lock (which happens in the parent upon receipt +- // of the Send__delete__ message). ++ // of the Close message). + FileDescriptorHolder::Finish(); + + MOZ_ASSERT(mOpened); + mOpened = false; + +- // Match the AddRef in BlockUntilOpen(). The main thread event loop still +- // holds an outstanding ref which will keep 'this' alive until returning to +- // the event loop. +- Release(); ++ if (mActorDestroyed) { ++ // Match the AddRef in BlockUntilOpen(). The main thread event loop ++ // still holds an outstanding ref which will keep 'this' alive until ++ // returning to the event loop. ++ Release(); + +- if (!mActorDestroyed) { +- Unused << Send__delete__(this, JS::AsmJSCache_Success); ++ mState = eFinished; ++ } else { ++ Unused << SendClose(); ++ ++ mState = eFinishing; + } + +- mState = eFinished; + return NS_OK; + } + + case eBackgroundChildPending: + case eOpening: + case eOpened: ++ case eFinishing: + case eFinished: { + MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Shouldn't Run() in this state"); + } +diff --git dom/asmjscache/PAsmJSCacheEntry.ipdl dom/asmjscache/PAsmJSCacheEntry.ipdl +index d16c9284ff9d..bb88a25b5615 100644 +--- dom/asmjscache/PAsmJSCacheEntry.ipdl ++++ dom/asmjscache/PAsmJSCacheEntry.ipdl +@@ -11,6 +11,12 @@ namespace mozilla { + namespace dom { + namespace asmjscache { + ++union OpenMetadataForReadResponse ++{ ++ AsmJSCacheResult; ++ uint32_t; ++}; ++ + protocol PAsmJSCacheEntry + { + manager PBackground; +@@ -21,14 +27,24 @@ protocol PAsmJSCacheEntry + child: + async OnOpenMetadataForRead(Metadata metadata); + parent: +- async SelectCacheFileToRead(uint32_t moduleIndex); ++ async SelectCacheFileToRead(OpenMetadataForReadResponse response); + + child: + // Once the cache file has been opened, the child is notified and sent an + // open file descriptor. + async OnOpenCacheFile(int64_t fileSize, FileDescriptor fileDesc); + +-both: ++parent: ++ // When the child process is done with the cache entry, the parent process ++ // is notified (via Close). ++ async Close(); ++ ++child: ++ // When there's an error during the opening phase, the child process is ++ // notified (via __delete__) and sent an error result. ++ // When the parent process receives the Close message, it closes the cache ++ // entry on the parent side and the child is notified (via __delete__). ++ // The protocol is destroyed in both cases. + async __delete__(AsmJSCacheResult result); + }; + + +commit 04d80fd8932a +Author: Jan Varga <jan.varga@gmail.com> +Date: Sat Nov 4 23:13:51 2017 +0100 + + Bug 1331209 - Part 4: Prevent the state machine from continuing if QM is shutting down or the actor has been destroyed; r=asuth +--- + dom/asmjscache/AsmJSCache.cpp | 97 +++++++++++++++++++++++++++++++++++++------ + 1 file changed, 84 insertions(+), 13 deletions(-) + +diff --git dom/asmjscache/AsmJSCache.cpp dom/asmjscache/AsmJSCache.cpp +index 2216149cd762..7c96bc71ac0a 100644 +--- dom/asmjscache/AsmJSCache.cpp ++++ dom/asmjscache/AsmJSCache.cpp +@@ -443,6 +443,7 @@ public: + mPrincipalInfo(aPrincipalInfo), + mOpenMode(aOpenMode), + mWriteParams(aWriteParams), ++ mOperationMayProceed(true), + mState(eInitial), + mResult(JS::AsmJSCache_InternalError), + mActorDestroyed(false), +@@ -485,6 +486,22 @@ private: + MOZ_ASSERT(!IsOnOwningThread()); + } + ++ bool ++ IsActorDestroyed() const ++ { ++ AssertIsOnOwningThread(); ++ ++ return mActorDestroyed; ++ } ++ ++ // May be called on any thread, but you should call IsActorDestroyed() if ++ // you know you're on the background thread because it is slightly faster. ++ bool ++ OperationMayProceed() const ++ { ++ return mOperationMayProceed; ++ } ++ + // This method is called on the owning thread when the JS engine is finished + // reading/writing the cache entry. + void +@@ -497,6 +514,7 @@ private: + mState = eFinished; + + MOZ_ASSERT(mOpened); ++ mOpened = false; + + FinishOnOwningThread(); + +@@ -562,13 +580,15 @@ private: + { + AssertIsOnOwningThread(); + +- // If shutdown just started, the QuotaManager may have been deleted. +- QuotaManager* qm = QuotaManager::Get(); +- if (!qm) { ++ if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) || ++ IsActorDestroyed()) { + Fail(); + return; + } + ++ QuotaManager* qm = QuotaManager::Get(); ++ MOZ_ASSERT(qm); ++ + nsresult rv = qm->IOThread()->Dispatch(this, NS_DISPATCH_NORMAL); + if (NS_FAILED(rv)) { + Fail(); +@@ -589,23 +609,30 @@ private: + { + AssertIsOnOwningThread(); + MOZ_ASSERT(!mActorDestroyed); ++ MOZ_ASSERT(mOperationMayProceed); + + mActorDestroyed = true; ++ mOperationMayProceed = false; + +- // Assume ActorDestroy can happen at any time, so probe the current state to +- // determine what needs to happen. +- +- if (mState == eFinished) { +- return; +- } ++ // Assume ActorDestroy can happen at any time, so we can't probe the ++ // current state since mState can be modified on any thread (only one ++ // thread at a time based on the state machine). ++ // However we can use mOpened which is only touched on the owning thread. ++ // If mOpened is true, we can also modify mState since we are guaranteed ++ // that there are no pending runnables which would probe mState to decide ++ // what code needs to run (there shouldn't be any running runnables on ++ // other threads either). + + if (mOpened) { + Close(); +- } else { +- Fail(); ++ ++ MOZ_ASSERT(mState == eFinished); + } + +- MOZ_ASSERT(mState == eFinished); ++ // We don't have to call Fail() if mOpened is not true since it means that ++ // either nothing has been initialized yet, so nothing to cleanup or there ++ // are pending runnables that will detect that the actor has been destroyed ++ // and call Fail(). + } + + mozilla::ipc::IPCResult +@@ -617,6 +644,11 @@ private: + MOZ_ASSERT(mOpenMode == eOpenForRead); + MOZ_ASSERT(!mOpened); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread())) { ++ Fail(); ++ return IPC_OK(); ++ } ++ + switch (aResponse.type()) { + case OpenMetadataForReadResponse::TAsmJSCacheResult: { + MOZ_ASSERT(aResponse.get_AsmJSCacheResult() != JS::AsmJSCache_Success); +@@ -682,6 +714,8 @@ private: + nsCOMPtr<nsIFile> mMetadataFile; + Metadata mMetadata; + ++ Atomic<bool> mOperationMayProceed; ++ + // State initialized during eWaitingToOpenCacheFileForRead + unsigned mModuleIndex; + +@@ -942,6 +976,12 @@ ParentRunnable::Run() + case eInitial: { + MOZ_ASSERT(NS_IsMainThread()); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnNonBackgroundThread()) || ++ !OperationMayProceed()) { ++ FailOnNonOwningThread(); ++ return NS_OK; ++ } ++ + rv = InitOnMainThread(); + if (NS_FAILED(rv)) { + FailOnNonOwningThread(); +@@ -957,7 +997,8 @@ ParentRunnable::Run() + case eWaitingToFinishInit: { + AssertIsOnOwningThread(); + +- if (QuotaManager::IsShuttingDown()) { ++ if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) || ++ IsActorDestroyed()) { + Fail(); + return NS_OK; + } +@@ -976,6 +1017,12 @@ ParentRunnable::Run() + case eWaitingToOpenDirectory: { + AssertIsOnOwningThread(); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) || ++ IsActorDestroyed()) { ++ Fail(); ++ return NS_OK; ++ } ++ + if (NS_WARN_IF(!QuotaManager::Get())) { + Fail(); + return NS_OK; +@@ -988,6 +1035,12 @@ ParentRunnable::Run() + case eReadyToReadMetadata: { + AssertIsOnIOThread(); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnNonBackgroundThread()) || ++ !OperationMayProceed()) { ++ FailOnNonOwningThread(); ++ return NS_OK; ++ } ++ + rv = ReadMetadata(); + if (NS_FAILED(rv)) { + FailOnNonOwningThread(); +@@ -1016,6 +1069,12 @@ ParentRunnable::Run() + AssertIsOnOwningThread(); + MOZ_ASSERT(mOpenMode == eOpenForRead); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) || ++ IsActorDestroyed()) { ++ Fail(); ++ return NS_OK; ++ } ++ + mState = eWaitingToOpenCacheFileForRead; + + // Metadata is now open. +@@ -1031,6 +1090,12 @@ ParentRunnable::Run() + AssertIsOnIOThread(); + MOZ_ASSERT(mOpenMode == eOpenForRead); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnNonBackgroundThread()) || ++ !OperationMayProceed()) { ++ FailOnNonOwningThread(); ++ return NS_OK; ++ } ++ + rv = OpenCacheFileForRead(); + if (NS_FAILED(rv)) { + FailOnNonOwningThread(); +@@ -1045,6 +1110,12 @@ ParentRunnable::Run() + case eSendingCacheFile: { + AssertIsOnOwningThread(); + ++ if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread()) || ++ IsActorDestroyed()) { ++ Fail(); ++ return NS_OK; ++ } ++ + mState = eOpened; + + FileDescriptor::PlatformHandleType handle = diff --git a/www/waterfox/files/patch-bug1334465 b/www/waterfox/files/patch-bug1334465 new file mode 100644 index 000000000000..9a5220b13475 --- /dev/null +++ b/www/waterfox/files/patch-bug1334465 @@ -0,0 +1,62 @@ +commit 646f99465e4f +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Fri Feb 9 13:20:04 2018 +0100 + + Bug 1334465 - Make HttpChannelParent::mIPCClosed atomic r=bagder a=ritu + + MozReview-Commit-ID: 6irCJMAjzjW + + --HG-- + extra : source : bd315ae86709c3459a3dbf0778022ff3b1908723 +--- + netwerk/protocol/http/HttpChannelParent.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git netwerk/protocol/http/HttpChannelParent.h netwerk/protocol/http/HttpChannelParent.h +index 572d7f177d7a..ef4dbd84f792 100644 +--- netwerk/protocol/http/HttpChannelParent.h ++++ netwerk/protocol/http/HttpChannelParent.h +@@ -264,7 +264,7 @@ private: + RefPtr<HttpBaseChannel> mChannel; + nsCOMPtr<nsICacheEntry> mCacheEntry; + nsCOMPtr<nsIAssociatedContentSecurity> mAssociatedContentSecurity; +- bool mIPCClosed; // PHttpChannel actor has been Closed() ++ Atomic<bool> mIPCClosed; // PHttpChannel actor has been Closed() + + nsCOMPtr<nsIChannel> mRedirectChannel; + nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback; +commit a87603550115 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Sun Feb 11 03:51:09 2018 +0100 + + Bug 1334465 - Set mIPCClosed to true before calling SendDeleteSelf in order to avoid race r=bagder a=ritu + + In the previous code, a race condition could cause us to call SendSetPriority() after calling SendDeleteSelf. + + For example: + T1: SendDeleteSelf() + T2: if (!mIPCClosed) SendSetPriority() + T1: mIPCClosed = true + + MozReview-Commit-ID: 3XOwCaphb2o + + --HG-- + extra : source : 4ebdab0e332892378558817e30d0138c95199ce5 +--- + netwerk/protocol/http/HttpChannelParent.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git netwerk/protocol/http/HttpChannelParent.cpp netwerk/protocol/http/HttpChannelParent.cpp +index 064c5659e9ed..8ee13c2b5fbd 100644 +--- netwerk/protocol/http/HttpChannelParent.cpp ++++ netwerk/protocol/http/HttpChannelParent.cpp +@@ -2262,8 +2262,8 @@ HttpChannelParent::UpdateAndSerializeSecurityInfo(nsACString& aSerializedSecurit + bool + HttpChannelParent::DoSendDeleteSelf() + { +- bool rv = SendDeleteSelf(); + mIPCClosed = true; ++ bool rv = SendDeleteSelf(); + + CleanupBackgroundChannel(); + diff --git a/www/waterfox/files/patch-bug1334981 b/www/waterfox/files/patch-bug1334981 new file mode 100644 index 000000000000..4c778d4adbf2 --- /dev/null +++ b/www/waterfox/files/patch-bug1334981 @@ -0,0 +1,29 @@ +commit 57a68dc342dd +Author: Henrik Skupin <mail@hskupin.info> +Date: Thu Jun 7 15:48:48 2018 +0200 + + Bug 1334981 - Backed out changeset d6ca24ba3673 for regression caused by bug 887718. r=enndeakin, a=RyanVM + + MozReview-Commit-ID: 9hIcRVRseO1 + + --HG-- + extra : source : 1f16a2ff45ab492025e42afb8122f4d52cb24c0b +--- + dom/base/nsFocusManager.cpp | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git dom/base/nsFocusManager.cpp dom/base/nsFocusManager.cpp +index 864c76402cb12..c5758cfabd523 100644 +--- dom/base/nsFocusManager.cpp ++++ dom/base/nsFocusManager.cpp +@@ -742,9 +742,7 @@ nsFocusManager::WindowRaised(mozIDOMWindowProxy* aWindow) + return NS_ERROR_FAILURE; + } + +- if (!sTestMode) { +- baseWindow->SetVisibility(true); +- } ++ baseWindow->SetVisibility(true); + } + + // If this is a parent or single process window, send the activate event. diff --git a/www/waterfox/files/patch-bug1338764 b/www/waterfox/files/patch-bug1338764 new file mode 100644 index 000000000000..fcedb824ff69 --- /dev/null +++ b/www/waterfox/files/patch-bug1338764 @@ -0,0 +1,120 @@ +commit 0e98738d78b9 +Author: Xidorn Quan <me@upsuper.org> +Date: Mon Jul 17 15:10:50 2017 +1000 + + Bug 1338764 part 1 - Use const rather than enum for context flags of nsStyleSVG. r=manishearth + + MozReview-Commit-ID: KzORnfVXgLJ + + --HG-- + extra : rebase_source : 365842d6e6fda4b35a5932272773a3d88bfc04c6 +--- + layout/style/nsStyleStruct.h | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git layout/style/nsStyleStruct.h layout/style/nsStyleStruct.h +index 59833e37f3bb..eccc02380f7e 100644 +--- layout/style/nsStyleStruct.h ++++ layout/style/nsStyleStruct.h +@@ -3603,15 +3603,19 @@ private: + // Flags to represent the use of context-fill and context-stroke + // for fill-opacity or stroke-opacity, and context-value for stroke-dasharray, + // stroke-dashoffset and stroke-width. +- enum { +- FILL_OPACITY_SOURCE_MASK = 0x03, // fill-opacity: context-{fill,stroke} +- STROKE_OPACITY_SOURCE_MASK = 0x0C, // stroke-opacity: context-{fill,stroke} +- STROKE_DASHARRAY_CONTEXT = 0x10, // stroke-dasharray: context-value +- STROKE_DASHOFFSET_CONTEXT = 0x20, // stroke-dashoffset: context-value +- STROKE_WIDTH_CONTEXT = 0x40, // stroke-width: context-value +- FILL_OPACITY_SOURCE_SHIFT = 0, +- STROKE_OPACITY_SOURCE_SHIFT = 2, +- }; ++ ++ // fill-opacity: context-{fill,stroke} ++ static const uint8_t FILL_OPACITY_SOURCE_MASK = 0x03; ++ // stroke-opacity: context-{fill,stroke} ++ static const uint8_t STROKE_OPACITY_SOURCE_MASK = 0x0C; ++ // stroke-dasharray: context-value ++ static const uint8_t STROKE_DASHARRAY_CONTEXT = 0x10; ++ // stroke-dashoffset: context-value ++ static const uint8_t STROKE_DASHOFFSET_CONTEXT = 0x20; ++ // stroke-width: context-value ++ static const uint8_t STROKE_WIDTH_CONTEXT = 0x40; ++ static const uint8_t FILL_OPACITY_SOURCE_SHIFT = 0; ++ static const uint8_t STROKE_OPACITY_SOURCE_SHIFT = 2; + + uint8_t mContextFlags; // [inherited] + }; + +commit 63d6f06939ee +Author: Xidorn Quan <me@upsuper.org> +Date: Tue Aug 1 16:05:04 2017 +1000 + + Bug 1338764 part 2 - Add context-{fill,stroke}-opacity support to {fill,stroke}-opacity. r=manishearth + + MozReview-Commit-ID: HzUHmZb8ICl + + --HG-- + extra : rebase_source : b8746c4d9d4cfc3abe6645f583dc08d0f7c75341 +--- + layout/style/ServoBindings.toml | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git layout/style/ServoBindings.toml layout/style/ServoBindings.toml +index 5e09c24eb0e3..6d8e979fdc1f 100644 +--- layout/style/ServoBindings.toml ++++ layout/style/ServoBindings.toml +@@ -232,6 +232,7 @@ whitelist-types = [ + "nsStylePadding", + "nsStylePosition", + "nsStyleSVG", ++ "nsStyleSVGOpacitySource", + "nsStyleSVGPaint", + "nsStyleSVGReset", + "nsStyleTable", +@@ -458,6 +459,7 @@ structs-types = [ + "nsStylePosition", + "nsStyleQuoteValues", + "nsStyleSVG", ++ "nsStyleSVGOpacitySource", + "nsStyleSVGPaint", + "nsStyleSVGReset", + "nsStyleTable", + +commit 03e036aff26d +Author: Xidorn Quan <me@upsuper.org> +Date: Tue Aug 1 16:38:27 2017 +1000 + + Bug 1338764 part 3 - Update test expectations. r=manishearth + + MozReview-Commit-ID: HzN5WP210G7 + + --HG-- + extra : rebase_source : c3585958cb5159a242515a80f226e43f506319d8 +--- + layout/style/test/stylo-failures.md | 8 -------- + 1 file changed, 8 deletions(-) + +diff --git layout/style/test/stylo-failures.md layout/style/test/stylo-failures.md +index 0509269b1334..d69fa898d9be 100644 +--- layout/style/test/stylo-failures.md ++++ layout/style/test/stylo-failures.md +@@ -34,10 +34,6 @@ to mochitest command. + * Animation support: + * SMIL Animation + * test_restyles_in_smil_animation.html [2] +-* Unsupported values +- * SVG-in-OpenType values not supported servo/servo#15211 bug 1338764 +- * test_value_storage.html `context-` [7] +- * test_bug798843_pref.html [3] + * Incorrect serialization + * place-{content,items,self} shorthands bug 1363971 + * test_align_shorthand_serialization.html [6] +@@ -58,7 +54,3 @@ to mochitest command. + ## Unknown / Unsure + + ## Ignore +- +-* Ignore for now since should be mostly identical to test_value_storage.html +- * test_value_cloning.html [*] +- * test_value_computation.html [*] diff --git a/www/waterfox/files/patch-bug1340039 b/www/waterfox/files/patch-bug1340039 new file mode 100644 index 000000000000..2f601b7db234 --- /dev/null +++ b/www/waterfox/files/patch-bug1340039 @@ -0,0 +1,232 @@ +commit 753d522440f6 +Author: Hector Zhao <bzhao@mozilla.com> +Date: Wed Mar 14 16:44:36 2018 +0800 + + Bug 1340039 - Set contentPolicyType when copying image, and pass it between processes. r=smaug, a=jcristau + + MozReview-Commit-ID: CJj1a1Lj699 + + --HG-- + extra : source : 445ec9da938f984a6fe2fe163c7f3d7be4710a77 +--- + dom/base/nsContentUtils.cpp | 2 ++ + dom/base/nsContentUtils.h | 1 + + dom/base/nsCopySupport.cpp | 1 + + dom/events/EventStateManager.cpp | 5 ++++- + dom/ipc/ContentParent.cpp | 2 ++ + dom/ipc/ContentParent.h | 1 + + dom/ipc/PBrowser.ipdl | 3 ++- + dom/ipc/PContent.ipdl | 1 + + dom/ipc/TabChild.cpp | 4 +++- + dom/ipc/TabChild.h | 3 ++- + dom/ipc/TabParent.cpp | 6 ++++-- + dom/ipc/TabParent.h | 3 ++- + widget/nsClipboardProxy.cpp | 5 ++++- + 13 files changed, 29 insertions(+), 8 deletions(-) + +diff --git dom/base/nsContentUtils.cpp dom/base/nsContentUtils.cpp +index fe773465faba..63e1ac06bf2d 100644 +--- dom/base/nsContentUtils.cpp ++++ dom/base/nsContentUtils.cpp +@@ -7986,6 +7986,7 @@ nsresult + nsContentUtils::IPCTransferableToTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + nsIPrincipal* aRequestingPrincipal, ++ const nsContentPolicyType& aContentPolicyType, + nsITransferable* aTransferable, + mozilla::dom::nsIContentParent* aContentParent, + mozilla::dom::TabChild* aTabChild) +@@ -8051,6 +8052,7 @@ nsContentUtils::IPCTransferableToTransferable(const IPCDataTransfer& aDataTransf + + aTransferable->SetIsPrivateData(aIsPrivateData); + aTransferable->SetRequestingPrincipal(aRequestingPrincipal); ++ aTransferable->SetContentPolicyType(aContentPolicyType); + return NS_OK; + } + +diff --git dom/base/nsContentUtils.h dom/base/nsContentUtils.h +index 356d3841b9e9..9ef79a569ea3 100644 +--- dom/base/nsContentUtils.h ++++ dom/base/nsContentUtils.h +@@ -2845,6 +2845,7 @@ public: + static nsresult IPCTransferableToTransferable(const mozilla::dom::IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + nsIPrincipal* aRequestingPrincipal, ++ const nsContentPolicyType& aContentPolicyType, + nsITransferable* aTransferable, + mozilla::dom::nsIContentParent* aContentParent, + mozilla::dom::TabChild* aTabChild); +diff --git dom/base/nsCopySupport.cpp dom/base/nsCopySupport.cpp +index 0f680c21c126..5e2d4065b3b7 100644 +--- dom/base/nsCopySupport.cpp ++++ dom/base/nsCopySupport.cpp +@@ -680,6 +680,7 @@ static nsresult AppendImagePromise(nsITransferable* aTransferable, + NS_ENSURE_SUCCESS(rv, rv); + + aTransferable->SetRequestingPrincipal(node->NodePrincipal()); ++ aTransferable->SetContentPolicyType(nsIContentPolicy::TYPE_INTERNAL_IMAGE); + + // add the dataless file promise flavor + return aTransferable->AddDataFlavor(kFilePromiseMime); +diff --git dom/events/EventStateManager.cpp dom/events/EventStateManager.cpp +index 4423e3aecc5e..bdc1bb6e50c9 100644 +--- dom/events/EventStateManager.cpp ++++ dom/events/EventStateManager.cpp +@@ -5469,8 +5469,11 @@ EventStateManager::DoContentCommandEvent(WidgetContentCommandEvent* aEvent) + transferable->GetIsPrivateData(&isPrivateData); + nsCOMPtr<nsIPrincipal> requestingPrincipal; + transferable->GetRequestingPrincipal(getter_AddRefs(requestingPrincipal)); ++ nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_OTHER; ++ transferable->GetContentPolicyType(&contentPolicyType); + remote->SendPasteTransferable(ipcDataTransfer, isPrivateData, +- IPC::Principal(requestingPrincipal)); ++ IPC::Principal(requestingPrincipal), ++ contentPolicyType); + rv = NS_OK; + } else { + nsCOMPtr<nsICommandController> commandController = do_QueryInterface(controller); +diff --git dom/ipc/ContentParent.cpp dom/ipc/ContentParent.cpp +index e27f3eedc1b1..3c3d2fbc3735 100644 +--- dom/ipc/ContentParent.cpp ++++ dom/ipc/ContentParent.cpp +@@ -2605,6 +2605,7 @@ mozilla::ipc::IPCResult + ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + const IPC::Principal& aRequestingPrincipal, ++ const uint32_t& aContentPolicyType, + const int32_t& aWhichClipboard) + { + nsresult rv; +@@ -2619,6 +2620,7 @@ ContentParent::RecvSetClipboard(const IPCDataTransfer& aDataTransfer, + rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer, + aIsPrivateData, + aRequestingPrincipal, ++ aContentPolicyType, + trans, this, nullptr); + NS_ENSURE_SUCCESS(rv, IPC_OK()); + +diff --git dom/ipc/ContentParent.h dom/ipc/ContentParent.h +index 1977cfbfd651..a1311bd39403 100644 +--- dom/ipc/ContentParent.h ++++ dom/ipc/ContentParent.h +@@ -976,6 +976,7 @@ private: + virtual mozilla::ipc::IPCResult RecvSetClipboard(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, + const IPC::Principal& aRequestingPrincipal, ++ const uint32_t& aContentPolicyType, + const int32_t& aWhichClipboard) override; + + virtual mozilla::ipc::IPCResult RecvGetClipboard(nsTArray<nsCString>&& aTypes, +diff --git dom/ipc/PBrowser.ipdl dom/ipc/PBrowser.ipdl +index 3a7b21271fec..b1cf9efbe964 100644 +--- dom/ipc/PBrowser.ipdl ++++ dom/ipc/PBrowser.ipdl +@@ -720,7 +720,8 @@ child: + */ + async PasteTransferable(IPCDataTransfer aDataTransfer, + bool aIsPrivateData, +- Principal aRequestingPrincipal); ++ Principal aRequestingPrincipal, ++ uint32_t aContentPolicyType); + + /** + * Activate event forwarding from client to parent. +diff --git dom/ipc/PContent.ipdl dom/ipc/PContent.ipdl +index 7e33b2920cbe..4ab9da3cc105 100644 +--- dom/ipc/PContent.ipdl ++++ dom/ipc/PContent.ipdl +@@ -837,6 +837,7 @@ parent: + async SetClipboard(IPCDataTransfer aDataTransfer, + bool aIsPrivateData, + Principal aRequestingPrincipal, ++ uint32_t aContentPolicyType, + int32_t aWhichClipboard); + + // Given a list of supported types, returns the clipboard data for the +diff --git dom/ipc/TabChild.cpp dom/ipc/TabChild.cpp +index 50725636d280..72df59ea98c0 100644 +--- dom/ipc/TabChild.cpp ++++ dom/ipc/TabChild.cpp +@@ -2164,7 +2164,8 @@ TabChild::RecvNormalPrioritySelectionEvent(const WidgetSelectionEvent& aEvent) + mozilla::ipc::IPCResult + TabChild::RecvPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, +- const IPC::Principal& aRequestingPrincipal) ++ const IPC::Principal& aRequestingPrincipal, ++ const uint32_t& aContentPolicyType) + { + nsresult rv; + nsCOMPtr<nsITransferable> trans = +@@ -2175,6 +2176,7 @@ TabChild::RecvPasteTransferable(const IPCDataTransfer& aDataTransfer, + rv = nsContentUtils::IPCTransferableToTransferable(aDataTransfer, + aIsPrivateData, + aRequestingPrincipal, ++ aContentPolicyType, + trans, nullptr, this); + NS_ENSURE_SUCCESS(rv, IPC_OK()); + +diff --git dom/ipc/TabChild.h dom/ipc/TabChild.h +index f18906568c1c..48bd8e9eb86e 100644 +--- dom/ipc/TabChild.h ++++ dom/ipc/TabChild.h +@@ -454,7 +454,8 @@ public: + virtual mozilla::ipc::IPCResult + RecvPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, +- const IPC::Principal& aRequestingPrincipal) override; ++ const IPC::Principal& aRequestingPrincipal, ++ const uint32_t& aContentPolicyType) override; + + virtual mozilla::ipc::IPCResult + RecvActivateFrameEvent(const nsString& aType, const bool& aCapture) override; +diff --git dom/ipc/TabParent.cpp dom/ipc/TabParent.cpp +index d4e3d11ea2e9..ae43c24e8891 100644 +--- dom/ipc/TabParent.cpp ++++ dom/ipc/TabParent.cpp +@@ -2312,11 +2312,13 @@ TabParent::SendSelectionEvent(WidgetSelectionEvent& aEvent) + bool + TabParent::SendPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, +- const IPC::Principal& aRequestingPrincipal) ++ const IPC::Principal& aRequestingPrincipal, ++ const uint32_t& aContentPolicyType) + { + return PBrowserParent::SendPasteTransferable(aDataTransfer, + aIsPrivateData, +- aRequestingPrincipal); ++ aRequestingPrincipal, ++ aContentPolicyType); + } + + /*static*/ TabParent* +diff --git dom/ipc/TabParent.h dom/ipc/TabParent.h +index c31827499403..e3c2601ce0b4 100644 +--- dom/ipc/TabParent.h ++++ dom/ipc/TabParent.h +@@ -497,7 +497,8 @@ public: + + bool SendPasteTransferable(const IPCDataTransfer& aDataTransfer, + const bool& aIsPrivateData, +- const IPC::Principal& aRequestingPrincipal); ++ const IPC::Principal& aRequestingPrincipal, ++ const uint32_t& aContentPolicyType); + + static TabParent* GetFrom(nsFrameLoader* aFrameLoader); + +diff --git widget/nsClipboardProxy.cpp widget/nsClipboardProxy.cpp +index f7d863475b13..4fb90721c0b6 100644 +--- widget/nsClipboardProxy.cpp ++++ widget/nsClipboardProxy.cpp +@@ -37,8 +37,11 @@ nsClipboardProxy::SetData(nsITransferable *aTransferable, + aTransferable->GetIsPrivateData(&isPrivateData); + nsCOMPtr<nsIPrincipal> requestingPrincipal; + aTransferable->GetRequestingPrincipal(getter_AddRefs(requestingPrincipal)); ++ nsContentPolicyType contentPolicyType = nsIContentPolicy::TYPE_OTHER; ++ aTransferable->GetContentPolicyType(&contentPolicyType); + child->SendSetClipboard(ipcDataTransfer, isPrivateData, +- IPC::Principal(requestingPrincipal), aWhichClipboard); ++ IPC::Principal(requestingPrincipal), ++ contentPolicyType, aWhichClipboard); + + return NS_OK; + } diff --git a/www/waterfox/files/patch-bug1343147 b/www/waterfox/files/patch-bug1343147 new file mode 100644 index 000000000000..a548c655e4dc --- /dev/null +++ b/www/waterfox/files/patch-bug1343147 @@ -0,0 +1,117 @@ +commit e215b167b9b9 +Author: cku <cku@mozilla.com> +Date: Tue Oct 3 11:29:19 2017 +0800 + + Bug 1343147 - Do not double applying transform vector of the root frame in a glyph mask into the target context. r=mstange, a=ritu + + When we generate the glyph mask for a transformed frame in + GenerateAndPushTextMask, the transform vector had been applied into aContext[1], + so we should find a way to prevent applying the vector again when painting the + glyph mask. + + In bug 1299715, I tried to prevent double apply at [2], it caused two problems: + 1. We only skip generating nsDisplayTransform, but we may still create a + nsDisplayPerspactive bellow. Since the parent of a nsDisplayPerspective must be + a nsDisplayTransform, which have been ignored, so we hit this assertion. + 2. We skip all transform for all frames while painting the glyph mask, which is + not correct. We should only skip double applying transform vector of the root + frame. + + This patch fixes both of these issues: + a. We will still create a nsDisplayTransform for the root frame if need. But + the transform matrix we apply into the target context will be an identity + matrix, so we fix #1 above. + b. In #a, we change the transform matrix to an identity matrix only for the root + frame of the glyph mask, so we fix #2. + + [1] + https://hg.mozilla.org/mozilla-central/file/59e5ec5729db/layout/painting/nsDisplayList.cpp#l752 + [2] + https://hg.mozilla.org/mozilla-central/file/ce2c129f0a87/layout/generic/nsFrame.cpp#l2806 + + MozReview-Commit-ID: 973lkQQxLB6 + + --HG-- + extra : source : 84451d723686bc47b81c44ed2ddf6c61f3e35915 +--- + layout/generic/nsFrame.cpp | 13 +++++-------- + layout/painting/nsDisplayList.cpp | 9 ++++++++- + 2 files changed, 13 insertions(+), 9 deletions(-) + +diff --git layout/generic/nsFrame.cpp layout/generic/nsFrame.cpp +index 37f2e2801220..dbfd61b7e142 100644 +--- layout/generic/nsFrame.cpp ++++ layout/generic/nsFrame.cpp +@@ -2803,14 +2803,11 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, + buildingDisplayList.SetReferenceFrameAndCurrentOffset(outerReferenceFrame, + GetOffsetToCrossDoc(outerReferenceFrame)); + +- if (!aBuilder->IsForGenerateGlyphMask() && +- !aBuilder->IsForPaintingSelectionBG()) { +- nsDisplayTransform *transformItem = +- new (aBuilder) nsDisplayTransform(aBuilder, this, +- &resultList, dirtyRect, 0, +- allowAsyncAnimation); +- resultList.AppendNewToTop(transformItem); +- } ++ nsDisplayTransform *transformItem = ++ new (aBuilder) nsDisplayTransform(aBuilder, this, ++ &resultList, dirtyRect, 0, ++ allowAsyncAnimation); ++ resultList.AppendNewToTop(transformItem); + + if (hasPerspective) { + if (clipCapturedBy == ContainerItemType::ePerspective) { +diff --git layout/painting/nsDisplayList.cpp layout/painting/nsDisplayList.cpp +index 801e1ea2fb4d..6477bda52f01 100644 +--- layout/painting/nsDisplayList.cpp ++++ layout/painting/nsDisplayList.cpp +@@ -7976,11 +7976,18 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu + LayerManager *aManager, + const ContainerLayerParameters& aContainerParameters) + { ++ // While generating a glyph mask, the transform vector of the root frame had ++ // been applied into the target context, so stop applying it again here. ++ const bool shouldSkipTransform = ++ (aBuilder->RootReferenceFrame() == mFrame) && ++ (aBuilder->IsForGenerateGlyphMask() || aBuilder->IsForPaintingSelectionBG()); ++ + /* For frames without transform, it would not be removed for + * backface hidden here. But, it would be removed by the init + * function of nsDisplayTransform. + */ +- const Matrix4x4& newTransformMatrix = GetTransformForRendering(); ++ const Matrix4x4 newTransformMatrix = ++ shouldSkipTransform ? Matrix4x4(): GetTransformForRendering(); + + uint32_t flags = FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR; + RefPtr<ContainerLayer> container = aManager->GetLayerBuilder()-> +diff --git dom/svg/crashtests/1343147.svg dom/svg/crashtests/1343147.svg +new file mode 100644 +index 000000000000..d9c2611ca822 +--- /dev/null ++++ dom/svg/crashtests/1343147.svg +@@ -0,0 +1,13 @@ ++<svg xmlns="http://www.w3.org/2000/svg"> ++<style> ++<![CDATA[ ++ svg { ++ background-image: linear-gradient(lime, lime); ++ background-clip: text; ++ } ++ text { transform: skewy(30grad); } ++ g { perspective: 0; } ++]]> ++</style> ++ <g><text>hello</text></g> ++</svg> +diff --git dom/svg/crashtests/crashtests.list dom/svg/crashtests/crashtests.list +index 1727a206ec4f..57ab320161e2 100644 +--- dom/svg/crashtests/crashtests.list ++++ dom/svg/crashtests/crashtests.list +@@ -90,4 +90,5 @@ load 1329849-5.svg + load 1329849-6.svg + load 1329093-1.html + load 1329093-2.html ++load 1343147.svg + load 1402798.html diff --git a/www/waterfox/files/patch-bug1345058 b/www/waterfox/files/patch-bug1345058 new file mode 100644 index 000000000000..02874af1505b --- /dev/null +++ b/www/waterfox/files/patch-bug1345058 @@ -0,0 +1,620 @@ +commit 1f57fdb85d3d +Author: Thomas Nguyen <tnguyen@mozilla.com> +Date: Mon Aug 14 14:05:23 2017 +0800 + + Bug 1345058 - Asynchronously decide if a flash document should be blocked. r=baku + + MozReview-Commit-ID: K91cSvIdOrb + + --HG-- + extra : rebase_source : 4d91ab3499c0124129e74a054c5cc78882ff351e +--- + dom/base/nsDocument.cpp | 447 ++++++++++++++++++--- + dom/base/nsDocument.h | 5 + + .../url-classifier/nsUrlClassifierDBService.cpp | 22 +- + 3 files changed, 401 insertions(+), 73 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index acfde3bc0210..386c96745438 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -279,6 +279,7 @@ + #include "nsIURIClassifier.h" + #include "mozilla/DocumentStyleRootIterator.h" + #include "mozilla/ServoRestyleManager.h" ++#include "mozilla/ClearOnShutdown.h" + + using namespace mozilla; + using namespace mozilla::dom; +@@ -319,6 +320,65 @@ GetHttpChannelHelper(nsIChannel* aChannel, nsIHttpChannel** aHttpChannel) + return NS_OK; + } + ++//////////////////////////////////////////////////////////////////// ++// PrincipalFlashClassifier ++ ++// Classify the flash based on the document principal. ++// The usage of this class is as follows: ++// ++// 1) Call AsyncClassify() as early as possible to asynchronously do ++// classification against all the flash blocking related tables ++// via nsIURIClassifier.asyncClassifyLocalWithTables. ++// ++// 2) At any time you need the classification result, call Result() ++// and it is guaranteed to give you the result. Note that you have ++// to specify "aIsThirdParty" to the function so please make sure ++// you can already correctly decide if the document is third-party. ++// ++// Behind the scenes, the sync classification API ++// (nsIURIClassifier.classifyLocalWithTable) may be called as a fallback to ++// synchronously get the result if the asyncClassifyLocalWithTables hasn't ++// been done yet. ++// ++// 3) You can call Result() as many times as you want and only the first time ++// it may unfortunately call the blocking sync API. The subsequent call ++// will just return the result that came out at the first time. ++// ++class PrincipalFlashClassifier final : public nsIURIClassifierCallback ++{ ++public: ++ NS_DECL_THREADSAFE_ISUPPORTS ++ NS_DECL_NSIURICLASSIFIERCALLBACK ++ ++ PrincipalFlashClassifier(); ++ ++ // Fire async classification based on the given principal. ++ void AsyncClassify(nsIPrincipal* aPrincipal); ++ ++ // Would block if the result hasn't come out. ++ mozilla::dom::FlashClassification ClassifyMaybeSync(nsIPrincipal* aPrincipal, ++ bool aIsThirdParty); ++ ++private: ++ ~PrincipalFlashClassifier() = default; ++ ++ void Reset(); ++ bool EnsureUriClassifier(); ++ mozilla::dom::FlashClassification CheckIfClassifyNeeded(nsIPrincipal* aPrincipal); ++ mozilla::dom::FlashClassification Resolve(bool aIsThirdParty); ++ mozilla::dom::FlashClassification AsyncClassifyInternal(nsIPrincipal* aPrincipal); ++ void GetClassificationTables(bool aIsThirdParty, nsACString& aTables); ++ ++ // For the fallback sync classification. ++ nsCOMPtr<nsIURI> mClassificationURI; ++ ++ nsCOMPtr<nsIURIClassifier> mUriClassifier; ++ bool mAsyncClassified; ++ nsTArray<nsCString> mMatchedTables; ++ mozilla::dom::FlashClassification mResult; ++}; ++ ++ + #define NAME_NOT_VALID ((nsSimpleContentList*)1) + + nsIdentifierMapEntry::~nsIdentifierMapEntry() +@@ -1575,6 +1635,9 @@ nsDocument::nsDocument(const char* aContentType) + + // void state used to differentiate an empty source from an unselected source + mPreloadPictureFoundSource.SetIsVoid(true); ++ // For determining if this is a flash document which should be ++ // blocked based on its principal. ++ mPrincipalFlashClassifier = new PrincipalFlashClassifier(); + } + + void +@@ -2761,6 +2824,11 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsIChannel* aChannel, + aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION); + } + ++ // Perform a async flash classification based on the doc principal ++ // in an early stage to reduce the blocking time. ++ mFlashClassification = FlashClassification::Unclassified; ++ mPrincipalFlashClassifier->AsyncClassify(GetPrincipal()); ++ + return NS_OK; + } + +@@ -13483,6 +13551,23 @@ nsIDocument::UpdateStyleBackendType() + #endif + } + ++/** ++ * Retrieves the classification of the Flash plugins in the document based on ++ * the classification lists. We perform AsyncInitFlashClassification on ++ * StartDocumentLoad() and the result may not be initialized when this function ++ * gets called. In that case, We can only unfortunately have a blocking wait. ++ * ++ * For more information, see ++ * toolkit/components/url-classifier/flash-block-lists.rst ++ */ ++FlashClassification ++nsDocument::PrincipalFlashClassification() ++{ ++ MOZ_ASSERT(mPrincipalFlashClassifier); ++ return mPrincipalFlashClassifier->ClassifyMaybeSync(GetPrincipal(), ++ IsThirdParty()); ++} ++ + /** + * Helper function for |nsDocument::PrincipalFlashClassification| + * +@@ -13523,27 +13608,279 @@ ArrayContainsTable(const nsTArray<nsCString>& aTableArray, + return false; + } + +-/** +- * Retrieves the classification of the Flash plugins in the document based on +- * the classification lists. +- * +- * For more information, see +- * toolkit/components/url-classifier/flash-block-lists.rst +- */ ++namespace { ++ ++// An object to store all preferences we need for flash blocking feature. ++struct PrefStore ++{ ++ PrefStore() ++ { ++ Preferences::AddBoolVarCache(&mFlashBlockEnabled, ++ "plugins.flashBlock.enabled"); ++ Preferences::AddBoolVarCache(&mPluginsHttpOnly, ++ "plugins.http_https_only"); ++ ++ // We only need to register string-typed preferences. ++ Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowTable", this); ++ Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowExceptTable", this); ++ Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashTable", this); ++ Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashExceptTable", this); ++ Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocTable", this); ++ Preferences::RegisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocExceptTable", this); ++ ++ UpdateStringPrefs(); ++ } ++ ++ ~PrefStore() ++ { ++ Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowTable", this); ++ Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashAllowExceptTable", this); ++ Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashTable", this); ++ Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashExceptTable", this); ++ Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocTable", this); ++ Preferences::UnregisterCallback(UpdateStringPrefs, "urlclassifier.flashSubDocExceptTable", this); ++ } ++ ++ void UpdateStringPrefs() ++ { ++ Preferences::GetCString("urlclassifier.flashAllowTable", mAllowTables); ++ Preferences::GetCString("urlclassifier.flashAllowExceptTable", mAllowExceptionsTables); ++ Preferences::GetCString("urlclassifier.flashTable", mDenyTables); ++ Preferences::GetCString("urlclassifier.flashExceptTable", mDenyExceptionsTables); ++ Preferences::GetCString("urlclassifier.flashSubDocTable", mSubDocDenyTables); ++ Preferences::GetCString("urlclassifier.flashSubDocExceptTable", mSubDocDenyExceptionsTables); ++ } ++ ++ static void UpdateStringPrefs(const char*, void* aClosure) ++ { ++ static_cast<PrefStore*>(aClosure)->UpdateStringPrefs(); ++ } ++ ++ bool mFlashBlockEnabled; ++ bool mPluginsHttpOnly; ++ ++ nsCString mAllowTables; ++ nsCString mAllowExceptionsTables; ++ nsCString mDenyTables; ++ nsCString mDenyExceptionsTables; ++ nsCString mSubDocDenyTables; ++ nsCString mSubDocDenyExceptionsTables; ++}; ++ ++static const ++PrefStore& GetPrefStore() ++{ ++ static UniquePtr<PrefStore> sPrefStore; ++ if (!sPrefStore) { ++ sPrefStore.reset(new PrefStore()); ++ ClearOnShutdown(&sPrefStore); ++ } ++ return *sPrefStore; ++} ++ ++} // end of unnamed namespace. ++ ++//////////////////////////////////////////////////////////////////// ++// PrincipalFlashClassifier implementation. ++ ++NS_IMPL_ISUPPORTS(PrincipalFlashClassifier, nsIURIClassifierCallback) ++ ++PrincipalFlashClassifier::PrincipalFlashClassifier() ++{ ++ Reset(); ++} ++ ++void ++PrincipalFlashClassifier::Reset() ++{ ++ mAsyncClassified = false; ++ mMatchedTables.Clear(); ++ mResult = FlashClassification::Unclassified; ++} ++ ++void ++PrincipalFlashClassifier::GetClassificationTables(bool aIsThirdParty, ++ nsACString& aTables) ++{ ++ aTables.Truncate(); ++ auto& prefs = GetPrefStore(); ++ ++ MaybeAddTableToTableList(prefs.mAllowTables, aTables); ++ MaybeAddTableToTableList(prefs.mAllowExceptionsTables, aTables); ++ MaybeAddTableToTableList(prefs.mDenyTables, aTables); ++ MaybeAddTableToTableList(prefs.mDenyExceptionsTables, aTables); ++ ++ if (aIsThirdParty) { ++ MaybeAddTableToTableList(prefs.mSubDocDenyTables, aTables); ++ MaybeAddTableToTableList(prefs.mSubDocDenyExceptionsTables, aTables); ++ } ++} ++ ++bool ++PrincipalFlashClassifier::EnsureUriClassifier() ++{ ++ if (!mUriClassifier) { ++ mUriClassifier = do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID); ++ } ++ ++ return !!mUriClassifier; ++} ++ + FlashClassification +-nsDocument::PrincipalFlashClassification() ++PrincipalFlashClassifier::ClassifyMaybeSync(nsIPrincipal* aPrincipal, bool aIsThirdParty) ++{ ++ if (FlashClassification::Unclassified != mResult) { ++ // We already have the result. Just return it. ++ return mResult; ++ } ++ ++ // TODO: Bug 1342333 - Entirely remove the use of the sync API ++ // (ClassifyLocalWithTables). ++ if (!mAsyncClassified) { ++ ++ // ++ // We may ++ // 1) have called AsyncClassifyLocalWithTables but OnClassifyComplete ++ // hasn't been called. ++ // 2) haven't even called AsyncClassifyLocalWithTables. ++ // ++ // In both cases we need to do the synchronous classification as the fallback. ++ // ++ ++ if (!EnsureUriClassifier()) { ++ return FlashClassification::Denied; ++ } ++ mResult = CheckIfClassifyNeeded(aPrincipal); ++ if (FlashClassification::Unclassified != mResult) { ++ return mResult; ++ } ++ ++ nsresult rv; ++ nsAutoCString classificationTables; ++ GetClassificationTables(aIsThirdParty, classificationTables); ++ ++ if (!mClassificationURI) { ++ rv = aPrincipal->GetURI(getter_AddRefs(mClassificationURI)); ++ if (NS_FAILED(rv) || !mClassificationURI) { ++ mResult = FlashClassification::Denied; ++ return mResult; ++ } ++ } ++ ++ rv = mUriClassifier->ClassifyLocalWithTables(mClassificationURI, ++ classificationTables, ++ mMatchedTables); ++ if (NS_WARN_IF(NS_FAILED(rv))) { ++ if (rv == NS_ERROR_MALFORMED_URI) { ++ // This means that the URI had no hostname (ex: file://doc.html). In this ++ // case, we allow the default (Unknown plugin) behavior. ++ mResult = FlashClassification::Unknown; ++ } else { ++ mResult = FlashClassification::Denied; ++ } ++ return mResult; ++ } ++ } ++ ++ // Resolve the result based on mMatchedTables and aIsThirdParty. ++ mResult = Resolve(aIsThirdParty); ++ MOZ_ASSERT(FlashClassification::Unclassified != mResult); ++ ++ // The subsequent call of Result() will return the resolved result ++ // and never reach here until Reset() is called. ++ return mResult; ++} ++ ++/*virtual*/ nsresult ++PrincipalFlashClassifier::OnClassifyComplete(nsresult /*aErrorCode*/, ++ const nsACString& aLists, // Only this matters. ++ const nsACString& /*aProvider*/, ++ const nsACString& /*aPrefix*/) ++{ ++ mAsyncClassified = true; ++ ++ if (FlashClassification::Unclassified != mResult) { ++ // Result() has been called prior to this callback. ++ return NS_OK; ++ } ++ ++ // TODO: Bug 1364804 - We should use a callback type which notifies ++ // the result as a string array rather than a formatted string. ++ ++ // We only populate the matched list without resolving the classification ++ // result because we are not sure if the parent doc has been properly set. ++ // We also parse the comma-separated tables to array. (the code is copied ++ // from Classifier::SplitTables.) ++ nsACString::const_iterator begin, iter, end; ++ aLists.BeginReading(begin); ++ aLists.EndReading(end); ++ while (begin != end) { ++ iter = begin; ++ FindCharInReadable(',', iter, end); ++ nsDependentCSubstring table = Substring(begin,iter); ++ if (!table.IsEmpty()) { ++ mMatchedTables.AppendElement(Substring(begin, iter)); ++ } ++ begin = iter; ++ if (begin != end) { ++ begin++; ++ } ++ } ++ ++ return NS_OK; ++} ++ ++// We resolve the classification result based on aIsThirdParty ++// and the matched tables we got ealier on (via either sync or async API). ++FlashClassification ++PrincipalFlashClassifier::Resolve(bool aIsThirdParty) ++{ ++ MOZ_ASSERT(FlashClassification::Unclassified == mResult, ++ "We already have resolved classification result."); ++ ++ if (mMatchedTables.IsEmpty()) { ++ return FlashClassification::Unknown; ++ } ++ ++ auto& prefs = GetPrefStore(); ++ if (ArrayContainsTable(mMatchedTables, prefs.mDenyTables) && ++ !ArrayContainsTable(mMatchedTables, prefs.mDenyExceptionsTables)) { ++ return FlashClassification::Denied; ++ } else if (ArrayContainsTable(mMatchedTables, prefs.mAllowTables) && ++ !ArrayContainsTable(mMatchedTables, prefs.mAllowExceptionsTables)) { ++ return FlashClassification::Allowed; ++ } ++ ++ if (aIsThirdParty && ArrayContainsTable(mMatchedTables, prefs.mSubDocDenyTables) && ++ !ArrayContainsTable(mMatchedTables, prefs.mSubDocDenyExceptionsTables)) { ++ return FlashClassification::Denied; ++ } ++ ++ return FlashClassification::Unknown; ++} ++ ++void ++PrincipalFlashClassifier::AsyncClassify(nsIPrincipal* aPrincipal) ++{ ++ MOZ_ASSERT(FlashClassification::Unclassified == mResult, ++ "The old classification result should be reset first."); ++ Reset(); ++ mResult = AsyncClassifyInternal(aPrincipal); ++} ++ ++FlashClassification ++PrincipalFlashClassifier::CheckIfClassifyNeeded(nsIPrincipal* aPrincipal) + { + nsresult rv; + +- bool httpOnly = Preferences::GetBool("plugins.http_https_only", true); +- bool flashBlock = Preferences::GetBool("plugins.flashBlock.enabled", false); ++ auto& prefs = GetPrefStore(); + + // If neither pref is on, skip the null-principal and principal URI checks. +- if (!httpOnly && !flashBlock) { +- return FlashClassification::Unknown; ++ if (prefs.mPluginsHttpOnly && !prefs.mFlashBlockEnabled) { ++ return FlashClassification::Unknown; + } + +- nsCOMPtr<nsIPrincipal> principal = GetPrincipal(); ++ nsCOMPtr<nsIPrincipal> principal = aPrincipal; + if (principal->GetIsNullPrincipal()) { + return FlashClassification::Denied; + } +@@ -13554,7 +13891,7 @@ nsDocument::PrincipalFlashClassification() + return FlashClassification::Denied; + } + +- if (httpOnly) { ++ if (prefs.mPluginsHttpOnly) { + // Only allow plugins for documents from an HTTP/HTTPS origin. This should + // allow dependent data: URIs to load plugins, but not: + // * chrome documents +@@ -13570,49 +13907,50 @@ nsDocument::PrincipalFlashClassification() + + // If flash blocking is disabled, it is equivalent to all sites being + // on neither list. +- if (!flashBlock) { ++ if (!prefs.mFlashBlockEnabled) { + return FlashClassification::Unknown; + } + +- nsAutoCString allowTables, allowExceptionsTables, +- denyTables, denyExceptionsTables, +- subDocDenyTables, subDocDenyExceptionsTables, +- tables; +- Preferences::GetCString("urlclassifier.flashAllowTable", allowTables); +- MaybeAddTableToTableList(allowTables, tables); +- Preferences::GetCString("urlclassifier.flashAllowExceptTable", +- allowExceptionsTables); +- MaybeAddTableToTableList(allowExceptionsTables, tables); +- Preferences::GetCString("urlclassifier.flashTable", denyTables); +- MaybeAddTableToTableList(denyTables, tables); +- Preferences::GetCString("urlclassifier.flashExceptTable", +- denyExceptionsTables); +- MaybeAddTableToTableList(denyExceptionsTables, tables); +- +- bool isThirdPartyDoc = IsThirdParty(); +- if (isThirdPartyDoc) { +- Preferences::GetCString("urlclassifier.flashSubDocTable", +- subDocDenyTables); +- MaybeAddTableToTableList(subDocDenyTables, tables); +- Preferences::GetCString("urlclassifier.flashSubDocExceptTable", +- subDocDenyExceptionsTables); +- MaybeAddTableToTableList(subDocDenyExceptionsTables, tables); ++ return FlashClassification::Unclassified; ++} ++ ++// Using nsIURIClassifier.asyncClassifyLocalWithTables to do classification ++// against the flash related tables based on the given principal. ++FlashClassification ++PrincipalFlashClassifier::AsyncClassifyInternal(nsIPrincipal* aPrincipal) ++{ ++ auto result = CheckIfClassifyNeeded(aPrincipal); ++ if (FlashClassification::Unclassified != result) { ++ return result; + } + ++ // We haven't been able to decide if it's a third party document ++ // since determining if a document is third-party may depend on its ++ // parent document. At the time we call AsyncClassifyInternal ++ // (i.e. StartDocumentLoad) the parent document may not have been ++ // set. As a result, we wait until Resolve() to be called to ++ // take "is third party" into account. At this point, we just assume ++ // it's third-party to include every list. ++ nsAutoCString tables; ++ GetClassificationTables(true, tables); ++ + if (tables.IsEmpty()) { + return FlashClassification::Unknown; + } + +- nsCOMPtr<nsIURIClassifier> uriClassifier = +- do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv); +- if (NS_FAILED(rv)) { ++ if (!EnsureUriClassifier()) { + return FlashClassification::Denied; + } + +- nsTArray<nsCString> results; +- rv = uriClassifier->ClassifyLocalWithTables(classificationURI, +- tables, +- results); ++ nsresult rv = aPrincipal->GetURI(getter_AddRefs(mClassificationURI)); ++ if (NS_FAILED(rv) || !mClassificationURI) { ++ return FlashClassification::Denied; ++ } ++ ++ rv = mUriClassifier->AsyncClassifyLocalWithTables(mClassificationURI, ++ tables, ++ this); ++ + if (NS_FAILED(rv)) { + if (rv == NS_ERROR_MALFORMED_URI) { + // This means that the URI had no hostname (ex: file://doc.html). In this +@@ -13623,24 +13961,7 @@ nsDocument::PrincipalFlashClassification() + } + } + +- if (results.IsEmpty()) { +- return FlashClassification::Unknown; +- } +- +- if (ArrayContainsTable(results, denyTables) && +- !ArrayContainsTable(results, denyExceptionsTables)) { +- return FlashClassification::Denied; +- } else if (ArrayContainsTable(results, allowTables) && +- !ArrayContainsTable(results, allowExceptionsTables)) { +- return FlashClassification::Allowed; +- } +- +- if (isThirdPartyDoc && ArrayContainsTable(results, subDocDenyTables) && +- !ArrayContainsTable(results, subDocDenyExceptionsTables)) { +- return FlashClassification::Denied; +- } +- +- return FlashClassification::Unknown; ++ return FlashClassification::Unclassified; + } + + FlashClassification +diff --git dom/base/nsDocument.h dom/base/nsDocument.h +index be3d59698b56..5a2938f353a3 100644 +--- dom/base/nsDocument.h ++++ dom/base/nsDocument.h +@@ -72,6 +72,7 @@ + #include "CustomElementRegistry.h" + #include "mozilla/dom/Performance.h" + #include "mozilla/Maybe.h" ++#include "nsIURIClassifier.h" + + #define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0) + #define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1) +@@ -346,6 +347,9 @@ protected: + bool mHaveShutDown; + }; + ++// For classifying a flash document based on its principal. ++class PrincipalFlashClassifier; ++ + // Base class for our document implementations. + class nsDocument : public nsIDocument, + public nsIDOMDocument, +@@ -1184,6 +1188,7 @@ protected: + // non-null when this document is in fullscreen mode. + nsWeakPtr mFullscreenRoot; + ++ RefPtr<PrincipalFlashClassifier> mPrincipalFlashClassifier; + mozilla::dom::FlashClassification mFlashClassification; + // Do not use this value directly. Call the |IsThirdParty()| method, which + // caches its result here. +diff --git toolkit/components/url-classifier/nsUrlClassifierDBService.cpp toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +index 074bfc583b93..6476b8d546f3 100644 +--- toolkit/components/url-classifier/nsUrlClassifierDBService.cpp ++++ toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +@@ -1783,6 +1783,18 @@ nsUrlClassifierDBService::AsyncClassifyLocalWithTables(nsIURI *aURI, + MOZ_ASSERT(NS_IsMainThread(), "AsyncClassifyLocalWithTables must be called " + "on main thread"); + ++ // We do this check no matter what process we are in to return ++ // error as early as possible. ++ nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI); ++ NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); ++ ++ nsAutoCString key; ++ // Canonicalize the url ++ nsCOMPtr<nsIUrlClassifierUtils> utilsService = ++ do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID); ++ nsresult rv = utilsService->GetKeyForURI(uri, key); ++ NS_ENSURE_SUCCESS(rv, rv); ++ + if (XRE_IsContentProcess()) { + using namespace mozilla::dom; + using namespace mozilla::ipc; +@@ -1815,16 +1827,6 @@ nsUrlClassifierDBService::AsyncClassifyLocalWithTables(nsIURI *aURI, + using namespace mozilla::Telemetry; + auto startTime = TimeStamp::Now(); // For telemetry. + +- nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI); +- NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); +- +- nsAutoCString key; +- // Canonicalize the url +- nsCOMPtr<nsIUrlClassifierUtils> utilsService = +- do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID); +- nsresult rv = utilsService->GetKeyForURI(uri, key); +- NS_ENSURE_SUCCESS(rv, rv); +- + auto worker = mWorker; + nsCString tables(aTables); + diff --git a/www/waterfox/files/patch-bug1346126 b/www/waterfox/files/patch-bug1346126 new file mode 100644 index 000000000000..667a2620904d --- /dev/null +++ b/www/waterfox/files/patch-bug1346126 @@ -0,0 +1,27 @@ +commit b46bdf1c51e0 +Author: Ryan Hunt <rhunt@eqrion.net> +Date: Fri Jun 1 11:18:07 2018 -0500 + + Bug 1346126 - Use RemoveAllChildren in ~ContainerLayerComposite. r=mattwoodrow, a=RyanVM + + --HG-- + extra : source : b9814173e9a8ebbf9e6a0cb6dbf751fadead17c4 +--- + gfx/layers/composite/ContainerLayerComposite.cpp | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git gfx/layers/composite/ContainerLayerComposite.cpp gfx/layers/composite/ContainerLayerComposite.cpp +index c40b3c19f8a88..74aed9bbcc03c 100644 +--- gfx/layers/composite/ContainerLayerComposite.cpp ++++ gfx/layers/composite/ContainerLayerComposite.cpp +@@ -650,9 +650,7 @@ ContainerLayerComposite::~ContainerLayerComposite() + // LayerManagerComposite::Destroy(), a parent + // *ContainerLayerComposite::Destroy(), or Disconnect() will trigger + // cleanup of our resources. +- while (mFirstChild) { +- RemoveChild(mFirstChild); +- } ++ RemoveAllChildren(); + } + + void diff --git a/www/waterfox/files/patch-bug1346535 b/www/waterfox/files/patch-bug1346535 new file mode 100644 index 000000000000..c7621895d3dd --- /dev/null +++ b/www/waterfox/files/patch-bug1346535 @@ -0,0 +1,504 @@ +commit 8ed454acd81e +Author: Samuel Thibault <samuel.thibault@ens-lyon.org> +Date: Fri Mar 16 15:57:00 2018 -0400 + + Bug 1346535 - atk: Introduce U+FEFF characters to match AT-SPI offsets with DOM offsets. r=surkov, r=dbaron a=jcristau + + --HG-- + extra : source : 6f9396e9ea0a261c881dfafbfce894d7138beb6f +--- + accessible/atk/DOMtoATK.cpp | 161 +++++++++++++++++++++++++++++++++ + accessible/atk/DOMtoATK.h | 163 ++++++++++++++++++++++++++++++++++ + accessible/atk/moz.build | 1 + + accessible/atk/nsMaiInterfaceText.cpp | 40 ++++----- + xpcom/string/nsUTF8Utils.h | 24 +++++ + 5 files changed, 369 insertions(+), 20 deletions(-) + +diff --git accessible/atk/DOMtoATK.cpp accessible/atk/DOMtoATK.cpp +new file mode 100644 +index 000000000000..ea9fa543186c +--- /dev/null ++++ accessible/atk/DOMtoATK.cpp +@@ -0,0 +1,161 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=2 et sw=2 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 "DOMtoATK.h" ++#include "nsUTF8Utils.h" ++ ++namespace mozilla { ++namespace a11y { ++ ++namespace DOMtoATK { ++ ++void ++AddBOMs(nsACString& aDest, const nsACString& aSource) ++{ ++ uint32_t destlength = 0; ++ ++ // First compute how much room we will need. ++ for (uint32_t srci = 0; srci < aSource.Length(); ) { ++ int bytes = UTF8traits::bytes(aSource[srci]); ++ if (bytes >= 4) { ++ // Non-BMP character, will add a BOM after it. ++ destlength += 3; ++ } ++ // Skip whole character encoding. ++ srci += bytes; ++ destlength += bytes; ++ } ++ ++ uint32_t desti = 0; // Index within aDest. ++ ++ // Add BOMs after non-BMP characters. ++ aDest.SetLength(destlength); ++ for (uint32_t srci = 0; srci < aSource.Length(); ) { ++ uint32_t bytes = UTF8traits::bytes(aSource[srci]); ++ ++ MOZ_ASSERT(bytes <= aSource.Length() - srci, "We should have the whole sequence"); ++ ++ // Copy whole sequence. ++ aDest.Replace(desti, bytes, Substring(aSource, srci, bytes)); ++ desti += bytes; ++ srci += bytes; ++ ++ if (bytes >= 4) { ++ // More than 4 bytes in UTF-8 encoding exactly means more than 16 encoded ++ // bits. This is thus a non-BMP character which needed a surrogate ++ // pair to get encoded in UTF-16, add a BOM after it. ++ ++ // And add a BOM after it. ++ aDest.Replace(desti, 3, "\xEF\xBB\xBF"); ++ desti += 3; ++ } ++ } ++ MOZ_ASSERT(desti == destlength, "Incoherency between computed length" ++ "and actually translated length"); ++} ++ ++void ++ATKStringConverterHelper::AdjustOffsets(gint* aStartOffset, gint* aEndOffset, ++ gint count) ++{ ++ MOZ_ASSERT(!mAdjusted, "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be called only once"); ++ ++ if (*aStartOffset > 0) { ++ (*aStartOffset)--; ++ mStartShifted = true; ++ } ++ ++ if (*aEndOffset != -1 && *aEndOffset < count) { ++ (*aEndOffset)++; ++ mEndShifted = true; ++ } ++ ++#ifdef DEBUG ++ mAdjusted = true; ++#endif ++} ++ ++gchar* ++ATKStringConverterHelper::FinishUTF16toUTF8(nsCString& aStr) ++{ ++ int skip = 0; ++ ++ if (mStartShifted) { ++ // AdjustOffsets added a leading character. ++ ++ MOZ_ASSERT(aStr.Length() > 0, "There should be a leading character"); ++ MOZ_ASSERT(static_cast<int>(aStr.Length()) >= UTF8traits::bytes(aStr.CharAt(0)), ++ "The leading character should be complete"); ++ ++ // drop first character ++ skip = UTF8traits::bytes(aStr.CharAt(0)); ++ } ++ ++ if (mEndShifted) { ++ // AdjustOffsets added a trailing character. ++ ++ MOZ_ASSERT(aStr.Length() > 0, "There should be a trailing character"); ++ ++ int trail = -1; ++ // Find beginning of last character. ++ for (trail = aStr.Length() - 1; trail >= 0; trail--) { ++ if (!UTF8traits::isInSeq(aStr.CharAt(trail))) { ++ break; ++ } ++ } ++ MOZ_ASSERT(trail >= 0, ++ "There should be at least a whole trailing character"); ++ MOZ_ASSERT(trail + UTF8traits::bytes(aStr.CharAt(trail)) == static_cast<int>(aStr.Length()), ++ "The trailing character should be complete"); ++ ++ // Drop the last character. ++ aStr.Truncate(trail); ++ } ++ ++ // copy and return, libspi will free it ++ return g_strdup(aStr.get() + skip); ++} ++ ++gchar* ++ATKStringConverterHelper::ConvertAdjusted(const nsAString& aStr) ++{ ++ MOZ_ASSERT(mAdjusted, "DOMtoATK::ATKStringConverterHelper::AdjustOffsets needs to be called before ATKStringConverterHelper::ConvertAdjusted"); ++ ++ NS_ConvertUTF16toUTF8 cautoStr(aStr); ++ if (!cautoStr.get()) { ++ return nullptr; ++ } ++ ++ nsAutoCString cautoStrBOMs; ++ AddBOMs(cautoStrBOMs, cautoStr); ++ return FinishUTF16toUTF8(cautoStrBOMs); ++} ++ ++gchar* ++Convert(const nsAString& aStr) ++{ ++ NS_ConvertUTF16toUTF8 cautoStr(aStr); ++ if (!cautoStr.get()) { ++ return nullptr; ++ } ++ ++ nsAutoCString cautoStrBOMs; ++ AddBOMs(cautoStrBOMs, cautoStr); ++ return g_strdup(cautoStrBOMs.get()); ++} ++ ++void ++ConvertTexttoAsterisks(nsAString& aString) ++{ ++ for (uint32_t i = 0; i < aString.Length(); i++) { ++ aString.ReplaceLiteral(i, 1, u"*"); ++ } ++} ++ ++} ++ ++} // namespace a11y ++} // namespace mozilla +diff --git accessible/atk/DOMtoATK.h accessible/atk/DOMtoATK.h +new file mode 100644 +index 000000000000..1f1b125ebbbe +--- /dev/null ++++ accessible/atk/DOMtoATK.h +@@ -0,0 +1,163 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=2 et sw=2 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 "AccessibleWrap.h" ++#include "nsString.h" ++#include "nsMai.h" ++ ++/** ++ * ATK offsets are counted in unicode codepoints, while DOM offsets are counted ++ * in UTF-16 code units. That makes a difference for non-BMP characters, ++ * which need two UTF-16 code units to be represented (a pair of surrogates), ++ * while they are just one unicode character. ++ * ++ * To keep synchronization between ATK offsets (unicode codepoints) and DOM ++ * offsets (UTF-16 code units), after translation from UTF-16 to UTF-8 we add a ++ * BOM after each non-BMP character (which would otherwise use 2 UTF-16 ++ * code units for only 1 unicode codepoint). ++ * ++ * BOMs (Byte Order Marks, U+FEFF, also known as ZERO WIDTH NO-BREAK SPACE, but ++ * that usage is deprecated) normally only appear at the beginning of unicode ++ * files, but their occurrence within text (notably after cut&paste) is not ++ * uncommon, and are thus considered as non-text. ++ * ++ * Since the selection requested through ATK may not contain both surrogates ++ * at the ends of the selection, we need to fetch one UTF-16 code point more ++ * on both side, and get rid of it before returning the string to ATK. The ++ * ATKStringConverterHelper class maintains this, NewATKString should be used ++ * to call it properly. ++ * ++ * In the end, ++ * - if the start is between the high and low surrogates, the UTF-8 result ++ * includes a BOM from it but not the character ++ * - if the end is between the high and low surrogates, the UTF-8 result ++ * includes the character but *not* the BOM ++ * - all non-BMP characters that are fully in the string are in the UTF-8 result ++ * as character followed by BOM ++ */ ++namespace mozilla { ++namespace a11y { ++ ++namespace DOMtoATK ++{ ++ ++ /** ++ * Converts a string of accessible text into ATK gchar* string (by adding ++ * BOMs). This can be used when offsets do not need to be adjusted because ++ * ends of the string can not fall between surrogates. ++ */ ++ gchar* Convert(const nsAString& aStr); ++ ++ /** ++ * Add a BOM after each non-BMP character. ++ */ ++ void AddBOMs(nsACString& aDest, const nsACString& aSource); ++ ++ /** ++ * Replace all characters with asterisks (e.g. for password fields). ++ */ ++ void ConvertTexttoAsterisks(nsAString& aString); ++ ++ /** ++ * Parameterize conversion. ++ */ ++ enum class AtkStringConvertFlags : uint32_t { ++ None = 0, ++ ConvertTextToAsterisks = 1 << 0, ++ }; ++ ++ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AtkStringConvertFlags) ++ ++ class ATKStringConverterHelper { ++ public: ++ ATKStringConverterHelper(void) : ++#ifdef DEBUG ++ mAdjusted (false), ++#endif ++ mStartShifted (false), ++ mEndShifted (false) { } ++ ++ /** ++ * In order to properly get non-BMP values, offsets need to be changed ++ * to get one character more on each end, so that ConvertUTF16toUTF8 can ++ * convert surrogates even if the originally requested offsets fall between ++ * them. ++ */ ++ void AdjustOffsets(gint* aStartOffset, gint* aEndOffset, gint count); ++ ++ /** ++ * Converts a string of accessible text with adjusted offsets into ATK ++ * gchar* string (by adding BOMs). Note, AdjustOffsets has to be called ++ * before getting the text passed to this. ++ */ ++ gchar* ConvertAdjusted(const nsAString& aStr); ++ ++ private: ++ /** ++ * Remove the additional characters requested by PrepareUTF16toUTF8. ++ */ ++ gchar* FinishUTF16toUTF8(nsCString& aStr); ++ ++#ifdef DEBUG ++ bool mAdjusted; ++#endif ++ bool mStartShifted; ++ bool mEndShifted; ++ }; ++ ++ /** ++ * Get text from aAccessible, using ATKStringConverterHelper to properly ++ * introduce appropriate BOMs. ++ */ ++ template <class AccessibleOrProxy> ++ gchar* NewATKString(AccessibleOrProxy* aAccessible, ++ gint aStartOffset, gint aEndOffset, ++ AtkStringConvertFlags aFlags) ++ { ++ gint startOffset = aStartOffset, endOffset = aEndOffset; ++ ATKStringConverterHelper converter; ++ converter.AdjustOffsets(&startOffset, &endOffset, ++ gint(aAccessible->CharacterCount())); ++ nsAutoString str; ++ aAccessible->TextSubstring(startOffset, endOffset, str); ++ if (aFlags & AtkStringConvertFlags::ConvertTextToAsterisks) ++ ConvertTexttoAsterisks(str); ++ return converter.ConvertAdjusted(str); ++ } ++ ++ /** ++ * Get a character from aAccessible, fetching more data as appropriate to ++ * properly get non-BMP characters or a BOM as appropriate. ++ */ ++ template <class AccessibleCharAt> ++ gunichar ATKCharacter(AccessibleCharAt* aAccessible, gint aOffset) ++ { ++ // char16_t is unsigned short in Mozilla, gnuichar is guint32 in glib. ++ gunichar character = static_cast<gunichar>(aAccessible->CharAt(aOffset)); ++ ++ if (NS_IS_LOW_SURROGATE(character)) { ++ // Trailing surrogate, return BOM instead. ++ return 0xFEFF; ++ } ++ ++ if (NS_IS_HIGH_SURROGATE(character)) { ++ // Heading surrogate, get the trailing surrogate and combine them. ++ gunichar characterLow = static_cast<gunichar>(aAccessible->CharAt(aOffset + 1)); ++ ++ if (!NS_IS_LOW_SURROGATE(characterLow)) { ++ // It should have been a trailing surrogate... Flag the error. ++ return 0xFFFD; ++ } ++ return SURROGATE_TO_UCS4(character, characterLow); ++ } ++ ++ return character; ++ } ++ ++} ++ ++} // namespace a11y ++} // namespace mozilla +diff --git accessible/atk/moz.build accessible/atk/moz.build +index baf71c6656b5..19b94bcca723 100644 +--- accessible/atk/moz.build ++++ accessible/atk/moz.build +@@ -14,6 +14,7 @@ SOURCES += [ + 'ApplicationAccessibleWrap.cpp', + 'AtkSocketAccessible.cpp', + 'DocAccessibleWrap.cpp', ++ 'DOMtoATK.cpp', + 'nsMaiHyperlink.cpp', + 'nsMaiInterfaceAction.cpp', + 'nsMaiInterfaceComponent.cpp', +diff --git accessible/atk/nsMaiInterfaceText.cpp accessible/atk/nsMaiInterfaceText.cpp +index d8c162855343..0c723279046e 100644 +--- accessible/atk/nsMaiInterfaceText.cpp ++++ accessible/atk/nsMaiInterfaceText.cpp +@@ -14,9 +14,12 @@ + #include "nsIAccessibleTypes.h" + #include "nsIPersistentProperties2.h" + #include "nsISimpleEnumerator.h" ++#include "nsUTF8Utils.h" + + #include "mozilla/Likely.h" + ++#include "DOMtoATK.h" ++ + using namespace mozilla; + using namespace mozilla::a11y; + +@@ -128,8 +131,7 @@ ConvertTexttoAsterisks(AccessibleWrap* accWrap, nsAString& aString) + { + // convert each char to "*" when it's "password text" + if (accWrap->NativeRole() == roles::PASSWORD_TEXT) { +- for (uint32_t i = 0; i < aString.Length(); i++) +- aString.Replace(i, 1, NS_LITERAL_STRING("*")); ++ DOMtoATK::ConvertTexttoAsterisks(aString); + } + } + +@@ -142,20 +144,20 @@ getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset) + nsAutoString autoStr; + if (accWrap) { + HyperTextAccessible* text = accWrap->AsHyperText(); +- if (!text || !text->IsTextRole()) ++ if (!text || !text->IsTextRole() || text->IsDefunct()) + return nullptr; + +- text->TextSubstring(aStartOffset, aEndOffset, autoStr); ++ return DOMtoATK::NewATKString(text, aStartOffset, aEndOffset, ++ accWrap->NativeRole() == roles::PASSWORD_TEXT ? ++ DOMtoATK::AtkStringConvertFlags::ConvertTextToAsterisks : ++ DOMtoATK::AtkStringConvertFlags::None); + +- ConvertTexttoAsterisks(accWrap, autoStr); + } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) { +- proxy->TextSubstring(aStartOffset, aEndOffset, autoStr); ++ return DOMtoATK::NewATKString(proxy, aStartOffset, aEndOffset, ++ DOMtoATK::AtkStringConvertFlags::None); + } + +- NS_ConvertUTF16toUTF8 cautoStr(autoStr); +- +- //copy and return, libspi will free it. +- return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr; ++ return nullptr; + } + + static gchar* +@@ -181,8 +183,8 @@ getTextAfterOffsetCB(AtkText *aText, gint aOffset, + *aStartOffset = startOffset; + *aEndOffset = endOffset; + +- NS_ConvertUTF16toUTF8 cautoStr(autoStr); +- return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr; ++ // libspi will free it. ++ return DOMtoATK::Convert(autoStr); + } + + static gchar* +@@ -208,8 +210,8 @@ getTextAtOffsetCB(AtkText *aText, gint aOffset, + *aStartOffset = startOffset; + *aEndOffset = endOffset; + +- NS_ConvertUTF16toUTF8 cautoStr(autoStr); +- return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr; ++ // libspi will free it. ++ return DOMtoATK::Convert(autoStr); + } + + static gunichar +@@ -221,13 +223,11 @@ getCharacterAtOffsetCB(AtkText* aText, gint aOffset) + if (!text || !text->IsTextRole()) { + return 0; + } +- +- // char16_t is unsigned short in Mozilla, gnuichar is guint32 in glib. +- return static_cast<gunichar>(text->CharAt(aOffset)); ++ return DOMtoATK::ATKCharacter(text, aOffset); + } + + if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) { +- return static_cast<gunichar>(proxy->CharAt(aOffset)); ++ return DOMtoATK::ATKCharacter(proxy, aOffset); + } + + return 0; +@@ -257,8 +257,8 @@ getTextBeforeOffsetCB(AtkText *aText, gint aOffset, + *aStartOffset = startOffset; + *aEndOffset = endOffset; + +- NS_ConvertUTF16toUTF8 cautoStr(autoStr); +- return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nullptr; ++ // libspi will free it. ++ return DOMtoATK::Convert(autoStr); + } + + static gint +diff --git xpcom/string/nsUTF8Utils.h xpcom/string/nsUTF8Utils.h +index ef140084c2e6..5d39b05e799a 100644 +--- xpcom/string/nsUTF8Utils.h ++++ xpcom/string/nsUTF8Utils.h +@@ -56,6 +56,30 @@ public: + { + return (aChar & 0xFE) == 0xFC; + } ++ // return the number of bytes in a sequence beginning with aChar ++ static int bytes(char aChar) ++ { ++ if (isASCII(aChar)) { ++ return 1; ++ } ++ if (is2byte(aChar)) { ++ return 2; ++ } ++ if (is3byte(aChar)) { ++ return 3; ++ } ++ if (is4byte(aChar)) { ++ return 4; ++ } ++ if (is5byte(aChar)) { ++ return 5; ++ } ++ if (is6byte(aChar)) { ++ return 6; ++ } ++ MOZ_ASSERT_UNREACHABLE("should not be used for in-sequence characters"); ++ return 1; ++ } + }; + + /** diff --git a/www/waterfox/files/patch-bug1347984 b/www/waterfox/files/patch-bug1347984 new file mode 100644 index 000000000000..fa976288d452 --- /dev/null +++ b/www/waterfox/files/patch-bug1347984 @@ -0,0 +1,96 @@ +commit d40956eaa7d8 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Fri Oct 6 20:11:07 2017 +0200 + + Bug 1347984 - Check for dead object proxies in TriggerPromiseReactions. r=till, a=ritu + + --HG-- + extra : source : 754a3e12321c8656a83759adf297e61b0e188368 +--- + js/src/builtin/Promise.cpp | 6 +++++- + js/src/jit-test/tests/basic/bug908915.js | 1 + + js/src/jit-test/tests/promise/bug1347984.js | 6 ++++++ + js/src/shell/js.cpp | 21 +++++++++++++++++++++ + 4 files changed, 33 insertions(+), 1 deletion(-) + +diff --git js/src/builtin/Promise.cpp js/src/builtin/Promise.cpp +index 2462f1f07853..1cb1cff0682e 100644 +--- js/src/builtin/Promise.cpp ++++ js/src/builtin/Promise.cpp +@@ -1017,8 +1017,12 @@ TriggerPromiseReactions(JSContext* cx, HandleValue reactionsVal, JS::PromiseStat + RootedObject reactions(cx, &reactionsVal.toObject()); + RootedObject reaction(cx); + +- if (reactions->is<PromiseReactionRecord>() || IsWrapper(reactions)) ++ if (reactions->is<PromiseReactionRecord>() || ++ IsWrapper(reactions) || ++ JS_IsDeadWrapper(reactions)) ++ { + return EnqueuePromiseReactionJob(cx, reactions, valueOrReason, state); ++ } + + RootedNativeObject reactionsList(cx, &reactions->as<NativeObject>()); + size_t reactionsCount = reactionsList->getDenseInitializedLength(); +diff --git js/src/jit-test/tests/basic/bug908915.js js/src/jit-test/tests/basic/bug908915.js +index 5077801b1b67..f0213296e769 100644 +--- js/src/jit-test/tests/basic/bug908915.js ++++ js/src/jit-test/tests/basic/bug908915.js +@@ -11,6 +11,7 @@ var blacklist = { + 'readline': true, + 'terminate': true, + 'nestedShell': true, ++ 'nukeAllCCWs': true, + }; + + function f(y) {} +diff --git js/src/jit-test/tests/promise/bug1347984.js js/src/jit-test/tests/promise/bug1347984.js +new file mode 100644 +index 000000000000..5fc458cd452e +--- /dev/null ++++ js/src/jit-test/tests/promise/bug1347984.js +@@ -0,0 +1,6 @@ ++// |jit-test| error:dead object ++var g = newGlobal(); ++var p = new Promise(() => {}); ++g.Promise.prototype.then.call(p, () => void 0); ++g.eval("nukeAllCCWs()"); ++resolvePromise(p, 9); +diff --git js/src/shell/js.cpp js/src/shell/js.cpp +index 2bb7e97120a7..8e9aee7c854a 100644 +--- js/src/shell/js.cpp ++++ js/src/shell/js.cpp +@@ -5049,6 +5049,23 @@ NukeCCW(JSContext* cx, unsigned argc, Value* vp) + return true; + } + ++static bool ++NukeAllCCWs(JSContext* cx, unsigned argc, Value* vp) ++{ ++ CallArgs args = CallArgsFromVp(argc, vp); ++ ++ if (args.length() != 0) { ++ JS_ReportErrorNumberASCII(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, ++ "nukeAllCCWs"); ++ return false; ++ } ++ ++ NukeCrossCompartmentWrappers(cx, AllCompartments(), cx->compartment(), ++ NukeWindowReferences, NukeAllReferences); ++ args.rval().setUndefined(); ++ return true; ++} ++ + static bool + GetMaxArgs(JSContext* cx, unsigned argc, Value* vp) + { +@@ -6552,6 +6569,10 @@ static const JSFunctionSpecWithHelp shell_functions[] = { + "nukeCCW(wrapper)", + " Nuke a CrossCompartmentWrapper, which turns it into a DeadProxyObject."), + ++ JS_FN_HELP("nukeAllCCWs", NukeAllCCWs, 0, 0, ++"nukeAllCCWs()", ++" Like nukeCCW, but for all CrossCompartmentWrappers targeting the current compartment."), ++ + JS_FN_HELP("createMappedArrayBuffer", CreateMappedArrayBuffer, 1, 0, + "createMappedArrayBuffer(filename, [offset, [size]])", + " Create an array buffer that mmaps the given file."), diff --git a/www/waterfox/files/patch-bug1352453 b/www/waterfox/files/patch-bug1352453 new file mode 100644 index 000000000000..87630d5510d2 --- /dev/null +++ b/www/waterfox/files/patch-bug1352453 @@ -0,0 +1,27 @@ +commit 96ac0874dc2e +Author: Ethan Lin <ethlin@mozilla.com> +Date: Sat Sep 23 15:06:07 2017 +0800 + + Bug 1352453 - Check image dimension when computing border space size. r=heycam, a=sledru + + MozReview-Commit-ID: LQcf9UGyUUq + + --HG-- + extra : source : 6974ff079df11b3e7dc46e2df754149321e3f3aa +--- + layout/painting/nsCSSRendering.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git layout/painting/nsCSSRendering.cpp layout/painting/nsCSSRendering.cpp +index 89760f33229b..55051c9ac376 100644 +--- layout/painting/nsCSSRendering.cpp ++++ layout/painting/nsCSSRendering.cpp +@@ -3068,7 +3068,7 @@ nsCSSRendering::ComputeBorderSpacedRepeatSize(nscoord aImageDimension, + nscoord aAvailableSpace, + nscoord& aSpace) + { +- int32_t count = aAvailableSpace / aImageDimension; ++ int32_t count = aImageDimension ? (aAvailableSpace / aImageDimension) : 0; + aSpace = (aAvailableSpace - aImageDimension * count) / (count + 1); + return aSpace + aImageDimension; + } diff --git a/www/waterfox/files/patch-bug1355576 b/www/waterfox/files/patch-bug1355576 new file mode 100644 index 000000000000..cc9c8236a2b4 --- /dev/null +++ b/www/waterfox/files/patch-bug1355576 @@ -0,0 +1,262 @@ +commit e530ba4d4394 +Author: Thomas Wisniewski <wisniewskit@gmail.com> +Date: Tue Jul 4 20:59:26 2017 -0400 + + Bug 1355576 - Add ability to clear all localStorage with the browsingData API; r=bsilverberg,janv + + MozReview-Commit-ID: 4UUqg62yIo9 + + --HG-- + extra : rebase_source : 9c6154bbe878fc3921d22027fdc90dbdaed05be9 +--- + browser/components/extensions/ext-browsingData.js | 10 +++ + .../extensions/schemas/browsing_data.json | 1 - + .../extensions/test/browser/browser-common.ini | 1 + + .../browser_ext_browsingData_localStorage.js | 93 ++++++++++++++++++++++ + .../test/xpcshell/test_ext_browsingData.js | 4 +- + dom/storage/LocalStorageManager.cpp | 3 +- + dom/storage/StorageObserver.cpp | 12 +++ + .../extensions/schemas/browsing_data.json | 1 - + 8 files changed, 120 insertions(+), 5 deletions(-) + +diff --git browser/components/extensions/ext-browsingData.js browser/components/extensions/ext-browsingData.js +index fd59141dd15d..109ec9601487 100644 +--- browser/components/extensions/ext-browsingData.js ++++ browser/components/extensions/ext-browsingData.js +@@ -83,6 +83,10 @@ const clearHistory = options => { + return sanitizer.items.history.clear(makeRange(options)); + }; + ++const clearLocalStorage = async function(options) { ++ Services.obs.notifyObservers(null, "extension:purge-localStorage"); ++}; ++ + const clearPasswords = async function(options) { + let loginManager = Services.logins; + let yieldCounter = 0; +@@ -152,6 +156,9 @@ const doRemoval = (options, dataToRemove, extension) => { + case "history": + removalPromises.push(clearHistory(options)); + break; ++ case "localStorage": ++ removalPromises.push(clearLocalStorage(options)); ++ break; + case "passwords": + removalPromises.push(clearPasswords(options)); + break; +@@ -225,6 +232,9 @@ this.browsingData = class extends ExtensionAPI { + removeHistory(options) { + return doRemoval(options, {history: true}); + }, ++ removeLocalStorage(options) { ++ return doRemoval(options, {localStorage: true}); ++ }, + removePasswords(options) { + return doRemoval(options, {passwords: true}); + }, +diff --git browser/components/extensions/schemas/browsing_data.json browser/components/extensions/schemas/browsing_data.json +index a780f5640c8f..7755714eb898 100644 +--- browser/components/extensions/schemas/browsing_data.json ++++ browser/components/extensions/schemas/browsing_data.json +@@ -341,7 +341,6 @@ + "description": "Clears websites' local storage data.", + "type": "function", + "async": "callback", +- "unsupported": true, + "parameters": [ + { + "$ref": "RemovalOptions", +diff --git browser/components/extensions/test/browser/browser-common.ini browser/components/extensions/test/browser/browser-common.ini +index 464b8ba18f37..e3f7700f3939 100644 +--- browser/components/extensions/test/browser/browser-common.ini ++++ browser/components/extensions/test/browser/browser-common.ini +@@ -46,6 +46,7 @@ skip-if = (os == 'win' && !debug) # bug 1352668 + [browser_ext_browserAction_theme_icons.js] + [browser_ext_browsingData_formData.js] + [browser_ext_browsingData_history.js] ++[browser_ext_browsingData_localStorage.js] + [browser_ext_browsingData_pluginData.js] + [browser_ext_browsingData_serviceWorkers.js] + [browser_ext_commands_execute_browser_action.js] +diff --git browser/components/extensions/test/browser/browser_ext_browsingData_localStorage.js browser/components/extensions/test/browser/browser_ext_browsingData_localStorage.js +new file mode 100644 +index 000000000000..215f26d1fcb6 +--- /dev/null ++++ browser/components/extensions/test/browser/browser_ext_browsingData_localStorage.js +@@ -0,0 +1,93 @@ ++/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++/* vim: set sts=2 sw=2 et tw=80: */ ++"use strict"; ++ ++add_task(async function testLocalStorage() { ++ async function background() { ++ function openTabs() { ++ let promise = new Promise(resolve => { ++ let tabURLs = [ ++ "http://example.com/", ++ "http://example.net/", ++ ]; ++ ++ let tabs; ++ let waitingCount = tabURLs.length; ++ ++ let listener = async msg => { ++ if (msg !== "content-script-ready" || --waitingCount) { ++ return; ++ } ++ browser.runtime.onMessage.removeListener(listener); ++ resolve(Promise.all(tabs)); ++ }; ++ ++ browser.runtime.onMessage.addListener(listener); ++ ++ tabs = tabURLs.map(url => { ++ return browser.tabs.create({url: url}); ++ }); ++ }); ++ ++ return promise; ++ } ++ ++ function sendMessageToTabs(tabs, message) { ++ return Promise.all( ++ tabs.map(tab => { return browser.tabs.sendMessage(tab.id, message); })); ++ } ++ ++ let tabs = await openTabs(); ++ ++ await sendMessageToTabs(tabs, "resetLocalStorage"); ++ await sendMessageToTabs(tabs, "checkLocalStorageSet"); ++ await browser.browsingData.removeLocalStorage({}); ++ await sendMessageToTabs(tabs, "checkLocalStorageCleared"); ++ ++ await sendMessageToTabs(tabs, "resetLocalStorage"); ++ await sendMessageToTabs(tabs, "checkLocalStorageSet"); ++ await browser.browsingData.remove({}, {localStorage: true}); ++ await sendMessageToTabs(tabs, "checkLocalStorageCleared"); ++ ++ browser.tabs.remove(tabs.map(tab => tab.id)); ++ ++ browser.test.notifyPass("done"); ++ } ++ ++ function contentScript() { ++ browser.runtime.onMessage.addListener(msg => { ++ if (msg === "resetLocalStorage") { ++ localStorage.clear(); ++ localStorage.setItem("test", "test"); ++ } else if (msg === "checkLocalStorageSet") { ++ browser.test.assertEq("test", localStorage.getItem("test")); ++ } else if (msg === "checkLocalStorageCleared") { ++ browser.test.assertEq(null, localStorage.getItem("test")); ++ } ++ }); ++ browser.runtime.sendMessage("content-script-ready"); ++ } ++ ++ let extension = ExtensionTestUtils.loadExtension({ ++ background, ++ manifest: { ++ "permissions": ["browsingData"], ++ "content_scripts": [{ ++ "matches": [ ++ "http://example.com/", ++ "http://example.net/", ++ ], ++ "js": ["content-script.js"], ++ "run_at": "document_start", ++ }], ++ }, ++ files: { ++ "content-script.js": contentScript, ++ }, ++ }); ++ ++ await extension.startup(); ++ await extension.awaitFinish("done"); ++ await extension.unload(); ++}); ++ +diff --git browser/components/extensions/test/xpcshell/test_ext_browsingData.js browser/components/extensions/test/xpcshell/test_ext_browsingData.js +index 0c1c4874ca44..0b8972058e64 100644 +--- browser/components/extensions/test/xpcshell/test_ext_browsingData.js ++++ browser/components/extensions/test/xpcshell/test_ext_browsingData.js +@@ -44,7 +44,7 @@ add_task(async function testInvalidArguments() { + + add_task(async function testUnimplementedDataType() { + function background() { +- browser.browsingData.remove({}, {localStorage: true}); ++ browser.browsingData.remove({}, {indexedDB: true}); + browser.test.sendMessage("finished"); + } + +@@ -61,6 +61,6 @@ add_task(async function testUnimplementedDataType() { + await extension.unload(); + }); + +- let warningObserved = messages.find(line => /Firefox does not support dataTypes: localStorage/.test(line)); ++ let warningObserved = messages.find(line => /Firefox does not support dataTypes: indexedDB/.test(line)); + ok(warningObserved, "Warning issued when calling remove with an unimplemented dataType."); + }); +diff --git dom/storage/LocalStorageManager.cpp dom/storage/LocalStorageManager.cpp +index a161de2bc596..f366e7874a90 100644 +--- dom/storage/LocalStorageManager.cpp ++++ dom/storage/LocalStorageManager.cpp +@@ -386,7 +386,8 @@ LocalStorageManager::Observe(const char* aTopic, + } + + // Clear everything, caches + database +- if (!strcmp(aTopic, "cookie-cleared")) { ++ if (!strcmp(aTopic, "cookie-cleared") || ++ !strcmp(aTopic, "extension:purge-localStorage-caches")) { + ClearCaches(LocalStorageCache::kUnloadComplete, pattern, EmptyCString()); + return NS_OK; + } +diff --git dom/storage/StorageObserver.cpp dom/storage/StorageObserver.cpp +index e5b010f88c7b..48d484748209 100644 +--- dom/storage/StorageObserver.cpp ++++ dom/storage/StorageObserver.cpp +@@ -66,6 +66,7 @@ StorageObserver::Init() + obs->AddObserver(sSelf, "browser:purge-domain-data", true); + obs->AddObserver(sSelf, "last-pb-context-exited", true); + obs->AddObserver(sSelf, "clear-origin-attributes-data", true); ++ obs->AddObserver(sSelf, "extension:purge-localStorage", true); + + // Shutdown + obs->AddObserver(sSelf, "profile-after-change", true); +@@ -270,6 +271,23 @@ StorageObserver::Observe(nsISupports* aSubject, + + Notify("session-only-cleared", NS_ConvertUTF8toUTF16(originSuffix), + originScope); ++ ++ return NS_OK; ++ } ++ ++ if (!strcmp(aTopic, "extension:purge-localStorage")) { ++ StorageDBChild* storageChild = StorageDBChild::GetOrCreate(); ++ if (NS_WARN_IF(!storageChild)) { ++ return NS_ERROR_FAILURE; ++ } ++ ++ storageChild->AsyncClearAll(); ++ ++ if (XRE_IsParentProcess()) { ++ storageChild->SendClearAll(); ++ } ++ ++ Notify("extension:purge-localStorage-caches"); + + return NS_OK; + } +diff --git mobile/android/components/extensions/schemas/browsing_data.json mobile/android/components/extensions/schemas/browsing_data.json +index 483a462d422c..1019c1a23953 100644 +--- mobile/android/components/extensions/schemas/browsing_data.json ++++ mobile/android/components/extensions/schemas/browsing_data.json +@@ -345,7 +345,6 @@ + "description": "Clears websites' local storage data.", + "type": "function", + "async": "callback", +- "unsupported": true, + "parameters": [ + { + "$ref": "RemovalOptions", diff --git a/www/waterfox/files/patch-bug1356854 b/www/waterfox/files/patch-bug1356854 new file mode 100644 index 000000000000..013cb6fac559 --- /dev/null +++ b/www/waterfox/files/patch-bug1356854 @@ -0,0 +1,28 @@ +commit 6435e5f65538 +Author: Thomas Nguyen <tnguyen@mozilla.com> +Date: Thu Sep 21 16:39:36 2017 +0800 + + Bug 1356854 - Check mFD is not null before PR_Write. r=mcmanus, a=ritu + + MozReview-Commit-ID: INoTUvPpPrs + + --HG-- + extra : source : 638f326530b719ce386bb5d1701fed4ae4604690 +--- + netwerk/base/nsFileStreams.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git netwerk/base/nsFileStreams.cpp netwerk/base/nsFileStreams.cpp +index ac259c1c7e94..6be501456656 100644 +--- netwerk/base/nsFileStreams.cpp ++++ netwerk/base/nsFileStreams.cpp +@@ -378,6 +378,9 @@ nsFileStreamBase::DoPendingOpen() + + case eOpened: + MOZ_ASSERT(mFD); ++ if (NS_WARN_IF(!mFD)) { ++ return NS_ERROR_FAILURE; ++ } + return NS_OK; + + case eClosed: diff --git a/www/waterfox/files/patch-bug1357523 b/www/waterfox/files/patch-bug1357523 new file mode 100644 index 000000000000..32d453e9e3b7 --- /dev/null +++ b/www/waterfox/files/patch-bug1357523 @@ -0,0 +1,96 @@ +commit ad103dfd3abe +Author: Prathiksha <prathikshaprasadsuman@gmail.com> +Date: Fri Sep 15 22:08:12 2017 +0530 + + Bug 1357523 - Make about:home and about:newtab search box search for the value in the search textbox when we use non-default search engines. r=nhnt11, a=ritu + + MozReview-Commit-ID: CdgqghkmXau + + --HG-- + extra : source : e029590936c56ac269d68610ab389ab25887b6e1 +--- + browser/base/content/contentSearchUI.js | 2 ++ + .../test/general/browser_contentSearchUI.js | 30 +++++----------------- + 2 files changed, 9 insertions(+), 23 deletions(-) + +diff --git browser/base/content/contentSearchUI.js browser/base/content/contentSearchUI.js +index bacb985fb6ee..ffada60c3571 100644 +--- browser/base/content/contentSearchUI.js ++++ browser/base/content/contentSearchUI.js +@@ -478,6 +478,8 @@ ContentSearchUIController.prototype = { + _onMousemove(event) { + let idx = this._indexOfTableItem(event.target); + if (idx >= this.numSuggestions) { ++ // Deselect any search suggestion that has been selected. ++ this.selectedIndex = -1; + this.selectedButtonIndex = idx - this.numSuggestions; + return; + } +diff --git browser/base/content/test/general/browser_contentSearchUI.js browser/base/content/test/general/browser_contentSearchUI.js +index 51538b29e27f..85b65d40bf0b 100644 +--- browser/base/content/test/general/browser_contentSearchUI.js ++++ browser/base/content/test/general/browser_contentSearchUI.js +@@ -300,13 +300,13 @@ add_task(async function mouse() { + checkState(state, "x", ["xfoo", "xbar"], 1); + + state = await msg("mousemove", 2); +- checkState(state, "x", ["xfoo", "xbar"], 1, 0); ++ checkState(state, "x", ["xfoo", "xbar"], 2, 0); + + state = await msg("mousemove", 3); +- checkState(state, "x", ["xfoo", "xbar"], 1, 1); ++ checkState(state, "x", ["xfoo", "xbar"], 3, 1); + + state = await msg("mousemove", -1); +- checkState(state, "x", ["xfoo", "xbar"], 1); ++ checkState(state, "x", ["xfoo", "xbar"], -1); + + await msg("reset"); + await setUp(); +@@ -318,10 +318,10 @@ add_task(async function mouse() { + checkState(state, "x", ["xfoo", "xbar"], 0); + + state = await msg("mousemove", 2); +- checkState(state, "x", ["xfoo", "xbar"], 0, 0); ++ checkState(state, "x", ["xfoo", "xbar"], 2, 0); + + state = await msg("mousemove", -1); +- checkState(state, "x", ["xfoo", "xbar"], 0); ++ checkState(state, "x", ["xfoo", "xbar"], -1); + + await msg("reset"); + }); +@@ -510,24 +510,7 @@ add_task(async function search() { + await setUp(); + + // Test selecting a suggestion, then clicking a one-off without deselecting the +- // suggestion. +- await msg("key", { key: "x", waitForSuggestions: true }); +- p = msg("waitForSearch"); +- await msg("mousemove", 1); +- await msg("mousemove", 3); +- await msg("click", { eltIdx: 3, modifiers }); +- mesg = await p; +- eventData.searchString = "xfoo" +- eventData.selection = { +- index: 1, +- kind: "mouse", +- }; +- SimpleTest.isDeeply(eventData, mesg, "Search event data"); +- +- await promiseTab(); +- await setUp(); +- +- // Same as above, but with the keyboard. ++ // suggestion, using the keyboard. + delete modifiers.button; + await msg("key", { key: "x", waitForSuggestions: true }); + p = msg("waitForSearch"); +@@ -536,6 +519,7 @@ add_task(async function search() { + await msg("key", "VK_TAB"); + await msg("key", { key: "VK_RETURN", modifiers }); + mesg = await p; ++ eventData.searchString = "xfoo"; + eventData.selection = { + index: 1, + kind: "key", diff --git a/www/waterfox/files/patch-bug1360278 b/www/waterfox/files/patch-bug1360278 new file mode 100644 index 000000000000..75e49f92f346 --- /dev/null +++ b/www/waterfox/files/patch-bug1360278 @@ -0,0 +1,184 @@ +commit 5d127ad3bd50 +Author: Robin Grenet <robin.grenet@wanadoo.fr> +Date: Thu Nov 16 13:35:58 2017 +0100 + + Bug 1360278 - Add preference to trigger context menu on mouse up for GTK+ and macOS, r=mstange,smaug a=gchang + + MozReview-Commit-ID: Bg60bD8jIg6 + + --HG-- + extra : source : f540f9e801cb2e0be5259baea13dfce953ccb520 +--- + modules/libpref/init/all.js | 4 ++++ + widget/cocoa/nsChildView.mm | 23 +++++++++++++++++++++-- + widget/gtk/nsWindow.cpp | 27 ++++++++++++++++++++------- + widget/gtk/nsWindow.h | 2 ++ + widget/nsBaseWidget.cpp | 16 ++++++++++++++++ + widget/nsBaseWidget.h | 6 ++++++ + 6 files changed, 69 insertions(+), 9 deletions(-) + +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index f9402630cf27..97ece9f13467 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -234,6 +234,10 @@ pref("browser.sessionhistory.max_total_viewers", -1); + + pref("ui.use_native_colors", true); + pref("ui.click_hold_context_menus", false); ++ ++// Pop up context menu on mouseup instead of mousedown, if that's the OS default. ++// Note: ignored on Windows (context menus always use mouseup) ++pref("ui.context_menus.after_mouseup", false); + // Duration of timeout of incremental search in menus (ms). 0 means infinite. + pref("ui.menu.incremental_search.timeout", 1000); + // If true, all popups won't hide automatically on blur +diff --git widget/cocoa/nsChildView.mm widget/cocoa/nsChildView.mm +index cac897327a19..bf42b4f8c095 100644 +--- widget/cocoa/nsChildView.mm ++++ widget/cocoa/nsChildView.mm +@@ -4700,8 +4700,10 @@ NSEvent* gLastDragMouseDownEvent = nil; + if (!mGeckoChild) + return; + +- // Let the superclass do the context menu stuff. +- [super rightMouseDown:theEvent]; ++ if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ // Let the superclass do the context menu stuff. ++ [super rightMouseDown:theEvent]; ++ } + + NS_OBJC_END_TRY_ABORT_BLOCK; + } +@@ -4724,6 +4726,23 @@ NSEvent* gLastDragMouseDownEvent = nil; + + nsAutoRetainCocoaObject kungFuDeathGrip(self); + mGeckoChild->DispatchInputEvent(&geckoEvent); ++ if (!mGeckoChild) ++ return; ++ ++ if (nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ // Let the superclass do the context menu stuff, but pretend it's rightMouseDown. ++ NSEvent *dupeEvent = [NSEvent mouseEventWithType:NSRightMouseDown ++ location:theEvent.locationInWindow ++ modifierFlags:theEvent.modifierFlags ++ timestamp:theEvent.timestamp ++ windowNumber:theEvent.windowNumber ++ context:theEvent.context ++ eventNumber:theEvent.eventNumber ++ clickCount:theEvent.clickCount ++ pressure:theEvent.pressure]; ++ ++ [super rightMouseDown:dupeEvent]; ++ } + + NS_OBJC_END_TRY_ABORT_BLOCK; + } +diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp +index c3da6dc00b0c..c220d0bb2192 100644 +--- widget/gtk/nsWindow.cpp ++++ widget/gtk/nsWindow.cpp +@@ -2737,6 +2737,19 @@ static guint ButtonMaskFromGDKButton(guint button) + return GDK_BUTTON1_MASK << (button - 1); + } + ++void ++nsWindow::DispatchContextMenuEventFromMouseEvent(uint16_t domButton, ++ GdkEventButton *aEvent) ++{ ++ if (domButton == WidgetMouseEvent::eRightButton && MOZ_LIKELY(!mIsDestroyed)) { ++ WidgetMouseEvent contextMenuEvent(true, eContextMenu, this, ++ WidgetMouseEvent::eReal); ++ InitButtonEvent(contextMenuEvent, aEvent); ++ contextMenuEvent.pressure = mLastMotionPressure; ++ DispatchInputEvent(&contextMenuEvent); ++ } ++} ++ + void + nsWindow::OnButtonPressEvent(GdkEventButton *aEvent) + { +@@ -2806,13 +2819,8 @@ nsWindow::OnButtonPressEvent(GdkEventButton *aEvent) + DispatchInputEvent(&event); + + // right menu click on linux should also pop up a context menu +- if (domButton == WidgetMouseEvent::eRightButton && +- MOZ_LIKELY(!mIsDestroyed)) { +- WidgetMouseEvent contextMenuEvent(true, eContextMenu, this, +- WidgetMouseEvent::eReal); +- InitButtonEvent(contextMenuEvent, aEvent); +- contextMenuEvent.pressure = mLastMotionPressure; +- DispatchInputEvent(&contextMenuEvent); ++ if (!nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ DispatchContextMenuEventFromMouseEvent(domButton, aEvent); + } + } + +@@ -2848,6 +2856,11 @@ nsWindow::OnButtonReleaseEvent(GdkEventButton *aEvent) + + DispatchInputEvent(&event); + mLastMotionPressure = pressure; ++ ++ // right menu click on linux should also pop up a context menu ++ if (nsBaseWidget::ShowContextMenuAfterMouseUp()) { ++ DispatchContextMenuEventFromMouseEvent(domButton, aEvent); ++ } + } + + void +diff --git widget/gtk/nsWindow.h widget/gtk/nsWindow.h +index 0fafc8994579..7a28e3260c0f 100644 +--- widget/gtk/nsWindow.h ++++ widget/gtk/nsWindow.h +@@ -245,6 +245,8 @@ private: + + void UpdateClientOffset(); + ++ void DispatchContextMenuEventFromMouseEvent(uint16_t domButton, ++ GdkEventButton *aEvent); + public: + void ThemeChanged(void); + void OnDPIChanged(void); +diff --git widget/nsBaseWidget.cpp widget/nsBaseWidget.cpp +index c0694714c69d..4a1320fe23d5 100644 +--- widget/nsBaseWidget.cpp ++++ widget/nsBaseWidget.cpp +@@ -1218,6 +1218,22 @@ nsBaseWidget::DispatchEventToAPZOnly(mozilla::WidgetInputEvent* aEvent) + } + } + ++// static ++bool ++nsBaseWidget::ShowContextMenuAfterMouseUp() ++{ ++ static bool gContextMenuAfterMouseUp = false; ++ static bool gContextMenuAfterMouseUpCached = false; ++ if (!gContextMenuAfterMouseUpCached) { ++ Preferences::AddBoolVarCache(&gContextMenuAfterMouseUp, ++ "ui.context_menus.after_mouseup", ++ false); ++ ++ gContextMenuAfterMouseUpCached = true; ++ } ++ return gContextMenuAfterMouseUp; ++} ++ + nsIDocument* + nsBaseWidget::GetDocument() const + { +diff --git widget/nsBaseWidget.h widget/nsBaseWidget.h +index f4e8e3d78330..3cb56f38b6ce 100644 +--- widget/nsBaseWidget.h ++++ widget/nsBaseWidget.h +@@ -417,6 +417,12 @@ public: + void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize) override {}; + #endif + ++ /** ++ * Whether context menus should only appear on mouseup instead of mousedown, ++ * on OSes where they normally appear on mousedown (macOS, *nix). ++ */ ++ static bool ShowContextMenuAfterMouseUp(); ++ + protected: + // These are methods for CompositorWidgetWrapper, and should only be + // accessed from that class. Derived widgets can choose which methods to diff --git a/www/waterfox/files/patch-bug1360603 b/www/waterfox/files/patch-bug1360603 new file mode 100644 index 000000000000..b7e5e247a43a --- /dev/null +++ b/www/waterfox/files/patch-bug1360603 @@ -0,0 +1,101 @@ +commit b5d0a61cd5df +Author: Amy Chung <amchung@mozilla.com> +Date: Sun Sep 24 00:38:32 2017 +0800 + + Bug 1360603 - Mark the save channel as throttleable. r=baku, a=sledru + + --HG-- + extra : source : d409c2ac7d88b7193e8369aa3359a9368e1135b3 +--- + dom/webbrowserpersist/nsWebBrowserPersist.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git dom/webbrowserpersist/nsWebBrowserPersist.cpp dom/webbrowserpersist/nsWebBrowserPersist.cpp +index a9b37ed281ca..a5971216d8b4 100644 +--- dom/webbrowserpersist/nsWebBrowserPersist.cpp ++++ dom/webbrowserpersist/nsWebBrowserPersist.cpp +@@ -13,6 +13,7 @@ + #include "nsAutoPtr.h" + #include "nsNetCID.h" + #include "nsNetUtil.h" ++#include "nsIClassOfService.h" + #include "nsIInterfaceRequestorUtils.h" + #include "nsILoadContext.h" + #include "nsIPrivateBrowsingChannel.h" +@@ -1497,6 +1498,12 @@ nsresult nsWebBrowserPersist::SaveChannelInternal( + return StartUpload(bufferedInputStream, aFile, contentType); + } + ++ // Mark save channel as throttleable. ++ nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(aChannel)); ++ if (cos) { ++ cos->AddClassFlags(nsIClassOfService::Throttleable); ++ } ++ + // Read from the input channel + nsresult rv = NS_MaybeOpenChannelUsingAsyncOpen2(aChannel, this); + if (rv == NS_ERROR_NO_CONTENT) +commit 1e11071bc4f9 +Author: Amy Chung <amchung@mozilla.com> +Date: Sun Sep 24 00:56:04 2017 +0800 + + Bug 1360603 - Confirm the Throttleable flag on browser_saveImageURL.js. r=baku, a=sledru + + --HG-- + extra : source : 6d7610f4d26d76878b83b1f2489a96116c2bdf15 +--- + toolkit/content/contentAreaUtils.js | 4 ++++ + toolkit/content/tests/browser/browser_saveImageURL.js | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git toolkit/content/contentAreaUtils.js toolkit/content/contentAreaUtils.js +index fba70c91c8a3..1492b4c1654c 100644 +--- toolkit/content/contentAreaUtils.js ++++ toolkit/content/contentAreaUtils.js +@@ -1264,6 +1264,10 @@ function openURL(aURL) { + loadUsingSystemPrincipal: true + }); + ++ if (channel) { ++ channel.channelIsForDownload = true; ++ } ++ + var uriLoader = Components.classes["@mozilla.org/uriloader;1"] + .getService(Components.interfaces.nsIURILoader); + uriLoader.openURI(channel, +diff --git toolkit/content/tests/browser/browser_saveImageURL.js toolkit/content/tests/browser/browser_saveImageURL.js +index fe10482f35dc..0d9c872921c2 100644 +--- toolkit/content/tests/browser/browser_saveImageURL.js ++++ toolkit/content/tests/browser/browser_saveImageURL.js +@@ -37,6 +37,15 @@ add_task(async function preferred_API() { + }); + + saveImageURL(url, "image.jpg", null, true, false, null, null, null, null, false); ++ let channel = content.document.docShell.currentDocumentChannel; ++ if (channel) { ++ ok(true, channel.QueryInterface(Ci.nsIHttpChannelInternal) ++ .channelIsForDownload); ++ ++ // Throttleable is the only class flag assigned to downloads. ++ ok(channel.QueryInterface(Ci.nsIClassOfService).classFlags, ++ Ci.nsIClassOfService.Throttleable); ++ } + await waitForFilePicker(); + }); + }); +@@ -64,6 +73,15 @@ add_task(async function deprecated_API() { + // pass the XUL document instead to test this interface. + let doc = document; + ++ let channel = content.document.docShell.currentDocumentChannel; ++ if (channel) { ++ ok(true, channel.QueryInterface(Ci.nsIHttpChannelInternal) ++ .channelIsForDownload); ++ ++ // Throttleable is the only class flag assigned to downloads. ++ ok(channel.QueryInterface(Ci.nsIClassOfService).classFlags, ++ Ci.nsIClassOfService.Throttleable); ++ } + saveImageURL(url, "image.jpg", null, true, false, null, doc, null, null); + await waitForFilePicker(); + }); diff --git a/www/waterfox/files/patch-bug1363038 b/www/waterfox/files/patch-bug1363038 new file mode 100644 index 000000000000..5f8465966d55 --- /dev/null +++ b/www/waterfox/files/patch-bug1363038 @@ -0,0 +1,68 @@ +commit 9d1887c28c05 +Author: Thomas Nguyen <tnguyen@mozilla.com> +Date: Tue Aug 22 14:51:44 2017 +0800 + + Bug 1363038 - Remove synchronous dispatch when worker is racing against shutdown r=hchang + + MozReview-Commit-ID: JOkOukz1fov + + --HG-- + extra : rebase_source : 9e4204cebcd4615078019a51818250ff8125efe1 +--- + .../url-classifier/nsUrlClassifierDBService.cpp | 21 ++++++++------------- + .../url-classifier/nsUrlClassifierDBService.h | 3 +++ + 2 files changed, 11 insertions(+), 13 deletions(-) + +diff --git toolkit/components/url-classifier/nsUrlClassifierDBService.cpp toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +index 3f7e3c8daaac..074bfc583b93 100644 +--- toolkit/components/url-classifier/nsUrlClassifierDBService.cpp ++++ toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +@@ -1616,12 +1616,6 @@ nsUrlClassifierDBService::Init() + ReadTablesFromPrefs(); + nsresult rv; + +- { +- // Force PSM loading on main thread +- nsCOMPtr<nsICryptoHash> dummy = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &rv); +- NS_ENSURE_SUCCESS(rv, rv); +- } +- + { + // Force nsIUrlClassifierUtils loading on main thread. + nsCOMPtr<nsIUrlClassifierUtils> dummy = +@@ -2278,13 +2272,14 @@ nsUrlClassifierDBService::Shutdown() + // is to avoid racing for Classifier::mUpdateThread + // between main thread and the worker thread. (Both threads + // would access Classifier::mUpdateThread.) +- using Worker = nsUrlClassifierDBServiceWorker; +- RefPtr<nsIRunnable> r = NewRunnableMethod( +- "nsUrlClassifierDBServiceWorker::FlushAndDisableAsyncUpdate", +- mWorker, +- &Worker::FlushAndDisableAsyncUpdate); +- SyncRunnable::DispatchToThread(gDbBackgroundThread, r); +- ++ if (mWorker->IsDBOpened()) { ++ using Worker = nsUrlClassifierDBServiceWorker; ++ RefPtr<nsIRunnable> r = NewRunnableMethod( ++ "nsUrlClassifierDBServiceWorker::FlushAndDisableAsyncUpdate", ++ mWorker, ++ &Worker::FlushAndDisableAsyncUpdate); ++ SyncRunnable::DispatchToThread(gDbBackgroundThread, r); ++ } + // At this point the update thread has been shut down and + // the worker thread should only have at most one event, + // which is the callback event. +diff --git toolkit/components/url-classifier/nsUrlClassifierDBService.h toolkit/components/url-classifier/nsUrlClassifierDBService.h +index 13987b0ed2ee..8d284f5b0842 100644 +--- toolkit/components/url-classifier/nsUrlClassifierDBService.h ++++ toolkit/components/url-classifier/nsUrlClassifierDBService.h +@@ -227,6 +227,9 @@ public: + // will be nulled out in NotifyUpdateObserver. + bool IsBusyUpdating() const { return !!mUpdateObserver; } + ++ // Check the DB ready state of the worker thread ++ bool IsDBOpened() const { return !!mClassifier; } ++ + // Delegate Classifier to disable async update. If there is an + // ongoing update on the update thread, we will be blocked until + // the background update is done and callback is fired. diff --git a/www/waterfox/files/patch-bug1370508 b/www/waterfox/files/patch-bug1370508 new file mode 100644 index 000000000000..3f5ffc992a6c --- /dev/null +++ b/www/waterfox/files/patch-bug1370508 @@ -0,0 +1,79 @@ +commit c40f44ef9b35 +Author: Xidorn Quan <me@upsuper.org> +Date: Wed Aug 9 19:57:33 2017 +1000 + + Bug 1370508 - Enable stylo on generic XML documents. r=heycam + + MozReview-Commit-ID: 4XQ9RPQ7oa1 + + --HG-- + extra : rebase_source : 74e411e2280e818fc1fbd2efda677565cfa2f8b6 +--- + dom/base/nsDocument.cpp | 3 +-- + layout/reftests/w3c-css/failures.list | 4 ++++ + layout/reftests/w3c-css/received/reftest.list | 2 +- + layout/xul/crashtests/crashtests.list | 2 +- + testing/web-platform/meta/css/css-namespaces-3/syntax-013.xml.ini | 4 ++++ + 5 files changed, 11 insertions(+), 4 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 2a01e6ec3a67..66a860ff3257 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -13293,8 +13293,7 @@ nsIDocument::UpdateStyleBackendType() + mStyleBackendType = StyleBackendType::Servo; + } else if (!mDocumentContainer) { + NS_WARNING("stylo: No docshell yet, assuming Gecko style system"); +- } else if ((IsHTMLOrXHTML() || IsSVGDocument()) && +- IsContentDocument()) { ++ } else if (!IsXULDocument() && IsContentDocument()) { + // Disable stylo for about: pages other than about:blank, since + // they tend to use unsupported selectors like XUL tree pseudos. + bool isAbout = false; +diff --git layout/reftests/w3c-css/failures.list layout/reftests/w3c-css/failures.list +index 966f69ff9ae0..1560f4ad673d 100644 +--- layout/reftests/w3c-css/failures.list ++++ layout/reftests/w3c-css/failures.list +@@ -314,3 +314,7 @@ fuzzy(255,2808) css-multicol-1/multicol-rule-large-001.xht + fails-if(!styloVsGecko) css-multicol-1/multicol-fill-auto-block-children-001.xht + fails-if(!styloVsGecko) css-multicol-1/multicol-fill-auto-block-children-002.xht + fails-if(!styloVsGecko) css-multicol-1/multicol-span-all-block-sibling-003.xht ++ ++#### CSS Namespaces 3 ############################################## ++ ++fails-if(stylo||styloVsGecko) css-namespaces-3/syntax-013.xml +diff --git layout/reftests/w3c-css/received/reftest.list layout/reftests/w3c-css/received/reftest.list +index eb6151266acd..128d1fcf8121 100644 +--- layout/reftests/w3c-css/received/reftest.list ++++ layout/reftests/w3c-css/received/reftest.list +@@ -205,7 +205,7 @@ fails-if(!styloVsGecko) == css-multicol-1/multicol-zero-height-001.xht css-multi + == css-namespaces-3/syntax-010.xml css-namespaces-3/reftest/ref-lime-3.xml + == css-namespaces-3/syntax-011.xml css-namespaces-3/reftest/ref-lime-6.xml + == css-namespaces-3/syntax-012.xml css-namespaces-3/reftest/ref-lime-3.xml +-== css-namespaces-3/syntax-013.xml css-namespaces-3/reftest/ref-lime-5.xml ++fails-if(stylo||styloVsGecko) == css-namespaces-3/syntax-013.xml css-namespaces-3/reftest/ref-lime-5.xml # bug 1388911 + == css-namespaces-3/syntax-014.xml css-namespaces-3/reftest/ref-lime-3.xml + == css-namespaces-3/syntax-015.xml css-namespaces-3/reftest/ref-lime-1.xml + fails-if(!styloVsGecko) == css-values-3/attr-color-invalid-cast.html css-values-3/reference/200-200-green.html +diff --git layout/xul/crashtests/crashtests.list layout/xul/crashtests/crashtests.list +index c1445cb5ec7a..e60af3526383 100644 +--- layout/xul/crashtests/crashtests.list ++++ layout/xul/crashtests/crashtests.list +@@ -1,6 +1,6 @@ + load 131008-1.xul + load 137216-1.xul +-load 140218-1.xml ++asserts-if(stylo,3) load 140218-1.xml + load 151826-1.xul + load 168724-1.xul + load 189814-1.xul +diff --git testing/web-platform/meta/css/css-namespaces-3/syntax-013.xml.ini testing/web-platform/meta/css/css-namespaces-3/syntax-013.xml.ini +new file mode 100644 +index 000000000000..b034ccf978f5 +--- /dev/null ++++ testing/web-platform/meta/css/css-namespaces-3/syntax-013.xml.ini +@@ -0,0 +1,4 @@ ++[syntax-013.xml] ++ type: reftest ++ expected: ++ if stylo: FAIL diff --git a/www/waterfox/files/patch-bug1370791 b/www/waterfox/files/patch-bug1370791 new file mode 100644 index 000000000000..038094fd6fb5 --- /dev/null +++ b/www/waterfox/files/patch-bug1370791 @@ -0,0 +1,104 @@ +commit 4ab22d92be00 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Oct 4 19:12:40 2017 +0100 + + Bug 1370791 - Use CUI listener and an attribute to toggle hiding/showing the new tab button. r=jaws, a=ritu + + MozReview-Commit-ID: DaKohSCnrJn + + --HG-- + extra : source : 3894d341fe1631dc755e5b16b3a286ec4e741991 + extra : amend_source : 14a18fd29a60434f84664ee21eb245397a87f160 +--- + browser/base/content/browser.css | 4 +-- + browser/base/content/tabbrowser.xml | 49 +++++++++++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 2 deletions(-) + +diff --git browser/base/content/browser.css browser/base/content/browser.css +index 8afcbf4a5f48..4527cd480fb0 100644 +--- browser/base/content/browser.css ++++ browser/base/content/browser.css +@@ -114,9 +114,9 @@ tabbrowser { + } + + #tabbrowser-tabs:not([overflow="true"]) ~ #alltabs-button, +-#tabbrowser-tabs:not([overflow="true"]) + #new-tab-button, ++#tabbrowser-tabs[hasadjacentnewtabbutton]:not([overflow="true"]) ~ #new-tab-button, + #tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button, +-#TabsToolbar[currentset]:not([currentset*="tabbrowser-tabs,new-tab-button"]) > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button, ++#tabbrowser-tabs:not([hasadjacentnewtabbutton]) > .tabbrowser-arrowscrollbox > .tabs-newtab-button, + #TabsToolbar[customizing="true"] > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button { + visibility: collapse; + } +diff --git browser/base/content/tabbrowser.xml browser/base/content/tabbrowser.xml +index 7575a985eeba..7e6c321e5dee 100644 +--- browser/base/content/tabbrowser.xml ++++ browser/base/content/tabbrowser.xml +@@ -5808,11 +5808,58 @@ + ]]></body> + </method> + ++ <method name="_updateNewTabVisibility"> ++ <body><![CDATA[ ++ let sib = this.tabContainer.nextElementSibling; ++ while (sib && sib.hidden) { ++ sib = sib.nextElementSibling; ++ } ++ const kAttr = "hasadjacentnewtabbutton"; ++ if (sib && sib.id == "new-tab-button") { ++ this.tabContainer.setAttribute(kAttr, "true"); ++ } else { ++ this.tabContainer.removeAttribute(kAttr); ++ } ++ ]]></body> ++ </method> ++ ++ <method name="onWidgetAfterDOMChange"> ++ <parameter name="aNode"/> ++ <parameter name="aNextNode"/> ++ <parameter name="aContainer"/> ++ <body><![CDATA[ ++ if (aContainer.ownerDocument == document && ++ aContainer.id == "TabsToolbar") { ++ this._updateNewTabVisibility(); ++ } ++ ]]></body> ++ </method> ++ <method name="onAreaNodeRegistered"> ++ <parameter name="aArea"/> ++ <parameter name="aContainer"/> ++ <body><![CDATA[ ++ if (aContainer.ownerDocument == document && ++ aArea == "TabsToolbar") { ++ this._updateNewTabVisibility(); ++ } ++ ]]></body> ++ </method> ++ <method name="onAreaReset"> ++ <parameter name="aArea"/> ++ <parameter name="aContainer"/> ++ <body><![CDATA[ ++ this.onAreaNodeRegistered(aArea, aContainer); ++ ]]></body> ++ </method> ++ + <constructor> + <![CDATA[ + this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser"); + this.mCurrentBrowser.permanentKey = {}; + ++ CustomizableUI.addListener(this); ++ this._updateNewTabVisibility(); ++ + Services.obs.addObserver(this, "contextual-identity-updated"); + + this.mCurrentTab = this.tabContainer.firstChild; +@@ -5922,6 +5969,8 @@ + <![CDATA[ + Services.obs.removeObserver(this, "contextual-identity-updated"); + ++ CustomizableUI.removeListener(this); ++ + for (let tab of this.tabs) { + let browser = tab.linkedBrowser; + if (browser.registeredOpenURI) { diff --git a/www/waterfox/files/patch-bug1372107 b/www/waterfox/files/patch-bug1372107 new file mode 100644 index 000000000000..298cc734250b --- /dev/null +++ b/www/waterfox/files/patch-bug1372107 @@ -0,0 +1,82 @@ +commit 4224928879ee +Author: Michael Kaply <mozilla@kaply.com> +Date: Wed Mar 14 13:30:53 2018 -0500 + + Bug 1372107 - Allow browser to be started despite Autoconfig errors. r=florian, a=ritu + + MozReview-Commit-ID: of8cdUMedC + + --HG-- + extra : rebase_source : d58039b1f2e268c7a0af77e9a0680f759f203d99 + extra : source : dad020b0bb45903972c2856cc3a2968f39a27635 +--- + extensions/pref/autoconfig/src/nsReadConfig.cpp | 27 +++++++++++++------------ + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git extensions/pref/autoconfig/src/nsReadConfig.cpp extensions/pref/autoconfig/src/nsReadConfig.cpp +index a87b5b2c1bd4..8939fdc268eb 100644 +--- extensions/pref/autoconfig/src/nsReadConfig.cpp ++++ extensions/pref/autoconfig/src/nsReadConfig.cpp +@@ -36,35 +36,35 @@ extern nsresult CentralizedAdminPrefManagerInit(); + extern nsresult CentralizedAdminPrefManagerFinish(); + + +-static void DisplayError(void) ++static nsresult DisplayError(void) + { + nsresult rv; + + nsCOMPtr<nsIPromptService> promptService = do_GetService("@mozilla.org/embedcomp/prompt-service;1"); + if (!promptService) +- return; ++ return NS_ERROR_FAILURE; + + nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID); + if (!bundleService) +- return; ++ return NS_ERROR_FAILURE; + + nsCOMPtr<nsIStringBundle> bundle; + bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties", + getter_AddRefs(bundle)); + if (!bundle) +- return; ++ return NS_ERROR_FAILURE; + + nsXPIDLString title; + rv = bundle->GetStringFromName("readConfigTitle", getter_Copies(title)); + if (NS_FAILED(rv)) +- return; ++ return rv; + + nsXPIDLString err; + rv = bundle->GetStringFromName("readConfigMsg", getter_Copies(err)); + if (NS_FAILED(rv)) +- return; ++ return rv; + +- promptService->Alert(nullptr, title.get(), err.get()); ++ return promptService->Alert(nullptr, title.get(), err.get()); + } + + // nsISupports Implementation +@@ -101,12 +101,13 @@ NS_IMETHODIMP nsReadConfig::Observe(nsISupports *aSubj + if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) { + rv = readConfigFile(); + if (NS_FAILED(rv)) { +- DisplayError(); +- +- nsCOMPtr<nsIAppStartup> appStartup = +- do_GetService(NS_APPSTARTUP_CONTRACTID); +- if (appStartup) +- appStartup->Quit(nsIAppStartup::eAttemptQuit); ++ rv = DisplayError(); ++ if (NS_FAILED(rv)) { ++ nsCOMPtr<nsIAppStartup> appStartup = ++ do_GetService(NS_APPSTARTUP_CONTRACTID); ++ if (appStartup) ++ appStartup->Quit(nsIAppStartup::eAttemptQuit); ++ } + } + } + return rv; diff --git a/www/waterfox/files/patch-bug1373371 b/www/waterfox/files/patch-bug1373371 new file mode 100644 index 000000000000..75362fc53d31 --- /dev/null +++ b/www/waterfox/files/patch-bug1373371 @@ -0,0 +1,44 @@ +commit 94b1df91cc7f +Author: Eric Rahm <erahm@mozilla.com> +Date: Mon Jun 19 17:09:54 2017 -0700 + + Bug 1373371 - Properly convert index in RemoveElementsAt. r=froydnj, a=ritu + + MozReview-Commit-ID: 2CRrUmOxA9B + + --HG-- + extra : source : 337103b85c025be555c107c7710ebe25d2feb6ed +--- + xpcom/ds/nsTArray.h | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git xpcom/ds/nsTArray.h xpcom/ds/nsTArray.h +index 4e9b57126bfb..e0244846aca3 100644 +--- xpcom/ds/nsTArray.h ++++ xpcom/ds/nsTArray.h +@@ -13,6 +13,7 @@ + #include "mozilla/Assertions.h" + #include "mozilla/Attributes.h" + #include "mozilla/BinarySearch.h" ++#include "mozilla/CheckedInt.h" + #include "mozilla/fallible.h" + #include "mozilla/MathAlgorithms.h" + #include "mozilla/MemoryReporting.h" +@@ -2053,9 +2054,14 @@ void + nsTArray_Impl<E, Alloc>::RemoveElementsAt(index_type aStart, size_type aCount) + { + MOZ_ASSERT(aCount == 0 || aStart < Length(), "Invalid aStart index"); +- MOZ_ASSERT(aStart + aCount <= Length(), "Invalid length"); +- // Check that the previous assert didn't overflow +- MOZ_ASSERT(aStart <= aStart + aCount, "Start index plus length overflows"); ++ ++ mozilla::CheckedInt<index_type> rangeEnd = aStart; ++ rangeEnd += aCount; ++ ++ if (MOZ_UNLIKELY(!rangeEnd.isValid() || rangeEnd.value() > Length())) { ++ InvalidArrayIndex_CRASH(aStart, Length()); ++ } ++ + DestructRange(aStart, aCount); + this->template ShiftData<InfallibleAlloc>(aStart, aCount, 0, + sizeof(elem_type), diff --git a/www/waterfox/files/patch-bug1377158 b/www/waterfox/files/patch-bug1377158 new file mode 100644 index 000000000000..dc4385635715 --- /dev/null +++ b/www/waterfox/files/patch-bug1377158 @@ -0,0 +1,285 @@ +commit 9e809e01c262 +Author: Xidorn Quan <me@upsuper.org> +Date: Thu Aug 3 11:24:55 2017 +1000 + + Bug 1377158 - (Part 1) Set style backend to stylo when SVG is used as an image. r=heycam + + MozReview-Commit-ID: 9FnA8X84h87 + + --HG-- + extra : rebase_source : 49a6140c4c78c35f755710934c798ce46dafa213 +--- + dom/base/nsDocument.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 3585a7e222df..b4773160af92 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -13219,7 +13219,10 @@ nsIDocument::UpdateStyleBackendType() + + #ifdef MOZ_STYLO + if (nsLayoutUtils::StyloEnabled()) { +- if (!mDocumentContainer) { ++ if (IsBeingUsedAsImage()) { ++ // Enable stylo for SVG-as-image. ++ mStyleBackendType = StyleBackendType::Servo; ++ } else if (!mDocumentContainer) { + NS_WARNING("stylo: No docshell yet, assuming Gecko style system"); + } else if ((IsHTMLOrXHTML() || IsSVGDocument()) && + IsContentDocument()) { + +commit e418f1ccf520 +Author: KuoE0 <kuoe0.tw@gmail.com> +Date: Mon Jul 24 11:51:20 2017 +0800 + + Bug 1377158 - (Part 2) Add the info of StyloEnabled() to hash function to make reftests of styloVsGecko get the correct caches. r=heycam + + MozReview-Commit-ID: 7cyXheHQ7Ot + + --HG-- + extra : rebase_source : 4a92de63228cb2a138d95d8f366b39122dbdc05e +--- + image/ImageCacheKey.cpp | 20 ++++++++++++++++---- + image/ImageCacheKey.h | 7 ++++++- + 2 files changed, 22 insertions(+), 5 deletions(-) + +diff --git image/ImageCacheKey.cpp image/ImageCacheKey.cpp +index c3327155c1cd..2dfdc7c763cc 100644 +--- image/ImageCacheKey.cpp ++++ image/ImageCacheKey.cpp +@@ -8,6 +8,7 @@ + #include "mozilla/Move.h" + #include "ImageURL.h" + #include "nsHostObjectProtocolHandler.h" ++#include "nsLayoutUtils.h" + #include "nsString.h" + #include "mozilla/dom/File.h" + #include "mozilla/dom/workers/ServiceWorkerManager.h" +@@ -53,6 +54,7 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI, + , mOriginAttributes(aAttrs) + , mControlledDocument(GetControlledDocumentToken(aDocument)) + , mIsChrome(URISchemeIs(mURI, "chrome")) ++ , mIsStyloEnabled(nsLayoutUtils::StyloEnabled()) + { + NS_ENSURE_SUCCESS_VOID(aRv); + +@@ -62,7 +64,8 @@ ImageCacheKey::ImageCacheKey(nsIURI* aURI, + mBlobSerial = BlobSerial(mURI); + } + +- mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument); ++ mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument, ++ mIsStyloEnabled); + } + + ImageCacheKey::ImageCacheKey(ImageURL* aURI, +@@ -72,6 +75,7 @@ ImageCacheKey::ImageCacheKey(ImageURL* aURI, + , mOriginAttributes(aAttrs) + , mControlledDocument(GetControlledDocumentToken(aDocument)) + , mIsChrome(URISchemeIs(mURI, "chrome")) ++ , mIsStyloEnabled(nsLayoutUtils::StyloEnabled()) + { + MOZ_ASSERT(aURI); + +@@ -79,7 +83,8 @@ ImageCacheKey::ImageCacheKey(ImageURL* aURI, + mBlobSerial = BlobSerial(mURI); + } + +- mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument); ++ mHash = ComputeHash(mURI, mBlobSerial, mOriginAttributes, mControlledDocument, ++ mIsStyloEnabled); + } + + ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther) +@@ -89,6 +94,7 @@ ImageCacheKey::ImageCacheKey(const ImageCacheKey& aOther) + , mControlledDocument(aOther.mControlledDocument) + , mHash(aOther.mHash) + , mIsChrome(aOther.mIsChrome) ++ , mIsStyloEnabled(aOther.mIsStyloEnabled) + { } + + ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther) +@@ -98,11 +104,15 @@ ImageCacheKey::ImageCacheKey(ImageCacheKey&& aOther) + , mControlledDocument(aOther.mControlledDocument) + , mHash(aOther.mHash) + , mIsChrome(aOther.mIsChrome) ++ , mIsStyloEnabled(aOther.mIsStyloEnabled) + { } + + bool + ImageCacheKey::operator==(const ImageCacheKey& aOther) const + { ++ if (mIsStyloEnabled != aOther.mIsStyloEnabled) { ++ return false; ++ } + // Don't share the image cache between a controlled document and anything else. + if (mControlledDocument != aOther.mControlledDocument) { + return false; +@@ -132,7 +142,8 @@ ImageCacheKey::Spec() const + ImageCacheKey::ComputeHash(ImageURL* aURI, + const Maybe<uint64_t>& aBlobSerial, + const OriginAttributes& aAttrs, +- void* aControlledDocument) ++ void* aControlledDocument, ++ bool aIsStyloEnabled) + { + // Since we frequently call Hash() several times in a row on the same + // ImageCacheKey, as an optimization we compute our hash once and store it. +@@ -142,7 +153,8 @@ ImageCacheKey::ComputeHash(ImageURL* aURI, + aAttrs.CreateSuffix(suffix); + + return AddToHash(0, aURI->ComputeHash(aBlobSerial), +- HashString(suffix), HashString(ptr)); ++ HashString(suffix), HashString(ptr), ++ aIsStyloEnabled); + } + + /* static */ void* +diff --git image/ImageCacheKey.h image/ImageCacheKey.h +index c5acd0ea495e..6d676ccb6338 100644 +--- image/ImageCacheKey.h ++++ image/ImageCacheKey.h +@@ -58,7 +58,8 @@ private: + static PLDHashNumber ComputeHash(ImageURL* aURI, + const Maybe<uint64_t>& aBlobSerial, + const OriginAttributes& aAttrs, +- void* aControlledDocument); ++ void* aControlledDocument, ++ bool aIsStyloEnabled); + static void* GetControlledDocumentToken(nsIDocument* aDocument); + + RefPtr<ImageURL> mURI; +@@ -67,6 +68,10 @@ private: + void* mControlledDocument; + PLDHashNumber mHash; + bool mIsChrome; ++ // To prevent the reftests of styloVsGecko taking the same image cache after ++ // refreshing, we need to store different caches of stylo and gecko. So, we ++ // also consider the info of StyloEnabled() in ImageCacheKey. ++ bool mIsStyloEnabled; + }; + + } // namespace image + +commit c95ed14053c7 +Author: KuoE0 <kuoe0.tw@gmail.com> +Date: Thu Jul 27 14:06:54 2017 +0800 + + Bug 1377158 - (Part 3) Update the expectation of test cases. r=bholley,heycam + + MozReview-Commit-ID: K3gmTudkzol + + --HG-- + extra : rebase_source : 32ba6ceb37fa2f29cde8d2534d73108e87dfa406 +--- + layout/reftests/css-break/reftest.list | 2 +- + layout/reftests/svg/as-image/reftest.list | 2 +- + layout/reftests/table-background/reftest.list | 8 ++++---- + 3 files changed, 6 insertions(+), 6 deletions(-) + +diff --git layout/reftests/css-break/reftest.list layout/reftests/css-break/reftest.list +index 4364cf7d93fc..54cfbcbbeefc 100644 +--- layout/reftests/css-break/reftest.list ++++ layout/reftests/css-break/reftest.list +@@ -2,7 +2,7 @@ default-preferences pref(layout.css.box-decoration-break.enabled,true) + + == box-decoration-break-1.html box-decoration-break-1-ref.html + fuzzy(1,20) fuzzy-if(skiaContent,1,700) fuzzy-if(webrender,4-4,3273-3273) == box-decoration-break-with-inset-box-shadow-1.html box-decoration-break-with-inset-box-shadow-1-ref.html +-fuzzy(16,460) fuzzy-if(Android,10,3673) fuzzy-if(skiaContent,57,374) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html ++fuzzy(16,460) fuzzy-if(Android,10,3673) fuzzy-if(skiaContent,57,374) fuzzy-if(styloVsGecko,1,420) == box-decoration-break-with-outset-box-shadow-1.html box-decoration-break-with-outset-box-shadow-1-ref.html # Bug 1386543 + random-if(!gtkWidget) HTTP(..) == box-decoration-break-border-image.html box-decoration-break-border-image-ref.html + == box-decoration-break-block-border-padding.html box-decoration-break-block-border-padding-ref.html + == box-decoration-break-block-margin.html box-decoration-break-block-margin-ref.html +diff --git layout/reftests/svg/as-image/reftest.list layout/reftests/svg/as-image/reftest.list +index d5feb66693ad..acff18d18b50 100644 +--- layout/reftests/svg/as-image/reftest.list ++++ layout/reftests/svg/as-image/reftest.list +@@ -58,7 +58,7 @@ fuzzy(1,2) fuzzy-if(azureSkia,1,40000) == canvas-drawImage-alpha-2.html canvas-d + # context-fill: + == context-fill-01.html blue100x100-ref.html + test-pref(svg.context-properties.content.enabled,true) == context-fill-01.html lime100x100-ref.html +-== context-fill-02.html transparent100x100-w-border-ref.html ++fails-if(styloVsGecko||stylo) == context-fill-02.html transparent100x100-w-border-ref.html # Bug 1380590 + test-pref(svg.context-properties.content.enabled,true) == context-fill-02.html lime100x100-w-border-ref.html + test-pref(svg.context-properties.content.enabled,true) == context-fill-03.html lime100x100-50pct-ref.html + # fuzz because on win8 the r & b components are off by one +diff --git layout/reftests/table-background/reftest.list layout/reftests/table-background/reftest.list +index d8a138112527..df2f629d0d7f 100644 +--- layout/reftests/table-background/reftest.list ++++ layout/reftests/table-background/reftest.list +@@ -1,11 +1,11 @@ + # these could be moved to crashtests + != backgr_border-table-cell.html empty.html +-!= backgr_border-table-column-group.html empty.html ++fuzzy-if(styloVsGecko,5,330) != backgr_border-table-column-group.html empty.html # Bug 1386543 + # This seems to be caused by bug 527825 +-asserts-if(gtkWidget,0-12) != backgr_border-table-column.html empty.html ++fuzzy-if(styloVsGecko,5,561) asserts-if(gtkWidget,0-12) != backgr_border-table-column.html empty.html # Bug 1386543 + asserts-if(gtkWidget,0-6) != backgr_border-table-quirks.html empty.html +-!= backgr_border-table-row-group.html empty.html +-!= backgr_border-table-row.html empty.html ++fuzzy-if(styloVsGecko,1,168) != backgr_border-table-row-group.html empty.html # Bug 1386543 ++fuzzy-if(styloVsGecko,1,168) != backgr_border-table-row.html empty.html # Bug 1386543 + != backgr_border-table.html empty.html + != backgr_fixed-bg.html empty.html + != backgr_index.html empty.html + +commit dd7cb82fb7b5 +Author: KuoE0 <kuoe0.tw@gmail.com> +Date: Fri Jul 28 00:23:05 2017 +0800 + + Bug 1377158 - (Part 4) Reduce the assertion cost to check reconstruction frame hint. r=bholley,heycam + + The original assertion took too long time to check nsStyleChangeList. It + caused the test case with many elements timed-out and failed. + + MozReview-Commit-ID: FpNZvdQFTtR + + --HG-- + extra : rebase_source : c68072448061c4dcc8399131924cf718a5e53700 +--- + layout/base/nsStyleChangeList.cpp | 30 +++++++++++++++++++----------- + 1 file changed, 19 insertions(+), 11 deletions(-) + +diff --git layout/base/nsStyleChangeList.cpp layout/base/nsStyleChangeList.cpp +index 6f68cded3814..af6256f46c22 100644 +--- layout/base/nsStyleChangeList.cpp ++++ layout/base/nsStyleChangeList.cpp +@@ -41,17 +41,25 @@ nsStyleChangeList::AppendChange(nsIFrame* aFrame, nsIContent* aContent, nsChange + (aHint & nsChangeHint_NeedReflow), + "Reflow hint bits set without actually asking for a reflow"); + +- // If Servo fires reconstruct at a node, it is the only change hint fired at +- // that node. +- if (IsServo()) { +- for (size_t i = 0; i < Length(); ++i) { +- MOZ_ASSERT(!aContent || !((aHint | (*this)[i].mHint) & nsChangeHint_ReconstructFrame) || +- (*this)[i].mContent != aContent); +- } +- } else { +- // Filter out all other changes for same content for Gecko (Servo asserts against this +- // case above). +- if (aContent && (aHint & nsChangeHint_ReconstructFrame)) { ++ if (aContent && (aHint & nsChangeHint_ReconstructFrame)) { ++ // If Servo fires reconstruct at a node, it is the only change hint fired at ++ // that node. ++ if (IsServo()) { ++ // Note: Because we check whether |aHint| is a reconstruct above (which is ++ // necessary to avoid debug test timeouts on certain crashtests), this check ++ // will not find bugs where we add a non-reconstruct hint for an element after ++ // adding a reconstruct. This is ok though, since ProcessRestyledFrames will ++ // handle that case via mDestroyedFrames. ++ for (size_t i = 0; i < Length(); ++i) { ++ MOZ_ASSERT(aContent != (*this)[i].mContent || ++ !((*this)[i].mHint & nsChangeHint_ReconstructFrame), ++ "Should not append a non-ReconstructFrame hint after \ ++ appending a ReconstructFrame hint for the same \ ++ content."); ++ } ++ } else { ++ // Filter out all other changes for same content for Gecko (Servo asserts against this ++ // case above). + // NOTE: This is captured by reference to please static analysis. + // Capturing it by value as a pointer should be fine in this case. + RemoveElementsBy([&](const nsStyleChangeData& aData) { diff --git a/www/waterfox/files/patch-bug1377587 b/www/waterfox/files/patch-bug1377587 new file mode 100644 index 000000000000..5e58f504cffd --- /dev/null +++ b/www/waterfox/files/patch-bug1377587 @@ -0,0 +1,929 @@ +commit 2b68b38709b1 +Author: Andrew McCreight <continuation@gmail.com> +Date: Tue Aug 22 14:24:11 2017 -0700 + + Bug 1377587, part 1 - Always act like __exposedProps__ is missing. r=krizsa + + This patch gently removes support for __exposedProps__ by changing + ExposedPropertiesOnly::check() to always return false, while still + failing silently in deny for some kinds of access. + + The tests that I changed all involve testing the behavior with + __exposedProps__. I adjusted them to expect it to fail, or to adjust + the error message they get when they fail. That seemed better than + deleting them entirely. + + Note that test_bug1065185.html had a bug, so that it never executed + the first case. I fixed that, and then fixed up the test to work when + __exposedProps__ is not supported. + + This also removes various bits of the test framework that use + __exposedProps__, but don't actually need to. + + MozReview-Commit-ID: 8fvkAmITmXY + + --HG-- + extra : rebase_source : ef7e2c55adc12511f17f3865ebb46c343875f0b3 +--- + addon-sdk/source/lib/sdk/console/plain-text.js | 10 -- + addon-sdk/source/lib/sdk/test/loader.js | 5 - + .../addons/e10s-content/lib/test-content-script.js | 6 +- + addon-sdk/source/test/test-content-script.js | 6 +- + devtools/server/tests/unit/test_objectgrips-17.js | 4 - + dom/base/nsDeprecatedOperationList.h | 1 - + dom/base/test/chrome/cpows_child.js | 12 +- + dom/locales/en-US/chrome/dom/dom.properties | 2 - + js/xpconnect/src/XPCJSRuntime.cpp | 1 - + js/xpconnect/src/xpcprivate.h | 1 - + js/xpconnect/tests/chrome/test_bug1065185.html | 6 +- + js/xpconnect/tests/chrome/test_cows.xul | 80 +++------ + js/xpconnect/tests/chrome/test_exposeInDerived.xul | 13 +- + js/xpconnect/tests/unit/test_bug1082450.js | 20 +-- + js/xpconnect/tests/unit/test_bug780370.js | 7 +- + js/xpconnect/tests/unit/test_bug813901.js | 2 +- + js/xpconnect/tests/unit/test_bug853709.js | 4 +- + js/xpconnect/tests/unit/test_bug854558.js | 2 +- + js/xpconnect/tests/unit/test_bug930091.js | 2 +- + js/xpconnect/wrappers/AccessCheck.cpp | 179 --------------------- + js/xpconnect/wrappers/AccessCheck.h | 11 +- + js/xpconnect/wrappers/ChromeObjectWrapper.h | 6 +- + js/xpconnect/wrappers/WrapperFactory.cpp | 4 +- + js/xpconnect/wrappers/XrayWrapper.cpp | 2 +- + testing/mochitest/tests/SimpleTest/ChromePowers.js | 9 -- + .../specialpowers/content/MockPermissionPrompt.jsm | 12 -- + .../components/addoncompat/RemoteAddonsParent.jsm | 2 +- + 27 files changed, 74 insertions(+), 335 deletions(-) + +diff --git addon-sdk/source/lib/sdk/console/plain-text.js addon-sdk/source/lib/sdk/console/plain-text.js +index 0e44cf106d52..07b8eb629e12 100644 +--- addon-sdk/source/lib/sdk/console/plain-text.js ++++ addon-sdk/source/lib/sdk/console/plain-text.js +@@ -62,16 +62,6 @@ function PlainTextConsole(print, innerID) { + } + }); + +- // We defined the `__exposedProps__` in our console chrome object. +- // +- // Meanwhile we're investigating with the platform team if `__exposedProps__` +- // are needed, or are just a left-over. +- +- console.__exposedProps__ = Object.keys(ConsoleAPI.prototype).reduce(function(exposed, prop) { +- exposed[prop] = "r"; +- return exposed; +- }, {}); +- + Object.freeze(console); + return console; + }; +diff --git addon-sdk/source/lib/sdk/test/loader.js addon-sdk/source/lib/sdk/test/loader.js +index 33ba2ca5a029..b555de63f02a 100644 +--- addon-sdk/source/lib/sdk/test/loader.js ++++ addon-sdk/source/lib/sdk/test/loader.js +@@ -53,11 +53,6 @@ function HookedPlainTextConsole(hook, print, innerID) { + this.exception = hook.bind(null, "exception", innerID); + this.time = hook.bind(null, "time", innerID); + this.timeEnd = hook.bind(null, "timeEnd", innerID); +- +- this.__exposedProps__ = { +- log: "rw", info: "rw", warn: "rw", error: "rw", debug: "rw", +- exception: "rw", time: "rw", timeEnd: "rw" +- }; + } + + // Creates a custom loader instance whose console module is hooked in order +diff --git addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js +index 477895e40481..3dccfec618d3 100644 +--- addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js ++++ addon-sdk/source/test/addons/e10s-content/lib/test-content-script.js +@@ -444,7 +444,7 @@ exports["test Highlight toString Behavior"] = createProxyTest("", function (help + let strToString = helper.rawWindow.Object.prototype.toString.call(""); + assert.ok(/\[object String.*\]/.test(strToString), "strings are strings"); + +- let o = {__exposedProps__:{}}; ++ let o = {}; + let objToString = helper.rawWindow.Object.prototype.toString.call(o); + assert.ok(/\[object Object.*\]/.test(objToString), "objects are objects"); + +@@ -622,10 +622,6 @@ exports["test Functions"] = createProxyTest("", function (helper) { + helper.rawWindow.isEqual = function isEqual(a, b) { + return a == b; + }; +- // bug 784116: workaround in order to allow proxy code to cache proxies on +- // these functions: +- helper.rawWindow.callFunction.__exposedProps__ = {__proxy: 'rw'}; +- helper.rawWindow.isEqual.__exposedProps__ = {__proxy: 'rw'}; + + helper.createWorker( + 'new ' + function ContentScriptScope() { +diff --git addon-sdk/source/test/test-content-script.js addon-sdk/source/test/test-content-script.js +index 709fb5a3aa91..a02e66f65eea 100644 +--- addon-sdk/source/test/test-content-script.js ++++ addon-sdk/source/test/test-content-script.js +@@ -444,7 +444,7 @@ exports["test Highlight toString Behavior"] = createProxyTest("", function (help + let strToString = helper.rawWindow.Object.prototype.toString.call(""); + assert.ok(/\[object String.*\]/.test(strToString), "strings are strings"); + +- let o = {__exposedProps__:{}}; ++ let o = {}; + let objToString = helper.rawWindow.Object.prototype.toString.call(o); + assert.ok(/\[object Object.*\]/.test(objToString), "objects are objects"); + +@@ -622,10 +622,6 @@ exports["test Functions"] = createProxyTest("", function (helper) { + helper.rawWindow.isEqual = function isEqual(a, b) { + return a == b; + }; +- // bug 784116: workaround in order to allow proxy code to cache proxies on +- // these functions: +- helper.rawWindow.callFunction.__exposedProps__ = {__proxy: 'rw'}; +- helper.rawWindow.isEqual.__exposedProps__ = {__proxy: 'rw'}; + + helper.createWorker( + 'new ' + function ContentScriptScope() { +diff --git dom/base/nsDeprecatedOperationList.h dom/base/nsDeprecatedOperationList.h +index 2523187c63a7..adcf4d9d8202 100644 +--- dom/base/nsDeprecatedOperationList.h ++++ dom/base/nsDeprecatedOperationList.h +@@ -21,7 +21,6 @@ DEPRECATED_OPERATION(NodeValue) + DEPRECATED_OPERATION(TextContent) + DEPRECATED_OPERATION(EnablePrivilege) + DEPRECATED_OPERATION(DOMExceptionCode) +-DEPRECATED_OPERATION(NoExposedProps) + DEPRECATED_OPERATION(MutationEvent) + DEPRECATED_OPERATION(Components) + DEPRECATED_OPERATION(PrefixedVisibilityAPI) +diff --git dom/base/test/chrome/cpows_child.js dom/base/test/chrome/cpows_child.js +index 6d240a7eaa51..fc7e3f2c9d0f 100644 +--- dom/base/test/chrome/cpows_child.js ++++ dom/base/test/chrome/cpows_child.js +@@ -105,7 +105,13 @@ function parent_test(finish) + + addMessageListener("cpows:from_parent", (msg) => { + let obj = msg.objects.obj; +- ok(obj.a == 1, "correct value from parent"); ++ if (is_remote) { ++ ok(obj.a == undefined, "__exposedProps__ should not work"); ++ } else { ++ // The same process test is not run as content, so the field can ++ // be accessed even though __exposedProps__ has been removed. ++ ok(obj.a == 1, "correct value from parent"); ++ } + + // Test that a CPOW reference to a function in the chrome process + // is callable from unprivileged content. Greasemonkey uses this +@@ -260,11 +266,11 @@ function lifetime_test(finish) + var obj = {"will_die": {"f": 1}}; + let [result] = sendRpcMessage("cpows:lifetime_test_1", {}, {obj: obj}); + ok(result == 10, "got sync result"); +- ok(obj.wont_die.f == 2, "got reverse CPOW"); ++ ok(obj.wont_die.f == undefined, "got reverse CPOW"); + obj.will_die = null; + Components.utils.schedulePreciseGC(function() { + addMessageListener("cpows:lifetime_test_3", (msg) => { +- ok(obj.wont_die.f == 2, "reverse CPOW still works"); ++ ok(obj.wont_die.f == undefined, "reverse CPOW still works"); + finish(); + }); + sendRpcMessage("cpows:lifetime_test_2"); +diff --git dom/locales/en-US/chrome/dom/dom.properties dom/locales/en-US/chrome/dom/dom.properties +index 5c94a580287a..ac9dbed58e08 100644 +--- dom/locales/en-US/chrome/dom/dom.properties ++++ dom/locales/en-US/chrome/dom/dom.properties +@@ -154,8 +154,6 @@ MediaEMENoCapabilitiesDeprecatedWarning=Calling navigator.requestMediaKeySystemA + MediaEMENoCodecsDeprecatedWarning=Calling navigator.requestMediaKeySystemAccess() (at %S) passing a candidate MediaKeySystemConfiguration containing audioCapabilities or videoCapabilities without a contentType with a “codecs” string is deprecated and will soon become unsupported. + # LOCALIZATION NOTE: Do not translate "DOMException", "code" and "name" + DOMExceptionCodeWarning=Use of DOMException’s code attribute is deprecated. Use name instead. +-# LOCALIZATION NOTE: Do not translate "__exposedProps__" +-NoExposedPropsWarning=Exposing chrome JS objects to content without __exposedProps__ is insecure and deprecated. See https://developer.mozilla.org/en/XPConnect_wrappers for more information. + # LOCALIZATION NOTE: Do not translate "Mutation Event" and "MutationObserver" + MutationEventWarning=Use of Mutation Events is deprecated. Use MutationObserver instead. + # LOCALIZATION NOTE: Do not translate "Components" +diff --git js/xpconnect/src/XPCJSRuntime.cpp js/xpconnect/src/XPCJSRuntime.cpp +index 455b9f8e963f..ff9aea0a41eb 100644 +--- js/xpconnect/src/XPCJSRuntime.cpp ++++ js/xpconnect/src/XPCJSRuntime.cpp +@@ -93,7 +93,6 @@ const char* const XPCJSRuntime::mStrings[] = { + "item", // IDX_ITEM + "__proto__", // IDX_PROTO + "__iterator__", // IDX_ITERATOR +- "__exposedProps__", // IDX_EXPOSEDPROPS + "eval", // IDX_EVAL + "controllers", // IDX_CONTROLLERS + "Controllers", // IDX_CONTROLLERS_CLASS +diff --git js/xpconnect/src/xpcprivate.h js/xpconnect/src/xpcprivate.h +index fb7e43c22cd0..5d877f09d301 100644 +--- js/xpconnect/src/xpcprivate.h ++++ js/xpconnect/src/xpcprivate.h +@@ -460,7 +460,6 @@ public: + IDX_ITEM , + IDX_PROTO , + IDX_ITERATOR , +- IDX_EXPOSEDPROPS , + IDX_EVAL , + IDX_CONTROLLERS , + IDX_CONTROLLERS_CLASS , +diff --git js/xpconnect/tests/chrome/test_bug1065185.html js/xpconnect/tests/chrome/test_bug1065185.html +index cdd65326f9c8..7ea81fc8aa6f 100644 +--- js/xpconnect/tests/chrome/test_bug1065185.html ++++ js/xpconnect/tests/chrome/test_bug1065185.html +@@ -25,11 +25,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1065185 + + var gLoadCount = 0; + function loaded() { +- switch(++gLoadCount) { ++ switch(gLoadCount++) { + case 0: +- doMonitor([]); ++ doMonitor([/access to property "a"/i]); + window[0].wrappedJSObject.probe = { a: 2, __exposedProps__: { 'a': 'r' } }; +- is(window[0].eval('probe.a'), 2, "Accessed exposed prop"); ++ is(window[0].eval('probe.a'), undefined, "Accessed exposed prop"); + endMonitor(); + break; + case 1: +diff --git js/xpconnect/tests/chrome/test_cows.xul js/xpconnect/tests/chrome/test_cows.xul +index 75c5250dd150..adfdd686540b 100644 +--- js/xpconnect/tests/chrome/test_cows.xul ++++ js/xpconnect/tests/chrome/test_cows.xul +@@ -49,13 +49,6 @@ sandbox.getCOW = getCOW; + const TEST_API = ['is', 'isnot', 'ok', 'todo_is', 'todo_isnot', 'todo']; + TEST_API.forEach(function(name) { sandbox[name] = window[name]; }); + +-sandbox.alienObject = { +- __exposedProps__: {funProp: 'r'}, +- funProp: function foo(x) { +- return x + 1; +- } +-}; +- + sandbox.chromeGet = function (obj, prop) { return obj[prop]; }; + + function COWTests() { +@@ -74,17 +67,6 @@ function COWTests() { + // functions like assertIsWritable(myObj, 'someproperty') might + // be useful. + +- function isProp(obj, propName, value, desc) { +- try { +- is(obj[propName], value, "getting " + propName + " on " + desc); +- ok(propName in obj, +- propName + " on " + desc + " should exist"); +- ok(Object.hasOwnProperty.call(obj, propName), +- propName + " on " + desc + " should exist"); +- } catch (e) { +- ok(false, "getting " + propName + " on " + desc + " threw " + e); +- } +- } + function isPropHidden(obj, propName, desc) { + try { + is(obj[propName], undefined, +@@ -103,7 +85,7 @@ function COWTests() { + var empty = {}; + var nonempty = {foo: 42, bar: 33}; + is(getCOW(empty).foo, undefined, +- "shouldn't throw when accessing exposed properties that doesn't exist"); ++ "shouldn't throw when accessing exposed properties that don't exist"); + + PROPS_TO_TEST.forEach(function(name) { + isPropHidden(getCOW(nonempty), name, "object without exposedProps"); +@@ -135,18 +117,12 @@ function COWTests() { + var strict = { __exposedProps__: { foo: "r" }, foo: "foo property" }; + var strictCOWr = getCOW(strict); + PROPS_TO_TEST.forEach(function(name) { +- if (name == "foo") { +- isProp(strictCOWr, name, "foo property", +- "object with exposed 'foo'"); +- } +- else { +- isPropHidden(strictCOW, name, "object with exposed 'foo'"); +- } ++ isPropHidden(strictCOW, name, "object with exposed 'foo'"); + }); +- is(getNames(strictCOWr).length, 1, +- "object with exposedProps only enumerate exposed props"); +- is(getNames(strictCOWr)[0], "foo", +- "object with exposedProps only enumerate exposed props"); ++ is(getNames(strictCOWr).length, 0, ++ "exposed props does not enumerate anything"); ++ is(getNames(strictCOWr)[0], undefined, ++ "exposed props does not enumerate anything"); + + // Test writable property + var writable = getCOW({ __exposedProps__: {foo: 'w'}}); +@@ -154,25 +130,18 @@ function COWTests() { + ok(!("foo" in writable), + "non-existing write-only property shouldn't exist"); + writable.foo = 5; +- is(chromeGet(writable, "foo"), 5, "writing to a write-only exposed prop works"); +- todo("foo" in writable, +- "existing write-only property should exist"); +- } catch (e) { +- ok(false, "writing to a write-only exposed prop shouldn't throw " + e); +- } +- try { +- writable.foo; +- todo(false, "reading from a write-only exposed prop should throw"); ++ ok(false, "writing to a write-only exposed prop should throw"); + } catch (e) { +- todo(/Permission denied/.test(e), +- "reading from a write-only exposed prop should throw"); ++ ok(/Permission denied/.test(e), ++ "writing to a write-only exposed prop should throw the right error"); + } ++ is(writable.foo, undefined, ++ "reading from a write-only exposed prop should return undefined"); + try { + delete writable.foo; +- is(chromeGet(writable, "foo"), undefined, +- "deleting a write-only exposed prop works"); ++ ok(false, "deleting a write-only exposed prop should throw"); + } catch (e) { +- ok(false, "deleting a write-only exposed prop shouldn't throw " + e); ++ ok(true, "deleting a write-only exposed prop should throw " + e); + } + + // Test readable property +@@ -180,8 +149,8 @@ function COWTests() { + foo: 5, + bar: 6 }; + try { +- isProp(getCOW(readable), "foo", 5, +- "reading from a readable exposed prop works"); ++ isPropHidden(getCOW(readable), "foo", undefined, ++ "reading from a readable exposed prop shouldn't work"); + } catch (e) { + ok(false, "reading from a readable exposed prop shouldn't throw " + e); + } +@@ -202,8 +171,7 @@ function COWTests() { + + try { + var props = getNames(getCOW(readable)); +- is(props.length, 1, "COW w/ one exposed prop should enumerate once"); +- is(props[0], 'foo', "COW w/ one exposed prop should enumerate it"); ++ is(props.length, 0, "COW w/ one exposed prop should not enumerate"); + } catch (e) { + ok(false, "COW w/ a readable prop should not raise exc " + + "on enumeration: " + e); +@@ -215,21 +183,17 @@ function COWTests() { + ok(!("foo" in readwrite), + "non-existing readwrite property shouldn't exist"); + readwrite.foo = 5; +- is(readwrite.foo, 5, "writing to a readwrite exposed prop looks like it worked"); +- is(chromeGet(readwrite, "foo"), 5, "writing to a readwrite exposed prop works"); +- ok("foo" in readwrite, +- "existing readwrite property should exist"); ++ ok(false, "writing to a readwrite exposed prop should throw"); + } catch (e) { +- ok(false, "writing to a readwrite exposed prop shouldn't throw " + e); ++ ok(/Permission denied/.test(e), ++ "writing to a readwrite exposed prop should throw the right error"); + } + try { + delete readwrite.foo; +- is(readwrite.foo, undefined, "deleting readwrite prop looks like it worked"); +- ok(!("foo" in readwrite), "deleting readwrite prop looks like it really worked"); +- is(chromeGet(readwrite, "foo"), undefined, +- "deleting a readwrite exposed prop works"); ++ ok(false, "deleting a readwrite prop should throw"); + } catch (e) { +- ok(false, "deleting a readwrite exposed prop shouldn't throw " + e); ++ ok(/Permission denied/.test(e), ++ "deleting a readwrite exposed prop should throw the right error"); + } + + // Readables and functions +diff --git js/xpconnect/tests/chrome/test_exposeInDerived.xul js/xpconnect/tests/chrome/test_exposeInDerived.xul +index 2ed3bb91e7fd..7e6c24e56db1 100644 +--- js/xpconnect/tests/chrome/test_exposeInDerived.xul ++++ js/xpconnect/tests/chrome/test_exposeInDerived.xul +@@ -17,7 +17,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=804630 + <!-- test code goes here --> + <script type="application/javascript"> + <![CDATA[ +- /** Test to make sure that COWed objects can expose properties from their prototypes. **/ ++ /** Test to make sure that COWed objects can't expose properties from their prototypes. **/ + const Cu = Components.utils; + + // Set up the sandbox. +@@ -25,7 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=804630 + sb.ok = ok; + sb.is = is; + +- // Make a chrome object that exposes objects off its prototype. ++ // Make a chrome object that tries to expose objects off its prototype. + sb.proto = { read: 42, readWrite: 32, __exposedProps__: {} }; + sb.obj = { __exposedProps__: { read: 'r', readWrite: 'rw' } }; + sb.obj.__proto__ = sb.proto; +@@ -36,10 +36,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=804630 + 'try { proto.readWrite = 12; wrote = true; } catch(e) {} ' + + ' ok(!wrote, "Should not write proto property");', sb); + +- // Make sure we can access the exposed properties via the derived object. +- Cu.evalInSandbox('is(obj.read, 42, "obj.read accessible");', sb); +- Cu.evalInSandbox('is(obj.readWrite, 32, "obj.readWrite is readable");', sb); +- Cu.evalInSandbox('obj.readWrite = 8; is(obj.readWrite, 8, "obj.readWrite is writable");', sb); ++ // Make sure we can't access the exposed properties via the derived object. ++ Cu.evalInSandbox('is(obj.read, undefined, "obj.read inaccessible");', sb); ++ Cu.evalInSandbox('is(obj.readWrite, undefined, "obj.readWrite is not readable");', sb); ++ Cu.evalInSandbox('try { obj.readWrite = 8; ok(false, "obj.readWrite is not writable"); } catch (e) {};', ++ sb); + + ]]> + </script> +diff --git js/xpconnect/tests/unit/test_bug1082450.js js/xpconnect/tests/unit/test_bug1082450.js +index 07f45f06beef..5880fcbcd4e6 100644 +--- js/xpconnect/tests/unit/test_bug1082450.js ++++ js/xpconnect/tests/unit/test_bug1082450.js +@@ -5,9 +5,9 @@ function run_test() { + function checkThrows(str, rgxp) { + try { + sb.eval(str); +- do_check_true(false); ++ do_check_true(false, "eval should have thrown"); + } catch (e) { +- do_check_true(rgxp.test(e)); ++ do_check_true(rgxp.test(e), "error message should match"); + } + } + +@@ -29,12 +29,12 @@ function run_test() { + chromeCallableValueProp: 'r' } + }; + +- do_check_eq(sb.eval('exposed.simpleValueProp'), 42); +- do_check_eq(sb.eval('exposed.objectValueProp.val'), 42); +- checkThrows('exposed.getterProp;', /privileged accessor/i); +- checkThrows('exposed.setterProp = 42;', /privileged accessor/i); +- checkThrows('exposed.getterSetterProp;', /privileged accessor/i); +- checkThrows('exposed.getterSetterProp = 42;', /privileged accessor/i); +- do_check_eq(sb.eval('exposed.contentCallableValueProp()'), 42); +- checkThrows('exposed.chromeCallableValueProp();', /privileged or cross-origin callable/i); ++ do_check_eq(sb.eval('exposed.simpleValueProp'), undefined); ++ do_check_eq(sb.eval('exposed.objectValueProp'), undefined); ++ do_check_eq(sb.eval('exposed.getterProp;'), undefined); ++ do_check_eq(sb.eval('exposed.getterSetterProp;'), undefined); ++ checkThrows('exposed.setterProp = 42;', /Permission denied/i); ++ checkThrows('exposed.getterSetterProp = 42;', /Permission denied/i); ++ do_check_eq(sb.eval('exposed.contentCallableValueProp'), undefined); ++ checkThrows('exposed.chromeCallableValueProp();', /is not a function/i); + } +diff --git js/xpconnect/tests/unit/test_bug780370.js js/xpconnect/tests/unit/test_bug780370.js +index 40d6f9748015..7ae757f0cd01 100644 +--- js/xpconnect/tests/unit/test_bug780370.js ++++ js/xpconnect/tests/unit/test_bug780370.js +@@ -14,10 +14,5 @@ function run_test() + var sb = Cu.Sandbox("http://www.example.com"); + sb.obj = { foo: 42, __exposedProps__: { hasOwnProperty: 'r' } }; + do_check_eq(Cu.evalInSandbox('typeof obj.foo', sb), 'undefined', "COW works as expected"); +- try { +- Cu.evalInSandbox('obj.hasOwnProperty', sb); +- do_check_true(false); +- } catch (e) { +- do_check_true(/privileged or cross-origin callable/i.test(e)); +- } ++ do_check_eq(Cu.evalInSandbox('obj.hasOwnProperty', sb), undefined); + } +diff --git js/xpconnect/tests/unit/test_bug813901.js js/xpconnect/tests/unit/test_bug813901.js +index 42f981581b51..2efc6539e879 100644 +--- js/xpconnect/tests/unit/test_bug813901.js ++++ js/xpconnect/tests/unit/test_bug813901.js +@@ -21,5 +21,5 @@ function run_test() { + checkThrows('obj.foo = 3;', sb, /denied/); + Cu.evalInSandbox("var p = {__exposedProps__: {foo: 'rw'}};", sb); + sb.obj.__proto__ = sb.p; +- checkThrows('obj.foo = 4;', sb, /__exposedProps__/); ++ checkThrows('obj.foo = 4;', sb, /denied/); + } +diff --git js/xpconnect/tests/unit/test_bug853709.js js/xpconnect/tests/unit/test_bug853709.js +index c7e51757dc63..1667d2241f93 100644 +--- js/xpconnect/tests/unit/test_bug853709.js ++++ js/xpconnect/tests/unit/test_bug853709.js +@@ -8,7 +8,7 @@ function setupChromeSandbox() { + function checkDefineThrows(sb, obj, prop, desc) { + var result = Cu.evalInSandbox('(function() { try { Object.defineProperty(' + obj + ', "' + prop + '", ' + desc.toSource() + '); return "nothrow"; } catch (e) { return e.toString(); }})();', sb); + do_check_neq(result, 'nothrow'); +- do_check_true(!!/denied/.exec(result)); ++ do_check_true(!!/denied|prohibited/.exec(result)); + do_check_true(result.indexOf(prop) != -1); // Make sure the prop name is in the error message. + } + +@@ -19,7 +19,7 @@ function run_test() { + contentSB.chromeObj = chromeSB.chromeObj; + contentSB.chromeArr = chromeSB.chromeArr; + +- do_check_eq(Cu.evalInSandbox('chromeObj.a', contentSB), 2); ++ do_check_eq(Cu.evalInSandbox('chromeObj.a', contentSB), undefined); + try { + Cu.evalInSandbox('chromeArr[1]', contentSB); + do_check_true(false); +diff --git js/xpconnect/tests/unit/test_bug854558.js js/xpconnect/tests/unit/test_bug854558.js +index d60d23a5baf8..574194dc3f52 100644 +--- js/xpconnect/tests/unit/test_bug854558.js ++++ js/xpconnect/tests/unit/test_bug854558.js +@@ -7,5 +7,5 @@ function run_test() { + contentSB.foo = chromeSB.foo; + do_check_eq(Cu.evalInSandbox('foo.a', contentSB), undefined, "Default deny with no __exposedProps__"); + Cu.evalInSandbox('this.foo.__exposedProps__ = {a: "r"}', chromeSB); +- do_check_eq(Cu.evalInSandbox('foo.a', contentSB), 2, "works with __exposedProps__"); ++ do_check_eq(Cu.evalInSandbox('foo.a', contentSB), undefined, "Still not allowed with __exposedProps__"); + } +diff --git js/xpconnect/tests/unit/test_bug930091.js js/xpconnect/tests/unit/test_bug930091.js +index aa11d5db2640..ecb2a60aed11 100644 +--- js/xpconnect/tests/unit/test_bug930091.js ++++ js/xpconnect/tests/unit/test_bug930091.js +@@ -5,7 +5,7 @@ function checkThrows(fn) { + fn(); + ok(false, "Should have thrown"); + } catch (e) { +- do_check_true(/denied|insecure/.test(e)); ++ do_check_true(/denied|insecure|prohibited/.test(e)); + } + } + +diff --git js/xpconnect/wrappers/AccessCheck.cpp js/xpconnect/wrappers/AccessCheck.cpp +index 07599ce7906a..b730310731e2 100644 +--- js/xpconnect/wrappers/AccessCheck.cpp ++++ js/xpconnect/wrappers/AccessCheck.cpp +@@ -252,20 +252,6 @@ AccessCheck::checkPassToPrivilegedCode(JSContext* cx, HandleObject wrapper, Hand + return true; + } + +- // COWs are fine to pass to chrome if and only if they have __exposedProps__, +- // since presumably content should never have a reason to pass an opaque +- // object back to chrome. +- if (AccessCheck::isChrome(js::UncheckedUnwrap(wrapper)) && WrapperFactory::IsCOW(obj)) { +- RootedObject target(cx, js::UncheckedUnwrap(obj)); +- JSAutoCompartment ac(cx, target); +- RootedId id(cx, GetJSIDByIndex(cx, XPCJSContext::IDX_EXPOSEDPROPS)); +- bool found = false; +- if (!JS_HasPropertyById(cx, target, id, &found)) +- return false; +- if (found) +- return true; +- } +- + // Same-origin wrappers are fine. + if (AccessCheck::wrapperSubsumes(obj)) + return true; +@@ -323,171 +309,6 @@ AccessCheck::reportCrossOriginDenial(JSContext* cx, JS::HandleId id, + MOZ_ALWAYS_TRUE(rv.MaybeSetPendingException(cx)); + } + +-enum Access { READ = (1<<0), WRITE = (1<<1), NO_ACCESS = 0 }; +- +-static void +-EnterAndThrowASCII(JSContext* cx, JSObject* wrapper, const char* msg) +-{ +- JSAutoCompartment ac(cx, wrapper); +- JS_ReportErrorASCII(cx, "%s", msg); +-} +- +-bool +-ExposedPropertiesOnly::check(JSContext* cx, HandleObject wrapper, HandleId id, Wrapper::Action act) +-{ +- RootedObject wrappedObject(cx, Wrapper::wrappedObject(wrapper)); +- +- if (act == Wrapper::CALL) +- return false; +- +- // For the case of getting a property descriptor, we allow if either GET or SET +- // is allowed, and rely on FilteringWrapper to filter out any disallowed accessors. +- if (act == Wrapper::GET_PROPERTY_DESCRIPTOR) { +- return check(cx, wrapper, id, Wrapper::GET) || +- check(cx, wrapper, id, Wrapper::SET); +- } +- +- RootedId exposedPropsId(cx, GetJSIDByIndex(cx, XPCJSContext::IDX_EXPOSEDPROPS)); +- +- // We need to enter the wrappee's compartment to look at __exposedProps__, +- // but we want to be in the wrapper's compartment if we call Deny(). +- // +- // Unfortunately, |cx| can be in either compartment when we call ::check. :-( +- JSAutoCompartment ac(cx, wrappedObject); +- +- bool found = false; +- if (!JS_HasPropertyById(cx, wrappedObject, exposedPropsId, &found)) +- return false; +- +- // If no __exposedProps__ existed, deny access. +- if (!found) { +- // Previously we automatically granted access to indexed properties and +- // .length for Array COWs. We're not doing that anymore, so make sure to +- // let people know what's going on. +- bool isArray; +- if (!JS_IsArrayObject(cx, wrappedObject, &isArray)) +- return false; +- if (!isArray) +- isArray = JS_IsTypedArrayObject(wrappedObject); +- bool isIndexedAccessOnArray = isArray && JSID_IS_INT(id) && JSID_TO_INT(id) >= 0; +- bool isLengthAccessOnArray = isArray && JSID_IS_STRING(id) && +- JS_FlatStringEqualsAscii(JSID_TO_FLAT_STRING(id), "length"); +- if (isIndexedAccessOnArray || isLengthAccessOnArray) { +- JSAutoCompartment ac2(cx, wrapper); +- ReportWrapperDenial(cx, id, WrapperDenialForCOW, +- "Access to elements and length of privileged Array not permitted"); +- } +- +- return false; +- } +- +- if (id == JSID_VOID) +- return true; +- +- Rooted<PropertyDescriptor> desc(cx); +- if (!JS_GetPropertyDescriptorById(cx, wrappedObject, exposedPropsId, &desc)) +- return false; +- +- if (!desc.object()) +- return false; +- +- if (desc.hasGetterOrSetter()) { +- EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be a value property"); +- return false; +- } +- +- RootedValue exposedProps(cx, desc.value()); +- if (exposedProps.isNullOrUndefined()) +- return false; +- +- if (!exposedProps.isObject()) { +- EnterAndThrowASCII(cx, wrapper, "__exposedProps__ must be undefined, null, or an Object"); +- return false; +- } +- +- RootedObject hallpass(cx, &exposedProps.toObject()); +- +- if (!AccessCheck::subsumes(js::UncheckedUnwrap(hallpass), wrappedObject)) { +- EnterAndThrowASCII(cx, wrapper, "Invalid __exposedProps__"); +- return false; +- } +- +- Access access = NO_ACCESS; +- +- if (!JS_GetPropertyDescriptorById(cx, hallpass, id, &desc)) { +- return false; // Error +- } +- if (!desc.object() || !desc.enumerable()) +- return false; +- +- if (!desc.value().isString()) { +- EnterAndThrowASCII(cx, wrapper, "property must be a string"); +- return false; +- } +- +- JSFlatString* flat = JS_FlattenString(cx, desc.value().toString()); +- if (!flat) +- return false; +- +- size_t length = JS_GetStringLength(JS_FORGET_STRING_FLATNESS(flat)); +- +- for (size_t i = 0; i < length; ++i) { +- char16_t ch = JS_GetFlatStringCharAt(flat, i); +- switch (ch) { +- case 'r': +- if (access & READ) { +- EnterAndThrowASCII(cx, wrapper, "duplicate 'readable' property flag"); +- return false; +- } +- access = Access(access | READ); +- break; +- +- case 'w': +- if (access & WRITE) { +- EnterAndThrowASCII(cx, wrapper, "duplicate 'writable' property flag"); +- return false; +- } +- access = Access(access | WRITE); +- break; +- +- default: +- EnterAndThrowASCII(cx, wrapper, "properties can only be readable or read and writable"); +- return false; +- } +- } +- +- if (access == NO_ACCESS) { +- EnterAndThrowASCII(cx, wrapper, "specified properties must have a permission bit set"); +- return false; +- } +- +- if ((act == Wrapper::SET && !(access & WRITE)) || +- (act != Wrapper::SET && !(access & READ))) { +- return false; +- } +- +- // Inspect the property on the underlying object to check for red flags. +- if (!JS_GetPropertyDescriptorById(cx, wrappedObject, id, &desc)) +- return false; +- +- // Reject accessor properties. +- if (desc.hasGetterOrSetter()) { +- EnterAndThrowASCII(cx, wrapper, "Exposing privileged accessor properties is prohibited"); +- return false; +- } +- +- // Reject privileged or cross-origin callables. +- if (desc.value().isObject()) { +- RootedObject maybeCallable(cx, js::UncheckedUnwrap(&desc.value().toObject())); +- if (JS::IsCallable(maybeCallable) && !AccessCheck::subsumes(wrapper, maybeCallable)) { +- EnterAndThrowASCII(cx, wrapper, "Exposing privileged or cross-origin callable is prohibited"); +- return false; +- } +- } +- +- return true; +-} +- + bool + ExposedPropertiesOnly::deny(JSContext* cx, js::Wrapper::Action act, HandleId id, + bool mayThrow) +diff --git js/xpconnect/wrappers/AccessCheck.h js/xpconnect/wrappers/AccessCheck.h +index 678dce3e0b81..c4873760ab7a 100644 +--- js/xpconnect/wrappers/AccessCheck.h ++++ js/xpconnect/wrappers/AccessCheck.h +@@ -104,10 +104,15 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy { + } + }; + +-// This policy only permits access to properties if they appear in the +-// objects exposed properties list. ++// This class used to support permitting access to properties if they ++// appeared in an access list on the object, but now it acts like an ++// Opaque wrapper, with the exception that it fails silently for GET, ++// ENUMERATE, and GET_PROPERTY_DESCRIPTOR. This is done for backwards ++// compatibility. See bug 1397513. + struct ExposedPropertiesOnly : public Policy { +- static bool check(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, js::Wrapper::Action act); ++ static bool check(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, js::Wrapper::Action act) { ++ return false; ++ } + + static bool deny(JSContext* cx, js::Wrapper::Action act, JS::HandleId id, + bool mayThrow); +diff --git js/xpconnect/wrappers/ChromeObjectWrapper.h js/xpconnect/wrappers/ChromeObjectWrapper.h +index 8b273e470814..c17feed10b9a 100644 +--- js/xpconnect/wrappers/ChromeObjectWrapper.h ++++ js/xpconnect/wrappers/ChromeObjectWrapper.h +@@ -16,9 +16,9 @@ namespace xpc { + struct ExposedPropertiesOnly; + + // When a vanilla chrome JS object is exposed to content, we use a wrapper that +-// supports __exposedProps__ for legacy reasons. For extra security, we override +-// the traps that allow content to pass an object to chrome, and perform extra +-// security checks on them. ++// fails silently on GET, ENUMERATE, and GET_PROPERTY_DESCRIPTOR for legacy ++// reasons. For extra security, we override the traps that allow content to pass ++// an object to chrome, and perform extra security checks on them. + #define ChromeObjectWrapperBase \ + FilteringWrapper<js::CrossCompartmentSecurityWrapper, ExposedPropertiesOnly> + +diff --git js/xpconnect/wrappers/WrapperFactory.cpp js/xpconnect/wrappers/WrapperFactory.cpp +index 6296f69fbea4..760d2c9afda8 100644 +--- js/xpconnect/wrappers/WrapperFactory.cpp ++++ js/xpconnect/wrappers/WrapperFactory.cpp +@@ -514,8 +514,8 @@ WrapperFactory::Rewrap(JSContext* cx, HandleObject existing, HandleObject obj) + wrapper = &FilteringWrapper<CrossCompartmentSecurityWrapper, OpaqueWithCall>::singleton; + } + +- // For Vanilla JSObjects exposed from chrome to content, we use a wrapper +- // that supports __exposedProps__. We'd like to get rid of these eventually, ++ // For vanilla JSObjects exposed from chrome to content, we use a wrapper ++ // that fails silently in a few cases. We'd like to get rid of this eventually, + // but in their current form they don't cause much trouble. + else if (IdentifyStandardInstance(obj) == JSProto_Object) { + wrapper = &ChromeObjectWrapper::singleton; +diff --git js/xpconnect/wrappers/XrayWrapper.cpp js/xpconnect/wrappers/XrayWrapper.cpp +index 44dd7cb47146..28e29ea13d93 100644 +--- js/xpconnect/wrappers/XrayWrapper.cpp ++++ js/xpconnect/wrappers/XrayWrapper.cpp +@@ -291,7 +291,7 @@ ReportWrapperDenial(JSContext* cx, HandleId id, WrapperDenialType type, const ch + MOZ_ASSERT(type == WrapperDenialForCOW); + errorMessage.emplace("Security wrapper denied access to property %s on privileged " + "Javascript object. Support for exposing privileged objects " +- "to untrusted content via __exposedProps__ is being gradually " ++ "to untrusted content via __exposedProps__ has been " + "removed - use WebIDL bindings or Components.utils.cloneInto " + "instead. Note that only the first denied property access from a " + "given global object will be reported.", +diff --git testing/mochitest/tests/SimpleTest/ChromePowers.js testing/mochitest/tests/SimpleTest/ChromePowers.js +index 97de578157c0..7fbf66e2fd00 100644 +--- testing/mochitest/tests/SimpleTest/ChromePowers.js ++++ testing/mochitest/tests/SimpleTest/ChromePowers.js +@@ -104,15 +104,6 @@ ChromePowers.prototype.executeAfterFlushingMessageQueue = function(aCallback) { + aCallback(); + }; + +-// Expose everything but internal APIs (starting with underscores) to +-// web content. We cannot use Object.keys to view SpecialPowers.prototype since +-// we are using the functions from SpecialPowersAPI.prototype +-ChromePowers.prototype.__exposedProps__ = {}; +-for (var i in ChromePowers.prototype) { +- if (i.charAt(0) != "_") +- ChromePowers.prototype.__exposedProps__[i] = "r"; +-} +- + if ((window.parent !== null) && + (window.parent !== undefined) && + (window.parent.wrappedJSObject.SpecialPowers) && +diff --git testing/specialpowers/content/MockPermissionPrompt.jsm testing/specialpowers/content/MockPermissionPrompt.jsm +index 71d0f5d2768a..1d86cc00e360 100644 +--- testing/specialpowers/content/MockPermissionPrompt.jsm ++++ testing/specialpowers/content/MockPermissionPrompt.jsm +@@ -83,15 +83,3 @@ MockPermissionPromptInstance.prototype = { + request.allow(); + } + }; +- +-// Expose everything to content. We call reset() here so that all of the relevant +-// lazy expandos get added. +-MockPermissionPrompt.reset(); +-function exposeAll(obj) { +- var props = {}; +- for (var prop in obj) +- props[prop] = "rw"; +- obj.__exposedProps__ = props; +-} +-exposeAll(MockPermissionPrompt); +-exposeAll(MockPermissionPromptInstance.prototype); +diff --git toolkit/components/addoncompat/RemoteAddonsParent.jsm toolkit/components/addoncompat/RemoteAddonsParent.jsm +index 1adbc0397729..d640c47d31f8 100644 +--- toolkit/components/addoncompat/RemoteAddonsParent.jsm ++++ toolkit/components/addoncompat/RemoteAddonsParent.jsm +@@ -735,7 +735,7 @@ var SandboxParent = { + if (rest.length) { + // Do a shallow copy of the options object into the child + // process. This way we don't have to access it through a Chrome +- // object wrapper, which would require __exposedProps__. ++ // object wrapper, which would not let us access any properties. + // + // The only object property here is sandboxPrototype. We assume + // it's a child process object (since that's what Greasemonkey +commit f89c72edb79e +Author: Andrew McCreight <continuation@gmail.com> +Date: Thu Sep 7 11:17:16 2017 -0700 + + Bug 1377587, part 2 - Rename ExposedPropertiesOnly to OpaqueWithSilentFailing. r=krizsa + + This class doesn't have anything to do with __exposedProps__ any more, + so give it a more descriptive name. We'd still like to remove it + entirely eventually. + + MozReview-Commit-ID: 87KCpG6f8rI + + --HG-- + extra : rebase_source : 98a51a6af0fc8446dbcd8efa083d6c79286279d3 +--- + js/xpconnect/wrappers/AccessCheck.cpp | 4 ++-- + js/xpconnect/wrappers/AccessCheck.h | 2 +- + js/xpconnect/wrappers/ChromeObjectWrapper.h | 4 ++-- + 3 files changed, 5 insertions(+), 5 deletions(-) + +diff --git js/xpconnect/wrappers/AccessCheck.cpp js/xpconnect/wrappers/AccessCheck.cpp +index b730310731e2..620f1f678f51 100644 +--- js/xpconnect/wrappers/AccessCheck.cpp ++++ js/xpconnect/wrappers/AccessCheck.cpp +@@ -310,8 +310,8 @@ AccessCheck::reportCrossOriginDenial(JSContext* cx, JS::HandleId id, + } + + bool +-ExposedPropertiesOnly::deny(JSContext* cx, js::Wrapper::Action act, HandleId id, +- bool mayThrow) ++OpaqueWithSilentFailing::deny(JSContext* cx, js::Wrapper::Action act, HandleId id, ++ bool mayThrow) + { + // Fail silently for GET, ENUMERATE, and GET_PROPERTY_DESCRIPTOR. + if (act == js::Wrapper::GET || act == js::Wrapper::ENUMERATE || +diff --git js/xpconnect/wrappers/AccessCheck.h js/xpconnect/wrappers/AccessCheck.h +index c4873760ab7a..6783258f8d94 100644 +--- js/xpconnect/wrappers/AccessCheck.h ++++ js/xpconnect/wrappers/AccessCheck.h +@@ -109,7 +109,7 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy { + // Opaque wrapper, with the exception that it fails silently for GET, + // ENUMERATE, and GET_PROPERTY_DESCRIPTOR. This is done for backwards + // compatibility. See bug 1397513. +-struct ExposedPropertiesOnly : public Policy { ++struct OpaqueWithSilentFailing : public Policy { + static bool check(JSContext* cx, JS::HandleObject wrapper, JS::HandleId id, js::Wrapper::Action act) { + return false; + } +diff --git js/xpconnect/wrappers/ChromeObjectWrapper.h js/xpconnect/wrappers/ChromeObjectWrapper.h +index c17feed10b9a..da4870237501 100644 +--- js/xpconnect/wrappers/ChromeObjectWrapper.h ++++ js/xpconnect/wrappers/ChromeObjectWrapper.h +@@ -13,14 +13,14 @@ + + namespace xpc { + +-struct ExposedPropertiesOnly; ++struct OpaqueWithSilentFailing; + + // When a vanilla chrome JS object is exposed to content, we use a wrapper that + // fails silently on GET, ENUMERATE, and GET_PROPERTY_DESCRIPTOR for legacy + // reasons. For extra security, we override the traps that allow content to pass + // an object to chrome, and perform extra security checks on them. + #define ChromeObjectWrapperBase \ +- FilteringWrapper<js::CrossCompartmentSecurityWrapper, ExposedPropertiesOnly> ++ FilteringWrapper<js::CrossCompartmentSecurityWrapper, OpaqueWithSilentFailing> + + class ChromeObjectWrapper : public ChromeObjectWrapperBase + { + diff --git a/www/waterfox/files/patch-bug1379148 b/www/waterfox/files/patch-bug1379148 new file mode 100644 index 000000000000..e7b01c6eee83 --- /dev/null +++ b/www/waterfox/files/patch-bug1379148 @@ -0,0 +1,366 @@ +commit 708a5eba5908 +Author: Kris Maglione <maglione.k@gmail.com> +Date: Wed Sep 20 16:12:27 2017 -0700 + + Bug 1379148 - Part 1: Allow blocking only non-script-created parsers. r=hsivonen, a=sledru + + MozReview-Commit-ID: 8cGxywiUzWj + + --HG-- + extra : source : bee57767629862c4b4bfa6258918551ed7d82998 +--- + dom/base/nsDocument.cpp | 10 ++++++---- + dom/base/nsIDocument.h | 1 + + dom/webidl/Document.webidl | 11 ++++++++++- + 3 files changed, 17 insertions(+), 5 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 086b386d35f0..d7d1428966f1 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -10919,11 +10919,12 @@ public: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(UnblockParsingPromiseHandler) + +- explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise) ++ explicit UnblockParsingPromiseHandler(nsIDocument* aDocument, Promise* aPromise, ++ const BlockParsingOptions& aOptions) + : mPromise(aPromise) + { + nsCOMPtr<nsIParser> parser = aDocument->CreatorParserOrNull(); +- if (parser) { ++ if (parser && (aOptions.mBlockScriptCreated || !parser->IsScriptCreated())) { + parser->BlockParser(); + mParser = do_GetWeakReference(parser); + mDocument = aDocument; +@@ -10986,14 +10987,15 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(UnblockParsingPromiseHandler) + NS_IMPL_CYCLE_COLLECTING_RELEASE(UnblockParsingPromiseHandler) + + already_AddRefed<Promise> +-nsIDocument::BlockParsing(Promise& aPromise, ErrorResult& aRv) ++nsIDocument::BlockParsing(Promise& aPromise, const BlockParsingOptions& aOptions, ErrorResult& aRv) + { + RefPtr<Promise> resultPromise = Promise::Create(aPromise.GetParentObject(), aRv); + if (aRv.Failed()) { + return nullptr; + } + +- RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise); ++ RefPtr<PromiseNativeHandler> promiseHandler = new UnblockParsingPromiseHandler(this, resultPromise, ++ aOptions); + aPromise.AppendNativeHandler(promiseHandler); + + return resultPromise.forget(); +diff --git dom/base/nsIDocument.h dom/base/nsIDocument.h +index 2f287ae2ccb7..512de896fddf 100644 +--- dom/base/nsIDocument.h ++++ dom/base/nsIDocument.h +@@ -2952,6 +2952,7 @@ public: + void ObsoleteSheet(const nsAString& aSheetURI, mozilla::ErrorResult& rv); + + already_AddRefed<mozilla::dom::Promise> BlockParsing(mozilla::dom::Promise& aPromise, ++ const mozilla::dom::BlockParsingOptions& aOptions, + mozilla::ErrorResult& aRv); + + already_AddRefed<nsIURI> GetMozDocumentURIIfNotForErrorPages(); +diff --git dom/webidl/Document.webidl dom/webidl/Document.webidl +index 8a629502a6ce..f83874fa7315 100644 +--- dom/webidl/Document.webidl ++++ dom/webidl/Document.webidl +@@ -385,13 +385,22 @@ partial interface Document { + + // Blocks the initial document parser until the given promise is settled. + [ChromeOnly, Throws] +- Promise<any> blockParsing(Promise<any> promise); ++ Promise<any> blockParsing(Promise<any> promise, ++ optional BlockParsingOptions options); + + // like documentURI, except that for error pages, it returns the URI we were + // trying to load when we hit an error, rather than the error page's own URI. + [ChromeOnly] readonly attribute URI? mozDocumentURIIfNotForErrorPages; + }; + ++dictionary BlockParsingOptions { ++ /** ++ * If true, blocks script-created parsers (created via document.open()) in ++ * addition to network-created parsers. ++ */ ++ boolean blockScriptCreated = true; ++}; ++ + // Extension to give chrome JS the ability to determine when a document was + // created to satisfy an iframe with srcdoc attribute. + partial interface Document { + +commit 0947c7c07361 +Author: Kris Maglione <maglione.k@gmail.com> +Date: Wed Sep 20 16:13:03 2017 -0700 + + Bug 1379148 - Part 2: Don't block script-created parsers when executing content scripts. r=mixedpuppy, a=sledru + + MozReview-Commit-ID: GsqsaOVob4B + + --HG-- + extra : source : ba22a83959a06a457c8a22d0cd9521eaed220bac +--- + toolkit/components/extensions/ExtensionContent.jsm | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git toolkit/components/extensions/ExtensionContent.jsm toolkit/components/extensions/ExtensionContent.jsm +index 3429ae14daff..c05a00e95398 100644 +--- toolkit/components/extensions/ExtensionContent.jsm ++++ toolkit/components/extensions/ExtensionContent.jsm +@@ -324,7 +324,7 @@ class Script { + // until the scripts have been loaded. + let {document} = context.contentWindow; + if (this.runAt === "document_start" && document.readyState !== "complete") { +- document.blockParsing(scriptsPromise); ++ document.blockParsing(scriptsPromise, {blockScriptCreated: false}); + } + + let scripts = await scriptsPromise; + +commit 5f856a2ba599 +Author: Kris Maglione <maglione.k@gmail.com> +Date: Wed Sep 20 17:00:44 2017 -0700 + + Bug 1379148 - Part 3: Inject scripts synchronously if they're already available. r=mixedpuppy, a=sledru + + MozReview-Commit-ID: J6vheuxsqJR + + --HG-- + extra : source : 14ab0648ea9194b7ad84ecf7a330c9bbdadfb303 +--- + toolkit/components/extensions/ExtensionContent.jsm | 36 ++++++++++++++++------ + toolkit/components/extensions/ExtensionUtils.jsm | 12 +++++--- + 2 files changed, 34 insertions(+), 14 deletions(-) + +diff --git toolkit/components/extensions/ExtensionContent.jsm toolkit/components/extensions/ExtensionContent.jsm +index c05a00e95398..9af6870a829b 100644 +--- toolkit/components/extensions/ExtensionContent.jsm ++++ toolkit/components/extensions/ExtensionContent.jsm +@@ -137,8 +137,16 @@ class CacheMap extends DefaultMap { + + class ScriptCache extends CacheMap { + constructor(options) { +- super(SCRIPT_EXPIRY_TIMEOUT_MS, +- url => ChromeUtils.compileScript(url, options)); ++ super(SCRIPT_EXPIRY_TIMEOUT_MS); ++ this.options = options; ++ } ++ ++ defaultConstructor(url) { ++ let promise = ChromeUtils.compileScript(url, this.options); ++ promise.then(script => { ++ promise.script = script; ++ }); ++ return promise; + } + } + +@@ -317,17 +325,25 @@ class Script { + } + } + +- let scriptsPromise = Promise.all(this.compileScripts()); ++ let scriptPromises = this.compileScripts(); ++ ++ let scripts = scriptPromises.map(promise => promise.script); ++ // If not all scripts are already available in the cache, block ++ // parsing and wait all promises to resolve. ++ if (!scripts.every(script => script)) { ++ let promise = Promise.all(scriptPromises); ++ ++ // If we're supposed to inject at the start of the document load, ++ // and we haven't already missed that point, block further parsing ++ // until the scripts have been loaded. ++ let {document} = context.contentWindow; ++ if (this.runAt === "document_start" && document.readyState !== "complete") { ++ document.blockParsing(promise, {blockScriptCreated: false}); ++ } + +- // If we're supposed to inject at the start of the document load, +- // and we haven't already missed that point, block further parsing +- // until the scripts have been loaded. +- let {document} = context.contentWindow; +- if (this.runAt === "document_start" && document.readyState !== "complete") { +- document.blockParsing(scriptsPromise, {blockScriptCreated: false}); ++ scripts = await promise; + } + +- let scripts = await scriptsPromise; + let result; + + // The evaluations below may throw, in which case the promise will be +diff --git toolkit/components/extensions/ExtensionUtils.jsm toolkit/components/extensions/ExtensionUtils.jsm +index a3ed895de6df..4a5fcb19c58d 100644 +--- toolkit/components/extensions/ExtensionUtils.jsm ++++ toolkit/components/extensions/ExtensionUtils.jsm +@@ -67,9 +67,11 @@ function instanceOf(value, type) { + * constructor if one is not present. + */ + class DefaultWeakMap extends WeakMap { +- constructor(defaultConstructor, init) { ++ constructor(defaultConstructor = undefined, init = undefined) { + super(init); +- this.defaultConstructor = defaultConstructor; ++ if (defaultConstructor) { ++ this.defaultConstructor = defaultConstructor; ++ } + } + + get(key) { +@@ -83,9 +85,11 @@ class DefaultWeakMap extends WeakMap { + } + + class DefaultMap extends Map { +- constructor(defaultConstructor, init) { ++ constructor(defaultConstructor = undefined, init = undefined) { + super(init); +- this.defaultConstructor = defaultConstructor; ++ if (defaultConstructor) { ++ this.defaultConstructor = defaultConstructor; ++ } + } + + get(key) { + +commit 3ab96ab42d99 +Author: Kris Maglione <maglione.k@gmail.com> +Date: Wed Sep 20 17:01:33 2017 -0700 + + Bug 1379148 - Part 4: Add tests for document.write() with document_start content script present. r=mixedpuppy, a=sledru + + MozReview-Commit-ID: 5yxgpur1tvf + + --HG-- + extra : source : 14298b92236cfcfdd0b9dc43d8077e576f775b4d +--- + .../extensions/ExtensionXPCShellUtils.jsm | 5 +++ + .../test/xpcshell/data/file_document_write.html | 35 ++++++++++++++++ + .../test_ext_contentscript_scriptCreated.js | 49 ++++++++++++++++++++++ + .../extensions/test/xpcshell/xpcshell-content.ini | 1 + + 4 files changed, 90 insertions(+) + +diff --git toolkit/components/extensions/ExtensionXPCShellUtils.jsm toolkit/components/extensions/ExtensionXPCShellUtils.jsm +index d16003d79944..3420ce175d8a 100644 +--- toolkit/components/extensions/ExtensionXPCShellUtils.jsm ++++ toolkit/components/extensions/ExtensionXPCShellUtils.jsm +@@ -59,6 +59,11 @@ function frameScript() { + Components.utils.import("resource://gre/modules/Services.jsm"); + + Services.obs.notifyObservers(this, "tab-content-frameloader-created"); ++ ++ // eslint-disable-next-line mozilla/balanced-listeners ++ addEventListener("MozHeapMinimize", () => { ++ Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize"); ++ }, true, true); + } + + const FRAME_SCRIPT = `data:text/javascript,(${encodeURI(frameScript)}).call(this)`; +diff --git toolkit/components/extensions/test/xpcshell/data/file_document_write.html toolkit/components/extensions/test/xpcshell/data/file_document_write.html +new file mode 100644 +index 000000000000..fbae3d6d763a +--- /dev/null ++++ toolkit/components/extensions/test/xpcshell/data/file_document_write.html +@@ -0,0 +1,35 @@ ++<!DOCTYPE HTML> ++<html> ++<head> ++<meta charset="utf-8"> ++</head> ++<body> ++ <iframe id="iframe"></iframe> ++ ++ <script type="text/javascript"> ++ "use strict"; ++ addEventListener("load", () => { ++ // Send a heap-minimize observer notification so our script cache is ++ // cleared, and our content script isn't available for synchronous ++ // insertion. ++ window.dispatchEvent(new CustomEvent("MozHeapMinimize")); ++ ++ let iframe = document.getElementById("iframe"); ++ let doc = iframe.contentDocument; ++ doc.open("text/html"); ++ // We need to do two writes here. The first creates the document element, ++ // which normally triggers parser blocking. The second triggers the ++ // creation of the element we're about to query for, which would normally ++ // happen asynchronously if the parser were blocked. ++ doc.write("<div id=meh>"); ++ doc.write("<div id=beer></div>"); ++ ++ let elem = doc.getElementById("beer"); ++ top.postMessage(elem instanceof HTMLDivElement ? "ok" : "fail", ++ "*"); ++ ++ doc.close(); ++ }, {once: true}); ++ </script> ++</body> ++</html> +diff --git toolkit/components/extensions/test/xpcshell/test_ext_contentscript_scriptCreated.js toolkit/components/extensions/test/xpcshell/test_ext_contentscript_scriptCreated.js +new file mode 100644 +index 000000000000..00407b914015 +--- /dev/null ++++ toolkit/components/extensions/test/xpcshell/test_ext_contentscript_scriptCreated.js +@@ -0,0 +1,49 @@ ++"use strict"; ++ ++const server = createHttpServer(); ++server.registerDirectory("/data/", do_get_file("data")); ++ ++const BASE_URL = `http://localhost:${server.identity.primaryPort}/data`; ++ ++// ExtensionContent.jsm needs to know when it's running from xpcshell, ++// to use the right timeout for content scripts executed at document_idle. ++ExtensionTestUtils.mockAppInfo(); ++ ++// Test that document_start content scripts don't block script-created ++// parsers. ++add_task(async function test_contentscript_scriptCreated() { ++ let extensionData = { ++ manifest: { ++ content_scripts: [{ ++ "matches": ["http://*/*/file_document_write.html"], ++ "js": ["content_script.js"], ++ "run_at": "document_start", ++ "match_about_blank": true, ++ "all_frames": true, ++ }], ++ }, ++ ++ files: { ++ "content_script.js": function() { ++ if (window === top) { ++ addEventListener("message", msg => { ++ browser.test.assertEq("ok", msg.data, "document.write() succeeded"); ++ browser.test.sendMessage("content-script-done"); ++ }, {once: true}); ++ } ++ }, ++ }, ++ }; ++ ++ let extension = ExtensionTestUtils.loadExtension(extensionData); ++ ++ await extension.startup(); ++ ++ let contentPage = await ExtensionTestUtils.loadContentPage(`${BASE_URL}/file_document_write.html`); ++ ++ await extension.awaitMessage("content-script-done"); ++ ++ await contentPage.close(); ++ ++ await extension.unload(); ++}); +diff --git toolkit/components/extensions/test/xpcshell/xpcshell-content.ini toolkit/components/extensions/test/xpcshell/xpcshell-content.ini +index e34ec0717691..65814ff5da97 100644 +--- toolkit/components/extensions/test/xpcshell/xpcshell-content.ini ++++ toolkit/components/extensions/test/xpcshell/xpcshell-content.ini +@@ -2,4 +2,5 @@ + skip-if = os == "android" || (os == "win" && debug) + [test_ext_i18n_css.js] + [test_ext_contentscript.js] ++[test_ext_contentscript_scriptCreated.js] + [test_ext_contentscript_xrays.js] diff --git a/www/waterfox/files/patch-bug1381761 b/www/waterfox/files/patch-bug1381761 new file mode 100644 index 000000000000..416bd4ac8c26 --- /dev/null +++ b/www/waterfox/files/patch-bug1381761 @@ -0,0 +1,362 @@ +commit 256e249566d8 +Author: Christoph Kerschbaumer <ckerschb@christophkerschbaumer.com> +Date: Fri Aug 4 14:11:17 2017 +0200 + + Bug 1381761 - Treating 'data:' documents as unique, opaque origins should still inherit the CSP. r=smaug,dveditz +--- + caps/moz.build | 1 + + caps/nsScriptSecurityManager.cpp | 96 +++++++++++++++++++++++++--------------- + 2 files changed, 62 insertions(+), 35 deletions(-) + +diff --git caps/moz.build caps/moz.build +index 46331e93f097..af369e3268e0 100644 +--- caps/moz.build ++++ caps/moz.build +@@ -56,6 +56,7 @@ LOCAL_INCLUDES += [ + '/docshell/base', + '/dom/base', + '/js/xpconnect/src', ++ '/netwerk/base', + ] + + if CONFIG['ENABLE_TESTS']: +diff --git caps/nsScriptSecurityManager.cpp caps/nsScriptSecurityManager.cpp +index a930b324a6a2..90695ebd126f 100644 +--- caps/nsScriptSecurityManager.cpp ++++ caps/nsScriptSecurityManager.cpp +@@ -45,6 +45,7 @@ + #include "nsIWindowWatcher.h" + #include "nsIConsoleService.h" + #include "nsIObserverService.h" ++#include "nsIOService.h" + #include "nsIContent.h" + #include "nsDOMJSUtils.h" + #include "nsAboutProtocolUtils.h" +@@ -265,6 +266,61 @@ nsScriptSecurityManager::GetChannelResultPrincipalIfNotSandboxed(nsIChannel* aCh + /*aIgnoreSandboxing*/ true); + } + ++static void ++InheritAndSetCSPOnPrincipalIfNeeded(nsIChannel* aChannel, nsIPrincipal* aPrincipal) ++{ ++ // loading a data: URI into an iframe, or loading frame[srcdoc] need ++ // to inherit the CSP (see Bug 1073952, 1381761). ++ MOZ_ASSERT(aChannel && aPrincipal, "need a valid channel and principal"); ++ if (!aChannel) { ++ return; ++ } ++ ++ nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); ++ if (!loadInfo || ++ loadInfo->GetExternalContentPolicyType() != nsIContentPolicy::TYPE_SUBDOCUMENT) { ++ return; ++ } ++ ++ nsCOMPtr<nsIURI> uri; ++ nsresult rv = aChannel->GetURI(getter_AddRefs(uri)); ++ NS_ENSURE_SUCCESS_VOID(rv); ++ nsAutoCString URISpec; ++ rv = uri->GetSpec(URISpec); ++ NS_ENSURE_SUCCESS_VOID(rv); ++ ++ bool isSrcDoc = URISpec.EqualsLiteral("about:srcdoc"); ++ bool isData = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData); ++ ++ if (!isSrcDoc && !isData) { ++ return; ++ } ++ ++ nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit(); ++ if (!principalToInherit) { ++ principalToInherit = loadInfo->TriggeringPrincipal(); ++ } ++ nsCOMPtr<nsIContentSecurityPolicy> originalCSP; ++ principalToInherit->GetCsp(getter_AddRefs(originalCSP)); ++ if (!originalCSP) { ++ return; ++ } ++ ++ // if the principalToInherit had a CSP, add it to the before ++ // created NullPrincipal (unless it already has one) ++ MOZ_ASSERT(aPrincipal->GetIsNullPrincipal(), ++ "inheriting the CSP only valid for NullPrincipal"); ++ nsCOMPtr<nsIContentSecurityPolicy> nullPrincipalCSP; ++ aPrincipal->GetCsp(getter_AddRefs(nullPrincipalCSP)); ++ if (nullPrincipalCSP) { ++ MOZ_ASSERT(nullPrincipalCSP == originalCSP, ++ "There should be no other CSP here."); ++ // CSPs are equal, no need to set it again. ++ return; ++ } ++ aPrincipal->SetCsp(originalCSP); ++} ++ + nsresult + nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel, + nsIPrincipal** aPrincipal, +@@ -295,40 +351,7 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel, + if (!aIgnoreSandboxing && loadInfo->GetLoadingSandboxed()) { + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(loadInfo->GetSandboxedLoadingPrincipal(aPrincipal))); + MOZ_ASSERT(*aPrincipal); +- // if the new NullPrincipal (above) loads an iframe[srcdoc], we +- // need to inherit an existing CSP to avoid bypasses (bug 1073952). +- // We continue inheriting for nested frames with e.g., data: URLs. +- if (loadInfo->GetExternalContentPolicyType() == nsIContentPolicy::TYPE_SUBDOCUMENT) { +- nsCOMPtr<nsIURI> uri; +- aChannel->GetURI(getter_AddRefs(uri)); +- nsAutoCString URISpec; +- uri->GetSpec(URISpec); +- bool isData = (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData); +- if (URISpec.EqualsLiteral("about:srcdoc") || isData) { +- nsCOMPtr<nsIPrincipal> principalToInherit = loadInfo->PrincipalToInherit(); +- if (!principalToInherit) { +- principalToInherit = loadInfo->TriggeringPrincipal(); +- } +- nsCOMPtr<nsIContentSecurityPolicy> originalCSP; +- principalToInherit->GetCsp(getter_AddRefs(originalCSP)); +- if (originalCSP) { +- // if the principalToInherit had a CSP, +- // add it to the newly created NullPrincipal +- // (unless it already has one) +- nsCOMPtr<nsIContentSecurityPolicy> nullPrincipalCSP; +- (*aPrincipal)->GetCsp(getter_AddRefs(nullPrincipalCSP)); +- if (nullPrincipalCSP) { +- MOZ_ASSERT(nullPrincipalCSP == originalCSP, +- "There should be no other CSP here."); +- // CSPs are equal, no need to set it again. +- return NS_OK; +- } else { +- nsresult rv = (*aPrincipal)->SetCsp(originalCSP); +- NS_ENSURE_SUCCESS(rv, rv); +- } +- } +- } +- } ++ InheritAndSetCSPOnPrincipalIfNeeded(aChannel, *aPrincipal); + return NS_OK; + } + +@@ -376,7 +399,10 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel, + } + } + } +- return GetChannelURIPrincipal(aChannel, aPrincipal); ++ nsresult rv = GetChannelURIPrincipal(aChannel, aPrincipal); ++ NS_ENSURE_SUCCESS(rv, rv); ++ InheritAndSetCSPOnPrincipalIfNeeded(aChannel, *aPrincipal); ++ return NS_OK; + } + + /* The principal of the URI that this channel is loading. This is never + +commit 9427f1bbd826 +Author: Christoph Kerschbaumer <ckerschb@christophkerschbaumer.com> +Date: Fri Aug 4 14:10:21 2017 +0200 + + Bug 1381761 - Convert test browser_911547.js to comply with new data: URI inheritance model. r=dveditz +--- + .../components/sessionstore/test/browser_911547.js | 47 ++++++++++++++++------ + .../sessionstore/test/browser_911547_sample.html | 6 +-- + 2 files changed, 37 insertions(+), 16 deletions(-) + +diff --git browser/components/sessionstore/test/browser_911547.js browser/components/sessionstore/test/browser_911547.js +index f0da70ed8f8c..cb95ddad7f2a 100644 +--- browser/components/sessionstore/test/browser_911547.js ++++ browser/components/sessionstore/test/browser_911547.js +@@ -1,11 +1,17 @@ + /* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +-// This tests that session restore component does restore the right content +-// security policy with the document. +-// The policy being tested disallows inline scripts ++// This test is two fold: ++// a) if security.data_uri.unique_opaque_origin == false, then ++// this tests that session restore component does restore the right ++// content security policy with the document. (The policy being ++// tested disallows inline scripts). ++// b) if security.data_uri.unique_opaque_origin == true, then ++// this tests that data: URIs do not inherit the CSP from ++// it's enclosing context. + + add_task(async function test() { ++ let dataURIPref = Services.prefs.getBoolPref("security.data_uri.unique_opaque_origin"); + // create a tab that has a CSP + let testURL = "http://mochi.test:8888/browser/browser/components/sessionstore/test/browser_911547_sample.html"; + let tab = gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, testURL); +@@ -16,23 +22,33 @@ add_task(async function test() { + + // this is a baseline to ensure CSP is active + // attempt to inject and run a script via inline (pre-restore, allowed) +- await injectInlineScript(browser, `document.getElementById("test_id").value = "fail";`); ++ await injectInlineScript(browser, `document.getElementById("test_id1").value = "id1_modified";`); + + let loadedPromise = promiseBrowserLoaded(browser); + await ContentTask.spawn(browser, null, function() { +- is(content.document.getElementById("test_id").value, "ok", ++ is(content.document.getElementById("test_id1").value, "id1_initial", + "CSP should block the inline script that modifies test_id"); + +- // attempt to click a link to a data: URI (will inherit the CSP of the +- // origin document) and navigate to the data URI in the link. ++ ++ // (a) if security.data_uri.unique_opaque_origin == false: ++ // attempt to click a link to a data: URI (will inherit the CSP of ++ // the origin document) and navigate to the data URI in the link. ++ // (b) if security.data_uri.unique_opaque_origin == true: ++ // attempt to click a link to a data: URI (will *not* inherit the CSP of ++ // the origin document) and navigate to the data URI in the link. + content.document.getElementById("test_data_link").click(); + }); + + await loadedPromise; + +- await ContentTask.spawn(browser, null, function() { +- is(content.document.getElementById("test_id2").value, "ok", +- "CSP should block the script loaded by the clicked data URI"); ++ await ContentTask.spawn(browser, {dataURIPref}, function( {dataURIPref}) { // eslint-disable-line ++ if (dataURIPref) { ++ is(content.document.getElementById("test_id2").value, "id2_modified", ++ "data: URI should *not* inherit the CSP of the enclosing context"); ++ } else { ++ is(content.document.getElementById("test_id2").value, "id2_initial", ++ "CSP should block the script loaded by the clicked data URI"); ++ } + }); + + // close the tab +@@ -43,9 +59,14 @@ add_task(async function test() { + await promiseTabRestored(tab); + browser = tab.linkedBrowser; + +- await ContentTask.spawn(browser, null, function() { +- is(content.document.getElementById("test_id2").value, "ok", +- "CSP should block the script loaded by the clicked data URI after restore"); ++ await ContentTask.spawn(browser, {dataURIPref}, function({dataURIPref}) { // eslint-disable-line ++ if (dataURIPref) { ++ is(content.document.getElementById("test_id2").value, "id2_modified", ++ "data: URI should *not* inherit the CSP of the enclosing context"); ++ } else { ++ is(content.document.getElementById("test_id2").value, "id2_initial", ++ "CSP should block the script loaded by the clicked data URI after restore"); ++ } + }); + + // clean up +diff --git browser/components/sessionstore/test/browser_911547_sample.html browser/components/sessionstore/test/browser_911547_sample.html +index ccc2011593d4..73cb99ee41f1 100644 +--- browser/components/sessionstore/test/browser_911547_sample.html ++++ browser/components/sessionstore/test/browser_911547_sample.html +@@ -8,12 +8,12 @@ + + <!-- + this element gets modified by an injected script; +- that script should be blocked by CSP. ++ that script should be blocked by CSP if security.data_uri.unique_opaque_origin == false; + Inline scripts can modify it, but not data uris. + --> +- <input type="text" id="test_id" value="ok"> ++ <input type="text" id="test_id1" value="id1_initial"> + +- <a id="test_data_link" href="data:text/html;charset=utf-8,<input type='text' id='test_id2' value='ok'/> <script>document.getElementById('test_id2').value = 'fail';</script>">Test Link</a> ++ <a id="test_data_link" href="data:text/html;charset=utf-8,<input type='text' id='test_id2' value='id2_initial'/> <script>document.getElementById('test_id2').value = 'id2_modified';</script>">Test Link</a> + + </body> + </html> + +commit 8b999864f0bb +Author: Christoph Kerschbaumer <ckerschb@christophkerschbaumer.com> +Date: Fri Aug 4 14:10:38 2017 +0200 + + Bug 1381761 - Test data: URIs inherit the CSP even if treated as unique, opaque origins. r=dveditz +--- + .../test/csp/file_data_csp_inheritance.html | 21 +++++++++++++ + dom/security/test/csp/mochitest.ini | 2 ++ + .../test/csp/test_data_csp_inheritance.html | 34 ++++++++++++++++++++++ + 3 files changed, 57 insertions(+) + +diff --git dom/security/test/csp/file_data_csp_inheritance.html dom/security/test/csp/file_data_csp_inheritance.html +new file mode 100644 +index 000000000000..299c30255aa6 +--- /dev/null ++++ dom/security/test/csp/file_data_csp_inheritance.html +@@ -0,0 +1,21 @@ ++<!DOCTYPE HTML> ++<html> ++<head> ++ <title>Bug 1381761 - Treating 'data:' documents as unique, opaque origins should still inherit the CSP</title> ++ <meta charset="utf-8"> ++ <meta http-equiv="Content-Security-Policy" content= "img-src 'none'"/> ++</head> ++<body> ++<iframe id="dataFrame" src="data:text/html,<body>should inherit csp</body>"></iframe> ++ ++<script type="application/javascript"> ++ // get the csp in JSON notation from the principal ++ var frame = document.getElementById("dataFrame"); ++ var principal = SpecialPowers.wrap(frame.contentDocument).nodePrincipal; ++ var cspJSON = principal.cspJSON; ++ var result = principal.cspJSON ? "dataInheritsCSP" : "dataDoesNotInheritCSP"; ++ window.parent.postMessage({result}, "*"); ++</script> ++ ++</body> ++</html> +diff --git dom/security/test/csp/mochitest.ini dom/security/test/csp/mochitest.ini +index ba391ad59799..09f80b2969d7 100644 +--- dom/security/test/csp/mochitest.ini ++++ dom/security/test/csp/mochitest.ini +@@ -217,6 +217,7 @@ support-files = + file_ignore_xfo.html^headers^ + file_ro_ignore_xfo.html + file_ro_ignore_xfo.html^headers^ ++ file_data_csp_inheritance.html + file_report_font_cache-1.html + file_report_font_cache-2.html + file_report_font_cache-2.html^headers^ +@@ -308,4 +309,5 @@ tags = mcb + [test_websocket_self.html] + skip-if = toolkit == 'android' + [test_ignore_xfo.html] ++[test_data_csp_inheritance.html] + [test_data_csp_merge.html] +diff --git dom/security/test/csp/test_data_csp_inheritance.html dom/security/test/csp/test_data_csp_inheritance.html +new file mode 100644 +index 000000000000..3afc4f7c02bc +--- /dev/null ++++ dom/security/test/csp/test_data_csp_inheritance.html +@@ -0,0 +1,34 @@ ++<!DOCTYPE HTML> ++<html> ++<head> ++ <title>Bug 1381761 - Treating 'data:' documents as unique, opaque origins should still inherit the CSP</title> ++ <!-- Including SimpleTest.js so we can use waitForExplicitFinish !--> ++ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> ++ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> ++</head> ++<body> ++<iframe style="width:100%;" id="testframe"></iframe> ++ ++<script class="testbody" type="text/javascript"> ++ ++SimpleTest.waitForExplicitFinish(); ++ ++/* Description of the test: ++ * We load an iframe using a meta CSP which includes another iframe ++ * using a data: URI. We make sure the CSP gets inherited into ++ * the data: URI iframe. ++ */ ++ ++window.addEventListener("message", receiveMessage); ++function receiveMessage(event) { ++ window.removeEventListener("message", receiveMessage); ++ is(event.data.result, "dataInheritsCSP", ++ "data: URI iframe inherits CSP from including context"); ++ SimpleTest.finish(); ++} ++ ++document.getElementById("testframe").src = "file_data_csp_inheritance.html"; ++ ++</script> ++</body> ++</html> diff --git a/www/waterfox/files/patch-bug1381815 b/www/waterfox/files/patch-bug1381815 new file mode 100644 index 000000000000..5681303ce451 --- /dev/null +++ b/www/waterfox/files/patch-bug1381815 @@ -0,0 +1,278 @@ +commit 165fab2f8596 +Author: Jan Horak <jhorak@redhat.com> +Date: Tue Oct 10 13:35:56 2017 +0200 + + Bug 1381815 - fixing dimensions of radio and checkbox for GTK 3.20+; r=karlt + + In the GTK < 3.20 the size of radio and checkbox toggle is determined by indicator + spacing and indicator size. By GTK 3.20+ it is replaced by standard box model + (padding, margin, border). The patch fixes that while keeping the functionality + for older GTK. The values are also cached by similar way as scrollbar metrics + are cached now. + + The focus is no longer rendered by GTK but by Mozilla code, so the extra + size for toggles has been removed from GetExtraSizeForWidget and toggles + no longer render focus indicator. + + MozReview-Commit-ID: 1Wg5AgHy1Vz + + --HG-- + extra : rebase_source : 81437f45b7d32555942d21fccc9de4a561d85111 +--- + widget/gtk/gtk3drawing.cpp | 121 ++++++++++++++++++++++++++++++---------- + widget/gtk/gtkdrawing.h | 14 +++++ + widget/gtk/nsNativeThemeGTK.cpp | 32 +---------- + 3 files changed, 107 insertions(+), 60 deletions(-) + +diff --git widget/gtk/gtk3drawing.cpp widget/gtk/gtk3drawing.cpp +index 4c562b380095..7968aef920f6 100644 +--- widget/gtk/gtk3drawing.cpp ++++ widget/gtk/gtk3drawing.cpp +@@ -22,6 +22,8 @@ static gboolean checkbox_check_state; + static gboolean notebook_has_tab_gap; + + static ScrollbarGTKMetrics sScrollbarMetrics[2]; ++static ToggleGTKMetrics sCheckboxMetrics; ++static ToggleGTKMetrics sRadioMetrics; + + #define ARROW_UP 0 + #define ARROW_DOWN G_PI +@@ -110,6 +112,8 @@ moz_gtk_refresh() + + sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; + sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; ++ sCheckboxMetrics.initialized = false; ++ sRadioMetrics.initialized = false; + } + + gint +@@ -308,33 +312,21 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect, + gboolean isradio, GtkTextDirection direction) + { + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); +- gint indicator_size, indicator_spacing; + gint x, y, width, height; +- gint focus_x, focus_y, focus_width, focus_height; + GtkStyleContext *style; + +- GtkWidget *widget = GetWidget(isradio ? MOZ_GTK_RADIOBUTTON_CONTAINER : +- MOZ_GTK_CHECKBUTTON_CONTAINER); +- gtk_widget_style_get(widget, +- "indicator_size", &indicator_size, +- "indicator_spacing", &indicator_spacing, +- nullptr); ++ const ToggleGTKMetrics* metrics = GetToggleMetrics(isradio); + + // XXX we should assert rect->height >= indicator_size too + // after bug 369581 is fixed. +- MOZ_ASSERT(rect->width >= indicator_size, ++ MOZ_ASSERT(rect->width >= metrics->minSizeWithBorder.width, + "GetMinimumWidgetSize was ignored"); + + // Paint it center aligned in the rect. +- x = rect->x + (rect->width - indicator_size) / 2; +- y = rect->y + (rect->height - indicator_size) / 2; +- width = indicator_size; +- height = indicator_size; +- +- focus_x = x - indicator_spacing; +- focus_y = y - indicator_spacing; +- focus_width = width + 2 * indicator_spacing; +- focus_height = height + 2 * indicator_spacing; ++ width = metrics->minSizeWithBorder.width; ++ height = metrics->minSizeWithBorder.height; ++ x = rect->x + (rect->width - width) / 2; ++ y = rect->y + (rect->height - height) / 2; + + if (selected) + state_flags = static_cast<GtkStateFlags>(state_flags|checkbox_check_state); +@@ -348,20 +340,25 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect, + if (gtk_check_version(3, 20, 0) == nullptr) { + gtk_render_background(style, cr, x, y, width, height); + gtk_render_frame(style, cr, x, y, width, height); +- } +- +- if (isradio) { +- gtk_render_option(style, cr, x, y, width, height); +- if (state->focused) { +- gtk_render_focus(style, cr, focus_x, focus_y, +- focus_width, focus_height); ++ // Indicator is inset by the toggle's padding and border. ++ gint indicator_x = x + metrics->borderAndPadding.left; ++ gint indicator_y = y + metrics->borderAndPadding.top; ++ gint indicator_width = metrics->minSizeWithBorder.width - ++ metrics->borderAndPadding.left - metrics->borderAndPadding.right; ++ gint indicator_height = metrics->minSizeWithBorder.height - ++ metrics->borderAndPadding.top - metrics->borderAndPadding.bottom; ++ if (isradio) { ++ gtk_render_option(style, cr, indicator_x, indicator_y, ++ indicator_width, indicator_height); ++ } else { ++ gtk_render_check(style, cr, indicator_x, indicator_y, ++ indicator_width, indicator_height); + } +- } +- else { +- gtk_render_check(style, cr, x, y, width, height); +- if (state->focused) { +- gtk_render_focus(style, cr, +- focus_x, focus_y, focus_width, focus_height); ++ } else { ++ if (isradio) { ++ gtk_render_option(style, cr, x, y, width, height); ++ } else { ++ gtk_render_check(style, cr, x, y, width, height); + } + } + +@@ -2514,6 +2511,68 @@ SizeFromLengthAndBreadth(GtkOrientation aOrientation, + MozGtkSize({aLength, aBreadth}) : MozGtkSize({aBreadth, aLength}); + } + ++const ToggleGTKMetrics* ++GetToggleMetrics(bool isRadio) ++{ ++ ToggleGTKMetrics* metrics; ++ if (isRadio) { ++ metrics = &sRadioMetrics; ++ } else { ++ metrics = &sCheckboxMetrics; ++ } ++ if (metrics->initialized) ++ return metrics; ++ ++ metrics->initialized = true; ++ if (gtk_check_version(3,20,0) == nullptr) { ++ GtkStyleContext* style; ++ if (isRadio) { ++ style = GetStyleContext(MOZ_GTK_RADIOBUTTON); ++ } else { ++ style = GetStyleContext(MOZ_GTK_CHECKBUTTON); ++ } ++ GtkStateFlags state_flags = gtk_style_context_get_state(style); ++ gtk_style_context_get(style, state_flags, ++ "min-height",&(metrics->minSizeWithBorder.height), ++ "min-width", &(metrics->minSizeWithBorder.width), ++ nullptr); ++ // Fallback to indicator size if min dimensions are zero ++ if (metrics->minSizeWithBorder.height == 0 || ++ metrics->minSizeWithBorder.width == 0) { ++ gint indicator_size; ++ gtk_widget_style_get(GetWidget(MOZ_GTK_CHECKBUTTON_CONTAINER), ++ "indicator_size", &indicator_size, nullptr); ++ if (metrics->minSizeWithBorder.height == 0) { ++ metrics->minSizeWithBorder.height = indicator_size; ++ } ++ if (metrics->minSizeWithBorder.width == 0) { ++ metrics->minSizeWithBorder.width = indicator_size; ++ } ++ } ++ ++ GtkBorder border, padding; ++ gtk_style_context_get_border(style, state_flags, &border); ++ gtk_style_context_get_padding(style, state_flags, &padding); ++ metrics->borderAndPadding.left = border.left + padding.left; ++ metrics->borderAndPadding.right = border.right + padding.right; ++ metrics->borderAndPadding.top = border.top + padding.top; ++ metrics->borderAndPadding.bottom = border.bottom + padding.bottom; ++ metrics->minSizeWithBorder.width += metrics->borderAndPadding.left + ++ metrics->borderAndPadding.right; ++ metrics->minSizeWithBorder.height += metrics->borderAndPadding.top + ++ metrics->borderAndPadding.bottom; ++ } else { ++ gint indicator_size, indicator_spacing; ++ gtk_widget_style_get(GetWidget(MOZ_GTK_CHECKBUTTON_CONTAINER), ++ "indicator_size", &indicator_size, ++ "indicator_spacing", &indicator_spacing, ++ nullptr); ++ metrics->minSizeWithBorder.width = ++ metrics->minSizeWithBorder.height = indicator_size; ++ } ++ return metrics; ++} ++ + const ScrollbarGTKMetrics* + GetScrollbarMetrics(GtkOrientation aOrientation) + { +diff --git widget/gtk/gtkdrawing.h widget/gtk/gtkdrawing.h +index 42dbf8287499..909c18f7f525 100644 +--- widget/gtk/gtkdrawing.h ++++ widget/gtk/gtkdrawing.h +@@ -83,6 +83,12 @@ typedef struct { + } border; + } ScrollbarGTKMetrics; + ++typedef struct { ++ bool initialized; ++ MozGtkSize minSizeWithBorder; ++ GtkBorder borderAndPadding; ++} ToggleGTKMetrics; ++ + typedef enum { + MOZ_GTK_STEPPER_DOWN = 1 << 0, + MOZ_GTK_STEPPER_BOTTOM = 1 << 1, +@@ -391,6 +397,14 @@ moz_gtk_get_tab_border(gint* left, gint* top, gint* right, gint* bottom, + gint + moz_gtk_checkbox_get_metrics(gint* indicator_size, gint* indicator_spacing); + ++/** ++ * Get metrics of the toggle (radio or checkbox) ++ * isRadio: [IN] true when requesting metrics for the radio button ++ * returns: pointer to ToggleGTKMetrics struct ++ */ ++const ToggleGTKMetrics* ++GetToggleMetrics(bool isRadio); ++ + /** + * Get the desired size of a GtkRadioButton + * indicator_size: [OUT] the indicator size +diff --git widget/gtk/nsNativeThemeGTK.cpp widget/gtk/nsNativeThemeGTK.cpp +index 06e62efbcda8..da3eaa71a6b4 100644 +--- widget/gtk/nsNativeThemeGTK.cpp ++++ widget/gtk/nsNativeThemeGTK.cpp +@@ -1020,24 +1020,6 @@ nsNativeThemeGTK::GetExtraSizeForWidget(nsIFrame* aFrame, uint8_t aWidgetType, + aExtra->left = aExtra->right = 1; + break; + +- // Include the indicator spacing (the padding around the control). +- case NS_THEME_CHECKBOX: +- case NS_THEME_RADIO: +- { +- gint indicator_size, indicator_spacing; +- +- if (aWidgetType == NS_THEME_CHECKBOX) { +- moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing); +- } else { +- moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing); +- } +- +- aExtra->top = indicator_spacing; +- aExtra->right = indicator_spacing; +- aExtra->bottom = indicator_spacing; +- aExtra->left = indicator_spacing; +- break; +- } + case NS_THEME_BUTTON : + { + if (IsDefaultButton(aFrame)) { +@@ -1595,17 +1577,9 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, + case NS_THEME_CHECKBOX: + case NS_THEME_RADIO: + { +- gint indicator_size, indicator_spacing; +- +- if (aWidgetType == NS_THEME_CHECKBOX) { +- moz_gtk_checkbox_get_metrics(&indicator_size, &indicator_spacing); +- } else { +- moz_gtk_radio_get_metrics(&indicator_size, &indicator_spacing); +- } +- +- // Include space for the indicator and the padding around it. +- aResult->width = indicator_size; +- aResult->height = indicator_size; ++ const ToggleGTKMetrics* metrics = GetToggleMetrics(aWidgetType == NS_THEME_RADIO); ++ aResult->width = metrics->minSizeWithBorder.width; ++ aResult->height = metrics->minSizeWithBorder.height; + } + break; + case NS_THEME_TOOLBARBUTTON_DROPDOWN: diff --git a/www/waterfox/files/patch-bug1382359 b/www/waterfox/files/patch-bug1382359 new file mode 100644 index 000000000000..27cf995ec543 --- /dev/null +++ b/www/waterfox/files/patch-bug1382359 @@ -0,0 +1,138 @@ +commit dd4fb3ba9f14 +Author: Georg Koppen <gk@torproject.org> +Date: Thu Mar 1 09:44:30 2018 +0100 + + Bug 1382359: Treat .onion as a secure context + + Websites which collect passwords but don't use HTTPS start showing scary + warnings from Firefox 51 onwards and mixed context blocking has been + available even longer. + + .onion sites without HTTPS support are affected as well, although their + traffic is encrypted and authenticated. This patch addresses this + shortcoming by making sure .onion sites are treated as potentially + trustworthy origins. + + The secure context specification + (https://w3c.github.io/webappsec-secure-contexts/) is pretty much focused + on tying security and trustworthiness to the protocol over which domains + are accessed. However, it is not obvious why .onion sites should not be + treated as potentially trustworthy given: + + "A potentially trustworthy origin is one which a user agent can + generally trust as delivering data securely. + + This algorithms [sic] considers certain hosts, scheme, and origins as + potentially trustworthy, even though they might not be authenticated and + encrypted in the traditional sense." + (https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy) + + We use step 8 in the algorithm to establish trustworthiness of .onion + sites by whitelisting them given the encrypted and authenticated nature + of their traffic. +--- + dom/html/HTMLFormElement.cpp | 4 ++++ + dom/security/nsContentSecurityManager.cpp | 7 +++++++ + dom/security/nsMixedContentBlocker.cpp | 29 +++++++++++++++++++++++++++++ + dom/security/nsMixedContentBlocker.h | 1 + + 4 files changed, 41 insertions(+) + +diff --git dom/html/HTMLFormElement.cpp dom/html/HTMLFormElement.cpp +index 02b3553c8a14..0e00b961ed45 100644 +--- dom/html/HTMLFormElement.cpp ++++ dom/html/HTMLFormElement.cpp +@@ -867,6 +867,10 @@ HTMLFormElement::DoSecureToInsecureSubmitCheck(nsIURI* aActionURL, + return NS_OK; + } + ++ if (nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(aActionURL)) { ++ return NS_OK; ++ } ++ + nsCOMPtr<nsPIDOMWindowOuter> window = OwnerDoc()->GetWindow(); + if (!window) { + return NS_ERROR_FAILURE; +diff --git dom/security/nsContentSecurityManager.cpp dom/security/nsContentSecurityManager.cpp +index ed83d490ca3f..d0e50d51bfd2 100644 +--- dom/security/nsContentSecurityManager.cpp ++++ dom/security/nsContentSecurityManager.cpp +@@ -13,6 +13,7 @@ + #include "nsIImageLoadingContent.h" + + #include "mozilla/dom/Element.h" ++#include "mozilla/dom/nsMixedContentBlocker.h" + + NS_IMPL_ISUPPORTS(nsContentSecurityManager, + nsIContentSecurityManager, +@@ -879,6 +880,12 @@ nsContentSecurityManager::IsOriginPotentiallyTrustworthy(nsIPrincipal* aPrincipa + } + } + } ++ // Maybe we have a .onion URL. Treat it as whitelisted as well if ++ // `dom.securecontext.whitelist_onions` is `true`. ++ if (nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(uri)) { ++ *aIsTrustWorthy = true; ++ return NS_OK; ++ } + } + + return NS_OK; +diff --git dom/security/nsMixedContentBlocker.cpp dom/security/nsMixedContentBlocker.cpp +index 918a6ce53132..0361e744c800 100644 +--- dom/security/nsMixedContentBlocker.cpp ++++ dom/security/nsMixedContentBlocker.cpp +@@ -395,6 +395,28 @@ nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(nsIURI* aURL) { + return host.EqualsLiteral("127.0.0.1") || host.EqualsLiteral("::1"); + } + ++/* Maybe we have a .onion URL. Treat it as whitelisted as well if ++ * `dom.securecontext.whitelist_onions` is `true`. ++ */ ++bool ++nsMixedContentBlocker::IsPotentiallyTrustworthyOnion(nsIURI* aURL) { ++ static bool sInited = false; ++ static bool sWhiteListOnions = false; ++ if (!sInited) { ++ Preferences::AddBoolVarCache(&sWhiteListOnions, ++ "dom.securecontext.whitelist_onions"); ++ sInited = true; ++ } ++ if (!sWhiteListOnions) { ++ return false; ++ } ++ ++ nsAutoCString host; ++ nsresult rv = aURL->GetHost(host); ++ NS_ENSURE_SUCCESS(rv, false); ++ return StringEndsWith(host, NS_LITERAL_CSTRING(".onion")); ++} ++ + /* Static version of ShouldLoad() that contains all the Mixed Content Blocker + * logic. Called from non-static ShouldLoad(). + */ +@@ -725,6 +747,13 @@ nsMixedContentBlocker::ShouldLoad(bool aHadInsecureImageRedirect, + return NS_OK; + } + ++ // .onion URLs are encrypted and authenticated. Don't treat them as mixed ++ // content if potentially trustworthy (i.e. whitelisted). ++ if (isHttpScheme && IsPotentiallyTrustworthyOnion(innerContentLocation)) { ++ *aDecision = ACCEPT; ++ return NS_OK; ++ } ++ + // The page might have set the CSP directive 'upgrade-insecure-requests'. In such + // a case allow the http: load to succeed with the promise that the channel will + // get upgraded to https before fetching any data from the netwerk. +diff --git dom/security/nsMixedContentBlocker.h dom/security/nsMixedContentBlocker.h +index b7e4a7457bd2..a9b4dbdb612e 100644 +--- dom/security/nsMixedContentBlocker.h ++++ dom/security/nsMixedContentBlocker.h +@@ -48,6 +48,7 @@ public: + // See: + // https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy + static bool IsPotentiallyTrustworthyLoopbackURL(nsIURI* aURL); ++ static bool IsPotentiallyTrustworthyOnion(nsIURI* aURL); + + /* Static version of ShouldLoad() that contains all the Mixed Content Blocker + * logic. Called from non-static ShouldLoad(). diff --git a/www/waterfox/files/patch-bug1383501 b/www/waterfox/files/patch-bug1383501 new file mode 100644 index 000000000000..372046df120b --- /dev/null +++ b/www/waterfox/files/patch-bug1383501 @@ -0,0 +1,83 @@ +commit 8ba0e2ee02b0 +Author: Aaron Klotz <aklotz@mozilla.com> +Date: Wed Oct 4 09:12:25 2017 -0600 + + Bug 1383501 - Do not crash when TabParent::RecvPDocAccessibleConstructor receives a null COM proxy sent to the parent process. r=jimm, a=ritu + + MozReview-Commit-ID: 5IOuLXc375T + + --HG-- + extra : source : e2a6e2ddfa184b5a1f410408d7232ed0041a360f +--- + accessible/ipc/win/ProxyAccessible.cpp | 2 +- + accessible/ipc/win/ProxyAccessible.h | 13 ++++++++++++- + dom/ipc/TabParent.cpp | 2 ++ + 3 files changed, 15 insertions(+), 2 deletions(-) + +diff --git accessible/ipc/win/ProxyAccessible.cpp accessible/ipc/win/ProxyAccessible.cpp +index 0942e280ea30..383ece99fb0c 100644 +--- accessible/ipc/win/ProxyAccessible.cpp ++++ accessible/ipc/win/ProxyAccessible.cpp +@@ -34,7 +34,7 @@ ProxyAccessible::GetCOMInterface(void** aOutAccessible) const + return false; + } + +- if (!mCOMProxy) { ++ if (!mCOMProxy && mSafeToRecurse) { + // See if we can lazily obtain a COM proxy + AccessibleWrap* wrap = WrapperFor(this); + bool isDefunct = false; +diff --git accessible/ipc/win/ProxyAccessible.h accessible/ipc/win/ProxyAccessible.h +index 83f1e6093253..4fd897e588fe 100644 +--- accessible/ipc/win/ProxyAccessible.h ++++ accessible/ipc/win/ProxyAccessible.h +@@ -27,6 +27,7 @@ public: + ProxyAccessible(uint64_t aID, ProxyAccessible* aParent, + DocAccessibleParent* aDoc, role aRole, uint32_t aInterfaces) + : ProxyAccessibleBase(aID, aParent, aDoc, aRole, aInterfaces) ++ , mSafeToRecurse(true) + { + MOZ_COUNT_CTOR(ProxyAccessible); + } +@@ -40,7 +41,16 @@ public: + + bool GetCOMInterface(void** aOutAccessible) const; + void SetCOMInterface(const RefPtr<IAccessible>& aIAccessible) +- { mCOMProxy = aIAccessible; } ++ { ++ if (aIAccessible) { ++ mCOMProxy = aIAccessible; ++ } else { ++ // If we were supposed to be receiving an interface (hence the call to ++ // this function), but the interface turns out to be null, then we're ++ // broken for some reason. ++ mSafeToRecurse = false; ++ } ++ } + + protected: + explicit ProxyAccessible(DocAccessibleParent* aThisAsDoc) +@@ -49,6 +59,7 @@ protected: + + private: + RefPtr<IAccessible> mCOMProxy; ++ bool mSafeToRecurse; + }; + + } +diff --git dom/ipc/TabParent.cpp dom/ipc/TabParent.cpp +index 7fc5689e6211..d8733a377219 100644 +--- dom/ipc/TabParent.cpp ++++ dom/ipc/TabParent.cpp +@@ -972,9 +972,11 @@ TabParent::RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc, + #ifdef XP_WIN + a11y::WrapperFor(doc)->SetID(aMsaaID); + MOZ_ASSERT(!aDocCOMProxy.IsNull()); ++#ifdef NIGHTLY_BUILD + if (aDocCOMProxy.IsNull()) { + return IPC_FAIL(this, "Constructing a top-level PDocAccessible with null COM proxy"); + } ++#endif + + RefPtr<IAccessible> proxy(aDocCOMProxy.Get()); + doc->SetCOMInterface(proxy); diff --git a/www/waterfox/files/patch-bug1384121 b/www/waterfox/files/patch-bug1384121 new file mode 100644 index 000000000000..94a261585850 --- /dev/null +++ b/www/waterfox/files/patch-bug1384121 @@ -0,0 +1,218 @@ +commit 485ed2f2b015 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Mon Sep 18 15:08:44 2017 +0200 + + Bug 1384121 part 1 - Don't sweep ObjectGroups under IC helper functions. r=bhackett +--- + js/src/jit/IonCacheIRCompiler.cpp | 4 ++-- + js/src/vm/ObjectGroup.h | 2 ++ + js/src/vm/TypeInference-inl.h | 29 ++++++++++++++++++++++------- + js/src/vm/UnboxedObject.cpp | 2 +- + 4 files changed, 27 insertions(+), 10 deletions(-) + +diff --git js/src/jit/IonCacheIRCompiler.cpp js/src/jit/IonCacheIRCompiler.cpp +index b11aed7966b6..bbfbdae57b12 100644 +--- js/src/jit/IonCacheIRCompiler.cpp ++++ js/src/jit/IonCacheIRCompiler.cpp +@@ -1324,9 +1324,9 @@ IonCacheIRCompiler::emitCallStringSplitResult() + static bool + GroupHasPropertyTypes(ObjectGroup* group, jsid* id, Value* v) + { +- if (group->unknownProperties()) ++ if (group->unknownPropertiesDontCheckGeneration()) + return true; +- HeapTypeSet* propTypes = group->maybeGetProperty(*id); ++ HeapTypeSet* propTypes = group->maybeGetPropertyDontCheckGeneration(*id); + if (!propTypes) + return true; + if (!propTypes->nonConstantProperty()) +diff --git js/src/vm/ObjectGroup.h js/src/vm/ObjectGroup.h +index 237b5a152576..0eba71ee084f 100644 +--- js/src/vm/ObjectGroup.h ++++ js/src/vm/ObjectGroup.h +@@ -390,6 +390,7 @@ class ObjectGroup : public gc::TenuredCell + + /* Get a property only if it already exists. */ + MOZ_ALWAYS_INLINE HeapTypeSet* maybeGetProperty(jsid id); ++ MOZ_ALWAYS_INLINE HeapTypeSet* maybeGetPropertyDontCheckGeneration(jsid id); + + /* + * Iterate through the group's properties. getPropertyCount overapproximates +@@ -471,6 +472,7 @@ class ObjectGroup : public gc::TenuredCell + } + + inline uint32_t basePropertyCount(); ++ inline uint32_t basePropertyCountDontCheckGeneration(); + + private: + inline void setBasePropertyCount(uint32_t count); +diff --git js/src/vm/TypeInference-inl.h js/src/vm/TypeInference-inl.h +index f7cd3459ef19..f2b0b9a52fbc 100644 +--- js/src/vm/TypeInference-inl.h ++++ js/src/vm/TypeInference-inl.h +@@ -369,10 +369,10 @@ TypeMonitorCall(JSContext* cx, const js::CallArgs& args, bool constructing) + MOZ_ALWAYS_INLINE bool + TrackPropertyTypes(JSObject* obj, jsid id) + { +- if (obj->hasLazyGroup() || obj->group()->unknownProperties()) ++ if (obj->hasLazyGroup() || obj->group()->unknownPropertiesDontCheckGeneration()) + return false; + +- if (obj->isSingleton() && !obj->group()->maybeGetProperty(id)) ++ if (obj->isSingleton() && !obj->group()->maybeGetPropertyDontCheckGeneration(id)) + return false; + + return true; +@@ -410,7 +410,7 @@ HasTrackedPropertyType(JSObject* obj, jsid id, TypeSet::Type type) + MOZ_ASSERT(id == IdToTypeId(id)); + MOZ_ASSERT(TrackPropertyTypes(obj, id)); + +- if (HeapTypeSet* types = obj->group()->maybeGetProperty(id)) { ++ if (HeapTypeSet* types = obj->group()->maybeGetPropertyDontCheckGeneration(id)) { + if (!types->hasType(type)) + return false; + // Non-constant properties are only relevant for singleton objects. +@@ -1074,10 +1074,18 @@ TypeSet::getObjectClass(unsigned i) const + // ObjectGroup + ///////////////////////////////////////////////////////////////////// + ++inline uint32_t ++ObjectGroup::basePropertyCountDontCheckGeneration() ++{ ++ uint32_t flags = flagsDontCheckGeneration(); ++ return (flags & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT; ++} ++ + inline uint32_t + ObjectGroup::basePropertyCount() + { +- return (flags() & OBJECT_FLAG_PROPERTY_COUNT_MASK) >> OBJECT_FLAG_PROPERTY_COUNT_SHIFT; ++ maybeSweep(nullptr); ++ return basePropertyCountDontCheckGeneration(); + } + + inline void +@@ -1134,14 +1142,14 @@ ObjectGroup::getProperty(JSContext* cx, JSObject* obj, jsid id) + } + + MOZ_ALWAYS_INLINE HeapTypeSet* +-ObjectGroup::maybeGetProperty(jsid id) ++ObjectGroup::maybeGetPropertyDontCheckGeneration(jsid id) + { + MOZ_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id) || JSID_IS_SYMBOL(id)); + MOZ_ASSERT_IF(!JSID_IS_EMPTY(id), id == IdToTypeId(id)); +- MOZ_ASSERT(!unknownProperties()); ++ MOZ_ASSERT(!unknownPropertiesDontCheckGeneration()); + + Property* prop = TypeHashSet::Lookup<jsid, Property, Property> +- (propertySet, basePropertyCount(), id); ++ (propertySet, basePropertyCountDontCheckGeneration(), id); + + if (!prop) + return nullptr; +@@ -1150,6 +1158,13 @@ ObjectGroup::maybeGetProperty(jsid id) + return &prop->types; + } + ++MOZ_ALWAYS_INLINE HeapTypeSet* ++ObjectGroup::maybeGetProperty(jsid id) ++{ ++ maybeSweep(nullptr); ++ return maybeGetPropertyDontCheckGeneration(id); ++} ++ + inline unsigned + ObjectGroup::getPropertyCount() + { +diff --git js/src/vm/UnboxedObject.cpp js/src/vm/UnboxedObject.cpp +index c155b7dc47c9..4e007489a67e 100644 +--- js/src/vm/UnboxedObject.cpp ++++ js/src/vm/UnboxedObject.cpp +@@ -363,7 +363,7 @@ UnboxedPlainObject::ensureExpando(JSContext* cx, Handle<UnboxedPlainObject*> obj + bool + UnboxedPlainObject::containsUnboxedOrExpandoProperty(JSContext* cx, jsid id) const + { +- if (layout().lookup(id)) ++ if (layoutDontCheckGeneration().lookup(id)) + return true; + + if (maybeExpando() && maybeExpando()->containsShapeOrElement(cx, id)) +commit e240cf665f74 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Wed Sep 20 12:13:54 2017 +0200 + + Bug 1384121 part 2 - Add asserts to catch similar bugs and fix some false positives. r=nbp +--- + js/src/jit/Bailouts.cpp | 4 ---- + js/src/jit/JSJitFrameIter.cpp | 2 ++ + js/src/jit/VMFunctions.cpp | 1 - + js/src/jit/arm/Trampoline-arm.cpp | 9 ++++++--- + js/src/jit/arm64/Trampoline-arm64.cpp | 9 ++++++--- + js/src/jit/mips32/Trampoline-mips32.cpp | 9 ++++++--- + js/src/jit/mips64/Trampoline-mips64.cpp | 9 ++++++--- + js/src/jit/x64/Trampoline-x64.cpp | 9 ++++++--- + js/src/jit/x86/Trampoline-x86.cpp | 9 ++++++--- + js/src/vm/ObjectGroup-inl.h | 1 + + js/src/vm/Stack.cpp | 2 ++ + js/src/vm/TypeInference.cpp | 3 +++ + 12 files changed, 44 insertions(+), 23 deletions(-) + +diff --git js/src/jit/JSJitFrameIter.cpp js/src/jit/JSJitFrameIter.cpp +index 3774b327d21c..ae76bc2abaf0 100644 +--- js/src/jit/JitFrameIterator.cpp ++++ js/src/jit/JitFrameIterator.cpp +@@ -25,6 +25,8 @@ JSJitFrameIter::JSJitFrameIter(const JitActivation* activation) + current_ = activation_->bailoutData()->fp(); + frameSize_ = activation_->bailoutData()->topFrameSize(); + type_ = JitFrame_Bailout; ++ } else { ++ MOZ_ASSERT(!TlsContext.get()->inUnsafeCallWithABI); + } + } + +diff --git js/src/vm/ObjectGroup-inl.h js/src/vm/ObjectGroup-inl.h +index 7e023ecbad8e..d7caa63d8725 100644 +--- js/src/vm/ObjectGroup-inl.h ++++ js/src/vm/ObjectGroup-inl.h +@@ -16,6 +16,7 @@ ObjectGroup::needsSweep() + { + // Note: this can be called off thread during compacting GCs, in which case + // nothing will be running on the active thread. ++ MOZ_ASSERT(!TlsContext.get()->inUnsafeCallWithABI); + return generation() != zoneFromAnyThread()->types.generation; + } + +diff --git js/src/vm/Stack.cpp js/src/vm/Stack.cpp +index d3c0038db5ca..0406195abd56 100644 +--- js/src/vm/Stack.cpp ++++ js/src/vm/Stack.cpp +@@ -605,6 +605,8 @@ FrameIter::popInterpreterFrame() + void + FrameIter::settleOnActivation() + { ++ MOZ_ASSERT(!data_.cx_->inUnsafeCallWithABI); ++ + while (true) { + if (data_.activations_.done()) { + data_.state_ = DONE; +diff --git js/src/vm/TypeInference.cpp js/src/vm/TypeInference.cpp +index f0562a4355f8..eba18e34397e 100644 +--- js/src/vm/TypeInference.cpp ++++ js/src/vm/TypeInference.cpp +@@ -4428,6 +4428,8 @@ ObjectGroup::sweep(AutoClearTypeInferenceStateOnOOM* oom) + /* static */ void + JSScript::maybeSweepTypes(AutoClearTypeInferenceStateOnOOM* oom) + { ++ MOZ_ASSERT(!TlsContext.get()->inUnsafeCallWithABI); ++ + if (!types_ || typesGeneration() == zone()->types.generation) + return; + +@@ -4611,6 +4613,7 @@ AutoClearTypeInferenceStateOnOOM::AutoClearTypeInferenceStateOnOOM(Zone* zone) + : zone(zone), oom(false) + { + MOZ_RELEASE_ASSERT(CurrentThreadCanAccessZone(zone)); ++ MOZ_ASSERT(!TlsContext.get()->inUnsafeCallWithABI); + zone->types.setSweepingTypes(true); + } + diff --git a/www/waterfox/files/patch-bug1384701 b/www/waterfox/files/patch-bug1384701 new file mode 100644 index 000000000000..142d5430d266 --- /dev/null +++ b/www/waterfox/files/patch-bug1384701 @@ -0,0 +1,796 @@ +diff --git widget/gtk/nsLookAndFeel.cpp widget/gtk/nsLookAndFeel.cpp +index 6bb3e27c6653..f4c35d82200a 100644 +--- widget/gtk/nsLookAndFeel.cpp ++++ widget/gtk/nsLookAndFeel.cpp +@@ -29,11 +29,9 @@ + + #include "mozilla/gfx/2D.h" + +-#if MOZ_WIDGET_GTK != 2 + #include <cairo-gobject.h> + #include "WidgetStyleCache.h" + #include "prenv.h" +-#endif + + using mozilla::LookAndFeel; + +@@ -49,9 +47,6 @@ using mozilla::LookAndFeel; + + nsLookAndFeel::nsLookAndFeel() + : nsXPLookAndFeel(), +-#if (MOZ_WIDGET_GTK == 2) +- mStyle(nullptr), +-#endif + mDefaultFontCached(false), mButtonFontCached(false), + mFieldFontCached(false), mMenuFontCached(false), + mInitialized(false) +@@ -66,12 +61,8 @@ nsLookAndFeel::NativeInit() + + nsLookAndFeel::~nsLookAndFeel() + { +-#if (MOZ_WIDGET_GTK == 2) +- g_object_unref(mStyle); +-#endif + } + +-#if MOZ_WIDGET_GTK != 2 + // Modifies color |*aDest| as if a pattern of color |aSource| was painted with + // CAIRO_OPERATOR_OVER to a surface with color |*aDest|. + static void +@@ -228,42 +219,19 @@ GetBorderColors(GtkStyleContext* aContext, + *aDarkColor = GDK_RGBA_TO_NS_RGBA(darkColor); + return ret; + } +-#endif + + nsresult + nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + { + EnsureInit(); + +-#if (MOZ_WIDGET_GTK == 3) + GdkRGBA gdk_color; +-#endif + nsresult res = NS_OK; + + switch (aID) { + // These colors don't seem to be used for anything anymore in Mozilla + // (except here at least TextSelectBackground and TextSelectForeground) + // The CSS2 colors below are used. +-#if (MOZ_WIDGET_GTK == 2) +- case eColorID_WindowBackground: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_NORMAL]); +- break; +- case eColorID_WindowForeground: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_NORMAL]); +- break; +- case eColorID_WidgetBackground: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID_WidgetForeground: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]); +- break; +- case eColorID_WidgetSelectBackground: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]); +- break; +- case eColorID_WidgetSelectForeground: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_SELECTED]); +- break; +-#else + case eColorID_WindowBackground: + case eColorID_WidgetBackground: + case eColorID_TextBackground: +@@ -303,35 +271,12 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + case eColorID__moz_html_cellhighlighttext: + aColor = sTextSelectedText; + break; +-#endif + case eColorID_Widget3DHighlight: + aColor = NS_RGB(0xa0,0xa0,0xa0); + break; + case eColorID_Widget3DShadow: + aColor = NS_RGB(0x40,0x40,0x40); + break; +-#if (MOZ_WIDGET_GTK == 2) +- case eColorID_TextBackground: +- // not used? +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_NORMAL]); +- break; +- case eColorID_TextForeground: +- // not used? +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_NORMAL]); +- break; +- case eColorID_TextSelectBackground: +- case eColorID_IMESelectedRawTextBackground: +- case eColorID_IMESelectedConvertedTextBackground: +- // still used +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_SELECTED]); +- break; +- case eColorID_TextSelectForeground: +- case eColorID_IMESelectedRawTextForeground: +- case eColorID_IMESelectedConvertedTextForeground: +- // still used +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_SELECTED]); +- break; +-#endif + case eColorID_IMERawInputBackground: + case eColorID_IMEConvertedTextBackground: + aColor = NS_TRANSPARENT; +@@ -352,53 +297,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + aColor = NS_RGB(0xff, 0, 0); + break; + +-#if (MOZ_WIDGET_GTK == 2) +- // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors +- case eColorID_activeborder: +- // active window border +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID_activecaption: +- // active window caption background +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID_appworkspace: +- // MDI background color +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID_background: +- // desktop background +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID_captiontext: +- // text in active window caption, size box, and scrollbar arrow box (!) +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]); +- break; +- case eColorID_graytext: +- // disabled text in windows, menus, etc. +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]); +- break; +- case eColorID_highlight: +- // background of selected item +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_SELECTED]); +- break; +- case eColorID_highlighttext: +- // text of selected item +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_SELECTED]); +- break; +- case eColorID_inactiveborder: +- // inactive window border +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID_inactivecaption: +- // inactive window caption +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_INSENSITIVE]); +- break; +- case eColorID_inactivecaptiontext: +- // text in inactive window caption +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_INSENSITIVE]); +- break; +-#else + // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors + case eColorID_activeborder: { + // active window border +@@ -433,7 +331,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + ReleaseStyleContext(style); + break; + } +-#endif + case eColorID_infobackground: + // tooltip background color + aColor = sInfoBackground; +@@ -452,11 +349,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + break; + case eColorID_scrollbar: + // scrollbar gray area +-#if (MOZ_WIDGET_GTK == 2) +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_ACTIVE]); +-#else + aColor = sMozScrollbar; +-#endif + break; + + case eColorID_threedlightshadow: +@@ -465,11 +358,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + case eColorID_threedface: + case eColorID_buttonface: + // 3-D face color +-#if (MOZ_WIDGET_GTK == 3) + aColor = sMozWindowBackground; +-#else +- aColor = sButtonBackground; +-#endif + break; + + case eColorID_buttontext: +@@ -491,56 +380,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + aColor = sFrameInnerDarkBorder; + break; + +-#if (MOZ_WIDGET_GTK == 2) +- case eColorID_threeddarkshadow: +- // 3-D shadow outer edge color +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->black); +- break; +- +- case eColorID_window: +- case eColorID_windowframe: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- +- case eColorID_windowtext: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]); +- break; +- +- case eColorID__moz_eventreerow: +- case eColorID__moz_field: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_NORMAL]); +- break; +- case eColorID__moz_fieldtext: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_NORMAL]); +- break; +- case eColorID__moz_dialog: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_NORMAL]); +- break; +- case eColorID__moz_dialogtext: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_NORMAL]); +- break; +- case eColorID__moz_dragtargetzone: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_SELECTED]); +- break; +- case eColorID__moz_buttondefault: +- // default button border color +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->black); +- break; +- case eColorID__moz_buttonhoverface: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->bg[GTK_STATE_PRELIGHT]); +- break; +- case eColorID__moz_buttonhovertext: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->fg[GTK_STATE_PRELIGHT]); +- break; +- case eColorID__moz_cellhighlight: +- case eColorID__moz_html_cellhighlight: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->base[GTK_STATE_ACTIVE]); +- break; +- case eColorID__moz_cellhighlighttext: +- case eColorID__moz_html_cellhighlighttext: +- aColor = GDK_COLOR_TO_NS_RGB(mStyle->text[GTK_STATE_ACTIVE]); +- break; +-#else + case eColorID_threeddarkshadow: + // Hardcode to black + aColor = NS_RGB(0x00,0x00,0x00); +@@ -574,7 +413,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + case eColorID__moz_buttonhovertext: + aColor = sButtonHoverText; + break; +-#endif + case eColorID__moz_menuhover: + aColor = sMenuHover; + break; +@@ -590,11 +428,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + case eColorID__moz_comboboxtext: + aColor = sComboBoxText; + break; +-#if (MOZ_WIDGET_GTK == 2) +- case eColorID__moz_combobox: +- aColor = sComboBoxBackground; +- break; +-#endif + case eColorID__moz_menubartext: + aColor = sMenuBarText; + break; +@@ -602,11 +435,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + aColor = sMenuBarHoverText; + break; + case eColorID__moz_gtk_info_bar_text: +-#if (MOZ_WIDGET_GTK == 3) + aColor = sInfoBarText; +-#else +- aColor = sInfoText; +-#endif + break; + default: + /* default color is BLACK */ +@@ -618,27 +447,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + return res; + } + +-#if (MOZ_WIDGET_GTK == 2) +-static void darken_gdk_color(GdkColor *src, GdkColor *dest) +-{ +- gdouble red; +- gdouble green; +- gdouble blue; +- +- red = (gdouble) src->red / 65535.0; +- green = (gdouble) src->green / 65535.0; +- blue = (gdouble) src->blue / 65535.0; +- +- red *= 0.93; +- green *= 0.93; +- blue *= 0.93; +- +- dest->red = red * 65535.0; +- dest->green = green * 65535.0; +- dest->blue = blue * 65535.0; +-} +-#endif +- + static int32_t CheckWidgetStyle(GtkWidget* aWidget, const char* aStyle, int32_t aResult) { + gboolean value = FALSE; + gtk_widget_style_get(aWidget, aStyle, &value, nullptr); +@@ -826,14 +634,8 @@ nsLookAndFeel::GetIntImpl(IntID aID, int32_t &aResult) + res = NS_ERROR_NOT_IMPLEMENTED; + break; + case eIntID_TouchEnabled: +-#if MOZ_WIDGET_GTK == 3 + aResult = mozilla::widget::WidgetUtils::IsTouchDeviceSupportPresent(); + break; +-#else +- aResult = 0; +- res = NS_ERROR_NOT_IMPLEMENTED; +-#endif +- break; + case eIntID_MacGraphiteTheme: + aResult = 0; + res = NS_ERROR_NOT_IMPLEMENTED; +@@ -905,24 +707,20 @@ nsLookAndFeel::GetFloatImpl(FloatID aID, float &aResult) + } + + static void +-GetSystemFontInfo(GtkWidget *aWidget, ++GetSystemFontInfo(GtkStyleContext *aStyle, + nsString *aFontName, + gfxFontStyle *aFontStyle) + { +- GtkSettings *settings = gtk_widget_get_settings(aWidget); +- + aFontStyle->style = NS_FONT_STYLE_NORMAL; + +- gchar *fontname; +- g_object_get(settings, "gtk-font-name", &fontname, nullptr); +- ++ // As in ++ // https://git.gnome.org/browse/gtk+/tree/gtk/gtkwidget.c?h=3.22.19#n10333 + PangoFontDescription *desc; +- desc = pango_font_description_from_string(fontname); ++ gtk_style_context_get(aStyle, gtk_style_context_get_state(aStyle), ++ "font", &desc, nullptr); + + aFontStyle->systemFont = true; + +- g_free(fontname); +- + NS_NAMED_LITERAL_STRING(quote, "\""); + NS_ConvertUTF8toUTF16 family(pango_font_description_get_family(desc)); + *aFontName = quote + family + quote; +@@ -953,96 +751,28 @@ GetSystemFontInfo(GtkWidget *aWidget, + pango_font_description_free(desc); + } + +-static void +-GetSystemFontInfo(LookAndFeel::FontID aID, +- nsString *aFontName, +- gfxFontStyle *aFontStyle) +-{ +- if (aID == LookAndFeel::eFont_Widget) { +- GtkWidget *label = gtk_label_new("M"); +- GtkWidget *parent = gtk_fixed_new(); +- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP); +- +- gtk_container_add(GTK_CONTAINER(parent), label); +- gtk_container_add(GTK_CONTAINER(window), parent); +- +- gtk_widget_ensure_style(label); +- GetSystemFontInfo(label, aFontName, aFontStyle); +- gtk_widget_destroy(window); // no unref, windows are different +- +- } else if (aID == LookAndFeel::eFont_Button) { +- GtkWidget *label = gtk_label_new("M"); +- GtkWidget *parent = gtk_fixed_new(); +- GtkWidget *button = gtk_button_new(); +- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP); +- +- gtk_container_add(GTK_CONTAINER(button), label); +- gtk_container_add(GTK_CONTAINER(parent), button); +- gtk_container_add(GTK_CONTAINER(window), parent); +- +- gtk_widget_ensure_style(label); +- GetSystemFontInfo(label, aFontName, aFontStyle); +- gtk_widget_destroy(window); // no unref, windows are different +- +- } else if (aID == LookAndFeel::eFont_Field) { +- GtkWidget *entry = gtk_entry_new(); +- GtkWidget *parent = gtk_fixed_new(); +- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP); +- +- gtk_container_add(GTK_CONTAINER(parent), entry); +- gtk_container_add(GTK_CONTAINER(window), parent); +- +- gtk_widget_ensure_style(entry); +- GetSystemFontInfo(entry, aFontName, aFontStyle); +- gtk_widget_destroy(window); // no unref, windows are different +- +- } else { +- MOZ_ASSERT(aID == LookAndFeel::eFont_Menu, "unexpected font ID"); +- GtkWidget *accel_label = gtk_accel_label_new("M"); +- GtkWidget *menuitem = gtk_menu_item_new(); +- GtkWidget *menu = gtk_menu_new(); +- g_object_ref_sink(menu); +- +- gtk_container_add(GTK_CONTAINER(menuitem), accel_label); +- gtk_menu_shell_append((GtkMenuShell *)GTK_MENU(menu), menuitem); +- +- gtk_widget_ensure_style(accel_label); +- GetSystemFontInfo(accel_label, aFontName, aFontStyle); +- g_object_unref(menu); +- } +-} +- + bool + nsLookAndFeel::GetFontImpl(FontID aID, nsString& aFontName, + gfxFontStyle& aFontStyle, + float aDevPixPerCSSPixel) + { +- nsString *cachedFontName = nullptr; +- gfxFontStyle *cachedFontStyle = nullptr; +- bool *isCached = nullptr; +- + switch (aID) { + case eFont_Menu: // css2 + case eFont_PullDownMenu: // css3 +- cachedFontName = &mMenuFontName; +- cachedFontStyle = &mMenuFontStyle; +- isCached = &mMenuFontCached; +- aID = eFont_Menu; +- break; ++ aFontName = mMenuFontName; ++ aFontStyle = mMenuFontStyle; ++ return true; + + case eFont_Field: // css3 + case eFont_List: // css3 +- cachedFontName = &mFieldFontName; +- cachedFontStyle = &mFieldFontStyle; +- isCached = &mFieldFontCached; +- aID = eFont_Field; +- break; ++ aFontName = mFieldFontName; ++ aFontStyle = mFieldFontStyle; ++ return true; + + case eFont_Button: // css3 +- cachedFontName = &mButtonFontName; +- cachedFontStyle = &mButtonFontStyle; +- isCached = &mButtonFontCached; +- break; ++ aFontName = mButtonFontName; ++ aFontStyle = mButtonFontStyle; ++ return true; + + case eFont_Caption: // css2 + case eFont_Icon: // css2 +@@ -1057,21 +787,11 @@ nsLookAndFeel::GetFontImpl(FontID aID, nsString& aFontName, + case eFont_Dialog: // css3 + case eFont_Tooltips: // moz + case eFont_Widget: // moz +- cachedFontName = &mDefaultFontName; +- cachedFontStyle = &mDefaultFontStyle; +- isCached = &mDefaultFontCached; +- aID = eFont_Widget; +- break; +- } +- +- if (!*isCached) { +- GetSystemFontInfo(aID, cachedFontName, cachedFontStyle); +- *isCached = true; ++ default: ++ aFontName = mDefaultFontName; ++ aFontStyle = mDefaultFontStyle; ++ return true; + } +- +- aFontName = *cachedFontName; +- aFontStyle = *cachedFontStyle; +- return true; + } + + void +@@ -1087,70 +807,6 @@ nsLookAndFeel::EnsureInit() + // gtk does non threadsafe refcounting + MOZ_ASSERT(NS_IsMainThread()); + +-#if (MOZ_WIDGET_GTK == 2) +- NS_ASSERTION(!mStyle, "already initialized"); +- // GtkInvisibles come with a refcount that is not floating +- // (since their initialization code calls g_object_ref_sink) and +- // their destroy code releases that reference (which means they +- // have to be explicitly destroyed, since calling unref enough +- // to cause destruction would lead to *another* unref). +- // However, this combination means that it's actually still ok +- // to use the normal pattern, which is to g_object_ref_sink +- // after construction, and then destroy *and* unref when we're +- // done. (Though we could skip the g_object_ref_sink and the +- // corresponding g_object_unref, but that's particular to +- // GtkInvisibles and GtkWindows.) +- GtkWidget *widget = gtk_invisible_new(); +- g_object_ref_sink(widget); // effectively g_object_ref (see above) +- +- gtk_widget_ensure_style(widget); +- mStyle = gtk_style_copy(gtk_widget_get_style(widget)); +- +- gtk_widget_destroy(widget); +- g_object_unref(widget); +- +- // tooltip foreground and background +- GtkStyle *style = gtk_rc_get_style_by_paths(gtk_settings_get_default(), +- "gtk-tooltips", "GtkWindow", +- GTK_TYPE_WINDOW); +- if (style) { +- sInfoBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]); +- sInfoText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]); +- } +- +- // menu foreground & menu background +- GtkWidget *accel_label = gtk_accel_label_new("M"); +- GtkWidget *menuitem = gtk_menu_item_new(); +- GtkWidget *menu = gtk_menu_new(); +- +- g_object_ref_sink(menu); +- +- gtk_container_add(GTK_CONTAINER(menuitem), accel_label); +- gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); +- +- gtk_widget_set_style(accel_label, nullptr); +- gtk_widget_set_style(menu, nullptr); +- gtk_widget_realize(menu); +- gtk_widget_realize(accel_label); +- +- style = gtk_widget_get_style(accel_label); +- if (style) { +- sMenuText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]); +- } +- +- style = gtk_widget_get_style(menu); +- if (style) { +- sMenuBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]); +- } +- +- style = gtk_widget_get_style(menuitem); +- if (style) { +- sMenuHover = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_PRELIGHT]); +- sMenuHoverText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_PRELIGHT]); +- } +- +- g_object_unref(menu); +-#else + GdkRGBA color; + GtkStyleContext *style; + +@@ -1195,6 +851,12 @@ nsLookAndFeel::EnsureInit() + } + } + ++ // The label is not added to a parent widget, but shared for constructing ++ // different style contexts. The node hierarchy is constructed only on ++ // the label style context. ++ GtkWidget *labelWidget = gtk_label_new("M"); ++ g_object_ref_sink(labelWidget); ++ + // Scrollbar colors + style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); +@@ -1208,6 +870,13 @@ nsLookAndFeel::EnsureInit() + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMozWindowText = GDK_RGBA_TO_NS_RGBA(color); + ReleaseStyleContext(style); ++ style = ClaimStyleContext(MOZ_GTK_WINDOW_CONTAINER); ++ { ++ GtkStyleContext* labelStyle = CreateStyleForWidget(labelWidget, style); ++ GetSystemFontInfo(labelStyle, &mDefaultFontName, &mDefaultFontStyle); ++ g_object_unref(labelStyle); ++ } ++ ReleaseStyleContext(style); + + // tooltip foreground and background + style = ClaimStyleContext(MOZ_GTK_TOOLTIP); +@@ -1224,6 +893,9 @@ nsLookAndFeel::EnsureInit() + { + GtkStyleContext* accelStyle = + CreateStyleForWidget(gtk_accel_label_new("M"), style); ++ ++ GetSystemFontInfo(accelStyle, &mMenuFontName, &mMenuFontStyle); ++ + gtk_style_context_get_color(accelStyle, GTK_STATE_FLAG_NORMAL, &color); + sMenuText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(accelStyle, GTK_STATE_FLAG_INSENSITIVE, &color); +@@ -1243,17 +915,8 @@ nsLookAndFeel::EnsureInit() + gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + sMenuHoverText = GDK_RGBA_TO_NS_RGBA(color); + ReleaseStyleContext(style); +-#endif + +- // button styles + GtkWidget *parent = gtk_fixed_new(); +- GtkWidget *button = gtk_button_new(); +- GtkWidget *label = gtk_label_new("M"); +-#if (MOZ_WIDGET_GTK == 2) +- GtkWidget *combobox = gtk_combo_box_new(); +- GtkWidget *comboboxLabel = gtk_label_new("M"); +- gtk_container_add(GTK_CONTAINER(combobox), comboboxLabel); +-#endif + GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP); + GtkWidget *treeView = gtk_tree_view_new(); + GtkWidget *linkButton = gtk_link_button_new("http://example.com/"); +@@ -1262,94 +925,14 @@ nsLookAndFeel::EnsureInit() + GtkWidget *entry = gtk_entry_new(); + GtkWidget *textView = gtk_text_view_new(); + +- gtk_container_add(GTK_CONTAINER(button), label); +- gtk_container_add(GTK_CONTAINER(parent), button); + gtk_container_add(GTK_CONTAINER(parent), treeView); + gtk_container_add(GTK_CONTAINER(parent), linkButton); +-#if (MOZ_WIDGET_GTK == 2) +- gtk_container_add(GTK_CONTAINER(parent), combobox); +-#endif + gtk_container_add(GTK_CONTAINER(parent), menuBar); + gtk_menu_shell_append(GTK_MENU_SHELL(menuBar), menuBarItem); + gtk_container_add(GTK_CONTAINER(window), parent); + gtk_container_add(GTK_CONTAINER(parent), entry); + gtk_container_add(GTK_CONTAINER(parent), textView); + +-#if (MOZ_WIDGET_GTK == 2) +- gtk_widget_set_style(button, nullptr); +- gtk_widget_set_style(label, nullptr); +- gtk_widget_set_style(treeView, nullptr); +- gtk_widget_set_style(linkButton, nullptr); +- gtk_widget_set_style(combobox, nullptr); +- gtk_widget_set_style(comboboxLabel, nullptr); +- gtk_widget_set_style(menuBar, nullptr); +- gtk_widget_set_style(entry, nullptr); +- +- gtk_widget_realize(button); +- gtk_widget_realize(label); +- gtk_widget_realize(treeView); +- gtk_widget_realize(linkButton); +- gtk_widget_realize(combobox); +- gtk_widget_realize(comboboxLabel); +- gtk_widget_realize(menuBar); +- gtk_widget_realize(entry); +- +- style = gtk_widget_get_style(label); +- if (style) { +- sButtonText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]); +- } +- +- style = gtk_widget_get_style(comboboxLabel); +- if (style) { +- sComboBoxText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]); +- } +- style = gtk_widget_get_style(combobox); +- if (style) { +- sComboBoxBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]); +- } +- +- style = gtk_widget_get_style(menuBar); +- if (style) { +- sMenuBarText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_NORMAL]); +- sMenuBarHoverText = GDK_COLOR_TO_NS_RGB(style->fg[GTK_STATE_SELECTED]); +- } +- +- // GTK's guide to fancy odd row background colors: +- // 1) Check if a theme explicitly defines an odd row color +- // 2) If not, check if it defines an even row color, and darken it +- // slightly by a hardcoded value (gtkstyle.c) +- // 3) If neither are defined, take the base background color and +- // darken that by a hardcoded value +- colorValuePtr = nullptr; +- gtk_widget_style_get(treeView, +- "odd-row-color", &colorValuePtr, +- nullptr); +- +- if (colorValuePtr) { +- colorValue = *colorValuePtr; +- } else { +- gtk_widget_style_get(treeView, +- "even-row-color", &colorValuePtr, +- nullptr); +- if (colorValuePtr) +- darken_gdk_color(colorValuePtr, &colorValue); +- else +- darken_gdk_color(&treeView->style->base[GTK_STATE_NORMAL], &colorValue); +- } +- +- sOddCellBackground = GDK_COLOR_TO_NS_RGB(colorValue); +- if (colorValuePtr) +- gdk_color_free(colorValuePtr); +- +- style = gtk_widget_get_style(button); +- if (style) { +- sButtonBackground = GDK_COLOR_TO_NS_RGB(style->bg[GTK_STATE_NORMAL]); +- sFrameOuterLightBorder = +- GDK_COLOR_TO_NS_RGB(style->light[GTK_STATE_NORMAL]); +- sFrameInnerDarkBorder = +- GDK_COLOR_TO_NS_RGB(style->dark[GTK_STATE_NORMAL]); +- } +-#else + // Text colors + GdkRGBA bgColor; + // If the text window background is translucent, then the background of +@@ -1381,8 +964,10 @@ nsLookAndFeel::EnsureInit() + // Button text color + style = ClaimStyleContext(MOZ_GTK_BUTTON); + { +- GtkStyleContext* labelStyle = +- CreateStyleForWidget(gtk_label_new("M"), style); ++ GtkStyleContext* labelStyle = CreateStyleForWidget(labelWidget, style); ++ ++ GetSystemFontInfo(labelStyle, &mButtonFontName, &mButtonFontStyle); ++ + gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_NORMAL, &color); + sButtonText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_PRELIGHT, &color); +@@ -1446,7 +1031,6 @@ nsLookAndFeel::EnsureInit() + gtk_style_context_add_class(style, GTK_STYLE_CLASS_INFO); + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sInfoBarText = GDK_RGBA_TO_NS_RGBA(color); +-#endif + // Some themes have a unified menu bar, and support window dragging on it + gboolean supports_menubar_drag = FALSE; + GParamSpec *param_spec = +@@ -1493,7 +1074,11 @@ nsLookAndFeel::EnsureInit() + "cursor-aspect-ratio", &sCaretRatio, + nullptr); + ++ GetSystemFontInfo(gtk_widget_get_style_context(entry), ++ &mFieldFontName, &mFieldFontStyle); ++ + gtk_widget_destroy(window); ++ g_object_unref(labelWidget); + } + + // virtual +@@ -1515,11 +1100,6 @@ nsLookAndFeel::RefreshImpl() + mFieldFontCached = false; + mMenuFontCached = false; + +-#if (MOZ_WIDGET_GTK == 2) +- g_object_unref(mStyle); +- mStyle = nullptr; +-#endif +- + mInitialized = false; + } + +diff --git widget/gtk/nsLookAndFeel.h widget/gtk/nsLookAndFeel.h +index 9a4015e95415..38cd51c056d6 100644 +--- widget/gtk/nsLookAndFeel.h ++++ widget/gtk/nsLookAndFeel.h +@@ -33,9 +33,6 @@ public: + virtual bool GetEchoPasswordImpl(); + + protected: +-#if (MOZ_WIDGET_GTK == 2) +- struct _GtkStyle *mStyle; +-#endif + + // Cached fonts + bool mDefaultFontCached; +@@ -63,7 +60,6 @@ protected: + nscolor sMenuHoverText; + nscolor sButtonText; + nscolor sButtonHoverText; +- nscolor sButtonBackground; + nscolor sFrameOuterLightBorder; + nscolor sFrameInnerDarkBorder; + nscolor sOddCellBackground; +@@ -77,9 +73,7 @@ protected: + nscolor sTextSelectedText; + nscolor sTextSelectedBackground; + nscolor sMozScrollbar; +-#if (MOZ_WIDGET_GTK == 3) + nscolor sInfoBarText; +-#endif + char16_t sInvisibleCharacter; + float sCaretRatio; + bool sMenuSupportsDrag; diff --git a/www/waterfox/files/patch-bug1385013 b/www/waterfox/files/patch-bug1385013 new file mode 100644 index 000000000000..66307f92ac6a --- /dev/null +++ b/www/waterfox/files/patch-bug1385013 @@ -0,0 +1,92 @@ +commit 09e1ad759b21 +Author: Hiroyuki Ikezoe <hikezoe@mozilla.com> +Date: Wed Oct 18 10:43:22 2017 +0900 + + Bug 1385013 - Check all vertexes for the target frame are outside of the parent frame if the target frame is empty. r=birtles, a=ritu + + We create empty rectangle (zero-height or zero-width) frame for element which + has no content inside it, e.g. '<p></p>'. And nsRect.Intersects returns false + if either of the rectangles are empty, so if we check + !transformedRect.Intersects(scrollableRect) and transformedRect is empty, we + will end up returning true from IsFrameScrolledOutOfView even though the point + represented by the empty transformedRect might be inside the + scrollableRect. + + The reftest causes timeout without this fix since the animation never updates + after the initial paint. + + MozReview-Commit-ID: FymFJfjxyGc + + --HG-- + extra : source : 69e2ab081d3d71ef131f0ce878ee7830ae881d08 +--- + layout/generic/nsFrame.cpp | 11 +++++++++- + .../animation-on-empty-height-frame.html | 25 ++++++++++++++++++++++ + layout/reftests/css-animations/reftest.list | 1 + + 3 files changed, 36 insertions(+), 1 deletion(-) + +diff --git layout/generic/nsFrame.cpp layout/generic/nsFrame.cpp +index dbfd61b7e142..991ccbceeb65 100644 +--- layout/generic/nsFrame.cpp ++++ layout/generic/nsFrame.cpp +@@ -10555,7 +10555,16 @@ IsFrameScrolledOutOfView(nsIFrame *aFrame) + scrollableParent); + + nsRect scrollableRect = scrollableParent->GetVisualOverflowRect(); +- if (!transformedRect.Intersects(scrollableRect)) { ++ if (transformedRect.IsEmpty()) { ++ // If the transformed rect is empty it represents a line or a point that we ++ // should check is outside the the scrollable rect. ++ if (transformedRect.x > scrollableRect.XMost() || ++ transformedRect.y > scrollableRect.YMost() || ++ scrollableRect.x > transformedRect.XMost() || ++ scrollableRect.y > transformedRect.YMost()) { ++ return true; ++ } ++ } else if (!transformedRect.Intersects(scrollableRect)) { + return true; + } + +diff --git layout/reftests/css-animations/animation-on-empty-height-frame.html layout/reftests/css-animations/animation-on-empty-height-frame.html +new file mode 100644 +index 000000000000..eb3f58127b16 +--- /dev/null ++++ layout/reftests/css-animations/animation-on-empty-height-frame.html +@@ -0,0 +1,25 @@ ++<!DOCTYPE html> ++<html class="reftest-wait reftest-no-flush"> ++<style> ++@keyframes anim { ++ from { background-color: white; } ++ to { background-color: red; } ++} ++</style> ++<body> ++</body> ++<script> ++window.addEventListener('load', () => { ++ const body = document.querySelector('body'); ++ body.style.animation = 'anim 100s step-end reverse'; ++ body.addEventListener('animationstart', () => { ++ // This MozAfterPaint event corresponds to the white background paint. ++ // (The animation will initially paint the background red since it is playing ++ // a step-end animation in reverse.) ++ window.addEventListener('MozAfterPaint', () => { ++ document.documentElement.classList.remove('reftest-wait'); ++ }, {once: true}); ++ }); ++}); ++</script> ++</html> +diff --git layout/reftests/css-animations/reftest.list layout/reftests/css-animations/reftest.list +index 61e3e9ea6101..ed615645f707 100644 +--- layout/reftests/css-animations/reftest.list ++++ layout/reftests/css-animations/reftest.list +@@ -4,6 +4,7 @@ skip-if(stylo) fails == print-no-animations.html print-no-animations-ref.html # + skip-if(stylo) fails != print-no-animations.html print-no-animations-notref.html # reftest harness doesn't actually make pres context non-dynamic for reftest-paged tests. Bug 1374154 for stylo + == animate-opacity.html animate-opacity-ref.html + == animate-preserves3d.html animate-preserves3d-ref.html ++== animation-on-empty-height-frame.html about:blank + == in-visibility-hidden-animation.html in-visibility-hidden-animation-ref.html + == in-visibility-hidden-animation-pseudo-element.html in-visibility-hidden-animation-pseudo-element-ref.html + == partially-out-of-view-animation.html partially-out-of-view-animation-ref.html diff --git a/www/waterfox/files/patch-bug1385609 b/www/waterfox/files/patch-bug1385609 new file mode 100644 index 000000000000..0fd7ca695a5a --- /dev/null +++ b/www/waterfox/files/patch-bug1385609 @@ -0,0 +1,102 @@ +commit dd42019824ed +Author: Thomas Nguyen <tnguyen@mozilla.com> +Date: Wed Aug 30 18:04:10 2017 +0800 + + Bug 1385609 - Fix backoff issue that makes SB lists no longer update r=francois + + The issue occurs when nsITimer is fired earlier than the backoff time. In that + case, the update doesn't proceed and we never make another attempt because the + backoff update timer was oneshot. + + We fix the issue in two ways: + + - Add a tolerance of 1 second in case the timer fires too early. + - Set another oneshot timer whenever we are prevented from updating due to + backoff. + + MozReview-Commit-ID: E2ogNRsHJVK + + --HG-- + extra : rebase_source : c81fa77934f6c39e1c5d07b19785a01546e02542 +--- + toolkit/components/url-classifier/nsUrlClassifierLib.js | 12 +++++++++--- + .../components/url-classifier/nsUrlClassifierListManager.js | 5 ++++- + toolkit/components/url-classifier/tests/unit/test_backoff.js | 2 +- + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git toolkit/components/url-classifier/nsUrlClassifierLib.js toolkit/components/url-classifier/nsUrlClassifierLib.js +index e2457d85474c..38d1977e4641 100644 +--- toolkit/components/url-classifier/nsUrlClassifierLib.js ++++ toolkit/components/url-classifier/nsUrlClassifierLib.js +@@ -77,17 +77,20 @@ this.HTTP_TEMPORARY_REDIRECT = 307; + * @param timeoutIncrement Number time (ms) the starting timeout period + * we double this time for consecutive errors + * @param maxTimeout Number time (ms) maximum timeout period ++ * @param tolerance Checking next request tolerance. + */ + this.RequestBackoff = + function RequestBackoff(maxErrors, retryIncrement, + maxRequests, requestPeriod, +- timeoutIncrement, maxTimeout) { ++ timeoutIncrement, maxTimeout, ++ tolerance) { + this.MAX_ERRORS_ = maxErrors; + this.RETRY_INCREMENT_ = retryIncrement; + this.MAX_REQUESTS_ = maxRequests; + this.REQUEST_PERIOD_ = requestPeriod; + this.TIMEOUT_INCREMENT_ = timeoutIncrement; + this.MAX_TIMEOUT_ = maxTimeout; ++ this.TOLERANCE_ = tolerance; + + // Queue of ints keeping the time of all requests + this.requestTimes_ = []; +@@ -111,7 +114,9 @@ RequestBackoff.prototype.reset = function() { + */ + RequestBackoff.prototype.canMakeRequest = function() { + var now = Date.now(); +- if (now < this.nextRequestTime_) { ++ // Note that nsITimer delay is approximate: the timer can be fired before the ++ // requested time has elapsed. So, give it a tolerance ++ if (now + this.TOLERANCE_ < this.nextRequestTime_) { + return false; + } + +@@ -180,7 +185,8 @@ function RequestBackoffV4(maxRequests, requestPeriod) { + maxRequests /* num requests */, + requestPeriod /* request time, 60 min */, + backoffInterval /* backoff interval, 60 min */, +- 24 * 60 * 60 * 1000 /* max backoff, 24hr */); ++ 24 * 60 * 60 * 1000 /* max backoff, 24hr */, ++ 1000 /* tolerance of 1 sec */); + } + + // Expose this whole component. +diff --git toolkit/components/url-classifier/nsUrlClassifierListManager.js toolkit/components/url-classifier/nsUrlClassifierListManager.js +index 1e976b8597b7..5f10933163b6 100644 +--- toolkit/components/url-classifier/nsUrlClassifierListManager.js ++++ toolkit/components/url-classifier/nsUrlClassifierListManager.js +@@ -236,7 +236,10 @@ PROT_ListManager.prototype.setUpdateCheckTimer = function(updateUrl, + .createInstance(Ci.nsITimer); + this.updateCheckers_[updateUrl].initWithCallback(() => { + this.updateCheckers_[updateUrl] = null; +- this.checkForUpdates(updateUrl); ++ if (updateUrl && !this.checkForUpdates(updateUrl)) { ++ // Make another attempt later. ++ this.setUpdateCheckTimer(updateUrl, this.updateInterval); ++ } + }, delay, Ci.nsITimer.TYPE_ONE_SHOT); + } + /** +diff --git toolkit/components/url-classifier/tests/unit/test_backoff.js toolkit/components/url-classifier/tests/unit/test_backoff.js +index 365568c479e9..205507e83dd6 100644 +--- toolkit/components/url-classifier/tests/unit/test_backoff.js ++++ toolkit/components/url-classifier/tests/unit/test_backoff.js +@@ -11,7 +11,7 @@ function setNow(time) { + function run_test() { + // 3 errors, 1ms retry period, max 3 requests per ten milliseconds, + // 5ms backoff interval, 19ms max delay +- var rb = new jslib.RequestBackoff(3, 1, 3, 10, 5, 19); ++ var rb = new jslib.RequestBackoff(3, 1, 3, 10, 5, 19, 0); + setNow(1); + rb.noteServerResponse(200); + do_check_true(rb.canMakeRequest()); diff --git a/www/waterfox/files/patch-bug1387170 b/www/waterfox/files/patch-bug1387170 new file mode 100644 index 000000000000..fae4b65e028b --- /dev/null +++ b/www/waterfox/files/patch-bug1387170 @@ -0,0 +1,148 @@ +commit 02dc1567cd7d +Author: Brendan Dahl <brendan.dahl@gmail.com> +Date: Thu Aug 3 15:08:16 2017 -0700 + + Bug 1387170 - Use custom clipboard constructor instead of singleton. r=jrmuizel + + This allows instances of the clipboard to be created (like it + was pre-headless). +--- + widget/gtk/nsClipboard.cpp | 31 ------------------------------- + widget/gtk/nsClipboard.h | 2 -- + widget/gtk/nsWidgetFactory.cpp | 26 ++++++++++++++++++++++++-- + 3 files changed, 24 insertions(+), 35 deletions(-) + +diff --git widget/gtk/nsClipboard.cpp widget/gtk/nsClipboard.cpp +index 6972715a72df..d07d5baeede3 100644 +--- widget/gtk/nsClipboard.cpp ++++ widget/gtk/nsClipboard.cpp +@@ -9,7 +9,6 @@ + + #include "nsArrayUtils.h" + #include "nsClipboard.h" +-#include "HeadlessClipboard.h" + #include "nsSupportsPrimitives.h" + #include "nsString.h" + #include "nsReadableUtils.h" +@@ -21,7 +20,6 @@ + #include "nsIObserverService.h" + #include "mozilla/Services.h" + #include "mozilla/RefPtr.h" +-#include "mozilla/ClearOnShutdown.h" + #include "mozilla/TimeStamp.h" + + #include "imgIContainer.h" +@@ -39,7 +37,6 @@ + + #include "mozilla/Encoding.h" + +-#include "gfxPlatform.h" + + using namespace mozilla; + +@@ -81,34 +78,6 @@ selection_request_filter (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + +-namespace mozilla { +-namespace clipboard { +-StaticRefPtr<nsIClipboard> sInstance; +-} +-} +-/* static */ already_AddRefed<nsIClipboard> +-nsClipboard::GetInstance() +-{ +- using namespace mozilla::clipboard; +- +- if (!sInstance) { +- if (gfxPlatform::IsHeadless()) { +- sInstance = new widget::HeadlessClipboard(); +- } else { +- RefPtr<nsClipboard> clipboard = new nsClipboard(); +- nsresult rv = clipboard->Init(); +- if (NS_FAILED(rv)) { +- return nullptr; +- } +- sInstance = clipboard.forget(); +- } +- ClearOnShutdown(&sInstance); +- } +- +- RefPtr<nsIClipboard> service = sInstance.get(); +- return service.forget(); +-} +- + nsClipboard::nsClipboard() + { + } +diff --git widget/gtk/nsClipboard.h widget/gtk/nsClipboard.h +index 725bcdce846a..70c866a013c9 100644 +--- widget/gtk/nsClipboard.h ++++ widget/gtk/nsClipboard.h +@@ -23,8 +23,6 @@ public: + NS_DECL_NSICLIPBOARD + NS_DECL_NSIOBSERVER + +- static already_AddRefed<nsIClipboard> GetInstance(); +- + // Make sure we are initialized, called from the factory + // constructor + nsresult Init (void); +diff --git widget/gtk/nsWidgetFactory.cpp widget/gtk/nsWidgetFactory.cpp +index 3c8bc02ebbb5..86b9cdab77e7 100644 +--- widget/gtk/nsWidgetFactory.cpp ++++ widget/gtk/nsWidgetFactory.cpp +@@ -17,6 +17,7 @@ + #include "nsWindow.h" + #include "nsTransferable.h" + #include "nsHTMLFormatConverter.h" ++#include "HeadlessClipboard.h" + #ifdef MOZ_X11 + #include "nsClipboardHelper.h" + #include "nsClipboard.h" +@@ -72,7 +73,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) + #ifdef MOZ_X11 + NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceGTK, nsIdleServiceGTK::GetInstance) + NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) +-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIClipboard, nsClipboard::GetInstance) + NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDragService, nsDragService::GetInstance) + #endif + NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISound, nsSound::GetInstance) +@@ -194,6 +194,28 @@ nsColorPickerConstructor(nsISupports *aOuter, REFNSIID aIID, + return picker->QueryInterface(aIID, aResult); + } + ++static nsresult ++nsClipboardConstructor(nsISupports *aOuter, REFNSIID aIID, ++ void **aResult) ++{ ++ *aResult = nullptr; ++ if (aOuter != nullptr) { ++ return NS_ERROR_NO_AGGREGATION; ++ } ++ ++ nsCOMPtr<nsIClipboard> inst; ++ if (gfxPlatform::IsHeadless()) { ++ inst = new HeadlessClipboard(); ++ } else { ++ RefPtr<nsClipboard> clipboard = new nsClipboard(); ++ nsresult rv = clipboard->Init(); ++ NS_ENSURE_SUCCESS(rv, rv); ++ inst = clipboard; ++ } ++ ++ return inst->QueryInterface(aIID, aResult); ++} ++ + NS_DEFINE_NAMED_CID(NS_WINDOW_CID); + NS_DEFINE_NAMED_CID(NS_CHILD_CID); + NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); +@@ -239,7 +261,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { + { &kNS_SOUND_CID, false, nullptr, nsISoundConstructor, Module::MAIN_PROCESS_ONLY }, + { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor }, + #ifdef MOZ_X11 +- { &kNS_CLIPBOARD_CID, false, nullptr, nsIClipboardConstructor, Module::MAIN_PROCESS_ONLY }, ++ { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor, Module::MAIN_PROCESS_ONLY }, + { &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor }, + { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY }, + #endif diff --git a/www/waterfox/files/patch-bug1387811 b/www/waterfox/files/patch-bug1387811 new file mode 100644 index 000000000000..9198b313f899 --- /dev/null +++ b/www/waterfox/files/patch-bug1387811 @@ -0,0 +1,42 @@ +commit a1341ccf6d63 +Author: Christoph Kerschbaumer <ckerschb@christophkerschbaumer.com> +Date: Sun Aug 6 11:37:09 2017 +0200 + + Bug 1387811 - Follow up for Test within Bug 1381761: CSP JSON is never null, hence it's better to check actual contents of JSON for testing. r=dveditz +--- + dom/security/test/csp/file_data_csp_inheritance.html | 6 ++++-- + dom/security/test/csp/test_data_csp_inheritance.html | 4 +++- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git dom/security/test/csp/file_data_csp_inheritance.html dom/security/test/csp/file_data_csp_inheritance.html +index 299c30255aa6..cbb4865343db 100644 +--- dom/security/test/csp/file_data_csp_inheritance.html ++++ dom/security/test/csp/file_data_csp_inheritance.html +@@ -13,8 +13,10 @@ + var frame = document.getElementById("dataFrame"); + var principal = SpecialPowers.wrap(frame.contentDocument).nodePrincipal; + var cspJSON = principal.cspJSON; +- var result = principal.cspJSON ? "dataInheritsCSP" : "dataDoesNotInheritCSP"; +- window.parent.postMessage({result}, "*"); ++ var cspOBJ = JSON.parse(principal.cspJSON); ++ // make sure we got >>one<< policy ++ var policies = cspOBJ["csp-policies"]; ++ window.parent.postMessage({result: policies.length}, "*"); + </script> + + </body> +diff --git dom/security/test/csp/test_data_csp_inheritance.html dom/security/test/csp/test_data_csp_inheritance.html +index 3afc4f7c02bc..bde2f5617e65 100644 +--- dom/security/test/csp/test_data_csp_inheritance.html ++++ dom/security/test/csp/test_data_csp_inheritance.html +@@ -22,7 +22,9 @@ SimpleTest.waitForExplicitFinish(); + window.addEventListener("message", receiveMessage); + function receiveMessage(event) { + window.removeEventListener("message", receiveMessage); +- is(event.data.result, "dataInheritsCSP", ++ // toplevel CSP should apply to data: URI iframe hence resulting ++ // in 1 applied policy. ++ is(event.data.result, 1, + "data: URI iframe inherits CSP from including context"); + SimpleTest.finish(); + } diff --git a/www/waterfox/files/patch-bug1388020 b/www/waterfox/files/patch-bug1388020 new file mode 100644 index 000000000000..5f1b30cd64f6 --- /dev/null +++ b/www/waterfox/files/patch-bug1388020 @@ -0,0 +1,158 @@ +commit fde468da7b64 +Author: Andrew Osmond <aosmond@mozilla.com> +Date: Tue Apr 10 09:40:02 2018 -0400 + + Bug 1388020. r=nical, a=RyanVM +--- + gfx/gl/GLTextureImage.cpp | 3 +++ + gfx/gl/GLUploadHelpers.cpp | 31 ++++++++++++++++++++++++++++++- + gfx/gl/GLUploadHelpers.h | 2 ++ + gfx/gl/TextureImageEGL.cpp | 4 ++++ + gfx/layers/composite/TextureHost.cpp | 3 +-- + gfx/layers/opengl/TextureHostOGL.cpp | 4 +--- + 6 files changed, 41 insertions(+), 6 deletions(-) + +diff --git gfx/gl/GLTextureImage.cpp gfx/gl/GLTextureImage.cpp +index c91d558af441..65678432dace 100644 +--- gfx/gl/GLTextureImage.cpp ++++ gfx/gl/GLTextureImage.cpp +@@ -149,6 +149,9 @@ BasicTextureImage::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion + &uploadSize, + needInit, + aFrom); ++ if (mTextureFormat == SurfaceFormat::UNKNOWN) { ++ return false; ++ } + + if (uploadSize > 0) { + UpdateUploadSize(uploadSize); +diff --git gfx/gl/GLUploadHelpers.cpp gfx/gl/GLUploadHelpers.cpp +index 75165eedf787..ca1c890a486d 100644 +--- gfx/gl/GLUploadHelpers.cpp ++++ gfx/gl/GLUploadHelpers.cpp +@@ -27,6 +27,23 @@ DataOffset(const IntPoint& aPoint, int32_t aStride, SurfaceFormat aFormat) + return data; + } + ++static bool ++CheckUploadBounds(const IntSize& aDst, const IntSize& aSrc, const IntPoint& aOffset) ++{ ++ if (aOffset.x < 0 || aOffset.y < 0 || ++ aOffset.x >= aSrc.width || ++ aOffset.y >= aSrc.height) { ++ MOZ_ASSERT_UNREACHABLE("Offset outside source bounds"); ++ return false; ++ } ++ if (aDst.width > (aSrc.width - aOffset.x) || ++ aDst.height > (aSrc.height - aOffset.y)) { ++ MOZ_ASSERT_UNREACHABLE("Source has insufficient data"); ++ return false; ++ } ++ return true; ++} ++ + static GLint GetAddressAlignment(ptrdiff_t aAddress) + { + if (!(aAddress & 0x7)) { +@@ -375,6 +392,7 @@ TexImage2DHelper(GLContext* gl, + SurfaceFormat + UploadImageDataToTexture(GLContext* gl, + unsigned char* aData, ++ const gfx::IntSize& aDataSize, + int32_t aStride, + SurfaceFormat aFormat, + const nsIntRegion& aDstRegion, +@@ -498,6 +516,10 @@ UploadImageDataToTexture(GLContext* gl, + // Upload each rect in the region to the texture + for (auto iter = aDstRegion.RectIter(); !iter.Done(); iter.Next()) { + const IntRect& rect = iter.Get(); ++ if (!CheckUploadBounds(rect.Size(), aDataSize, rect.TopLeft())) { ++ return SurfaceFormat::UNKNOWN; ++ } ++ + const unsigned char* rectData = + aData + DataOffset(rect.TopLeft(), aStride, aFormat); + +@@ -534,10 +556,17 @@ UploadSurfaceToTexture(GLContext* gl, + + int32_t stride = aSurface->Stride(); + SurfaceFormat format = aSurface->GetFormat(); ++ gfx::IntSize size = aSurface->GetSize(); ++ if (!CheckUploadBounds(aSize, size, aSrcPoint)) { ++ return SurfaceFormat::UNKNOWN; ++ } ++ + unsigned char* data = aSurface->GetData() + + DataOffset(aSrcPoint, stride, format); ++ size.width -= aSrcPoint.x; ++ size.height -= aSrcPoint.y; + +- return UploadImageDataToTexture(gl, data, stride, format, ++ return UploadImageDataToTexture(gl, data, size, stride, format, + aDstRegion, aTexture, aSize, + aOutUploadSize, aNeedInit, + aTextureUnit, aTextureTarget); +diff --git gfx/gl/GLUploadHelpers.h gfx/gl/GLUploadHelpers.h +index 866d44adbed0..f732d2b3834f 100644 +--- gfx/gl/GLUploadHelpers.h ++++ gfx/gl/GLUploadHelpers.h +@@ -28,6 +28,7 @@ class GLContext; + * \param gl The GL Context to use. + * \param aData Start of image data of surface to upload. + * Corresponds to the first pixel of the texture. ++ * \param aDataSize The image data's size. + * \param aStride The image data's stride. + * \param aFormat The image data's format. + * \param aDstRegion Region of the texture to upload. +@@ -46,6 +47,7 @@ class GLContext; + gfx::SurfaceFormat + UploadImageDataToTexture(GLContext* gl, + unsigned char* aData, ++ const gfx::IntSize& aDataSize, + int32_t aStride, + gfx::SurfaceFormat aFormat, + const nsIntRegion& aDstRegion, +diff --git gfx/gl/TextureImageEGL.cpp gfx/gl/TextureImageEGL.cpp +index 87a547c26925..3bb2987d1da5 100644 +--- gfx/gl/TextureImageEGL.cpp ++++ gfx/gl/TextureImageEGL.cpp +@@ -119,6 +119,10 @@ TextureImageEGL::DirectUpdate(gfx::DataSourceSurface* aSurf, const nsIntRegion& + &uploadSize, + needInit, + aFrom); ++ if (mTextureFormat == SurfaceFormat::UNKNOWN) { ++ return false; ++ } ++ + if (uploadSize > 0) { + UpdateUploadSize(uploadSize); + } +diff --git gfx/layers/composite/TextureHost.cpp gfx/layers/composite/TextureHost.cpp +index e7d87e238913..c93037384744 100644 +--- gfx/layers/composite/TextureHost.cpp ++++ gfx/layers/composite/TextureHost.cpp +@@ -888,8 +888,7 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) + mFirstSource = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::RGB_FROM_YCBCR); + mFirstSource->SetOwner(this); + } +- mFirstSource->Update(surf, aRegion); +- return true; ++ return mFirstSource->Update(surf, aRegion); + } + + RefPtr<DataTextureSource> srcY; +diff --git gfx/layers/opengl/TextureHostOGL.cpp gfx/layers/opengl/TextureHostOGL.cpp +index 02c398b51fe7..ec6ba913123f 100644 +--- gfx/layers/opengl/TextureHostOGL.cpp ++++ gfx/layers/opengl/TextureHostOGL.cpp +@@ -161,9 +161,7 @@ TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface, + } + } + +- mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset); +- +- return true; ++ return mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset); + } + + void diff --git a/www/waterfox/files/patch-bug1388319 b/www/waterfox/files/patch-bug1388319 new file mode 100644 index 000000000000..8b26989437d1 --- /dev/null +++ b/www/waterfox/files/patch-bug1388319 @@ -0,0 +1,30 @@ +commit e572d7e6e7cf +Author: Xidorn Quan <me@upsuper.org> +Date: Tue Aug 8 22:41:32 2017 +1000 + + Bug 1388319 - Mark ServoStyleSet dirty in its Init. r=emilio + + MozReview-Commit-ID: 804KasIiS6E + + --HG-- + extra : rebase_source : 36eb21c5ffc4321aef652947455e73970419803a +--- + layout/style/ServoStyleSet.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git layout/style/ServoStyleSet.cpp layout/style/ServoStyleSet.cpp +index adb3cba922d2..a1cd15903ade 100644 +--- layout/style/ServoStyleSet.cpp ++++ layout/style/ServoStyleSet.cpp +@@ -81,8 +81,9 @@ ServoStyleSet::Init(nsPresContext* aPresContext, nsBindingManager* aBindingManag + } + } + +- // No need to Servo_StyleSet_FlushStyleSheets because we just created the +- // mRawSet, so there was nothing to flush. ++ // We added prefilled stylesheets into mRawSet, so the stylist is dirty. ++ // The Stylist should be updated later when necessary. ++ SetStylistStyleSheetsDirty(); + } + + void diff --git a/www/waterfox/files/patch-bug1388744 b/www/waterfox/files/patch-bug1388744 new file mode 100644 index 000000000000..abee54061188 --- /dev/null +++ b/www/waterfox/files/patch-bug1388744 @@ -0,0 +1,14 @@ +Unbreak pingsender build on Tier3 archs + +--- toolkit/crashreporter/google-breakpad/src/third_party/curl/curlbuild.h ++++ toolkit/crashreporter/google-breakpad/src/third_party/curl/curlbuild.h +@@ -154,8 +154,7 @@ + #endif + + /* The size of `long', as computed by sizeof. */ +-#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \ +- defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABI64) ++#if defined(_M_X64) || defined(__LP64__) + #define CURL_SIZEOF_LONG 8 + #else + #define CURL_SIZEOF_LONG 4 diff --git a/www/waterfox/files/patch-bug1393235 b/www/waterfox/files/patch-bug1393235 new file mode 100644 index 000000000000..c7586334a05d --- /dev/null +++ b/www/waterfox/files/patch-bug1393235 @@ -0,0 +1,88 @@ +commit 9398bd6f4378 +Author: Eric Rahm <erahm@mozilla.com> +Date: Tue Aug 22 19:30:46 2017 -0700 + + Bug 1393235 - Fix improper usages of string functions. r=njn + + This fixes usages of `Find`, `RFind` and the equality operator that kind of + work right now but will break with the proper type checking of a templatized + version of the string classes. + + For `Find` and `RFind` it appears that `nsCString::(R)Find("foo", 0)` calls + were being coerced to the `Find(char*, bool, int, int)` versions. The intent was + probably to just start searching from position zero. + + For the equality operator, the type of nullptr is nullptr_t rather than + char(16_t)* so we'd need to add an operator overload that takes nullptr_t. In + this case just using `IsVoid` is probably more appropriate. + + --HG-- + extra : rebase_source : 50f78519084012ca669da0a211c489520c11d6b6 +--- + docshell/base/nsDefaultURIFixup.cpp | 2 +- + dom/media/gmp/ChromiumCDMChild.cpp | 2 +- + toolkit/components/places/nsNavHistory.cpp | 2 +- + toolkit/components/url-classifier/Classifier.cpp | 4 ++-- + 4 files changed, 5 insertions(+), 5 deletions(-) + +diff --git docshell/base/nsDefaultURIFixup.cpp docshell/base/nsDefaultURIFixup.cpp +index 77e008b15a17..a1a893b8efb2 100644 +--- docshell/base/nsDefaultURIFixup.cpp ++++ docshell/base/nsDefaultURIFixup.cpp +@@ -687,7 +687,7 @@ nsDefaultURIFixup::FixupURIProtocol(const nsACString& aURIString, + // no-scheme.com/query?foo=http://www.foo.com + // user:pass@no-scheme.com + // +- int32_t schemeDelim = uriString.Find("://", 0); ++ int32_t schemeDelim = uriString.Find("://"); + int32_t firstDelim = uriString.FindCharInSet("/:"); + if (schemeDelim <= 0 || + (firstDelim != -1 && schemeDelim > firstDelim)) { +diff --git dom/media/gmp/ChromiumCDMChild.cpp dom/media/gmp/ChromiumCDMChild.cpp +index e99f913622ab..8dc288b4c57e 100644 +--- dom/media/gmp/ChromiumCDMChild.cpp ++++ dom/media/gmp/ChromiumCDMChild.cpp +@@ -232,7 +232,7 @@ ChromiumCDMChild::OnResolveNewSessionPromiseInternal(uint32_t aPromiseId, + // a session it calls OnResolveNewSessionPromise with nullptr as the sessionId. + // We can safely assume this means that we have failed to load a session + // as the other methods specify calling 'OnRejectPromise' when they fail. +- bool loadSuccessful = aSessionId != nullptr; ++ bool loadSuccessful = !aSessionId.IsEmpty(); + GMP_LOG("ChromiumCDMChild::OnResolveNewSessionPromise(pid=%u, sid=%s) " + "resolving %s load session ", + aPromiseId, +diff --git toolkit/components/places/nsNavHistory.cpp toolkit/components/places/nsNavHistory.cpp +index 4e52752529fa..0b01d904b2f7 100644 +--- toolkit/components/places/nsNavHistory.cpp ++++ toolkit/components/places/nsNavHistory.cpp +@@ -1939,7 +1939,7 @@ PlacesSQLQueryBuilder::Where() + + // If we used WHERE already, we inject the conditions + // in place of {ADDITIONAL_CONDITIONS} +- if (mQueryString.Find("{ADDITIONAL_CONDITIONS}", 0) != kNotFound) { ++ if (mQueryString.Find("{ADDITIONAL_CONDITIONS}") != kNotFound) { + nsAutoCString innerCondition; + // If we have condition AND it + if (!mConditions.IsEmpty()) { +diff --git toolkit/components/url-classifier/Classifier.cpp toolkit/components/url-classifier/Classifier.cpp +index 500780150a91..68169925d2d0 100644 +--- toolkit/components/url-classifier/Classifier.cpp ++++ toolkit/components/url-classifier/Classifier.cpp +@@ -992,7 +992,7 @@ Classifier::ScanStoreDir(nsIFile* aDirectory, nsTArray<nsCString>& aTables) + // Both v2 and v4 contain .pset file + nsCString suffix(NS_LITERAL_CSTRING(".pset")); + +- int32_t dot = leafName.RFind(suffix, 0); ++ int32_t dot = leafName.RFind(suffix); + if (dot != -1) { + leafName.Cut(dot, suffix.Length()); + aTables.AppendElement(leafName); +@@ -1582,7 +1582,7 @@ Classifier::LoadMetadata(nsIFile* aDirectory, nsACString& aResult) + rv = file->GetNativeLeafName(tableName); + NS_ENSURE_SUCCESS(rv, rv); + +- int32_t dot = tableName.RFind(METADATA_SUFFIX, 0); ++ int32_t dot = tableName.RFind(METADATA_SUFFIX); + if (dot == -1) { + continue; + } diff --git a/www/waterfox/files/patch-bug1393283 b/www/waterfox/files/patch-bug1393283 new file mode 100644 index 000000000000..b9c763fe47ec --- /dev/null +++ b/www/waterfox/files/patch-bug1393283 @@ -0,0 +1,144 @@ +commit d20c7d929c84 +Author: Ethan <ettseng@mozilla.com> +Date: Fri Sep 1 17:29:44 2017 +0800 + + Bug 1393283 - Use the last ESR version as the spoofed Firefox version. r=tihuang, r=mcmanus +--- + .../test/browser/browser_navigator.js | 2 +- + netwerk/protocol/http/nsHttpHandler.cpp | 16 +++---- + .../resistfingerprinting/nsRFPService.cpp | 56 ++++++++++++++++++++++ + .../components/resistfingerprinting/nsRFPService.h | 3 ++ + 4 files changed, 66 insertions(+), 11 deletions(-) + +diff --git browser/components/resistfingerprinting/test/browser/browser_navigator.js browser/components/resistfingerprinting/test/browser/browser_navigator.js +index 25c393d8bb2a..9f52e34a9451 100644 +--- browser/components/resistfingerprinting/test/browser/browser_navigator.js ++++ browser/components/resistfingerprinting/test/browser/browser_navigator.js +@@ -91,7 +91,7 @@ add_task(async function setup() { + + let appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); + let appVersion = parseInt(appInfo.version); +- let spoofedVersion = appVersion - (appVersion % 10); ++ let spoofedVersion = appVersion - ((appVersion - 3) % 7); + spoofedUserAgent = `Mozilla/5.0 (${SPOOFED_OSCPU}; rv:${spoofedVersion}.0) Gecko/20100101 Firefox/${spoofedVersion}.0`; + }); + +diff --git netwerk/protocol/http/nsHttpHandler.cpp netwerk/protocol/http/nsHttpHandler.cpp +index 31d0f8832732..b957d835b52f 100644 +--- netwerk/protocol/http/nsHttpHandler.cpp ++++ netwerk/protocol/http/nsHttpHandler.cpp +@@ -461,16 +461,12 @@ nsHttpHandler::Init() + mAppVersion.AssignLiteral(MOZ_APP_UA_VERSION); + } + +- // Generating the spoofed userAgent for fingerprinting resistance. +- // The browser version will be rounded down to a multiple of 10. +- // By doing so, the anonymity group will cover more versions instead of one +- // version. +- uint32_t spoofedVersion = mAppVersion.ToInteger(&rv); +- if (NS_SUCCEEDED(rv)) { +- spoofedVersion = (10 - spoofedVersion % 10) + spoofedVersion; +- mSpoofedUserAgent.Assign(nsPrintfCString( +- "Mozilla/5.0 (%s; rv:%d.0) Gecko/%s Firefox/%d.0", +- SPOOFED_OSCPU, spoofedVersion, LEGACY_BUILD_ID, spoofedVersion)); ++ // Generating the spoofed User Agent for fingerprinting resistance. ++ rv = nsRFPService::GetSpoofedUserAgent(mSpoofedUserAgent); ++ if (NS_FAILED(rv)) { ++ // Empty mSpoofedUserAgent to make sure the unsuccessful spoofed UA string ++ // will not be used anywhere. ++ mSpoofedUserAgent.Truncate(); + } + + mSessionStartTime = NowInSeconds(); +diff --git toolkit/components/resistfingerprinting/nsRFPService.cpp toolkit/components/resistfingerprinting/nsRFPService.cpp +index 94554200c3b8..96a2940c04a0 100644 +--- toolkit/components/resistfingerprinting/nsRFPService.cpp ++++ toolkit/components/resistfingerprinting/nsRFPService.cpp +@@ -18,10 +18,13 @@ + #include "nsServiceManagerUtils.h" + #include "nsString.h" + #include "nsXULAppAPI.h" ++#include "nsPrintfCString.h" + + #include "nsIObserverService.h" + #include "nsIPrefBranch.h" + #include "nsIPrefService.h" ++#include "nsIXULAppInfo.h" ++#include "nsIXULRuntime.h" + #include "nsJSUtils.h" + + #include "prenv.h" +@@ -162,6 +165,59 @@ nsRFPService::GetSpoofedPresentedFrames(double aTime, uint32_t aWidth, uint32_t + return NSToIntFloor(time * sVideoFramesPerSec * ((100 - boundedDroppedRatio) / 100.0)); + } + ++/* static */ ++nsresult ++nsRFPService::GetSpoofedUserAgent(nsACString &userAgent) ++{ ++ // This function generates the spoofed value of User Agent. ++ // We spoof the values of the platform and Firefox version, which could be ++ // used as fingerprinting sources to identify individuals. ++ // Reference of the format of User Agent: ++ // https://developer.mozilla.org/en-US/docs/Web/API/NavigatorID/userAgent ++ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent ++ ++ nsresult rv; ++ nsCOMPtr<nsIXULAppInfo> appInfo = ++ do_GetService("@mozilla.org/xre/app-info;1", &rv); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ nsAutoCString appVersion; ++ rv = appInfo->GetVersion(appVersion); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ // The browser version will be spoofed as the last ESR version. ++ // By doing so, the anonymity group will cover more versions instead of one ++ // version. ++ uint32_t firefoxVersion = appVersion.ToInteger(&rv); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ // Starting from Firefox 10, Firefox ESR was released once every seven ++ // Firefox releases, e.g. Firefox 10, 17, 24, 31, and so on. ++ // We infer the last and closest ESR version based on this rule. ++ nsCOMPtr<nsIXULRuntime> runtime = ++ do_GetService("@mozilla.org/xre/runtime;1", &rv); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ nsAutoCString updateChannel; ++ rv = runtime->GetDefaultUpdateChannel(updateChannel); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ // If we are running in Firefox ESR, determine whether the formula of ESR ++ // version has changed. Once changed, we must update the formula in this ++ // function. ++ if (updateChannel.Equals("esr")) { ++ MOZ_ASSERT(((firefoxVersion % 7) == 3), ++ "Please udpate ESR version formula in nsRFPService.cpp"); ++ } ++ ++ uint32_t spoofedVersion = firefoxVersion - ((firefoxVersion - 3) % 7); ++ userAgent.Assign(nsPrintfCString( ++ "Mozilla/5.0 (%s; rv:%d.0) Gecko/%s Firefox/%d.0", ++ SPOOFED_OSCPU, spoofedVersion, LEGACY_BUILD_ID, spoofedVersion)); ++ ++ return rv; ++} ++ + nsresult + nsRFPService::Init() + { +diff --git toolkit/components/resistfingerprinting/nsRFPService.h toolkit/components/resistfingerprinting/nsRFPService.h +index cf1f688bb992..bad80383883b 100644 +--- toolkit/components/resistfingerprinting/nsRFPService.h ++++ toolkit/components/resistfingerprinting/nsRFPService.h +@@ -49,6 +49,9 @@ public: + static uint32_t GetSpoofedDroppedFrames(double aTime, uint32_t aWidth, uint32_t aHeight); + static uint32_t GetSpoofedPresentedFrames(double aTime, uint32_t aWidth, uint32_t aHeight); + ++ // This method generates the spoofed value of User Agent. ++ static nsresult GetSpoofedUserAgent(nsACString &userAgent); ++ + private: + nsresult Init(); + diff --git a/www/waterfox/files/patch-bug1393627 b/www/waterfox/files/patch-bug1393627 new file mode 100644 index 000000000000..759cbffe52bc --- /dev/null +++ b/www/waterfox/files/patch-bug1393627 @@ -0,0 +1,30 @@ +commit 7f3f4f7f6ad3 +Author: Francois Marier <francois@mozilla.com> +Date: Fri Nov 3 11:44:43 2017 -0700 + + Bug 1393627 - Expose the full tracking protection UI preferences. r=mossop, a=ritu + + MozReview-Commit-ID: KyDBuHyDPLP + + --HG-- + extra : source : 516690579442aecc1bea191e905f019acfad5b48 +--- + browser/app/profile/firefox.js | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git browser/app/profile/firefox.js browser/app/profile/firefox.js +index 137462dc857e..9e08a0f166f9 100644 +--- browser/app/profile/firefox.js ++++ browser/app/profile/firefox.js +@@ -1511,11 +1511,7 @@ pref("browser.ping-centre.production.endpoint", "https://tiles.services.mozilla. + // Enable GMP support in the addon manager. + pref("media.gmp-provider.enabled", true); + +-#ifdef NIGHTLY_BUILD + pref("privacy.trackingprotection.ui.enabled", true); +-#else +-pref("privacy.trackingprotection.ui.enabled", false); +-#endif + pref("privacy.trackingprotection.introCount", 0); + pref("privacy.trackingprotection.introURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tracking-protection/start/"); + diff --git a/www/waterfox/files/patch-bug1394146 b/www/waterfox/files/patch-bug1394146 new file mode 100644 index 000000000000..d3cba27a5a88 --- /dev/null +++ b/www/waterfox/files/patch-bug1394146 @@ -0,0 +1,119 @@ +commit f8221b58e542 +Author: Sean Stangl <sstangl@mozilla.com> +Date: Thu Sep 21 15:37:00 2017 -0400 + + Bug 1394146 - Avoid overflow on backwards iteration of IC entries. r=jandem, a=sledru + + --HG-- + extra : source : 9f05ef54c84d9b63fb3ad2dd2916df34cb35df8d + extra : histedit_source : 753ccc8652983bb35d3a1f9f89638902d3b0a2a5 +--- + js/src/jit/BaselineJIT.cpp | 11 +++++++++-- + js/src/jit/IonControlFlow.cpp | 16 ++++++++++++---- + 2 files changed, 21 insertions(+), 6 deletions(-) + +diff --git js/src/jit/BaselineJIT.cpp js/src/jit/BaselineJIT.cpp +index 3e25fd7b7120..baec7b63b8f0 100644 +--- js/src/jit/BaselineJIT.cpp ++++ js/src/jit/BaselineJIT.cpp +@@ -669,12 +669,16 @@ BaselineScript::maybeICEntryFromPCOffset(uint32_t pcOffset) + if (!ComputeBinarySearchMid(this, pcOffset, &mid)) + return nullptr; + ++ MOZ_ASSERT(mid < numICEntries()); ++ + // Found an IC entry with a matching PC offset. Search backward, and then + // forward from this IC entry, looking for one with the same PC offset which + // has isForOp() set. +- for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) { ++ for (size_t i = mid; icEntry(i).pcOffset() == pcOffset; i--) { + if (icEntry(i).isForOp()) + return &icEntry(i); ++ if (i == 0) ++ break; + } + for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++) { + if (icEntry(i).isForOp()) +@@ -728,10 +732,13 @@ BaselineScript::callVMEntryFromPCOffset(uint32_t pcOffset) + // inserted by VM calls. + size_t mid; + MOZ_ALWAYS_TRUE(ComputeBinarySearchMid(this, pcOffset, &mid)); ++ MOZ_ASSERT(mid < numICEntries()); + +- for (size_t i = mid; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i--) { ++ for (size_t i = mid; icEntry(i).pcOffset() == pcOffset; i--) { + if (icEntry(i).kind() == ICEntry::Kind_CallVM) + return icEntry(i); ++ if (i == 0) ++ break; + } + for (size_t i = mid+1; i < numICEntries() && icEntry(i).pcOffset() == pcOffset; i++) { + if (icEntry(i).kind() == ICEntry::Kind_CallVM) +diff --git js/src/jit/IonControlFlow.cpp js/src/jit/IonControlFlow.cpp +index 4f27cd53dcaa..8d8a796d3f3b 100644 +--- js/src/jit/IonControlFlow.cpp ++++ js/src/jit/IonControlFlow.cpp +@@ -1619,7 +1619,7 @@ ControlFlowGenerator::processBreak(JSOp op, jssrcnote* sn) + DebugOnly<bool> found = false; + + if (SN_TYPE(sn) == SRC_BREAK2LABEL) { +- for (size_t i = labels_.length() - 1; i < labels_.length(); i--) { ++ for (size_t i = labels_.length() - 1; ; i--) { + CFGState& cfg = cfgStack_[labels_[i].cfgEntry]; + MOZ_ASSERT(cfg.state == CFGState::LABEL); + if (cfg.stopAt == target) { +@@ -1627,9 +1627,11 @@ ControlFlowGenerator::processBreak(JSOp op, jssrcnote* sn) + found = true; + break; + } ++ if (i == 0) ++ break; + } + } else { +- for (size_t i = loops_.length() - 1; i < loops_.length(); i--) { ++ for (size_t i = loops_.length() - 1; ; i--) { + CFGState& cfg = cfgStack_[loops_[i].cfgEntry]; + MOZ_ASSERT(cfg.isLoop()); + if (cfg.loop.exitpc == target) { +@@ -1637,6 +1639,8 @@ ControlFlowGenerator::processBreak(JSOp op, jssrcnote* sn) + found = true; + break; + } ++ if (i == 0) ++ break; + } + } + +@@ -1665,7 +1669,7 @@ ControlFlowGenerator::processContinue(JSOp op) + // Find the target loop. + CFGState* found = nullptr; + jsbytecode* target = pc + GetJumpOffset(pc); +- for (size_t i = loops_.length() - 1; i < loops_.length(); i--) { ++ for (size_t i = loops_.length() - 1; ; i--) { + // +1 to skip JSOP_JUMPTARGET. + if (loops_[i].continuepc == target + 1 || + EffectiveContinue(loops_[i].continuepc) == target) +@@ -1673,6 +1677,8 @@ ControlFlowGenerator::processContinue(JSOp op) + found = &cfgStack_[loops_[i].cfgEntry]; + break; + } ++ if (i == 0) ++ break; + } + + // There must always be a valid target loop structure. If not, there's +@@ -1698,11 +1704,13 @@ ControlFlowGenerator::processSwitchBreak(JSOp op) + // Find the target switch. + CFGState* found = nullptr; + jsbytecode* target = pc + GetJumpOffset(pc); +- for (size_t i = switches_.length() - 1; i < switches_.length(); i--) { ++ for (size_t i = switches_.length() - 1; ; i--) { + if (switches_[i].continuepc == target) { + found = &cfgStack_[switches_[i].cfgEntry]; + break; + } ++ if (i == 0) ++ break; + } + + // There must always be a valid target loop structure. If not, there's diff --git a/www/waterfox/files/patch-bug1394601 b/www/waterfox/files/patch-bug1394601 new file mode 100644 index 000000000000..582385d1f60c --- /dev/null +++ b/www/waterfox/files/patch-bug1394601 @@ -0,0 +1,26 @@ +commit 99cb2b5a1879 +Author: Francois Marier <francois@mozilla.com> +Date: Mon Aug 28 17:06:00 2017 -0700 + + Bug 1394601 - Log an error when the Google API key is missing during Safe Browsing initialization. r=gcp + + MozReview-Commit-ID: DNwa9lR0J6K + + --HG-- + extra : rebase_source : 0a547c0cf88e1ed09268cbb810abaaca09e98531 +--- + toolkit/components/url-classifier/SafeBrowsing.jsm | 1 + + 1 file changed, 1 insertion(+) + +diff --git toolkit/components/url-classifier/SafeBrowsing.jsm toolkit/components/url-classifier/SafeBrowsing.jsm +index 051432393539..32cab18c187f 100644 +--- toolkit/components/url-classifier/SafeBrowsing.jsm ++++ toolkit/components/url-classifier/SafeBrowsing.jsm +@@ -343,6 +343,7 @@ this.SafeBrowsing = { + let googleKey = Services.urlFormatter.formatURL("%GOOGLE_API_KEY%").trim(); + if ((provider == "google" || provider == "google4") && + (!googleKey || googleKey == "no-google-api-key")) { ++ log("Missing Google API key, clearing updateURL and gethashURL."); + updateURL= ""; + gethashURL= ""; + } diff --git a/www/waterfox/files/patch-bug1395246 b/www/waterfox/files/patch-bug1395246 new file mode 100644 index 000000000000..ba7e6fecbcda --- /dev/null +++ b/www/waterfox/files/patch-bug1395246 @@ -0,0 +1,83 @@ +commit be7a92ebe633 +Author: Randell Jesup <rjesup@jesup.org> +Date: Thu Jun 7 15:26:25 2018 -0400 + + Bug 1395246 - Nullcheck DataChannel SendPacket calls, add some diagnostics. r=drno, a=RyanVM + + --HG-- + extra : source : 4d7a8d001f087fc500be3b4ca2469310fa39e6be +--- + netwerk/sctp/datachannel/DataChannel.cpp | 12 +++++++++++- + netwerk/sctp/datachannel/DataChannel.h | 8 ++++++-- + 2 files changed, 17 insertions(+), 3 deletions(-) + +diff --git netwerk/sctp/datachannel/DataChannel.cpp netwerk/sctp/datachannel/DataChannel.cpp +index b07cfaa4c273d..d7a9b64f155b7 100644 +--- netwerk/sctp/datachannel/DataChannel.cpp ++++ netwerk/sctp/datachannel/DataChannel.cpp +@@ -220,6 +220,9 @@ DataChannelConnection::DataChannelConnection(DataConnectionListener *listener, + mRemotePort = 0; + LOG(("Constructor DataChannelConnection=%p, listener=%p", this, mListener.get())); + mInternalIOThread = nullptr; ++#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED ++ mShutdown = false; ++#endif + } + + DataChannelConnection::~DataChannelConnection() +@@ -307,6 +310,10 @@ void DataChannelConnection::DestroyOnSTS(struct socket *aMasterSocket, + if (aMasterSocket) + usrsctp_close(aMasterSocket); + ++#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED ++ mShutdown = true; ++#endif ++ + disconnect_all(); + } + +@@ -657,7 +664,10 @@ int + DataChannelConnection::SendPacket(unsigned char data[], size_t len, bool release) + { + //LOG(("%p: SCTP/DTLS sent %ld bytes", this, len)); +- int res = mTransportFlow->SendPacket(data, len) < 0 ? 1 : 0; ++ int res = 0; ++ if (mTransportFlow) { ++ res = mTransportFlow->SendPacket(data, len) < 0 ? 1 : 0; ++ } + if (release) + delete [] data; + return res; +@@ -670,6 +680,7 @@ DataChannelConnection::SctpDtlsOutput(void *addr, void *buffer, size_t length, + { + DataChannelConnection *peer = static_cast<DataChannelConnection *>(addr); + int res; ++ MOZ_DIAGNOSTIC_ASSERT(!peer->mShutdown); + + if (MOZ_LOG_TEST(gSCTPLog, LogLevel::Debug)) { + char *buf; +diff --git netwerk/sctp/datachannel/DataChannel.h netwerk/sctp/datachannel/DataChannel.h +index 8141ed64e3176..eaf2055aacaa0 100644 +--- netwerk/sctp/datachannel/DataChannel.h ++++ netwerk/sctp/datachannel/DataChannel.h +@@ -113,8 +113,8 @@ public: + virtual void NotifyDataChannel(already_AddRefed<DataChannel> channel) = 0; + }; + +- explicit DataChannelConnection(DataConnectionListener *listener, +- nsIEventTarget *aTarget); ++ DataChannelConnection(DataConnectionListener *listener, ++ nsIEventTarget *aTarget); + + bool Init(unsigned short aPort, uint16_t aNumStreams, bool aUsingDtls); + void Destroy(); // So we can spawn refs tied to runnables in shutdown +@@ -285,6 +285,9 @@ private: + bool mUsingDtls; + + nsCOMPtr<nsIThread> mInternalIOThread; ++#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED ++ bool mShutdown; ++#endif + }; + + #define ENSURE_DATACONNECTION \ diff --git a/www/waterfox/files/patch-bug1395486 b/www/waterfox/files/patch-bug1395486 new file mode 100644 index 000000000000..06309b87a661 --- /dev/null +++ b/www/waterfox/files/patch-bug1395486 @@ -0,0 +1,53 @@ +commit c978a96e849c +Author: Chung-Sheng Fu <cfu@mozilla.com> +Date: Thu Aug 31 17:06:22 2017 +0800 + + Bug 1395486 - Move resource://gre-resource/plaintext.css to resource://content-accessible/plaintext.css. r=heycam + + MozReview-Commit-ID: Efz2Z78W2ix + + --HG-- + extra : rebase_source : 0522f382acd14372c6fea0a695f1d09300810912 +--- + layout/style/jar.mn | 1 - + layout/style/moz.build | 1 + + parser/html/nsHtml5PlainTextUtils.cpp | 2 +- + 3 files changed, 2 insertions(+), 2 deletions(-) + +diff --git layout/style/jar.mn layout/style/jar.mn +index 81af0f7540fc..4a4418218290 100644 +--- layout/style/jar.mn ++++ layout/style/jar.mn +@@ -6,7 +6,6 @@ toolkit.jar: + * res/ua.css (res/ua.css) + * res/html.css (res/html.css) + res/quirk.css (res/quirk.css) +- res/plaintext.css (res/plaintext.css) + res/counterstyles.css (res/counterstyles.css) + res/noscript.css (res/noscript.css) + res/noframes.css (res/noframes.css) +diff --git layout/style/moz.build layout/style/moz.build +index d4fbd0fef384..b5b19ee62232 100644 +--- layout/style/moz.build ++++ layout/style/moz.build +@@ -304,6 +304,7 @@ RESOURCE_FILES += [ + + CONTENT_ACCESSIBLE_FILES += [ + 'ImageDocument.css', ++ 'res/plaintext.css', + 'res/viewsource.css', + 'TopLevelImageDocument.css', + 'TopLevelVideoDocument.css', +diff --git parser/html/nsHtml5PlainTextUtils.cpp parser/html/nsHtml5PlainTextUtils.cpp +index e68522987784..920c5eee89d1 100644 +--- parser/html/nsHtml5PlainTextUtils.cpp ++++ parser/html/nsHtml5PlainTextUtils.cpp +@@ -22,7 +22,7 @@ nsHtml5PlainTextUtils::NewLinkAttributes() + nsHtml5String type = nsHtml5Portability::newStringFromLiteral("text/css"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_TYPE, type, -1); + nsHtml5String href = nsHtml5Portability::newStringFromLiteral( +- "resource://gre-resources/plaintext.css"); ++ "resource://content-accessible/plaintext.css"); + linkAttrs->addAttribute(nsHtml5AttributeName::ATTR_HREF, href, -1); + + nsresult rv; diff --git a/www/waterfox/files/patch-bug1396722 b/www/waterfox/files/patch-bug1396722 new file mode 100644 index 000000000000..55e085860e96 --- /dev/null +++ b/www/waterfox/files/patch-bug1396722 @@ -0,0 +1,1426 @@ +commit 00beb3311073 +Author: Karl Tomlinson <karlt+@karlt.net> +Date: Tue Sep 5 09:16:01 2017 +1200 + + bug 1396722 remove no-op ReleaseStyleContext() r=stransky+263117 + + MozReview-Commit-ID: DgKM0wrStrk + + --HG-- + extra : rebase_source : a26fdc5e5d6c63e21bb98a19ee7bf58042f9b3ba +--- + widget/gtk/WidgetStyleCache.cpp | 9 +- + widget/gtk/WidgetStyleCache.h | 15 +- + widget/gtk/gtk3drawing.cpp | 306 +++++++++++++++------------------------- + widget/gtk/nsLookAndFeel.cpp | 63 +++------ + 4 files changed, 142 insertions(+), 251 deletions(-) + +diff --git widget/gtk/WidgetStyleCache.cpp widget/gtk/WidgetStyleCache.cpp +index bf0c2d080c17..39b7893df3bd 100644 +--- widget/gtk/WidgetStyleCache.cpp ++++ widget/gtk/WidgetStyleCache.cpp +@@ -1220,8 +1220,8 @@ ResetWidgetCache(void) + } + + GtkStyleContext* +-ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection, +- GtkStateFlags aStateFlags, StyleFlags aFlags) ++GetStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection, ++ GtkStateFlags aStateFlags, StyleFlags aFlags) + { + GtkStyleContext* style; + if (gtk_check_version(3, 20, 0) != nullptr) { +@@ -1276,8 +1276,3 @@ ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection, + } + return style; + } +- +-void +-ReleaseStyleContext(GtkStyleContext* aStyleContext) +-{ +-} +diff --git widget/gtk/WidgetStyleCache.h widget/gtk/WidgetStyleCache.h +index 2cbb5f96076f..6cce492de2b6 100644 +--- widget/gtk/WidgetStyleCache.h ++++ widget/gtk/WidgetStyleCache.h +@@ -33,14 +33,15 @@ CreateCSSNode(const char* aName, + GtkStyleContext* aParentStyle, + GType aType = G_TYPE_NONE); + +-// Callers must call ReleaseStyleContext() on the returned context. ++/* ++ * Returns a pointer to a style context for the specified node and state. ++ * The context is owned by WidgetStyleCache. Do not unref. ++ */ + GtkStyleContext* +-ClaimStyleContext(WidgetNodeType aNodeType, +- GtkTextDirection aDirection = GTK_TEXT_DIR_NONE, +- GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL, +- StyleFlags aFlags = NO_STYLE_FLAGS); +-void +-ReleaseStyleContext(GtkStyleContext* style); ++GetStyleContext(WidgetNodeType aNodeType, ++ GtkTextDirection aDirection = GTK_TEXT_DIR_NONE, ++ GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL, ++ StyleFlags aFlags = NO_STYLE_FLAGS); + + void + ResetWidgetCache(void); +diff --git widget/gtk/gtk3drawing.cpp widget/gtk/gtk3drawing.cpp +index 73bd1987fd39..4c562b380095 100644 +--- widget/gtk/gtk3drawing.cpp ++++ widget/gtk/gtk3drawing.cpp +@@ -100,10 +100,9 @@ moz_gtk_refresh() + gtk_check_version(3, 20, 0) != nullptr) + { + // Deprecated for Gtk >= 3.20+ +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_TAB_TOP); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_TAB_TOP); + gtk_style_context_get_style(style, + "has-tab-gap", ¬ebook_has_tab_gap, NULL); +- ReleaseStyleContext(style); + } + else { + notebook_has_tab_gap = true; +@@ -149,31 +148,28 @@ moz_gtk_get_focus_outline_size(GtkStyleContext* style, + gint + moz_gtk_get_focus_outline_size(gint* focus_h_width, gint* focus_v_width) + { +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_ENTRY); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_ENTRY); + moz_gtk_get_focus_outline_size(style, focus_h_width, focus_v_width); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + + gint + moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding) + { +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_MENUITEM); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_MENUITEM); + gtk_style_context_get_style(style, + "horizontal-padding", horizontal_padding, + nullptr); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + + gint + moz_gtk_checkmenuitem_get_horizontal_padding(gint* horizontal_padding) + { +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_CHECKMENUITEM); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_CHECKMENUITEM); + gtk_style_context_get_style(style, + "horizontal-padding", horizontal_padding, + nullptr); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -183,11 +179,10 @@ moz_gtk_button_get_default_overflow(gint* border_top, gint* border_left, + { + GtkBorder* default_outside_border; + +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_BUTTON); + gtk_style_context_get_style(style, + "default-outside-border", &default_outside_border, + NULL); +- ReleaseStyleContext(style); + + if (default_outside_border) { + *border_top = default_outside_border->top; +@@ -207,11 +202,10 @@ moz_gtk_button_get_default_border(gint* border_top, gint* border_left, + { + GtkBorder* default_border; + +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_BUTTON); + gtk_style_context_get_style(style, + "default-border", &default_border, + NULL); +- ReleaseStyleContext(style); + + if (default_border) { + *border_top = default_border->top; +@@ -231,12 +225,11 @@ moz_gtk_splitter_get_metrics(gint orientation, gint* size) + { + GtkStyleContext *style; + if (orientation == GTK_ORIENTATION_HORIZONTAL) { +- style = ClaimStyleContext(MOZ_GTK_SPLITTER_HORIZONTAL); ++ style = GetStyleContext(MOZ_GTK_SPLITTER_HORIZONTAL); + } else { +- style = ClaimStyleContext(MOZ_GTK_SPLITTER_VERTICAL); ++ style = GetStyleContext(MOZ_GTK_SPLITTER_VERTICAL); + } + gtk_style_context_get_style(style, "handle_size", size, NULL); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -244,15 +237,13 @@ static gint + moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW, direction); + + gtk_style_context_save(style); + gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_style_context_restore(style); + +- ReleaseStyleContext(style); +- + return MOZ_GTK_SUCCESS; + } + +@@ -351,9 +342,8 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect, + if (inconsistent) + state_flags = static_cast<GtkStateFlags>(state_flags|GTK_STATE_FLAG_INCONSISTENT); + +- style = ClaimStyleContext(isradio ? MOZ_GTK_RADIOBUTTON : +- MOZ_GTK_CHECKBUTTON, +- direction, state_flags); ++ style = GetStyleContext(isradio ? MOZ_GTK_RADIOBUTTON : MOZ_GTK_CHECKBUTTON, ++ direction, state_flags); + + if (gtk_check_version(3, 20, 0) == nullptr) { + gtk_render_background(style, cr, x, y, width, height); +@@ -375,8 +365,6 @@ moz_gtk_toggle_paint(cairo_t *cr, GdkRectangle* rect, + } + } + +- ReleaseStyleContext(style); +- + return MOZ_GTK_SUCCESS; + } + +@@ -460,7 +448,7 @@ static void + moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, + int* height) + { +- GtkStyleContext* style = ClaimStyleContext(aGtkWidgetType); ++ GtkStyleContext* style = GetStyleContext(aGtkWidgetType); + GtkStateFlags state_flags = gtk_style_context_get_state(style); + gtk_style_context_get(style, state_flags, + "min-height", height, +@@ -471,7 +459,6 @@ moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, + gtk_style_context_get_border(style, state_flags, &border); + gtk_style_context_get_padding(style, state_flags, &padding); + gtk_style_context_get_margin(style, state_flags, &margin); +- ReleaseStyleContext(style); + + *width += border.left + border.right + margin.left + margin.right + + padding.left + padding.right; +@@ -666,7 +653,7 @@ moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, + MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : + MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; + MozGtkSize thumbSize = GetMinMarginBox(thumb); +- style = ClaimStyleContext(widget, direction); ++ style = GetStyleContext(widget, direction); + MozGtkSize trackSize = GetMinContentBox(style); + trackSize.Include(thumbSize); + trackSize += GetMarginBorderPadding(style); +@@ -681,11 +668,10 @@ moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, + rect.height = trackSize.height; + } + } else { +- style = ClaimStyleContext(widget, direction); ++ style = GetStyleContext(widget, direction); + } + + moz_gtk_draw_styled_frame(style, cr, &rect, state->focused); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -696,18 +682,16 @@ moz_gtk_scrollbar_paint(WidgetNodeType widget, + GtkWidgetState* state, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(widget, direction); ++ GtkStyleContext* style = GetStyleContext(widget, direction); + moz_gtk_update_scrollbar_style(style, widget, direction); + + moz_gtk_draw_styled_frame(style, cr, rect, state->focused); + +- ReleaseStyleContext(style); +- style = ClaimStyleContext((widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) ? +- MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL : +- MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL, +- direction); ++ style = GetStyleContext((widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) ? ++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL : ++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL, ++ direction); + moz_gtk_draw_styled_frame(style, cr, rect, state->focused); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -721,7 +705,7 @@ moz_gtk_scrollbar_thumb_paint(WidgetNodeType widget, + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); + + GdkRectangle rect = *aRect; +- GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags); ++ GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); + InsetByMargin(&rect, style); + + gtk_render_slider(style, cr, +@@ -732,7 +716,6 @@ moz_gtk_scrollbar_thumb_paint(WidgetNodeType widget, + (widget == MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL) ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL); + +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -741,10 +724,9 @@ static gint + moz_gtk_spin_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON, direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_SPINBUTTON, direction); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -753,7 +735,7 @@ moz_gtk_spin_updown_paint(cairo_t *cr, GdkRectangle* rect, + gboolean isDown, GtkWidgetState* state, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON, direction, ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_SPINBUTTON, direction, + GetStateFlagsFromGtkWidgetState(state)); + + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); +@@ -772,7 +754,6 @@ moz_gtk_spin_updown_paint(cairo_t *cr, GdkRectangle* rect, + arrow_rect.x, arrow_rect.y, + arrow_rect.width); + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -793,7 +774,7 @@ moz_gtk_scale_paint(cairo_t *cr, GdkRectangle* rect, + WidgetNodeType widget = (flags == GTK_ORIENTATION_HORIZONTAL) ? + MOZ_GTK_SCALE_TROUGH_HORIZONTAL : + MOZ_GTK_SCALE_TROUGH_VERTICAL; +- style = ClaimStyleContext(widget, direction, state_flags); ++ style = GetStyleContext(widget, direction, state_flags); + gtk_style_context_get_margin(style, state_flags, &margin); + + // Clamp the dimension perpendicular to the direction that the slider crosses +@@ -817,7 +798,6 @@ moz_gtk_scale_paint(cairo_t *cr, GdkRectangle* rect, + gtk_render_focus(style, cr, + rect->x, rect->y, rect->width, rect->height); + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -846,9 +826,8 @@ moz_gtk_scale_thumb_paint(cairo_t *cr, GdkRectangle* rect, + WidgetNodeType widget = (flags == GTK_ORIENTATION_HORIZONTAL) ? + MOZ_GTK_SCALE_THUMB_HORIZONTAL : + MOZ_GTK_SCALE_THUMB_VERTICAL; +- style = ClaimStyleContext(widget, direction, state_flags); ++ style = GetStyleContext(widget, direction, state_flags); + gtk_render_slider(style, cr, x, y, thumb_width, thumb_height, flags); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -859,11 +838,10 @@ moz_gtk_gripper_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_GRIPPER, direction, +- GetStateFlagsFromGtkWidgetState(state)); ++ GetStyleContext(MOZ_GTK_GRIPPER, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -872,12 +850,11 @@ moz_gtk_hpaned_paint(cairo_t *cr, GdkRectangle* rect, + GtkWidgetState* state) + { + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL, +- GTK_TEXT_DIR_LTR, +- GetStateFlagsFromGtkWidgetState(state)); ++ GetStyleContext(MOZ_GTK_SPLITTER_SEPARATOR_HORIZONTAL, ++ GTK_TEXT_DIR_LTR, ++ GetStateFlagsFromGtkWidgetState(state)); + gtk_render_handle(style, cr, + rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -886,12 +863,11 @@ moz_gtk_vpaned_paint(cairo_t *cr, GdkRectangle* rect, + GtkWidgetState* state) + { + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL, +- GTK_TEXT_DIR_LTR, +- GetStateFlagsFromGtkWidgetState(state)); ++ GetStyleContext(MOZ_GTK_SPLITTER_SEPARATOR_VERTICAL, ++ GTK_TEXT_DIR_LTR, ++ GetStateFlagsFromGtkWidgetState(state)); + gtk_render_handle(style, cr, + rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -939,26 +915,22 @@ moz_gtk_text_view_paint(cairo_t *cr, GdkRectangle* aRect, + GTK_STATE_FLAG_NORMAL; + + GtkStyleContext* style_frame = +- ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction, state_flags); ++ GetStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction, state_flags); + gtk_render_frame(style_frame, cr, + aRect->x, aRect->y, aRect->width, aRect->height); + + GdkRectangle rect = *aRect; + InsetByBorderPadding(&rect, style_frame); + +- ReleaseStyleContext(style_frame); +- + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_TEXT_VIEW, direction, state_flags); ++ GetStyleContext(MOZ_GTK_TEXT_VIEW, direction, state_flags); + gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); +- ReleaseStyleContext(style); + // There is a separate "text" window, which usually provides the + // background behind the text. However, this is transparent in Ambiance + // for GTK 3.20, in which case the MOZ_GTK_TEXT_VIEW background is + // visible. +- style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW_TEXT, direction, state_flags); ++ style = GetStyleContext(MOZ_GTK_TEXT_VIEW_TEXT, direction, state_flags); + gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -978,23 +950,20 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkRectangle* rect, + * area will be painted differently with other states */ + state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL; + +- style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction); ++ style = GetStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction); + gtk_style_context_get_border(style, state_flags, &border); + xthickness = border.left; + ythickness = border.top; +- ReleaseStyleContext(style); + +- style_tree = ClaimStyleContext(MOZ_GTK_TREEVIEW_VIEW, direction); ++ style_tree = GetStyleContext(MOZ_GTK_TREEVIEW_VIEW, direction); + gtk_render_background(style_tree, cr, + rect->x + xthickness, rect->y + ythickness, + rect->width - 2 * xthickness, + rect->height - 2 * ythickness); +- ReleaseStyleContext(style_tree); + +- style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction); ++ style = GetStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction); + gtk_render_frame(style, cr, + rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1022,8 +991,8 @@ moz_gtk_tree_header_sort_arrow_paint(cairo_t *cr, GdkRectangle* rect, + arrow_rect.height = 11; + arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2; + arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2; +- style = ClaimStyleContext(MOZ_GTK_TREE_HEADER_SORTARROW, direction, +- GetStateFlagsFromGtkWidgetState(state)); ++ style = GetStyleContext(MOZ_GTK_TREE_HEADER_SORTARROW, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + switch (arrow_type) { + case GTK_ARROW_LEFT: + arrow_angle = ARROW_LEFT; +@@ -1042,7 +1011,6 @@ moz_gtk_tree_header_sort_arrow_paint(cairo_t *cr, GdkRectangle* rect, + gtk_render_arrow(style, cr, arrow_angle, + arrow_rect.x, arrow_rect.y, + arrow_rect.width); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1067,15 +1035,14 @@ moz_gtk_treeview_expander_paint(cairo_t *cr, GdkRectangle* rect, + else + state_flags = static_cast<GtkStateFlags>(state_flags&~(checkbox_check_state)); + +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_TREEVIEW_EXPANDER, +- direction, state_flags); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_TREEVIEW_EXPANDER, ++ direction, state_flags); + gtk_render_expander(style, cr, + rect->x, + rect->y, + rect->width, + rect->height); + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1112,11 +1079,10 @@ moz_gtk_combo_box_paint(cairo_t *cr, GdkRectangle* rect, + calculate_arrow_rect(comboBoxArrow, + &arrow_rect, &real_arrow_rect, direction); + +- style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ARROW); ++ style = GetStyleContext(MOZ_GTK_COMBOBOX_ARROW); + gtk_render_arrow(style, cr, ARROW_DOWN, + real_arrow_rect.x, real_arrow_rect.y, + real_arrow_rect.width); +- ReleaseStyleContext(style); + + /* If there is no separator in the theme, there's nothing left to do. */ + GtkWidget* widget = GetWidget(MOZ_GTK_COMBOBOX_SEPARATOR); +@@ -1187,11 +1153,10 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRectangle* rect, + calculate_arrow_rect(GetWidget(MOZ_GTK_BUTTON_ARROW), rect, &arrow_rect, + direction); + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_BUTTON_ARROW, +- direction, state_flags); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_BUTTON_ARROW, ++ direction, state_flags); + gtk_render_arrow(style, cr, arrow_angle, + arrow_rect.x, arrow_rect.y, arrow_rect.width); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1224,11 +1189,10 @@ moz_gtk_combo_box_entry_button_paint(cairo_t *cr, GdkRectangle* rect, + calculate_arrow_rect(GetWidget(MOZ_GTK_COMBOBOX_ENTRY_ARROW), + &arrow_rect, &real_arrow_rect, direction); + +- style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ENTRY_ARROW); ++ style = GetStyleContext(MOZ_GTK_COMBOBOX_ENTRY_ARROW); + gtk_render_arrow(style, cr, ARROW_DOWN, + real_arrow_rect.x, real_arrow_rect.y, + real_arrow_rect.width); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1239,15 +1203,14 @@ moz_gtk_container_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); +- GtkStyleContext* style = ClaimStyleContext(widget_type, direction, +- state_flags); ++ GtkStyleContext* style = GetStyleContext(widget_type, direction, ++ state_flags); + /* this is for drawing a prelight box */ + if (state_flags & GTK_STATE_FLAG_PRELIGHT) { + gtk_render_background(style, cr, + rect->x, rect->y, rect->width, rect->height); + } + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1260,15 +1223,13 @@ moz_gtk_toggle_label_paint(cairo_t *cr, GdkRectangle* rect, + return MOZ_GTK_SUCCESS; + + GtkStyleContext *style = +- ClaimStyleContext(isradio ? MOZ_GTK_RADIOBUTTON_CONTAINER : +- MOZ_GTK_CHECKBUTTON_CONTAINER, +- direction, +- GetStateFlagsFromGtkWidgetState(state)); ++ GetStyleContext(isradio ? MOZ_GTK_RADIOBUTTON_CONTAINER : ++ MOZ_GTK_CHECKBUTTON_CONTAINER, ++ direction, ++ GetStateFlagsFromGtkWidgetState(state)); + gtk_render_focus(style, cr, + rect->x, rect->y, rect->width, rect->height); + +- ReleaseStyleContext(style); +- + return MOZ_GTK_SUCCESS; + } + +@@ -1276,10 +1237,9 @@ static gint + moz_gtk_toolbar_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR, direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_TOOLBAR, direction); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1297,14 +1257,13 @@ moz_gtk_toolbar_separator_paint(cairo_t *cr, GdkRectangle* rect, + const double start_fraction = 0.2; + const double end_fraction = 0.8; + +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_TOOLBAR); + gtk_style_context_get_style(style, + "wide-separators", &wide_separators, + "separator-width", &separator_width, + NULL); +- ReleaseStyleContext(style); + +- style = ClaimStyleContext(MOZ_GTK_TOOLBAR_SEPARATOR, direction); ++ style = GetStyleContext(MOZ_GTK_TOOLBAR_SEPARATOR, direction); + if (wide_separators) { + if (separator_width > rect->width) + separator_width = rect->width; +@@ -1328,7 +1287,6 @@ moz_gtk_toolbar_separator_paint(cairo_t *cr, GdkRectangle* rect, + rect->x + (rect->width - paint_width) / 2, + rect->y + rect->height * end_fraction); + } +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1345,11 +1303,10 @@ moz_gtk_tooltip_paint(cairo_t *cr, const GdkRectangle* aRect, + // We have to draw all elements with appropriate offset and right dimensions. + + // Tooltip drawing +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLTIP, direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_TOOLTIP, direction); + GdkRectangle rect = *aRect; + gtk_render_background(style, cr, rect.x, rect.y, rect.width, rect.height); + gtk_render_frame(style, cr, rect.x, rect.y, rect.width, rect.height); +- ReleaseStyleContext(style); + + // Horizontal Box drawing + // +@@ -1359,7 +1316,7 @@ moz_gtk_tooltip_paint(cairo_t *cr, const GdkRectangle* aRect, + // 6px margin. + // For drawing Horizontal Box we have to inset drawing area by that 6px + // plus its CSS margin. +- GtkStyleContext* boxStyle = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX, direction); ++ GtkStyleContext* boxStyle = GetStyleContext(MOZ_GTK_TOOLTIP_BOX, direction); + + rect.x += 6; + rect.y += 6; +@@ -1372,12 +1329,10 @@ moz_gtk_tooltip_paint(cairo_t *cr, const GdkRectangle* aRect, + + // Label drawing + InsetByBorderPadding(&rect, boxStyle); +- ReleaseStyleContext(boxStyle); + + GtkStyleContext* labelStyle = +- ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL, direction); ++ GetStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL, direction); + moz_gtk_draw_styled_frame(labelStyle, cr, &rect, false); +- ReleaseStyleContext(labelStyle); + + return MOZ_GTK_SUCCESS; + } +@@ -1388,8 +1343,8 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_RESIZER, GTK_TEXT_DIR_LTR, +- GetStateFlagsFromGtkWidgetState(state)); ++ GetStyleContext(MOZ_GTK_RESIZER, GTK_TEXT_DIR_LTR, ++ GetStateFlagsFromGtkWidgetState(state)); + + // Workaround unico not respecting the text direction for resizers. + // See bug 1174248. +@@ -1403,7 +1358,6 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRectangle* rect, + + gtk_render_handle(style, cr, rect->x, rect->y, rect->width, rect->height); + cairo_restore(cr); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1412,9 +1366,8 @@ static gint + moz_gtk_frame_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_FRAME, direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_FRAME, direction); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1422,11 +1375,10 @@ static gint + moz_gtk_progressbar_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_PROGRESS_TROUGH, +- direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_PROGRESS_TROUGH, ++ direction); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1437,7 +1389,7 @@ moz_gtk_progress_chunk_paint(cairo_t *cr, GdkRectangle* rect, + WidgetNodeType widget) + { + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_PROGRESS_CHUNK, direction); ++ GetStyleContext(MOZ_GTK_PROGRESS_CHUNK, direction); + + if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE || + widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) { +@@ -1481,7 +1433,6 @@ moz_gtk_progress_chunk_paint(cairo_t *cr, GdkRectangle* rect, + } else { + gtk_render_activity(style, cr, rect->x, rect->y, rect->width, rect->height); + } +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1503,9 +1454,8 @@ moz_gtk_get_tab_thickness(GtkStyleContext *style) + gint + moz_gtk_get_tab_thickness(WidgetNodeType aNodeType) + { +- GtkStyleContext *style = ClaimStyleContext(aNodeType); ++ GtkStyleContext *style = GetStyleContext(aNodeType); + int thickness = moz_gtk_get_tab_thickness(style); +- ReleaseStyleContext(style); + return thickness; + } + +@@ -1528,8 +1478,8 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectangle* rect, + int initial_gap = 0; + bool isBottomTab = (widget == MOZ_GTK_TAB_BOTTOM); + +- style = ClaimStyleContext(widget, direction, +- GetStateFlagsFromGtkTabFlags(flags)); ++ style = GetStyleContext(widget, direction, ++ GetStateFlagsFromGtkTabFlags(flags)); + tabRect = *rect; + + if (flags & MOZ_GTK_TAB_FIRST) { +@@ -1606,7 +1556,7 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectangle* rect, + } + + GtkStyleContext* panelStyle = +- ClaimStyleContext(MOZ_GTK_TABPANELS, direction); ++ GetStyleContext(MOZ_GTK_TABPANELS, direction); + + if (isBottomTab) { + /* Draw the tab on bottom */ +@@ -1681,7 +1631,6 @@ moz_gtk_tab_paint(cairo_t *cr, GdkRectangle* rect, + gtk_render_focus(style, cr, + focusRect.x, focusRect.y, focusRect.width, focusRect.height); + } +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1691,7 +1640,7 @@ static gint + moz_gtk_tabpanels_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TABPANELS, direction); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_TABPANELS, direction); + gtk_render_background(style, cr, rect->x, rect->y, + rect->width, rect->height); + /* +@@ -1728,7 +1677,6 @@ moz_gtk_tabpanels_paint(cairo_t *cr, GdkRectangle* rect, + GTK_POS_TOP, 0, 1); + cairo_restore(cr); + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1763,11 +1711,10 @@ moz_gtk_tab_scroll_arrow_paint(cairo_t *cr, GdkRectangle* rect, + break; + } + if (arrow_type != GTK_ARROW_NONE) { +- style = ClaimStyleContext(MOZ_GTK_TAB_SCROLLARROW, direction, +- GetStateFlagsFromGtkWidgetState(state)); ++ style = GetStyleContext(MOZ_GTK_TAB_SCROLLARROW, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + gtk_render_arrow(style, cr, arrow_angle, + x, y, arrow_size); +- ReleaseStyleContext(style); + } + return MOZ_GTK_SUCCESS; + } +@@ -1833,7 +1780,7 @@ moz_gtk_menu_separator_paint(cairo_t *cr, GdkRectangle* rect, + gint x, y, w; + GtkBorder padding; + +- style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR, direction); ++ style = GetStyleContext(MOZ_GTK_MENUSEPARATOR, direction); + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + + x = rect->x; +@@ -1863,7 +1810,6 @@ moz_gtk_menu_separator_paint(cairo_t *cr, GdkRectangle* rect, + } + + gtk_style_context_restore(style); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1883,7 +1829,7 @@ moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect, + !(state_flags & GTK_STATE_FLAG_PRELIGHT))) + return MOZ_GTK_SUCCESS; + +- GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags); ++ GtkStyleContext* style = GetStyleContext(widget, direction, state_flags); + + if (minorVersion < 6) { + // GTK+ 3.4 saves the style context and adds the menubar class to +@@ -1906,7 +1852,6 @@ moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect, + if (minorVersion < 6) { + gtk_style_context_restore(style); + } +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1917,12 +1862,11 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) + { + GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state); +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_MENUITEM, +- direction, state_flags); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_MENUITEM, ++ direction, state_flags); + gtk_render_arrow(style, cr, + (direction == GTK_TEXT_DIR_LTR) ? ARROW_RIGHT : ARROW_LEFT, + rect->x, rect->y, rect->width); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -1947,7 +1891,7 @@ moz_gtk_check_menu_item_paint(WidgetNodeType widgetType, + + bool pre_3_20 = gtk_get_minor_version() < 20; + gint offset; +- style = ClaimStyleContext(widgetType, direction); ++ style = GetStyleContext(widgetType, direction); + gtk_style_context_get_style(style, + "indicator-size", &indicator_size, + "horizontal-padding", &horizontal_padding, +@@ -1962,12 +1906,11 @@ moz_gtk_check_menu_item_paint(WidgetNodeType widgetType, + InsetByBorderPadding(&r, style); + offset = r.x; + } +- ReleaseStyleContext(style); + + bool isRadio = (widgetType == MOZ_GTK_RADIOMENUITEM); + WidgetNodeType indicatorType = isRadio ? MOZ_GTK_RADIOMENUITEM_INDICATOR + : MOZ_GTK_CHECKMENUITEM_INDICATOR; +- style = ClaimStyleContext(indicatorType, direction, state_flags); ++ style = GetStyleContext(indicatorType, direction, state_flags); + + if (direction == GTK_TEXT_DIR_RTL) { + x = rect->width - indicator_size - offset; +@@ -1987,7 +1930,6 @@ moz_gtk_check_menu_item_paint(WidgetNodeType widgetType, + } else { + gtk_render_check(style, cr, x, y, indicator_size, indicator_size); + } +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -1997,12 +1939,11 @@ moz_gtk_info_bar_paint(cairo_t *cr, GdkRectangle* rect, + GtkWidgetState* state) + { + GtkStyleContext *style = +- ClaimStyleContext(MOZ_GTK_INFO_BAR, GTK_TEXT_DIR_LTR, +- GetStateFlagsFromGtkWidgetState(state)); ++ GetStyleContext(MOZ_GTK_INFO_BAR, GTK_TEXT_DIR_LTR, ++ GetStateFlagsFromGtkWidgetState(state)); + gtk_render_background(style, cr, rect->x, rect->y, rect->width, + rect->height); + gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + + return MOZ_GTK_SUCCESS; + } +@@ -2087,7 +2028,7 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + case MOZ_GTK_BUTTON: + case MOZ_GTK_TOOLBAR_BUTTON: + { +- style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ style = GetStyleContext(MOZ_GTK_BUTTON); + + *left = *top = *right = *bottom = + gtk_container_get_border_width(GTK_CONTAINER(GetWidget(MOZ_GTK_BUTTON))); +@@ -2104,12 +2045,11 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + + moz_gtk_add_style_border(style, left, top, right, bottom); + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_ENTRY: + { +- style = ClaimStyleContext(MOZ_GTK_ENTRY); ++ style = GetStyleContext(MOZ_GTK_ENTRY); + + // XXX: Subtract 1 pixel from the padding to account for the default + // padding in forms.css. See bug 1187385. +@@ -2117,15 +2057,13 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + moz_gtk_add_style_padding(style, left, top, right, bottom); + moz_gtk_add_style_border(style, left, top, right, bottom); + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_TEXT_VIEW: + case MOZ_GTK_TREEVIEW: + { +- style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW); ++ style = GetStyleContext(MOZ_GTK_SCROLLED_WINDOW); + moz_gtk_add_style_border(style, left, top, right, bottom); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_TREE_HEADER_CELL: +@@ -2139,10 +2077,9 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + gtk_container_get_border_width(GTK_CONTAINER( + GetWidget(MOZ_GTK_TREE_HEADER_CELL))); + +- style = ClaimStyleContext(MOZ_GTK_TREE_HEADER_CELL); ++ style = GetStyleContext(MOZ_GTK_TREE_HEADER_CELL); + moz_gtk_add_style_border(style, left, top, right, bottom); + moz_gtk_add_style_padding(style, left, top, right, bottom); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_TREE_HEADER_SORTARROW: +@@ -2167,10 +2104,9 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + *left = *top = *right = *bottom = + gtk_container_get_border_width(GTK_CONTAINER( + GetWidget(MOZ_GTK_COMBOBOX_BUTTON))); +- style = ClaimStyleContext(MOZ_GTK_COMBOBOX_BUTTON); ++ style = GetStyleContext(MOZ_GTK_COMBOBOX_BUTTON); + moz_gtk_add_style_padding(style, left, top, right, bottom); + moz_gtk_add_style_border(style, left, top, right, bottom); +- ReleaseStyleContext(style); + + /* If there is no separator, don't try to count its width. */ + separator_width = 0; +@@ -2241,7 +2177,7 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + // Bug 1274143 for MOZ_GTK_MENUBARITEM + WidgetNodeType type = + widget == MOZ_GTK_MENUBARITEM ? MOZ_GTK_MENUITEM : widget; +- style = ClaimStyleContext(type); ++ style = GetStyleContext(type); + + if (gtk_get_minor_version() < 20) { + moz_gtk_add_style_padding(style, left, top, right, bottom); +@@ -2249,7 +2185,6 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + moz_gtk_add_margin_border_padding(style, + left, top, right, bottom); + } +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + case MOZ_GTK_INFO_BAR: +@@ -2265,15 +2200,13 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + // We also need to add margin/padding/borders from Tooltip content. + // Tooltip contains horizontal box, where icon and label is put. + // We ignore icon as long as we don't have support for it. +- GtkStyleContext* boxStyle = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX); ++ GtkStyleContext* boxStyle = GetStyleContext(MOZ_GTK_TOOLTIP_BOX); + moz_gtk_add_margin_border_padding(boxStyle, + left, top, right, bottom); +- ReleaseStyleContext(boxStyle); + +- GtkStyleContext* labelStyle = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL); ++ GtkStyleContext* labelStyle = GetStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL); + moz_gtk_add_margin_border_padding(labelStyle, + left, top, right, bottom); +- ReleaseStyleContext(labelStyle); + + return MOZ_GTK_SUCCESS; + } +@@ -2324,7 +2257,7 @@ moz_gtk_get_tab_border(gint* left, gint* top, gint* right, gint* bottom, + GtkTextDirection direction, GtkTabFlags flags, + WidgetNodeType widget) + { +- GtkStyleContext* style = ClaimStyleContext(widget, direction, ++ GtkStyleContext* style = GetStyleContext(widget, direction, + GetStateFlagsFromGtkTabFlags(flags)); + + *left = *top = *right = *bottom = 0; +@@ -2354,15 +2287,13 @@ moz_gtk_get_tab_border(gint* left, gint* top, gint* right, gint* bottom, + *right += margin.right; + + if (flags & MOZ_GTK_TAB_FIRST) { +- ReleaseStyleContext(style); +- style = ClaimStyleContext(MOZ_GTK_NOTEBOOK_HEADER, direction); ++ style = GetStyleContext(MOZ_GTK_NOTEBOOK_HEADER, direction); + gtk_style_context_get_margin(style, GTK_STATE_FLAG_NORMAL, &margin); + *left += margin.left; + *right += margin.right; + } + } + +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -2389,11 +2320,10 @@ moz_gtk_get_tab_scroll_arrow_size(gint* width, gint* height) + { + gint arrow_size; + +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_TABPANELS); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_TABPANELS); + gtk_style_context_get_style(style, + "scroll-arrow-hlength", &arrow_size, + NULL); +- ReleaseStyleContext(style); + + *height = *width = arrow_size; + +@@ -2426,7 +2356,7 @@ moz_gtk_get_toolbar_separator_width(gint* size) + gint separator_width; + GtkBorder border; + +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_TOOLBAR); + gtk_style_context_get_style(style, + "space-size", size, + "wide-separators", &wide_separators, +@@ -2435,27 +2365,24 @@ moz_gtk_get_toolbar_separator_width(gint* size) + /* Just in case... */ + gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border); + *size = MAX(*size, (wide_separators ? separator_width : border.left)); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + + gint + moz_gtk_get_expander_size(gint* size) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_EXPANDER); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_EXPANDER); + gtk_style_context_get_style(style, + "expander-size", size, + NULL); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + + gint + moz_gtk_get_treeview_expander_size(gint* size) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TREEVIEW); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_TREEVIEW); + gtk_style_context_get_style(style, "expander-size", size, NULL); +- ReleaseStyleContext(style); + return MOZ_GTK_SUCCESS; + } + +@@ -2466,7 +2393,7 @@ moz_gtk_get_menu_separator_height(gint *size) + gboolean wide_separators; + gint separator_height; + GtkBorder padding; +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_MENUSEPARATOR); + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + + gtk_style_context_save(style); +@@ -2478,7 +2405,6 @@ moz_gtk_get_menu_separator_height(gint *size) + NULL); + + gtk_style_context_restore(style); +- ReleaseStyleContext(style); + + *size = padding.top + padding.bottom; + *size += (wide_separators) ? separator_height : 1; +@@ -2489,7 +2415,7 @@ moz_gtk_get_menu_separator_height(gint *size) + void + moz_gtk_get_entry_min_height(gint* height) + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_ENTRY); ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_ENTRY); + if (!gtk_check_version(3, 20, 0)) { + gtk_style_context_get(style, gtk_style_context_get_state(style), + "min-height", height, +@@ -2504,7 +2430,6 @@ moz_gtk_get_entry_min_height(gint* height) + gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding); + + *height += (border.top + border.bottom + padding.top + padding.bottom); +- ReleaseStyleContext(style); + } + + void +@@ -2519,7 +2444,7 @@ moz_gtk_get_scale_metrics(GtkOrientation orient, gint* scale_width, + gint thumb_length, thumb_height, trough_border; + moz_gtk_get_scalethumb_metrics(orient, &thumb_length, &thumb_height); + +- GtkStyleContext* style = ClaimStyleContext(widget); ++ GtkStyleContext* style = GetStyleContext(widget); + gtk_style_context_get_style(style, "trough-border", &trough_border, NULL); + + if (orient == GTK_ORIENTATION_HORIZONTAL) { +@@ -2529,7 +2454,6 @@ moz_gtk_get_scale_metrics(GtkOrientation orient, gint* scale_width, + *scale_width = thumb_height + trough_border * 2; + *scale_height = thumb_length + trough_border * 2; + } +- ReleaseStyleContext(style); + } else { + WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? + MOZ_GTK_SCALE_TROUGH_HORIZONTAL : +@@ -2546,17 +2470,16 @@ moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* + WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? + MOZ_GTK_SCALE_HORIZONTAL: + MOZ_GTK_SCALE_VERTICAL; +- GtkStyleContext* style = ClaimStyleContext(widget); ++ GtkStyleContext* style = GetStyleContext(widget); + gtk_style_context_get_style(style, + "slider_length", thumb_length, + "slider_width", thumb_height, + NULL); +- ReleaseStyleContext(style); + } else { + WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? + MOZ_GTK_SCALE_THUMB_HORIZONTAL: + MOZ_GTK_SCALE_THUMB_VERTICAL; +- GtkStyleContext* style = ClaimStyleContext(widget); ++ GtkStyleContext* style = GetStyleContext(widget); + + gint min_width, min_height; + GtkStateFlags state = gtk_style_context_get_state(style); +@@ -2578,8 +2501,6 @@ moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* + + *thumb_length = min_width; + *thumb_height = min_height; +- +- ReleaseStyleContext(style); + } + + return MOZ_GTK_SUCCESS; +@@ -2606,7 +2527,7 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; + + gboolean backward, forward, secondary_backward, secondary_forward; +- GtkStyleContext* style = ClaimStyleContext(scrollbar); ++ GtkStyleContext* style = GetStyleContext(scrollbar); + gtk_style_context_get_style(style, + "has-backward-stepper", &backward, + "has-forward-stepper", &forward, +@@ -2626,7 +2547,6 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + "stepper-size", &stepper_size, + "min-slider-length", &min_slider_size, + nullptr); +- ReleaseStyleContext(style); + + metrics->size.thumb = + SizeFromLengthAndBreadth(aOrientation, min_slider_size, slider_width); +@@ -2663,7 +2583,6 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + // GTK version > 3.20 + // scrollbar + metrics->border.scrollbar = GetMarginBorderPadding(style); +- ReleaseStyleContext(style); + + WidgetNodeType contents, track, thumb; + if (aOrientation == GTK_ORIENTATION_HORIZONTAL) { +@@ -2678,10 +2597,9 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + // thumb + metrics->size.thumb = GetMinMarginBox(thumb); + // track +- style = ClaimStyleContext(track); ++ style = GetStyleContext(track); + metrics->border.track = GetMarginBorderPadding(style); + MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; +- ReleaseStyleContext(style); + MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; + // button + if (hasButtons) { +@@ -2719,9 +2637,8 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + } + } + +- style = ClaimStyleContext(contents); ++ style = GetStyleContext(contents); + GtkBorder contentsBorder = GetMarginBorderPadding(style); +- ReleaseStyleContext(style); + + metrics->size.scrollbar = + trackSizeForThumb + contentsBorder + metrics->border.scrollbar; +@@ -2771,10 +2688,9 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, + case MOZ_GTK_SCROLLBAR_VERTICAL: + if (flags & MOZ_GTK_TRACK_OPAQUE) { + GtkStyleContext* style = +- ClaimStyleContext(MOZ_GTK_WINDOW, direction); ++ GetStyleContext(MOZ_GTK_WINDOW, direction); + gtk_render_background(style, cr, + rect->x, rect->y, rect->width, rect->height); +- ReleaseStyleContext(style); + } + if (gtk_check_version(3,20,0) == nullptr) { + return moz_gtk_scrollbar_paint(widget, cr, rect, state, direction); +@@ -2818,10 +2734,10 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, + break; + case MOZ_GTK_SPINBUTTON_ENTRY: + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_SPINBUTTON_ENTRY, +- direction, GetStateFlagsFromGtkWidgetState(state)); ++ GtkStyleContext* style = ++ GetStyleContext(MOZ_GTK_SPINBUTTON_ENTRY, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + gint ret = moz_gtk_entry_paint(cr, rect, state, style); +- ReleaseStyleContext(style); + return ret; + } + break; +@@ -2849,10 +2765,10 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, + break; + case MOZ_GTK_ENTRY: + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_ENTRY, +- direction, GetStateFlagsFromGtkWidgetState(state)); ++ GtkStyleContext* style = ++ GetStyleContext(MOZ_GTK_ENTRY, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + gint ret = moz_gtk_entry_paint(cr, rect, state, style); +- ReleaseStyleContext(style); + return ret; + } + case MOZ_GTK_TEXT_VIEW: +@@ -2867,10 +2783,10 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, + break; + case MOZ_GTK_DROPDOWN_ENTRY: + { +- GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA, +- direction, GetStateFlagsFromGtkWidgetState(state)); ++ GtkStyleContext* style = ++ GetStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA, direction, ++ GetStateFlagsFromGtkWidgetState(state)); + gint ret = moz_gtk_entry_paint(cr, rect, state, style); +- ReleaseStyleContext(style); + return ret; + } + break; +diff --git widget/gtk/nsLookAndFeel.cpp widget/gtk/nsLookAndFeel.cpp +index f4c35d82200a..9a2684412ee8 100644 +--- widget/gtk/nsLookAndFeel.cpp ++++ widget/gtk/nsLookAndFeel.cpp +@@ -300,21 +300,19 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors + case eColorID_activeborder: { + // active window border +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_WINDOW); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_WINDOW); + gtk_style_context_get_border_color(style, + GTK_STATE_FLAG_NORMAL, &gdk_color); + aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); +- ReleaseStyleContext(style); + break; + } + case eColorID_inactiveborder: { + // inactive window border +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_WINDOW); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_WINDOW); + gtk_style_context_get_border_color(style, + GTK_STATE_FLAG_INSENSITIVE, + &gdk_color); + aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); +- ReleaseStyleContext(style); + break; + } + case eColorID_graytext: // disabled text in windows, menus, etc. +@@ -323,12 +321,11 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + break; + case eColorID_inactivecaption: { + // inactive window caption +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_WINDOW); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_WINDOW); + gtk_style_context_get_background_color(style, + GTK_STATE_FLAG_INSENSITIVE, + &gdk_color); + aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); +- ReleaseStyleContext(style); + break; + } + case eColorID_infobackground: +@@ -394,20 +391,18 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + break; + case eColorID__moz_buttondefault: { + // default button border color +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_BUTTON); + gtk_style_context_get_border_color(style, + GTK_STATE_FLAG_NORMAL, &gdk_color); + aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); +- ReleaseStyleContext(style); + break; + } + case eColorID__moz_buttonhoverface: { +- GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ GtkStyleContext *style = GetStyleContext(MOZ_GTK_BUTTON); + gtk_style_context_get_background_color(style, + GTK_STATE_FLAG_PRELIGHT, + &gdk_color); + aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); +- ReleaseStyleContext(style); + break; + } + case eColorID__moz_buttonhovertext: +@@ -858,38 +853,33 @@ nsLookAndFeel::EnsureInit() + g_object_ref_sink(labelWidget); + + // Scrollbar colors +- style = ClaimStyleContext(MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL); ++ style = GetStyleContext(MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMozScrollbar = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + + // Window colors +- style = ClaimStyleContext(MOZ_GTK_WINDOW); ++ style = GetStyleContext(MOZ_GTK_WINDOW); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMozWindowBackground = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMozWindowText = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); +- style = ClaimStyleContext(MOZ_GTK_WINDOW_CONTAINER); ++ style = GetStyleContext(MOZ_GTK_WINDOW_CONTAINER); + { + GtkStyleContext* labelStyle = CreateStyleForWidget(labelWidget, style); + GetSystemFontInfo(labelStyle, &mDefaultFontName, &mDefaultFontStyle); + g_object_unref(labelStyle); + } +- ReleaseStyleContext(style); + + // tooltip foreground and background +- style = ClaimStyleContext(MOZ_GTK_TOOLTIP); ++ style = GetStyleContext(MOZ_GTK_TOOLTIP); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + sInfoBackground = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + +- style = ClaimStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL); ++ style = GetStyleContext(MOZ_GTK_TOOLTIP_BOX_LABEL); + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sInfoText = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + +- style = ClaimStyleContext(MOZ_GTK_MENUITEM); ++ style = GetStyleContext(MOZ_GTK_MENUITEM); + { + GtkStyleContext* accelStyle = + CreateStyleForWidget(gtk_accel_label_new("M"), style); +@@ -902,19 +892,16 @@ nsLookAndFeel::EnsureInit() + sMenuTextInactive = GDK_RGBA_TO_NS_RGBA(color); + g_object_unref(accelStyle); + } +- ReleaseStyleContext(style); + +- style = ClaimStyleContext(MOZ_GTK_MENUPOPUP); ++ style = GetStyleContext(MOZ_GTK_MENUPOPUP); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMenuBackground = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + +- style = ClaimStyleContext(MOZ_GTK_MENUITEM); ++ style = GetStyleContext(MOZ_GTK_MENUITEM); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + sMenuHover = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + sMenuHoverText = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + + GtkWidget *parent = gtk_fixed_new(); + GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP); +@@ -937,12 +924,11 @@ nsLookAndFeel::EnsureInit() + GdkRGBA bgColor; + // If the text window background is translucent, then the background of + // the textview root node is visible. +- style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW); ++ style = GetStyleContext(MOZ_GTK_TEXT_VIEW); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, + &bgColor); +- ReleaseStyleContext(style); + +- style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW_TEXT); ++ style = GetStyleContext(MOZ_GTK_TEXT_VIEW_TEXT); + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, + &color); + ApplyColorOver(color, &bgColor); +@@ -959,10 +945,9 @@ nsLookAndFeel::EnsureInit() + static_cast<GtkStateFlags>(GTK_STATE_FLAG_FOCUSED|GTK_STATE_FLAG_SELECTED), + &color); + sTextSelectedText = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + + // Button text color +- style = ClaimStyleContext(MOZ_GTK_BUTTON); ++ style = GetStyleContext(MOZ_GTK_BUTTON); + { + GtkStyleContext* labelStyle = CreateStyleForWidget(labelWidget, style); + +@@ -974,21 +959,18 @@ nsLookAndFeel::EnsureInit() + sButtonHoverText = GDK_RGBA_TO_NS_RGBA(color); + g_object_unref(labelStyle); + } +- ReleaseStyleContext(style); + + // Combobox text color +- style = ClaimStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA); ++ style = GetStyleContext(MOZ_GTK_COMBOBOX_ENTRY_TEXTAREA); + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sComboBoxText = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + + // Menubar text and hover text colors +- style = ClaimStyleContext(MOZ_GTK_MENUBARITEM); ++ style = GetStyleContext(MOZ_GTK_MENUBARITEM); + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMenuBarText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(style, GTK_STATE_FLAG_PRELIGHT, &color); + sMenuBarHoverText = GDK_RGBA_TO_NS_RGBA(color); +- ReleaseStyleContext(style); + + // GTK's guide to fancy odd row background colors: + // 1) Check if a theme explicitly defines an odd row color +@@ -996,7 +978,7 @@ nsLookAndFeel::EnsureInit() + // slightly by a hardcoded value (gtkstyle.c) + // 3) If neither are defined, take the base background color and + // darken that by a hardcoded value +- style = ClaimStyleContext(MOZ_GTK_TREEVIEW); ++ style = GetStyleContext(MOZ_GTK_TREEVIEW); + + // Get odd row background color + gtk_style_context_save(style); +@@ -1004,20 +986,17 @@ nsLookAndFeel::EnsureInit() + gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color); + sOddCellBackground = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_restore(style); +- ReleaseStyleContext(style); + + // GtkFrame has a "border" subnode on which Adwaita draws the border. + // Some themes do not draw on this node but draw a border on the widget + // root node, so check the root node if no border is found on the border + // node. +- style = ClaimStyleContext(MOZ_GTK_FRAME_BORDER); ++ style = GetStyleContext(MOZ_GTK_FRAME_BORDER); + bool themeUsesColors = + GetBorderColors(style, &sFrameOuterLightBorder, &sFrameInnerDarkBorder); +- ReleaseStyleContext(style); + if (!themeUsesColors) { +- style = ClaimStyleContext(MOZ_GTK_FRAME); ++ style = GetStyleContext(MOZ_GTK_FRAME); + GetBorderColors(style, &sFrameOuterLightBorder, &sFrameInnerDarkBorder); +- ReleaseStyleContext(style); + } + + // GtkInfoBar diff --git a/www/waterfox/files/patch-bug1397114 b/www/waterfox/files/patch-bug1397114 new file mode 100644 index 000000000000..fe12dce4f535 --- /dev/null +++ b/www/waterfox/files/patch-bug1397114 @@ -0,0 +1,105 @@ +commit 92b82f64e587 +Author: Scott Wu <scottcwwu@gmail.com> +Date: Wed Sep 20 16:45:03 2017 +0800 + + Bug 1397114 - Disable smooth scrolling when value changes come from input box. r=mconley, a=ritu + + MozReview-Commit-ID: 9ZLSB2HQvcu + + --HG-- + extra : source : f215f88437f1db1884858be2c78582ab2b11bbb0 +--- + toolkit/content/widgets/datepicker.js | 11 ++++++----- + toolkit/content/widgets/spinner.js | 16 ++-------------- + 2 files changed, 8 insertions(+), 19 deletions(-) + +diff --git toolkit/content/widgets/datepicker.js toolkit/content/widgets/datepicker.js +index 31651dc63665..b125c5103a9a 100644 +--- toolkit/content/widgets/datepicker.js ++++ toolkit/content/widgets/datepicker.js +@@ -133,7 +133,7 @@ function DatePicker(context) { + /** + * Update date picker and its components. + */ +- _update() { ++ _update(options = {}) { + const { dateKeeper, isMonthPickerVisible } = this.state; + + if (isMonthPickerVisible) { +@@ -148,7 +148,8 @@ function DatePicker(context) { + dateObj: dateKeeper.state.dateObj, + months: this.state.months, + years: this.state.years, +- toggleMonthPicker: this.state.toggleMonthPicker ++ toggleMonthPicker: this.state.toggleMonthPicker, ++ noSmoothScroll: options.noSmoothScroll + }); + this.components.calendar.setProps({ + isVisible: !isMonthPickerVisible, +@@ -269,7 +270,7 @@ function DatePicker(context) { + dateKeeper.setSelection({ + year, month, day + }); +- this._update(); ++ this._update({ noSmoothScroll: true }); + } + }; + +@@ -350,14 +351,14 @@ function DatePicker(context) { + items: props.months, + isInfiniteScroll: true, + isValueSet: this.state.isMonthSet, +- smoothScroll: !this.state.firstOpened ++ smoothScroll: !(this.state.firstOpened || props.noSmoothScroll) + }); + this.components.year.setState({ + value: props.dateObj.getUTCFullYear(), + items: props.years, + isInfiniteScroll: false, + isValueSet: this.state.isYearSet, +- smoothScroll: !this.state.firstOpened ++ smoothScroll: !(this.state.firstOpened || props.noSmoothScroll) + }); + this.state.firstOpened = false; + } else { +diff --git toolkit/content/widgets/spinner.js toolkit/content/widgets/spinner.js +index 101cb01658a0..0a30766f8d13 100644 +--- toolkit/content/widgets/spinner.js ++++ toolkit/content/widgets/spinner.js +@@ -124,8 +124,6 @@ function Spinner(props, context) { + /** + * Whenever scroll event is detected: + * - Update the index state +- * - If a smooth scroll has reached its destination, set [isScrolling] state +- * to false + * - If the value has changed, update the [value] state and call [setValue] + * - If infinite scrolling is on, reset the scrolling position if necessary + */ +@@ -138,14 +136,8 @@ function Spinner(props, context) { + + const value = itemsView[this.state.index + viewportTopOffset].value; + +- // Check if smooth scrolling has reached its destination. +- // This prevents input box jump when input box changes values. +- if (this.state.value == value && this.state.isScrolling) { +- this.state.isScrolling = false; +- } +- +- // Call setValue if value has changed, and is not smooth scrolling +- if (this.state.value != value && !this.state.isScrolling) { ++ // Call setValue if value has changed ++ if (this.state.value != value) { + this.state.value = value; + this.props.setValue(value); + } +@@ -444,10 +436,6 @@ function Spinner(props, context) { + _smoothScrollToIndex(index) { + const element = this.elements.spinner.children[index]; + if (element) { +- // Set the isScrolling flag before smooth scrolling begins +- // and remove it when it has reached the destination. +- // This prevents input box jump when input box changes values +- this.state.isScrolling = true; + element.scrollIntoView({ + behavior: "smooth", block: "start" + }); diff --git a/www/waterfox/files/patch-bug1397671 b/www/waterfox/files/patch-bug1397671 new file mode 100644 index 000000000000..567fd3f34817 --- /dev/null +++ b/www/waterfox/files/patch-bug1397671 @@ -0,0 +1,105 @@ +commit 553df1231272 +Author: Matt Woodrow <mwoodrow@mozilla.com> +Date: Tue Sep 26 15:57:56 2017 +1300 + + Bug 1397671 - Don't treat SVG transformed frames as being transformed for the purposes of computing Combines3DTransformWithAncestors. r=dbaron, a=sledru + + --HG-- + extra : source : 70b150570407df427bed31965fe29cf8736beab6 +--- + layout/generic/nsFrame.cpp | 11 +++++++++-- + layout/generic/nsIFrame.h | 6 ++++++ + layout/reftests/transform-3d/preserve3d-8-ref.html | 11 +++++++++++ + layout/reftests/transform-3d/preserve3d-8.html | 17 +++++++++++++++++ + 4 files changed, 43 insertions(+), 2 deletions(-) + +diff --git layout/generic/nsFrame.cpp layout/generic/nsFrame.cpp +index 6e6f2bfa5379..02d1dafec21e 100644 +--- layout/generic/nsFrame.cpp ++++ layout/generic/nsFrame.cpp +@@ -1326,11 +1326,18 @@ nsIFrame::GetMarginRectRelativeToSelf() const + bool + nsIFrame::IsTransformed(const nsStyleDisplay* aStyleDisplay, + EffectSet* aEffectSet) const ++{ ++ return IsCSSTransformed(aStyleDisplay, aEffectSet) || ++ IsSVGTransformed(); ++} ++ ++bool ++nsIFrame::IsCSSTransformed(const nsStyleDisplay* aStyleDisplay, ++ EffectSet* aEffectSet) const + { + MOZ_ASSERT(aStyleDisplay == StyleDisplay()); + return ((mState & NS_FRAME_MAY_BE_TRANSFORMED) && + (aStyleDisplay->HasTransform(this) || +- IsSVGTransformed() || + HasAnimationOfTransform(aEffectSet))); + } + +@@ -1402,7 +1409,7 @@ nsIFrame::Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay, + if (!parent || !parent->Extend3DContext()) { + return false; + } +- return IsTransformed(aStyleDisplay,aEffectSet) || ++ return IsCSSTransformed(aStyleDisplay, aEffectSet) || + BackfaceIsHidden(aStyleDisplay); + } + +diff --git layout/generic/nsIFrame.h layout/generic/nsIFrame.h +index e8fb4c71a16f..b3ca08370d34 100644 +--- layout/generic/nsIFrame.h ++++ layout/generic/nsIFrame.h +@@ -1724,6 +1724,12 @@ public: + return IsTransformed(StyleDisplay(), aEffectSet); + } + ++ /** ++ * Same as IsTransformed, except that it doesn't take SVG transforms ++ * into account. ++ */ ++ bool IsCSSTransformed(const nsStyleDisplay* aStyleDisplay, mozilla::EffectSet* aEffectSet = nullptr) const; ++ + /** + * True if this frame has any animation of transform in effect. + * +diff --git layout/reftests/transform-3d/preserve3d-8-ref.html layout/reftests/transform-3d/preserve3d-8-ref.html +new file mode 100644 +index 000000000000..afddf05d4d81 +--- /dev/null ++++ layout/reftests/transform-3d/preserve3d-8-ref.html +@@ -0,0 +1,11 @@ ++<html> ++<head> ++</head> ++<body style="width:100px"> ++ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="js" viewBox="0 0 200 200" style="transform: rotateX(180deg)"> ++ <g> ++ <rect width="100" height="100" style="fill:rgb(0,0,255)"></rect> ++ </g> ++ </svg> ++</body> ++</html> +diff --git layout/reftests/transform-3d/preserve3d-8.html layout/reftests/transform-3d/preserve3d-8.html +new file mode 100644 +index 000000000000..76e9c10c33bc +--- /dev/null ++++ layout/reftests/transform-3d/preserve3d-8.html +@@ -0,0 +1,17 @@ ++<html> ++<head> ++</head> ++<body> ++ <div style="transform: rotatex(45deg); transform-style: preserve-3d; width: 100px;"> ++ <div style="transform: rotatex(45deg); transform-style: preserve-3d; width: 100px;"> ++ <div style="transform: rotatex(45deg); transform-style: preserve-3d; width: 100px;"> ++ <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="js" viewBox="0 0 200 200" style="transform: rotateX(45deg)"> ++ <g> ++ <rect width="100" height="100" style="fill:rgb(0,0,255)"></rect> ++ </g> ++ </svg> ++ </div> ++ </div> ++ </div> ++</body> ++</html> diff --git a/www/waterfox/files/patch-bug1397686 b/www/waterfox/files/patch-bug1397686 new file mode 100644 index 000000000000..3f1687062afc --- /dev/null +++ b/www/waterfox/files/patch-bug1397686 @@ -0,0 +1,69 @@ +commit 21d6d91c77f1 +Author: Dragana Damjanovic <dd.mozilla@gmail.com> +Date: Fri Sep 22 09:09:57 2017 +0200 + + Bug 1397686 - The streams that cannot do 0RTT data need to be put in list and added to mReadyForWrite when 0RTT is done. r=hurley, a=sledru + + --HG-- + extra : source : 5cf7391a9825fda34241f6d7974940f8460804fd +--- + netwerk/protocol/http/Http2Session.cpp | 15 +++++++++++++++ + netwerk/protocol/http/Http2Session.h | 3 +++ + 2 files changed, 18 insertions(+) + +diff --git netwerk/protocol/http/Http2Session.cpp netwerk/protocol/http/Http2Session.cpp +index 42dd829dc73d..c652189a0e16 100644 +--- netwerk/protocol/http/Http2Session.cpp ++++ netwerk/protocol/http/Http2Session.cpp +@@ -2769,6 +2769,9 @@ Http2Session::ReadSegmentsAgain(nsAHttpSegmentReader *reader, + this, stream, stream->StreamID())); + FlushOutputQueue(); + SetWriteCallbacks(); ++ if (!mCannotDo0RTTStreams.Contains(stream)) { ++ mCannotDo0RTTStreams.AppendElement(stream); ++ } + // We can still send our preamble + *countRead = mOutputQueueUsed - mOutputQueueSent; + return *countRead ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK; +@@ -3393,15 +3396,27 @@ Http2Session::Finish0RTT(bool aRestart, bool aAlpnChanged) + // This is the easy case - early data failed, but we're speaking h2, so + // we just need to rewind to the beginning of the preamble and try again. + mOutputQueueSent = 0; ++ ++ for (size_t i = 0; i < mCannotDo0RTTStreams.Length(); ++i) { ++ if (mCannotDo0RTTStreams[i] && VerifyStream(mCannotDo0RTTStreams[i])) { ++ TransactionHasDataToWrite(mCannotDo0RTTStreams[i]); ++ } ++ } + } + } else { + // 0RTT succeeded ++ for (size_t i = 0; i < mCannotDo0RTTStreams.Length(); ++i) { ++ if (mCannotDo0RTTStreams[i] && VerifyStream(mCannotDo0RTTStreams[i])) { ++ TransactionHasDataToWrite(mCannotDo0RTTStreams[i]); ++ } ++ } + // Make sure we look for any incoming data in repsonse to our early data. + Unused << ResumeRecv(); + } + + mAttemptingEarlyData = false; + m0RTTStreams.Clear(); ++ mCannotDo0RTTStreams.Clear(); + RealignOutputQueue(); + + return NS_OK; +diff --git netwerk/protocol/http/Http2Session.h netwerk/protocol/http/Http2Session.h +index 87c4e8b9fcb9..4fdc175ab166 100644 +--- netwerk/protocol/http/Http2Session.h ++++ netwerk/protocol/http/Http2Session.h +@@ -529,6 +529,9 @@ private: + bool mAttemptingEarlyData; + // The ID(s) of the stream(s) that we are getting 0RTT data from. + nsTArray<WeakPtr<Http2Stream>> m0RTTStreams; ++ // The ID(s) of the stream(s) that are not able to send 0RTT data. We need to ++ // remember them put them into mReadyForWrite queue when 0RTT finishes. ++ nsTArray<WeakPtr<Http2Stream>> mCannotDo0RTTStreams; + + bool RealJoinConnection(const nsACString &hostname, int32_t port, bool jk); + bool TestOriginFrame(const nsACString &name, int32_t port); diff --git a/www/waterfox/files/patch-bug1397795 b/www/waterfox/files/patch-bug1397795 new file mode 100644 index 000000000000..61b6e2c82978 --- /dev/null +++ b/www/waterfox/files/patch-bug1397795 @@ -0,0 +1,61 @@ +commit fc56d498fd83 +Author: Jonathan Watt <jwatt@jwatt.org> +Date: Fri Feb 23 10:40:12 2018 +0000 + + Bug 1397795 - Fix stack overflow crash due to box-shadow. r=mstange, a=jcristau + + GetBoxShadowRectForFrame is called while we're calculating the visual + overflow bounds for a frame. So it is not valid for it to use the frame's + "current" visual overflow rect (which may be uninitialized or stale). + + MozReview-Commit-ID: J52dxIMrMg5 + + --HG-- + extra : source : d7c420c8dc2a6b28500eae0e35cd9f17a22908ec +--- + layout/base/nsLayoutUtils.cpp | 22 +++++++++++++--------- + 1 file changed, 13 insertions(+), 9 deletions(-) + +diff --git layout/base/nsLayoutUtils.cpp layout/base/nsLayoutUtils.cpp +index 53c43f6b3546..f85273fbf232 100644 +--- layout/base/nsLayoutUtils.cpp ++++ layout/base/nsLayoutUtils.cpp +@@ -8747,25 +8747,29 @@ nsLayoutUtils::GetBoxShadowRectForFrame(nsIFrame* aFrame, + return nsRect(); + } + +- bool nativeTheme; ++ nsRect inputRect(nsPoint(0, 0), aFrameSize); ++ ++ // According to the CSS spec, box-shadow should be based on the border box. ++ // However, that looks broken when the background extends outside the border ++ // box, as can be the case with native theming. To fix that we expand the ++ // area that we shadow to include the bounds of any native theme drawing. + const nsStyleDisplay* styleDisplay = aFrame->StyleDisplay(); + nsITheme::Transparency transparency; + if (aFrame->IsThemed(styleDisplay, &transparency)) { + // For opaque (rectangular) theme widgets we can take the generic + // border-box path with border-radius disabled. +- nativeTheme = transparency != nsITheme::eOpaque; +- } else { +- nativeTheme = false; ++ if (transparency != nsITheme::eOpaque) { ++ nsPresContext *presContext = aFrame->PresContext(); ++ presContext->GetTheme()-> ++ GetWidgetOverflow(presContext->DeviceContext(), aFrame, ++ styleDisplay->mAppearance, &inputRect); ++ } + } + +- nsRect frameRect = nativeTheme ? +- aFrame->GetVisualOverflowRectRelativeToSelf() : +- nsRect(nsPoint(0, 0), aFrameSize); +- + nsRect shadows; + int32_t A2D = aFrame->PresContext()->AppUnitsPerDevPixel(); + for (uint32_t i = 0; i < boxShadows->Length(); ++i) { +- nsRect tmpRect = frameRect; ++ nsRect tmpRect = inputRect; + nsCSSShadowItem* shadow = boxShadows->ShadowAt(i); + + // inset shadows are never painted outside the frame diff --git a/www/waterfox/files/patch-bug1397989 b/www/waterfox/files/patch-bug1397989 new file mode 100644 index 000000000000..8cbd63606549 --- /dev/null +++ b/www/waterfox/files/patch-bug1397989 @@ -0,0 +1,42 @@ +commit f7c4ef799832 +Author: Mike de Boer <mdeboer@mozilla.com> +Date: Tue Oct 10 19:14:01 2017 +0200 + + Bug 1397989 - Make sure to only set non-empty values as the content-type of a document in the remote browser binding. r=mconley, a=ritu + + What happens is the following: + - browser-child.js sends a statechange up to RemoteWebProgress.jsm that contains + a `documentContentType` value of `null`, along with `requestURI` and `originalRequestURI` + _after_ other state changes that did send a valid content-type. + - The content-type is used by the WebProgressListener in browser.js to toggle the + disabled state of the 'isImage' broadcaster. + - The 'isImage' broadcaster is used by the 'cmd_find' and 'cmd_findAgain' commands to + determine whether they should be enabled. In this case: not. + The fix here is to _not_ set the documentContentType in the browser binding when + it's `null`. + + MozReview-Commit-ID: IELoCrnOH0j + + --HG-- + extra : source : 4c86b1f93b8482ea3097a4edb51bb8c0e8dc67fc +--- + toolkit/modules/RemoteWebProgress.jsm | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git toolkit/modules/RemoteWebProgress.jsm toolkit/modules/RemoteWebProgress.jsm +index 04eb37d580f5..05e3dabda941 100644 +--- toolkit/modules/RemoteWebProgress.jsm ++++ toolkit/modules/RemoteWebProgress.jsm +@@ -222,7 +222,11 @@ RemoteWebProgressManager.prototype = { + + if (isTopLevel) { + this._browser._contentWindow = objects.contentWindow; +- this._browser._documentContentType = json.documentContentType; ++ // Setting a content-type back to `null` is quite nonsensical for the ++ // frontend, especially since we're not expecting it. ++ if (json.documentContentType !== null) { ++ this._browser._documentContentType = json.documentContentType; ++ } + if (typeof json.inLoadURI != "undefined") { + this._browser.inLoadURI = json.inLoadURI; + } diff --git a/www/waterfox/files/patch-bug1398021 b/www/waterfox/files/patch-bug1398021 new file mode 100644 index 000000000000..0f31bc6df559 --- /dev/null +++ b/www/waterfox/files/patch-bug1398021 @@ -0,0 +1,2737 @@ +commit 909ebdebd850 +Author: Ryan VanderMeulen <ryanvm@gmail.com> +Date: Tue Sep 12 09:00:37 2017 -0400 + + Bug 1398021 - Update lz4 to version 1.8.0. r=froydnj +--- + mfbt/Compression.cpp | 7 +- + mfbt/lz4.c | 1593 ++++++++++++++++++++++++++++++-------------------- + mfbt/lz4.h | 531 +++++++++++------ + 3 files changed, 1319 insertions(+), 812 deletions(-) + +diff --git mfbt/Compression.cpp mfbt/Compression.cpp +index 3f5fff53c425..ed0bb4ef72c7 100644 +--- mfbt/Compression.cpp ++++ mfbt/Compression.cpp +@@ -36,7 +36,8 @@ LZ4::compress(const char* aSource, size_t aInputSize, char* aDest) + { + CheckedInt<int> inputSizeChecked = aInputSize; + MOZ_ASSERT(inputSizeChecked.isValid()); +- return LZ4_compress(aSource, aDest, inputSizeChecked.value()); ++ return LZ4_compress_default(aSource, aDest, inputSizeChecked.value(), ++ LZ4_compressBound(inputSizeChecked.value())); + } + + size_t +@@ -47,8 +48,8 @@ LZ4::compressLimitedOutput(const char* aSource, size_t aInputSize, char* aDest, + MOZ_ASSERT(inputSizeChecked.isValid()); + CheckedInt<int> maxOutputSizeChecked = aMaxOutputSize; + MOZ_ASSERT(maxOutputSizeChecked.isValid()); +- return LZ4_compress_limitedOutput(aSource, aDest, inputSizeChecked.value(), +- maxOutputSizeChecked.value()); ++ return LZ4_compress_default(aSource, aDest, inputSizeChecked.value(), ++ maxOutputSizeChecked.value()); + } + + bool +diff --git mfbt/lz4.c mfbt/lz4.c +index c416fe815a42..5752b4d17b0e 100644 +--- mfbt/lz4.c ++++ mfbt/lz4.c +@@ -1,6 +1,7 @@ + /* + LZ4 - Fast LZ compression algorithm +- Copyright (C) 2011-2014, Yann Collet. ++ Copyright (C) 2011-2017, Yann Collet. ++ + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without +@@ -27,118 +28,96 @@ + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : +- - LZ4 source repository : http://code.google.com/p/lz4/ +- - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c ++ - LZ4 homepage : http://www.lz4.org ++ - LZ4 source repository : https://github.com/lz4/lz4 + */ + +-/************************************** +- Tuning parameters ++ ++/*-************************************ ++* Tuning parameters + **************************************/ + /* +- * HEAPMODE : ++ * LZ4_HEAPMODE : + * Select how default compression functions will allocate memory for their hash table, +- * in memory stack (0:default, fastest), or in memory heap (1:requires memory allocation (malloc)). ++ * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). + */ +-#define HEAPMODE 0 +- +- +-/************************************** +- CPU Feature Detection +-**************************************/ +-/* 32 or 64 bits ? */ +-#if (defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) \ +- || defined(__powerpc64__) || defined(__powerpc64le__) \ +- || defined(__ppc64__) || defined(__ppc64le__) \ +- || defined(__PPC64__) || defined(__PPC64LE__) \ +- || defined(__ia64) || defined(__itanium__) || defined(_M_IA64) \ +- || (defined(__mips64) && defined(_ABI64))) /* Detects 64 bits mode */ +-# define LZ4_ARCH64 1 +-#else +-# define LZ4_ARCH64 0 ++#ifndef LZ4_HEAPMODE ++# define LZ4_HEAPMODE 0 + #endif + + /* +- * Little Endian or Big Endian ? +- * Overwrite the #define below if you know your architecture endianess ++ * ACCELERATION_DEFAULT : ++ * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 + */ +-#include <stdlib.h> /* Apparently required to detect endianess */ +-#if defined (__GLIBC__) +-# include <endian.h> +-# if (__BYTE_ORDER == __BIG_ENDIAN) +-# define LZ4_BIG_ENDIAN 1 ++#define ACCELERATION_DEFAULT 1 ++ ++ ++/*-************************************ ++* CPU Feature Detection ++**************************************/ ++/* LZ4_FORCE_MEMORY_ACCESS ++ * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. ++ * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. ++ * The below switch allow to select different access method for improved performance. ++ * Method 0 (default) : use `memcpy()`. Safe and portable. ++ * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). ++ * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. ++ * Method 2 : direct access. This method is portable but violate C standard. ++ * It can generate buggy code on targets which assembly generation depends on alignment. ++ * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) ++ * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. ++ * Prefer these methods in priority order (0 > 1 > 2) ++ */ ++#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally */ ++# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) ++# define LZ4_FORCE_MEMORY_ACCESS 2 ++# elif defined(__INTEL_COMPILER) || defined(__GNUC__) ++# define LZ4_FORCE_MEMORY_ACCESS 1 + # endif +-#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) +-# define LZ4_BIG_ENDIAN 1 +-#elif defined(__sparc) || defined(__sparc__) \ +- || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \ +- || defined(__hpux) || defined(__hppa) \ +- || defined(_MIPSEB) || defined(__s390__) +-# define LZ4_BIG_ENDIAN 1 +-#else +-/* Little Endian assumed. PDP Endian and other very rare endian format are unsupported. */ + #endif + + /* +- * Unaligned memory access is automatically enabled for "common" CPU, such as x86. +- * For others CPU, such as ARM, the compiler may be more cautious, inserting unnecessary extra code to ensure aligned access property +- * If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance ++ * LZ4_FORCE_SW_BITCOUNT ++ * Define this parameter if your target system or compiler does not support hardware bit count + */ +-#if defined(__ARM_FEATURE_UNALIGNED) +-# define LZ4_FORCE_UNALIGNED_ACCESS 1 +-#endif +- +-/* Define this parameter if your target system or compiler does not support hardware bit count */ + #if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */ + # define LZ4_FORCE_SW_BITCOUNT + #endif + +-/* +- * BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE : +- * This option may provide a small boost to performance for some big endian cpu, although probably modest. +- * You may set this option to 1 if data will remain within closed environment. +- * This option is useless on Little_Endian CPU (such as x86) +- */ + +-/* #define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 */ ++/*-************************************ ++* Dependency ++**************************************/ ++#include "lz4.h" ++/* see also "memory routines" below */ + + +-/************************************** +- Compiler Options ++/*-************************************ ++* Compiler Options + **************************************/ +-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +-/* "restrict" is a known keyword */ +-#else +-# define restrict /* Disable restrict */ +-#endif +- + #ifdef _MSC_VER /* Visual Studio */ +-# define FORCE_INLINE static __forceinline +-# include <intrin.h> /* For Visual 2005 */ +-# if LZ4_ARCH64 /* 64-bits */ +-# pragma intrinsic(_BitScanForward64) /* For Visual 2005 */ +-# pragma intrinsic(_BitScanReverse64) /* For Visual 2005 */ +-# else /* 32-bits */ +-# pragma intrinsic(_BitScanForward) /* For Visual 2005 */ +-# pragma intrinsic(_BitScanReverse) /* For Visual 2005 */ +-# endif ++# include <intrin.h> + # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +-#else +-# ifdef __GNUC__ +-# define FORCE_INLINE static inline __attribute__((always_inline)) +-# else +-# define FORCE_INLINE static inline +-# endif +-#endif +- +-#ifdef _MSC_VER /* Visual Studio */ +-# define lz4_bswap16(x) _byteswap_ushort(x) +-#else +-# define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))) +-#endif +- +-#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) ++# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ ++#endif /* _MSC_VER */ + +-#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) ++#ifndef FORCE_INLINE ++# ifdef _MSC_VER /* Visual Studio */ ++# define FORCE_INLINE static __forceinline ++# else ++# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ ++# ifdef __GNUC__ ++# define FORCE_INLINE static inline __attribute__((always_inline)) ++# else ++# define FORCE_INLINE static inline ++# endif ++# else ++# define FORCE_INLINE static ++# endif /* __STDC_VERSION__ */ ++# endif /* _MSC_VER */ ++#endif /* FORCE_INLINE */ ++ ++#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) + # define expect(expr,value) (__builtin_expect ((expr),(value)) ) + #else + # define expect(expr,value) (expr) +@@ -148,8 +127,8 @@ + #define unlikely(expr) expect((expr) != 0, 0) + + +-/************************************** +- Memory routines ++/*-************************************ ++* Memory routines + **************************************/ + #include <stdlib.h> /* malloc, calloc, free */ + #define ALLOCATOR(n,s) calloc(n,s) +@@ -158,84 +137,146 @@ + #define MEM_INIT memset + + +-/************************************** +- Includes ++/*-************************************ ++* Basic Types + **************************************/ +-#include "lz4.h" +- +- +-/************************************** +- Basic Types +-**************************************/ +-#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ ++#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) + # include <stdint.h> + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; ++ typedef uintptr_t uptrval; + #else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; ++ typedef size_t uptrval; /* generally true, except OpenVMS-64 */ + #endif + +-#if defined(__GNUC__) && !defined(LZ4_FORCE_UNALIGNED_ACCESS) +-# define _PACKED __attribute__ ((packed)) ++#if defined(__x86_64__) ++ typedef U64 reg_t; /* 64-bits in x32 mode */ + #else +-# define _PACKED ++ typedef size_t reg_t; /* 32-bits in x32 mode */ + #endif + +-#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__) +-# if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) +-# pragma pack(1) +-# else +-# pragma pack(push, 1) +-# endif +-#endif ++/*-************************************ ++* Reading and writing into memory ++**************************************/ ++static unsigned LZ4_isLittleEndian(void) ++{ ++ const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ ++ return one.c[0]; ++} + +-typedef struct { U16 v; } _PACKED U16_S; +-typedef struct { U32 v; } _PACKED U32_S; +-typedef struct { U64 v; } _PACKED U64_S; +-typedef struct {size_t v;} _PACKED size_t_S; + +-#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__) +-# if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +-# pragma pack(0) +-# else +-# pragma pack(pop) +-# endif +-#endif ++#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) ++/* lie to the compiler about data alignment; use with caution */ + +-#define A16(x) (((U16_S *)(x))->v) +-#define A32(x) (((U32_S *)(x))->v) +-#define A64(x) (((U64_S *)(x))->v) +-#define AARCH(x) (((size_t_S *)(x))->v) ++static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } ++static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } ++static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } + ++static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } ++static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } + +-/************************************** +- Constants +-**************************************/ +-#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) +-#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) +-#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) ++#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) ++ ++/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ ++/* currently only defined for gcc and icc */ ++typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; ++ ++static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } ++static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } ++static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } ++ ++static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } ++static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } ++ ++#else /* safe and portable access through memcpy() */ + ++static U16 LZ4_read16(const void* memPtr) ++{ ++ U16 val; memcpy(&val, memPtr, sizeof(val)); return val; ++} ++ ++static U32 LZ4_read32(const void* memPtr) ++{ ++ U32 val; memcpy(&val, memPtr, sizeof(val)); return val; ++} ++ ++static reg_t LZ4_read_ARCH(const void* memPtr) ++{ ++ reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; ++} ++ ++static void LZ4_write16(void* memPtr, U16 value) ++{ ++ memcpy(memPtr, &value, sizeof(value)); ++} ++ ++static void LZ4_write32(void* memPtr, U32 value) ++{ ++ memcpy(memPtr, &value, sizeof(value)); ++} ++ ++#endif /* LZ4_FORCE_MEMORY_ACCESS */ ++ ++ ++static U16 LZ4_readLE16(const void* memPtr) ++{ ++ if (LZ4_isLittleEndian()) { ++ return LZ4_read16(memPtr); ++ } else { ++ const BYTE* p = (const BYTE*)memPtr; ++ return (U16)((U16)p[0] + (p[1]<<8)); ++ } ++} ++ ++static void LZ4_writeLE16(void* memPtr, U16 value) ++{ ++ if (LZ4_isLittleEndian()) { ++ LZ4_write16(memPtr, value); ++ } else { ++ BYTE* p = (BYTE*)memPtr; ++ p[0] = (BYTE) value; ++ p[1] = (BYTE)(value>>8); ++ } ++} ++ ++static void LZ4_copy8(void* dst, const void* src) ++{ ++ memcpy(dst,src,8); ++} ++ ++/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ ++static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) ++{ ++ BYTE* d = (BYTE*)dstPtr; ++ const BYTE* s = (const BYTE*)srcPtr; ++ BYTE* const e = (BYTE*)dstEnd; ++ ++ do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e); ++} ++ ++ ++/*-************************************ ++* Common Constants ++**************************************/ + #define MINMATCH 4 + +-#define COPYLENGTH 8 ++#define WILDCOPYLENGTH 8 + #define LASTLITERALS 5 +-#define MFLIMIT (COPYLENGTH+MINMATCH) ++#define MFLIMIT (WILDCOPYLENGTH+MINMATCH) + static const int LZ4_minLength = (MFLIMIT+1); + +-#define KB *(1U<<10) +-#define MB *(1U<<20) ++#define KB *(1 <<10) ++#define MB *(1 <<20) + #define GB *(1U<<30) + +-#define LZ4_64KLIMIT ((64 KB) + (MFLIMIT-1)) +-#define SKIPSTRENGTH 6 /* Increasing this value will make the compression run slower on incompressible data */ +- + #define MAXD_LOG 16 + #define MAX_DISTANCE ((1 << MAXD_LOG) - 1) + +@@ -245,208 +286,213 @@ static const int LZ4_minLength = (MFLIMIT+1); + #define RUN_MASK ((1U<<RUN_BITS)-1) + + +-/************************************** +- Structures and local types ++/*-************************************ ++* Error detection + **************************************/ +-typedef struct { +- U32 hashTable[HASH_SIZE_U32]; +- U32 currentOffset; +- U32 initCheck; +- const BYTE* dictionary; +- const BYTE* bufferStart; +- U32 dictSize; +-} LZ4_stream_t_internal; ++#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ ++ ++#if defined(LZ4_DEBUG) && (LZ4_DEBUG>=2) ++# include <stdio.h> ++# define DEBUGLOG(l, ...) { \ ++ if (l<=LZ4_DEBUG) { \ ++ fprintf(stderr, __FILE__ ": "); \ ++ fprintf(stderr, __VA_ARGS__); \ ++ fprintf(stderr, " \n"); \ ++ } } ++#else ++# define DEBUGLOG(l, ...) {} /* disabled */ ++#endif + +-typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; +-typedef enum { byPtr, byU32, byU16 } tableType_t; + +-typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; +-typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; ++/*-************************************ ++* Common functions ++**************************************/ ++static unsigned LZ4_NbCommonBytes (register reg_t val) ++{ ++ if (LZ4_isLittleEndian()) { ++ if (sizeof(val)==8) { ++# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ unsigned long r = 0; ++ _BitScanForward64( &r, (U64)val ); ++ return (int)(r>>3); ++# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ return (__builtin_ctzll((U64)val) >> 3); ++# else ++ static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; ++ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; ++# endif ++ } else /* 32 bits */ { ++# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ unsigned long r; ++ _BitScanForward( &r, (U32)val ); ++ return (int)(r>>3); ++# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ return (__builtin_ctz((U32)val) >> 3); ++# else ++ static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; ++ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; ++# endif ++ } ++ } else /* Big Endian CPU */ { ++ if (sizeof(val)==8) { ++# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ unsigned long r = 0; ++ _BitScanReverse64( &r, val ); ++ return (unsigned)(r>>3); ++# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ return (__builtin_clzll((U64)val) >> 3); ++# else ++ unsigned r; ++ if (!(val>>32)) { r=4; } else { r=0; val>>=32; } ++ if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } ++ r += (!val); ++ return r; ++# endif ++ } else /* 32 bits */ { ++# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ unsigned long r = 0; ++ _BitScanReverse( &r, (unsigned long)val ); ++ return (unsigned)(r>>3); ++# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) ++ return (__builtin_clz((U32)val) >> 3); ++# else ++ unsigned r; ++ if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } ++ r += (!val); ++ return r; ++# endif ++ } ++ } ++} + +-typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; +-typedef enum { full = 0, partial = 1 } earlyEnd_directive; ++#define STEPSIZE sizeof(reg_t) ++static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) ++{ ++ const BYTE* const pStart = pIn; + ++ while (likely(pIn<pInLimit-(STEPSIZE-1))) { ++ reg_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn); ++ if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; } ++ pIn += LZ4_NbCommonBytes(diff); ++ return (unsigned)(pIn - pStart); ++ } + +-/************************************** +- Architecture-specific macros +-**************************************/ +-#define STEPSIZE sizeof(size_t) +-#define LZ4_COPYSTEP(d,s) { AARCH(d) = AARCH(s); d+=STEPSIZE; s+=STEPSIZE; } +-#define LZ4_COPY8(d,s) { LZ4_COPYSTEP(d,s); if (STEPSIZE<8) LZ4_COPYSTEP(d,s); } +- +-#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE)) +-# define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; } +-# define LZ4_WRITE_LITTLEENDIAN_16(p,i) { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; } +-#else /* Little Endian */ +-# define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); } +-# define LZ4_WRITE_LITTLEENDIAN_16(p,v) { A16(p) = v; p+=2; } +-#endif ++ if ((STEPSIZE==8) && (pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; } ++ if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; } ++ if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++; ++ return (unsigned)(pIn - pStart); ++} + + +-/************************************** +- Macros ++#ifndef LZ4_COMMONDEFS_ONLY ++/*-************************************ ++* Local Constants + **************************************/ +-#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(!!(c)) }; } /* use only *after* variable declarations */ +-#if LZ4_ARCH64 || !defined(__GNUC__) +-# define LZ4_WILDCOPY(d,s,e) { do { LZ4_COPY8(d,s) } while (d<e); } /* at the end, d>=e; */ +-#else +-# define LZ4_WILDCOPY(d,s,e) { if (likely(e-d <= 8)) LZ4_COPY8(d,s) else do { LZ4_COPY8(d,s) } while (d<e); } +-#endif ++static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1)); ++static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */ + + +-/**************************** +- Private local functions +-****************************/ +-#if LZ4_ARCH64 ++/*-************************************ ++* Local Structures and types ++**************************************/ ++typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; ++typedef enum { byPtr, byU32, byU16 } tableType_t; + +-int LZ4_NbCommonBytes (register U64 val) +-{ +-# if defined(LZ4_BIG_ENDIAN) +-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) +- unsigned long r = 0; +- _BitScanReverse64( &r, val ); +- return (int)(r>>3); +-# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) +- return (__builtin_clzll(val) >> 3); +-# else +- int r; +- if (!(val>>32)) { r=4; } else { r=0; val>>=32; } +- if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } +- r += (!val); +- return r; +-# endif +-# else +-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) +- unsigned long r = 0; +- _BitScanForward64( &r, val ); +- return (int)(r>>3); +-# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) +- return (__builtin_ctzll(val) >> 3); +-# else +- static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; +- return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; +-# endif +-# endif +-} ++typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; ++typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; + +-#else ++typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; ++typedef enum { full = 0, partial = 1 } earlyEnd_directive; + +-int LZ4_NbCommonBytes (register U32 val) +-{ +-# if defined(LZ4_BIG_ENDIAN) +-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) +- unsigned long r = 0; +- _BitScanReverse( &r, val ); +- return (int)(r>>3); +-# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) +- return (__builtin_clz(val) >> 3); +-# else +- int r; +- if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } +- r += (!val); +- return r; +-# endif +-# else +-# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) +- unsigned long r; +- _BitScanForward( &r, val ); +- return (int)(r>>3); +-# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) +- return (__builtin_ctz(val) >> 3); +-# else +- static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; +- return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; +-# endif +-# endif +-} + +-#endif ++/*-************************************ ++* Local Utils ++**************************************/ ++int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } ++const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } ++int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } ++int LZ4_sizeofState() { return LZ4_STREAMSIZE; } + + +-/******************************** +- Compression functions ++/*-****************************** ++* Compression functions + ********************************/ +-int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } +- +-static int LZ4_hashSequence(U32 sequence, tableType_t tableType) ++static U32 LZ4_hash4(U32 sequence, tableType_t const tableType) + { + if (tableType == byU16) +- return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); ++ return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + else +- return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); ++ return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); + } + +-static int LZ4_hashPosition(const BYTE* p, tableType_t tableType) { return LZ4_hashSequence(A32(p), tableType); } ++static U32 LZ4_hash5(U64 sequence, tableType_t const tableType) ++{ ++ static const U64 prime5bytes = 889523592379ULL; ++ static const U64 prime8bytes = 11400714785074694791ULL; ++ const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; ++ if (LZ4_isLittleEndian()) ++ return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); ++ else ++ return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); ++} ++ ++FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) ++{ ++ if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); ++ return LZ4_hash4(LZ4_read32(p), tableType); ++} + +-static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) ++static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) + { + switch (tableType) + { +- case byPtr: { const BYTE** hashTable = (const BYTE**) tableBase; hashTable[h] = p; break; } +- case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); break; } +- case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); break; } ++ case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } ++ case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } ++ case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } + } + } + +-static void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) ++FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) + { +- U32 h = LZ4_hashPosition(p, tableType); ++ U32 const h = LZ4_hashPosition(p, tableType); + LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); + } + + static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) + { + if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } +- if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } +- { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ ++ if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } ++ { const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ + } + +-static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) ++FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) + { +- U32 h = LZ4_hashPosition(p, tableType); ++ U32 const h = LZ4_hashPosition(p, tableType); + return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); + } + +-static unsigned LZ4_count(const BYTE* pIn, const BYTE* pRef, const BYTE* pInLimit) +-{ +- const BYTE* const pStart = pIn; +- +- while (likely(pIn<pInLimit-(STEPSIZE-1))) +- { +- size_t diff = AARCH(pRef) ^ AARCH(pIn); +- if (!diff) { pIn+=STEPSIZE; pRef+=STEPSIZE; continue; } +- pIn += LZ4_NbCommonBytes(diff); +- return (unsigned)(pIn - pStart); +- } +- if (sizeof(void*)==8) if ((pIn<(pInLimit-3)) && (A32(pRef) == A32(pIn))) { pIn+=4; pRef+=4; } +- if ((pIn<(pInLimit-1)) && (A16(pRef) == A16(pIn))) { pIn+=2; pRef+=2; } +- if ((pIn<pInLimit) && (*pRef == *pIn)) pIn++; +- +- return (unsigned)(pIn - pStart); +-} +- + +-static int LZ4_compress_generic( +- void* ctx, +- const char* source, +- char* dest, +- int inputSize, +- int maxOutputSize, +- +- limitedOutput_directive outputLimited, +- tableType_t tableType, +- dict_directive dict, +- dictIssue_directive dictIssue) ++/** LZ4_compress_generic() : ++ inlined, to ensure branches are decided at compilation time */ ++FORCE_INLINE int LZ4_compress_generic( ++ LZ4_stream_t_internal* const cctx, ++ const char* const source, ++ char* const dest, ++ const int inputSize, ++ const int maxOutputSize, ++ const limitedOutput_directive outputLimited, ++ const tableType_t tableType, ++ const dict_directive dict, ++ const dictIssue_directive dictIssue, ++ const U32 acceleration) + { +- LZ4_stream_t_internal* const dictPtr = (LZ4_stream_t_internal*)ctx; +- + const BYTE* ip = (const BYTE*) source; + const BYTE* base; + const BYTE* lowLimit; +- const BYTE* const lowRefLimit = ip - dictPtr->dictSize; +- const BYTE* const dictionary = dictPtr->dictionary; +- const BYTE* const dictEnd = dictionary + dictPtr->dictSize; +- const size_t dictDelta = dictEnd - (const BYTE*)source; ++ const BYTE* const lowRefLimit = ip - cctx->dictSize; ++ const BYTE* const dictionary = cctx->dictionary; ++ const BYTE* const dictEnd = dictionary + cctx->dictSize; ++ const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source; + const BYTE* anchor = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimit = iend - MFLIMIT; +@@ -455,12 +501,10 @@ static int LZ4_compress_generic( + BYTE* op = (BYTE*) dest; + BYTE* const olimit = op + maxOutputSize; + +- const int skipStrength = SKIPSTRENGTH; + U32 forwardH; +- size_t refDelta=0; + + /* Init conditions */ +- if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ ++ if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */ + switch(dict) + { + case noDict: +@@ -469,125 +513,118 @@ static int LZ4_compress_generic( + lowLimit = (const BYTE*)source; + break; + case withPrefix64k: +- base = (const BYTE*)source - dictPtr->currentOffset; +- lowLimit = (const BYTE*)source - dictPtr->dictSize; ++ base = (const BYTE*)source - cctx->currentOffset; ++ lowLimit = (const BYTE*)source - cctx->dictSize; + break; + case usingExtDict: +- base = (const BYTE*)source - dictPtr->currentOffset; ++ base = (const BYTE*)source - cctx->currentOffset; + lowLimit = (const BYTE*)source; + break; + } +- if ((tableType == byU16) && (inputSize>=(int)LZ4_64KLIMIT)) return 0; /* Size too large (not within 64K limit) */ +- if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ ++ if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ ++ if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ + + /* First Byte */ +- LZ4_putPosition(ip, ctx, tableType, base); ++ LZ4_putPosition(ip, cctx->hashTable, tableType, base); + ip++; forwardH = LZ4_hashPosition(ip, tableType); + + /* Main Loop */ +- for ( ; ; ) +- { +- const BYTE* ref; ++ for ( ; ; ) { ++ ptrdiff_t refDelta = 0; ++ const BYTE* match; + BYTE* token; +- { +- const BYTE* forwardIp = ip; +- unsigned step=1; +- unsigned searchMatchNb = (1U << skipStrength); + +- /* Find a match */ ++ /* Find a match */ ++ { const BYTE* forwardIp = ip; ++ unsigned step = 1; ++ unsigned searchMatchNb = acceleration << LZ4_skipTrigger; + do { +- U32 h = forwardH; ++ U32 const h = forwardH; + ip = forwardIp; + forwardIp += step; +- step = searchMatchNb++ >> skipStrength; +- //if (step>8) step=8; // required for valid forwardIp ; slows down uncompressible data a bit ++ step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimit)) goto _last_literals; + +- ref = LZ4_getPositionOnHash(h, ctx, tableType, base); +- if (dict==usingExtDict) +- { +- if (ref<(const BYTE*)source) +- { ++ match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); ++ if (dict==usingExtDict) { ++ if (match < (const BYTE*)source) { + refDelta = dictDelta; + lowLimit = dictionary; +- } +- else +- { ++ } else { + refDelta = 0; + lowLimit = (const BYTE*)source; +- } +- } ++ } } + forwardH = LZ4_hashPosition(forwardIp, tableType); +- LZ4_putPositionOnHash(ip, h, ctx, tableType, base); ++ LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); + +- } while ( ((dictIssue==dictSmall) ? (ref < lowRefLimit) : 0) +- || ((tableType==byU16) ? 0 : (ref + MAX_DISTANCE < ip)) +- || (A32(ref+refDelta) != A32(ip)) ); ++ } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) ++ || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) ++ || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) ); + } + + /* Catch up */ +- while ((ip>anchor) && (ref+refDelta > lowLimit) && (unlikely(ip[-1]==ref[refDelta-1]))) { ip--; ref--; } ++ while (((ip>anchor) & (match+refDelta > lowLimit)) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } + +- { +- /* Encode Literal length */ +- unsigned litLength = (unsigned)(ip - anchor); ++ /* Encode Literals */ ++ { unsigned const litLength = (unsigned)(ip - anchor); + token = op++; +- if ((outputLimited) && (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) +- return 0; /* Check output limit */ +- if (litLength>=RUN_MASK) +- { ++ if ((outputLimited) && /* Check output buffer overflow */ ++ (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) ++ return 0; ++ if (litLength >= RUN_MASK) { + int len = (int)litLength-RUN_MASK; +- *token=(RUN_MASK<<ML_BITS); ++ *token = (RUN_MASK<<ML_BITS); + for(; len >= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength<<ML_BITS); + + /* Copy Literals */ +- { BYTE* end = op+litLength; LZ4_WILDCOPY(op,anchor,end); op=end; } ++ LZ4_wildCopy(op, anchor, op+litLength); ++ op+=litLength; + } + + _next_match: + /* Encode Offset */ +- LZ4_WRITE_LITTLEENDIAN_16(op, (U16)(ip-ref)); ++ LZ4_writeLE16(op, (U16)(ip-match)); op+=2; + + /* Encode MatchLength */ +- { +- unsigned matchLength; ++ { unsigned matchCode; + +- if ((dict==usingExtDict) && (lowLimit==dictionary)) +- { ++ if ((dict==usingExtDict) && (lowLimit==dictionary)) { + const BYTE* limit; +- ref += refDelta; +- limit = ip + (dictEnd-ref); ++ match += refDelta; ++ limit = ip + (dictEnd-match); + if (limit > matchlimit) limit = matchlimit; +- matchLength = LZ4_count(ip+MINMATCH, ref+MINMATCH, limit); +- ip += MINMATCH + matchLength; +- if (ip==limit) +- { +- unsigned more = LZ4_count(ip, (const BYTE*)source, matchlimit); +- matchLength += more; ++ matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); ++ ip += MINMATCH + matchCode; ++ if (ip==limit) { ++ unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit); ++ matchCode += more; + ip += more; + } +- } +- else +- { +- matchLength = LZ4_count(ip+MINMATCH, ref+MINMATCH, matchlimit); +- ip += MINMATCH + matchLength; ++ } else { ++ matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); ++ ip += MINMATCH + matchCode; + } + +- if (matchLength>=ML_MASK) +- { +- if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit))) +- return 0; /* Check output limit */ ++ if ( outputLimited && /* Check output buffer overflow */ ++ (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) ++ return 0; ++ if (matchCode >= ML_MASK) { + *token += ML_MASK; +- matchLength -= ML_MASK; +- for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; } +- if (matchLength >= 255) { matchLength-=255; *op++ = 255; } +- *op++ = (BYTE)matchLength; +- } +- else *token += (BYTE)(matchLength); ++ matchCode -= ML_MASK; ++ LZ4_write32(op, 0xFFFFFFFF); ++ while (matchCode >= 4*255) { ++ op+=4; ++ LZ4_write32(op, 0xFFFFFFFF); ++ matchCode -= 4*255; ++ } ++ op += matchCode / 255; ++ *op++ = (BYTE)(matchCode % 255); ++ } else ++ *token += (BYTE)(matchCode); + } + + anchor = ip; +@@ -596,27 +633,22 @@ _next_match: + if (ip > mflimit) break; + + /* Fill table */ +- LZ4_putPosition(ip-2, ctx, tableType, base); ++ LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); + + /* Test next position */ +- ref = LZ4_getPosition(ip, ctx, tableType, base); +- if (dict==usingExtDict) +- { +- if (ref<(const BYTE*)source) +- { ++ match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); ++ if (dict==usingExtDict) { ++ if (match < (const BYTE*)source) { + refDelta = dictDelta; + lowLimit = dictionary; +- } +- else +- { ++ } else { + refDelta = 0; + lowLimit = (const BYTE*)source; +- } +- } +- LZ4_putPosition(ip, ctx, tableType, base); +- if ( ((dictIssue==dictSmall) ? (ref>=lowRefLimit) : 1) +- && (ref+MAX_DISTANCE>=ip) +- && (A32(ref+refDelta)==A32(ip)) ) ++ } } ++ LZ4_putPosition(ip, cctx->hashTable, tableType, base); ++ if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) ++ && (match+MAX_DISTANCE>=ip) ++ && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + /* Prepare next loop */ +@@ -625,14 +657,20 @@ _next_match: + + _last_literals: + /* Encode Last Literals */ +- { +- int lastRun = (int)(iend - anchor); +- if ((outputLimited) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) +- return 0; /* Check output limit */ +- if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<<ML_BITS); lastRun-=RUN_MASK; for(; lastRun >= 255 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } +- else *op++ = (BYTE)(lastRun<<ML_BITS); +- memcpy(op, anchor, iend - anchor); +- op += iend-anchor; ++ { size_t const lastRun = (size_t)(iend - anchor); ++ if ( (outputLimited) && /* Check output buffer overflow */ ++ ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) ++ return 0; ++ if (lastRun >= RUN_MASK) { ++ size_t accumulator = lastRun - RUN_MASK; ++ *op++ = RUN_MASK << ML_BITS; ++ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; ++ *op++ = (BYTE) accumulator; ++ } else { ++ *op++ = (BYTE)(lastRun<<ML_BITS); ++ } ++ memcpy(op, anchor, lastRun); ++ op += lastRun; + } + + /* End */ +@@ -640,109 +678,325 @@ _last_literals: + } + + +-int LZ4_compress(const char* source, char* dest, int inputSize) ++int LZ4_compress_fast_extState(void* state, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) + { +-#if (HEAPMODE) +- void* ctx = ALLOCATOR(LZ4_STREAMSIZE_U32, 4); /* Aligned on 4-bytes boundaries */ ++ LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)state)->internal_donotuse; ++ LZ4_resetStream((LZ4_stream_t*)state); ++ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; ++ ++ if (maxOutputSize >= LZ4_compressBound(inputSize)) { ++ if (inputSize < LZ4_64Klimit) ++ return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); ++ else ++ return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); ++ } else { ++ if (inputSize < LZ4_64Klimit) ++ return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); ++ else ++ return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); ++ } ++} ++ ++ ++int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) ++{ ++#if (LZ4_HEAPMODE) ++ void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + #else +- U32 ctx[LZ4_STREAMSIZE_U32] = {0}; /* Ensure data is aligned on 4-bytes boundaries */ ++ LZ4_stream_t ctx; ++ void* const ctxPtr = &ctx; + #endif +- int result; + +- if (inputSize < (int)LZ4_64KLIMIT) +- result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue); +- else +- result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue); ++ int const result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + +-#if (HEAPMODE) +- FREEMEM(ctx); ++#if (LZ4_HEAPMODE) ++ FREEMEM(ctxPtr); + #endif + return result; + } + +-int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) ++ ++int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize) + { +-#if (HEAPMODE) +- void* ctx = ALLOCATOR(LZ4_STREAMSIZE_U32, 4); /* Aligned on 4-bytes boundaries */ ++ return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1); ++} ++ ++ ++/* hidden debug function */ ++/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ ++int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) ++{ ++ LZ4_stream_t ctx; ++ LZ4_resetStream(&ctx); ++ ++ if (inputSize < LZ4_64Klimit) ++ return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); ++ else ++ return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); ++} ++ ++ ++/*-****************************** ++* *_destSize() variant ++********************************/ ++ ++static int LZ4_compress_destSize_generic( ++ LZ4_stream_t_internal* const ctx, ++ const char* const src, ++ char* const dst, ++ int* const srcSizePtr, ++ const int targetDstSize, ++ const tableType_t tableType) ++{ ++ const BYTE* ip = (const BYTE*) src; ++ const BYTE* base = (const BYTE*) src; ++ const BYTE* lowLimit = (const BYTE*) src; ++ const BYTE* anchor = ip; ++ const BYTE* const iend = ip + *srcSizePtr; ++ const BYTE* const mflimit = iend - MFLIMIT; ++ const BYTE* const matchlimit = iend - LASTLITERALS; ++ ++ BYTE* op = (BYTE*) dst; ++ BYTE* const oend = op + targetDstSize; ++ BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */; ++ BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */); ++ BYTE* const oMaxSeq = oMaxLit - 1 /* token */; ++ ++ U32 forwardH; ++ ++ ++ /* Init conditions */ ++ if (targetDstSize < 1) return 0; /* Impossible to store anything */ ++ if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ ++ if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ ++ if (*srcSizePtr<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */ ++ ++ /* First Byte */ ++ *srcSizePtr = 0; ++ LZ4_putPosition(ip, ctx->hashTable, tableType, base); ++ ip++; forwardH = LZ4_hashPosition(ip, tableType); ++ ++ /* Main Loop */ ++ for ( ; ; ) { ++ const BYTE* match; ++ BYTE* token; ++ ++ /* Find a match */ ++ { const BYTE* forwardIp = ip; ++ unsigned step = 1; ++ unsigned searchMatchNb = 1 << LZ4_skipTrigger; ++ ++ do { ++ U32 h = forwardH; ++ ip = forwardIp; ++ forwardIp += step; ++ step = (searchMatchNb++ >> LZ4_skipTrigger); ++ ++ if (unlikely(forwardIp > mflimit)) goto _last_literals; ++ ++ match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base); ++ forwardH = LZ4_hashPosition(forwardIp, tableType); ++ LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base); ++ ++ } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) ++ || (LZ4_read32(match) != LZ4_read32(ip)) ); ++ } ++ ++ /* Catch up */ ++ while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } ++ ++ /* Encode Literal length */ ++ { unsigned litLength = (unsigned)(ip - anchor); ++ token = op++; ++ if (op + ((litLength+240)/255) + litLength > oMaxLit) { ++ /* Not enough space for a last match */ ++ op--; ++ goto _last_literals; ++ } ++ if (litLength>=RUN_MASK) { ++ unsigned len = litLength - RUN_MASK; ++ *token=(RUN_MASK<<ML_BITS); ++ for(; len >= 255 ; len-=255) *op++ = 255; ++ *op++ = (BYTE)len; ++ } ++ else *token = (BYTE)(litLength<<ML_BITS); ++ ++ /* Copy Literals */ ++ LZ4_wildCopy(op, anchor, op+litLength); ++ op += litLength; ++ } ++ ++_next_match: ++ /* Encode Offset */ ++ LZ4_writeLE16(op, (U16)(ip-match)); op+=2; ++ ++ /* Encode MatchLength */ ++ { size_t matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); ++ ++ if (op + ((matchLength+240)/255) > oMaxMatch) { ++ /* Match description too long : reduce it */ ++ matchLength = (15-1) + (oMaxMatch-op) * 255; ++ } ++ ip += MINMATCH + matchLength; ++ ++ if (matchLength>=ML_MASK) { ++ *token += ML_MASK; ++ matchLength -= ML_MASK; ++ while (matchLength >= 255) { matchLength-=255; *op++ = 255; } ++ *op++ = (BYTE)matchLength; ++ } ++ else *token += (BYTE)(matchLength); ++ } ++ ++ anchor = ip; ++ ++ /* Test end of block */ ++ if (ip > mflimit) break; ++ if (op > oMaxSeq) break; ++ ++ /* Fill table */ ++ LZ4_putPosition(ip-2, ctx->hashTable, tableType, base); ++ ++ /* Test next position */ ++ match = LZ4_getPosition(ip, ctx->hashTable, tableType, base); ++ LZ4_putPosition(ip, ctx->hashTable, tableType, base); ++ if ( (match+MAX_DISTANCE>=ip) ++ && (LZ4_read32(match)==LZ4_read32(ip)) ) ++ { token=op++; *token=0; goto _next_match; } ++ ++ /* Prepare next loop */ ++ forwardH = LZ4_hashPosition(++ip, tableType); ++ } ++ ++_last_literals: ++ /* Encode Last Literals */ ++ { size_t lastRunSize = (size_t)(iend - anchor); ++ if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) { ++ /* adapt lastRunSize to fill 'dst' */ ++ lastRunSize = (oend-op) - 1; ++ lastRunSize -= (lastRunSize+240)/255; ++ } ++ ip = anchor + lastRunSize; ++ ++ if (lastRunSize >= RUN_MASK) { ++ size_t accumulator = lastRunSize - RUN_MASK; ++ *op++ = RUN_MASK << ML_BITS; ++ for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; ++ *op++ = (BYTE) accumulator; ++ } else { ++ *op++ = (BYTE)(lastRunSize<<ML_BITS); ++ } ++ memcpy(op, anchor, lastRunSize); ++ op += lastRunSize; ++ } ++ ++ /* End */ ++ *srcSizePtr = (int) (((const char*)ip)-src); ++ return (int) (((char*)op)-dst); ++} ++ ++ ++static int LZ4_compress_destSize_extState (LZ4_stream_t* state, const char* src, char* dst, int* srcSizePtr, int targetDstSize) ++{ ++ LZ4_resetStream(state); ++ ++ if (targetDstSize >= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ ++ return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); ++ } else { ++ if (*srcSizePtr < LZ4_64Klimit) ++ return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16); ++ else ++ return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, sizeof(void*)==8 ? byU32 : byPtr); ++ } ++} ++ ++ ++int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) ++{ ++#if (LZ4_HEAPMODE) ++ LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ + #else +- U32 ctx[LZ4_STREAMSIZE_U32] = {0}; /* Ensure data is aligned on 4-bytes boundaries */ ++ LZ4_stream_t ctxBody; ++ LZ4_stream_t* ctx = &ctxBody; + #endif +- int result; + +- if (inputSize < (int)LZ4_64KLIMIT) +- result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue); +- else +- result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue); ++ int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + +-#if (HEAPMODE) ++#if (LZ4_HEAPMODE) + FREEMEM(ctx); + #endif + return result; + } + + +-/***************************************** +- Experimental : Streaming functions +-*****************************************/ + +-void* LZ4_createStream() ++/*-****************************** ++* Streaming functions ++********************************/ ++ ++LZ4_stream_t* LZ4_createStream(void) + { +- void* lz4s = ALLOCATOR(4, LZ4_STREAMSIZE_U32); +- MEM_INIT(lz4s, 0, LZ4_STREAMSIZE); ++ LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64); ++ LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ ++ LZ4_resetStream(lz4s); + return lz4s; + } + +-int LZ4_free (void* LZ4_stream) ++void LZ4_resetStream (LZ4_stream_t* LZ4_stream) ++{ ++ MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); ++} ++ ++int LZ4_freeStream (LZ4_stream_t* LZ4_stream) + { ++ if (!LZ4_stream) return 0; /* support free on NULL */ + FREEMEM(LZ4_stream); + return (0); + } + + +-int LZ4_loadDict (void* LZ4_dict, const char* dictionary, int dictSize) ++#define HASH_UNIT sizeof(reg_t) ++int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) + { +- LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; ++ LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; + const BYTE* p = (const BYTE*)dictionary; + const BYTE* const dictEnd = p + dictSize; + const BYTE* base; + +- LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ +- if (dict->initCheck) MEM_INIT(dict, 0, sizeof(LZ4_stream_t_internal)); /* Uninitialized structure detected */ ++ if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */ ++ LZ4_resetStream(LZ4_dict); + +- if (dictSize < MINMATCH) +- { ++ if (dictSize < (int)HASH_UNIT) { + dict->dictionary = NULL; + dict->dictSize = 0; +- return 1; ++ return 0; + } + +- if (p <= dictEnd - 64 KB) p = dictEnd - 64 KB; ++ if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; ++ dict->currentOffset += 64 KB; + base = p - dict->currentOffset; + dict->dictionary = p; + dict->dictSize = (U32)(dictEnd - p); + dict->currentOffset += dict->dictSize; + +- while (p <= dictEnd-MINMATCH) +- { +- LZ4_putPosition(p, dict, byU32, base); ++ while (p <= dictEnd-HASH_UNIT) { ++ LZ4_putPosition(p, dict->hashTable, byU32, base); + p+=3; + } + +- return 1; ++ return dict->dictSize; + } + + +-void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) ++static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) + { + if ((LZ4_dict->currentOffset > 0x80000000) || +- ((size_t)LZ4_dict->currentOffset > (size_t)src)) /* address space overflow */ +- { ++ ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) { /* address space overflow */ + /* rescale hash table */ +- U32 delta = LZ4_dict->currentOffset - 64 KB; ++ U32 const delta = LZ4_dict->currentOffset - 64 KB; + const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; + int i; +- for (i=0; i<HASH_SIZE_U32; i++) +- { ++ for (i=0; i<LZ4_HASH_SIZE_U32; i++) { + if (LZ4_dict->hashTable[i] < delta) LZ4_dict->hashTable[i]=0; + else LZ4_dict->hashTable[i] -= delta; + } +@@ -753,22 +1007,20 @@ void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) + } + + +-FORCE_INLINE int LZ4_compress_continue_generic (void* LZ4_stream, const char* source, char* dest, int inputSize, +- int maxOutputSize, limitedOutput_directive limit) ++int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) + { +- LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_stream; ++ LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + const BYTE* smallest = (const BYTE*) source; + if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */ + if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd; + LZ4_renormDictT(streamPtr, smallest); ++ if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + + /* Check overlapping input/dictionary space */ +- { +- const BYTE* sourceEnd = (const BYTE*) source + inputSize; +- if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) +- { ++ { const BYTE* sourceEnd = (const BYTE*) source + inputSize; ++ if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) { + streamPtr->dictSize = (U32)(dictEnd - sourceEnd); + if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; + if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; +@@ -777,25 +1029,23 @@ FORCE_INLINE int LZ4_compress_continue_generic (void* LZ4_stream, const char* so + } + + /* prefix mode : source data follows dictionary */ +- if (dictEnd == (const BYTE*)source) +- { ++ if (dictEnd == (const BYTE*)source) { + int result; + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) +- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limit, byU32, withPrefix64k, dictSmall); ++ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); + else +- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limit, byU32, withPrefix64k, noDictIssue); ++ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); + streamPtr->dictSize += (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + return result; + } + + /* external dictionary mode */ +- { +- int result; ++ { int result; + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) +- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limit, byU32, usingExtDict, dictSmall); ++ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); + else +- result = LZ4_compress_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limit, byU32, usingExtDict, noDictIssue); ++ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; +@@ -804,29 +1054,18 @@ FORCE_INLINE int LZ4_compress_continue_generic (void* LZ4_stream, const char* so + } + + +-int LZ4_compress_continue (void* LZ4_stream, const char* source, char* dest, int inputSize) +-{ +- return LZ4_compress_continue_generic(LZ4_stream, source, dest, inputSize, 0, notLimited); +-} +- +-int LZ4_compress_limitedOutput_continue (void* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize) +-{ +- return LZ4_compress_continue_generic(LZ4_stream, source, dest, inputSize, maxOutputSize, limitedOutput); +-} +- +- +-// Hidden debug function, to force separate dictionary mode ++/* Hidden debug function, to force external dictionary mode */ + int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize) + { +- LZ4_stream_t_internal* streamPtr = (LZ4_stream_t_internal*)LZ4_dict; ++ LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; + int result; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + const BYTE* smallest = dictEnd; + if (smallest > (const BYTE*) source) smallest = (const BYTE*) source; +- LZ4_renormDictT((LZ4_stream_t_internal*)LZ4_dict, smallest); ++ LZ4_renormDictT(streamPtr, smallest); + +- result = LZ4_compress_generic(LZ4_dict, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue); ++ result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; +@@ -836,36 +1075,43 @@ int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* + } + + +-int LZ4_saveDict (void* LZ4_dict, char* safeBuffer, int dictSize) ++/*! LZ4_saveDict() : ++ * If previously compressed data block is not guaranteed to remain available at its memory location, ++ * save it into a safer place (char* safeBuffer). ++ * Note : you don't need to call LZ4_loadDict() afterwards, ++ * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). ++ * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. ++ */ ++int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) + { +- LZ4_stream_t_internal* dict = (LZ4_stream_t_internal*) LZ4_dict; +- const BYTE* previousDictEnd = dict->dictionary + dict->dictSize; ++ LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; ++ const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; + + if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ + if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; + +- memcpy(safeBuffer, previousDictEnd - dictSize, dictSize); ++ memmove(safeBuffer, previousDictEnd - dictSize, dictSize); + + dict->dictionary = (const BYTE*)safeBuffer; + dict->dictSize = (U32)dictSize; + +- return 1; ++ return dictSize; + } + + + +-/**************************** +- Decompression functions +-****************************/ +-/* +- * This generic decompression function cover all use cases. +- * It shall be instanciated several times, using different sets of directives +- * Note that it is essential this generic function is really inlined, +- * in order to remove useless branches during compilation optimisation. ++/*-***************************** ++* Decompression functions ++*******************************/ ++/*! LZ4_decompress_generic() : ++ * This generic decompression function cover all use cases. ++ * It shall be instantiated several times, using different sets of directives ++ * Note that it is important this generic function is really inlined, ++ * in order to remove useless branches during compilation optimization. + */ + FORCE_INLINE int LZ4_decompress_generic( +- const char* source, +- char* dest, ++ const char* const source, ++ char* const dest, + int inputSize, + int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */ + +@@ -873,162 +1119,143 @@ FORCE_INLINE int LZ4_decompress_generic( + int partialDecoding, /* full, partial */ + int targetOutputSize, /* only used if partialDecoding==partial */ + int dict, /* noDict, withPrefix64k, usingExtDict */ +- const char* dictStart, /* only if dict==usingExtDict */ +- int dictSize /* note : = 0 if noDict */ ++ const BYTE* const lowPrefix, /* == dest when no prefix */ ++ const BYTE* const dictStart, /* only if dict==usingExtDict */ ++ const size_t dictSize /* note : = 0 if noDict */ + ) + { + /* Local Variables */ +- const BYTE* restrict ip = (const BYTE*) source; +- const BYTE* ref; ++ const BYTE* ip = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + outputSize; + BYTE* cpy; + BYTE* oexit = op + targetOutputSize; +- const BYTE* const lowLimit = (const BYTE*)dest - dictSize; ++ const BYTE* const lowLimit = lowPrefix - dictSize; + + const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; +-//#define OLD +-#ifdef OLD +- const size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; /* static reduces speed for LZ4_decompress_safe() on GCC64 */ +-#else +- const size_t dec32table[] = {4-0, 4-3, 4-2, 4-3, 4-0, 4-0, 4-0, 4-0}; /* static reduces speed for LZ4_decompress_safe() on GCC64 */ +-#endif +- static const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; ++ const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; ++ const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; + +- const int checkOffset = (endOnInput) && (dictSize < (int)(64 KB)); ++ const int safeDecode = (endOnInput==endOnInputSize); ++ const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); + + + /* Special cases */ +- if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ +- if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ ++ if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ ++ if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ + if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); + +- +- /* Main Loop */ +- while (1) +- { +- unsigned token; ++ /* Main Loop : decode sequences */ ++ while (1) { + size_t length; ++ const BYTE* match; ++ size_t offset; + +- /* get runlength */ +- token = *ip++; +- if ((length=(token>>ML_BITS)) == RUN_MASK) +- { ++ /* get literal length */ ++ unsigned const token = *ip++; ++ if ((length=(token>>ML_BITS)) == RUN_MASK) { + unsigned s; +- do +- { ++ do { + s = *ip++; + length += s; +- } +- while (likely((endOnInput)?ip<iend-RUN_MASK:1) && (s==255)); +- //if ((sizeof(void*)==4) && unlikely(length>LZ4_MAX_INPUT_SIZE)) goto _output_error; /* overflow detection */ +- if ((sizeof(void*)==4) && unlikely((size_t)(op+length)<(size_t)(op))) goto _output_error; /* quickfix issue 134 */ +- if ((endOnInput) && (sizeof(void*)==4) && unlikely((size_t)(ip+length)<(size_t)(ip))) goto _output_error; /* quickfix issue 134 */ ++ } while ( likely(endOnInput ? ip<iend-RUN_MASK : 1) & (s==255) ); ++ if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)(op))) goto _output_error; /* overflow detection */ ++ if ((safeDecode) && unlikely((uptrval)(ip)+length<(uptrval)(ip))) goto _output_error; /* overflow detection */ + } + + /* copy literals */ + cpy = op+length; +- if (((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) +- || ((!endOnInput) && (cpy>oend-COPYLENGTH))) ++ if ( ((endOnInput) && ((cpy>(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) ++ || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) + { +- if (partialDecoding) +- { ++ if (partialDecoding) { + if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ + if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ +- } +- else +- { ++ } else { + if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ + if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ + } + memcpy(op, ip, length); + ip += length; + op += length; +- break; /* Necessarily EOF, due to parsing restrictions */ ++ break; /* Necessarily EOF, due to parsing restrictions */ + } +- LZ4_WILDCOPY(op, ip, cpy); ip -= (op-cpy); op = cpy; ++ LZ4_wildCopy(op, ip, cpy); ++ ip += length; op = cpy; + + /* get offset */ +- LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2; +- if ((checkOffset) && (unlikely(ref < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */ ++ offset = LZ4_readLE16(ip); ip+=2; ++ match = op - offset; ++ if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */ ++ LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */ + + /* get matchlength */ +- if ((length=(token&ML_MASK)) == ML_MASK) +- { ++ length = token & ML_MASK; ++ if (length == ML_MASK) { + unsigned s; +- do +- { +- if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; ++ do { + s = *ip++; ++ if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; + length += s; + } while (s==255); +- //if ((sizeof(void*)==4) && unlikely(length>LZ4_MAX_INPUT_SIZE)) goto _output_error; /* overflow detection */ +- if ((sizeof(void*)==4) && unlikely((size_t)(op+length)<(size_t)op)) goto _output_error; /* quickfix issue 134 */ ++ if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ + } ++ length += MINMATCH; + + /* check external dictionary */ +- if ((dict==usingExtDict) && (ref < (BYTE* const)dest)) +- { +- if (unlikely(op+length+MINMATCH > oend-LASTLITERALS)) goto _output_error; +- +- if (length+MINMATCH <= (size_t)(dest-(char*)ref)) +- { +- ref = dictEnd - (dest-(char*)ref); +- memcpy(op, ref, length+MINMATCH); +- op += length+MINMATCH; +- } +- else +- { +- size_t copySize = (size_t)(dest-(char*)ref); ++ if ((dict==usingExtDict) && (match < lowPrefix)) { ++ if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ ++ ++ if (length <= (size_t)(lowPrefix-match)) { ++ /* match can be copied as a single segment from external dictionary */ ++ memmove(op, dictEnd - (lowPrefix-match), length); ++ op += length; ++ } else { ++ /* match encompass external dictionary and current block */ ++ size_t const copySize = (size_t)(lowPrefix-match); ++ size_t const restSize = length - copySize; + memcpy(op, dictEnd - copySize, copySize); + op += copySize; +- copySize = length+MINMATCH - copySize; +- if (copySize > (size_t)((char*)op-dest)) /* overlap */ +- { +- BYTE* const cpy = op + copySize; +- const BYTE* ref = (BYTE*)dest; +- while (op < cpy) *op++ = *ref++; +- } +- else +- { +- memcpy(op, dest, copySize); +- op += copySize; +- } +- } ++ if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ ++ BYTE* const endOfMatch = op + restSize; ++ const BYTE* copyFrom = lowPrefix; ++ while (op < endOfMatch) *op++ = *copyFrom++; ++ } else { ++ memcpy(op, lowPrefix, restSize); ++ op += restSize; ++ } } + continue; + } + +- /* copy repeated sequence */ +- if (unlikely((op-ref)<(int)STEPSIZE)) +- { +- const size_t dec64 = dec64table[(sizeof(void*)==4) ? 0 : op-ref]; +- op[0] = ref[0]; +- op[1] = ref[1]; +- op[2] = ref[2]; +- op[3] = ref[3]; +-#ifdef OLD +- op += 4, ref += 4; ref -= dec32table[op-ref]; +- A32(op) = A32(ref); +- op += STEPSIZE-4; ref -= dec64; +-#else +- ref += dec32table[op-ref]; +- A32(op+4) = A32(ref); +- op += STEPSIZE; ref -= dec64; +-#endif +- } else { LZ4_COPYSTEP(op,ref); } +- cpy = op + length - (STEPSIZE-4); +- +- if (unlikely(cpy>oend-COPYLENGTH-(STEPSIZE-4))) +- { +- if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last 5 bytes must be literals */ +- if (op<oend-COPYLENGTH) LZ4_WILDCOPY(op, ref, (oend-COPYLENGTH)); +- while(op<cpy) *op++=*ref++; +- op=cpy; +- continue; ++ /* copy match within block */ ++ cpy = op + length; ++ if (unlikely(offset<8)) { ++ const int dec64 = dec64table[offset]; ++ op[0] = match[0]; ++ op[1] = match[1]; ++ op[2] = match[2]; ++ op[3] = match[3]; ++ match += dec32table[offset]; ++ memcpy(op+4, match, 4); ++ match -= dec64; ++ } else { LZ4_copy8(op, match); match+=8; } ++ op += 8; ++ ++ if (unlikely(cpy>oend-12)) { ++ BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1); ++ if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ ++ if (op < oCopyLimit) { ++ LZ4_wildCopy(op, match, oCopyLimit); ++ match += oCopyLimit - op; ++ op = oCopyLimit; ++ } ++ while (op<cpy) *op++ = *match++; ++ } else { ++ LZ4_copy8(op, match); ++ if (length>16) LZ4_wildCopy(op+8, match+8, cpy); + } +- LZ4_WILDCOPY(op, ref, cpy); + op=cpy; /* correction */ + } + +@@ -1036,64 +1263,59 @@ FORCE_INLINE int LZ4_decompress_generic( + if (endOnInput) + return (int) (((char*)op)-dest); /* Nb of output bytes decoded */ + else +- return (int) (((char*)ip)-source); /* Nb of input bytes read */ ++ return (int) (((const char*)ip)-source); /* Nb of input bytes read */ + + /* Overflow error detected */ + _output_error: +- return (int) (-(((char*)ip)-source))-1; ++ return (int) (-(((const char*)ip)-source))-1; + } + + +-int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxOutputSize) ++int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) + { +- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, noDict, NULL, 0); ++ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0); + } + +-int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxOutputSize) ++int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize) + { +- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, partial, targetOutputSize, noDict, NULL, 0); ++ return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0); + } + + int LZ4_decompress_fast(const char* source, char* dest, int originalSize) + { +- return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, NULL, 0); ++ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB); + } + +-/* streaming decompression functions */ + +-//#define LZ4_STREAMDECODESIZE_U32 4 +-//#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U32 * sizeof(unsigned int)) +-//typedef struct { unsigned int table[LZ4_STREAMDECODESIZE_U32]; } LZ4_streamDecode_t; +-typedef struct +-{ +- const char* dictionary; +- int dictSize; +-} LZ4_streamDecode_t_internal; ++/*===== streaming decompression functions =====*/ + +-/* +- * If you prefer dynamic allocation methods, +- * LZ4_createStreamDecode() +- * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure. +- */ +-void* LZ4_createStreamDecode() ++LZ4_streamDecode_t* LZ4_createStreamDecode(void) + { +- void* lz4s = ALLOCATOR(sizeof(U32), LZ4_STREAMDECODESIZE_U32); +- MEM_INIT(lz4s, 0, LZ4_STREAMDECODESIZE); ++ LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t)); + return lz4s; + } + +-/* +- * LZ4_setDictDecode +- * Use this function to instruct where to find the dictionary ++int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) ++{ ++ if (!LZ4_stream) return 0; /* support free on NULL */ ++ FREEMEM(LZ4_stream); ++ return 0; ++} ++ ++/*! ++ * LZ4_setStreamDecode() : ++ * Use this function to instruct where to find the dictionary. + * This function is not necessary if previous data is still available where it was decoded. + * Loading a size of 0 is allowed (same effect as no dictionary). + * Return : 1 if OK, 0 if error + */ +-int LZ4_setDictDecode (void* LZ4_streamDecode, const char* dictionary, int dictSize) ++int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) + { +- LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; +- lz4sd->dictionary = dictionary; +- lz4sd->dictSize = dictSize; ++ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; ++ lz4sd->prefixSize = (size_t) dictSize; ++ lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; ++ lz4sd->externalDict = NULL; ++ lz4sd->extDictSize = 0; + return 1; + } + +@@ -1102,43 +1324,55 @@ int LZ4_setDictDecode (void* LZ4_streamDecode, const char* dictionary, int dictS + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks must still be available at the memory position where they were decoded. + If it's not possible, save the relevant part of decoded data into a safe buffer, +- and indicate where it stands using LZ4_setDictDecode() ++ and indicate where it stands using LZ4_setStreamDecode() + */ +-int LZ4_decompress_safe_continue (void* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) ++int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) + { +- LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; ++ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + +- result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, lz4sd->dictionary, lz4sd->dictSize); +- if (result <= 0) return result; +- if (lz4sd->dictionary + lz4sd->dictSize == dest) +- { +- lz4sd->dictSize += result; +- } +- else +- { +- lz4sd->dictionary = dest; +- lz4sd->dictSize = result; ++ if (lz4sd->prefixEnd == (BYTE*)dest) { ++ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, ++ endOnInputSize, full, 0, ++ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); ++ if (result <= 0) return result; ++ lz4sd->prefixSize += result; ++ lz4sd->prefixEnd += result; ++ } else { ++ lz4sd->extDictSize = lz4sd->prefixSize; ++ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; ++ result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, ++ endOnInputSize, full, 0, ++ usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); ++ if (result <= 0) return result; ++ lz4sd->prefixSize = result; ++ lz4sd->prefixEnd = (BYTE*)dest + result; + } + + return result; + } + +-int LZ4_decompress_fast_continue (void* LZ4_streamDecode, const char* source, char* dest, int originalSize) ++int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) + { +- LZ4_streamDecode_t_internal* lz4sd = (LZ4_streamDecode_t_internal*) LZ4_streamDecode; ++ LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + +- result = LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, lz4sd->dictionary, lz4sd->dictSize); +- if (result <= 0) return result; +- if (lz4sd->dictionary + lz4sd->dictSize == dest) +- { +- lz4sd->dictSize += result; +- } +- else +- { +- lz4sd->dictionary = dest; +- lz4sd->dictSize = result; ++ if (lz4sd->prefixEnd == (BYTE*)dest) { ++ result = LZ4_decompress_generic(source, dest, 0, originalSize, ++ endOnOutputSize, full, 0, ++ usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); ++ if (result <= 0) return result; ++ lz4sd->prefixSize += originalSize; ++ lz4sd->prefixEnd += originalSize; ++ } else { ++ lz4sd->extDictSize = lz4sd->prefixSize; ++ lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; ++ result = LZ4_decompress_generic(source, dest, 0, originalSize, ++ endOnOutputSize, full, 0, ++ usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); ++ if (result <= 0) return result; ++ lz4sd->prefixSize = originalSize; ++ lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } + + return result; +@@ -1152,12 +1386,97 @@ Advanced decoding functions : + the dictionary must be explicitly provided within parameters + */ + ++FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize) ++{ ++ if (dictSize==0) ++ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); ++ if (dictStart+dictSize == dest) { ++ if (dictSize >= (int)(64 KB - 1)) ++ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); ++ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); ++ } ++ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); ++} ++ + int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) + { +- return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, dictStart, dictSize); ++ return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize); + } + + int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) + { +- return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, usingExtDict, dictStart, dictSize); ++ return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize); ++} ++ ++/* debug function */ ++int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) ++{ ++ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); + } ++ ++ ++/*=************************************************* ++* Obsolete Functions ++***************************************************/ ++/* obsolete compression functions */ ++int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); } ++int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); } ++int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); } ++int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); } ++int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); } ++int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); } ++ ++/* ++These function names are deprecated and should no longer be used. ++They are only provided here for compatibility with older user programs. ++- LZ4_uncompress is totally equivalent to LZ4_decompress_fast ++- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe ++*/ ++int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); } ++int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); } ++ ++ ++/* Obsolete Streaming functions */ ++ ++int LZ4_sizeofStreamState() { return LZ4_STREAMSIZE; } ++ ++static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base) ++{ ++ MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t)); ++ lz4ds->internal_donotuse.bufferStart = base; ++} ++ ++int LZ4_resetStreamState(void* state, char* inputBuffer) ++{ ++ if ((((uptrval)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ ++ LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer); ++ return 0; ++} ++ ++void* LZ4_create (char* inputBuffer) ++{ ++ LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t)); ++ LZ4_init (lz4ds, (BYTE*)inputBuffer); ++ return lz4ds; ++} ++ ++char* LZ4_slideInputBuffer (void* LZ4_Data) ++{ ++ LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)LZ4_Data)->internal_donotuse; ++ int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB); ++ return (char*)(ctx->bufferStart + dictSize); ++} ++ ++/* Obsolete streaming decompression functions */ ++ ++int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) ++{ ++ return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); ++} ++ ++int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) ++{ ++ return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); ++} ++ ++#endif /* LZ4_COMMONDEFS_ONLY */ +diff --git mfbt/lz4.h mfbt/lz4.h +index bf6780122f6f..86ca0d59c1f4 100644 +--- mfbt/lz4.h ++++ mfbt/lz4.h +@@ -1,7 +1,8 @@ + /* +- LZ4 - Fast LZ compression algorithm +- Header File +- Copyright (C) 2011-2014, Yann Collet. ++ * LZ4 - Fast LZ compression algorithm ++ * Header File ++ * Copyright (C) 2011-2017, Yann Collet. ++ + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without +@@ -28,247 +29,433 @@ + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : +- - LZ4 source repository : http://code.google.com/p/lz4/ +- - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c ++ - LZ4 homepage : http://www.lz4.org ++ - LZ4 source repository : https://github.com/lz4/lz4 + */ +-#pragma once +- + #if defined (__cplusplus) + extern "C" { + #endif + ++#ifndef LZ4_H_2983827168210 ++#define LZ4_H_2983827168210 + +-/************************************** +- Version +-**************************************/ +-#define LZ4_VERSION_MAJOR 1 /* for major interface/format changes */ +-#define LZ4_VERSION_MINOR 2 /* for minor interface/format changes */ ++/* --- Dependency --- */ ++#include <stddef.h> /* size_t */ ++ ++ ++/** ++ Introduction ++ ++ LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core, ++ scalable with multi-cores CPU. It features an extremely fast decoder, with speed in ++ multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. ++ ++ The LZ4 compression library provides in-memory compression and decompression functions. ++ Compression can be done in: ++ - a single step (described as Simple Functions) ++ - a single step, reusing a context (described in Advanced Functions) ++ - unbounded multiple steps (described as Streaming compression) ++ ++ lz4.h provides block compression functions. It gives full buffer control to user. ++ Decompressing an lz4-compressed block also requires metadata (such as compressed size). ++ Each application is free to encode such metadata in whichever way it wants. ++ ++ An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md), ++ take care of encoding standard metadata alongside LZ4-compressed blocks. ++ If your application requires interoperability, it's recommended to use it. ++ A library is provided to take care of it, see lz4frame.h. ++*/ ++ ++/*^*************************************************************** ++* Export parameters ++*****************************************************************/ ++/* ++* LZ4_DLL_EXPORT : ++* Enable exporting of functions when building a Windows DLL ++* LZ4LIB_API : ++* Control library symbols visibility. ++*/ ++#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) ++# define LZ4LIB_API __declspec(dllexport) ++#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) ++# define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ ++#elif defined(__GNUC__) && (__GNUC__ >= 4) ++# define LZ4LIB_API __attribute__ ((__visibility__ ("default"))) ++#else ++# define LZ4LIB_API ++#endif ++ ++ ++/*------ Version ------*/ ++#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ ++#define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */ + #define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */ + ++#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) + +-/************************************** +- Tuning parameter ++#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE ++#define LZ4_QUOTE(str) #str ++#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) ++#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) ++ ++LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; to be used when checking dll version */ ++LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; to be used when checking dll version */ ++ ++ ++/*-************************************ ++* Tuning parameter + **************************************/ +-/* ++/*! + * LZ4_MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + */ +-#define LZ4_MEMORY_USAGE 14 +- ++#ifndef LZ4_MEMORY_USAGE ++# define LZ4_MEMORY_USAGE 14 ++#endif + +-/************************************** +- Simple Functions ++/*-************************************ ++* Simple Functions + **************************************/ +- +-int LZ4_compress (const char* source, char* dest, int inputSize); +-int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxOutputSize); +- +-/* +-LZ4_compress() : +- Compresses 'inputSize' bytes from 'source' into 'dest'. +- Destination buffer must be already allocated, +- and must be sized to handle worst cases situations (input data not compressible) +- Worst case size evaluation is provided by function LZ4_compressBound() +- inputSize : Max supported value is LZ4_MAX_INPUT_VALUE +- return : the number of bytes written in buffer dest +- or 0 if the compression fails +- +-LZ4_decompress_safe() : +- compressedSize : is obviously the source size +- maxOutputSize : is the size of the destination buffer, which must be already allocated. +- return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) +- If the destination buffer is not large enough, decoding will stop and output an error code (<0). ++/*! LZ4_compress_default() : ++ Compresses 'sourceSize' bytes from buffer 'source' ++ into already allocated 'dest' buffer of size 'maxDestSize'. ++ Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). ++ It also runs faster, so it's a recommended setting. ++ If the function cannot compress 'source' into a more limited 'dest' budget, ++ compression stops *immediately*, and the function result is zero. ++ As a consequence, 'dest' content is not valid. ++ This function never writes outside 'dest' buffer, nor read outside 'source' buffer. ++ sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE ++ maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) ++ return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) ++ or 0 if compression fails */ ++LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); ++ ++/*! LZ4_decompress_safe() : ++ compressedSize : is the precise full size of the compressed block. ++ maxDecompressedSize : is the size of destination buffer, which must be already allocated. ++ return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) ++ If destination buffer is not large enough, decoding will stop and output an error code (<0). + If the source stream is detected malformed, the function will stop decoding and return a negative result. +- This function is protected against buffer overflow exploits : +- it never writes outside of output buffer, and never reads outside of input buffer. +- Therefore, it is protected against malicious data packets. +-*/ +- +- +-/* +-Note : +- Should you prefer to explicitly allocate compression-table memory using your own allocation method, +- use the streaming functions provided below, simply reset the memory area between each call to LZ4_compress_continue() ++ This function is protected against buffer overflow exploits, including malicious data packets. ++ It never writes outside output buffer, nor reads outside input buffer. + */ ++LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); + + +-/************************************** +- Advanced Functions ++/*-************************************ ++* Advanced Functions + **************************************/ + #define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ +-#define LZ4_COMPRESSBOUND(isize) ((unsigned int)(isize) > (unsigned int)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) ++#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) + +-/* ++/*! + LZ4_compressBound() : +- Provides the maximum size that LZ4 may output in a "worst case" scenario (input data not compressible) +- primarily useful for memory allocation of output buffer. +- macro is also provided when result needs to be evaluated at compilation (such as stack memory allocation). +- +- isize : is the input size. Max supported value is LZ4_MAX_INPUT_SIZE +- return : maximum output size in a "worst case" scenario +- or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) ++ Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) ++ This function is primarily useful for memory allocation purposes (destination buffer size). ++ Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). ++ Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize) ++ inputSize : max supported value is LZ4_MAX_INPUT_SIZE ++ return : maximum output size in a "worst case" scenario ++ or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) ++*/ ++LZ4LIB_API int LZ4_compressBound(int inputSize); ++ ++/*! ++LZ4_compress_fast() : ++ Same as LZ4_compress_default(), but allows to select an "acceleration" factor. ++ The larger the acceleration value, the faster the algorithm, but also the lesser the compression. ++ It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. ++ An acceleration value of "1" is the same as regular LZ4_compress_default() ++ Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1. + */ +-int LZ4_compressBound(int isize); ++LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); + + +-/* +-LZ4_compress_limitedOutput() : +- Compress 'inputSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'. +- If it cannot achieve it, compression will stop, and result of the function will be zero. +- This function never writes outside of provided output buffer. +- +- inputSize : Max supported value is LZ4_MAX_INPUT_VALUE +- maxOutputSize : is the size of the destination buffer (which must be already allocated) +- return : the number of bytes written in buffer 'dest' +- or 0 if the compression fails ++/*! ++LZ4_compress_fast_extState() : ++ Same compression function, just using an externally allocated memory space to store compression state. ++ Use LZ4_sizeofState() to know how much memory must be allocated, ++ and allocate it on 8-bytes boundaries (using malloc() typically). ++ Then, provide it as 'void* state' to compression function. ++*/ ++LZ4LIB_API int LZ4_sizeofState(void); ++LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); ++ ++ ++/*! ++LZ4_compress_destSize() : ++ Reverse the logic, by compressing as much data as possible from 'source' buffer ++ into already allocated buffer 'dest' of size 'targetDestSize'. ++ This function either compresses the entire 'source' content into 'dest' if it's large enough, ++ or fill 'dest' buffer completely with as much data as possible from 'source'. ++ *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'. ++ New value is necessarily <= old value. ++ return : Nb bytes written into 'dest' (necessarily <= targetDestSize) ++ or 0 if compression fails + */ +-int LZ4_compress_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize); ++LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); + + +-/* ++/*! + LZ4_decompress_fast() : + originalSize : is the original and therefore uncompressed size + return : the number of bytes read from the source buffer (in other words, the compressed size) +- If the source stream is malformed, the function will stop decoding and return a negative result. ++ If the source stream is detected malformed, the function will stop decoding and return a negative result. + Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes. +- note : This function is a bit faster than LZ4_decompress_safe() +- It provides fast decompression and fully respect memory boundaries for properly formed compressed data. +- It does not provide full protection against intentionnally modified data stream. +- Use this function in a trusted environment (data to decode comes from a trusted source). ++ note : This function fully respect memory boundaries for properly formed compressed data. ++ It is a bit faster than LZ4_decompress_safe(). ++ However, it does not provide any protection against intentionally modified data stream (malicious input). ++ Use this function in trusted environment only (data to decode comes from a trusted source). + */ +-int LZ4_decompress_fast (const char* source, char* dest, int originalSize); ++LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize); + +- +-/* ++/*! + LZ4_decompress_safe_partial() : + This function decompress a compressed block of size 'compressedSize' at position 'source' +- into output buffer 'dest' of size 'maxOutputSize'. ++ into destination buffer 'dest' of size 'maxDecompressedSize'. + The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, + reducing decompression time. +- return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) ++ return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize) + Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. + Always control how many bytes were decoded. + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets + */ +-int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxOutputSize); ++LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); + + +-/*********************************************** +- Experimental Streaming Compression Functions ++/*-********************************************* ++* Streaming Compression Functions + ***********************************************/ ++typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ + +-#define LZ4_STREAMSIZE_U32 ((1 << (LZ4_MEMORY_USAGE-2)) + 8) +-#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U32 * sizeof(unsigned int)) +-/* +- * LZ4_stream_t +- * information structure to track an LZ4 stream. +- * important : set this structure content to zero before first use ! +- */ +-typedef struct { unsigned int table[LZ4_STREAMSIZE_U32]; } LZ4_stream_t; +- +-/* +- * If you prefer dynamic allocation methods, +- * LZ4_createStream +- * provides a pointer (void*) towards an initialized LZ4_stream_t structure. +- * LZ4_free just frees it. ++/*! LZ4_createStream() and LZ4_freeStream() : ++ * LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure. ++ * LZ4_freeStream() releases its memory. + */ +-void* LZ4_createStream(); +-int LZ4_free (void* LZ4_stream); +- ++LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); ++LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); + +-/* +- * LZ4_loadDict +- * Use this function to load a static dictionary into LZ4_stream. +- * Any previous data will be forgotten, only 'dictionary' will remain in memory. +- * Loading a size of 0 is allowed (same effect as init). +- * Return : 1 if OK, 0 if error ++/*! LZ4_resetStream() : ++ * An LZ4_stream_t structure can be allocated once and re-used multiple times. ++ * Use this function to init an allocated `LZ4_stream_t` structure and start a new compression. + */ +-int LZ4_loadDict (void* LZ4_stream, const char* dictionary, int dictSize); ++LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); + +-/* +- * LZ4_compress_continue +- * Compress data block 'source', using blocks compressed before as dictionary to improve compression ratio +- * Previous data blocks are assumed to still be present at their previous location. ++/*! LZ4_loadDict() : ++ * Use this function to load a static dictionary into LZ4_stream. ++ * Any previous data will be forgotten, only 'dictionary' will remain in memory. ++ * Loading a size of 0 is allowed. ++ * Return : dictionary size, in bytes (necessarily <= 64 KB) + */ +-int LZ4_compress_continue (void* LZ4_stream, const char* source, char* dest, int inputSize); +- +-/* +- * LZ4_compress_limitedOutput_continue +- * Same as before, but also specify a maximum target compressed size (maxOutputSize) +- * If objective cannot be met, compression exits, and returns a zero. ++LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); ++ ++/*! LZ4_compress_fast_continue() : ++ * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. ++ * Important : Previous data blocks are assumed to remain present and unmodified ! ++ * 'dst' buffer must be already allocated. ++ * If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. ++ * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function @return==0. ++ * After an error, the stream status is invalid, it can only be reset or freed. + */ +-int LZ4_compress_limitedOutput_continue (void* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize); ++LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration); + +-/* +- * LZ4_saveDict +- * If previously compressed data block is not guaranteed to remain at its previous memory location +- * save it into a safe place (char* safeBuffer) +- * Note : you don't need to call LZ4_loadDict() afterwards, +- * dictionary is immediately usable, you can therefore call again LZ4_compress_continue() +- * Return : 1 if OK, 0 if error +- * Note : any dictSize > 64 KB will be interpreted as 64KB. ++/*! LZ4_saveDict() : ++ * If previously compressed data block is not guaranteed to remain available at its current memory location, ++ * save it into a safer place (char* safeBuffer). ++ * Note : it's not necessary to call LZ4_loadDict() after LZ4_saveDict(), dictionary is immediately usable. ++ * @return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ +-int LZ4_saveDict (void* LZ4_stream, char* safeBuffer, int dictSize); ++LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); + + +-/************************************************ +- Experimental Streaming Decompression Functions ++/*-********************************************** ++* Streaming Decompression Functions ++* Bufferless synchronous API + ************************************************/ ++typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */ + +-#define LZ4_STREAMDECODESIZE_U32 4 +-#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U32 * sizeof(unsigned int)) +-/* +- * LZ4_streamDecode_t +- * information structure to track an LZ4 stream. +- * important : set this structure content to zero before first use ! ++/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() : ++ * creation / destruction of streaming decompression tracking structure */ ++LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); ++LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); ++ ++/*! LZ4_setStreamDecode() : ++ * Use this function to instruct where to find the dictionary. ++ * Setting a size of 0 is allowed (same effect as reset). ++ * @return : 1 if OK, 0 if error + */ +-typedef struct { unsigned int table[LZ4_STREAMDECODESIZE_U32]; } LZ4_streamDecode_t; ++LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); ++ ++/*! LZ4_decompress_*_continue() : ++ * These decoding functions allow decompression of multiple blocks in "streaming" mode. ++ * Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) ++ * In the case of a ring buffers, decoding buffer must be either : ++ * - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions) ++ * In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB). ++ * - Larger than encoding buffer, by a minimum of maxBlockSize more bytes. ++ * maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block. ++ * In which case, encoding and decoding buffers do not need to be synchronized, ++ * and encoding ring buffer can have any size, including small ones ( < 64 KB). ++ * - _At least_ 64 KB + 8 bytes + maxBlockSize. ++ * In which case, encoding and decoding buffers do not need to be synchronized, ++ * and encoding ring buffer can have any size, including larger than decoding buffer. ++ * Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, ++ * and indicate where it is saved using LZ4_setStreamDecode() ++*/ ++LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); ++LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); + +-/* +- * If you prefer dynamic allocation methods, +- * LZ4_createStreamDecode() +- * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure. +- * LZ4_free just frees it. ++ ++/*! LZ4_decompress_*_usingDict() : ++ * These decoding functions work the same as ++ * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() ++ * They are stand-alone, and don't need an LZ4_streamDecode_t structure. + */ +-void* LZ4_createStreamDecode(); +-int LZ4_free (void* LZ4_stream); /* yes, it's the same one as for compression */ ++LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); ++LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); ++ ++ ++/*^********************************************** ++ * !!!!!! STATIC LINKING ONLY !!!!!! ++ ***********************************************/ ++/*-************************************ ++ * Private definitions ++ ************************************** ++ * Do not use these definitions. ++ * They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. ++ * Using these definitions will expose code to API and/or ABI break in future versions of the library. ++ **************************************/ ++#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) ++#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) ++#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ ++ ++#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ++#include <stdint.h> ++ ++typedef struct { ++ uint32_t hashTable[LZ4_HASH_SIZE_U32]; ++ uint32_t currentOffset; ++ uint32_t initCheck; ++ const uint8_t* dictionary; ++ uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */ ++ uint32_t dictSize; ++} LZ4_stream_t_internal; ++ ++typedef struct { ++ const uint8_t* externalDict; ++ size_t extDictSize; ++ const uint8_t* prefixEnd; ++ size_t prefixSize; ++} LZ4_streamDecode_t_internal; ++ ++#else ++ ++typedef struct { ++ unsigned int hashTable[LZ4_HASH_SIZE_U32]; ++ unsigned int currentOffset; ++ unsigned int initCheck; ++ const unsigned char* dictionary; ++ unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */ ++ unsigned int dictSize; ++} LZ4_stream_t_internal; ++ ++typedef struct { ++ const unsigned char* externalDict; ++ size_t extDictSize; ++ const unsigned char* prefixEnd; ++ size_t prefixSize; ++} LZ4_streamDecode_t_internal; + +-/* +-*_continue() : +- These decoding functions allow decompression of multiple blocks in "streaming" mode. +- Previously decoded blocks must still be available at the memory position where they were decoded. +- If it's not possible, save the relevant part of decoded data into a safe buffer, +- and indicate where it stands using LZ4_setDictDecode() +-*/ +-int LZ4_decompress_safe_continue (void* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize); +-int LZ4_decompress_fast_continue (void* LZ4_streamDecode, const char* source, char* dest, int originalSize); ++#endif + +-/* +- * LZ4_setDictDecode +- * Use this function to instruct where to find the dictionary. +- * This function can be used to specify a static dictionary, +- * or to instruct where to find some previously decoded data saved into a different memory space. +- * Setting a size of 0 is allowed (same effect as no dictionary). +- * Return : 1 if OK, 0 if error ++/*! ++ * LZ4_stream_t : ++ * information structure to track an LZ4 stream. ++ * init this structure before first use. ++ * note : only use in association with static linking ! ++ * this definition is not API/ABI safe, ++ * it may change in a future version ! + */ +-int LZ4_setDictDecode (void* LZ4_streamDecode, const char* dictionary, int dictSize); ++#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) ++#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) ++union LZ4_stream_u { ++ unsigned long long table[LZ4_STREAMSIZE_U64]; ++ LZ4_stream_t_internal internal_donotuse; ++} ; /* previously typedef'd to LZ4_stream_t */ ++ ++ ++/*! ++ * LZ4_streamDecode_t : ++ * information structure to track an LZ4 stream during decompression. ++ * init this structure using LZ4_setStreamDecode (or memset()) before first use ++ * note : only use in association with static linking ! ++ * this definition is not API/ABI safe, ++ * and may change in a future version ! ++ */ ++#define LZ4_STREAMDECODESIZE_U64 4 ++#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) ++union LZ4_streamDecode_u { ++ unsigned long long table[LZ4_STREAMDECODESIZE_U64]; ++ LZ4_streamDecode_t_internal internal_donotuse; ++} ; /* previously typedef'd to LZ4_streamDecode_t */ + + +-/* +-Advanced decoding functions : +-*_usingDict() : +- These decoding functions work the same as +- a combination of LZ4_setDictDecode() followed by LZ4_decompress_x_continue() +- all together into a single function call. +- It doesn't use nor update an LZ4_streamDecode_t structure. +-*/ +-int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize); +-int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); ++/*-************************************ ++* Obsolete Functions ++**************************************/ + ++/*! Deprecation warnings ++ Should deprecation warnings be a problem, ++ it is generally possible to disable them, ++ typically with -Wno-deprecated-declarations for gcc ++ or _CRT_SECURE_NO_WARNINGS in Visual. ++ Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */ ++#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS ++# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ ++#else ++# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) ++# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ ++# define LZ4_DEPRECATED(message) [[deprecated(message)]] ++# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__) ++# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) ++# elif (LZ4_GCC_VERSION >= 301) ++# define LZ4_DEPRECATED(message) __attribute__((deprecated)) ++# elif defined(_MSC_VER) ++# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) ++# else ++# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") ++# define LZ4_DEPRECATED(message) ++# endif ++#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ ++ ++/* Obsolete compression functions */ ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); ++ ++/* Obsolete decompression functions */ ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast() instead") int LZ4_uncompress (const char* source, char* dest, int outputSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_safe() instead") int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); ++ ++/* Obsolete streaming functions; use new streaming interface whenever possible */ ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state); ++ ++/* Obsolete streaming decoding functions */ ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); ++LZ4LIB_API LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); ++ ++#endif /* LZ4_H_2983827168210 */ + + + #if defined (__cplusplus) diff --git a/www/waterfox/files/patch-bug1398539 b/www/waterfox/files/patch-bug1398539 new file mode 100644 index 000000000000..1ae235da8b41 --- /dev/null +++ b/www/waterfox/files/patch-bug1398539 @@ -0,0 +1,159 @@ +commit 8b33a0a29e7e +Author: Lee Bousfield <ljbousfield@gmail.com> +Date: Wed Sep 13 18:28:51 2017 -0600 + + Bug 1398539: Inhibit screensaver with XScreenSaverSuspend r=karlt + + MozReview-Commit-ID: LhhpaDaPdaO + + --HG-- + extra : rebase_source : 6d53031ea8669b15cdf6fad4c55c58624bd54c38 +--- + widget/gtk/WakeLockListener.cpp | 91 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 90 insertions(+), 1 deletion(-) + +diff --git widget/gtk/WakeLockListener.cpp widget/gtk/WakeLockListener.cpp +index 3c6d7fb186a3..93d2c5a16208 100644 +--- widget/gtk/WakeLockListener.cpp ++++ widget/gtk/WakeLockListener.cpp +@@ -15,6 +15,10 @@ + #include "mozilla/ipc/DBusMessageRefPtr.h" + #include "mozilla/ipc/DBusPendingCallRefPtr.h" + ++#if defined(MOZ_X11) ++#include "prlink.h" ++#endif ++ + #define FREEDESKTOP_SCREENSAVER_TARGET "org.freedesktop.ScreenSaver" + #define FREEDESKTOP_SCREENSAVER_OBJECT "/ScreenSaver" + #define FREEDESKTOP_SCREENSAVER_INTERFACE "org.freedesktop.ScreenSaver" +@@ -32,6 +36,9 @@ StaticRefPtr<WakeLockListener> WakeLockListener::sSingleton; + enum DesktopEnvironment { + FreeDesktop, + GNOME, ++#if defined(MOZ_X11) ++ XScreenSaver, ++#endif + Unsupported, + }; + +@@ -59,6 +66,11 @@ private: + bool SendGNOMEInhibitMessage(); + bool SendMessage(DBusMessage* aMessage); + ++#if defined(MOZ_X11) ++ static bool CheckXScreenSaverSupport(); ++ static bool InhibitXScreenSaver(bool inhibit); ++#endif ++ + static void ReceiveInhibitReply(DBusPendingCall* aPending, void* aUserData); + void InhibitFailed(); + void InhibitSucceeded(uint32_t aInhibitRequest); +@@ -143,6 +155,71 @@ WakeLockTopic::SendGNOMEInhibitMessage() + } + + ++#if defined(MOZ_X11) ++ ++typedef Bool (*_XScreenSaverQueryExtension_fn)(Display* dpy, int* event_base, ++ int* error_base); ++typedef Bool (*_XScreenSaverQueryVersion_fn)(Display* dpy, int* major, ++ int* minor); ++typedef void (*_XScreenSaverSuspend_fn)(Display* dpy, Bool suspend); ++ ++static PRLibrary* sXssLib = nullptr; ++static _XScreenSaverQueryExtension_fn _XSSQueryExtension = nullptr; ++static _XScreenSaverQueryVersion_fn _XSSQueryVersion = nullptr; ++static _XScreenSaverSuspend_fn _XSSSuspend = nullptr; ++ ++/* static */ bool ++WakeLockTopic::CheckXScreenSaverSupport() ++{ ++ if (!sXssLib) { ++ sXssLib = PR_LoadLibrary("libXss.so.1"); ++ if (!sXssLib) { ++ return false; ++ } ++ } ++ ++ _XSSQueryExtension = (_XScreenSaverQueryExtension_fn) ++ PR_FindFunctionSymbol(sXssLib, "XScreenSaverQueryExtension"); ++ _XSSQueryVersion = (_XScreenSaverQueryVersion_fn) ++ PR_FindFunctionSymbol(sXssLib, "XScreenSaverQueryVersion"); ++ _XSSSuspend = (_XScreenSaverSuspend_fn) ++ PR_FindFunctionSymbol(sXssLib, "XScreenSaverSuspend"); ++ if (!_XSSQueryExtension || !_XSSQueryVersion || !_XSSSuspend) { ++ return false; ++ } ++ ++ GdkDisplay* gDisplay = gdk_display_get_default(); ++ if (!GDK_IS_X11_DISPLAY(gDisplay)) return false; ++ Display* display = GDK_DISPLAY_XDISPLAY(gDisplay); ++ ++ int throwaway; ++ if (!_XSSQueryExtension(display, &throwaway, &throwaway)) return false; ++ ++ int major, minor; ++ if (!_XSSQueryVersion(display, &major, &minor)) return false; ++ // Needs to be compatible with version 1.1 ++ if (major != 1) return false; ++ if (minor < 1) return false; ++ ++ return true; ++} ++ ++/* static */ bool ++WakeLockTopic::InhibitXScreenSaver(bool inhibit) ++{ ++ // Should only be called if CheckXScreenSaverSupport returns true. ++ // There's a couple of safety checks here nonetheless. ++ if (!_XSSSuspend) return false; ++ GdkDisplay* gDisplay = gdk_display_get_default(); ++ if (!GDK_IS_X11_DISPLAY(gDisplay)) return false; ++ Display* display = GDK_DISPLAY_XDISPLAY(gDisplay); ++ _XSSSuspend(display, inhibit); ++ return true; ++} ++ ++#endif ++ ++ + bool + WakeLockTopic::SendInhibit() + { +@@ -156,6 +233,10 @@ WakeLockTopic::SendInhibit() + case GNOME: + sendOk = SendGNOMEInhibitMessage(); + break; ++#if defined(MOZ_X11) ++ case XScreenSaver: ++ return InhibitXScreenSaver(true); ++#endif + case Unsupported: + return false; + } +@@ -185,6 +266,11 @@ WakeLockTopic::SendUninhibit() + SESSION_MANAGER_INTERFACE, + "Uninhibit")); + } ++#if defined(MOZ_X11) ++ else if (mDesktopEnvironment == XScreenSaver) { ++ return InhibitXScreenSaver(false); ++ } ++#endif + + if (!message) { + return false; +@@ -249,8 +335,11 @@ WakeLockTopic::InhibitFailed() + + if (mDesktopEnvironment == FreeDesktop) { + mDesktopEnvironment = GNOME; ++#if defined(MOZ_X11) ++ } else if (mDesktopEnvironment == GNOME && CheckXScreenSaverSupport()) { ++ mDesktopEnvironment = XScreenSaver; ++#endif + } else { +- NS_ASSERTION(mDesktopEnvironment == GNOME, "Unknown desktop environment"); + mDesktopEnvironment = Unsupported; + mShouldInhibit = false; + } diff --git a/www/waterfox/files/patch-bug1398581 b/www/waterfox/files/patch-bug1398581 new file mode 100644 index 000000000000..36845cb0a1a4 --- /dev/null +++ b/www/waterfox/files/patch-bug1398581 @@ -0,0 +1,125 @@ +commit 762a3ec064d0 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Sep 11 09:51:30 2017 +0200 + + Bug 1398581: Ensure a first-letter doesn't incorrectly inherit from a first-line. r=heycam + + This approach kinda sucks, because we woefully throw away the style context + computed in the case it inherited from a first-line, but it's the easiest thing + I could think of without either making it more inefficient, or threading a + parent style ignoring first-line through ResolvePseudoElementStyle and related + functions. + + MozReview-Commit-ID: 3uGuU7dHEnE +--- + layout/base/nsCSSFrameConstructor.cpp | 20 +++++++++++++++++--- + 1 file changed, 17 insertions(+), 3 deletions(-) + +diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp +index 76d97a32ee4d..b668a837e2f3 100644 +--- layout/base/nsCSSFrameConstructor.cpp ++++ layout/base/nsCSSFrameConstructor.cpp +@@ -11861,10 +11861,11 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame, + + // Get style context for the first-letter-frame. Keep this in sync with + // nsBlockFrame::UpdatePseudoElementStyles. +- nsStyleContext* parentStyleContext = ++ nsIFrame* parentFrame = + nsFrame::CorrectStyleParentFrame(aParentFrame, +- nsCSSPseudoElements::firstLetter)-> +- StyleContext(); ++ nsCSSPseudoElements::firstLetter); ++ ++ nsStyleContext* parentStyleContext = parentFrame->StyleContext(); + + // Use content from containing block so that we can actually + // find a matching style rule. +@@ -11873,7 +11874,20 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame, + // Create first-letter style rule + RefPtr<nsStyleContext> sc = + GetFirstLetterStyle(blockContent, parentStyleContext); ++ + if (sc) { ++ if (sc->IsServo() && parentFrame->IsLineFrame()) { ++ ServoStyleContext* parentStyleIgnoringFirstLine = ++ aBlockFrame->StyleContext()->AsServo(); ++ sc = ++ mPresShell->StyleSet()->AsServo()->ReparentStyleContext( ++ sc->AsServo(), ++ parentStyleContext->AsServo(), ++ parentStyleIgnoringFirstLine, ++ parentStyleIgnoringFirstLine, ++ blockContent->AsElement()); ++ } ++ + RefPtr<nsStyleContext> textSC = mPresShell->StyleSet()-> + ResolveStyleForText(aTextContent, sc); + +commit 2a9742d4b68a +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Sep 11 17:19:05 2017 +0200 + + Bug 1398581: Address followup comments. r=me + + MozReview-Commit-ID: CymOOl4VLPj +--- + layout/base/nsCSSFrameConstructor.cpp | 15 +-------------- + 1 file changed, 1 insertion(+), 14 deletions(-) + +diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp +index b668a837e2f3..bd3d406f664f 100644 +--- layout/base/nsCSSFrameConstructor.cpp ++++ layout/base/nsCSSFrameConstructor.cpp +@@ -11884,7 +11884,7 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame, + sc->AsServo(), + parentStyleContext->AsServo(), + parentStyleIgnoringFirstLine, +- parentStyleIgnoringFirstLine, ++ parentStyleContext->AsServo(), + blockContent->AsElement()); + } + +commit 9a42394a1f71 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Sep 11 17:19:30 2017 +0200 + + Bug 1398581: Crashtest. r=me + + MozReview-Commit-ID: 5xy5aeDWU12 +--- + layout/style/crashtests/1398581.html | 17 +++++++++++++++++ + layout/style/crashtests/crashtests.list | 1 + + 2 files changed, 18 insertions(+) + +diff --git layout/style/crashtests/1398581.html layout/style/crashtests/1398581.html +new file mode 100644 +index 000000000000..e056ab44d55c +--- /dev/null ++++ layout/style/crashtests/1398581.html +@@ -0,0 +1,17 @@ ++<script> ++function start() { ++ o3=document.createElement('div'); ++ document.body.appendChild(o3); ++ o14=document.createElement('style'); ++ document.documentElement.appendChild(o14); ++ o18=document.createElement('style'); ++ o14.appendChild(o18); ++ s4=unescape('%u06A10'); ++ o3.appendChild(document.createTextNode(s4)); ++ o59=document.createTextNode("{}:first-letter{ all: inherit;'x'}\n*{ float: left}:first-line{"); ++ o18['before'](o18,-1,o59); ++ document.documentElement.offsetHeight; ++ o3.appendChild(document.createTextNode("x")); ++} ++</script> ++<body onload="start()"></body> +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index a32d48fa3299..719bdaf8328a 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -201,3 +201,4 @@ load 1384824-2.html + load 1387481-1.html + load 1387499.html + load 1391577.html ++load 1398581.html diff --git a/www/waterfox/files/patch-bug1398806 b/www/waterfox/files/patch-bug1398806 new file mode 100644 index 000000000000..ecb7d12aefce --- /dev/null +++ b/www/waterfox/files/patch-bug1398806 @@ -0,0 +1,438 @@ +commit 95d5501cd96b +Author: Robert Longson <longsonr@gmail.com> +Date: Tue Oct 10 07:58:34 2017 +0100 + + Bug 1398806 - GetCtx and GetNearestViewport should return the nearest svg or symbol element which is now an SVGViewportElement rather than only returning the nearest svg element because a symbol establishes a viewport too. r=dholbert, a=ritu + + --HG-- + extra : source : 813d4e250712d296eb4b11b0b89e10ed6a94e3d4 +--- + dom/svg/SVGContentUtils.cpp | 12 ++++++---- + dom/svg/SVGContentUtils.h | 5 ++-- + dom/svg/SVGLength.cpp | 2 +- + dom/svg/SVGMarkerElement.cpp | 2 +- + dom/svg/SVGMarkerElement.h | 4 ++-- + dom/svg/SVGSVGElement.h | 9 ------- + dom/svg/SVGViewportElement.h | 9 +++++++ + dom/svg/nsSVGElement.cpp | 34 +++++++++++++-------------- + dom/svg/nsSVGElement.h | 3 ++- + layout/base/nsLayoutUtils.cpp | 4 ++-- + layout/reftests/svg/reftest.list | 1 + + layout/reftests/svg/viewBox-and-symbol-01.svg | 14 +++++++++++ + layout/svg/nsCSSClipPathInstance.cpp | 1 - + layout/svg/nsSVGImageFrame.cpp | 1 - + layout/svg/nsSVGImageFrame.h | 1 - + layout/svg/nsSVGMarkerFrame.cpp | 4 ++-- + layout/svg/nsSVGMarkerFrame.h | 4 ++-- + layout/svg/nsSVGPatternFrame.cpp | 2 +- + layout/svg/nsSVGUtils.cpp | 6 ++--- + 19 files changed, 68 insertions(+), 50 deletions(-) + +diff --git dom/svg/SVGContentUtils.cpp dom/svg/SVGContentUtils.cpp +index 0f744ffd8dd1..a6bf6245e95e 100644 +--- dom/svg/SVGContentUtils.cpp ++++ dom/svg/SVGContentUtils.cpp +@@ -374,8 +374,8 @@ SVGContentUtils::EstablishesViewport(nsIContent *aContent) + nsGkAtoms::symbol); + } + +-nsSVGElement* +-SVGContentUtils::GetNearestViewportElement(nsIContent *aContent) ++SVGViewportElement* ++SVGContentUtils::GetNearestViewportElement(const nsIContent *aContent) + { + nsIContent *element = aContent->GetFlattenedTreeParent(); + +@@ -384,7 +384,11 @@ SVGContentUtils::GetNearestViewportElement(nsIContent *aContent) + if (element->IsSVGElement(nsGkAtoms::foreignObject)) { + return nullptr; + } +- return static_cast<nsSVGElement*>(element); ++ MOZ_ASSERT(element->IsAnyOfSVGElements(nsGkAtoms::svg, ++ nsGkAtoms::symbol), ++ "upcoming static_cast is only valid for " ++ "SVGViewportElement subclasses"); ++ return static_cast<SVGViewportElement*>(element); + } + element = element->GetFlattenedTreeParent(); + } +@@ -828,7 +832,7 @@ SVGContentUtils::CoordToFloat(nsSVGElement *aContent, + return nsPresContext::AppUnitsToFloatCSSPixels(aCoord.GetCoordValue()); + + case eStyleUnit_Percent: { +- SVGSVGElement* ctx = aContent->GetCtx(); ++ SVGViewportElement* ctx = aContent->GetCtx(); + return ctx ? aCoord.GetPercentValue() * ctx->GetLength(SVGContentUtils::XY) : 0.0f; + } + default: +diff --git dom/svg/SVGContentUtils.h dom/svg/SVGContentUtils.h +index 36c74f47d75a..8ec309daf6f8 100644 +--- dom/svg/SVGContentUtils.h ++++ dom/svg/SVGContentUtils.h +@@ -32,6 +32,7 @@ class SVGPreserveAspectRatio; + namespace dom { + class Element; + class SVGSVGElement; ++class SVGViewportElement; + } // namespace dom + + } // namespace mozilla +@@ -238,8 +239,8 @@ public: + */ + static bool EstablishesViewport(nsIContent *aContent); + +- static nsSVGElement* +- GetNearestViewportElement(nsIContent *aContent); ++ static mozilla::dom::SVGViewportElement* ++ GetNearestViewportElement(const nsIContent *aContent); + + /* enum for specifying coordinate direction for ObjectSpace/UserSpace */ + enum ctxDirection { X, Y, XY }; +diff --git dom/svg/SVGLength.cpp dom/svg/SVGLength.cpp +index 6c13e2e8d1a0..cecbbc8f5b40 100644 +--- dom/svg/SVGLength.cpp ++++ dom/svg/SVGLength.cpp +@@ -177,7 +177,7 @@ SVGLength::GetUserUnitsPerUnit(const nsSVGElement *aElement, uint8_t aAxis) cons + SVGLength::GetUserUnitsPerPercent(const nsSVGElement *aElement, uint8_t aAxis) + { + if (aElement) { +- dom::SVGSVGElement *viewportElement = aElement->GetCtx(); ++ dom::SVGViewportElement *viewportElement = aElement->GetCtx(); + if (viewportElement) { + return std::max(viewportElement->GetLength(aAxis) / 100.0f, 0.0f); + } +diff --git dom/svg/SVGMarkerElement.cpp dom/svg/SVGMarkerElement.cpp +index 9b0b2fcfab1e..c4cf29ae274f 100644 +--- dom/svg/SVGMarkerElement.cpp ++++ dom/svg/SVGMarkerElement.cpp +@@ -250,7 +250,7 @@ SVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsIAtom* aName, + // nsSVGElement methods + + void +-SVGMarkerElement::SetParentCoordCtxProvider(SVGSVGElement *aContext) ++SVGMarkerElement::SetParentCoordCtxProvider(SVGViewportElement *aContext) + { + mCoordCtx = aContext; + mViewBoxToViewportTransform = nullptr; +diff --git dom/svg/SVGMarkerElement.h dom/svg/SVGMarkerElement.h +index 5d32de840b7a..ae08885c646e 100644 +--- dom/svg/SVGMarkerElement.h ++++ dom/svg/SVGMarkerElement.h +@@ -153,7 +153,7 @@ protected: + const nsAString& aValue, + nsAttrValue& aResult) override; + +- void SetParentCoordCtxProvider(SVGSVGElement *aContext); ++ void SetParentCoordCtxProvider(SVGViewportElement *aContext); + + virtual LengthAttributesInfo GetLengthInfo() override; + virtual AngleAttributesInfo GetAngleInfo() override; +@@ -180,7 +180,7 @@ protected: + // derived properties (from 'orient') handled separately + nsSVGOrientType mOrientType; + +- SVGSVGElement *mCoordCtx; ++ SVGViewportElement* mCoordCtx; + nsAutoPtr<gfx::Matrix> mViewBoxToViewportTransform; + }; + +diff --git dom/svg/SVGSVGElement.h dom/svg/SVGSVGElement.h +index fc3d7f3b55c5..431d70da2bef 100644 +--- dom/svg/SVGSVGElement.h ++++ dom/svg/SVGSVGElement.h +@@ -182,15 +182,6 @@ public: + // SVG-as-an-image documents.) + virtual void FlushImageTransformInvalidation(); + +- svgFloatSize GetViewportSize() const { +- return svgFloatSize(mViewportWidth, mViewportHeight); +- } +- +- void SetViewportSize(const svgFloatSize& aSize) { +- mViewportWidth = aSize.width; +- mViewportHeight = aSize.height; +- } +- + private: + // SVGViewportElement methods: + +diff --git dom/svg/SVGViewportElement.h dom/svg/SVGViewportElement.h +index fbc866e6a8d2..202797785131 100644 +--- dom/svg/SVGViewportElement.h ++++ dom/svg/SVGViewportElement.h +@@ -127,6 +127,15 @@ public: + + gfx::Matrix GetViewBoxTransform() const; + ++ svgFloatSize GetViewportSize() const { ++ return svgFloatSize(mViewportWidth, mViewportHeight); ++ } ++ ++ void SetViewportSize(const svgFloatSize& aSize) { ++ mViewportWidth = aSize.width; ++ mViewportHeight = aSize.height; ++ } ++ + // WebIDL + already_AddRefed<SVGAnimatedRect> ViewBox(); + already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio(); +diff --git dom/svg/nsSVGElement.cpp dom/svg/nsSVGElement.cpp +index 8757150c5925..a8aaa2fb5274 100644 +--- dom/svg/nsSVGElement.cpp ++++ dom/svg/nsSVGElement.cpp +@@ -1107,7 +1107,20 @@ nsSVGElement::GetOwnerSVGElement(nsIDOMSVGElement * *aOwnerSVGElement) + SVGSVGElement* + nsSVGElement::GetOwnerSVGElement() + { +- return GetCtx(); // this may return nullptr ++ nsIContent* ancestor = GetFlattenedTreeParent(); ++ ++ while (ancestor && ancestor->IsSVGElement()) { ++ if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) { ++ return nullptr; ++ } ++ if (ancestor->IsSVGElement(nsGkAtoms::svg)) { ++ return static_cast<SVGSVGElement*>(ancestor); ++ } ++ ancestor = ancestor->GetFlattenedTreeParent(); ++ } ++ ++ // we don't have an ancestor <svg> element... ++ return nullptr; + } + + NS_IMETHODIMP +@@ -1543,23 +1556,10 @@ nsIAtom* nsSVGElement::GetEventNameForAttr(nsIAtom* aAttr) + return aAttr; + } + +-SVGSVGElement * ++SVGViewportElement * + nsSVGElement::GetCtx() const + { +- nsIContent* ancestor = GetFlattenedTreeParent(); +- +- while (ancestor && ancestor->IsSVGElement()) { +- if (ancestor->IsSVGElement(nsGkAtoms::foreignObject)) { +- return nullptr; +- } +- if (ancestor->IsSVGElement(nsGkAtoms::svg)) { +- return static_cast<SVGSVGElement*>(ancestor); +- } +- ancestor = ancestor->GetFlattenedTreeParent(); +- } +- +- // we don't have an ancestor <svg> element... +- return nullptr; ++ return SVGContentUtils::GetNearestViewportElement(this); + } + + /* virtual */ gfxMatrix +@@ -1658,7 +1658,7 @@ nsSVGElement::GetAnimatedLengthValues(float *aFirst, ...) + NS_ASSERTION(info.mLengthCount > 0, + "GetAnimatedLengthValues on element with no length attribs"); + +- SVGSVGElement *ctx = nullptr; ++ SVGViewportElement *ctx = nullptr; + + float *f = aFirst; + uint32_t i = 0; +diff --git dom/svg/nsSVGElement.h dom/svg/nsSVGElement.h +index 28c46188d4e4..955a327561d3 100644 +--- dom/svg/nsSVGElement.h ++++ dom/svg/nsSVGElement.h +@@ -44,6 +44,7 @@ class DeclarationBlock; + + namespace dom { + class SVGSVGElement; ++class SVGViewportElement; + + static const unsigned short SVG_UNIT_TYPE_UNKNOWN = 0; + static const unsigned short SVG_UNIT_TYPE_USERSPACEONUSE = 1; +@@ -145,7 +146,7 @@ public: + // Gets the element that establishes the rectangular viewport against which + // we should resolve percentage lengths (our "coordinate context"). Returns + // nullptr for outer <svg> or SVG without an <svg> parent (invalid SVG). +- mozilla::dom::SVGSVGElement* GetCtx() const; ++ mozilla::dom::SVGViewportElement* GetCtx() const; + + /** + * Returns aMatrix pre-multiplied by (explicit or implicit) transforms that +diff --git layout/base/nsLayoutUtils.cpp layout/base/nsLayoutUtils.cpp +index f5ca2719e333..7f3f5354befc 100644 +--- layout/base/nsLayoutUtils.cpp ++++ layout/base/nsLayoutUtils.cpp +@@ -120,7 +120,7 @@ + #include "mozilla/StyleSetHandle.h" + #include "mozilla/StyleSetHandleInlines.h" + #include "RegionBuilder.h" +-#include "SVGSVGElement.h" ++#include "SVGViewportElement.h" + #include "DisplayItemClip.h" + #include "mozilla/layers/WebRenderLayerManager.h" + #include "prenv.h" +@@ -9479,7 +9479,7 @@ ComputeSVGReferenceRect(nsIFrame* aFrame, + case StyleGeometryBox::ViewBox: { + nsIContent* content = aFrame->GetContent(); + nsSVGElement* element = static_cast<nsSVGElement*>(content); +- SVGSVGElement* svgElement = element->GetCtx(); ++ SVGViewportElement* svgElement = element->GetCtx(); + MOZ_ASSERT(svgElement); + + if (svgElement && svgElement->HasViewBoxRect()) { +diff --git layout/reftests/svg/reftest.list layout/reftests/svg/reftest.list +index 2d3981f0b65e..0b96144724bb 100644 +--- layout/reftests/svg/reftest.list ++++ layout/reftests/svg/reftest.list +@@ -532,6 +532,7 @@ fuzzy-if(skiaContent,1,100) == tspan-xy-anchor-end-01.svg tspan-xy-anchor-end-re + == viewBox-and-pattern-02.svg pass.svg + == viewBox-and-pattern-03.svg pass.svg + == viewBox-and-pattern-04.svg pass.svg ++== viewBox-and-symbol-01.svg pass.svg + == viewBox-invalid-01.svg pass.svg + == viewBox-invalid-02.svg pass.svg + == viewBox-valid-01.svg pass.svg +diff --git layout/reftests/svg/viewBox-and-symbol-01.svg layout/reftests/svg/viewBox-and-symbol-01.svg +new file mode 100644 +index 000000000000..5c8ebf7bc3ea +--- /dev/null ++++ layout/reftests/svg/viewBox-and-symbol-01.svg +@@ -0,0 +1,14 @@ ++<svg xmlns="http://www.w3.org/2000/svg"> ++ <defs> ++ <symbol id="mySymbol" viewBox="0 0 20 20"> ++ <rect fill="lime" x="50%" height="20px" width="3%"/> ++ </symbol> ++ </defs> ++ <rect width="100%" height="100%" fill="lime"/> ++ <svg viewBox="0 0 20 20"> ++ <rect fill="red" x="50%" height="20px" width="2%"/> ++ </svg> ++ <svg> ++ <use href="#mySymbol"/> ++ </svg> ++</svg> +diff --git layout/svg/nsCSSClipPathInstance.cpp layout/svg/nsCSSClipPathInstance.cpp +index 09d3530c4ef0..0c25f7a21bb8 100644 +--- layout/svg/nsCSSClipPathInstance.cpp ++++ layout/svg/nsCSSClipPathInstance.cpp +@@ -9,7 +9,6 @@ + #include "gfx2DGlue.h" + #include "gfxContext.h" + #include "gfxPlatform.h" +-#include "mozilla/dom/SVGSVGElement.h" + #include "mozilla/gfx/2D.h" + #include "mozilla/gfx/PathHelpers.h" + #include "mozilla/ShapeUtils.h" +diff --git layout/svg/nsSVGImageFrame.cpp layout/svg/nsSVGImageFrame.cpp +index 074415854667..21834954721d 100644 +--- layout/svg/nsSVGImageFrame.cpp ++++ layout/svg/nsSVGImageFrame.cpp +@@ -16,7 +16,6 @@ + #include "nsLayoutUtils.h" + #include "imgINotificationObserver.h" + #include "nsSVGEffects.h" +-#include "mozilla/dom/SVGSVGElement.h" + #include "nsSVGUtils.h" + #include "SVGContentUtils.h" + #include "SVGGeometryFrame.h" +diff --git layout/svg/nsSVGImageFrame.h layout/svg/nsSVGImageFrame.h +index b2c90fd6402d..fe0ac33ac02a 100644 +--- layout/svg/nsSVGImageFrame.h ++++ layout/svg/nsSVGImageFrame.h +@@ -17,7 +17,6 @@ + #include "nsLayoutUtils.h" + #include "imgINotificationObserver.h" + #include "nsSVGEffects.h" +-#include "mozilla/dom/SVGSVGElement.h" + #include "nsSVGUtils.h" + #include "SVGContentUtils.h" + #include "SVGGeometryFrame.h" +diff --git layout/svg/nsSVGMarkerFrame.cpp layout/svg/nsSVGMarkerFrame.cpp +index dbeb02ea5b2d..365a0aa70a26 100644 +--- layout/svg/nsSVGMarkerFrame.cpp ++++ layout/svg/nsSVGMarkerFrame.cpp +@@ -194,7 +194,7 @@ nsSVGMarkerFrame::GetMarkBBoxContribution(const Matrix& aToBBoxUserspace, + } + + void +-nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGSVGElement *aContext) ++nsSVGMarkerFrame::SetParentCoordCtxProvider(SVGViewportElement *aContext) + { + SVGMarkerElement *marker = static_cast<SVGMarkerElement*>(mContent); + marker->SetParentCoordCtxProvider(aContext); +@@ -219,7 +219,7 @@ nsSVGMarkerFrame::AutoMarkerReferencer::AutoMarkerReferencer( + mFrame->mInUse = true; + mFrame->mMarkedFrame = aMarkedFrame; + +- SVGSVGElement *ctx = ++ SVGViewportElement *ctx = + static_cast<nsSVGElement*>(aMarkedFrame->GetContent())->GetCtx(); + mFrame->SetParentCoordCtxProvider(ctx); + } +diff --git layout/svg/nsSVGMarkerFrame.h layout/svg/nsSVGMarkerFrame.h +index 95415e6dcc21..03099eab9324 100644 +--- layout/svg/nsSVGMarkerFrame.h ++++ layout/svg/nsSVGMarkerFrame.h +@@ -20,7 +20,7 @@ class gfxContext; + namespace mozilla { + class SVGGeometryFrame; + namespace dom { +-class SVGSVGElement; ++class SVGViewportElement; + } // namespace dom + } // namespace mozilla + +@@ -119,7 +119,7 @@ private: + }; + + // nsSVGMarkerFrame methods: +- void SetParentCoordCtxProvider(mozilla::dom::SVGSVGElement *aContext); ++ void SetParentCoordCtxProvider(mozilla::dom::SVGViewportElement *aContext); + + // recursion prevention flag + bool mInUse; +diff --git layout/svg/nsSVGPatternFrame.cpp layout/svg/nsSVGPatternFrame.cpp +index 488ac2f5c783..5078fb1b5a31 100644 +--- layout/svg/nsSVGPatternFrame.cpp ++++ layout/svg/nsSVGPatternFrame.cpp +@@ -660,7 +660,7 @@ nsSVGPatternFrame::ConstructCTM(const nsSVGViewBox& aViewBox, + const Matrix &callerCTM, + nsIFrame *aTarget) + { +- SVGSVGElement *ctx = nullptr; ++ SVGViewportElement *ctx = nullptr; + nsIContent* targetContent = aTarget->GetContent(); + gfxFloat scaleX, scaleY; + +diff --git layout/svg/nsSVGUtils.cpp layout/svg/nsSVGUtils.cpp +index d53a3ede0be7..f21c23491285 100644 +--- layout/svg/nsSVGUtils.cpp ++++ layout/svg/nsSVGUtils.cpp +@@ -49,7 +49,7 @@ + #include "SVGGeometryElement.h" + #include "SVGGeometryFrame.h" + #include "nsSVGPaintServerFrame.h" +-#include "mozilla/dom/SVGSVGElement.h" ++#include "mozilla/dom/SVGViewportElement.h" + #include "nsTextFrame.h" + #include "SVGContentUtils.h" + #include "SVGTextFrame.h" +@@ -290,7 +290,7 @@ nsSVGUtils::GetContextSize(const nsIFrame* aFrame) + MOZ_ASSERT(aFrame->GetContent()->IsSVGElement(), "bad cast"); + const nsSVGElement* element = static_cast<nsSVGElement*>(aFrame->GetContent()); + +- SVGSVGElement* ctx = element->GetCtx(); ++ SVGViewportElement* ctx = element->GetCtx(); + if (ctx) { + size.width = ctx->GetLength(SVGContentUtils::X); + size.height = ctx->GetLength(SVGContentUtils::Y); +@@ -323,7 +323,7 @@ nsSVGUtils::ObjectSpace(const gfxRect &aRect, const nsSVGLength2 *aLength) + // Multiply first to avoid precision errors: + return axis * aLength->GetAnimValInSpecifiedUnits() / 100; + } +- return aLength->GetAnimValue(static_cast<SVGSVGElement*>(nullptr)) * axis; ++ return aLength->GetAnimValue(static_cast<SVGViewportElement*>(nullptr)) * axis; + } + + float diff --git a/www/waterfox/files/patch-bug1398983 b/www/waterfox/files/patch-bug1398983 new file mode 100644 index 000000000000..b273a11cd518 --- /dev/null +++ b/www/waterfox/files/patch-bug1398983 @@ -0,0 +1,25 @@ +commit 6b2dbc2b8216 +Author: Bobby Holley <bobbyholley@gmail.com> +Date: Fri Sep 15 12:25:46 2017 -0700 + + Bug 1398983 - Remove warning about assuming gecko style system. r=me + + MozReview-Commit-ID: BCeG81uxLvS +--- + dom/base/nsDocument.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 9d9af08ba04b..076fe1a5d444 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -13490,7 +13490,8 @@ nsIDocument::UpdateStyleBackendType() + // Enable stylo for SVG-as-image. + mStyleBackendType = StyleBackendType::Servo; + } else if (!mDocumentContainer) { +- NS_WARNING("stylo: No docshell yet, assuming Gecko style system"); ++ // Not docshell, assume Gecko. Various callers can end up setting this ++ // explicitly afterwards to inherit it in various situations. + } else if (!IsXULDocument() && IsContentDocument()) { + // Disable stylo for about: pages other than about:blank, since + // they tend to use unsupported selectors like XUL tree pseudos. diff --git a/www/waterfox/files/patch-bug1399091 b/www/waterfox/files/patch-bug1399091 new file mode 100644 index 000000000000..5b94ab09a5b9 --- /dev/null +++ b/www/waterfox/files/patch-bug1399091 @@ -0,0 +1,36 @@ +commit 4d1c939529c1 +Author: Catalin Badea <catalin.badea392@gmail.com> +Date: Sun Sep 24 16:44:51 2017 -0400 + + Bug 1399091 - Avoid adding the same range to multiple selections. r=mats, a=sledru + + --HG-- + extra : source : c3b24ef4281035ee00e09b3386fcbf2d672775c4 +--- + dom/base/nsRange.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git dom/base/nsRange.cpp dom/base/nsRange.cpp +index 1e95ec629f55..8221450b828b 100644 +--- dom/base/nsRange.cpp ++++ dom/base/nsRange.cpp +@@ -1048,12 +1048,19 @@ nsRange::SetSelection(mozilla::dom::Selection* aSelection) + if (mSelection == aSelection) { + return; + } ++ + // At least one of aSelection and mSelection must be null + // aSelection will be null when we are removing from a selection + // and a range can't be in more than one selection at a time, + // thus mSelection must be null too. + MOZ_ASSERT(!aSelection || !mSelection); + ++ // Extra step in case our parent failed to ensure the above ++ // invariant. ++ if (aSelection && mSelection) { ++ mSelection->RemoveRange(this); ++ } ++ + mSelection = aSelection; + if (mSelection) { + nsINode* commonAncestor = GetCommonAncestor(); diff --git a/www/waterfox/files/patch-bug1399177 b/www/waterfox/files/patch-bug1399177 new file mode 100644 index 000000000000..f412dbb621cf --- /dev/null +++ b/www/waterfox/files/patch-bug1399177 @@ -0,0 +1,47 @@ +commit 376eb2d39f54 +Author: Doug Thayer <dothayer@mozilla.com> +Date: Wed Sep 20 15:58:25 2017 -0700 + + Bug 1399177 - Pull label out of description in update popups. r=Gijs, a=sledru + + The margin rules for labels mean that if the See what's new link + starts its own line, the alignment looks off. We could override this, + but matching the styling for "Learn more" links, which get their own + line, seemed the better option. + + MozReview-Commit-ID: 4WK9QtRMUQs + + --HG-- + extra : source : f81f645704e4cdfaeebeb21d53d5d749718c3959 +--- + browser/components/customizableui/content/panelUI.inc.xul | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git browser/components/customizableui/content/panelUI.inc.xul browser/components/customizableui/content/panelUI.inc.xul +index 86fc1fa5639f..e7c63f612dc6 100644 +--- browser/components/customizableui/content/panelUI.inc.xul ++++ browser/components/customizableui/content/panelUI.inc.xul +@@ -421,9 +421,8 @@ + buttonhighlight="true" + hidden="true"> + <popupnotificationcontent id="update-available-notification-content" orient="vertical"> +- <description id="update-available-description">&updateAvailable.message; +- <label id="update-available-whats-new" class="text-link" value="&updateAvailable.whatsnew.label;" /> +- </description> ++ <description id="update-available-description">&updateAvailable.message;</description> ++ <label id="update-available-whats-new" class="text-link" value="&updateAvailable.whatsnew.label;" /> + </popupnotificationcontent> + </popupnotification> + +@@ -440,9 +439,8 @@ + buttonhighlight="true" + hidden="true"> + <popupnotificationcontent id="update-manual-notification-content" orient="vertical"> +- <description id="update-manual-description">&updateManual.message; +- <label id="update-manual-whats-new" class="text-link" value="&updateManual.whatsnew.label;" /> +- </description> ++ <description id="update-manual-description">&updateManual.message;</description> ++ <label id="update-manual-whats-new" class="text-link" value="&updateManual.whatsnew.label;" /> + </popupnotificationcontent> + </popupnotification> + diff --git a/www/waterfox/files/patch-bug1399336 b/www/waterfox/files/patch-bug1399336 new file mode 100644 index 000000000000..cdd53e791954 --- /dev/null +++ b/www/waterfox/files/patch-bug1399336 @@ -0,0 +1,153 @@ +commit 355019fdeca4 +Author: Mantaroh Yoshinaga <mantaroh@gmail.com> +Date: Wed Sep 13 14:23:59 2017 +0900 + + Bug 1399336 - Memory leak of char16_t internal variables of widget/nsPrintOptionsImpl.cpp r=m_kato + + A nsPrintOptionsImpl has char16_t internal variables, and gecko will not release + these allocated variable. So we should use nsString instead of char16_t. + + MozReview-Commit-ID: 4ZMtUKoVCcR + + --HG-- + extra : rebase_source : 1720483301b900f8135c3d5f8f32d7051191aa8f +--- + widget/nsPrintOptionsImpl.cpp | 46 ++++++++++++++++++++----------------------- + 1 file changed, 21 insertions(+), 25 deletions(-) + +diff --git widget/nsPrintOptionsImpl.cpp widget/nsPrintOptionsImpl.cpp +index c36b5be3e8a7..c2b5e113612e 100644 +--- widget/nsPrintOptionsImpl.cpp ++++ widget/nsPrintOptionsImpl.cpp +@@ -765,13 +765,13 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName, + if (aFlags & nsIPrintSettings::kInitSavePaperSize) { + int16_t sizeUnit; + double width, height; +- char16_t *name; ++ nsString name; + + if ( + NS_SUCCEEDED(aPS->GetPaperSizeUnit(&sizeUnit)) && + NS_SUCCEEDED(aPS->GetPaperWidth(&width)) && + NS_SUCCEEDED(aPS->GetPaperHeight(&height)) && +- NS_SUCCEEDED(aPS->GetPaperName(&name)) ++ NS_SUCCEEDED(aPS->GetPaperName(getter_Copies(name))) + ) { + DUMP_INT(kWriteStr, kPrintPaperSizeUnit, sizeUnit); + Preferences::SetInt(GetPrefName(kPrintPaperSizeUnit, aPrinterName), +@@ -780,7 +780,7 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName, + WritePrefDouble(GetPrefName(kPrintPaperWidth, aPrinterName), width); + DUMP_DBL(kWriteStr, kPrintPaperHeight, height); + WritePrefDouble(GetPrefName(kPrintPaperHeight, aPrinterName), height); +- DUMP_STR(kWriteStr, kPrintPaperName, name); ++ DUMP_STR(kWriteStr, kPrintPaperName, name.get()); + Preferences::SetString(GetPrefName(kPrintPaperName, aPrinterName), name); + #if defined(XP_WIN) + // If the height and width are -1 then this might be a save triggered by +@@ -800,7 +800,7 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName, + } + + bool b; +- char16_t* uStr; ++ nsString uStr; + int32_t iVal; + int16_t iVal16; + double dbl; +@@ -822,48 +822,48 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName, + } + + if (aFlags & nsIPrintSettings::kInitSaveHeaderLeft) { +- if (NS_SUCCEEDED(aPS->GetHeaderStrLeft(&uStr))) { +- DUMP_STR(kWriteStr, kPrintHeaderStrLeft, uStr); ++ if (NS_SUCCEEDED(aPS->GetHeaderStrLeft(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintHeaderStrLeft, uStr.get()); + Preferences::SetString(GetPrefName(kPrintHeaderStrLeft, aPrinterName), + uStr); + } + } + + if (aFlags & nsIPrintSettings::kInitSaveHeaderCenter) { +- if (NS_SUCCEEDED(aPS->GetHeaderStrCenter(&uStr))) { +- DUMP_STR(kWriteStr, kPrintHeaderStrCenter, uStr); ++ if (NS_SUCCEEDED(aPS->GetHeaderStrCenter(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintHeaderStrCenter, uStr.get()); + Preferences::SetString(GetPrefName(kPrintHeaderStrCenter, aPrinterName), + uStr); + } + } + + if (aFlags & nsIPrintSettings::kInitSaveHeaderRight) { +- if (NS_SUCCEEDED(aPS->GetHeaderStrRight(&uStr))) { +- DUMP_STR(kWriteStr, kPrintHeaderStrRight, uStr); ++ if (NS_SUCCEEDED(aPS->GetHeaderStrRight(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintHeaderStrRight, uStr.get()); + Preferences::SetString(GetPrefName(kPrintHeaderStrRight, aPrinterName), + uStr); + } + } + + if (aFlags & nsIPrintSettings::kInitSaveFooterLeft) { +- if (NS_SUCCEEDED(aPS->GetFooterStrLeft(&uStr))) { +- DUMP_STR(kWriteStr, kPrintFooterStrLeft, uStr); ++ if (NS_SUCCEEDED(aPS->GetFooterStrLeft(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintFooterStrLeft, uStr.get()); + Preferences::SetString(GetPrefName(kPrintFooterStrLeft, aPrinterName), + uStr); + } + } + + if (aFlags & nsIPrintSettings::kInitSaveFooterCenter) { +- if (NS_SUCCEEDED(aPS->GetFooterStrCenter(&uStr))) { +- DUMP_STR(kWriteStr, kPrintFooterStrCenter, uStr); ++ if (NS_SUCCEEDED(aPS->GetFooterStrCenter(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintFooterStrCenter, uStr.get()); + Preferences::SetString(GetPrefName(kPrintFooterStrCenter, aPrinterName), + uStr); + } + } + + if (aFlags & nsIPrintSettings::kInitSaveFooterRight) { +- if (NS_SUCCEEDED(aPS->GetFooterStrRight(&uStr))) { +- DUMP_STR(kWriteStr, kPrintFooterStrRight, uStr); ++ if (NS_SUCCEEDED(aPS->GetFooterStrRight(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintFooterStrRight, uStr.get()); + Preferences::SetString(GetPrefName(kPrintFooterStrRight, aPrinterName), + uStr); + } +@@ -915,8 +915,8 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName, + // Only the general version of this pref is saved + if ((aFlags & nsIPrintSettings::kInitSavePrinterName) + && aPrinterName.IsEmpty()) { +- if (NS_SUCCEEDED(aPS->GetPrinterName(&uStr))) { +- DUMP_STR(kWriteStr, kPrinterName, uStr); ++ if (NS_SUCCEEDED(aPS->GetPrinterName(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrinterName, uStr.get()); + Preferences::SetString(kPrinterName, uStr); + } + } +@@ -929,8 +929,8 @@ nsPrintOptions::WritePrefs(nsIPrintSettings *aPS, const nsAString& aPrinterName, + } + + if (aFlags & nsIPrintSettings::kInitSaveToFileName) { +- if (NS_SUCCEEDED(aPS->GetToFileName(&uStr))) { +- DUMP_STR(kWriteStr, kPrintToFileName, uStr); ++ if (NS_SUCCEEDED(aPS->GetToFileName(getter_Copies(uStr)))) { ++ DUMP_STR(kWriteStr, kPrintToFileName, uStr.get()); + Preferences::SetString(GetPrefName(kPrintToFileName, aPrinterName), uStr); + } + } +@@ -1105,13 +1105,9 @@ GetAdjustedPrinterName(nsIPrintSettings* aPS, bool aUsePNP, + + // Get the Printer Name from the PrintSettings + // to use as a prefix for Pref Names +- char16_t* prtName = nullptr; +- +- nsresult rv = aPS->GetPrinterName(&prtName); ++ nsresult rv = aPS->GetPrinterName(getter_Copies(aPrinterName)); + NS_ENSURE_SUCCESS(rv, rv); + +- aPrinterName = nsDependentString(prtName); +- + // Convert any whitespaces, carriage returns or newlines to _ + // The below algorithm is supposedly faster than using iterators + NS_NAMED_LITERAL_STRING(replSubstr, "_"); diff --git a/www/waterfox/files/patch-bug1399412 b/www/waterfox/files/patch-bug1399412 new file mode 100644 index 000000000000..29d0b3c5701a --- /dev/null +++ b/www/waterfox/files/patch-bug1399412 @@ -0,0 +1,31 @@ +commit f2d86a8b3050 +Author: Dimitry Andric <dimitry@andric.com> +Date: Wed Sep 13 09:43:00 2017 -0400 + + Bug 1399412 - Work around clang assertion by wrapping lz4.c in an extern C block. r=froydnj + + MozReview-Commit-ID: LLgSbJadbyJ + + --HG-- + extra : amend_source : 08d7908fe6807db654411fc291bccc98496d4275 +--- + mfbt/Compression.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git mfbt/Compression.cpp mfbt/Compression.cpp +index 0a94cc69e224..c675aa90af62 100644 +--- mfbt/Compression.cpp ++++ mfbt/Compression.cpp +@@ -25,8 +25,12 @@ using namespace mozilla::Compression; + + namespace { + ++extern "C" { ++ + #include "lz4.c" + ++} ++ + }/* anonymous namespace */ + + /* Our wrappers */ diff --git a/www/waterfox/files/patch-bug1399520 b/www/waterfox/files/patch-bug1399520 new file mode 100644 index 000000000000..0db6cf64bb7c --- /dev/null +++ b/www/waterfox/files/patch-bug1399520 @@ -0,0 +1,93 @@ +commit b4603106d015 +Author: Liang-Heng Chen <xeonchen@gmail.com> +Date: Thu Oct 19 22:29:41 2017 -0400 + + Bug 1399520 - Avoid race condition. r=dragana + + MozReview-Commit-ID: 6Pd2HXqBgX4 +--- + modules/libjar/nsJAR.cpp | 26 ++++++++++++++++++-------- + modules/libjar/nsJAR.h | 8 +++++--- + 2 files changed, 23 insertions(+), 11 deletions(-) + +diff --git modules/libjar/nsJAR.cpp modules/libjar/nsJAR.cpp +index 80589e03f92b..b3121d99ef0a 100644 +--- modules/libjar/nsJAR.cpp ++++ modules/libjar/nsJAR.cpp +@@ -43,11 +43,27 @@ NS_IMPL_QUERY_INTERFACE(nsJAR, nsIZipReader) + NS_IMPL_ADDREF(nsJAR) + + // Custom Release method works with nsZipReaderCache... ++// Release might be called from multi-thread, we have to ++// take this function carefully to avoid delete-after-use. + MozExternalRefCountType nsJAR::Release(void) + { + nsrefcnt count; + NS_PRECONDITION(0 != mRefCnt, "dup release"); +- count = --mRefCnt; ++ ++ RefPtr<nsZipReaderCache> cache; ++ if (mRefCnt == 2) { // don't use a lock too frequently ++ // Use a mutex here to guarantee mCache is not racing and the target instance ++ // is still valid to increase ref-count. ++ MutexAutoLock lock(mLock); ++ cache = mCache; ++ mCache = nullptr; ++ } ++ if (cache) { ++ DebugOnly<nsresult> rv = cache->ReleaseZip(this); ++ MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to release zip file"); ++ } ++ ++ count = --mRefCnt; // don't access any member variable after this line + NS_LOG_RELEASE(this, count, "nsJAR"); + if (0 == count) { + mRefCnt = 1; /* stabilize */ +@@ -56,13 +72,7 @@ MozExternalRefCountType nsJAR::Release(void) + delete this; + return 0; + } +- if (1 == count && mCache) { +-#ifdef DEBUG +- nsresult rv = +-#endif +- mCache->ReleaseZip(this); +- NS_ASSERTION(NS_SUCCEEDED(rv), "failed to release zip file"); +- } ++ + return count; + } + +diff --git modules/libjar/nsJAR.h modules/libjar/nsJAR.h +index 7f675c93003b..4fe948680fbf 100644 +--- modules/libjar/nsJAR.h ++++ modules/libjar/nsJAR.h +@@ -12,6 +12,7 @@ + #include "mozilla/Logging.h" + #include "prinrval.h" + ++#include "mozilla/Atomics.h" + #include "mozilla/Mutex.h" + #include "nsIComponentManager.h" + #include "nsCOMPtr.h" +@@ -75,8 +76,9 @@ class nsJAR final : public nsIZipReader + mReleaseTime = PR_INTERVAL_NO_TIMEOUT; + } + +- void SetZipReaderCache(nsZipReaderCache* cache) { +- mCache = cache; ++ void SetZipReaderCache(nsZipReaderCache* aCache) { ++ mozilla::MutexAutoLock lock(mLock); ++ mCache = aCache; + } + + nsresult GetNSPRFileDesc(PRFileDesc** aNSPRFileDesc); +@@ -89,7 +91,7 @@ class nsJAR final : public nsIZipReader + RefPtr<nsZipArchive> mZip; // The underlying zip archive + PRIntervalTime mReleaseTime; // used by nsZipReaderCache for flushing entries + nsZipReaderCache* mCache; // if cached, this points to the cache it's contained in +- mozilla::Mutex mLock; ++ mozilla::Mutex mLock; // protect mCache and mZip + int64_t mMtime; + bool mOpened; + bool mIsOmnijar; diff --git a/www/waterfox/files/patch-bug1399939 b/www/waterfox/files/patch-bug1399939 new file mode 100644 index 000000000000..95bdfb17d22a --- /dev/null +++ b/www/waterfox/files/patch-bug1399939 @@ -0,0 +1,36 @@ +commit b0369ebbca69 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Thu Sep 28 12:00:22 2017 +0100 + + Bug 1399939 - Switch to highly restrictive profile for IDN. r=dveditz, r=jfkthame, a=sledru + + MozReview-Commit-ID: E5LRuQVfIZP + + --HG-- + extra : source : e1c1ebf60808e5e94b9a03d8cb577990ac0b9ca1 +--- + modules/libpref/init/all.js | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index c74659f8d4a5..c796df0fef1d 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -1913,7 +1913,7 @@ pref("network.IDN_show_punycode", false); + // IDN-safe. Otherwise, they're treated as unsafe and punycode will be used + // for displaying them in the UI (e.g. URL bar), unless they conform to one of + // the profiles specified in +-// http://www.unicode.org/reports/tr36/proposed.html#Security_Levels_and_Alerts ++// https://www.unicode.org/reports/tr39/#Restriction_Level_Detection + // If "network.IDN.restriction_profile" is "high", the Highly Restrictive + // profile is used. + // If "network.IDN.restriction_profile" is "moderate", the Moderately +@@ -1922,7 +1922,7 @@ pref("network.IDN_show_punycode", false); + // Note that these preferences are referred to ONLY when + // "network.IDN_show_punycode" is false. In other words, all IDNs will be shown + // in punycode if "network.IDN_show_punycode" is true. +-pref("network.IDN.restriction_profile", "moderate"); ++pref("network.IDN.restriction_profile", "high"); + pref("network.IDN.use_whitelist", false); + + // ccTLDs diff --git a/www/waterfox/files/patch-bug1400238 b/www/waterfox/files/patch-bug1400238 new file mode 100644 index 000000000000..efc0314ff24c --- /dev/null +++ b/www/waterfox/files/patch-bug1400238 @@ -0,0 +1,30 @@ +commit 02ae35c9e105 +Author: Botond Ballo <botond@mozilla.com> +Date: Wed Oct 18 13:29:47 2017 -0400 + + Bug 1400238 - Notify TabParent when the GTK client offset changes. r=karlt + + MozReview-Commit-ID: 1TacAhl6c2M + + --HG-- + extra : rebase_source : 5641d417a6245cc2f8027fd91032119f1b36d461 +--- + widget/gtk/nsWindow.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp +index 955327297ac9..e58f3dcb59d5 100644 +--- widget/gtk/nsWindow.cpp ++++ widget/gtk/nsWindow.cpp +@@ -1567,6 +1567,11 @@ nsWindow::OnPropertyNotifyEvent(GtkWidget* aWidget, GdkEventProperty* aEvent) + { + if (aEvent->atom == gdk_atom_intern("_NET_FRAME_EXTENTS", FALSE)) { + UpdateClientOffset(); ++ ++ // Send a WindowMoved notification. This ensures that TabParent ++ // picks up the new client offset and sends it to the child process ++ // if appropriate. ++ NotifyWindowMoved(mBounds.x, mBounds.y); + return FALSE; + } + diff --git a/www/waterfox/files/patch-bug1400540 b/www/waterfox/files/patch-bug1400540 new file mode 100644 index 000000000000..6cbe87dc3d61 --- /dev/null +++ b/www/waterfox/files/patch-bug1400540 @@ -0,0 +1,47 @@ +commit 6905267b2878 +Author: Xidorn Quan <me@upsuper.org> +Date: Wed Sep 20 08:26:53 2017 +1000 + + Bug 1400540 - Decide style backend type based on principal. r=bholley + + MozReview-Commit-ID: A4y9Shdbr7g + + --HG-- + extra : source : cdfe5e5e059273a1c7fc6506d6e0fecb2bb7affb +--- + dom/base/nsDocument.cpp | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 642960e6a155..265af0df07b9 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -13465,20 +13465,15 @@ nsIDocument::UpdateStyleBackendType() + + #ifdef MOZ_STYLO + if (nsLayoutUtils::StyloEnabled()) { +- if (IsBeingUsedAsImage()) { +- // Enable stylo for SVG-as-image. ++ // Disable stylo only for system principal. Other principals aren't ++ // able to use XUL by default, and the back door to enable XUL is ++ // mostly just for testing, which means they don't matter, and we ++ // shouldn't respect them at the same time. ++ // Note that, since tests can have XUL support, we still need to ++ // explicitly exclude XUL documents here. ++ if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()) && ++ !IsXULDocument()) { + mStyleBackendType = StyleBackendType::Servo; +- } else if (!mDocumentContainer) { +- // Not docshell, assume Gecko. Various callers can end up setting this +- // explicitly afterwards to inherit it in various situations. +- } else if (!IsXULDocument() && IsContentDocument()) { +- // Disable stylo for about: pages other than about:blank, since +- // they tend to use unsupported selectors like XUL tree pseudos. +- bool isAbout = false; +- mDocumentURI->SchemeIs("about", &isAbout); +- if (!isAbout || NS_IsAboutBlank(mDocumentURI)) { +- mStyleBackendType = StyleBackendType::Servo; +- } + } + } + #endif diff --git a/www/waterfox/files/patch-bug1400674 b/www/waterfox/files/patch-bug1400674 new file mode 100644 index 000000000000..955ac0e9f58c --- /dev/null +++ b/www/waterfox/files/patch-bug1400674 @@ -0,0 +1,70 @@ +commit c08bea16ab67 (HEAD) +Author: JW Wang <jwwang@mozilla.com> +Date: Fri Oct 13 17:24:24 2017 +0800 + + Bug 1400674 - Fix the algorithm of filling audio gaps with silence. r=jya, a=ritu + + MozReview-Commit-ID: Hjsboq6PdlN + + --HG-- + extra : source : aecaa85bb1d9d8b7d2cbd9ab84eb6dbc0ed9eee8 +--- + dom/media/mediasink/AudioSink.cpp | 37 +++++++++++++++---------------------- + 1 file changed, 15 insertions(+), 22 deletions(-) + +diff --git dom/media/mediasink/AudioSink.cpp dom/media/mediasink/AudioSink.cpp +index 0dbb53a3387a..81be7ac0bd89 100644 +--- dom/media/mediasink/AudioSink.cpp ++++ dom/media/mediasink/AudioSink.cpp +@@ -426,28 +426,21 @@ AudioSink::NotifyAudioNeeded() + missingFrames = std::min<int64_t>(INT32_MAX, missingFrames.value()); + mFramesParsed += missingFrames.value(); + +- // We need to calculate how many frames are missing at the output rate. +- missingFrames = +- SaferMultDiv(missingFrames.value(), mOutputRate, data->mRate); +- if (!missingFrames.isValid()) { +- NS_WARNING("Int overflow in AudioSink"); +- mErrored = true; +- return; +- } +- +- // We need to insert silence, first use drained frames if any. +- missingFrames -= DrainConverter(missingFrames.value()); +- // Insert silence if still needed. +- if (missingFrames.value()) { +- AlignedAudioBuffer silenceData(missingFrames.value() * mOutputChannels); +- if (!silenceData) { +- NS_WARNING("OOM in AudioSink"); +- mErrored = true; +- return; +- } +- RefPtr<AudioData> silence = CreateAudioFromBuffer(Move(silenceData), data); +- PushProcessedAudio(silence); ++ RefPtr<AudioData> silenceData; ++ AlignedAudioBuffer silenceBuffer(missingFrames.value() * data->mChannels); ++ if (!silenceBuffer) { ++ NS_WARNING("OOM in AudioSink"); ++ mErrored = true; ++ return; ++ } ++ if (mConverter->InputConfig() != mConverter->OutputConfig()) { ++ AlignedAudioBuffer convertedData = ++ mConverter->Process(AudioSampleBuffer(Move(silenceBuffer))).Forget(); ++ silenceData = CreateAudioFromBuffer(Move(convertedData), data); ++ } else { ++ silenceData = CreateAudioFromBuffer(Move(silenceBuffer), data); + } ++ PushProcessedAudio(silenceData); + } + + mLastEndTime = data->GetEndTime(); +@@ -488,7 +481,7 @@ AudioSink::PushProcessedAudio(AudioData* aData) + + already_AddRefed<AudioData> + AudioSink::CreateAudioFromBuffer(AlignedAudioBuffer&& aBuffer, +- AudioData* aReference) ++ AudioData* aReference) + { + uint32_t frames = aBuffer.Length() / mOutputChannels; + if (!frames) { diff --git a/www/waterfox/files/patch-bug1400839 b/www/waterfox/files/patch-bug1400839 new file mode 100644 index 000000000000..88f5d88c2e16 --- /dev/null +++ b/www/waterfox/files/patch-bug1400839 @@ -0,0 +1,49 @@ +commit a0bf5a4eff67 +Author: sebastian@ifyouwantblood.de <sebastian@ifyouwantblood.de> +Date: Tue Sep 19 11:47:12 2017 +1200 + + bug 1400839 use -1 instead of 0 to indicate absent glxtest_pipe fd r=karlt + + Englightenment closes fd 0 on child processes and so pipe() can return a zero fd. + + MozReview-Commit-ID: 5d9xQXgwgfv + + --HG-- + extra : rebase_source : c31aa7ce731ba325993f463b79b446ae67c932dd +--- + widget/GfxInfoX11.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git widget/GfxInfoX11.cpp widget/GfxInfoX11.cpp +index bf99367d084b..8bb54a99136f 100644 +--- widget/GfxInfoX11.cpp ++++ widget/GfxInfoX11.cpp +@@ -28,7 +28,7 @@ NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, GfxInfoBase, nsIGfxInfoDebug) + #endif + + // these global variables will be set when firing the glxtest process +-int glxtest_pipe = 0; ++int glxtest_pipe = -1; + pid_t glxtest_pid = 0; + + nsresult +@@ -55,8 +55,8 @@ GfxInfo::GetData() + // to understand this function, see bug 639842. We retrieve the OpenGL driver information in a + // separate process to protect against bad drivers. + +- // if glxtest_pipe == 0, that means that we already read the information +- if (!glxtest_pipe) ++ // if glxtest_pipe == -1, that means that we already read the information ++ if (glxtest_pipe == -1) + return; + + enum { buf_size = 1024 }; +@@ -65,7 +65,7 @@ GfxInfo::GetData() + &buf, + buf_size-1); // -1 because we'll append a zero + close(glxtest_pipe); +- glxtest_pipe = 0; ++ glxtest_pipe = -1; + + // bytesread < 0 would mean that the above read() call failed. + // This should never happen. If it did, the outcome would be to blacklist anyway. diff --git a/www/waterfox/files/patch-bug1401063 b/www/waterfox/files/patch-bug1401063 new file mode 100644 index 000000000000..d151a96dfd6e --- /dev/null +++ b/www/waterfox/files/patch-bug1401063 @@ -0,0 +1,160 @@ +commit fb488ded4b64 +Author: Brad Werth <bwerth@mozilla.com> +Date: Tue Sep 19 13:00:28 2017 -0700 + + Bug 1401063: Cache remaining gtk window and button colors to eliminate on-demand gtk calls in ::NativeGetColor. r=karlt + + MozReview-Commit-ID: HbZqBUG0w7y + + --HG-- + extra : rebase_source : 0b26c22113c2cda49129006fe933f20719b7a679 +--- + widget/gtk/nsLookAndFeel.cpp | 62 +++++++++++++++++++------------------------- + widget/gtk/nsLookAndFeel.h | 5 ++++ + 2 files changed, 31 insertions(+), 36 deletions(-) + +diff --git widget/gtk/nsLookAndFeel.cpp widget/gtk/nsLookAndFeel.cpp +index 9a2684412ee8..e02bf10fe87f 100644 +--- widget/gtk/nsLookAndFeel.cpp ++++ widget/gtk/nsLookAndFeel.cpp +@@ -225,7 +225,6 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + { + EnsureInit(); + +- GdkRGBA gdk_color; + nsresult res = NS_OK; + + switch (aID) { +@@ -294,40 +293,26 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + aColor = NS_TRANSPARENT; + break; + case eColorID_SpellCheckerUnderline: +- aColor = NS_RGB(0xff, 0, 0); +- break; ++ aColor = NS_RGB(0xff, 0, 0); ++ break; + + // css2 http://www.w3.org/TR/REC-CSS2/ui.html#system-colors +- case eColorID_activeborder: { ++ case eColorID_activeborder: + // active window border +- GtkStyleContext *style = GetStyleContext(MOZ_GTK_WINDOW); +- gtk_style_context_get_border_color(style, +- GTK_STATE_FLAG_NORMAL, &gdk_color); +- aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); ++ aColor = sMozWindowActiveBorder; + break; +- } +- case eColorID_inactiveborder: { ++ case eColorID_inactiveborder: + // inactive window border +- GtkStyleContext *style = GetStyleContext(MOZ_GTK_WINDOW); +- gtk_style_context_get_border_color(style, +- GTK_STATE_FLAG_INSENSITIVE, +- &gdk_color); +- aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); ++ aColor = sMozWindowInactiveBorder; + break; +- } + case eColorID_graytext: // disabled text in windows, menus, etc. + case eColorID_inactivecaptiontext: // text in inactive window caption + aColor = sMenuTextInactive; + break; +- case eColorID_inactivecaption: { ++ case eColorID_inactivecaption: + // inactive window caption +- GtkStyleContext *style = GetStyleContext(MOZ_GTK_WINDOW); +- gtk_style_context_get_background_color(style, +- GTK_STATE_FLAG_INSENSITIVE, +- &gdk_color); +- aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); ++ aColor = sMozWindowInactiveCaption; + break; +- } + case eColorID_infobackground: + // tooltip background color + aColor = sInfoBackground; +@@ -389,22 +374,13 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor) + case eColorID__moz_fieldtext: + aColor = sMozFieldText; + break; +- case eColorID__moz_buttondefault: { ++ case eColorID__moz_buttondefault: + // default button border color +- GtkStyleContext *style = GetStyleContext(MOZ_GTK_BUTTON); +- gtk_style_context_get_border_color(style, +- GTK_STATE_FLAG_NORMAL, &gdk_color); +- aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); ++ aColor = sButtonDefault; + break; +- } +- case eColorID__moz_buttonhoverface: { +- GtkStyleContext *style = GetStyleContext(MOZ_GTK_BUTTON); +- gtk_style_context_get_background_color(style, +- GTK_STATE_FLAG_PRELIGHT, +- &gdk_color); +- aColor = GDK_RGBA_TO_NS_RGBA(gdk_color); ++ case eColorID__moz_buttonhoverface: ++ aColor = sButtonHoverFace; + break; +- } + case eColorID__moz_buttonhovertext: + aColor = sButtonHoverText; + break; +@@ -863,6 +839,15 @@ nsLookAndFeel::EnsureInit() + sMozWindowBackground = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color); + sMozWindowText = GDK_RGBA_TO_NS_RGBA(color); ++ gtk_style_context_get_border_color(style, GTK_STATE_FLAG_NORMAL, &color); ++ sMozWindowActiveBorder = GDK_RGBA_TO_NS_RGBA(color); ++ gtk_style_context_get_border_color(style, GTK_STATE_FLAG_INSENSITIVE, ++ &color); ++ sMozWindowInactiveBorder = GDK_RGBA_TO_NS_RGBA(color); ++ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_INSENSITIVE, ++ &color); ++ sMozWindowInactiveCaption = GDK_RGBA_TO_NS_RGBA(color); ++ + style = GetStyleContext(MOZ_GTK_WINDOW_CONTAINER); + { + GtkStyleContext* labelStyle = CreateStyleForWidget(labelWidget, style); +@@ -953,10 +938,15 @@ nsLookAndFeel::EnsureInit() + + GetSystemFontInfo(labelStyle, &mButtonFontName, &mButtonFontStyle); + ++ gtk_style_context_get_border_color(style, GTK_STATE_FLAG_NORMAL, &color); ++ sButtonDefault = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_NORMAL, &color); + sButtonText = GDK_RGBA_TO_NS_RGBA(color); + gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_PRELIGHT, &color); + sButtonHoverText = GDK_RGBA_TO_NS_RGBA(color); ++ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_PRELIGHT, ++ &color); ++ sButtonHoverFace = GDK_RGBA_TO_NS_RGBA(color); + g_object_unref(labelStyle); + } + +diff --git widget/gtk/nsLookAndFeel.h widget/gtk/nsLookAndFeel.h +index 38cd51c056d6..177d069f6567 100644 +--- widget/gtk/nsLookAndFeel.h ++++ widget/gtk/nsLookAndFeel.h +@@ -58,8 +58,10 @@ protected: + nscolor sMenuTextInactive; + nscolor sMenuHover; + nscolor sMenuHoverText; ++ nscolor sButtonDefault; + nscolor sButtonText; + nscolor sButtonHoverText; ++ nscolor sButtonHoverFace; + nscolor sFrameOuterLightBorder; + nscolor sFrameInnerDarkBorder; + nscolor sOddCellBackground; +@@ -70,6 +72,9 @@ protected: + nscolor sMozFieldBackground; + nscolor sMozWindowText; + nscolor sMozWindowBackground; ++ nscolor sMozWindowActiveBorder; ++ nscolor sMozWindowInactiveBorder; ++ nscolor sMozWindowInactiveCaption; + nscolor sTextSelectedText; + nscolor sTextSelectedBackground; + nscolor sMozScrollbar; diff --git a/www/waterfox/files/patch-bug1401416 b/www/waterfox/files/patch-bug1401416 new file mode 100644 index 000000000000..63f0f8e8e713 --- /dev/null +++ b/www/waterfox/files/patch-bug1401416 @@ -0,0 +1,29 @@ +commit c5123938eb1e +Author: Tobias Schneider <schneider@jancona.com> +Date: Thu Sep 21 12:43:35 2017 -0700 + + Bug 1401416 - [intersection-observer] Let intersection rect be empty if do_QueryFrame(rootFrame) returns null. r=dholbert, a=sledru + + --HG-- + extra : source : 90be30b5206c2b2724d61f4f6782197bfa768428 +--- + dom/base/DOMIntersectionObserver.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git dom/base/DOMIntersectionObserver.cpp dom/base/DOMIntersectionObserver.cpp +index 606a1de5ed8c..1ca909e3cfbf 100644 +--- dom/base/DOMIntersectionObserver.cpp ++++ dom/base/DOMIntersectionObserver.cpp +@@ -308,7 +308,11 @@ DOMIntersectionObserver::Update(nsIDocument* aDocument, DOMHighResTimeStamp time + } + root = rootFrame->GetContent()->AsElement(); + nsIScrollableFrame* scrollFrame = do_QueryFrame(rootFrame); +- rootRect = scrollFrame->GetScrollPortRect(); ++ // If we end up with a null root frame for some reason, we'll proceed ++ // with an empty root intersection rect. ++ if (scrollFrame) { ++ rootRect = scrollFrame->GetScrollPortRect(); ++ } + } + } + } diff --git a/www/waterfox/files/patch-bug1401522 b/www/waterfox/files/patch-bug1401522 new file mode 100644 index 000000000000..ac62fbdbb66e --- /dev/null +++ b/www/waterfox/files/patch-bug1401522 @@ -0,0 +1,34 @@ +commit e9d4b51968e0 +Author: Samael Wang <freesamael@gmail.com> +Date: Thu Sep 28 11:16:53 2017 +0800 + + Bug 1401522 - Don't apply statusCode sent from parent if mCanceled or mStatus has been modified in the child. r=mayhemer, a=ritu + + When a WyciwygChannel is canceled, but WyciwygChannelParent::RecvCancel happens + after WyciwygChannelParent::SendOnStartRequest, it would send statusCode=NS_OK + to WyciwygChannelChild::OnStartRequest. So we should not apply the statusCode + if mCanceled, just like how HttpChannelChild handles it. + + MozReview-Commit-ID: 5H3PUrlArIA + + --HG-- + extra : source : 8ebfa90c4ebca44ac1c3829ef54de74d3b004dfc +--- + netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +index d14b6f925e37..85d3ebf24439 100644 +--- netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp ++++ netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +@@ -191,7 +191,9 @@ WyciwygChannelChild::OnStartRequest(const nsresult& statusCode, + + mState = WCC_ONSTART; + +- mStatus = statusCode; ++ if (!mCanceled && NS_SUCCEEDED(mStatus)) { ++ mStatus = statusCode; ++ } + mContentLength = contentLength; + mCharsetSource = source; + mCharset = charset; diff --git a/www/waterfox/files/patch-bug1401573 b/www/waterfox/files/patch-bug1401573 new file mode 100644 index 000000000000..22fc6f569a59 --- /dev/null +++ b/www/waterfox/files/patch-bug1401573 @@ -0,0 +1,27 @@ +commit d0ed05261f20 +Author: jason laster <jlaster@mozilla.com> +Date: Wed Sep 20 10:52:54 2017 -0400 + + Bug 1401573 - Fix PoE, Link, and linux issue. r=nchevobbe + + MozReview-Commit-ID: 35TA6bhW1Wr +--- + devtools/client/debugger/new/debugger.js | 68 +++++++++++++++++----- + devtools/client/debugger/new/panel.js | 27 ++++++++- + .../new/test/mochitest/browser_dbg-expressions.js | 2 +- + 3 files changed, 79 insertions(+), 18 deletions(-) + +diff --git devtools/client/debugger/new/debugger.js devtools/client/debugger/new/debugger.js +index f52a3e380ab6..c1213180cb13 100644 +--- devtools/client/debugger/new/debugger.js ++++ devtools/client/debugger/new/debugger.js +@@ -29493,7 +29493,8 @@ return /******/ (function(modules) { // webpackBootstr + } + + function getKeyForOS(os, action) { +- return KEYS[os][action]; ++ var osActions = KEYS[os] || KEYS.Linux; ++ return osActions[action]; + } + + function formatKey(action) { diff --git a/www/waterfox/files/patch-bug1401726 b/www/waterfox/files/patch-bug1401726 new file mode 100644 index 000000000000..a4697e6263c1 --- /dev/null +++ b/www/waterfox/files/patch-bug1401726 @@ -0,0 +1,60 @@ +commit ccbee985a281 +Author: John Dai <jdai@mozilla.com> +Date: Thu Sep 21 16:32:18 2017 +0800 + + Bug 1401726 - Fix crash in nsLabelsNodeList::PopulateSelf. r=smaug, a=sledru + + From 045228df087f7612bde09d2f715ec33f2aaf777c Mon Sep 17 00:00:00 2001 +--- + dom/base/nsContentList.cpp | 4 +++- + dom/html/crashtests/1401726.html | 17 +++++++++++++++++ + dom/html/crashtests/crashtests.list | 1 + + 3 files changed, 21 insertions(+), 1 deletion(-) + +diff --git dom/base/nsContentList.cpp dom/base/nsContentList.cpp +index f943039e7fca..9b7bd6323aa8 100644 +--- dom/base/nsContentList.cpp ++++ dom/base/nsContentList.cpp +@@ -1266,7 +1266,9 @@ nsLabelsNodeList::MaybeResetRoot(nsINode* aRootNode) + void + nsLabelsNodeList::PopulateSelf(uint32_t aNeededLength) + { +- MOZ_ASSERT(mRootNode, "Must have root"); ++ if (!mRootNode) { ++ return; ++ } + + // Start searching at the root. + nsINode* cur = mRootNode; +diff --git dom/html/crashtests/1401726.html dom/html/crashtests/1401726.html +new file mode 100644 +index 000000000000..bf4b4918abd4 +--- /dev/null ++++ dom/html/crashtests/1401726.html +@@ -0,0 +1,17 @@ ++<!DOCTYPE HTML> ++<html> ++<head> ++<script> ++ try { o1 = document.createElement('button') } catch(e) { } ++ try { o2 = document.createElement('p') } catch(e) { } ++ try { o3 = o1.labels } catch(e) { } ++ try { o4 = document.createNSResolver(document.documentElement) } catch(e) { } ++ try { o5 = document.createRange(); } catch(e) { } ++ try { document.documentElement.appendChild(o1) } catch(e) { } ++ try { o5.selectNode(o4); } catch(e) { } ++ try { o5.surroundContents(o2) } catch(e) { } ++ try { o5.surroundContents(o2) } catch(e) { } ++ try { o1.labels.length } catch(e) { } ++</script> ++</head> ++</html> +diff --git dom/html/crashtests/crashtests.list dom/html/crashtests/crashtests.list +index a60cc9f99474..581ed10cefc8 100644 +--- dom/html/crashtests/crashtests.list ++++ dom/html/crashtests/crashtests.list +@@ -83,3 +83,4 @@ load 1343886-2.xml + load 1343886-3.xml + asserts(0-3) load 1350972.html + load 1386905.html ++asserts(0-4) load 1401726.html diff --git a/www/waterfox/files/patch-bug1401876 b/www/waterfox/files/patch-bug1401876 new file mode 100644 index 000000000000..be5ff6d9811b --- /dev/null +++ b/www/waterfox/files/patch-bug1401876 @@ -0,0 +1,48 @@ +commit 09ba71b3a5e9 +Author: Scott Wu <scottcwwu@gmail.com> +Date: Thu Sep 21 15:37:25 2017 +0800 + + Bug 1401876 - Part 1: Close datetime picker on popuphidden. r=mconley, a=ritu + + MozReview-Commit-ID: FUqbtAftQxh + + --HG-- + extra : source : e238860e4943cd1bb4c2c5f7175a36d494f0e91b +--- + toolkit/content/tests/browser/head.js | 1 + + toolkit/content/widgets/datetimepopup.xml | 2 +- + toolkit/modules/DateTimePickerHelper.jsm | 1 + + 3 files changed, 3 insertions(+), 1 deletion(-) + +diff --git toolkit/content/widgets/datetimepopup.xml toolkit/content/widgets/datetimepopup.xml +index 7e4e5bcfe4e8..7397e1d310d4 100644 +--- toolkit/content/widgets/datetimepopup.xml ++++ toolkit/content/widgets/datetimepopup.xml +@@ -75,7 +75,6 @@ + this.dateTimePopupFrame.removeEventListener("load", this, true); + this.dateTimePopupFrame.contentDocument.removeEventListener("message", this); + this.dateTimePopupFrame.setAttribute("src", ""); +- this.hidePopup(); + this.hidden = true; + ]]></body> + </method> +@@ -320,6 +319,7 @@ + break; + } + case "ClosePopup": { ++ this.hidePopup(); + this.closePicker(); + break; + } +diff --git toolkit/modules/DateTimePickerHelper.jsm toolkit/modules/DateTimePickerHelper.jsm +index ced4e401815b..38e89bd0d160 100644 +--- toolkit/modules/DateTimePickerHelper.jsm ++++ toolkit/modules/DateTimePickerHelper.jsm +@@ -90,6 +90,7 @@ this.DateTimePickerHelper = { + if (browser) { + browser.messageManager.sendAsyncMessage("FormDateTime:PickerClosed"); + } ++ this.picker.closePicker(); + this.close(); + break; + } diff --git a/www/waterfox/files/patch-bug1401878 b/www/waterfox/files/patch-bug1401878 new file mode 100644 index 000000000000..8f762bf24bbd --- /dev/null +++ b/www/waterfox/files/patch-bug1401878 @@ -0,0 +1,70 @@ +commit 59e5b0881ec2 +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Thu Sep 21 21:32:00 2017 +0200 + + Bug 1401878 - Remove ServiceWorkers in SiteDataManager.jsm. r=bkelly, a=sledru + + --HG-- + extra : source : 04888373f12bd5d86ec3f4057c3a2f0b2240c963 + extra : intermediate-source : e2b1cd9fd4a66fc932d8f74cfe2b38c55b9a7a1e +--- + browser/components/preferences/SiteDataManager.jsm | 26 ++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git browser/components/preferences/SiteDataManager.jsm browser/components/preferences/SiteDataManager.jsm +index d6dd5c78656a..8f2ac2a34188 100644 +--- browser/components/preferences/SiteDataManager.jsm ++++ browser/components/preferences/SiteDataManager.jsm +@@ -9,6 +9,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "OfflineAppCacheHelper", + "resource:///modules/offlineAppCache.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService", + "resource://gre/modules/ContextualIdentityService.jsm"); ++XPCOMUtils.defineLazyServiceGetter(this, "serviceWorkerManager", ++ "@mozilla.org/serviceworkers/manager;1", ++ "nsIServiceWorkerManager"); + + this.EXPORTED_SYMBOLS = [ + "SiteDataManager" +@@ -216,6 +219,19 @@ this.SiteDataManager = { + } + }, + ++ _removeServiceWorkers(site) { ++ let serviceWorkers = serviceWorkerManager.getAllRegistrations(); ++ for (let i = 0; i < serviceWorkers.length; i++) { ++ let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo); ++ for (let principal of site.principals) { ++ if (sw.principal.equals(principal)) { ++ serviceWorkerManager.removeAndPropagate(sw.principal.URI.host); ++ break; ++ } ++ } ++ } ++ }, ++ + remove(hosts) { + let promises = []; + let unknownHost = ""; +@@ -225,6 +241,7 @@ this.SiteDataManager = { + this._removePermission(site); + this._removeAppCache(site); + this._removeCookie(site); ++ this._removeServiceWorkers(site); + promises.push(this._removeQuotaUsage(site)); + } else { + unknownHost = host; +@@ -240,6 +257,14 @@ this.SiteDataManager = { + }, + + removeAll() { ++ // Iterate through the service workers and remove them. ++ let serviceWorkers = serviceWorkerManager.getAllRegistrations(); ++ for (let i = 0; i < serviceWorkers.length; i++) { ++ let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo); ++ let host = sw.principal.URI.host; ++ serviceWorkerManager.removeAndPropagate(host); ++ } ++ + let promises = []; + for (let site of this._sites.values()) { + this._removePermission(site); diff --git a/www/waterfox/files/patch-bug1401909 b/www/waterfox/files/patch-bug1401909 new file mode 100644 index 000000000000..f376a52b2732 --- /dev/null +++ b/www/waterfox/files/patch-bug1401909 @@ -0,0 +1,30 @@ +commit ec17ee7e24b2 +Author: Kaku Kuo <kaku@mozilla.com> +Date: Thu Sep 21 17:47:45 2017 +0800 + + Bug 1401909 - Turn on preference of ShutdownDecoder feature on desktop version release and beta channel. r=bwu, a=sledru + + MozReview-Commit-ID: JB3RmyjhvK9 + + --HG-- + extra : source : 27953b6cbc9b9bff5fb14cb0e69b492f08e62da8 +--- + modules/libpref/init/all.js | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index 6d66d27d987c..c74659f8d4a5 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -432,11 +432,7 @@ pref("media.decoder-doctor.wmf-disabled-is-failure", false); + pref("media.decoder-doctor.new-issue-endpoint", "https://webcompat.com/issues/new"); + + // Whether to suspend decoding of videos in background tabs. +-#ifdef RELEASE_OR_BETA +-pref("media.suspend-bkgnd-video.enabled", false); +-#else + pref("media.suspend-bkgnd-video.enabled", true); +-#endif + // Delay, in ms, from time window goes to background to suspending + // video decoders. Defaults to 10 seconds. + pref("media.suspend-bkgnd-video.delay-ms", 10000); diff --git a/www/waterfox/files/patch-bug1401992 b/www/waterfox/files/patch-bug1401992 new file mode 100644 index 000000000000..cc3a94b30f9d --- /dev/null +++ b/www/waterfox/files/patch-bug1401992 @@ -0,0 +1,239 @@ +commit b00a6f8952ad +Author: Bobby Holley <bobbyholley@gmail.com> +Date: Fri Sep 22 12:34:00 2017 -0700 + + Bug 1401992 - Don't cross anonymous boundaries when finding the fieldset. r=bz, a=sledru + + MozReview-Commit-ID: DiywRognpqx + + --HG-- + extra : source : 581b6ab2826a3a90f3d47713b3940f176aa4d39f +--- + dom/html/nsGenericHTMLElement.cpp | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git dom/html/nsGenericHTMLElement.cpp dom/html/nsGenericHTMLElement.cpp +index 61953dab88ce..eda85c9eebaf 100644 +--- dom/html/nsGenericHTMLElement.cpp ++++ dom/html/nsGenericHTMLElement.cpp +@@ -545,7 +545,7 @@ nsGenericHTMLElement::FindAncestorForm(HTMLFormElement* aCurrentForm) + "FindAncestorForm should not be called if @form is set!"); + + // Make sure we don't end up finding a form that's anonymous from +- // our point of view. ++ // our point of view. See also nsGenericHTMLFormElement::UpdateFieldSet. + nsIContent* bindingParent = GetBindingParent(); + + nsIContent* content = this; +@@ -2365,7 +2365,11 @@ nsGenericHTMLFormElement::UpdateFieldSet(bool aNotify) + nsIContent* parent = nullptr; + nsIContent* prev = nullptr; + +- for (parent = GetParent(); parent; ++ // Don't walk out of anonymous subtrees. Note the similar code in ++ // nsGenericHTMLElement::FindAncestorForm. ++ nsIContent* bindingParent = GetBindingParent(); ++ ++ for (parent = GetParent(); parent && parent != bindingParent; + prev = parent, parent = parent->GetParent()) { + HTMLFieldSetElement* fieldset = + HTMLFieldSetElement::FromContent(parent); + +commit 637fd3497d25 +Author: Bobby Holley <bobbyholley@gmail.com> +Date: Fri Sep 22 17:06:00 2017 -0700 + + Bug 1401992 - Reftest. r=me, a=sledru + + MozReview-Commit-ID: C7UQEQOkE7q + + --HG-- + extra : source : 5bfa23832767e42835f4c144fcbd4a351b7feca2 + extra : histedit_source : 31c6d70fac5308f511033692eeb3d8907a88ccab%2Ce5b28d61e7e6cffa0aee00cc2d563be5052830f0 +--- + layout/reftests/bugs/1401992-ref.html | 21 +++++++++++++++++++++ + layout/reftests/bugs/1401992.html | 32 ++++++++++++++++++++++++++++++++ + layout/reftests/bugs/reftest.list | 1 + + 3 files changed, 54 insertions(+) + +diff --git layout/reftests/bugs/1401992-ref.html layout/reftests/bugs/1401992-ref.html +new file mode 100644 +index 000000000000..8fb36196cf39 +--- /dev/null ++++ layout/reftests/bugs/1401992-ref.html +@@ -0,0 +1,21 @@ ++<!doctype html> ++<html> ++<head> ++<style> ++video { ++ width: 100px; ++ height: 100px; ++ border: 10px solid purple; ++} ++fieldset { ++ border: 10px solid blue; ++ border-color: green; ++} ++</style> ++<script> ++</script> ++</head> ++<body> ++<fieldset><video id="x" style="visibility:hidden"></video></fieldset> ++</body> ++</html> +diff --git layout/reftests/bugs/1401992.html layout/reftests/bugs/1401992.html +new file mode 100644 +index 000000000000..f48f563a01a8 +--- /dev/null ++++ layout/reftests/bugs/1401992.html +@@ -0,0 +1,32 @@ ++<!doctype html> ++<html> ++<head> ++<style> ++video { ++ width: 100px; ++ height: 100px; ++ border: 10px solid purple; ++} ++fieldset { ++ border: 10px solid blue; ++} ++fieldset:valid { ++ border-color: green; ++} ++fieldset:invalid { ++ border-color: red; ++} ++</style> ++<script> ++window.onload = function() { ++ let v = document.getElementById("x"); ++ v.currentTime = -128; ++ v.controls = !v.controls; ++} ++</script> ++</head> ++<body> ++<!-- Native anonymous content shouldn't affect fieldset validity --> ++<fieldset><video id="x" style="visibility:hidden"></video></fieldset> ++</body> ++</html> +diff --git layout/reftests/bugs/reftest.list layout/reftests/bugs/reftest.list +index e95eb8318a5a..55eb7da5611f 100644 +--- layout/reftests/bugs/reftest.list ++++ layout/reftests/bugs/reftest.list +@@ -2037,3 +2037,4 @@ needs-focus != 1377447-1.html 1377447-2.html + == 1380224-1.html 1380224-1-ref.html + == 1384065.html 1384065-ref.html + == 1384275-1.html 1384275-1-ref.html ++== 1401992.html 1401992-ref.html + +commit 67ad215f14ae +Author: Bobby Holley <bobbyholley@gmail.com> +Date: Fri Sep 22 17:20:31 2017 -0700 + + Bug 1401992 - Mark some tests as passing on android. r=me, a=sledru + + MozReview-Commit-ID: HJuIX5VXBm5 + + --HG-- + extra : source : 4c191b4e631f2f6f672598d70359438d18d05884 + extra : histedit_source : ad3d624a38b1f0134cd286ea592586f23c52d21b +--- + layout/reftests/bugs/reftest.list | 2 +- + layout/reftests/css-disabled/select/reftest.list | 10 +++++----- + layout/reftests/css-invalid/select/reftest.list | 4 ++-- + layout/reftests/css-ui-invalid/select/reftest.list | 4 ++-- + layout/reftests/css-ui-valid/select/reftest.list | 4 ++-- + layout/reftests/css-valid/select/reftest.list | 4 ++-- + 6 files changed, 14 insertions(+), 14 deletions(-) + +diff --git layout/reftests/bugs/reftest.list layout/reftests/bugs/reftest.list +index 55eb7da5611f..7815eaf2b69d 100644 +--- layout/reftests/bugs/reftest.list ++++ layout/reftests/bugs/reftest.list +@@ -1502,7 +1502,7 @@ random != 553571-1.html 553571-1-notref.html # expect dotted circle in test, not + fuzzy-if(!contentSameGfxBackendAsCanvas,128,91) random-if(d2d) skip-if(azureSkiaGL) fuzzy-if(skiaContent,32,150) == 555388-1.html 555388-1-ref.html + == 556661-1.html 556661-1-ref.html + fuzzy-if(skiaContent,4,5) == 557087-1.html 557087-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,5) == 557087-2.html 557087-ref.html ++fuzzy-if(skiaContent&&!Android,2,5) == 557087-2.html 557087-ref.html + == 557736-1.html 557736-1-ref.html + != 558011-1.xul 558011-1-ref.xul + == 559284-1.html 559284-1-ref.html +diff --git layout/reftests/css-disabled/select/reftest.list layout/reftests/css-disabled/select/reftest.list +index 700f06471cda..d6abbd6bd903 100644 +--- layout/reftests/css-disabled/select/reftest.list ++++ layout/reftests/css-disabled/select/reftest.list +@@ -1,9 +1,9 @@ + fuzzy-if(Android,12,1) == select-fieldset-1.html select-fieldset-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,17) == select-fieldset-2.html select-fieldset-ref-disabled.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,17) == select-fieldset-3.html select-fieldset-ref-disabled.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,13) == select-fieldset-4.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,2,17) == select-fieldset-2.html select-fieldset-ref-disabled.html ++fuzzy-if(skiaContent&&!Android,2,17) == select-fieldset-3.html select-fieldset-ref-disabled.html ++fuzzy-if(skiaContent&&!Android,2,13) == select-fieldset-4.html select-fieldset-ref.html + == select-fieldset-legend-1.html select-fieldset-legend-ref-1.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,6) == select-fieldset-legend-2.html select-fieldset-legend-ref-2.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,8) == select-fieldset-legend-3.html select-fieldset-legend-ref-3.html ++fuzzy-if(skiaContent&&!Android,2,6) == select-fieldset-legend-2.html select-fieldset-legend-ref-2.html ++fuzzy-if(skiaContent&&!Android,2,8) == select-fieldset-legend-3.html select-fieldset-legend-ref-3.html + fuzzy-if(skiaContent,2,12) == select-fieldset-legend-4.html select-fieldset-legend-ref-4.html + fuzzy-if(skiaContent,2,5) == select-fieldset-legend-5.html select-fieldset-legend-ref-5.html +diff --git layout/reftests/css-invalid/select/reftest.list layout/reftests/css-invalid/select/reftest.list +index 2d16e1603b0c..44bd631b6215 100644 +--- layout/reftests/css-invalid/select/reftest.list ++++ layout/reftests/css-invalid/select/reftest.list +@@ -7,6 +7,6 @@ needs-focus == select-required-invalid.html select-required-ref.html + needs-focus == select-required-valid.html select-required-ref.html + needs-focus == select-required-multiple-still-valid.html select-required-multiple-ref.html + fuzzy-if(skiaContent,1,250) needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,1,3) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,3) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,1,3) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,2,3) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html + fuzzy-if(skiaContent,2,5) needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html +diff --git layout/reftests/css-ui-invalid/select/reftest.list layout/reftests/css-ui-invalid/select/reftest.list +index 1fd197793914..f0b298401ced 100644 +--- layout/reftests/css-ui-invalid/select/reftest.list ++++ layout/reftests/css-ui-invalid/select/reftest.list +@@ -12,7 +12,7 @@ fuzzy-if(skiaContent,2,5) needs-focus == select-required-valid.html select-requi + needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html + fuzzy-if(asyncPan&&!layersGPUAccelerated,84,77) fuzzy-if(skiaContent,1,1000) needs-focus == select-required-multiple-invalid-changed.html select-required-multiple-ref.html + needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,10) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,10) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,2,10) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,2,10) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html + fuzzy-if(skiaContent,2,10) needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html + fuzzy-if(skiaContent,1,5) needs-focus == select-novalidate.html select-required-ref.html +diff --git layout/reftests/css-ui-valid/select/reftest.list layout/reftests/css-ui-valid/select/reftest.list +index 082a6fc0ce40..815cb4635ddb 100644 +--- layout/reftests/css-ui-valid/select/reftest.list ++++ layout/reftests/css-ui-valid/select/reftest.list +@@ -12,7 +12,7 @@ fuzzy-if(skiaContent,2,5) needs-focus == select-required-valid-changed-2.html se + needs-focus == select-required-multiple-invalid.html select-required-multiple-ref.html + needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html + fuzzy(64,4) fuzzy-if(asyncPan&&layersGPUAccelerated,84,77) fuzzy-if(skiaContent,1,1000) needs-focus == select-required-multiple-valid-changed.html select-required-multiple-ref.html +-fails-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,2,10) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html ++needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,2,10) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html + fuzzy-if(skiaContent,2,10) needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html + fuzzy-if(skiaContent,2,5) needs-focus == select-novalidate.html select-required-ref.html +diff --git layout/reftests/css-valid/select/reftest.list layout/reftests/css-valid/select/reftest.list +index ac77e60d68a7..fc84eb8541c5 100644 +--- layout/reftests/css-valid/select/reftest.list ++++ layout/reftests/css-valid/select/reftest.list +@@ -7,6 +7,6 @@ needs-focus == select-required-invalid.html select-required-ref.html + needs-focus == select-required-valid.html select-required-ref.html + needs-focus == select-required-multiple-still-valid.html select-required-multiple-ref.html + fuzzy-if(skiaContent,1,250) needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html +-fails-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html +-fails-if(Android) fuzzy-if(skiaContent&&!Android,1,3) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html ++needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html ++fuzzy-if(skiaContent&&!Android,1,3) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html + needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html diff --git a/www/waterfox/files/patch-bug1402025 b/www/waterfox/files/patch-bug1402025 new file mode 100644 index 000000000000..841abfb757c0 --- /dev/null +++ b/www/waterfox/files/patch-bug1402025 @@ -0,0 +1,201 @@ +commit a80cfb448ce3 +Author: Kirk Steuber <ksteuber@mozilla.com> +Date: Thu Sep 28 12:09:56 2017 -0700 + + Bug 1402025 - Ensure form submission flush when unsetting relevant attributes. r=bz, a=ritu + + It seems that we were flushing any pending submission when changing the action or target attributes of a form, but not when unsetting those attributes. + + MozReview-Commit-ID: E6aUnokg54k + + --HG-- + extra : source : 32fa20aaa56cfb063433ff46f202e99eb35043d7 +--- + dom/html/HTMLFormElement.cpp | 25 ++++----- + dom/html/test/browser.ini | 3 ++ + dom/html/test/browser_submission_flush.js | 85 +++++++++++++++++++++++++++++++ + dom/html/test/post_action_page.html | 10 ++++ + dom/html/test/submission_flush.html | 13 +++++ + 5 files changed, 122 insertions(+), 14 deletions(-) + +diff --git dom/html/HTMLFormElement.cpp dom/html/HTMLFormElement.cpp +index 6b87c8b54255..c9ff6ffc8f2a 100644 +--- dom/html/HTMLFormElement.cpp ++++ dom/html/HTMLFormElement.cpp +@@ -189,21 +189,18 @@ HTMLFormElement::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName, + { + if (aNamespaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::action || aName == nsGkAtoms::target) { +- // This check is mostly to preserve previous behavior. +- if (aValue) { +- if (mPendingSubmission) { +- // aha, there is a pending submission that means we're in +- // the script and we need to flush it. let's tell it +- // that the event was ignored to force the flush. +- // the second argument is not playing a role at all. +- FlushPendingSubmission(); +- } +- // Don't forget we've notified the password manager already if the +- // page sets the action/target in the during submit. (bug 343182) +- bool notifiedObservers = mNotifiedObservers; +- ForgetCurrentSubmission(); +- mNotifiedObservers = notifiedObservers; ++ if (mPendingSubmission) { ++ // aha, there is a pending submission that means we're in ++ // the script and we need to flush it. let's tell it ++ // that the event was ignored to force the flush. ++ // the second argument is not playing a role at all. ++ FlushPendingSubmission(); + } ++ // Don't forget we've notified the password manager already if the ++ // page sets the action/target in the during submit. (bug 343182) ++ bool notifiedObservers = mNotifiedObservers; ++ ForgetCurrentSubmission(); ++ mNotifiedObservers = notifiedObservers; + } + } + +diff --git dom/html/test/browser.ini dom/html/test/browser.ini +index 34a32b833652..67754c995dfa 100644 +--- dom/html/test/browser.ini ++++ dom/html/test/browser.ini +@@ -6,6 +6,8 @@ support-files = + file_bug649778.html^headers^ + file_fullscreen-api-keys.html + file_content_contextmenu.html ++ submission_flush.html ++ post_action_page.html + form_data_file.bin + form_data_file.txt + form_submit_server.sjs +@@ -27,3 +29,4 @@ support-files = + tags = fullscreen + [browser_fullscreen-contextmenu-esc.js] + tags = fullscreen ++[browser_submission_flush.js] +diff --git dom/html/test/browser_submission_flush.js dom/html/test/browser_submission_flush.js +new file mode 100644 +index 000000000000..e3948e7071e8 +--- /dev/null ++++ dom/html/test/browser_submission_flush.js +@@ -0,0 +1,85 @@ ++"use strict"; ++// Form submissions triggered by the Javascript 'submit' event listener are ++// deferred until the event listener finishes. However, changes to specific ++// attributes ("action" and "target" attributes) need to cause an immediate ++// flush of any pending submission to prevent the form submission from using the ++// wrong action or target. This test ensures that such flushes happen properly. ++ ++const kTestPage = "http://example.org/browser/dom/html/test/submission_flush.html"; ++// This is the page pointed to by the form action in the test HTML page. ++const kPostActionPage = "http://example.org/browser/dom/html/test/post_action_page.html"; ++ ++const kFormId = "test_form" ++const kFrameId = "test_frame" ++const kSubmitButtonId = "submit_button" ++ ++// Take in a variety of actions (in the form of setting and unsetting form ++// attributes). Then submit the form in the submit event listener to cause a ++// deferred form submission. Then perform the test actions and ensure that the ++// form used the correct attribute values rather than the changed ones. ++async function runTest(aTestActions) { ++ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kTestPage); ++ registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); ++ ++ let frame_url = await ContentTask.spawn(gBrowser.selectedBrowser, ++ {kFormId, kFrameId, kSubmitButtonId, aTestActions}, ++ async function({kFormId, kFrameId, kSubmitButtonId, ++ aTestActions}) { ++ let form = content.document.getElementById(kFormId); ++ ++ form.addEventListener("submit", (event) => { ++ // Need to trigger the deferred submission by submitting in the submit ++ // event handler. To prevent the form from being submitted twice, the ++ // <form> tag contains the attribute |onsubmit="return false;"| to cancel ++ // the original submission. ++ form.submit(); ++ ++ if (aTestActions.setattr) { ++ for (let {attr, value} of aTestActions.setattr) { ++ form.setAttribute(attr, value); ++ } ++ } ++ if (aTestActions.unsetattr) { ++ for (let attr of aTestActions.unsetattr) { ++ form.removeAttribute(attr); ++ } ++ } ++ }, {capture: true, once: true}); ++ ++ // Trigger the above event listener ++ content.document.getElementById(kSubmitButtonId).click(); ++ ++ // Test that the form was submitted to the correct target (the frame) with ++ // the correct action (kPostActionPage). ++ let frame = content.document.getElementById(kFrameId); ++ await new Promise(resolve => { ++ frame.addEventListener("load", resolve, {once: true}); ++ }); ++ return frame.contentWindow.location.href; ++ }); ++ is(frame_url, kPostActionPage, ++ "Form should have submitted with correct target and action"); ++} ++ ++add_task(async function() { ++ info("Changing action should flush pending submissions"); ++ await runTest({setattr: [{attr: "action", value: "about:blank"}]}); ++}); ++ ++add_task(async function() { ++ info("Changing target should flush pending submissions"); ++ await runTest({setattr: [{attr: "target", value: "_blank"}]}); ++}); ++ ++add_task(async function() { ++ info("Unsetting action should flush pending submissions"); ++ await runTest({unsetattr: ["action"]}); ++}); ++ ++// On failure, this test will time out rather than failing an assert. When the ++// target attribute is not set, the form will submit the active page, navigating ++// it away and preventing the wait for iframe load from ever finishing. ++add_task(async function() { ++ info("Unsetting target should flush pending submissions"); ++ await runTest({unsetattr: ["target"]}); ++}); +diff --git dom/html/test/post_action_page.html dom/html/test/post_action_page.html +new file mode 100644 +index 000000000000..ba6ae514f2e9 +--- /dev/null ++++ dom/html/test/post_action_page.html +@@ -0,0 +1,10 @@ ++<!DOCTYPE html> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8"/> ++ <title>Submission Flush Test Post Action Page</title> ++ </head> ++ <body> ++ <h1>Post Action Page</h1> ++ </body> ++</html> +diff --git dom/html/test/submission_flush.html dom/html/test/submission_flush.html +new file mode 100644 +index 000000000000..f70884c66ac8 +--- /dev/null ++++ dom/html/test/submission_flush.html +@@ -0,0 +1,13 @@ ++<!DOCTYPE html> ++<html lang="en"> ++ <head> ++ <meta charset="utf-8"/> ++ <title>Submission Flush Test</title> ++ </head> ++ <body> ++ <form id="test_form" action="post_action_page.html" target="form_target" method="POST" onsubmit="return false;"> ++ <button type="submit" id="submit_button">Submit</button> ++ </form> ++ <iframe name="form_target" id="test_frame"></iframe> ++ </body> ++</html> diff --git a/www/waterfox/files/patch-bug1402094 b/www/waterfox/files/patch-bug1402094 new file mode 100644 index 000000000000..b901b43f5f13 --- /dev/null +++ b/www/waterfox/files/patch-bug1402094 @@ -0,0 +1,57 @@ +commit 447413f00860 +Author: Xidorn Quan <me@upsuper.org> +Date: Thu Sep 28 16:19:45 2017 +1000 + + Bug 1402094 - Blacklist about:reader from using stylo. r=bholley, a=sledru + + MozReview-Commit-ID: 6cG1x1tcOwn + + --HG-- + extra : source : 813556d9e389f580d8e6efa9c24825edec952259 +--- + dom/base/nsDocument.cpp | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 07ef9ef817b7..7f8ebecffa97 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -13575,6 +13575,29 @@ nsIDocument::ReportHasScrollLinkedEffect() + "ScrollLinkedEffectFound2"); + } + ++#ifdef MOZ_STYLO ++// URL-based blacklist for stylo. ++static bool ++ShouldUseGeckoBackend(nsIURI* aDocumentURI) ++{ ++ if (!aDocumentURI) { ++ return false; ++ } ++ bool isScheme = false; ++ if (NS_SUCCEEDED(aDocumentURI->SchemeIs("about", &isScheme))) { ++ nsAutoCString path; ++ aDocumentURI->GetFilePath(path); ++ // about:reader requires support of :scope pseudo-class so we have ++ // to use Gecko backend for now. See bug 1402094. ++ // This should be fixed by bug 1204818. ++ if (path.EqualsLiteral("reader")) { ++ return true; ++ } ++ } ++ return false; ++} ++#endif // MOZ_STYLO ++ + void + nsIDocument::UpdateStyleBackendType() + { +@@ -13593,7 +13616,7 @@ nsIDocument::UpdateStyleBackendType() + // Note that, since tests can have XUL support, we still need to + // explicitly exclude XUL documents here. + if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()) && +- !IsXULDocument()) { ++ !IsXULDocument() && !ShouldUseGeckoBackend(mDocumentURI)) { + mStyleBackendType = StyleBackendType::Servo; + } + } diff --git a/www/waterfox/files/patch-bug1402205 b/www/waterfox/files/patch-bug1402205 new file mode 100644 index 000000000000..a91f52251035 --- /dev/null +++ b/www/waterfox/files/patch-bug1402205 @@ -0,0 +1,77 @@ +commit 86b6592ab804 +Author: Haik Aftandilian <haftandilian@mozilla.com> +Date: Mon Sep 25 15:48:40 2017 -0700 + + Bug 1402205 - Non-existent background page blocks extension startup. r=kmag, a=sledru + + Add calls to OnStartRequest() and OnStopRequest() to properly handle async + read failures for remote JAR's and remote unpacked extension resources. + + MozReview-Commit-ID: Dcg0LDht9B9 + + --HG-- + extra : source : 611582e42451dd26fcaa38f251e2203a6e8b0bf9 +--- + netwerk/protocol/res/ExtensionProtocolHandler.cpp | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git netwerk/protocol/res/ExtensionProtocolHandler.cpp netwerk/protocol/res/ExtensionProtocolHandler.cpp +index 326c21d13057..a2d900f95b96 100644 +--- netwerk/protocol/res/ExtensionProtocolHandler.cpp ++++ netwerk/protocol/res/ExtensionProtocolHandler.cpp +@@ -253,6 +253,19 @@ ExtensionStreamGetter::GetAsync(nsIStreamListener* aListener, + return Ok(); + } + ++static void ++CancelRequest(nsIStreamListener* aListener, ++ nsIChannel* aChannel, ++ nsresult aResult) ++{ ++ MOZ_ASSERT(aListener); ++ MOZ_ASSERT(aChannel); ++ ++ aListener->OnStartRequest(aChannel, nullptr); ++ aListener->OnStopRequest(aChannel, nullptr, aResult); ++ aChannel->Cancel(NS_BINDING_ABORTED); ++} ++ + // Handle an input stream sent from the parent. + void + ExtensionStreamGetter::OnStream(nsIInputStream* aStream) +@@ -269,9 +282,7 @@ ExtensionStreamGetter::OnStream(nsIInputStream* aStream) + + if (!aStream) { + // The parent didn't send us back a stream. +- listener->OnStartRequest(mChannel, nullptr); +- listener->OnStopRequest(mChannel, nullptr, NS_ERROR_FILE_ACCESS_DENIED); +- mChannel->Cancel(NS_BINDING_ABORTED); ++ CancelRequest(listener, mChannel, NS_ERROR_FILE_ACCESS_DENIED); + return; + } + +@@ -279,13 +290,13 @@ ExtensionStreamGetter::OnStream(nsIInputStream* aStream) + nsresult rv = NS_NewInputStreamPump(getter_AddRefs(pump), aStream, -1, -1, 0, + 0, false, mMainThreadEventTarget); + if (NS_FAILED(rv)) { +- mChannel->Cancel(NS_BINDING_ABORTED); ++ CancelRequest(listener, mChannel, rv); + return; + } + + rv = pump->AsyncRead(listener, nullptr); + if (NS_FAILED(rv)) { +- mChannel->Cancel(NS_BINDING_ABORTED); ++ CancelRequest(listener, mChannel, rv); + } + } + +@@ -310,7 +321,7 @@ ExtensionStreamGetter::OnFD(const FileDescriptor& aFD) + mJarChannel->SetJarFile(fdFile); + nsresult rv = mJarChannel->AsyncOpen2(listener); + if (NS_FAILED(rv)) { +- mChannel->Cancel(NS_BINDING_ABORTED); ++ CancelRequest(listener, mChannel, rv); + } + } + diff --git a/www/waterfox/files/patch-bug1402218 b/www/waterfox/files/patch-bug1402218 new file mode 100644 index 000000000000..e407960ef94b --- /dev/null +++ b/www/waterfox/files/patch-bug1402218 @@ -0,0 +1,91 @@ +commit 3ddaaf254633 +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Thu Sep 28 22:04:34 2017 -0400 + + Bug 1402218 - Make sure to clone our CSSDeclaration as needed when removing properties. r=emilio, a=sledru + + MozReview-Commit-ID: 6LRjLU3QQok + + --HG-- + extra : source : 76b6ae2fc6eb389810cb2a745f976be11516eb44 + extra : amend_source : 849900fa9c4e12b62cf73175666a672ca6ab3914 +--- + layout/style/DeclarationBlockInlines.h | 9 +++++++++ + layout/style/crashtests/1402218-1.html | 15 +++++++++++++++ + layout/style/crashtests/crashtests.list | 3 ++- + layout/style/nsDOMCSSDeclaration.cpp | 12 +----------- + 4 files changed, 27 insertions(+), 12 deletions(-) + +diff --git layout/style/DeclarationBlockInlines.h layout/style/DeclarationBlockInlines.h +index 5438bd1957c2..c9e0d4f82e31 100644 +--- layout/style/DeclarationBlockInlines.h ++++ layout/style/DeclarationBlockInlines.h +@@ -46,6 +46,15 @@ DeclarationBlock::EnsureMutable() + AsGecko()->AssertNotExpanded(); + } + #endif ++ if (IsServo() && !IsDirty()) { ++ // In stylo, the old DeclarationBlock is stored in element's rule node tree ++ // directly, to avoid new values replacing the DeclarationBlock in the tree ++ // directly, we need to copy the old one here if we haven't yet copied. ++ // As a result the new value does not replace rule node tree until traversal ++ // happens. ++ return Clone(); ++ } ++ + if (!IsMutable()) { + return Clone(); + } +diff --git layout/style/crashtests/1402218-1.html layout/style/crashtests/1402218-1.html +new file mode 100644 +index 000000000000..597c1c4d5e53 +--- /dev/null ++++ layout/style/crashtests/1402218-1.html +@@ -0,0 +1,15 @@ ++<!DOCTYPE html> ++<style> ++#wrapper::first-line {} ++</style> ++<body> ++<div id="wrapper"> ++ <div id="test"></div> ++</div> ++<script> ++ document.querySelector('#test').style.position = 'absolute'; ++ document.body.offsetHeight; ++ document.querySelector('#wrapper').style.color = 'green'; ++ document.querySelector('#test').style.position = ''; ++</script> ++</body> +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index e0a7fe4a20c5..ab9b5a7a9a4e 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -202,3 +202,4 @@ load 1387481-1.html + load 1387499.html + load 1391577.html + load 1398581.html ++load 1402218-1.html +diff --git layout/style/nsDOMCSSDeclaration.cpp layout/style/nsDOMCSSDeclaration.cpp +index a828f0e7b3dd..12e03c314fe9 100644 +--- layout/style/nsDOMCSSDeclaration.cpp ++++ layout/style/nsDOMCSSDeclaration.cpp +@@ -305,17 +305,7 @@ nsDOMCSSDeclaration::ModifyDeclaration(GeckoFunc aGeckoFunc, + // between when we mutate the declaration and when we set the new + // rule (see stack in bug 209575). + mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true); +- RefPtr<DeclarationBlock> decl; +- if (olddecl->IsServo() && !olddecl->IsDirty()) { +- // In stylo, the old DeclarationBlock is stored in element's rule node tree +- // directly, to avoid new values replacing the DeclarationBlock in the tree +- // directly, we need to copy the old one here if we haven't yet copied. +- // As a result the new value does not replace rule node tree until traversal +- // happens. +- decl = olddecl->Clone(); +- } else { +- decl = olddecl->EnsureMutable(); +- } ++ RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable(); + + bool changed; + if (decl->IsGecko()) { diff --git a/www/waterfox/files/patch-bug1402366 b/www/waterfox/files/patch-bug1402366 new file mode 100644 index 000000000000..393c36e27ef0 --- /dev/null +++ b/www/waterfox/files/patch-bug1402366 @@ -0,0 +1,87 @@ +commit 0211305e7012 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Fri Sep 22 21:23:11 2017 +0200 + + Bug 1402366 - Mark datetimebox as not needing xul.css. r=bholley, r=jessica, a=sledru + + We create a datetimebox in content documents that gets an XBL binding on + nsDateTimeControlFrame::CreateAnonymousContent. + + This is done during frame construction, and loading a datetimebox insert xul.css + in the document, which causes invalidation to run. + + datetimebox styles are in html.css, and there's no rule in xul.css that styles + it, so we don't need to load the stylesheet at all. + + MozReview-Commit-ID: 2SbIOoER2uB + + --HG-- + extra : source : 5b642e09aacd450f7ea2b667d2d453a701a30e15 +--- + dom/xul/nsXULElement.cpp | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git dom/xul/nsXULElement.cpp dom/xul/nsXULElement.cpp +index f1a87e917182..2c3574cd6580 100644 +--- dom/xul/nsXULElement.cpp ++++ dom/xul/nsXULElement.cpp +@@ -696,6 +696,7 @@ static inline bool XULElementsRulesInMinimalXULSheet(nsIAtom* aTag) + aTag == nsGkAtoms::thumb || + aTag == nsGkAtoms::scale || + // other ++ aTag == nsGkAtoms::datetimebox || + aTag == nsGkAtoms::resizer || + aTag == nsGkAtoms::label || + aTag == nsGkAtoms::videocontrols; +@@ -810,9 +811,7 @@ nsXULElement::BindToTree(nsIDocument* aDocument, + // pulling in xul.css. + // Note that add-ons may introduce bindings that cause this assertion to + // fire. +- NS_ASSERTION(IsInVideoControls(this) || +- IsInFeedSubscribeLine(this) || +- IsXULElement(nsGkAtoms::datetimebox), ++ NS_ASSERTION(IsInVideoControls(this) || IsInFeedSubscribeLine(this), + "Unexpected XUL element in non-XUL doc"); + } + } + +commit 07adf4398955 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Sep 25 10:16:36 2017 +0200 + + Bug 1402366 - Crashtest. r=me, a=sledru + + MozReview-Commit-ID: 8ZcVBHKNntj + + --HG-- + extra : source : 7fde3082d44b416af788f2ba09834fb3403eb8ff +--- + layout/style/crashtests/1402366.html | 10 ++++++++++ + layout/style/crashtests/crashtests.list | 1 + + 2 files changed, 11 insertions(+) + +diff --git layout/style/crashtests/1402366.html layout/style/crashtests/1402366.html +new file mode 100644 +index 000000000000..9cffd08f0415 +--- /dev/null ++++ layout/style/crashtests/1402366.html +@@ -0,0 +1,10 @@ ++<script> ++document.documentElement.appendChild(document.createElement('x')) ++a = document.createElement('x') ++document.documentElement.appendChild(a) ++new Range().getClientRects() ++document.documentElement.appendChild(document.createElement('tr')) ++b = document.createElement('input') ++b.type = 'date' ++document.documentElement.insertBefore(b, a) ++</script> +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index 9cd557a44187..be05f417d6aa 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -203,3 +203,4 @@ load 1387499.html + load 1391577.html + load 1398581.html + load 1402218-1.html ++load 1402366.html diff --git a/www/waterfox/files/patch-bug1402377 b/www/waterfox/files/patch-bug1402377 new file mode 100644 index 000000000000..6d5322defb37 --- /dev/null +++ b/www/waterfox/files/patch-bug1402377 @@ -0,0 +1,36 @@ +commit 9e374938aaac +Author: Munro Mengjue Chiang <mchiang@mozilla.com> +Date: Wed Sep 27 10:16:46 2017 +0800 + + Bug 1402377 - Stop the corresponding track instead of the whole stream when an external device is plugged out. r=jib, r=pehrsons, a=ritu + + MozReview-Commit-ID: 7gbB5sgn6xI + + --HG-- + extra : source : 140805019de38dbfbb9f4fe363de8d7c8a52d387 + extra : histedit_source : 9f60927d8c7dfba265a60497b305e65eeb28939b +--- + dom/media/MediaManager.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git dom/media/MediaManager.cpp dom/media/MediaManager.cpp +index a06296086a28..6b37fa4206a2 100644 +--- dom/media/MediaManager.cpp ++++ dom/media/MediaManager.cpp +@@ -4067,14 +4067,14 @@ GetUserMediaWindowListener::StopRawID(const nsString& removedDeviceID) + nsString id; + source->GetAudioDevice()->GetRawId(id); + if (removedDeviceID.Equals(id)) { +- source->Stop(); ++ source->StopTrack(kAudioTrack); + } + } + if (source->GetVideoDevice()) { + nsString id; + source->GetVideoDevice()->GetRawId(id); + if (removedDeviceID.Equals(id)) { +- source->Stop(); ++ source->StopTrack(kVideoTrack); + } + } + } diff --git a/www/waterfox/files/patch-bug1402380 b/www/waterfox/files/patch-bug1402380 new file mode 100644 index 000000000000..cb0f76b6caa2 --- /dev/null +++ b/www/waterfox/files/patch-bug1402380 @@ -0,0 +1,257 @@ +commit fb06fdcf7d66 +Author: Tooru Fujisawa <arai_a@mac.com> +Date: Sun Mar 25 17:23:48 2018 +0900 + + Bug 1402380 - Set text/x-moz-url flavor of data transfer for places container with URLs inside it. r=enndeakin, a=jcristau + + --HG-- + extra : source : e4cc022b417a1268fa063fe054aa79f3c141c2e2 +--- + .../components/places/tests/browser/browser.ini | 1 + + .../tests/browser/browser_drag_folder_on_newTab.js | 94 ++++++++++++++++++++++ + testing/mochitest/tests/SimpleTest/EventUtils.js | 86 ++++++++++++++++++++ + toolkit/components/places/PlacesUtils.jsm | 11 ++- + 4 files changed, 191 insertions(+), 1 deletion(-) + +diff --git browser/components/places/tests/browser/browser.ini browser/components/places/tests/browser/browser.ini +index 64b7782c5f83..33c4cf5cc416 100644 +--- browser/components/places/tests/browser/browser.ini ++++ browser/components/places/tests/browser/browser.ini +@@ -63,3 +63,4 @@ support-files = + support-files = + bookmark_dummy_1.html + bookmark_dummy_2.html ++[browser_drag_folder_on_newTab.js] +diff --git browser/components/places/tests/browser/browser_drag_folder_on_newTab.js browser/components/places/tests/browser/browser_drag_folder_on_newTab.js +new file mode 100644 +index 000000000000..00646fff18b4 +--- /dev/null ++++ browser/components/places/tests/browser/browser_drag_folder_on_newTab.js +@@ -0,0 +1,94 @@ ++/* Any copyright is dedicated to the Public Domain. ++ * http://creativecommons.org/publicdomain/zero/1.0/ */ ++ ++"use strict"; ++ ++add_task(async function setup() { ++ let toolbar = document.getElementById("PersonalToolbar"); ++ let wasCollapsed = toolbar.collapsed; ++ ++ // Uncollapse the personal toolbar if needed. ++ if (wasCollapsed) { ++ await promiseSetToolbarVisibility(toolbar, true); ++ } ++ ++ // Clean before and after so we don't have anything in the folders. ++ await PlacesUtils.bookmarks.eraseEverything(); ++ ++ registerCleanupFunction(async function() { ++ // Collapse the personal toolbar if needed. ++ if (wasCollapsed) { ++ await promiseSetToolbarVisibility(toolbar, false); ++ } ++ ++ await PlacesUtils.bookmarks.eraseEverything(); ++ }); ++}); ++ ++const TEST_FOLDER_NAME = "Test folder"; ++ ++add_task(async function test_change_location_from_Toolbar() { ++ let newTabButton = document.getElementById("new-tab-button"); ++ ++ let children = [ ++ { ++ title: "first", ++ url: "http://www.mochi.test/first" ++ }, ++ { ++ title: "second", ++ url: "http://www.mochi.test/second" ++ }, ++ { ++ type: PlacesUtils.bookmarks.TYPE_SEPARATOR, ++ }, ++ { ++ title: "third", ++ url: "http://www.mochi.test/third" ++ }, ++ ]; ++ let guid = PlacesUtils.history.makeGuid(); ++ await PlacesUtils.bookmarks.insertTree({ ++ guid: PlacesUtils.bookmarks.toolbarGuid, ++ children: [ ++ { ++ guid, ++ type: PlacesUtils.bookmarks.TYPE_FOLDER, ++ title: TEST_FOLDER_NAME, ++ children, ++ }, ++ ], ++ }); ++ ++ let folder = getToolbarNodeForItemGuid(guid); ++ ++ let loadedPromises = children.filter(item => "url" in item).map( ++ item => BrowserTestUtils.waitForNewTab(gBrowser, item.url, false, true)); ++ ++ let srcX = 10, srcY = 10; ++ // We should drag upwards, since dragging downwards opens menu instead. ++ let stepX = 0, stepY = -5; ++ ++ // We need to dispatch mousemove before dragging, to populate ++ // PlacesToolbar._cachedMouseMoveEvent, with the cursor position after the ++ // first step, so that the places code detects it as dragging upward. ++ EventUtils.synthesizeMouse(folder, srcX + stepX, srcY + stepY, ++ { type: "mousemove" }); ++ ++ await EventUtils.synthesizePlainDragAndDrop({ ++ srcElement: folder, ++ destElement: newTabButton, ++ srcX, ++ srcY, ++ stepX, ++ stepY, ++ }); ++ ++ let tabs = await Promise.all(loadedPromises); ++ ++ for (let tab of tabs) { ++ BrowserTestUtils.removeTab(tab); ++ } ++ ++ ok(true); ++}); +diff --git testing/mochitest/tests/SimpleTest/EventUtils.js testing/mochitest/tests/SimpleTest/EventUtils.js +index cad43966d91d..907cf60dc254 100644 +--- testing/mochitest/tests/SimpleTest/EventUtils.js ++++ testing/mochitest/tests/SimpleTest/EventUtils.js +@@ -17,6 +17,7 @@ + * synthesizeMouseExpectEvent + * synthesizeKeyExpectEvent + * synthesizeNativeOSXClick ++ * synthesizePlainDragAndDrop + * + * When adding methods to this file, please add a performance test for it. + */ +@@ -2161,6 +2162,91 @@ function synthesizeDrop(aSrcElement, aDestElement, aDragData, aDropEffect, aWind + } + } + ++/** ++ * Emulate a drag and drop by emulating a dragstart by mousedown and mousemove, ++ * and firing events dragenter, dragover, drop, and mouseup. ++ * This does not modify dataTransfer and tries to emulate the plain drag and ++ * drop as much as possible, compared to synthesizeDrop. ++ * ++ * @param aParams ++ * { ++ * srcElement: The element to start dragging ++ * destElement: The element to drop on ++ * srcX: The initial x coordinate inside srcElement ++ * srcY: The initial y coordinate inside srcElement ++ * stepX: The x-axis step for mousemove inside srcElement ++ * stepY: The y-axis step for mousemove inside srcElement ++ * destX: The x coordinate inside destElement ++ * destY: The x coordinate inside destElement ++ * srcWindow: The window for dispatching event on srcElement, ++ * defaults to the current window object ++ * destWindow: The window for dispatching event on destElement, ++ * defaults to the current window object ++ * } ++ */ ++async function synthesizePlainDragAndDrop(aParams) ++{ ++ let { ++ srcElement, ++ destElement, ++ srcX = 2, ++ srcY = 2, ++ stepX = 9, ++ stepY = 9, ++ destX = 2, ++ destY = 2, ++ srcWindow = window, ++ destWindow = window, ++ } = aParams; ++ ++ const ds = _EU_Cc["@mozilla.org/widget/dragservice;1"] ++ .getService(_EU_Ci.nsIDragService); ++ ds.startDragSession(); ++ ++ try { ++ let dataTransfer = null; ++ function trapDrag(aEvent) { ++ dataTransfer = aEvent.dataTransfer; ++ } ++ srcElement.addEventListener("dragstart", trapDrag, true); ++ synthesizeMouse(srcElement, srcX, srcY, { type: "mousedown" }, srcWindow); ++ ++ // Wait for the next event tick after each event dispatch, so that UI elements ++ // (e.g. menu) work like the real user input. ++ await new Promise(r => setTimeout(r, 0)); ++ ++ srcX += stepX; srcY += stepY; ++ synthesizeMouse(srcElement, srcX, srcY, { type: "mousemove" }, srcWindow); ++ ++ await new Promise(r => setTimeout(r, 0)); ++ ++ srcX += stepX; srcY += stepY; ++ synthesizeMouse(srcElement, srcX, srcY, { type: "mousemove" }, srcWindow); ++ ++ await new Promise(r => setTimeout(r, 0)); ++ ++ srcElement.removeEventListener("dragstart", trapDrag, true); ++ ++ await new Promise(r => setTimeout(r, 0)); ++ ++ let event = createDragEventObject("dragover", destElement, destWindow, ++ dataTransfer, {}); ++ sendDragEvent(event, destElement, destWindow); ++ ++ await new Promise(r => setTimeout(r, 0)); ++ ++ event = createDragEventObject("drop", destElement, destWindow, ++ dataTransfer, {}); ++ sendDragEvent(event, destElement, destWindow); ++ ++ await new Promise(r => setTimeout(r, 0)); ++ ++ synthesizeMouseAtCenter(destElement, { type: "mouseup" }, destWindow); ++ } finally { ++ ds.endDragSession(true, 0); ++ } ++} ++ + var PluginUtils = + { + withTestPlugin : function(callback) +diff --git toolkit/components/places/PlacesUtils.jsm toolkit/components/places/PlacesUtils.jsm +index f6315f68eb4c..5aebe0496ee8 100644 +--- toolkit/components/places/PlacesUtils.jsm ++++ toolkit/components/places/PlacesUtils.jsm +@@ -896,6 +896,11 @@ this.PlacesUtils = { + case this.TYPE_X_MOZ_URL: { + if (aFeedURI || PlacesUtils.nodeIsURI(aNode)) + return (aFeedURI || aNode.uri) + NEWLINE + aNode.title; ++ if (PlacesUtils.nodeIsContainer(aNode)) { ++ return PlacesUtils.getURLsForContainerNode(aNode) ++ .map(item => item.uri + "\n" + item.title) ++ .join("\n"); ++ } + return ""; + } + case this.TYPE_HTML: { +@@ -1491,7 +1496,11 @@ this.PlacesUtils = { + for (let i = 0; i < root.childCount; ++i) { + let child = root.getChild(i); + if (this.nodeIsURI(child)) +- urls.push({uri: child.uri, isBookmark: this.nodeIsBookmark(child)}); ++ urls.push({ ++ uri: child.uri, ++ isBookmark: this.nodeIsBookmark(child), ++ title: child.title, ++ }); + } + + if (!wasOpen) { diff --git a/www/waterfox/files/patch-bug1402442 b/www/waterfox/files/patch-bug1402442 new file mode 100644 index 000000000000..18bf1c88ca47 --- /dev/null +++ b/www/waterfox/files/patch-bug1402442 @@ -0,0 +1,181 @@ +commit 44b4458e2d21 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Sep 25 18:25:29 2017 +0200 + + Bug 1402442 - Properly remove display: contents pseudo-frames. r=mats, a=ritu + + MozReview-Commit-ID: 4pjVLQfv3YR + Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io> + + --HG-- + extra : source : faa69ac1c14b79838cc0aac842b470a110542ebd + extra : amend_source : 3a76e0123bf3f7d10295000cc44fd8bdddf700df +--- + layout/base/nsCSSFrameConstructor.cpp | 26 +++++++++++++++------- + testing/web-platform/meta/MANIFEST.json | 25 +++++++++++++++++++++ + ...dynamic-generated-content-fieldset-001.html.ini | 4 ++++ + ...dynamic-generated-content-fieldset-001-ref.html | 16 +++++++++++++ + ...nts-dynamic-generated-content-fieldset-001.html | 26 ++++++++++++++++++++++ + 5 files changed, 89 insertions(+), 8 deletions(-) + +diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp +index 99b1211b399b..4fce3fb381a7 100644 +--- layout/base/nsCSSFrameConstructor.cpp ++++ layout/base/nsCSSFrameConstructor.cpp +@@ -1698,6 +1698,17 @@ nsCSSFrameConstructor::NotifyDestroyingFrame(nsIFrame* aFrame) + nsFrameManager::NotifyDestroyingFrame(aFrame); + } + ++static bool ++HasGeneratedContent(const nsIContent* aChild) ++{ ++ if (!aChild->MayHaveAnonymousChildren()) { ++ return false; ++ } ++ ++ return nsLayoutUtils::GetBeforeFrame(aChild) || ++ nsLayoutUtils::GetAfterFrame(aChild); ++} ++ + struct nsGenConInitializer { + nsAutoPtr<nsGenConNode> mNode; + nsGenConList* mList; +@@ -8642,16 +8653,15 @@ nsCSSFrameConstructor::ContentRemoved(nsIContent* aCo + MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild), + "display:contents nodes shouldn't have a frame"); + if (!childFrame && GetDisplayContentsStyleFor(aChild)) { +- nsIContent* ancestor = aContainer; +- MOZ_ASSERT(ancestor, "display: contents on the root?"); +- while (!ancestor->GetPrimaryFrame()) { +- // FIXME(emilio): Should this use the flattened tree parent instead? +- ancestor = ancestor->GetParent(); +- MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!"); +- } ++ if (HasGeneratedContent(aChild)) { ++ nsIContent* ancestor = aContainer; ++ MOZ_ASSERT(ancestor, "display: contents on the root?"); ++ while (!ancestor->GetPrimaryFrame()) { ++ // FIXME(emilio): Should this use the flattened tree parent instead? ++ ancestor = ancestor->GetParent(); ++ MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!"); ++ } + +- nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame(); +- if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) { + *aDidReconstruct = true; + LAYOUT_PHASE_TEMP_EXIT(); + +diff --git testing/web-platform/meta/MANIFEST.json testing/web-platform/meta/MANIFEST.json +index 5f05321c5a70..8aed4a4b5078 100644 +--- testing/web-platform/meta/MANIFEST.json ++++ testing/web-platform/meta/MANIFEST.json +@@ -102975,6 +102975,18 @@ + {} + ] + ], ++ "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html": [ ++ [ ++ "/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html", ++ [ ++ [ ++ "/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html", ++ "==" ++ ] ++ ], ++ {} ++ ] ++ ], + "css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html": [ + [ + "/css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html", +@@ -227658,6 +227670,11 @@ + {} + ] + ], ++ "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html": [ ++ [ ++ {} ++ ] ++ ], + "css/css-display-3/display-contents-flex-001-ref.html": [ + [ + {} +@@ -502880,6 +502897,14 @@ + "a2d7c9368ed8c01ca06c36646666270e85aee070", + "reftest" + ], ++ "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html": [ ++ "30ec5c8ddacfbfef8434c37ca7a0a766f2bbc89a", ++ "support" ++ ], ++ "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html": [ ++ "984bebb3c3b8661aedef4a229848dfa818bb1f4a", ++ "reftest" ++ ], + "css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html": [ + "40fb07e8ada1530e6835ff2d4e49c5571ffb0baa", + "reftest" +diff --git testing/web-platform/meta/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html.ini testing/web-platform/meta/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html.ini +new file mode 100644 +index 000000000000..63c7442a2362 +--- /dev/null ++++ testing/web-platform/meta/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html.ini +@@ -0,0 +1,4 @@ ++[display-contents-dynamic-generated-content-fieldset-001.html] ++ type: reftest ++ expected: ++ if not stylo: FAIL +diff --git testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html +new file mode 100644 +index 000000000000..651bc19b83e9 +--- /dev/null ++++ testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html +@@ -0,0 +1,16 @@ ++<!doctype html> ++<meta charset="utf-8"> ++<title>CSS Reftest Reference</title> ++<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> ++<style> ++div { ++ display: contents; ++ border: 10px solid red; ++} ++</style> ++<p> ++ Test passes if there is no red text and no red border. ++</p> ++<fieldset> ++ <div></div> ++</fieldset> +diff --git testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html +new file mode 100644 +index 000000000000..8f8a0ba47971 +--- /dev/null ++++ testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html +@@ -0,0 +1,26 @@ ++<!doctype html> ++<meta charset="utf-8"> ++<title>CSS Test: Dynamic changes to display: contents generated content in fieldsets.</title> ++<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> ++<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents"> ++<link rel="match" href="display-contents-dynamic-generated-content-fieldset-001-ref.html"> ++<style> ++.after::after { ++ content: "FAIL"; ++ color: red; ++} ++div { ++ display: contents; ++ border: 10px solid red; ++} ++</style> ++<p> ++ Test passes if there is no red text and no red border. ++</p> ++<fieldset> ++ <div class="after"></div> ++</fieldset> ++<script> ++document.body.offsetHeight; ++document.querySelector("div").classList.remove("after"); ++</script> diff --git a/www/waterfox/files/patch-bug1402469 b/www/waterfox/files/patch-bug1402469 new file mode 100644 index 000000000000..4dae69a93f04 --- /dev/null +++ b/www/waterfox/files/patch-bug1402469 @@ -0,0 +1,182 @@ +commit 6b4f644b9a4e +Author: Makoto Kato <m_kato@ga2.so-net.ne.jp> +Date: Mon Sep 25 14:15:50 2017 +0900 + + Bug 1402469 - Part 1. Return value of ConvertListType should use Element instead of nsresult. r=masayuki, a=sledru + + This is a typo bug of Bug 1053779 Part 2. ConvertListType might return NS_OK + even if ReplaceContainer doesn't return valid value. + + So, to clean up code, we should return Element instead of nsresult since out + parameter of this function is Element only. + + MozReview-Commit-ID: 44UHETzcdGy + + --HG-- + extra : source : 5efdecc086858b4b4e5b0fcf9b7f27ef63d91738 +--- + editor/libeditor/HTMLEditRules.cpp | 47 +++++++++++++++++--------------------- + editor/libeditor/HTMLEditRules.h | 4 ++-- + 2 files changed, 23 insertions(+), 28 deletions(-) + +diff --git editor/libeditor/HTMLEditRules.cpp editor/libeditor/HTMLEditRules.cpp +index ad613517269d..fdb15fec7b2f 100644 +--- editor/libeditor/HTMLEditRules.cpp ++++ editor/libeditor/HTMLEditRules.cpp +@@ -2960,9 +2960,8 @@ HTMLEditRules::TryToJoinBlocks(nsIContent& aLeftNode, + // Nodes are same type. merge them. + EditorDOMPoint pt = JoinNodesSmart(*leftBlock, *rightBlock); + if (pt.node && mergeLists) { +- nsCOMPtr<Element> newBlock; +- ConvertListType(rightBlock, getter_AddRefs(newBlock), +- existingList, nsGkAtoms::li); ++ RefPtr<Element> newBlock = ++ ConvertListType(rightBlock, existingList, nsGkAtoms::li); + } + ret.MarkAsHandled(); + } else { +@@ -3320,18 +3319,19 @@ HTMLEditRules::WillMakeList(Selection* aSelection, + NS_ENSURE_STATE(mHTMLEditor); + rv = mHTMLEditor->MoveNode(curNode, curList, -1); + NS_ENSURE_SUCCESS(rv, rv); +- rv = ConvertListType(curNode->AsElement(), getter_AddRefs(newBlock), +- listType, itemType); +- NS_ENSURE_SUCCESS(rv, rv); ++ newBlock = ConvertListType(curNode->AsElement(), listType, itemType); ++ if (NS_WARN_IF(!newBlock)) { ++ return NS_ERROR_FAILURE; ++ } + NS_ENSURE_STATE(mHTMLEditor); + rv = mHTMLEditor->RemoveBlockContainer(*newBlock); + NS_ENSURE_SUCCESS(rv, rv); + } else { + // replace list with new list type +- rv = ConvertListType(curNode->AsElement(), getter_AddRefs(newBlock), +- listType, itemType); +- NS_ENSURE_SUCCESS(rv, rv); +- curList = newBlock; ++ curList = ConvertListType(curNode->AsElement(), listType, itemType); ++ if (NS_WARN_IF(!curList)) { ++ return NS_ERROR_FAILURE; ++ } + } + prevListItem = nullptr; + continue; +@@ -4495,14 +4495,12 @@ HTMLEditRules::OutdentPartOfBlock(Element& aBlock, + /** + * ConvertListType() converts list type and list item type. + */ +-nsresult ++already_AddRefed<Element> + HTMLEditRules::ConvertListType(Element* aList, +- Element** aOutList, + nsIAtom* aListType, + nsIAtom* aItemType) + { + MOZ_ASSERT(aList); +- MOZ_ASSERT(aOutList); + MOZ_ASSERT(aListType); + MOZ_ASSERT(aItemType); + +@@ -4513,29 +4511,26 @@ HTMLEditRules::ConvertListType(Element* aList, + if (HTMLEditUtils::IsListItem(element) && + !element->IsHTMLElement(aItemType)) { + child = mHTMLEditor->ReplaceContainer(element, aItemType); +- NS_ENSURE_STATE(child); ++ if (NS_WARN_IF(!child)) { ++ return nullptr; ++ } + } else if (HTMLEditUtils::IsList(element) && + !element->IsHTMLElement(aListType)) { +- nsCOMPtr<dom::Element> temp; +- nsresult rv = ConvertListType(child->AsElement(), getter_AddRefs(temp), +- aListType, aItemType); +- NS_ENSURE_SUCCESS(rv, rv); +- child = temp.forget(); ++ child = ConvertListType(child->AsElement(), aListType, aItemType); ++ if (NS_WARN_IF(!child)) { ++ return nullptr; ++ } + } + } + child = child->GetNextSibling(); + } + + if (aList->IsHTMLElement(aListType)) { +- nsCOMPtr<dom::Element> list = aList->AsElement(); +- list.forget(aOutList); +- return NS_OK; ++ RefPtr<dom::Element> list = aList->AsElement(); ++ return list.forget(); + } + +- *aOutList = mHTMLEditor->ReplaceContainer(aList, aListType).take(); +- NS_ENSURE_STATE(aOutList); +- +- return NS_OK; ++ return mHTMLEditor->ReplaceContainer(aList, aListType); + } + + +diff --git editor/libeditor/HTMLEditRules.h editor/libeditor/HTMLEditRules.h +index d1bb1fa7e3b2..0dde7f01e408 100644 +--- editor/libeditor/HTMLEditRules.h ++++ editor/libeditor/HTMLEditRules.h +@@ -316,8 +316,8 @@ protected: + nsIContent** aOutLeftNode, + nsIContent** aOutRightNode); + +- nsresult ConvertListType(Element* aList, Element** aOutList, +- nsIAtom* aListType, nsIAtom* aItemType); ++ already_AddRefed<Element> ConvertListType(Element* aList, nsIAtom* aListType, ++ nsIAtom* aItemType); + + nsresult CreateStyleForInsertText(Selection& aSelection, nsIDocument& aDoc); + enum class MozBRCounts { yes, no }; + +commit 5e5f298b8e42 +Author: Makoto Kato <m_kato@ga2.so-net.ne.jp> +Date: Mon Sep 25 14:11:29 2017 +0900 + + Bug 1402469 - Part 2. Add crash test. r=masayuki, a=sledru + + MozReview-Commit-ID: HogVH2OTyd6 + + --HG-- + extra : source : 5e311cd7074e6b649187f5a79371f0681c2d7504 +--- + editor/libeditor/crashtests/1402469.html | 16 ++++++++++++++++ + editor/libeditor/crashtests/crashtests.list | 1 + + 2 files changed, 17 insertions(+) + +diff --git editor/libeditor/crashtests/1402469.html editor/libeditor/crashtests/1402469.html +new file mode 100644 +index 000000000000..04b1adc96f25 +--- /dev/null ++++ editor/libeditor/crashtests/1402469.html +@@ -0,0 +1,16 @@ ++<html> ++<head> ++<script type="application/javascript"> ++function do_test() { ++ document.execCommand("insertUnorderedList", false); ++} ++</script> ++</head> ++<body onload="do_test()"> ++<table> ++ <th contenteditable="true"> ++ <ol contenteditable="false"> ++ </th> ++</table> ++</body> ++</html> +diff --git editor/libeditor/crashtests/crashtests.list editor/libeditor/crashtests/crashtests.list +index 11672c41d102..840e26f2fe62 100644 +--- editor/libeditor/crashtests/crashtests.list ++++ editor/libeditor/crashtests/crashtests.list +@@ -80,3 +80,4 @@ load 1366176.html + load 1375131.html + load 1381541.html + load 1383755.html ++load 1402469.html diff --git a/www/waterfox/files/patch-bug1402681 b/www/waterfox/files/patch-bug1402681 new file mode 100644 index 000000000000..6fddbdf9937d --- /dev/null +++ b/www/waterfox/files/patch-bug1402681 @@ -0,0 +1,138 @@ +commit ffcf40b7a0e9 +Author: Alastor Wu <alwu@mozilla.com> +Date: Tue Sep 26 17:48:19 2017 +0800 + + Bug 1402681 - Part 1: Do not queue the task without task queue. r=jya, a=sledru + + Since the source buffer is a wrapped native, it would be unlinked twice and then the + TrackBuffersManager::Detach() would also be called twice. + + The first detach task would clear the task queue of TrackBuffersManager, and then we + won't accept any new task without task queue. The second detach task should not be + executed. + + MozReview-Commit-ID: AWTzVbRH5B1 + + --HG-- + extra : source : 145eac8ba70636cdb1a235d6d7094b87bbfd8022 +--- + dom/media/mediasource/TrackBuffersManager.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git dom/media/mediasource/TrackBuffersManager.cpp dom/media/mediasource/TrackBuffersManager.cpp +index 50293810064b..cda89faaff51 100644 +--- dom/media/mediasource/TrackBuffersManager.cpp ++++ dom/media/mediasource/TrackBuffersManager.cpp +@@ -145,6 +145,15 @@ TrackBuffersManager::DoAppendData(already_AddRefed<MediaByteBuffer> aData, + void + TrackBuffersManager::QueueTask(SourceBufferTask* aTask) + { ++ // The source buffer is a wrapped native, it would be unlinked twice and so ++ // the TrackBuffersManager::Detach() would also be called twice. Since the ++ // detach task has been done before, we could ignore this task. ++ if (!GetTaskQueue()) { ++ MOZ_ASSERT(aTask->GetType() == SourceBufferTask::Type::Detach, ++ "only detach task could happen here!"); ++ return; ++ } ++ + if (!OnTaskQueue()) { + GetTaskQueue()->Dispatch(NewRunnableMethod<RefPtr<SourceBufferTask>>( + "TrackBuffersManager::QueueTask", + +commit 99e2204da6a1 +Author: Alastor Wu <alwu@mozilla.com> +Date: Tue Sep 26 17:48:39 2017 +0800 + + Bug 1402681 - Part 2: Add log. r=jya, a=sledru + + MozReview-Commit-ID: 8qINxSCKrvg + + --HG-- + extra : source : 0cac2e15b4ca7cf03e75ee208da624495215382f +--- + dom/media/mediasource/SourceBufferTask.h | 7 +++++++ + dom/media/mediasource/TrackBuffersManager.cpp | 4 ++++ + 2 files changed, 11 insertions(+) + +diff --git dom/media/mediasource/SourceBufferTask.h dom/media/mediasource/SourceBufferTask.h +index 183e7b4b2a0b..b73094fbd282 100644 +--- dom/media/mediasource/SourceBufferTask.h ++++ dom/media/mediasource/SourceBufferTask.h +@@ -32,6 +32,7 @@ public: + typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> RangeRemovalPromise; + + virtual Type GetType() const = 0; ++ virtual const char* GetTypeName() const = 0; + + template<typename ReturnType> + ReturnType* As() +@@ -54,6 +55,7 @@ public: + + static const Type sType = Type::AppendBuffer; + Type GetType() const override { return Type::AppendBuffer; } ++ const char* GetTypeName() const override { return "AppendBuffer"; } + + RefPtr<MediaByteBuffer> mBuffer; + SourceBufferAttributes mAttributes; +@@ -64,12 +66,14 @@ class AbortTask : public SourceBufferTask { + public: + static const Type sType = Type::Abort; + Type GetType() const override { return Type::Abort; } ++ const char* GetTypeName() const override { return "Abort"; } + }; + + class ResetTask : public SourceBufferTask { + public: + static const Type sType = Type::Reset; + Type GetType() const override { return Type::Reset; } ++ const char* GetTypeName() const override { return "Reset"; } + }; + + class RangeRemovalTask : public SourceBufferTask { +@@ -80,6 +84,7 @@ public: + + static const Type sType = Type::RangeRemoval; + Type GetType() const override { return Type::RangeRemoval; } ++ const char* GetTypeName() const override { return "RangeRemoval"; } + + media::TimeInterval mRange; + MozPromiseHolder<RangeRemovalPromise> mPromise; +@@ -94,6 +99,7 @@ public: + + static const Type sType = Type::EvictData; + Type GetType() const override { return Type::EvictData; } ++ const char* GetTypeName() const override { return "EvictData"; } + + media::TimeUnit mPlaybackTime; + int64_t mSizeToEvict; +@@ -103,6 +109,7 @@ class DetachTask : public SourceBufferTask { + public: + static const Type sType = Type::Detach; + Type GetType() const override { return Type::Detach; } ++ const char* GetTypeName() const override { return "Detach"; } + }; + + } // end mozilla namespace +diff --git dom/media/mediasource/TrackBuffersManager.cpp dom/media/mediasource/TrackBuffersManager.cpp +index cda89faaff51..b9b768b726a2 100644 +--- dom/media/mediasource/TrackBuffersManager.cpp ++++ dom/media/mediasource/TrackBuffersManager.cpp +@@ -151,6 +151,8 @@ TrackBuffersManager::QueueTask(SourceBufferTask* aTask) + if (!GetTaskQueue()) { + MOZ_ASSERT(aTask->GetType() == SourceBufferTask::Type::Detach, + "only detach task could happen here!"); ++ MSE_DEBUG("Could not queue the task '%s' without task queue", ++ aTask->GetTypeName()); + return; + } + +@@ -183,6 +185,8 @@ TrackBuffersManager::ProcessTasks() + // nothing to do. + return; + } ++ ++ MSE_DEBUG("Process task '%s'", task->GetTypeName()); + switch (task->GetType()) { + case Type::AppendBuffer: + mCurrentTask = task; diff --git a/www/waterfox/files/patch-bug1402715 b/www/waterfox/files/patch-bug1402715 new file mode 100644 index 000000000000..c8857edb5eee --- /dev/null +++ b/www/waterfox/files/patch-bug1402715 @@ -0,0 +1,44 @@ +commit 6c7fb56e58c5 +Author: Mats Palmgren <mats@mozilla.com> +Date: Wed Sep 27 14:12:01 2017 +0200 + + Bug 1402715 - Treat URL bar contents as raw text when copying. r=mak + + MozReview-Commit-ID: LuSvwRUVwAq +--- + browser/base/content/test/urlbar/browser_urlbarCopying.js | 5 +++++ + browser/base/content/urlbarBindings.xml | 5 ++++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git browser/base/content/test/urlbar/browser_urlbarCopying.js browser/base/content/test/urlbar/browser_urlbarCopying.js +index 521dace780f2..9559b06b2ec6 100644 +--- browser/base/content/test/urlbar/browser_urlbarCopying.js ++++ browser/base/content/test/urlbar/browser_urlbarCopying.js +@@ -164,6 +164,11 @@ var tests = [ + copyVal: "<example.com/?\xf7>\xf7", + copyExpected: "http://example.com/?\xf7" + }, ++ { ++ loadURL: "http://example.com/%20%20%20", ++ expectedURL: "example.com/ ", ++ copyExpected: "http://example.com/%20%20%20" ++ }, + + // data: and javsacript: URIs shouldn't be encoded + { +diff --git browser/base/content/urlbarBindings.xml browser/base/content/urlbarBindings.xml +index 8999ab379cb2..4a86ce38e893 100644 +--- browser/base/content/urlbarBindings.xml ++++ browser/base/content/urlbarBindings.xml +@@ -972,7 +972,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. + // Grab the actual input field's value, not our value, which could include moz-action: + var inputVal = this.inputField.value; + let selection = this.editor.selection; +- var selectedVal = selection.toString(); ++ const flags = Ci.nsIDocumentEncoder.OutputPreformatted | ++ Ci.nsIDocumentEncoder.OutputRaw; ++ let selectedVal = selection.QueryInterface(Ci.nsISelectionPrivate) ++ .toStringWithFormat("text/plain", flags, 0); + + // Handle multiple-range selection as a string for simplicity. + if (selection.rangeCount > 1) { diff --git a/www/waterfox/files/patch-bug1402766 b/www/waterfox/files/patch-bug1402766 new file mode 100644 index 000000000000..a339af5d1188 --- /dev/null +++ b/www/waterfox/files/patch-bug1402766 @@ -0,0 +1,69 @@ +commit fd42606e30e4 +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Tue Oct 3 18:50:10 2017 -0400 + + Bug 1402766 - Work around layout violating its own invariants and causing stylo code to crash. r=emilio, a=sledru + + MozReview-Commit-ID: 3ggJI0qmOJV + + --HG-- + extra : source : 71d02a129bebc9dfd804b1babb8fae587d1930a8 + extra : histedit_source : d36726bf4182c3820a3f8efd2d2599b114cb55c4 +--- + layout/generic/crashtests/1405443.html | 19 +++++++++++++++++++ + layout/generic/crashtests/crashtests.list | 1 + + layout/generic/nsInlineFrame.cpp | 7 +++++++ + 3 files changed, 27 insertions(+) + +diff --git layout/generic/crashtests/1405443.html layout/generic/crashtests/1405443.html +new file mode 100644 +index 000000000000..79313ae1c4d4 +--- /dev/null ++++ layout/generic/crashtests/1405443.html +@@ -0,0 +1,19 @@ ++<style> ++#htmlvar00009 { page-break-inside: avoid; } ++* { padding-left: 1vw; border-right: solid green 3em; } ++#htmlvar00001 { columns: 1px; ) ++</style> ++<script> ++function jsfuzzer() { ++try { htmlvar00009.appendChild(htmlvar00013); } catch(e) { } ++try { var var00143 = htmlvar00009.x; } catch(e) { } ++try { htmlvar00009.appendChild(document.createElement("table").createCaption()); } catch(e) { } ++} ++</script> ++<body onload=jsfuzzer()> ++<dl id="htmlvar00001"> ++A ++<img id="htmlvar00009" align="left"></img> ++<menu id="htmlvar00013"> ++<menuitem> ++<hr> +diff --git layout/generic/crashtests/crashtests.list layout/generic/crashtests/crashtests.list +index 25c2c32470fc..07cc75ea0f9a 100644 +--- layout/generic/crashtests/crashtests.list ++++ layout/generic/crashtests/crashtests.list +@@ -659,3 +659,4 @@ load 1367413-1.html + load 1368617-1.html + load 1373586.html + load 1401420-1.html ++asserts(11) load 1405443.html # bug 1405443 +diff --git layout/generic/nsInlineFrame.cpp layout/generic/nsInlineFrame.cpp +index 089178a6ada2..ce62f822bda0 100644 +--- layout/generic/nsInlineFrame.cpp ++++ layout/generic/nsInlineFrame.cpp +@@ -1065,6 +1065,13 @@ nsInlineFrame::UpdateStyleOfOwnedAnonBoxesForIBSplit( + } + + nsIFrame* nextInline = blockFrame->GetProperty(nsIFrame::IBSplitSibling()); ++ ++ // This check is here due to bug 1405443. Please remove it once ++ // that bug is fixed. ++ if (!nextInline) { ++ break; ++ } ++ + MOZ_ASSERT(nextInline, "There is always a trailing inline in an IB split"); + + for (nsIFrame* cont = nextInline; cont; cont = cont->GetNextContinuation()) { diff --git a/www/waterfox/files/patch-bug1402871 b/www/waterfox/files/patch-bug1402871 new file mode 100644 index 000000000000..a0b71c81a4a1 --- /dev/null +++ b/www/waterfox/files/patch-bug1402871 @@ -0,0 +1,28 @@ +commit 6f6ee3c5b2ad +Author: Kearwood Gilbert <kgilbert@mozilla.com> +Date: Wed Oct 11 14:25:51 2017 -0700 + + Bug 1402871 - Change VREventObserver::mWindow to a RefPtr. r=dveditz, a=ritu + + MozReview-Commit-ID: 79MlNMAvIQD + + --HG-- + extra : source : 84ff58454e222ce067ec27f8841ba684934b7666 +--- + dom/vr/VREventObserver.h | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git dom/vr/VREventObserver.h dom/vr/VREventObserver.h +index 24a1065a18fe..cd2cf69469b5 100644 +--- dom/vr/VREventObserver.h ++++ dom/vr/VREventObserver.h +@@ -34,8 +34,7 @@ public: + private: + ~VREventObserver(); + +- // Weak pointer, instance is owned by mWindow. +- nsGlobalWindow* MOZ_NON_OWNING_REF mWindow; ++ RefPtr<nsGlobalWindow> mWindow; + // For WebVR telemetry for tracking users who view content + // in the 2D view. + TimeStamp mSpendTimeIn2DView; diff --git a/www/waterfox/files/patch-bug1402951 b/www/waterfox/files/patch-bug1402951 new file mode 100644 index 000000000000..7c9a14017c7e --- /dev/null +++ b/www/waterfox/files/patch-bug1402951 @@ -0,0 +1,164 @@ +commit 71daba14a2c4 +Author: Alexander Surkov <surkov.alexander@gmail.com> +Date: Tue Oct 3 10:58:27 2017 -0400 + + Bug 1402951 - No show events for content on document load complete. r=aklotz, r=yzen, a=ritu + + --HG-- + extra : source : ffc4c63976921cbfec03b26ff48541c2f414d2e3 +--- + accessible/generic/DocAccessible.cpp | 14 ++++++++------ + accessible/ipc/DocAccessibleChildBase.cpp | 15 ++++++++++++++- + accessible/ipc/DocAccessibleChildBase.h | 5 +++++ + accessible/ipc/DocAccessibleParent.cpp | 5 +++++ + accessible/ipc/other/PDocAccessible.ipdl | 1 + + accessible/ipc/win/DocAccessibleChild.h | 3 ++- + accessible/ipc/win/PDocAccessible.ipdl | 1 + + accessible/tests/mochitest/treeupdate/test_ariaowns.html | 5 ++--- + 8 files changed, 38 insertions(+), 11 deletions(-) + +diff --git accessible/generic/DocAccessible.cpp accessible/generic/DocAccessible.cpp +index 60b160b21a78..fa6f3c6a70d5 100644 +--- accessible/generic/DocAccessible.cpp ++++ accessible/generic/DocAccessible.cpp +@@ -1536,13 +1536,15 @@ DocAccessible::DoInitialUpdate() + ParentDocument()->FireDelayedEvent(reorderEvent); + } + +- TreeMutation mt(this); +- uint32_t childCount = ChildCount(); +- for (uint32_t i = 0; i < childCount; i++) { +- Accessible* child = GetChildAt(i); +- mt.AfterInsertion(child); ++ if (IPCAccessibilityActive()) { ++ DocAccessibleChild* ipcDoc = IPCDoc(); ++ MOZ_ASSERT(ipcDoc); ++ if (ipcDoc) { ++ for (auto idx = 0U; idx < mChildren.Length(); idx++) { ++ ipcDoc->InsertIntoIpcTree(this, mChildren.ElementAt(idx), idx); ++ } ++ } + } +- mt.Done(); + } + + void +diff --git accessible/ipc/DocAccessibleChildBase.cpp accessible/ipc/DocAccessibleChildBase.cpp +index 6a0ad9b7dbc6..19a858aa6d9b 100644 +--- accessible/ipc/DocAccessibleChildBase.cpp ++++ accessible/ipc/DocAccessibleChildBase.cpp +@@ -80,6 +80,19 @@ DocAccessibleChildBase::SerializeTree(Accessible* aRoot, + } + } + ++void ++DocAccessibleChildBase::InsertIntoIpcTree(Accessible* aParent, ++ Accessible* aChild, ++ uint32_t aIdxInParent) ++{ ++ uint64_t parentID = aParent->IsDoc() ? ++ 0 : reinterpret_cast<uint64_t>(aParent->UniqueID()); ++ nsTArray<AccessibleData> shownTree; ++ ShowEventData data(parentID, aIdxInParent, shownTree, true); ++ SerializeTree(aChild, data.NewTree()); ++ MaybeSendShowEvent(data, false); ++} ++ + void + DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent) + { +@@ -87,7 +100,7 @@ DocAccessibleChildBase::ShowEvent(AccShowEvent* aShowEvent) + uint64_t parentID = parent->IsDoc() ? 0 : reinterpret_cast<uint64_t>(parent->UniqueID()); + uint32_t idxInParent = aShowEvent->GetAccessible()->IndexInParent(); + nsTArray<AccessibleData> shownTree; +- ShowEventData data(parentID, idxInParent, shownTree); ++ ShowEventData data(parentID, idxInParent, shownTree, false); + SerializeTree(aShowEvent->GetAccessible(), data.NewTree()); + MaybeSendShowEvent(data, aShowEvent->IsFromUserInput()); + } +diff --git accessible/ipc/DocAccessibleChildBase.h accessible/ipc/DocAccessibleChildBase.h +index b8a8bfde1d0c..13146e5d44e2 100644 +--- accessible/ipc/DocAccessibleChildBase.h ++++ accessible/ipc/DocAccessibleChildBase.h +@@ -45,6 +45,11 @@ public: + SendShutdown(); + } + ++ /** ++ * Serializes a shown tree and sends it to the chrome process. ++ */ ++ void InsertIntoIpcTree(Accessible* aParent, ++ Accessible* aChild, uint32_t aIdxInParent); + void ShowEvent(AccShowEvent* aShowEvent); + + virtual void ActorDestroy(ActorDestroyReason) override +diff --git accessible/ipc/DocAccessibleParent.cpp accessible/ipc/DocAccessibleParent.cpp +index 4bbf261273c5..34c334847c04 100644 +--- accessible/ipc/DocAccessibleParent.cpp ++++ accessible/ipc/DocAccessibleParent.cpp +@@ -79,6 +79,11 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData, + + MOZ_ASSERT(CheckDocTree()); + ++ // Just update, no events. ++ if (aData.EventSuppressed()) { ++ return IPC_OK(); ++ } ++ + ProxyAccessible* target = parent->ChildAt(newChildIdx); + ProxyShowHideEvent(target, parent, true, aFromUser); + +diff --git accessible/ipc/other/PDocAccessible.ipdl accessible/ipc/other/PDocAccessible.ipdl +index 4c084bbee125..ffed961185fa 100644 +--- accessible/ipc/other/PDocAccessible.ipdl ++++ accessible/ipc/other/PDocAccessible.ipdl +@@ -29,6 +29,7 @@ struct ShowEventData + uint64_t ID; + uint32_t Idx; + AccessibleData[] NewTree; ++ bool EventSuppressed; + }; + + struct Attribute +diff --git accessible/ipc/win/DocAccessibleChild.h accessible/ipc/win/DocAccessibleChild.h +index e34987005a40..9b4586a16cda 100644 +--- accessible/ipc/win/DocAccessibleChild.h ++++ accessible/ipc/win/DocAccessibleChild.h +@@ -110,7 +110,8 @@ private: + SerializedShow(DocAccessibleChild* aTarget, + ShowEventData& aEventData, bool aFromUser) + : DeferredEvent(aTarget) +- , mEventData(aEventData.ID(), aEventData.Idx(), nsTArray<AccessibleData>()) ++ , mEventData(aEventData.ID(), aEventData.Idx(), ++ nsTArray<AccessibleData>(), aEventData.EventSuppressed()) + , mFromUser(aFromUser) + { + // Since IPDL doesn't generate a move constructor for ShowEventData, +diff --git accessible/ipc/win/PDocAccessible.ipdl accessible/ipc/win/PDocAccessible.ipdl +index afd3b991efdc..da7128e87a65 100644 +--- accessible/ipc/win/PDocAccessible.ipdl ++++ accessible/ipc/win/PDocAccessible.ipdl +@@ -29,6 +29,7 @@ struct ShowEventData + uint64_t ID; + uint32_t Idx; + AccessibleData[] NewTree; ++ bool EventSuppressed; + }; + + struct Attribute +diff --git accessible/tests/mochitest/treeupdate/test_ariaowns.html accessible/tests/mochitest/treeupdate/test_ariaowns.html +index 7d88b9a0698b..bf47bc84c280 100644 +--- accessible/tests/mochitest/treeupdate/test_ariaowns.html ++++ accessible/tests/mochitest/treeupdate/test_ariaowns.html +@@ -580,9 +580,8 @@ + function test9_prepare() + { + this.eventSeq = [ +- new invokerChecker(EVENT_SHOW, () => { +- let doc = getNode('t9_container').contentDocument; +- return doc && doc.getElementById('container'); ++ new invokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, () => { ++ return getNode('t9_container').contentDocument; + }) + ]; + diff --git a/www/waterfox/files/patch-bug1402966 b/www/waterfox/files/patch-bug1402966 new file mode 100644 index 000000000000..51123f684a06 --- /dev/null +++ b/www/waterfox/files/patch-bug1402966 @@ -0,0 +1,51 @@ +commit 6149574dc0f9 +Author: Gabriele Svelto <gsvelto@mozilla.com> +Date: Tue Sep 26 09:35:03 2017 +0200 + + Bug 1402966 - Search for libcurl in more paths to support various *BSDs. r=Dexter, a=sledru + + MozReview-Commit-ID: J4ykuSVEa0y + + --HG-- + extra : source : 4741b93cfdf29517ff8eae863825fdc2ab5bd7bd +--- + .../telemetry/pingsender/pingsender_unix_common.cpp | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git toolkit/components/telemetry/pingsender/pingsender_unix_common.cpp toolkit/components/telemetry/pingsender/pingsender_unix_common.cpp +index ae20f4114193..7817e93e3d1f 100644 +--- toolkit/components/telemetry/pingsender/pingsender_unix_common.cpp ++++ toolkit/components/telemetry/pingsender/pingsender_unix_common.cpp +@@ -88,10 +88,19 @@ CurlWrapper::Init() + "/usr/lib/i386-linux-gnu", // Debian 32-bit x86 + "/usr/lib/x86_64-linux-gnu", // Debian 64-bit x86 + #endif // XP_LINUX ++#if !defined(XP_MACOSX) && !defined(XP_LINUX) // Various BSDs ++ "/usr/local/lib", // FreeBSD, OpenBSD ++ "/usr/pkg/lib", // NetBSD ++#endif // !defined(XP_MACOSX) && !defined(XP_LINUX) + }; + + const char* libcurlNames[] = { +-#ifdef XP_LINUX ++#if defined(XP_MACOSX) ++ // macOS ++ "libcurl.dylib", ++ "libcurl.4.dylib", ++ "libcurl.3.dylib", ++#else // Linux, *BSD, ... + "libcurl.so", + "libcurl.so.4", + // Debian gives libcurl a different name when it is built against GnuTLS +@@ -100,11 +109,6 @@ CurlWrapper::Init() + // Older versions in case we find nothing better + "libcurl.so.3", + "libcurl-gnutls.so.3", // See above for Debian +-#elif defined(XP_MACOSX) +- // macOS +- "libcurl.dylib", +- "libcurl.4.dylib", +- "libcurl.3.dylib", + #endif + }; + diff --git a/www/waterfox/files/patch-bug1402981 b/www/waterfox/files/patch-bug1402981 new file mode 100644 index 000000000000..9e177ca672e2 --- /dev/null +++ b/www/waterfox/files/patch-bug1402981 @@ -0,0 +1,172 @@ +commit bcef6c71b916 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Sep 27 22:37:19 2017 +0100 + + Bug 1402981 - Add light and dark themes to the list of themes in customize mode by default. r=jaws, a=sledru + + MozReview-Commit-ID: 4GxPEm119Yc + + --HG-- + extra : source : ed2a1dff7a2e544a76de0eb65139f0febd0211e4 +--- + .../components/customizableui/CustomizeMode.jsm | 45 +++++++++++++++------- + .../browser_1007336_lwthemes_in_customize_mode.js | 44 +++++++++++++++------ + 2 files changed, 64 insertions(+), 25 deletions(-) + +diff --git browser/components/customizableui/CustomizeMode.jsm browser/components/customizableui/CustomizeMode.jsm +index fbc8ff27093c..aa80840a3c42 100644 +--- browser/components/customizableui/CustomizeMode.jsm ++++ browser/components/customizableui/CustomizeMode.jsm +@@ -1311,7 +1311,9 @@ CustomizeMode.prototype = { + + onLWThemesMenuShowing(aEvent) { + const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}"; +- const RECENT_LWT_COUNT = 5; ++ const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org"; ++ const DARK_THEME_ID = "firefox-compact-dark@mozilla.org"; ++ const MAX_THEME_COUNT = 6; + + this._clearLWThemesMenu(aEvent.target); + +@@ -1366,19 +1368,27 @@ CustomizeMode.prototype = { + let themes = [aDefaultTheme]; + let lwts = LightweightThemeManager.usedThemes; + let currentLwt = LightweightThemeManager.currentTheme; +- let currentLwtIndex = lwts.indexOf(currentLwt); +- if (currentLwtIndex > -1) { +- // Make sure that the current lightweight theme +- // is at the beginning of the array to avoid truncation +- // in the next step. +- lwts = lwts.splice(currentLwtIndex, 1).concat(lwts); +- } +- if (lwts.length > RECENT_LWT_COUNT) +- lwts.length = RECENT_LWT_COUNT; ++ // The lwts besides the builtin themes don't have an isActive property: + for (let lwt of lwts) { +- lwt.isActive = !!currentLwt && (lwt.id == currentLwt.id); +- themes.push(lwt); ++ if (!lwt.hasOwnProperty("isActive")) { ++ lwt.isActive = !!currentLwt && (lwt.id == currentLwt.id); ++ } ++ } ++ ++ // Move the current theme (if any) and the light/dark themes to the start: ++ let importantThemes = [LIGHT_THEME_ID, DARK_THEME_ID]; ++ if (currentLwt && !importantThemes.includes(currentLwt.id)) { ++ importantThemes.push(currentLwt.id); ++ } ++ for (let importantTheme of importantThemes) { ++ let themeIndex = lwts.findIndex(theme => theme.id == importantTheme); ++ if (themeIndex > -1) { ++ themes.push(...lwts.splice(themeIndex, 1)); ++ } + } ++ themes = themes.concat(lwts); ++ if (themes.length > MAX_THEME_COUNT) ++ themes.length = MAX_THEME_COUNT; + + let footer = doc.getElementById("customization-lwtheme-menu-footer"); + let panel = footer.parentNode; +@@ -1400,8 +1410,15 @@ CustomizeMode.prototype = { + recommendedThemes = JSON.parse(recommendedThemes); + let sb = Services.strings.createBundle("chrome://browser/locale/lightweightThemes.properties"); + for (let theme of recommendedThemes) { +- theme.name = sb.GetStringFromName("lightweightThemes." + theme.id + ".name"); +- theme.description = sb.GetStringFromName("lightweightThemes." + theme.id + ".description"); ++ try { ++ theme.name = sb.GetStringFromName("lightweightThemes." + theme.id + ".name"); ++ theme.description = sb.GetStringFromName("lightweightThemes." + theme.id + ".description"); ++ } catch (ex) { ++ // If finding strings for this failed, just don't build it. This can ++ // happen for users with 'older' recommended themes lists, some of which ++ // have since been removed from Firefox. ++ continue; ++ } + let button = buildToolbarButton(theme); + button.addEventListener("command", () => { + LightweightThemeManager.setLocalTheme(button.theme); +diff --git browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js +index 3cb3ee34c7cf..3ee8f9b8f697 100644 +--- browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js ++++ browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js +@@ -5,12 +5,13 @@ + "use strict"; + + const DEFAULT_THEME_ID = "{972ce4c6-7e08-4474-a285-3208198ce6fd}"; ++const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org"; ++const DARK_THEME_ID = "firefox-compact-dark@mozilla.org"; + const {LightweightThemeManager} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {}); + + add_task(async function() { + Services.prefs.clearUserPref("lightweightThemes.usedThemes"); + Services.prefs.clearUserPref("lightweightThemes.recommendedThemes"); +- LightweightThemeManager.clearBuiltInThemes(); + + await startCustomizing(); + +@@ -35,9 +36,14 @@ add_task(async function() { + let header = document.getElementById("customization-lwtheme-menu-header"); + let recommendedHeader = document.getElementById("customization-lwtheme-menu-recommended"); + +- is(header.nextSibling.nextSibling, recommendedHeader, +- "There should only be one theme (default) in the 'My Themes' section by default"); +- is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "That theme should be the default theme"); ++ is(header.nextSibling.nextSibling.nextSibling.nextSibling, recommendedHeader, ++ "There should only be three themes (default, light, dark) in the 'My Themes' section by default"); ++ is(header.nextSibling.theme.id, DEFAULT_THEME_ID, ++ "The first theme should be the default theme"); ++ is(header.nextSibling.nextSibling.theme.id, LIGHT_THEME_ID, ++ "The second theme should be the light theme"); ++ is(header.nextSibling.nextSibling.nextSibling.theme.id, DARK_THEME_ID, ++ "The third theme should be the dark theme"); + + let firstLWTheme = recommendedHeader.nextSibling; + let firstLWThemeId = firstLWTheme.theme.id; +@@ -52,12 +58,18 @@ add_task(async function() { + await popupShownPromise; + + is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme"); +- let installedThemeId = header.nextSibling.nextSibling.theme.id; ++ let installedThemeId = header.nextSibling.nextSibling.nextSibling.nextSibling.theme.id; + ok(installedThemeId.startsWith(firstLWThemeId), + "The second theme in the 'My Themes' section should be the newly installed theme: " + + "Installed theme id: " + installedThemeId + "; First theme ID: " + firstLWThemeId); +- is(header.nextSibling.nextSibling.nextSibling, recommendedHeader, +- "There should be two themes in the 'My Themes' section"); ++ let themeCount = 0; ++ let iterNode = header; ++ while (iterNode.nextSibling && iterNode.nextSibling.theme) { ++ themeCount++; ++ iterNode = iterNode.nextSibling; ++ } ++ is(themeCount, 4, ++ "There should be four themes in the 'My Themes' section"); + + let defaultTheme = header.nextSibling; + defaultTheme.doCommand(); +@@ -90,11 +102,21 @@ add_task(async function() { + await popupShownPromise; + header = document.getElementById("customization-lwtheme-menu-header"); + is(header.hidden, false, "Header should never be hidden"); +- is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme"); +- is(header.nextSibling.hidden, false, "The default theme should never be hidden"); ++ let themeNode = header.nextSibling; ++ is(themeNode.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme"); ++ is(themeNode.hidden, false, "The default theme should never be hidden"); ++ ++ themeNode = themeNode.nextSibling; ++ is(themeNode.theme.id, LIGHT_THEME_ID, "The second theme should be the Light theme"); ++ is(themeNode.hidden, false, "The light theme should never be hidden"); ++ ++ themeNode = themeNode.nextSibling; ++ is(themeNode.theme.id, DARK_THEME_ID, "The third theme should be the Dark theme"); ++ is(themeNode.hidden, false, "The dark theme should never be hidden"); ++ + recommendedHeader = document.getElementById("customization-lwtheme-menu-recommended"); +- is(header.nextSibling.nextSibling, recommendedHeader, +- "There should only be one theme (default) in the 'My Themes' section by default"); ++ is(themeNode.nextSibling, recommendedHeader, ++ "There should only be three themes (default, light, dark) in the 'My Themes' section now"); + let footer = document.getElementById("customization-lwtheme-menu-footer"); + is(recommendedHeader.nextSibling.id, footer.id, "There should be no recommended themes in the menu"); + is(recommendedHeader.hidden, true, "The recommendedHeader should be hidden since there are no recommended themes"); diff --git a/www/waterfox/files/patch-bug1403282 b/www/waterfox/files/patch-bug1403282 new file mode 100644 index 000000000000..baab3804b1bb --- /dev/null +++ b/www/waterfox/files/patch-bug1403282 @@ -0,0 +1,180 @@ +commit fc20d87173c4 +Author: Manish Goregaokar <manishearth@gmail.com> +Date: Tue Sep 26 23:56:15 2017 -0500 + + Bug 1403282 - stylo: Don't error out on trailing whitespace in attr(). r=bz, a=sledru + + Source-Repo: https://github.com/servo/servo + Source-Revision: 97227aaca3613e22afc832554d29f7f7fdfb7220 + + --HG-- + extra : source : 4263e1c081c940b4eae7bcd388274ec8c5b5dd8b +--- + servo/components/style/values/specified/mod.rs | 44 ++++++++++++++------------ + 1 file changed, 24 insertions(+), 20 deletions(-) + +diff --git servo/components/style/values/specified/mod.rs servo/components/style/values/specified/mod.rs +index 856aecca90ac..72ed1b1de83a 100644 +--- servo/components/style/values/specified/mod.rs ++++ servo/components/style/values/specified/mod.rs +@@ -739,28 +739,32 @@ impl Attr { + let first = input.try(|i| i.expect_ident_cloned()).ok(); + if let Ok(token) = input.try(|i| i.next_including_whitespace().map(|t| t.clone())) { + match token { +- Token::Delim('|') => {} ++ Token::Delim('|') => { ++ // must be followed by an ident ++ let second_token = match *input.next_including_whitespace()? { ++ Token::Ident(ref second) => second, ++ ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), ++ }; ++ ++ let ns_with_id = if let Some(ns) = first { ++ let ns = Namespace::from(ns.as_ref()); ++ let id: Result<_, ParseError> = ++ get_id_for_namespace(&ns, context) ++ .map_err(|()| StyleParseError::UnspecifiedError.into()); ++ Some((ns, id?)) ++ } else { ++ None ++ }; ++ return Ok(Attr { ++ namespace: ns_with_id, ++ attribute: second_token.as_ref().to_owned(), ++ }) ++ } ++ // In the case of attr(foobar ) we don't want to error out ++ // because of the trailing whitespace ++ Token::WhiteSpace(_) => (), + ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), + } +- // must be followed by an ident +- let second_token = match *input.next_including_whitespace()? { +- Token::Ident(ref second) => second, +- ref t => return Err(BasicParseError::UnexpectedToken(t.clone()).into()), +- }; +- +- let ns_with_id = if let Some(ns) = first { +- let ns = Namespace::from(ns.as_ref()); +- let id: Result<_, ParseError> = +- get_id_for_namespace(&ns, context) +- .map_err(|()| StyleParseError::UnspecifiedError.into()); +- Some((ns, id?)) +- } else { +- None +- }; +- return Ok(Attr { +- namespace: ns_with_id, +- attribute: second_token.as_ref().to_owned(), +- }) + } + + if let Some(first) = first { + +commit 20bbda2d12de +Author: Manish Goregaokar <manishearth@gmail.com> +Date: Tue Sep 26 13:54:22 2017 -0700 + + Bug 1403282 - stylo: Add reftests for whitespace in attr(). r=bz, a=sledru + + MozReview-Commit-ID: IMXFY7bpKGf + + --HG-- + extra : source : cfcb518088438415e5c6f7776dc268abd0b86119 +--- + .../generated-content/attr-whitespace-ref.html | 10 ++++ + .../generated-content/attr-whitespace.xhtml | 60 ++++++++++++++++++++++ + layout/reftests/generated-content/reftest.list | 1 + + 3 files changed, 71 insertions(+) + +diff --git layout/reftests/generated-content/attr-whitespace-ref.html layout/reftests/generated-content/attr-whitespace-ref.html +new file mode 100644 +index 000000000000..54a74fe4d81f +--- /dev/null ++++ layout/reftests/generated-content/attr-whitespace-ref.html +@@ -0,0 +1,10 @@ ++<!DOCTYPE HTML> ++<html> ++<body> ++<div>HelloWorld</div> ++<div>HelloWorld</div> ++<div>HelloWorld</div> ++<div>Hello</div> ++<div>Hello</div> ++</body> ++</html> +diff --git layout/reftests/generated-content/attr-whitespace.xhtml layout/reftests/generated-content/attr-whitespace.xhtml +new file mode 100644 +index 000000000000..e9b6554849b0 +--- /dev/null ++++ layout/reftests/generated-content/attr-whitespace.xhtml +@@ -0,0 +1,60 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ++ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> ++<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml"> ++<head> ++ <title>Whitespace in attributes</title> ++ <link rel="author" title="Manish Goregaokar" href="mailto:manishearth@gmail.com" /> ++ <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" /> ++ <link rel="help" href="https://drafts.csswg.org/css-values-3/#attr-notation"/> ++<style> ++@namespace ns url(http://www.example.com/ns); ++/* Spaces within attr() are fine*/ ++#a::after { ++ ++ content: attr( ++ data-text ++ ++ ++ ); ++} ++#b::after { ++ ++ content: attr(ns|data-text); ++} ++#c::after { ++ ++ content: attr( ++ ns|data-text ++ ++ ++ ); ++} ++ ++/* No whitespace around the | */ ++#d::after { ++ ++ content: attr( ++ ns |data-text ++ ++ ++ ); ++} ++#e::after { ++ ++ content: attr( ++ ns| data-text ++ ++ ++ ); ++} ++</style> ++</head> ++<body xmlns:ns="http://www.example.com/ns"> ++<div id="a" data-text="World">Hello</div> ++<div id="b" ns:data-text="World">Hello</div> ++<div id="b" ns:data-text="World">Hello</div> ++<div id="d" ns:data-text="World">Hello</div> ++<div id="e" ns:data-text="World">Hello</div> ++</body> ++</html> +diff --git layout/reftests/generated-content/reftest.list layout/reftests/generated-content/reftest.list +index e07a0dd565a5..c789f1845421 100644 +--- layout/reftests/generated-content/reftest.list ++++ layout/reftests/generated-content/reftest.list +@@ -19,3 +19,4 @@ fuzzy-if(OSX==1010,1,10) == table-parts-01.html table-parts-01-ref.html + == before-style-sharing.html before-style-sharing-ref.html + == transitive-style-invalidation.html transitive-style-invalidation-ref.html + == dynamic-content.html dynamic-content-ref.html ++== attr-whitespace.xhtml attr-whitespace-ref.html diff --git a/www/waterfox/files/patch-bug1403349 b/www/waterfox/files/patch-bug1403349 new file mode 100644 index 000000000000..bdeb5aa56580 --- /dev/null +++ b/www/waterfox/files/patch-bug1403349 @@ -0,0 +1,1216 @@ +commit bec0ae08b1a9 +Author: Luca Greco <lgreco@mozilla.com> +Date: Wed Sep 27 14:24:54 2017 +0200 + + Bug 1403349 - Fix wrong sourceTabId on webNavigation.onCreatedTarget event. r=aswan, a=ritu + + This changes fixes the regression introduced by Bug 1355120 and adds a new + test case which contains a browserAction popup which open and immediately + close a new window and ensure that the received onCreatedNavigationTarget + is the expected one. + + MozReview-Commit-ID: JIcVCpBTpxj + + --HG-- + extra : source : 435db72f9b6ab5ec9144bbf92611c5c877342410 + extra : histedit_source : 99ba482dfa4bacfbd3b96d4044fdab536c1955e5 +--- + ...gation_onCreatedNavigationTarget_window_open.js | 76 ++++++++++++++++++++-- + toolkit/modules/addons/WebNavigation.jsm | 23 ++++--- + toolkit/modules/addons/WebNavigationContent.js | 16 ++++- + 3 files changed, 99 insertions(+), 16 deletions(-) + +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +index 1dd79b4256f7..993d7c50ff43 100644 +--- browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +@@ -58,7 +58,7 @@ async function runTestCase({extension, openNavTarget, expectedWebNavProps}) { + is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property"); + } + +-add_task(async function test_on_created_navigation_target_from_window_open() { ++add_task(async function test_window_open() { + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + + gBrowser.selectedTab = tab1; +@@ -74,7 +74,7 @@ add_task(async function test_on_created_navigation_target_from_window_open() { + + const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); + +- info("open an url in a new tab from a window.open call"); ++ info("open a url in a new tab from a window.open call"); + + await runTestCase({ + extension, +@@ -91,7 +91,7 @@ add_task(async function test_on_created_navigation_target_from_window_open() { + }, + }); + +- info("open an url in a new window from a window.open call"); ++ info("open a url in a new window from a window.open call"); + + await runTestCase({ + extension, +@@ -113,7 +113,7 @@ add_task(async function test_on_created_navigation_target_from_window_open() { + await extension.unload(); + }); + +-add_task(async function test_on_created_navigation_target_from_window_open_subframe() { ++add_task(async function test_window_open_from_subframe() { + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + + gBrowser.selectedTab = tab1; +@@ -129,7 +129,7 @@ add_task(async function test_on_created_navigation_target_from_window_open_subfr + + const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); + +- info("open an url in a new tab from subframe window.open call"); ++ info("open a url in a new tab from subframe window.open call"); + + await runTestCase({ + extension, +@@ -146,7 +146,7 @@ add_task(async function test_on_created_navigation_target_from_window_open_subfr + }, + }); + +- info("open an url in a new window from subframe window.open call"); ++ info("open a url in a new window from subframe window.open call"); + + await runTestCase({ + extension, +@@ -167,3 +167,67 @@ add_task(async function test_on_created_navigation_target_from_window_open_subfr + + await extension.unload(); + }); ++ ++add_task(async function test_window_open_close_from_browserAction_popup() { ++ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); ++ ++ gBrowser.selectedTab = tab1; ++ ++ function popup() { ++ window.open("", "_self").close(); ++ ++ browser.test.sendMessage("browserAction_popup_executed"); ++ } ++ ++ const extension = ExtensionTestUtils.loadExtension({ ++ background, ++ manifest: { ++ browser_action: { ++ default_popup: "popup.html", ++ }, ++ permissions: ["webNavigation", "tabs", "<all_urls>"], ++ }, ++ files: { ++ "popup.html": `<!DOCTYPE html> ++ <html> ++ <head> ++ <meta charset="utf-8"> ++ </head> ++ <body> ++ <script src="popup.js"></script> ++ </body> ++ </html> ++ `, ++ "popup.js": popup, ++ }, ++ }); ++ ++ await extension.startup(); ++ ++ const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); ++ ++ clickBrowserAction(extension); ++ ++ await extension.awaitMessage("browserAction_popup_executed"); ++ ++ info("open a url in a new tab from a window.open call"); ++ ++ await runTestCase({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `window.open("${OPENED_PAGE}#new-tab-from-window-open"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: 0, ++ url: `${OPENED_PAGE}#new-tab-from-window-open`, ++ }, ++ }); ++ ++ await BrowserTestUtils.removeTab(tab1); ++ ++ await extension.unload(); ++}); +diff --git toolkit/modules/addons/WebNavigation.jsm toolkit/modules/addons/WebNavigation.jsm +index 1aadbd579e05..a0c774665d17 100644 +--- toolkit/modules/addons/WebNavigation.jsm ++++ toolkit/modules/addons/WebNavigation.jsm +@@ -306,19 +306,26 @@ var Manager = { + }, + + onCreatedNavigationTarget(browser, data) { +- const {isSourceTab, createdWindowId, sourceFrameId, url} = data; +- +- // We are going to potentially received two message manager messages for a single +- // onCreatedNavigationTarget event that is happening in the child process, +- // we are going to use the generate uuid to pair them together. +- const pairedMessage = this.createdNavigationTargetByOuterWindowId.get(createdWindowId); ++ const { ++ createdOuterWindowId, ++ isSourceTab, ++ sourceFrameId, ++ url, ++ } = data; ++ ++ // We are going to receive two message manager messages for a single ++ // onCreatedNavigationTarget event related to a window.open that is happening ++ // in the child process (one from the source tab and one from the created tab), ++ // the unique createdWindowId (the outerWindowID of the created docShell) ++ // to pair them together. ++ const pairedMessage = this.createdNavigationTargetByOuterWindowId.get(createdOuterWindowId); + + if (!pairedMessage) { +- this.createdNavigationTargetByOuterWindowId.set(createdWindowId, {browser, data}); ++ this.createdNavigationTargetByOuterWindowId.set(createdOuterWindowId, {browser, data}); + return; + } + +- this.createdNavigationTargetByOuterWindowId.delete(createdWindowId); ++ this.createdNavigationTargetByOuterWindowId.delete(createdOuterWindowId); + + let sourceTabBrowser; + let createdTabBrowser; +diff --git toolkit/modules/addons/WebNavigationContent.js toolkit/modules/addons/WebNavigationContent.js +index 31a8b7328fc9..ed873cc98644 100644 +--- toolkit/modules/addons/WebNavigationContent.js ++++ toolkit/modules/addons/WebNavigationContent.js +@@ -10,6 +10,17 @@ Components.utils.import("resource://gre/modules/Services.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "WebNavigationFrames", + "resource://gre/modules/WebNavigationFrames.jsm"); + ++function getDocShellOuterWindowId(docShell) { ++ if (!docShell) { ++ return undefined; ++ } ++ ++ return docShell.QueryInterface(Ci.nsIInterfaceRequestor) ++ .getInterface(Ci.nsIDOMWindow) ++ .getInterface(Ci.nsIDOMWindowUtils) ++ .outerWindowID; ++} ++ + function loadListener(event) { + let document = event.target; + let window = document.defaultView; +@@ -56,8 +67,9 @@ var CreatedNavigationTargetListener = { + } + + const isSourceTab = docShell === sourceDocShell || isSourceTabDescendant; ++ + const sourceFrameId = WebNavigationFrames.getDocShellFrameId(sourceDocShell); +- const createdWindowId = WebNavigationFrames.getDocShellFrameId(createdDocShell); ++ const createdOuterWindowId = getDocShellOuterWindowId(sourceDocShell); + + let url; + if (props.hasKey("url")) { +@@ -67,7 +79,7 @@ var CreatedNavigationTargetListener = { + sendAsyncMessage("Extension:CreatedNavigationTarget", { + url, + sourceFrameId, +- createdWindowId, ++ createdOuterWindowId, + isSourceTab, + }); + }, + +commit 27a18112bd4c +Author: Luca Greco <lgreco@mozilla.com> +Date: Wed Sep 27 19:07:41 2017 +0200 + + Bug 1403349 - Prevent WebNavigation jsm to leak the sourceTab browser on unpaired CreatedNavigationTarget messages. r=aswan, a=ritu + + This applies the following changes: + + - store a weak reference to the browser element in the WebNavigation.jsm Manager's map + of pending CreatedNavigationTarget messages + + - when a CreatedNavigationTarget message is received from a sourceTab + for a created window that is not currently tracked in the map + (e.g. it has been immediately closed), the message received from the sourceTab + is not saved in the map of the pending CreatedNavigationTarget (and a message + is logged in the console to make easier to investigate issues related to discarded + CreatedNavigationTarget events). + + - adds an additional assertion to the related test case to ensure that no CreatedNavigationTarget + message is still pending in the WebNavigation/jsm's Manager. + + MozReview-Commit-ID: FijQ8IqiY8L + + --HG-- + extra : source : 6692df0c568732b5f38bc594e7e020b3ea2e0f41 + extra : histedit_source : cd9bd61c19bf32bdd24f0faed101a0da9faf5ed4 +--- + ...gation_onCreatedNavigationTarget_window_open.js | 16 +++++++ + toolkit/modules/addons/WebNavigation.jsm | 50 ++++++++++++++++++---- + 2 files changed, 57 insertions(+), 9 deletions(-) + +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +index 993d7c50ff43..1fbb3c07d4a9 100644 +--- browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +@@ -58,6 +58,16 @@ async function runTestCase({extension, openNavTarget, expectedWebNavProps}) { + is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property"); + } + ++// Test that there are no pending createdNavigationTarget messages still tracked ++// in WebNavigation.jsm (to be called before the extension is unloaded, because ++// once the last extension which have subscribed a webNavigation event is unloaded ++// all the pending created navigation target data is completely cleared). ++function assertNoPendingCreatedNavigationTargetData() { ++ const {Manager} = Cu.import("resource://gre/modules/WebNavigation.jsm", {}); ++ Assert.equal(Manager.createdNavigationTargetByOuterWindowId.size, 0, ++ "There should be no pending createdNavigationTarget messages in WebNavigation"); ++} ++ + add_task(async function test_window_open() { + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + +@@ -108,6 +118,8 @@ add_task(async function test_window_open() { + }, + }); + ++ assertNoPendingCreatedNavigationTargetData(); ++ + await BrowserTestUtils.removeTab(tab1); + + await extension.unload(); +@@ -163,6 +175,8 @@ add_task(async function test_window_open_from_subframe() { + }, + }); + ++ assertNoPendingCreatedNavigationTargetData(); ++ + await BrowserTestUtils.removeTab(tab1); + + await extension.unload(); +@@ -227,6 +241,8 @@ add_task(async function test_window_open_close_from_browserAction_popup() { + }, + }); + ++ assertNoPendingCreatedNavigationTargetData(); ++ + await BrowserTestUtils.removeTab(tab1); + + await extension.unload(); +diff --git toolkit/modules/addons/WebNavigation.jsm toolkit/modules/addons/WebNavigation.jsm +index a0c774665d17..db6efdb443de 100644 +--- toolkit/modules/addons/WebNavigation.jsm ++++ toolkit/modules/addons/WebNavigation.jsm +@@ -320,22 +320,54 @@ var Manager = { + // to pair them together. + const pairedMessage = this.createdNavigationTargetByOuterWindowId.get(createdOuterWindowId); + ++ if (!isSourceTab) { ++ if (pairedMessage) { ++ // This should not happen, print a warning before overwriting the unexpected pending data. ++ Services.console.logStringMessage( ++ `Discarding onCreatedNavigationTarget for ${createdOuterWindowId}: ` + ++ "unexpected pending data while receiving the created tab data" ++ ); ++ } ++ ++ // Store a weak reference to the browser XUL element, so that we don't prevent ++ // it to be garbage collected if it has been destroyed. ++ const browserWeakRef = Cu.getWeakReference(browser); ++ ++ this.createdNavigationTargetByOuterWindowId.set(createdOuterWindowId, { ++ browserWeakRef, ++ data, ++ }); ++ ++ return; ++ } ++ + if (!pairedMessage) { +- this.createdNavigationTargetByOuterWindowId.set(createdOuterWindowId, {browser, data}); ++ // The sourceTab should always be received after the message coming from the created ++ // top level frame because the "webNavigation-createdNavigationTarget-from-js" observers ++ // subscribed by WebNavigationContent.js are going to be executed in reverse order ++ // (See http://searchfox.org/mozilla-central/rev/f54c1723be/xpcom/ds/nsObserverList.cpp#76) ++ // and the observer subscribed to the created target will be the last one subscribed ++ // to the ObserverService (and the first one to be triggered). ++ Services.console.logStringMessage( ++ `Discarding onCreatedNavigationTarget for ${createdOuterWindowId}: ` + ++ "received source tab data without any created tab data available" ++ ); ++ + return; + } + + this.createdNavigationTargetByOuterWindowId.delete(createdOuterWindowId); + +- let sourceTabBrowser; +- let createdTabBrowser; ++ let sourceTabBrowser = browser; ++ let createdTabBrowser = pairedMessage.browserWeakRef.get(); + +- if (isSourceTab) { +- sourceTabBrowser = browser; +- createdTabBrowser = pairedMessage.browser; +- } else { +- sourceTabBrowser = pairedMessage.browser; +- createdTabBrowser = browser; ++ if (!createdTabBrowser) { ++ Services.console.logStringMessage( ++ `Discarding onCreatedNavigationTarget for ${createdOuterWindowId}: ` + ++ "the created tab has been already destroyed" ++ ); ++ ++ return; + } + + this.fire("onCreatedNavigationTarget", createdTabBrowser, {}, { + +commit 9f0305064bbe +Author: Luca Greco <lgreco@mozilla.com> +Date: Thu Sep 28 22:04:14 2017 +0200 + + Bug 1403349 - Add a new webNavigation test for window.open called with a named window target. r=aswan, a=ritu + + MozReview-Commit-ID: Aj8uMtcGwJx + + --HG-- + extra : source : acc39e04d4f0559b796916d5f54a36673708766a + extra : histedit_source : 2366c25a25acf76333f6b9386886ca5c866dad54 +--- + ...gation_onCreatedNavigationTarget_window_open.js | 57 ++++++++++++++++++++++ + 1 file changed, 57 insertions(+) + +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +index 1fbb3c07d4a9..232b9321fcd3 100644 +--- browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +@@ -247,3 +247,60 @@ add_task(async function test_window_open_close_from_browserAction_popup() { + + await extension.unload(); + }); ++ ++add_task(async function test_window_open_in_named_win() { ++ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); ++ ++ gBrowser.selectedTab = tab1; ++ ++ const extension = ExtensionTestUtils.loadExtension({ ++ background, ++ manifest: { ++ permissions: ["webNavigation", "tabs", "<all_urls>"], ++ }, ++ }); ++ ++ await extension.startup(); ++ ++ const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); ++ ++ info("open a url in a new named window from a window.open call"); ++ ++ await runTestCase({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `window.open("${OPENED_PAGE}#new-named-window-open", "TestWinName"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: 0, ++ url: `${OPENED_PAGE}#new-named-window-open`, ++ }, ++ }); ++ ++ info("open a url in an existent named window from a window.open call"); ++ ++ await runTestCase({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `window.open("${OPENED_PAGE}#existent-named-window-open", "TestWinName"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: 0, ++ url: `${OPENED_PAGE}#existent-named-window-open`, ++ }, ++ }); ++ ++ assertNoPendingCreatedNavigationTargetData(); ++ ++ await BrowserTestUtils.removeTab(tab1); ++ ++ await extension.unload(); ++}); + +commit 2a05645d21a8 +Author: Luca Greco <lgreco@mozilla.com> +Date: Fri Oct 13 18:19:47 2017 +0200 + + Bug 1403349 - Split webNavigation onCreatedNavigationTarget tests to prevent timeouts on linux32 debug. r=aswan, a=ritu + + MozReview-Commit-ID: 50JLocTVvfu + + --HG-- + rename : browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js => browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_named_window.js + rename : browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js => browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_subframe_window_open.js + extra : source : e802283bbf21d14d431901dd286681cd1933bb97 + extra : histedit_source : dfedfb9746b98e9ee96e768a53aa0f6cbdc8b6ee +--- + .../extensions/test/browser/browser-common.ini | 3 + + ..._ext_webNavigation_onCreatedNavigationTarget.js | 36 +---- + ...gation_onCreatedNavigationTarget_contextmenu.js | 47 ++---- + ...ation_onCreatedNavigationTarget_named_window.js | 97 ++++++++++++ + ...CreatedNavigationTarget_subframe_window_open.js | 163 +++++++++++++++++++++ + ...gation_onCreatedNavigationTarget_window_open.js | 153 +------------------ + .../extensions/test/browser/head_webNavigation.js | 39 +++++ + 7 files changed, 329 insertions(+), 209 deletions(-) + +diff --git browser/components/extensions/test/browser/browser-common.ini browser/components/extensions/test/browser/browser-common.ini +index a03cb9147a7f..3a672f737a59 100644 +--- browser/components/extensions/test/browser/browser-common.ini ++++ browser/components/extensions/test/browser/browser-common.ini +@@ -3,6 +3,7 @@ support-files = + head.js + head_pageAction.js + head_sessions.js ++ head_webNavigation.js + profilerSymbols.sjs + context.html + context_frame.html +@@ -171,6 +172,8 @@ skip-if = true # Bug 1398514 + [browser_ext_webNavigation_getFrames.js] + [browser_ext_webNavigation_onCreatedNavigationTarget.js] + [browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js] ++[browser_ext_webNavigation_onCreatedNavigationTarget_named_window.js] ++[browser_ext_webNavigation_onCreatedNavigationTarget_subframe_window_open.js] + [browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js] + [browser_ext_webNavigation_urlbar_transitions.js] + [browser_ext_windows.js] +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget.js +index 2c17f9e711f8..47d8b0a8c65a 100644 +--- browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget.js ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget.js +@@ -2,9 +2,8 @@ + /* vim: set sts=2 sw=2 et tw=80: */ + "use strict"; + +-const BASE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser"; +-const SOURCE_PAGE = `${BASE_URL}/webNav_createdTargetSource.html`; +-const OPENED_PAGE = `${BASE_URL}/webNav_createdTarget.html`; ++Services.scriptloader.loadSubScript(new URL("head_webNavigation.js", gTestPath).href, ++ this); + + async function background() { + const tabs = await browser.tabs.query({active: true, currentWindow: true}); +@@ -34,24 +33,6 @@ async function background() { + }); + } + +-async function runTestCase({extension, openNavTarget, expectedWebNavProps}) { +- await openNavTarget(); +- +- const webNavMsg = await extension.awaitMessage("webNavOnCreated"); +- const createdTabId = await extension.awaitMessage("tabsOnCreated"); +- const completedNavMsg = await extension.awaitMessage("webNavOnCompleted"); +- +- let {sourceTabId, sourceFrameId, url} = expectedWebNavProps; +- +- is(webNavMsg.tabId, createdTabId, "Got the expected tabId property"); +- is(webNavMsg.sourceTabId, sourceTabId, "Got the expected sourceTabId property"); +- is(webNavMsg.sourceFrameId, sourceFrameId, "Got the expected sourceFrameId property"); +- is(webNavMsg.url, url, "Got the expected url property"); +- +- is(completedNavMsg.tabId, createdTabId, "Got the expected webNavigation.onCompleted tabId property"); +- is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property"); +-} +- + add_task(async function test_on_created_navigation_target_from_mouse_click() { + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + +@@ -68,7 +49,7 @@ add_task(async function test_on_created_navigation_target_from_mouse_click() { + + info("Open link in a new tab using Ctrl-click"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + BrowserTestUtils.synthesizeMouseAtCenter("#test-create-new-tab-from-mouse-click", +@@ -84,7 +65,7 @@ add_task(async function test_on_created_navigation_target_from_mouse_click() { + + info("Open link in a new window using Shift-click"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + BrowserTestUtils.synthesizeMouseAtCenter("#test-create-new-window-from-mouse-click", +@@ -100,7 +81,7 @@ add_task(async function test_on_created_navigation_target_from_mouse_click() { + + info("Open link with target=\"_blank\" in a new tab using click"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + BrowserTestUtils.synthesizeMouseAtCenter("#test-create-new-tab-from-targetblank-click", +@@ -135,7 +116,7 @@ add_task(async function test_on_created_navigation_target_from_mouse_click_subfr + + info("Open a subframe link in a new tab using Ctrl-click"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + BrowserTestUtils.synthesizeMouseAtCenter(function() { +@@ -154,7 +135,7 @@ add_task(async function test_on_created_navigation_target_from_mouse_click_subfr + + info("Open a subframe link in a new window using Shift-click"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + BrowserTestUtils.synthesizeMouseAtCenter(function() { +@@ -173,7 +154,7 @@ add_task(async function test_on_created_navigation_target_from_mouse_click_subfr + + info("Open a subframe link with target=\"_blank\" in a new tab using click"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + BrowserTestUtils.synthesizeMouseAtCenter(function() { +@@ -194,4 +175,3 @@ add_task(async function test_on_created_navigation_target_from_mouse_click_subfr + + await extension.unload(); + }); +- +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js +index 670dad87f1e4..e29fccf57a5b 100644 +--- browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_contextmenu.js +@@ -2,9 +2,16 @@ + /* vim: set sts=2 sw=2 et tw=80: */ + "use strict"; + +-const BASE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser"; +-const SOURCE_PAGE = `${BASE_URL}/webNav_createdTargetSource.html`; +-const OPENED_PAGE = `${BASE_URL}/webNav_createdTarget.html`; ++Services.scriptloader.loadSubScript(new URL("head_webNavigation.js", gTestPath).href, ++ this); ++ ++async function clickContextMenuItem({pageElementSelector, contextMenuItemLabel}) { ++ const contentAreaContextMenu = await openContextMenu(pageElementSelector); ++ const item = contentAreaContextMenu.getElementsByAttribute("label", contextMenuItemLabel); ++ is(item.length, 1, `found contextMenu item for "${contextMenuItemLabel}"`); ++ item[0].click(); ++ await closeContextMenu(); ++} + + async function background() { + const tabs = await browser.tabs.query({active: true, currentWindow: true}); +@@ -34,32 +41,6 @@ async function background() { + }); + } + +-async function runTestCase({extension, openNavTarget, expectedWebNavProps}) { +- await openNavTarget(); +- +- const webNavMsg = await extension.awaitMessage("webNavOnCreated"); +- const createdTabId = await extension.awaitMessage("tabsOnCreated"); +- const completedNavMsg = await extension.awaitMessage("webNavOnCompleted"); +- +- let {sourceTabId, sourceFrameId, url} = expectedWebNavProps; +- +- is(webNavMsg.tabId, createdTabId, "Got the expected tabId property"); +- is(webNavMsg.sourceTabId, sourceTabId, "Got the expected sourceTabId property"); +- is(webNavMsg.sourceFrameId, sourceFrameId, "Got the expected sourceFrameId property"); +- is(webNavMsg.url, url, "Got the expected url property"); +- +- is(completedNavMsg.tabId, createdTabId, "Got the expected webNavigation.onCompleted tabId property"); +- is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property"); +-} +- +-async function clickContextMenuItem({pageElementSelector, contextMenuItemLabel}) { +- const contentAreaContextMenu = await openContextMenu(pageElementSelector); +- const item = contentAreaContextMenu.getElementsByAttribute("label", contextMenuItemLabel); +- is(item.length, 1, `found contextMenu item for "${contextMenuItemLabel}"`); +- item[0].click(); +- await closeContextMenu(); +-} +- + add_task(async function test_on_created_navigation_target_from_context_menu() { + const tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + +@@ -76,7 +57,7 @@ add_task(async function test_on_created_navigation_target_from_context_menu() { + + info("Open link in a new tab from the context menu"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + async openNavTarget() { + await clickContextMenuItem({ +@@ -93,7 +74,7 @@ add_task(async function test_on_created_navigation_target_from_context_menu() { + + info("Open link in a new window from the context menu"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + async openNavTarget() { + await clickContextMenuItem({ +@@ -129,7 +110,7 @@ add_task(async function test_on_created_navigation_target_from_context_menu_subf + + info("Open a subframe link in a new tab from the context menu"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + async openNavTarget() { + await clickContextMenuItem({ +@@ -151,7 +132,7 @@ add_task(async function test_on_created_navigation_target_from_context_menu_subf + + info("Open a subframe link in a new window from the context menu"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + async openNavTarget() { + await clickContextMenuItem({ +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_named_window.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_named_window.js +new file mode 100644 +index 000000000000..9888bfb23da6 +--- /dev/null ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_named_window.js +@@ -0,0 +1,97 @@ ++/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++/* vim: set sts=2 sw=2 et tw=80: */ ++"use strict"; ++ ++Services.scriptloader.loadSubScript(new URL("head_webNavigation.js", gTestPath).href, ++ this); ++ ++async function background() { ++ const tabs = await browser.tabs.query({active: true, currentWindow: true}); ++ const sourceTabId = tabs[0].id; ++ ++ const sourceTabFrames = await browser.webNavigation.getAllFrames({tabId: sourceTabId}); ++ ++ browser.webNavigation.onCreatedNavigationTarget.addListener((msg) => { ++ browser.test.sendMessage("webNavOnCreated", msg); ++ }); ++ ++ browser.webNavigation.onCompleted.addListener(async (msg) => { ++ // NOTE: checking the url is currently necessary because of Bug 1252129 ++ // ( Filter out webNavigation events related to new window initialization phase). ++ if (msg.tabId !== sourceTabId && msg.url !== "about:blank") { ++ await browser.tabs.remove(msg.tabId); ++ browser.test.sendMessage("webNavOnCompleted", msg); ++ } ++ }); ++ ++ browser.tabs.onCreated.addListener((tab) => { ++ browser.test.sendMessage("tabsOnCreated", tab.id); ++ }); ++ ++ browser.test.onMessage.addListener(({type, code}) => { ++ if (type === "execute-contentscript") { ++ browser.tabs.executeScript(sourceTabId, {code: code}); ++ } ++ }); ++ ++ browser.test.sendMessage("expectedSourceTab", { ++ sourceTabId, sourceTabFrames, ++ }); ++} ++ ++add_task(async function test_window_open_in_named_win() { ++ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); ++ ++ gBrowser.selectedTab = tab1; ++ ++ const extension = ExtensionTestUtils.loadExtension({ ++ background, ++ manifest: { ++ permissions: ["webNavigation", "tabs", "<all_urls>"], ++ }, ++ }); ++ ++ await extension.startup(); ++ ++ const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); ++ ++ info("open a url in a new named window from a window.open call"); ++ ++ await runCreatedNavigationTargetTest({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `window.open("${OPENED_PAGE}#new-named-window-open", "TestWinName"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: 0, ++ url: `${OPENED_PAGE}#new-named-window-open`, ++ }, ++ }); ++ ++ info("open a url in an existent named window from a window.open call"); ++ ++ await runCreatedNavigationTargetTest({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `window.open("${OPENED_PAGE}#existent-named-window-open", "TestWinName"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: 0, ++ url: `${OPENED_PAGE}#existent-named-window-open`, ++ }, ++ }); ++ ++ assertNoPendingCreatedNavigationTargetData(); ++ ++ await BrowserTestUtils.removeTab(tab1); ++ ++ await extension.unload(); ++}); +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_subframe_window_open.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_subframe_window_open.js +new file mode 100644 +index 000000000000..147c943f7102 +--- /dev/null ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_subframe_window_open.js +@@ -0,0 +1,163 @@ ++/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++/* vim: set sts=2 sw=2 et tw=80: */ ++"use strict"; ++ ++Services.scriptloader.loadSubScript(new URL("head_webNavigation.js", gTestPath).href, ++ this); ++ ++async function background() { ++ const tabs = await browser.tabs.query({active: true, currentWindow: true}); ++ const sourceTabId = tabs[0].id; ++ ++ const sourceTabFrames = await browser.webNavigation.getAllFrames({tabId: sourceTabId}); ++ ++ browser.webNavigation.onCreatedNavigationTarget.addListener((msg) => { ++ browser.test.sendMessage("webNavOnCreated", msg); ++ }); ++ ++ browser.webNavigation.onCompleted.addListener(async (msg) => { ++ // NOTE: checking the url is currently necessary because of Bug 1252129 ++ // ( Filter out webNavigation events related to new window initialization phase). ++ if (msg.tabId !== sourceTabId && msg.url !== "about:blank") { ++ await browser.tabs.remove(msg.tabId); ++ browser.test.sendMessage("webNavOnCompleted", msg); ++ } ++ }); ++ ++ browser.tabs.onCreated.addListener((tab) => { ++ browser.test.sendMessage("tabsOnCreated", tab.id); ++ }); ++ ++ browser.test.onMessage.addListener(({type, code}) => { ++ if (type === "execute-contentscript") { ++ browser.tabs.executeScript(sourceTabId, {code: code}); ++ } ++ }); ++ ++ browser.test.sendMessage("expectedSourceTab", { ++ sourceTabId, sourceTabFrames, ++ }); ++} ++ ++add_task(async function test_window_open_from_subframe() { ++ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); ++ ++ gBrowser.selectedTab = tab1; ++ ++ const extension = ExtensionTestUtils.loadExtension({ ++ background, ++ manifest: { ++ permissions: ["webNavigation", "tabs", "<all_urls>"], ++ }, ++ }); ++ ++ await extension.startup(); ++ ++ const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); ++ ++ info("open a url in a new tab from subframe window.open call"); ++ ++ await runCreatedNavigationTargetTest({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `document.querySelector('iframe').contentWindow.open("${OPENED_PAGE}#new-tab-from-window-open-subframe"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId, ++ url: `${OPENED_PAGE}#new-tab-from-window-open-subframe`, ++ }, ++ }); ++ ++ info("open a url in a new window from subframe window.open call"); ++ ++ await runCreatedNavigationTargetTest({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `document.querySelector('iframe').contentWindow.open("${OPENED_PAGE}#new-win-from-window-open-subframe", "_blank", "toolbar=0"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId, ++ url: `${OPENED_PAGE}#new-win-from-window-open-subframe`, ++ }, ++ }); ++ ++ assertNoPendingCreatedNavigationTargetData(); ++ ++ await BrowserTestUtils.removeTab(tab1); ++ ++ await extension.unload(); ++}); ++ ++add_task(async function test_window_open_close_from_browserAction_popup() { ++ const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); ++ ++ gBrowser.selectedTab = tab1; ++ ++ function popup() { ++ window.open("", "_self").close(); ++ ++ browser.test.sendMessage("browserAction_popup_executed"); ++ } ++ ++ const extension = ExtensionTestUtils.loadExtension({ ++ background, ++ manifest: { ++ browser_action: { ++ default_popup: "popup.html", ++ }, ++ permissions: ["webNavigation", "tabs", "<all_urls>"], ++ }, ++ files: { ++ "popup.html": `<!DOCTYPE html> ++ <html> ++ <head> ++ <meta charset="utf-8"> ++ </head> ++ <body> ++ <script src="popup.js"></script> ++ </body> ++ </html> ++ `, ++ "popup.js": popup, ++ }, ++ }); ++ ++ await extension.startup(); ++ ++ const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); ++ ++ clickBrowserAction(extension); ++ ++ await extension.awaitMessage("browserAction_popup_executed"); ++ ++ info("open a url in a new tab from a window.open call"); ++ ++ await runCreatedNavigationTargetTest({ ++ extension, ++ openNavTarget() { ++ extension.sendMessage({ ++ type: "execute-contentscript", ++ code: `window.open("${OPENED_PAGE}#new-tab-from-window-open"); true;`, ++ }); ++ }, ++ expectedWebNavProps: { ++ sourceTabId: expectedSourceTab.sourceTabId, ++ sourceFrameId: 0, ++ url: `${OPENED_PAGE}#new-tab-from-window-open`, ++ }, ++ }); ++ ++ assertNoPendingCreatedNavigationTargetData(); ++ ++ await BrowserTestUtils.removeTab(tab1); ++ ++ await extension.unload(); ++}); +diff --git browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +index 232b9321fcd3..b56097e44484 100644 +--- browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js ++++ browser/components/extensions/test/browser/browser_ext_webNavigation_onCreatedNavigationTarget_window_open.js +@@ -2,9 +2,8 @@ + /* vim: set sts=2 sw=2 et tw=80: */ + "use strict"; + +-const BASE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser"; +-const SOURCE_PAGE = `${BASE_URL}/webNav_createdTargetSource.html`; +-const OPENED_PAGE = `${BASE_URL}/webNav_createdTarget.html`; ++Services.scriptloader.loadSubScript(new URL("head_webNavigation.js", gTestPath).href, ++ this); + + async function background() { + const tabs = await browser.tabs.query({active: true, currentWindow: true}); +@@ -40,34 +39,6 @@ async function background() { + }); + } + +-async function runTestCase({extension, openNavTarget, expectedWebNavProps}) { +- await openNavTarget(); +- +- const webNavMsg = await extension.awaitMessage("webNavOnCreated"); +- const createdTabId = await extension.awaitMessage("tabsOnCreated"); +- const completedNavMsg = await extension.awaitMessage("webNavOnCompleted"); +- +- let {sourceTabId, sourceFrameId, url} = expectedWebNavProps; +- +- is(webNavMsg.tabId, createdTabId, "Got the expected tabId property"); +- is(webNavMsg.sourceTabId, sourceTabId, "Got the expected sourceTabId property"); +- is(webNavMsg.sourceFrameId, sourceFrameId, "Got the expected sourceFrameId property"); +- is(webNavMsg.url, url, "Got the expected url property"); +- +- is(completedNavMsg.tabId, createdTabId, "Got the expected webNavigation.onCompleted tabId property"); +- is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property"); +-} +- +-// Test that there are no pending createdNavigationTarget messages still tracked +-// in WebNavigation.jsm (to be called before the extension is unloaded, because +-// once the last extension which have subscribed a webNavigation event is unloaded +-// all the pending created navigation target data is completely cleared). +-function assertNoPendingCreatedNavigationTargetData() { +- const {Manager} = Cu.import("resource://gre/modules/WebNavigation.jsm", {}); +- Assert.equal(Manager.createdNavigationTargetByOuterWindowId.size, 0, +- "There should be no pending createdNavigationTarget messages in WebNavigation"); +-} +- + add_task(async function test_window_open() { + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + +@@ -86,7 +57,7 @@ add_task(async function test_window_open() { + + info("open a url in a new tab from a window.open call"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + extension.sendMessage({ +@@ -103,7 +74,7 @@ add_task(async function test_window_open() { + + info("open a url in a new window from a window.open call"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + extension.sendMessage({ +@@ -125,63 +96,6 @@ add_task(async function test_window_open() { + await extension.unload(); + }); + +-add_task(async function test_window_open_from_subframe() { +- const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); +- +- gBrowser.selectedTab = tab1; +- +- const extension = ExtensionTestUtils.loadExtension({ +- background, +- manifest: { +- permissions: ["webNavigation", "tabs", "<all_urls>"], +- }, +- }); +- +- await extension.startup(); +- +- const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); +- +- info("open a url in a new tab from subframe window.open call"); +- +- await runTestCase({ +- extension, +- openNavTarget() { +- extension.sendMessage({ +- type: "execute-contentscript", +- code: `document.querySelector('iframe').contentWindow.open("${OPENED_PAGE}#new-tab-from-window-open-subframe"); true;`, +- }); +- }, +- expectedWebNavProps: { +- sourceTabId: expectedSourceTab.sourceTabId, +- sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId, +- url: `${OPENED_PAGE}#new-tab-from-window-open-subframe`, +- }, +- }); +- +- info("open a url in a new window from subframe window.open call"); +- +- await runTestCase({ +- extension, +- openNavTarget() { +- extension.sendMessage({ +- type: "execute-contentscript", +- code: `document.querySelector('iframe').contentWindow.open("${OPENED_PAGE}#new-win-from-window-open-subframe", "_blank", "toolbar=0"); true;`, +- }); +- }, +- expectedWebNavProps: { +- sourceTabId: expectedSourceTab.sourceTabId, +- sourceFrameId: expectedSourceTab.sourceTabFrames[1].frameId, +- url: `${OPENED_PAGE}#new-win-from-window-open-subframe`, +- }, +- }); +- +- assertNoPendingCreatedNavigationTargetData(); +- +- await BrowserTestUtils.removeTab(tab1); +- +- await extension.unload(); +-}); +- + add_task(async function test_window_open_close_from_browserAction_popup() { + const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); + +@@ -226,7 +140,7 @@ add_task(async function test_window_open_close_from_browserAction_popup() { + + info("open a url in a new tab from a window.open call"); + +- await runTestCase({ ++ await runCreatedNavigationTargetTest({ + extension, + openNavTarget() { + extension.sendMessage({ +@@ -247,60 +161,3 @@ add_task(async function test_window_open_close_from_browserAction_popup() { + + await extension.unload(); + }); +- +-add_task(async function test_window_open_in_named_win() { +- const tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, SOURCE_PAGE); +- +- gBrowser.selectedTab = tab1; +- +- const extension = ExtensionTestUtils.loadExtension({ +- background, +- manifest: { +- permissions: ["webNavigation", "tabs", "<all_urls>"], +- }, +- }); +- +- await extension.startup(); +- +- const expectedSourceTab = await extension.awaitMessage("expectedSourceTab"); +- +- info("open a url in a new named window from a window.open call"); +- +- await runTestCase({ +- extension, +- openNavTarget() { +- extension.sendMessage({ +- type: "execute-contentscript", +- code: `window.open("${OPENED_PAGE}#new-named-window-open", "TestWinName"); true;`, +- }); +- }, +- expectedWebNavProps: { +- sourceTabId: expectedSourceTab.sourceTabId, +- sourceFrameId: 0, +- url: `${OPENED_PAGE}#new-named-window-open`, +- }, +- }); +- +- info("open a url in an existent named window from a window.open call"); +- +- await runTestCase({ +- extension, +- openNavTarget() { +- extension.sendMessage({ +- type: "execute-contentscript", +- code: `window.open("${OPENED_PAGE}#existent-named-window-open", "TestWinName"); true;`, +- }); +- }, +- expectedWebNavProps: { +- sourceTabId: expectedSourceTab.sourceTabId, +- sourceFrameId: 0, +- url: `${OPENED_PAGE}#existent-named-window-open`, +- }, +- }); +- +- assertNoPendingCreatedNavigationTargetData(); +- +- await BrowserTestUtils.removeTab(tab1); +- +- await extension.unload(); +-}); +diff --git browser/components/extensions/test/browser/head_webNavigation.js browser/components/extensions/test/browser/head_webNavigation.js +new file mode 100644 +index 000000000000..a98ccd9934ba +--- /dev/null ++++ browser/components/extensions/test/browser/head_webNavigation.js +@@ -0,0 +1,39 @@ ++/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++/* vim: set sts=2 sw=2 et tw=80: */ ++"use strict"; ++ ++/* exported BASE_URL, SOURCE_PAGE, OPENED_PAGE, ++ runCreatedNavigationTargetTest, assertNoPendingCreatedNavigationTargetData */ ++ ++const BASE_URL = "http://mochi.test:8888/browser/browser/components/extensions/test/browser"; ++const SOURCE_PAGE = `${BASE_URL}/webNav_createdTargetSource.html`; ++const OPENED_PAGE = `${BASE_URL}/webNav_createdTarget.html`; ++ ++async function runCreatedNavigationTargetTest({extension, openNavTarget, expectedWebNavProps}) { ++ await openNavTarget(); ++ ++ const webNavMsg = await extension.awaitMessage("webNavOnCreated"); ++ const createdTabId = await extension.awaitMessage("tabsOnCreated"); ++ const completedNavMsg = await extension.awaitMessage("webNavOnCompleted"); ++ ++ let {sourceTabId, sourceFrameId, url} = expectedWebNavProps; ++ ++ is(webNavMsg.tabId, createdTabId, "Got the expected tabId property"); ++ is(webNavMsg.sourceTabId, sourceTabId, "Got the expected sourceTabId property"); ++ is(webNavMsg.sourceFrameId, sourceFrameId, "Got the expected sourceFrameId property"); ++ is(webNavMsg.url, url, "Got the expected url property"); ++ ++ is(completedNavMsg.tabId, createdTabId, "Got the expected webNavigation.onCompleted tabId property"); ++ is(completedNavMsg.url, url, "Got the expected webNavigation.onCompleted url property"); ++} ++ ++ ++// Test that there are no pending createdNavigationTarget messages still tracked ++// in WebNavigation.jsm (to be called before the extension is unloaded, because ++// once the last extension which have subscribed a webNavigation event is unloaded ++// all the pending created navigation target data is completely cleared). ++function assertNoPendingCreatedNavigationTargetData() { ++ const {Manager} = Cu.import("resource://gre/modules/WebNavigation.jsm", {}); ++ Assert.equal(Manager.createdNavigationTargetByOuterWindowId.size, 0, ++ "There should be no pending createdNavigationTarget messages in WebNavigation"); ++} diff --git a/www/waterfox/files/patch-bug1403465 b/www/waterfox/files/patch-bug1403465 new file mode 100644 index 000000000000..23ed5a79d30d --- /dev/null +++ b/www/waterfox/files/patch-bug1403465 @@ -0,0 +1,60 @@ +commit f2c88f86dc5b +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Thu Sep 28 10:40:02 2017 +0200 + + Bug 1403465 - style: Avoid creating element data in Servo_ResolvePseudoStyle. r=bholley, a=sledru + + The reason the patch in bug 1402285 doesn't work is that we call this function + multiple times with the same element. This fixes it. + + MozReview-Commit-ID: Ko9zirCOzTR + + --HG-- + extra : transplant_source : qegB%06%15r/%F2%BDm%86%9C%C7%91%06%FA-%1E%A8 +--- + servo/ports/geckolib/glue.rs | 27 +++++++++++++++++---------- + 1 file changed, 17 insertions(+), 10 deletions(-) + +diff --git servo/ports/geckolib/glue.rs servo/ports/geckolib/glue.rs +index 714947fc1812..2f2938f4890b 100644 +--- servo/ports/geckolib/glue.rs ++++ servo/ports/geckolib/glue.rs +@@ -1767,21 +1767,28 @@ pub extern "C" fn Servo_ResolvePseudoStyle(element: RawGeckoElementBorrowed, + -> ServoStyleContextStrong + { + let element = GeckoElement(element); +- let data = unsafe { element.ensure_data() }; + let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow(); + + debug!("Servo_ResolvePseudoStyle: {:?} {:?}, is_probe: {}", + element, PseudoElement::from_pseudo_type(pseudo_type), is_probe); + +- // FIXME(bholley): Assert against this. +- if !data.has_styles() { +- warn!("Calling Servo_ResolvePseudoStyle on unstyled element"); +- return if is_probe { +- Strong::null() +- } else { +- doc_data.default_computed_values().clone().into() +- }; +- } ++ let data = element.borrow_data(); ++ ++ let data = match data.as_ref() { ++ Some(data) if data.has_styles() => data, ++ _ => { ++ // FIXME(bholley, emilio): Assert against this. ++ // ++ // Known offender is nsMathMLmoFrame::MarkIntrinsicISizesDirty, ++ // which goes and does a bunch of work involving style resolution. ++ warn!("Calling Servo_ResolvePseudoStyle on unstyled element"); ++ return if is_probe { ++ Strong::null() ++ } else { ++ doc_data.default_computed_values().clone().into() ++ }; ++ } ++ }; + + let pseudo = PseudoElement::from_pseudo_type(pseudo_type) + .expect("ResolvePseudoStyle with a non-pseudo?"); diff --git a/www/waterfox/files/patch-bug1403466 b/www/waterfox/files/patch-bug1403466 new file mode 100644 index 000000000000..434752911bd1 --- /dev/null +++ b/www/waterfox/files/patch-bug1403466 @@ -0,0 +1,50 @@ +commit 0d4a6317df44 +Author: Mike de Boer <mdeboer@mozilla.com> +Date: Tue Oct 10 12:44:04 2017 +0200 + + Bug 1403466 - Don't set a max-height on panelviews used by WebExtensions, because it causes browser contents to be cut-off. r=Gijs, a=ritu + + Setting a max-height caused the '_handleDOMChange' method in ext-browser-content.js + to consistently lie about the scrollHeight, since it was never allowed to grow + beyond the maxHeight - even when the document needs to be larger to fit its contents. + We don't need this aggressiveness in Photon panels anyway, so that makes it + doubly safe to remove this code. + + MozReview-Commit-ID: HJVMXXHS4By + + --HG-- + extra : source : cd62fb50fe61504937ff3d37db3852bae0d73d0c +--- + browser/components/extensions/ExtensionPopups.jsm | 10 +--------- + 1 file changed, 1 insertion(+), 9 deletions(-) + +diff --git browser/components/extensions/ExtensionPopups.jsm browser/components/extensions/ExtensionPopups.jsm +index 5ac4f43943f1..cc02e48b32dd 100644 +--- browser/components/extensions/ExtensionPopups.jsm ++++ browser/components/extensions/ExtensionPopups.jsm +@@ -123,7 +123,6 @@ class BasePopup { + + if (this.viewNode) { + this.viewNode.removeEventListener(this.DESTROY_EVENT, this); +- this.viewNode.style.maxHeight = ""; + delete this.viewNode.customRectGetter; + } + +@@ -331,16 +330,9 @@ class BasePopup { + height = Math.min(height, maxHeight); + this.browser.style.height = `${height}px`; + +- // Set a maximum height on the <panelview> element to our preferred +- // maximum height, so that the PanelUI resizing code can make an accurate +- // calculation. If we don't do this, the flex sizing logic will prevent us +- // from ever reporting a preferred size smaller than the height currently +- // available to us in the panel. +- height = Math.max(height, this.viewHeight); +- this.viewNode.style.maxHeight = `${height}px`; + // Used by the panelmultiview code to figure out sizing without reparenting + // (which would destroy the browser and break us). +- this.lastCalculatedInViewHeight = height; ++ this.lastCalculatedInViewHeight = Math.max(height, this.viewHeight); + } else { + this.browser.style.width = `${width}px`; + this.browser.style.minWidth = `${width}px`; diff --git a/www/waterfox/files/patch-bug1403473 b/www/waterfox/files/patch-bug1403473 new file mode 100644 index 000000000000..87196f41522a --- /dev/null +++ b/www/waterfox/files/patch-bug1403473 @@ -0,0 +1,27 @@ +commit 3da3e74521d4 (HEAD) +Author: Thomas Nguyen <tnguyen@mozilla.com> +Date: Fri Sep 29 01:46:00 2017 -0400 + + Bug 1403473 - Init loggingEnable for hashcompleter. r=dimi, a=sledru + + MozReview-Commit-ID: 1BpErwmbgCM + + --HG-- + extra : amend_source : 5993fe27195003ac1fa77f89b4d14187cbff591e +--- + toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js +index eac72dadabd3..16b1b7dc7c52 100644 +--- toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js ++++ toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js +@@ -184,6 +184,8 @@ function HashCompleter() { + + Services.obs.addObserver(this, "quit-application"); + Services.prefs.addObserver(PREF_DEBUG_ENABLED, this); ++ ++ loggingEnabled = Services.prefs.getBoolPref(PREF_DEBUG_ENABLED); + } + + HashCompleter.prototype = { diff --git a/www/waterfox/files/patch-bug1403592 b/www/waterfox/files/patch-bug1403592 new file mode 100644 index 000000000000..a716a4fd183e --- /dev/null +++ b/www/waterfox/files/patch-bug1403592 @@ -0,0 +1,157 @@ +commit 79c72166bf05 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Wed Sep 27 18:09:31 2017 +0200 + + Bug 1403592 - Never flush the user font set when getting font metrics from style resolution. r=Manishearth, a=sledru + + In this case, the caller doesn't go through all the PreTraverseSync stuff (we + don't really want it to do so), via GetComputedStyleNoFlush. + + It makes sense to not flush the user font set that case, we'll schedule a + restyle properly if / when needed. + + Since the set should be flushed otherwise, let's just not flush it from the + styling code. + + MozReview-Commit-ID: LLHfxemJ8QQ + + --HG-- + extra : source : 0a0cc4bb885a2487b643e94fc244620751616d03 +--- + layout/style/ServoBindings.cpp | 7 ++++--- + layout/style/nsRuleNode.cpp | 13 ++++++++----- + layout/style/nsRuleNode.h | 8 +++++++- + 3 files changed, 19 insertions(+), 9 deletions(-) + +diff --git layout/style/ServoBindings.cpp layout/style/ServoBindings.cpp +index ac2a6cc2ec01..d248e6ad1401 100644 +--- layout/style/ServoBindings.cpp ++++ layout/style/ServoBindings.cpp +@@ -2482,9 +2482,10 @@ Gecko_GetFontMetrics(RawGeckoPresContextBorrowed aPresContext, + + nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext); + presContext->SetUsesExChUnits(true); +- RefPtr<nsFontMetrics> fm = nsRuleNode::GetMetricsFor(presContext, aIsVertical, +- aFont, aFontSize, +- aUseUserFontSet); ++ RefPtr<nsFontMetrics> fm = nsRuleNode::GetMetricsFor( ++ presContext, aIsVertical, aFont, aFontSize, aUseUserFontSet, ++ nsRuleNode::FlushUserFontSet::No); ++ + ret.mXSize = fm->XHeight(); + gfxFloat zeroWidth = fm->GetThebesFontGroup()->GetFirstValidFont()-> + GetMetrics(fm->Orientation()).zeroOrAveCharWidth; +diff --git layout/style/nsRuleNode.cpp layout/style/nsRuleNode.cpp +index ccccce98009e..fbb5e3824e2f 100644 +--- layout/style/nsRuleNode.cpp ++++ layout/style/nsRuleNode.cpp +@@ -377,7 +377,8 @@ nsRuleNode::GetMetricsFor(nsPresContext* aPresContext, + bool aIsVertical, + const nsStyleFont* aStyleFont, + nscoord aFontSize, +- bool aUseUserFontSet) ++ bool aUseUserFontSet, ++ FlushUserFontSet aFlushUserFontSet) + { + nsFont font = aStyleFont->mFont; + font.size = aFontSize; +@@ -387,8 +388,9 @@ nsRuleNode::GetMetricsFor(nsPresContext* aPresContext, + params.language = aStyleFont->mLanguage; + params.explicitLanguage = aStyleFont->mExplicitLanguage; + params.orientation = orientation; +- params.userFontSet = +- aUseUserFontSet ? aPresContext->GetUserFontSet() : nullptr; ++ params.userFontSet = aUseUserFontSet ++ ? aPresContext->GetUserFontSet(aFlushUserFontSet == FlushUserFontSet::Yes) ++ : nullptr; + params.textPerf = aPresContext->GetTextPerfMetrics(); + return aPresContext->DeviceContext()->GetMetricsFor(font, params); + } +@@ -408,8 +410,9 @@ nsRuleNode::GetMetricsFor(nsPresContext* aPresContext, + isVertical = true; + } + } +- return nsRuleNode::GetMetricsFor(aPresContext, isVertical, aStyleFont, +- aFontSize, aUseUserFontSet); ++ return nsRuleNode::GetMetricsFor( ++ aPresContext, isVertical, aStyleFont, aFontSize, aUseUserFontSet, ++ FlushUserFontSet::Yes); + } + + /* static */ +diff --git layout/style/nsRuleNode.h layout/style/nsRuleNode.h +index 423545ffd198..719eb0c51eb0 100644 +--- layout/style/nsRuleNode.h ++++ layout/style/nsRuleNode.h +@@ -807,11 +807,17 @@ public: + bool aConvertListItem = false); + static void EnsureInlineDisplay(mozilla::StyleDisplay& display); + ++ enum class FlushUserFontSet { ++ Yes, ++ No, ++ }; ++ + static already_AddRefed<nsFontMetrics> GetMetricsFor(nsPresContext* aPresContext, + bool aIsVertical, + const nsStyleFont* aStyleFont, + nscoord aFontSize, +- bool aUseUserFontSet); ++ bool aUseUserFontSet, ++ FlushUserFontSet aFlushUserFontSet); + + static already_AddRefed<nsFontMetrics> GetMetricsFor(nsPresContext* aPresContext, + nsStyleContext* aStyleContext, +commit f01f1d6ac516 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Wed Sep 27 18:16:25 2017 +0200 + + Bug 1403592 - Crashtest. r=Manishearth, a=sledru + + I've made it crash at least once, though it's intermittent-y. I guess it's + better than no crashtest. + + MozReview-Commit-ID: 5m2VCrEs8lM + + --HG-- + extra : source : c050d8574203c0344a9570fef73df51a1a489091 + extra : amend_source : 45265a4fbe7d484fc784c3389f912d45eebf15de +--- + layout/style/crashtests/1403592.html | 19 +++++++++++++++++++ + layout/style/crashtests/crashtests.list | 1 + + 2 files changed, 20 insertions(+) + +diff --git layout/style/crashtests/1403592.html layout/style/crashtests/1403592.html +new file mode 100644 +index 000000000000..fdd810b88603 +--- /dev/null ++++ layout/style/crashtests/1403592.html +@@ -0,0 +1,19 @@ ++<!DOCTYPE html> ++<html class="reftest-wait"> ++<head> ++<style></style> ++<script> ++function boom() { ++ a = document.createElement("x") ++ a.style.overflow = "o" ++ document.styleSheets[0].insertRule("i {}", 0) ++ requestIdleCallback(function() { ++ document.documentElement.className = ""; ++ }); ++} ++requestIdleCallback(boom) ++</script> ++</head> ++<i id=id0 style="margin: 15ch"> ++<svg><animate xlink:href=#id0 attributeName=width to></svg> ++</html> +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index 565abf6c1f83..e811e54554b3 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -204,3 +204,4 @@ load 1391577.html + load 1398581.html + load 1402218-1.html + load 1402366.html ++load 1403592.html diff --git a/www/waterfox/files/patch-bug1403721 b/www/waterfox/files/patch-bug1403721 new file mode 100644 index 000000000000..6459c0894087 --- /dev/null +++ b/www/waterfox/files/patch-bug1403721 @@ -0,0 +1,182 @@ +commit 637bcd0503db +Author: Tom Schuster <evilpies@gmail.com> +Date: Thu Sep 28 12:46:09 2017 +0200 + + Bug 1403723 - Correct metadata when using management.get. r=mixedpuppy, a=ritu + * * * + Bug 1403721 - Limit management.get to allowed addon types. r=mixedpuppy +--- + toolkit/components/extensions/ext-management.js | 36 ++++++++++++++-------- + .../test/xpcshell/test_ext_experiments.js | 25 +++++++++++++++ + .../test/xpcshell/test_ext_management.js | 8 +++++ + .../mozapps/extensions/internal/XPIProvider.jsm | 4 +++ + 4 files changed, 61 insertions(+), 12 deletions(-) + +diff --git toolkit/components/extensions/ext-management.js toolkit/components/extensions/ext-management.js +index 0e46732b201d..d86a15ceb6a1 100644 +--- toolkit/components/extensions/ext-management.js ++++ toolkit/components/extensions/ext-management.js +@@ -91,6 +91,16 @@ const listenerMap = new WeakMap(); + // Some management APIs are intentionally limited. + const allowedTypes = ["theme", "extension"]; + ++function checkAllowedAddon(addon) { ++ if (addon.isSystem || addon.isAPIExtension) { ++ return false; ++ } ++ if (addon.type == "extension" && !addon.isWebExtension) { ++ return false; ++ } ++ return allowedTypes.includes(addon.type); ++} ++ + class AddonListener { + constructor() { + AddonManager.addAddonListener(this); +@@ -106,33 +116,29 @@ class AddonListener { + return getExtensionInfoForAddon(ext, addon); + } + +- checkAllowed(addon) { +- return !addon.isSystem && allowedTypes.includes(addon.type); +- } +- + onEnabled(addon) { +- if (!this.checkAllowed(addon)) { ++ if (!checkAllowedAddon(addon)) { + return; + } + this.emit("onEnabled", this.getExtensionInfo(addon)); + } + + onDisabled(addon) { +- if (!this.checkAllowed(addon)) { ++ if (!checkAllowedAddon(addon)) { + return; + } + this.emit("onDisabled", this.getExtensionInfo(addon)); + } + + onInstalled(addon) { +- if (!this.checkAllowed(addon)) { ++ if (!checkAllowedAddon(addon)) { + return; + } + this.emit("onInstalled", this.getExtensionInfo(addon)); + } + + onUninstalled(addon) { +- if (!this.checkAllowed(addon)) { ++ if (!checkAllowedAddon(addon)) { + return; + } + this.emit("onUninstalled", this.getExtensionInfo(addon)); +@@ -167,16 +173,22 @@ this.management = class extends ExtensionAPI { + management: { + async get(id) { + let addon = await AddonManager.getAddonByID(id); +- if (!addon.isSystem) { +- return getExtensionInfoForAddon(extension, addon); ++ if (!addon) { ++ throw new ExtensionError(`No such addon ${id}`); ++ } ++ if (!checkAllowedAddon(addon)) { ++ throw new ExtensionError("get not allowed for this addon"); + } ++ // If the extension is enabled get it and use it for more data. ++ let ext = GlobalManager.extensionMap.get(addon.id); ++ return getExtensionInfoForAddon(ext, addon); + }, + + async getAll() { + let addons = await AddonManager.getAddonsByTypes(allowedTypes); +- return addons.filter(addon => !addon.isSystem).map(addon => { ++ return addons.filter(checkAllowedAddon).map(addon => { + // If the extension is enabled get it and use it for more data. +- let ext = addon.isWebExtension && GlobalManager.extensionMap.get(addon.id); ++ let ext = GlobalManager.extensionMap.get(addon.id); + return getExtensionInfoForAddon(ext, addon); + }); + }, +diff --git toolkit/components/extensions/test/xpcshell/test_ext_experiments.js toolkit/components/extensions/test/xpcshell/test_ext_experiments.js +index 343e1e50d983..c8d097decf90 100644 +--- toolkit/components/extensions/test/xpcshell/test_ext_experiments.js ++++ toolkit/components/extensions/test/xpcshell/test_ext_experiments.js +@@ -148,6 +148,31 @@ add_task(async function test_experiments_api() { + let hello = await promise; + equal(hello, "Here I am", "Should get hello from add-on"); + ++ // Install management test add-on. ++ let managementAddon = ExtensionTestUtils.loadExtension({ ++ manifest: { ++ applications: {gecko: {id: "management@web.extension"}}, ++ permissions: ["management"], ++ }, ++ async background() { ++ // Should find the simple extension. ++ let normalAddon = await browser.management.get("boring@web.extension"); ++ browser.test.assertEq(normalAddon.id, "boring@web.extension", "Found boring addon"); ++ ++ try { ++ // Not allowed to get the API experiment. ++ await browser.management.get("fooBar@experiments.addons.mozilla.org"); ++ } catch (e) { ++ browser.test.sendMessage("done"); ++ } ++ }, ++ useAddonManager: "temporary", ++ }); ++ ++ await managementAddon.startup(); ++ await managementAddon.awaitMessage("done"); ++ await managementAddon.unload(); ++ + // Cleanup. + apiAddon.uninstall(); + +diff --git toolkit/components/extensions/test/xpcshell/test_ext_management.js toolkit/components/extensions/test/xpcshell/test_ext_management.js +index c1702042c054..975c14a566e4 100644 +--- toolkit/components/extensions/test/xpcshell/test_ext_management.js ++++ toolkit/components/extensions/test/xpcshell/test_ext_management.js +@@ -22,6 +22,7 @@ add_task(async function test_management_getAll() { + }, + name: id, + version: "1.0", ++ short_name: id, + permissions: ["management"], + }; + } +@@ -55,11 +56,18 @@ add_task(async function test_management_getAll() { + for (let id of [id1, id2]) { + let addon = addons.find(a => { return a.id === id; }); + equal(addon.name, id, `The extension with id ${id} was returned by getAll.`); ++ equal(addon.shortName, id, "Additional extension metadata was correct"); + } + + extension2.sendMessage("getAddon", id1); + let addon = await extension2.awaitMessage("addon"); + equal(addon.name, id1, `The extension with id ${id1} was returned by get.`); ++ equal(addon.shortName, id1, "Additional extension metadata was correct"); ++ ++ extension2.sendMessage("getAddon", id2); ++ addon = await extension2.awaitMessage("addon"); ++ equal(addon.name, id2, `The extension with id ${id2} was returned by get.`); ++ equal(addon.shortName, id2, "Additional extension metadata was correct"); + + await extension2.unload(); + await extension1.unload(); +diff --git toolkit/mozapps/extensions/internal/XPIProvider.jsm toolkit/mozapps/extensions/internal/XPIProvider.jsm +index 0027e13e3804..56f3982e7214 100644 +--- toolkit/mozapps/extensions/internal/XPIProvider.jsm ++++ toolkit/mozapps/extensions/internal/XPIProvider.jsm +@@ -5197,6 +5197,10 @@ AddonWrapper.prototype = { + return isWebExtension(addonFor(this).type); + }, + ++ get isAPIExtension() { ++ return addonFor(this).type == "apiextension"; ++ }, ++ + get temporarilyInstalled() { + return addonFor(this)._installLocation == TemporaryInstallLocation; + }, diff --git a/www/waterfox/files/patch-bug1403998 b/www/waterfox/files/patch-bug1403998 new file mode 100644 index 000000000000..585198482647 --- /dev/null +++ b/www/waterfox/files/patch-bug1403998 @@ -0,0 +1,167 @@ +commit b5254d352036 +Author: Honza Bambas <honzab.moz@firemni.cz> +Date: Mon Oct 2 10:12:00 2017 -0400 + + Bug 1403998 - Make view-source channels return correct resultPrincipalURI via LoadInfo after redirect. r=bz, a=ritu + + --HG-- + extra : source : f693bf1345f941592b1ce19514a2bbf00e6ef06a +--- + .../protocol/viewsource/nsViewSourceChannel.cpp | 95 ++++++++++++++++++---- + netwerk/protocol/viewsource/nsViewSourceChannel.h | 10 +++ + 2 files changed, 91 insertions(+), 14 deletions(-) + +diff --git netwerk/protocol/viewsource/nsViewSourceChannel.cpp netwerk/protocol/viewsource/nsViewSourceChannel.cpp +index 4c7f335352d3..1f1ee01818fb 100644 +--- netwerk/protocol/viewsource/nsViewSourceChannel.cpp ++++ netwerk/protocol/viewsource/nsViewSourceChannel.cpp +@@ -129,12 +129,87 @@ nsViewSourceChannel::InitSrcdoc(nsIURI* aURI, + mApplicationCacheChannel = do_QueryInterface(mChannel); + mUploadChannel = do_QueryInterface(mChannel); + ++ rv = UpdateLoadInfoResultPrincipalURI(); ++ NS_ENSURE_SUCCESS(rv, rv); ++ + nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(mChannel); + MOZ_ASSERT(isc); + isc->SetBaseURI(aBaseURI); + return NS_OK; + } + ++nsresult ++nsViewSourceChannel::UpdateLoadInfoResultPrincipalURI() ++{ ++ nsresult rv; ++ ++ MOZ_ASSERT(mChannel); ++ ++ nsCOMPtr<nsILoadInfo> channelLoadInfo = mChannel->GetLoadInfo(); ++ if (!channelLoadInfo) { ++ return NS_OK; ++ } ++ ++ nsCOMPtr<nsIURI> channelResultPrincipalURI; ++ rv = channelLoadInfo->GetResultPrincipalURI(getter_AddRefs(channelResultPrincipalURI)); ++ if (NS_FAILED(rv)) { ++ return rv; ++ } ++ ++ if (!channelResultPrincipalURI) { ++ mChannel->GetOriginalURI(getter_AddRefs(channelResultPrincipalURI)); ++ return NS_OK; ++ } ++ ++ if (!channelResultPrincipalURI) { ++ return NS_ERROR_UNEXPECTED; ++ } ++ ++ bool alreadyViewSource; ++ if (NS_SUCCEEDED(channelResultPrincipalURI->SchemeIs("view-source", &alreadyViewSource)) && ++ alreadyViewSource) { ++ return NS_OK; ++ } ++ ++ nsCOMPtr<nsIURI> updatedResultPrincipalURI; ++ rv = BuildViewSourceURI(channelResultPrincipalURI, ++ getter_AddRefs(updatedResultPrincipalURI)); ++ if (NS_FAILED(rv)) { ++ return rv; ++ } ++ ++ rv = channelLoadInfo->SetResultPrincipalURI(updatedResultPrincipalURI); ++ if (NS_FAILED(rv)) { ++ return rv; ++ } ++ ++ return NS_OK; ++} ++ ++nsresult ++nsViewSourceChannel::BuildViewSourceURI(nsIURI * aURI, nsIURI ** aResult) ++{ ++ nsresult rv; ++ ++ // protect ourselves against broken channel implementations ++ if (!aURI) { ++ NS_ERROR("no URI to build view-source uri!"); ++ return NS_ERROR_UNEXPECTED; ++ } ++ ++ nsAutoCString spec; ++ rv = aURI->GetSpec(spec); ++ if (NS_FAILED(rv)) { ++ return rv; ++ } ++ ++ return NS_NewURI(aResult, ++ /* XXX Gross hack -- NS_NewURI goes into an infinite loop on ++ non-flat specs. See bug 136980 */ ++ nsAutoCString(NS_LITERAL_CSTRING("view-source:") + spec), ++ nullptr); ++} ++ + //////////////////////////////////////////////////////////////////////////////// + // nsIRequest methods: + +@@ -229,24 +304,11 @@ nsViewSourceChannel::GetURI(nsIURI* *aURI) + + nsCOMPtr<nsIURI> uri; + nsresult rv = mChannel->GetURI(getter_AddRefs(uri)); +- if (NS_FAILED(rv)) +- return rv; +- +- // protect ourselves against broken channel implementations +- if (!uri) { +- NS_ERROR("inner channel returned NS_OK and a null URI"); +- return NS_ERROR_UNEXPECTED; +- } +- +- nsAutoCString spec; +- rv = uri->GetSpec(spec); + if (NS_FAILED(rv)) { + return rv; + } + +- /* XXX Gross hack -- NS_NewURI goes into an infinite loop on +- non-flat specs. See bug 136980 */ +- return NS_NewURI(aURI, nsAutoCString(NS_LITERAL_CSTRING("view-source:")+spec), nullptr); ++ return BuildViewSourceURI(uri, aURI); + } + + NS_IMETHODIMP +@@ -671,6 +733,11 @@ nsViewSourceChannel::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) + mCacheInfoChannel = do_QueryInterface(mChannel); + mUploadChannel = do_QueryInterface(aRequest); + ++ nsresult rv = UpdateLoadInfoResultPrincipalURI(); ++ if (NS_FAILED(rv)) { ++ Cancel(rv); ++ } ++ + return mListener->OnStartRequest(static_cast<nsIViewSourceChannel*> + (this), + aContext); +diff --git netwerk/protocol/viewsource/nsViewSourceChannel.h netwerk/protocol/viewsource/nsViewSourceChannel.h +index 002739b361f7..1970c01588e3 100644 +--- netwerk/protocol/viewsource/nsViewSourceChannel.h ++++ netwerk/protocol/viewsource/nsViewSourceChannel.h +@@ -55,9 +55,19 @@ public: + const nsAString &aSrcdoc, + nsILoadInfo* aLoadInfo); + ++ // Updates or sets the result principal URI of the underlying channel's ++ // loadinfo to be prefixed with the "view-source:" schema as: ++ // ++ // mChannel.loadInfo.resultPrincipalURI = "view-source:" + ++ // (mChannel.loadInfo.resultPrincipalURI | mChannel.orignalURI); ++ nsresult UpdateLoadInfoResultPrincipalURI(); ++ + protected: + ~nsViewSourceChannel() {} + ++ // Clones aURI and prefixes it with "view-source:" schema, ++ nsresult BuildViewSourceURI(nsIURI* aURI, nsIURI** aResult); ++ + nsCOMPtr<nsIChannel> mChannel; + nsCOMPtr<nsIHttpChannel> mHttpChannel; + nsCOMPtr<nsIHttpChannelInternal> mHttpChannelInternal; diff --git a/www/waterfox/files/patch-bug1404057 b/www/waterfox/files/patch-bug1404057 new file mode 100644 index 000000000000..e82bafd8ba75 --- /dev/null +++ b/www/waterfox/files/patch-bug1404057 @@ -0,0 +1,139 @@ +commit 52f5824f49d0 +Author: Manish Goregaokar <manishsmail@gmail.com> +Date: Wed Oct 4 20:57:24 2017 -0500 + + Bug 1404057 - stylo: `all` shorthand should not apply to internal properties. r=xidorn, a=ritu + + Source-Repo: https://github.com/servo/servo + Source-Revision: 43686a8738513db728eebcc535b5ac6e1a2f17f7 +--- + servo/components/style/properties/properties.mako.rs | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git servo/components/style/properties/properties.mako.rs servo/components/style/properties/properties.mako.rs +index 13dd6212fe1a..269bf0dbbbb5 100644 +--- servo/components/style/properties/properties.mako.rs ++++ servo/components/style/properties/properties.mako.rs +@@ -217,7 +217,9 @@ pub mod shorthands { + // We don't defined the 'all' shorthand using the regular helpers:shorthand + // mechanism, since it causes some very large types to be generated. + <% data.declare_shorthand("all", +- [p.name for p in data.longhands if p.name not in ['direction', 'unicode-bidi']], ++ [p.name for p in data.longhands ++ if p.name not in ['direction', 'unicode-bidi'] ++ and not p.internal], + spec="https://drafts.csswg.org/css-cascade-3/#all-shorthand") %> + } + +commit ff25959d0893 +Author: Manish Goregaokar <manishearth@gmail.com> +Date: Mon Oct 2 18:53:19 2017 -0700 + + Bug 1404057 - stylo: Add crashtest for text-zoom being reenabled within svg:text. r=xidorn, a=ritu + + MozReview-Commit-ID: 3dIDW8Tz6Mj +--- + layout/style/crashtests/1404057.html | 6 ++++++ + layout/style/crashtests/crashtests.list | 1 + + 2 files changed, 7 insertions(+) + +diff --git layout/style/crashtests/1404057.html layout/style/crashtests/1404057.html +new file mode 100644 +index 000000000000..4c4a33ce495d +--- /dev/null ++++ layout/style/crashtests/1404057.html +@@ -0,0 +1,6 @@ ++<html> ++ <title>Testcase, bug 143862</title> ++ <head> ++<svg><text><t style='all:initial'>aaa</t></text></svg> ++ </head> ++</html> +\ No newline at end of file +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index 5eaba6935ee2..70e240d14e2f 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -205,3 +205,4 @@ asserts-if(stylo,1) load 1404324-1.html # bug 1405605 + load 1387499.html + load 1391577.html + load 1398581.html ++load 1404057.html +commit c883f59323fd +Author: Manish Goregaokar <manishearth@gmail.com> +Date: Tue Oct 3 08:30:34 2017 -0700 + + Bug 1404057 - stylo: Add reftest for ensuring lang is not reset by the `all` shorthand. r=xidorn, a=ritu + + MozReview-Commit-ID: HgjJDwUM6Ju +--- + layout/reftests/bugs/1404057-noref.html | 12 ++++++++++++ + layout/reftests/bugs/1404057-ref.html | 12 ++++++++++++ + layout/reftests/bugs/1404057.html | 12 ++++++++++++ + layout/reftests/bugs/reftest.list | 2 ++ + 4 files changed, 38 insertions(+) + +diff --git layout/reftests/bugs/1404057-noref.html layout/reftests/bugs/1404057-noref.html +new file mode 100644 +index 000000000000..dc734b6b1f5e +--- /dev/null ++++ layout/reftests/bugs/1404057-noref.html +@@ -0,0 +1,12 @@ ++<!DOCTYPE html> ++<meta charset="UTF-8"> ++<style> ++ div { ++ height: 2em; ++ } ++</style> ++<body> ++ <div lang="ja">令</div> ++ <div lang="ja">令</div> ++ <div lang="ja">令</div> ++</body> +diff --git layout/reftests/bugs/1404057-ref.html layout/reftests/bugs/1404057-ref.html +new file mode 100644 +index 000000000000..3c06958591be +--- /dev/null ++++ layout/reftests/bugs/1404057-ref.html +@@ -0,0 +1,12 @@ ++<!DOCTYPE html> ++<meta charset="UTF-8"> ++<style> ++ div { ++ height: 2em; ++ } ++</style> ++<body> ++ <div lang="zh-CN">令</div> ++ <div lang="ja">令</div> ++ <div lang="ja">令</div> ++</body> +diff --git layout/reftests/bugs/1404057.html layout/reftests/bugs/1404057.html +new file mode 100644 +index 000000000000..3a9e3af26a25 +--- /dev/null ++++ layout/reftests/bugs/1404057.html +@@ -0,0 +1,12 @@ ++<!DOCTYPE html> ++<meta charset="UTF-8"> ++<style> ++ div { ++ height: 2em; ++ } ++</style> ++<body lang="zh-CN"> ++ <div>令</div> ++ <div lang="ja">令</div> ++ <div><div lang="ja" style="all: inherit">令</div></div> ++</body> +diff --git layout/reftests/bugs/reftest.list layout/reftests/bugs/reftest.list +index 679672b8c24b..52f8cb915cee 100644 +--- layout/reftests/bugs/reftest.list ++++ layout/reftests/bugs/reftest.list +@@ -2037,3 +2037,5 @@ needs-focus != 1377447-1.html 1377447-2.html + == 1380224-1.html 1380224-1-ref.html + == 1384065.html 1384065-ref.html + == 1384275-1.html 1384275-1-ref.html ++== 1404057.html 1404057-ref.html ++!= 1404057.html 1404057-noref.html diff --git a/www/waterfox/files/patch-bug1404180 b/www/waterfox/files/patch-bug1404180 new file mode 100644 index 000000000000..87ad2b6c5382 --- /dev/null +++ b/www/waterfox/files/patch-bug1404180 @@ -0,0 +1,68 @@ +commit 5d2f7f4ae8d8 +Author: Cameron McCormack <cam@mcc.id.au> +Date: Mon Oct 2 13:10:18 2017 +0800 + + Bug 1404180 - Don't allow associating form elements by ID to <form>s across anonymous subtree boundaries. r=smaug, a=ritu + + MozReview-Commit-ID: KRJjrkL4FgZ + + --HG-- + extra : source : 123004932443033cc9490e80d52c827d60079c65 +--- + dom/html/nsGenericHTMLElement.cpp | 4 +++- + layout/style/crashtests/1404180-1.html | 22 ++++++++++++++++++++++ + layout/style/crashtests/crashtests.list | 1 + + 3 files changed, 26 insertions(+), 1 deletion(-) + +diff --git dom/html/nsGenericHTMLElement.cpp dom/html/nsGenericHTMLElement.cpp +index eda85c9eebaf..54041d7bf071 100644 +--- dom/html/nsGenericHTMLElement.cpp ++++ dom/html/nsGenericHTMLElement.cpp +@@ -2319,7 +2319,9 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree, + "element should be equals to the current element " + "associated with the id in @form!"); + +- if (element && element->IsHTMLElement(nsGkAtoms::form)) { ++ if (element && ++ element->IsHTMLElement(nsGkAtoms::form) && ++ nsContentUtils::IsInSameAnonymousTree(this, element)) { + SetForm(static_cast<HTMLFormElement*>(element), aBindToTree); + } + } +diff --git layout/style/crashtests/1404180-1.html layout/style/crashtests/1404180-1.html +new file mode 100644 +index 000000000000..079d6800f55f +--- /dev/null ++++ layout/style/crashtests/1404180-1.html +@@ -0,0 +1,22 @@ ++<script> ++function jsfuzzer() { ++ try { htmlvar00016.appendChild(htmlvar00017); } catch(e) { } ++ try { htmlvar00016.form.setAttribute("novalidate", "novalidate"); } catch(e) { } ++ try { htmlvar00017.appendChild(htmlvar00036); } catch(e) { } ++ try { svgvar00007.appendChild(htmlvar00008); } catch(e) { } ++} ++</script> ++<body onload=jsfuzzer()> ++<form id="htmlvar00007"> ++<legend id="htmlvar00008"> ++<output id="htmlvar00016"></output> ++</legend> ++<link id="htmlvar00017"></link> ++<svg> ++<path id="svgvar00006"> ++<animateTransform id="svgvar00007"/> ++</path> ++<use xlink:href="#svgvar00006"> ++<table id="htmlvar00036"> ++<th> ++<output form="htmlvar00007"> +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index d75d5559ec2b..be9a46c52bfa 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -206,3 +206,4 @@ load 1404324-2.html + load 1404324-3.html + load 1398581.html + load 1404057.html ++load 1404180-1.html diff --git a/www/waterfox/files/patch-bug1404323 b/www/waterfox/files/patch-bug1404323 new file mode 100644 index 000000000000..20adb23c2c44 --- /dev/null +++ b/www/waterfox/files/patch-bug1404323 @@ -0,0 +1,27 @@ +commit f9c6b4c7459c +Author: Lee Salzman <lsalzman@mozilla.com> +Date: Fri Sep 29 23:59:40 2017 -0400 + + Bug 1404323 - Limit WindowSurfaceX11Image::Commit to clip bounds. r=gankro, a=ritu + + MozReview-Commit-ID: 55GbZ2EHdbQ + + --HG-- + extra : source : 19c2892e7a3ad24b6d235948ef514b20e216b57d +--- + widget/gtk/WindowSurfaceX11Image.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git widget/gtk/WindowSurfaceX11Image.cpp widget/gtk/WindowSurfaceX11Image.cpp +index 5de0288043d6..59db17b642f2 100644 +--- widget/gtk/WindowSurfaceX11Image.cpp ++++ widget/gtk/WindowSurfaceX11Image.cpp +@@ -93,7 +93,7 @@ WindowSurfaceX11Image::Commit(const LayoutDeviceIntRegion& aInvalidRegion) + } + + gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect(); +- gfx::Rect rect(0, 0, bounds.XMost(), bounds.YMost()); ++ gfx::Rect rect(bounds); + if (rect.IsEmpty()) { + return; + } diff --git a/www/waterfox/files/patch-bug1404324 b/www/waterfox/files/patch-bug1404324 new file mode 100644 index 000000000000..afcbc3efb2ec --- /dev/null +++ b/www/waterfox/files/patch-bug1404324 @@ -0,0 +1,299 @@ +commit 5647dde295f4 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Wed Oct 4 11:36:20 2017 +0200 + + Bug 1404324 - Use the placeholder state to remove out-of-flows that aren't real descendants of the destruction root. r=bz, a=ritu + + Using the style of the frame can mess things up when we reparent them due to + ::first-line before removing them. + + MozReview-Commit-ID: 3Dt0wF2XRAH + + --HG-- + extra : source : 5a034cdb513208dd19adf0babf30ee734968a78f + extra : histedit_source : 4cd958939c5a76e013695e931d721454268a0dc7%2C96bdeda302c567493c7db5105f306595d25332e1 +--- + layout/base/nsCSSFrameConstructor.cpp | 8 +++--- + layout/base/nsLayoutUtils.cpp | 46 +++------------------------------ + layout/generic/nsPlaceholderFrame.cpp | 27 ++++++++++++++++--- + layout/generic/nsPlaceholderFrame.h | 21 ++++++++------- + layout/style/crashtests/1404324-1.html | 12 +++++++++ + layout/style/crashtests/1404324-2.html | 10 +++++++ + layout/style/crashtests/1404324-3.html | 14 ++++++++++ + layout/style/crashtests/crashtests.list | 3 +++ + 8 files changed, 83 insertions(+), 58 deletions(-) + +diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp +index c840416fd6a7..99b1211b399b 100644 +--- layout/base/nsCSSFrameConstructor.cpp ++++ layout/base/nsCSSFrameConstructor.cpp +@@ -1260,8 +1260,10 @@ nsFrameConstructorState::GetOutOfFlowFrameItems(nsIFrame* aNewFrame, + if (disp->mTopLayer != NS_STYLE_TOP_LAYER_NONE) { + *aPlaceholderType = PLACEHOLDER_FOR_TOPLAYER; + if (disp->mPosition == NS_STYLE_POSITION_FIXED) { ++ *aPlaceholderType |= PLACEHOLDER_FOR_FIXEDPOS; + return &mTopLayerFixedItems; + } ++ *aPlaceholderType |= PLACEHOLDER_FOR_ABSPOS; + return &mTopLayerAbsoluteItems; + } + if (disp->mPosition == NS_STYLE_POSITION_ABSOLUTE) { +@@ -1303,11 +1305,11 @@ nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent, + nsAbsoluteItems* frameItems = GetOutOfFlowFrameItems(backdropFrame, + true, true, false, + &placeholderType); +- MOZ_ASSERT(placeholderType == PLACEHOLDER_FOR_TOPLAYER); ++ MOZ_ASSERT(placeholderType & PLACEHOLDER_FOR_TOPLAYER); + + nsIFrame* placeholder = nsCSSFrameConstructor:: + CreatePlaceholderFrameFor(mPresShell, aContent, backdropFrame, +- frame, nullptr, PLACEHOLDER_FOR_TOPLAYER); ++ frame, nullptr, placeholderType); + nsFrameList temp(placeholder, placeholder); + frame->SetInitialChildList(nsIFrame::kBackdropList, temp); + +@@ -1361,7 +1363,7 @@ nsFrameConstructorState::AddChild(nsIFrame* aNewFrame, + // Add the placeholder frame to the flow + aFrameItems.AddChild(placeholderFrame); + +- if (placeholderType == PLACEHOLDER_FOR_TOPLAYER) { ++ if (placeholderType & PLACEHOLDER_FOR_TOPLAYER) { + ConstructBackdropFrameFor(aContent, aNewFrame); + } + } +diff --git layout/base/nsLayoutUtils.cpp layout/base/nsLayoutUtils.cpp +index cb010c0a1a80..94ead9830c25 100644 +--- layout/base/nsLayoutUtils.cpp ++++ layout/base/nsLayoutUtils.cpp +@@ -1525,6 +1525,8 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame) + { + nsIFrame::ChildListID id = nsIFrame::kPrincipalList; + ++ MOZ_DIAGNOSTIC_ASSERT(!(aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)); ++ + if (aChildFrame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) { + nsIFrame* pif = aChildFrame->GetPrevInFlow(); + if (pif->GetParent() == aChildFrame->GetParent()) { +@@ -1533,35 +1535,6 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame) + else { + id = nsIFrame::kOverflowContainersList; + } +- } +- // See if the frame is moved out of the flow +- else if (aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) { +- // Look at the style information to tell +- const nsStyleDisplay* disp = aChildFrame->StyleDisplay(); +- +- if (NS_STYLE_POSITION_ABSOLUTE == disp->mPosition) { +- id = nsIFrame::kAbsoluteList; +- } else if (NS_STYLE_POSITION_FIXED == disp->mPosition) { +- if (nsLayoutUtils::IsReallyFixedPos(aChildFrame)) { +- id = nsIFrame::kFixedList; +- } else { +- id = nsIFrame::kAbsoluteList; +- } +-#ifdef MOZ_XUL +- } else if (StyleDisplay::MozPopup == disp->mDisplay) { +- // Out-of-flows that are DISPLAY_POPUP must be kids of the root popup set +-#ifdef DEBUG +- nsIFrame* parent = aChildFrame->GetParent(); +- NS_ASSERTION(parent && parent->IsPopupSetFrame(), "Unexpected parent"); +-#endif // DEBUG +- +- id = nsIFrame::kPopupList; +-#endif // MOZ_XUL +- } else { +- NS_ASSERTION(aChildFrame->IsFloating(), "not a floated frame"); +- id = nsIFrame::kFloatList; +- } +- + } else { + LayoutFrameType childType = aChildFrame->Type(); + if (LayoutFrameType::MenuPopup == childType) { +@@ -1596,19 +1569,8 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame) + nsContainerFrame* parent = aChildFrame->GetParent(); + bool found = parent->GetChildList(id).ContainsFrame(aChildFrame); + if (!found) { +- if (!(aChildFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) { +- found = parent->GetChildList(nsIFrame::kOverflowList) +- .ContainsFrame(aChildFrame); +- } +- else if (aChildFrame->IsFloating()) { +- found = parent->GetChildList(nsIFrame::kOverflowOutOfFlowList) +- .ContainsFrame(aChildFrame); +- if (!found) { +- found = parent->GetChildList(nsIFrame::kPushedFloatsList) +- .ContainsFrame(aChildFrame); +- } +- } +- // else it's positioned and should have been on the 'id' child list. ++ found = parent->GetChildList(nsIFrame::kOverflowList) ++ .ContainsFrame(aChildFrame); + NS_POSTCONDITION(found, "not in child list"); + } + #endif +diff --git layout/generic/nsPlaceholderFrame.cpp layout/generic/nsPlaceholderFrame.cpp +index 7da2582ae526..4b2e1bf84b36 100644 +--- layout/generic/nsPlaceholderFrame.cpp ++++ layout/generic/nsPlaceholderFrame.cpp +@@ -25,9 +25,9 @@ using namespace mozilla::gfx; + + nsIFrame* + NS_NewPlaceholderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, +- nsFrameState aTypeBit) ++ nsFrameState aTypeBits) + { +- return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBit); ++ return new (aPresShell) nsPlaceholderFrame(aContext, aTypeBits); + } + + NS_IMPL_FRAMEARENA_HELPERS(nsPlaceholderFrame) +@@ -155,6 +155,26 @@ nsPlaceholderFrame::Reflow(nsPresContext* aPresContext, + NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize); + } + ++static nsIFrame::ChildListID ++ChildListIDForOutOfFlow(nsFrameState aPlaceholderState, nsIFrame* aChild) ++{ ++ if (aPlaceholderState & PLACEHOLDER_FOR_FLOAT) { ++ return nsIFrame::kFloatList; ++ } ++ if (aPlaceholderState & PLACEHOLDER_FOR_POPUP) { ++ return nsIFrame::kPopupList; ++ } ++ if (aPlaceholderState & PLACEHOLDER_FOR_FIXEDPOS) { ++ return nsLayoutUtils::IsReallyFixedPos(aChild) ++ ? nsIFrame::kFixedList : nsIFrame::kAbsoluteList; ++ } ++ if (aPlaceholderState & PLACEHOLDER_FOR_ABSPOS) { ++ return nsIFrame::kAbsoluteList; ++ } ++ MOZ_DIAGNOSTIC_ASSERT(false, "unknown list"); ++ return nsIFrame::kFloatList; ++} ++ + void + nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot) + { +@@ -162,12 +182,13 @@ nsPlaceholderFrame::DestroyFrom(nsIFrame* aDestructRoot) + if (oof) { + mOutOfFlowFrame = nullptr; + oof->DeleteProperty(nsIFrame::PlaceholderFrameProperty()); ++ + // If aDestructRoot is not an ancestor of the out-of-flow frame, + // then call RemoveFrame on it here. + // Also destroy it here if it's a popup frame. (Bug 96291) + if ((GetStateBits() & PLACEHOLDER_FOR_POPUP) || + !nsLayoutUtils::IsProperAncestorFrame(aDestructRoot, oof)) { +- ChildListID listId = nsLayoutUtils::GetChildListNameFor(oof); ++ ChildListID listId = ChildListIDForOutOfFlow(GetStateBits(), oof); + nsFrameManager* fm = PresContext()->GetPresShell()->FrameManager(); + fm->RemoveFrame(listId, oof); + } +diff --git layout/generic/nsPlaceholderFrame.h layout/generic/nsPlaceholderFrame.h +index e270c76cdd31..2af9b4ccbc93 100644 +--- layout/generic/nsPlaceholderFrame.h ++++ layout/generic/nsPlaceholderFrame.h +@@ -40,7 +40,7 @@ + + nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell, + nsStyleContext* aContext, +- nsFrameState aTypeBit); ++ nsFrameState aTypeBits); + + #define PLACEHOLDER_TYPE_MASK (PLACEHOLDER_FOR_FLOAT | \ + PLACEHOLDER_FOR_ABSPOS | \ +@@ -65,18 +65,19 @@ public: + */ + friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell, + nsStyleContext* aContext, +- nsFrameState aTypeBit); +- nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBit) ++ nsFrameState aTypeBits); ++ nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBits) + : nsFrame(aContext, kClassID) + , mOutOfFlowFrame(nullptr) + { +- NS_PRECONDITION(aTypeBit == PLACEHOLDER_FOR_FLOAT || +- aTypeBit == PLACEHOLDER_FOR_ABSPOS || +- aTypeBit == PLACEHOLDER_FOR_FIXEDPOS || +- aTypeBit == PLACEHOLDER_FOR_POPUP || +- aTypeBit == PLACEHOLDER_FOR_TOPLAYER, +- "Unexpected type bit"); +- AddStateBits(aTypeBit); ++ MOZ_ASSERT(aTypeBits == PLACEHOLDER_FOR_FLOAT || ++ aTypeBits == PLACEHOLDER_FOR_ABSPOS || ++ aTypeBits == PLACEHOLDER_FOR_FIXEDPOS || ++ aTypeBits == PLACEHOLDER_FOR_POPUP || ++ aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_ABSPOS) || ++ aTypeBits == (PLACEHOLDER_FOR_TOPLAYER | PLACEHOLDER_FOR_FIXEDPOS), ++ "Unexpected type bit"); ++ AddStateBits(aTypeBits); + } + + // Get/Set the associated out of flow frame +diff --git layout/style/crashtests/1404324-1.html layout/style/crashtests/1404324-1.html +new file mode 100644 +index 000000000000..574a5437cb1b +--- /dev/null ++++ layout/style/crashtests/1404324-1.html +@@ -0,0 +1,12 @@ ++<style></style> ++<script> ++document.documentElement.className = 'c1' ++o1 = document.createElement('form') ++o2 = document.createElement('e') ++o1.className = 'c2' ++document.documentElement.appendChild(o1) ++document.documentElement.appendChild(o2) ++document.styleSheets[0].insertRule('.c1:first-line, .c2 { position:fixed', 0); ++document.documentElement.getBoundingClientRect() ++document.styleSheets[0].cssRules[0].style.position = 'relative' ++</script> +diff --git layout/style/crashtests/1404324-2.html layout/style/crashtests/1404324-2.html +new file mode 100644 +index 000000000000..797347d5c058 +--- /dev/null ++++ layout/style/crashtests/1404324-2.html +@@ -0,0 +1,10 @@ ++<style> ++ del, *::first-line { ++ position: absolute; ++ } ++</style> ++<del></del> ++<script> ++ document.documentElement.offsetTop; ++ document.styleSheets[0].cssRules[0].style.position = 'sticky' ++</script> +diff --git layout/style/crashtests/1404324-3.html layout/style/crashtests/1404324-3.html +new file mode 100644 +index 000000000000..3b06f12a2bf6 +--- /dev/null ++++ layout/style/crashtests/1404324-3.html +@@ -0,0 +1,14 @@ ++<style> ++del { ++ position: absolute; ++} ++ ++body::first-line { ++ color: red; ++} ++</style> ++<del></del> ++<script> ++ document.documentElement.offsetTop; ++ document.styleSheets[0].cssRules[0].style.position = 'sticky' ++</script> +diff --git layout/style/crashtests/crashtests.list layout/style/crashtests/crashtests.list +index be9a46c52bfa..5eaba6935ee2 100644 +--- layout/style/crashtests/crashtests.list ++++ layout/style/crashtests/crashtests.list +@@ -238,3 +238,6 @@ load 1403615.html + load 1387481-1.html + load 1387499.html + load 1391577.html ++asserts-if(stylo,1) load 1404324-1.html # bug 1405605 ++load 1404324-2.html ++load 1404324-3.html diff --git a/www/waterfox/files/patch-bug1404568 b/www/waterfox/files/patch-bug1404568 new file mode 100644 index 000000000000..3884d431c1bb --- /dev/null +++ b/www/waterfox/files/patch-bug1404568 @@ -0,0 +1,120 @@ +commit 7d205a638012 +Author: Ian Moody <moz-ian@perix.co.uk> +Date: Sun Oct 8 13:23:33 2017 +0100 + + Bug 1404568 - Improve webext browser_action icon fallbacks. r=mixedpuppy, a=ritu + + Currently if there is no default icon at the specified size, the default icon + falls back to the light text icon at that size. This is wrong in two ways: + First, the default theme uses dark text, so it should fallback to the dark icon + Secondly, authors expect the unsized default_icon to be used if specified + + This patch fixes both of these issues, so that the default icon first falls back + to the unsized default_icon, and then only if that is not specified falls back + to the dark icon + + MozReview-Commit-ID: C3RRTKhYq6r + + --HG-- + extra : source : ca81275884eb6147bd1022779fcac81fa0930128 +--- + .../extensions/test/browser/browser_ext_browserAction_theme_icons.js | 4 ++-- + toolkit/components/extensions/ExtensionParent.jsm | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git browser/components/extensions/test/browser/browser_ext_browserAction_theme_icons.js browser/components/extensions/test/browser/browser_ext_browserAction_theme_icons.js +index 05d8474ab2b6..b910568e0f78 100644 +--- browser/components/extensions/test/browser/browser_ext_browserAction_theme_icons.js ++++ browser/components/extensions/test/browser/browser_ext_browserAction_theme_icons.js +@@ -46,7 +46,7 @@ async function testStaticTheme(options) { + await extension.startup(); + + // Confirm that the browser action has the correct default icon before a theme is loaded. +- let expectedDefaultIcon = withDefaultIcon ? "default.png" : "light.png"; ++ let expectedDefaultIcon = withDefaultIcon ? "default.png" : "dark.png"; + await testBrowserAction(extension, expectedDefaultIcon); + + let theme = ExtensionTestUtils.loadExtension({ +@@ -164,7 +164,7 @@ add_task(async function browseraction_theme_icons_dynamic_theme() { + "theme_icons": [{ + "light": "light.png", + "dark": "dark.png", +- "size": 19, ++ "size": 16, + }], + }, + }, +diff --git toolkit/components/extensions/ExtensionParent.jsm toolkit/components/extensions/ExtensionParent.jsm +index e608ff2d19c6..75df6a285195 100644 +--- toolkit/components/extensions/ExtensionParent.jsm ++++ toolkit/components/extensions/ExtensionParent.jsm +@@ -1306,9 +1306,9 @@ let IconDetails = { + this._checkURL(lightURL, extension); + this._checkURL(darkURL, extension); + +- let defaultURL = result[size]; ++ let defaultURL = result[size] || result[19]; // always fallback to default first + result[size] = { +- "default": defaultURL || lightURL, // Fallback to the light url if no default is specified. ++ "default": defaultURL || darkURL, // Fallback to the dark url if no default is specified. + "light": lightURL, + "dark": darkURL, + }; + +commit 1cceb370d13c +Author: Ian Moody <moz-ian@perix.co.uk> +Date: Wed Oct 4 01:40:45 2017 +0100 + + Bug 1404568 - Use the correct browser_action theme icons when the action is in a menu-panel. r=mixedpuppy, a=ritu + + The patch adding support for specifying theme icons had a bug in the CSS: it + added styles for the action in a menu-panel depending on theme, but missed out + the theme pseudo-class selectors. Therefore the dark text icon was always used + since it was last in the CSS. + Additionally, the menu panels can't be styled, so still have light backgrounds + and dark text even in light text themes. If a light icon is used in the menu + panel in a light text theme it will be hard to see. + + Thus, this patch adds the pseudo-class for dark text themes, but removes the + selector entirely for light text themes. + + MozReview-Commit-ID: AmKVDYwGGKj + + --HG-- + extra : source : 38347dff77997359905b6efc1f6061e4103431d6 +--- + browser/base/content/browser.css | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git browser/base/content/browser.css browser/base/content/browser.css +index bbd7310f55d0..fe940cf58408 100644 +--- browser/base/content/browser.css ++++ browser/base/content/browser.css +@@ -377,12 +377,11 @@ toolbarpaletteitem > toolbaritem[sdkstylewidget="true"][cui-areatype="toolbar"] + list-style-image: var(--webextension-menupanel-image, inherit); + } + +- .webextension-browser-action[cui-areatype="menu-panel"], + toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-brighttext { + list-style-image: var(--webextension-menupanel-image-light, inherit); + } + +- .webextension-browser-action[cui-areatype="menu-panel"], ++ .webextension-browser-action[cui-areatype="menu-panel"]:-moz-lwtheme-darktext, + toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-darktext { + list-style-image: var(--webextension-menupanel-image-dark, inherit); + } +@@ -414,12 +413,11 @@ toolbarpaletteitem > toolbaritem[sdkstylewidget="true"][cui-areatype="toolbar"] + list-style-image: var(--webextension-menupanel-image-2x, inherit); + } + +- .webextension-browser-action[cui-areatype="menu-panel"], + toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-brighttext { + list-style-image: var(--webextension-menupanel-image-2x-light, inherit); + } + +- .webextension-browser-action[cui-areatype="menu-panel"], ++ .webextension-browser-action[cui-areatype="menu-panel"]:-moz-lwtheme-darktext, + toolbarpaletteitem[place="palette"] > .webextension-browser-action:-moz-lwtheme-darktext { + list-style-image: var(--webextension-menupanel-image-2x-dark, inherit); + } diff --git a/www/waterfox/files/patch-bug1404651 b/www/waterfox/files/patch-bug1404651 new file mode 100644 index 000000000000..0c9f490f52ca --- /dev/null +++ b/www/waterfox/files/patch-bug1404651 @@ -0,0 +1,39 @@ +commit 698e5f304f4b +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Oct 4 13:29:53 2017 +0100 + + Bug 1404651 - Keep focus in the tabstrip when the focus has shifted with the arrow keys. r=dao, a=ritu + + MozReview-Commit-ID: Brm9jImW9bc + + --HG-- + extra : source : 0304a90aee90618165af50193ea6255c54a6b9ea +--- + browser/base/content/tabbrowser.xml | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git browser/base/content/tabbrowser.xml browser/base/content/tabbrowser.xml +index 37efdcc5bc0c..4f40e45f2446 100644 +--- browser/base/content/tabbrowser.xml ++++ browser/base/content/tabbrowser.xml +@@ -1417,13 +1417,14 @@ + findBar._findField.getAttribute("focused") == "true"); + } + +- // If focus is in the tab bar, retain it there. +- if (document.activeElement == oldTab) { +- // We need to explicitly focus the new tab, because +- // tabbox.xml does this only in some cases. ++ let activeEl = document.activeElement; ++ // If focus is on the old tab, move it to the new tab. ++ if (activeEl == oldTab) { + newTab.focus(); +- } else if (gMultiProcessBrowser && document.activeElement !== newBrowser) { +- ++ } else if (gMultiProcessBrowser && activeEl != newBrowser && activeEl != newTab) { ++ // In e10s, if focus isn't already in the tabstrip or on the new browser, ++ // and the new browser's previous focus wasn't in the url bar but focus is ++ // there now, we need to adjust focus further. + let keepFocusOnUrlBar = newBrowser && + newBrowser._urlbarFocused && + gURLBar && diff --git a/www/waterfox/files/patch-bug1404714 b/www/waterfox/files/patch-bug1404714 new file mode 100644 index 000000000000..5c867926d439 --- /dev/null +++ b/www/waterfox/files/patch-bug1404714 @@ -0,0 +1,34 @@ +commit 867b599b37e0 +Author: Benjamin Bouvier <benj@benj.me> +Date: Tue Oct 3 19:57:05 2017 +0200 + + Bug 1404714 - inIon() should return false when in wasm. r=nbp, a=test-only on a CLOSED TREE + + MozReview-Commit-ID: 76qU9UjcROt + + --HG-- + extra : source : 6956f4fcbb7973e93c7314eb8bb9e7f8de93b96f + extra : amend_source : ed03aa30810d829dbf0951ccbc7aaab805afa280 + extra : intermediate-source : d5f57ad0a0fb5b362ed6abc150aa1038a1555fa5 +--- + js/src/builtin/TestingFunctions.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git js/src/builtin/TestingFunctions.cpp js/src/builtin/TestingFunctions.cpp +index cf2f0e3ecc2a..5cc776d0a7cc 100644 +--- js/src/builtin/TestingFunctions.cpp ++++ js/src/builtin/TestingFunctions.cpp +@@ -2199,6 +2199,13 @@ testingFunc_inIon(JSContext* cx, unsigned argc, Value* vp) + return true; + } + ++ if (cx->activation()->isWasm()) { ++ // Exited through wasm. Note this is false when the fast wasm->jit exit ++ // was taken, in which case we actually have jit frames on the stack. ++ args.rval().setBoolean(false); ++ return true; ++ } ++ + ScriptFrameIter iter(cx); + if (!iter.done() && iter.isIon()) { + // Reset the counter of the IonScript's script. diff --git a/www/waterfox/files/patch-bug1404760 b/www/waterfox/files/patch-bug1404760 new file mode 100644 index 000000000000..68cf6f5f73b6 --- /dev/null +++ b/www/waterfox/files/patch-bug1404760 @@ -0,0 +1,65 @@ +commit a73710615fe2 +Author: Lars T Hansen <lhansen@mozilla.com> +Date: Mon Oct 2 10:45:26 2017 +0200 + + Bug 1404760 - wasm baseline, disable branch optimization for int64 on x86 to avoid register starvation. r=bbouvier, a=ritu + + --HG-- + extra : source : c80e87f3242679c9e9548592f27173871824b681 + extra : intermediate-source : 12d671fcc1f1c25898ebb0723e1eb0b20b5b4838 +--- + .../jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js | 16 ++++++++++++++++ + js/src/wasm/WasmBaselineCompile.cpp | 14 ++++++++------ + 2 files changed, 24 insertions(+), 6 deletions(-) + +diff --git js/src/jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js js/src/jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js +new file mode 100644 +index 000000000000..aad892558a15 +--- /dev/null ++++ js/src/jit-test/tests/wasm/regress/baseline-i64-opt-cmp.js +@@ -0,0 +1,16 @@ ++// Bug 1404760: Optimized compare-and-branch with a preserved value would fail ++// the baseline compiler on x86 debug builds (and would just generate bad code ++// on non-debug builds) because of register starvation. ++ ++wasmEvalText( ++ `(module ++ (func $run (param i64) (param i64) (result i64) ++ block i64 ++ i64.const 1 ++ (i64.lt_s (get_local 0) (get_local 1)) ++ br_if 0 ++ drop ++ i64.const 2 ++ end) ++ (export "run" $run))` ++); +diff --git js/src/wasm/WasmBaselineCompile.cpp js/src/wasm/WasmBaselineCompile.cpp +index bf83cbb3f818..50de676de678 100644 +--- js/src/wasm/WasmBaselineCompile.cpp ++++ js/src/wasm/WasmBaselineCompile.cpp +@@ -5212,16 +5212,18 @@ BaseCompiler::sniffConditionalControlCmp(Cond compareOp, ValType operandType) + { + MOZ_ASSERT(latentOp_ == LatentOp::None, "Latent comparison state not properly reset"); + ++#ifdef JS_CODEGEN_X86 ++ // On x86, latent i64 binary comparisons use too many registers: the ++ // reserved join register and the lhs and rhs operands require six, but we ++ // only have five. ++ if (operandType == ValType::I64) ++ return false; ++#endif ++ + OpBytes op; + iter_.peekOp(&op); + switch (op.b0) { + case uint16_t(Op::Select): +-#ifdef JS_CODEGEN_X86 +- // On x86, with only 5 available registers, a latent i64 binary +- // comparison takes 4 leaving only 1 which is not enough for select. +- if (operandType == ValType::I64) +- return false; +-#endif + MOZ_FALLTHROUGH; + case uint16_t(Op::BrIf): + case uint16_t(Op::If): diff --git a/www/waterfox/files/patch-bug1404910 b/www/waterfox/files/patch-bug1404910 new file mode 100644 index 000000000000..1157ce538381 --- /dev/null +++ b/www/waterfox/files/patch-bug1404910 @@ -0,0 +1,170 @@ +commit 2c8bf0ecbc5d +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Wed Oct 4 14:18:19 2017 +0200 + + Bug 1404910 - WebSocket should consider the corrent top-level window principal. r=smaug, a=ritu + + --HG-- + extra : source : c543c0a50db700883b57c052710c97b5ef731e1f +--- + dom/base/WebSocket.cpp | 15 ++++--- + dom/base/test/iframe_webSocket_sandbox.html | 65 +++++++++++++++++++++++++++++ + dom/base/test/mochitest.ini | 3 ++ + dom/base/test/test_webSocket_sandbox.html | 34 +++++++++++++++ + 4 files changed, 109 insertions(+), 8 deletions(-) + +diff --git dom/base/WebSocket.cpp dom/base/WebSocket.cpp +index dc2c1c70107b..982c67cd2abd 100644 +--- dom/base/WebSocket.cpp ++++ dom/base/WebSocket.cpp +@@ -1666,18 +1666,17 @@ WebSocketImpl::Init(JSContext* aCx, + nsCOMPtr<nsPIDOMWindowInner> innerWindow; + + while (true) { +- if (principal) { +- bool isNullPrincipal = true; +- isNullPrincipal = principal->GetIsNullPrincipal(); +- if (isNullPrincipal || nsContentUtils::IsSystemPrincipal(principal)) { +- break; +- } ++ if (principal && !principal->GetIsNullPrincipal()) { ++ break; + } + + if (!innerWindow) { + innerWindow = do_QueryInterface(globalObject); +- if (NS_WARN_IF(!innerWindow)) { +- return NS_ERROR_DOM_SECURITY_ERR; ++ if (!innerWindow) { ++ // If we are in a XPConnect sandbox or in a JS component, ++ // innerWindow will be null. There is nothing on top of this to be ++ // considered. ++ break; + } + } + +diff --git dom/base/test/iframe_webSocket_sandbox.html dom/base/test/iframe_webSocket_sandbox.html +new file mode 100644 +index 000000000000..d889a79b05da +--- /dev/null ++++ dom/base/test/iframe_webSocket_sandbox.html +@@ -0,0 +1,65 @@ ++<html><body> ++<iframe id="frame" sandbox="allow-scripts allow-popups"></iframe> ++<script type="application/javascript;version=1.8"> ++onmessage = function(e) { ++ parent.postMessage(e.data, '*'); ++} ++ ++var ifr = document.getElementById('frame'); ++ ++if (location.search == '?nested') { ++ var url = new URL(location); ++ url.search = ""; ++ ifr.src = url.href; ++} else if (location.search == '?popup') { ++ var url = new URL(location); ++ url.search = "?opener"; ++ ++ ifr.srcdoc = "<html><script>" + ++ "window.open('" + url.href + "', 'foobar');" + ++ "onmessage = function(e) { " + ++ " parent.postMessage(e.data, '*'); " + ++ "}" + ++ "</scr" + "ipt></html>"; ++} else if (location.search == '?opener') { ++ try{ ++ var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic'); ++ socket.onerror = function(e) { ++ opener.postMessage('WS onerror', '*'); ++ close(); ++ }; ++ socket.onopen = function(event) { ++ opener.postMessage('WS onopen', '*'); ++ close(); ++ }; ++ } catch(e) { ++ if (e.name == 'SecurityError') { ++ opener.postMessage('WS Throws!', '*'); ++ } else { ++ opener.postMessage('WS Throws something else!', '*'); ++ } ++ close(); ++ } ++} else { ++ ifr.srcdoc = ` ++ <html><script> ++ try{ ++ var socket = new WebSocket('ws://mochi.test:8888/tests/dom/base/test/file_websocket_basic'); ++ socket.onerror = function(e) { ++ parent.postMessage('WS onerror', '*'); ++ }; ++ socket.onopen = function(event) { ++ parent.postMessage('WS onopen', '*'); ++ }; ++ } catch(e) { ++ if (e.name == 'SecurityError') { ++ parent.postMessage('WS Throws!', '*'); ++ } else { ++ parent.postMessage('WS Throws something else!', '*'); ++ } ++ } ++ </scr`+`ipt> ++ </html>`; ++} ++</script> ++</body></html> +diff --git dom/base/test/mochitest.ini dom/base/test/mochitest.ini +index 670dd5ae0a06..5d59fe1ea7b8 100644 +--- dom/base/test/mochitest.ini ++++ dom/base/test/mochitest.ini +@@ -804,6 +804,9 @@ skip-if = toolkit == 'android' + skip-if = toolkit == 'android' + [test_websocket_permessage_deflate.html] + skip-if = toolkit == 'android' ++[test_webSocket_sandbox.html] ++skip-if = toolkit == 'android' ++support-files = iframe_webSocket_sandbox.html + [test_websocket1.html] + skip-if = toolkit == 'android' + [test_websocket2.html] +diff --git dom/base/test/test_webSocket_sandbox.html dom/base/test/test_webSocket_sandbox.html +new file mode 100644 +index 000000000000..b343fa784f39 +--- /dev/null ++++ dom/base/test/test_webSocket_sandbox.html +@@ -0,0 +1,34 @@ ++<!DOCTYPE HTML> ++<html> ++<head> ++ <title>Bug 1252751</title> ++ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> ++ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> ++</head> ++<body> ++<div id="container"></div> ++<iframe id="frame"></iframe> ++<script type="application/javascript;version=1.8"> ++var urls = [ "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html", ++ "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html?nested", ++ "https://example.com/tests/dom/base/test/iframe_webSocket_sandbox.html?popup" ]; ++ ++onmessage = function(e) { ++ is(e.data, "WS Throws!", "ws://URI cannot be used by a https iframe"); ++ runTest(); ++} ++ ++function runTest() { ++ if (!urls.length) { ++ SimpleTest.finish(); ++ return; ++ } ++ ++ document.getElementById("frame").src = urls.shift(); ++} ++ ++SimpleTest.waitForExplicitFinish(); ++runTest(); ++</script> ++</body> ++</html> diff --git a/www/waterfox/files/patch-bug1405199 b/www/waterfox/files/patch-bug1405199 new file mode 100644 index 000000000000..6e7ffc1c0d44 --- /dev/null +++ b/www/waterfox/files/patch-bug1405199 @@ -0,0 +1,45 @@ +commit a8e2534607cc +Author: Honza Bambas <honzab.moz@firemni.cz> +Date: Mon Oct 9 07:50:00 2017 -0400 + + Bug 1405199 - Update result principal URI on the new channel when nsBaseChannel redirects. r=bz, a=ritu + + --HG-- + extra : source : 41697bca82fb1cb74c3617f8c7496cebacf81efc +--- + netwerk/base/nsBaseChannel.cpp | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git netwerk/base/nsBaseChannel.cpp netwerk/base/nsBaseChannel.cpp +index 07a12c8fa5b6..b839bc6e1b7e 100644 +--- netwerk/base/nsBaseChannel.cpp ++++ netwerk/base/nsBaseChannel.cpp +@@ -106,6 +106,28 @@ nsBaseChannel::Redirect(nsIChannel *newChannel, uint32_t redirectFlags, + new nsRedirectHistoryEntry(uriPrincipal, nullptr, EmptyCString()); + + newLoadInfo->AppendRedirectHistoryEntry(entry, isInternalRedirect); ++ ++ // Ensure the channel's loadInfo's result principal URI so that it's ++ // either non-null or updated to the redirect target URI. ++ // We must do this because in case the loadInfo's result principal URI ++ // is null, it would be taken from OriginalURI of the channel. But we ++ // overwrite it with the whole redirect chain first URI before opening ++ // the target channel, hence the information would be lost. ++ // If the protocol handler that created the channel wants to use ++ // the originalURI of the channel as the principal URI, it has left ++ // the result principal URI on the load info null. ++ nsCOMPtr<nsIURI> resultPrincipalURI; ++ ++ nsCOMPtr<nsILoadInfo> existingLoadInfo = newChannel->GetLoadInfo(); ++ if (existingLoadInfo) { ++ existingLoadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); ++ } ++ if (!resultPrincipalURI) { ++ newChannel->GetOriginalURI(getter_AddRefs(resultPrincipalURI)); ++ } ++ ++ newLoadInfo->SetResultPrincipalURI(resultPrincipalURI); ++ + newChannel->SetLoadInfo(newLoadInfo); + } + else { diff --git a/www/waterfox/files/patch-bug1405267 b/www/waterfox/files/patch-bug1405267 new file mode 100644 index 000000000000..63fc86f584b9 --- /dev/null +++ b/www/waterfox/files/patch-bug1405267 @@ -0,0 +1,32 @@ +commit 28e925727f61 +Author: Chris Coulson <chrisccoulson@ubuntu.com> +Date: Tue Oct 3 04:58:00 2017 -0400 + + Bug 1405267 - Don't stub gdk_window_get_window_type in mozgtk2. r=karlt, a=ritu + + --HG-- + extra : source : d06512adfab5cc90d985a1b814e8ba3dc4b81fff +--- + widget/gtk/mozgtk/mozgtk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git widget/gtk/mozgtk/mozgtk.c widget/gtk/mozgtk/mozgtk.c +index 7285b7f001ac..9a5498a173fd 100644 +--- widget/gtk/mozgtk/mozgtk.c ++++ widget/gtk/mozgtk/mozgtk.c +@@ -95,6 +95,7 @@ STUB(gdk_window_get_update_area) + STUB(gdk_window_get_user_data) + STUB(gdk_window_get_visual) + STUB(gdk_window_get_width) ++STUB(gdk_window_get_window_type) + STUB(gdk_window_hide) + STUB(gdk_window_input_shape_combine_region) + STUB(gdk_window_invalidate_rect) +@@ -520,7 +521,6 @@ STUB(gdk_error_trap_pop_ignored) + STUB(gdk_event_get_source_device) + STUB(gdk_screen_get_monitor_workarea) + STUB(gdk_window_get_type) +-STUB(gdk_window_get_window_type) + STUB(gdk_x11_window_get_xid) + STUB(gdk_x11_display_get_type) + STUB(gdk_wayland_display_get_type) diff --git a/www/waterfox/files/patch-bug1405364 b/www/waterfox/files/patch-bug1405364 new file mode 100644 index 000000000000..b3cec01bcb64 --- /dev/null +++ b/www/waterfox/files/patch-bug1405364 @@ -0,0 +1,84 @@ +commit bc3e9c9c8230 +Author: Andrew Osmond <aosmond@mozilla.com> +Date: Mon Oct 30 06:58:04 2017 -0400 + + Bug 1405364 - ImageBridgeParent::GetInstance should not mutate sImageBridges for lookups. r=sotaro a=sylvestre + + --HG-- + extra : amend_source : 6121399940a53f45027923e0e3f5a517722036ed + extra : transplant_source : %D1%06%8F%0D%25%B3%FD%82%3D%C9%0A%5C%9B%C7%3B%15%9C%A7%EC%91 +--- + gfx/layers/ipc/ImageBridgeParent.cpp | 18 ++++++++++++------ + gfx/layers/ipc/ImageBridgeParent.h | 5 +++-- + 2 files changed, 15 insertions(+), 8 deletions(-) + +diff --git gfx/layers/ipc/ImageBridgeParent.cpp gfx/layers/ipc/ImageBridgeParent.cpp +index 745576a3a7b3..8f8f60ffcd78 100644 +--- gfx/layers/ipc/ImageBridgeParent.cpp ++++ gfx/layers/ipc/ImageBridgeParent.cpp +@@ -42,7 +42,7 @@ using namespace mozilla::ipc; + using namespace mozilla::gfx; + using namespace mozilla::media; + +-std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges; ++ImageBridgeParent::ImageBridgeMap ImageBridgeParent::sImageBridges; + + StaticAutoPtr<mozilla::Monitor> sImageBridgesLock; + +@@ -366,8 +366,9 @@ ImageBridgeParent::NotifyImageComposites(nsTArray<ImageCompositeNotificationInfo + notifications.AppendElement(aNotifications[end].mNotification); + ++end; + } +- GetInstance(pid)->SendPendingAsyncMessages(); +- if (!GetInstance(pid)->SendDidComposite(notifications)) { ++ RefPtr<ImageBridgeParent> bridge = GetInstance(pid); ++ bridge->SendPendingAsyncMessages(); ++ if (!bridge->SendDidComposite(notifications)) { + ok = false; + } + i = end; +@@ -382,13 +383,18 @@ ImageBridgeParent::DeferredDestroy() + mSelfRef = nullptr; // "this" ImageBridge may get deleted here. + } + +-RefPtr<ImageBridgeParent> ++already_AddRefed<ImageBridgeParent> + ImageBridgeParent::GetInstance(ProcessId aId) + { + MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); + MonitorAutoLock lock(*sImageBridgesLock); +- NS_ASSERTION(sImageBridges.count(aId) == 1, "ImageBridgeParent for the process"); +- return sImageBridges[aId]; ++ ImageBridgeMap::const_iterator i = sImageBridges.find(aId); ++ if (i == sImageBridges.end()) { ++ NS_ASSERTION(false, "Cannot find image bridge for process!"); ++ return nullptr; ++ } ++ RefPtr<ImageBridgeParent> bridge = i->second; ++ return bridge.forget(); + } + + bool +diff --git gfx/layers/ipc/ImageBridgeParent.h gfx/layers/ipc/ImageBridgeParent.h +index 7475b67e356d..3edd1f8861ee 100644 +--- gfx/layers/ipc/ImageBridgeParent.h ++++ gfx/layers/ipc/ImageBridgeParent.h +@@ -114,7 +114,7 @@ public: + + virtual bool IsSameProcess() const override; + +- static RefPtr<ImageBridgeParent> GetInstance(ProcessId aId); ++ static already_AddRefed<ImageBridgeParent> GetInstance(ProcessId aId); + + static bool NotifyImageComposites(nsTArray<ImageCompositeNotificationInfo>& aNotifications); + +@@ -140,7 +140,8 @@ private: + /** + * Map of all living ImageBridgeParent instances + */ +- static std::map<base::ProcessId, ImageBridgeParent*> sImageBridges; ++ typedef std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeMap; ++ static ImageBridgeMap sImageBridges; + + RefPtr<CompositorThreadHolder> mCompositorThreadHolder; + }; diff --git a/www/waterfox/files/patch-bug1405377 b/www/waterfox/files/patch-bug1405377 new file mode 100644 index 000000000000..4f6a39347fbc --- /dev/null +++ b/www/waterfox/files/patch-bug1405377 @@ -0,0 +1,31 @@ +commit 3036b2933fde +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Tue Oct 3 19:29:36 2017 +0100 + + Bug 1405377 - Remove trailing separator in recently closed tabs/windows subviews. r=mikedeboer, a=ritu + + The third param of 'getTabsFragment' and 'getWindowsFragment' toggles whether the 'restore all' item + gets prefixed (true) or suffixed (false). The prefixed version doesn't get a separator, so this + seems like the simplest fix. + + MozReview-Commit-ID: BzKWvndWUMp + + --HG-- + extra : source : ed7b92c9eca5e1faa1b193918f0b9ddf7fc9c0e5 +--- + browser/components/customizableui/CustomizableWidgets.jsm | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git browser/components/customizableui/CustomizableWidgets.jsm browser/components/customizableui/CustomizableWidgets.jsm +index fb12d40da42d..b197d2d72fdc 100644 +--- browser/components/customizableui/CustomizableWidgets.jsm ++++ browser/components/customizableui/CustomizableWidgets.jsm +@@ -215,7 +215,7 @@ const CustomizableWidgets = [ + + let utils = RecentlyClosedTabsAndWindowsMenuUtils; + let method = `get${viewType}Fragment`; +- let fragment = utils[method](window, "toolbarbutton"); ++ let fragment = utils[method](window, "toolbarbutton", true); + let elementCount = fragment.childElementCount; + this._panelMenuView._setEmptyPopupStatus(panelview, !elementCount); + if (!elementCount) diff --git a/www/waterfox/files/patch-bug1405635 b/www/waterfox/files/patch-bug1405635 new file mode 100644 index 000000000000..c4a015d63fb1 --- /dev/null +++ b/www/waterfox/files/patch-bug1405635 @@ -0,0 +1,100 @@ +commit c10a94980921 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Thu Oct 5 05:49:06 2017 -0500 + + Bug 1405635 - style: Use the flattened tree parent to find the closest non-nac ancestor of an element. r=bzbarsky, a=ritu + + This only matters for document level NAC like canvas custom content, in which + case otherwise we inherit from the document element (which is wrong). + + Source-Repo: https://github.com/servo/servo + Source-Revision: 35e84c5cdf9cad0f16f94525d425a3b881b3b524 + + --HG-- + extra : source : 657529d410eb93f3e89cde5e11b9ca7a6f882d39 +--- + servo/components/style/gecko/wrapper.rs | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git servo/components/style/gecko/wrapper.rs servo/components/style/gecko/wrapper.rs +index 1d6864a482bd..353bbeeedffc 100644 +--- servo/components/style/gecko/wrapper.rs ++++ servo/components/style/gecko/wrapper.rs +@@ -934,7 +934,7 @@ impl<'le> TElement for GeckoElement<'le> { + + fn closest_non_native_anonymous_ancestor(&self) -> Option<Self> { + debug_assert!(self.is_native_anonymous()); +- let mut parent = match self.parent_element() { ++ let mut parent = match self.traversal_parent() { + Some(e) => e, + None => return None, + }; +@@ -944,7 +944,7 @@ impl<'le> TElement for GeckoElement<'le> { + return Some(parent); + } + +- parent = match parent.parent_element() { ++ parent = match parent.traversal_parent() { + Some(p) => p, + None => return None, + }; +commit efb04b1d1114 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Thu Oct 5 01:40:48 2017 +0200 + + Bug 1405635 - Test that custom content doesn't inherit from the root element. r=bholley, a=ritu + + MozReview-Commit-ID: GvjsdQk5Wt4 + + --HG-- + extra : source : 777faf67f590f1d1c64f1b09601a7974a8f627ce +--- + layout/style/test/mochitest.ini | 2 ++ + .../test/test_custom_content_inheritance.html | 26 ++++++++++++++++++++++ + 2 files changed, 28 insertions(+) + +diff --git layout/style/test/mochitest.ini layout/style/test/mochitest.ini +index dafe0434981c..5a8beed3b103 100644 +--- layout/style/test/mochitest.ini ++++ layout/style/test/mochitest.ini +@@ -194,6 +194,8 @@ skip-if = toolkit == 'android' #bug 536603 + [test_css_parse_error_smoketest.html] + [test_css_supports.html] + [test_css_supports_variables.html] ++[test_custom_content_inheritance.html] ++skip-if = !stylo # Gecko fails this and messes up inheritance + [test_default_bidi_css.html] + [test_default_computed_style.html] + [test_descriptor_storage.html] +diff --git layout/style/test/test_custom_content_inheritance.html layout/style/test/test_custom_content_inheritance.html +new file mode 100644 +index 000000000000..ccbce86574bb +--- /dev/null ++++ layout/style/test/test_custom_content_inheritance.html +@@ -0,0 +1,26 @@ ++<!doctype html> ++<title>Test for custom content inheritance</title> ++<style> ++ html { color: red !important; } ++</style> ++<script src="/tests/SimpleTest/SimpleTest.js"></script> ++<script> ++onload = function() { ++ try { ++ let doc = SpecialPowers.wrap(document); ++ let div = doc.createElement('div'); ++ div.id = "test-id"; ++ ok(!!doc.insertAnonymousContent, ++ "Must have the insertAnonymousContent API"); ++ let content = doc.insertAnonymousContent(div); ++ ok(!!content, "Must have anon content"); ++ isnot(content.getComputedStylePropertyValue("test-id", "color"), ++ getComputedStyle(document.documentElement).color, ++ "Custom anon content shouldn't inherit from the root element"); ++ } catch(e) { ++ ok(false, "Threw: " + e); ++ } ++ SimpleTest.finish(); ++}; ++SimpleTest.waitForExplicitFinish(); ++</script> diff --git a/www/waterfox/files/patch-bug1405655 b/www/waterfox/files/patch-bug1405655 new file mode 100644 index 000000000000..0a2d6529a5db --- /dev/null +++ b/www/waterfox/files/patch-bug1405655 @@ -0,0 +1,256 @@ +commit 5b5983d8528a +Author: Felipe Gomes <felipc@gmail.com> +Date: Tue Oct 17 12:10:31 2017 -0200 + + Bug 1405655 - Only hide Flash Activation overlay UI if the entire plugin is covered. r=dthayer, a=ritu + + As opposed to right now where we hide if any of the corners or the center of the plugin is covered. + + MozReview-Commit-ID: 9mOVXYyV1Il + + --HG-- + extra : source : a6aaaf9cb7d3a4f3baa430cfa88671f0acabed6c +--- + browser/base/content/test/plugins/browser.ini | 2 + + .../test/plugins/browser_CTP_shouldShowOverlay.js | 56 ++++++++++ + .../test/plugins/plugin_shouldShowOverlay.html | 116 +++++++++++++++++++++ + browser/modules/PluginContent.jsm | 13 ++- + 4 files changed, 180 insertions(+), 7 deletions(-) + +diff --git browser/base/content/test/plugins/browser.ini browser/base/content/test/plugins/browser.ini +index 56f5fba1a9d0..9b3a518ecb7c 100644 +--- browser/base/content/test/plugins/browser.ini ++++ browser/base/content/test/plugins/browser.ini +@@ -29,6 +29,7 @@ support-files = + plugin_overlayed.html + plugin_positioned.html + plugin_simple_blank.swf ++ plugin_shouldShowOverlay.html + plugin_small.html + plugin_small_2.html + plugin_syncRemoved.html +@@ -76,6 +77,7 @@ tags = blocklist + tags = blocklist + [browser_CTP_resize.js] + tags = blocklist ++[browser_CTP_shouldShowOverlay.js] + [browser_CTP_zoom.js] + tags = blocklist + [browser_blocking.js] +diff --git browser/base/content/test/plugins/browser_CTP_shouldShowOverlay.js browser/base/content/test/plugins/browser_CTP_shouldShowOverlay.js +new file mode 100644 +index 000000000000..6af674a0e5b2 +--- /dev/null ++++ browser/base/content/test/plugins/browser_CTP_shouldShowOverlay.js +@@ -0,0 +1,56 @@ ++/* 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/. */ ++ ++"use strict"; ++ ++/* This test ensures that the click-to-play "Activate Plugin" overlay ++ * is shown when expected. ++ * All testcases are in the plugin_shouldShowOverlay.html file. ++ */ ++ ++var rootDir = getRootDirectory(gTestPath); ++const gTestRoot = rootDir.replace("chrome://mochitests/content/", "http://127.0.0.1:8888/"); ++ ++var gTestBrowser = null; ++ ++add_task(async function() { ++ registerCleanupFunction(function() { ++ clearAllPluginPermissions(); ++ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in"); ++ gBrowser.removeCurrentTab(); ++ gTestBrowser = null; ++ }); ++}); ++ ++add_task(async function() { ++ gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser); ++ gTestBrowser = gBrowser.selectedBrowser; ++ ++ setTestPluginEnabledState(Ci.nsIPluginTag.STATE_CLICKTOPLAY, "Test Plug-in"); ++ ++ let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser); ++ ok(!popupNotification, "Sanity check, should not have a click-to-play notification"); ++ ++ await promiseTabLoadEvent(gBrowser.selectedTab, gTestRoot + "plugin_shouldShowOverlay.html"); ++ ++ // Work around for delayed PluginBindingAttached ++ await promiseUpdatePluginBindings(gTestBrowser); ++ ++ await ContentTask.spawn(gTestBrowser, null, async function() { ++ let doc = content.document; ++ let testcases = doc.querySelectorAll(".testcase"); ++ ++ for (let testcase of testcases) { ++ let plugin = testcase.querySelector("object"); ++ Assert.ok(plugin, `plugin exists in ${testcase.id}`); ++ ++ let overlay = doc.getAnonymousElementByAttribute(plugin, "anonid", "main"); ++ Assert.ok(overlay, `overlay exists in ${testcase.id}`); ++ ++ let expectedVisibility = (testcase.getAttribute("shouldshow") == "true"); ++ Assert.ok(overlay.classList.contains("visible") == expectedVisibility, ++ `The expected visibility is correct in ${testcase.id}`); ++ } ++ }) ++}); +diff --git browser/base/content/test/plugins/plugin_shouldShowOverlay.html browser/base/content/test/plugins/plugin_shouldShowOverlay.html +new file mode 100644 +index 000000000000..24d07d164260 +--- /dev/null ++++ browser/base/content/test/plugins/plugin_shouldShowOverlay.html +@@ -0,0 +1,116 @@ ++<!DOCTYPE html> ++<html> ++<head> ++<meta charset="utf-8"> ++<style> ++object { ++ width: 200px; ++ height: 200px; ++} ++ ++.testcase { ++ position: relative; ++ margin-bottom: 5px; ++} ++ ++.cover { ++ position: absolute; ++ width: 20px; ++ height: 20px; ++ background-color: green; ++} ++</style> ++</head> ++<body> ++ ++ <div id="testcase1" class="testcase" shouldshow="true" ++ style="top: -100px"> ++ <!-- Should show overlay even though the top part is outside ++ of the page. --> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase2" class="testcase" shouldshow="true" ++ style="left: -100px"> ++ <!-- Should show overlay even though the left part is outside ++ of the page. --> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase3" class="testcase" shouldshow="false" ++ style="left: -210px"> ++ <!-- The object is entirely outside of the page, so the overlay ++ should NOT show. --> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase4" class="testcase" shouldshow="true"> ++ <!-- Should show overlay even though the top-left corner is covered. --> ++ <div class="cover" style="top: 0; left: 0"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase5" class="testcase" shouldshow="true"> ++ <!-- Should show overlay even though the top-right corner is covered. --> ++ <div class="cover" style="top: 0; left: 180px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase6" class="testcase" shouldshow="true"> ++ <!-- Should show overlay even though the bottom-left corner is covered. --> ++ <div class="cover" style="top: 180px; left: 0"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ ++ <div id="testcase7" class="testcase" shouldshow="true"> ++ <!-- Should show overlay even though the bottom-right corner is covered. --> ++ <div class="cover" style="top: 180px; left: 180px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase8" class="testcase" shouldshow="true"> ++ <!-- Should show overlay even though the center is covered. --> ++ <div class="cover" style="top: 90px; left: 90px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase9" class="testcase" shouldshow="true"> ++ <!-- Should show overlay even though multiple points are covered, ++ but not all of them. --> ++ <div class="cover" style="top: 0; left: 0"></div> ++ <div class="cover" style="top: 0; left: 180px"></div> ++ <div class="cover" style="top: 180px; left: 0"></div> ++ <div class="cover" style="top: 180px; left: 180px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase10" class="testcase" shouldshow="true"> ++ <!-- Another case where 4 are covered, but not all. --> ++ <div class="cover" style="top: 90px; left: 90px"></div> ++ <div class="cover" style="top: 0; left: 180px"></div> ++ <div class="cover" style="top: 180px; left: 0"></div> ++ <div class="cover" style="top: 180px; left: 180px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase11" class="testcase" shouldshow="false"> ++ <!-- All corners and center are covered here, so in this ++ case the overlay should NOT show. --> ++ <div class="cover" style="top: 0; left: 0"></div> ++ <div class="cover" style="top: 0; left: 180px"></div> ++ <div class="cover" style="top: 180px; left: 0"></div> ++ <div class="cover" style="top: 180px; left: 180px"></div> ++ <div class="cover" style="top: 90px; left: 90px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++ <div id="testcase12" class="testcase" shouldshow="false"> ++ <!-- All corners and center are covered here, by a single ++ element. In this case the overlay should NOT show. --> ++ <div class="cover" style="width: 200px; height:200px"></div> ++ <object type="application/x-test"></object> ++ </div> ++ ++</body> ++</html> +diff --git browser/modules/PluginContent.jsm browser/modules/PluginContent.jsm +index 678369d7e3ec..6aec465a2955 100644 +--- browser/modules/PluginContent.jsm ++++ browser/modules/PluginContent.jsm +@@ -330,22 +330,21 @@ PluginContent.prototype = { + [right, bottom], + [centerX, centerY]]; + +- if (right <= 0 || top <= 0) { +- return false; +- } +- + let contentWindow = plugin.ownerGlobal; + let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils); + + for (let [x, y] of points) { ++ if (x < 0 || y < 0) { ++ continue; ++ } + let el = cwu.elementFromPoint(x, y, true, true); +- if (el !== plugin) { +- return false; ++ if (el === plugin) { ++ return true; + } + } + +- return true; ++ return false; + }, + + addLinkClickCallback(linkNode, callbackName /* callbackArgs...*/) { diff --git a/www/waterfox/files/patch-bug1405720 b/www/waterfox/files/patch-bug1405720 new file mode 100644 index 000000000000..c316067d398a --- /dev/null +++ b/www/waterfox/files/patch-bug1405720 @@ -0,0 +1,122 @@ +commit f0664b7a8e76 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Thu Oct 5 15:17:12 2017 +0100 + + Bug 1405720 - Ensure only 1 theme is ever shown as selected in customize mode. r=jaws, r=johannh, a=ritu + + The previous code here always set the `isActive` property on all themes. When writing the + patch for bug 1402981 I ran into issues because the default theme has an `isActive` property + anyway (it's a different type of object). So I tried to avoid setting `isActive` if it was + already present. Unfortunately, the result was that `isActive` values, once set, weren't + correctly updated. Worse, these values are (and were, prior to bug 1402981) persisted in + some cases. + + There's no point persisting these values, all that will happen is that they'll start + mismatching the 'real' state of the world (LightweightThemeManager.currentTheme). So instead, + let's just not set the `isActive` property at all, and rely solely on the ID of the current + theme (or the default theme's ID, now that we no longer support non-lightweight-themes) to + establish whether any of the themes should appear selected or not. + + MozReview-Commit-ID: 7rajS71FoQR + + --HG-- + extra : source : 4099fa94e3ba6728761655f0e11e7b65d573617d +--- + .../components/customizableui/CustomizeMode.jsm | 13 ++++------ + .../browser_1007336_lwthemes_in_customize_mode.js | 28 +++++++++++++++++++--- + 2 files changed, 30 insertions(+), 11 deletions(-) + +diff --git browser/components/customizableui/CustomizeMode.jsm browser/components/customizableui/CustomizeMode.jsm +index b0e31cad63fc..79f23079b1a0 100644 +--- browser/components/customizableui/CustomizeMode.jsm ++++ browser/components/customizableui/CustomizeMode.jsm +@@ -1358,9 +1358,10 @@ CustomizeMode.prototype = { + tbb.setAttribute("tooltiptext", aTheme.description); + tbb.setAttribute("tabindex", "0"); + tbb.classList.add("customization-lwtheme-menu-theme"); +- tbb.setAttribute("aria-checked", aTheme.isActive); ++ let isActive = activeThemeID == aTheme.id; ++ tbb.setAttribute("aria-checked", isActive); + tbb.setAttribute("role", "menuitemradio"); +- if (aTheme.isActive) { ++ if (isActive) { + tbb.setAttribute("active", "true"); + } + tbb.addEventListener("focus", previewTheme); +@@ -1374,12 +1375,8 @@ CustomizeMode.prototype = { + let themes = [aDefaultTheme]; + let lwts = LightweightThemeManager.usedThemes; + let currentLwt = LightweightThemeManager.currentTheme; +- // The lwts besides the builtin themes don't have an isActive property: +- for (let lwt of lwts) { +- if (!lwt.hasOwnProperty("isActive")) { +- lwt.isActive = !!currentLwt && (lwt.id == currentLwt.id); +- } +- } ++ ++ let activeThemeID = currentLwt ? currentLwt.id : DEFAULT_THEME_ID; + + // Move the current theme (if any) and the light/dark themes to the start: + let importantThemes = [LIGHT_THEME_ID, DARK_THEME_ID]; +diff --git browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js +index 3ee8f9b8f697..7b94289c0177 100644 +--- browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js ++++ browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js +@@ -45,9 +45,25 @@ add_task(async function() { + is(header.nextSibling.nextSibling.nextSibling.theme.id, DARK_THEME_ID, + "The third theme should be the dark theme"); + ++ let themeChangedPromise = promiseObserverNotified("lightweight-theme-changed"); ++ header.nextSibling.nextSibling.doCommand(); // Select light theme ++ info("Clicked on light theme"); ++ await themeChangedPromise; ++ ++ popupShownPromise = popupShown(popup); ++ EventUtils.synthesizeMouseAtCenter(themesButton, {}); ++ info("Clicked on themes button a third time"); ++ await popupShownPromise; ++ ++ let activeThemes = popup.querySelectorAll("toolbarbutton.customization-lwtheme-menu-theme[active]"); ++ is(activeThemes.length, 1, "Exactly 1 theme should be selected"); ++ if (activeThemes.length > 0) { ++ is(activeThemes[0].theme.id, LIGHT_THEME_ID, "Light theme should be selected"); ++ } ++ + let firstLWTheme = recommendedHeader.nextSibling; + let firstLWThemeId = firstLWTheme.theme.id; +- let themeChangedPromise = promiseObserverNotified("lightweight-theme-changed"); ++ themeChangedPromise = promiseObserverNotified("lightweight-theme-changed"); + firstLWTheme.doCommand(); + info("Clicked on first theme"); + await themeChangedPromise; +@@ -57,6 +73,12 @@ add_task(async function() { + info("Clicked on themes button"); + await popupShownPromise; + ++ activeThemes = popup.querySelectorAll("toolbarbutton.customization-lwtheme-menu-theme[active]"); ++ is(activeThemes.length, 1, "Exactly 1 theme should be selected"); ++ if (activeThemes.length > 0) { ++ is(activeThemes[0].theme.id, firstLWThemeId, "First theme should be selected"); ++ } ++ + is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme"); + let installedThemeId = header.nextSibling.nextSibling.nextSibling.nextSibling.theme.id; + ok(installedThemeId.startsWith(firstLWThemeId), +@@ -78,7 +100,7 @@ add_task(async function() { + // ensure current theme isn't set to "Default" + popupShownPromise = popupShown(popup); + EventUtils.synthesizeMouseAtCenter(themesButton, {}); +- info("Clicked on themes button a second time"); ++ info("Clicked on themes button a fourth time"); + await popupShownPromise; + + firstLWTheme = recommendedHeader.nextSibling; +@@ -98,7 +120,7 @@ add_task(async function() { + await startCustomizing(); + popupShownPromise = popupShown(popup); + EventUtils.synthesizeMouseAtCenter(themesButton, {}); +- info("Clicked on themes button a second time"); ++ info("Clicked on themes button a fifth time"); + await popupShownPromise; + header = document.getElementById("customization-lwtheme-menu-header"); + is(header.hidden, false, "Header should never be hidden"); diff --git a/www/waterfox/files/patch-bug1405761 b/www/waterfox/files/patch-bug1405761 new file mode 100644 index 000000000000..fcd51bf2ca29 --- /dev/null +++ b/www/waterfox/files/patch-bug1405761 @@ -0,0 +1,109 @@ +commit 0e2ac46fa12c +Author: Dragana Damjanovic <dd.mozilla@gmail.com> +Date: Wed Oct 11 03:20:00 2017 -0400 + + Bug 1405761 - If the preload pref is disabled rel=preload should be shown as not supported. r=smaug, a=ritu + + --HG-- + extra : source : 1f4d35d137631cde34f318fac0c33421d5360dc3 +--- + dom/base/test/test_bug1222633.html | 4 +++- + dom/base/test/test_bug1222633_link_update.html | 4 +++- + dom/html/HTMLLinkElement.cpp | 19 ++++++++++++++++++- + modules/libpref/init/all.js | 2 +- + .../tools/wptrunner/wptrunner/browsers/firefox.py | 3 ++- + 5 files changed, 27 insertions(+), 5 deletions(-) + +diff --git dom/base/test/test_bug1222633.html dom/base/test/test_bug1222633.html +index 52fecff16e9b..099345dab0b7 100644 +--- dom/base/test/test_bug1222633.html ++++ dom/base/test/test_bug1222633.html +@@ -88,8 +88,10 @@ const CROSS_ORIGIN = "http://example.com" + SJS_PATH; + + SimpleTest.waitForExplicitFinish(); + ++SpecialPowers.pushPrefEnv({"set": [["network.preload", true]]}) ++ + // test same origin +-testPreloadEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, false) ++.then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=no-cache", false, false)) + .then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=404&cacheControl=no-cache", false, false)) + .then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", false, true)) + .then(() => testPreloadEvent(SAME_ORIGIN + "?statusCode=404&cacheControl=max-age%3D120", false, false)) +diff --git dom/base/test/test_bug1222633_link_update.html dom/base/test/test_bug1222633_link_update.html +index 97508d3596cf..1f18284c9470 100644 +--- dom/base/test/test_bug1222633_link_update.html ++++ dom/base/test/test_bug1222633_link_update.html +@@ -122,8 +122,10 @@ const CROSS_ORIGIN = "http://example.com" + SJS_PATH; + + SimpleTest.waitForExplicitFinish(); + ++SpecialPowers.pushPrefEnv({"set": [["network.preload", true]]}) ++ + // Test changing as parameter from a wrong to a correct one. +-testPreloadEventAsAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120") ++.then(() => testPreloadEventAsAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120")) + // Test changing type parameter from a wrong to a correct one for given as parameter. + .then(() => testPreloadEventAttributeChange(SAME_ORIGIN + "?statusCode=200&cacheControl=max-age%3D120", "type", "text/vtt", "image/png", false, true)) + // Test changing media parameter from a wrong to a correct one. +diff --git dom/html/HTMLLinkElement.cpp dom/html/HTMLLinkElement.cpp +index 810b47aed670..37b45ca03636 100644 +--- dom/html/HTMLLinkElement.cpp ++++ dom/html/HTMLLinkElement.cpp +@@ -408,11 +408,28 @@ static const DOMTokenListSupportedToken sSupportedRelValues[] = { + nullptr + }; + ++static const DOMTokenListSupportedToken sSupportedRelValuesNoPreload[] = { ++ // Keep this in sync with ToLinkMask in nsStyleLinkElement.cpp. ++ // "import" must come first because it's conditional. ++ "prefetch", ++ "dns-prefetch", ++ "stylesheet", ++ "next", ++ "alternate", ++ "preconnect", ++ "icon", ++ "search", ++ nullptr ++}; + nsDOMTokenList* + HTMLLinkElement::RelList() + { + if (!mRelList) { +- mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues); ++ if (Preferences::GetBool("network.preload")) { ++ mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValues); ++ } else { ++ mRelList = new nsDOMTokenList(this, nsGkAtoms::rel, sSupportedRelValuesNoPreload); ++ } + } + return mRelList; + } +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index e83781623803..79a0ea89d6de 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -2105,7 +2105,7 @@ pref("network.dir.format", 2); + // <link rel="prefetch"> URLs). + pref("network.prefetch-next", true); + // enables the preloading (i.e., preloading of <link rel="preload"> URLs). +-pref("network.preload", true); ++pref("network.preload", false); + + // enables the predictive service + pref("network.predictor.enabled", true); +diff --git testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py +index f869c82a8ed0..43da63c7ca4e 100644 +--- testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py ++++ testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py +@@ -190,7 +190,8 @@ class FirefoxBrowser(Browser): + "network.dns.localDomains": ",".join(hostnames), + "network.proxy.type": 0, + "places.history.enabled": False, +- "dom.send_after_paint_to_content": True}) ++ "dom.send_after_paint_to_content": True, ++ "network.preload": True}) + if self.e10s: + self.profile.set_preferences({"browser.tabs.remote.autostart": True}) + diff --git a/www/waterfox/files/patch-bug1405878 b/www/waterfox/files/patch-bug1405878 new file mode 100644 index 000000000000..fa3d058e234c --- /dev/null +++ b/www/waterfox/files/patch-bug1405878 @@ -0,0 +1,120 @@ +commit 87f3d592d92f +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Mon Oct 9 14:49:19 2017 -0400 + + Bug 1405878 - Make sure to notify for our kids, if needed, before calling DoneAddingChildren in the XML content sink. r=hsivonen, a=sledru + + Once we call DoneAddingChildren, random code of various sorts will run, which + can flush our notification state. If that happens before we've notified on our + kids, but after we've popped the element we're closing off the element stack, + we will fail to ever notify on the kids. + + MozReview-Commit-ID: Ei7v5OobX8R + + --HG-- + extra : source : f144e1434312485cf9ee16a36d6159dbcb13a07d +--- + dom/xml/crashtests/1405878.xml | 11 +++++++++++ + dom/xml/crashtests/crashtests.list | 1 + + dom/xml/nsXMLContentSink.cpp | 18 +++++++++++------- + layout/reftests/bugs/1405878-1-ref.xml | 7 +++++++ + layout/reftests/bugs/1405878-1.xml | 6 ++++++ + layout/reftests/bugs/reftest.list | 1 + + 6 files changed, 37 insertions(+), 7 deletions(-) + +diff --git dom/xml/crashtests/1405878.xml dom/xml/crashtests/1405878.xml +new file mode 100644 +index 000000000000..12677ade938d +--- /dev/null ++++ dom/xml/crashtests/1405878.xml +@@ -0,0 +1,11 @@ ++<html xmlns="http://www.w3.org/1999/xhtml"> ++ <body> ++ <select> ++ <script>document.documentElement.offsetHeight</script> ++ <option>Hello there</option> ++ </select> ++ <script> ++ document.querySelector("body").style.display = "inline"; ++ </script> ++ </body> ++</html> +diff --git dom/xml/crashtests/crashtests.list dom/xml/crashtests/crashtests.list +index f18767d582c2..2c06ffc545ec 100644 +--- dom/xml/crashtests/crashtests.list ++++ dom/xml/crashtests/crashtests.list +@@ -10,3 +10,4 @@ load 453278.html + load 803586.xhtml + load 994740-1.xhtml + load 1038887.xhtml ++load 1405878.xml +diff --git dom/xml/nsXMLContentSink.cpp dom/xml/nsXMLContentSink.cpp +index 2593519aa44b..b04977d62cf1 100644 +--- dom/xml/nsXMLContentSink.cpp ++++ dom/xml/nsXMLContentSink.cpp +@@ -1071,6 +1071,17 @@ nsXMLContentSink::HandleEndElement(const char16_t *aName, + isTemplateElement, "Wrong element being closed"); + #endif + ++ // Make sure to notify on our kids before we call out to any other code that ++ // might reenter us and call FlushTags, in a state in which we've already ++ // popped "content" from the stack but haven't notified on its kids yet. ++ int32_t stackLen = mContentStack.Length(); ++ if (mNotifyLevel >= stackLen) { ++ if (numFlushed < content->GetChildCount()) { ++ NotifyAppend(content, numFlushed); ++ } ++ mNotifyLevel = stackLen - 1; ++ } ++ + result = CloseElement(content); + + if (mCurrentHead == content) { +@@ -1086,13 +1097,6 @@ nsXMLContentSink::HandleEndElement(const char16_t *aName, + MaybeStartLayout(false); + } + +- int32_t stackLen = mContentStack.Length(); +- if (mNotifyLevel >= stackLen) { +- if (numFlushed < content->GetChildCount()) { +- NotifyAppend(content, numFlushed); +- } +- mNotifyLevel = stackLen - 1; +- } + DidAddContent(); + + if (content->IsSVGElement(nsGkAtoms::svg)) { +diff --git layout/reftests/bugs/1405878-1-ref.xml layout/reftests/bugs/1405878-1-ref.xml +new file mode 100644 +index 000000000000..6d1dd199b41e +--- /dev/null ++++ layout/reftests/bugs/1405878-1-ref.xml +@@ -0,0 +1,7 @@ ++<html xmlns="http://www.w3.org/1999/xhtml"> ++ <select> ++ <script>document.documentElement.offsetHeight</script> ++ <option>Hello there</option> ++ <script>document.documentElement.offsetHeight</script> ++ </select> ++</html> +diff --git layout/reftests/bugs/1405878-1.xml layout/reftests/bugs/1405878-1.xml +new file mode 100644 +index 000000000000..3915711b1103 +--- /dev/null ++++ layout/reftests/bugs/1405878-1.xml +@@ -0,0 +1,6 @@ ++<html xmlns="http://www.w3.org/1999/xhtml"> ++ <select> ++ <script>document.documentElement.offsetHeight</script> ++ <option>Hello there</option> ++ </select> ++</html> +diff --git layout/reftests/bugs/reftest.list layout/reftests/bugs/reftest.list +index 52f8cb915cee..47c04cdf41d6 100644 +--- layout/reftests/bugs/reftest.list ++++ layout/reftests/bugs/reftest.list +@@ -2037,3 +2037,4 @@ needs-focus != 1377447-1.html 1377447-2.html + == 1380224-1.html 1380224-1-ref.html + == 1384065.html 1384065-ref.html + == 1384275-1.html 1384275-1-ref.html ++== 1405878-1.xml 1405878-1-ref.xml diff --git a/www/waterfox/files/patch-bug1406222 b/www/waterfox/files/patch-bug1406222 new file mode 100644 index 000000000000..86efe7c15e63 --- /dev/null +++ b/www/waterfox/files/patch-bug1406222 @@ -0,0 +1,39 @@ +commit 04dfc1bac3e0 +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Fri Oct 6 01:53:12 2017 -0500 + + Bug 1406222 - servo: Don't assume that inputs to compute_style_with_inputs have any rules. r=heycam, a=ritu + + It could be a text style, which never has any rules attached to it. + + Source-Repo: https://github.com/servo/servo + Source-Revision: 117dbfaac20d8a388cf3cf5d2bc103b9d6249ee8 + + --HG-- + extra : source : 97fcd35b0d3792e7305bcb46b303ce409b30d23e + extra : histedit_source : 72acaec12ed99fa306148b7679c682abc0abaeea +--- + servo/components/style/stylist.rs | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git servo/components/style/stylist.rs servo/components/style/stylist.rs +index b40c5825a55c..e6feb6f26d15 100644 +--- servo/components/style/stylist.rs ++++ servo/components/style/stylist.rs +@@ -896,12 +896,12 @@ impl Stylist { + // We need to compute visited values if we have visited rules or if our + // parent has visited values. + let visited_values = if inputs.visited_rules.is_some() || parent_style.get_visited_style().is_some() { +- // Slightly annoying: we know that inputs has either rules or +- // visited rules, but we can't do inputs.rules() up front because +- // maybe it just has visited rules, so can't unwrap_or. ++ // At this point inputs may have visited rules, or rules, or both, ++ // or neither (e.g. if it's a text style it may have neither). So ++ // we have to be a bit careful here. + let rule_node = match inputs.visited_rules.as_ref() { + Some(rules) => rules, +- None => inputs.rules.as_ref().unwrap(), ++ None => inputs.rules.as_ref().unwrap_or(self.rule_tree().root()), + }; + let inherited_style; + let inherited_style_ignoring_first_line; diff --git a/www/waterfox/files/patch-bug1406229 b/www/waterfox/files/patch-bug1406229 new file mode 100644 index 000000000000..defa50654997 --- /dev/null +++ b/www/waterfox/files/patch-bug1406229 @@ -0,0 +1,32 @@ +commit 2e9ce146b6b5 +Author: Shane Caraveo <scaraveo@mozilla.com> +Date: Fri Oct 6 16:58:15 2017 -0700 + + Bug 1406229 - Fix autocomplete crash in panels when window is closed during event. r=mak, a=ritu + + MozReview-Commit-ID: 6TrLuwrk2nD + + --HG-- + extra : source : 118b67c940dc554a4adf6fb397db775861962c68 +--- + toolkit/components/autocomplete/nsAutoCompleteController.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git toolkit/components/autocomplete/nsAutoCompleteController.cpp toolkit/components/autocomplete/nsAutoCompleteController.cpp +index 3876380201f6..ba5287f1fabd 100644 +--- toolkit/components/autocomplete/nsAutoCompleteController.cpp ++++ toolkit/components/autocomplete/nsAutoCompleteController.cpp +@@ -367,6 +367,13 @@ nsAutoCompleteController::HandleEnter(bool aIsPopupSelection, + + // Stop the search, and handle the enter. + StopSearch(); ++ // StopSearch() can call PostSearchCleanup() which might result ++ // in a blur event, which could null out mInput, so we need to check it ++ // again. See bug #408463 for more details ++ if (!mInput) { ++ return NS_OK; ++ } ++ + EnterMatch(aIsPopupSelection, aEvent); + + return NS_OK; diff --git a/www/waterfox/files/patch-bug1406254 b/www/waterfox/files/patch-bug1406254 new file mode 100644 index 000000000000..15337c4be605 --- /dev/null +++ b/www/waterfox/files/patch-bug1406254 @@ -0,0 +1,155 @@ +commit e07fe5183b75 +Author: J. Ryan Stinnett <jryans@gmail.com> +Date: Wed Oct 11 18:50:23 2017 -0500 + + Bug 1406254 - servo: Clear visited rules for text inheritance. r=emilio, a=ritu + + Source-Repo: https://github.com/servo/servo + Source-Revision: dbf0991f8cab54516c5b0211e1818a16cfbf9e19 + MozReview-Commit-ID: LP8VmxRopA4 +--- + servo/components/style/properties/gecko.mako.rs | 2 +- + servo/components/style/properties/properties.mako.rs | 16 ++++++++++++++-- + 2 files changed, 15 insertions(+), 3 deletions(-) + +diff --git servo/components/style/properties/gecko.mako.rs servo/components/style/properties/gecko.mako.rs +index d7e5496971e3..090a31ff9d4b 100644 +--- servo/components/style/properties/gecko.mako.rs ++++ servo/components/style/properties/gecko.mako.rs +@@ -323,7 +323,7 @@ impl ComputedValuesInner { + } + + /// Clone the visited style. Used for inheriting parent styles in +- /// StyleBuilder::for_inheritance. ++ /// StyleBuilder::for_derived_style. + pub fn clone_visited_style(&self) -> Option<Arc<ComputedValues>> { + self.visited_style.as_ref().map(|x| x.clone_arc()) + } +diff --git servo/components/style/properties/properties.mako.rs servo/components/style/properties/properties.mako.rs +index 269bf0dbbbb5..80238450a9c5 100644 +--- servo/components/style/properties/properties.mako.rs ++++ servo/components/style/properties/properties.mako.rs +@@ -2170,7 +2170,7 @@ impl ComputedValuesInner { + } + + /// Clone the visited style. Used for inheriting parent styles in +- /// StyleBuilder::for_inheritance. ++ /// StyleBuilder::for_derived_style. + pub fn clone_visited_style(&self) -> Option<Arc<ComputedValues>> { + self.visited_style.clone() + } +@@ -2830,6 +2830,18 @@ impl<'a> StyleBuilder<'a> { + parent: &'a ComputedValues, + pseudo: Option<<&'a PseudoElement>, + ) -> Self { ++ // Rebuild the visited style from the parent, ensuring that it will also ++ // not have rules. This matches the unvisited style that will be ++ // produced by this builder. This assumes that the caller doesn't need ++ // to adjust or process visited style, so we can just build visited ++ // style here for simplicity. ++ let visited_style = parent.get_visited_style().map(|style| { ++ Self::for_inheritance( ++ device, ++ style, ++ pseudo, ++ ).build() ++ }); + // FIXME(emilio): This Some(parent) here is inconsistent with what we + // usually do if `parent` is the default computed values, but that's + // fine, and we want to eventually get rid of it. +@@ -2844,7 +2856,7 @@ impl<'a> StyleBuilder<'a> { + parent.writing_mode, + parent.font_computation_data, + parent.flags, +- parent.clone_visited_style() ++ visited_style, + ) + } + +commit d8586d78bd43 +Author: J. Ryan Stinnett <jryans@gmail.com> +Date: Wed Oct 11 15:33:14 2017 -0500 + + Bug 1406254 - Visited reftest for ::first-line inheritance. r=emilio, a=ritu + + MozReview-Commit-ID: 4ZOlVvBuSfT +--- + .../css-visited/color-on-visited-text-1-ref.html | 16 ++++++++++++++++ + .../css-visited/color-on-visited-text-1.html | 20 ++++++++++++++++++++ + layout/style/test/moz.build | 2 ++ + layout/style/test/test_visited_reftests.html | 1 + + 4 files changed, 39 insertions(+) + +diff --git layout/reftests/css-visited/color-on-visited-text-1-ref.html layout/reftests/css-visited/color-on-visited-text-1-ref.html +new file mode 100644 +index 000000000000..b144767ce76e +--- /dev/null ++++ layout/reftests/css-visited/color-on-visited-text-1-ref.html +@@ -0,0 +1,16 @@ ++<!DOCTYPE html> ++<style> ++ .unvisited { ++ color: blue; ++ } ++ .visited { ++ color: purple; ++ } ++ .first-line { ++ color: green; ++ } ++</style> ++<div class="first-line">Visited</div> ++<div class="first-line">Visited with span</div> ++<div class="unvisited">Visited with inner unvisited</div> ++<div class="visited">Visited with inner visited</div> +diff --git layout/reftests/css-visited/color-on-visited-text-1.html layout/reftests/css-visited/color-on-visited-text-1.html +new file mode 100644 +index 000000000000..d9dab8f3b8a7 +--- /dev/null ++++ layout/reftests/css-visited/color-on-visited-text-1.html +@@ -0,0 +1,20 @@ ++<!DOCTYPE html> ++<style> ++ a { ++ display: block; ++ text-decoration: none; ++ } ++ :link { ++ color: blue; ++ } ++ :visited { ++ color: purple; ++ } ++ .outer::first-line { ++ color: green; ++ } ++</style> ++<a class="outer" href>Visited</a> ++<a class="outer" href><span>Visited with span</span></a> ++<a class="outer" href><a href="unvisited-page.html">Visited with inner unvisited</a></a> ++<a class="outer" href><a href>Visited with inner visited</a></a> +diff --git layout/style/test/moz.build layout/style/test/moz.build +index fa646ca16dd3..74fe23260aa7 100644 +--- layout/style/test/moz.build ++++ layout/style/test/moz.build +@@ -60,6 +60,8 @@ TEST_HARNESS_FILES.testing.mochitest.tests.layout.style.test['css-visited'] += [ + '/layout/reftests/css-visited/color-on-visited-1-ref.html', + '/layout/reftests/css-visited/color-on-visited-1.html', + '/layout/reftests/css-visited/color-on-visited-before-1.html', ++ '/layout/reftests/css-visited/color-on-visited-text-1-ref.html', ++ '/layout/reftests/css-visited/color-on-visited-text-1.html', + '/layout/reftests/css-visited/column-rule-1-notref.html', + '/layout/reftests/css-visited/column-rule-1-ref.html', + '/layout/reftests/css-visited/column-rule-1.html', +diff --git layout/style/test/test_visited_reftests.html layout/style/test/test_visited_reftests.html +index aea857f031d2..850d35bae867 100644 +--- layout/style/test/test_visited_reftests.html ++++ layout/style/test/test_visited_reftests.html +@@ -38,6 +38,7 @@ var gTests = [ + "== color-on-link-before-1.html color-on-link-1-ref.html", + "== color-on-visited-1.html color-on-visited-1-ref.html", + "== color-on-visited-before-1.html color-on-visited-1-ref.html", ++ "== color-on-visited-text-1.html color-on-visited-text-1-ref.html", + "!= content-color-on-link-before-1-ref.html content-color-on-visited-before-1-ref.html", + "== content-color-on-link-before-1.html content-color-on-link-before-1-ref.html", + "== content-color-on-visited-before-1.html content-color-on-visited-before-1-ref.html", diff --git a/www/waterfox/files/patch-bug1406396 b/www/waterfox/files/patch-bug1406396 new file mode 100644 index 000000000000..40d5e3c13a6b --- /dev/null +++ b/www/waterfox/files/patch-bug1406396 @@ -0,0 +1,211 @@ +commit 45ffbc50f1f2 +Author: David Keeler <dkeeler@mozilla.com> +Date: Fri Oct 13 11:27:30 2017 -0700 + + Bug 1406396 - Work around NSS utils potentially loading spurious root cert modules. r=mgoodwin, a=ritu, l10n=flod + + NSS command-line utilities may add a built-in root certificate module with the + name "Root Certs" if run on a profile that has a copy of the module file (which + is an unexpected configuration in general for Firefox). This can cause breakage. + To work around this, PSM now simply deletes any module named "Root Certs" at + startup. In an effort to prevent PSM from deleting unrelated modules + coincidentally named "Root Certs", we also prevent the user from using the + Firefox UI to name modules "Root Certs". + + MozReview-Commit-ID: ABja3wpShO9 + + --HG-- + extra : histedit_source : 3f8a20980a1f7fbc838b610763369af3ddf95e16 +--- + security/certverifier/NSSCertDBTrustDomain.cpp | 6 +++++ + .../locales/en-US/chrome/pippki/pippki.properties | 5 ++++ + .../manager/pki/resources/content/load_device.js | 17 ++++++++++++ + .../manager/pki/resources/content/load_device.xul | 4 ++- + security/manager/ssl/PKCS11ModuleDB.cpp | 11 ++++++++ + .../browser/browser_loadPKCS11Module_ui.js | 30 ++++++++++++++++++++++ + .../manager/ssl/tests/unit/test_pkcs11_moduleDB.js | 28 ++++++++++++++++++++ + .../manager/ssl/tests/unit/xpcshell-smartcards.ini | 1 + + 8 files changed, 101 insertions(+), 1 deletion(-) + +diff --git security/certverifier/NSSCertDBTrustDomain.cpp security/certverifier/NSSCertDBTrustDomain.cpp +index a352d928a3c9..229a0b5df28c 100644 +--- security/certverifier/NSSCertDBTrustDomain.cpp ++++ security/certverifier/NSSCertDBTrustDomain.cpp +@@ -1216,6 +1216,12 @@ LoadLoadableRoots(const nsCString& dir, const nsCString& modNameUTF8) + // the return value would be detrimental in that case. + int unusedModType; + Unused << SECMOD_DeleteModule(modNameUTF8.get(), &unusedModType); ++ // Some NSS command-line utilities will load a roots module under the name ++ // "Root Certs" if there happens to be a `DLL_PREFIX "nssckbi" DLL_SUFFIX` ++ // file in the directory being operated on. In some cases this can cause us to ++ // fail to load our roots module. In these cases, deleting the "Root Certs" ++ // module allows us to load the correct one. See bug 1406396. ++ Unused << SECMOD_DeleteModule("Root Certs", &unusedModType); + + nsAutoCString fullLibraryPath; + if (!dir.IsEmpty()) { +diff --git security/manager/locales/en-US/chrome/pippki/pippki.properties security/manager/locales/en-US/chrome/pippki/pippki.properties +index 4bf67da7bab2..163384651067 100644 +--- security/manager/locales/en-US/chrome/pippki/pippki.properties ++++ security/manager/locales/en-US/chrome/pippki/pippki.properties +@@ -185,3 +185,8 @@ addExceptionCheckingShort=Checking Information + addExceptionCheckingLong2=Attempting to identify this site… + addExceptionNoCertShort=No Information Available + addExceptionNoCertLong2=Unable to obtain identification status for this site. ++ ++# Load Module Dialog ++loadModuleHelp_emptyModuleName=The module name cannot be empty. ++# LOCALIZATION NOTE(loadModuleHelp_rootCertsModuleName): Do not translate 'Root Certs' ++loadModuleHelp_rootCertsModuleName=‘Root Certs‘ is reserved and cannot be used as the module name. +diff --git security/manager/pki/resources/content/load_device.js security/manager/pki/resources/content/load_device.js +index b3b020236b93..08831f16e27e 100644 +--- security/manager/pki/resources/content/load_device.js ++++ security/manager/pki/resources/content/load_device.js +@@ -51,3 +51,20 @@ function onDialogAccept() { + + return true; + } ++ ++function validateModuleName() { ++ let bundle = document.getElementById("pippki_bundle"); ++ let name = document.getElementById("device_name").value; ++ let helpText = document.getElementById("helpText"); ++ helpText.value = ""; ++ let dialogNode = document.querySelector("dialog"); ++ dialogNode.removeAttribute("buttondisabledaccept"); ++ if (name == "") { ++ helpText.value = bundle.getString("loadModuleHelp_emptyModuleName"); ++ dialogNode.setAttribute("buttondisabledaccept", true); ++ } ++ if (name == "Root Certs") { ++ helpText.value = bundle.getString("loadModuleHelp_rootCertsModuleName"); ++ dialogNode.setAttribute("buttondisabledaccept", true); ++ } ++} +diff --git security/manager/pki/resources/content/load_device.xul security/manager/pki/resources/content/load_device.xul +index b3a82df7ac57..f7cfca3cacf7 100644 +--- security/manager/pki/resources/content/load_device.xul ++++ security/manager/pki/resources/content/load_device.xul +@@ -29,7 +29,8 @@ + <hbox align="center"> + <label value="&loaddevice.modname2;" accesskey="&loaddevice.modname2.accesskey;" + control="device_name"/> +- <textbox id="device_name" flex="1" value="&loaddevice.modname.default;"/> ++ <textbox id="device_name" flex="1" value="&loaddevice.modname.default;" ++ onchange="validateModuleName();"/> + </hbox> + <hbox align="center"> + <label value="&loaddevice.filename2;" accesskey="&loaddevice.filename2.accesskey;" +@@ -39,5 +40,6 @@ + accesskey="&loaddevice.browse.accesskey;" + oncommand="onBrowseBtnPress();"/> + </hbox> ++ <label id="helpText" value=""/> + + </dialog> +diff --git security/manager/ssl/PKCS11ModuleDB.cpp security/manager/ssl/PKCS11ModuleDB.cpp +index f5fc4c8ce4ba..3e7f2586ff62 100644 +--- security/manager/ssl/PKCS11.cpp ++++ security/manager/ssl/PKCS11.cpp +@@ -118,6 +118,17 @@ PKCS11::AddModule(const nsAString& aModuleName, + return NS_ERROR_INVALID_ARG; + } + ++ // "Root Certs" is the name some NSS command-line utilities will give the ++ // roots module if they decide to load it when there happens to be a ++ // `DLL_PREFIX "nssckbi" DLL_SUFFIX` file in the directory being operated on. ++ // This causes failures, so as a workaround, the PSM initialization code will ++ // unconditionally remove any module named "Root Certs". We should prevent the ++ // user from adding an unrelated module named "Root Certs" in the first place ++ // so PSM doesn't delete it. See bug 1406396. ++ if (aModuleName.EqualsLiteral("Root Certs")) { ++ return NS_ERROR_ILLEGAL_VALUE; ++ } ++ + NS_ConvertUTF16toUTF8 moduleName(aModuleName); + nsCString fullPath; + // NSS doesn't support Unicode path. Use native charset +diff --git security/manager/ssl/tests/mochitest/browser/browser_loadPKCS11Module_ui.js security/manager/ssl/tests/mochitest/browser/browser_loadPKCS11Module_ui.js +index c458181a0067..65649d453a6b 100644 +--- security/manager/ssl/tests/mochitest/browser/browser_loadPKCS11Module_ui.js ++++ security/manager/ssl/tests/mochitest/browser/browser_loadPKCS11Module_ui.js +@@ -231,3 +231,33 @@ add_task(async function testCancel() { + + await BrowserTestUtils.windowClosed(win); + }); ++ ++async function testModuleNameHelper(moduleName, acceptButtonShouldBeDisabled) { ++ let win = await openLoadModuleDialog(); ++ resetCallCounts(); ++ ++ info(`Setting Module Name to '${moduleName}'`); ++ let moduleNameBox = win.document.getElementById("device_name"); ++ moduleNameBox.value = moduleName; ++ // this makes this not a great test, but it's the easiest way to simulate this ++ moduleNameBox.onchange(); ++ ++ let dialogNode = win.document.querySelector("dialog"); ++ Assert.equal(dialogNode.getAttribute("buttondisabledaccept"), ++ acceptButtonShouldBeDisabled ? "true" : "", // it's a string ++ `dialog accept button should ${acceptButtonShouldBeDisabled ? "" : "not "}be disabled`); ++ ++ return BrowserTestUtils.closeWindow(win); ++} ++ ++add_task(async function testEmptyModuleName() { ++ await testModuleNameHelper("", true); ++}); ++ ++add_task(async function testReservedModuleName() { ++ await testModuleNameHelper("Root Certs", true); ++}); ++ ++add_task(async function testAcceptableModuleName() { ++ await testModuleNameHelper("Some Module Name", false); ++}); +diff --git security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js +new file mode 100644 +index 000000000000..110f5a8461e5 +--- /dev/null ++++ security/manager/ssl/tests/unit/test_pkcs11_moduleDB.js +@@ -0,0 +1,28 @@ ++/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++// Any copyright is dedicated to the Public Domain. ++// http://creativecommons.org/publicdomain/zero/1.0/ ++"use strict"; ++ ++// Tests that adding modules with invalid names are prevented. ++ ++// Ensure that the appropriate initialization has happened. ++do_get_profile(); ++ ++const gModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"] ++ .getService(Ci.nsIPKCS11ModuleDB); ++ ++function run_test() { ++ let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile); ++ libraryFile.append("pkcs11testmodule"); ++ libraryFile.append(ctypes.libraryName("pkcs11testmodule")); ++ ok(libraryFile.exists(), "The pkcs11testmodule file should exist"); ++ ++ let pkcs11ModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"] ++ .getService(Ci.nsIPKCS11ModuleDB); ++ throws(() => pkcs11ModuleDB.addModule("Root Certs", libraryFile.path, 0, 0), ++ /NS_ERROR_ILLEGAL_VALUE/, ++ "Adding a module named 'Root Certs' should fail"); ++ throws(() => pkcs11ModuleDB.addModule("", libraryFile.path, 0, 0), ++ /NS_ERROR_ILLEGAL_VALUE/, ++ "Adding a module with an empty name should fail."); ++} +diff --git security/manager/ssl/tests/unit/xpcshell-smartcards.ini security/manager/ssl/tests/unit/xpcshell-smartcards.ini +index 66f4d842642f..eab7ee368e7c 100644 +--- security/manager/ssl/tests/unit/xpcshell-smartcards.ini ++++ security/manager/ssl/tests/unit/xpcshell-smartcards.ini +@@ -7,6 +7,7 @@ support-files = + + [test_pkcs11_insert_remove.js] + [test_pkcs11_module.js] ++[test_pkcs11_moduleDB.js] + [test_pkcs11_no_events_after_removal.js] + [test_pkcs11_safe_mode.js] + skip-if = coverage # bug 1336728 diff --git a/www/waterfox/files/patch-bug1406474 b/www/waterfox/files/patch-bug1406474 new file mode 100644 index 000000000000..fc2d42261f98 --- /dev/null +++ b/www/waterfox/files/patch-bug1406474 @@ -0,0 +1,37 @@ +commit 78e3035e7b19 +Author: Nathan Froyd <froydnj@mozilla.com> +Date: Mon Oct 9 16:11:10 2017 -0400 + + Bug 1406474 - Provide gfxUserFontSet::Entry with a move constructor. r=heycam, a=ritu + + This change makes moving Entry around more efficient, and also copies + the mAllowedFontSets member as a ride-along bonus fix. + + --HG-- + extra : source : 2b181f6ba9d4c0e82d3abc947b31270114425b5c +--- + gfx/thebes/gfxUserFontSet.h | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git gfx/thebes/gfxUserFontSet.h gfx/thebes/gfxUserFontSet.h +index 1c84ceb128d5..b71219901ca9 100644 +--- gfx/thebes/gfxUserFontSet.h ++++ gfx/thebes/gfxUserFontSet.h +@@ -403,11 +403,12 @@ public: + mPrivate(aKey->mPrivate) + { } + +- Entry(const Entry& aOther) +- : mURI(aOther.mURI), +- mPrincipal(aOther.mPrincipal), +- mFontEntry(aOther.mFontEntry), +- mPrivate(aOther.mPrivate) ++ Entry(Entry&& aOther) ++ : mAllowedFontSets(mozilla::Move(aOther.mAllowedFontSets)), ++ mURI(mozilla::Move(aOther.mURI)), ++ mPrincipal(mozilla::Move(aOther.mPrincipal)), ++ mFontEntry(mozilla::Move(aOther.mFontEntry)), ++ mPrivate(mozilla::Move(aOther.mPrivate)) + { } + + ~Entry() { } diff --git a/www/waterfox/files/patch-bug1406859 b/www/waterfox/files/patch-bug1406859 new file mode 100644 index 000000000000..6f925ac600cf --- /dev/null +++ b/www/waterfox/files/patch-bug1406859 @@ -0,0 +1,50 @@ +commit ab3fe8821636 +Author: Jessica Jong <jjong@mozilla.com> +Date: Thu Oct 19 09:14:56 2017 +0800 + + Bug 1406859 - [DateTimePicker] Let the first picker close gracefully before opening a second picker. r=mconley, a=ritu + + If we're trying to open a picker while one is already open, we should let the + first one close gracefully, that is, we should consume the popuphidden event, + otherwise the event will be fired when we re-add the listeners. + + MozReview-Commit-ID: CGy86le1F4g + + --HG-- + extra : source : 629afbb52163b54ec832d8f83f90bb3bcbe929a2 +--- + toolkit/content/browser-content.js | 8 ++++++++ + toolkit/modules/DateTimePickerHelper.jsm | 1 + + 2 files changed, 9 insertions(+) + +diff --git toolkit/content/browser-content.js toolkit/content/browser-content.js +index ea830c8e8cdb..e5d01bb720f9 100644 +--- toolkit/content/browser-content.js ++++ toolkit/content/browser-content.js +@@ -1790,6 +1790,14 @@ let DateTimePickerListener = { + (aEvent.originalTarget.type == "time" && !this.getTimePickerPref())) { + return; + } ++ ++ if (this._inputElement) { ++ // This happens when we're trying to open a picker when another picker ++ // is still open. We ignore this request to let the first picker ++ // close gracefully. ++ return; ++ } ++ + this._inputElement = aEvent.originalTarget; + this._inputElement.setDateTimePickerState(true); + this.addListeners(); +diff --git toolkit/modules/DateTimePickerHelper.jsm toolkit/modules/DateTimePickerHelper.jsm +index 38e89bd0d160..ad187dab9fed 100644 +--- toolkit/modules/DateTimePickerHelper.jsm ++++ toolkit/modules/DateTimePickerHelper.jsm +@@ -63,6 +63,7 @@ this.DateTimePickerHelper = { + return; + } + this.picker.closePicker(); ++ this.close(); + break; + } + case "FormDateTime:UpdatePicker": { diff --git a/www/waterfox/files/patch-bug1407001 b/www/waterfox/files/patch-bug1407001 new file mode 100644 index 000000000000..577193e4a362 --- /dev/null +++ b/www/waterfox/files/patch-bug1407001 @@ -0,0 +1,33 @@ +commit 979b5671a61f +Author: Ryan Hunt <rhunt@eqrion.net> +Date: Mon Oct 9 12:49:53 2017 -0500 + + Bug 1407001 - Don't reset compositors for composited changed callback when GPUProcessManager is null. r=lsalzman + + MozReview-Commit-ID: 4E31bt3Rzkz + + --HG-- + extra : rebase_source : 84a18ffcc77f37220284679c1dbb916a25524d31 +--- + widget/gtk/nsWindow.cpp | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git widget/gtk/nsWindow.cpp widget/gtk/nsWindow.cpp +index 575dc83d964c..eb2f0e5e95cd 100644 +--- widget/gtk/nsWindow.cpp ++++ widget/gtk/nsWindow.cpp +@@ -5923,7 +5923,13 @@ check_resize_cb (GtkContainer* container, gpointer user_data) + static void + screen_composited_changed_cb (GdkScreen* screen, gpointer user_data) + { +- GPUProcessManager::Get()->ResetCompositors(); ++ // This callback can run before gfxPlatform::Init() in rare ++ // cases involving the profile manager. When this happens, ++ // we have no reason to reset any compositors as graphics ++ // hasn't been initialized yet. ++ if (GPUProcessManager::Get()) { ++ GPUProcessManager::Get()->ResetCompositors(); ++ } + } + + static void diff --git a/www/waterfox/files/patch-bug1407092 b/www/waterfox/files/patch-bug1407092 new file mode 100644 index 000000000000..a7444eb126bb --- /dev/null +++ b/www/waterfox/files/patch-bug1407092 @@ -0,0 +1,28 @@ +commit 573e1d05dfe1 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Tue Oct 10 14:13:29 2017 -0500 + + Bug 1407092 - style: Fix ex computation with more than one operand. r=jdm, a=ritu + + Source-Repo: https://github.com/servo/servo + Source-Revision: b1926b465671ce56474fc24827eb9562ff7b575b + + --HG-- + extra : source : c75889c4efb4b22666b568304eb27fad37fd66b2 +--- + servo/components/style/values/specified/calc.rs | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git servo/components/style/values/specified/calc.rs servo/components/style/values/specified/calc.rs +index 3ac81d5903c9..431248f704de 100644 +--- servo/components/style/values/specified/calc.rs ++++ servo/components/style/values/specified/calc.rs +@@ -372,7 +372,7 @@ impl CalcNode { + ret.em = Some(ret.em.unwrap_or(0.) + em * factor); + } + FontRelativeLength::Ex(ex) => { +- ret.ex = Some(ret.em.unwrap_or(0.) + ex * factor); ++ ret.ex = Some(ret.ex.unwrap_or(0.) + ex * factor); + } + FontRelativeLength::Ch(ch) => { + ret.ch = Some(ret.ch.unwrap_or(0.) + ch * factor); diff --git a/www/waterfox/files/patch-bug1407243 b/www/waterfox/files/patch-bug1407243 new file mode 100644 index 000000000000..08a2baa3bc02 --- /dev/null +++ b/www/waterfox/files/patch-bug1407243 @@ -0,0 +1,31 @@ +commit fb2240799f3c +Author: Jean-Yves Avenard <jyavenard@mozilla.com> +Date: Tue Oct 10 16:14:24 2017 +0200 + + Bug 1407243 - Don't immediately fire canplaythrough for infinite/live streams. r=jwwang, a=ritu + + MozReview-Commit-ID: 2LQFa8PHvO5 + + --HG-- + extra : source : 6f2fa0f0d78132f5411f648f7c787c2aeeffbd69 +--- + dom/media/mediasource/MediaSourceDecoder.cpp | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git dom/media/mediasource/MediaSourceDecoder.cpp dom/media/mediasource/MediaSourceDecoder.cpp +index d85f7ec51226..54c7d79e9bdd 100644 +--- dom/media/mediasource/MediaSourceDecoder.cpp ++++ dom/media/mediasource/MediaSourceDecoder.cpp +@@ -310,11 +310,7 @@ MediaSourceDecoder::CanPlayThroughImpl() + } + TimeUnit duration = TimeUnit::FromSeconds(mMediaSource->Duration()); + auto currentPosition = CurrentPosition(); +- if (duration.IsInfinite()) { +- // We can't make an informed decision and just assume that it's a live +- // stream +- return true; +- } else if (duration <= currentPosition) { ++ if (duration <= currentPosition) { + return true; + } + // If we have data up to the mediasource's duration or 10s ahead, we can diff --git a/www/waterfox/files/patch-bug1407245 b/www/waterfox/files/patch-bug1407245 new file mode 100644 index 000000000000..f59fa4ba2be5 --- /dev/null +++ b/www/waterfox/files/patch-bug1407245 @@ -0,0 +1,34 @@ +commit 3c4493ef2e44 +Author: Ben Kelly <ben@wanderview.com> +Date: Tue Oct 10 13:50:36 2017 -0700 + + Bug 1407245 - Fix service worker update 24-hour time check conversion from microseconds. r=asuth, a=ritu + + --HG-- + extra : source : 412da89cc8e754831e6942b55d3cfd0ea3f1c88b +--- + dom/workers/ServiceWorkerRegistrationInfo.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git dom/workers/ServiceWorkerRegistrationInfo.cpp dom/workers/ServiceWorkerRegistrationInfo.cpp +index 07b9726677cc..beca30d82387 100644 +--- dom/workers/ServiceWorkerRegistrationInfo.cpp ++++ dom/workers/ServiceWorkerRegistrationInfo.cpp +@@ -346,14 +346,14 @@ ServiceWorkerRegistrationInfo::IsLastUpdateCheckTimeOverOneDay() const + } + + const int64_t kSecondsPerDay = 86400; +- const int64_t now = ++ const int64_t nowMicros = + mCreationTime + static_cast<PRTime>((TimeStamp::Now() - + mCreationTimeStamp).ToMicroseconds()); + + // now < mLastUpdateTime if the system time is reset between storing + // and loading mLastUpdateTime from ServiceWorkerRegistrar. +- if (now < mLastUpdateTime || +- (now - mLastUpdateTime) / PR_MSEC_PER_SEC > kSecondsPerDay) { ++ if (nowMicros < mLastUpdateTime || ++ (nowMicros - mLastUpdateTime) / PR_USEC_PER_SEC > kSecondsPerDay) { + return true; + } + return false; diff --git a/www/waterfox/files/patch-bug1407414 b/www/waterfox/files/patch-bug1407414 new file mode 100644 index 000000000000..7c49495f21be --- /dev/null +++ b/www/waterfox/files/patch-bug1407414 @@ -0,0 +1,25 @@ +commit 94ba7703f923 +Author: Jason Orendorff <jorendorff@mozilla.com> +Date: Tue Oct 17 16:25:40 2017 +0100 + + Bug 1407414 - Crash in js::GetOwnPropertyDescriptor. r=bz, a=lizzard + + --HG-- + extra : source : 0181d804e8bf9babc3e91f4fcd7d2cf6491372ab +--- + js/xpconnect/wrappers/XrayWrapper.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git js/xpconnect/wrappers/XrayWrapper.cpp js/xpconnect/wrappers/XrayWrapper.cpp +index c3385511da20..76b29483a020 100644 +--- js/xpconnect/wrappers/XrayWrapper.cpp ++++ js/xpconnect/wrappers/XrayWrapper.cpp +@@ -2167,6 +2167,8 @@ XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext* cx, HandleObject + BaseProxyHandler::GET_PROPERTY_DESCRIPTOR); + RootedObject target(cx, XrayTraits::getTargetObject(wrapper)); + RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper)); ++ if (!holder) ++ return false; + + if (!Traits::singleton.resolveOwnProperty(cx, wrapper, target, holder, id, desc)) + return false; diff --git a/www/waterfox/files/patch-bug1407680 b/www/waterfox/files/patch-bug1407680 new file mode 100644 index 000000000000..bea703455fe6 --- /dev/null +++ b/www/waterfox/files/patch-bug1407680 @@ -0,0 +1,115 @@ +commit 4fc0d0a89efa +Author: Randell Jesup <rjesup@jesup.org> +Date: Tue Oct 17 16:27:20 2017 -0400 + + Bug 1407680 - Set DelayAgnostic and ExtendedFilter options. r=dminor, a=ritu + + This was lost due to API changes in the update to upstream v57 + + --HG-- + extra : source : 123965af3a606397e7b0f5705ae3365ad64a1258 +--- + dom/media/webrtc/MediaEngineWebRTC.cpp | 7 +++++-- + dom/media/webrtc/MediaEngineWebRTC.h | 8 +++++++- + dom/media/webrtc/MediaEngineWebRTCAudio.cpp | 10 +++++++++- + 3 files changed, 21 insertions(+), 4 deletions(-) + +diff --git dom/media/webrtc/MediaEngineWebRTC.cpp dom/media/webrtc/MediaEngineWebRTC.cpp +index 772b9bb6e52f..e8429506dcae 100644 +--- dom/media/webrtc/MediaEngineWebRTC.cpp ++++ dom/media/webrtc/MediaEngineWebRTC.cpp +@@ -111,6 +111,8 @@ MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs) + mVoiceEngine(nullptr), + mAudioInput(nullptr), + mFullDuplex(aPrefs.mFullDuplex), ++ mDelayAgnostic(aPrefs.mDelayAgnostic), ++ mExtendedFilter(aPrefs.mExtendedFilter), + mHasTabVideoSource(false) + { + nsCOMPtr<nsIComponentRegistrar> compMgr; +@@ -294,7 +296,7 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource, + #endif + + if (!mVoiceEngine) { +- mVoiceEngine = webrtc::VoiceEngine::Create(/*mConfig*/); ++ mVoiceEngine = webrtc::VoiceEngine::Create(); + if (!mVoiceEngine) { + return; + } +@@ -367,7 +369,8 @@ MediaEngineWebRTC::EnumerateAudioDevices(dom::MediaSourceEnum aMediaSource, + audioinput = new mozilla::AudioInputCubeb(mVoiceEngine, i); + } + aSource = new MediaEngineWebRTCMicrophoneSource(mVoiceEngine, audioinput, +- i, deviceName, uniqueId); ++ i, deviceName, uniqueId, ++ mDelayAgnostic, mExtendedFilter); + mAudioSources.Put(uuid, aSource); // Hashtable takes ownership. + aASources->AppendElement(aSource); + } +diff --git dom/media/webrtc/MediaEngineWebRTC.h dom/media/webrtc/MediaEngineWebRTC.h +index 6b636adf396d..4567a5c0211a 100644 +--- dom/media/webrtc/MediaEngineWebRTC.h ++++ dom/media/webrtc/MediaEngineWebRTC.h +@@ -501,7 +501,9 @@ public: + mozilla::AudioInput* aAudioInput, + int aIndex, + const char* name, +- const char* uuid); ++ const char* uuid, ++ bool aDelayAgnostic, ++ bool aExtendedFilter); + + void GetName(nsAString& aName) const override; + void GetUUID(nsACString& aUUID) const override; +@@ -624,6 +626,8 @@ private: + + int mCapIndex; + int mChannel; ++ bool mDelayAgnostic; ++ bool mExtendedFilter; + MOZ_INIT_OUTSIDE_CTOR TrackID mTrackID; + bool mStarted; + +@@ -678,6 +682,8 @@ private: + webrtc::VoiceEngine* mVoiceEngine; + RefPtr<mozilla::AudioInput> mAudioInput; + bool mFullDuplex; ++ bool mDelayAgnostic; ++ bool mExtendedFilter; + bool mHasTabVideoSource; + + // Store devices we've already seen in a hashtable for quick return. +diff --git dom/media/webrtc/MediaEngineWebRTCAudio.cpp dom/media/webrtc/MediaEngineWebRTCAudio.cpp +index ff77065b09fa..a8bd52f01b24 100644 +--- dom/media/webrtc/MediaEngineWebRTCAudio.cpp ++++ dom/media/webrtc/MediaEngineWebRTCAudio.cpp +@@ -191,13 +191,17 @@ MediaEngineWebRTCMicrophoneSource::MediaEngineWebRTCMicrophoneSource( + mozilla::AudioInput* aAudioInput, + int aIndex, + const char* name, +- const char* uuid) ++ const char* uuid, ++ bool aDelayAgnostic, ++ bool aExtendedFilter) + : MediaEngineAudioSource(kReleased) + , mVoiceEngine(aVoiceEnginePtr) + , mAudioInput(aAudioInput) + , mMonitor("WebRTCMic.Monitor") + , mCapIndex(aIndex) + , mChannel(-1) ++ , mDelayAgnostic(aDelayAgnostic) ++ , mExtendedFilter(aExtendedFilter) + , mTrackID(TRACK_NONE) + , mStarted(false) + , mSampleFrequency(MediaEngine::DEFAULT_SAMPLE_RATE) +@@ -781,6 +785,10 @@ MediaEngineWebRTCMicrophoneSource::InitEngine() + mVoEBase = webrtc::VoEBase::GetInterface(mVoiceEngine); + + mVoEBase->Init(); ++ webrtc::Config config; ++ config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(mExtendedFilter)); ++ config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(mDelayAgnostic)); ++ mVoEBase->audio_processing()->SetExtraOptions(config); + + mVoERender = webrtc::VoEExternalMedia::GetInterface(mVoiceEngine); + if (mVoERender) { diff --git a/www/waterfox/files/patch-bug1407936 b/www/waterfox/files/patch-bug1407936 new file mode 100644 index 000000000000..72bd6645d546 --- /dev/null +++ b/www/waterfox/files/patch-bug1407936 @@ -0,0 +1,71 @@ +commit 50296b42e3e2 +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Thu Oct 19 19:06:18 2017 +0200 + + Bug 1407936 - Cleaning up QuotaManagar data only when ServiceWorkers are correctly unregistered. r=bkelly, a=ritu + + --HG-- + extra : source : 3624656ebe465779d8ec8fa4103d477a0e725165 + extra : histedit_source : 4a0d0011a098a070d2da7c5288d51c2cbed01e1c +--- + browser/base/content/sanitize.js | 19 ++++++++++++++++--- + dom/interfaces/base/nsIServiceWorkerManager.idl | 3 --- + 2 files changed, 16 insertions(+), 6 deletions(-) + +diff --git browser/base/content/sanitize.js browser/base/content/sanitize.js +index 25c56c47bc2e..27e1343bc89b 100644 +--- browser/base/content/sanitize.js ++++ browser/base/content/sanitize.js +@@ -297,15 +297,28 @@ Sanitizer.prototype = { + Services.obs.notifyObservers(null, "extension:purge-localStorage"); + + // ServiceWorkers ++ let promises = []; + let serviceWorkers = serviceWorkerManager.getAllRegistrations(); + for (let i = 0; i < serviceWorkers.length; i++) { + let sw = serviceWorkers.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo); +- let host = sw.principal.URI.host; +- serviceWorkerManager.removeAndPropagate(host); ++ ++ promises.push(new Promise(resolve => { ++ let unregisterCallback = { ++ unregisterSucceeded: () => { resolve(true); }, ++ // We don't care about failures. ++ unregisterFailed: () => { resolve(true); }, ++ QueryInterface: XPCOMUtils.generateQI( ++ [Ci.nsIServiceWorkerUnregisterCallback]) ++ }; ++ ++ serviceWorkerManager.propagateUnregister(sw.principal, unregisterCallback, sw.scope); ++ })); + } + ++ await Promise.all(promises); ++ + // QuotaManager +- let promises = []; ++ promises = []; + await new Promise(resolve => { + quotaManagerService.getUsage(request => { + if (request.resultCode != Cr.NS_OK) { +diff --git dom/interfaces/base/nsIServiceWorkerManager.idl dom/interfaces/base/nsIServiceWorkerManager.idl +index 6b4505f7e185..42e38f4afceb 100644 +--- dom/interfaces/base/nsIServiceWorkerManager.idl ++++ dom/interfaces/base/nsIServiceWorkerManager.idl +@@ -186,16 +186,13 @@ interface nsIServiceWorkerManager : nsISupports + // Testing + DOMString getScopeForUrl(in nsIPrincipal aPrincipal, in DOMString aPath); + +- // Note: This is meant to be used only by about:serviceworkers. + // It returns an array of nsIServiceWorkerRegistrationInfos. + nsIArray getAllRegistrations(); + +- // Note: This is meant to be used only by about:serviceworkers. + // It calls softUpdate() for each child process. + [implicit_jscontext] void propagateSoftUpdate(in jsval aOriginAttributes, + in DOMString aScope); + +- // Note: This is meant to be used only by about:serviceworkers. + // It calls unregister() in each child process. The callback is used to + // inform when unregister() is completed on the current process. + void propagateUnregister(in nsIPrincipal aPrincipal, diff --git a/www/waterfox/files/patch-bug1408017 b/www/waterfox/files/patch-bug1408017 new file mode 100644 index 000000000000..90358c9ccb59 --- /dev/null +++ b/www/waterfox/files/patch-bug1408017 @@ -0,0 +1,40 @@ +commit 5738242a26f0 +Author: Andrew McCreight <continuation@gmail.com> +Date: Thu Oct 26 16:47:27 2017 -0400 + + Bug 1408017 - Clear gStartupCacheWrapper in the dtor. r=froydnj +--- + startupcache/StartupCache.cpp | 6 ++++++ + startupcache/StartupCache.h | 2 +- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git startupcache/StartupCache.cpp startupcache/StartupCache.cpp +index 895696d854eb..c84da5c16d41 100644 +--- startupcache/StartupCache.cpp ++++ startupcache/StartupCache.cpp +@@ -700,6 +700,12 @@ StartupCacheWrapper* StartupCacheWrapper::gStartupCach + + NS_IMPL_ISUPPORTS(StartupCacheWrapper, nsIStartupCache) + ++StartupCacheWrapper::~StartupCacheWrapper() ++{ ++ MOZ_ASSERT(gStartupCacheWrapper == this); ++ gStartupCacheWrapper = nullptr; ++} ++ + StartupCacheWrapper* StartupCacheWrapper::GetSingleton() + { + if (!gStartupCacheWrapper) +diff --git startupcache/StartupCache.h startupcache/StartupCache.h +index a7618415dd1f..f8994749aa5c 100644 +--- startupcache/StartupCache.h ++++ startupcache/StartupCache.h +@@ -209,7 +209,7 @@ class StartupCacheDebugOutputStream final + class StartupCacheWrapper final + : public nsIStartupCache + { +- ~StartupCacheWrapper() {} ++ ~StartupCacheWrapper(); + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSISTARTUPCACHE diff --git a/www/waterfox/files/patch-bug1408276 b/www/waterfox/files/patch-bug1408276 new file mode 100644 index 000000000000..e0e434921252 --- /dev/null +++ b/www/waterfox/files/patch-bug1408276 @@ -0,0 +1,170 @@ +commit a9bc6108422a +Author: Karl Tomlinson <karlt+@karlt.net> +Date: Tue Oct 17 18:14:43 2017 +1300 + + Bug 1408276 - Move to LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP at end of iteration. r=padenot, a=gchang + + MozReview-Commit-ID: GbfIOPZPuGu + + --HG-- + extra : rebase_source : acc2bcee9a36d2b8f18826f08825895de5df0c1e +--- + dom/media/GraphDriver.cpp | 27 +++++++++++++++++---------- + dom/media/MediaStreamGraph.cpp | 32 +++++++++++++++++++++----------- + dom/media/MediaStreamGraphImpl.h | 12 +++++++++++- + 3 files changed, 49 insertions(+), 22 deletions(-) + +diff --git dom/media/GraphDriver.cpp dom/media/GraphDriver.cpp +index 7f6f386fdaca..13944338e3d7 100644 +--- dom/media/GraphDriver.cpp ++++ dom/media/GraphDriver.cpp +@@ -284,8 +284,7 @@ SystemClockDriver::IsFallback() + void + ThreadedDriver::RunThread() + { +- bool stillProcessing = true; +- while (stillProcessing) { ++ while (true) { + mIterationStart = IterationEnd(); + mIterationEnd += GetIntervalForIteration(); + +@@ -324,10 +323,16 @@ ThreadedDriver::RunThread() + (long)stateComputedTime, + (long)nextStateComputedTime)); + +- stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime); ++ bool stillProcessing = mGraphImpl->OneIteration(nextStateComputedTime); + ++ if (!stillProcessing) { ++ // Enter shutdown mode. The stable-state handler will detect this ++ // and complete shutdown if the graph does not get restarted. ++ mGraphImpl->SignalMainThreadCleanup(); ++ return; ++ } + MonitorAutoLock lock(GraphImpl()->GetMonitor()); +- if (NextDriver() && stillProcessing) { ++ if (NextDriver()) { + LOG(LogLevel::Debug, ("Switching to AudioCallbackDriver")); + RemoveCallback(); + NextDriver()->SetGraphTime(this, mIterationStart, mIterationEnd); +@@ -1009,13 +1014,20 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, + mGraphImpl->NotifyOutputData(aOutputBuffer, static_cast<size_t>(aFrames), + mSampleRate, mOutputChannels); + ++ if (!stillProcessing) { ++ // Enter shutdown mode. The stable-state handler will detect this ++ // and complete shutdown if the graph does not get restarted. ++ mGraphImpl->SignalMainThreadCleanup(); ++ return aFrames - 1; ++ } ++ + bool switching = false; + { + MonitorAutoLock mon(mGraphImpl->GetMonitor()); + switching = !!NextDriver(); + } + +- if (switching && stillProcessing) { ++ if (switching) { + // If the audio stream has not been started by the previous driver or + // the graph itself, keep it alive. + MonitorAutoLock mon(mGraphImpl->GetMonitor()); +@@ -1032,11 +1044,6 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, + return aFrames - 1; + } + +- if (!stillProcessing) { +- LOG(LogLevel::Debug, +- ("Stopping audio thread for MediaStreamGraph %p", this)); +- return aFrames - 1; +- } + return aFrames; + } + +diff --git dom/media/MediaStreamGraph.cpp dom/media/MediaStreamGraph.cpp +index 3a742aafe9b2..6420e038a8fe 100644 +--- dom/media/MediaStreamGraph.cpp ++++ dom/media/MediaStreamGraph.cpp +@@ -1193,11 +1193,13 @@ MediaStreamGraphImpl::PrepareUpdatesToMainThreadState(bool aFinalUpdate) + } + } + +- // Don't send the message to the main thread if it's not going to have +- // any work to do. +- if (aFinalUpdate || +- !mUpdateRunnables.IsEmpty() || +- !mStreamUpdates.IsEmpty()) { ++ // If this is the final update, then a stable state event will soon be ++ // posted just before this thread finishes, and so there is no need to also ++ // post here. ++ if (!aFinalUpdate && ++ // Don't send the message to the main thread if it's not going to have ++ // any work to do. ++ !(mUpdateRunnables.IsEmpty() && mStreamUpdates.IsEmpty())) { + EnsureStableStateEventPosted(); + } + } +@@ -1430,12 +1432,7 @@ MediaStreamGraphImpl::UpdateMainThreadState() + (IsEmpty() && mBackMessageQueue.IsEmpty()); + PrepareUpdatesToMainThreadState(finalUpdate); + if (finalUpdate) { +- // Enter shutdown mode. The stable-state handler will detect this +- // and complete shutdown. Destroy any streams immediately. +- LOG(LogLevel::Debug, +- ("MediaStreamGraph %p waiting for main thread cleanup", this)); +- // We'll shut down this graph object if it does not get restarted. +- mLifecycleState = LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP; ++ // Enter shutdown mode when this iteration is completed. + // No need to Destroy streams here. The main-thread owner of each + // stream is responsible for calling Destroy on them. + return false; +@@ -1861,6 +1858,19 @@ MediaStreamGraphImpl::EnsureStableStateEventPosted() + mAbstractMainThread->Dispatch(event.forget()); + } + ++void ++MediaStreamGraphImpl::SignalMainThreadCleanup() ++{ ++ MOZ_ASSERT(mDriver->OnThread()); ++ ++ MonitorAutoLock lock(mMonitor); ++ LOG(LogLevel::Debug, ++ ("MediaStreamGraph %p waiting for main thread cleanup", this)); ++ mLifecycleState = ++ MediaStreamGraphImpl::LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP; ++ EnsureStableStateEventPosted(); ++} ++ + void + MediaStreamGraphImpl::AppendMessage(UniquePtr<ControlMessage> aMessage) + { +diff --git dom/media/MediaStreamGraphImpl.h dom/media/MediaStreamGraphImpl.h +index dfea12bca3a8..dce49da39166 100644 +--- dom/media/MediaStreamGraphImpl.h ++++ dom/media/MediaStreamGraphImpl.h +@@ -197,6 +197,14 @@ public: + */ + bool OneIteration(GraphTime aStateEnd); + ++ /** ++ * Called from the driver, when the graph thread is about to stop, to tell ++ * the main thread to attempt to begin cleanup. The main thread may either ++ * shutdown or revive the graph depending on whether it receives new ++ * messages. ++ */ ++ void SignalMainThreadCleanup(); ++ + bool Running() const + { + mMonitor.AssertCurrentThreadOwns(); +@@ -720,7 +728,9 @@ public: + LIFECYCLE_WAITING_FOR_STREAM_DESTRUCTION + }; + /** +- * Modified only on the main thread in mMonitor. ++ * Modified only in mMonitor. Transitions to ++ * LIFECYCLE_WAITING_FOR_MAIN_THREAD_CLEANUP occur on the graph thread at ++ * the end of an iteration. All other transitions occur on the main thread. + */ + LifecycleState mLifecycleState; + /** diff --git a/www/waterfox/files/patch-bug1408397 b/www/waterfox/files/patch-bug1408397 new file mode 100644 index 000000000000..468a92d75db0 --- /dev/null +++ b/www/waterfox/files/patch-bug1408397 @@ -0,0 +1,185 @@ +commit 97e7c363f664 +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Tue Oct 17 13:17:51 2017 +0200 + + Bug 1408397 - FileReader should not use a bufferStream together with an async inputStream. r=smaug, a=ritu + + --HG-- + extra : source : 61118e8a62afbc51169515f50c3b12b334219aa3 +--- + dom/file/FileReader.cpp | 93 +++++++++++++++++++++++-------------------------- + dom/file/FileReader.h | 1 - + 2 files changed, 44 insertions(+), 50 deletions(-) + +diff --git dom/file/FileReader.cpp dom/file/FileReader.cpp +index 17d38f293519..ccd2a43986ef 100644 +--- dom/file/FileReader.cpp ++++ dom/file/FileReader.cpp +@@ -19,6 +19,7 @@ + #include "mozilla/dom/FileReaderBinding.h" + #include "mozilla/dom/ProgressEvent.h" + #include "mozilla/Encoding.h" ++#include "nsAlgorithm.h" + #include "nsCycleCollectionParticipant.h" + #include "nsDOMJSUtils.h" + #include "nsError.h" +@@ -187,27 +188,6 @@ FileReader::GetResult(JSContext* aCx, + } + } + +-static nsresult +-ReadFuncBinaryString(nsIInputStream* in, +- void* closure, +- const char* fromRawSegment, +- uint32_t toOffset, +- uint32_t count, +- uint32_t *writeCount) +-{ +- char16_t* dest = static_cast<char16_t*>(closure) + toOffset; +- char16_t* end = dest + count; +- const unsigned char* source = (const unsigned char*)fromRawSegment; +- while (dest != end) { +- *dest = *source; +- ++dest; +- ++source; +- } +- *writeCount = count; +- +- return NS_OK; +-} +- + void + FileReader::OnLoadEndArrayBuffer() + { +@@ -290,32 +270,56 @@ FileReader::DoReadData(uint64_t aCount) + + if (mDataFormat == FILE_AS_BINARY) { + //Continuously update our binary string as data comes in +- uint32_t oldLen = mResult.Length(); +- MOZ_ASSERT(mResult.Length() == mDataLen, "unexpected mResult length"); +- if (uint64_t(oldLen) + aCount > UINT32_MAX) ++ CheckedInt<uint64_t> size = mResult.Length(); ++ size += aCount; ++ ++ if (!size.isValid() || ++ size.value() > UINT32_MAX || ++ size.value() > mTotal) { + return NS_ERROR_OUT_OF_MEMORY; +- char16_t *buf = nullptr; +- mResult.GetMutableData(&buf, oldLen + aCount, fallible); +- NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY); ++ } + +- nsresult rv; ++ uint32_t oldLen = mResult.Length(); ++ MOZ_ASSERT(oldLen == mDataLen, "unexpected mResult length"); ++ ++ char16_t* dest = nullptr; ++ mResult.GetMutableData(&dest, size.value(), fallible); ++ NS_ENSURE_TRUE(dest, NS_ERROR_OUT_OF_MEMORY); ++ ++ dest += oldLen; ++ ++ while (aCount > 0) { ++ char tmpBuffer[4096]; ++ uint32_t minCount = ++ XPCOM_MIN(aCount, static_cast<uint64_t>(sizeof(tmpBuffer))); ++ uint32_t read; ++ ++ nsresult rv = mAsyncStream->Read(tmpBuffer, minCount, &read); ++ if (rv == NS_BASE_STREAM_CLOSED) { ++ rv = NS_OK; ++ } + +- // nsFileStreams do not implement ReadSegment. In case here we are dealing +- // with a nsIAsyncInputStream, in content process, we need to wrap a +- // nsIBufferedInputStream around it. +- if (!mBufferedStream) { +- rv = NS_NewBufferedInputStream(getter_AddRefs(mBufferedStream), +- mAsyncStream, 8192); + NS_ENSURE_SUCCESS(rv, rv); +- } + +- rv = mBufferedStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, +- aCount, &bytesRead); +- if (NS_WARN_IF(NS_FAILED(rv))) { +- return rv; ++ if (read == 0) { ++ // The stream finished too early. ++ return NS_ERROR_OUT_OF_MEMORY; ++ } ++ ++ char16_t* end = dest + read; ++ const unsigned char* source = (const unsigned char*)tmpBuffer; ++ while (dest != end) { ++ *dest = *source; ++ ++dest; ++ ++source; ++ } ++ ++ aCount -= read; ++ bytesRead += read; + } + +- mResult.Truncate(oldLen + bytesRead); ++ MOZ_ASSERT(size.value() == oldLen + bytesRead); ++ mResult.Truncate(size.value()); + } + else { + CheckedInt<uint64_t> size = mDataLen; +@@ -363,7 +367,6 @@ FileReader::ReadFileContent(Blob& aBlob, + mResultArrayBuffer = nullptr; + + mAsyncStream = nullptr; +- mBufferedStream = nullptr; + + mTransferred = 0; + mTotal = 0; +@@ -557,7 +560,6 @@ FileReader::FreeDataAndDispatchSuccess() + FreeFileData(); + mResult.SetIsVoid(false); + mAsyncStream = nullptr; +- mBufferedStream = nullptr; + mBlob = nullptr; + + // Dispatch event to signify end of a successful operation +@@ -573,7 +575,6 @@ FileReader::FreeDataAndDispatchError() + FreeFileData(); + mResult.SetIsVoid(true); + mAsyncStream = nullptr; +- mBufferedStream = nullptr; + mBlob = nullptr; + + // Dispatch error event to signify load failure +@@ -768,7 +769,6 @@ FileReader::Abort() + mResultArrayBuffer = nullptr; + + mAsyncStream = nullptr; +- mBufferedStream = nullptr; + mBlob = nullptr; + + //Clean up memory buffer +@@ -822,11 +822,6 @@ FileReader::Shutdown() + mAsyncStream = nullptr; + } + +- if (mBufferedStream) { +- mBufferedStream->Close(); +- mBufferedStream = nullptr; +- } +- + FreeFileData(); + mResultArrayBuffer = nullptr; + +diff --git dom/file/FileReader.h dom/file/FileReader.h +index 32ea1f9bc329..7aa52107dc46 100644 +--- dom/file/FileReader.h ++++ dom/file/FileReader.h +@@ -183,7 +183,6 @@ private: + bool mTimerIsActive; + + nsCOMPtr<nsIAsyncInputStream> mAsyncStream; +- nsCOMPtr<nsIInputStream> mBufferedStream; + + RefPtr<DOMError> mError; + diff --git a/www/waterfox/files/patch-bug1408631 b/www/waterfox/files/patch-bug1408631 new file mode 100644 index 000000000000..ff58eaad4fbc --- /dev/null +++ b/www/waterfox/files/patch-bug1408631 @@ -0,0 +1,174 @@ +commit 48a63f5601f6 +Author: dimi <dlee@mozilla.com> +Date: Fri Oct 20 10:18:59 2017 +0800 + + Bug 1408631 - Release SafeBrowsing lookupcache in worker thread while shutdown. r=francois + + MozReview-Commit-ID: HuPUyIDFLPX + + --HG-- + extra : rebase_source : d6e4f5bbcf96c97541792e23447f0810150c5ac9 +--- + toolkit/components/url-classifier/Classifier.cpp | 13 +++++--- + .../url-classifier/nsUrlClassifierDBService.cpp | 37 ++++++++++++++++++++++ + .../url-classifier/nsUrlClassifierDBService.h | 5 +++ + .../url-classifier/nsUrlClassifierProxies.cpp | 10 ++++++ + .../url-classifier/nsUrlClassifierProxies.h | 1 + + 5 files changed, 62 insertions(+), 4 deletions(-) + +diff --git toolkit/components/url-classifier/Classifier.cpp toolkit/components/url-classifier/Classifier.cpp +index 404e31e2421e..9946469268fa 100644 +--- toolkit/components/url-classifier/Classifier.cpp ++++ toolkit/components/url-classifier/Classifier.cpp +@@ -267,6 +267,8 @@ Classifier::Open(nsIFile& aCacheDirectory) + void + Classifier::Close() + { ++ // Close will be called by PreShutdown, so it is important to note that ++ // things put here should not affect an ongoing update thread. + DropStores(); + } + +@@ -1428,10 +1430,8 @@ Classifier::UpdateCache(TableUpdate* aUpdate) + LookupCache * + Classifier::GetLookupCache(const nsACString& aTable, bool aForUpdate) + { +- if (aForUpdate) { +- MOZ_ASSERT(NS_GetCurrentThread() == mUpdateThread, +- "GetLookupCache(aForUpdate==true) can only be called on update thread."); +- } ++ // GetLookupCache(aForUpdate==true) can only be called on update thread. ++ MOZ_ASSERT_IF(aForUpdate, NS_GetCurrentThread() == mUpdateThread); + + nsTArray<LookupCache*>& lookupCaches = aForUpdate ? mNewLookupCaches + : mLookupCaches; +@@ -1444,6 +1444,11 @@ Classifier::GetLookupCache(const nsACString& aTable, bool aForUpdate) + } + } + ++ // We don't want to create lookupcache when shutdown is already happening. ++ if (nsUrlClassifierDBService::ShutdownHasStarted()) { ++ return nullptr; ++ } ++ + // TODO : Bug 1302600, It would be better if we have a more general non-main + // thread method to convert table name to protocol version. Currently + // we can only know this by checking if the table name ends with '-proto'. +diff --git toolkit/components/url-classifier/nsUrlClassifierDBService.cpp toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +index 78dbfaeaf046..e1a1be065aaf 100644 +--- toolkit/components/url-classifier/nsUrlClassifierDBService.cpp ++++ toolkit/components/url-classifier/nsUrlClassifierDBService.cpp +@@ -817,6 +817,20 @@ nsUrlClassifierDBServiceWorker::CloseDb() + return NS_OK; + } + ++nsresult ++nsUrlClassifierDBServiceWorker::PreShutdown() ++{ ++ if (mClassifier) { ++ // Classifier close will release all lookup caches which may be a time-consuming job. ++ // See Bug 1408631. ++ mClassifier->Close(); ++ } ++ ++ // WARNING: nothing we put here should affect an ongoing update thread. When in doubt, ++ // put things in Shutdown() instead. ++ return NS_OK; ++} ++ + nsresult + nsUrlClassifierDBServiceWorker::CacheCompletions(CacheResultArray *results) + { +@@ -2427,6 +2441,13 @@ nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic, + } else if (!strcmp(aTopic, "quit-application")) { + // Tell the update thread to finish as soon as possible. + gShuttingDownThread = true; ++ ++ // The code in ::Shutdown() is run on a 'profile-before-change' event and ++ // ensures that objects are freed by blocking on this freeing. ++ // We can however speed up the shutdown time by using the worker thread to ++ // release, in an earlier event, any objects that cannot affect an ongoing ++ // update on the update thread. ++ PreShutdown(); + } else if (!strcmp(aTopic, "profile-before-change")) { + gShuttingDownThread = true; + Shutdown(); +@@ -2437,6 +2458,22 @@ nsUrlClassifierDBService::Observe(nsISupports *aSubject, const char *aTopic, + return NS_OK; + } + ++// Post a PreShutdown task to worker thread to release objects without blocking ++// main-thread. Notice that shutdown process may still be blocked by PreShutdown task ++// when ::Shutdown() is executed and synchronously waits for worker thread to finish ++// PreShutdown event. ++nsresult ++nsUrlClassifierDBService::PreShutdown() ++{ ++ MOZ_ASSERT(XRE_IsParentProcess()); ++ ++ if (mWorkerProxy) { ++ mWorkerProxy->PreShutdown(); ++ } ++ ++ return NS_OK; ++} ++ + // Join the background thread if it exists. + nsresult + nsUrlClassifierDBService::Shutdown() +diff --git toolkit/components/url-classifier/nsUrlClassifierDBService.h toolkit/components/url-classifier/nsUrlClassifierDBService.h +index a4c5952e91bb..9d9671d9d8fa 100644 +--- toolkit/components/url-classifier/nsUrlClassifierDBService.h ++++ toolkit/components/url-classifier/nsUrlClassifierDBService.h +@@ -140,6 +140,9 @@ private: + nsIUrlClassifierCallback* c, + bool forceCheck, bool *didCheck); + ++ // Post an event to worker thread to release objects when receive 'quit-application' ++ nsresult PreShutdown(); ++ + // Close db connection and join the background thread if it exists. + nsresult Shutdown(); + +@@ -220,6 +223,8 @@ public: + // Provide a way to forcibly close the db connection. + nsresult GCC_MANGLING_WORKAROUND CloseDb(); + ++ nsresult GCC_MANGLING_WORKAROUND PreShutdown(); ++ + nsresult CacheCompletions(CacheResultArray * aEntries); + + // Used to probe the state of the worker thread. When the update begins, +diff --git toolkit/components/url-classifier/nsUrlClassifierProxies.cpp toolkit/components/url-classifier/nsUrlClassifierProxies.cpp +index 1af4f9266aeb..38e294df7320 100644 +--- toolkit/components/url-classifier/nsUrlClassifierProxies.cpp ++++ toolkit/components/url-classifier/nsUrlClassifierProxies.cpp +@@ -214,6 +214,16 @@ UrlClassifierDBServiceWorkerProxy::CloseDb() + return DispatchToWorkerThread(r); + } + ++nsresult ++UrlClassifierDBServiceWorkerProxy::PreShutdown() ++{ ++ nsCOMPtr<nsIRunnable> r = ++ NewRunnableMethod("nsUrlClassifierDBServiceWorker::PreShutdown", ++ mTarget, ++ &nsUrlClassifierDBServiceWorker::PreShutdown); ++ return DispatchToWorkerThread(r); ++} ++ + nsresult + UrlClassifierDBServiceWorkerProxy::CacheCompletions(CacheResultArray * aEntries) + { +diff --git toolkit/components/url-classifier/nsUrlClassifierProxies.h toolkit/components/url-classifier/nsUrlClassifierProxies.h +index f8cf5229e1ca..39cf47f837a2 100644 +--- toolkit/components/url-classifier/nsUrlClassifierProxies.h ++++ toolkit/components/url-classifier/nsUrlClassifierProxies.h +@@ -229,6 +229,7 @@ public: + + nsresult OpenDb(); + nsresult CloseDb(); ++ nsresult PreShutdown(); + + nsresult CacheCompletions(mozilla::safebrowsing::CacheResultArray * aEntries); + diff --git a/www/waterfox/files/patch-bug1408672 b/www/waterfox/files/patch-bug1408672 new file mode 100644 index 000000000000..74c3261b9c3c --- /dev/null +++ b/www/waterfox/files/patch-bug1408672 @@ -0,0 +1,37 @@ +commit fe19ce17d4f9 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Sat Oct 14 10:50:00 2017 -0400 + + Bug 1408672 - Disable the hover / active quirk for invalidation. r=heycam, a=ritu + + MozReview-Commit-ID: 6wlDm8cNEYD +--- + servo/components/selectors/matching.rs | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git servo/components/selectors/matching.rs servo/components/selectors/matching.rs +index ff0dd40b484c..c6c2db3c4719 100644 +--- servo/components/selectors/matching.rs ++++ servo/components/selectors/matching.rs +@@ -393,7 +393,9 @@ pub fn matches_selector<E, F>(selector: &Selector<E::Impl>, + let iter = if offset == 0 { + selector.iter() + } else { +- selector.iter_from(offset) ++ let iter = selector.iter_from(offset); ++ local_context.note_position(&iter); ++ iter + }; + matches_complex_selector(iter, element, &mut local_context, flags_setter) + } +@@ -432,6 +434,10 @@ where + } + + let mut local_context = LocalMatchingContext::new(context, selector); ++ // Disable the hover quirk here, since we're in a random position inside the ++ // selector, and this is only used for invalidation, so incorrectly ++ // returning true doesn't affect correctness, only does a bit more work. ++ local_context.hover_active_quirk_disabled = true; + for component in selector.iter_raw_parse_order_from(from_offset - 1) { + if matches!(*component, Component::Combinator(..)) { + return CompoundSelectorMatchingResult::Matched { diff --git a/www/waterfox/files/patch-bug1408990 b/www/waterfox/files/patch-bug1408990 new file mode 100644 index 000000000000..9c089b728499 --- /dev/null +++ b/www/waterfox/files/patch-bug1408990 @@ -0,0 +1,34 @@ +commit 53a3958e0a76 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Sat Oct 28 00:15:01 2017 +0200 + + Bug 1408990 - Only add the entry to the performance object if the loading document's principal is the same as the triggering principal. r=bz, r=dragana, a=lizzard + + MozReview-Commit-ID: 7o8XKHioP1p + + --HG-- + extra : rebase_source : 33d4044b4901cee460cc69a0bae1fe0e84dab2aa + extra : source : ff9e841ff8544053f184d2e425500d5dd13ee14d +--- + netwerk/protocol/http/HttpBaseChannel.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git netwerk/protocol/http/HttpBaseChannel.cpp netwerk/protocol/http/HttpBaseChannel.cpp +index 8a5c4d8d9f45..16e59241e2fc 100644 +--- netwerk/protocol/http/HttpBaseChannel.cpp ++++ netwerk/protocol/http/HttpBaseChannel.cpp +@@ -4088,6 +4088,14 @@ HttpBaseChannel::GetPerformance() + return nullptr; + } + ++ // We only add to the document's performance object if it has the same ++ // principal as the one triggering the load. This is to prevent navigations ++ // triggered _by_ the iframe from showing up in the parent document's ++ // performance entries if they have different origins. ++ if (!mLoadInfo->TriggeringPrincipal()->Equals(loadingDocument->NodePrincipal())) { ++ return nullptr; ++ } ++ + nsCOMPtr<nsPIDOMWindowInner> innerWindow = loadingDocument->GetInnerWindow(); + if (!innerWindow) { + return nullptr; diff --git a/www/waterfox/files/patch-bug1409101 b/www/waterfox/files/patch-bug1409101 new file mode 100644 index 000000000000..3fb2198eae4f --- /dev/null +++ b/www/waterfox/files/patch-bug1409101 @@ -0,0 +1,23 @@ +commit d4e320f4bf02 +Author: Jason Laster <jason.laster.11@gmail.com> +Date: Thu Oct 19 07:57:00 2017 -0400 + + Bug 1409101 - Editor is occasionally empty. r=jdescottes, a=ritu +--- + devtools/client/debugger/new/debugger.js | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git devtools/client/debugger/new/debugger.js devtools/client/debugger/new/debugger.js +index a96351f65acf..dd8b81c06aec 100644 +--- devtools/client/debugger/new/debugger.js ++++ devtools/client/debugger/new/debugger.js +@@ -24187,6 +24187,9 @@ return /******/ (function(modules) { // webpackBootstrap + var selectedSource = nextProps.selectedSource, + selectedLocation = nextProps.selectedLocation; + ++ if (!this.state.editor) { ++ return; ++ } + + if (nextProps.startPanelSize !== this.props.startPanelSize || nextProps.endPanelSize !== this.props.endPanelSize) { + this.state.editor.codeMirror.setSize(); diff --git a/www/waterfox/files/patch-bug1409277 b/www/waterfox/files/patch-bug1409277 new file mode 100644 index 000000000000..aab7c36d471c --- /dev/null +++ b/www/waterfox/files/patch-bug1409277 @@ -0,0 +1,38 @@ +commit 4a74980d5d86 +Author: J. Ryan Stinnett <jryans@gmail.com> +Date: Fri Oct 20 15:24:51 2017 -0500 + + Bug 1409277 - Ignore non-URLs for background pres attr. r=manishearth, a=ritu + + Check background attribute values for the same types (URL, image) in Stylo mode + as we do in Gecko mode. + + In particular, this ignores the edge case of the empty attribute, which comes + through as a string value type, and leads Stylo to trigger a load of the page + itself as the background image (since the empty URL is interpreted as relative + to the page). + + MozReview-Commit-ID: CUhq5nS8kVw + + --HG-- + extra : source : 1fe7b56a29c6a2cac69fc986c5fb4b99a92d7781 + extra : histedit_source : cc3086f60235d56bb69368fb754fd61c3dffe86f +--- + layout/style/ServoSpecifiedValues.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git layout/style/ServoSpecifiedValues.cpp layout/style/ServoSpecifiedValues.cpp +index bb8d425316b0..c374a6061ac9 100644 +--- layout/style/ServoSpecifiedValues.cpp ++++ layout/style/ServoSpecifiedValues.cpp +@@ -121,6 +121,10 @@ ServoSpecifiedValues::SetTextDecorationColorOverride() + void + ServoSpecifiedValues::SetBackgroundImage(nsAttrValue& aValue) + { ++ if (aValue.Type() != nsAttrValue::eURL && ++ aValue.Type() != nsAttrValue::eImage) { ++ return; ++ } + nsAutoString str; + aValue.ToString(str); + Servo_DeclarationBlock_SetBackgroundImage( diff --git a/www/waterfox/files/patch-bug1409496 b/www/waterfox/files/patch-bug1409496 new file mode 100644 index 000000000000..87f931c1d1a6 --- /dev/null +++ b/www/waterfox/files/patch-bug1409496 @@ -0,0 +1,25 @@ +commit bd6a81ae5873 +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Wed Oct 25 19:14:34 2017 +0200 + + Bug 1409496 - Cleaning data per domain, must delete localStorage data. r=asuth, a=lizzard + + --HG-- + extra : source : 6019c89b317d960c1c323dc2c037d5e65414fde2 +--- + browser/components/preferences/SiteDataManager.jsm | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git browser/components/preferences/SiteDataManager.jsm browser/components/preferences/SiteDataManager.jsm +index 8f2ac2a34188..3f7cc19ffbaa 100644 +--- browser/components/preferences/SiteDataManager.jsm ++++ browser/components/preferences/SiteDataManager.jsm +@@ -217,6 +217,8 @@ this.SiteDataManager = { + cookie.host, cookie.name, cookie.path, false, cookie.originAttributes); + } + } ++ ++ Services.obs.notifyObservers(null, "browser:purge-domain-data", principal.URI.host); + } + }, + diff --git a/www/waterfox/files/patch-bug1409649 b/www/waterfox/files/patch-bug1409649 new file mode 100644 index 000000000000..f2dd8edf8d43 --- /dev/null +++ b/www/waterfox/files/patch-bug1409649 @@ -0,0 +1,34 @@ +commit 259b43dfa9cd +Author: JW Wang <jwwang@mozilla.com> +Date: Wed Oct 18 16:08:33 2017 +0800 + + Bug 1409649 - Shut down the decoder when MEDIA_ERR_ABORTED is received. r=gerald, a=ritu + + http://searchfox.org/mozilla-central/rev/dca019c94bf3a840ed7ff50261483410cfece24f/dom/html/HTMLMediaElement.cpp#1395-1400 + + We need to shut down the decoder after setting network state to EMPTY. + Otherwise the decoder will keep loading and change ready state to HAVE_METADATA + or greater and then fail the assertion in AssertReadyStateIsNothing(). + + MozReview-Commit-ID: FpMDVAJHTS5 + + --HG-- + extra : source : 6a815fb0b667075041404ebd0b1ee7b87f46e3a2 +--- + dom/html/HTMLMediaElement.cpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp +index d1f12e7bceed..5d51851047cf 100644 +--- dom/html/HTMLMediaElement.cpp ++++ dom/html/HTMLMediaElement.cpp +@@ -1376,6 +1376,9 @@ public: + mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("abort")); + mOwner->ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_EMPTY); + mOwner->DispatchAsyncEvent(NS_LITERAL_STRING("emptied")); ++ if (mOwner->mDecoder) { ++ mOwner->ShutdownDecoder(); ++ } + } else if (aErrorCode == MEDIA_ERR_SRC_NOT_SUPPORTED) { + mOwner->ChangeNetworkState(nsIDOMHTMLMediaElement::NETWORK_NO_SOURCE); + } else { diff --git a/www/waterfox/files/patch-bug1409951 b/www/waterfox/files/patch-bug1409951 new file mode 100644 index 000000000000..22c8398360bb --- /dev/null +++ b/www/waterfox/files/patch-bug1409951 @@ -0,0 +1,177 @@ +commit d5562dbcfd63 +Author: Henri Sivonen <hsivonen@hsivonen.fi> +Date: Fri Dec 1 10:45:25 2017 -0500 + + Bug 1409951 - Use a stack to end serializer contexts instead of recomputing them. r=smaug, a=gchang + + MozReview-Commit-ID: FOd8AUmtYyA + + --HG-- + extra : rebase_source : 1f02ebc32fe80591d617f27ec70094a109ead2b0 + extra : source : b0a3a621f5c85b5e9a4eb97de77fcb2558ac17c6 +--- + dom/base/nsDocumentEncoder.cpp | 56 +++++++++++++++++++------------------- + dom/base/nsPlainTextSerializer.cpp | 1 + + 2 files changed, 29 insertions(+), 28 deletions(-) + +diff --git dom/base/nsDocumentEncoder.cpp dom/base/nsDocumentEncoder.cpp +index 5912d67da86e..2fb488750366 100644 +--- dom/base/nsDocumentEncoder.cpp ++++ dom/base/nsDocumentEncoder.cpp +@@ -49,6 +49,7 @@ + #include "mozilla/dom/Element.h" + #include "mozilla/dom/ShadowRoot.h" + #include "nsLayoutUtils.h" ++#include "mozilla/ScopeExit.h" + + using namespace mozilla; + using namespace mozilla::dom; +@@ -92,8 +93,8 @@ protected: + int32_t aDepth); + nsresult SerializeRangeContextStart(const nsTArray<nsINode*>& aAncestorArray, + nsAString& aString); +- nsresult SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray, +- nsAString& aString); ++ nsresult SerializeRangeContextEnd(nsAString& aString); ++ + virtual int32_t + GetImmediateContextCount(const nsTArray<nsINode*>& aAncestorArray) + { +@@ -185,6 +186,7 @@ protected: + AutoTArray<int32_t, 8> mStartOffsets; + AutoTArray<nsIContent*, 8> mEndNodes; + AutoTArray<int32_t, 8> mEndOffsets; ++ AutoTArray<AutoTArray<nsINode*, 8>, 8> mRangeContexts; + // Whether the serializer cares about being notified to scan elements to + // keep track of whether they are preformatted. This stores the out + // argument of nsIContentSerializer::Init(). +@@ -874,6 +876,9 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncesto + if (mDisableContextSerialize) { + return NS_OK; + } ++ ++ AutoTArray<nsINode*, 8>* serializedContext = mRangeContexts.AppendElement(); ++ + int32_t i = aAncestorArray.Length(), j; + nsresult rv = NS_OK; + +@@ -889,7 +894,7 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncesto + // Either a general inclusion or as immediate context + if (IncludeInContext(node) || i < j) { + rv = SerializeNodeStart(node, 0, -1, aString); +- ++ serializedContext->AppendElement(node); + if (NS_FAILED(rv)) + break; + } +@@ -899,34 +904,24 @@ nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncesto + } + + nsresult +-nsDocumentEncoder::SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray, +- nsAString& aString) ++nsDocumentEncoder::SerializeRangeContextEnd(nsAString& aString) + { + if (mDisableContextSerialize) { + return NS_OK; + } +- int32_t i = 0, j; +- int32_t count = aAncestorArray.Length(); +- nsresult rv = NS_OK; + +- // currently only for table-related elements +- j = GetImmediateContextCount(aAncestorArray); ++ MOZ_RELEASE_ASSERT(!mRangeContexts.IsEmpty(), "Tried to end context without starting one."); ++ AutoTArray<nsINode*, 8>& serializedContext = mRangeContexts.LastElement(); + +- while (i < count) { +- nsINode *node = aAncestorArray.ElementAt(i++); ++ nsresult rv = NS_OK; ++ for (nsINode* node : Reversed(serializedContext)) { ++ rv = SerializeNodeEnd(node, aString); + +- if (!node) ++ if (NS_FAILED(rv)) + break; +- +- // Either a general inclusion or as immediate context +- if (IncludeInContext(node) || i - 1 < j) { +- rv = SerializeNodeEnd(node, aString); +- +- if (NS_FAILED(rv)) +- break; +- } + } + ++ mRangeContexts.RemoveElementAt(mRangeContexts.Length() - 1); + return rv; + } + +@@ -992,7 +987,7 @@ nsDocumentEncoder::SerializeRangeToString(nsRange *aRange, + rv = SerializeRangeNodes(aRange, mCommonParent, aOutputString, 0); + NS_ENSURE_SUCCESS(rv, rv); + } +- rv = SerializeRangeContextEnd(mCommonAncestors, aOutputString); ++ rv = SerializeRangeContextEnd(aOutputString); + NS_ENSURE_SUCCESS(rv, rv); + + return rv; +@@ -1029,6 +1024,11 @@ NS_IMETHODIMP + nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + nsAString& aOutputString) + { ++ MOZ_ASSERT(mRangeContexts.IsEmpty(), "Re-entrant call to nsDocumentEncoder."); ++ auto rangeContextGuard = MakeScopeExit([&] { ++ mRangeContexts.Clear(); ++ }); ++ + if (!mDocument) + return NS_ERROR_NOT_INITIALIZED; + +@@ -1112,10 +1112,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + prevNode = node; + } else if (prevNode) { + // Went from a <tr> to a non-<tr> +- mCommonAncestors.Clear(); +- nsContentUtils::GetAncestors(p->GetParentNode(), mCommonAncestors); + mDisableContextSerialize = false; +- rv = SerializeRangeContextEnd(mCommonAncestors, output); ++ rv = SerializeRangeContextEnd(output); + NS_ENSURE_SUCCESS(rv, rv); + prevNode = nullptr; + } +@@ -1134,10 +1132,8 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + nsCOMPtr<nsINode> p = do_QueryInterface(prevNode); + rv = SerializeNodeEnd(p, output); + NS_ENSURE_SUCCESS(rv, rv); +- mCommonAncestors.Clear(); +- nsContentUtils::GetAncestors(p->GetParentNode(), mCommonAncestors); + mDisableContextSerialize = false; +- rv = SerializeRangeContextEnd(mCommonAncestors, output); ++ rv = SerializeRangeContextEnd(output); + NS_ENSURE_SUCCESS(rv, rv); + } + +@@ -1196,6 +1192,10 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength, + NS_IMETHODIMP + nsDocumentEncoder::EncodeToStream(nsIOutputStream* aStream) + { ++ MOZ_ASSERT(mRangeContexts.IsEmpty(), "Re-entrant call to nsDocumentEncoder."); ++ auto rangeContextGuard = MakeScopeExit([&] { ++ mRangeContexts.Clear(); ++ }); + nsresult rv = NS_OK; + + if (!mDocument) +diff --git dom/base/nsPlainTextSerializer.cpp dom/base/nsPlainTextSerializer.cpp +index 189469f73bb6..d7ddb0274be5 100644 +--- dom/base/nsPlainTextSerializer.cpp ++++ dom/base/nsPlainTextSerializer.cpp +@@ -388,6 +388,7 @@ nsPlainTextSerializer::ScanElementForPreformat(Element* aElement) + NS_IMETHODIMP + nsPlainTextSerializer::ForgetElementForPreformat(Element* aElement) + { ++ MOZ_RELEASE_ASSERT(!mPreformatStack.empty(), "Tried to pop without previous push."); + mPreformatStack.pop(); + return NS_OK; + } diff --git a/www/waterfox/files/patch-bug1410134 b/www/waterfox/files/patch-bug1410134 new file mode 100644 index 000000000000..7a30e8a20fe8 --- /dev/null +++ b/www/waterfox/files/patch-bug1410134 @@ -0,0 +1,52 @@ +commit 2d5001acfa08 +Author: Tim Huang <tihuang@mozilla.com> +Date: Tue Nov 28 14:56:55 2017 -0500 + + Bug 1410134 - Fix the remove-while-iterating for RemoveCookiesWithOriginAttributes. r=jdm, a=gchang + + MozReview-Commit-ID: u56N4084lL + + --HG-- + extra : source : ffab26e34d92c1fc2e5103d2bad3625e180963bb +--- + netwerk/cookie/nsCookieService.cpp | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git netwerk/cookie/nsCookieService.cpp netwerk/cookie/nsCookieService.cpp +index 7d939da101e2..0692b7088751 100644 +--- netwerk/cookie/nsCookieService.cpp ++++ netwerk/cookie/nsCookieService.cpp +@@ -4899,23 +4899,19 @@ nsCookieService::RemoveCookiesWithOriginAttributes( + } + + // Pattern matches. Delete all cookies within this nsCookieEntry. +- const nsCookieEntry::ArrayType& cookies = entry->GetCookies(); ++ uint32_t cookiesCount = entry->GetCookies().Length(); + +- while (!cookies.IsEmpty()) { +- nsCookie *cookie = cookies.LastElement(); +- +- nsAutoCString host; +- cookie->GetHost(host); +- +- nsAutoCString name; +- cookie->GetName(name); +- +- nsAutoCString path; +- cookie->GetPath(path); ++ for (nsCookieEntry::IndexType i = 0 ; i < cookiesCount; ++i) { ++ // Remove the first cookie from the list. ++ nsListIter iter(entry, 0); ++ RefPtr<nsCookie> cookie = iter.Cookie(); + + // Remove the cookie. +- nsresult rv = Remove(host, entry->mOriginAttributes, name, path, false); +- NS_ENSURE_SUCCESS(rv, rv); ++ RemoveCookieFromList(iter); ++ ++ if (cookie) { ++ NotifyChanged(cookie, u"deleted"); ++ } + } + } + DebugOnly<nsresult> rv = transaction.Commit(); diff --git a/www/waterfox/files/patch-bug1410146 b/www/waterfox/files/patch-bug1410146 new file mode 100644 index 000000000000..258525f9bc9c --- /dev/null +++ b/www/waterfox/files/patch-bug1410146 @@ -0,0 +1,27 @@ +commit a8fff8ff6df2 +Author: Dragana Damjanovic dd.mozilla@gmail.com <Dragana Damjanovic dd.mozilla@gmail.com> +Date: Tue Oct 24 14:23:00 2017 -0400 + + Bug 1410146 - Fix UnknownDecoder. r=mayhemer, a=ritu + + --HG-- + extra : source : 8e55fa4da0cb3213d24aca8326792f6346594ed6 +--- + netwerk/streamconv/converters/nsUnknownDecoder.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git netwerk/streamconv/converters/nsUnknownDecoder.cpp netwerk/streamconv/converters/nsUnknownDecoder.cpp +index f3249942580c..ea69d4eb63a3 100644 +--- netwerk/streamconv/converters/nsUnknownDecoder.cpp ++++ netwerk/streamconv/converters/nsUnknownDecoder.cpp +@@ -75,6 +75,10 @@ nsUnknownDecoder::ConvertedStreamListener:: + { + uint32_t read; + nsAutoCString decodedData; ++ { ++ MutexAutoLock lock(mDecoder->mMutex); ++ decodedData = mDecoder->mDecodedData; ++ } + nsresult rv = stream->ReadSegments(AppendDataToString, &decodedData, count, + &read); + if (NS_FAILED(rv)) { diff --git a/www/waterfox/files/patch-bug1410420 b/www/waterfox/files/patch-bug1410420 new file mode 100644 index 000000000000..0d7ea1d89147 --- /dev/null +++ b/www/waterfox/files/patch-bug1410420 @@ -0,0 +1,140 @@ +commit 7bc1ff4cdf6e +Author: Jan Varga <jan.varga@gmail.com> +Date: Mon Oct 30 07:13:40 2017 +0100 + + Bug 1410420 - Clear database actor's strong reference to IDBDatabase when opening of a database fails. r=asuth, a=ritu + + --HG-- + extra : source : d7a53e1454addc0d6bdda84e6c5125c88a14d5cc +--- + dom/indexedDB/ActorsChild.cpp | 25 +++++++++++++++++++++++++ + dom/indexedDB/ActorsChild.h | 17 +++++++++++++++++ + 2 files changed, 42 insertions(+) + +diff --git dom/indexedDB/ActorsChild.cpp dom/indexedDB/ActorsChild.cpp +index a720e9520e6e..0074956761e0 100644 +--- dom/indexedDB/ActorsChild.cpp ++++ dom/indexedDB/ActorsChild.cpp +@@ -1755,6 +1755,7 @@ BackgroundFactoryRequestChild::BackgroundFactoryRequestChild( + uint64_t aRequestedVersion) + : BackgroundRequestChildBase(aOpenRequest) + , mFactory(aFactory) ++ , mDatabaseActor(nullptr) + , mRequestedVersion(aRequestedVersion) + , mIsDeleteOp(aIsDeleteOp) + { +@@ -1779,6 +1780,15 @@ BackgroundFactoryRequestChild::GetOpenDBRequest() const + return static_cast<IDBOpenDBRequest*>(mRequest.get()); + } + ++void ++BackgroundFactoryRequestChild::SetDatabaseActor(BackgroundDatabaseChild* aActor) ++{ ++ AssertIsOnOwningThread(); ++ MOZ_ASSERT(!aActor || !mDatabaseActor); ++ ++ mDatabaseActor = aActor; ++} ++ + bool + BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse) + { +@@ -1790,6 +1800,11 @@ BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse) + + DispatchErrorEvent(mRequest, aResponse); + ++ if (mDatabaseActor) { ++ mDatabaseActor->ReleaseDOMObject(); ++ MOZ_ASSERT(!mDatabaseActor); ++ } ++ + return true; + } + +@@ -1808,6 +1823,7 @@ BackgroundFactoryRequestChild::HandleResponse( + IDBDatabase* database = databaseActor->GetDOMObject(); + if (!database) { + databaseActor->EnsureDOMObject(); ++ MOZ_ASSERT(mDatabaseActor); + + database = databaseActor->GetDOMObject(); + MOZ_ASSERT(database); +@@ -1815,6 +1831,8 @@ BackgroundFactoryRequestChild::HandleResponse( + MOZ_ASSERT(!database->IsClosed()); + } + ++ MOZ_ASSERT(mDatabaseActor == databaseActor); ++ + if (database->IsClosed()) { + // If the database was closed already, which is only possible if we fired an + // "upgradeneeded" event, then we shouldn't fire a "success" event here. +@@ -1827,6 +1845,7 @@ BackgroundFactoryRequestChild::HandleResponse( + } + + databaseActor->ReleaseDOMObject(); ++ MOZ_ASSERT(!mDatabaseActor); + + return true; + } +@@ -1847,6 +1866,8 @@ BackgroundFactoryRequestChild::HandleResponse( + + DispatchSuccessEvent(&helper, successEvent); + ++ MOZ_ASSERT(!mDatabaseActor); ++ + return true; + } + +@@ -2095,6 +2116,8 @@ BackgroundDatabaseChild::EnsureDOMObject() + + mDatabase = mTemporaryStrongDatabase; + mSpec.forget(); ++ ++ mOpenRequestActor->SetDatabaseActor(this); + } + + void +@@ -2106,6 +2129,8 @@ BackgroundDatabaseChild::ReleaseDOMObject() + MOZ_ASSERT(mOpenRequestActor); + MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase); + ++ mOpenRequestActor->SetDatabaseActor(nullptr); ++ + mOpenRequestActor = nullptr; + + // This may be the final reference to the IDBDatabase object so we may end up +diff --git dom/indexedDB/ActorsChild.h dom/indexedDB/ActorsChild.h +index 866a405fb4e2..d82a188b8253 100644 +--- dom/indexedDB/ActorsChild.h ++++ dom/indexedDB/ActorsChild.h +@@ -253,6 +253,20 @@ class BackgroundFactoryRequestChild final + friend class PermissionRequestParent; + + RefPtr<IDBFactory> mFactory; ++ ++ // Normally when opening of a database is successful, we receive a database ++ // actor in request response, so we can use it to call ReleaseDOMObject() ++ // which clears temporary strong reference to IDBDatabase. ++ // However, when there's an error, we don't receive a database actor and ++ // IDBRequest::mTransaction is already cleared (must be). So the only way how ++ // to call ReleaseDOMObject() is to have a back-reference to database actor. ++ // This creates a weak ref cycle between ++ // BackgroundFactoryRequestChild (using mDatabaseActor member) and ++ // BackgroundDatabaseChild actor (using mOpenRequestActor member). ++ // mDatabaseActor is set in EnsureDOMObject() and cleared in ++ // ReleaseDOMObject(). ++ BackgroundDatabaseChild* mDatabaseActor; ++ + const uint64_t mRequestedVersion; + const bool mIsDeleteOp; + +@@ -270,6 +284,9 @@ private: + // Only destroyed by BackgroundFactoryChild. + ~BackgroundFactoryRequestChild(); + ++ void ++ SetDatabaseActor(BackgroundDatabaseChild* aActor); ++ + bool + HandleResponse(nsresult aResponse); + diff --git a/www/waterfox/files/patch-bug1410457 b/www/waterfox/files/patch-bug1410457 new file mode 100644 index 000000000000..a9d6511bfc03 --- /dev/null +++ b/www/waterfox/files/patch-bug1410457 @@ -0,0 +1,117 @@ +commit 1b99cb80da51 +Author: Marco Bonardo <mbonardo@mozilla.com> +Date: Fri Oct 20 17:14:17 2017 +0200 + + Bug 1410457 - Places.sqlite may be marked as corrupt if schema migration mixes up sync and async execution. r=Paolo, a=ritu + + MozReview-Commit-ID: 7O18MLdHU08 + + --HG-- + extra : source : c7cab42203dfce68c8c4cd152055a22b4fdbc402 + extra : histedit_source : dbec7034f68805d1597e4577534de934be04af59 +--- + toolkit/components/places/Database.cpp | 45 +++++++++++++++++++++++++++++----- + toolkit/components/places/Database.h | 3 +++ + 2 files changed, 42 insertions(+), 6 deletions(-) + +diff --git toolkit/components/places/Database.cpp toolkit/components/places/Database.cpp +index 85e365ff3d9e..3ff9e0fa2078 100644 +--- toolkit/components/places/Database.cpp ++++ toolkit/components/places/Database.cpp +@@ -370,6 +370,7 @@ Database::Database() + , mDBPageSize(0) + , mDatabaseStatus(nsINavHistoryService::DATABASE_STATUS_OK) + , mClosed(false) ++ , mShouldConvertIconPayloads(false) + , mClientsShutdown(new ClientsShutdownBlocker()) + , mConnectionShutdown(new ConnectionShutdownBlocker(this)) + , mMaxUrlLength(0) +@@ -588,13 +589,31 @@ Database::EnsureConnection() + bool databaseMigrated = false; + rv = SetupDatabaseConnection(storage); + if (NS_SUCCEEDED(rv)) { +- // Failing to initialize the schema always indicates a corruption. +- if (NS_FAILED(InitSchema(&databaseMigrated))) { +- rv = NS_ERROR_FILE_CORRUPTED; ++ // Failing to initialize the schema may indicate a corruption. ++ rv = InitSchema(&databaseMigrated); ++ if (NS_FAILED(rv)) { ++ if (rv == NS_ERROR_STORAGE_BUSY || ++ rv == NS_ERROR_FILE_IS_LOCKED || ++ rv == NS_ERROR_FILE_NO_DEVICE_SPACE || ++ rv == NS_ERROR_OUT_OF_MEMORY) { ++ // The database is not corrupt, though some migration step failed. ++ // This may be caused by concurrent use of sync and async Storage APIs ++ // or by a system issue. ++ // The best we can do is trying again. If it should still fail, Places ++ // won't work properly and will be handled as LOCKED. ++ rv = InitSchema(&databaseMigrated); ++ if (NS_FAILED(rv)) { ++ rv = NS_ERROR_FILE_IS_LOCKED; ++ } ++ } else { ++ rv = NS_ERROR_FILE_CORRUPTED; ++ } + } + } + if (NS_WARN_IF(NS_FAILED(rv))) { +- mDatabaseStatus = nsINavHistoryService::DATABASE_STATUS_CORRUPT; ++ if (rv != NS_ERROR_FILE_IS_LOCKED) { ++ mDatabaseStatus = nsINavHistoryService::DATABASE_STATUS_CORRUPT; ++ } + // Some errors may not indicate a database corruption, for those cases we + // just bail out without throwing away a possibly valid places.sqlite. + if (rv == NS_ERROR_FILE_CORRUPTED) { +@@ -961,6 +980,14 @@ Database::InitSchema(bool* aDatabaseMigrated) + return NS_ERROR_FILE_CORRUPTED; + } + ++ auto guard = MakeScopeExit([&]() { ++ // This runs at the end of the migration, regardless of its success. ++ if (mShouldConvertIconPayloads) { ++ mShouldConvertIconPayloads = false; ++ nsFaviconService::ConvertUnsupportedPayloads(mMainConn); ++ } ++ }); ++ + // Firefox 4 uses schema version 11. + + // Firefox 8 uses schema version 12. +@@ -1122,6 +1149,11 @@ Database::InitSchema(bool* aDatabaseMigrated) + // Firefox 57 uses schema version 39. + + // Schema Upgrades must add migration code here. ++ // >>> IMPORTANT! <<< ++ // NEVER MIX UP SYNC AND ASYNC EXECUTION IN MIGRATORS, YOU MAY LOCK THE ++ // CONNECTION AND CAUSE FURTHER STEPS TO FAIL. ++ // In case, set a bool and do the async work in the ScopeExit guard just ++ // before the migration steps. + + rv = UpdateBookmarkRootTitles(); + // We don't want a broken localization to cause us to think +@@ -2304,8 +2336,9 @@ Database::MigrateV37Up() { + )); + NS_ENSURE_SUCCESS(rv, rv); + +- // Start the async conversion +- nsFaviconService::ConvertUnsupportedPayloads(mMainConn); ++ // The async favicons conversion will happen at the end of the normal schema ++ // migration. ++ mShouldConvertIconPayloads = true; + + return NS_OK; + } +diff --git toolkit/components/places/Database.h toolkit/components/places/Database.h +index 9000fb269dc2..6213678b3e47 100644 +--- toolkit/components/places/Database.h ++++ toolkit/components/places/Database.h +@@ -333,6 +333,9 @@ private: + int32_t mDBPageSize; + uint16_t mDatabaseStatus; + bool mClosed; ++ // Used to track whether icon payloads should be converted at the end of ++ // schema migration. ++ bool mShouldConvertIconPayloads; + + /** + * Phases for shutting down the Database. diff --git a/www/waterfox/files/patch-bug1410634 b/www/waterfox/files/patch-bug1410634 new file mode 100644 index 000000000000..0fdc6cbe00ca --- /dev/null +++ b/www/waterfox/files/patch-bug1410634 @@ -0,0 +1,145 @@ +commit a34cf3c8ad18 +Author: Ben Kelly <ben@wanderview.com> +Date: Tue Oct 24 09:24:53 2017 -0400 + + Bug 1410634 - Part 1: Call channel IsFromCache() during OnStartRequest() to determine if update result came from http cache or network. r=tt, a=ritu + + --HG-- + extra : source : 087e11c956e368c41e91bdc5d689d5e94f3ef7ef +--- + dom/workers/ServiceWorkerScriptCache.cpp | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git dom/workers/ServiceWorkerScriptCache.cpp dom/workers/ServiceWorkerScriptCache.cpp +index a065a6fafbf8..f30bca95229c 100644 +--- dom/workers/ServiceWorkerScriptCache.cpp ++++ dom/workers/ServiceWorkerScriptCache.cpp +@@ -100,12 +100,13 @@ public: + bool aIsMainScript) + : mManager(aManager) + , mRegistration(aRegistration) +- , mIsMainScript(aIsMainScript) + , mInternalHeaders(new InternalHeaders()) + , mLoadFlags(nsIChannel::LOAD_BYPASS_SERVICE_WORKER) + , mState(WaitingForInitialization) + , mNetworkResult(NS_OK) + , mCacheResult(NS_OK) ++ , mIsMainScript(aIsMainScript) ++ , mIsFromCache(false) + { + MOZ_ASSERT(aManager); + AssertIsOnMainThread(); +@@ -180,8 +181,6 @@ private: + RefPtr<CompareCache> mCC; + RefPtr<ServiceWorkerRegistrationInfo> mRegistration; + +- bool mIsMainScript; +- + nsCOMPtr<nsIChannel> mChannel; + nsString mBuffer; + nsString mURL; +@@ -202,6 +201,9 @@ private: + + nsresult mNetworkResult; + nsresult mCacheResult; ++ ++ const bool mIsMainScript; ++ bool mIsFromCache; + }; + + NS_IMPL_ISUPPORTS(CompareNetwork, nsIStreamLoaderObserver, +@@ -863,6 +865,12 @@ CompareNetwork::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) + } + + mInternalHeaders->FillResponseHeaders(mChannel); ++ ++ nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(mChannel)); ++ if (cacheChannel) { ++ cacheChannel->IsFromCache(&mIsFromCache); ++ } ++ + return NS_OK; + } + +@@ -959,15 +967,9 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext + NS_LITERAL_CSTRING("Service-Worker-Allowed"), + mMaxScope); + +- bool isFromCache = false; +- nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(httpChannel)); +- if (cacheChannel) { +- cacheChannel->IsFromCache(&isFromCache); +- } +- + // [9.2 Update]4.13, If response's cache state is not "local", + // set registration's last update check time to the current time +- if (!isFromCache) { ++ if (!mIsFromCache) { + mRegistration->RefreshLastUpdateCheckTime(); + } + + +commit 5aebe3f6b13b +Author: Ben Kelly <ben@wanderview.com> +Date: Tue Oct 24 09:24:53 2017 -0400 + + Bug 1410634 - Part 2: Verify ServiceWorkerInfo.lastUpdateTime is not changed when reading from http cache. r=tt, a=ritu + + --HG-- + extra : source : 1abb70007b4c50a588b6a344879fd9efc3ef9ca5 +--- + .../test/serviceworkers/serviceworkerinfo_iframe.html | 3 ++- + .../test_devtools_track_serviceworker_time.html | 12 ++++++++++++ + 2 files changed, 14 insertions(+), 1 deletion(-) + +diff --git dom/workers/test/serviceworkers/serviceworkerinfo_iframe.html dom/workers/test/serviceworkers/serviceworkerinfo_iframe.html +index a0a2de76030e..16a175836981 100644 +--- dom/workers/test/serviceworkers/serviceworkerinfo_iframe.html ++++ dom/workers/test/serviceworkers/serviceworkerinfo_iframe.html +@@ -7,7 +7,8 @@ + if (event.data !== "register") { + return; + } +- var promise = navigator.serviceWorker.register("worker.js"); ++ var promise = navigator.serviceWorker.register("worker.js", ++ { updateViaCache: 'all' }); + window.onmessage = function (event) { + if (event.data !== "unregister") { + return; +diff --git dom/workers/test/serviceworkers/test_devtools_track_serviceworker_time.html dom/workers/test/serviceworkers/test_devtools_track_serviceworker_time.html +index 4b58d659f565..6b95d6b34fe1 100644 +--- dom/workers/test/serviceworkers/test_devtools_track_serviceworker_time.html ++++ dom/workers/test/serviceworkers/test_devtools_track_serviceworker_time.html +@@ -53,6 +53,8 @@ let expectedResults = [ + state: State.ACTIVATED, installedTimeRecorded: true, + activatedTimeRecorded: true, redundantTimeRecorded: false + }, ++ ++ // On unregister + { + state: State.REDUNDANT, installedTimeRecorded: true, + activatedTimeRecorded: true, redundantTimeRecorded: true +@@ -170,6 +172,15 @@ function testServiceWorkerInfo() { + return promise; + } + ++async function testHttpCacheUpdateTime() { ++ let iframe = document.querySelector("iframe"); ++ let reg = await iframe.contentWindow.navigator.serviceWorker.getRegistration(); ++ let lastUpdateTime = registrationInfo.lastUpdateTime; ++ await reg.update(); ++ is(lastUpdateTime, registrationInfo.lastUpdateTime, ++ "The update time should not change when SW script is read from http cache."); ++} ++ + function unregister() { + info("Unregister the ServiceWorker"); + +@@ -196,6 +207,7 @@ function runTest() { + return Promise.resolve() + .then(register) + .then(testServiceWorkerInfo) ++ .then(testHttpCacheUpdateTime) + .then(unregister) + .catch(aError => ok(false, "Some test failed with error " + aError)) + .then(cleanAll) diff --git a/www/waterfox/files/patch-bug1410808 b/www/waterfox/files/patch-bug1410808 new file mode 100644 index 000000000000..885dd10db626 --- /dev/null +++ b/www/waterfox/files/patch-bug1410808 @@ -0,0 +1,27 @@ +commit 17ccad87f85c +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Oct 23 17:17:13 2017 +0200 + + Bug 1410808. r=xidorn, a=ritu + + MozReview-Commit-ID: 5uufVVEIw20 + + --HG-- + extra : source : d44c182148c233556f38d1c6dc61ab6098f44e85 +--- + layout/style/ServoKeyframeRule.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git layout/style/ServoKeyframeRule.cpp layout/style/ServoKeyframeRule.cpp +index 4fe9f6440211..1be82c3100c5 100644 +--- layout/style/ServoKeyframeRule.cpp ++++ layout/style/ServoKeyframeRule.cpp +@@ -31,7 +31,7 @@ public: + + NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParent) final + { +- *aParent = mRule; ++ NS_IF_ADDREF(*aParent = mRule); + return NS_OK; + } + diff --git a/www/waterfox/files/patch-bug1411415 b/www/waterfox/files/patch-bug1411415 new file mode 100644 index 000000000000..b988d95e11be --- /dev/null +++ b/www/waterfox/files/patch-bug1411415 @@ -0,0 +1,383 @@ +commit 627eb6ae9a72 +Author: Kannan Vijayan <kvijayan@mozilla.com> +Date: Mon Mar 5 19:27:02 2018 -0500 + + Bug 1411415 - r=bz r=fitzgen +--- + dom/bindings/BindingUtils.cpp | 20 +++++------ + dom/bindings/ErrorResult.h | 2 +- + dom/xslt/xpath/txXPCOMExtensionFunction.cpp | 2 +- + js/public/Value.h | 55 ++++++++++++++++++++++++++--- + js/rust/build.rs | 1 + + js/src/jit/BaselineFrameInfo.h | 4 +-- + js/src/jit/CacheIRCompiler.cpp | 2 +- + js/src/jit/RegisterSets.h | 8 ++--- + js/src/jit/RematerializedFrame.cpp | 14 ++++++-- + js/src/wasm/AsmJS.cpp | 10 +++--- + js/xpconnect/src/XPCWrappedNative.cpp | 7 ++-- + layout/style/ServoBindings.toml | 6 ++-- + xpcom/reflect/xptcall/xptcall.h | 2 +- + 13 files changed, 97 insertions(+), 36 deletions(-) + +diff --git dom/bindings/BindingUtils.cpp dom/bindings/BindingUtils.cpp +index 93069ac4a8b8..ac8c7a2229f3 100644 +--- dom/bindings/BindingUtils.cpp ++++ dom/bindings/BindingUtils.cpp +@@ -287,8 +287,8 @@ TErrorResult<CleanupPolicy>::ThrowJSException(JSContext* cx, JS::Handle<JS::Valu + // Make sure mJSException is initialized _before_ we try to root it. But + // don't set it to exn yet, because we don't want to do that until after we + // root. +- mJSException.setUndefined(); +- if (!js::AddRawValueRoot(cx, &mJSException, "TErrorResult::mJSException")) { ++ mJSException.asValueRef().setUndefined(); ++ if (!js::AddRawValueRoot(cx, &mJSException.asValueRef(), "TErrorResult::mJSException")) { + // Don't use NS_ERROR_INTERNAL_ERRORRESULT_JS_EXCEPTION, because that + // indicates we have in fact rooted mJSException. + mResult = NS_ERROR_OUT_OF_MEMORY; +@@ -317,7 +317,7 @@ TErrorResult<CleanupPolicy>::SetPendingJSException(JSContext* cx) + mJSException = exception; + // If JS_WrapValue failed, not much we can do about it... No matter + // what, go ahead and unroot mJSException. +- js::RemoveRawValueRoot(cx, &mJSException); ++ js::RemoveRawValueRoot(cx, &mJSException.asValueRef()); + + mResult = NS_OK; + #ifdef DEBUG +@@ -423,8 +423,8 @@ TErrorResult<CleanupPolicy>::ClearUnionData() + if (IsJSException()) { + JSContext* cx = dom::danger::GetJSContext(); + MOZ_ASSERT(cx); +- mJSException.setUndefined(); +- js::RemoveRawValueRoot(cx, &mJSException); ++ mJSException.asValueRef().setUndefined(); ++ js::RemoveRawValueRoot(cx, &mJSException.asValueRef()); + #ifdef DEBUG + mUnionState = HasNothing; + #endif // DEBUG +@@ -467,13 +467,13 @@ TErrorResult<CleanupPolicy>::operator=(TErrorResult<CleanupPolicy>&& aRHS) + } else if (aRHS.IsJSException()) { + JSContext* cx = dom::danger::GetJSContext(); + MOZ_ASSERT(cx); +- mJSException.setUndefined(); +- if (!js::AddRawValueRoot(cx, &mJSException, "TErrorResult::mJSException")) { ++ mJSException.asValueRef().setUndefined(); ++ if (!js::AddRawValueRoot(cx, &mJSException.asValueRef(), "TErrorResult::mJSException")) { + MOZ_CRASH("Could not root mJSException, we're about to OOM"); + } + mJSException = aRHS.mJSException; +- aRHS.mJSException.setUndefined(); +- js::RemoveRawValueRoot(cx, &aRHS.mJSException); ++ aRHS.mJSException.asValueRef().setUndefined(); ++ js::RemoveRawValueRoot(cx, &aRHS.mJSException.asValueRef()); + } else if (aRHS.IsDOMException()) { + mDOMExceptionInfo = aRHS.mDOMExceptionInfo; + aRHS.mDOMExceptionInfo = nullptr; +@@ -525,7 +525,7 @@ TErrorResult<CleanupPolicy>::CloneTo(TErrorResult& aRv) const + aRv.mUnionState = HasJSException; + #endif + JSContext* cx = dom::danger::GetJSContext(); +- JS::Rooted<JS::Value> exception(cx, mJSException); ++ JS::Rooted<JS::Value> exception(cx, mJSException.asValueRef()); + aRv.ThrowJSException(cx, exception); + } + } +diff --git dom/bindings/ErrorResult.h dom/bindings/ErrorResult.h +index 7b38226691bb..a406a2c490a5 100644 +--- dom/bindings/ErrorResult.h ++++ dom/bindings/ErrorResult.h +@@ -507,7 +507,7 @@ private: + // (and deallocated) by SetPendingDOMException. + union { + Message* mMessage; // valid when IsErrorWithMessage() +- JS::Value mJSException; // valid when IsJSException() ++ JS::UninitializedValue mJSException; // valid when IsJSException() + DOMExceptionInfo* mDOMExceptionInfo; // valid when IsDOMException() + }; + +diff --git dom/xslt/xpath/txXPCOMExtensionFunction.cpp dom/xslt/xpath/txXPCOMExtensionFunction.cpp +index e95baa0bbde8..e1387422c303 100644 +--- dom/xslt/xpath/txXPCOMExtensionFunction.cpp ++++ dom/xslt/xpath/txXPCOMExtensionFunction.cpp +@@ -322,7 +322,7 @@ public: + void trace(JSTracer* trc) { + for (uint8_t i = 0; i < mCount; ++i) { + if (mArray[i].type == nsXPTType::T_JSVAL) { +- JS::UnsafeTraceRoot(trc, &mArray[i].val.j, "txParam value"); ++ JS::UnsafeTraceRoot(trc, &mArray[i].val.j.asValueRef(), "txParam value"); + } + } + } +diff --git js/public/Value.h js/public/Value.h +index b7c4e1b8a770..96a1b703bbc1 100644 +--- js/public/Value.h ++++ js/public/Value.h +@@ -137,12 +137,16 @@ static_assert(sizeof(JSValueShiftedTag) == sizeof(uint64_t), + + #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_CLEAR | (type))) + ++#define JSVAL_RAW64_UNDEFINED (uint64_t(JSVAL_TAG_UNDEFINED) << 32) ++ + #define JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET JSVAL_TAG_OBJECT + #define JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET JSVAL_TAG_INT32 + #define JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET JSVAL_TAG_STRING + + #elif defined(JS_PUNBOX64) + ++#define JSVAL_RAW64_UNDEFINED (uint64_t(JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT) ++ + #define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL + #define JSVAL_TAG_MASK 0xFFFF800000000000LL + #define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type))) +@@ -814,7 +818,7 @@ class MOZ_NON_PARAM alignas(8) Value + double asDouble; + void* asPtr; + +- layout() = default; ++ layout() : asBits(JSVAL_RAW64_UNDEFINED) {} + explicit constexpr layout(uint64_t bits) : asBits(bits) {} + explicit constexpr layout(double d) : asDouble(d) {} + } data; +@@ -840,7 +844,7 @@ class MOZ_NON_PARAM alignas(8) Value + size_t asWord; + uintptr_t asUIntPtr; + +- layout() = default; ++ layout() : asBits(JSVAL_RAW64_UNDEFINED) {} + explicit constexpr layout(uint64_t bits) : asBits(bits) {} + explicit constexpr layout(double d) : asDouble(d) {} + } data; +@@ -868,7 +872,7 @@ class MOZ_NON_PARAM alignas(8) Value + double asDouble; + void* asPtr; + +- layout() = default; ++ layout() : asBits(JSVAL_RAW64_UNDEFINED) {} + explicit constexpr layout(uint64_t bits) : asBits(bits) {} + explicit constexpr layout(double d) : asDouble(d) {} + } data; +@@ -892,7 +896,7 @@ class MOZ_NON_PARAM alignas(8) Value + size_t asWord; + uintptr_t asUIntPtr; + +- layout() = default; ++ layout() : asBits(JSVAL_RAW64_UNDEFINED) {} + explicit constexpr layout(uint64_t bits) : asBits(bits) {} + explicit constexpr layout(double d) : asDouble(d) {} + } data; +@@ -945,8 +949,51 @@ class MOZ_NON_PARAM alignas(8) Value + } + } JS_HAZ_GC_POINTER; + ++/** ++ * This is a null-constructible structure that can convert to and from ++ * a Value, allowing UninitializedValue to be stored in unions. ++ */ ++struct MOZ_NON_PARAM alignas(8) UninitializedValue ++{ ++ private: ++ uint64_t bits; ++ ++ public: ++ UninitializedValue() = default; ++ UninitializedValue(const UninitializedValue&) = default; ++ MOZ_IMPLICIT UninitializedValue(const Value& val) : bits(val.asRawBits()) {} ++ ++ inline uint64_t asRawBits() const { ++ return bits; ++ } ++ ++ inline Value& asValueRef() { ++ return *reinterpret_cast<Value*>(this); ++ } ++ inline const Value& asValueRef() const { ++ return *reinterpret_cast<const Value*>(this); ++ } ++ ++ inline operator Value&() { ++ return asValueRef(); ++ } ++ inline operator Value const&() const { ++ return asValueRef(); ++ } ++ inline operator Value() const { ++ return asValueRef(); ++ } ++ ++ inline void operator=(Value const& other) { ++ asValueRef() = other; ++ } ++}; ++ + static_assert(sizeof(Value) == 8, "Value size must leave three tag bits, be a binary power, and is ubiquitously depended upon everywhere"); + ++static_assert(sizeof(UninitializedValue) == sizeof(Value), "Value and UninitializedValue must be the same size"); ++static_assert(alignof(UninitializedValue) == alignof(Value), "Value and UninitializedValue must have same alignment"); ++ + inline bool + IsOptimizedPlaceholderMagicValue(const Value& v) + { +diff --git js/src/jit/BaselineFrameInfo.h js/src/jit/BaselineFrameInfo.h +index 13bf0358d944..1691270acf17 100644 +--- js/src/jit/BaselineFrameInfo.h ++++ js/src/jit/BaselineFrameInfo.h +@@ -67,7 +67,7 @@ class StackValue + + union { + struct { +- Value v; ++ JS::UninitializedValue v; + } constant; + struct { + mozilla::AlignedStorage2<ValueOperand> reg; +@@ -112,7 +112,7 @@ class StackValue + } + Value constant() const { + MOZ_ASSERT(kind_ == Constant); +- return data.constant.v; ++ return data.constant.v.asValueRef(); + } + ValueOperand reg() const { + MOZ_ASSERT(kind_ == Register); +diff --git js/src/jit/CacheIRCompiler.cpp js/src/jit/CacheIRCompiler.cpp +index 98d2dcbf1b23..35357ed7c8da 100644 +--- js/src/jit/CacheIRCompiler.cpp ++++ js/src/jit/CacheIRCompiler.cpp +@@ -925,7 +925,7 @@ CacheIRWriter::copyStubData(uint8_t* dest) const + *reinterpret_cast<uint64_t*>(destWords) = field.asInt64(); + break; + case StubField::Type::Value: +- InitGCPtr<JS::Value>(destWords, field.asInt64()); ++ AsGCPtr<Value>(destWords)->init(Value::fromRawBits(uint64_t(field.asInt64()))); + break; + case StubField::Type::Limit: + MOZ_CRASH("Invalid type"); +diff --git js/src/jit/RegisterSets.h js/src/jit/RegisterSets.h +index b6436a801b1c..749730aac4c6 100644 +--- js/src/jit/RegisterSets.h ++++ js/src/jit/RegisterSets.h +@@ -226,13 +226,13 @@ class ConstantOrRegister + + // Space to hold either a Value or a TypedOrValueRegister. + union U { +- Value constant; ++ JS::UninitializedValue constant; + TypedOrValueRegister reg; + } data; + +- const Value& dataValue() const { ++ Value dataValue() const { + MOZ_ASSERT(constant()); +- return data.constant; ++ return data.constant.asValueRef(); + } + void setDataValue(const Value& value) { + MOZ_ASSERT(constant()); +@@ -268,7 +268,7 @@ class ConstantOrRegister + return constant_; + } + +- const Value& value() const { ++ Value value() const { + return dataValue(); + } + +diff --git js/src/jit/RematerializedFrame.cpp js/src/jit/RematerializedFrame.cpp +index f12475e5ee55..8cfb0c0d0b87 100644 +--- js/src/jit/RematerializedFrame.cpp ++++ js/src/jit/RematerializedFrame.cpp +@@ -60,9 +60,17 @@ RematerializedFrame::New(JSContext* cx, uint8_t* top, InlineFrameIterator& iter, + { + unsigned numFormals = iter.isFunctionFrame() ? iter.calleeTemplate()->nargs() : 0; + unsigned argSlots = Max(numFormals, iter.numActualArgs()); +- size_t numBytes = sizeof(RematerializedFrame) + +- (argSlots + iter.script()->nfixed()) * sizeof(Value) - +- sizeof(Value); // 1 Value included in sizeof(RematerializedFrame) ++ unsigned extraSlots = argSlots + iter.script()->nfixed(); ++ ++ // One Value slot is included in sizeof(RematerializedFrame), so we can ++ // reduce the extra slot count by one. However, if there are zero slot ++ // allocations total, then reducing the slots by one will lead to ++ // the memory allocation being smaller than sizeof(RematerializedFrame). ++ if (extraSlots > 0) ++ extraSlots -= 1; ++ ++ size_t numBytes = sizeof(RematerializedFrame) + (extraSlots * sizeof(Value)); ++ MOZ_ASSERT(numBytes >= sizeof(RematerializedFrame)); + + void* buf = cx->pod_calloc<uint8_t>(numBytes); + if (!buf) +diff --git js/src/wasm/AsmJS.cpp js/src/wasm/AsmJS.cpp +index a5102bd66373..9fe705976ea3 100644 +--- js/src/wasm/AsmJS.cpp ++++ js/src/wasm/AsmJS.cpp +@@ -851,7 +851,7 @@ class NumLit + private: + Which which_; + union { +- Value scalar_; ++ JS::UninitializedValue scalar_; + SimdConstant simd_; + } u; + +@@ -874,7 +874,7 @@ class NumLit + + int32_t toInt32() const { + MOZ_ASSERT(which_ == Fixnum || which_ == NegativeInt || which_ == BigUnsigned); +- return u.scalar_.toInt32(); ++ return u.scalar_.asValueRef().toInt32(); + } + + uint32_t toUint32() const { +@@ -883,17 +883,17 @@ class NumLit + + double toDouble() const { + MOZ_ASSERT(which_ == Double); +- return u.scalar_.toDouble(); ++ return u.scalar_.asValueRef().toDouble(); + } + + float toFloat() const { + MOZ_ASSERT(which_ == Float); +- return float(u.scalar_.toDouble()); ++ return float(u.scalar_.asValueRef().toDouble()); + } + + Value scalarValue() const { + MOZ_ASSERT(which_ != OutOfRangeInt); +- return u.scalar_; ++ return u.scalar_.asValueRef(); + } + + bool isSimd() const +diff --git js/xpconnect/src/XPCWrappedNative.cpp js/xpconnect/src/XPCWrappedNative.cpp +index fd992eb22465..946d671ddd00 100644 +--- js/xpconnect/src/XPCWrappedNative.cpp ++++ js/xpconnect/src/XPCWrappedNative.cpp +@@ -1723,9 +1723,12 @@ CallMethodHelper::ConvertIndependentParam(uint8_t i) + // indirectly, regardless of in/out-ness. + if (type_tag == nsXPTType::T_JSVAL) { + // Root the value. +- dp->val.j.setUndefined(); +- if (!js::AddRawValueRoot(mCallContext, &dp->val.j, "XPCWrappedNative::CallMethod param")) ++ dp->val.j.asValueRef().setUndefined(); ++ if (!js::AddRawValueRoot(mCallContext, &dp->val.j.asValueRef(), ++ "XPCWrappedNative::CallMethod param")) ++ { + return false; ++ } + } + + // Flag cleanup for anything that isn't self-contained. +diff --git xpcom/reflect/xptcall/xptcall.h xpcom/reflect/xptcall/xptcall.h +index ddab2e4af127..4b387e8ee9c1 100644 +--- xpcom/reflect/xptcall/xptcall.h ++++ xpcom/reflect/xptcall/xptcall.h +@@ -39,7 +39,7 @@ struct nsXPTCMiniVariant + // Types below here are unknown to the assembly implementations, and + // therefore _must_ be passed with indirect semantics. We put them in + // the union here for type safety, so that we can avoid void* tricks. +- JS::Value j; ++ JS::UninitializedValue j; + } val; + }; + diff --git a/www/waterfox/files/patch-bug1411745 b/www/waterfox/files/patch-bug1411745 new file mode 100644 index 000000000000..f5f25d894da6 --- /dev/null +++ b/www/waterfox/files/patch-bug1411745 @@ -0,0 +1,26 @@ +commit 4bd747285cad +Author: Magnus Melin <mkmelin+mozilla@iki.fi> +Date: Sat Dec 9 16:43:16 2017 +0200 + + Bug 1411745 - crash for svg linking to mailbox URI. r=smaug a=gchang + + --HG-- + extra : source : 2a01f65ec8af02827f0621f86e501ad236431415 +--- + dom/base/nsDocument.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index fe44e902241f..ce511f50e9de 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -1233,7 +1233,8 @@ nsExternalResourceMap::PendingLoad::OnDataAvailable(nsIRequest* aRequest, + uint64_t aOffset, + uint32_t aCount) + { +- NS_PRECONDITION(mTargetListener, "Shouldn't be getting called!"); ++ // mTargetListener might be null if SetupViewer or AddExternalResource failed. ++ NS_ENSURE_TRUE(mTargetListener, NS_ERROR_FAILURE); + if (mDisplayDocument->ExternalResourceMap().HaveShutDown()) { + return NS_BINDING_ABORTED; + } diff --git a/www/waterfox/files/patch-bug1412011 b/www/waterfox/files/patch-bug1412011 new file mode 100644 index 000000000000..88937770f575 --- /dev/null +++ b/www/waterfox/files/patch-bug1412011 @@ -0,0 +1,100 @@ +commit 4112ea0d8cb1 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Oct 30 11:02:16 2017 -0400 + + Bug 1412011 - selectors: Be consistent about how we get a parent element for selector matching. r=xidorn, a=ritu + + Source-Repo: https://github.com/servo/servo + Source-Revision: de7595f16fa41c32ca5654aef53c60ad19bb108a + + --HG-- + extra : rebase_source : fc932c8d05ec1861ee16d7a89bfe1da1228d1c08 +--- + servo/components/selectors/matching.rs | 49 +++++++++++++++++++++++----------- + 1 file changed, 33 insertions(+), 16 deletions(-) + +diff --git servo/components/selectors/matching.rs servo/components/selectors/matching.rs +index c6c2db3c4719..30586b27f457 100644 +--- servo/components/selectors/matching.rs ++++ servo/components/selectors/matching.rs +@@ -515,6 +515,32 @@ pub fn matches_complex_selector<E, F>(mut iter: SelectorIter<E::Impl>, + } + } + ++#[inline(always)] ++fn next_element_for_combinator<E>( ++ element: &E, ++ combinator: Combinator, ++) -> Option<E> ++where ++ E: Element, ++{ ++ match combinator { ++ Combinator::NextSibling | ++ Combinator::LaterSibling => { ++ element.prev_sibling_element() ++ } ++ Combinator::Child | ++ Combinator::Descendant => { ++ if element.blocks_ancestor_combinators() { ++ return None; ++ } ++ element.parent_element() ++ } ++ Combinator::PseudoElement => { ++ element.pseudo_element_originating_element() ++ } ++ } ++} ++ + fn matches_complex_selector_internal<E, F>(mut selector_iter: SelectorIter<E::Impl>, + element: &E, + context: &mut LocalMatchingContext<E::Impl>, +@@ -546,28 +572,23 @@ fn matches_complex_selector_internal<E, F>(mut selector_iter: SelectorIter<E::Im + match combinator { + None => SelectorMatchingResult::Matched, + Some(c) => { +- let (mut next_element, candidate_not_found) = match c { ++ let candidate_not_found= match c { + Combinator::NextSibling | Combinator::LaterSibling => { + // Only ancestor combinators are allowed while looking for + // relevant links, so switch to not looking. + *relevant_link = RelevantLinkStatus::NotLooking; +- (element.prev_sibling_element(), +- SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant) ++ SelectorMatchingResult::NotMatchedAndRestartFromClosestDescendant + } + Combinator::Child | Combinator::Descendant => { +- if element.blocks_ancestor_combinators() { +- (None, SelectorMatchingResult::NotMatchedGlobally) +- } else { +- (element.parent_element(), +- SelectorMatchingResult::NotMatchedGlobally) +- } ++ SelectorMatchingResult::NotMatchedGlobally + } + Combinator::PseudoElement => { +- (element.pseudo_element_originating_element(), +- SelectorMatchingResult::NotMatchedGlobally) ++ SelectorMatchingResult::NotMatchedGlobally + } + }; + ++ let mut next_element = next_element_for_combinator(element, c); ++ + loop { + let element = match next_element { + None => return candidate_not_found, +@@ -607,11 +628,7 @@ fn matches_complex_selector_internal<E, F>(mut selector_iter: SelectorIter<E::Im + // can continue to matching on the next candidate element. + _ => {}, + } +- next_element = if siblings { +- element.prev_sibling_element() +- } else { +- element.parent_element() +- }; ++ next_element = next_element_for_combinator(&element, c); + } + } + } diff --git a/www/waterfox/files/patch-bug1412145 b/www/waterfox/files/patch-bug1412145 new file mode 100644 index 000000000000..595ba7297dc9 --- /dev/null +++ b/www/waterfox/files/patch-bug1412145 @@ -0,0 +1,286 @@ +commit d83a24ce6fb3 +Author: Xidorn Quan <me@upsuper.org> +Date: Tue Nov 28 17:06:51 2017 -0600 + + Bug 1412145 - Drop more backpointers of CSSOM objects in dtor and unlink. r=bz, a=gchang + + MozReview-Commit-ID: Ftg3WMBBNlO +--- + layout/style/GroupRule.cpp | 7 +++++++ + layout/style/GroupRule.h | 1 + + layout/style/MediaList.h | 4 +++- + layout/style/ServoCSSRuleList.cpp | 2 ++ + layout/style/ServoKeyframeRule.cpp | 12 ++++++++++-- + layout/style/ServoKeyframesRule.cpp | 23 ++++++++++++++++------- + layout/style/ServoMediaRule.cpp | 17 +++++++++++++++-- + layout/style/ServoPageRule.cpp | 2 ++ + layout/style/ServoStyleRule.cpp | 1 + + layout/style/nsCSSRules.cpp | 31 +++++++++++++++++++++++++++---- + 10 files changed, 84 insertions(+), 16 deletions(-) + +diff --git layout/style/GroupRule.cpp layout/style/GroupRule.cpp +index 28739e1818eb..32bd8c83e43a 100644 +--- layout/style/GroupRule.cpp ++++ layout/style/GroupRule.cpp +@@ -198,6 +198,13 @@ GeckoGroupRuleRules::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const + // ServoGroupRuleRules + // + ++ServoGroupRuleRules::~ServoGroupRuleRules() ++{ ++ if (mRuleList) { ++ mRuleList->DropReference(); ++ } ++} ++ + #ifdef DEBUG + void + ServoGroupRuleRules::List(FILE* out, int32_t aIndent) const +diff --git layout/style/GroupRule.h layout/style/GroupRule.h +index ac9e26921f0b..5c336e5c3611 100644 +--- layout/style/GroupRule.h ++++ layout/style/GroupRule.h +@@ -87,6 +87,7 @@ struct ServoGroupRuleRules + // Do we ever clone Servo rules? + MOZ_ASSERT_UNREACHABLE("stylo: Cloning GroupRule not implemented"); + } ++ ~ServoGroupRuleRules(); + + void SetParentRule(GroupRule* aParentRule) { + if (mRuleList) { +diff --git layout/style/MediaList.h layout/style/MediaList.h +index 4e8c12a2461a..b95e6ec26895 100644 +--- layout/style/MediaList.h ++++ layout/style/MediaList.h +@@ -84,7 +84,9 @@ protected: + virtual nsresult Delete(const nsAString& aOldMedium) = 0; + virtual nsresult Append(const nsAString& aNewMedium) = 0; + +- virtual ~MediaList() {} ++ virtual ~MediaList() { ++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared"); ++ } + + // not refcounted; sheet will let us know when it goes away + // mStyleSheet is the sheet that needs to be dirtied when this +diff --git layout/style/ServoCSSRuleList.cpp layout/style/ServoCSSRuleList.cpp +index 37ce9be9f337..31f481899964 100644 +--- layout/style/ServoCSSRuleList.cpp ++++ layout/style/ServoCSSRuleList.cpp +@@ -234,6 +234,8 @@ ServoCSSRuleList::GetDOMCSSRuleType(uint32_t aIndex) const + + ServoCSSRuleList::~ServoCSSRuleList() + { ++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared"); ++ MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared"); + DropAllRules(); + } + +diff --git layout/style/ServoKeyframeRule.cpp layout/style/ServoKeyframeRule.cpp +index 1be82c3100c5..6ca8a1815f8c 100644 +--- layout/style/ServoKeyframeRule.cpp ++++ layout/style/ServoKeyframeRule.cpp +@@ -35,7 +35,10 @@ public: + return NS_OK; + } + +- void DropReference() { mRule = nullptr; } ++ void DropReference() { ++ mRule = nullptr; ++ mDecls->SetOwningRule(nullptr); ++ } + + DeclarationBlock* GetCSSDeclaration(Operation aOperation) final + { +@@ -81,7 +84,9 @@ public: + } + + private: +- virtual ~ServoKeyframeDeclaration() {} ++ virtual ~ServoKeyframeDeclaration() { ++ MOZ_ASSERT(!mRule, "Backpointer should have been cleared"); ++ } + + ServoKeyframeRule* mRule; + RefPtr<ServoDeclarationBlock> mDecls; +@@ -102,6 +107,9 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration) + + ServoKeyframeRule::~ServoKeyframeRule() + { ++ if (mDeclaration) { ++ mDeclaration->DropReference(); ++ } + } + + NS_IMPL_ADDREF_INHERITED(ServoKeyframeRule, dom::CSSKeyframeRule) +diff --git layout/style/ServoKeyframesRule.cpp layout/style/ServoKeyframesRule.cpp +index 9a7252a5a639..7341b954ec60 100644 +--- layout/style/ServoKeyframesRule.cpp ++++ layout/style/ServoKeyframesRule.cpp +@@ -90,7 +90,12 @@ public: + { + mStyleSheet = nullptr; + mParentRule = nullptr; +- DropAllRules(); ++ for (css::Rule* rule : mRules) { ++ if (rule) { ++ rule->SetStyleSheet(nullptr); ++ rule->SetParentRule(nullptr); ++ } ++ } + } + + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const +@@ -103,15 +108,16 @@ public: + } + + private: +- virtual ~ServoKeyframeList() {} ++ virtual ~ServoKeyframeList() { ++ MOZ_ASSERT(!mParentRule, "Backpointer should have been cleared"); ++ MOZ_ASSERT(!mStyleSheet, "Backpointer should have been cleared"); ++ DropAllRules(); ++ } + + void DropAllRules() + { +- for (css::Rule* rule : mRules) { +- if (rule) { +- rule->SetStyleSheet(nullptr); +- rule->SetParentRule(nullptr); +- } ++ if (mParentRule || mStyleSheet) { ++ DropReference(); + } + mRules.Clear(); + mRawRule = nullptr; +@@ -163,6 +169,9 @@ ServoKeyframesRule::ServoKeyframesRule(RefPtr<RawServoKeyframesRule> aRawRule, + + ServoKeyframesRule::~ServoKeyframesRule() + { ++ if (mKeyframeList) { ++ mKeyframeList->DropReference(); ++ } + } + + NS_IMPL_ADDREF_INHERITED(ServoKeyframesRule, dom::CSSKeyframesRule) +diff --git layout/style/ServoMediaRule.cpp layout/style/ServoMediaRule.cpp +index 002ae20ffd0b..fbda581a377f 100644 +--- layout/style/ServoMediaRule.cpp ++++ layout/style/ServoMediaRule.cpp +@@ -24,6 +24,9 @@ ServoMediaRule::ServoMediaRule(RefPtr<RawServoMediaRule> aRawRule, + + ServoMediaRule::~ServoMediaRule() + { ++ if (mMediaList) { ++ mMediaList->SetStyleSheet(nullptr); ++ } + } + + NS_IMPL_ADDREF_INHERITED(ServoMediaRule, CSSMediaRule) +@@ -33,8 +36,18 @@ NS_IMPL_RELEASE_INHERITED(ServoMediaRule, CSSMediaRule) + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServoMediaRule) + NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule) + +-NS_IMPL_CYCLE_COLLECTION_INHERITED(ServoMediaRule, CSSMediaRule, +- mMediaList) ++NS_IMPL_CYCLE_COLLECTION_CLASS(ServoMediaRule) ++ ++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoMediaRule, CSSMediaRule) ++ if (tmp->mMediaList) { ++ tmp->mMediaList->SetStyleSheet(nullptr); ++ tmp->mMediaList = nullptr; ++ } ++NS_IMPL_CYCLE_COLLECTION_UNLINK_END ++ ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoMediaRule, CSSMediaRule) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMediaList) ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + + /* virtual */ already_AddRefed<css::Rule> + ServoMediaRule::Clone() const +diff --git layout/style/ServoPageRule.cpp layout/style/ServoPageRule.cpp +index 97c718ed1ba9..93e8ff334122 100644 +--- layout/style/ServoPageRule.cpp ++++ layout/style/ServoPageRule.cpp +@@ -26,6 +26,7 @@ ServoPageRuleDeclaration::ServoPageRuleDeclaration( + + ServoPageRuleDeclaration::~ServoPageRuleDeclaration() + { ++ mDecls->SetOwningRule(nullptr); + } + + // QueryInterface implementation for ServoPageRuleDeclaration +@@ -141,6 +142,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServoPageRule, CSSPageRule) + // NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER which we can't use + // directly because the wrapper is on the declaration, not on us. + tmp->mDecls.ReleaseWrapper(static_cast<nsISupports*>(p)); ++ tmp->mDecls.mDecls->SetOwningRule(nullptr); + NS_IMPL_CYCLE_COLLECTION_UNLINK_END + + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServoPageRule, CSSPageRule) +diff --git layout/style/ServoStyleRule.cpp layout/style/ServoStyleRule.cpp +index 1d7470eef037..855e643515f9 100644 +--- layout/style/ServoStyleRule.cpp ++++ layout/style/ServoStyleRule.cpp +@@ -28,6 +28,7 @@ ServoStyleRuleDeclaration::ServoStyleRuleDeclaration( + + ServoStyleRuleDeclaration::~ServoStyleRuleDeclaration() + { ++ mDecls->SetOwningRule(nullptr); + } + + // QueryInterface implementation for ServoStyleRuleDeclaration +diff --git layout/style/nsCSSRules.cpp layout/style/nsCSSRules.cpp +index 5081244c6a53..0bdedc4a3b03 100644 +--- layout/style/nsCSSRules.cpp ++++ layout/style/nsCSSRules.cpp +@@ -212,12 +212,25 @@ ImportRule::~ImportRule() + NS_IMPL_ADDREF_INHERITED(ImportRule, CSSImportRule) + NS_IMPL_RELEASE_INHERITED(ImportRule, CSSImportRule) + +-NS_IMPL_CYCLE_COLLECTION_INHERITED(ImportRule, CSSImportRule, mMedia, mChildSheet) +- + // QueryInterface implementation for ImportRule + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ImportRule) + NS_INTERFACE_MAP_END_INHERITING(CSSImportRule) + ++NS_IMPL_CYCLE_COLLECTION_CLASS(ImportRule) ++ ++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ImportRule, CSSImportRule) ++ if (tmp->mChildSheet) { ++ tmp->mChildSheet->SetOwnerRule(nullptr); ++ tmp->mChildSheet = nullptr; ++ } ++ tmp->mMedia = nullptr; ++NS_IMPL_CYCLE_COLLECTION_UNLINK_END ++ ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ImportRule, CSSImportRule) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildSheet) ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END ++ + #ifdef DEBUG + /* virtual */ void + ImportRule::List(FILE* out, int32_t aIndent) const +@@ -342,8 +355,18 @@ NS_IMPL_RELEASE_INHERITED(MediaRule, CSSMediaRule) + NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaRule) + NS_INTERFACE_MAP_END_INHERITING(CSSMediaRule) + +-NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaRule, CSSMediaRule, +- mMedia) ++NS_IMPL_CYCLE_COLLECTION_CLASS(MediaRule) ++ ++NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaRule, CSSMediaRule) ++ if (tmp->mMedia) { ++ tmp->mMedia->SetStyleSheet(nullptr); ++ tmp->mMedia = nullptr; ++ } ++NS_IMPL_CYCLE_COLLECTION_UNLINK_END ++ ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaRule, CSSMediaRule) ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMedia) ++NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + + /* virtual */ void + MediaRule::SetStyleSheet(StyleSheet* aSheet) diff --git a/www/waterfox/files/patch-bug1412420 b/www/waterfox/files/patch-bug1412420 new file mode 100644 index 000000000000..6bafc3fb91fc --- /dev/null +++ b/www/waterfox/files/patch-bug1412420 @@ -0,0 +1,284 @@ +commit c3b597795e95 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Sat Dec 16 16:22:13 2017 -0600 + + Bug 1412420 - Ensure upper bits are zeroed when calling a function that returns int32. r=nbp a=ritu + + --HG-- + extra : source : 26d3df5b58fb60facb9057dc1e86576127c9e1f5 +--- + js/src/irregexp/NativeRegExpMacroAssembler.cpp | 4 ++-- + js/src/irregexp/RegExpStack.cpp | 2 +- + js/src/irregexp/RegExpStack.h | 2 +- + js/src/jit/CodeGenerator.cpp | 12 ++++++------ + js/src/jit/MacroAssembler-inl.h | 11 +++++++++++ + js/src/jit/MacroAssembler.cpp | 2 +- + js/src/jit/MacroAssembler.h | 3 ++- + js/src/jit/SharedIC.cpp | 16 ++++++++-------- + js/src/jit/shared/CodeGenerator-shared.h | 8 +++++--- + js/src/jit/x86/CodeGenerator-x86.cpp | 4 ++-- + 10 files changed, 39 insertions(+), 25 deletions(-) + +diff --git js/src/irregexp/NativeRegExpMacroAssembler.cpp js/src/irregexp/NativeRegExpMacroAssembler.cpp +index 004bb8e108f2..0c5743ea506b 100644 +--- js/src/irregexp/NativeRegExpMacroAssembler.cpp ++++ js/src/irregexp/NativeRegExpMacroAssembler.cpp +@@ -453,7 +453,7 @@ NativeRegExpMacroAssembler::GenerateCode(JSContext* cx, bool match_only) + masm.setupUnalignedABICall(temp0); + masm.passABIArg(temp1); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, GrowBacktrackStack)); +- masm.storeCallWordResult(temp0); ++ masm.storeCallBoolResult(temp0); + + masm.PopRegsInMask(volatileRegs); + +@@ -882,7 +882,7 @@ NativeRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(int start_reg, Label + int (*fun)(const char16_t*, const char16_t*, size_t) = CaseInsensitiveCompareUCStrings; + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, fun)); + } +- masm.storeCallWordResult(temp0); ++ masm.storeCallInt32Result(temp0); + + masm.PopRegsInMask(volatileRegs); + +diff --git js/src/irregexp/RegExpStack.cpp js/src/irregexp/RegExpStack.cpp +index 7ea47149ed40..15008ccd7b9b 100644 +--- js/src/irregexp/RegExpStack.cpp ++++ js/src/irregexp/RegExpStack.cpp +@@ -44,7 +44,7 @@ RegExpStackScope::~RegExpStackScope() + regexp_stack->reset(); + } + +-int ++bool + irregexp::GrowBacktrackStack(JSRuntime* rt) + { + AutoUnsafeCallWithABI unsafe; +diff --git js/src/irregexp/RegExpStack.h js/src/irregexp/RegExpStack.h +index da81567a11b6..c92666f2427a 100644 +--- js/src/irregexp/RegExpStack.h ++++ js/src/irregexp/RegExpStack.h +@@ -114,7 +114,7 @@ class RegExpStack + } + }; + +-int ++bool + GrowBacktrackStack(JSRuntime* rt); + + }} // namespace js::irregexp +diff --git js/src/jit/CodeGenerator.cpp js/src/jit/CodeGenerator.cpp +index 22c0a3163232..4befbdc285db 100644 +--- js/src/jit/CodeGenerator.cpp ++++ js/src/jit/CodeGenerator.cpp +@@ -1640,7 +1640,7 @@ CreateDependentString::generateFallback(MacroAssembler& masm, LiveRegisterSet re + masm.callWithABI(kind == FallbackKind::FatInlineString + ? JS_FUNC_TO_DATA_PTR(void*, AllocateFatInlineString) + : JS_FUNC_TO_DATA_PTR(void*, AllocateString)); +- masm.storeCallWordResult(string_); ++ masm.storeCallPointerResult(string_); + + masm.PopRegsInMask(regsToSave); + +@@ -1679,7 +1679,7 @@ CreateMatchResultFallback(MacroAssembler& masm, LiveRegisterSet regsToSave, + masm.move32(Imm32(int32_t(templateObj->as<NativeObject>().numDynamicSlots())), temp5); + masm.passABIArg(temp5); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, CreateMatchResultFallbackFunc)); +- masm.storeCallWordResult(object); ++ masm.storeCallPointerResult(object); + + masm.PopRegsInMask(regsToSave); + +@@ -7976,7 +7976,7 @@ JitRuntime::generateMallocStub(JSContext* cx) + masm.passABIArg(regZone); + masm.passABIArg(regNBytes); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, MallocWrapper)); +- masm.storeCallWordResult(regReturn); ++ masm.storeCallPointerResult(regReturn); + + masm.PopRegsInMask(save); + masm.ret(); +@@ -9445,7 +9445,7 @@ CodeGenerator::emitRest(LInstruction* lir, Register array, Register numActuals, + callVM(InitRestParameterInfo, lir); + + if (saveAndRestore) { +- storeResultTo(resultreg); ++ storePointerResultTo(resultreg); + restoreLive(lir); + } + } +@@ -10682,8 +10682,8 @@ CodeGenerator::visitOutOfLineTypeOfV(OutOfLineTypeOfV* ool) + masm.passABIArg(obj); + masm.movePtr(ImmPtr(gen->runtime), output); + masm.passABIArg(output); +- masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, TypeOfObject)); +- masm.storeCallWordResult(output); ++ masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, jit::TypeOfObject)); ++ masm.storeCallPointerResult(output); + restoreVolatile(output); + + masm.jump(ool->rejoin()); +diff --git js/src/jit/MacroAssembler-inl.h js/src/jit/MacroAssembler-inl.h +index 9d0acbfb4002..a1f9716e1329 100644 +--- js/src/jit/MacroAssembler-inl.h ++++ js/src/jit/MacroAssembler-inl.h +@@ -831,6 +831,17 @@ MacroAssembler::storeCallBoolResult(Register reg) + and32(Imm32(0xFF), reg); + } + ++void ++MacroAssembler::storeCallInt32Result(Register reg) ++{ ++#if JS_BITS_PER_WORD == 32 ++ storeCallPointerResult(reg); ++#else ++ // Ensure the upper 32 bits are cleared. ++ move32(ReturnReg, reg); ++#endif ++} ++ + void + MacroAssembler::storeCallResultValue(AnyRegister dest) + { +diff --git js/src/jit/MacroAssembler.cpp js/src/jit/MacroAssembler.cpp +index 0863dd980e93..25c284324bfe 100644 +--- js/src/jit/MacroAssembler.cpp ++++ js/src/jit/MacroAssembler.cpp +@@ -2117,7 +2117,7 @@ MacroAssembler::outOfLineTruncateSlow(FloatRegister src, Register dest, bool wid + callWithABI(mozilla::BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32), + MoveOp::GENERAL, CheckUnsafeCallWithABI::DontCheckOther); + } +- storeCallWordResult(dest); ++ storeCallInt32Result(dest); + + #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \ + defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) +diff --git js/src/jit/MacroAssembler.h js/src/jit/MacroAssembler.h +index e353c5aa10f5..2c8b005b7008 100644 +--- js/src/jit/MacroAssembler.h ++++ js/src/jit/MacroAssembler.h +@@ -1630,12 +1630,13 @@ class MacroAssembler : public MacroAssemblerSpecific + storeTypedOrValue(src.reg(), dest); + } + +- void storeCallWordResult(Register reg) { ++ void storeCallPointerResult(Register reg) { + if (reg != ReturnReg) + mov(ReturnReg, reg); + } + + inline void storeCallBoolResult(Register reg); ++ inline void storeCallInt32Result(Register reg); + + void storeCallFloatResult(FloatRegister reg) { + if (reg != ReturnDoubleReg) +diff --git js/src/jit/SharedIC.cpp js/src/jit/SharedIC.cpp +index 0c8be36a592d..1f88cc93176d 100644 +--- js/src/jit/SharedIC.cpp ++++ js/src/jit/SharedIC.cpp +@@ -1145,19 +1145,19 @@ ICBinaryArith_BooleanWithInt32::Compiler::generateStubCode(MacroAssembler& masm) + break; + } + case JSOP_BITOR: { +- masm.orPtr(rhsReg, lhsReg); ++ masm.or32(rhsReg, lhsReg); + masm.tagValue(JSVAL_TYPE_INT32, lhsReg, R0); + EmitReturnFromIC(masm); + break; + } + case JSOP_BITXOR: { +- masm.xorPtr(rhsReg, lhsReg); ++ masm.xor32(rhsReg, lhsReg); + masm.tagValue(JSVAL_TYPE_INT32, lhsReg, R0); + EmitReturnFromIC(masm); + break; + } + case JSOP_BITAND: { +- masm.andPtr(rhsReg, lhsReg); ++ masm.and32(rhsReg, lhsReg); + masm.tagValue(JSVAL_TYPE_INT32, lhsReg, R0); + EmitReturnFromIC(masm); + break; +@@ -1206,7 +1206,7 @@ ICBinaryArith_DoubleWithInt32::Compiler::generateStubCode(MacroAssembler& masm) + masm.setupUnalignedABICall(scratchReg); + masm.passABIArg(FloatReg0, MoveOp::DOUBLE); + masm.callWithABI(mozilla::BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32)); +- masm.storeCallWordResult(scratchReg); ++ masm.storeCallInt32Result(scratchReg); + masm.pop(intReg); + + masm.bind(&doneTruncate); +@@ -1216,13 +1216,13 @@ ICBinaryArith_DoubleWithInt32::Compiler::generateStubCode(MacroAssembler& masm) + // All handled ops commute, so no need to worry about ordering. + switch(op) { + case JSOP_BITOR: +- masm.orPtr(intReg, intReg2); ++ masm.or32(intReg, intReg2); + break; + case JSOP_BITXOR: +- masm.xorPtr(intReg, intReg2); ++ masm.xor32(intReg, intReg2); + break; + case JSOP_BITAND: +- masm.andPtr(intReg, intReg2); ++ masm.and32(intReg, intReg2); + break; + default: + MOZ_CRASH("Unhandled op for BinaryArith_DoubleWithInt32."); +@@ -1359,7 +1359,7 @@ ICUnaryArith_Double::Compiler::generateStubCode(MacroAssembler& masm) + masm.setupUnalignedABICall(scratchReg); + masm.passABIArg(FloatReg0, MoveOp::DOUBLE); + masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32)); +- masm.storeCallWordResult(scratchReg); ++ masm.storeCallInt32Result(scratchReg); + + masm.bind(&doneTruncate); + masm.not32(scratchReg); +diff --git js/src/jit/shared/CodeGenerator-shared.h js/src/jit/shared/CodeGenerator-shared.h +index d75572dac0a6..48b2b4d8561c 100644 +--- js/src/jit/shared/CodeGenerator-shared.h ++++ js/src/jit/shared/CodeGenerator-shared.h +@@ -454,8 +454,8 @@ class CodeGeneratorShared : public LElementVisitor + return masm.PushWithPatch(t); + } + +- void storeResultTo(Register reg) { +- masm.storeCallWordResult(reg); ++ void storePointerResultTo(Register reg) { ++ masm.storeCallPointerResult(reg); + } + + void storeFloatResultTo(FloatRegister reg) { +@@ -725,7 +725,9 @@ class StoreRegisterTo + { } + + inline void generate(CodeGeneratorShared* codegen) const { +- codegen->storeResultTo(out_); ++ // It's okay to use storePointerResultTo here - the VMFunction wrapper ++ // ensures the upper bytes are zero for bool/int32 return values. ++ codegen->storePointerResultTo(out_); + } + inline LiveRegisterSet clobbered() const { + LiveRegisterSet set; +diff --git js/src/jit/x86/CodeGenerator-x86.cpp js/src/jit/x86/CodeGenerator-x86.cpp +index e2f80c4ac8fc..fe358c370baf 100644 +--- js/src/jit/x86/CodeGenerator-x86.cpp ++++ js/src/jit/x86/CodeGenerator-x86.cpp +@@ -747,7 +747,7 @@ CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate* ool) + masm.callWithABI(BitwiseCast<void*, int32_t(*)(double)>(JS::ToInt32), MoveOp::GENERAL, + CheckUnsafeCallWithABI::DontCheckOther); + } +- masm.storeCallWordResult(output); ++ masm.storeCallInt32Result(output); + + restoreVolatile(output); + } +@@ -839,7 +839,7 @@ CodeGeneratorX86::visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32* ool) + CheckUnsafeCallWithABI::DontCheckOther); + } + +- masm.storeCallWordResult(output); ++ masm.storeCallInt32Result(output); + masm.Pop(input); + + restoreVolatile(output); diff --git a/www/waterfox/files/patch-bug1412558 b/www/waterfox/files/patch-bug1412558 new file mode 100644 index 000000000000..dd142370e238 --- /dev/null +++ b/www/waterfox/files/patch-bug1412558 @@ -0,0 +1,42 @@ +diff --git dom/media/flac/FlacDecoder.cpp dom/media/flac/FlacDecoder.cpp +index 53fc3c9937f7..b23771ab80fa 100644 +--- dom/media/flac/FlacDecoder.cpp ++++ dom/media/flac/FlacDecoder.cpp +@@ -7,6 +7,7 @@ + #include "FlacDecoder.h" + #include "MediaContainerType.h" + #include "MediaPrefs.h" ++#include "PDMFactory.h" + + namespace mozilla { + +@@ -15,6 +16,10 @@ FlacDecoder::IsEnabled() + { + #ifdef MOZ_FFVPX + return MediaPrefs::FlacEnabled(); ++#elif defined(MOZ_FFMPEG) ++ RefPtr<PDMFactory> platform = new PDMFactory(); ++ return MediaPrefs::FlacEnabled() && platform->SupportsMimeType(NS_LITERAL_CSTRING("audio/flac"), ++ /* DecoderDoctorDiagnostics* */ nullptr); + #else + // Until bug 1295886 is fixed. + return false; +diff --git old-configure.in old-configure.in +index b8ce71278548..410be683c2f6 100644 +--- old-configure.in ++++ old-configure.in +@@ -3279,11 +3279,11 @@ dnl = FFmpeg's ffvpx configuration + dnl ======================================================== + + MOZ_FFVPX= +-case "$CPU_ARCH" in +- x86) ++case "$OS_ARCH:$CPU_ARCH" in ++ WINNT:x86) + MOZ_FFVPX=1 + ;; +- x86_64) ++ *:x86_64) + MOZ_FFVPX=1 + ;; + esac diff --git a/www/waterfox/files/patch-bug1412741 b/www/waterfox/files/patch-bug1412741 new file mode 100644 index 000000000000..5bf24d87ce61 --- /dev/null +++ b/www/waterfox/files/patch-bug1412741 @@ -0,0 +1,87 @@ +commit 9bfa45f5e083 +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Thu Nov 2 13:02:55 2017 -0400 + + Bug 1412741 - Back out the fix for bug 1381408, because that change doesn't look like it's web-compatible. r=peterv, a=ritu + + MozReview-Commit-ID: LSYYAt0bAkT + + --HG-- + extra : source : 1fdce3a0396c599ad52749e1650beeb8f455d891 +--- + js/xpconnect/tests/mochitest/test_bug862380.html | 23 +++++----------------- + js/xpconnect/wrappers/FilteringWrapper.cpp | 5 +++-- + .../cross-origin-objects.html.ini | 10 ++++++++++ + 3 files changed, 18 insertions(+), 20 deletions(-) + +diff --git js/xpconnect/tests/mochitest/test_bug862380.html js/xpconnect/tests/mochitest/test_bug862380.html +index 0f1611776320..0d3fb7329358 100644 +--- js/xpconnect/tests/mochitest/test_bug862380.html ++++ js/xpconnect/tests/mochitest/test_bug862380.html +@@ -13,29 +13,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=862380 + /** Test for Bug 862380 **/ + SimpleTest.waitForExplicitFinish(); + function go() { +- checkNotEnumerable($('ifr').contentWindow, true); +- checkNotEnumerable($('ifr').contentWindow.location, false); ++ checkNotEnumerable($('ifr').contentWindow); ++ checkNotEnumerable($('ifr').contentWindow.location); + SimpleTest.finish(); + } + +-function checkNotEnumerable(obj, isWindow) { ++ function checkNotEnumerable(obj) { + try { +- const expectedWindow = ["0", "window", "location", "top", "close", +- "focus", "blur", "postMessage", "self", "closed", +- "frames", "length", "opener", "parent"]; +- const expectedLocation = ["replace", "href"]; +- const expected = isWindow ? expectedWindow : expectedLocation; +- is(Object.keys(obj).length, expected.length, +- "Object.keys gives right array length"); +- var actual = []; ++ is(Object.keys(obj).length, 0, "Object.keys gives empty array"); + for (var i in obj) +- actual.push(i); +- is(actual.length, expected.length, +- "Enumeration sees the right number of props"); +- actual.sort(); +- expected.sort(); +- for (var i = 0; i < actual.length; ++i) +- is(actual[i], expected[i], "Arrays should be the same " + i); ++ ok(false, "Enumerated something: " + i); + } catch (e) { + ok(false, "threw: " + e); + } +diff --git js/xpconnect/wrappers/FilteringWrapper.cpp js/xpconnect/wrappers/FilteringWrapper.cpp +index c35c3e896afc..1e986c734cde 100644 +--- js/xpconnect/wrappers/FilteringWrapper.cpp ++++ js/xpconnect/wrappers/FilteringWrapper.cpp +@@ -223,8 +223,9 @@ CrossOriginXrayWrapper::getPropertyDescriptor(JSContext* cx, + // All properties on cross-origin DOM objects are |own|. + desc.object().set(wrapper); + +- // All properties on cross-origin DOM objects are "configurable". Any +- // value attributes are read-only. ++ // All properties on cross-origin DOM objects are non-enumerable and ++ // "configurable". Any value attributes are read-only. ++ desc.attributesRef() &= ~JSPROP_ENUMERATE; + desc.attributesRef() &= ~JSPROP_PERMANENT; + if (!desc.getter() && !desc.setter()) + desc.attributesRef() |= JSPROP_READONLY; +diff --git testing/web-platform/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini testing/web-platform/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini +new file mode 100644 +index 000000000000..6c5e683863e9 +--- /dev/null ++++ testing/web-platform/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini +@@ -0,0 +1,10 @@ ++[cross-origin-objects.html] ++ type: testharness ++ [[[GetOwnProperty\]\] - Property descriptors for cross-origin properties should be set up correctly] ++ expected: FAIL ++ ++ [Can only enumerate safelisted properties] ++ expected: FAIL ++ ++ [[[OwnPropertyKeys\]\] should return all properties from cross-origin objects] ++ expected: FAIL diff --git a/www/waterfox/files/patch-bug1412882 b/www/waterfox/files/patch-bug1412882 new file mode 100644 index 000000000000..327b6da45b9b --- /dev/null +++ b/www/waterfox/files/patch-bug1412882 @@ -0,0 +1,192 @@ +commit 7513891383a1 +Author: Jonathan Kew <jkew@mozilla.com> +Date: Sat May 19 08:32:22 2018 +0100 + + Bug 1412882 - Rework gfxFontUtils::MapCharToGlyphFormat4 to be more robust. r=lsalzman, a=RyanVM + + --HG-- + extra : source : e96eaa6603005c3e2361d9d32ef59adb718d4203 +--- + gfx/thebes/gfxFontUtils.cpp | 89 ++++++++++++++++++++++------------------ + gfx/thebes/gfxFontUtils.h | 2 +- + gfx/thebes/gfxHarfBuzzShaper.cpp | 8 +++- + 3 files changed, 57 insertions(+), 42 deletions(-) + +diff --git gfx/thebes/gfxFontUtils.cpp gfx/thebes/gfxFontUtils.cpp +index b3c1cae1bbb67..1590fb52ab6b7 100644 +--- gfx/thebes/gfxFontUtils.cpp ++++ gfx/thebes/gfxFontUtils.cpp +@@ -569,55 +569,64 @@ typedef struct { + #pragma pack() + + uint32_t +-gfxFontUtils::MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh) ++gfxFontUtils::MapCharToGlyphFormat4(const uint8_t* aBuf, uint32_t aLength, ++ char16_t aCh) + { + const Format4Cmap *cmap4 = reinterpret_cast<const Format4Cmap*>(aBuf); +- uint16_t segCount; +- const AutoSwap_PRUint16 *endCodes; +- const AutoSwap_PRUint16 *startCodes; +- const AutoSwap_PRUint16 *idDelta; +- const AutoSwap_PRUint16 *idRangeOffset; +- uint16_t probe; +- uint16_t rangeShiftOver2; +- uint16_t index; +- +- segCount = (uint16_t)(cmap4->segCountX2) / 2; +- +- endCodes = &cmap4->arrays[0]; +- startCodes = &cmap4->arrays[segCount + 1]; // +1 for reserved word between arrays +- idDelta = &startCodes[segCount]; +- idRangeOffset = &idDelta[segCount]; +- +- probe = 1 << (uint16_t)(cmap4->entrySelector); +- rangeShiftOver2 = (uint16_t)(cmap4->rangeShift) / 2; +- +- if ((uint16_t)(startCodes[rangeShiftOver2]) <= aCh) { +- index = rangeShiftOver2; +- } else { +- index = 0; +- } +- +- while (probe > 1) { +- probe >>= 1; +- if ((uint16_t)(startCodes[index + probe]) <= aCh) { +- index += probe; ++ ++ uint16_t segCount = (uint16_t)(cmap4->segCountX2) / 2; ++ ++ const AutoSwap_PRUint16* endCodes = &cmap4->arrays[0]; ++ const AutoSwap_PRUint16* startCodes = &cmap4->arrays[segCount + 1]; ++ const AutoSwap_PRUint16* idDelta = &startCodes[segCount]; ++ const AutoSwap_PRUint16* idRangeOffset = &idDelta[segCount]; ++ ++ // Sanity-check that the fixed-size arrays don't exceed the buffer. ++ const uint8_t* const limit = aBuf + aLength; ++ if ((const uint8_t*)(&idRangeOffset[segCount]) > limit) { ++ return 0; // broken font, just bail out safely ++ } ++ ++ // For most efficient binary search, we want to work on a range of segment ++ // indexes that is a power of 2 so that we can always halve it by shifting. ++ // So we find the largest power of 2 that is <= segCount. ++ // We will offset this range by segOffset so as to reach the end ++ // of the table, provided that doesn't put us beyond the target ++ // value from the outset. ++ uint32_t powerOf2 = mozilla::FindHighestBit(segCount); ++ uint32_t segOffset = segCount - powerOf2; ++ uint32_t idx = 0; ++ ++ if (uint16_t(startCodes[segOffset]) <= aCh) { ++ idx = segOffset; ++ } ++ ++ // Repeatedly halve the size of the range until we find the target group ++ while (powerOf2 > 1) { ++ powerOf2 >>= 1; ++ if (uint16_t(startCodes[idx + powerOf2]) <= aCh) { ++ idx += powerOf2; + } + } + +- if (aCh >= (uint16_t)(startCodes[index]) && aCh <= (uint16_t)(endCodes[index])) { ++ if (aCh >= uint16_t(startCodes[idx]) && aCh <= uint16_t(endCodes[idx])) { + uint16_t result; +- if ((uint16_t)(idRangeOffset[index]) == 0) { ++ if (uint16_t(idRangeOffset[idx]) == 0) { + result = aCh; + } else { +- uint16_t offset = aCh - (uint16_t)(startCodes[index]); +- const AutoSwap_PRUint16 *glyphIndexTable = +- (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[index] + +- (uint16_t)(idRangeOffset[index])); ++ uint16_t offset = aCh - uint16_t(startCodes[idx]); ++ const AutoSwap_PRUint16* glyphIndexTable = ++ (const AutoSwap_PRUint16*)((const char*)&idRangeOffset[idx] + ++ uint16_t(idRangeOffset[idx])); ++ if ((const uint8_t*)(glyphIndexTable + offset + 1) > limit) { ++ return 0; // broken font, just bail out safely ++ } + result = glyphIndexTable[offset]; + } + +- // note that this is unsigned 16-bit arithmetic, and may wrap around +- result += (uint16_t)(idDelta[index]); ++ // Note that this is unsigned 16-bit arithmetic, and may wrap around ++ // (which is required behavior per spec) ++ result += uint16_t(idDelta[idx]); + return result; + } + +@@ -761,7 +770,8 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, + switch (format) { + case 4: + gid = aUnicode < UNICODE_BMP_LIMIT ? +- MapCharToGlyphFormat4(aCmapBuf + offset, char16_t(aUnicode)) : 0; ++ MapCharToGlyphFormat4(aCmapBuf + offset, aBufLength - offset, ++ char16_t(aUnicode)) : 0; + break; + case 10: + gid = MapCharToGlyphFormat10(aCmapBuf + offset, aUnicode); +@@ -786,6 +796,7 @@ gfxFontUtils::MapCharToGlyph(const uint8_t *aCmapBuf, uint32_t aBufLength, + case 4: + if (aUnicode < UNICODE_BMP_LIMIT) { + varGID = MapCharToGlyphFormat4(aCmapBuf + offset, ++ aBufLength - offset, + char16_t(aUnicode)); + } + break; +diff --git gfx/thebes/gfxFontUtils.h gfx/thebes/gfxFontUtils.h +index 250df442c3a2e..be2f54a9a7026 100644 +--- gfx/thebes/gfxFontUtils.h ++++ gfx/thebes/gfxFontUtils.h +@@ -804,7 +804,7 @@ public: + uint32_t& aUVSOffset); + + static uint32_t +- MapCharToGlyphFormat4(const uint8_t *aBuf, char16_t aCh); ++ MapCharToGlyphFormat4(const uint8_t *aBuf, uint32_t aLength, char16_t aCh); + + static uint32_t + MapCharToGlyphFormat10(const uint8_t *aBuf, uint32_t aCh); +diff --git gfx/thebes/gfxHarfBuzzShaper.cpp gfx/thebes/gfxHarfBuzzShaper.cpp +index c57504a4d9db4..ff638dcef73ad 100644 +--- gfx/thebes/gfxHarfBuzzShaper.cpp ++++ gfx/thebes/gfxHarfBuzzShaper.cpp +@@ -116,13 +116,15 @@ gfxHarfBuzzShaper::GetNominalGlyph(hb_codepoint_t unicode) const + NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0), + "cmap data not correctly set up, expect disaster"); + ++ uint32_t length; + const uint8_t* data = +- (const uint8_t*)hb_blob_get_data(mCmapTable, nullptr); ++ (const uint8_t*)hb_blob_get_data(mCmapTable, &length); + + switch (mCmapFormat) { + case 4: + gid = unicode < UNICODE_BMP_LIMIT ? + gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset, ++ length - mSubtableOffset, + unicode) : 0; + break; + case 10: +@@ -164,8 +166,9 @@ gfxHarfBuzzShaper::GetVariationGlyph(hb_codepoint_t unicode, + NS_ASSERTION(mCmapTable && (mCmapFormat > 0) && (mSubtableOffset > 0), + "cmap data not correctly set up, expect disaster"); + ++ uint32_t length; + const uint8_t* data = +- (const uint8_t*)hb_blob_get_data(mCmapTable, nullptr); ++ (const uint8_t*)hb_blob_get_data(mCmapTable, &length); + + if (mUVSTableOffset) { + hb_codepoint_t gid = +@@ -183,6 +186,7 @@ gfxHarfBuzzShaper::GetVariationGlyph(hb_codepoint_t unicode, + case 4: + if (compat < UNICODE_BMP_LIMIT) { + return gfxFontUtils::MapCharToGlyphFormat4(data + mSubtableOffset, ++ length - mSubtableOffset, + compat); + } + break; diff --git a/www/waterfox/files/patch-bug1413143 b/www/waterfox/files/patch-bug1413143 new file mode 100644 index 000000000000..19067f325bd3 --- /dev/null +++ b/www/waterfox/files/patch-bug1413143 @@ -0,0 +1,306 @@ +commit 51708fb1315d +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Wed Nov 1 11:24:17 2017 +0100 + + Bug 1413143: Make font inflation computation less lazy. r=bz,JanH + + This makes it a bit more straight-forward to change the system font scale, + preserving the sync MediaFeatureChanged event. + + This also avoids notifying media queries when the shell is not initialized. + + In particular, the patch in bug 1404545 allows calling MediaFeatureValuesChanged + on a still-initializing pres-shell. This is nasty, and all this initialization + order is kind of a mess, but I'm not reworking it for now... + + Also, this drops the invalidation of font-inflation when a doctype is added to + the document. GetViewportInfo() already relies on the doctype not changing, as + noted in a comment. + + MozReview-Commit-ID: Knw7dM1B04Y +--- + dom/base/nsDocument.cpp | 2 + + layout/base/PresShell.cpp | 84 ++++++++++++++------------------------- + layout/base/nsIPresShell.h | 36 ++++------------- + layout/base/nsLayoutUtils.cpp | 8 ++-- + layout/base/nsPresContext.cpp | 6 ++- + layout/reftests/bugs/reftest.list | 2 +- + 6 files changed, 48 insertions(+), 90 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 03bf17e6a4b9..f3579c9420d6 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -8172,6 +8172,8 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv) + nsViewportInfo + nsDocument::GetViewportInfo(const ScreenIntSize& aDisplaySize) + { ++ MOZ_ASSERT(mPresShell); ++ + // Compute the CSS-to-LayoutDevice pixel scale as the product of the + // widget scale and the full zoom. + nsPresContext* context = mPresShell->GetPresContext(); +diff --git layout/base/PresShell.cpp layout/base/PresShell.cpp +index 6983d2d3c894..a883791d3695 100644 +--- layout/base/PresShell.cpp ++++ layout/base/PresShell.cpp +@@ -765,7 +765,6 @@ nsIPresShell::nsIPresShell() + , mFontSizeInflationForceEnabled(false) + , mFontSizeInflationDisabledInMasterProcess(false) + , mFontSizeInflationEnabled(false) +- , mFontSizeInflationEnabledIsDirty(false) + , mPaintingIsFrozen(false) + , mIsNeverPainting(false) + , mInFlush(false) +@@ -1010,7 +1009,13 @@ PresShell::Init(nsIDocument* aDocument, + QueryIsActive(); + + // Setup our font inflation preferences. +- SetupFontInflation(); ++ mFontSizeInflationEmPerLine = nsLayoutUtils::FontSizeInflationEmPerLine(); ++ mFontSizeInflationMinTwips = nsLayoutUtils::FontSizeInflationMinTwips(); ++ mFontSizeInflationLineThreshold = nsLayoutUtils::FontSizeInflationLineThreshold(); ++ mFontSizeInflationForceEnabled = nsLayoutUtils::FontSizeInflationForceEnabled(); ++ mFontSizeInflationDisabledInMasterProcess = nsLayoutUtils::FontSizeInflationDisabledInMasterProcess(); ++ // We'll compute the font size inflation state in Initialize(), when we know ++ // the document type. + + mTouchManager.Init(this, mDocument); + +@@ -1700,6 +1705,10 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight) + NS_ASSERTION(!mDidInitialize, "Why are we being called?"); + + nsCOMPtr<nsIPresShell> kungFuDeathGrip(this); ++ ++ RecomputeFontSizeInflationEnabled(); ++ MOZ_DIAGNOSTIC_ASSERT(!mIsDestroying); ++ + mDidInitialize = true; + + #ifdef DEBUG +@@ -1725,6 +1734,7 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight) + // time we do this! + nsIFrame* rootFrame = mFrameConstructor->GetRootFrame(); + NS_ASSERTION(!rootFrame, "How did that happen, exactly?"); ++ + if (!rootFrame) { + nsAutoScriptBlocker scriptBlocker; + mFrameConstructor->BeginUpdate(); +@@ -4456,11 +4466,6 @@ PresShell::ContentInserted(nsIDocument* aDocument, + nullptr, + nsCSSFrameConstructor::InsertionKind::Async); + +- if (aChild->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) { +- MOZ_ASSERT(container == aDocument); +- NotifyFontSizeInflationEnabledIsDirty(); +- } +- + VERIFY_STYLE_TREE; + } + +@@ -4505,11 +4510,6 @@ PresShell::ContentRemoved(nsIDocument *aDocument, + mFrameConstructor->ContentRemoved(aMaybeContainer, aChild, oldNextSibling, + nsCSSFrameConstructor::REMOVE_CONTENT); + +- if (aChild->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE) { +- MOZ_ASSERT(container == aDocument); +- NotifyFontSizeInflationEnabledIsDirty(); +- } +- + VERIFY_STYLE_TREE; + } + +@@ -10701,33 +10701,34 @@ nsIPresShell::SetScrollPositionClampingScrollPortSize(nscoord aWidth, nscoord aH + } + } + +-void +-PresShell::SetupFontInflation() +-{ +- mFontSizeInflationEmPerLine = nsLayoutUtils::FontSizeInflationEmPerLine(); +- mFontSizeInflationMinTwips = nsLayoutUtils::FontSizeInflationMinTwips(); +- mFontSizeInflationLineThreshold = nsLayoutUtils::FontSizeInflationLineThreshold(); +- mFontSizeInflationForceEnabled = nsLayoutUtils::FontSizeInflationForceEnabled(); +- mFontSizeInflationDisabledInMasterProcess = nsLayoutUtils::FontSizeInflationDisabledInMasterProcess(); +- +- NotifyFontSizeInflationEnabledIsDirty(); +-} +- + void + nsIPresShell::RecomputeFontSizeInflationEnabled() + { +- mFontSizeInflationEnabledIsDirty = false; + mFontSizeInflationEnabled = DetermineFontSizeInflationState(); + +- HandleSystemFontScale(); ++ float fontScale = nsLayoutUtils::SystemFontScale(); ++ if (fontScale == 0.0f) { ++ return; ++ } ++ ++ MOZ_ASSERT(mDocument); ++ MOZ_ASSERT(mPresContext); ++ if (mFontSizeInflationEnabled || mDocument->IsSyntheticDocument()) { ++ mPresContext->SetSystemFontScale(1.0f); ++ } else { ++ mPresContext->SetSystemFontScale(fontScale); ++ } + } + + bool + nsIPresShell::DetermineFontSizeInflationState() + { + MOZ_ASSERT(mPresContext, "our pres context should not be null"); +- if ((FontSizeInflationEmPerLine() == 0 && +- FontSizeInflationMinTwips() == 0) || mPresContext->IsChrome()) { ++ if (mPresContext->IsChrome()) { ++ return false; ++ } ++ ++ if (FontSizeInflationEmPerLine() == 0 && FontSizeInflationMinTwips() == 0) { + return false; + } + +@@ -10788,33 +10789,6 @@ nsIPresShell::DetermineFontSizeInflationState() + return true; + } + +-bool +-nsIPresShell::FontSizeInflationEnabled() +-{ +- if (mFontSizeInflationEnabledIsDirty) { +- RecomputeFontSizeInflationEnabled(); +- } +- +- return mFontSizeInflationEnabled; +-} +- +-void +-nsIPresShell::HandleSystemFontScale() +-{ +- float fontScale = nsLayoutUtils::SystemFontScale(); +- if (fontScale == 0.0f) { +- return; +- } +- +- MOZ_ASSERT(mDocument && mPresContext, "our document and pres context should not be null"); +- +- if (!mFontSizeInflationEnabled && !mDocument->IsSyntheticDocument()) { +- mPresContext->SetSystemFontScale(fontScale); +- } else { +- mPresContext->SetSystemFontScale(1.0f); +- } +-} +- + void + PresShell::PausePainting() + { +diff --git layout/base/nsIPresShell.h layout/base/nsIPresShell.h +index 32f4855347d5..3f6be216a60c 100644 +--- layout/base/nsIPresShell.h ++++ layout/base/nsIPresShell.h +@@ -1507,24 +1507,14 @@ public: + return mFontSizeInflationDisabledInMasterProcess; + } + +- /** +- * Determine if font size inflation is enabled. This value is cached until +- * it becomes dirty. +- * +- * @returns true, if font size inflation is enabled; false otherwise. +- */ +- bool FontSizeInflationEnabled(); ++ bool FontSizeInflationEnabled() const { ++ return mFontSizeInflationEnabled; ++ } + + /** +- * Notify the pres shell that an event occurred making the current value of +- * mFontSizeInflationEnabled invalid. This will schedule a recomputation of +- * whether font size inflation is enabled on the next call to +- * FontSizeInflationEnabled(). ++ * Recomputes whether font-size inflation is enabled. + */ +- void NotifyFontSizeInflationEnabledIsDirty() +- { +- mFontSizeInflationEnabledIsDirty = true; +- } ++ void RecomputeFontSizeInflationEnabled(); + + /** + * Return true if the most recent interruptible reflow was interrupted. +@@ -1590,23 +1580,11 @@ protected: + void DoObserveLayoutFlushes(); + + /** +- * Do computations necessary to determine if font size inflation is enabled. +- * This value is cached after computation, as the computation is somewhat +- * expensive. +- */ +- void RecomputeFontSizeInflationEnabled(); +- +- /** +- * Does the actual work of figuring out the current state of font size inflation. ++ * Does the actual work of figuring out the current state of font size ++ * inflation. + */ + bool DetermineFontSizeInflationState(); + +- /** +- * Apply the system font scale from the corresponding pref to the PresContext, +- * taking into account the current state of font size inflation. +- */ +- void HandleSystemFontScale(); +- + void RecordAlloc(void* aPtr) { + #ifdef DEBUG + MOZ_ASSERT(!mAllocatedPointers.Contains(aPtr)); +diff --git layout/base/nsLayoutUtils.cpp layout/base/nsLayoutUtils.cpp +index e1289fd4a6a6..e165588e9c6c 100644 +--- layout/base/nsLayoutUtils.cpp ++++ layout/base/nsLayoutUtils.cpp +@@ -9130,16 +9130,16 @@ MaybeReflowForInflationScreenSizeChange(nsPresContext *aPresContext) + { + if (aPresContext) { + nsIPresShell* presShell = aPresContext->GetPresShell(); +- bool fontInflationWasEnabled = presShell->FontSizeInflationEnabled(); +- presShell->NotifyFontSizeInflationEnabledIsDirty(); ++ const bool fontInflationWasEnabled = presShell->FontSizeInflationEnabled(); ++ presShell->RecomputeFontSizeInflationEnabled(); + bool changed = false; +- if (presShell && presShell->FontSizeInflationEnabled() && ++ if (presShell->FontSizeInflationEnabled() && + presShell->FontSizeInflationMinTwips() != 0) { + aPresContext->ScreenSizeInchesForFontInflation(&changed); + } + + changed = changed || +- (fontInflationWasEnabled != presShell->FontSizeInflationEnabled()); ++ fontInflationWasEnabled != presShell->FontSizeInflationEnabled(); + if (changed) { + nsCOMPtr<nsIDocShell> docShell = aPresContext->GetDocShell(); + if (docShell) { +diff --git layout/base/nsPresContext.cpp layout/base/nsPresContext.cpp +index 2fadaf78a29f..1ce0b492673d 100644 +--- layout/base/nsPresContext.cpp ++++ layout/base/nsPresContext.cpp +@@ -2123,6 +2123,10 @@ nsPresContext::MediaFeatureValuesChanged(nsRestyleHint aRestyleHint, + + mPendingViewportChange = false; + ++ if (!mShell || !mShell->DidInitialize()) { ++ return; ++ } ++ + if (mDocument->IsBeingUsedAsImage()) { + MOZ_ASSERT(mDocument->MediaQueryLists().isEmpty()); + return; +@@ -2130,7 +2134,7 @@ nsPresContext::MediaFeatureValuesChanged(nsRestyleHint aRestyleHint, + + mDocument->NotifyMediaFeatureValuesChanged(); + +- MOZ_ASSERT(nsContentUtils::IsSafeToRunScript()); ++ MOZ_DIAGNOSTIC_ASSERT(nsContentUtils::IsSafeToRunScript()); + + // Media query list listeners should be notified from a queued task + // (in HTML5 terms), although we also want to notify them on certain diff --git a/www/waterfox/files/patch-bug1413741 b/www/waterfox/files/patch-bug1413741 new file mode 100644 index 000000000000..28e94186d836 --- /dev/null +++ b/www/waterfox/files/patch-bug1413741 @@ -0,0 +1,25 @@ +commit bd17df85baf4 +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Tue Nov 14 08:18:41 2017 +0100 + + Bug 1413741 - Improve the use of XHR.mProxy in workers after the dispatching of sync OpenRunnable, r=smaug a=gchang + + --HG-- + extra : source : 063022b93ec40d00601a21b92525a4285f984484 +--- + dom/xhr/XMLHttpRequestWorker.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git dom/xhr/XMLHttpRequestWorker.cpp dom/xhr/XMLHttpRequestWorker.cpp +index c337bb258767..9954da23493f 100644 +--- dom/xhr/XMLHttpRequestWorker.cpp ++++ dom/xhr/XMLHttpRequestWorker.cpp +@@ -1895,7 +1895,7 @@ XMLHttpRequestWorker::Open(const nsACString& aMethod, + ++mProxy->mOpenCount; + runnable->Dispatch(Terminating, aRv); + if (aRv.Failed()) { +- if (!--mProxy->mOpenCount) { ++ if (mProxy && !--mProxy->mOpenCount) { + ReleaseProxy(); + } + diff --git a/www/waterfox/files/patch-bug1414292 b/www/waterfox/files/patch-bug1414292 new file mode 100644 index 000000000000..77100836514f --- /dev/null +++ b/www/waterfox/files/patch-bug1414292 @@ -0,0 +1,171 @@ +commit e66612be968f +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Tue Nov 7 15:36:16 2017 -0500 + + Bug 1414292. Update to HTML spec changes for cross-origin object property enumerability. r=peterv + + Updates to https://github.com/whatwg/html/pull/3186 + + Includes the changes from https://github.com/w3c/web-platform-tests/pull/8045 + + MozReview-Commit-ID: 5vEo1QGPufE +--- + js/xpconnect/wrappers/FilteringWrapper.cpp | 9 ++++--- + .../cross-origin-objects.html.ini | 10 ------- + .../cross-origin-objects/cross-origin-objects.html | 31 +++++++++++----------- + 3 files changed, 22 insertions(+), 28 deletions(-) + +diff --git js/xpconnect/wrappers/FilteringWrapper.cpp js/xpconnect/wrappers/FilteringWrapper.cpp +index 1e986c734cde..4c9db40cdd5d 100644 +--- js/xpconnect/wrappers/FilteringWrapper.cpp ++++ js/xpconnect/wrappers/FilteringWrapper.cpp +@@ -223,9 +223,12 @@ CrossOriginXrayWrapper::getPropertyDescriptor(JSContext* cx, + // All properties on cross-origin DOM objects are |own|. + desc.object().set(wrapper); + +- // All properties on cross-origin DOM objects are non-enumerable and +- // "configurable". Any value attributes are read-only. +- desc.attributesRef() &= ~JSPROP_ENUMERATE; ++ // All properties on cross-origin DOM objects are "configurable". Any ++ // value attributes are read-only. Indexed properties are enumerable, ++ // but nothing else is. ++ if (!JSID_IS_INT(id)) { ++ desc.attributesRef() &= ~JSPROP_ENUMERATE; ++ } + desc.attributesRef() &= ~JSPROP_PERMANENT; + if (!desc.getter() && !desc.setter()) + desc.attributesRef() |= JSPROP_READONLY; +diff --git testing/web-platform/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini testing/web-platform/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini +deleted file mode 100644 +index 6c5e683863e9..000000000000 +--- testing/web-platform/meta/html/browsers/origin/cross-origin-objects/cross-origin-objects.html.ini ++++ /dev/null +@@ -1,10 +0,0 @@ +-[cross-origin-objects.html] +- type: testharness +- [[[GetOwnProperty\]\] - Property descriptors for cross-origin properties should be set up correctly] +- expected: FAIL +- +- [Can only enumerate safelisted properties] +- expected: FAIL +- +- [[[OwnPropertyKeys\]\] should return all properties from cross-origin objects] +- expected: FAIL +diff --git testing/web-platform/tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html testing/web-platform/tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html +index 06d96b11372d..f79f7ce4ae51 100644 +--- testing/web-platform/tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html ++++ testing/web-platform/tests/html/browsers/origin/cross-origin-objects/cross-origin-objects.html +@@ -184,17 +184,20 @@ addTest(function() { + }, "[[GetOwnProperty]] - Properties on cross-origin objects should be reported |own|"); + + function checkPropertyDescriptor(desc, propName, expectWritable) { +- var isSymbol = (typeof(propName) == "symbol"); ++ const isSymbol = typeof(propName) === "symbol"; ++ const isArrayIndexPropertyName = !isSymbol && !isNaN(parseInt(propName, 10)); + propName = String(propName); + assert_true(isObject(desc), "property descriptor for " + propName + " should exist"); + assert_equals(desc.configurable, true, "property descriptor for " + propName + " should be configurable"); +- if (isSymbol) { +- assert_equals(desc.enumerable, false, "symbol-property descriptor for " + propName + " should not be enumerable"); +- assert_true("value" in desc, +- "property descriptor for " + propName + " should be a value descriptor"); +- assert_equals(desc.value, undefined, ++ if (!isArrayIndexPropertyName) { ++ assert_equals(desc.enumerable, false, "property descriptor for " + propName + " should not be enumerable"); ++ if(isSymbol) { ++ assert_true("value" in desc, ++ "property descriptor for " + propName + " should be a value descriptor"); ++ assert_equals(desc.value, undefined, + "symbol-named cross-origin visible prop " + propName + + " should come back as undefined"); ++ } + } else { + assert_equals(desc.enumerable, true, "property descriptor for " + propName + " should be enumerable"); + } +@@ -265,16 +268,15 @@ addTest(function() { + let i = 0; + for (var prop in C) { + i++; +- assert_true(whitelistedWindowPropNames.includes(prop), prop + " is not safelisted for a cross-origin Window"); ++ assert_true(whitelistedWindowIndices.includes(prop), prop + " is not safelisted for a cross-origin Window"); + } +- assert_equals(i, whitelistedWindowPropNames.length, "Enumerate all safelisted cross-origin Window properties"); ++ assert_equals(i, whitelistedWindowIndices.length, "Enumerate all enumerable safelisted cross-origin Window properties"); + i = 0; + for (var prop in C.location) { + i++; +- assert_true(whitelistedLocationPropNames.includes(prop), prop + " is not safelisted for a cross-origin Location"); + } +- assert_equals(i, whitelistedLocationPropNames.length, "Enumerate all safelisted cross-origin Location properties"); +-}, "Can only enumerate safelisted properties"); ++ assert_equals(i, 0, "There's nothing to enumerate for cross-origin Location properties"); ++}, "Can only enumerate safelisted enumerable properties"); + + /* + * [[OwnPropertyKeys]] +@@ -285,14 +287,13 @@ addTest(function() { + whitelistedWindowPropNames, + "Object.getOwnPropertyNames() gives the right answer for cross-origin Window"); + assert_array_equals(Object.keys(C).sort(), +- whitelistedWindowPropNames, ++ whitelistedWindowIndices, + "Object.keys() gives the right answer for cross-origin Window"); + assert_array_equals(Object.getOwnPropertyNames(C.location).sort(), + whitelistedLocationPropNames, + "Object.getOwnPropertyNames() gives the right answer for cross-origin Location"); +- assert_array_equals(Object.keys(C.location).sort(), +- whitelistedLocationPropNames, +- "Object.keys() gives the right answer for cross-origin Location"); ++ assert_equals(Object.keys(C.location).length, 0, ++ "Object.keys() gives the right answer for cross-origin Location"); + }, "[[OwnPropertyKeys]] should return all properties from cross-origin objects"); + + addTest(function() { +commit 25f3d350f097 +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Tue Nov 7 16:55:29 2017 -0500 + + Bug 1414292 followup. Indexed properties are enumerable on Window per spec, and thus we fix the CLOSED TREE. + + MozReview-Commit-ID: 6Q76VqwSiEx +--- + js/xpconnect/tests/mochitest/test_bug862380.html | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git js/xpconnect/tests/mochitest/test_bug862380.html js/xpconnect/tests/mochitest/test_bug862380.html +index 0d3fb7329358..eb7cd99c3080 100644 +--- js/xpconnect/tests/mochitest/test_bug862380.html ++++ js/xpconnect/tests/mochitest/test_bug862380.html +@@ -13,16 +13,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=862380 + /** Test for Bug 862380 **/ + SimpleTest.waitForExplicitFinish(); + function go() { +- checkNotEnumerable($('ifr').contentWindow); +- checkNotEnumerable($('ifr').contentWindow.location); ++ checkNotEnumerable($('ifr').contentWindow, true); ++ checkNotEnumerable($('ifr').contentWindow.location, false); + SimpleTest.finish(); + } + +- function checkNotEnumerable(obj) { ++function checkNotEnumerable(obj, isWindow) { + try { +- is(Object.keys(obj).length, 0, "Object.keys gives empty array"); ++ const expectedWindow = ["0"]; ++ const expectedLocation = []; ++ const expected = isWindow ? expectedWindow : expectedLocation; ++ is(Object.keys(obj).length, expected.length, ++ "Object.keys gives right array length"); ++ var actual = []; + for (var i in obj) +- ok(false, "Enumerated something: " + i); ++ actual.push(i); ++ is(actual.length, expected.length, ++ "Enumeration sees the right number of props"); ++ actual.sort(); ++ expected.sort(); ++ for (var i = 0; i < actual.length; ++i) ++ is(actual[i], expected[i], "Arrays should be the same " + i); + } catch (e) { + ok(false, "threw: " + e); + } diff --git a/www/waterfox/files/patch-bug1414425 b/www/waterfox/files/patch-bug1414425 new file mode 100644 index 000000000000..4ae66b3a662a --- /dev/null +++ b/www/waterfox/files/patch-bug1414425 @@ -0,0 +1,231 @@ +commit 8dce7d3eb6a3 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Thu Nov 9 16:32:51 2017 +0100 + + Bug 1414425 - Make sure the appropriate triggeringPrincipal is set for a meta refresh. r=bz, a=gchang + + MozReview-Commit-ID: 4Kn6P4hnx74 + + --HG-- + extra : source : 229546747cbf04cf71a235275d7c2eb2520a298b +--- + browser/base/content/tab-content.js | 2 +- + .../content/test/general/browser_refreshBlocker.js | 2 +- + docshell/base/nsDocShell.cpp | 28 +++++++++++++++------- + docshell/base/nsDocShell.h | 12 +++++++--- + docshell/base/nsIRefreshURI.idl | 23 ++++++++++++++---- + 5 files changed, 50 insertions(+), 17 deletions(-) + +diff --git browser/base/content/tab-content.js browser/base/content/tab-content.js +index 4d85ada0321b..5497a1cc208d 100644 +--- browser/base/content/tab-content.js ++++ browser/base/content/tab-content.js +@@ -995,7 +995,7 @@ var RefreshBlocker = { + + let URI = Services.io.newURI(data.URI); + +- refreshURI.forceRefreshURI(URI, data.delay, true); ++ refreshURI.forceRefreshURI(URI, null, data.delay, true); + } + }, + +diff --git browser/base/content/test/general/browser_refreshBlocker.js browser/base/content/test/general/browser_refreshBlocker.js +index cd82cf40b479..4a280d4cb12b 100644 +--- browser/base/content/test/general/browser_refreshBlocker.js ++++ browser/base/content/test/general/browser_refreshBlocker.js +@@ -20,7 +20,7 @@ async function attemptFakeRefresh(browser, expectRefresh) { + await ContentTask.spawn(browser, expectRefresh, async function(contentExpectRefresh) { + let URI = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI; + let refresher = docShell.QueryInterface(Ci.nsIRefreshURI); +- refresher.refreshURI(URI, 0, false, true); ++ refresher.refreshURI(URI, null, 0, false, true); + + Assert.equal(refresher.refreshPending, contentExpectRefresh, + "Got the right refreshPending state"); +diff --git docshell/base/nsDocShell.cpp docshell/base/nsDocShell.cpp +index 3ded70a66fe8..83cb87dd8255 100644 +--- docshell/base/nsDocShell.cpp ++++ docshell/base/nsDocShell.cpp +@@ -6831,7 +6831,8 @@ nsDocShell::ScrollByPages(int32_t aNumPages) + //***************************************************************************** + + NS_IMETHODIMP +-nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat, ++nsDocShell::RefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, ++ int32_t aDelay, bool aRepeat, + bool aMetaRefresh) + { + NS_ENSURE_ARG(aURI); +@@ -6860,7 +6861,7 @@ nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat, + } + + nsCOMPtr<nsITimerCallback> refreshTimer = +- new nsRefreshTimer(this, aURI, aDelay, aRepeat, aMetaRefresh); ++ new nsRefreshTimer(this, aURI, aPrincipal, aDelay, aRepeat, aMetaRefresh); + + uint32_t busyFlags = 0; + GetBusyFlags(&busyFlags); +@@ -6891,6 +6892,7 @@ nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat, + + nsresult + nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI, ++ nsIPrincipal* aPrincipal, + int32_t aDelay, + bool aMetaRefresh, + nsITimer* aTimer) +@@ -6911,11 +6913,11 @@ nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI, + } + } + +- return ForceRefreshURI(aURI, aDelay, aMetaRefresh); ++ return ForceRefreshURI(aURI, aPrincipal, aDelay, aMetaRefresh); + } + + NS_IMETHODIMP +-nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh) ++nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDelay, bool aMetaRefresh) + { + NS_ENSURE_ARG(aURI); + +@@ -6963,6 +6965,13 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh) + loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh); + } + ++ // If the principal is null, the refresh will have a triggeringPrincipal ++ // derived from the referrer URI, or will be set to the system principal ++ // if there is no refererrer. See LoadURI() ++ if (aPrincipal) { ++ loadInfo->SetTriggeringPrincipal(aPrincipal); ++ } ++ + /* + * LoadURI(...) will cancel all refresh timers... This causes the + * Timer and its refreshData instance to be released... +@@ -7203,7 +7212,7 @@ nsDocShell::SetupRefreshURIFromHeader(nsIURI* aBaseURI, + return NS_ERROR_FAILURE; + } + +- rv = RefreshURI(uri, seconds * 1000, false, true); ++ rv = RefreshURI(uri, aPrincipal, seconds * 1000, false, true); + } + } + } +@@ -13793,9 +13802,12 @@ nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState) + return NS_OK; + } + +-nsRefreshTimer::nsRefreshTimer(nsDocShell* aDocShell, nsIURI* aURI, ++nsRefreshTimer::nsRefreshTimer(nsDocShell* aDocShell, ++ nsIURI* aURI, ++ nsIPrincipal* aPrincipal, + int32_t aDelay, bool aRepeat, bool aMetaRefresh) +- : mDocShell(aDocShell), mURI(aURI), mDelay(aDelay), mRepeat(aRepeat), ++ : mDocShell(aDocShell), mURI(aURI), mPrincipal(aPrincipal), ++ mDelay(aDelay), mRepeat(aRepeat), + mMetaRefresh(aMetaRefresh) + { + } +@@ -13822,7 +13834,7 @@ nsRefreshTimer::Notify(nsITimer* aTimer) + // Get the delay count to determine load type + uint32_t delay = 0; + aTimer->GetDelay(&delay); +- mDocShell->ForceRefreshURIFromTimer(mURI, delay, mMetaRefresh, aTimer); ++ mDocShell->ForceRefreshURIFromTimer(mURI, mPrincipal, delay, mMetaRefresh, aTimer); + } + return NS_OK; + } +diff --git docshell/base/nsDocShell.h docshell/base/nsDocShell.h +index f805deaa2edf..57fc63fe5795 100644 +--- docshell/base/nsDocShell.h ++++ docshell/base/nsDocShell.h +@@ -114,8 +114,12 @@ class nsRefreshTimer : public nsITimerCallback + , public nsINamed + { + public: +- nsRefreshTimer(nsDocShell* aDocShell, nsIURI* aURI, int32_t aDelay, +- bool aRepeat, bool aMetaRefresh); ++ nsRefreshTimer(nsDocShell* aDocShell, ++ nsIURI* aURI, ++ nsIPrincipal* aPrincipal, ++ int32_t aDelay, ++ bool aRepeat, ++ bool aMetaRefresh); + + NS_DECL_THREADSAFE_ISUPPORTS + NS_DECL_NSITIMERCALLBACK +@@ -125,6 +129,7 @@ public: + + RefPtr<nsDocShell> mDocShell; + nsCOMPtr<nsIURI> mURI; ++ nsCOMPtr<nsIPrincipal> mPrincipal; + int32_t mDelay; + bool mRepeat; + bool mMetaRefresh; +@@ -259,7 +264,8 @@ public: + // ForceRefreshURI method on nsIRefreshURI, but makes sure to take + // the timer involved out of mRefreshURIList if it's there. + // aTimer must not be null. +- nsresult ForceRefreshURIFromTimer(nsIURI* aURI, int32_t aDelay, ++ nsresult ForceRefreshURIFromTimer(nsIURI* aURI, nsIPrincipal* aPrincipal, ++ int32_t aDelay, + bool aMetaRefresh, nsITimer* aTimer); + + friend class OnLinkClickEvent; +diff --git docshell/base/nsIRefreshURI.idl docshell/base/nsIRefreshURI.idl +index f872d8b7f5cf..3e85e4c516c6 100644 +--- docshell/base/nsIRefreshURI.idl ++++ docshell/base/nsIRefreshURI.idl +@@ -18,23 +18,33 @@ interface nsIRefreshURI : nsISupports { + * queued and executed when the current load finishes. + * + * @param aUri The uri to refresh. ++ * @param aPrincipal The triggeringPrincipal for the refresh load ++ * May be null, in which case a principal will be built based on the ++ * referrer URI of the previous docshell load, or will use the system ++ * principal when there is no referrer. + * @param aMillis The number of milliseconds to wait. + * @param aRepeat Flag to indicate if the uri is to be + * repeatedly refreshed every aMillis milliseconds. + * @param aMetaRefresh Flag to indicate if this is a Meta refresh. + */ +- void refreshURI(in nsIURI aURI, in long aMillis, in boolean aRepeat, ++ void refreshURI(in nsIURI aURI, in nsIPrincipal aPrincipal, ++ in long aMillis, in boolean aRepeat, + in boolean aMetaRefresh); + + /** + * Loads a URI immediately as if it were a refresh. + * + * @param aURI The URI to refresh. ++ * @param aPrincipal The triggeringPrincipal for the refresh load ++ * May be null, in which case a principal will be built based on the ++ * referrer URI of the previous docshell load, or will use the system ++ * principal when there is no referrer. + * @param aMillis The number of milliseconds by which this refresh would + * be delayed if it were not being forced. + * @param aMetaRefresh Flag to indicate if this is a meta refresh. + */ +- void forceRefreshURI(in nsIURI aURI, in long aMillis, in boolean aMetaRefresh); ++ void forceRefreshURI(in nsIURI aURI, in nsIPrincipal aPrincipal, ++ in long aMillis, in boolean aMetaRefresh); + + /** + * Checks the passed in channel to see if there is a refresh header, +@@ -57,10 +67,15 @@ interface nsIRefreshURI : nsISupports { + * the current page finishes loading. + * + * @param aBaseURI base URI to resolve refresh uri with. +- * @param principal the associated principal ++ * @param aPrincipal The triggeringPrincipal for the refresh load ++ * May be null, in which case a principal will be built based on the ++ * referrer URI of the previous docshell load, or will use the system ++ * principal when there is no referrer. + * @param aHeader The meta refresh header string. + */ +- void setupRefreshURIFromHeader(in nsIURI aBaseURI, in nsIPrincipal principal, in ACString aHeader); ++ void setupRefreshURIFromHeader(in nsIURI aBaseURI, ++ in nsIPrincipal principal, ++ in ACString aHeader); + + /** + * Cancels all timer loads. diff --git a/www/waterfox/files/patch-bug1414452 b/www/waterfox/files/patch-bug1414452 new file mode 100644 index 000000000000..695ea3e848a9 --- /dev/null +++ b/www/waterfox/files/patch-bug1414452 @@ -0,0 +1,70 @@ +commit 24a8b8309514 +Author: Olli Pettay <Olli.Pettay@helsinki.fi> +Date: Tue Nov 28 16:17:17 2017 +0200 + + Bug 1414452 - Clear dirAutoSetBy properties iteratively. r=peterv, a=abillings + + --HG-- + extra : source : 157a15cd5ecc8706b502f78c51e79b58ac59eaf0 +--- + dom/base/DirectionalityUtils.cpp | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git dom/base/DirectionalityUtils.cpp dom/base/DirectionalityUtils.cpp +index fb443e23688c..f132c8970fe7 100644 +--- dom/base/DirectionalityUtils.cpp ++++ dom/base/DirectionalityUtils.cpp +@@ -419,7 +419,7 @@ class nsTextNodeDirectionalityMap + + nsTextNodeDirectionalityMap* map = + reinterpret_cast<nsTextNodeDirectionalityMap * >(aPropertyValue); +- map->EnsureMapIsClear(textNode); ++ map->EnsureMapIsClear(); + delete map; + } + +@@ -548,11 +548,11 @@ private: + return OpRemove; + } + +- static nsCheapSetOperator ClearEntry(nsPtrHashKey<Element>* aEntry, void* aData) ++ static nsCheapSetOperator TakeEntries(nsPtrHashKey<Element>* aEntry, void* aData) + { +- Element* rootNode = aEntry->GetKey(); +- rootNode->ClearHasDirAutoSet(); +- rootNode->DeleteProperty(nsGkAtoms::dirAutoSetBy); ++ AutoTArray<Element*, 8>* entries = ++ static_cast<AutoTArray<Element*, 8>*>(aData); ++ entries->AppendElement(aEntry->GetKey()); + return OpRemove; + } + +@@ -568,12 +568,15 @@ public: + mElements.EnumerateEntries(ResetNodeDirection, &data); + } + +- void EnsureMapIsClear(nsINode* aTextNode) ++ void EnsureMapIsClear() + { + AutoRestore<Element*> restore(mElementToBeRemoved); +- DebugOnly<uint32_t> clearedEntries = +- mElements.EnumerateEntries(ClearEntry, aTextNode); +- MOZ_ASSERT(clearedEntries == 0, "Map should be empty already"); ++ AutoTArray<Element*, 8> entries; ++ mElements.EnumerateEntries(TakeEntries, &entries); ++ for (Element* el : entries) { ++ el->ClearHasDirAutoSet(); ++ el->DeleteProperty(nsGkAtoms::dirAutoSetBy); ++ } + } + + static void RemoveElementFromMap(nsTextNode* aTextNode, Element* aElement) +@@ -613,7 +616,7 @@ public: + static void EnsureMapIsClearFor(nsINode* aTextNode) + { + if (aTextNode->HasTextNodeDirectionalityMap()) { +- GetDirectionalityMap(aTextNode)->EnsureMapIsClear(aTextNode); ++ GetDirectionalityMap(aTextNode)->EnsureMapIsClear(); + } + } + }; diff --git a/www/waterfox/files/patch-bug1414945 b/www/waterfox/files/patch-bug1414945 new file mode 100644 index 000000000000..3b57e971dc90 --- /dev/null +++ b/www/waterfox/files/patch-bug1414945 @@ -0,0 +1,43 @@ +commit 26740772e0c9 +Author: Philip Chimento <philip.chimento@gmail.com> +Date: Mon Nov 6 15:49:15 2017 -0800 + + Bug 1414945 - Don't use TimeDuration in static initializer. r=jandem + + On Darwin this would cause a race between two static initializers. + + --HG-- + extra : rebase_source : 0547c4018334f7112022f1893c5f36a47dc14501 +--- + js/src/shell/js.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git js/src/shell/js.cpp js/src/shell/js.cpp +index afb4990ecc0f..f8f81446c7ae 100644 +--- js/src/shell/js.cpp ++++ js/src/shell/js.cpp +@@ -150,7 +150,7 @@ static const size_t gMaxStackSize = 128 * sizeof(size_t) * 1024; + * Limit the timeout to 30 minutes to prevent an overflow on platfoms + * that represent the time internally in microseconds using 32-bit int. + */ +-static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.0); ++static const double MAX_TIMEOUT_SECONDS = 1800.0; + + // SharedArrayBuffer and Atomics are enabled by default (tracking Firefox). + #define SHARED_MEMORY_DEFAULT 1 +@@ -3852,6 +3852,7 @@ Sleep_fn(JSContext* cx, unsigned argc, Value* vp) + } + + duration = TimeDuration::FromSeconds(Max(0.0, t_secs)); ++ const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(MAX_TIMEOUT_SECONDS); + if (duration > MAX_TIMEOUT_INTERVAL) { + JS_ReportErrorASCII(cx, "Excessive sleep interval"); + return false; +@@ -4019,6 +4020,7 @@ SetTimeoutValue(JSContext* cx, double t) + JS_ReportErrorASCII(cx, "timeout is not a number"); + return false; + } ++ const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(MAX_TIMEOUT_SECONDS); + if (TimeDuration::FromSeconds(t) > MAX_TIMEOUT_INTERVAL) { + JS_ReportErrorASCII(cx, "Excessive timeout value"); + return false; diff --git a/www/waterfox/files/patch-bug1415291 b/www/waterfox/files/patch-bug1415291 new file mode 100644 index 000000000000..e4bdf334753c --- /dev/null +++ b/www/waterfox/files/patch-bug1415291 @@ -0,0 +1,52 @@ +commit e5ec8a70ef9e +Author: Luke Wagner <luke@mozilla.com> +Date: Sat Dec 2 12:33:29 2017 -0500 + + Bug 1415291 - Baldr: factor out ToTableIndex(). r=bbouvier, a=gchang +--- + js/src/wasm/WasmJS.cpp | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git js/src/wasm/WasmJS.cpp js/src/wasm/WasmJS.cpp +index 1d07b0d065fe..482de9788221 100644 +--- js/src/wasm/WasmJS.cpp ++++ js/src/wasm/WasmJS.cpp +@@ -1694,6 +1694,20 @@ const JSPropertySpec WasmTableObject::properties[] = + JS_PS_END + }; + ++static bool ++ToTableIndex(JSContext* cx, HandleValue v, const Table& table, const char* noun, uint32_t* index) ++{ ++ if (!ToNonWrappingUint32(cx, v, UINT32_MAX, "Table", noun, index)) ++ return false; ++ ++ if (*index >= table.length()) { ++ JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_WASM_BAD_UINT32, "Table", noun); ++ return false; ++ } ++ ++ return true; ++} ++ + /* static */ bool + WasmTableObject::getImpl(JSContext* cx, const CallArgs& args) + { +@@ -1701,7 +1715,7 @@ WasmTableObject::getImpl(JSContext* cx, const CallArgs& args) + const Table& table = tableObj->table(); + + uint32_t index; +- if (!ToNonWrappingUint32(cx, args.get(0), table.length() - 1, "Table", "get index", &index)) ++ if (!ToTableIndex(cx, args.get(0), table, "get index", &index)) + return false; + + ExternalTableElem& elem = table.externalArray()[index]; +@@ -1740,7 +1754,7 @@ WasmTableObject::setImpl(JSContext* cx, const CallArgs& args) + return false; + + uint32_t index; +- if (!ToNonWrappingUint32(cx, args.get(0), table.length() - 1, "Table", "set index", &index)) ++ if (!ToTableIndex(cx, args.get(0), table, "set index", &index)) + return false; + + RootedFunction value(cx); diff --git a/www/waterfox/files/patch-bug1415441 b/www/waterfox/files/patch-bug1415441 new file mode 100644 index 000000000000..c51fed60cfea --- /dev/null +++ b/www/waterfox/files/patch-bug1415441 @@ -0,0 +1,22 @@ +commit 8b02d6d479da +Author: JW Wang <jwwang@mozilla.com> +Date: Fri Dec 8 10:01:18 2017 +0800 + + Bug 1415441 - Eagerly init gMediaDecoderLog to debug crash. r=cpearce, a=jcristau +--- + dom/media/MediaDecoder.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git dom/media/MediaDecoder.cpp dom/media/MediaDecoder.cpp +index cbf97ddf084d..5de31894d9d9 100644 +--- dom/media/MediaDecoder.cpp ++++ dom/media/MediaDecoder.cpp +@@ -280,6 +280,8 @@ void + MediaDecoder::InitStatics() + { + MOZ_ASSERT(NS_IsMainThread()); ++ // Eagerly init gMediaDecoderLog to work around bug 1415441. ++ MOZ_LOG(gMediaDecoderLog, LogLevel::Info, ("MediaDecoder::InitStatics")); + } + + NS_IMPL_ISUPPORTS(MediaMemoryTracker, nsIMemoryReporter) diff --git a/www/waterfox/files/patch-bug1415582 b/www/waterfox/files/patch-bug1415582 new file mode 100644 index 000000000000..47faa0eb70d1 --- /dev/null +++ b/www/waterfox/files/patch-bug1415582 @@ -0,0 +1,34 @@ +commit 1ab98367b3c1 +Author: Randell Jesup <rjesup@jesup.org> +Date: Wed Nov 8 11:00:24 2017 -0500 + + Bug 1415582 - Mirror changes done to Encoder InitDone to decoder. r=bwc, a=gchang + + --HG-- + extra : source : 833205c1f498bed137fb2e0a06d14ef31e3c0609 +--- + media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h +index b8067a278f18..50189c488df1 100644 +--- media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h ++++ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h +@@ -449,7 +449,7 @@ private: + class InitDoneCallback : public GetGMPVideoDecoderCallback + { + public: +- explicit InitDoneCallback(WebrtcGmpVideoDecoder* aDecoder, ++ explicit InitDoneCallback(const RefPtr<WebrtcGmpVideoDecoder>& aDecoder, + const RefPtr<GmpInitDoneRunnable>& aInitDone) + : mDecoder(aDecoder), + mInitDone(aInitDone) +@@ -465,7 +465,7 @@ private: + } + + private: +- WebrtcGmpVideoDecoder* mDecoder; ++ RefPtr<WebrtcGmpVideoDecoder> mDecoder; + RefPtr<GmpInitDoneRunnable> mInitDone; + }; + diff --git a/www/waterfox/files/patch-bug1415598 b/www/waterfox/files/patch-bug1415598 new file mode 100644 index 000000000000..6fd819610ca9 --- /dev/null +++ b/www/waterfox/files/patch-bug1415598 @@ -0,0 +1,58 @@ +commit 63db080ae5cb +Author: Marco Bonardo <mbonardo@mozilla.com> +Date: Thu Dec 7 15:28:41 2017 +0100 + + Bug 1415598. r=gijs, a=jcristau + + --HG-- + extra : source : 94f1fb1043a81e619d7b73d48a86d66d1cf4eebc +--- + toolkit/components/places/History.cpp | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git toolkit/components/places/History.cpp toolkit/components/places/History.cpp +index 94755d3bdde5..b3618c065601 100644 +--- toolkit/components/places/History.cpp ++++ toolkit/components/places/History.cpp +@@ -1955,6 +1955,7 @@ History::InitMemoryReporter() + NS_IMETHODIMP + History::NotifyVisited(nsIURI* aURI) + { ++ MOZ_ASSERT(NS_IsMainThread()); + NS_ENSURE_ARG(aURI); + + nsAutoScriptBlocker scriptBlocker; +@@ -2565,6 +2566,7 @@ NS_IMETHODIMP + History::RegisterVisitedCallback(nsIURI* aURI, + Link* aLink) + { ++ MOZ_ASSERT(NS_IsMainThread()); + NS_ASSERTION(aURI, "Must pass a non-null URI!"); + if (XRE_IsContentProcess()) { + NS_PRECONDITION(aLink, "Must pass a non-null Link!"); +@@ -2594,7 +2596,16 @@ History::RegisterVisitedCallback(nsIURI* aURI, + if (NS_FAILED(rv) || !aLink) { + // Remove our array from the hashtable so we don't keep it around. + MOZ_ASSERT(key == mObservers.GetEntry(aURI), "The URIs hash mutated!"); +- mObservers.RemoveEntry(key); ++ // In some case calling RemoveEntry on the key obtained by PutEntry ++ // crashes for currently unknown reasons. Our suspect is that something ++ // between PutEntry and this call causes a nested loop that either removes ++ // the entry or reallocs the hash. ++ // TODO (Bug 1412647): we must figure the root cause for these issues and ++ // remove this stop-gap crash fix. ++ key = mObservers.GetEntry(aURI); ++ if (key) { ++ mObservers.RemoveEntry(key); ++ } + return rv; + } + } +@@ -2626,6 +2637,7 @@ NS_IMETHODIMP + History::UnregisterVisitedCallback(nsIURI* aURI, + Link* aLink) + { ++ MOZ_ASSERT(NS_IsMainThread()); + // TODO: aURI is sometimes null - see bug 548685 + NS_ASSERTION(aURI, "Must pass a non-null URI!"); + NS_ASSERTION(aLink, "Must pass a non-null Link object!"); diff --git a/www/waterfox/files/patch-bug1415883 b/www/waterfox/files/patch-bug1415883 new file mode 100644 index 000000000000..3d862aa510cd --- /dev/null +++ b/www/waterfox/files/patch-bug1415883 @@ -0,0 +1,44 @@ +commit a4d70f676839 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Wed Nov 29 16:03:12 2017 +0100 + + Bug 1415883 - Fix some issues in ShiftFromList. r=arai, a=abillings + + --HG-- + extra : source : 2467d71d0e0de20103ce61cdd221461a48e4591b +--- + js/src/vm/List-inl.h | 4 ++-- + js/src/vm/NativeObject.cpp | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git js/src/builtin/Stream.cpp js/src/builtin/Stream.cpp +index e53f811a02e1..28cafd6c06d6 100644 +--- js/src/builtin/Stream.cpp ++++ js/src/builtin/Stream.cpp +@@ -357,11 +357,11 @@ ShiftFromList(JSContext* cx, HandleNativeObject list) + Rooted<T*> entry(cx, &list->getDenseElement(0).toObject().as<T>()); + if (!list->tryShiftDenseElements(1)) { + list->moveDenseElements(0, 1, length - 1); ++ list->setDenseInitializedLength(length - 1); + list->shrinkElements(cx, length - 1); + } + +- list->setDenseInitializedLength(length - 1); +- ++ MOZ_ASSERT(list->getDenseInitializedLength() == length - 1); + return entry; + } + +diff --git js/src/vm/NativeObject.cpp js/src/vm/NativeObject.cpp +index 780bc74192dc..deab37154af2 100644 +--- js/src/vm/NativeObject.cpp ++++ js/src/vm/NativeObject.cpp +@@ -1000,6 +1000,8 @@ void + NativeObject::shrinkElements(JSContext* cx, uint32_t reqCapacity) + { + MOZ_ASSERT(canHaveNonEmptyElements()); ++ MOZ_ASSERT(reqCapacity >= getDenseInitializedLength()); ++ + if (denseElementsAreCopyOnWrite()) + MOZ_CRASH(); + diff --git a/www/waterfox/files/patch-bug1415946 b/www/waterfox/files/patch-bug1415946 new file mode 100644 index 000000000000..9bc3ea846532 --- /dev/null +++ b/www/waterfox/files/patch-bug1415946 @@ -0,0 +1,33 @@ +commit 9a1395f61292 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Fri Nov 10 17:33:00 2017 -0500 + + Bug 1415946 - Make font-variant-alternates: historical-forms parsing ascii case insensitive. r=jfkthame, a=sledru + + MozReview-Commit-ID: 42bKZEgysdW +--- + servo/components/style/properties/longhand/font.mako.rs | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git servo/components/style/properties/longhand/font.mako.rs servo/components/style/properties/longhand/font.mako.rs +index b880cd335321..91d2c254d219 100644 +--- servo/components/style/properties/longhand/font.mako.rs ++++ servo/components/style/properties/longhand/font.mako.rs +@@ -1450,6 +1450,8 @@ ${helpers.single_keyword_system("font-kerning", + /// annotation(<feature-value-name>) ] + pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) + -> Result<SpecifiedValue, ParseError<'i>> { ++ #[allow(unused_imports)] use std::ascii::AsciiExt; ++ + let mut alternates = Vec::new(); + if input.try(|input| input.expect_ident_matching("normal")).is_ok() { + return Ok(SpecifiedValue::Value(VariantAlternatesList(alternates.into_boxed_slice()))); +@@ -1468,7 +1470,7 @@ ${helpers.single_keyword_system("font-kerning", + // FIXME: remove clone() when lifetimes are non-lexical + match input.next()?.clone() { + Token::Ident(ref ident) => { +- if *ident == "historical-forms" { ++ if ident.eq_ignore_ascii_case("historical-forms") { + check_if_parsed!(HISTORICAL_FORMS); + alternates.push(VariantAlternates::HistoricalForms); + Ok(()) diff --git a/www/waterfox/files/patch-bug1416307 b/www/waterfox/files/patch-bug1416307 new file mode 100644 index 000000000000..7d77ad317937 --- /dev/null +++ b/www/waterfox/files/patch-bug1416307 @@ -0,0 +1,94 @@ +commit 1159955c684f +Author: Samael Wang <freesamael@gmail.com> +Date: Tue Feb 6 13:28:30 2018 -0500 + + Bug 1416307 - Set triggeringPrincipal to current document's principal, if aPrincipal is not given. r=bz a=ritu + + MozReview-Commit-ID: 8lxKFeUlyzq + + --HG-- + extra : source : 9fcf48189000ab8ee16f236be57c9659c7243b42 +--- + docshell/base/nsDocShell.cpp | 21 +++++++++++---------- + docshell/base/nsIRefreshURI.idl | 15 ++++++--------- + 2 files changed, 17 insertions(+), 19 deletions(-) + +diff --git docshell/base/nsDocShell.cpp docshell/base/nsDocShell.cpp +index fa3707880772..84a9086a1a00 100644 +--- docshell/base/nsDocShell.cpp ++++ docshell/base/nsDocShell.cpp +@@ -6396,9 +6396,17 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel + */ + loadInfo->SetReferrer(mCurrentURI); + +- /* Don't ever "guess" on which principal to use to avoid picking +- * the current principal. +- */ ++ // Set the triggering pricipal to aPrincipal if available, or current ++ // document's principal otherwise. ++ nsCOMPtr<nsIPrincipal> principal = aPrincipal; ++ if (!principal) { ++ nsCOMPtr<nsIDocument> doc = GetDocument(); ++ if (!doc) { ++ return NS_ERROR_FAILURE; ++ } ++ principal = doc->NodePrincipal(); ++ } ++ loadInfo->SetTriggeringPrincipal(principal); + loadInfo->SetPrincipalIsExplicit(true); + + /* Check if this META refresh causes a redirection +@@ -6426,13 +6434,6 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel + loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh); + } + +- // If the principal is null, the refresh will have a triggeringPrincipal +- // derived from the referrer URI, or will be set to the system principal +- // if there is no refererrer. See LoadURI() +- if (aPrincipal) { +- loadInfo->SetTriggeringPrincipal(aPrincipal); +- } +- + /* + * LoadURI(...) will cancel all refresh timers... This causes the + * Timer and its refreshData instance to be released... +diff --git docshell/base/nsIRefreshURI.idl docshell/base/nsIRefreshURI.idl +index 3e85e4c516c6..77d8fd660674 100644 +--- docshell/base/nsIRefreshURI.idl ++++ docshell/base/nsIRefreshURI.idl +@@ -19,9 +19,8 @@ interface nsIRefreshURI : nsISupports { + * + * @param aUri The uri to refresh. + * @param aPrincipal The triggeringPrincipal for the refresh load +- * May be null, in which case a principal will be built based on the +- * referrer URI of the previous docshell load, or will use the system +- * principal when there is no referrer. ++ * May be null, in which case the principal of current document will be ++ * applied. + * @param aMillis The number of milliseconds to wait. + * @param aRepeat Flag to indicate if the uri is to be + * repeatedly refreshed every aMillis milliseconds. +@@ -36,9 +35,8 @@ interface nsIRefreshURI : nsISupports { + * + * @param aURI The URI to refresh. + * @param aPrincipal The triggeringPrincipal for the refresh load +- * May be null, in which case a principal will be built based on the +- * referrer URI of the previous docshell load, or will use the system +- * principal when there is no referrer. ++ * May be null, in which case the principal of current document will be ++ * applied. + * @param aMillis The number of milliseconds by which this refresh would + * be delayed if it were not being forced. + * @param aMetaRefresh Flag to indicate if this is a meta refresh. +@@ -68,9 +66,8 @@ interface nsIRefreshURI : nsISupports { + * + * @param aBaseURI base URI to resolve refresh uri with. + * @param aPrincipal The triggeringPrincipal for the refresh load +- * May be null, in which case a principal will be built based on the +- * referrer URI of the previous docshell load, or will use the system +- * principal when there is no referrer. ++ * May be null, in which case the principal of current document will be ++ * applied. + * @param aHeader The meta refresh header string. + */ + void setupRefreshURIFromHeader(in nsIURI aBaseURI, diff --git a/www/waterfox/files/patch-bug1416529 b/www/waterfox/files/patch-bug1416529 new file mode 100644 index 000000000000..a88f4e28941e --- /dev/null +++ b/www/waterfox/files/patch-bug1416529 @@ -0,0 +1,101 @@ +commit 4cfa1b84d80c +Author: Nicholas Hurley <hurley@mozilla.com> +Date: Fri Feb 2 11:03:08 2018 -0800 + + Bug 1416529 r=mcmanus a=ritu + MozReview-Commit-ID: CD1l5vLB4yy + + --HG-- + extra : amend_source : 44c6368af20b158091a90c627ea4f206871dfa9d +--- + netwerk/protocol/http/Http2Session.cpp | 18 +++++++++--------- + netwerk/protocol/http/Http2Stream.cpp | 14 ++++++++++++++ + netwerk/protocol/http/Http2Stream.h | 1 + + 3 files changed, 24 insertions(+), 9 deletions(-) + +diff --git netwerk/protocol/http/Http2Session.cpp netwerk/protocol/http/Http2Session.cpp +index 9fd021065742..622c1657027a 100644 +--- netwerk/protocol/http/Http2Session.cpp ++++ netwerk/protocol/http/Http2Session.cpp +@@ -1136,6 +1136,15 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult, + return; + } + ++ Http2PushedStream *pushSource = aStream->PushSource(); ++ if (pushSource) { ++ // aStream is a synthetic attached to an even push ++ MOZ_ASSERT(pushSource->GetConsumerStream() == aStream); ++ MOZ_ASSERT(!aStream->StreamID()); ++ MOZ_ASSERT(!(pushSource->StreamID() & 0x1)); ++ aStream->ClearPushSource(); ++ } ++ + if (aStream->DeferCleanup(aResult)) { + LOG3(("Http2Session::CleanupStream 0x%X deferred\n", aStream->StreamID())); + return; +@@ -1146,15 +1155,6 @@ Http2Session::CleanupStream(Http2Stream *aStream, nsresult aResult, + return; + } + +- Http2PushedStream *pushSource = aStream->PushSource(); +- if (pushSource) { +- // aStream is a synthetic attached to an even push +- MOZ_ASSERT(pushSource->GetConsumerStream() == aStream); +- MOZ_ASSERT(!aStream->StreamID()); +- MOZ_ASSERT(!(pushSource->StreamID() & 0x1)); +- pushSource->SetConsumerStream(nullptr); +- } +- + // don't reset a stream that has recevied a fin or rst + if (!aStream->RecvdFin() && !aStream->RecvdReset() && aStream->StreamID() && + !(mInputFrameFinal && (aStream == mInputFrameDataStream))) { // !(recvdfin with mark pending) +diff --git netwerk/protocol/http/Http2Stream.cpp netwerk/protocol/http/Http2Stream.cpp +index d2f304b5ed7b..95674d018ab1 100644 +--- netwerk/protocol/http/Http2Stream.cpp ++++ netwerk/protocol/http/Http2Stream.cpp +@@ -112,12 +112,22 @@ Http2Stream::Http2Stream(nsAHttpTransaction *httpTransaction, + + Http2Stream::~Http2Stream() + { ++ ClearPushSource(); + ClearTransactionsBlockedOnTunnel(); + mStreamID = Http2Session::kDeadStreamID; + + LOG3(("Http2Stream::~Http2Stream %p", this)); + } + ++void ++Http2Stream::ClearPushSource() ++{ ++ if (mPushSource) { ++ mPushSource->SetConsumerStream(nullptr); ++ mPushSource = nullptr; ++ } ++} ++ + // ReadSegments() is used to write data down the socket. Generally, HTTP + // request data is pulled from the approriate transaction and + // converted to HTTP/2 data. Sometimes control data like a window-update is +@@ -1135,6 +1145,10 @@ Http2Stream::ConvertPushHeaders(Http2Decompressor *decompressor, + void + Http2Stream::Close(nsresult reason) + { ++ // In case we are connected to a push, make sure the push knows we are closed, ++ // so it doesn't try to give us any more DATA that comes on it after our close. ++ ClearPushSource(); ++ + mTransaction->Close(reason); + } + +diff --git netwerk/protocol/http/Http2Stream.h netwerk/protocol/http/Http2Stream.h +index 3412eb56f809..29f98163c4ac 100644 +--- netwerk/protocol/http/Http2Stream.h ++++ netwerk/protocol/http/Http2Stream.h +@@ -56,6 +56,7 @@ public: + + uint32_t StreamID() { return mStreamID; } + Http2PushedStream *PushSource() { return mPushSource; } ++ void ClearPushSource(); + + stateType HTTPState() { return mState; } + void SetHTTPState(stateType val) { mState = val; } diff --git a/www/waterfox/files/patch-bug1417661 b/www/waterfox/files/patch-bug1417661 new file mode 100644 index 000000000000..a9ac6a9835cb --- /dev/null +++ b/www/waterfox/files/patch-bug1417661 @@ -0,0 +1,37 @@ +commit ad9b162b2a97 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Tue Nov 28 19:27:49 2017 +0100 + + Bug 1417661 - Use the correct parent style for inheriting from first-letter if the container is an anonymous box. r=bz, a=gchang + + MozReview-Commit-ID: 1B7DrAVa274 + + --HG-- + extra : source : 2be23298d4872b9d1677b6014683f554d857966f +--- + layout/base/nsCSSFrameConstructor.cpp | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp +index f9994b31e649..0da45cc33544 100644 +--- layout/base/nsCSSFrameConstructor.cpp ++++ layout/base/nsCSSFrameConstructor.cpp +@@ -11666,13 +11666,15 @@ nsCSSFrameConstructor::CreateLetterFrame(nsContainerFrame* aBlockFrame, + + if (sc) { + if (sc->IsServo() && parentFrame->IsLineFrame()) { +- ServoStyleContext* parentStyleIgnoringFirstLine = +- aBlockFrame->StyleContext()->AsServo(); ++ nsIFrame* parentIgnoringFirstLine = ++ nsFrame::CorrectStyleParentFrame(aBlockFrame, ++ nsCSSPseudoElements::firstLetter); ++ + sc = + mPresShell->StyleSet()->AsServo()->ReparentStyleContext( + sc->AsServo(), + parentStyleContext->AsServo(), +- parentStyleIgnoringFirstLine, ++ parentIgnoringFirstLine->StyleContext()->AsServo(), + parentStyleContext->AsServo(), + blockContent->AsElement()); + } diff --git a/www/waterfox/files/patch-bug1417751 b/www/waterfox/files/patch-bug1417751 new file mode 100644 index 000000000000..aea1eddf0f5b --- /dev/null +++ b/www/waterfox/files/patch-bug1417751 @@ -0,0 +1,379 @@ +commit e889dbe68557 +Author: lochang <lochang@mozilla.com> +Date: Wed Nov 29 10:43:13 2017 +0800 + + Bug 1417751 - Implement a new value inner-spin-button to -moz-appearance on all platforms except Android. r=mats + + MozReview-Commit-ID: 7jpLCOWZA2x + + --HG-- + extra : rebase_source : d2a4d160d26e6f6996ed1cb3a673576236b8ef23 +--- + devtools/shared/css/generated/properties-db.js | 2 ++ + gfx/src/nsThemeConstants.h | 3 ++ + layout/style/nsCSSKeywordList.h | 1 + + layout/style/nsCSSProps.cpp | 1 + + widget/cocoa/nsNativeThemeCocoa.mm | 9 +++-- + widget/gtk/gtk2drawing.c | 49 ++++++++++++++++++++++++++ + widget/gtk/gtk3drawing.cpp | 38 ++++++++++++++++++++ + widget/gtk/gtkdrawing.h | 1 + + widget/gtk/nsNativeThemeGTK.cpp | 5 +++ + widget/headless/HeadlessThemeGTK.cpp | 2 ++ + widget/windows/nsNativeThemeWin.cpp | 9 +++++ + 11 files changed, 118 insertions(+), 2 deletions(-) + +diff --git devtools/shared/css/generated/properties-db.js devtools/shared/css/generated/properties-db.js +index 6d12ca38f14d..b87366998a16 100644 +--- devtools/shared/css/generated/properties-db.js ++++ devtools/shared/css/generated/properties-db.js +@@ -236,6 +236,7 @@ exports.CSS_PROPERTIES = { + "groupbox", + "inherit", + "initial", ++ "inner-spin-button", + "listbox", + "listitem", + "menuarrow", +@@ -3458,6 +3459,7 @@ exports.CSS_PROPERTIES = { + "inline-grid", + "inline-start", + "inline-table", ++ "inner-spin-button", + "inset", + "inside", + "inter-character", +diff --git gfx/src/nsThemeConstants.h gfx/src/nsThemeConstants.h +index 439ada6e80a6..0688222ef7ea 100644 +--- gfx/src/nsThemeConstants.h ++++ gfx/src/nsThemeConstants.h +@@ -135,6 +135,9 @@ enum ThemeWidgetType : uint8_t { + // A tooltip + NS_THEME_TOOLTIP, + ++ // A inner-spin control ++ NS_THEME_INNER_SPIN_BUTTON, ++ + // A spin control (up/down control for time/date pickers) + NS_THEME_SPINNER, + +diff --git layout/style/nsCSSKeywordList.h layout/style/nsCSSKeywordList.h +index f184592ad7c6..ff448c87b761 100644 +--- layout/style/nsCSSKeywordList.h ++++ layout/style/nsCSSKeywordList.h +@@ -683,6 +683,7 @@ CSS_KEY(tabpanel, tabpanel) + CSS_KEY(tab-scroll-arrow-back, tab_scroll_arrow_back) + CSS_KEY(tab-scroll-arrow-forward, tab_scroll_arrow_forward) + CSS_KEY(tooltip, tooltip) ++CSS_KEY(inner-spin-button, inner_spin_button) + CSS_KEY(spinner, spinner) + CSS_KEY(spinner-upbutton, spinner_upbutton) + CSS_KEY(spinner-downbutton, spinner_downbutton) +diff --git layout/style/nsCSSProps.cpp layout/style/nsCSSProps.cpp +index b7815699afa6..5c1ab8e8aae3 100644 +--- layout/style/nsCSSProps.cpp ++++ layout/style/nsCSSProps.cpp +@@ -786,6 +786,7 @@ const KTableEntry nsCSSProps::kAppearanceKTable[] = { + { eCSSKeyword_tab_scroll_arrow_back, NS_THEME_TAB_SCROLL_ARROW_BACK }, + { eCSSKeyword_tab_scroll_arrow_forward, NS_THEME_TAB_SCROLL_ARROW_FORWARD }, + { eCSSKeyword_tooltip, NS_THEME_TOOLTIP }, ++ { eCSSKeyword_inner_spin_button, NS_THEME_INNER_SPIN_BUTTON }, + { eCSSKeyword_spinner, NS_THEME_SPINNER }, + { eCSSKeyword_spinner_upbutton, NS_THEME_SPINNER_UPBUTTON }, + { eCSSKeyword_spinner_downbutton, NS_THEME_SPINNER_DOWNBUTTON }, +diff --git widget/cocoa/nsNativeThemeCocoa.mm widget/cocoa/nsNativeThemeCocoa.mm +index 760279b3a972..a4066b030897 100644 +--- widget/cocoa/nsNativeThemeCocoa.mm ++++ widget/cocoa/nsNativeThemeCocoa.mm +@@ -2551,9 +2551,11 @@ nsNativeThemeCocoa::DrawWidgetBackground(gfxContext* aContext, + eventState, aFrame); + break; + +- case NS_THEME_SPINNER: { ++ case NS_THEME_INNER_SPIN_BUTTON: { ++ case NS_THEME_SPINNER: ++ bool isSpinner = (aWidgetType == NS_THEME_SPINNER); + nsIContent* content = aFrame->GetContent(); +- if (content->IsHTMLElement()) { ++ if (isSpinner && content->IsHTMLElement()) { + // In HTML the theming for the spin buttons is drawn individually into + // their own backgrounds instead of being drawn into the background of + // their spinner parent as it is for XUL. +@@ -3454,6 +3456,7 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsPresContext* aPresContext, + break; + } + ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: +@@ -3838,6 +3841,7 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a + case NS_THEME_BUTTON_ARROW_DOWN: + case NS_THEME_BUTTON_BEVEL: + case NS_THEME_TOOLBARBUTTON: ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: +@@ -3978,6 +3982,7 @@ nsNativeThemeCocoa::WidgetAppearanceDependsOnWindowFocus(uint8_t aWidgetType) + case NS_THEME_MENUITEM: + case NS_THEME_MENUSEPARATOR: + case NS_THEME_TOOLTIP: ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: +diff --git widget/gtk/gtk2drawing.c widget/gtk/gtk2drawing.c +index 9b523c8f893e..e7f9d32a4d1c 100644 +--- widget/gtk/gtk2drawing.c ++++ widget/gtk/gtk2drawing.c +@@ -1365,6 +1365,51 @@ moz_gtk_scrollbar_thumb_paint(WidgetNodeType widget, + return MOZ_GTK_SUCCESS; + } + ++static gint ++moz_gtk_inner_spin_paint(GdkDrawable* drawable, GdkRectangle* rect, ++ GtkWidgetState* state, ++ GtkTextDirection direction) ++{ ++ GdkRectangle arrow_rect; ++ GtkStateType state_type = ConvertGtkState(state); ++ GtkShadowType shadow_type = state_type == GTK_STATE_ACTIVE ? ++ GTK_SHADOW_IN : GTK_SHADOW_OUT; ++ GtkStyle* style; ++ ++ ensure_spin_widget(); ++ style = gSpinWidget->style; ++ gtk_widget_set_direction(gSpinWidget, direction); ++ ++ TSOffsetStyleGCs(style, rect->x, rect->y); ++ gtk_paint_box(style, drawable, state_type, shadow_type, NULL, gSpinWidget, ++ "spinbutton", rect->x, rect->y, rect->width, rect->height); ++ ++ /* hard code these values */ ++ arrow_rect.width = 6; ++ arrow_rect.height = 6; ++ ++ // align spin to the left ++ arrow_rect.x = rect->x; ++ ++ // up button ++ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2 - 3; ++ gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL, ++ gSpinWidget, "spinbutton", ++ GTK_ARROW_UP, TRUE, ++ arrow_rect.x, arrow_rect.y, ++ arrow_rect.width, arrow_rect.height); ++ ++ // down button ++ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2 + 3; ++ gtk_paint_arrow(style, drawable, state_type, shadow_type, NULL, ++ gSpinWidget, "spinbutton", ++ GTK_ARROW_DOWN, ++ arrow_rect.x, arrow_rect.y, ++ arrow_rect.width, arrow_rect.height); ++ ++ return MOZ_GTK_SUCCESS; ++} ++ + static gint + moz_gtk_spin_paint(GdkDrawable* drawable, GdkRectangle* rect, + GtkTextDirection direction) +@@ -2984,6 +3029,7 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + case MOZ_GTK_TOOLBAR_SEPARATOR: + case MOZ_GTK_MENUSEPARATOR: + /* These widgets have no borders.*/ ++ case MOZ_GTK_INNER_SPIN_BUTTON: + case MOZ_GTK_SPINBUTTON: + case MOZ_GTK_WINDOW: + case MOZ_GTK_RESIZER: +@@ -3247,6 +3293,9 @@ moz_gtk_widget_paint(WidgetNodeType widget, GdkDrawable* drawable, + return moz_gtk_scale_thumb_paint(drawable, rect, cliprect, state, + (GtkOrientation) flags, direction); + break; ++ case MOZ_GTK_INNER_SPIN_BUTTON: ++ return moz_gtk_inner_spin_paint(drawable, rect, state, direction); ++ break; + case MOZ_GTK_SPINBUTTON: + return moz_gtk_spin_paint(drawable, rect, direction); + break; +diff --git widget/gtk/gtk3drawing.cpp widget/gtk/gtk3drawing.cpp +index 2969be818e96..a3a1478bfe85 100644 +--- widget/gtk/gtk3drawing.cpp ++++ widget/gtk/gtk3drawing.cpp +@@ -797,6 +797,40 @@ moz_gtk_scrollbar_thumb_paint(WidgetNodeType widget, + return MOZ_GTK_SUCCESS; + } + ++static gint ++moz_gtk_inner_spin_paint(cairo_t *cr, GdkRectangle* rect, ++ GtkWidgetState* state, ++ GtkTextDirection direction) ++{ ++ GtkStyleContext* style = GetStyleContext(MOZ_GTK_SPINBUTTON, direction, ++ GetStateFlagsFromGtkWidgetState(state)); ++ ++ gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height); ++ gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height); ++ ++ /* hard code these values */ ++ GdkRectangle arrow_rect; ++ arrow_rect.width = 6; ++ arrow_rect.height = 6; ++ ++ // align spin to the left ++ arrow_rect.x = rect->x; ++ ++ // up button ++ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2 - 3; ++ gtk_render_arrow(style, cr, ARROW_UP, ++ arrow_rect.x, arrow_rect.y, ++ arrow_rect.width); ++ ++ // down button ++ arrow_rect.y = rect->y + (rect->height - arrow_rect.height) / 2 + 3; ++ gtk_render_arrow(style, cr, ARROW_DOWN, ++ arrow_rect.x, arrow_rect.y, ++ arrow_rect.width); ++ ++ return MOZ_GTK_SUCCESS; ++} ++ + static gint + moz_gtk_spin_paint(cairo_t *cr, GdkRectangle* rect, + GtkTextDirection direction) +@@ -2283,6 +2317,7 @@ moz_gtk_get_widget_border(WidgetNodeType widget, gint* left, gint* top, + case MOZ_GTK_TOOLBAR_SEPARATOR: + case MOZ_GTK_MENUSEPARATOR: + /* These widgets have no borders.*/ ++ case MOZ_GTK_INNER_SPIN_BUTTON: + case MOZ_GTK_SPINBUTTON: + case MOZ_GTK_WINDOW: + case MOZ_GTK_RESIZER: +@@ -2845,6 +2880,9 @@ moz_gtk_widget_paint(WidgetNodeType widget, cairo_t *cr, + return moz_gtk_scale_thumb_paint(cr, rect, state, + (GtkOrientation) flags, direction); + break; ++ case MOZ_GTK_INNER_SPIN_BUTTON: ++ return moz_gtk_inner_spin_paint(cr, rect, state, direction); ++ break; + case MOZ_GTK_SPINBUTTON: + return moz_gtk_spin_paint(cr, rect, direction); + break; +diff --git widget/gtk/gtkdrawing.h widget/gtk/gtkdrawing.h +index 59fd1256e22d..4e796d0237d9 100644 +--- widget/gtk/gtkdrawing.h ++++ widget/gtk/gtkdrawing.h +@@ -175,6 +175,7 @@ typedef enum { + MOZ_GTK_SCALE_THUMB_HORIZONTAL, + MOZ_GTK_SCALE_THUMB_VERTICAL, + /* Paints a GtkSpinButton */ ++ MOZ_GTK_INNER_SPIN_BUTTON, + MOZ_GTK_SPINBUTTON, + MOZ_GTK_SPINBUTTON_UP, + MOZ_GTK_SPINBUTTON_DOWN, +diff --git widget/gtk/nsNativeThemeGTK.cpp widget/gtk/nsNativeThemeGTK.cpp +index c38c9e1eed3d..953aead6cdd4 100644 +--- widget/gtk/nsNativeThemeGTK.cpp ++++ widget/gtk/nsNativeThemeGTK.cpp +@@ -439,6 +439,9 @@ nsNativeThemeGTK::GetGtkWidgetAndState(uint8_t aWidgetType, nsIFrame* aFrame, + case NS_THEME_SCROLLBARTHUMB_HORIZONTAL: + aGtkWidgetType = MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; + break; ++ case NS_THEME_INNER_SPIN_BUTTON: ++ aGtkWidgetType = MOZ_GTK_INNER_SPIN_BUTTON; ++ break; + case NS_THEME_SPINNER: + aGtkWidgetType = MOZ_GTK_SPINBUTTON; + break; +@@ -1657,6 +1660,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, + aResult->width = separator_width; + } + break; ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER: + // hard code these sizes + aResult->width = 14; +@@ -1844,6 +1848,7 @@ nsNativeThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext, + case NS_THEME_TAB_SCROLL_ARROW_BACK: + case NS_THEME_TAB_SCROLL_ARROW_FORWARD: + case NS_THEME_TOOLTIP: ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: +diff --git widget/windows/nsNativeThemeWin.cpp widget/windows/nsNativeThemeWin.cpp +index 5bbdc3aacc1e..bd6f76ca3e52 100644 +--- widget/windows/nsNativeThemeWin.cpp ++++ widget/windows/nsNativeThemeWin.cpp +@@ -682,6 +682,7 @@ nsresult nsNativeThemeWin::GetCachedMinimumWidgetSize(nsIFrame * aFrame, HANDLE + aResult->height = sz.cy; + + switch (aWidgetType) { ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + aResult->width++; +@@ -766,6 +767,7 @@ mozilla::Maybe<nsUXThemeClass> nsNativeThemeWin::GetThemeClass(uint8_t aWidgetTy + case NS_THEME_SCALETHUMB_HORIZONTAL: + case NS_THEME_SCALETHUMB_VERTICAL: + return Some(eUXTrackbar); ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + return Some(eUXSpin); +@@ -1143,6 +1145,7 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType, + } + return NS_OK; + } ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: { + aPart = (aWidgetType == NS_THEME_SPINNER_UPBUTTON) ? +@@ -2718,6 +2721,7 @@ nsNativeThemeWin::ClassicThemeSupportsWidget(nsIFrame* aFrame, + case NS_THEME_SCALETHUMB_HORIZONTAL: + case NS_THEME_SCALETHUMB_VERTICAL: + case NS_THEME_MENULIST_BUTTON: ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + case NS_THEME_LISTBOX: +@@ -2873,6 +2877,7 @@ nsNativeThemeWin::ClassicGetMinimumWidgetSize(nsIFrame* aFrame, + (*aResult).width = ::GetSystemMetrics(SM_CXMENUCHECK); + (*aResult).height = ::GetSystemMetrics(SM_CYMENUCHECK); + break; ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + (*aResult).width = ::GetSystemMetrics(SM_CXVSCROLL); +@@ -3274,6 +3279,7 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, uint8_t + + return NS_OK; + } ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: { + EventStates contentState = GetContentState(aFrame, aWidgetType); +@@ -3283,6 +3289,7 @@ nsresult nsNativeThemeWin::ClassicGetThemePartAndState(nsIFrame* aFrame, uint8_t + case NS_THEME_SPINNER_UPBUTTON: + aState = DFCS_SCROLLUP; + break; ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + aState = DFCS_SCROLLDOWN; + break; +@@ -3583,6 +3590,7 @@ RENDER_AGAIN: + case NS_THEME_SCROLLBARBUTTON_DOWN: + case NS_THEME_SCROLLBARBUTTON_LEFT: + case NS_THEME_SCROLLBARBUTTON_RIGHT: ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + case NS_THEME_MENULIST_BUTTON: +@@ -3987,6 +3995,7 @@ nsNativeThemeWin::GetWidgetNativeDrawingFlags(uint8_t aWidgetType) + case NS_THEME_SCALE_VERTICAL: + case NS_THEME_SCALETHUMB_HORIZONTAL: + case NS_THEME_SCALETHUMB_VERTICAL: ++ case NS_THEME_INNER_SPIN_BUTTON: + case NS_THEME_SPINNER_UPBUTTON: + case NS_THEME_SPINNER_DOWNBUTTON: + case NS_THEME_LISTBOX: diff --git a/www/waterfox/files/patch-bug1417797 b/www/waterfox/files/patch-bug1417797 new file mode 100644 index 000000000000..e3e1fc5d44a3 --- /dev/null +++ b/www/waterfox/files/patch-bug1417797 @@ -0,0 +1,25 @@ +commit 95077ef89979 +Author: Dan Minor <dminor@mozilla.com> +Date: Mon Nov 20 07:09:19 2017 -0500 + + Bug 1417797 - Stop callback in WebrtcGmpVideoDecoder::ReleaseGmp. r=jesup, a=gchang + + --HG-- + extra : source : d0eb2fe1a7389d40d1abdccbeeaef9c4b30ae7b1 +--- + media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp +index 53212d888dcb..e3063ea3fefb 100644 +--- media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp ++++ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp +@@ -923,6 +923,8 @@ int32_t + WebrtcGmpVideoDecoder::ReleaseGmp() + { + LOGD(("GMP Released:")); ++ RegisterDecodeCompleteCallback(nullptr); ++ + if (mGMPThread) { + mGMPThread->Dispatch( + WrapRunnableNM(&WebrtcGmpVideoDecoder::ReleaseGmp_g, diff --git a/www/waterfox/files/patch-bug1417869 b/www/waterfox/files/patch-bug1417869 new file mode 100644 index 000000000000..cc344f72dbc3 --- /dev/null +++ b/www/waterfox/files/patch-bug1417869 @@ -0,0 +1,42 @@ +commit 22760bd00a04 +Author: JW Wang <jwwang@mozilla.com> +Date: Fri Nov 24 11:14:51 2017 +0100 + + Bug 1417869. P2 - abort the load algorithm early if media not allowed to load. r=jya, a=sledru + + MozReview-Commit-ID: DUxyo4ywCPW +--- + dom/html/HTMLMediaElement.cpp | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp +index 5d51851047cf..c2106402c661 100644 +--- dom/html/HTMLMediaElement.cpp ++++ dom/html/HTMLMediaElement.cpp +@@ -1956,6 +1956,13 @@ NS_IMETHODIMP HTMLMediaElement::Load() + + void HTMLMediaElement::DoLoad() + { ++ // Check if media is allowed for the docshell. ++ nsCOMPtr<nsIDocShell> docShell = OwnerDoc()->GetDocShell(); ++ if (docShell && !docShell->GetAllowMedia()) { ++ LOG(LogLevel::Debug, ("%p Media not allowed", this)); ++ return; ++ } ++ + if (mIsRunningLoadMethod) { + return; + } +@@ -2497,12 +2504,6 @@ nsresult HTMLMediaElement::LoadResource() + mChannelLoader = nullptr; + } + +- // Check if media is allowed for the docshell. +- nsCOMPtr<nsIDocShell> docShell = OwnerDoc()->GetDocShell(); +- if (docShell && !docShell->GetAllowMedia()) { +- return NS_ERROR_FAILURE; +- } +- + // Set the media element's CORS mode only when loading a resource + mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin)); + diff --git a/www/waterfox/files/patch-bug1418009 b/www/waterfox/files/patch-bug1418009 new file mode 100644 index 000000000000..2a9f5a7fd4fa --- /dev/null +++ b/www/waterfox/files/patch-bug1418009 @@ -0,0 +1,28 @@ +commit 068a8c4feb56 +Author: Oriol Brufau <oriol-bugzilla@hotmail.com> +Date: Fri Mar 16 16:58:36 2018 +0100 + + Bug 1418009 - Avoid speculative connections on prematurely inserted lazy tabs. r=dao, a=RyanVM + + MozReview-Commit-ID: 3T8PLBLEGNt + + --HG-- + extra : rebase_source : 5839f1ede2a3d939e8bad02520979a8911f69553 + extra : source : 6d67283033868a54d89a936ba5e336d9bad5c79c +--- + browser/components/sessionstore/SessionStore.jsm | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git browser/components/sessionstore/SessionStore.jsm browser/components/sessionstore/SessionStore.jsm +index dee998cbe7eb..88de8a64f0fc 100644 +--- browser/components/sessionstore/SessionStore.jsm ++++ browser/components/sessionstore/SessionStore.jsm +@@ -3547,7 +3547,7 @@ var SessionStoreInternal = { + * a tab to speculatively connect on mouse hover. + */ + speculativeConnectOnTabHover(tab) { +- if (this._restore_on_demand && !tab.__SS_connectionPrepared && tab.hasAttribute("pending")) { ++ if (tab.__SS_lazyData && !tab.__SS_connectionPrepared) { + let url = this.getLazyTabValue(tab, "url"); + let prepared = this.prepareConnectionToHost(url); + // This is used to test if a connection has been made beforehand. diff --git a/www/waterfox/files/patch-bug1418152 b/www/waterfox/files/patch-bug1418152 new file mode 100644 index 000000000000..d7634229aa8e --- /dev/null +++ b/www/waterfox/files/patch-bug1418152 @@ -0,0 +1,36 @@ +commit d7441ef15616 +Author: Cameron McCormack <cam@mcc.id.au> +Date: Sat Nov 18 00:47:57 2017 -0600 + + Bug 1418152 - servo: Merge #19263 - selectors: Allow white space in the brackets of an attribute selector (from heycam:attr-ws); r=SimonSapin a=sylvestre + + Source-Repo: https://github.com/servo/servo + Source-Revision: 7b886b4479763018ecad62aa6db96049732ca9ed + + --HG-- + extra : amend_source : 67e691f8caf4bc07a9ea0e33bd31286ae123f5ff + extra : transplant_source : %C6%FF%3A%13I%5E%B7%14%3C%F2%F7%CE%80%DB%08%16bh%60s +--- + servo/components/selectors/parser.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git servo/components/selectors/parser.rs servo/components/selectors/parser.rs +index b020a04fd032..b7c421998530 100644 +--- servo/components/selectors/parser.rs ++++ servo/components/selectors/parser.rs +@@ -1306,6 +1306,15 @@ fn parse_attribute_selector<'i, 't, P, E, Impl>(parser: &P, input: &mut CssParse + { + let namespace; + let local_name; ++ ++ loop { ++ let position = input.position(); ++ if !matches!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(_))) { ++ input.reset(position); ++ break ++ } ++ } ++ + match parse_qualified_name(parser, input, /* in_attr_selector = */ true)? { + None => return Err(ParseError::Custom(SelectorParseError::NoQualifiedNameInAttributeSelector)), + Some((_, None)) => unreachable!(), diff --git a/www/waterfox/files/patch-bug1418757 b/www/waterfox/files/patch-bug1418757 new file mode 100644 index 000000000000..139fce6ec8c7 --- /dev/null +++ b/www/waterfox/files/patch-bug1418757 @@ -0,0 +1,169 @@ +commit 1b3df31dd202 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Nov 22 13:49:07 2017 +0000 + + Bug 1418757 - new tab button isn't adjacent to the last tab when customizing in customize mode, r=jaws a=gchang + + MozReview-Commit-ID: bQoNfDD2sX + + --HG-- + extra : histedit_source : 15b29e1c8e8ba295ecbd76d266de3611862a72c3 +--- + browser/base/content/tabbrowser.xml | 15 ++- + browser/components/customizableui/test/browser.ini | 1 + + .../test/browser_newtab_button_customizemode.js | 106 +++++++++++++++++++++ + 3 files changed, 121 insertions(+), 1 deletion(-) + +diff --git browser/base/content/tabbrowser.xml browser/base/content/tabbrowser.xml +index dc4560e0f5b2..a13df7715f2d 100644 +--- browser/base/content/tabbrowser.xml ++++ browser/base/content/tabbrowser.xml +@@ -5448,10 +5448,23 @@ + + <method name="_updateNewTabVisibility"> + <body><![CDATA[ ++ let isCustomizing = this.tabContainer.parentNode.getAttribute("customizing") == "true"; ++ ++ // Confusingly, the <tabs> are never wrapped in <toolbarpaletteitem>s in customize mode, ++ // but the other items will be. + let sib = this.tabContainer.nextElementSibling; ++ if (isCustomizing) { ++ sib = sib && sib.firstElementChild; ++ } + while (sib && sib.hidden) { +- sib = sib.nextElementSibling; ++ if (isCustomizing) { ++ sib = sib.parentNode.nextElementSibling; ++ sib = sib && sib.firstElementChild; ++ } else { ++ sib = sib.nextElementSibling; ++ } + } ++ + const kAttr = "hasadjacentnewtabbutton"; + if (sib && sib.id == "new-tab-button") { + this.tabContainer.setAttribute(kAttr, "true"); +diff --git browser/components/customizableui/test/browser.ini browser/components/customizableui/test/browser.ini +index d5f5eaf2a113..b164a573f094 100644 +--- browser/components/customizableui/test/browser.ini ++++ browser/components/customizableui/test/browser.ini +@@ -164,6 +164,7 @@ tags = fullscreen + [browser_check_tooltips_in_navbar.js] + [browser_editcontrols_update.js] + subsuite = clipboard ++[browser_newtab_button_customizemode.js] + [browser_photon_customization_context_menus.js] + [browser_sidebar_toggle.js] + [browser_remote_tabs_button.js] +diff --git browser/components/customizableui/test/browser_newtab_button_customizemode.js browser/components/customizableui/test/browser_newtab_button_customizemode.js +new file mode 100644 +index 000000000000..da886fc47376 +--- /dev/null ++++ browser/components/customizableui/test/browser_newtab_button_customizemode.js +@@ -0,0 +1,106 @@ ++/* Any copyright is dedicated to the Public Domain. ++ * http://creativecommons.org/publicdomain/zero/1.0/ */ ++ ++"use strict"; ++ ++/** ++ * Tests in this file check that user customizations to the tabstrip show ++ * the correct type of new tab button while the tabstrip isn't overflowing. ++ */ ++ ++const kGlobalNewTabButton = document.getElementById("new-tab-button"); ++const kInnerNewTabButton = document.getAnonymousElementByAttribute(gBrowser.tabContainer, "anonid", "tabs-newtab-button"); ++ ++function assertNewTabButton(which) { ++ if (which == "global") { ++ isnot(kGlobalNewTabButton.getBoundingClientRect().width, 0, ++ "main new tab button should be visible"); ++ is(kInnerNewTabButton.getBoundingClientRect().width, 0, ++ "inner new tab button should be hidden"); ++ } else if (which == "inner") { ++ is(kGlobalNewTabButton.getBoundingClientRect().width, 0, ++ "main new tab button should be hidden"); ++ isnot(kInnerNewTabButton.getBoundingClientRect().width, 0, ++ "inner new tab button should be visible"); ++ } else { ++ ok(false, "Unexpected button: " + which); ++ } ++} ++ ++/** ++ * Add and remove items *after* the new tab button in customize mode. ++ */ ++add_task(async function addremove_after_newtab_customizemode() { ++ await startCustomizing(); ++ simulateItemDrag(document.getElementById("home-button"), ++ kGlobalNewTabButton.parentNode.nextElementSibling); ++ ok(gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should have the adjacent newtab attribute"); ++ await endCustomizing(); ++ assertNewTabButton("inner"); ++ ++ await startCustomizing(); ++ simulateItemDrag(document.getElementById("home-button"), ++ document.getElementById("stop-reload-button").parentNode.nextElementSibling); ++ ok(gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should still have the adjacent newtab attribute"); ++ await endCustomizing(); ++ assertNewTabButton("inner"); ++ ok(CustomizableUI.inDefaultState, "Should be in default state"); ++}); ++ ++/** ++ * Add and remove items *before* the new tab button in customize mode. ++ */ ++add_task(async function addremove_before_newtab_customizemode() { ++ await startCustomizing(); ++ simulateItemDrag(document.getElementById("home-button"), kGlobalNewTabButton); ++ ok(!gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should no longer have the adjacent newtab attribute"); ++ await endCustomizing(); ++ assertNewTabButton("global"); ++ await startCustomizing(); ++ simulateItemDrag(document.getElementById("home-button"), ++ document.getElementById("stop-reload-button").parentNode.nextElementSibling); ++ ok(gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should have the adjacent newtab attribute again"); ++ await endCustomizing(); ++ assertNewTabButton("inner"); ++ ok(CustomizableUI.inDefaultState, "Should be in default state"); ++}); ++ ++/** ++ * Add and remove items *after* the new tab button outside of customize mode. ++ */ ++add_task(async function addremove_after_newtab_api() { ++ CustomizableUI.addWidgetToArea("home-button", "TabsToolbar"); ++ ok(gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should have the adjacent newtab attribute"); ++ assertNewTabButton("inner"); ++ ++ CustomizableUI.reset(); ++ ok(gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should still have the adjacent newtab attribute"); ++ assertNewTabButton("inner"); ++ ok(CustomizableUI.inDefaultState, "Should be in default state"); ++ ++}); ++ ++/** ++ * Add and remove items *before* the new tab button outside of customize mode. ++ */ ++add_task(async function addremove_before_newtab_api() { ++ let index = CustomizableUI.getWidgetIdsInArea("TabsToolbar").indexOf("new-tab-button"); ++ CustomizableUI.addWidgetToArea("home-button", "TabsToolbar", index); ++ ok(!gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should no longer have the adjacent newtab attribute"); ++ assertNewTabButton("global"); ++ ++ CustomizableUI.removeWidgetFromArea("home-button"); ++ ok(gBrowser.tabContainer.hasAttribute("hasadjacentnewtabbutton"), ++ "tabs should have the adjacent newtab attribute again"); ++ assertNewTabButton("inner"); ++ ++ CustomizableUI.reset(); ++ ok(CustomizableUI.inDefaultState, "Should be in default state"); ++}); diff --git a/www/waterfox/files/patch-bug1418854 b/www/waterfox/files/patch-bug1418854 new file mode 100644 index 000000000000..e707d06094ac --- /dev/null +++ b/www/waterfox/files/patch-bug1418854 @@ -0,0 +1,102 @@ +commit 1fe2b37624d6 +Author: Michal Novotny <michal.novotny@gmail.com> +Date: Wed Dec 6 20:48:06 2017 -0500 + + Bug 1418854 - Race condition in AutoClose. r=honzab, a=jcristau + + --HG-- + extra : source : 3e425d2e71df08dc944a26eaa41158522a75ff02 +--- + netwerk/base/AutoClose.h | 43 ++++++++++++++++++++++--------------------- + 1 file changed, 22 insertions(+), 21 deletions(-) + +diff --git netwerk/base/AutoClose.h netwerk/base/AutoClose.h +index 8c401071428f..43ab27133fdd 100644 +--- netwerk/base/AutoClose.h ++++ netwerk/base/AutoClose.h +@@ -8,6 +8,7 @@ + #define mozilla_net_AutoClose_h + + #include "nsCOMPtr.h" ++#include "mozilla/Mutex.h" + + namespace mozilla { namespace net { + +@@ -18,49 +19,48 @@ template <typename T> + class AutoClose + { + public: +- AutoClose() { } ++ AutoClose() : mMutex("net::AutoClose.mMutex") { } + ~AutoClose(){ +- Close(); ++ CloseAndRelease(); + } + +- explicit operator bool() const ++ explicit operator bool() + { ++ MutexAutoLock lock(mMutex); + return mPtr; + } + + already_AddRefed<T> forget() + { ++ MutexAutoLock lock(mMutex); + return mPtr.forget(); + } + + void takeOver(nsCOMPtr<T> & rhs) + { +- Close(); +- mPtr = rhs.forget(); +- } +- +- void takeOver(AutoClose<T> & rhs) +- { +- Close(); +- mPtr = rhs.mPtr.forget(); ++ already_AddRefed<T> other = rhs.forget(); ++ TakeOverInternal(&other); + } + + void CloseAndRelease() + { +- Close(); +- mPtr = nullptr; +- } +- +- T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN +- { +- return mPtr.operator->(); ++ TakeOverInternal(nullptr); + } + + private: +- void Close() ++ void TakeOverInternal(already_AddRefed<T> *aOther) + { +- if (mPtr) { +- mPtr->Close(); ++ nsCOMPtr<T> ptr; ++ { ++ MutexAutoLock lock(mMutex); ++ ptr.swap(mPtr); ++ if (aOther) { ++ mPtr = *aOther; ++ } ++ } ++ ++ if (ptr) { ++ ptr->Close(); + } + } + +@@ -68,6 +68,7 @@ private: + AutoClose(const AutoClose<T> &) = delete; + + nsCOMPtr<T> mPtr; ++ Mutex mMutex; + }; + + } // namespace net diff --git a/www/waterfox/files/patch-bug1418894 b/www/waterfox/files/patch-bug1418894 new file mode 100644 index 000000000000..b092b623b5b1 --- /dev/null +++ b/www/waterfox/files/patch-bug1418894 @@ -0,0 +1,244 @@ +commit 408a8eddca66 +Author: Ted Campbell <tcampbell@mozilla.com> +Date: Tue Nov 28 22:52:34 2017 -0500 + + Bug 1418894 - Use marker values in XDR data to detect corruption. r=nbp a=gchang + + MozReview-Commit-ID: D6PxPBdgtPP + + --HG-- + extra : source : 3c5cc7786d922c70b937d1dbe57f0ce700c39551 +--- + js/src/jsfun.cpp | 4 ++++ + js/src/jsscript.cpp | 10 ++++++++++ + js/src/vm/Xdr.h | 12 ++++++++++++ + 3 files changed, 26 insertions(+) + +diff --git js/src/jsfun.cpp js/src/jsfun.cpp +index 234d0cc3438c..5a461c9230eb 100644 +--- js/src/jsfun.cpp ++++ js/src/jsfun.cpp +@@ -682,6 +682,10 @@ js::XDRInterpretedFunction(XDRState<mode>* xdr, HandleScope enclosingScope, + objp.set(fun); + } + ++ // Verify marker at end of function to detect buffer trunction. ++ if (!xdr->codeMarker(0x9E35CA1F)) ++ return false; ++ + return true; + } + +diff --git js/src/jsscript.cpp js/src/jsscript.cpp +index 1b31a0639644..88d6c7bc75b6 100644 +--- js/src/jsscript.cpp ++++ js/src/jsscript.cpp +@@ -808,6 +808,11 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, + if (mode == XDR_DECODE) + vector[i].init(scope); + } ++ ++ // Verify marker to detect data corruption after decoding scope data. A ++ // mismatch here indicates we will almost certainly crash in release. ++ if (!xdr->codeMarker(0x48922BAB)) ++ return false; + } + + /* +@@ -900,6 +905,11 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, + } + } + ++ // Verify marker to detect data corruption after decoding object data. A ++ // mismatch here indicates we will almost certainly crash in release. ++ if (!xdr->codeMarker(0xF83B989A)) ++ return false; ++ + if (ntrynotes != 0) { + JSTryNote* tnfirst = script->trynotes()->vector; + MOZ_ASSERT(script->trynotes()->length == ntrynotes); +diff --git js/src/vm/Xdr.h js/src/vm/Xdr.h +index 18fa1af8ab5b..0a6cbf01b50f 100644 +--- js/src/vm/Xdr.h ++++ js/src/vm/Xdr.h +@@ -307,6 +307,18 @@ class XDRState : public XDRCoderBase + return true; + } + ++ bool codeMarker(uint32_t magic) { ++ uint32_t actual = magic; ++ if (!codeUint32(&actual)) ++ return false; ++ if (actual != magic) { ++ // Fail in debug, but only soft-fail in release ++ MOZ_ASSERT(false, "Bad XDR marker"); ++ return fail(JS::TranscodeResult_Failure_BadDecode); ++ } ++ return true; ++ } ++ + bool codeBytes(void* bytes, size_t len) { + if (len == 0) + return true; + +commit 885c19e8e675 +Author: Ted Campbell <tcampbell@mozilla.com> +Date: Tue Nov 28 23:01:49 2017 -0500 + + Bug 1418894 - Harden XDR data decoding. r=nbp a=gchang + + This patch adds better error detection to XDR decoding to reduce memory + corruption in the event that XDR data is corrupt (which is not + *supposed* to happen). + + Add missing default cases. Make out-of-range values fail the decode by + asserting in debug, and returning a TranscodeError in release. Mix a + magic value into enum value before transcoding to buffer (to reduce + chance of garbage data being decoded). + + MozReview-Commit-ID: 1wPkho9dm8c + + --HG-- + extra : source : 484499ffcbbad636a904832cc90c56c016ad4582 +--- + js/src/jsapi.h | 2 +- + js/src/jsscript.cpp | 40 ++++++++++++++++++++++------------------ + js/src/shell/js.cpp | 4 ++-- + js/src/vm/Xdr.h | 8 ++++++-- + 4 files changed, 31 insertions(+), 23 deletions(-) + +diff --git js/src/jsapi.h js/src/jsapi.h +index 323396025b7a..c43a4c693778 100644 +--- js/src/jsapi.h ++++ js/src/jsapi.h +@@ -6420,7 +6420,7 @@ enum TranscodeResult + TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1, + TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2, + TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3, +- TranscodeResult_Failure_UnknownClassKind = TranscodeResult_Failure | 0x4, ++ TranscodeResult_Failure_BadDecode = TranscodeResult_Failure | 0x4, + TranscodeResult_Failure_WrongCompileOption = TranscodeResult_Failure | 0x5, + TranscodeResult_Failure_NotInterpretedFun = TranscodeResult_Failure | 0x6, + +diff --git js/src/jsscript.cpp js/src/jsscript.cpp +index eff03d909353..1b31a0639644 100644 +--- js/src/jsscript.cpp ++++ js/src/jsscript.cpp +@@ -92,24 +92,19 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp) + { + JSContext* cx = xdr->cx(); + +- /* +- * A script constant can be an arbitrary primitive value as they are used +- * to implement JSOP_LOOKUPSWITCH. But they cannot be objects, see +- * bug 407186. +- */ + enum ConstTag { +- SCRIPT_INT = 0, +- SCRIPT_DOUBLE = 1, +- SCRIPT_ATOM = 2, +- SCRIPT_TRUE = 3, +- SCRIPT_FALSE = 4, +- SCRIPT_NULL = 5, +- SCRIPT_OBJECT = 6, +- SCRIPT_VOID = 7, +- SCRIPT_HOLE = 8 ++ SCRIPT_INT, ++ SCRIPT_DOUBLE, ++ SCRIPT_ATOM, ++ SCRIPT_TRUE, ++ SCRIPT_FALSE, ++ SCRIPT_NULL, ++ SCRIPT_OBJECT, ++ SCRIPT_VOID, ++ SCRIPT_HOLE + }; + +- uint32_t tag; ++ ConstTag tag; + if (mode == XDR_ENCODE) { + if (vp.isInt32()) { + tag = SCRIPT_INT; +@@ -133,7 +128,7 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp) + } + } + +- if (!xdr->codeUint32(&tag)) ++ if (!xdr->codeEnum32(&tag)) + return false; + + switch (tag) { +@@ -199,6 +194,10 @@ js::XDRScriptConst(XDRState<mode>* xdr, MutableHandleValue vp) + if (mode == XDR_DECODE) + vp.setMagic(JS_ELEMENTS_HOLE); + break; ++ default: ++ // Fail in debug, but only soft-fail in release ++ MOZ_ASSERT(false, "Bad XDR value kind"); ++ return xdr->fail(JS::TranscodeResult_Failure_BadDecode); + } + return true; + } +@@ -800,6 +799,10 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, + case ScopeKind::WasmFunction: + MOZ_CRASH("wasm functions cannot be nested in JSScripts"); + break; ++ default: ++ // Fail in debug, but only soft-fail in release ++ MOZ_ASSERT(false, "Bad XDR scope kind"); ++ return xdr->fail(JS::TranscodeResult_Failure_BadDecode); + } + + if (mode == XDR_DECODE) +@@ -890,8 +893,9 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, + } + + default: { +- MOZ_ASSERT(false, "Unknown class kind."); +- return xdr->fail(JS::TranscodeResult_Failure_UnknownClassKind); ++ // Fail in debug, but only soft-fail in release ++ MOZ_ASSERT(false, "Bad XDR class kind"); ++ return xdr->fail(JS::TranscodeResult_Failure_BadDecode); + } + } + } +diff --git js/src/shell/js.cpp js/src/shell/js.cpp +index 16ee93bc66a8..1f5afb04e1f8 100644 +--- js/src/shell/js.cpp ++++ js/src/shell/js.cpp +@@ -1519,9 +1519,9 @@ ConvertTranscodeResultToJSException(JSContext* cx, JS::TranscodeResult rv) + MOZ_ASSERT(!cx->isExceptionPending()); + JS_ReportErrorASCII(cx, "Asm.js is not supported by XDR"); + return false; +- case JS::TranscodeResult_Failure_UnknownClassKind: ++ case JS::TranscodeResult_Failure_BadDecode: + MOZ_ASSERT(!cx->isExceptionPending()); +- JS_ReportErrorASCII(cx, "Unknown class kind, go fix it."); ++ JS_ReportErrorASCII(cx, "XDR data corruption"); + return false; + case JS::TranscodeResult_Failure_WrongCompileOption: + MOZ_ASSERT(!cx->isExceptionPending()); +diff --git js/src/vm/Xdr.h js/src/vm/Xdr.h +index e88968b9a4c0..18fa1af8ab5b 100644 +--- js/src/vm/Xdr.h ++++ js/src/vm/Xdr.h +@@ -279,13 +279,17 @@ class XDRState : public XDRCoderBase + template <typename T> + bool codeEnum32(T* val, typename mozilla::EnableIf<mozilla::IsEnum<T>::value, T>::Type * = NULL) + { ++ // Mix the enumeration value with a random magic number, such that a ++ // corruption with a low-ranged value (like 0) is less likely to cause a ++ // miss-interpretation of the XDR content and instead cause a failure. ++ const uint32_t MAGIC = 0x21AB218C; + uint32_t tmp; + if (mode == XDR_ENCODE) +- tmp = uint32_t(*val); ++ tmp = uint32_t(*val) ^ MAGIC; + if (!codeUint32(&tmp)) + return false; + if (mode == XDR_DECODE) +- *val = T(tmp); ++ *val = T(tmp ^ MAGIC); + return true; + } + diff --git a/www/waterfox/files/patch-bug1419508 b/www/waterfox/files/patch-bug1419508 new file mode 100644 index 000000000000..4d5ca04baaa1 --- /dev/null +++ b/www/waterfox/files/patch-bug1419508 @@ -0,0 +1,29 @@ +commit 4d25545cc673 +Author: Gerald Squelart <gsquelart@mozilla.com> +Date: Thu Jan 25 16:21:23 2018 +1100 + + Bug 1419508 - Return early from CreateMaskLayer if there is no visible data - r=mattwoodrow a=lizzard + + MozReview-Commit-ID: 9jWGXA2eGvv + + --HG-- + extra : source : c5d8b1ed27228f4bcf45b2746f78dba3795d0868 +--- + layout/painting/FrameLayerBuilder.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git layout/painting/FrameLayerBuilder.cpp layout/painting/FrameLayerBuilder.cpp +index 3c5d04260f7e..48ec5db56251 100644 +--- layout/painting/FrameLayerBuilder.cpp ++++ layout/painting/FrameLayerBuilder.cpp +@@ -6358,6 +6358,10 @@ ContainerState::CreateMaskLayer(Layer *aLayer, + gfx::Rect boundingRect = CalculateBounds(newData.mRoundedClipRects, + newData.mAppUnitsPerDevPixel); + boundingRect.Scale(mParameters.mXScale, mParameters.mYScale); ++ if (boundingRect.IsEmpty()) { ++ // Return early if we know that there is effectively no visible data. ++ return nullptr; ++ } + + uint32_t maxSize = mManager->GetMaxTextureSize(); + NS_ASSERTION(maxSize > 0, "Invalid max texture size"); diff --git a/www/waterfox/files/patch-bug1419762 b/www/waterfox/files/patch-bug1419762 new file mode 100644 index 000000000000..57599be571f2 --- /dev/null +++ b/www/waterfox/files/patch-bug1419762 @@ -0,0 +1,69 @@ +commit 0f58a35d5cb7 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Thu Nov 23 01:01:34 2017 +0100 + + Bug 1419762 - Return the inline continuation of an IB split when appending. r=mats, a=jcristau + + The only reason not to do that is when there's after content in there. We know + that there isn't really any ::after content, since it would've been handled by + FindNextSibling, so we know we're performing a real append. + + MozReview-Commit-ID: ExoPolZy4gG + + --HG-- + extra : source : 333214e07fd463dc1c7db00875bb6dff98eb0cdf +--- + layout/base/crashtests/1419762.html | 15 +++++++++++++++ + layout/base/crashtests/crashtests.list | 1 + + layout/base/nsCSSFrameConstructor.cpp | 7 ++++--- + 3 files changed, 20 insertions(+), 3 deletions(-) + +diff --git layout/base/crashtests/1419762.html layout/base/crashtests/1419762.html +new file mode 100644 +index 000000000000..08a56106db93 +--- /dev/null ++++ layout/base/crashtests/1419762.html +@@ -0,0 +1,15 @@ ++<style id='style_1'> ++ :first-child { display: table-column-group; } ++</style> ++<script> ++ try { o1 = document.createElement('isindex') } catch(e) { } ++ try { o2 = document.createElement('input') } catch(e) { } ++ try { o3 = document.createElement('optgroup') } catch(e) { } ++ try { o4 = document.createElement('col') } catch(e) { } ++ try { document.documentElement.appendChild(o1) } catch(e) { } ++ try { o1.appendChild(o2) } catch(e) { } ++ try { o1.appendChild(o3) } catch(e) { } ++ try { document.documentElement.offsetTop; } catch (e) { } ++ try { document.documentElement.appendChild(o4) } catch(e) { } ++ try { document.styleSheets[0].insertRule('optgroup::first-line { list-style-type: japanese-formal; }', 0); } catch(e) { } ++</script> +diff --git layout/base/crashtests/crashtests.list layout/base/crashtests/crashtests.list +index 7010ca4f2d3f..ecced042e228 100644 +--- layout/base/crashtests/crashtests.list ++++ layout/base/crashtests/crashtests.list +@@ -493,3 +493,4 @@ asserts(0-1) load 1343606.html # bug 1343948 + load 1352380.html + load 1362423-1.html + load 1381323.html ++load 1419762.html +diff --git layout/base/nsCSSFrameConstructor.cpp layout/base/nsCSSFrameConstructor.cpp +index bb6da0dba1da..0a1b588c21df 100644 +--- layout/base/nsCSSFrameConstructor.cpp ++++ layout/base/nsCSSFrameConstructor.cpp +@@ -7044,10 +7044,11 @@ nsCSSFrameConstructor::GetInsertionPrevSibling(InsertionPoint* aInsertion, + *aIsAppend = true; + if (IsFramePartOfIBSplit(aInsertion->mParentFrame)) { + // Since we're appending, we'll walk to the last anonymous frame +- // that was created for the broken inline frame. But don't walk +- // to the trailing inline if it's empty; stop at the block. ++ // that was created for the broken inline frame. We can walk to the ++ // trailing inline, since we know this is a real append, and not an ++ // insert (that would've been handled by `FindNextSibling`). + aInsertion->mParentFrame = +- GetLastIBSplitSibling(aInsertion->mParentFrame, false); ++ GetLastIBSplitSibling(aInsertion->mParentFrame, true); + } + // Get continuation that parents the last child. This MUST be done + // before the AdjustAppendParentForAfterContent call. diff --git a/www/waterfox/files/patch-bug1420001 b/www/waterfox/files/patch-bug1420001 new file mode 100644 index 000000000000..384c973c54d2 --- /dev/null +++ b/www/waterfox/files/patch-bug1420001 @@ -0,0 +1,67 @@ +commit 3bd032461399 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Nov 27 14:57:57 2017 -0600 + + Bug 1420001 - style: Disable :visited if the document is being used as an image (from emilio:visited-as-an-image). r=dholbert, a=sledru + + MozReview-Commit-ID: F9MeT1kXZER + Source-Repo: https://github.com/servo/servo + Source-Revision: 7c99ae3bb8056f7e30a3b40340200eced385902d + + --HG-- + extra : source : ed1802f246cb377522e492bf313038213c114843 + extra : intermediate-source : d1599028c579f31e1441b9df277bf8f38c0e7f56 +--- + servo/components/style/gecko/data.rs | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +diff --git servo/components/style/gecko/data.rs servo/components/style/gecko/data.rs +index aeab6a938b9f..244fa034ba61 100644 +--- servo/components/style/gecko/data.rs ++++ servo/components/style/gecko/data.rs +@@ -165,12 +165,20 @@ impl PerDocumentStyleDataImpl { + } + + /// Returns whether private browsing is enabled. +- pub fn is_private_browsing_enabled(&self) -> bool { ++ fn is_private_browsing_enabled(&self) -> bool { + let doc = + self.stylist.device().pres_context().mDocument.raw::<nsIDocument>(); + unsafe { bindings::Gecko_IsPrivateBrowsingEnabled(doc) } + } + ++ /// Returns whether the document is being used as an image. ++ fn is_being_used_as_an_image(&self) -> bool { ++ let doc = ++ self.stylist.device().pres_context().mDocument.raw::<nsIDocument>(); ++ ++ unsafe { (*doc).mIsBeingUsedAsImage() } ++ } ++ + /// Get the default computed values for this document. + pub fn default_computed_values(&self) -> &Arc<ComputedValues> { + self.stylist.device().default_computed_values_arc() +@@ -180,9 +188,22 @@ impl PerDocumentStyleDataImpl { + fn visited_links_enabled(&self) -> bool { + unsafe { bindings::Gecko_AreVisitedLinksEnabled() } + } ++ + /// Returns whether visited styles are enabled. + pub fn visited_styles_enabled(&self) -> bool { +- self.visited_links_enabled() && !self.is_private_browsing_enabled() ++ if !self.visited_links_enabled() { ++ return false; ++ } ++ ++ if self.is_private_browsing_enabled() { ++ return false; ++ } ++ ++ if self.is_being_used_as_an_image() { ++ return false; ++ } ++ ++ true + } + + /// Measure heap usage. diff --git a/www/waterfox/files/patch-bug1421009 b/www/waterfox/files/patch-bug1421009 new file mode 100644 index 000000000000..81357b67ec14 --- /dev/null +++ b/www/waterfox/files/patch-bug1421009 @@ -0,0 +1,24 @@ +commit d4db948c9381 +Author: Andreas Farre <farre@mozilla.com> +Date: Tue Dec 5 04:54:00 2017 -0500 + + Bug 1421009 - Don't schedule idle callback if window is shutting down. r=bkelly, a=gchang +--- + dom/base/nsGlobalWindow.cpp | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git dom/base/nsGlobalWindow.cpp dom/base/nsGlobalWindow.cpp +index 40b0847e9b1c..bbbc94095896 100644 +--- dom/base/nsGlobalWindow.cpp ++++ dom/base/nsGlobalWindow.cpp +@@ -913,6 +913,10 @@ nsGlobalWindow::RequestIdleCallback(JSContext* aCx, + MOZ_RELEASE_ASSERT(IsInnerWindow()); + AssertIsOnMainThread(); + ++ if (mInnerObjectsFreed) { ++ return 0; ++ } ++ + uint32_t handle = mIdleRequestCallbackCounter++; + + RefPtr<IdleRequest> request = diff --git a/www/waterfox/files/patch-bug1421963 b/www/waterfox/files/patch-bug1421963 new file mode 100644 index 000000000000..538df5e120fa --- /dev/null +++ b/www/waterfox/files/patch-bug1421963 @@ -0,0 +1,39 @@ +commit edbe55cb9057 +Author: Randell Jesup <rjesup@jesup.org> +Date: Thu Dec 7 13:24:46 2017 -0500 + + Bug 1421963: lock around SCTP input processing, not just the receive callback r=drno +--- + netwerk/sctp/datachannel/DataChannel.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git netwerk/sctp/datachannel/DataChannel.cpp netwerk/sctp/datachannel/DataChannel.cpp +index 4a0432469a80..6f13826ed7c6 100644 +--- netwerk/sctp/datachannel/DataChannel.cpp ++++ netwerk/sctp/datachannel/DataChannel.cpp +@@ -817,6 +817,7 @@ DataChannelConnection::SctpDtlsInput(TransportFlow *flow, + } + } + // Pass the data to SCTP ++ MutexAutoLock lock(mLock); + usrsctp_conninput(static_cast<void *>(this), data, len, 0); + } + +@@ -1224,7 +1225,7 @@ DataChannelConnection::SendDeferredMessages() + RefPtr<DataChannel> channel; // we may null out the refs to this + + // This may block while something is modifying channels, but should not block for IO +- MutexAutoLock lock(mLock); ++ mLock.AssertCurrentThreadOwns(); + + LOG(("SendDeferredMessages called, pending type: %d", mPendingType)); + if (!mPendingType) { +@@ -2307,7 +2308,7 @@ DataChannelConnection::ReceiveCallback(struct socket* sock, void *data, size_t d + if (!data) { + usrsctp_close(sock); // SCTP has finished shutting down + } else { +- MutexAutoLock lock(mLock); ++ mLock.AssertCurrentThreadOwns(); + if (flags & MSG_NOTIFICATION) { + HandleNotification(static_cast<union sctp_notification *>(data), datalen); + } else { diff --git a/www/waterfox/files/patch-bug1422036 b/www/waterfox/files/patch-bug1422036 new file mode 100644 index 000000000000..3f19764927f5 --- /dev/null +++ b/www/waterfox/files/patch-bug1422036 @@ -0,0 +1,229 @@ +commit 74ed31e949fa +Author: Andrea Marchesini <amarchesini@mozilla.com> +Date: Mon Feb 5 19:55:08 2018 +0100 + + Bug 1422036 - Using WorkerControlRunnable to release resources in fetch when the worker is shutting down. r=catalinb, a=RyanVM + + --HG-- + extra : source : d79788e03f7451ebc4a3c694117497f091a5a129 +--- + dom/fetch/FetchConsumer.cpp | 123 +++++++++++++++++++++++++++++++++++++------- + dom/fetch/FetchConsumer.h | 5 +- + 2 files changed, 106 insertions(+), 22 deletions(-) + +diff --git dom/fetch/FetchConsumer.cpp dom/fetch/FetchConsumer.cpp +index b83c8671404a..1e173f9c9661 100644 +--- dom/fetch/FetchConsumer.cpp ++++ dom/fetch/FetchConsumer.cpp +@@ -102,6 +102,32 @@ public: + } + }; + ++// ControlRunnable used to complete the releasing of resources on the worker ++// thread when already shutting down. ++template <class Derived> ++class ContinueConsumeBodyControlRunnable final : public MainThreadWorkerControlRunnable ++{ ++ RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer; ++ ++public: ++ ContinueConsumeBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer, ++ uint8_t* aResult) ++ : MainThreadWorkerControlRunnable(aFetchBodyConsumer->GetWorkerPrivate()) ++ , mFetchBodyConsumer(aFetchBodyConsumer) ++ { ++ MOZ_ASSERT(NS_IsMainThread()); ++ free(aResult); ++ } ++ ++ bool ++ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override ++ { ++ mFetchBodyConsumer->ContinueConsumeBody(NS_BINDING_ABORTED, 0, nullptr, ++ true /* shutting down */); ++ return true; ++ } ++}; ++ + template <class Derived> + class FailConsumeBodyWorkerRunnable : public MainThreadWorkerControlRunnable + { +@@ -189,6 +215,31 @@ public: + } + }; + ++// ControlRunnable used to complete the releasing of resources on the worker ++// thread when already shutting down. ++template <class Derived> ++class ContinueConsumeBlobBodyControlRunnable final ++ : public MainThreadWorkerControlRunnable ++{ ++ RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer; ++ ++public: ++ explicit ContinueConsumeBlobBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer) ++ : MainThreadWorkerControlRunnable(aFetchBodyConsumer->GetWorkerPrivate()) ++ , mFetchBodyConsumer(aFetchBodyConsumer) ++ { ++ MOZ_ASSERT(NS_IsMainThread()); ++ } ++ ++ bool ++ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override ++ { ++ mFetchBodyConsumer->ContinueConsumeBlobBody(nullptr, ++ true /* shutting down */); ++ return true; ++ } ++}; ++ + template <class Derived> + class ConsumeBodyDoneObserver : public nsIStreamLoaderObserver + , public MutableBlobStorageCallback +@@ -216,20 +267,33 @@ public: + mFetchBodyConsumer->NullifyConsumeBodyPump(); + + uint8_t* nonconstResult = const_cast<uint8_t*>(aResult); +- if (mFetchBodyConsumer->GetWorkerPrivate()) { ++ if (!mFetchBodyConsumer->GetWorkerPrivate()) { ++ mFetchBodyConsumer->ContinueConsumeBody(aStatus, aResultLength, ++ nonconstResult); ++ // FetchBody is responsible for data. ++ return NS_SUCCESS_ADOPTED_DATA; ++ } ++ ++ { + RefPtr<ContinueConsumeBodyRunnable<Derived>> r = + new ContinueConsumeBodyRunnable<Derived>(mFetchBodyConsumer, + aStatus, + aResultLength, + nonconstResult); +- if (!r->Dispatch()) { +- NS_WARNING("Could not dispatch ConsumeBodyRunnable"); +- // Return failure so that aResult is freed. +- return NS_ERROR_FAILURE; ++ if (r->Dispatch()) { ++ // FetchBody is responsible for data. ++ return NS_SUCCESS_ADOPTED_DATA; + } +- } else { +- mFetchBodyConsumer->ContinueConsumeBody(aStatus, aResultLength, +- nonconstResult); ++ } ++ ++ // The worker is shutting down. Let's use a control runnable to complete the ++ // shutting down procedure. ++ ++ RefPtr<ContinueConsumeBodyControlRunnable<Derived>> r = ++ new ContinueConsumeBodyControlRunnable<Derived>(mFetchBodyConsumer, ++ nonconstResult); ++ if (NS_WARN_IF(!r->Dispatch())) { ++ return NS_ERROR_FAILURE; + } + + // FetchBody is responsible for data. +@@ -252,18 +316,28 @@ public: + + MOZ_ASSERT(aBlob); + +- if (mFetchBodyConsumer->GetWorkerPrivate()) { ++ if (!mFetchBodyConsumer->GetWorkerPrivate()) { ++ mFetchBodyConsumer->ContinueConsumeBlobBody(aBlob->Impl()); ++ return; ++ } ++ ++ { + RefPtr<ContinueConsumeBlobBodyRunnable<Derived>> r = + new ContinueConsumeBlobBodyRunnable<Derived>(mFetchBodyConsumer, + aBlob->Impl()); + +- if (!r->Dispatch()) { +- NS_WARNING("Could not dispatch ConsumeBlobBodyRunnable"); ++ if (r->Dispatch()) { + return; + } +- } else { +- mFetchBodyConsumer->ContinueConsumeBlobBody(aBlob->Impl()); + } ++ ++ // The worker is shutting down. Let's use a control runnable to complete the ++ // shutting down procedure. ++ ++ RefPtr<ContinueConsumeBlobBodyControlRunnable<Derived>> r = ++ new ContinueConsumeBlobBodyControlRunnable<Derived>(mFetchBodyConsumer); ++ ++ Unused << NS_WARN_IF(!r->Dispatch()); + } + + private: +@@ -525,7 +599,8 @@ template <class Derived> + void + FetchBodyConsumer<Derived>::ContinueConsumeBody(nsresult aStatus, + uint32_t aResultLength, +- uint8_t* aResult) ++ uint8_t* aResult, ++ bool aShuttingDown) + { + AssertIsOnTargetThread(); + +@@ -550,6 +625,11 @@ FetchBodyConsumer<Derived>::ContinueConsumeBody(nsresult aStatus, + self->ReleaseObject(); + }); + ++ if (aShuttingDown) { ++ // If shutting down, we don't want to resolve any promise. ++ return; ++ } ++ + if (NS_WARN_IF(NS_FAILED(aStatus))) { + localPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + } +@@ -632,7 +712,8 @@ FetchBodyConsumer<Derived>::ContinueConsumeBody(nsresult aStatus, + + template <class Derived> + void +-FetchBodyConsumer<Derived>::ContinueConsumeBlobBody(BlobImpl* aBlobImpl) ++FetchBodyConsumer<Derived>::ContinueConsumeBlobBody(BlobImpl* aBlobImpl, ++ bool aShuttingDown) + { + AssertIsOnTargetThread(); + MOZ_ASSERT(mConsumeType == CONSUME_BLOB); +@@ -646,13 +727,15 @@ FetchBodyConsumer<Derived>::ContinueConsumeBlobBody(BlobImpl* aBlobImpl) + // sync with a body read. + MOZ_ASSERT(mBody->BodyUsed()); + +- MOZ_ASSERT(mConsumePromise); +- RefPtr<Promise> localPromise = mConsumePromise.forget(); ++ if (!aShuttingDown) { ++ MOZ_ASSERT(mConsumePromise); ++ RefPtr<Promise> localPromise = mConsumePromise.forget(); + +- RefPtr<dom::Blob> blob = dom::Blob::Create(mGlobal, aBlobImpl); +- MOZ_ASSERT(blob); ++ RefPtr<dom::Blob> blob = dom::Blob::Create(mGlobal, aBlobImpl); ++ MOZ_ASSERT(blob); + +- localPromise->MaybeResolve(blob); ++ localPromise->MaybeResolve(blob); ++ } + + ReleaseObject(); + } +diff --git dom/fetch/FetchConsumer.h dom/fetch/FetchConsumer.h +index 04b02aee5d4b..d45b62b8379b 100644 +--- dom/fetch/FetchConsumer.h ++++ dom/fetch/FetchConsumer.h +@@ -54,10 +54,11 @@ public: + BeginConsumeBodyMainThread(); + + void +- ContinueConsumeBody(nsresult aStatus, uint32_t aLength, uint8_t* aResult); ++ ContinueConsumeBody(nsresult aStatus, uint32_t aLength, uint8_t* aResult, ++ bool aShuttingDown = false); + + void +- ContinueConsumeBlobBody(BlobImpl* aBlobImpl); ++ ContinueConsumeBlobBody(BlobImpl* aBlobImpl, bool aShuttingDown = false); + + void + ShutDownMainThreadConsuming(); diff --git a/www/waterfox/files/patch-bug1422389 b/www/waterfox/files/patch-bug1422389 new file mode 100644 index 000000000000..07096fca06db --- /dev/null +++ b/www/waterfox/files/patch-bug1422389 @@ -0,0 +1,28 @@ +commit 25e68494fad3 +Author: Jan-Ivar Bruaroey <jib@mozilla.com> +Date: Fri Dec 1 20:49:46 2017 -0500 + + Bug 1422389 - Limit default engine resolution. r=mchiang, a=abillings + + MozReview-Commit-ID: LS1z7I4myeb + + --HG-- + extra : rebase_source : 200216163b4555ede8912e64871eea81eb8affac + extra : source : f0fd6e20a13d11660a5ac57e9703f09978f12acb +--- + dom/media/webrtc/MediaEngineDefault.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git dom/media/webrtc/MediaEngineDefault.cpp dom/media/webrtc/MediaEngineDefault.cpp +index ea5996e92e23..01efb04b5df8 100644 +--- dom/media/webrtc/MediaEngineDefault.cpp ++++ dom/media/webrtc/MediaEngineDefault.cpp +@@ -120,6 +120,8 @@ MediaEngineDefaultVideoSource::Allocate(const dom::MediaTrackConstraints &aConst + MediaEngine::DEFAULT_43_VIDEO_HEIGHT + #endif + ); ++ mOpts.mWidth = std::max(160, std::min(mOpts.mWidth, 4096)); ++ mOpts.mHeight = std::max(90, std::min(mOpts.mHeight, 2160)); + mState = kAllocated; + *aOutHandle = nullptr; + return NS_OK; diff --git a/www/waterfox/files/patch-bug1422518 b/www/waterfox/files/patch-bug1422518 new file mode 100644 index 000000000000..bc8a641cb337 --- /dev/null +++ b/www/waterfox/files/patch-bug1422518 @@ -0,0 +1,27 @@ +commit 22e0f06767fe +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Tue Dec 5 02:29:41 2017 +0100 + + Bug 1422518 - Use LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL for meta refresh r=bz a=gchang + MozReview-Commit-ID: H3hnO3NmHYA + + --HG-- + extra : rebase_source : b9f7cbccdd2f2723e6d66d89f9ac529d462d75dd + extra : source : 6f5aec4cde6f874921eaa1b0b9d7e9d4c7feabe0 +--- + docshell/base/nsDocShell.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git docshell/base/nsDocShell.cpp docshell/base/nsDocShell.cpp +index 83cb87dd8255..31d414d1b57d 100644 +--- docshell/base/nsDocShell.cpp ++++ docshell/base/nsDocShell.cpp +@@ -6976,7 +6976,7 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDel + * LoadURI(...) will cancel all refresh timers... This causes the + * Timer and its refreshData instance to be released... + */ +- LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true); ++ LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, true); + + return NS_OK; + } diff --git a/www/waterfox/files/patch-bug1422545 b/www/waterfox/files/patch-bug1422545 new file mode 100644 index 000000000000..0bf2e1e3109d --- /dev/null +++ b/www/waterfox/files/patch-bug1422545 @@ -0,0 +1,38 @@ +commit d5e722168a84 +Author: Dragana Damjanovic <dd.mozilla@gmail.com> +Date: Wed Dec 20 16:13:36 2017 +0100 + + Bug 1422545 - Do not close connection between a httpChannelChild and its httpChannelParent if we need to divert to parent. r=mayhemer, a=jcristau + + If UnknowDecoder is involved and the received content is short we will know whether we need to divert to parent only after OnStartRequest of the listener chain is called. Therefore do not do cleanup if we detect diversion. + + --HG-- + extra : source : e87b07c9db7c302237fa0adbb68c0f31b1840191 +--- + netwerk/protocol/http/HttpChannelChild.cpp | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git netwerk/protocol/http/HttpChannelChild.cpp netwerk/protocol/http/HttpChannelChild.cpp +index 18b9fe2de1db..8fc7746a2a42 100644 +--- netwerk/protocol/http/HttpChannelChild.cpp ++++ netwerk/protocol/http/HttpChannelChild.cpp +@@ -1100,6 +1100,19 @@ HttpChannelChild::OnStopRequest(const nsresult& channelStatus, + // DoOnStopRequest() calls ReleaseListeners() + } + ++ // If unknownDecoder is involved and the received content is short we will ++ // know whether we need to divert to parent only after OnStopRequest of the ++ // listeners chain is called in DoOnStopRequest. At that moment ++ // unknownDecoder will call OnStartRequest of the real listeners of the ++ // channel including the OnStopRequest of UrlLoader which decides whether we ++ // need to divert to parent. ++ // If we are diverting to parent we should not do a cleanup. ++ if (mDivertingToParent) { ++ LOG(("HttpChannelChild::OnStopRequest - We are diverting to parent, " ++ "postpone cleaning up.")); ++ return; ++ } ++ + CleanupBackgroundChannel(); + + // If there is a possibility we might want to write alt data to the cache diff --git a/www/waterfox/files/patch-bug1423647 b/www/waterfox/files/patch-bug1423647 new file mode 100644 index 000000000000..06855735a096 --- /dev/null +++ b/www/waterfox/files/patch-bug1423647 @@ -0,0 +1,37 @@ +commit 65de8dd25011 +Author: Dão Gottwald <dao@mozilla.com> +Date: Thu Dec 7 12:25:33 2017 +0100 + + Bug 1423647 - Restore border-radius for buttons in the Downloads View in the Library. r=mak, a=jcristau + + MozReview-Commit-ID: 6kkdp8pHAlv + + --HG-- + extra : source : 1b381ddb9779e2e0bc2be4f9382ca8560862b409 +--- + browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css +index 063668d48509..663b0893892c 100644 +--- browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css ++++ browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css +@@ -80,10 +80,6 @@ + padding: 0 18px; + } + +-.downloadButton:-moz-focusring { +- -moz-outline-radius: 50%; +-} +- + .downloadButton > .button-box { + -moz-appearance: none; + padding: 2px !important; +@@ -104,6 +100,7 @@ + .downloadButton:hover > .button-box { + background-color: graytext; + color: -moz-field; ++ border-radius: 50%; + } + + .downloadButton:hover:active > .button-box { diff --git a/www/waterfox/files/patch-bug1423770 b/www/waterfox/files/patch-bug1423770 new file mode 100644 index 000000000000..bd82b116bf1d --- /dev/null +++ b/www/waterfox/files/patch-bug1423770 @@ -0,0 +1,44 @@ +commit 2506c20ded5b +Author: Alex Chronopoulos <achronop@gmail.com> +Date: Wed Dec 20 09:21:40 2017 -0500 + + Bug 1423770. r=padenot, a=jcristau + + --HG-- + extra : rebase_source : 6c9ad483fe1ef89966e1a2a1fac8a9bdb8bf43c8 +--- + media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +index 5c2bcd16d017..2bb7203f85bd 100644 +--- media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp ++++ media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +@@ -518,6 +518,7 @@ public: + packetizer_->Channels() != outputChannels) { + // It's ok to drop the audio still in the packetizer here. + packetizer_ = new AudioPacketizer<int16_t, int16_t>(audio_10ms, outputChannels); ++ packet_ = MakeUnique<int16_t[]>(audio_10ms * outputChannels); + } + + packetizer_->Input(samples, chunk.mDuration); +@@ -525,8 +526,8 @@ public: + while (packetizer_->PacketsAvailable()) { + uint32_t samplesPerPacket = packetizer_->PacketSize() * + packetizer_->Channels(); +- packetizer_->Output(packet_); +- mConduit->SendAudioFrame(packet_, samplesPerPacket, rate, 0); ++ packetizer_->Output(packet_.get()); ++ mConduit->SendAudioFrame(packet_.get(), samplesPerPacket, rate, 0); + } + } + +@@ -555,7 +556,7 @@ protected: + // Only accessed on mThread + nsAutoPtr<AudioPacketizer<int16_t, int16_t>> packetizer_; + // A buffer to hold a single packet of audio. +- int16_t packet_[AUDIO_SAMPLE_BUFFER_MAX_BYTES / sizeof(int16_t)]; ++ UniquePtr<int16_t[]> packet_; + }; + + static char kDTLSExporterLabel[] = "EXTRACTOR-dtls_srtp"; diff --git a/www/waterfox/files/patch-bug1424311 b/www/waterfox/files/patch-bug1424311 new file mode 100644 index 000000000000..8db2056c22af --- /dev/null +++ b/www/waterfox/files/patch-bug1424311 @@ -0,0 +1,66 @@ +commit af4e28ddf70d +Author: David Keeler <dkeeler@mozilla.com> +Date: Wed Mar 28 13:43:03 2018 -0700 + + Bug 1424311 - Don't persist the certificate exception dialog's size so it doesn't grow unboundedly. r=jcj, a=RyanVM + + window.sizeToContent() apparently interacts poorly with windows that have a + persisted size (see bug 90276, which is a 5-digit bug that hasn't been touched + in over a decade). As a workaround, don't persist the certificate exception + dialog's size. This means we have to call window.sizeToContent() more often and + unfortunately results in the window growing and shrinking again on Windows, but + at least it will always be the "right size" for its content. + + MozReview-Commit-ID: 9UT3X8IEqZg + + --HG-- + extra : source : 02213fd3a9c84544936a6901adb8821e0c0f44b9 +--- + security/manager/pki/resources/content/exceptionDialog.js | 3 ++- + security/manager/pki/resources/content/exceptionDialog.xul | 2 -- + 2 files changed, 2 insertions(+), 3 deletions(-) + +diff --git security/manager/pki/resources/content/exceptionDialog.js security/manager/pki/resources/content/exceptionDialog.js +index bf17af169c54..72c7d455e958 100644 +--- security/manager/pki/resources/content/exceptionDialog.js ++++ security/manager/pki/resources/content/exceptionDialog.js +@@ -59,6 +59,7 @@ function initExceptionDialog() { + // Set out parameter to false by default + args[0].exceptionAdded = false; + } ++ window.sizeToContent(); + } + + /** +@@ -150,6 +151,7 @@ function resetDialog() { + setText("status2LongDescription", ""); + setText("status3Description", ""); + setText("status3LongDescription", ""); ++ window.sizeToContent(); + } + + /** +@@ -275,7 +277,6 @@ function updateCertStatus() { + } + + window.sizeToContent(); +- + gNeedReset = true; + } + +diff --git security/manager/pki/resources/content/exceptionDialog.xul security/manager/pki/resources/content/exceptionDialog.xul +index 6d417f360ccd..b7d85e2930c4 100644 +--- security/manager/pki/resources/content/exceptionDialog.xul ++++ security/manager/pki/resources/content/exceptionDialog.xul +@@ -14,11 +14,9 @@ + buttons="cancel,extra1,extra2" + buttonlabelextra1="&exceptionMgr.exceptionButton.label;" + buttonaccesskeyextra1="&exceptionMgr.exceptionButton.accesskey;" +- style="width: 46em; min-height: 38em;" + onload="initExceptionDialog();" + ondialogextra1="addException();" + ondialogextra2="checkCert();" +- persist="screenX screenY width height" + defaultButton="extra2"> + + <stringbundleset id="stringbundleset"> diff --git a/www/waterfox/files/patch-bug1424373 b/www/waterfox/files/patch-bug1424373 new file mode 100644 index 000000000000..e237dfc67cd8 --- /dev/null +++ b/www/waterfox/files/patch-bug1424373 @@ -0,0 +1,305 @@ +commit 3512ab03dd1f +Author: Mike Conley <mconley@mozilla.com> +Date: Mon Dec 18 11:19:53 2017 -0500 + + Bug 1424373 - Don't set crash reporting prefs when showing about:tabcrashed for a crash without a report. r=Mossop a=jcristau +--- + browser/base/content/aboutTabCrashed.js | 1 + + .../test/tabcrashed/browser_autoSubmitRequest.js | 63 ++++++++++++++++++++-- + .../content/test/tabcrashed/browser_withoutDump.js | 10 +--- + browser/base/content/test/tabcrashed/head.js | 12 +++++ + browser/modules/ContentCrashHandlers.jsm | 13 +++-- + 5 files changed, 83 insertions(+), 16 deletions(-) + +diff --git browser/base/content/aboutTabCrashed.js browser/base/content/aboutTabCrashed.js +index 822e3f78d4b5..8fccc92aa0fe 100644 +--- browser/base/content/aboutTabCrashed.js ++++ browser/base/content/aboutTabCrashed.js +@@ -303,6 +303,7 @@ var AboutTabCrashed = { + includeURL, + URL, + autoSubmit, ++ hasReport: this.hasReport, + }); + }, + }; +diff --git browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js +index a86b1e2c79b7..e04ebc80cdea 100644 +--- browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js ++++ browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js +@@ -19,9 +19,9 @@ requestLongerTimeout(2); + add_task(async function test_show_form() { + await SpecialPowers.pushPrefEnv({ + set: [[AUTOSUBMIT_PREF, false]], +- }) ++ }); + +- return BrowserTestUtils.withNewTab({ ++ await BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE, + }, async function(browser) { +@@ -66,9 +66,9 @@ add_task(async function test_show_form() { + add_task(async function test_show_form() { + await SpecialPowers.pushPrefEnv({ + set: [[AUTOSUBMIT_PREF, true]], +- }) ++ }); + +- return BrowserTestUtils.withNewTab({ ++ await BrowserTestUtils.withNewTab({ + gBrowser, + url: PAGE, + }, async function(browser) { +@@ -95,3 +95,58 @@ add_task(async function test_show_form() { + "Autosubmission pref should have been set."); + }); + }); ++ ++/** ++ * Tests that we properly set the autoSubmit preference if the user is ++ * presented with a tabcrashed page without a crash report. ++ */ ++add_task(async function test_no_offer() { ++ // We should default to sending the report. ++ Assert.ok(TabCrashHandler.prefs.getBoolPref("sendReport")); ++ ++ await SpecialPowers.pushPrefEnv({ ++ set: [[AUTOSUBMIT_PREF, false]], ++ }); ++ ++ await BrowserTestUtils.withNewTab({ ++ gBrowser, ++ url: PAGE, ++ }, async function(browser) { ++ await TabStateFlusher.flush(browser); ++ ++ // Make it so that it seems like no dump is available for the next crash. ++ prepareNoDump(); ++ ++ // Now crash the browser. ++ await BrowserTestUtils.crashBrowser(browser); ++ ++ // eslint-disable-next-line mozilla/no-cpows-in-tests ++ let doc = browser.contentDocument; ++ ++ // Ensure the request to autosubmit is invisible, since there's no report. ++ let requestRect = doc.getElementById("requestAutoSubmit") ++ .getBoundingClientRect(); ++ Assert.equal(0, requestRect.height, ++ "Request for autosubmission has no height"); ++ Assert.equal(0, requestRect.width, ++ "Request for autosubmission has no width"); ++ ++ // Since the pref is set to false, the checkbox should be ++ // unchecked. ++ let autoSubmit = doc.getElementById("autoSubmit"); ++ Assert.ok(!autoSubmit.checked, ++ "Checkbox for autosubmission is not checked."); ++ ++ let restoreButton = doc.getElementById("restoreTab"); ++ restoreButton.click(); ++ ++ await BrowserTestUtils.browserLoaded(browser, false, PAGE); ++ ++ // The autosubmission pref should now be set. ++ Assert.ok(!Services.prefs.getBoolPref(AUTOSUBMIT_PREF), ++ "Autosubmission pref should not have changed."); ++ }); ++ ++ // We should not have changed the default value for sending the report. ++ Assert.ok(TabCrashHandler.prefs.getBoolPref("sendReport")); ++}); +diff --git browser/base/content/test/tabcrashed/browser_withoutDump.js browser/base/content/test/tabcrashed/browser_withoutDump.js +index 62d997240af4..33bc2b3164a1 100644 +--- browser/base/content/test/tabcrashed/browser_withoutDump.js ++++ browser/base/content/test/tabcrashed/browser_withoutDump.js +@@ -2,16 +2,8 @@ + + const PAGE = "data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page."; + +-/** +- * Monkey patches TabCrashHandler.getDumpID to return null in order to test +- * about:tabcrashed when a dump is not available. +- */ + add_task(async function setup() { +- let originalGetDumpID = TabCrashHandler.getDumpID; +- TabCrashHandler.getDumpID = function(browser) { return null; }; +- registerCleanupFunction(() => { +- TabCrashHandler.getDumpID = originalGetDumpID; +- }); ++ prepareNoDump(); + }); + + /** +diff --git browser/base/content/test/tabcrashed/head.js browser/base/content/test/tabcrashed/head.js +index e437acbcc4d5..9102e409ee91 100644 +--- browser/base/content/test/tabcrashed/head.js ++++ browser/base/content/test/tabcrashed/head.js +@@ -121,3 +121,15 @@ async function setupLocalCrashReportServer() { + env.set("MOZ_CRASHREPORTER_URL", serverUrl); + }); + } ++ ++/** ++ * Monkey patches TabCrashHandler.getDumpID to return null in order to test ++ * about:tabcrashed when a dump is not available. ++ */ ++function prepareNoDump() { ++ let originalGetDumpID = TabCrashHandler.getDumpID; ++ TabCrashHandler.getDumpID = function(browser) { return null; }; ++ registerCleanupFunction(() => { ++ TabCrashHandler.getDumpID = originalGetDumpID; ++ }); ++} +diff --git browser/modules/ContentCrashHandlers.jsm browser/modules/ContentCrashHandlers.jsm +index 36e60ede4f03..524d6a86a50a 100644 +--- browser/modules/ContentCrashHandlers.jsm ++++ browser/modules/ContentCrashHandlers.jsm +@@ -361,8 +361,14 @@ this.TabCrashHandler = { + * even if they are empty. + */ + maybeSendCrashReport(message) { +- if (!AppConstants.MOZ_CRASHREPORTER) ++ if (!AppConstants.MOZ_CRASHREPORTER) { ++ return; ++ } ++ ++ if (!message.data.hasReport) { ++ // There was no report, so nothing to do. + return; ++ } + + let browser = message.target.browser; + +@@ -374,8 +380,9 @@ this.TabCrashHandler = { + + let childID = this.browserMap.get(browser); + let dumpID = this.childMap.get(childID); +- if (!dumpID) +- return ++ if (!dumpID) { ++ return; ++ } + + if (!message.data.sendReport) { + Services.telemetry.getHistogramById("FX_CONTENT_CRASH_NOT_SUBMITTED").add(1); + +commit a4a421108540 +Author: Mike Conley <mconley@mozilla.com> +Date: Thu Dec 21 16:36:13 2017 -0500 + + Bug 1424373 - Rename crash report submission pref. r=Mossop a=jcristau +--- + browser/app/profile/firefox.js | 2 +- + browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js | 2 +- + browser/components/preferences/in-content/privacy.xul | 6 +++--- + .../tests/browser_bug1020245_openPreferences_to_paneContent.js | 4 ++-- + .../components/sessionstore/test/browser_background_tab_crash.js | 2 +- + browser/modules/ContentCrashHandlers.jsm | 4 ++-- + browser/modules/test/browser/browser_UnsubmittedCrashHandler.js | 4 ++-- + 7 files changed, 12 insertions(+), 12 deletions(-) + +diff --git browser/app/profile/firefox.js browser/app/profile/firefox.js +index 8c29be0acc58..a1844936fdea 100644 +--- browser/app/profile/firefox.js ++++ browser/app/profile/firefox.js +@@ -1664,7 +1664,7 @@ pref("browser.crashReports.unsubmittedCheck.enabled", false); + // without a user choice before we suppress the notification for + // some number of days. + pref("browser.crashReports.unsubmittedCheck.chancesUntilSuppress", 4); +-pref("browser.crashReports.unsubmittedCheck.autoSubmit", false); ++pref("browser.crashReports.unsubmittedCheck.autoSubmit2", false); + + // Preferences for the form autofill system extension + // The truthy values of "extensions.formautofill.available" are "on" and "detect", +diff --git browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js +index e04ebc80cdea..1d4a70a1d145 100644 +--- browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js ++++ browser/base/content/test/tabcrashed/browser_autoSubmitRequest.js +@@ -1,7 +1,7 @@ + "use strict"; + + const PAGE = "data:text/html,<html><body>A%20regular,%20everyday,%20normal%20page."; +-const AUTOSUBMIT_PREF = "browser.crashReports.unsubmittedCheck.autoSubmit"; ++const AUTOSUBMIT_PREF = "browser.crashReports.unsubmittedCheck.autoSubmit2"; + + const {TabStateFlusher} = + Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {}); +diff --git browser/components/preferences/in-content-new/privacy.xul browser/components/preferences/in-content-new/privacy.xul +index 7eb882972ffa..1d34065ac7e5 100644 +--- browser/components/preferences/in-content-new/privacy.xul ++++ browser/components/preferences/in-content-new/privacy.xul +@@ -161,8 +161,8 @@ + + <!-- Data Choices tab --> + #ifdef MOZ_CRASHREPORTER +- <preference id="browser.crashReports.unsubmittedCheck.autoSubmit" +- name="browser.crashReports.unsubmittedCheck.autoSubmit" ++ <preference id="browser.crashReports.unsubmittedCheck.autoSubmit2" ++ name="browser.crashReports.unsubmittedCheck.autoSubmit2" + type="bool"/> + #endif + +@@ -671,7 +671,7 @@ + #ifdef MOZ_CRASHREPORTER + <hbox align="center"> + <checkbox id="automaticallySubmitCrashesBox" +- preference="browser.crashReports.unsubmittedCheck.autoSubmit" ++ preference="browser.crashReports.unsubmittedCheck.autoSubmit2" + label="&alwaysSubmitCrashReports1.label;" + accesskey="&alwaysSubmitCrashReports1.accesskey;"/> + <label id="crashReporterLearnMore" +diff --git browser/components/sessionstore/test/browser_background_tab_crash.js browser/components/sessionstore/test/browser_background_tab_crash.js +index 9df18999a32f..34d92a9bdb39 100644 +--- browser/components/sessionstore/test/browser_background_tab_crash.js ++++ browser/components/sessionstore/test/browser_background_tab_crash.js +@@ -147,7 +147,7 @@ add_task(async function test_background_crash_simple() { + */ + add_task(async function test_background_crash_autosubmit_backlogged() { + await SpecialPowers.pushPrefEnv({ +- set: [["browser.crashReports.unsubmittedCheck.autoSubmit", true]], ++ set: [["browser.crashReports.unsubmittedCheck.autoSubmit2", true]], + }); + + await setupBackgroundTabs(async function([tab1, tab2]) { +diff --git browser/modules/ContentCrashHandlers.jsm browser/modules/ContentCrashHandlers.jsm +index a5f95677c006..7127e2785c3a 100644 +--- browser/modules/ContentCrashHandlers.jsm ++++ browser/modules/ContentCrashHandlers.jsm +@@ -885,11 +885,11 @@ this.UnsubmittedCrashHandler = { + + get autoSubmit() { + return Services.prefs +- .getBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit"); ++ .getBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit2"); + }, + + set autoSubmit(val) { +- Services.prefs.setBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit", ++ Services.prefs.setBoolPref("browser.crashReports.unsubmittedCheck.autoSubmit2", + val); + }, + +diff --git browser/modules/test/browser/browser_UnsubmittedCrashHandler.js browser/modules/test/browser/browser_UnsubmittedCrashHandler.js +index 12c673ca92d2..2e79413d0a15 100644 +--- browser/modules/test/browser/browser_UnsubmittedCrashHandler.js ++++ browser/modules/test/browser/browser_UnsubmittedCrashHandler.js +@@ -398,7 +398,7 @@ add_task(async function test_can_submit_several() { + * and sends the pending crash reports. + */ + add_task(async function test_can_submit_always() { +- let pref = "browser.crashReports.unsubmittedCheck.autoSubmit"; ++ let pref = "browser.crashReports.unsubmittedCheck.autoSubmit2"; + Assert.equal(Services.prefs.getBoolPref(pref), false, + "We should not be auto-submitting by default"); + +@@ -442,7 +442,7 @@ add_task(async function test_can_submit_always() { + */ + add_task(async function test_can_auto_submit() { + await SpecialPowers.pushPrefEnv({ set: [ +- ["browser.crashReports.unsubmittedCheck.autoSubmit", true], ++ ["browser.crashReports.unsubmittedCheck.autoSubmit2", true], + ]}); + + let reportIDs = await createPendingCrashReports(3); diff --git a/www/waterfox/files/patch-bug1424469 b/www/waterfox/files/patch-bug1424469 new file mode 100644 index 000000000000..2d7d4a14fc97 --- /dev/null +++ b/www/waterfox/files/patch-bug1424469 @@ -0,0 +1,36 @@ +commit 3c1a70ea1e0c +Author: Paolo Amadini <paolo.mozmail@amadzone.org> +Date: Tue Jan 30 14:38:25 2018 +0000 + + Bug 1424469 - The Downloads view in the Library window doesn't get focus when opened. r=mak, a=RyanVM + + We have to keep track of the focused element while we remove the richlistbox element temporarily. + + MozReview-Commit-ID: AePydUyyUS7 + + --HG-- + extra : source : 6aa2d7b4215e350c76bdfbb9132eb5ae42b23123 +--- + browser/components/downloads/content/allDownloadsViewOverlay.js | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git browser/components/downloads/content/allDownloadsViewOverlay.js browser/components/downloads/content/allDownloadsViewOverlay.js +index 64052c0259f1..7f1990651ced 100644 +--- browser/components/downloads/content/allDownloadsViewOverlay.js ++++ browser/components/downloads/content/allDownloadsViewOverlay.js +@@ -1022,11 +1022,15 @@ DownloadsPlacesView.prototype = { + xblFields.set(key, value); + } + ++ let oldActiveElement = document.activeElement; + let parentNode = this._richlistbox.parentNode; + let nextSibling = this._richlistbox.nextSibling; + parentNode.removeChild(this._richlistbox); + this._richlistbox.appendChild(aDOMFragment); + parentNode.insertBefore(this._richlistbox, nextSibling); ++ if (oldActiveElement && oldActiveElement != document.activeElement) { ++ oldActiveElement.focus(); ++ } + + for (let [key, value] of xblFields) { + this._richlistbox[key] = value; diff --git a/www/waterfox/files/patch-bug1425107 b/www/waterfox/files/patch-bug1425107 new file mode 100644 index 000000000000..68ce41bbad47 --- /dev/null +++ b/www/waterfox/files/patch-bug1425107 @@ -0,0 +1,43 @@ +commit 5f4e1908d910 +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Thu Dec 14 12:45:37 2017 -0500 + + Bug 1425107 - Fix setting scrollTop to 0 on an element with a pending scroll position restore to actually work correctly. r=mats, a=gchang + + MozReview-Commit-ID: 949eBXmKHlA + + --HG-- + extra : source : 81174f568eaa91aa8f5f65e05f35f4350a8cfb25 + extra : amend_source : a1142868a5029bcbaea6fc66bc0becd3ef8d6c9b +--- + layout/generic/nsGfxScrollFrame.cpp | 7 ++++++ + testing/web-platform/meta/MANIFEST.json | 27 +++++++++++++++++++++- + .../cssom-view/scrollTop-display-change-ref.html | 8 +++++++ + .../css/cssom-view/scrollTop-display-change.html | 17 ++++++++++++++ + 4 files changed, 58 insertions(+), 1 deletion(-) + +diff --git layout/generic/nsGfxScrollFrame.cpp layout/generic/nsGfxScrollFrame.cpp +index 9fee3cc2e502..b1575b214240 100644 +--- layout/generic/nsGfxScrollFrame.cpp ++++ layout/generic/nsGfxScrollFrame.cpp +@@ -2272,6 +2272,11 @@ ScrollFrameHelper::ScrollToWithOrigin(nsPoint aScrollPosition, + const nsRect* aRange, + nsIScrollbarMediator::ScrollSnapMode aSnap) + { ++ if (aOrigin != nsGkAtoms::restore) { ++ // If we're doing a non-restore scroll, we don't want to later ++ // override it by restoring our saved scroll position. ++ mRestorePos.x = mRestorePos.y = -1; ++ } + + if (aSnap == nsIScrollableFrame::ENABLE_SNAP) { + GetSnapPointForDestination(nsIScrollableFrame::DEVICE_PIXELS, +@@ -4316,6 +4321,8 @@ ScrollFrameHelper::ScrollToRestoredPosition() + (mScrollPort.XMost() - scrollToPos.x - mScrolledFrame->GetRect().width); + } + AutoWeakFrame weakFrame(mOuter); ++ // It's very important to pass nsGkAtoms::restore here, so ++ // ScrollToWithOrigin won't clear out mRestorePos. + ScrollToWithOrigin(scrollToPos, nsIScrollableFrame::INSTANT, + nsGkAtoms::restore, nullptr); + if (!weakFrame.IsAlive()) { diff --git a/www/waterfox/files/patch-bug1425267 b/www/waterfox/files/patch-bug1425267 new file mode 100644 index 000000000000..0dcca4ec774b --- /dev/null +++ b/www/waterfox/files/patch-bug1425267 @@ -0,0 +1,55 @@ +commit d60383c31a25 +Author: Shane Caraveo <scaraveo@mozilla.com> +Date: Thu Dec 21 15:18:26 2017 -0800 + + Bug 1425267 fix url param schema for launchWebAuthFlow, r=rpl a=gchang + + --HG-- + extra : source : 0c4f3b8d311e4751dafc00d689c3bf07f17c15dd +--- + toolkit/components/extensions/schemas/identity.json | 4 ++-- + .../components/extensions/test/mochitest/test_ext_identity.html | 9 +++++++-- + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git toolkit/components/extensions/schemas/identity.json toolkit/components/extensions/schemas/identity.json +index 308687ce8c83..97b8a57f379c 100644 +--- toolkit/components/extensions/schemas/identity.json ++++ toolkit/components/extensions/schemas/identity.json +@@ -162,7 +162,7 @@ + "name": "details", + "type": "object", + "properties": { +- "url": {"type": "string"}, ++ "url": {"$ref": "manifest.HttpURL"}, + "interactive": {"type": "boolean", "optional": true} + } + }, +@@ -185,7 +185,7 @@ + "description": "Generates a redirect URL to be used in |launchWebAuthFlow|.", + "parameters": [ + { +- "name": " path", ++ "name": "path", + "type": "string", + "default": "", + "optional": true, +diff --git toolkit/components/extensions/test/mochitest/test_chrome_ext_identity.html toolkit/components/extensions/test/mochitest/test_chrome_ext_identity.html +index adf67b6ffe59..278223896749 100644 +--- toolkit/components/extensions/test/mochitest/test_chrome_ext_identity.html ++++ toolkit/components/extensions/test/mochitest/test_chrome_ext_identity.html +@@ -78,8 +78,13 @@ add_task(async function test_badAuthURI() { + ], + }, + async background() { +- await browser.test.assertRejects(browser.identity.launchWebAuthFlow({interactive: true, url: "foobar"}), +- "details.url is invalid", "invalid param url"); ++ for (let url of ["foobar", "about:addons", "about:blank", "ftp://example.com/test"]) { ++ await browser.test.assertThrows( ++ () => { browser.identity.launchWebAuthFlow({interactive: true, url}); }, ++ /Type error for parameter details/, ++ "details.url is invalid"); ++ } ++ + browser.test.sendMessage("done"); + }, + }); diff --git a/www/waterfox/files/patch-bug1425520 b/www/waterfox/files/patch-bug1425520 new file mode 100644 index 000000000000..8a3ed5ac7986 --- /dev/null +++ b/www/waterfox/files/patch-bug1425520 @@ -0,0 +1,27 @@ +commit c4088252ee68 +Author: Henri Sivonen <hsivonen@hsivonen.fi> +Date: Wed Feb 28 13:53:29 2018 +0200 + + Bug 1425520. r=smaug. a=abillings + + MozReview-Commit-ID: IoZeR5BGjmQ + + --HG-- + extra : source : e20052aa341d6da4505eb84be6e061bb7f37de51 +--- + dom/base/nsDocumentEncoder.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git dom/base/nsDocumentEncoder.cpp dom/base/nsDocumentEncoder.cpp +index d591f61c6244..9c0eaaa63bc4 100644 +--- dom/base/nsDocumentEncoder.cpp ++++ dom/base/nsDocumentEncoder.cpp +@@ -517,7 +517,7 @@ nsDocumentEncoder::SerializeToStringRecursive(nsINode* aNode, + } + + if (!aDontSerializeRoot) { +- rv = SerializeNodeEnd(node, aStr); ++ rv = SerializeNodeEnd(maybeFixedNode, aStr); + NS_ENSURE_SUCCESS(rv, rv); + } + diff --git a/www/waterfox/files/patch-bug1425612 b/www/waterfox/files/patch-bug1425612 new file mode 100644 index 000000000000..95a6b3df58cf --- /dev/null +++ b/www/waterfox/files/patch-bug1425612 @@ -0,0 +1,85 @@ +commit 64e13f47e70c +Author: Jason Orendorff <jorendorff@mozilla.com> +Date: Wed Jan 10 20:45:39 2018 -0600 + + Bug 1425612 - Better error messages for invalid structured clone data. r=sfink, a=gchang. + + --HG-- + extra : source : 462f41ca6771fa573e6550509e78dddc8bd8d102 + extra : intermediate-source : a2cf3f843d0b5d99c9603d6d4c83146719634a4a + extra : histedit_source : d6a121b9aaa78c385a368667606126b4aaa6d8b2 +--- + js/src/vm/StructuredClone.cpp | 32 +++++++++++++++++++++++++++++--- + 1 file changed, 29 insertions(+), 3 deletions(-) + +diff --git js/src/vm/StructuredClone.cpp js/src/vm/StructuredClone.cpp +index e6623058459f..8d5f22a0f90b 100644 +--- js/src/vm/StructuredClone.cpp ++++ js/src/vm/StructuredClone.cpp +@@ -1873,6 +1873,12 @@ JSStructuredCloneReader::readTypedArray(uint32_t arrayType, uint32_t nelems, Mut + return false; + byteOffset = n; + } ++ if (!v.isObject() || !v.toObject().is<ArrayBufferObjectMaybeShared>()) { ++ JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, ++ "typed array must be backed by an ArrayBuffer"); ++ return false; ++ } ++ + RootedObject buffer(context(), &v.toObject()); + RootedObject obj(context(), nullptr); + +@@ -1930,6 +1936,11 @@ JSStructuredCloneReader::readDataView(uint32_t byteLength, MutableHandleValue vp + RootedValue v(context()); + if (!startRead(&v)) + return false; ++ if (!v.isObject() || !v.toObject().is<ArrayBufferObjectMaybeShared>()) { ++ JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, ++ "DataView must be backed by an ArrayBuffer"); ++ return false; ++ } + + // Read byteOffset. + uint64_t n; +@@ -1980,8 +1991,11 @@ JSStructuredCloneReader::readSharedArrayBuffer(uint32_t nbytes, MutableHandleVal + + // We must not transfer buffer pointers cross-process. The cloneDataPolicy + // in the sender should guard against this; check that it does. +- +- MOZ_RELEASE_ASSERT(storedScope <= JS::StructuredCloneScope::SameProcessDifferentThread); ++ if (storedScope > JS::StructuredCloneScope::SameProcessDifferentThread) { ++ JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, ++ "can't transfer SharedArrayBuffer cross-process"); ++ return false; ++ } + + // The new object will have a new reference to the rawbuf. + +@@ -2009,7 +2023,11 @@ bool + JSStructuredCloneReader::readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, + MutableHandleValue vp) + { +- MOZ_ASSERT(arrayType <= Scalar::Uint8Clamped); ++ if (arrayType > Scalar::Uint8Clamped) { ++ JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, ++ "invalid TypedArray type"); ++ return false; ++ } + + mozilla::CheckedInt<size_t> nbytes = + mozilla::CheckedInt<size_t>(nelems) * +@@ -2276,6 +2294,14 @@ JSStructuredCloneReader::readHeader() + } + + MOZ_ALWAYS_TRUE(in.readPair(&tag, &data)); ++ if (data != uint32_t(JS::StructuredCloneScope::SameProcessSameThread) && ++ data != uint32_t(JS::StructuredCloneScope::SameProcessDifferentThread) && ++ data != uint32_t(JS::StructuredCloneScope::DifferentProcess)) ++ { ++ JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, ++ "invalid structured clone scope"); ++ return false; ++ } + storedScope = JS::StructuredCloneScope(data); + if (storedScope < allowedScope) { + JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, diff --git a/www/waterfox/files/patch-bug1425780 b/www/waterfox/files/patch-bug1425780 new file mode 100644 index 000000000000..9baec597a379 --- /dev/null +++ b/www/waterfox/files/patch-bug1425780 @@ -0,0 +1,34 @@ +commit e5fb39219394 +Author: Michael Froman <mfroman@mozilla.com> +Date: Thu Jan 11 21:38:36 2018 -0500 + + Bug 1425780 - Don't allow queue-jumping for gathering state change events. r=bwc, a=abillings + + --HG-- + extra : source : 2fa8c2b1c9917c035e0d9cc7f7b18549d67e5ade +--- + .../signaling/src/peerconnection/PeerConnectionImpl.cpp | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +index edb07486b45a..6f9d92cde978 100644 +--- media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp ++++ media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +@@ -3585,12 +3585,11 @@ PeerConnectionImpl::IceGatheringStateChange( + return; + } + WrappableJSErrorResult rv; +- RUN_ON_THREAD(mThread, +- WrapRunnable(pco, +- &PeerConnectionObserver::OnStateChange, +- PCObserverStateType::IceGatheringState, +- rv, static_cast<JSCompartment*>(nullptr)), +- NS_DISPATCH_NORMAL); ++ mThread->Dispatch(WrapRunnable(pco, ++ &PeerConnectionObserver::OnStateChange, ++ PCObserverStateType::IceGatheringState, ++ rv, static_cast<JSCompartment*>(nullptr)), ++ NS_DISPATCH_NORMAL); + + if (mIceGatheringState == PCImplIceGatheringState::Complete) { + SendLocalIceCandidateToContent(0, "", ""); diff --git a/www/waterfox/files/patch-bug1425878 b/www/waterfox/files/patch-bug1425878 new file mode 100644 index 000000000000..df6ee9a62de0 --- /dev/null +++ b/www/waterfox/files/patch-bug1425878 @@ -0,0 +1,46 @@ +commit 2aaf6edd31d6 +Author: Kartikaya Gupta <kgupta@mozilla.com> +Date: Mon Dec 18 13:33:56 2017 -0500 + + Bug 1425878 - Don't expose raw pointers to refcounted vsync dispatcher object. r=sotaro + + MozReview-Commit-ID: 5ywkZqfY8uZ + + --HG-- + extra : rebase_source : 3a887a5765fb0f7c2b5acdc8be94f3ea84199081 +--- + widget/nsBaseWidget.cpp | 5 +++-- + widget/nsBaseWidget.h | 2 +- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git widget/nsBaseWidget.cpp widget/nsBaseWidget.cpp +index e4ca5e011894..da7b7b259d8d 100644 +--- widget/nsBaseWidget.cpp ++++ widget/nsBaseWidget.cpp +@@ -1255,10 +1255,11 @@ void nsBaseWidget::CreateCompositorVsyncDispatcher() + } + } + +-CompositorVsyncDispatcher* ++already_AddRefed<CompositorVsyncDispatcher> + nsBaseWidget::GetCompositorVsyncDispatcher() + { +- return mCompositorVsyncDispatcher; ++ RefPtr<CompositorVsyncDispatcher> dispatcher = mCompositorVsyncDispatcher; ++ return dispatcher.forget(); + } + + already_AddRefed<LayerManager> +diff --git widget/nsBaseWidget.h widget/nsBaseWidget.h +index 3cb56f38b6ce..a7b648806bcc 100644 +--- widget/nsBaseWidget.h ++++ widget/nsBaseWidget.h +@@ -209,7 +209,7 @@ public: + // returned. + void NotifyCompositorSessionLost(mozilla::layers::CompositorSession* aSession); + +- mozilla::CompositorVsyncDispatcher* GetCompositorVsyncDispatcher(); ++ already_AddRefed<mozilla::CompositorVsyncDispatcher> GetCompositorVsyncDispatcher(); + void CreateCompositorVsyncDispatcher(); + virtual void CreateCompositor(); + virtual void CreateCompositor(int aWidth, int aHeight); diff --git a/www/waterfox/files/patch-bug1426042 b/www/waterfox/files/patch-bug1426042 new file mode 100644 index 000000000000..2176a6dd69bb --- /dev/null +++ b/www/waterfox/files/patch-bug1426042 @@ -0,0 +1,31 @@ +commit df0b53a2bec2 +Author: Jonathan Kew <jkew@mozilla.com> +Date: Fri Jan 5 13:58:51 2018 +0000 + + Bug 1426042 - Ensure we don't forget to set bidi data when required on a zero-length trailing frame. r=dholbert, a=gchang + + --HG-- + extra : source : a37695e59774af91ca8e9e50bee369364cf4feaa +--- + layout/base/nsBidiPresUtils.cpp | 7 +++++++ + layout/reftests/bidi/reftest.list | 2 +- + 2 files changed, 8 insertions(+), 1 deletion(-) + +diff --git layout/base/nsBidiPresUtils.cpp layout/base/nsBidiPresUtils.cpp +index 6ac7cf64afe9..3fa6a4e030c9 100644 +--- layout/base/nsBidiPresUtils.cpp ++++ layout/base/nsBidiPresUtils.cpp +@@ -888,6 +888,13 @@ nsBidiPresUtils::ResolveParagraph(BidiParagraphData* aBpd) + if (runLength <= 0) { + // Get the next run of text from the Bidi engine + if (++numRun >= runCount) { ++ // We've run out of runs of text; but don't forget to store bidi data ++ // to the frame before breaking out of the loop (bug 1426042). ++ storeBidiDataToFrame(); ++ if (isTextFrame) { ++ frame->AdjustOffsetsForBidi(contentOffset, ++ contentOffset + fragmentLength); ++ } + break; + } + int32_t lineOffset = logicalLimit; diff --git a/www/waterfox/files/patch-bug1426087 b/www/waterfox/files/patch-bug1426087 new file mode 100644 index 000000000000..abd09689e666 --- /dev/null +++ b/www/waterfox/files/patch-bug1426087 @@ -0,0 +1,80 @@ +commit 1b9a43c32852 +Author: Bob Owen <bobowencode@gmail.com> +Date: Fri Jan 12 10:17:36 2018 +0000 + + Bug 1426087 - Decrement nsDocumentViewer::mDestroyRefCount in a separate function. r=jwatt, a=ritu + + --HG-- + extra : source : 86d41b5efe074f6988085082df9ef537eee0813a +--- + layout/base/nsDocumentViewer.cpp | 7 ++++++- + layout/base/nsIDocumentViewerPrint.h | 2 ++ + layout/printing/nsPagePrintTimer.cpp | 10 ++-------- + 3 files changed, 10 insertions(+), 9 deletions(-) + +diff --git layout/base/nsDocumentViewer.cpp layout/base/nsDocumentViewer.cpp +index 4fe03d3f7f88..58690001ad73 100644 +--- layout/base/nsDocumentViewer.cpp ++++ layout/base/nsDocumentViewer.cpp +@@ -1665,7 +1665,6 @@ nsDocumentViewer::Destroy() + // We also keep the viewer from being cached in session history, since + // we require all documents there to be sanitized. + if (mDestroyRefCount != 0) { +- --mDestroyRefCount; + return NS_OK; + } + +@@ -4471,6 +4470,12 @@ nsDocumentViewer::IncrementDestroyRefCount() + ++mDestroyRefCount; + } + ++void ++nsDocumentViewer::DecrementDestroyRefCount() ++{ ++ --mDestroyRefCount; ++} ++ + //------------------------------------------------------------ + + #if defined(NS_PRINTING) && defined(NS_PRINT_PREVIEW) +diff --git layout/base/nsIDocumentViewerPrint.h layout/base/nsIDocumentViewerPrint.h +index 874ee31e5344..e6ac5318f20c 100644 +--- layout/base/nsIDocumentViewerPrint.h ++++ layout/base/nsIDocumentViewerPrint.h +@@ -42,6 +42,7 @@ public: + virtual mozilla::StyleSetHandle CreateStyleSet(nsIDocument* aDocument) = 0; + + virtual void IncrementDestroyRefCount() = 0; ++ virtual void DecrementDestroyRefCount() = 0; + + virtual void ReturnToGalleyPresentation() = 0; + +@@ -76,6 +77,7 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocumentViewerPrint, + bool GetIsPrintPreview() override; \ + mozilla::StyleSetHandle CreateStyleSet(nsIDocument* aDocument) override; \ + void IncrementDestroyRefCount() override; \ ++ void DecrementDestroyRefCount() override; \ + void ReturnToGalleyPresentation() override; \ + void OnDonePrinting() override; \ + bool IsInitializedForPrintPreview() override; \ +diff --git layout/printing/nsPagePrintTimer.cpp layout/printing/nsPagePrintTimer.cpp +index 2a29bc85111c..25458b95b3b0 100644 +--- layout/printing/nsPagePrintTimer.cpp ++++ layout/printing/nsPagePrintTimer.cpp +@@ -17,14 +17,8 @@ NS_IMPL_ISUPPORTS_INHERITED(nsPagePrintTimer, mozilla::Runnable, nsITimerCallbac + + nsPagePrintTimer::~nsPagePrintTimer() + { +- // "Destroy" the document viewer; this normally doesn't actually +- // destroy it because of the IncrementDestroyRefCount call below +- // XXX This is messy; the document viewer should use a single approach +- // to keep itself alive during printing +- nsCOMPtr<nsIContentViewer> cv(do_QueryInterface(mDocViewerPrint)); +- if (cv) { +- cv->Destroy(); +- } ++ // This matches the IncrementDestroyRefCount call in the constructor. ++ mDocViewerPrint->DecrementDestroyRefCount(); + } + + nsresult diff --git a/www/waterfox/files/patch-bug1426783 b/www/waterfox/files/patch-bug1426783 new file mode 100644 index 000000000000..9af341358dd3 --- /dev/null +++ b/www/waterfox/files/patch-bug1426783 @@ -0,0 +1,38 @@ +commit bd6f4255ac32 +Author: Jason Orendorff <jorendorff@mozilla.com> +Date: Fri Jan 5 15:17:35 2018 -0600 + + Bug 1426783 - Fix error handling in deserialization of invalid typed arrays. r=sfink, a=gchang. + + --HG-- + extra : source : f10263c3babef5f70e1e8fdb9e52c2de15cf22e1 + extra : intermediate-source : 3bda6eb9e8469ac4347bb9738d720ea81c358aea + extra : histedit_source : 9d203779ff057ed4e857fe31ba5b51d38f1547e5 +--- + js/src/vm/StructuredClone.cpp | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git js/src/vm/StructuredClone.cpp js/src/vm/StructuredClone.cpp +index c18cd232a192..e6623058459f 100644 +--- js/src/vm/StructuredClone.cpp ++++ js/src/vm/StructuredClone.cpp +@@ -2011,8 +2011,17 @@ JSStructuredCloneReader::readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, + { + MOZ_ASSERT(arrayType <= Scalar::Uint8Clamped); + +- uint32_t nbytes = nelems << TypedArrayShift(static_cast<Scalar::Type>(arrayType)); +- JSObject* obj = ArrayBufferObject::create(context(), nbytes); ++ mozilla::CheckedInt<size_t> nbytes = ++ mozilla::CheckedInt<size_t>(nelems) * ++ TypedArrayElemSize(static_cast<Scalar::Type>(arrayType)); ++ if (!nbytes.isValid() || nbytes.value() > UINT32_MAX) { ++ JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, ++ JSMSG_SC_BAD_SERIALIZED_DATA, ++ "invalid typed array size"); ++ return false; ++ } ++ ++ JSObject* obj = ArrayBufferObject::create(context(), nbytes.value()); + if (!obj) + return false; + vp.setObject(*obj); diff --git a/www/waterfox/files/patch-bug1426801 b/www/waterfox/files/patch-bug1426801 new file mode 100644 index 000000000000..daffea1109ea --- /dev/null +++ b/www/waterfox/files/patch-bug1426801 @@ -0,0 +1,38 @@ +commit 8ef1f1a717cc +Author: Andrew McCreight <continuation@gmail.com> +Date: Thu Jan 4 14:59:14 2018 -0800 + + Bug 1426801 - Clear gFirstIdleTask if we fail to dispatch the runnable. r=mrbkap, a=gchang + + MozReview-Commit-ID: 23f9VDTyyqg + + --HG-- + extra : source : 1eb22728208e6fc9c785e5cf11bb68929d0a555d +--- + dom/ipc/ContentChild.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git dom/ipc/ContentChild.cpp dom/ipc/ContentChild.cpp +index cc7769daa805..84881a36f04d 100644 +--- dom/ipc/ContentChild.cpp ++++ dom/ipc/ContentChild.cpp +@@ -1875,7 +1875,10 @@ ContentChild::RecvPBrowserConstructor(PBrowserChild* aActor, + MOZ_ASSERT(!gFirstIdleTask); + RefPtr<CancelableRunnable> firstIdleTask = NewCancelableRunnableFunction(FirstIdle); + gFirstIdleTask = firstIdleTask; +- NS_IdleDispatchToCurrentThread(firstIdleTask.forget()); ++ if (NS_FAILED(NS_IdleDispatchToCurrentThread(firstIdleTask.forget()))) { ++ gFirstIdleTask = nullptr; ++ hasRunOnce = false; ++ } + } + + return nsIContentChild::RecvPBrowserConstructor(aActor, +@@ -2397,6 +2400,7 @@ ContentChild::ActorDestroy(ActorDestroyReason why) + #else + if (gFirstIdleTask) { + gFirstIdleTask->Cancel(); ++ gFirstIdleTask = nullptr; + } + + nsHostObjectProtocolHandler::RemoveDataEntries(); diff --git a/www/waterfox/files/patch-bug1426869 b/www/waterfox/files/patch-bug1426869 new file mode 100644 index 000000000000..6a2327cdfb3c --- /dev/null +++ b/www/waterfox/files/patch-bug1426869 @@ -0,0 +1,25 @@ +commit 65d845f891a3 +Author: Jet Villegas <jvillegas@mozilla.com> +Date: Tue Jan 9 08:00:00 2018 +0200 + + Bug 1426869 - td.contenteditable=true focus breaks text selection. r=masayuki, a=RyanVM + + --HG-- + extra : source : b3118b4fae1372c3aa57caf4b16af9834ce46539 + extra : amend_source : 1187aa7d3d760aa60b974b874968aea4d0e09eea +--- + layout/generic/nsFrameSelection.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git layout/generic/nsFrameSelection.cpp layout/generic/nsFrameSelection.cpp +index c483622e1ffb..a60d69bf79e0 100644 +--- layout/generic/nsFrameSelection.cpp ++++ layout/generic/nsFrameSelection.cpp +@@ -1403,6 +1403,7 @@ nsFrameSelection::TakeFocus(nsIContent* aNewFocus, + + NS_ENSURE_STATE(mShell); + bool editableCell = false; ++ mCellParent = nullptr; + RefPtr<nsPresContext> context = mShell->GetPresContext(); + if (context) { + RefPtr<HTMLEditor> htmlEditor = nsContentUtils::GetHTMLEditor(context); diff --git a/www/waterfox/files/patch-bug1426996 b/www/waterfox/files/patch-bug1426996 new file mode 100644 index 000000000000..d047041de735 --- /dev/null +++ b/www/waterfox/files/patch-bug1426996 @@ -0,0 +1,29 @@ +commit 8b0d59fb74b5 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Tue Dec 26 21:47:22 2017 +0100 + + Bug 1426996 - Use fallible assign in NS_EscapeAndFilterURL r=kershaw a=gchang + + MozReview-Commit-ID: EKVeQb3cboU + + --HG-- + extra : source : 8af6e9af76052696204adb50eba2b9bdfe81c149 +--- + xpcom/io/nsEscape.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git xpcom/io/nsEscape.cpp xpcom/io/nsEscape.cpp +index 7d072399d3cc..d0ce3f649fce 100644 +--- xpcom/io/nsEscape.cpp ++++ xpcom/io/nsEscape.cpp +@@ -446,7 +446,9 @@ NS_EscapeAndFilterURL(const nsACString& aStr, uint32_t aFlags, + } + + if (!appended) { +- aResult = aStr; ++ if (!aResult.Assign(aStr, fallible)) { ++ return NS_ERROR_OUT_OF_MEMORY; ++ } + } + + return rv; diff --git a/www/waterfox/files/patch-bug1427118 b/www/waterfox/files/patch-bug1427118 new file mode 100644 index 000000000000..81203ab48c94 --- /dev/null +++ b/www/waterfox/files/patch-bug1427118 @@ -0,0 +1,84 @@ +commit 85ac1989f1c2 +Author: Lee Salzman <lsalzman@mozilla.com> +Date: Mon Feb 19 21:19:53 2018 -0500 + + Bug 1427118 - Make RecordedFontData use fallible allocations. r=milan, a=RyanVM + + MozReview-Commit-ID: 3YzhOyXvrv + + --HG-- + extra : source : a35fe8a4a82de45e10627b6fc760dd13d5df64a8 +--- + gfx/2d/RecordedEventImpl.h | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git gfx/2d/RecordedEventImpl.h gfx/2d/RecordedEventImpl.h +index bc1cec648302..0e8efb032cdf 100644 +--- gfx/2d/RecordedEventImpl.h ++++ gfx/2d/RecordedEventImpl.h +@@ -913,7 +913,7 @@ public: + , mType(aUnscaledFont->GetType()) + , mData(nullptr) + { +- mGetFontFileDataSucceeded = aUnscaledFont->GetFontFileData(&FontDataProc, this); ++ mGetFontFileDataSucceeded = aUnscaledFont->GetFontFileData(&FontDataProc, this) && mData; + } + + ~RecordedFontData(); +@@ -2518,11 +2518,12 @@ RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(S &aStream) + ReadElement(aStream, mRefPtr); + ReadElement(aStream, mSize); + ReadElement(aStream, mFormat); +- mData = (uint8_t*)new (fallible) char[mSize.width * mSize.height * BytesPerPixel(mFormat)]; ++ size_t size = mSize.width * mSize.height * BytesPerPixel(mFormat); ++ mData = new (fallible) uint8_t[size]; + if (!mData) { +- gfxWarning() << "RecordedSourceSurfaceCreation failed to allocate data"; ++ gfxCriticalNote << "RecordedSourceSurfaceCreation failed to allocate data of size " << size; + } else { +- aStream.read((char*)mData, mSize.width * mSize.height * BytesPerPixel(mFormat)); ++ aStream.read((char*)mData, size); + } + } + +@@ -2767,6 +2768,10 @@ RecordedFontData::~RecordedFontData() + inline bool + RecordedFontData::PlayEvent(Translator *aTranslator) const + { ++ if (!mData) { ++ return false; ++ } ++ + RefPtr<NativeFontResource> fontResource = + Factory::CreateNativeFontResource(mData, mFontDetails.size, + aTranslator->GetReferenceDrawTarget()->GetBackendType(), +@@ -2800,8 +2805,12 @@ RecordedFontData::OutputSimpleEventInfo(std::stringstream &aStringStream) const + inline void + RecordedFontData::SetFontData(const uint8_t *aData, uint32_t aSize, uint32_t aIndex) + { +- mData = new uint8_t[aSize]; +- memcpy(mData, aData, aSize); ++ mData = new (fallible) uint8_t[aSize]; ++ if (!mData) { ++ gfxCriticalNote << "RecordedFontData failed to allocate data for recording of size " << aSize; ++ } else { ++ memcpy(mData, aData, aSize); ++ } + mFontDetails.fontDataKey = + SFNTData::GetUniqueKey(aData, aSize, 0, nullptr); + mFontDetails.size = aSize; +@@ -2830,8 +2839,12 @@ RecordedFontData::RecordedFontData(S &aStream) + ReadElement(aStream, mType); + ReadElement(aStream, mFontDetails.fontDataKey); + ReadElement(aStream, mFontDetails.size); +- mData = new uint8_t[mFontDetails.size]; +- aStream.read((char*)mData, mFontDetails.size); ++ mData = new (fallible) uint8_t[mFontDetails.size]; ++ if (!mData) { ++ gfxCriticalNote << "RecordedFontData failed to allocate data for playback of size " << mFontDetails.size; ++ } else { ++ aStream.read((char*)mData, mFontDetails.size); ++ } + } + + inline diff --git a/www/waterfox/files/patch-bug1427126 b/www/waterfox/files/patch-bug1427126 new file mode 100644 index 000000000000..6798217a66ad --- /dev/null +++ b/www/waterfox/files/patch-bug1427126 @@ -0,0 +1,25 @@ +commit 5b96c327f3f0 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Tue Jan 9 16:37:12 2018 -0500 + + Bug 1427126 - Use setElementWithType instead of setElement in AppendToList. r=bhackett, a=gchang + + --HG-- + extra : source : 6be5a45a855e2af656477c53ee1d6f9a9f518212 +--- + js/src/vm/List-inl.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git js/src/builtin/Stream.cpp js/src/builtin/Stream.cpp +index 8860c080b3b5..f9dd08642e65 100644 +--- js/src/builtin/Stream.cpp ++++ js/src/builtin/Stream.cpp +@@ -334,7 +334,7 @@ AppendToList(JSContext* cx, HandleNativeObject list, HandleValue value) + return false; + + list->ensureDenseInitializedLength(cx, length, 1); +- list->setDenseElement(length, value); ++ list->setDenseElementWithType(cx, length, value); + + return true; + } diff --git a/www/waterfox/files/patch-bug1427480 b/www/waterfox/files/patch-bug1427480 new file mode 100644 index 000000000000..006efc4dec24 --- /dev/null +++ b/www/waterfox/files/patch-bug1427480 @@ -0,0 +1,40 @@ +commit ce0b5382185d +Author: Jonathan Kew <jkew@mozilla.com> +Date: Tue Mar 20 18:02:18 2018 +0000 + + Bug 1427480 - Increase the MAX_FONT_SIZE limit applied in cairo_ft_font to match the gfxFont size limit. r=lsalzman, a=RyanVM + + --HG-- + extra : source : 74ffac5bc156c537ff4b1cc3d98dbb2c61b3127d + extra : histedit_source : ee241f50804b89b4d545aedc5503cf0cb7c767f7 +--- + gfx/cairo/cairo/src/cairo-ft-font.c | 2 +- + gfx/cairo/max-font-size.patch | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git gfx/cairo/cairo/src/cairo-ft-font.c gfx/cairo/cairo/src/cairo-ft-font.c +index 9d0e4951a28e..56430740a20c 100644 +--- gfx/cairo/cairo/src/cairo-ft-font.c ++++ gfx/cairo/cairo/src/cairo-ft-font.c +@@ -103,7 +103,7 @@ static setLcdFilterFunc setLcdFilter; + #define MAX_OPEN_FACES 10 + /* This is the maximum font size we allow to be passed to FT_Set_Char_Size + */ +-#define MAX_FONT_SIZE 1000 ++#define MAX_FONT_SIZE 2000 + + extern FT_Face mozilla_NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex); + extern FT_Face mozilla_NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex); +diff --git gfx/cairo/max-font-size.patch gfx/cairo/max-font-size.patch +index 99be23906ab4..efa54cef646a 100644 +--- gfx/cairo/max-font-size.patch ++++ gfx/cairo/max-font-size.patch +@@ -8,7 +8,7 @@ diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft- + + + +/* This is the maximum font size we allow to be passed to FT_Set_Char_Size + + */ +-+#define MAX_FONT_SIZE 1000 +++#define MAX_FONT_SIZE 2000 + + /* + * The simple 2x2 matrix is converted into separate scale and shape diff --git a/www/waterfox/files/patch-bug1428589 b/www/waterfox/files/patch-bug1428589 new file mode 100644 index 000000000000..d723bd4f1703 --- /dev/null +++ b/www/waterfox/files/patch-bug1428589 @@ -0,0 +1,50 @@ +commit 671dccb84a84 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Sun Jan 7 01:10:10 2018 +0100 + + Bug 1428589: Correctly handle expiring all the cookies in an entry. r=jdm + + MozReview-Commit-ID: 6qaC9yclvP2 +--- + netwerk/cookie/nsCookieService.cpp | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git netwerk/cookie/nsCookieService.cpp netwerk/cookie/nsCookieService.cpp +index b73aaa2129e3..672ca06be628 100644 +--- netwerk/cookie/nsCookieService.cpp ++++ netwerk/cookie/nsCookieService.cpp +@@ -4469,8 +4469,9 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec) + for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) { + nsCookieEntry* entry = iter.Get(); + +- const nsCookieEntry::ArrayType &cookies = entry->GetCookies(); +- for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ) { ++ const nsCookieEntry::ArrayType& cookies = entry->GetCookies(); ++ auto length = cookies.Length(); ++ for (nsCookieEntry::IndexType i = 0; i < length; ) { + nsListIter iter(entry, i); + nsCookie* cookie = cookies[i]; + +@@ -4479,9 +4480,12 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec) + removedList->AppendElement(cookie); + COOKIE_LOGEVICTED(cookie, "Cookie expired"); + +- // remove from list; do not increment our iterator ++ // remove from list; do not increment our iterator, but stop if we're ++ // done already. + gCookieService->RemoveCookieFromList(iter, paramsArray); +- ++ if (i == --length) { ++ break; ++ } + } else { + // check if the cookie is over the age limit + if (cookie->LastAccessed() <= purgeTime) { +@@ -4494,6 +4498,7 @@ nsCookieService::PurgeCookies(int64_t aCurrentTimeInUsec) + + ++i; + } ++ MOZ_ASSERT(length == cookies.Length()); + } + } + diff --git a/www/waterfox/files/patch-bug1428612 b/www/waterfox/files/patch-bug1428612 new file mode 100644 index 000000000000..c541459aaa19 --- /dev/null +++ b/www/waterfox/files/patch-bug1428612 @@ -0,0 +1,69 @@ +commit 2bfc5ca48a44 +Author: Eric Rahm <erahm@mozilla.com> +Date: Wed Jan 17 16:38:18 2018 -0800 + + Bug 1428612 - Part 1: Use nsLiteralCString to wrap histogram names. r=gfritzsche a=lizzard + + This switches from `nsDependentCString` to `nsLiteralCString` when adding + histograms to the table. It will help save some memory and should avoid the OOM + smalls we have been seeing. + + --HG-- + extra : source : 13493806c0472ebd52ab4140312747c5fbd42fbc +--- + toolkit/components/telemetry/TelemetryHistogram.cpp | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git toolkit/components/telemetry/TelemetryHistogram.cpp toolkit/components/telemetry/TelemetryHistogram.cpp +index a90e5d24aab8..eb28684fe4d1 100644 +--- toolkit/components/telemetry/TelemetryHistogram.cpp ++++ toolkit/components/telemetry/TelemetryHistogram.cpp +@@ -1740,9 +1740,14 @@ void TelemetryHistogram::InitializeGlobalState(bool canRecordBase, + // declaration point further up in this file. + + // Populate the static histogram name->id cache. +- // Note that the histogram names are statically allocated. ++ // Note that the histogram names come from a static table so we can wrap them ++ // in a literal string to avoid allocations when it gets copied. + for (uint32_t i = 0; i < HistogramCount; i++) { +- gNameToHistogramIDMap.Put(nsDependentCString(gHistogramInfos[i].name()), HistogramID(i)); ++ auto name = gHistogramInfos[i].name(); ++ ++ nsCString wrappedName; ++ wrappedName.AssignLiteral(name, strlen(name)); ++ gNameToHistogramIDMap.Put(wrappedName, HistogramID(i)); + } + + #ifdef DEBUG + +commit e31ac19b6163 +Author: Eric Rahm <erahm@mozilla.com> +Date: Wed Jan 17 16:52:37 2018 -0800 + + Bug 1428612 - Part 2: Add an assertion to check the histogram name pointer. r=gfritzsche a=lizzard + + This adds a dignostic assertion that the name pointer is actually within the + static name table. + + --HG-- + extra : source : 6931047d462f46b1f601cb5927e4185857400a63 +--- + toolkit/components/telemetry/TelemetryHistogram.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git toolkit/components/telemetry/TelemetryHistogram.cpp toolkit/components/telemetry/TelemetryHistogram.cpp +index eb28684fe4d1..926536e401b4 100644 +--- toolkit/components/telemetry/TelemetryHistogram.cpp ++++ toolkit/components/telemetry/TelemetryHistogram.cpp +@@ -1745,6 +1745,11 @@ void TelemetryHistogram::InitializeGlobalState(bool canRecordBase, + for (uint32_t i = 0; i < HistogramCount; i++) { + auto name = gHistogramInfos[i].name(); + ++ // Make sure the name pointer is in a valid region. See bug 1428612. ++ MOZ_DIAGNOSTIC_ASSERT(name >= gHistogramStringTable); ++ MOZ_DIAGNOSTIC_ASSERT( ++ uintptr_t(name) < (uintptr_t(gHistogramStringTable) + sizeof(gHistogramStringTable))); ++ + nsCString wrappedName; + wrappedName.AssignLiteral(name, strlen(name)); + gNameToHistogramIDMap.Put(wrappedName, HistogramID(i)); diff --git a/www/waterfox/files/patch-bug1429373 b/www/waterfox/files/patch-bug1429373 new file mode 100644 index 000000000000..e06759dbcd27 --- /dev/null +++ b/www/waterfox/files/patch-bug1429373 @@ -0,0 +1,142 @@ +commit e98ed2368b14 +Author: Botond Ballo <botond@mozilla.com> +Date: Wed Jan 17 18:46:07 2018 -0500 + + Bug 1429373 - Add a clarifying comment to the declaration of APZCTreeManager::SetTargetAPZC(). r=kats, a=lizzard + + MozReview-Commit-ID: CT1H5TH3UXn + + --HG-- + extra : source : 7acde19831d806ea2b27f19fc0de164272a8d691 +--- + gfx/layers/apz/src/APZCTreeManager.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git gfx/layers/apz/src/APZCTreeManager.h gfx/layers/apz/src/APZCTreeManager.h +index bcc84bac3a97..b4a92f07d4c5 100644 +--- gfx/layers/apz/src/APZCTreeManager.h ++++ gfx/layers/apz/src/APZCTreeManager.h +@@ -267,6 +267,13 @@ public: + * for the different touch points. In the case where the touch point has no + * target, or the target is not a scrollable frame, the target's |mScrollId| + * should be set to FrameMetrics::NULL_SCROLL_ID. ++ * Note: For mouse events that start a scrollbar drag, both SetTargetAPZC() ++ * and StartScrollbarDrag() will be called, and the calls may happen ++ * in either order. That's fine - whichever arrives first will confirm ++ * the block, and StartScrollbarDrag() will fill in the drag metrics. ++ * If the block is confirmed before we have drag metrics, some events ++ * in the drag block may be handled as no-ops until the drag metrics ++ * arrive. + */ + void SetTargetAPZC( + uint64_t aInputBlockId, +commit ed5f41305349 +Author: Botond Ballo <botond@mozilla.com> +Date: Wed Jan 17 18:45:25 2018 -0500 + + Bug 1429373 - During hit-testing, ignore clips on layers whose parent has a perspective transform. r=kats, a=lizzard + + This corresponds to the treatment of such layers in AsyncCompositionManager + added in bug 1168263. + + MozReview-Commit-ID: 34IKk5TH9vV + + --HG-- + extra : source : 5b0b60dd22e8f33634d9b0e425cad64b898b8500 +--- + gfx/layers/apz/src/APZCTreeManager.cpp | 25 ++++++++++++++++++++----- + 1 file changed, 20 insertions(+), 5 deletions(-) + +diff --git gfx/layers/apz/src/APZCTreeManager.cpp gfx/layers/apz/src/APZCTreeManager.cpp +index 2dfa9a3250b8..46f969d0fc7a 100644 +--- gfx/layers/apz/src/APZCTreeManager.cpp ++++ gfx/layers/apz/src/APZCTreeManager.cpp +@@ -97,6 +97,10 @@ struct APZCTreeManager::TreeBuildingState { + // to facilitate re-using the same APZC for different layers that scroll + // together (and thus have the same ScrollableLayerGuid). + std::unordered_map<ScrollableLayerGuid, AsyncPanZoomController*, ScrollableLayerGuidHash> mApzcMap; ++ ++ // As the tree is traversed, the top element of this stack tracks whether ++ // the parent scroll node has a perspective transform. ++ std::stack<bool> mParentHasPerspective; + }; + + class APZCTreeManager::CheckerboardFlushObserver : public nsIObserver { +@@ -321,6 +325,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId, + HitTestingTreeNode* next = nullptr; + uint64_t layersId = aRootLayerTreeId; + ancestorTransforms.push(Matrix4x4()); ++ state.mParentHasPerspective.push(false); + + state.mLayersIdsToDestroy.erase(aRootLayerTreeId); + +@@ -371,6 +376,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId, + } + + indents.push(gfx::TreeAutoIndent(mApzcTreeLog)); ++ state.mParentHasPerspective.push(aLayerMetrics.TransformIsPerspective()); + }, + [&](ScrollNode aLayerMetrics) + { +@@ -379,6 +385,7 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId, + layersId = next->GetLayersId(); + ancestorTransforms.pop(); + indents.pop(); ++ state.mParentHasPerspective.pop(); + }); + + mApzcTreeLog << "[end]\n"; +@@ -715,6 +722,8 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + needsApzc = false; + } + ++ bool parentHasPerspective = aState.mParentHasPerspective.top(); ++ + RefPtr<HitTestingTreeNode> node = nullptr; + if (!needsApzc) { + // Note: if layer properties must be propagated to nodes, RecvUpdate in +@@ -726,7 +735,9 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + GetEventRegions(aLayer), + aLayer.GetVisibleRegion(), + aLayer.GetTransformTyped(), +- aLayer.GetClipRect() ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) : Nothing(), ++ (!parentHasPerspective && aLayer.GetClipRect()) ++ ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) ++ : Nothing(), + GetEventRegionsOverride(aParent, aLayer)); + node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(), + aLayer.GetScrollbarAnimationId(), +@@ -833,12 +844,14 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + // or not, depending on whether it went through the newApzc branch above. + MOZ_ASSERT(node->IsPrimaryHolder() && node->GetApzc() && node->GetApzc()->Matches(guid)); + +- ParentLayerIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer); ++ Maybe<ParentLayerIntRegion> clipRegion = parentHasPerspective ++ ? Nothing() ++ : Some(ComputeClipRegion(state->mController, aLayer)); + node->SetHitTestData( + GetEventRegions(aLayer), + aLayer.GetVisibleRegion(), + aLayer.GetTransformTyped(), +- Some(clipRegion), ++ clipRegion, + GetEventRegionsOverride(aParent, aLayer)); + apzc->SetAncestorTransform(aAncestorTransform); + +@@ -910,12 +923,14 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + // instead of an exact one. + MOZ_ASSERT(aAncestorTransform.FuzzyEqualsMultiplicative(apzc->GetAncestorTransform())); + +- ParentLayerIntRegion clipRegion = ComputeClipRegion(state->mController, aLayer); ++ Maybe<ParentLayerIntRegion> clipRegion = parentHasPerspective ++ ? Nothing() ++ : Some(ComputeClipRegion(state->mController, aLayer)); + node->SetHitTestData( + GetEventRegions(aLayer), + aLayer.GetVisibleRegion(), + aLayer.GetTransformTyped(), +- Some(clipRegion), ++ clipRegion, + GetEventRegionsOverride(aParent, aLayer)); + } + diff --git a/www/waterfox/files/patch-bug1429666 b/www/waterfox/files/patch-bug1429666 new file mode 100644 index 000000000000..52a2ad5389ed --- /dev/null +++ b/www/waterfox/files/patch-bug1429666 @@ -0,0 +1,212 @@ +commit d16cbc0c61b1 +Author: Karl Tomlinson <karlt+@karlt.net> +Date: Thu Jan 11 13:30:24 2018 +1300 + + bug 1429666 cubeb_resampler_speex: don't call data callback while draining r=padenot a=gchang + + MozReview-Commit-ID: 1XEzZjPGai9 + + --HG-- + extra : source : 1ad55edca07d6706bdec5314724fd2361def43c3 +--- + media/libcubeb/README_MOZILLA | 8 +++-- + media/libcubeb/gtest/test_resampler.cpp | 15 ++++---- + media/libcubeb/src/cubeb_resampler.cpp | 51 +++++++++++++++++---------- + media/libcubeb/src/cubeb_resampler_internal.h | 9 ++--- + 4 files changed, 53 insertions(+), 30 deletions(-) + +diff --git media/libcubeb/README_MOZILLA media/libcubeb/README_MOZILLA +index 506d2dc5434b..44d36b45c500 100644 +--- media/libcubeb/README_MOZILLA ++++ media/libcubeb/README_MOZILLA +@@ -1,7 +1,11 @@ + The source from this directory was copied from the cubeb + git repository using the update.sh script. The only changes +-made were those applied by update.sh and the addition of +-Makefile.in build files for the Mozilla build system. ++made were those applied by update.sh, the addition of ++Makefile.in build files for the Mozilla build system, ++and the following patches, which may be overwritten when ++included upstream. ++https://github.com/kinetiknz/cubeb/pull/398/commits/c8e66dee61a35e6a6d54e3630e1668bdbd6984b4 ++https://github.com/kinetiknz/cubeb/pull/398/commits/2ed979bc891cf1a7822799947a357d4d3b625964 + + The cubeb git repository is: git://github.com/kinetiknz/cubeb.git + +diff --git media/libcubeb/gtest/test_resampler.cpp media/libcubeb/gtest/test_resampler.cpp +index 3eebce950845..1f5fb8f9e14c 100644 +--- media/libcubeb/gtest/test_resampler.cpp ++++ media/libcubeb/gtest/test_resampler.cpp +@@ -497,13 +497,15 @@ TEST(cubeb, resampler_output_only_noop) + cubeb_resampler_destroy(resampler); + } + +-long test_drain_data_cb(cubeb_stream * /*stm*/, void * /*user_ptr*/, ++long test_drain_data_cb(cubeb_stream * /*stm*/, void * user_ptr, + const void * input_buffer, + void * output_buffer, long frame_count) + { + EXPECT_TRUE(output_buffer); + EXPECT_TRUE(!input_buffer); +- return frame_count - 10; ++ auto cb_count = static_cast<int *>(user_ptr); ++ (*cb_count)++; ++ return frame_count - 1; + } + + TEST(cubeb, resampler_drain) +@@ -515,10 +517,11 @@ TEST(cubeb, resampler_drain) + output_params.channels = 1; + output_params.format = CUBEB_SAMPLE_FLOAT32NE; + target_rate = 48000; ++ int cb_count = 0; + + cubeb_resampler * resampler = + cubeb_resampler_create((cubeb_stream*)nullptr, nullptr, &output_params, target_rate, +- test_drain_data_cb, nullptr, ++ test_drain_data_cb, &cb_count, + CUBEB_RESAMPLER_QUALITY_VOIP); + + const long out_frames = 128; +@@ -530,9 +533,9 @@ TEST(cubeb, resampler_drain) + out_buffer, out_frames); + } while (got == out_frames); + +- /* If the above is not an infinite loop, the drain was a success, just mark +- * this test as such. */ +- ASSERT_TRUE(true); ++ /* The callback should be called once but not again after returning < ++ * frame_count. */ ++ ASSERT_EQ(cb_count, 1); + + cubeb_resampler_destroy(resampler); + } +diff --git media/libcubeb/src/cubeb_resampler.cpp media/libcubeb/src/cubeb_resampler.cpp +index 6002bd2161a9..fcccede28e2d 100644 +--- media/libcubeb/src/cubeb_resampler.cpp ++++ media/libcubeb/src/cubeb_resampler.cpp +@@ -145,26 +145,32 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> + assert(!input_buffer && (!input_frames_count || *input_frames_count == 0) && + output_buffer && output_frames_needed); + +- long got = 0; +- T * out_unprocessed = nullptr; +- long output_frames_before_processing = 0; ++ if (!draining) { ++ long got = 0; ++ T * out_unprocessed = nullptr; ++ long output_frames_before_processing = 0; + +- /* fill directly the input buffer of the output processor to save a copy */ +- output_frames_before_processing = +- output_processor->input_needed_for_output(output_frames_needed); ++ /* fill directly the input buffer of the output processor to save a copy */ ++ output_frames_before_processing = ++ output_processor->input_needed_for_output(output_frames_needed); + +- out_unprocessed = +- output_processor->input_buffer(output_frames_before_processing); ++ out_unprocessed = ++ output_processor->input_buffer(output_frames_before_processing); + +- got = data_callback(stream, user_ptr, +- nullptr, out_unprocessed, +- output_frames_before_processing); ++ got = data_callback(stream, user_ptr, ++ nullptr, out_unprocessed, ++ output_frames_before_processing); + +- if (got < 0) { +- return got; +- } ++ if (got < output_frames_before_processing) { ++ draining = true; + +- output_processor->written(got); ++ if (got < 0) { ++ return got; ++ } ++ } ++ ++ output_processor->written(got); ++ } + + /* Process the output. If not enough frames have been returned from the + * callback, drain the processors. */ +@@ -204,11 +210,16 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> + ::fill_internal_duplex(T * in_buffer, long * input_frames_count, + T * out_buffer, long output_frames_needed) + { ++ if (draining) { ++ // discard input and drain any signal remaining in the resampler. ++ return output_processor->output(out_buffer, output_frames_needed); ++ } ++ + /* The input data, after eventual resampling. This is passed to the callback. */ + T * resampled_input = nullptr; + /* The output buffer passed down in the callback, that might be resampled. */ + T * out_unprocessed = nullptr; +- size_t output_frames_before_processing = 0; ++ long output_frames_before_processing = 0; + /* The number of frames returned from the callback. */ + long got = 0; + +@@ -243,8 +254,12 @@ cubeb_resampler_speex<T, InputProcessor, OutputProcessor> + resampled_input, out_unprocessed, + output_frames_before_processing); + +- if (got < 0) { +- return got; ++ if (got < output_frames_before_processing) { ++ draining = true; ++ ++ if (got < 0) { ++ return got; ++ } + } + + output_processor->written(got); +diff --git media/libcubeb/src/cubeb_resampler_internal.h media/libcubeb/src/cubeb_resampler_internal.h +index ca08ec571422..fb69992ff159 100644 +--- media/libcubeb/src/cubeb_resampler_internal.h ++++ media/libcubeb/src/cubeb_resampler_internal.h +@@ -62,11 +62,11 @@ public: + : channels(channels) + {} + protected: +- size_t frames_to_samples(size_t frames) ++ size_t frames_to_samples(size_t frames) const + { + return frames * channels; + } +- size_t samples_to_frames(size_t samples) ++ size_t samples_to_frames(size_t samples) const + { + assert(!(samples % channels)); + return samples / channels; +@@ -157,6 +157,7 @@ private: + cubeb_stream * const stream; + const cubeb_data_callback data_callback; + void * const user_ptr; ++ bool draining = false; + }; + + /** Handles one way of a (possibly) duplex resampler, working on interleaved +@@ -282,7 +283,7 @@ public: + * exactly `output_frame_count` resampled frames. This can return a number + * slightly bigger than what is strictly necessary, but it guaranteed that the + * number of output frames will be exactly equal. */ +- uint32_t input_needed_for_output(uint32_t output_frame_count) ++ uint32_t input_needed_for_output(uint32_t output_frame_count) const + { + int32_t unresampled_frames_left = samples_to_frames(resampling_in_buffer.length()); + int32_t resampled_frames_left = samples_to_frames(resampling_out_buffer.length()); +@@ -461,7 +462,7 @@ public: + * @parameter frames_needed the number of frames one want to write into the + * delay_line + * @returns the number of frames one will get. */ +- size_t input_needed_for_output(uint32_t frames_needed) ++ size_t input_needed_for_output(uint32_t frames_needed) const + { + return frames_needed; + } diff --git a/www/waterfox/files/patch-bug1429764 b/www/waterfox/files/patch-bug1429764 new file mode 100644 index 000000000000..112692fd51ee --- /dev/null +++ b/www/waterfox/files/patch-bug1429764 @@ -0,0 +1,207 @@ +commit 6a927d435699 +Author: Tom Ritter <tom@mozilla.com> +Date: Fri Jan 12 13:36:04 2018 -0600 + + Bug 1429764 - Do not call ReduceTimerPrecision twice for DOM Navigation timers. r=bkelly, r=timhuang, a=jcristau + + Bug 1429764 details a test failure that was asserting that the performance navigation + timers were strictly increasing (or equal). fetchStart should have a timestamp before + domainLookupStart. But it didn't. + + The problem is two-fold. This corrects the test and the issue by addressing one part + of the problem, the second part of the problem needs to be written up in a new bug + and addressed there. (That bug is not yet filed at writing, but see dependencies of + 1429764 in the future to find it.) + + The second, and underlying, problem is that calling ReduceTimerPrecision with the + same value multiple times may continually reduce it. Meaning that the first you call + it with, say, .75, (and a precision of .20), it will be reduced to .6. The second time + you call it (with .6), instead of staying at .6 it will be reduced to .4. This is + because floats are fuzzy. Inside ReduceTimerPrecision we are multiplying a decimal by + a decimal, so while floor(.6 / .20) should equal 3, sometimes it's actually 2.999... + which gets floors to 2, gets multiplied again by .2, and which results in .4 + + If that's the underlying problem, the first, and surface, problem is - why are we + calling ReduceTimerPrecision multiple times? We shouldn't be. That's what this + patch fixes. + + TimeStampToDOMHighResOrFetchStart will return either TimeStampToDOMHighRes() or + FetchStartHighRes(). FetchStartHighRes() internally calls TimeStampToDOMHighRes + and then ReduceTimerPrecision - this is where (some of) the two reduction calls + happen - because TimeStampToDOMHighRes itself calls ReduceTimerPrecision also. + + I remove the ReduceTimerPrecision from TimeStampToDOMHighRes. FetchStartHighRes + will now only call ReduceTimerPrecision once, at the end of the return. + + But we have to fix places we call TimeStampToDOMHighResOrFetchStart, because the + callers of that function also call ReduceTimerPrecision. So if + TimeStampToDOMHighResOrFetchStart returned FetchStartHighRes, we'd be calling + ReduceTimerPrecision twice for those callers. + + So inside first off, we remove the outer call to ReduceTimerPrecision. that + surrounds the 5 or so callsites of TimeStampToDOMHighResOrFetchStart. Then + inside of TimeStampToDOMHighResOrFetchStart we return either FetchStartHighRes + (which is has already called ReduceTimerPrecision) or we call + ReduceTimerPrecision with the value. + + Now. TimeStampToDOMHighRes was used in more places than just FetchStartHighRes - + there were several other places where we were doing double rounding, and this + fixed those as well. AsyncOpenHighRes, WorkerStartHighRes, DomainLookupEndHighRes, + ConnectStartHighRes, SecureConnectionStartHighRes, ConnectEndHighRes, and + ResponseEndHighRes. + + MozReview-Commit-ID: K5nHql135rb + + --HG-- + extra : source : 17bf5819b42fa3b656f2d3c565bc4fb0ca050066 +--- + dom/performance/PerformanceTiming.cpp | 15 +++------ + dom/performance/PerformanceTiming.h | 7 ++-- + .../resistfingerprinting/nsRFPService.cpp | 38 +++++++++++++++++++--- + 3 files changed, 42 insertions(+), 18 deletions(-) + +diff --git dom/performance/PerformanceTiming.cpp dom/performance/PerformanceTiming.cpp +index 3d7e55a0c80f..f80d7f509a40 100644 +--- dom/performance/PerformanceTiming.cpp ++++ dom/performance/PerformanceTiming.cpp +@@ -222,7 +222,7 @@ PerformanceTiming::RedirectStartHighRes() + nsContentUtils::ShouldResistFingerprinting()) { + return mZeroTime; + } +- return TimeStampToDOMHighResOrFetchStart(mRedirectStart); ++ return TimeStampToReducedDOMHighResOrFetchStart(mRedirectStart); + } + + DOMTimeMilliSec +@@ -256,7 +256,7 @@ PerformanceTiming::RedirectEndHighRes() + nsContentUtils::ShouldResistFingerprinting()) { + return mZeroTime; + } +- return TimeStampToDOMHighResOrFetchStart(mRedirectEnd); ++ return TimeStampToReducedDOMHighResOrFetchStart(mRedirectEnd); + } + + DOMTimeMilliSec +@@ -280,7 +280,7 @@ PerformanceTiming::DomainLookupStartHighRes() + nsContentUtils::ShouldResistFingerprinting()) { + return mZeroTime; + } +- return TimeStampToDOMHighResOrFetchStart(mDomainLookupStart); ++ return TimeStampToReducedDOMHighResOrFetchStart(mDomainLookupStart); + } + + DOMTimeMilliSec +@@ -366,7 +366,7 @@ PerformanceTiming::RequestStartHighRes() + nsContentUtils::ShouldResistFingerprinting()) { + return mZeroTime; + } +- return TimeStampToDOMHighResOrFetchStart(mRequestStart); ++ return TimeStampToReducedDOMHighResOrFetchStart(mRequestStart); + } + + DOMTimeMilliSec +@@ -386,7 +386,7 @@ PerformanceTiming::ResponseStartHighRes() + (!mCacheReadStart.IsNull() && mCacheReadStart < mResponseStart)) { + mResponseStart = mCacheReadStart; + } +- return TimeStampToDOMHighResOrFetchStart(mResponseStart); ++ return TimeStampToReducedDOMHighResOrFetchStart(mResponseStart); + } + + DOMTimeMilliSec +diff --git dom/performance/PerformanceTiming.h dom/performance/PerformanceTiming.h +index 0558fc11d64e..9fba3210ef1d 100644 +--- dom/performance/PerformanceTiming.h ++++ dom/performance/PerformanceTiming.h +@@ -68,10 +68,10 @@ public: + * page), if the given TimeStamp is valid. Otherwise, it will return + * the FetchStart timing value. + */ +- inline DOMHighResTimeStamp TimeStampToDOMHighResOrFetchStart(TimeStamp aStamp) ++ inline DOMHighResTimeStamp TimeStampToReducedDOMHighResOrFetchStart(TimeStamp aStamp) + { + return (!aStamp.IsNull()) +- ? TimeStampToDOMHighRes(aStamp) ++ ? nsRFPService::ReduceTimePrecisionAsMSecs(TimeStampToDOMHighRes(aStamp)) + : FetchStartHighRes(); + } + +diff --git toolkit/components/resistfingerprinting/nsRFPService.cpp toolkit/components/resistfingerprinting/nsRFPService.cpp +index 51552da69923..98857a764721 100644 +--- toolkit/components/resistfingerprinting/nsRFPService.cpp ++++ toolkit/components/resistfingerprinting/nsRFPService.cpp +@@ -8,6 +8,7 @@ + #include <time.h> + + #include "mozilla/ClearOnShutdown.h" ++#include "mozilla/Logging.h" + #include "mozilla/Preferences.h" + #include "mozilla/Services.h" + #include "mozilla/StaticPtr.h" +@@ -28,6 +29,10 @@ + + using namespace mozilla; + ++#ifdef DEBUG ++static mozilla::LazyLogModule gResistFingerprintingLog("nsResistFingerprinting"); ++#endif ++ + #define RESIST_FINGERPRINTING_PREF "privacy.resistFingerprinting" + #define PROFILE_INITIALIZED_TOPIC "profile-initial-state" + +@@ -66,7 +71,13 @@ nsRFPService::ReduceTimePrecisionAsMSecs(double aTime) + return aTime; + } + const double resolutionMSec = kResolutionUSec / 1000.0; +- return floor(aTime / resolutionMSec) * resolutionMSec; ++ double ret = floor(aTime / resolutionMSec) * resolutionMSec; ++#if defined(DEBUG) ++ MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose, ++ ("Given: %.*f, Rounding with %.*f, Intermediate: %.*f, Got: %.*f", ++ DBL_DIG-1, aTime, DBL_DIG-1, resolutionMSec, DBL_DIG-1, floor(aTime / resolutionMSec), DBL_DIG-1, ret)); ++#endif ++ return ret; + } + + /* static */ +@@ -76,7 +87,14 @@ nsRFPService::ReduceTimePrecisionAsUSecs(double aTime) + if (!IsResistFingerprintingEnabled()) { + return aTime; + } +- return floor(aTime / kResolutionUSec) * kResolutionUSec; ++ double ret = floor(aTime / kResolutionUSec) * kResolutionUSec; ++#if defined(DEBUG) ++ double tmp_kResolutionUSec = kResolutionUSec; ++ MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose, ++ ("Given: %.*f, Rounding with %.*f, Intermediate: %.*f, Got: %.*f", ++ DBL_DIG-1, aTime, DBL_DIG-1, tmp_kResolutionUSec, DBL_DIG-1, floor(aTime / tmp_kResolutionUSec), DBL_DIG-1, ret)); ++#endif ++ return ret; + } + + /* static */ +@@ -90,10 +108,22 @@ nsRFPService::ReduceTimePrecisionAsSecs(double aTime) + // The resolution is smaller than one sec. Use the reciprocal to avoid + // floating point error. + const double resolutionSecReciprocal = 1000000.0 / kResolutionUSec; +- return floor(aTime * resolutionSecReciprocal) / resolutionSecReciprocal; ++ double ret = floor(aTime * resolutionSecReciprocal) / resolutionSecReciprocal; ++#if defined(DEBUG) ++ MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose, ++ ("Given: %.*f, Reciprocal Rounding with %.*f, Intermediate: %.*f, Got: %.*f", ++ DBL_DIG-1, aTime, DBL_DIG-1, resolutionSecReciprocal, DBL_DIG-1, floor(aTime * resolutionSecReciprocal), DBL_DIG-1, ret)); ++#endif ++ return ret; + } + const double resolutionSec = kResolutionUSec / 1000000.0; +- return floor(aTime / resolutionSec) * resolutionSec; ++ double ret = floor(aTime / resolutionSec) * resolutionSec; ++#if defined(DEBUG) ++ MOZ_LOG(gResistFingerprintingLog, LogLevel::Verbose, ++ ("Given: %.*f, Rounding with %.*f, Intermediate: %.*f, Got: %.*f", ++ DBL_DIG-1, aTime, DBL_DIG-1, resolutionSec, DBL_DIG-1, floor(aTime / resolutionSec), DBL_DIG-1, ret)); ++#endif ++ return ret; + } + + nsresult diff --git a/www/waterfox/files/patch-bug1430508 b/www/waterfox/files/patch-bug1430508 new file mode 100644 index 000000000000..25d3f962d0e4 --- /dev/null +++ b/www/waterfox/files/patch-bug1430508 @@ -0,0 +1,56 @@ +commit 47e68af6bce1 +Author: Kris Maglione <maglione.k@gmail.com> +Date: Sun Jan 14 17:40:09 2018 -0800 + + Bug 1430508 - Return 0 for ProcessId() when channel IPC is closed. r=dragana, a=jcristau + + There are some corner cases where we try to attach StreamFilter endpoints to a + channel after its IPC has been closed from from the other side, but request + listeners haven't been notified. This causes crashes in any of several places. + + This patch changes nsHttpChannel::ProcessId to return 0 when IPC is closed, so + callers can detect that it's no longer possible to attach endpoints to it. + + MozReview-Commit-ID: BZTOqezih0P + + --HG-- + extra : source : 06f766e7640a3cd180f7da7c092823e500a3d674 +--- + netwerk/protocol/http/HttpChannelParent.cpp | 9 +++++++++ + netwerk/protocol/http/HttpChannelParent.h | 2 ++ + toolkit/components/extensions/webrequest/StreamFilterParent.cpp | 5 ++++- + 3 files changed, 15 insertions(+), 1 deletion(-) + +diff --git netwerk/protocol/http/HttpChannelParent.cpp netwerk/protocol/http/HttpChannelParent.cpp +index db5f441e53c1..ab332ca1a587 100644 +--- netwerk/protocol/http/HttpChannelParent.cpp ++++ netwerk/protocol/http/HttpChannelParent.cpp +@@ -265,6 +265,15 @@ HttpChannelParent::CleanupBackgroundChannel() + } + } + ++base::ProcessId ++HttpChannelParent::OtherPid() const ++{ ++ if (mIPCClosed) { ++ return 0; ++ } ++ return Manager()->OtherPid(); ++} ++ + //----------------------------------------------------------------------------- + // HttpChannelParent::nsISupports + //----------------------------------------------------------------------------- +diff --git netwerk/protocol/http/HttpChannelParent.h netwerk/protocol/http/HttpChannelParent.h +index 19e6fca40bff..fbbad6c2f994 100644 +--- netwerk/protocol/http/HttpChannelParent.h ++++ netwerk/protocol/http/HttpChannelParent.h +@@ -120,6 +120,8 @@ public: + // Callback while background channel is destroyed. + void OnBackgroundParentDestroyed(); + ++ base::ProcessId OtherPid() const override; ++ + protected: + // used to connect redirected-to channel in parent with just created + // ChildChannel. Used during redirects. diff --git a/www/waterfox/files/patch-bug1430511 b/www/waterfox/files/patch-bug1430511 new file mode 100644 index 000000000000..115cb4e83db1 --- /dev/null +++ b/www/waterfox/files/patch-bug1430511 @@ -0,0 +1,72 @@ +commit 2050bcb92e39 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Jan 17 00:08:32 2018 +0000 + + Bug 1430511, r=jaws + + --HG-- + extra : rebase_source : e5ecfb98c1bbd1cd5f9a71be13416a1d041350ef +--- + browser/components/preferences/in-content/findInPage.js | 16 +++++++++++++--- + .../chrome/browser/preferences/preferences.properties | 8 +++++--- + 2 files changed, 18 insertions(+), 6 deletions(-) + +diff --git browser/base/content/test/static/browser_misused_characters_in_strings.js browser/base/content/test/static/browser_misused_characters_in_strings.js +index 9a8168bdb360..10b6796d3580 100644 +--- browser/base/content/test/static/browser_misused_characters_in_strings.js ++++ browser/base/content/test/static/browser_misused_characters_in_strings.js +@@ -110,7 +110,7 @@ let gWhitelist = [{ + type: "single-quote" + }, { + file: "preferences.properties", +- key: "searchResults.needHelp2", ++ key: "searchResults.needHelp3", + type: "double-quote" + } + ]; +diff --git browser/components/preferences/in-content-new/findInPage.js browser/components/preferences/in-content-new/findInPage.js +index a822ec04e728..d54ba7b0e355 100644 +--- browser/components/preferences/in-content-new/findInPage.js ++++ browser/components/preferences/in-content-new/findInPage.js +@@ -264,9 +264,19 @@ var gSearchResultsPane = { + strings.getFormattedString("searchResults.sorryMessageUnix", [this.query]); + let helpUrl = Services.urlFormatter.formatURLPref("app.support.baseURL") + "preferences"; + let brandName = document.getElementById("bundleBrand").getString("brandShortName"); +- // eslint-disable-next-line no-unsanitized/property +- document.getElementById("need-help").innerHTML = +- strings.getFormattedString("searchResults.needHelp2", [helpUrl, brandName]); ++ let helpString = strings.getString("searchResults.needHelp3"); ++ let helpItems = helpString.split(/%(?:\$1)?S/); ++ let helpContainer = document.getElementById("need-help"); ++ helpContainer.innerHTML = ""; ++ helpContainer.appendChild(document.createTextNode(helpItems[0])); ++ let link = document.createElement("label"); ++ link.className = "text-link"; ++ link.setAttribute("href", helpUrl); ++ link.textContent = strings.getFormattedString("searchResults.needHelpSupportLink", [brandName]); ++ helpContainer.appendChild(link); ++ if (helpItems[1]) { ++ helpContainer.appendChild(document.createTextNode(helpItems[1])); ++ } + } else { + // Creating tooltips for all the instances found + this.listSearchTooltips.forEach((anchorNode) => this.createSearchTooltip(anchorNode, this.query)); +diff --git browser/locales/en-US/chrome/browser/preferences/preferences.properties browser/locales/en-US/chrome/browser/preferences/preferences.properties +index 9066145c3c48..73410a196ebf 100644 +--- browser/locales/en-US/chrome/browser/preferences/preferences.properties ++++ browser/locales/en-US/chrome/browser/preferences/preferences.properties +@@ -263,9 +263,11 @@ searchInput.labelUnix=Find in Preferences + # LOCALIZATION NOTE %S will be replaced by the word being searched + searchResults.sorryMessageWin=Sorry! There are no results in Options for “%S”. + searchResults.sorryMessageUnix=Sorry! There are no results in Preferences for “%S”. +-# LOCALIZATION NOTE (searchResults.needHelp2): %1$S is a link to SUMO, %2$S is +-# the browser name +-searchResults.needHelp2=Need help? Visit <html:a id="need-help-link" target="_blank" href="%1$S">%2$S Support</html:a> ++# LOCALIZATION NOTE (searchResults.needHelp3): %S will be replaced with a link to the support page. ++# The label of the link is in searchResults.needHelpSupportLink . ++searchResults.needHelp3=Need help? Visit %S ++# LOCALIZATION NOTE (searchResults.needHelpSupportLink): %S will be replaced with the browser name. ++searchResults.needHelpSupportLink=%S Support + + # LOCALIZATION NOTE %S is the default value of the `dom.ipc.processCount` pref. + defaultContentProcessCount=%S (default) diff --git a/www/waterfox/files/patch-bug1430557 b/www/waterfox/files/patch-bug1430557 new file mode 100644 index 000000000000..045b55154c3b --- /dev/null +++ b/www/waterfox/files/patch-bug1430557 @@ -0,0 +1,51 @@ +commit a9691980909f +Author: Jonathan Watt <jwatt@jwatt.org> +Date: Tue Feb 20 16:13:05 2018 -0500 + + Bug 1430557. r=longsonr, a=lizzard + + --HG-- + extra : rebase_source : 5109c816d9ad1ce1881e3670b8d74ae0dc475223 +--- + dom/svg/DOMSVGPathSegList.cpp | 21 +++++++++++++++++++-- + 1 file changed, 19 insertions(+), 2 deletions(-) + +diff --git dom/svg/DOMSVGPathSegList.cpp dom/svg/DOMSVGPathSegList.cpp +index edacdfc93e9c..0b811cdb1f11 100644 +--- dom/svg/DOMSVGPathSegList.cpp ++++ dom/svg/DOMSVGPathSegList.cpp +@@ -460,6 +460,18 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem, + float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS]; + domItem->ToSVGPathSegEncodedData(segAsRaw); + ++ if (AnimListMirrorsBaseList()) { ++ // The anim val list is in sync with the base val list - remove mirroring ++ // animVal item if necessary. We do this *before* touching InternalList() ++ // so the removed item can correctly store its internal value. ++ DOMSVGPathSegList* animVal = ++ GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); ++ if (animVal->ItemAt(aIndex)) { ++ animVal->ItemAt(aIndex)->RemovingFromList(); ++ animVal->ItemAt(aIndex) = nullptr; ++ } ++ } ++ + if (!InternalList().mData.ReplaceElementsAt(internalIndex, 1 + oldArgCount, + segAsRaw, 1 + newArgCount, + fallible)) { +@@ -474,8 +486,13 @@ DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem, + + int32_t delta = newArgCount - oldArgCount; + if (delta != 0) { +- for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) { +- mItems[i].mInternalDataIndex += delta; ++ // Sync up the internal indexes of all ItemProxys that come after aIndex: ++ UpdateListIndicesFromIndex(aIndex + 1, delta); ++ if (AnimListMirrorsBaseList()) { ++ // The anim val list is in sync with the base val list ++ DOMSVGPathSegList* animVal = ++ GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); ++ animVal->UpdateListIndicesFromIndex(aIndex + 1, delta); + } + } + diff --git a/www/waterfox/files/patch-bug1431192 b/www/waterfox/files/patch-bug1431192 new file mode 100644 index 000000000000..3409a299dc24 --- /dev/null +++ b/www/waterfox/files/patch-bug1431192 @@ -0,0 +1,44 @@ +commit f953dbadab3f +Author: Francois Marier <francois@mozilla.com> +Date: Mon Jan 29 15:16:54 2018 -0800 + + Bug 1431192 - Only fetch download protection lists when Safe Browsing is enabled. r=gcp, a=RyanVM + + Download protection requires both the malware list as well as its + own special lists. The code therefore checks that both Safe + Browsing and download protection are enabled before checking + downloaded files. + + The list manager should check the same prefs before downloading + any of the download protection lists in order to avoid connecting + to the Safe Browsing server when Safe Browsing is fully disabled. + + MozReview-Commit-ID: 66vMA56T4pJ + + --HG-- + extra : source : 79905d4e85aba22cafcd8f331b06197134267975 +--- + toolkit/components/url-classifier/SafeBrowsing.jsm | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git toolkit/components/url-classifier/SafeBrowsing.jsm toolkit/components/url-classifier/SafeBrowsing.jsm +index 73bd04dafcf9..64b8dd35de03 100644 +--- toolkit/components/url-classifier/SafeBrowsing.jsm ++++ toolkit/components/url-classifier/SafeBrowsing.jsm +@@ -405,14 +405,14 @@ this.SafeBrowsing = { + } + } + for (let i = 0; i < this.downloadBlockLists.length; ++i) { +- if (this.downloadsEnabled) { ++ if (this.malwareEnabled && this.downloadsEnabled) { + listManager.enableUpdate(this.downloadBlockLists[i]); + } else { + listManager.disableUpdate(this.downloadBlockLists[i]); + } + } + for (let i = 0; i < this.downloadAllowLists.length; ++i) { +- if (this.downloadsEnabled) { ++ if (this.malwareEnabled && this.downloadsEnabled) { + listManager.enableUpdate(this.downloadAllowLists[i]); + } else { + listManager.disableUpdate(this.downloadAllowLists[i]); diff --git a/www/waterfox/files/patch-bug1431285 b/www/waterfox/files/patch-bug1431285 new file mode 100644 index 000000000000..2f9b80d2ff9b --- /dev/null +++ b/www/waterfox/files/patch-bug1431285 @@ -0,0 +1,34 @@ +commit 767fca9e52ef +Author: Bobby Holley <bobbyholley@gmail.com> +Date: Tue Jul 3 23:47:48 2018 +0000 + + Bug 1431285 - Cap the number of style threads at six. r=emilio a=lizzard + + MozReview-Commit-ID: 3qI1mIvDn8j + + Differential Revision: https://phabricator.services.mozilla.com/D1928 + + --HG-- + extra : source : 0d61bbcd24d8eb49d2beea278859da868186f783 +--- + servo/components/style/gecko/global_style_data.rs | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git servo/components/style/gecko/global_style_data.rs servo/components/style/gecko/global_style_data.rs +index f1cb107dff0fa..6671de9867d2f 100644 +--- servo/components/style/gecko/global_style_data.rs ++++ servo/components/style/gecko/global_style_data.rs +@@ -65,7 +65,12 @@ lazy_static! { + .map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS value")); + let mut num_threads = match stylo_threads { + Ok(num) => num, +- _ => cmp::max(num_cpus::get() * 3 / 4, 1), ++ // The default heuristic is num_virtual_cores * .75. This gives us ++ // three threads on a hyper-threaded dual core, and six threads on ++ // a hyper-threaded quad core. The performance benefit of additional ++ // threads seems to level off at around six, so we cap it there on ++ // many-core machines (see bug 1431285 comment 14). ++ _ => cmp::min(cmp::max(num_cpus::get() * 3 / 4, 1), 6), + }; + + // If num_threads is one, there's no point in creating a thread pool, so diff --git a/www/waterfox/files/patch-bug1431370 b/www/waterfox/files/patch-bug1431370 new file mode 100644 index 000000000000..dfa33ce32a61 --- /dev/null +++ b/www/waterfox/files/patch-bug1431370 @@ -0,0 +1,30 @@ +commit eed02e1bbf61 +Author: Francois Marier <francois@mozilla.com> +Date: Tue Jan 30 13:26:43 2018 -0800 + + Bug 1431370 - Make DoRiceDeltaDecode allocation fallible to fix startup OOM crash. r=gcp a=RyanVM + + MozReview-Commit-ID: 2vf4EU4TVCq + + --HG-- + extra : source : bdb502c30c7c72c758d7bc4f22774fe27d045c1d +--- + toolkit/components/url-classifier/ProtocolParser.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git toolkit/components/url-classifier/ProtocolParser.cpp toolkit/components/url-classifier/ProtocolParser.cpp +index d4fce581e394..a5da314bda30 100644 +--- toolkit/components/url-classifier/ProtocolParser.cpp ++++ toolkit/components/url-classifier/ProtocolParser.cpp +@@ -999,7 +999,10 @@ DoRiceDeltaDecode(const RiceDeltaEncoding& aEncoding, + + // Setup the output buffer. The "first value" is included in + // the output buffer. +- aDecoded.SetLength(aEncoding.num_entries() + 1); ++ if (!aDecoded.SetLength(aEncoding.num_entries() + 1, mozilla::fallible)) { ++ NS_WARNING("Not enough memory to decode the RiceDelta input."); ++ return NS_ERROR_OUT_OF_MEMORY; ++ } + + // Decode! + bool rv = decoder.Decode(aEncoding.rice_parameter(), diff --git a/www/waterfox/files/patch-bug1431434 b/www/waterfox/files/patch-bug1431434 new file mode 100644 index 000000000000..d0b8c894acfc --- /dev/null +++ b/www/waterfox/files/patch-bug1431434 @@ -0,0 +1,48 @@ +commit 4b2bdcc0f926 +Author: Sumit Tiwari <sumi29@gmail.com> +Date: Fri Apr 27 18:29:16 2018 -0400 + + Bug 1431434 - Merge SweepRegExps with SweepMisc; r=jonco + + MozReview-Commit-ID: 7EHJ5LOOuLQ + + --HG-- + extra : rebase_source : ac054fc26da7238fd5ba3bd63d32c5e136c44c0a +--- + js/src/gc/GC.cpp | 9 +-------- + 1 file changed, 1 insertion(+), 8 deletions(-) + +diff --git js/src/jsgc.cpp js/src/jsgc.cpp +index 2f552a14b5582..e6bc076b7c51c 100644 +--- js/src/jsgc.cpp ++++ js/src/jsgc.cpp +@@ -5032,13 +5032,6 @@ SweepObjectGroups(JSRuntime* runtime) + c->objectGroups.sweep(runtime->defaultFreeOp()); + } + +-static void +-SweepRegExps(JSRuntime* runtime) +-{ +- for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) +- c->sweepRegExps(); +-} +- + static void + SweepMisc(JSRuntime* runtime) + { +@@ -5050,6 +5043,7 @@ SweepMisc(JSRuntime* runtime) + c->sweepSelfHostingScriptSource(); + c->sweepNativeIterators(); + c->sweepWatchpoints(); ++ c->sweepRegExps(); + } + } + +@@ -5322,7 +5316,6 @@ GCRuntime::beginSweepingSweepGroup() + + AutoRunParallelTask sweepCCWrappers(rt, SweepCCWrappers, PhaseKind::SWEEP_CC_WRAPPER, lock); + AutoRunParallelTask sweepObjectGroups(rt, SweepObjectGroups, PhaseKind::SWEEP_TYPE_OBJECT, lock); +- AutoRunParallelTask sweepRegExps(rt, SweepRegExps, PhaseKind::SWEEP_REGEXP, lock); + AutoRunParallelTask sweepMisc(rt, SweepMisc, PhaseKind::SWEEP_MISC, lock); + AutoRunParallelTask sweepCompTasks(rt, SweepCompressionTasks, PhaseKind::SWEEP_COMPRESSION, lock); + AutoRunParallelTask sweepWeakMaps(rt, SweepWeakMaps, PhaseKind::SWEEP_WEAKMAPS, lock); diff --git a/www/waterfox/files/patch-bug1431781 b/www/waterfox/files/patch-bug1431781 new file mode 100644 index 000000000000..67863cc586d3 --- /dev/null +++ b/www/waterfox/files/patch-bug1431781 @@ -0,0 +1,30 @@ +commit f6cb7152c208 +Author: Mats Palmgren <mats@mozilla.com> +Date: Tue Jan 23 00:00:03 2018 +0100 + + Bug 1431781 - Report at least OverflowIncomplete reflow status when we skip reflowing OverflowContainer children and have a next-in-flow. r=dholbert a=lizzard + + --HG-- + extra : source : cef7ac1c276ba50a6789ca916568434dbc6990ae +--- + layout/generic/nsContainerFrame.cpp | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git layout/generic/nsContainerFrame.cpp layout/generic/nsContainerFrame.cpp +index d50e1fc6f613..732f24e00b1d 100644 +--- layout/generic/nsContainerFrame.cpp ++++ layout/generic/nsContainerFrame.cpp +@@ -1160,6 +1160,13 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres + if (frame->GetPrevInFlow()->GetParent() != GetPrevInFlow()) { + // frame's prevInFlow has moved, skip reflowing this frame; + // it will get reflowed once it's been placed ++ if (GetNextInFlow()) { ++ // We report OverflowIncomplete status in this case to avoid our parent ++ // deleting our next-in-flows which might destroy non-empty frames. ++ nsReflowStatus status; ++ status.SetOverflowIncomplete(); ++ aStatus.MergeCompletionStatusFrom(status); ++ } + continue; + } + // If the available vertical height has changed, we need to reflow diff --git a/www/waterfox/files/patch-bug1432793 b/www/waterfox/files/patch-bug1432793 new file mode 100644 index 000000000000..f7b193531d97 --- /dev/null +++ b/www/waterfox/files/patch-bug1432793 @@ -0,0 +1,218 @@ +commit b1ccdd29d2a5 +Author: Dan Minor <dminor@mozilla.com> +Date: Wed Mar 28 11:07:54 2018 -0400 + + Bug 1432793 - Force screensharing simulcast to one layer and stop generating layers once an odd width and height are found. r=bwc, a=RyanVM + + This limits screensharing simulcast to a single layer. When window sharing, our + source video can have arbitrary dimensions. If one of those dimensions ends up + being odd, the aspect ratio of the smaller layer will not match the aspect ratio + of the odd sized layer, causing a runtime assertion failure and crash. + + It is not sufficient to prevent the creation of odd sized layers in + CreateEncoderStreams because the user can resize the window while it is being + shared, which will cause a fatal assertion prior to the streams being recreated. + + When switching back from window sharing to camera, a call to + CreateEncoderStreams will occur with resolutions matching the dimensions of + the window that was just shared. To prevent a crash, this also adds a check + which prevents the creation of layers with odd resolutions. + + Looking at cricket::GetSimulcastConfig for the version of webrtc.org in tree, + the number of simulcast layers is limited to one, or two if a field experiment + is enabled. That code also limits resolutions at which screensharing is allowed + as well as the number of layers that can be created for each resolution, and + ensures that each layer is exactly half the size of the layer above. + + Adding these new constraints to CreateEncoderStreams makes us more consistent + with what the webrtc.org code would do when creating streams, which should + help to avoid more assertion failures in the future. Long term, I believe we + should just switch to using cricket::GetSimulcastConfig. + + MozReview-Commit-ID: 8gjdY5GPPjl + + --HG-- + extra : source : 5c5a16ba81b7a2599d2764164d959a549a131d0a +--- + media/webrtc/signaling/src/media-conduit/VideoConduit.cpp | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git media/webrtc/signaling/src/media-conduit/VideoConduit.cpp media/webrtc/signaling/src/media-conduit/VideoConduit.cpp +index b67e1d475e50..aafcbd3d4ddc 100644 +--- media/webrtc/signaling/src/media-conduit/VideoConduit.cpp ++++ media/webrtc/signaling/src/media-conduit/VideoConduit.cpp +@@ -579,7 +579,20 @@ std::vector<webrtc::VideoStream> + WebrtcVideoConduit::VideoStreamFactory::CreateEncoderStreams(int width, int height, + const webrtc::VideoEncoderConfig& config) + { +- auto streamCount = config.number_of_streams; ++ size_t streamCount = config.number_of_streams; ++ ++ // Disallow odd width and height, they will cause aspect ratio checks to ++ // fail in the webrtc.org code. We can hit transient states after window ++ // sharing ends where odd resolutions are requested for the camera. ++ streamCount = std::min(streamCount, static_cast<size_t>( ++ 1 + std::min(CountTrailingZeroes32(width), ++ CountTrailingZeroes32(height)))); ++ ++ // We only allow one layer when screensharing ++ if (mConduit->mCodecMode == webrtc::VideoCodecMode::kScreensharing) { ++ streamCount = 1; ++ } ++ + std::vector<webrtc::VideoStream> streams; + streams.reserve(streamCount); + MOZ_ASSERT(mConduit); + +commit 18e2cf9aac7a +Author: Dan Minor <dminor@mozilla.com> +Date: Wed Apr 4 09:24:28 2018 -0400 + + Bug 1432793 - Add mochitest for odd simulcast resolutions. r=bwc, a=RyanVM + + This creates a simulcast stream with an odd resolution. This previously would + have caused a runtime assertion failure and crash. + + MozReview-Commit-ID: IsywVOu6UeV + + --HG-- + extra : source : f1929e2b77a96af699e244f96bc4ecc17d34ece5 +--- + dom/media/tests/mochitest/head.js | 11 ++- + dom/media/tests/mochitest/mochitest.ini | 2 + + ...test_peerConnection_simulcastOddResolution.html | 91 ++++++++++++++++++++++ + 3 files changed, 100 insertions(+), 4 deletions(-) + +diff --git dom/media/tests/mochitest/head.js dom/media/tests/mochitest/head.js +index b125ecdeecf6..9bdfcdbfaf69 100644 +--- dom/media/tests/mochitest/head.js ++++ dom/media/tests/mochitest/head.js +@@ -994,11 +994,14 @@ AudioStreamHelper.prototype = { + } + + class VideoFrameEmitter { +- constructor(color1, color2, size) { +- if (!size) { +- size = 50; ++ constructor(color1, color2, width, height) { ++ if (!width) { ++ width = 50; + } +- this._helper = new CaptureStreamTestHelper2D(size, size); ++ if (!height) { ++ height = width; ++ } ++ this._helper = new CaptureStreamTestHelper2D(width, height); + this._canvas = this._helper.createAndAppendElement('canvas', 'source_canvas'); + this._color1 = color1 ? color1 : this._helper.green; + this._color2 = color2 ? color2 : this._helper.red; +diff --git dom/media/tests/mochitest/mochitest.ini dom/media/tests/mochitest/mochitest.ini +index 43e8492b9295..07c0876318a0 100644 +--- dom/media/tests/mochitest/mochitest.ini ++++ dom/media/tests/mochitest/mochitest.ini +@@ -194,6 +194,8 @@ skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emula + skip-if = android_version # no simulcast support on android + [test_peerConnection_simulcastAnswer.html] + skip-if = android_version # no simulcast support on android ++[test_peerConnection_simulcastOddResolution.html] ++skip-if = android_version # no simulcast support on android + #[test_peerConnection_relayOnly.html] + [test_peerConnection_callbacks.html] + skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator) +diff --git dom/media/tests/mochitest/test_peerConnection_simulcastOddResolution.html dom/media/tests/mochitest/test_peerConnection_simulcastOddResolution.html +new file mode 100644 +index 000000000000..351582b69fab +--- /dev/null ++++ dom/media/tests/mochitest/test_peerConnection_simulcastOddResolution.html +@@ -0,0 +1,91 @@ ++<!DOCTYPE HTML> ++<html> ++<head> ++ <script type="application/javascript" src="pc.js"></script> ++ <script type="application/javascript" src="/tests/dom/canvas/test/captureStream_common.js"></script> ++</head> ++<body> ++<pre id="test"> ++<script type="application/javascript"> ++ createHTML({ ++ bug: "1432793", ++ title: "Simulcast with odd resolution", ++ visible: true ++ }); ++ ++ function addRIDExtension(pc, extensionId) { ++ const receivers = pc._pc.getReceivers(); ++ is(receivers.length, 1, "We have exactly one RTP receiver"); ++ const receiver = receivers[0]; ++ ++ SpecialPowers.wrap(pc._pc).mozAddRIDExtension(receiver, extensionId); ++ } ++ ++ function selectRecvRID(pc, rid) { ++ const receivers = pc._pc.getReceivers(); ++ is(receivers.length, 1, "We have exactly one RTP receiver"); ++ const receiver = receivers[0]; ++ ++ SpecialPowers.wrap(pc._pc).mozAddRIDFilter(receiver, rid); ++ } ++ ++ runNetworkTest(() => ++ pushPrefs(['media.peerconnection.simulcast', true], ++ // 180Kbps was determined empirically, set well-higher than ++ // the 80Kbps+overhead needed for the two simulcast streams. ++ // 100Kbps was apparently too low. ++ ['media.peerconnection.video.min_bitrate_estimate', 180*1000]).then(() => { ++ let emitter, helper; ++ ++ test = new PeerConnectionTest({bundle: false}); ++ test.setMediaConstraints([{video: true}], [{video: true}]); ++ ++ test.chain.replace("PC_REMOTE_GUM", [ ++ function PC_REMOTE_CANVAS_CAPTURESTREAM(test) { ++ helper = new VideoStreamHelper(); ++ emitter = new VideoFrameEmitter(helper.green, helper.red, 49, 37); ++ test.pcRemote.attachLocalStream(emitter.stream()); ++ emitter.start(); ++ } ++ ]); ++ ++ test.chain.insertAfter('PC_REMOTE_GET_OFFER', [ ++ function PC_REMOTE_SET_RIDS(test) { ++ const senders = test.pcRemote._pc.getSenders(); ++ is(senders.length, 1, "We have exactly one RTP sender"); ++ const sender = senders[0]; ++ ok(sender.track, "Sender has a track"); ++ ++ return sender.setParameters({ ++ encodings: [{ rid: "foo", maxBitrate: 40000 }, ++ { rid: "bar", maxBitrate: 40000, scaleResolutionDownBy: 2 }] ++ }); ++ }, ++ function PC_LOCAL_ADD_RIDS_TO_OFFER(test) { ++ // Create a dummy offer, and use it to set simulcast stuff on the ++ // offer we will actually be using. ++ return test.createOffer(test.pcRemote).then(offer => { ++ test._local_offer.sdp = sdputils.transferSimulcastProperties( ++ offer.sdp, test._local_offer.sdp); ++ info("Offer with RIDs: " + JSON.stringify(test._local_offer)); ++ ok(test._local_offer.sdp.match(/a=simulcast:/), "Modified offer has simulcast"); ++ ok(test._local_offer.sdp.match(/a=rid:foo/), "Modified offer has rid foo"); ++ ok(test._local_offer.sdp.match(/a=rid:bar/), "Modified offer has rid bar"); ++ ok(test._local_offer.sdp.match(/urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id/), "Modified offer has RID"); ++ }); ++ } ++ ]); ++ ++ test.chain.insertAfter('PC_LOCAL_GET_ANSWER',[ ++ function PC_LOCAL_REMOVE_SIMULCAST_ATTRS_FROM_ANSWER(test) { ++ test._remote_answer.sdp = ++ sdputils.removeSimulcastProperties(test._remote_answer.sdp); ++ } ++ ]); ++ return test.run(); ++ }) ++ .catch(e => ok(false, "unexpected failure: " + e))); ++</script> ++</pre> ++</body> ++</html> diff --git a/www/waterfox/files/patch-bug1432870 b/www/waterfox/files/patch-bug1432870 new file mode 100644 index 000000000000..f276b2b822a0 --- /dev/null +++ b/www/waterfox/files/patch-bug1432870 @@ -0,0 +1,29 @@ +commit 4d12d7970aee +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Tue Jan 30 12:07:08 2018 +0000 + + Bug 1432870. r=bz, a=lizzard + + --HG-- + extra : source : 54491805113acdce065ed6164b524acc411986ef +--- + chrome/nsChromeRegistry.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git chrome/nsChromeRegistry.cpp chrome/nsChromeRegistry.cpp +index 4443b11f93ba..8e81c531c4cf 100644 +--- chrome/nsChromeRegistry.cpp ++++ chrome/nsChromeRegistry.cpp +@@ -235,6 +235,12 @@ nsChromeRegistry::Canonify(nsIURL* aChromeURL) + // path is already unescaped once, but uris can get unescaped twice + const char* pos = path.BeginReading(); + const char* end = path.EndReading(); ++ // Must start with [a-zA-Z0-9]. ++ if (!('a' <= *pos && *pos <= 'z') && ++ !('A' <= *pos && *pos <= 'Z') && ++ !('0' <= *pos && *pos <= '9')) { ++ return NS_ERROR_DOM_BAD_URI; ++ } + while (pos < end) { + switch (*pos) { + case ':': diff --git a/www/waterfox/files/patch-bug1432915 b/www/waterfox/files/patch-bug1432915 new file mode 100644 index 000000000000..cd584b59466f --- /dev/null +++ b/www/waterfox/files/patch-bug1432915 @@ -0,0 +1,27 @@ +commit aefee13a68d4 +Author: Luke Crouch <lcrouch@mozilla.com> +Date: Tue Jan 30 10:59:43 2018 -0600 + + Bug 1432915 - don't save download source url when aIsPrivate r=Ehsan a=RyanVM + + MozReview-Commit-ID: 9mQjwcCtrWg + + --HG-- + extra : source : 91c18ad31b298458978b2817a691d94b2c7d802d +--- + toolkit/components/jsdownloads/src/DownloadPlatform.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git toolkit/components/jsdownloads/src/DownloadPlatform.cpp toolkit/components/jsdownloads/src/DownloadPlatform.cpp +index fd7c8fbd9b18..b519d33fcfab 100644 +--- toolkit/components/jsdownloads/src/DownloadPlatform.cpp ++++ toolkit/components/jsdownloads/src/DownloadPlatform.cpp +@@ -167,7 +167,7 @@ nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIURI* aReferrer, nsIF + (const UniChar*)path.get(), + path.Length()); + } +- if (pathCFStr) { ++ if (pathCFStr && !aIsPrivate) { + bool isFromWeb = IsURLPossiblyFromWeb(aSource); + + CFURLRef sourceCFURL = CreateCFURLFromNSIURI(aSource); diff --git a/www/waterfox/files/patch-bug1433609 b/www/waterfox/files/patch-bug1433609 new file mode 100644 index 000000000000..0b6ecc63e18b --- /dev/null +++ b/www/waterfox/files/patch-bug1433609 @@ -0,0 +1,103 @@ +commit 9d65f87e8479 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Wed Feb 14 14:40:05 2018 +0100 + + Bug 1433609 - Ensure that deserialized URL is correct. r=mayhemer, a=RyanVM + + MozReview-Commit-ID: BMQfPzPhDhc + + --HG-- + extra : source : d0da2be2c9508f48b8e4804bd4a4ca3b37b56d4f +--- + netwerk/base/nsStandardURL.cpp | 64 ++++++++++++++++++++++++++++++++---------- + 1 file changed, 49 insertions(+), 15 deletions(-) + +diff --git netwerk/base/nsStandardURL.cpp netwerk/base/nsStandardURL.cpp +index 85ab13fed7ae..67dc701e7272 100644 +--- netwerk/base/nsStandardURL.cpp ++++ netwerk/base/nsStandardURL.cpp +@@ -3726,10 +3726,29 @@ ToIPCSegment(const nsStandardURL::URLSegment& aSegment) + } + + inline +-nsStandardURL::URLSegment +-FromIPCSegment(const ipc::StandardURLSegment& aSegment) ++MOZ_MUST_USE bool ++FromIPCSegment(const nsACString& aSpec, const ipc::StandardURLSegment& aSegment, nsStandardURL::URLSegment& aTarget) + { +- return nsStandardURL::URLSegment(aSegment.position(), aSegment.length()); ++ // This seems to be just an empty segment. ++ if (aSegment.length() == -1) { ++ aTarget = nsStandardURL::URLSegment(); ++ return true; ++ } ++ ++ // A value of -1 means an empty segment, but < -1 is undefined. ++ if (NS_WARN_IF(aSegment.length() < -1)) { ++ return false; ++ } ++ ++ // Make sure the segment does not extend beyond the spec. ++ if (NS_WARN_IF(aSegment.position() + aSegment.length() > aSpec.Length())) { ++ return false; ++ } ++ ++ aTarget.mPos = aSegment.position(); ++ aTarget.mLen = aSegment.length(); ++ ++ return true; + } + + void +@@ -3797,24 +3816,39 @@ nsStandardURL::Deserialize(const URIParams& aParams) + mPort = params.port(); + mDefaultPort = params.defaultPort(); + mSpec = params.spec(); +- mScheme = FromIPCSegment(params.scheme()); +- mAuthority = FromIPCSegment(params.authority()); +- mUsername = FromIPCSegment(params.username()); +- mPassword = FromIPCSegment(params.password()); +- mHost = FromIPCSegment(params.host()); +- mPath = FromIPCSegment(params.path()); +- mFilepath = FromIPCSegment(params.filePath()); +- mDirectory = FromIPCSegment(params.directory()); +- mBasename = FromIPCSegment(params.baseName()); +- mExtension = FromIPCSegment(params.extension()); +- mQuery = FromIPCSegment(params.query()); +- mRef = FromIPCSegment(params.ref()); ++ ++ NS_ENSURE_TRUE(mSpec.Length() <= (uint32_t) net_GetURLMaxLength(), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.scheme(), mScheme), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.authority(), mAuthority), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.username(), mUsername), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.password(), mPassword), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.host(), mHost), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.path(), mPath), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.filePath(), mFilepath), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.directory(), mDirectory), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.baseName(), mBasename), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.extension(), mExtension), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.query(), mQuery), false); ++ NS_ENSURE_TRUE(FromIPCSegment(mSpec, params.ref(), mRef), false); ++ + mOriginCharset = params.originCharset(); + mMutable = params.isMutable(); + mSupportsFileURL = params.supportsFileURL(); + + CALL_RUST_SYNC; + ++ // Some sanity checks ++ NS_ENSURE_TRUE(mScheme.mPos == 0, false); ++ NS_ENSURE_TRUE(mScheme.mLen > 0, false); ++ // Make sure scheme is followed by :// (3 characters) ++ NS_ENSURE_TRUE(mScheme.mLen < INT32_MAX - 3, false); // avoid overflow ++ NS_ENSURE_TRUE(mSpec.Length() >= (uint32_t) mScheme.mLen + 3, false); ++ NS_ENSURE_TRUE(nsDependentCSubstring(mSpec, mScheme.mLen, 3).EqualsLiteral("://"), false); ++ NS_ENSURE_TRUE(mPath.mLen != -1 && mSpec.CharAt(mPath.mPos) == '/', false); ++ NS_ENSURE_TRUE(mPath.mPos == mFilepath.mPos, false); ++ NS_ENSURE_TRUE(mQuery.mLen == -1 || mSpec.CharAt(mQuery.mPos - 1) == '?', false); ++ NS_ENSURE_TRUE(mRef.mLen == -1 || mSpec.CharAt(mRef.mPos - 1) == '#', false); ++ + // mSpecEncoding and mDisplayHost are just caches that can be recovered as needed. + return true; + } diff --git a/www/waterfox/files/patch-bug1433671 b/www/waterfox/files/patch-bug1433671 new file mode 100644 index 000000000000..b43f60006ca3 --- /dev/null +++ b/www/waterfox/files/patch-bug1433671 @@ -0,0 +1,179 @@ +commit c5af1605ca8e +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Mon Feb 5 15:27:35 2018 -0500 + + Bug 1433671 - Make AccessibleCaretManager flushes a bit more sound. r=TYLin, a=RyanVM + + The accessible caret manager is owned by the event hub, that is owned by the + shell. + + All the callers of methods that call FlushLayout on the AccessibleCaretManager + should hold an external reference to the event hub. + + Flushing pending notifications can run arbitrary script, that can call Destroy() + on the pres shell (and thus tear down the accessible caret event hub, and the + manager with him). + + I don't know why before my change this wasn't crashing badly, but the code as it + was just doesn't look sound to me at all either (maybe I'm misunderstanding + something and I should just revert that patch and give up on having nice + invariants during our flushes..., but I don't think it's the case). + + This also adds some sanity-checking that we don't die under our flush. + + MozReview-Commit-ID: 4s0UT0fD3TI +--- + layout/base/AccessibleCaretEventHub.cpp | 6 +++-- + layout/base/AccessibleCaretManager.cpp | 29 +++++++++++++----------- + layout/base/AccessibleCaretManager.h | 17 ++++++++++---- + layout/base/gtest/TestAccessibleCaretManager.cpp | 4 ++-- + 4 files changed, 34 insertions(+), 22 deletions(-) + +diff --git layout/base/AccessibleCaretEventHub.cpp layout/base/AccessibleCaretEventHub.cpp +index 2c777396c857..05da6cad3369 100644 +--- layout/base/AccessibleCaretEventHub.cpp ++++ layout/base/AccessibleCaretEventHub.cpp +@@ -677,7 +677,8 @@ AccessibleCaretEventHub::CancelLongTapInjector() + AccessibleCaretEventHub::FireLongTap(nsITimer* aTimer, + void* aAccessibleCaretEventHub) + { +- auto* self = static_cast<AccessibleCaretEventHub*>(aAccessibleCaretEventHub); ++ RefPtr<AccessibleCaretEventHub> self = ++ static_cast<AccessibleCaretEventHub*>(aAccessibleCaretEventHub); + self->mState->OnLongTap(self, self->mPressPoint); + } + +@@ -779,7 +780,8 @@ AccessibleCaretEventHub::CancelScrollEndInjector() + AccessibleCaretEventHub::FireScrollEnd(nsITimer* aTimer, + void* aAccessibleCaretEventHub) + { +- auto* self = static_cast<AccessibleCaretEventHub*>(aAccessibleCaretEventHub); ++ RefPtr<AccessibleCaretEventHub> self = ++ static_cast<AccessibleCaretEventHub*>(aAccessibleCaretEventHub); + self->mState->OnScrollEnd(self); + } + +diff --git layout/base/AccessibleCaretManager.cpp layout/base/AccessibleCaretManager.cpp +index 19ca4e3da9cc..994396785ba6 100644 +--- layout/base/AccessibleCaretManager.cpp ++++ layout/base/AccessibleCaretManager.cpp +@@ -124,6 +124,7 @@ AccessibleCaretManager::AccessibleCaretManager(nsIPresShell* aPresShell) + + AccessibleCaretManager::~AccessibleCaretManager() + { ++ MOZ_RELEASE_ASSERT(!mFlushingLayout, "Going away in FlushLayout? Bad!"); + } + + void +@@ -221,8 +222,7 @@ AccessibleCaretManager::HideCarets() + void + AccessibleCaretManager::UpdateCarets(UpdateCaretsHintSet aHint) + { +- FlushLayout(); +- if (IsTerminated()) { ++ if (!FlushLayout()) { + return; + } + +@@ -389,8 +389,7 @@ AccessibleCaretManager::UpdateCaretsForSelectionMode(UpdateCaretsHintSet aHints) + if (firstCaretResult == PositionChangedResult::Changed || + secondCaretResult == PositionChangedResult::Changed) { + // Flush layout to make the carets intersection correct. +- FlushLayout(); +- if (IsTerminated()) { ++ if (!FlushLayout()) { + return; + } + } +@@ -1022,12 +1021,17 @@ AccessibleCaretManager::ClearMaintainedSelection() const + } + } + +-void +-AccessibleCaretManager::FlushLayout() const ++bool ++AccessibleCaretManager::FlushLayout() + { + if (mPresShell) { ++ AutoRestore<bool> flushing(mFlushingLayout); ++ mFlushingLayout = true; ++ + mPresShell->FlushPendingNotifications(FlushType::Layout); + } ++ ++ return !IsTerminated(); + } + + nsIFrame* +@@ -1380,14 +1384,9 @@ AccessibleCaretManager::AdjustDragBoundary(const nsPoint& aPoint) const + } + + void +-AccessibleCaretManager::DispatchCaretStateChangedEvent(CaretChangedReason aReason) const ++AccessibleCaretManager::DispatchCaretStateChangedEvent(CaretChangedReason aReason) + { +- if (!mPresShell) { +- return; +- } +- +- FlushLayout(); +- if (IsTerminated()) { ++ if (!FlushLayout()) { + return; + } + +diff --git layout/base/AccessibleCaretManager.h layout/base/AccessibleCaretManager.h +index 2de756d4699b..4805b519585d 100644 +--- layout/base/AccessibleCaretManager.h ++++ layout/base/AccessibleCaretManager.h +@@ -193,9 +193,13 @@ protected: + nsPoint AdjustDragBoundary(const nsPoint& aPoint) const; + void ClearMaintainedSelection() const; + +- // Caller is responsible to use IsTerminated() to check whether PresShell is +- // still valid. +- void FlushLayout() const; ++ // This method could kill the shell, so callers to methods that call ++ // FlushLayout should ensure the event hub that owns us is still alive. ++ // ++ // See the mRefCnt assertions in AccessibleCaretEventHub. ++ // ++ // Returns whether mPresShell we're holding is still valid. ++ MOZ_MUST_USE bool FlushLayout(); + + dom::Element* GetEditingHostForFrame(nsIFrame* aFrame) const; + dom::Selection* GetSelection() const; +@@ -251,7 +255,7 @@ protected: + + // This function will flush layout, so caller must ensure the PresShell is + // still valid after calling this method. +- virtual void DispatchCaretStateChangedEvent(dom::CaretChangedReason aReason) const; ++ virtual void DispatchCaretStateChangedEvent(dom::CaretChangedReason aReason); + + // --------------------------------------------------------------------------- + // Member variables +@@ -295,6 +299,9 @@ protected: + // Set to true in OnScrollStart() and set to false in OnScrollEnd(). + bool mIsScrollStarted = false; + ++ // Whether we're flushing layout, used for sanity-checking. ++ bool mFlushingLayout = false; ++ + static const int32_t kAutoScrollTimerDelay = 30; + + // Clicking on the boundary of input or textarea will move the caret to the +diff --git layout/base/gtest/TestAccessibleCaretManager.cpp layout/base/gtest/TestAccessibleCaretManager.cpp +index 1d3a1c039404..118e5cbcf5fe 100644 +--- layout/base/gtest/TestAccessibleCaretManager.cpp ++++ layout/base/gtest/TestAccessibleCaretManager.cpp +@@ -108,8 +108,8 @@ public: + virtual bool IsTerminated() const override { return false; } + + MOCK_CONST_METHOD0(GetCaretMode, CaretMode()); +- MOCK_CONST_METHOD1(DispatchCaretStateChangedEvent, +- void(CaretChangedReason aReason)); ++ MOCK_METHOD1(DispatchCaretStateChangedEvent, ++ void(CaretChangedReason aReason)); + MOCK_CONST_METHOD1(HasNonEmptyTextContent, bool(nsINode* aNode)); + + }; // class MockAccessibleCaretManager diff --git a/www/waterfox/files/patch-bug1433747 b/www/waterfox/files/patch-bug1433747 new file mode 100644 index 000000000000..62543bfd8ad5 --- /dev/null +++ b/www/waterfox/files/patch-bug1433747 @@ -0,0 +1,24 @@ +Apply simd@cf87865a998a to unbreak -C target-cpu with Rust >= 1.24 + +diff --git third_party/rust/simd/.cargo-checksum.json third_party/rust/simd/.cargo-checksum.json +index 65f31b0560e6..f16d0dd4fd61 100644 +--- third_party/rust/simd/.cargo-checksum.json ++++ third_party/rust/simd/.cargo-checksum.json +@@ -1 +1 @@ +-{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e2c720c3633b7671efce49147c62b12bcbf630d7c5d6fc65cd97620bfa4ddcea","Cargo.toml":"608aad04f17a524ee21048fa2ce9f656ae344e0473dd0e331dc954f0f9677c63","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6d3a9431e65e69c73a8923e6517b889d17549b23db406b9ec027710d16af701f","README.md":"249294a9a5f63c64c0f7fe4a607060f43f3507dce2378067aa59d25fb3ae681d","benches/mandelbrot.rs":"051b5199e66bca6cf7774e9024915fd4e1349ab39726a10a14e06b60d65d87a4","benches/matrix.rs":"048a21dacdb62365e0105d00d2c8cd6bd2396ac81134f2bff7eb4f7d095fb735","examples/axpy.rs":"4307626045d64ec08361c97c9c72c5dc8d361bdc88f64453b97ac0212041a1b2","examples/convert.rs":"8e658fde050f8a0d8b84ad7570446b10fcf544afbd551b940ca340474f324840","examples/dot-product.rs":"6fe2e007c147af5353804173a593c5b9d57dbccec156e1da37e9e32537363f91","examples/fannkuch-redux-nosimd.rs":"7b2fbde35e8666929d14d67328471cb0483d038a5325232f8db148b30865312b","examples/fannkuch-redux.rs":"ea21fdbd2274488a62cc984acad6e0b65d52f24fb4ff63b7057a3a667e9c8aae","examples/mandelbrot.rs":"8b8fdca1edac50e5a33e0e0592bd41eb75114f31839ccd40d485c61a9a664380","examples/matrix-inverse.rs":"a378d20ef20c2119bb10a86de27c92fec2c2f77f374e6bfd36707c9825a5fe92","examples/nbody-nosimd.rs":"2c8e0a7feacd202fdd65eeceb6420d6e9f43340b81f20a8e532704a587a2796b","examples/nbody.rs":"a864311affab262024479d6348ff51af43d809e9ad332ec30ea4aacceaa2eae1","examples/ops.rs":"1316f915d0afcfa98fdc4077e965ccccf6b4b21c433cbe487ff0cdc60df3cd39","examples/spectral-norm-nosimd.rs":"ffc8512ecde779078ea467f38f423a0ea623c63da7078193f9dd370200773f79","examples/spectral-norm.rs":"edb09c9d477f83939098cfb77a27cc298bc7a0c8a8e29cece0cccae0d70d890e","src/aarch64/mod.rs":"83f52775364c98de0cecb7e1509530c18972e932469f5f1522aa24a735d0fa37","src/aarch64/neon.rs":"1fe769979e07d8e2bc3c78ce116e05d735860744efe097a894cc9421153257fb","src/arm/mod.rs":"dcdd90bc0b39abaf86a0c8946d442b16313563fbae1ff03248628275c74d8617","src/arm/neon.rs":"51cc509856200e80f8e4cc2c982586e6d1cef593ec4537e153dce0cfe31d3428","src/common.rs":"62f4e7e0fefb52ad190d0f2191bc435ac4deab3f2bc70dc427f2a7f9ccb7856e","src/lib.rs":"25f0b39c038fa85af858318135dfd87865be26c33bb4bd1438aec96a1e68d8b5","src/sixty_four.rs":"510a9e00189a61e4f0a5beb7052d5dee37fc8261f94a2af45ef10327e0f3b7df","src/v256.rs":"2e328e49034876d535e0627c7a62191da2b4fb156a657614bf531a5fc75b1385","src/x86/avx.rs":"c66140abefca634b48eae307c3ec8cf5a40f2279b10e246a7e2ac602a2a2bb28","src/x86/avx2.rs":"efe3006b13a13261a3dec3d37dc1d8cb53950f3803c420069231803374949937","src/x86/mod.rs":"0acc5a5e2672e2a0fddc11065663be8b8fa2da87320ea291fa86ff8c2f33edf5","src/x86/sse2.rs":"5ceda75a401958a135fc9d851b22075314cdeed69fd483b6a7be4f11373f40da","src/x86/sse3.rs":"9bd01a4f08069ca4f445952e744d651efe887e3835b18872e757375f0d053bd2","src/x86/sse4_1.rs":"9ceb80dd70a7e7dfeef508cb935e1a2637175bc87a3b090f5dea691ff6aa0516","src/x86/sse4_2.rs":"c59321aed8decdce4d0d8570cff46aed02e1a8265647ef7702e9b180fc581254","src/x86/ssse3.rs":"2290f0269bae316b8e0491495645ee38a9bd73525c8572759c1328341c3bdb4c"},"package":"7a94d14a2ae1f1f110937de5fb69e494372560181c7e1739a097fcc2cee37ba0"} +\ No newline at end of file ++{"files":{".cargo-ok":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",".travis.yml":"e2c720c3633b7671efce49147c62b12bcbf630d7c5d6fc65cd97620bfa4ddcea","Cargo.toml":"608aad04f17a524ee21048fa2ce9f656ae344e0473dd0e331dc954f0f9677c63","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6d3a9431e65e69c73a8923e6517b889d17549b23db406b9ec027710d16af701f","README.md":"249294a9a5f63c64c0f7fe4a607060f43f3507dce2378067aa59d25fb3ae681d","benches/mandelbrot.rs":"051b5199e66bca6cf7774e9024915fd4e1349ab39726a10a14e06b60d65d87a4","benches/matrix.rs":"048a21dacdb62365e0105d00d2c8cd6bd2396ac81134f2bff7eb4f7d095fb735","examples/axpy.rs":"4307626045d64ec08361c97c9c72c5dc8d361bdc88f64453b97ac0212041a1b2","examples/convert.rs":"8e658fde050f8a0d8b84ad7570446b10fcf544afbd551b940ca340474f324840","examples/dot-product.rs":"6fe2e007c147af5353804173a593c5b9d57dbccec156e1da37e9e32537363f91","examples/fannkuch-redux-nosimd.rs":"7b2fbde35e8666929d14d67328471cb0483d038a5325232f8db148b30865312b","examples/fannkuch-redux.rs":"ea21fdbd2274488a62cc984acad6e0b65d52f24fb4ff63b7057a3a667e9c8aae","examples/mandelbrot.rs":"8b8fdca1edac50e5a33e0e0592bd41eb75114f31839ccd40d485c61a9a664380","examples/matrix-inverse.rs":"a378d20ef20c2119bb10a86de27c92fec2c2f77f374e6bfd36707c9825a5fe92","examples/nbody-nosimd.rs":"2c8e0a7feacd202fdd65eeceb6420d6e9f43340b81f20a8e532704a587a2796b","examples/nbody.rs":"a864311affab262024479d6348ff51af43d809e9ad332ec30ea4aacceaa2eae1","examples/ops.rs":"1316f915d0afcfa98fdc4077e965ccccf6b4b21c433cbe487ff0cdc60df3cd39","examples/spectral-norm-nosimd.rs":"ffc8512ecde779078ea467f38f423a0ea623c63da7078193f9dd370200773f79","examples/spectral-norm.rs":"edb09c9d477f83939098cfb77a27cc298bc7a0c8a8e29cece0cccae0d70d890e","src/aarch64/mod.rs":"83f52775364c98de0cecb7e1509530c18972e932469f5f1522aa24a735d0fa37","src/aarch64/neon.rs":"1fe769979e07d8e2bc3c78ce116e05d735860744efe097a894cc9421153257fb","src/arm/mod.rs":"dcdd90bc0b39abaf86a0c8946d442b16313563fbae1ff03248628275c74d8617","src/arm/neon.rs":"51cc509856200e80f8e4cc2c982586e6d1cef593ec4537e153dce0cfe31d3428","src/common.rs":"62f4e7e0fefb52ad190d0f2191bc435ac4deab3f2bc70dc427f2a7f9ccb7856e","src/lib.rs":"25f0b39c038fa85af858318135dfd87865be26c33bb4bd1438aec96a1e68d8b5","src/sixty_four.rs":"510a9e00189a61e4f0a5beb7052d5dee37fc8261f94a2af45ef10327e0f3b7df","src/v256.rs":"2e328e49034876d535e0627c7a62191da2b4fb156a657614bf531a5fc75b1385","src/x86/avx.rs":"c66140abefca634b48eae307c3ec8cf5a40f2279b10e246a7e2ac602a2a2bb28","src/x86/avx2.rs":"3bcb3f391ad5f16f0a6da0bc1301329beb478ad6265bd3b2c9c124fc2e6198e5","src/x86/mod.rs":"0acc5a5e2672e2a0fddc11065663be8b8fa2da87320ea291fa86ff8c2f33edf5","src/x86/sse2.rs":"5ceda75a401958a135fc9d851b22075314cdeed69fd483b6a7be4f11373f40da","src/x86/sse3.rs":"9bd01a4f08069ca4f445952e744d651efe887e3835b18872e757375f0d053bd2","src/x86/sse4_1.rs":"9ceb80dd70a7e7dfeef508cb935e1a2637175bc87a3b090f5dea691ff6aa0516","src/x86/sse4_2.rs":"c59321aed8decdce4d0d8570cff46aed02e1a8265647ef7702e9b180fc581254","src/x86/ssse3.rs":"2290f0269bae316b8e0491495645ee38a9bd73525c8572759c1328341c3bdb4c"},"package":"7a94d14a2ae1f1f110937de5fb69e494372560181c7e1739a097fcc2cee37ba0"} +\ No newline at end of file +diff --git third_party/rust/simd/src/x86/avx2.rs third_party/rust/simd/src/x86/avx2.rs +index fa92e3b60786..e86a33d3b5bb 100644 +--- third_party/rust/simd/src/x86/avx2.rs ++++ third_party/rust/simd/src/x86/avx2.rs +@@ -42,7 +42,7 @@ extern "platform-intrinsic" { + fn x86_mm256_packus_epi32(x: i32x8, y: i32x8) -> u16x16; + fn x86_mm256_permutevar8x32_epi32(x: i32x8, y: i32x8) -> i32x8; + fn x86_mm256_permutevar8x32_ps(x: f32x8, y: i32x8) -> f32x8; +- fn x86_mm256_sad_epu8(x: u8x32, y: u8x32) -> u8x32; ++ fn x86_mm256_sad_epu8(x: u8x32, y: u8x32) -> u64x4; + fn x86_mm256_shuffle_epi8(x: i8x32, y: i8x32) -> i8x32; + fn x86_mm256_sign_epi8(x: i8x32, y: i8x32) -> i8x32; + fn x86_mm256_sign_epi16(x: i16x16, y: i16x16) -> i16x16; diff --git a/www/waterfox/files/patch-bug1434384 b/www/waterfox/files/patch-bug1434384 new file mode 100644 index 000000000000..99b7850e160f --- /dev/null +++ b/www/waterfox/files/patch-bug1434384 @@ -0,0 +1,41 @@ +commit 8143391c68e1 +Author: Steve Fink <sfink@mozilla.com> +Date: Fri Jan 5 14:37:47 2018 -0800 + + Bug 1434384 - Mark v1 structured clone data as cross-process. r=jorendorff, a=RyanVM + + --HG-- + extra : source : d85679eb427513cb18650f3d4e7d37a6ccbefbab +--- + js/src/vm/StructuredClone.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git js/src/vm/StructuredClone.cpp js/src/vm/StructuredClone.cpp +index 55b7fd76ea2d..f595132256e0 100644 +--- js/src/vm/StructuredClone.cpp ++++ js/src/vm/StructuredClone.cpp +@@ -2374,12 +2374,14 @@ JSStructuredCloneReader::readHeader() + return in.reportTruncated(); + + if (tag != SCTAG_HEADER) { +- // Old structured clone buffer. We must have read it from disk or +- // somewhere, so we can assume it's scope-compatible. ++ // Old structured clone buffer. We must have read it from disk. ++ storedScope = JS::StructuredCloneScope::DifferentProcess; + return true; + } + + MOZ_ALWAYS_TRUE(in.readPair(&tag, &data)); ++ storedScope = JS::StructuredCloneScope(data); ++ + if (data != uint32_t(JS::StructuredCloneScope::SameProcessSameThread) && + data != uint32_t(JS::StructuredCloneScope::SameProcessDifferentThread) && + data != uint32_t(JS::StructuredCloneScope::DifferentProcess)) +@@ -2388,7 +2390,6 @@ JSStructuredCloneReader::readHeader() + "invalid structured clone scope"); + return false; + } +- storedScope = JS::StructuredCloneScope(data); + if (storedScope < allowedScope) { + JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, + "incompatible structured clone scope"); diff --git a/www/waterfox/files/patch-bug1434580 b/www/waterfox/files/patch-bug1434580 new file mode 100644 index 000000000000..4d3569c17dc2 --- /dev/null +++ b/www/waterfox/files/patch-bug1434580 @@ -0,0 +1,29 @@ +commit dd8c13a8442d +Author: Olli Pettay <Olli.Pettay@helsinki.fi> +Date: Fri Feb 2 13:25:26 2018 +0200 + + Bug 1434580 - Ensure proper mouseover handling. r=masayuki, a=abillings + + --HG-- + extra : source : bfd4bdfd40b43d0491c66af5b599659427e4e795 +--- + dom/events/EventStateManager.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git dom/events/EventStateManager.cpp dom/events/EventStateManager.cpp +index 66b686dcf302..52f9f2313828 100644 +--- dom/events/EventStateManager.cpp ++++ dom/events/EventStateManager.cpp +@@ -4326,9 +4326,10 @@ EventStateManager::NotifyMouseOver(WidgetMouseEvent* aMouseEvent, + // content associated with our subdocument. + EnsureDocument(mPresContext); + if (nsIDocument *parentDoc = mDocument->GetParentDocument()) { +- if (nsIContent *docContent = parentDoc->FindContentForSubDocument(mDocument)) { ++ if (nsCOMPtr<nsIContent> docContent = ++ parentDoc->FindContentForSubDocument(mDocument)) { + if (nsIPresShell *parentShell = parentDoc->GetShell()) { +- EventStateManager* parentESM = ++ RefPtr<EventStateManager> parentESM = + parentShell->GetPresContext()->EventStateManager(); + parentESM->NotifyMouseOver(aMouseEvent, docContent); + } diff --git a/www/waterfox/files/patch-bug1435036 b/www/waterfox/files/patch-bug1435036 new file mode 100644 index 000000000000..4cb2b39fd1de --- /dev/null +++ b/www/waterfox/files/patch-bug1435036 @@ -0,0 +1,97 @@ +commit a857f1b964fc +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Mon Mar 19 09:40:38 2018 +0100 + + Bug 1435036 - Improve window checks. r=jib, a=RyanVM + + --HG-- + extra : source : 37039eaf524823ed3157fafbdfcfbc450b67b4ab +--- + dom/media/MediaManager.cpp | 30 +++++++++++++++++++----------- + dom/media/MediaManager.h | 1 + + 2 files changed, 20 insertions(+), 11 deletions(-) + +diff --git dom/media/MediaManager.cpp dom/media/MediaManager.cpp +index e96509db4ce0..f2862dc0b23c 100644 +--- dom/media/MediaManager.cpp ++++ dom/media/MediaManager.cpp +@@ -1013,14 +1013,17 @@ public: + public: + TracksAvailableCallback(MediaManager* aManager, + already_AddRefed<nsIDOMGetUserMediaSuccessCallback> aSuccess, +- uint64_t aWindowID, ++ const RefPtr<GetUserMediaWindowListener>& aWindowListener, + DOMMediaStream* aStream) +- : mWindowID(aWindowID), mOnSuccess(aSuccess), mManager(aManager), +- mStream(aStream) {} ++ : mWindowListener(aWindowListener), ++ mOnSuccess(aSuccess), ++ mManager(aManager), ++ mStream(aStream) ++ {} + void NotifyTracksAvailable(DOMMediaStream* aStream) override + { +- // We're in the main thread, so no worries here. +- if (!(mManager->IsWindowStillActive(mWindowID))) { ++ // We're on the main thread, so no worries here. ++ if (!mManager->IsWindowListenerStillActive(mWindowListener)) { + return; + } + +@@ -1033,7 +1036,7 @@ public: + LOG(("Returning success for getUserMedia()")); + mOnSuccess->OnSuccess(aStream); + } +- uint64_t mWindowID; ++ RefPtr<GetUserMediaWindowListener> mWindowListener; + nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess; + RefPtr<MediaManager> mManager; + // Keep the DOMMediaStream alive until the NotifyTracksAvailable callback +@@ -1056,10 +1059,8 @@ public: + + // We're on main-thread, and the windowlist can only + // be invalidated from the main-thread (see OnNavigation) +- GetUserMediaWindowListener* listener = +- mManager->GetWindowListener(mWindowID); +- if (!listener || !window || !window->GetExtantDoc()) { +- // This window is no longer live. mListener has already been removed ++ if (!mManager->IsWindowListenerStillActive(mWindowListener)) { ++ // This window is no longer live. mListener has already been removed. + return NS_OK; + } + +@@ -1219,7 +1220,7 @@ public: + + // Note: includes JS callbacks; must be released on MainThread + auto callback = MakeRefPtr<Refcountable<UniquePtr<OnTracksAvailableCallback>>>( +- new TracksAvailableCallback(mManager, mOnSuccess.forget(), mWindowID, domStream)); ++ new TracksAvailableCallback(mManager, mOnSuccess.forget(), mWindowListener, domStream)); + + // Dispatch to the media thread to ask it to start the sources, + // because that can take a while. +@@ -3015,6 +3016,13 @@ MediaManager::RemoveWindowID(uint64_t aWindowId) + aWindowId, outerID)); + } + ++bool ++MediaManager::IsWindowListenerStillActive(GetUserMediaWindowListener* aListener) ++{ ++ MOZ_DIAGNOSTIC_ASSERT(aListener); ++ return aListener && aListener == GetWindowListener(aListener->WindowID()); ++} ++ + void + MediaManager::GetPref(nsIPrefBranch *aBranch, const char *aPref, + const char *aData, int32_t *aVal) +diff --git dom/media/MediaManager.h dom/media/MediaManager.h +index 3d9d9e55f8ec..f9c5b0647f64 100644 +--- dom/media/MediaManager.h ++++ dom/media/MediaManager.h +@@ -237,6 +237,7 @@ public: + bool IsWindowStillActive(uint64_t aWindowId) { + return !!GetWindowListener(aWindowId); + } ++ bool IsWindowListenerStillActive(GetUserMediaWindowListener* aListener); + // Note: also calls aListener->Remove(), even if inactive + void RemoveFromWindowList(uint64_t aWindowID, + GetUserMediaWindowListener *aListener); diff --git a/www/waterfox/files/patch-bug1435098 b/www/waterfox/files/patch-bug1435098 new file mode 100644 index 000000000000..f1be765bbaa3 --- /dev/null +++ b/www/waterfox/files/patch-bug1435098 @@ -0,0 +1,46 @@ +commit 9cfd36156d04 +Author: Francois Marier <francois@mozilla.com> +Date: Fri Feb 2 13:30:28 2018 -0800 + + Bug 1435098 - Gate flashinfobar list on the plugins.show_infobar. r=bytesized,gcp a=RyanVM + + The list of sites to suppress flash infobars on should not be + downloaded from shavar unless the infobar feature is enabled. + + MozReview-Commit-ID: BjkS5vWiilg + + --HG-- + extra : source : 40f74605367ec4d620873fa8ff90c2dcc2a7ce31 +--- + toolkit/components/url-classifier/SafeBrowsing.jsm | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git toolkit/components/url-classifier/SafeBrowsing.jsm toolkit/components/url-classifier/SafeBrowsing.jsm +index 64b8dd35de03..29d2a46fe72c 100644 +--- toolkit/components/url-classifier/SafeBrowsing.jsm ++++ toolkit/components/url-classifier/SafeBrowsing.jsm +@@ -66,6 +66,7 @@ this.SafeBrowsing = { + Services.prefs.addObserver("privacy.trackingprotection", this); + Services.prefs.addObserver("urlclassifier", this); + Services.prefs.addObserver("plugins.flashBlock.enabled", this); ++ Services.prefs.addObserver("plugins.show_infobar", this); + + this.readPrefs(); + this.addMozEntries(); +@@ -151,7 +152,7 @@ this.SafeBrowsing = { + blockedEnabled: false, + trackingAnnotations: false, + flashBlockEnabled: false, +- flashInfobarListEnabled: true, ++ flashInfobarListEnabled: false, + + phishingLists: [], + malwareLists: [], +@@ -231,6 +232,7 @@ this.SafeBrowsing = { + this.blockedEnabled = Services.prefs.getBoolPref("browser.safebrowsing.blockedURIs.enabled"); + this.trackingAnnotations = Services.prefs.getBoolPref("privacy.trackingprotection.annotate_channels"); + this.flashBlockEnabled = Services.prefs.getBoolPref("plugins.flashBlock.enabled"); ++ this.flashInfobarListEnabled = Services.prefs.getBoolPref("plugins.show_infobar", false); + + let flashAllowTable, flashAllowExceptTable, flashTable, + flashExceptTable, flashSubDocTable, diff --git a/www/waterfox/files/patch-bug1435286 b/www/waterfox/files/patch-bug1435286 new file mode 100644 index 000000000000..4aa4aa1f8aa3 --- /dev/null +++ b/www/waterfox/files/patch-bug1435286 @@ -0,0 +1,294 @@ +commit 63d4e507c859 +Author: Jonathan Watt <jwatt@jwatt.org> +Date: Thu Jan 18 12:45:18 2018 +0000 + + Bug 1435286 - Stop recording draw events for reference DrawTargets returned from PrintTarget. r=bobowen a=RyanVM + + MozReview-Commit-ID: 1cE71hBCGx5 + + --HG-- + extra : source : 2ec583a00c078700add6a3615f6b6af12756695c +--- + gfx/src/nsDeviceContext.cpp | 9 ++++----- + gfx/thebes/PrintTarget.cpp | 24 +----------------------- + gfx/thebes/PrintTarget.h | 13 ++----------- + gfx/thebes/PrintTargetCG.h | 2 +- + gfx/thebes/PrintTargetCG.mm | 23 +---------------------- + gfx/thebes/PrintTargetEMF.cpp | 4 ++-- + gfx/thebes/PrintTargetEMF.h | 2 +- + gfx/thebes/PrintTargetSkPDF.cpp | 23 +---------------------- + gfx/thebes/PrintTargetSkPDF.h | 2 +- + gfx/thebes/PrintTargetThebes.cpp | 23 +---------------------- + gfx/thebes/PrintTargetThebes.h | 2 +- + 11 files changed, 16 insertions(+), 111 deletions(-) + +diff --git gfx/src/nsDeviceContext.cpp gfx/src/nsDeviceContext.cpp +index 913f46d272cc..ca5db861a303 100644 +--- gfx/src/nsDeviceContext.cpp ++++ gfx/src/nsDeviceContext.cpp +@@ -382,14 +382,13 @@ nsDeviceContext::CreateRenderingContextCommon(bool aWantReferenceContext) + MOZ_ASSERT(IsPrinterContext()); + MOZ_ASSERT(mWidth > 0 && mHeight > 0); + +- // This will usually be null, depending on the pref print.print_via_parent. +- RefPtr<DrawEventRecorder> recorder; +- mDeviceContextSpec->GetDrawEventRecorder(getter_AddRefs(recorder)); +- + RefPtr<gfx::DrawTarget> dt; + if (aWantReferenceContext) { +- dt = mPrintTarget->GetReferenceDrawTarget(recorder); ++ dt = mPrintTarget->GetReferenceDrawTarget(); + } else { ++ // This will be null if e10s is disabled or print.print_via_parent=false. ++ RefPtr<DrawEventRecorder> recorder; ++ mDeviceContextSpec->GetDrawEventRecorder(getter_AddRefs(recorder)); + dt = mPrintTarget->MakeDrawTarget(gfx::IntSize(mWidth, mHeight), recorder); + } + +diff --git gfx/thebes/PrintTarget.cpp gfx/thebes/PrintTarget.cpp +index bb81158e5b77..c76a930221bf 100644 +--- gfx/thebes/PrintTarget.cpp ++++ gfx/thebes/PrintTarget.cpp +@@ -25,7 +25,6 @@ PrintTarget::PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize) + , mIsFinished(false) + #ifdef DEBUG + , mHasActivePage(false) +- , mRecorder(nullptr) + #endif + + { +@@ -92,7 +91,7 @@ PrintTarget::MakeDrawTarget(const IntSize& aSize, + } + + already_AddRefed<DrawTarget> +-PrintTarget::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) ++PrintTarget::GetReferenceDrawTarget() + { + if (!mRefDT) { + const IntSize size(1, 1); +@@ -136,27 +135,6 @@ PrintTarget::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) + mRefDT = dt.forget(); + } + +- if (aRecorder) { +- if (!mRecordingRefDT) { +- RefPtr<DrawTarget> dt = CreateWrapAndRecordDrawTarget(aRecorder, mRefDT); +- if (!dt || !dt->IsValid()) { +- return nullptr; +- } +- mRecordingRefDT = dt.forget(); +-#ifdef DEBUG +- mRecorder = aRecorder; +-#endif +- } +-#ifdef DEBUG +- else { +- MOZ_ASSERT(aRecorder == mRecorder, +- "Caching mRecordingRefDT assumes the aRecorder is an invariant"); +- } +-#endif +- +- return do_AddRef(mRecordingRefDT); +- } +- + return do_AddRef(mRefDT); + } + +diff --git gfx/thebes/PrintTarget.h gfx/thebes/PrintTarget.h +index c5720c6cdb1f..818dc31fe0c4 100644 +--- gfx/thebes/PrintTarget.h ++++ gfx/thebes/PrintTarget.h +@@ -130,10 +130,9 @@ public: + /** + * Returns a reference DrawTarget. Unlike MakeDrawTarget, this method is not + * restricted to being called between BeginPage()/EndPage() calls, and the +- * returned DrawTarget it is still valid to use after EndPage() has been +- * called. ++ * returned DrawTarget is still valid to use after EndPage() has been called. + */ +- virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget(DrawEventRecorder* aRecorder); ++ virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget(); + + protected: + +@@ -150,18 +149,10 @@ protected: + cairo_surface_t* mCairoSurface; + RefPtr<DrawTarget> mRefDT; // reference DT + +- // Early on during printing we expect to be called without a recorder in +- // order to gather metrics for reflow. However, in a content process, once +- // we go on to paint we then expect to be called with a recorder. Hence why +- // we have this separate recording reference DrawTarget (which wraps mRefDT). +- RefPtr<DrawTarget> mRecordingRefDT; +- + IntSize mSize; + bool mIsFinished; + #ifdef DEBUG + bool mHasActivePage; +- // owned by mRecordingRefDT, so kept alive for our entire lifetime if set: +- DrawEventRecorder* mRecorder; + #endif + }; + +diff --git gfx/thebes/PrintTargetCG.h gfx/thebes/PrintTargetCG.h +index 8e0d2c505024..7808ebbd2a58 100644 +--- gfx/thebes/PrintTargetCG.h ++++ gfx/thebes/PrintTargetCG.h +@@ -34,7 +34,7 @@ public: + virtual nsresult EndPage() final; + + virtual already_AddRefed<DrawTarget> +- GetReferenceDrawTarget(DrawEventRecorder* aRecorder) final; ++ GetReferenceDrawTarget() final; + + private: + PrintTargetCG(PMPrintSession aPrintSession, +diff --git gfx/thebes/PrintTargetCG.mm gfx/thebes/PrintTargetCG.mm +index 7a7858f71456..93432711ed3d 100644 +--- gfx/thebes/PrintTargetCG.mm ++++ gfx/thebes/PrintTargetCG.mm +@@ -65,7 +65,7 @@ PutBytesNull(void* info, const void* buffer, size_t count) + } + + already_AddRefed<DrawTarget> +-PrintTargetCG::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) ++PrintTargetCG::GetReferenceDrawTarget() + { + if (!mRefDT) { + const IntSize size(1, 1); +@@ -97,27 +97,6 @@ PrintTargetCG::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) + mRefDT = dt.forget(); + } + +- if (aRecorder) { +- if (!mRecordingRefDT) { +- RefPtr<DrawTarget> dt = CreateWrapAndRecordDrawTarget(aRecorder, mRefDT); +- if (!dt || !dt->IsValid()) { +- return nullptr; +- } +- mRecordingRefDT = dt.forget(); +-#ifdef DEBUG +- mRecorder = aRecorder; +-#endif +- } +-#ifdef DEBUG +- else { +- MOZ_ASSERT(aRecorder == mRecorder, +- "Caching mRecordingRefDT assumes the aRecorder is an invariant"); +- } +-#endif +- +- return do_AddRef(mRecordingRefDT); +- } +- + return do_AddRef(mRefDT); + } + +diff --git gfx/thebes/PrintTargetSkPDF.cpp gfx/thebes/PrintTargetSkPDF.cpp +index bdc6f9fec21f..e89afaea5d47 100644 +--- gfx/thebes/PrintTargetSkPDF.cpp ++++ gfx/thebes/PrintTargetSkPDF.cpp +@@ -122,7 +122,7 @@ PrintTargetSkPDF::MakeDrawTarget(const IntSize& aSize, + } + + already_AddRefed<DrawTarget> +-PrintTargetSkPDF::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) ++PrintTargetSkPDF::GetReferenceDrawTarget() + { + if (!mRefDT) { + SkDocument::PDFMetadata metadata; +@@ -145,27 +145,6 @@ PrintTargetSkPDF::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) + mRefDT = dt.forget(); + } + +- if (aRecorder) { +- if (!mRecordingRefDT) { +- RefPtr<DrawTarget> dt = CreateWrapAndRecordDrawTarget(aRecorder, mRefDT); +- if (!dt || !dt->IsValid()) { +- return nullptr; +- } +- mRecordingRefDT = dt.forget(); +-#ifdef DEBUG +- mRecorder = aRecorder; +-#endif +- } +-#ifdef DEBUG +- else { +- MOZ_ASSERT(aRecorder == mRecorder, +- "Caching mRecordingRefDT assumes the aRecorder is an invariant"); +- } +-#endif +- +- return do_AddRef(mRecordingRefDT); +- } +- + return do_AddRef(mRefDT); + } + +diff --git gfx/thebes/PrintTargetSkPDF.h gfx/thebes/PrintTargetSkPDF.h +index fe5f28b31202..84ef2ff21ace 100644 +--- gfx/thebes/PrintTargetSkPDF.h ++++ gfx/thebes/PrintTargetSkPDF.h +@@ -44,7 +44,7 @@ public: + DrawEventRecorder* aRecorder = nullptr) final; + + virtual already_AddRefed<DrawTarget> +- GetReferenceDrawTarget(DrawEventRecorder* aRecorder) override final; ++ GetReferenceDrawTarget() override final; + + private: + PrintTargetSkPDF(const IntSize& aSize, +diff --git gfx/thebes/PrintTargetThebes.cpp gfx/thebes/PrintTargetThebes.cpp +index 3cb6d1e5d6b7..f12a7d5b3fb9 100644 +--- gfx/thebes/PrintTargetThebes.cpp ++++ gfx/thebes/PrintTargetThebes.cpp +@@ -57,7 +57,7 @@ PrintTargetThebes::MakeDrawTarget(const IntSize& aSize, + } + + already_AddRefed<DrawTarget> +-PrintTargetThebes::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) ++PrintTargetThebes::GetReferenceDrawTarget() + { + if (!mRefDT) { + RefPtr<gfx::DrawTarget> dt = +@@ -68,27 +68,6 @@ PrintTargetThebes::GetReferenceDrawTarget(DrawEventRecorder* aRecorder) + mRefDT = dt->CreateSimilarDrawTarget(IntSize(1,1), dt->GetFormat()); + } + +- if (aRecorder) { +- if (!mRecordingRefDT) { +- RefPtr<DrawTarget> dt = CreateWrapAndRecordDrawTarget(aRecorder, mRefDT); +- if (!dt || !dt->IsValid()) { +- return nullptr; +- } +- mRecordingRefDT = dt.forget(); +-#ifdef DEBUG +- mRecorder = aRecorder; +-#endif +- } +-#ifdef DEBUG +- else { +- MOZ_ASSERT(aRecorder == mRecorder, +- "Caching mRecordingRefDT assumes the aRecorder is an invariant"); +- } +-#endif +- +- return do_AddRef(mRecordingRefDT); +- } +- + return do_AddRef(mRefDT); + } + +diff --git gfx/thebes/PrintTargetThebes.h gfx/thebes/PrintTargetThebes.h +index 02f0e0ea51c3..94ffbc78fa6c 100644 +--- gfx/thebes/PrintTargetThebes.h ++++ gfx/thebes/PrintTargetThebes.h +@@ -43,7 +43,7 @@ public: + MakeDrawTarget(const IntSize& aSize, + DrawEventRecorder* aRecorder = nullptr) override; + +- virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget(DrawEventRecorder* aRecorder) final; ++ virtual already_AddRefed<DrawTarget> GetReferenceDrawTarget() final; + + private: + diff --git a/www/waterfox/files/patch-bug1435320 b/www/waterfox/files/patch-bug1435320 new file mode 100644 index 000000000000..0a56c51027f7 --- /dev/null +++ b/www/waterfox/files/patch-bug1435320 @@ -0,0 +1,42 @@ +commit 8b513c9c65e5 +Author: Ian Moody <moz-ian@perix.co.uk> +Date: Fri Feb 2 17:50:09 2018 +0000 + + Bug 1435320 - Specify a default empty object for the Chart.js table header. r=Honza a=lizzard + + So it doesn't break if one isn't supplied. + Also document the header argument. + + MozReview-Commit-ID: 8UAVztN12Gw + + --HG-- + extra : source : 353a5c7a0bb3e975a299a340692a79342a87adcb +--- + devtools/client/shared/widgets/Chart.js | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git devtools/client/shared/widgets/Chart.js devtools/client/shared/widgets/Chart.js +index 069fc673e8f6..acc7bfa28a25 100644 +--- devtools/client/shared/widgets/Chart.js ++++ devtools/client/shared/widgets/Chart.js +@@ -322,6 +322,12 @@ function createPieChart(document, { data, width, height, centerX, centerY, radiu + * label1: total => l10n.getFormatStr("...", total), // 5 + * label2: total => l10n.getFormatStr("...", total), // 9 + * } ++ * - header: an object specifying strings to use for table column ++ * headers ++ * e.g. { ++ * label1: l10n.getStr(...), ++ * label2: l10n.getStr(...), ++ * } + * @return TableChart + * A table chart proxy instance, which emits the following events: + * - "mouseover", when the mouse enters a row +@@ -331,6 +337,7 @@ function createPieChart(document, { data, width, height, centerX, centerY, radiu + function createTableChart(document, { title, data, strings, totals, header }) { + strings = strings || {}; + totals = totals || {}; ++ header = header || {}; + let isPlaceholder = false; + + // If there's no data available, display an empty placeholder. diff --git a/www/waterfox/files/patch-bug1435530 b/www/waterfox/files/patch-bug1435530 new file mode 100644 index 000000000000..7c0439dab359 --- /dev/null +++ b/www/waterfox/files/patch-bug1435530 @@ -0,0 +1,208 @@ +commit 16b8e12f668d +Author: Masayuki Nakano <masayuki@d-toybox.com> +Date: Mon Feb 5 18:01:25 2018 +0900 + + Bug 1435530 - part 1: Add automated tests to check Alt + D works as Ctrl + L when Alt is content access key's modifier r=enndeakin+6102 a=test-only + + MozReview-Commit-ID: FG5sRJfTvue + + --HG-- + extra : source : 1f89e76b2f3d31cea096b0c9e52000843b8a13d7 +--- + dom/events/moz.build | 4 ++ + dom/events/test/browser.ini | 4 ++ + ...er_conflicts_with_content_accesskey_modifier.js | 77 ++++++++++++++++++++++ + 3 files changed, 85 insertions(+) + +diff --git dom/events/moz.build dom/events/moz.build +index 16f75923c120..159635d47b89 100644 +--- dom/events/moz.build ++++ dom/events/moz.build +@@ -7,6 +7,10 @@ + with Files("**"): + BUG_COMPONENT = ("Core", "DOM: Events") + ++BROWSER_CHROME_MANIFESTS += [ ++ 'test/browser.ini', ++] ++ + MOCHITEST_MANIFESTS += [ + 'test/mochitest.ini', + 'test/pointerevents/mochitest.ini', +diff --git dom/events/test/browser.ini dom/events/test/browser.ini +new file mode 100644 +index 000000000000..71a61b5cdddb +--- /dev/null ++++ dom/events/test/browser.ini +@@ -0,0 +1,4 @@ ++[DEFAULT] ++ ++[browser_shortcutkey_modifier_conflicts_with_content_accesskey_modifier.js] ++skip-if = os != 'linux' && os != 'win' // Alt + D is defined only on Linux and Windows +diff --git dom/events/test/browser_shortcutkey_modifier_conflicts_with_content_accesskey_modifier.js dom/events/test/browser_shortcutkey_modifier_conflicts_with_content_accesskey_modifier.js +new file mode 100644 +index 000000000000..d458740dad3e +--- /dev/null ++++ dom/events/test/browser_shortcutkey_modifier_conflicts_with_content_accesskey_modifier.js +@@ -0,0 +1,77 @@ ++add_task(async function() { ++ // Even if modifier of a shortcut key same as modifier of content access key, ++ // the shortcut key should be executed if (remote) content doesn't handle it. ++ // This test uses existing shortcut key declaration on Linux and Windows. ++ // If you remove or change Alt + D, you need to keep check this with changing ++ // the pref or result check. ++ ++ await new Promise(resolve => { ++ SpecialPowers.pushPrefEnv({"set": [["ui.key.generalAccessKey", -1], ++ ["ui.key.chromeAccess", 0 /* disabled */], ++ ["ui.key.contentAccess", 4 /* Alt */], ++ ["browser.search.widget.inNavBar", true]]}, ++ resolve); ++ }); ++ ++ const kTestPage = "data:text/html,<body>simple web page</body>"; ++ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kTestPage); ++ ++ let searchBar = BrowserSearch.searchBar; ++ searchBar.focus(); ++ ++ function promiseURLBarHasFocus() { ++ return new Promise(resolve => { ++ if (gURLBar.focused) { ++ ok(true, "The URL bar already has focus"); ++ resolve(); ++ return; ++ } ++ info("Waiting focus event..."); ++ gURLBar.addEventListener("focus", () => { ++ ok(true, "The URL bar gets focus"); ++ resolve(); ++ }, {once: true}); ++ }); ++ } ++ ++ function promiseURLBarSelectsAllText() { ++ return new Promise(resolve => { ++ function isAllTextSelected() { ++ return gURLBar.inputField.selectionStart === 0 && ++ gURLBar.inputField.selectionEnd === gURLBar.inputField.value.length; ++ } ++ if (isAllTextSelected()) { ++ ok(true, "All text of the URL bar is already selected"); ++ isnot(gURLBar.inputField.value, "", "The URL bar should have non-empty text"); ++ resolve(); ++ return; ++ } ++ info("Waiting selectionchange event..."); ++ gURLBar.addEventListener("selectionchange", () => { ++ ok(isAllTextSelected(), "All text of the URL bar should be selected"); ++ isnot(gURLBar.inputField.value, "", "The URL bar should have non-empty text"); ++ resolve(); ++ }, {once: true}); ++ }); ++ } ++ ++ // Alt + D is a shortcut key to move focus to the URL bar and selects its text. ++ info("Pressing Alt + D in the search bar..."); ++ EventUtils.synthesizeKey("d", {code: "KeyD", altKey: true}); ++ ++ await promiseURLBarHasFocus(); ++ await promiseURLBarSelectsAllText(); ++ ++ // Alt + D in the URL bar should select all text in it. ++ await gURLBar.focus(); ++ await promiseURLBarHasFocus(); ++ gURLBar.inputField.selectionStart = gURLBar.inputField.selectionEnd = ++ gURLBar.inputField.value.length; ++ ++ info("Pressing Alt + D in the URL bar..."); ++ EventUtils.synthesizeKey("d", {code: "KeyD", altKey: true}); ++ await promiseURLBarHasFocus(); ++ await promiseURLBarSelectsAllText(); ++ ++ gBrowser.removeCurrentTab(); ++}); + +commit d48b9f93766d +Author: Masayuki Nakano <masayuki@d-toybox.com> +Date: Mon Feb 5 18:27:30 2018 +0900 + + Bug 1435530 - part 2: Make nsXBLWindowKeyHandler treat eAccessKeyNotFound as eKeyPress event r=enndeakin+6102 a=lizzard + + Modifiers of shortcut keys may be same as modifier of content access keys. + + When focus is in the main process, such eKeyPress event is sent to remote + content first. Then, and if it's not handled in the remote content, + eAccessKeyNotFound is dispatched into the DOM tree in the main process. + However, nsXBLWindowKeyHandler doesn't handle it as eKeyPress event. So, + it causes that shortcut keys whose modifier conflicts with content access key + won't be handled. + + This patch just makes nsXBLWindowKeyHandler treat eAccessKeyNotFound as + eKeyPress event even though other shortcut keys which are handled by JS + won't be executed. Perhaps, we should stop using eAccessKeyNotFound but + it's too risky change for now. + + MozReview-Commit-ID: IJltg5gwBc5 + + --HG-- + extra : source : 48bca44fe6a6e88f941a1a5ab2a41a041346fa21 +--- + dom/ipc/TabParent.cpp | 1 + + dom/xbl/nsXBLWindowKeyHandler.cpp | 17 ++++++++++++++++- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git dom/ipc/TabParent.cpp dom/ipc/TabParent.cpp +index d63a2ba595cd..ecb359f2a6be 100644 +--- dom/ipc/TabParent.cpp ++++ dom/ipc/TabParent.cpp +@@ -2244,6 +2244,7 @@ TabParent::RecvAccessKeyNotHandled(const WidgetKeyboardEvent& aEvent) + // twice or more for a keyboard event, that must be a bug. But how to + // detect if received event has already been handled? + ++ MOZ_ASSERT(aEvent.mMessage == eKeyPress); + WidgetKeyboardEvent localEvent(aEvent); + localEvent.MarkAsHandledInRemoteProcess(); + localEvent.mMessage = eAccessKeyNotFound; +diff --git dom/xbl/nsXBLWindowKeyHandler.cpp dom/xbl/nsXBLWindowKeyHandler.cpp +index dffb53b9a7e9..1c035d142836 100644 +--- dom/xbl/nsXBLWindowKeyHandler.cpp ++++ dom/xbl/nsXBLWindowKeyHandler.cpp +@@ -356,6 +356,12 @@ nsXBLWindowKeyHandler::InstallKeyboardEventListenersTo( + aEventListenerManager->AddEventListenerByType( + this, NS_LITERAL_STRING("keypress"), + TrustedEventsAtSystemGroupBubble()); ++ // mozaccesskeynotfound event is fired when modifiers of keypress event ++ // matches with modifier of content access key but it's not consumed by ++ // remote content. ++ aEventListenerManager->AddEventListenerByType( ++ this, NS_LITERAL_STRING("mozaccesskeynotfound"), ++ TrustedEventsAtSystemGroupBubble()); + aEventListenerManager->AddEventListenerByType( + this, NS_LITERAL_STRING("mozkeydownonplugin"), + TrustedEventsAtSystemGroupBubble()); +@@ -409,6 +415,9 @@ nsXBLWindowKeyHandler::RemoveKeyboardEventListenersFrom( + aEventListenerManager->RemoveEventListenerByType( + this, NS_LITERAL_STRING("keypress"), + TrustedEventsAtSystemGroupBubble()); ++ aEventListenerManager->RemoveEventListenerByType( ++ this, NS_LITERAL_STRING("mozaccesskeynotfound"), ++ TrustedEventsAtSystemGroupBubble()); + aEventListenerManager->RemoveEventListenerByType( + this, NS_LITERAL_STRING("mozkeydownonplugin"), + TrustedEventsAtSystemGroupBubble()); +@@ -465,7 +474,13 @@ nsXBLWindowKeyHandler::ConvertEventToDOMEventType( + if (aWidgetKeyboardEvent.IsKeyUpOrKeyUpOnPlugin()) { + return nsGkAtoms::keyup; + } +- if (aWidgetKeyboardEvent.mMessage == eKeyPress) { ++ // eAccessKeyNotFound event is always created from eKeyPress event and ++ // the original eKeyPress event has stopped its propagation before dispatched ++ // into the DOM tree in this process and not matched with remote content's ++ // access keys. So, we should treat it as an eKeyPress event and execute ++ // a command if it's registered as a shortcut key. ++ if (aWidgetKeyboardEvent.mMessage == eKeyPress || ++ aWidgetKeyboardEvent.mMessage == eAccessKeyNotFound) { + return nsGkAtoms::keypress; + } + MOZ_ASSERT_UNREACHABLE( diff --git a/www/waterfox/files/patch-bug1435859 b/www/waterfox/files/patch-bug1435859 new file mode 100644 index 000000000000..bf87b95869e9 --- /dev/null +++ b/www/waterfox/files/patch-bug1435859 @@ -0,0 +1,38 @@ +commit 58a5fb56c33a +Author: Francois Marier <francois@mozilla.com> +Date: Thu Feb 15 12:30:40 2018 -0800 + + Bug 1435859 - Fix OOM crash on filenames without extensions. r=gcp, a=RyanVM + + Passing a value of -1 to nsCString::Truncate() converts that + value to a large integer and leads to an unnecessary 4GB + memory allocation. + + MozReview-Commit-ID: Icm5iUsEgA6 + + --HG-- + extra : source : d418ce8a05644edb16f317c13fc1c8cd2b6c3c2f +--- + toolkit/components/url-classifier/Classifier.cpp | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git toolkit/components/url-classifier/Classifier.cpp toolkit/components/url-classifier/Classifier.cpp +index 9946469268fa..d5ba67fe300a 100644 +--- toolkit/components/url-classifier/Classifier.cpp ++++ toolkit/components/url-classifier/Classifier.cpp +@@ -359,8 +359,13 @@ Classifier::DeleteTables(nsIFile* aDirectory, const nsTArray<nsCString>& aTables + rv = file->GetNativeLeafName(leafName); + NS_ENSURE_SUCCESS_VOID(rv); + +- leafName.Truncate(leafName.RFind(".")); +- if (aTables.Contains(leafName)) { ++ // Remove file extension if there's one. ++ int32_t dotPosition = leafName.RFind("."); ++ if (dotPosition >= 0) { ++ leafName.Truncate(dotPosition); ++ } ++ ++ if (!leafName.IsEmpty() && aTables.Contains(leafName)) { + if (NS_FAILED(file->Remove(false))) { + NS_WARNING(nsPrintfCString("Fail to remove file %s from the disk", + leafName.get()).get()); diff --git a/www/waterfox/files/patch-bug1436117 b/www/waterfox/files/patch-bug1436117 new file mode 100644 index 000000000000..ac4b9cd4bd3d --- /dev/null +++ b/www/waterfox/files/patch-bug1436117 @@ -0,0 +1,42 @@ +commit 34646edc7884 +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Mon Feb 26 10:32:29 2018 +0100 + + Bug 1436117 - Keep aImage around until the WrappedI420Buffer is released. r=dminor + + MozReview-Commit-ID: GuBHFnPA3YQ + + --HG-- + extra : rebase_source : e5cc3c1d5e0f08279e8c40ebf03ef7e535cfe5e5 +--- + media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +index 2bb7203f85bd0..cfaadaaa7ff73 100644 +--- media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp ++++ media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +@@ -57,6 +57,7 @@ + #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" + #include "webrtc/common_video/include/video_frame_buffer.h" + #include "webrtc/base/bind.h" ++#include "webrtc/base/keep_ref_until_done.h" + + #include "nsThreadUtils.h" + +@@ -336,14 +337,13 @@ protected: + uint32_t width = yuv->GetSize().width; + uint32_t height = yuv->GetSize().height; + +- rtc::Callback0<void> callback_unused; + rtc::scoped_refptr<webrtc::WrappedI420Buffer> video_frame_buffer( + new rtc::RefCountedObject<webrtc::WrappedI420Buffer>( + width, height, + y, yStride, + cb, cbCrStride, + cr, cbCrStride, +- callback_unused)); ++ rtc::KeepRefUntilDone(aImage))); + + webrtc::VideoFrame i420_frame(video_frame_buffer, + 0, 0, // not setting timestamps diff --git a/www/waterfox/files/patch-bug1436768 b/www/waterfox/files/patch-bug1436768 new file mode 100644 index 000000000000..4cc959e92953 --- /dev/null +++ b/www/waterfox/files/patch-bug1436768 @@ -0,0 +1,106 @@ +commit 885fcfb6c9fe +Author: Eric Rahm <erahm@mozilla.com> +Date: Thu Feb 8 16:25:07 2018 -0800 + + Bug 1436768 - Avoid initializing LogModuleManager more than once. r=froydnj a=RyanVM + + This adds some assertions to make the intended usage of LogModuleManager::Init + more clear. + + --HG-- + extra : source : ec9f62910277ae252c3fb32166358419afb96b34 +--- + xpcom/base/Logging.cpp | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git xpcom/base/Logging.cpp xpcom/base/Logging.cpp +index 9d6a6d9ea861..eca3e97ee61e 100644 +--- xpcom/base/Logging.cpp ++++ xpcom/base/Logging.cpp +@@ -16,6 +16,7 @@ + #include "mozilla/Atomics.h" + #include "mozilla/Sprintf.h" + #include "mozilla/UniquePtrExtensions.h" ++#include "MainThreadUtils.h" + #include "nsClassHashtable.h" + #include "nsDebug.h" + #include "NSPRLogModulesParser.h" +@@ -179,6 +180,7 @@ public: + , mAddTimestamp(false) + , mIsSync(false) + , mRotate(0) ++ , mInitialized(false) + { + } + +@@ -190,9 +192,17 @@ public: + + /** + * Loads config from env vars if present. ++ * ++ * Notes: ++ * ++ * 1) This function is only intended to be called once per session. ++ * 2) None of the functions used in Init should rely on logging. + */ + void Init() + { ++ MOZ_DIAGNOSTIC_ASSERT(!mInitialized); ++ mInitialized = true; ++ + bool shouldAppend = false; + bool addTimestamp = false; + bool isSync = false; +@@ -213,8 +223,10 @@ public: + } + } + ++ // Need to capture `this` since `sLogModuleManager` is not set until after ++ // initialization is complete. + NSPRLogModulesParser(modules, +- [&shouldAppend, &addTimestamp, &isSync, &rotate] ++ [this, &shouldAppend, &addTimestamp, &isSync, &rotate] + (const char* aName, LogLevel aLevel, int32_t aValue) mutable { + if (strcmp(aName, "append") == 0) { + shouldAppend = true; +@@ -225,7 +237,7 @@ public: + } else if (strcmp(aName, "rotate") == 0) { + rotate = (aValue << 20) / kRotateFilesNumber; + } else { +- LogModule::Get(aName)->SetLevel(aLevel); ++ this->CreateOrGetModule(aName)->SetLevel(aLevel); + } + }); + +@@ -513,6 +525,7 @@ private: + Atomic<bool, Relaxed> mAddTimestamp; + Atomic<bool, Relaxed> mIsSync; + int32_t mRotate; ++ bool mInitialized; + }; + + StaticAutoPtr<LogModuleManager> sLogModuleManager; +@@ -557,6 +570,8 @@ LogModule::Init() + { + // NB: This method is not threadsafe; it is expected to be called very early + // in startup prior to any other threads being run. ++ MOZ_DIAGNOSTIC_ASSERT(NS_IsMainThread()); ++ + if (sLogModuleManager) { + // Already initialized. + return; +@@ -565,8 +580,12 @@ LogModule::Init() + // NB: We intentionally do not register for ClearOnShutdown as that happens + // before all logging is complete. And, yes, that means we leak, but + // we're doing that intentionally. +- sLogModuleManager = new LogModuleManager(); +- sLogModuleManager->Init(); ++ ++ // Don't assign the pointer until after Init is called. This should help us ++ // detect if any of the functions called by Init somehow rely on logging. ++ auto mgr = new LogModuleManager(); ++ mgr->Init(); ++ sLogModuleManager = mgr; + } + + void diff --git a/www/waterfox/files/patch-bug1437087 b/www/waterfox/files/patch-bug1437087 new file mode 100644 index 000000000000..8c55a149d5f7 --- /dev/null +++ b/www/waterfox/files/patch-bug1437087 @@ -0,0 +1,88 @@ +commit a2e5898c8de8 +Author: Makoto Kato <m_kato@ga2.so-net.ne.jp> +Date: Thu Feb 22 13:43:19 2018 +0200 + + Bug 1437087 - Call Disconnect on Unlink of cycle collector. r=masayuki a=abillings +--- + editor/libeditor/EditorBase.cpp | 17 +++++++++-------- + editor/libeditor/EditorBase.h | 4 ++-- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git editor/libeditor/EditorBase.cpp editor/libeditor/EditorBase.cpp +index 5cb7d62d9982..a30528fc6ebf 100644 +--- editor/libeditor/EditorBase.cpp ++++ editor/libeditor/EditorBase.cpp +@@ -168,7 +168,12 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(EditorBase) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mEditorObservers) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocStateListeners) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventTarget) +- NS_IMPL_CYCLE_COLLECTION_UNLINK(mEventListener) ++ ++ if (tmp->mEventListener) { ++ tmp->mEventListener->Disconnect(); ++ tmp->mEventListener = nullptr; ++ } ++ + NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaceholderTransaction) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mSavedSel); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mRangeUpdater); +@@ -318,9 +323,7 @@ EditorBase::PostCreate() + // If the text control gets reframed during focus, Focus() would not be + // called, so take a chance here to see if we need to spell check the text + // control. +- EditorEventListener* listener = +- reinterpret_cast<EditorEventListener*>(mEventListener.get()); +- listener->SpellCheckIfNeeded(); ++ mEventListener->SpellCheckIfNeeded(); + + IMEState newState; + rv = GetPreferredIMEState(&newState); +@@ -358,9 +361,7 @@ EditorBase::InstallEventListeners() + mEventTarget = do_QueryInterface(rootContent->GetParent()); + NS_ENSURE_TRUE(mEventTarget, NS_ERROR_NOT_AVAILABLE); + +- EditorEventListener* listener = +- reinterpret_cast<EditorEventListener*>(mEventListener.get()); +- nsresult rv = listener->Connect(this); ++ nsresult rv = mEventListener->Connect(this); + if (mComposition) { + // Restart to handle composition with new editor contents. + mComposition->StartHandlingComposition(this); +@@ -374,7 +375,7 @@ EditorBase::RemoveEventListeners() + if (!IsInitialized() || !mEventListener) { + return; + } +- reinterpret_cast<EditorEventListener*>(mEventListener.get())->Disconnect(); ++ mEventListener->Disconnect(); + if (mComposition) { + // Even if this is called, don't release mComposition because this is + // may be reused after reframing. +diff --git editor/libeditor/EditorBase.h editor/libeditor/EditorBase.h +index c59fbd0b0e71..91d390ae5d80 100644 +--- editor/libeditor/EditorBase.h ++++ editor/libeditor/EditorBase.h +@@ -37,7 +37,6 @@ class nsAtom; + class nsIContent; + class nsIDOMDocument; + class nsIDOMEvent; +-class nsIDOMEventListener; + class nsIDOMEventTarget; + class nsIDOMNode; + class nsIDocumentStateListener; +@@ -114,6 +113,7 @@ class CreateElementTransaction; + class DeleteNodeTransaction; + class DeleteTextTransaction; + class EditAggregateTransaction; ++class EditorEventListener; + class EditTransactionBase; + class ErrorResult; + class HTMLEditor; +@@ -1449,7 +1449,7 @@ protected: + nsCOMPtr<Element> mRootElement; + // The form field as an event receiver. + nsCOMPtr<dom::EventTarget> mEventTarget; +- nsCOMPtr<nsIDOMEventListener> mEventListener; ++ RefPtr<EditorEventListener> mEventListener; + // Strong reference to placeholder for begin/end batch purposes. + RefPtr<PlaceholderTransaction> mPlaceholderTransaction; + // Name of placeholder transaction. diff --git a/www/waterfox/files/patch-bug1437214 b/www/waterfox/files/patch-bug1437214 new file mode 100644 index 000000000000..eff3a47f7764 --- /dev/null +++ b/www/waterfox/files/patch-bug1437214 @@ -0,0 +1,217 @@ +commit 8fdc2449bfe2 +Author: David Keeler <dkeeler@mozilla.com> +Date: Fri Feb 9 16:35:54 2018 -0800 + + bug 1437214 - if PathBuildingStep::Check fails due to a problem with the subject certificate rather than the potential issuer, set keepGoing to false r=jcj a=RyanVM + + MozReview-Commit-ID: DEr4YgXfkOL + + --HG-- + extra : source : f2669a2b5934ac8e5637c3b96ab1f1dcdf502c00 +--- + security/pkix/lib/pkixbuild.cpp | 13 ++- + security/pkix/test/gtest/pkixbuild_tests.cpp | 163 +++++++++++++++++++++++++++ + 2 files changed, 174 insertions(+), 2 deletions(-) + +diff --git security/pkix/lib/pkixbuild.cpp security/pkix/lib/pkixbuild.cpp +index fd6a9d5115d4..0b33e3d5ae71 100644 +--- security/pkix/lib/pkixbuild.cpp ++++ security/pkix/lib/pkixbuild.cpp +@@ -241,7 +241,12 @@ PathBuildingStep::Check(Input potentialIssuerDER, + validityDuration, stapledOCSPResponse, + subject.GetAuthorityInfoAccess()); + if (rv != Success) { +- return RecordResult(rv, keepGoing); ++ // Since this is actually a problem with the current subject certificate ++ // (rather than the issuer), it doesn't make sense to keep going; all ++ // paths through this certificate will fail. ++ Result savedRv = RecordResult(rv, keepGoing); ++ keepGoing = false; ++ return savedRv; + } + + if (subject.endEntityOrCA == EndEntityOrCA::MustBeEndEntity) { +@@ -251,7 +256,11 @@ PathBuildingStep::Check(Input potentialIssuerDER, + rv = ExtractSignedCertificateTimestampListFromExtension(*sctExtension, + sctList); + if (rv != Success) { +- return RecordResult(rv, keepGoing); ++ // Again, the problem is with this certificate, and all paths through ++ // it will fail. ++ Result savedRv = RecordResult(rv, keepGoing); ++ keepGoing = false; ++ return savedRv; + } + trustDomain.NoteAuxiliaryExtension(AuxiliaryExtension::EmbeddedSCTList, + sctList); +diff --git security/pkix/test/gtest/pkixbuild_tests.cpp security/pkix/test/gtest/pkixbuild_tests.cpp +index 64fa4c307c76..5948df7037a8 100644 +--- security/pkix/test/gtest/pkixbuild_tests.cpp ++++ security/pkix/test/gtest/pkixbuild_tests.cpp +@@ -582,3 +582,166 @@ TEST_F(pkixbuild, CertificateTransparencyExtension) + ASSERT_EQ(BytesToByteString(dummySctList), + extTrustDomain.signedCertificateTimestamps); + } ++ ++// This TrustDomain implements a hierarchy like so: ++// ++// A B ++// | | ++// C D ++// \ / ++// E ++// ++// where A is a trust anchor, B is not a trust anchor and has no known issuer, C ++// and D are intermediates with the same subject and subject public key, and E ++// is an end-entity (in practice, the end-entity will be generated by the test ++// functions using this trust domain). ++class MultiplePathTrustDomain: public DefaultCryptoTrustDomain ++{ ++public: ++ void SetUpCerts() ++ { ++ ASSERT_FALSE(ENCODING_FAILED(CreateCert("UntrustedRoot", "UntrustedRoot", ++ EndEntityOrCA::MustBeCA, ++ &subjectDERToCertDER))); ++ // The subject DER -> cert DER mapping would be overwritten for subject ++ // "Intermediate" when we create the second "Intermediate" certificate, so ++ // we keep a copy of this "Intermediate". ++ intermediateSignedByUntrustedRootCertDER = ++ CreateCert("UntrustedRoot", "Intermediate", EndEntityOrCA::MustBeCA); ++ ASSERT_FALSE(ENCODING_FAILED(intermediateSignedByUntrustedRootCertDER)); ++ rootCACertDER = CreateCert("TrustedRoot", "TrustedRoot", ++ EndEntityOrCA::MustBeCA, &subjectDERToCertDER); ++ ASSERT_FALSE(ENCODING_FAILED(rootCACertDER)); ++ ASSERT_FALSE(ENCODING_FAILED(CreateCert("TrustedRoot", "Intermediate", ++ EndEntityOrCA::MustBeCA, ++ &subjectDERToCertDER))); ++ } ++ ++private: ++ Result GetCertTrust(EndEntityOrCA, const CertPolicyId&, Input candidateCert, ++ /*out*/ TrustLevel& trustLevel) override ++ { ++ trustLevel = InputEqualsByteString(candidateCert, rootCACertDER) ++ ? TrustLevel::TrustAnchor ++ : TrustLevel::InheritsTrust; ++ return Success; ++ } ++ ++ Result CheckCert(ByteString& certDER, IssuerChecker& checker, bool& keepGoing) ++ { ++ Input derCert; ++ Result rv = derCert.Init(certDER.data(), certDER.length()); ++ if (rv != Success) { ++ return rv; ++ } ++ return checker.Check(derCert, nullptr/*additionalNameConstraints*/, ++ keepGoing); ++ } ++ ++ Result FindIssuer(Input encodedIssuerName, IssuerChecker& checker, Time) ++ override ++ { ++ ByteString subjectDER(InputToByteString(encodedIssuerName)); ++ ByteString certDER(subjectDERToCertDER[subjectDER]); ++ assert(!ENCODING_FAILED(certDER)); ++ bool keepGoing; ++ Result rv = CheckCert(certDER, checker, keepGoing); ++ if (rv != Success) { ++ return rv; ++ } ++ // Also try the other intermediate. ++ if (keepGoing) { ++ rv = CheckCert(intermediateSignedByUntrustedRootCertDER, checker, ++ keepGoing); ++ if (rv != Success) { ++ return rv; ++ } ++ } ++ return Success; ++ } ++ ++ Result CheckRevocation(EndEntityOrCA, const CertID&, Time, Duration, ++ /*optional*/ const Input*, ++ /*optional*/ const Input*) override ++ { ++ return Success; ++ } ++ ++ Result IsChainValid(const DERArray&, Time, const CertPolicyId&) override ++ { ++ return Success; ++ } ++ ++ std::map<ByteString, ByteString> subjectDERToCertDER; ++ ByteString rootCACertDER; ++ ByteString intermediateSignedByUntrustedRootCertDER; ++}; ++ ++TEST_F(pkixbuild, BadEmbeddedSCTWithMultiplePaths) ++{ ++ MultiplePathTrustDomain trustDomain; ++ trustDomain.SetUpCerts(); ++ ++ // python security/pkix/tools/DottedOIDToCode.py --tlv ++ // id-embeddedSctList 1.3.6.1.4.1.11129.2.4.2 ++ static const uint8_t tlv_id_embeddedSctList[] = { ++ 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x04, 0x02 ++ }; ++ static const uint8_t dummySctList[] = { ++ 0x01, 0x02, 0x03, 0x04, 0x05 ++ }; ++ ByteString ctExtension = TLV(der::SEQUENCE, ++ BytesToByteString(tlv_id_embeddedSctList) + ++ Boolean(false) + ++ // The contents of the OCTET STRING are supposed to consist of an OCTET ++ // STRING of useful data. We're testing what happens if it isn't, so shove ++ // some bogus (non-OCTET STRING) data in there. ++ TLV(der::OCTET_STRING, BytesToByteString(dummySctList))); ++ ByteString certDER(CreateCert("Intermediate", "Cert with bogus SCT list", ++ EndEntityOrCA::MustBeEndEntity, ++ nullptr, /*subjectDERToCertDER*/ ++ &ctExtension)); ++ ASSERT_FALSE(ENCODING_FAILED(certDER)); ++ Input certDERInput; ++ ASSERT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length())); ++ ASSERT_EQ(Result::ERROR_BAD_DER, ++ BuildCertChain(trustDomain, certDERInput, Now(), ++ EndEntityOrCA::MustBeEndEntity, ++ KeyUsage::noParticularKeyUsageRequired, ++ KeyPurposeId::id_kp_serverAuth, ++ CertPolicyId::anyPolicy, ++ nullptr/*stapledOCSPResponse*/)); ++} ++ ++// Same as a MultiplePathTrustDomain, but the end-entity is revoked. ++class RevokedEndEntityTrustDomain final : public MultiplePathTrustDomain ++{ ++public: ++ Result CheckRevocation(EndEntityOrCA endEntityOrCA, const CertID&, Time, ++ Duration, /*optional*/ const Input*, ++ /*optional*/ const Input*) override ++ { ++ if (endEntityOrCA == EndEntityOrCA::MustBeEndEntity) { ++ return Result::ERROR_REVOKED_CERTIFICATE; ++ } ++ return Success; ++ } ++}; ++ ++TEST_F(pkixbuild, RevokedEndEntityWithMultiplePaths) ++{ ++ RevokedEndEntityTrustDomain trustDomain; ++ trustDomain.SetUpCerts(); ++ ByteString certDER(CreateCert("Intermediate", "RevokedEndEntity", ++ EndEntityOrCA::MustBeEndEntity)); ++ ASSERT_FALSE(ENCODING_FAILED(certDER)); ++ Input certDERInput; ++ ASSERT_EQ(Success, certDERInput.Init(certDER.data(), certDER.length())); ++ ASSERT_EQ(Result::ERROR_REVOKED_CERTIFICATE, ++ BuildCertChain(trustDomain, certDERInput, Now(), ++ EndEntityOrCA::MustBeEndEntity, ++ KeyUsage::noParticularKeyUsageRequired, ++ KeyPurposeId::id_kp_serverAuth, ++ CertPolicyId::anyPolicy, ++ nullptr/*stapledOCSPResponse*/)); ++} diff --git a/www/waterfox/files/patch-bug1437450 b/www/waterfox/files/patch-bug1437450 new file mode 100644 index 000000000000..de4abc28fa8e --- /dev/null +++ b/www/waterfox/files/patch-bug1437450 @@ -0,0 +1,30 @@ +commit 0f7fe8623060 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Thu Mar 1 15:36:13 2018 +0100 + + Bug 1437450 - Disable Ion no-clone optimization for regexps if the graph contains try blocks. r=nbp, a=RyanVM + + --HG-- + extra : source : 61b461277369e0cec89c79d8526a82c575818e94 + extra : histedit_source : 6bc47921de07340f563a8d7d81b260579483c753 +--- + js/src/jit/IonAnalysis.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git js/src/jit/IonAnalysis.cpp js/src/jit/IonAnalysis.cpp +index ff8de4dc9a83..3bb7f5fa0754 100644 +--- js/src/jit/IonAnalysis.cpp ++++ js/src/jit/IonAnalysis.cpp +@@ -2231,6 +2231,12 @@ IsRegExpHoistable(MIRGenerator* mir, MDefinition* regexp, MDefinitionVector& wor + bool + jit::MakeMRegExpHoistable(MIRGenerator* mir, MIRGraph& graph) + { ++ // If we are compiling try blocks, regular expressions may be observable ++ // from catch blocks (which Ion does not compile). For now just disable the ++ // pass in this case. ++ if (graph.hasTryBlock()) ++ return true; ++ + MDefinitionVector worklist(graph.alloc()); + + for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) { diff --git a/www/waterfox/files/patch-bug1437507 b/www/waterfox/files/patch-bug1437507 new file mode 100644 index 000000000000..49defedde158 --- /dev/null +++ b/www/waterfox/files/patch-bug1437507 @@ -0,0 +1,38 @@ +commit 4286f0e17d94 +Author: Brian Hackett <bhackett1024@gmail.com> +Date: Fri Feb 23 13:25:53 2018 -0500 + + Bug 1437507 - Fix JSObject::setFlags to call ensureShape before checking for dictionary mode. r=jandem, a=RyanVM + + --HG-- + extra : source : ca6b74831ec3db204e024b07f200b0d1ce93557e +--- + js/src/vm/Shape.cpp | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git js/src/vm/Shape.cpp js/src/vm/Shape.cpp +index 3ea96877b5f2..51eff27e0d1a 100644 +--- js/src/vm/Shape.cpp ++++ js/src/vm/Shape.cpp +@@ -1329,6 +1329,10 @@ JSObject::setFlags(JSContext* cx, HandleObject obj, BaseShape::Flag flags, + if (obj->hasAllFlags(flags)) + return true; + ++ Shape* existingShape = obj->ensureShape(cx); ++ if (!existingShape) ++ return false; ++ + if (obj->isNative() && obj->as<NativeObject>().inDictionaryMode()) { + if (generateShape == GENERATE_SHAPE) { + if (!NativeObject::generateOwnShape(cx, obj.as<NativeObject>())) +@@ -1344,10 +1348,6 @@ JSObject::setFlags(JSContext* cx, HandleObject obj, BaseShape::Flag flags, + return true; + } + +- Shape* existingShape = obj->ensureShape(cx); +- if (!existingShape) +- return false; +- + Shape* newShape = Shape::setObjectFlags(cx, flags, obj->taggedProto(), existingShape); + if (!newShape) + return false; diff --git a/www/waterfox/files/patch-bug1437880 b/www/waterfox/files/patch-bug1437880 new file mode 100644 index 000000000000..f4bb934f7b57 --- /dev/null +++ b/www/waterfox/files/patch-bug1437880 @@ -0,0 +1,26 @@ +commit 37c440a66fbb +Author: accakks <aakanksha.jain8@gmail.com> +Date: Fri Mar 23 20:04:34 2018 +0530 + + Bug 1437880 - Disable "Remove Selected" button in the site data manager dialog if a website is deselected. r=prathiksha, a=RyanVM + + MozReview-Commit-ID: 7YhXjg84QSx + + --HG-- + extra : source : e7de3b21524c2d56a5c82ecde470b43f3ddb2d87 +--- + browser/components/preferences/siteDataSettings.js | 1 + + 1 file changed, 1 insertion(+) + +diff --git browser/components/preferences/siteDataSettings.js browser/components/preferences/siteDataSettings.js +index 2be61084a8bd..141a4ec850ba 100644 +--- browser/components/preferences/siteDataSettings.js ++++ browser/components/preferences/siteDataSettings.js +@@ -263,6 +263,7 @@ let gSiteDataSettings = { + onClickTreeCol(e) { + this._sortSites(this._sites, e.target); + this._buildSitesList(this._sites); ++ this._list.clearSelection(); + }, + + onCommandSearch() { diff --git a/www/waterfox/files/patch-bug1438425 b/www/waterfox/files/patch-bug1438425 new file mode 100644 index 000000000000..f53e948ae223 --- /dev/null +++ b/www/waterfox/files/patch-bug1438425 @@ -0,0 +1,662 @@ +commit f324bee78e24 +Author: Jeff Muizelaar <jmuizelaar@mozilla.com> +Date: Wed Mar 7 11:54:01 2018 -0500 + + Bug 1438425 - Delete DocumentRenderer. r=jesup, r=jgilbert, a=RyanVM + + It is unused. +--- + dom/canvas/CanvasRenderingContext2D.cpp | 2 - + dom/canvas/DocumentRendererChild.cpp | 94 --------------------------------- + dom/canvas/DocumentRendererChild.h | 37 ------------- + dom/canvas/DocumentRendererParent.cpp | 63 ---------------------- + dom/canvas/DocumentRendererParent.h | 44 --------------- + dom/canvas/WebGL2ContextState.cpp | 1 + + dom/canvas/WebGLContextDraw.cpp | 1 + + dom/canvas/WebGLFramebuffer.cpp | 3 ++ + dom/canvas/WebGLObjectModel.h | 12 +++++ + dom/canvas/WebGLProgram.cpp | 1 + + dom/canvas/WebGLTransformFeedback.cpp | 1 + + dom/canvas/moz.build | 7 --- + dom/ipc/PBrowser.ipdl | 20 ------- + dom/ipc/PDocumentRenderer.ipdl | 25 --------- + dom/ipc/TabChild.cpp | 52 ------------------ + dom/ipc/TabChild.h | 21 -------- + dom/ipc/TabParent.cpp | 19 ------- + dom/ipc/TabParent.h | 11 ---- + dom/ipc/moz.build | 1 - + 19 files changed, 19 insertions(+), 396 deletions(-) + +diff --git dom/canvas/CanvasRenderingContext2D.cpp dom/canvas/CanvasRenderingContext2D.cpp +index 6c3f5878e724..f314f2022baf 100644 +--- dom/canvas/CanvasRenderingContext2D.cpp ++++ dom/canvas/CanvasRenderingContext2D.cpp +@@ -91,8 +91,6 @@ + #include "mozilla/gfx/DataSurfaceHelpers.h" + #include "mozilla/gfx/PatternHelpers.h" + #include "mozilla/gfx/Swizzle.h" +-#include "mozilla/ipc/DocumentRendererParent.h" +-#include "mozilla/ipc/PDocumentRendererParent.h" + #include "mozilla/layers/PersistentBufferProvider.h" + #include "mozilla/MathAlgorithms.h" + #include "mozilla/Preferences.h" +diff --git dom/canvas/DocumentRendererChild.cpp dom/canvas/DocumentRendererChild.cpp +deleted file mode 100644 +index edfc4746a72c..000000000000 +--- dom/canvas/DocumentRendererChild.cpp ++++ /dev/null +@@ -1,94 +0,0 @@ +-/* 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 "mozilla/ipc/DocumentRendererChild.h" +- +-#include "base/basictypes.h" +- +-#include "gfx2DGlue.h" +-#include "gfxContext.h" +-#include "gfxPattern.h" +-#include "mozilla/gfx/2D.h" +-#include "mozilla/RefPtr.h" +-#include "nsPIDOMWindow.h" +-#include "nsIDOMWindow.h" +-#include "nsIDocShell.h" +-#include "nsIInterfaceRequestorUtils.h" +-#include "nsComponentManagerUtils.h" +-#include "nsCSSParser.h" +-#include "nsPresContext.h" +-#include "nsCOMPtr.h" +-#include "nsColor.h" +-#include "nsLayoutUtils.h" +-#include "nsContentUtils.h" +-#include "nsCSSValue.h" +-#include "nsRuleNode.h" +-#include "mozilla/gfx/Matrix.h" +- +-using namespace mozilla; +-using namespace mozilla::gfx; +-using namespace mozilla::ipc; +- +-DocumentRendererChild::DocumentRendererChild() +-{} +- +-DocumentRendererChild::~DocumentRendererChild() +-{} +- +-bool +-DocumentRendererChild::RenderDocument(nsPIDOMWindowOuter* window, +- const nsRect& documentRect, +- const mozilla::gfx::Matrix& transform, +- const nsString& aBGColor, +- uint32_t renderFlags, +- bool flushLayout, +- const nsIntSize& renderSize, +- nsCString& data) +-{ +- if (flushLayout) +- nsContentUtils::FlushLayoutForTree(window); +- +- RefPtr<nsPresContext> presContext; +- if (window) { +- nsIDocShell* docshell = window->GetDocShell(); +- if (docshell) { +- docshell->GetPresContext(getter_AddRefs(presContext)); +- } +- } +- if (!presContext) +- return false; +- +- nsCSSParser parser; +- nsCSSValue bgColorValue; +- if (!parser.ParseColorString(aBGColor, nullptr, 0, bgColorValue)) { +- return false; +- } +- +- nscolor bgColor; +- if (!nsRuleNode::ComputeColor(bgColorValue, presContext, nullptr, bgColor)) { +- return false; +- } +- +- // Draw directly into the output array. +- data.SetLength(renderSize.width * renderSize.height * 4); +- +- RefPtr<DrawTarget> dt = +- Factory::CreateDrawTargetForData(gfxPlatform::GetPlatform()->GetSoftwareBackend(), +- reinterpret_cast<uint8_t*>(data.BeginWriting()), +- IntSize(renderSize.width, renderSize.height), +- 4 * renderSize.width, +- SurfaceFormat::B8G8R8A8); +- if (!dt || !dt->IsValid()) { +- gfxWarning() << "DocumentRendererChild::RenderDocument failed to Factory::CreateDrawTargetForData"; +- return false; +- } +- RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt); +- MOZ_ASSERT(ctx); // already checked the draw target above +- ctx->SetMatrix(mozilla::gfx::ThebesMatrix(transform)); +- +- nsCOMPtr<nsIPresShell> shell = presContext->PresShell(); +- shell->RenderDocument(documentRect, renderFlags, bgColor, ctx); +- +- return true; +-} +diff --git dom/canvas/DocumentRendererChild.h dom/canvas/DocumentRendererChild.h +deleted file mode 100644 +index 80fe0ddf64bc..000000000000 +--- dom/canvas/DocumentRendererChild.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/* This Source Code Form is subject to the terms of the Mozilla Public +- * License, v. 2.0. If a copy of the MPL was not distributed with this +- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +- +-#ifndef mozilla_dom_DocumentRendererChild +-#define mozilla_dom_DocumentRendererChild +- +-#include "gfxContext.h" +-#include "mozilla/ipc/PDocumentRendererChild.h" +-#include "nsString.h" +- +-class nsIDOMWindow; +- +-namespace mozilla { +-namespace ipc { +- +-class DocumentRendererChild : public PDocumentRendererChild +-{ +-public: +- DocumentRendererChild(); +- virtual ~DocumentRendererChild(); +- +- bool RenderDocument(nsPIDOMWindowOuter* window, +- const nsRect& documentRect, const gfx::Matrix& transform, +- const nsString& bgcolor, +- uint32_t renderFlags, bool flushLayout, +- const nsIntSize& renderSize, nsCString& data); +- +-private: +- +- DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererChild); +-}; +- +-} // namespace ipc +-} // namespace mozilla +- +-#endif +diff --git dom/canvas/DocumentRendererParent.cpp dom/canvas/DocumentRendererParent.cpp +deleted file mode 100644 +index 0783dee1ab79..000000000000 +--- dom/canvas/DocumentRendererParent.cpp ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* 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 "mozilla/ipc/DocumentRendererParent.h" +- +-#include "gfx2DGlue.h" +-#include "mozilla/gfx/2D.h" +-#include "mozilla/gfx/PathHelpers.h" +-#include "mozilla/RefPtr.h" +-#include "nsICanvasRenderingContextInternal.h" +- +-using namespace mozilla; +-using namespace mozilla::gfx; +-using namespace mozilla::ipc; +- +-DocumentRendererParent::DocumentRendererParent() +-{} +- +-DocumentRendererParent::~DocumentRendererParent() +-{} +- +-void DocumentRendererParent::SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas, +- gfxContext* ctx) +-{ +- mCanvas = aCanvas; +- mCanvasContext = ctx; +-} +- +-void DocumentRendererParent::DrawToCanvas(const nsIntSize& aSize, +- const nsCString& aData) +-{ +- if (!mCanvas || !mCanvasContext) +- return; +- +- DrawTarget* drawTarget = mCanvasContext->GetDrawTarget(); +- Rect rect(0, 0, aSize.width, aSize.height); +- MaybeSnapToDevicePixels(rect, *drawTarget, true); +- RefPtr<DataSourceSurface> dataSurface = +- Factory::CreateWrappingDataSourceSurface(reinterpret_cast<uint8_t*>(const_cast<nsCString&>(aData).BeginWriting()), +- aSize.width * 4, +- IntSize(aSize.width, aSize.height), +- SurfaceFormat::B8G8R8A8); +- SurfacePattern pattern(dataSurface, ExtendMode::CLAMP); +- drawTarget->FillRect(rect, pattern); +- +- gfxRect damageRect = mCanvasContext->UserToDevice(ThebesRect(rect)); +- mCanvas->Redraw(damageRect); +-} +- +-void +-DocumentRendererParent::ActorDestroy(ActorDestroyReason aWhy) +-{ +- // Implement me! Bug 1005139 +-} +- +-mozilla::ipc::IPCResult +-DocumentRendererParent::Recv__delete__(const nsIntSize& renderedSize, +- const nsCString& data) +-{ +- DrawToCanvas(renderedSize, data); +- return IPC_OK(); +-} +diff --git dom/canvas/DocumentRendererParent.h dom/canvas/DocumentRendererParent.h +deleted file mode 100644 +index 7cfe5322795f..000000000000 +--- dom/canvas/DocumentRendererParent.h ++++ /dev/null +@@ -1,44 +0,0 @@ +-/* This Source Code Form is subject to the terms of the Mozilla Public +- * License, v. 2.0. If a copy of the MPL was not distributed with this +- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +- +-#ifndef mozilla_dom_DocumentRendererParent +-#define mozilla_dom_DocumentRendererParent +- +-#include "gfxContext.h" +-#include "mozilla/ipc/PDocumentRendererParent.h" +-#include "nsCOMPtr.h" +-#include "nsString.h" +- +-class nsICanvasRenderingContextInternal; +- +-namespace mozilla { +-namespace ipc { +- +-class DocumentRendererParent : public PDocumentRendererParent +-{ +-public: +- DocumentRendererParent(); +- virtual ~DocumentRendererParent(); +- +- void SetCanvasContext(nsICanvasRenderingContextInternal* aCanvas, +- gfxContext* ctx); +- void DrawToCanvas(const nsIntSize& renderedSize, +- const nsCString& aData); +- +- virtual void ActorDestroy(ActorDestroyReason aWhy) override; +- +- virtual mozilla::ipc::IPCResult Recv__delete__(const nsIntSize& renderedSize, +- const nsCString& data) override; +- +-private: +- nsCOMPtr<nsICanvasRenderingContextInternal> mCanvas; +- RefPtr<gfxContext> mCanvasContext; +- +- DISALLOW_EVIL_CONSTRUCTORS(DocumentRendererParent); +-}; +- +-} // namespace ipc +-} // namespace mozilla +- +-#endif +diff --git dom/canvas/WebGL2ContextState.cpp dom/canvas/WebGL2ContextState.cpp +index be0a7a3cbdea..e6283b12dd9e 100644 +--- dom/canvas/WebGL2ContextState.cpp ++++ dom/canvas/WebGL2ContextState.cpp +@@ -7,6 +7,7 @@ + #include "WebGL2Context.h" + + #include "GLContext.h" ++#include "GLScreenBuffer.h" + #include "WebGLBuffer.h" + #include "WebGLContextUtils.h" + #include "WebGLFramebuffer.h" +diff --git dom/canvas/WebGLFramebuffer.cpp dom/canvas/WebGLFramebuffer.cpp +index e5150d5ddd43..e2fdea239632 100644 +--- dom/canvas/WebGLFramebuffer.cpp ++++ dom/canvas/WebGLFramebuffer.cpp +@@ -17,7 +17,9 @@ + #include "WebGLContextUtils.h" + #include "WebGLExtensions.h" + #include "WebGLRenderbuffer.h" ++#include "WebGLShader.h" + #include "WebGLTexture.h" ++#include "WebGLObjectModel.h" + + namespace mozilla { + +@@ -1990,6 +1992,7 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback, + } + } + ++ + NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLFramebuffer, + mDepthAttachment, + mStencilAttachment, +diff --git dom/canvas/WebGLObjectModel.h dom/canvas/WebGLObjectModel.h +index e19d2fd8e44d..b18b790c036e 100644 +--- dom/canvas/WebGLObjectModel.h ++++ dom/canvas/WebGLObjectModel.h +@@ -15,6 +15,7 @@ namespace mozilla { + template<typename> class LinkedList; + class WebGLContext; + ++ + //// + + // This class is a mixin for objects that are tied to a specific +@@ -352,6 +353,16 @@ ImplCycleCollectionUnlink(mozilla::WebGLRefPtr<T>& field) + field = nullptr; + } + ++template <typename T> ++inline void ++ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback, ++ mozilla::WebGLRefPtr<T>& field, ++ const char* name, ++ uint32_t flags = 0) ++{ ++ CycleCollectionNoteChild(callback, field.get(), name, flags); ++} ++ + template <typename T> + inline void + ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback, +@@ -362,4 +373,5 @@ ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback, + CycleCollectionNoteChild(callback, field.get(), name, flags); + } + ++ + #endif +diff --git dom/canvas/WebGLProgram.cpp dom/canvas/WebGLProgram.cpp +index 365b8e178af8..9e48a240332c 100644 +--- dom/canvas/WebGLProgram.cpp ++++ dom/canvas/WebGLProgram.cpp +@@ -17,6 +17,7 @@ + #include "WebGLTransformFeedback.h" + #include "WebGLUniformLocation.h" + #include "WebGLValidateStrings.h" ++#include "WebGLObjectModel.h" + + namespace mozilla { + +diff --git dom/canvas/moz.build dom/canvas/moz.build +index ac4172318a7e..b33b09d7bc70 100644 +--- dom/canvas/moz.build ++++ dom/canvas/moz.build +@@ -49,11 +49,6 @@ EXPORTS += [ + 'nsICanvasRenderingContextInternal.h', + ] + +-EXPORTS.mozilla.ipc += [ +- 'DocumentRendererChild.h', +- 'DocumentRendererParent.h', +-] +- + EXPORTS.mozilla.dom += [ + 'BasicRenderingContext2D.h', + 'CanvasGradient.h', +@@ -78,8 +73,6 @@ UNIFIED_SOURCES += [ + 'CanvasRenderingContext2D.cpp', + 'CanvasRenderingContextHelper.cpp', + 'CanvasUtils.cpp', +- 'DocumentRendererChild.cpp', +- 'DocumentRendererParent.cpp', + 'ImageBitmap.cpp', + 'ImageBitmapColorUtils.cpp', + 'ImageBitmapRenderingContext.cpp', +diff --git dom/ipc/PBrowser.ipdl dom/ipc/PBrowser.ipdl +index 5525931e914f..90f559063c4d 100644 +--- dom/ipc/PBrowser.ipdl ++++ dom/ipc/PBrowser.ipdl +@@ -9,7 +9,6 @@ include protocol PColorPicker; + include protocol PContent; + include protocol PContentBridge; + include protocol PDocAccessible; +-include protocol PDocumentRenderer; + include protocol PFilePicker; + include protocol PIndexedDBPermissionRequest; + include protocol PRenderFrame; +@@ -110,7 +109,6 @@ nested(upto inside_cpow) sync protocol PBrowser + + manages PColorPicker; + manages PDocAccessible; +- manages PDocumentRenderer; + manages PFilePicker; + manages PIndexedDBPermissionRequest; + manages PRenderFrame; +@@ -698,24 +696,6 @@ child: + + async LoadRemoteScript(nsString aURL, bool aRunInGlobalScope); + +- /** +- * Create a asynchronous request to render whatever document is +- * loaded in the child when this message arrives. When the +- * request finishes, PDocumentRenderer:__delete__ is sent back to +- * this side to notify completion. +- * +- * |documentRect| is the area of the remote document to draw, +- * transformed by |transform|. The rendered area will have the +- * default background color |bgcolor|. |renderFlags| are the +- * nsIPresShell::RenderDocument() flags to use on the remote side, +- * and if true, |flushLayout| will do just that before rendering +- * the document. The rendered image will be of size |renderSize|. +- */ +- async PDocumentRenderer(nsRect documentRect, Matrix transform, +- nsString bgcolor, +- uint32_t renderFlags, bool flushLayout, +- IntSize renderSize); +- + /** + * Sent by the chrome process when it no longer wants this remote + * <browser>. The child side cleans up in response, then +diff --git dom/ipc/PDocumentRenderer.ipdl dom/ipc/PDocumentRenderer.ipdl +deleted file mode 100644 +index bdaed45d7414..000000000000 +--- dom/ipc/PDocumentRenderer.ipdl ++++ /dev/null +@@ -1,25 +0,0 @@ +-/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ +-/* 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 protocol PBrowser; +- +-include "mozilla/GfxMessageUtils.h"; +- +-using nsIntSize from "nsSize.h"; +- +-namespace mozilla { +-namespace ipc { +- +-protocol PDocumentRenderer +-{ +- manager PBrowser; +- +-parent: +- // Returns the width and height, in pixels, of the returned ARGB32 data. +- async __delete__(nsIntSize renderedSize, nsCString data); +-}; +- +-} // namespace ipc +-} // namespace mozilla +diff --git dom/ipc/TabChild.cpp dom/ipc/TabChild.cpp +index 5a14fd9dc0ff..44f366056c2a 100644 +--- dom/ipc/TabChild.cpp ++++ dom/ipc/TabChild.cpp +@@ -23,7 +23,6 @@ + #include "mozilla/dom/PaymentRequestChild.h" + #include "mozilla/dom/TelemetryScrollProbe.h" + #include "mozilla/IMEStateManager.h" +-#include "mozilla/ipc/DocumentRendererChild.h" + #include "mozilla/ipc/URIUtils.h" + #include "mozilla/layers/APZChild.h" + #include "mozilla/layers/APZCCallbackHelper.h" +@@ -2027,60 +2026,6 @@ TabChild::DeallocPDocAccessibleChild(a11y::PDocAccessibleChild* aChild) + return true; + } + +-PDocumentRendererChild* +-TabChild::AllocPDocumentRendererChild(const nsRect& documentRect, +- const mozilla::gfx::Matrix& transform, +- const nsString& bgcolor, +- const uint32_t& renderFlags, +- const bool& flushLayout, +- const nsIntSize& renderSize) +-{ +- return new DocumentRendererChild(); +-} +- +-bool +-TabChild::DeallocPDocumentRendererChild(PDocumentRendererChild* actor) +-{ +- delete actor; +- return true; +-} +- +-mozilla::ipc::IPCResult +-TabChild::RecvPDocumentRendererConstructor(PDocumentRendererChild* actor, +- const nsRect& documentRect, +- const mozilla::gfx::Matrix& transform, +- const nsString& bgcolor, +- const uint32_t& renderFlags, +- const bool& flushLayout, +- const nsIntSize& renderSize) +-{ +- DocumentRendererChild *render = static_cast<DocumentRendererChild *>(actor); +- +- nsCOMPtr<nsIWebBrowser> browser = do_QueryInterface(WebNavigation()); +- if (!browser) +- return IPC_OK(); // silently ignore +- nsCOMPtr<mozIDOMWindowProxy> window; +- if (NS_FAILED(browser->GetContentDOMWindow(getter_AddRefs(window))) || +- !window) +- { +- return IPC_OK(); // silently ignore +- } +- +- nsCString data; +- bool ret = render->RenderDocument(nsPIDOMWindowOuter::From(window), +- documentRect, transform, +- bgcolor, +- renderFlags, flushLayout, +- renderSize, data); +- if (!ret) +- return IPC_OK(); // silently ignore +- +- if (!PDocumentRendererChild::Send__delete__(actor, renderSize, data)) { +- return IPC_FAIL_NO_REASON(this); +- } +- return IPC_OK(); +-} +- + PColorPickerChild* + TabChild::AllocPColorPickerChild(const nsString&, const nsString&) + { +diff --git dom/ipc/TabChild.h dom/ipc/TabChild.h +index af01a50542ac..1b1e580b29e6 100644 +--- dom/ipc/TabChild.h ++++ dom/ipc/TabChild.h +@@ -456,27 +456,6 @@ public: + + virtual bool DeallocPDocAccessibleChild(PDocAccessibleChild*) override; + +- virtual PDocumentRendererChild* +- AllocPDocumentRendererChild(const nsRect& aDocumentRect, +- const gfx::Matrix& aTransform, +- const nsString& aBggcolor, +- const uint32_t& aRenderFlags, +- const bool& aFlushLayout, +- const nsIntSize& arenderSize) override; +- +- virtual bool +- DeallocPDocumentRendererChild(PDocumentRendererChild* aCctor) override; +- +- virtual mozilla::ipc::IPCResult +- RecvPDocumentRendererConstructor(PDocumentRendererChild* aActor, +- const nsRect& aDocumentRect, +- const gfx::Matrix& aTransform, +- const nsString& aBgcolor, +- const uint32_t& aRenderFlags, +- const bool& aFlushLayout, +- const nsIntSize& aRenderSize) override; +- +- + virtual PColorPickerChild* + AllocPColorPickerChild(const nsString& aTitle, + const nsString& aInitialColor) override; +diff --git dom/ipc/TabParent.cpp dom/ipc/TabParent.cpp +index e6eac09db4aa..8468343b8930 100644 +--- dom/ipc/TabParent.cpp ++++ dom/ipc/TabParent.cpp +@@ -26,7 +26,6 @@ + #include "mozilla/gfx/GPUProcessManager.h" + #include "mozilla/Hal.h" + #include "mozilla/IMEStateManager.h" +-#include "mozilla/ipc/DocumentRendererParent.h" + #include "mozilla/jsipc/CrossProcessObjectWrappers.h" + #include "mozilla/layers/AsyncDragMetrics.h" + #include "mozilla/layers/InputAPZContext.h" +@@ -982,24 +981,6 @@ TabParent::GetTopLevelDocAccessible() const + return nullptr; + } + +-PDocumentRendererParent* +-TabParent::AllocPDocumentRendererParent(const nsRect& documentRect, +- const gfx::Matrix& transform, +- const nsString& bgcolor, +- const uint32_t& renderFlags, +- const bool& flushLayout, +- const nsIntSize& renderSize) +-{ +- return new DocumentRendererParent(); +-} +- +-bool +-TabParent::DeallocPDocumentRendererParent(PDocumentRendererParent* actor) +-{ +- delete actor; +- return true; +-} +- + PFilePickerParent* + TabParent::AllocPFilePickerParent(const nsString& aTitle, const int16_t& aMode) + { +diff --git dom/ipc/TabParent.h dom/ipc/TabParent.h +index 1f75d188d92e..0472dad56e97 100644 +--- dom/ipc/TabParent.h ++++ dom/ipc/TabParent.h +@@ -468,17 +468,6 @@ public: + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId); + +- virtual PDocumentRendererParent* +- AllocPDocumentRendererParent(const nsRect& documentRect, +- const gfx::Matrix& transform, +- const nsString& bgcolor, +- const uint32_t& renderFlags, +- const bool& flushLayout, +- const nsIntSize& renderSize) override; +- +- virtual bool +- DeallocPDocumentRendererParent(PDocumentRendererParent* actor) override; +- + virtual PFilePickerParent* + AllocPFilePickerParent(const nsString& aTitle, + const int16_t& aMode) override; +diff --git dom/ipc/moz.build dom/ipc/moz.build +index fa7d4a9ef549..4880a69f00ec 100644 +--- dom/ipc/moz.build ++++ dom/ipc/moz.build +@@ -91,7 +91,6 @@ IPDL_SOURCES += [ + 'PContentPermission.ipdlh', + 'PContentPermissionRequest.ipdl', + 'PCycleCollectWithLogs.ipdl', +- 'PDocumentRenderer.ipdl', + 'PFilePicker.ipdl', + 'PPluginWidget.ipdl', + 'PProcessHangMonitor.ipdl', diff --git a/www/waterfox/files/patch-bug1438645 b/www/waterfox/files/patch-bug1438645 new file mode 100644 index 000000000000..92c951c0cba2 --- /dev/null +++ b/www/waterfox/files/patch-bug1438645 @@ -0,0 +1,210 @@ +commit dc9f32108582 +Author: Ted Campbell <tcampbell@mozilla.com> +Date: Thu Feb 15 14:58:00 2018 +0200 + + Bug 1438645 - Prevent XDR from reading past its buffer. r=nbp a=lizzard + While XDR data is supposed to be trusted, we currently run into a + corruption for some users/use-cases and so make more XDR operations + fallible instead of crashing. + + MozReview-Commit-ID: 9FSLNWh9RxG + + --HG-- + extra : source : fb0c12a38e03ad49c40eb64df23885037d26053d +--- + js/src/jsatom.cpp | 18 ++++++++++++---- + js/src/vm/Xdr.cpp | 2 ++ + js/src/vm/Xdr.h | 62 ++++++++++++++++++++++++++++++++++++------------------- + 3 files changed, 57 insertions(+), 25 deletions(-) + +diff --git js/src/jsatom.cpp js/src/jsatom.cpp +index 5d3ed0040dc1..f1d975f6f03d 100644 +--- js/src/jsatom.cpp ++++ js/src/jsatom.cpp +@@ -644,15 +644,25 @@ js::XDRAtom(XDRState<mode>* xdr, MutableHandleAtom atomp) + JSAtom* atom; + if (latin1) { + const Latin1Char* chars = nullptr; +- if (length) +- chars = reinterpret_cast<const Latin1Char*>(xdr->buf.read(length)); ++ if (length) { ++ const uint8_t *ptr; ++ size_t nbyte = length * sizeof(Latin1Char); ++ if (!xdr->peekData(&ptr, nbyte)) ++ return false; ++ chars = reinterpret_cast<const Latin1Char*>(ptr); ++ } + atom = AtomizeChars(cx, chars, length); + } else { + #if MOZ_LITTLE_ENDIAN + /* Directly access the little endian chars in the XDR buffer. */ + const char16_t* chars = nullptr; +- if (length) +- chars = reinterpret_cast<const char16_t*>(xdr->buf.read(length * sizeof(char16_t))); ++ if (length) { ++ const uint8_t *ptr; ++ size_t nbyte = length * sizeof(char16_t); ++ if (!xdr->peekData(&ptr, nbyte)) ++ return false; ++ chars = reinterpret_cast<const char16_t*>(ptr); ++ } + atom = AtomizeChars(cx, chars, length); + #else + /* +diff --git js/src/vm/Xdr.cpp js/src/vm/Xdr.cpp +index ec184f31e0c7..5847dbbe3453 100644 +--- js/src/vm/Xdr.cpp ++++ js/src/vm/Xdr.cpp +@@ -73,6 +73,8 @@ XDRState<mode>::codeChars(char16_t* chars, size_t nchars) + mozilla::NativeEndian::copyAndSwapToLittleEndian(ptr, chars, nchars); + } else { + const uint8_t* ptr = buf.read(nbytes); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); + mozilla::NativeEndian::copyAndSwapFromLittleEndian(chars, ptr, nchars); + } + return true; +diff --git js/src/vm/Xdr.h js/src/vm/Xdr.h +index 0a6cbf01b50f..a60f43c6b531 100644 +--- js/src/vm/Xdr.h ++++ js/src/vm/Xdr.h +@@ -61,11 +61,6 @@ class XDRBuffer<XDR_ENCODE> : public XDRBufferBase + return ptr; + } + +- const char* readCString() { +- MOZ_CRASH("Should never read in encode mode"); +- return nullptr; +- } +- + const uint8_t* read(size_t n) { + MOZ_CRASH("Should never read in encode mode"); + return nullptr; +@@ -87,19 +82,15 @@ class XDRBuffer<XDR_DECODE> : public XDRBufferBase + : XDRBufferBase(cx, cursor), + buffer_(buffer.begin(), buffer.length()) { } + +- const char* readCString() { +- char* ptr = reinterpret_cast<char*>(&buffer_[cursor_]); +- uint8_t* end = reinterpret_cast<uint8_t*>(strchr(ptr, '\0')) + 1; +- MOZ_ASSERT(buffer_.begin().get() < end); +- MOZ_ASSERT(end <= buffer_.end().get()); +- cursor_ = end - buffer_.begin().get(); +- return ptr; +- } +- + const uint8_t* read(size_t n) { + MOZ_ASSERT(cursor_ < buffer_.length()); + uint8_t* ptr = &buffer_[cursor_]; + cursor_ += n; ++ ++ // Don't let buggy code read past our buffer ++ if (cursor_ > buffer_.length()) ++ return nullptr; ++ + return ptr; + } + +@@ -174,7 +165,7 @@ class XDRCoderBase + template <XDRMode mode> + class XDRState : public XDRCoderBase + { +- public: ++ protected: + XDRBuffer<mode> buf; + private: + JS::TranscodeResult resultCode_; +@@ -220,6 +211,14 @@ class XDRState : public XDRCoderBase + return false; + } + ++ bool peekData(const uint8_t** pptr, size_t length) { ++ const uint8_t* ptr = buf.read(length); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); ++ *pptr = ptr; ++ return true; ++ } ++ + bool codeUint8(uint8_t* n) { + if (mode == XDR_ENCODE) { + uint8_t* ptr = buf.write(sizeof(*n)); +@@ -227,7 +226,10 @@ class XDRState : public XDRCoderBase + return fail(JS::TranscodeResult_Throw); + *ptr = *n; + } else { +- *n = *buf.read(sizeof(*n)); ++ const uint8_t* ptr = buf.read(sizeof(*n)); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); ++ *n = *ptr; + } + return true; + } +@@ -240,6 +242,8 @@ class XDRState : public XDRCoderBase + mozilla::LittleEndian::writeUint16(ptr, *n); + } else { + const uint8_t* ptr = buf.read(sizeof(*n)); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); + *n = mozilla::LittleEndian::readUint16(ptr); + } + return true; +@@ -253,6 +257,8 @@ class XDRState : public XDRCoderBase + mozilla::LittleEndian::writeUint32(ptr, *n); + } else { + const uint8_t* ptr = buf.read(sizeof(*n)); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); + *n = mozilla::LittleEndian::readUint32(ptr); + } + return true; +@@ -266,6 +272,8 @@ class XDRState : public XDRCoderBase + mozilla::LittleEndian::writeUint64(ptr, *n); + } else { + const uint8_t* ptr = buf.read(sizeof(*n)); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); + *n = mozilla::LittleEndian::readUint64(ptr); + } + return true; +@@ -328,7 +336,10 @@ class XDRState : public XDRCoderBase + return fail(JS::TranscodeResult_Throw); + memcpy(ptr, bytes, len); + } else { +- memcpy(bytes, buf.read(len), len); ++ const uint8_t* ptr = buf.read(len); ++ if (!ptr) ++ return fail(JS::TranscodeResult_Failure_BadDecode); ++ memcpy(bytes, ptr, len); + } + return true; + } +@@ -340,14 +351,23 @@ class XDRState : public XDRCoderBase + * the decoding buffer. + */ + bool codeCString(const char** sp) { ++ uint64_t len64; ++ if (mode == XDR_ENCODE) ++ len64 = (uint64_t)(strlen(*sp) + 1); ++ if (!codeUint64(&len64)) ++ return false; ++ size_t len = (size_t) len64; ++ + if (mode == XDR_ENCODE) { +- size_t n = strlen(*sp) + 1; +- uint8_t* ptr = buf.write(n); ++ uint8_t* ptr = buf.write(len); + if (!ptr) + return fail(JS::TranscodeResult_Throw); +- memcpy(ptr, *sp, n); ++ memcpy(ptr, *sp, len); + } else { +- *sp = buf.readCString(); ++ const uint8_t* ptr = buf.read(len); ++ if (!ptr || ptr[len] != '\0') ++ return fail(JS::TranscodeResult_Failure_BadDecode); ++ *sp = reinterpret_cast<const char*>(ptr); + } + return true; + } diff --git a/www/waterfox/files/patch-bug1439236 b/www/waterfox/files/patch-bug1439236 new file mode 100644 index 000000000000..f13e1a56e681 --- /dev/null +++ b/www/waterfox/files/patch-bug1439236 @@ -0,0 +1,35 @@ +commit 7f6f5a06a070 +Author: Nils Ohlmeier [:drno] <drno@ohlmeier.org> +Date: Wed May 16 09:51:35 2018 -0700 + + Bug 1439236 - Exit early if m_copym gets called with null ptr. r=dminor, a=RyanVM + + Cheery-picked upstream commit: + https://github.com/sctplab/usrsctp/commit/d89882d04900c80860874b5eb389b3ed3a0bca3d + + MozReview-Commit-ID: 36bYbfIaqEz + + --HG-- + extra : source : 2755492fe3d1daa9dd6066b049bc7bb5941b28e9 +--- + netwerk/sctp/src/user_mbuf.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git netwerk/sctp/src/user_mbuf.c netwerk/sctp/src/user_mbuf.c +index ec83931e66e5a..bd17f9fbada60 100755 +--- netwerk/sctp/src/user_mbuf.c ++++ netwerk/sctp/src/user_mbuf.c +@@ -987,6 +987,13 @@ m_copym(struct mbuf *m, int off0, int len, int wait) + + KASSERT(off >= 0, ("m_copym, negative off %d", off)); + KASSERT(len >= 0, ("m_copym, negative len %d", len)); ++ KASSERT(m != NULL, ("m_copym, m is NULL")); ++ ++#if !defined(INVARIANTS) ++ if (m == NULL) { ++ return (NULL); ++ } ++#endif + + if (off == 0 && m->m_flags & M_PKTHDR) + copyhdr = 1; diff --git a/www/waterfox/files/patch-bug1439396 b/www/waterfox/files/patch-bug1439396 new file mode 100644 index 000000000000..4e8510b492a1 --- /dev/null +++ b/www/waterfox/files/patch-bug1439396 @@ -0,0 +1,39 @@ +commit be067d6efbf4 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Feb 21 12:18:40 2018 +0000 + + Bug 1439396, r=mak a=RyanVM + + --HG-- + extra : source : 2c38198fec8a7654862e491884db41b852ac367c +--- + browser/base/content/browser.js | 2 +- + .../content/test/urlbar/browser_removeUnsafeProtocolsFromURLBarPaste.js | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git browser/base/content/browser.js browser/base/content/browser.js +index efd1b6ef3a08..c74031c4e31d 100755 +--- browser/base/content/browser.js ++++ browser/base/content/browser.js +@@ -6038,7 +6038,7 @@ function stripUnsafeProtocolOnPaste(pasteData) { + try { + scheme = Services.io.extractScheme(pasteData); + } catch (ex) { } +- if (scheme != "javascript") { ++ if (scheme.toLowerCase() != "javascript") { + break; + } + +diff --git browser/base/content/test/urlbar/browser_removeUnsafeProtocolsFromURLBarPaste.js browser/base/content/test/urlbar/browser_removeUnsafeProtocolsFromURLBarPaste.js +index 70ecaa048626..94b417eb7435 100644 +--- browser/base/content/test/urlbar/browser_removeUnsafeProtocolsFromURLBarPaste.js ++++ browser/base/content/test/urlbar/browser_removeUnsafeProtocolsFromURLBarPaste.js +@@ -13,6 +13,8 @@ var pairs = [ + ["http://\nexample.com", "http://example.com"], + ["http://\nexample.com\n", "http://example.com"], + ["data:text/html,<body>hi</body>", "data:text/html,<body>hi</body>"], ++ ["javaScript:foopy", "foopy"], ++ ["javaScript:javaScript:alert('hi')", "alert('hi')"], + // Nested things get confusing because some things don't parse as URIs: + ["javascript:javascript:alert('hi!')", "alert('hi!')"], + ["data:data:text/html,<body>hi</body>", "data:data:text/html,<body>hi</body>"], diff --git a/www/waterfox/files/patch-bug1440943 b/www/waterfox/files/patch-bug1440943 new file mode 100644 index 000000000000..8840500cd8d1 --- /dev/null +++ b/www/waterfox/files/patch-bug1440943 @@ -0,0 +1,60 @@ +commit 00e6df2e9693 +Author: Jonathan Kew <jkew@mozilla.com> +Date: Tue Feb 27 10:34:25 2018 +0000 + + Bug 1440943 - Make GetScriptTagForCode safely return UNKNOWN tag if called with a script code that is out of range for the system ICU version. r=m_kato, a=RyanVM + + --HG-- + extra : source : 03a12246dd84ae384f973e148cec64662383e588 +--- + intl/unicharutil/util/nsUnicodeProperties.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git intl/unicharutil/util/nsUnicodeProperties.h intl/unicharutil/util/nsUnicodeProperties.h +index e2ee2a99bfe4..57cff6bc5562 100644 +--- intl/unicharutil/util/nsUnicodeProperties.h ++++ intl/unicharutil/util/nsUnicodeProperties.h +@@ -119,7 +119,11 @@ inline uint32_t + GetScriptTagForCode(Script aScriptCode) + { + const char* tag = uscript_getShortName(UScriptCode(aScriptCode)); +- return HB_TAG(tag[0], tag[1], tag[2], tag[3]); ++ if (tag) { ++ return HB_TAG(tag[0], tag[1], tag[2], tag[3]); ++ } ++ // return UNKNOWN script tag (running with older ICU?) ++ return HB_SCRIPT_UNKNOWN; + } + + inline PairedBracketType +commit 412f5f20ada0 +Author: Jonathan Kew <jkew@mozilla.com> +Date: Tue Feb 27 10:34:25 2018 +0000 + + Bug 1440943 - Ensure we don't try to look up script tags for codes that are not supported by the system ICU version. r=m_kato, a=RyanVM + + --HG-- + extra : source : 34d3a58cafc25d01d081195d2a396bc77342bf2c +--- + gfx/thebes/gfxFont.cpp | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git gfx/thebes/gfxFont.cpp gfx/thebes/gfxFont.cpp +index 1409cb087514..e4d04ffd48f5 100644 +--- gfx/thebes/gfxFont.cpp ++++ gfx/thebes/gfxFont.cpp +@@ -1193,7 +1193,13 @@ gfxFont::CheckForFeaturesInvolvingSpace() + new nsDataHashtable<nsUint32HashKey, + Script>(size_t(Script::NUM_SCRIPT_CODES)); + sScriptTagToCode->Put(HB_TAG('D','F','L','T'), Script::COMMON); +- for (Script s = Script::ARABIC; s < Script::NUM_SCRIPT_CODES; ++ // Ensure that we don't try to look at script codes beyond what the ++ // current version of ICU (at runtime -- in case of system ICU) ++ // knows about. ++ Script scriptCount = ++ Script(std::min<int>(u_getIntPropertyMaxValue(UCHAR_SCRIPT) + 1, ++ int(Script::NUM_SCRIPT_CODES))); ++ for (Script s = Script::ARABIC; s < scriptCount; + s = Script(static_cast<int>(s) + 1)) { + hb_script_t scriptTag = hb_script_t(GetScriptTagForCode(s)); + hb_tag_t s1, s2; diff --git a/www/waterfox/files/patch-bug1442504 b/www/waterfox/files/patch-bug1442504 new file mode 100644 index 000000000000..8378471e1254 --- /dev/null +++ b/www/waterfox/files/patch-bug1442504 @@ -0,0 +1,50 @@ +commit a5cc1f334aca +Author: Jeff Gilbert <jgilbert@mozilla.com> +Date: Sat Mar 3 00:50:10 2018 +0200 + + Bug 1442504 - Disable disjoint timer queries. r=milan, a=RyanVM + + MozReview-Commit-ID: IurPcGHzAoQ + + --HG-- + extra : source : bef3db82d7ca31a188f902e317713c88001938ed +--- + dom/canvas/WebGLContextExtensions.cpp | 4 ++-- + dom/canvas/test/webgl-mochitest/mochitest.ini | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git dom/canvas/WebGLContextExtensions.cpp dom/canvas/WebGLContextExtensions.cpp +index 120ca85a01a2..04cbbbe6b31d 100644 +--- dom/canvas/WebGLContextExtensions.cpp ++++ dom/canvas/WebGLContextExtensions.cpp +@@ -93,6 +93,8 @@ bool WebGLContext::IsExtensionSupported(dom::CallerType callerType, + + if (allowPrivilegedExts) { + switch (ext) { ++ case WebGLExtensionID::EXT_disjoint_timer_query: ++ return WebGLExtensionDisjointTimerQuery::IsSupported(this); + case WebGLExtensionID::MOZ_debug: + return true; + case WebGLExtensionID::WEBGL_debug_renderer_info: +@@ -118,8 +120,6 @@ WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const + switch (ext) { + // In alphabetical order + // EXT_ +- case WebGLExtensionID::EXT_disjoint_timer_query: +- return WebGLExtensionDisjointTimerQuery::IsSupported(this); + case WebGLExtensionID::EXT_texture_filter_anisotropic: + return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic); + +diff --git dom/canvas/test/webgl-mochitest/mochitest.ini dom/canvas/test/webgl-mochitest/mochitest.ini +index d36e66b7cdbd..08e2dd335dce 100644 +--- dom/canvas/test/webgl-mochitest/mochitest.ini ++++ dom/canvas/test/webgl-mochitest/mochitest.ini +@@ -19,7 +19,7 @@ fail-if = (os == 'android') + [ensure-exts/test_EXT_color_buffer_half_float.html] + fail-if = (os == 'android') + [ensure-exts/test_EXT_disjoint_timer_query.html] +-fail-if = (os == 'android') || (os == 'mac') || (os == 'win' && os_version == '5.1') ++fail-if = 1 + [ensure-exts/test_EXT_frag_depth.html] + fail-if = (os == 'android') + [ensure-exts/test_EXT_sRGB.html] diff --git a/www/waterfox/files/patch-bug1443149 b/www/waterfox/files/patch-bug1443149 new file mode 100644 index 000000000000..71b90d64818b --- /dev/null +++ b/www/waterfox/files/patch-bug1443149 @@ -0,0 +1,32 @@ +commit b28daeec3432 +Author: Jamie Nicol <jnicol@mozilla.com> +Date: Wed Mar 14 16:42:37 2018 +0000 + + Bug 1443149 - Ensure WebGLFBAttachPoint::HasImage() before dereferencing Format(). r=jrmuizel a=jcristau + + Previously we were checking IsDefined() rather than HasImage(), but + were hitting crashes. This was because Format() can return null if the + attach point is defined but the attached texture level or renderbuffer + aren't themselves defined. HasImage() checks for this case. + + MozReview-Commit-ID: 8KY3zPXXAFv + + --HG-- + extra : source : ebb9f83337a22ae8e77c3e7129f65178f1bedec5 +--- + dom/canvas/WebGLContextFramebufferOperations.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git dom/canvas/WebGLContextFramebufferOperations.cpp dom/canvas/WebGLContextFramebufferOperations.cpp +index 7133cdec2448..84a58e9da49f 100644 +--- dom/canvas/WebGLContextFramebufferOperations.cpp ++++ dom/canvas/WebGLContextFramebufferOperations.cpp +@@ -33,7 +33,7 @@ WebGLContext::Clear(GLbitfield mask) + if (mask & LOCAL_GL_COLOR_BUFFER_BIT && mBoundDrawFramebuffer) { + if (mask & LOCAL_GL_COLOR_BUFFER_BIT) { + for (const auto& cur : mBoundDrawFramebuffer->ColorDrawBuffers()) { +- if (!cur->IsDefined()) ++ if (!cur->HasImage()) + continue; + + switch (cur->Format()->format->componentType) { diff --git a/www/waterfox/files/patch-bug1444083 b/www/waterfox/files/patch-bug1444083 new file mode 100644 index 000000000000..9163fe84acb6 --- /dev/null +++ b/www/waterfox/files/patch-bug1444083 @@ -0,0 +1,17 @@ +Disable custom styling for <select> and <option> on Tier3 as well + +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index 322d009da739..06e2fd7f664a 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -1359,8 +1359,8 @@ pref("dom.forms.autocomplete.formautofill", false); + // Enable search in <select> dropdowns (more than 40 options) + pref("dom.forms.selectSearch", false); + // Allow for webpages to provide custom styling for <select> +-// popups. Disabled on Linux due to bug 1338283. +-#ifdef XP_LINUX ++// popups. Disabled on GTK due to bug 1338283. ++#ifdef MOZ_WIDGET_GTK + pref("dom.forms.select.customstyling", false); + #else + pref("dom.forms.select.customstyling", true); diff --git a/www/waterfox/files/patch-bug1444231 b/www/waterfox/files/patch-bug1444231 new file mode 100644 index 000000000000..e35a39d78b05 --- /dev/null +++ b/www/waterfox/files/patch-bug1444231 @@ -0,0 +1,45 @@ +commit 62d7770e2c7c +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Tue Mar 13 00:59:23 2018 -0400 + + Bug 1444231 - Fix QI implementation for FragmentOrElement. r=mccr8 a=jcristau + + MozReview-Commit-ID: 9mPO2ezk2Y7 + + --HG-- + extra : rebase_source : 1b15f9dac21206fbefeb9a6b72f3c54ff4d74537 + extra : source : 060024fa93121d878d27f329c959757e6f71017a +--- + dom/base/Element.cpp | 6 ++++++ + dom/base/FragmentOrElement.cpp | 1 - + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git dom/base/Element.cpp dom/base/Element.cpp +index 5f694b4b4ccd..26c7fbb6feef 100644 +--- dom/base/Element.cpp ++++ dom/base/Element.cpp +@@ -214,6 +214,12 @@ Element::GetSVGAnimatedClass() const + NS_IMETHODIMP + Element::QueryInterface(REFNSIID aIID, void** aInstancePtr) + { ++ if (aIID.Equals(NS_GET_IID(Element))) { ++ NS_ADDREF_THIS(); ++ *aInstancePtr = this; ++ return NS_OK; ++ } ++ + NS_ASSERTION(aInstancePtr, + "QueryInterface requires a non-NULL destination!"); + nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr); +diff --git dom/base/FragmentOrElement.cpp dom/base/FragmentOrElement.cpp +index 8c23d2de91f0..4b48fde78058 100644 +--- dom/base/FragmentOrElement.cpp ++++ dom/base/FragmentOrElement.cpp +@@ -2093,7 +2093,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + NS_INTERFACE_MAP_BEGIN(FragmentOrElement) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(FragmentOrElement) +- NS_INTERFACE_MAP_ENTRY(Element) + NS_INTERFACE_MAP_ENTRY(nsIContent) + NS_INTERFACE_MAP_ENTRY(nsINode) + NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget) diff --git a/www/waterfox/files/patch-bug1444521 b/www/waterfox/files/patch-bug1444521 new file mode 100644 index 000000000000..600f6a0d1d95 --- /dev/null +++ b/www/waterfox/files/patch-bug1444521 @@ -0,0 +1,26 @@ +commit 4694ff76f300 +Author: Punam <pdahiya@mozilla.com> +Date: Tue Mar 13 17:54:18 2018 -0700 + + Bug 1444521 - Preferences UI save to cloud downloads event listener. r=jaws, a=jcristau + + MozReview-Commit-ID: LbKr1rpXn4q + + --HG-- + extra : source : 2cab87e3a891fcdf4ef78b1dc01a6b7b5e69c853 +--- + browser/components/preferences/in-content/main.js | 1 + + 1 file changed, 1 insertion(+) + +diff --git browser/components/preferences/in-content-new/main.js browser/components/preferences/in-content-new/main.js +index 711a9e2cc424..5a579f4a49db 100644 +--- browser/components/preferences/in-content-new/main.js ++++ browser/components/preferences/in-content-new/main.js +@@ -410,6 +410,7 @@ var gMainPane = { + setEventListener("typeColumn", "click", gMainPane.sort); + setEventListener("actionColumn", "click", gMainPane.sort); + setEventListener("chooseFolder", "command", gMainPane.chooseFolder); ++ setEventListener("saveWhere", "command", gMainPane.handleSaveToCommand); + setEventListener("browser.download.dir", "change", gMainPane.displayDownloadDirPref); + setEventListener("saveWhere", "command", gMainPane.handleSaveToCommand); + diff --git a/www/waterfox/files/patch-bug1444541 b/www/waterfox/files/patch-bug1444541 new file mode 100644 index 000000000000..674bab18c65b --- /dev/null +++ b/www/waterfox/files/patch-bug1444541 @@ -0,0 +1,63 @@ +commit 2b33d877cb03 +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Mon Mar 19 15:52:36 2018 +0100 + + Bug 1444541 - Don't stop recorder on pagehide during frameswap. r=smaug, a=jcristau + + MozReview-Commit-ID: AZec0yXM1FI + + --HG-- + extra : source : bcdb264028e930756222a756e83bdca8574278e2 +--- + dom/media/MediaRecorder.cpp | 18 +++++++++++++++--- + dom/media/moz.build | 1 + + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git dom/media/MediaRecorder.cpp dom/media/MediaRecorder.cpp +index 60fe1ea0dae2..a229e4c38d73 100644 +--- dom/media/MediaRecorder.cpp ++++ dom/media/MediaRecorder.cpp +@@ -30,6 +30,7 @@ + #include "nsCharSeparatedTokenizer.h" + #include "nsContentTypeParser.h" + #include "nsContentUtils.h" ++#include "nsDocShell.h" + #include "nsError.h" + #include "nsIDocument.h" + #include "nsIPermissionManager.h" +@@ -1699,9 +1700,20 @@ MediaRecorder::NotifyOwnerDocumentActivityChanged() + nsIDocument* doc = window->GetExtantDoc(); + NS_ENSURE_TRUE_VOID(doc); + +- LOG(LogLevel::Debug, ("MediaRecorder %p document IsActive %d isVisible %d\n", +- this, doc->IsActive(), doc->IsVisible())); +- if (!doc->IsActive() || !doc->IsVisible()) { ++ bool inFrameSwap = false; ++ if (nsDocShell* docShell = static_cast<nsDocShell*>(doc->GetDocShell())) { ++ inFrameSwap = docShell->InFrameSwap(); ++ } ++ ++ LOG(LogLevel::Debug, ("MediaRecorder %p NotifyOwnerDocumentActivityChanged " ++ "IsActive=%d, " ++ "IsVisible=%d, " ++ "InFrameSwap=%d", ++ this, ++ doc->IsActive(), ++ doc->IsVisible(), ++ inFrameSwap)); ++ if (!doc->IsActive() || !(inFrameSwap || doc->IsVisible())) { + // Stop the session. + ErrorResult result; + Stop(result); +diff --git dom/media/moz.build dom/media/moz.build +index 194c73fd2f4c..4b1ca538f927 100644 +--- dom/media/moz.build ++++ dom/media/moz.build +@@ -312,6 +312,7 @@ EXTRA_JS_MODULES.media += [ + + LOCAL_INCLUDES += [ + '/caps', ++ '/docshell/base', + '/dom/base', + '/layout/generic', + '/layout/xul', diff --git a/www/waterfox/files/patch-bug1445582 b/www/waterfox/files/patch-bug1445582 new file mode 100644 index 000000000000..3d884316d61b --- /dev/null +++ b/www/waterfox/files/patch-bug1445582 @@ -0,0 +1,32 @@ +commit f708f8644183 +Author: Julien Cristau <jcristau@mozilla.com> +Date: Wed Mar 14 10:39:36 2018 +0100 + + Bug 1445582 - Error out when the searchplugins list is empty or a plugin is missing. r=froydnj, a=release + + MozReview-Commit-ID: DCUEc526d8D + + --HG-- + extra : source : 9bdac68266e290963ad3a47cad717339345d1f8a + extra : intermediate-source : 031af54f082d87d8a4b0bf6bb09556115ff59f20 +--- + browser/locales/Makefile.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git browser/locales/Makefile.in browser/locales/Makefile.in +index 6b0455bf0285..f4abd1f5e6ea 100644 +--- browser/locales/Makefile.in ++++ browser/locales/Makefile.in +@@ -61,10 +61,10 @@ STUB_HOOK = $(NSINSTALL) -D '$(ABS_DIST)/$(PKG_INST_PATH)'; \ + $(NULL) + endif + +-SEARCHPLUGINS_FILENAMES := $(shell $(call py_action,output_searchplugins_list,$(srcdir)/search/list.json $(AB_CD))) ++SEARCHPLUGINS_FILENAMES := $(or $(shell $(call py_action,output_searchplugins_list,$(srcdir)/search/list.json $(AB_CD))), $(error Missing search plugins)) + SEARCHPLUGINS_PATH := .deps/generated_$(AB_CD) + SEARCHPLUGINS_TARGET := libs searchplugins +-SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_FILENAMES)),$(or $(wildcard $(srcdir)/searchplugins/$(plugin)),$(warning Missing searchplugin: $(plugin)))) ++SEARCHPLUGINS := $(foreach plugin,$(addsuffix .xml,$(SEARCHPLUGINS_FILENAMES)),$(or $(wildcard $(srcdir)/searchplugins/$(plugin)),$(error Missing searchplugin: $(plugin)))) + # Some locale-specific search plugins may have preprocessor directives, but the + # default en-US ones do not. + SEARCHPLUGINS_FLAGS := --silence-missing-directive-warnings diff --git a/www/waterfox/files/patch-bug1447131 b/www/waterfox/files/patch-bug1447131 new file mode 100644 index 000000000000..ff424b941472 --- /dev/null +++ b/www/waterfox/files/patch-bug1447131 @@ -0,0 +1,160 @@ +commit c6116093dd45 +Author: Botond Ballo <botond@mozilla.com> +Date: Wed Mar 28 14:22:30 2018 -0400 + + Bug 1447131 - Handle backface-visibility:hidden in compositor hit testing. r=kats a=RyanVM + + MozReview-Commit-ID: EZhhSk3EZAL + + --HG-- + extra : source : e4b8a1682e6c4587649bcfbf5dab4b2ccdf4c741 +--- + gfx/layers/LayerMetricsWrapper.h | 7 +++++++ + gfx/layers/apz/src/APZCTreeManager.cpp | 9 ++++++--- + gfx/layers/apz/src/HitTestingTreeNode.cpp | 12 +++++++++++- + gfx/layers/apz/src/HitTestingTreeNode.h | 11 ++++++++++- + gfx/layers/wr/WebRenderScrollDataWrapper.h | 7 +++++++ + 5 files changed, 41 insertions(+), 5 deletions(-) + +diff --git gfx/layers/LayerMetricsWrapper.h gfx/layers/LayerMetricsWrapper.h +index baffde611220..dcf9fdc02b21 100644 +--- gfx/layers/LayerMetricsWrapper.h ++++ gfx/layers/LayerMetricsWrapper.h +@@ -446,6 +446,13 @@ public: + return mLayer->GetFixedPositionScrollContainerId(); + } + ++ bool IsBackfaceHidden() const ++ { ++ MOZ_ASSERT(IsValid()); ++ ++ return mLayer->IsBackfaceHidden(); ++ } ++ + // Expose an opaque pointer to the layer. Mostly used for printf + // purposes. This is not intended to be a general-purpose accessor + // for the underlying layer. +diff --git gfx/layers/apz/src/APZCTreeManager.cpp gfx/layers/apz/src/APZCTreeManager.cpp +index 9c66d22a41fe..7f82c3cee0a8 100644 +--- gfx/layers/apz/src/APZCTreeManager.cpp ++++ gfx/layers/apz/src/APZCTreeManager.cpp +@@ -835,7 +835,8 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + (!parentHasPerspective && aLayer.GetClipRect()) + ? Some(ParentLayerIntRegion(*aLayer.GetClipRect())) + : Nothing(), +- GetEventRegionsOverride(aParent, aLayer)); ++ GetEventRegionsOverride(aParent, aLayer), ++ aLayer.IsBackfaceHidden()); + node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(), + aLayer.GetScrollbarAnimationId(), + aLayer.GetScrollThumbData(), +@@ -948,7 +949,8 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + aLayer.GetVisibleRegion(), + aLayer.GetTransformTyped(), + clipRegion, +- GetEventRegionsOverride(aParent, aLayer)); ++ GetEventRegionsOverride(aParent, aLayer), ++ aLayer.IsBackfaceHidden()); + apzc->SetAncestorTransform(aAncestorTransform); + + PrintAPZCInfo(aLayer, apzc); +@@ -1047,7 +1049,8 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer, + aLayer.GetVisibleRegion(), + aLayer.GetTransformTyped(), + clipRegion, +- GetEventRegionsOverride(aParent, aLayer)); ++ GetEventRegionsOverride(aParent, aLayer), ++ aLayer.IsBackfaceHidden()); + } + + // Note: if layer properties must be propagated to nodes, RecvUpdate in +diff --git gfx/layers/apz/src/HitTestingTreeNode.cpp gfx/layers/apz/src/HitTestingTreeNode.cpp +index f16758e72ec6..ee1fce927c0d 100644 +--- gfx/layers/apz/src/HitTestingTreeNode.cpp ++++ gfx/layers/apz/src/HitTestingTreeNode.cpp +@@ -31,6 +31,7 @@ HitTestingTreeNode::HitTestingTreeNode(AsyncPanZoomController* aApzc, + , mScrollViewId(FrameMetrics::NULL_SCROLL_ID) + , mScrollbarAnimationId(0) + , mFixedPosTarget(FrameMetrics::NULL_SCROLL_ID) ++ , mIsBackfaceHidden(false) + , mOverride(EventRegionsOverride::NoOverride) + { + if (mIsPrimaryApzcHolder) { +@@ -263,13 +264,15 @@ HitTestingTreeNode::SetHitTestData(const EventRegions& aRegions, + const LayerIntRegion& aVisibleRegion, + const CSSTransformMatrix& aTransform, + const Maybe<ParentLayerIntRegion>& aClipRegion, +- const EventRegionsOverride& aOverride) ++ const EventRegionsOverride& aOverride, ++ bool aIsBackfaceHidden) + { + mEventRegions = aRegions; + mVisibleRegion = aVisibleRegion; + mTransform = aTransform; + mClipRegion = aClipRegion; + mOverride = aOverride; ++ mIsBackfaceHidden = aIsBackfaceHidden; + } + + bool +@@ -287,6 +290,13 @@ HitTestingTreeNode::HitTest(const LayerPoint& aPoint) const + } + + auto point = LayerIntPoint::Round(aPoint); ++ ++ // If the layer's backface is showing and it's hidden, don't hit it. ++ // This matches the behavior of main-thread hit testing in ++ // nsDisplayTransform::HitTest(). ++ if (mIsBackfaceHidden) { ++ return HitTestResult::HitNothing; ++ } + + // test against event regions in Layer coordinate space + if (!mEventRegions.mHitRegion.Contains(point.x, point.y)) { +diff --git gfx/layers/apz/src/HitTestingTreeNode.h gfx/layers/apz/src/HitTestingTreeNode.h +index 50e04e515652..aef703fd23b5 100644 +--- gfx/layers/apz/src/HitTestingTreeNode.h ++++ gfx/layers/apz/src/HitTestingTreeNode.h +@@ -89,7 +89,8 @@ public: + const LayerIntRegion& aVisibleRegion, + const CSSTransformMatrix& aTransform, + const Maybe<ParentLayerIntRegion>& aClipRegion, +- const EventRegionsOverride& aOverride); ++ const EventRegionsOverride& aOverride, ++ bool aIsBackfaceHidden); + bool IsOutsideClip(const ParentLayerPoint& aPoint) const; + + /* Scrollbar info */ +@@ -172,6 +173,14 @@ private: + * transforms. */ + CSSTransformMatrix mTransform; + ++ /* Whether layer L is backface-visibility:hidden, and its backface is ++ * currently visible. It's true that the latter depends on the layer's ++ * shadow transform, but the sorts of changes APZ makes to the shadow ++ * transform shouldn't change the backface from hidden to visible or ++ * vice versa, so it's sufficient to record this at hit test tree ++ * building time. */ ++ bool mIsBackfaceHidden; ++ + /* This is clip rect for L that we wish to use for hit-testing purposes. Note + * that this may not be exactly the same as the clip rect on layer L because + * of the touch-sensitive region provided by the GeckoContentController, or +diff --git gfx/layers/wr/WebRenderScrollDataWrapper.h gfx/layers/wr/WebRenderScrollDataWrapper.h +index 2e20bbdcdb8f..64d5319e10ff 100644 +--- gfx/layers/wr/WebRenderScrollDataWrapper.h ++++ gfx/layers/wr/WebRenderScrollDataWrapper.h +@@ -315,6 +315,13 @@ public: + return mLayer->GetFixedPositionScrollContainerId(); + } + ++ bool IsBackfaceHidden() const ++ { ++ // This is only used by APZCTM hit testing, and WR does its own ++ // hit testing, so no need to implement this. ++ return false; ++ } ++ + const void* GetLayer() const + { + MOZ_ASSERT(IsValid()); diff --git a/www/waterfox/files/patch-bug1447519 b/www/waterfox/files/patch-bug1447519 new file mode 100644 index 000000000000..dbad5642fa90 --- /dev/null +++ b/www/waterfox/files/patch-bug1447519 @@ -0,0 +1,22 @@ +Enable SkiaGL by default on OpenGL compositing platforms + +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index 93e56b00a961..61a2174c3384 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -882,15 +882,9 @@ pref("gfx.font_rendering.opentype_svg.enabled", true); + pref("gfx.canvas.azure.backends", "direct2d1.1,skia,cairo"); + pref("gfx.content.azure.backends", "direct2d1.1,skia,cairo"); + #else +-#ifdef XP_MACOSX + pref("gfx.content.azure.backends", "skia"); + pref("gfx.canvas.azure.backends", "skia"); +-// Accelerated cg canvas where available (10.7+) + pref("gfx.canvas.azure.accelerated", true); +-#else +-pref("gfx.canvas.azure.backends", "skia"); +-pref("gfx.content.azure.backends", "skia"); +-#endif + #endif + + pref("gfx.canvas.skiagl.dynamic-cache", true); diff --git a/www/waterfox/files/patch-bug1447969 b/www/waterfox/files/patch-bug1447969 new file mode 100644 index 000000000000..139b6248979d --- /dev/null +++ b/www/waterfox/files/patch-bug1447969 @@ -0,0 +1,26 @@ +commit 7cc076355a82 +Author: Gijs Kruitbosch <gijskruitbosch@gmail.com> +Date: Wed Mar 28 14:57:09 2018 +0100 + + Bug 1447969 - r=nchevobbe,a=abillings + + --HG-- + extra : rebase_source : e87a95170d907ddbc486e8536cee8685d6fe4a50 +--- + devtools/client/debugger/new/debugger.js | 2 +- + devtools/client/webconsole/console-output.js | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git devtools/client/webconsole/console-output.js devtools/client/webconsole/console-output.js +index 98fa15cb2858..701a38e970bd 100644 +--- devtools/client/webconsole/console-output.js ++++ devtools/client/webconsole/console-output.js +@@ -29,7 +29,7 @@ const defer = require("devtools/shared/defer"); + const MAX_STRING_GRIP_LENGTH = 36; + const {ELLIPSIS} = require("devtools/shared/l10n"); + +-const validProtocols = /^(http|https|ftp|data|javascript|resource|chrome):/i; ++const validProtocols = /^(http|https|ftp|resource|chrome):/i; + + // Constants for compatibility with the Web Console output implementation before + // bug 778766. diff --git a/www/waterfox/files/patch-bug1447989 b/www/waterfox/files/patch-bug1447989 new file mode 100644 index 000000000000..5feea1ff34d5 --- /dev/null +++ b/www/waterfox/files/patch-bug1447989 @@ -0,0 +1,25 @@ +commit d6e448266552 +Author: Jan de Mooij <jdemooij@mozilla.com> +Date: Wed Apr 25 09:02:12 2018 +0300 + + Bug 1447989 - Sweep script types in TypeMonitorResult. r=tcampbell a=lizzard + + --HG-- + extra : amend_source : f0b61269c44b087719613e4709a9e802cf9819f1 +--- + js/src/vm/TypeInference.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git js/src/vm/TypeInference.cpp js/src/vm/TypeInference.cpp +index 55897aa816db..4b44353d8d47 100644 +--- js/src/vm/TypeInference.cpp ++++ js/src/vm/TypeInference.cpp +@@ -3329,6 +3329,8 @@ js::TypeMonitorResult(JSContext* cx, JSScript* script, jsbytecode* pc, StackType + + AutoEnterAnalysis enter(cx); + ++ script->maybeSweepTypes(nullptr); ++ + MOZ_ASSERT(types == TypeScript::BytecodeTypes(script, pc)); + MOZ_ASSERT(!types->hasType(type)); + diff --git a/www/waterfox/files/patch-bug1448089 b/www/waterfox/files/patch-bug1448089 new file mode 100644 index 000000000000..620a12306ddd --- /dev/null +++ b/www/waterfox/files/patch-bug1448089 @@ -0,0 +1,207 @@ +commit f19c0ad7f5d0 +Author: Nicolas B. Pierron <nicolas.b.pierron@gmail.com> +Date: Thu Apr 19 07:32:00 2018 -0400 + + Bug 1448089 - Make MBasicBlock::addPredecessorSameInputsAs fallible. r=tcampbell a=lizzard + + --HG-- + extra : source : 131166cff47d79cdc09dd89a5a7d5d4ec9af6a75 +--- + js/src/jit/IonAnalysis.cpp | 51 ++++++++++++++++++++++++++++++---------------- + js/src/jit/MIRGraph.cpp | 7 ++++--- + js/src/jit/MIRGraph.h | 2 +- + 3 files changed, 39 insertions(+), 21 deletions(-) + +diff --git js/src/jit/IonAnalysis.cpp js/src/jit/IonAnalysis.cpp +index 7d15bbe0f290..d84af88991de 100644 +--- js/src/jit/IonAnalysis.cpp ++++ js/src/jit/IonAnalysis.cpp +@@ -714,7 +714,7 @@ BlockIsSingleTest(MBasicBlock* phiBlock, MBasicBlock* testBlock, MPhi** pphi, MT + + // Change block so that it ends in a goto to the specific target block. + // existingPred is an existing predecessor of the block. +-static void ++static MOZ_MUST_USE bool + UpdateGotoSuccessor(TempAllocator& alloc, MBasicBlock* block, MBasicBlock* target, + MBasicBlock* existingPred) + { +@@ -726,7 +726,7 @@ UpdateGotoSuccessor(TempAllocator& alloc, MBasicBlock* block, MBasicBlock* targe + MGoto* newGoto = MGoto::New(alloc, target); + block->end(newGoto); + +- target->addPredecessorSameInputsAs(block, existingPred); ++ return target->addPredecessorSameInputsAs(block, existingPred); + } + + // Change block so that it ends in a test of the specified value, going to +@@ -734,7 +734,7 @@ UpdateGotoSuccessor(TempAllocator& alloc, MBasicBlock* block, MBasicBlock* targe + // or ifFalse with the same values incoming to ifTrue/ifFalse as block. + // existingPred is not required to be a predecessor of ifTrue/ifFalse if block + // already ends in a test going to that block on a true/false result. +-static void ++static MOZ_MUST_USE bool + UpdateTestSuccessors(TempAllocator& alloc, MBasicBlock* block, + MDefinition* value, MBasicBlock* ifTrue, MBasicBlock* ifFalse, + MBasicBlock* existingPred) +@@ -746,19 +746,21 @@ UpdateTestSuccessors(TempAllocator& alloc, MBasicBlock* block, + + if (ifTrue != test->ifTrue()) { + test->ifTrue()->removePredecessor(block); +- ifTrue->addPredecessorSameInputsAs(block, existingPred); ++ if (!ifTrue->addPredecessorSameInputsAs(block, existingPred)) ++ return false; + MOZ_ASSERT(test->ifTrue() == test->getSuccessor(0)); + test->replaceSuccessor(0, ifTrue); + } + + if (ifFalse != test->ifFalse()) { + test->ifFalse()->removePredecessor(block); +- ifFalse->addPredecessorSameInputsAs(block, existingPred); ++ if (!ifFalse->addPredecessorSameInputsAs(block, existingPred)) ++ return false; + MOZ_ASSERT(test->ifFalse() == test->getSuccessor(1)); + test->replaceSuccessor(1, ifFalse); + } + +- return; ++ return true; + } + + MOZ_ASSERT(ins->isGoto()); +@@ -768,8 +770,11 @@ UpdateTestSuccessors(TempAllocator& alloc, MBasicBlock* block, + MTest* test = MTest::New(alloc, value, ifTrue, ifFalse); + block->end(test); + +- ifTrue->addPredecessorSameInputsAs(block, existingPred); +- ifFalse->addPredecessorSameInputsAs(block, existingPred); ++ if (!ifTrue->addPredecessorSameInputsAs(block, existingPred)) ++ return false; ++ if (!ifFalse->addPredecessorSameInputsAs(block, existingPred)) ++ return false; ++ return true; + } + + static bool +@@ -874,10 +879,14 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock) + phiBlock->removePredecessor(trueBranch); + graph.removeBlock(trueBranch); + } else if (initialTest->input() == trueResult) { +- UpdateGotoSuccessor(graph.alloc(), trueBranch, finalTest->ifTrue(), testBlock); ++ if (!UpdateGotoSuccessor(graph.alloc(), trueBranch, finalTest->ifTrue(), testBlock)) ++ return false; + } else { +- UpdateTestSuccessors(graph.alloc(), trueBranch, trueResult, +- finalTest->ifTrue(), finalTest->ifFalse(), testBlock); ++ if (!UpdateTestSuccessors(graph.alloc(), trueBranch, trueResult, ++ finalTest->ifTrue(), finalTest->ifFalse(), testBlock)) ++ { ++ return false; ++ } + } + + MBasicBlock* falseTarget = falseBranch; +@@ -886,15 +895,22 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock) + phiBlock->removePredecessor(falseBranch); + graph.removeBlock(falseBranch); + } else if (initialTest->input() == falseResult) { +- UpdateGotoSuccessor(graph.alloc(), falseBranch, finalTest->ifFalse(), testBlock); ++ if (!UpdateGotoSuccessor(graph.alloc(), falseBranch, finalTest->ifFalse(), testBlock)) ++ return false; + } else { +- UpdateTestSuccessors(graph.alloc(), falseBranch, falseResult, +- finalTest->ifTrue(), finalTest->ifFalse(), testBlock); ++ if (!UpdateTestSuccessors(graph.alloc(), falseBranch, falseResult, ++ finalTest->ifTrue(), finalTest->ifFalse(), testBlock)) ++ { ++ return false; ++ } + } + + // Short circuit the initial test to skip any constant branch eliminated above. +- UpdateTestSuccessors(graph.alloc(), initialBlock, initialTest->input(), +- trueTarget, falseTarget, testBlock); ++ if (!UpdateTestSuccessors(graph.alloc(), initialBlock, initialTest->input(), ++ trueTarget, falseTarget, testBlock)) ++ { ++ return false; ++ } + + // Remove phiBlock, if different from testBlock. + if (phiBlock != testBlock) { +@@ -950,7 +966,8 @@ jit::FoldEmptyBlocks(MIRGraph& graph) + + graph.removeBlock(block); + +- succ->addPredecessorSameInputsAs(pred, block); ++ if (!succ->addPredecessorSameInputsAs(pred, block)) ++ return false; + succ->removePredecessor(block); + } + return true; +diff --git js/src/jit/MIRGraph.cpp js/src/jit/MIRGraph.cpp +index 13d90d064555..f3466310f771 100644 +--- js/src/jit/MIRGraph.cpp ++++ js/src/jit/MIRGraph.cpp +@@ -1146,7 +1146,7 @@ MBasicBlock::addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred, uint32_ + return predecessors_.append(pred); + } + +-void ++bool + MBasicBlock::addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existingPred) + { + MOZ_ASSERT(pred); +@@ -1162,12 +1162,13 @@ MBasicBlock::addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existing + size_t existingPosition = indexForPredecessor(existingPred); + for (MPhiIterator iter = phisBegin(); iter != phisEnd(); iter++) { + if (!iter->addInputSlow(iter->getOperand(existingPosition))) +- oomUnsafe.crash("MBasicBlock::addPredecessorAdjustPhis"); ++ return false; + } + } + + if (!predecessors_.append(pred)) +- oomUnsafe.crash("MBasicBlock::addPredecessorAdjustPhis"); ++ return false; ++ return true; + } + + bool +diff --git js/src/jit/MIRGraph.h js/src/jit/MIRGraph.h +index bd661c5ca78f..ecc9a8871604 100644 +--- js/src/jit/MIRGraph.h ++++ js/src/jit/MIRGraph.h +@@ -272,7 +272,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock> + + // Add a predecessor which won't introduce any new phis to this block. + // This may be called after the contents of this block have been built. +- void addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existingPred); ++ MOZ_MUST_USE bool addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existingPred); + + // Stranger utilities used for inlining. + MOZ_MUST_USE bool addPredecessorWithoutPhis(MBasicBlock* pred); +commit 9544b32ac2a8 +Author: Steve Fink <sfink@mozilla.com> +Date: Fri Apr 20 13:32:47 2018 -0700 + + Bug 1448089 followup, remove now-unused variable to fix a CLOSED TREE. a=lizzard + + --HG-- + extra : source : d9f508d0e46e29c30a74d17820de3db933978324 +--- + js/src/jit/MIRGraph.cpp | 2 -- + 1 file changed, 2 deletions(-) + +diff --git js/src/jit/MIRGraph.cpp js/src/jit/MIRGraph.cpp +index f3466310f771..783ca2459226 100644 +--- js/src/jit/MIRGraph.cpp ++++ js/src/jit/MIRGraph.cpp +@@ -1156,8 +1156,6 @@ MBasicBlock::addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existing + MOZ_ASSERT(pred->hasLastIns()); + MOZ_ASSERT(!pred->successorWithPhis()); + +- AutoEnterOOMUnsafeRegion oomUnsafe; +- + if (!phisEmpty()) { + size_t existingPosition = indexForPredecessor(existingPred); + for (MPhiIterator iter = phisBegin(); iter != phisEnd(); iter++) { diff --git a/www/waterfox/files/patch-bug1448136 b/www/waterfox/files/patch-bug1448136 new file mode 100644 index 000000000000..c653ec375ad6 --- /dev/null +++ b/www/waterfox/files/patch-bug1448136 @@ -0,0 +1,71 @@ +commit 6ad2160158ba (origin/beta) +Author: Matthew Gaudet <mgaudet@mozilla.com> +Date: Fri Mar 23 13:10:08 2018 -0700 + + Bug 1448136 - Ensure Debug OSR transition is respected in InstanceOf Fallback stub. r=jandem, a=RyanVM + + --HG-- + extra : source : af66807a5c4b8366dc98d3aae7d55124003a1039 +--- + js/src/jit-test/tests/cacheir/bug1448136.js | 23 +++++++++++++++++++++++ + js/src/jit/BaselineIC.cpp | 9 ++++++++- + 2 files changed, 31 insertions(+), 1 deletion(-) + +diff --git js/src/jit-test/tests/cacheir/bug1448136.js js/src/jit-test/tests/cacheir/bug1448136.js +new file mode 100644 +index 000000000000..6256cb751e34 +--- /dev/null ++++ js/src/jit-test/tests/cacheir/bug1448136.js +@@ -0,0 +1,23 @@ ++print = function(s) { return s.toString(); } ++assertEq = function(a,b) { ++ try { print(a); print(b); } catch(exc) {} ++} ++g = newGlobal(); ++g.parent = this; ++g.eval("(" + function() { ++ Debugger(parent).onExceptionUnwind = function(frame) { ++ frame.older ++ } ++} + ")()") ++function a() {}; ++function b() {}; ++for (let _ of Array(100)) ++ assertEq(b instanceof a, true); ++function c(){}; ++function d(){}; ++function e(){}; ++Object.defineProperty(a, Symbol.hasInstance, {value: assertEq }); ++let funcs = [a, b, c, d]; ++for (let f of funcs) ++ assertEq(e instanceof f, true); ++ +diff --git js/src/jit/BaselineIC.cpp js/src/jit/BaselineIC.cpp +index 69aabacda0cd..20440b4a980b 100644 +--- js/src/jit/BaselineIC.cpp ++++ js/src/jit/BaselineIC.cpp +@@ -4146,9 +4146,12 @@ TryAttachInstanceOfStub(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallba + } + + static bool +-DoInstanceOfFallback(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallback* stub, ++DoInstanceOfFallback(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallback* stub_, + HandleValue lhs, HandleValue rhs, MutableHandleValue res) + { ++ // This fallback stub may trigger debug mode toggling. ++ DebugModeOSRVolatileStub<ICInstanceOf_Fallback*> stub(ICStubEngine::Baseline, frame, stub_); ++ + FallbackICSpew(cx, stub, "InstanceOf"); + + if (!rhs.isObject()) { +@@ -4163,6 +4166,10 @@ DoInstanceOfFallback(JSContext* cx, BaselineFrame* frame, ICInstanceOf_Fallback* + + res.setBoolean(cond); + ++ // Check if debug mode toggling made the stub invalid. ++ if (stub.invalid()) ++ return true; ++ + if (!obj->is<JSFunction>()) { + stub->noteUnoptimizableAccess(); + return true; diff --git a/www/waterfox/files/patch-bug1448200 b/www/waterfox/files/patch-bug1448200 new file mode 100644 index 000000000000..e2088da63b9e --- /dev/null +++ b/www/waterfox/files/patch-bug1448200 @@ -0,0 +1,36 @@ +commit 64e2cd0e1310 +Author: Blake Kaplan <mrbkap@gmail.com> +Date: Fri Mar 30 16:15:11 2018 -0700 + + Bug 1448200 - Handle the creation of the spellchecker more gracefully. r=Felipe a=lizzard + + If the user right-clicks on an input field and that click causes us to create + a spellchecker, then it won't be initialized in time to show the context menu. + Handle that case more gracefully by passing that state up to the parent. + + MozReview-Commit-ID: 1hjxloq2OLp + + --HG-- + extra : source : 8fbafbc46da259a054dd00feb93abc20e3140c56 + extra : histedit_source : 8f5a1548dad701ac23e34c9a15a59e67b50188c0 +--- + toolkit/modules/InlineSpellCheckerContent.jsm | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git toolkit/modules/InlineSpellCheckerContent.jsm toolkit/modules/InlineSpellCheckerContent.jsm +index 5184f1ec7dcb..974fbba879d7 100644 +--- toolkit/modules/InlineSpellCheckerContent.jsm ++++ toolkit/modules/InlineSpellCheckerContent.jsm +@@ -49,6 +49,12 @@ var InlineSpellCheckerContent = { + enableRealTimeSpell: false }; + } + ++ if (spellChecker.initialSpellCheckPending) { ++ return { canSpellCheck: true, ++ initialSpellCheckPending: true, ++ enableRealTimeSpell: true }; ++ } ++ + let dictionaryList = {}; + let realSpellChecker = spellChecker.mInlineSpellChecker.spellChecker; + realSpellChecker.GetDictionaryList(dictionaryList, {}); diff --git a/www/waterfox/files/patch-bug1448612 b/www/waterfox/files/patch-bug1448612 new file mode 100644 index 000000000000..61ab540b96f1 --- /dev/null +++ b/www/waterfox/files/patch-bug1448612 @@ -0,0 +1,72 @@ +commit 2ff478b5f969 +Author: Emilio Cobos Álvarez <emilio@crisal.io> +Date: Thu Mar 29 10:02:00 2018 -0400 + + Bug 1448612 - Don't take ownership of the stream data too early. r=baku, a=RyanVM + + MozReview-Commit-ID: 8e8PNR9NvwW +--- + dom/fetch/FetchConsumer.cpp | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git dom/fetch/FetchConsumer.cpp dom/fetch/FetchConsumer.cpp +index cde565705188..a374d1fed8c2 100644 +--- dom/fetch/FetchConsumer.cpp ++++ dom/fetch/FetchConsumer.cpp +@@ -109,13 +109,11 @@ class ContinueConsumeBodyControlRunnable final : public MainThreadWorkerControlR + RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer; + + public: +- ContinueConsumeBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer, +- uint8_t* aResult) ++ ContinueConsumeBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer) + : MainThreadWorkerControlRunnable(aFetchBodyConsumer->GetWorkerPrivate()) + , mFetchBodyConsumer(aFetchBodyConsumer) + { + MOZ_ASSERT(NS_IsMainThread()); +- free(aResult); + } + + bool +@@ -289,14 +287,12 @@ public: + // shutting down procedure. + + RefPtr<ContinueConsumeBodyControlRunnable<Derived>> r = +- new ContinueConsumeBodyControlRunnable<Derived>(mFetchBodyConsumer, +- nonconstResult); ++ new ContinueConsumeBodyControlRunnable<Derived>(mFetchBodyConsumer); + if (NS_WARN_IF(!r->Dispatch())) { + return NS_ERROR_FAILURE; + } + +- // FetchBody is responsible for data. +- return NS_SUCCESS_ADOPTED_DATA; ++ return NS_OK; + } + + virtual void BlobStoreCompleted(MutableBlobStorage* aBlobStorage, +commit 84a72343d0ba +Author: Ryan VanderMeulen <ryanvm@gmail.com> +Date: Thu Mar 29 10:46:07 2018 -0400 + + Bug 1448612 - Mark ContinueConsumeBodyControlRunnable as explicit to make the static analysis happy. r=emilio, a=bustage + + --HG-- + extra : rebase_source : d11e91ec335292d9448df17a5c05c98f6837884c +--- + dom/fetch/FetchConsumer.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git dom/fetch/FetchConsumer.cpp dom/fetch/FetchConsumer.cpp +index a374d1fed8c2..2771a23843e3 100644 +--- dom/fetch/FetchConsumer.cpp ++++ dom/fetch/FetchConsumer.cpp +@@ -109,7 +109,7 @@ class ContinueConsumeBodyControlRunnable final : public MainThreadWorkerControlR + RefPtr<FetchBodyConsumer<Derived>> mFetchBodyConsumer; + + public: +- ContinueConsumeBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer) ++ explicit ContinueConsumeBodyControlRunnable(FetchBodyConsumer<Derived>* aFetchBodyConsumer) + : MainThreadWorkerControlRunnable(aFetchBodyConsumer->GetWorkerPrivate()) + , mFetchBodyConsumer(aFetchBodyConsumer) + { diff --git a/www/waterfox/files/patch-bug1448863 b/www/waterfox/files/patch-bug1448863 new file mode 100644 index 000000000000..bf351ae38a1c --- /dev/null +++ b/www/waterfox/files/patch-bug1448863 @@ -0,0 +1,214 @@ +commit 7fd98bb22f4c +Author: Byron Campen [:bwc] <docfaraday@gmail.com> +Date: Mon Mar 26 10:19:31 2018 -0500 + + Bug 1448863 - Stop sync dispatching in Decode. r=jesup, a=RyanVM + + MozReview-Commit-ID: 3EK0zAsFpHz + + --HG-- + extra : source : 549f0b8075d587eca29a6a72b1b62caf84d4b4fc +--- + .../src/media-conduit/WebrtcGmpVideoCodec.cpp | 122 ++++++++++----------- + .../src/media-conduit/WebrtcGmpVideoCodec.h | 7 +- + media/webrtc/webrtc.mozbuild | 4 + + 3 files changed, 65 insertions(+), 68 deletions(-) + +diff --git media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp +index 6cd4a1e1e200..81fd5f099454 100644 +--- media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp ++++ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.cpp +@@ -770,14 +770,8 @@ WebrtcGmpVideoDecoder::GmpInitDone(GMPVideoDecoderProxy* aGMP, + nsTArray<UniquePtr<GMPDecodeData>> temp; + temp.SwapElements(mQueuedFrames); + for (auto& queued : temp) { +- int rv = Decode_g(queued->mImage, +- queued->mMissingFrames, +- nullptr, +- nullptr, +- queued->mRenderTimeMs); +- if (rv) { +- return rv; +- } ++ Decode_g(RefPtr<WebrtcGmpVideoDecoder>(this), ++ nsAutoPtr<GMPDecodeData>(queued.release())); + } + } + +@@ -805,61 +799,58 @@ WebrtcGmpVideoDecoder::Decode(const webrtc::EncodedImage& aInputImage, + const webrtc::CodecSpecificInfo* aCodecSpecificInfo, + int64_t aRenderTimeMs) + { +- int32_t ret; + MOZ_ASSERT(mGMPThread); + MOZ_ASSERT(!NS_IsMainThread()); +- // Would be really nice to avoid this sync dispatch, but it would require a +- // copy of the frame, since it doesn't appear to actually have a refcount. +- // Passing 'this' is safe since this is synchronous. +- mozilla::SyncRunnable::DispatchToThread(mGMPThread, +- WrapRunnableRet(&ret, this, +- &WebrtcGmpVideoDecoder::Decode_g, +- aInputImage, +- aMissingFrames, +- aFragmentation, +- aCodecSpecificInfo, +- aRenderTimeMs)); ++ if (!aInputImage._length) { ++ return WEBRTC_VIDEO_CODEC_ERROR; ++ } ++ ++ nsAutoPtr<GMPDecodeData> decodeData(new GMPDecodeData(aInputImage, ++ aMissingFrames, ++ aRenderTimeMs)); ++ ++ mGMPThread->Dispatch(WrapRunnableNM(&WebrtcGmpVideoDecoder::Decode_g, ++ RefPtr<WebrtcGmpVideoDecoder>(this), ++ decodeData), ++ NS_DISPATCH_NORMAL); + +- return ret; ++ return WEBRTC_VIDEO_CODEC_OK; + } + +-int32_t +-WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage, +- bool aMissingFrames, +- const webrtc::RTPFragmentationHeader* aFragmentation, +- const webrtc::CodecSpecificInfo* aCodecSpecificInfo, +- int64_t aRenderTimeMs) +-{ +- if (!mGMP) { +- if (mInitting) { ++/* static */ ++// Using nsAutoPtr because WrapRunnable doesn't support move semantics ++void ++WebrtcGmpVideoDecoder::Decode_g(const RefPtr<WebrtcGmpVideoDecoder>& aThis, ++ nsAutoPtr<GMPDecodeData> aDecodeData) ++{ ++ if (!aThis->mGMP) { ++ if (aThis->mInitting) { + // InitDone hasn't been called yet (race) +- GMPDecodeData *data = new GMPDecodeData(aInputImage, +- aMissingFrames, +- aRenderTimeMs); +- mQueuedFrames.AppendElement(data); +- return WEBRTC_VIDEO_CODEC_OK; ++ aThis->mQueuedFrames.AppendElement(aDecodeData.forget()); ++ return; + } + // destroyed via Terminate(), failed to init, or just not initted yet + LOGD(("GMP Decode: not initted yet")); +- return WEBRTC_VIDEO_CODEC_ERROR; ++ return; + } +- MOZ_ASSERT(mQueuedFrames.IsEmpty()); +- MOZ_ASSERT(mHost); + +- if (!aInputImage._length) { +- return WEBRTC_VIDEO_CODEC_ERROR; +- } ++ MOZ_ASSERT(aThis->mQueuedFrames.IsEmpty()); ++ MOZ_ASSERT(aThis->mHost); + + GMPVideoFrame* ftmp = nullptr; +- GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp); ++ GMPErr err = aThis->mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp); + if (err != GMPNoErr) { +- return WEBRTC_VIDEO_CODEC_ERROR; ++ LOG(LogLevel::Error, ("%s: CreateFrame failed (%u)!", ++ __PRETTY_FUNCTION__, static_cast<unsigned>(err))); ++ return; + } + + GMPUniquePtr<GMPVideoEncodedFrame> frame(static_cast<GMPVideoEncodedFrame*>(ftmp)); +- err = frame->CreateEmptyFrame(aInputImage._length); ++ err = frame->CreateEmptyFrame(aDecodeData->mImage._length); + if (err != GMPNoErr) { +- return WEBRTC_VIDEO_CODEC_ERROR; ++ LOG(LogLevel::Error, ("%s: CreateEmptyFrame failed (%u)!", ++ __PRETTY_FUNCTION__, static_cast<unsigned>(err))); ++ return; + } + + // XXX At this point, we only will get mode1 data (a single length and a buffer) +@@ -867,18 +858,20 @@ WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage, + *(reinterpret_cast<uint32_t*>(frame->Buffer())) = frame->Size(); + + // XXX It'd be wonderful not to have to memcpy the encoded data! +- memcpy(frame->Buffer()+4, aInputImage._buffer+4, frame->Size()-4); ++ memcpy(frame->Buffer()+4, aDecodeData->mImage._buffer+4, frame->Size()-4); + +- frame->SetEncodedWidth(aInputImage._encodedWidth); +- frame->SetEncodedHeight(aInputImage._encodedHeight); +- frame->SetTimeStamp((aInputImage._timeStamp * 1000ll)/90); // rounds down +- frame->SetCompleteFrame(aInputImage._completeFrame); ++ frame->SetEncodedWidth(aDecodeData->mImage._encodedWidth); ++ frame->SetEncodedHeight(aDecodeData->mImage._encodedHeight); ++ frame->SetTimeStamp((aDecodeData->mImage._timeStamp * 1000ll)/90); // rounds down ++ frame->SetCompleteFrame(aDecodeData->mImage._completeFrame); + frame->SetBufferType(GMP_BufferLength32); + + GMPVideoFrameType ft; +- int32_t ret = WebrtcFrameTypeToGmpFrameType(aInputImage._frameType, &ft); ++ int32_t ret = WebrtcFrameTypeToGmpFrameType(aDecodeData->mImage._frameType, &ft); + if (ret != WEBRTC_VIDEO_CODEC_OK) { +- return ret; ++ LOG(LogLevel::Error, ("%s: WebrtcFrameTypeToGmpFrameType failed (%u)!", ++ __PRETTY_FUNCTION__, static_cast<unsigned>(ret))); ++ return; + } + + // Bug XXXXXX: Set codecSpecific info +@@ -889,20 +882,23 @@ WebrtcGmpVideoDecoder::Decode_g(const webrtc::EncodedImage& aInputImage, + nsTArray<uint8_t> codecSpecificInfo; + codecSpecificInfo.AppendElements((uint8_t*)&info, sizeof(GMPCodecSpecificInfo)); + +- LOGD(("GMP Decode: %" PRIu64 ", len %zu%s", frame->TimeStamp(), aInputImage._length, +- ft == kGMPKeyFrame ? ", KeyFrame" : "")); +- nsresult rv = mGMP->Decode(Move(frame), +- aMissingFrames, +- codecSpecificInfo, +- aRenderTimeMs); ++ LOGD(("GMP Decode: %" PRIu64 ", len %zu%s", frame->TimeStamp(), ++ aDecodeData->mImage._length, ft == kGMPKeyFrame ? ", KeyFrame" : "")); ++ ++ nsresult rv = aThis->mGMP->Decode(Move(frame), ++ aDecodeData->mMissingFrames, ++ codecSpecificInfo, ++ aDecodeData->mRenderTimeMs); + if (NS_FAILED(rv)) { +- return WEBRTC_VIDEO_CODEC_ERROR; ++ LOG(LogLevel::Error, ("%s: Decode failed (rv=%u)!", ++ __PRETTY_FUNCTION__, static_cast<unsigned>(rv))); + } +- if(mDecoderStatus != GMPNoErr){ +- mDecoderStatus = GMPNoErr; +- return WEBRTC_VIDEO_CODEC_ERROR; ++ ++ if(aThis->mDecoderStatus != GMPNoErr){ ++ aThis->mDecoderStatus = GMPNoErr; ++ LOG(LogLevel::Error, ("%s: Decoder status is bad (%u)!", ++ __PRETTY_FUNCTION__, static_cast<unsigned>(aThis->mDecoderStatus))); + } +- return WEBRTC_VIDEO_CODEC_OK; + } + + int32_t +diff --git media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h +index 0f125d0b311a..92b5a270267e 100644 +--- media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h ++++ media/webrtc/signaling/src/media-conduit/WebrtcGmpVideoCodec.h +@@ -469,11 +469,8 @@ private: + RefPtr<GmpInitDoneRunnable> mInitDone; + }; + +- virtual int32_t Decode_g(const webrtc::EncodedImage& aInputImage, +- bool aMissingFrames, +- const webrtc::RTPFragmentationHeader* aFragmentation, +- const webrtc::CodecSpecificInfo* aCodecSpecificInfo, +- int64_t aRenderTimeMs); ++ static void Decode_g(const RefPtr<WebrtcGmpVideoDecoder>& aThis, ++ nsAutoPtr<GMPDecodeData> aDecodeData); + + nsCOMPtr<mozIGeckoMediaPluginService> mMPS; + nsCOMPtr<nsIThread> mGMPThread; diff --git a/www/waterfox/files/patch-bug1449157 b/www/waterfox/files/patch-bug1449157 new file mode 100644 index 000000000000..b1c4c5856bf0 --- /dev/null +++ b/www/waterfox/files/patch-bug1449157 @@ -0,0 +1,26 @@ +commit c05f2d4f28e9 +Author: Jonathan Kew <jkew@mozilla.com> +Date: Wed Mar 28 14:42:20 2018 +0100 + + Bug 1449157 - Guard against mContent being null in nsFrame::HandlePress. r=dholbert, a=jcristau + + --HG-- + extra : rebase_source : cee8a6f6ecce503cddf3492ffaf42bc317f1851c + extra : source : c09b8a694cb5d0442aa293eace75a18058b675d5 +--- + layout/generic/nsFrame.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git layout/generic/nsFrame.cpp layout/generic/nsFrame.cpp +index fd313f9a792f..5fa8bd9174e5 100644 +--- layout/generic/nsFrame.cpp ++++ layout/generic/nsFrame.cpp +@@ -4275,7 +4275,7 @@ nsFrame::HandlePress(nsPresContext* aPresContext, + // starting a new selection since the user may be trying to + // drag the selected region to some other app. + +- if (GetContent()->IsSelectionDescendant()) ++ if (GetContent() && GetContent()->IsSelectionDescendant()) + { + bool inSelection = false; + UniquePtr<SelectionDetails> details diff --git a/www/waterfox/files/patch-bug1449352 b/www/waterfox/files/patch-bug1449352 new file mode 100644 index 000000000000..917aee14bb2c --- /dev/null +++ b/www/waterfox/files/patch-bug1449352 @@ -0,0 +1,52 @@ +commit d09c62cb1ed0 +Author: Lee Salzman <lsalzman@mozilla.com> +Date: Tue Apr 10 12:43:59 2018 -0400 + + Bug 1449352 - always composite 24 depth WindowSurfaceX11 as BGRX. r=jrmuizel a=jcristau + + MozReview-Commit-ID: 3xeE3EEttR6 + + --HG-- + extra : source : c6860625a6fd2bcb64f23e9a621521741ae7503e +--- + widget/gtk/WindowSurfaceX11.cpp | 8 +------- + widget/gtk/WindowSurfaceX11Image.cpp | 4 ++++ + 2 files changed, 5 insertions(+), 7 deletions(-) + +diff --git widget/gtk/WindowSurfaceX11.cpp widget/gtk/WindowSurfaceX11.cpp +index 32e3c43ef9ef..a5616f77a6ed 100644 +--- widget/gtk/WindowSurfaceX11.cpp ++++ widget/gtk/WindowSurfaceX11.cpp +@@ -36,16 +36,10 @@ WindowSurfaceX11::GetVisualFormat(const Visual* aVisual, unsigned int aDepth) + } + break; + case 24: +- // Only support the BGRX layout, and report it as BGRA to the compositor. +- // The alpha channel will be discarded when we put the image. +- // Cairo/pixman lacks some fast paths for compositing BGRX onto BGRA, so +- // just report it as BGRX directly in that case. + if (aVisual->red_mask == 0xff0000 && + aVisual->green_mask == 0xff00 && + aVisual->blue_mask == 0xff) { +- gfx::BackendType backend = gfxPlatform::GetPlatform()->GetDefaultContentBackend(); +- return backend == gfx::BackendType::CAIRO ? gfx::SurfaceFormat::B8G8R8X8 +- : gfx::SurfaceFormat::B8G8R8A8; ++ return gfx::SurfaceFormat::B8G8R8X8; + } + break; + case 16: +diff --git widget/gtk/WindowSurfaceX11Image.cpp widget/gtk/WindowSurfaceX11Image.cpp +index 59db17b642f2..f89d0d1a13d5 100644 +--- widget/gtk/WindowSurfaceX11Image.cpp ++++ widget/gtk/WindowSurfaceX11Image.cpp +@@ -58,6 +58,10 @@ WindowSurfaceX11Image::Lock(const LayoutDeviceIntRegion& aRegion) + + gfxImageFormat format = mImageSurface->Format(); + // Cairo prefers compositing to BGRX instead of BGRA where possible. ++ // Cairo/pixman lacks some fast paths for compositing BGRX onto BGRA, so ++ // just report it as BGRX directly in that case. ++ // Otherwise, for Skia, report it as BGRA to the compositor. The alpha ++ // channel will be discarded when we put the image. + if (format == gfx::SurfaceFormat::X8R8G8B8_UINT32) { + gfx::BackendType backend = gfxVars::ContentBackend(); + if (!gfx::Factory::DoesBackendSupportDataDrawtarget(backend)) { diff --git a/www/waterfox/files/patch-bug1450448 b/www/waterfox/files/patch-bug1450448 new file mode 100644 index 000000000000..61489e3f638c --- /dev/null +++ b/www/waterfox/files/patch-bug1450448 @@ -0,0 +1,40 @@ +commit fbba8d988c94 +Author: Johann Hofmann <jhofmann@mozilla.com> +Date: Tue May 15 22:02:33 2018 +0200 + + Bug 1450448 - Correctly handle non-initialized appCache in site data preferences. r=Gijs, a=RyanVM + + MozReview-Commit-ID: IhQGAWNQtR0 + + --HG-- + extra : rebase_source : c1e902883a977c54ccafd4a1c3042d0a17660996 + extra : source : 9f41afd3012718d839033663196a746a47065007 +--- + browser/modules/SiteDataManager.jsm | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git browser/components/preferences/SiteDataManager.jsm browser/components/preferences/SiteDataManager.jsm +index 118a40ce38fc8..9e08e00c38c5b 100644 +--- browser/components/preferences/SiteDataManager.jsm ++++ browser/components/preferences/SiteDataManager.jsm +@@ -192,7 +192,19 @@ var SiteDataManager = { + }, + + _updateAppCache() { +- let groups = this._appCache.getGroups(); ++ let groups; ++ try { ++ groups = this._appCache.getGroups(); ++ } catch (e) { ++ // NS_ERROR_NOT_AVAILABLE means that appCache is not initialized, ++ // which probably means the user has disabled it. Otherwise, log an ++ // error. Either way, there's nothing we can do here. ++ if (e.result != Cr.NS_ERROR_NOT_AVAILABLE) { ++ Cu.reportError(e); ++ } ++ return; ++ } ++ + for (let group of groups) { + let cache = this._appCache.getActiveCache(group); + if (cache.usage <= 0) { diff --git a/www/waterfox/files/patch-bug1450538 b/www/waterfox/files/patch-bug1450538 new file mode 100644 index 000000000000..972d14989a87 --- /dev/null +++ b/www/waterfox/files/patch-bug1450538 @@ -0,0 +1,27 @@ +commit 62f1f53340be +Author: Masatoshi Kimura <VYV03354@nifty.ne.jp> +Date: Sat Apr 14 10:29:36 2018 +0900 + + Bug 1450538 - Use nsIURI::GetDisplaySpec to compensate a change to nsIURI::GetSpec. r=valentin a=jcristau + + MozReview-Commit-ID: 5xYAbx78K3q + + --HG-- + extra : source : aee0f2f18cde9801a95357c309bcdce7adf0f4f6 +--- + docshell/base/nsDocShell.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git docshell/base/nsDocShell.cpp docshell/base/nsDocShell.cpp +index 608977e54ec7..aae0e29265be 100644 +--- docshell/base/nsDocShell.cpp ++++ docshell/base/nsDocShell.cpp +@@ -13816,7 +13816,7 @@ nsDocShell::OnOverLink(nsIContent* aContent, + } + + nsAutoCString spec; +- rv = aURI->GetSpec(spec); ++ rv = aURI->GetDisplaySpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + + NS_ConvertUTF8toUTF16 uStr(spec); diff --git a/www/waterfox/files/patch-bug1450565 b/www/waterfox/files/patch-bug1450565 new file mode 100644 index 000000000000..0789fde4ddf9 --- /dev/null +++ b/www/waterfox/files/patch-bug1450565 @@ -0,0 +1,27 @@ +commit 50367fb5e8ce +Author: Shane Caraveo <scaraveo@mozilla.com> +Date: Tue Apr 17 10:06:13 2018 -0500 + + Bug 1450565 use GET for initial authorization request, r=mossop a=jcristau + + MozReview-Commit-ID: 70PQSeoxvOF + + --HG-- + extra : source : e17c105c0be870ad5d07a1ff0b0a5da1646f35a7 +--- + toolkit/components/extensions/ext-identity.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git toolkit/components/extensions/ext-identity.js toolkit/components/extensions/ext-identity.js +index db4ea3e80a06..ab7811774fb6 100644 +--- toolkit/components/extensions/ext-identity.js ++++ toolkit/components/extensions/ext-identity.js +@@ -14,7 +14,7 @@ var { + const checkRedirected = (url, redirectURI) => { + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); +- xhr.open("HEAD", url); ++ xhr.open("GET", url); + // We expect this if the user has not authenticated. + xhr.onload = () => { + reject(0); diff --git a/www/waterfox/files/patch-bug1451262 b/www/waterfox/files/patch-bug1451262 new file mode 100644 index 000000000000..d05ee1612e18 --- /dev/null +++ b/www/waterfox/files/patch-bug1451262 @@ -0,0 +1,62 @@ +commit 659634effe22 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Wed Apr 4 13:47:46 2018 +0300 + + Bug 1451262 - Clear gSocketThread after finishing all operations so we don't trigger thread assertions r=mayhemer + + MozReview-Commit-ID: AHMPd72S2GB + + --HG-- + extra : rebase_source : fe5fb1604e771f223d78f23fcf9d37b1f85763f9 +--- + netwerk/base/nsSocketTransportService2.cpp | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git netwerk/base/nsSocketTransportService2.cpp netwerk/base/nsSocketTransportService2.cpp +index abaa8f8fb6da3..a16d888998ae9 100644 +--- netwerk/base/nsSocketTransportService2.cpp ++++ netwerk/base/nsSocketTransportService2.cpp +@@ -1067,9 +1067,8 @@ nsSocketTransportService::Run() + // socket detach handlers get processed. + NS_ProcessPendingEvents(mRawThread); + +- gSocketThread = nullptr; +- + psm::StopSSLServerCertVerificationThreads(); ++ gSocketThread = nullptr; + + SOCKET_LOG(("STS thread exit\n")); + +commit 43e3838b681b +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Thu May 10 10:37:24 2018 +0200 + + Bug 1451262 - Call NS_ProcessPendingEvents after StopSSLServerCertVerificationThreads. r=mayhemer, a=RyanVM + + If there are still pending events after we null out gSocketThread, OnSocketThread() will always return false, which can trigger assertions. + + MozReview-Commit-ID: CovFIU3cKL + + --HG-- + extra : source : b859a16d74500eed3b00d7e0bc1eba0d9e0c34a4 +--- + netwerk/base/nsSocketTransportService2.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git netwerk/base/nsSocketTransportService2.cpp netwerk/base/nsSocketTransportService2.cpp +index 637a7d95f748c..06cda53f52056 100644 +--- netwerk/base/nsSocketTransportService2.cpp ++++ netwerk/base/nsSocketTransportService2.cpp +@@ -1067,7 +1067,12 @@ nsSocketTransportService::Run() + // socket detach handlers get processed. + NS_ProcessPendingEvents(mRawThread); + ++ // Stopping the SLL threads can generate new events, so we need to ++ // process them before nulling out gSocketThread, otherwise we can get ++ // !onSocketThread assertions. + psm::StopSSLServerCertVerificationThreads(); ++ NS_ProcessPendingEvents(mRawThread); ++ + gSocketThread = nullptr; + + SOCKET_LOG(("STS thread exit\n")); diff --git a/www/waterfox/files/patch-bug1451673 b/www/waterfox/files/patch-bug1451673 new file mode 100644 index 000000000000..e2534cbbdc2f --- /dev/null +++ b/www/waterfox/files/patch-bug1451673 @@ -0,0 +1,28 @@ +commit 5dbb51979bb7 +Author: alexander :surkov <surkov.alexander@gmail.com> +Date: Thu Apr 5 10:24:00 2018 +0300 + + Bug 1451673 - "Crash in mozilla::a11y::HTMLTableAccessible::IsProbablyLayoutTable" r=MarcoZ a=jcristau + + --HG-- + extra : source : 5a6db1121fcede3d0844ec1be195ab7858cd1e19 +--- + accessible/html/HTMLTableAccessible.cpp | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git accessible/html/HTMLTableAccessible.cpp accessible/html/HTMLTableAccessible.cpp +index 18c7c71a0ae2..1647f3251ec8 100644 +--- accessible/html/HTMLTableAccessible.cpp ++++ accessible/html/HTMLTableAccessible.cpp +@@ -1063,6 +1063,11 @@ HTMLTableAccessible::IsProbablyLayoutTable() + if (child->Role() == roles::ROW) { + prevRowColor = rowColor; + nsIFrame* rowFrame = child->GetFrame(); ++ MOZ_ASSERT(rowFrame, "Table hierarchy got screwed up"); ++ if (!rowFrame) { ++ RETURN_LAYOUT_ANSWER(false, "Unexpected table hierarchy"); ++ } ++ + rowColor = rowFrame->StyleBackground()->BackgroundColor(rowFrame); + + if (childIdx > 0 && prevRowColor != rowColor) diff --git a/www/waterfox/files/patch-bug1452619 b/www/waterfox/files/patch-bug1452619 new file mode 100644 index 000000000000..f86ea111b1f3 --- /dev/null +++ b/www/waterfox/files/patch-bug1452619 @@ -0,0 +1,234 @@ +commit d2a37cf6d599 +Author: Jeff Walden <jwalden@mit.edu> +Date: Mon Apr 9 12:02:43 2018 -0700 + + Bug 1452619 - Implement mozilla::IsAsciiAlpha. r=froydnj, a=lizzard +--- + js/src/jsstr.h | 3 +- + mfbt/TextUtils.h | 58 +++++++++++++++++++++++ + mfbt/moz.build | 1 + + mfbt/tests/TestTextUtils.cpp | 106 +++++++++++++++++++++++++++++++++++++++++++ + mfbt/tests/moz.build | 1 + + 5 files changed, 168 insertions(+), 1 deletion(-) + +diff --git js/src/jsstr.h js/src/jsstr.h +index 3b92aa21b344..7e9621d4a265 100644 +--- js/src/jsstr.h ++++ js/src/jsstr.h +@@ -9,6 +9,7 @@ + + #include "mozilla/HashFunctions.h" + #include "mozilla/PodOperations.h" ++#include "mozilla/TextUtils.h" + + #include <stdio.h> + +@@ -95,7 +96,7 @@ struct JSSubString { + #define JS7_UNOCT(c) (JS7_UNDEC(c)) + #define JS7_ISHEX(c) ((c) < 128 && isxdigit(c)) + #define JS7_UNHEX(c) (unsigned)(JS7_ISDEC(c) ? (c) - '0' : 10 + tolower(c) - 'a') +-#define JS7_ISLET(c) ((c) < 128 && isalpha(c)) ++#define JS7_ISLET(c) (mozilla::IsAsciiAlpha(c)) + + extern size_t + js_strlen(const char16_t* s); +diff --git mfbt/TextUtils.h mfbt/TextUtils.h +new file mode 100644 +index 000000000000..9494296ce1fc +--- /dev/null ++++ mfbt/TextUtils.h +@@ -0,0 +1,58 @@ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=8 sts=2 et sw=2 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/. */ ++ ++/* Character/text operations. */ ++ ++#ifndef mozilla_TextUtils_h ++#define mozilla_TextUtils_h ++ ++#include "mozilla/TypeTraits.h" ++ ++namespace mozilla { ++ ++namespace detail { ++ ++template<typename Char> ++class MakeUnsignedChar ++ : public MakeUnsigned<Char> ++{}; ++ ++template<> ++class MakeUnsignedChar<char16_t> ++{ ++public: ++ using Type = char16_t; ++}; ++ ++template<> ++class MakeUnsignedChar<char32_t> ++{ ++public: ++ using Type = char32_t; ++}; ++ ++} // namespace detail ++ ++/** ++ * Returns true iff |aChar| matches [a-zA-Z]. ++ * ++ * This function is basically what you thought isalpha was, except its behavior ++ * doesn't depend on the user's current locale. ++ */ ++template<typename Char> ++constexpr bool ++IsAsciiAlpha(Char aChar) ++{ ++ using UnsignedChar = typename detail::MakeUnsignedChar<Char>::Type; ++ return ('a' <= static_cast<UnsignedChar>(aChar) && ++ static_cast<UnsignedChar>(aChar) <= 'z') || ++ ('A' <= static_cast<UnsignedChar>(aChar) && ++ static_cast<UnsignedChar>(aChar) <= 'Z'); ++} ++ ++} // namespace mozilla ++ ++#endif /* mozilla_TextUtils_h */ +diff --git mfbt/moz.build mfbt/moz.build +index f23a3b6f5d86..897a686f48dd 100644 +--- mfbt/moz.build ++++ mfbt/moz.build +@@ -87,6 +87,7 @@ EXPORTS.mozilla = [ + 'StaticAnalysisFunctions.h', + 'TaggedAnonymousMemory.h', + 'TemplateLib.h', ++ 'TextUtils.h', + 'ThreadLocal.h', + 'ToString.h', + 'Tuple.h', +diff --git mfbt/tests/TestTextUtils.cpp mfbt/tests/TestTextUtils.cpp +new file mode 100644 +index 000000000000..db481c1389a1 +--- /dev/null ++++ mfbt/tests/TestTextUtils.cpp +@@ -0,0 +1,106 @@ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* vim: set ts=8 sts=2 et sw=2 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 "mozilla/Assertions.h" ++#include "mozilla/TextUtils.h" ++ ++using mozilla::IsAsciiAlpha; ++ ++// char ++ ++static_assert(!IsAsciiAlpha('@'), "'@' isn't ASCII alpha"); ++static_assert('@' == 0x40, "'@' has value 0x40"); ++ ++static_assert('A' == 0x41, "'A' has value 0x41"); ++static_assert(IsAsciiAlpha('A'), "'A' is ASCII alpha"); ++static_assert(IsAsciiAlpha('B'), "'B' is ASCII alpha"); ++static_assert(IsAsciiAlpha('M'), "'M' is ASCII alpha"); ++static_assert(IsAsciiAlpha('Y'), "'Y' is ASCII alpha"); ++static_assert(IsAsciiAlpha('Z'), "'Z' is ASCII alpha"); ++ ++static_assert('Z' == 0x5A, "'Z' has value 0x5A"); ++static_assert('[' == 0x5B, "'[' has value 0x5B"); ++static_assert(!IsAsciiAlpha('['), "'[' isn't ASCII alpha"); ++ ++static_assert(!IsAsciiAlpha('`'), "'`' isn't ASCII alpha"); ++static_assert('`' == 0x60, "'`' has value 0x60"); ++ ++static_assert('a' == 0x61, "'a' has value 0x61"); ++static_assert(IsAsciiAlpha('a'), "'a' is ASCII alpha"); ++static_assert(IsAsciiAlpha('b'), "'b' is ASCII alpha"); ++static_assert(IsAsciiAlpha('m'), "'m' is ASCII alpha"); ++static_assert(IsAsciiAlpha('y'), "'y' is ASCII alpha"); ++static_assert(IsAsciiAlpha('z'), "'z' is ASCII alpha"); ++ ++static_assert('z' == 0x7A, "'z' has value 0x7A"); ++static_assert('{' == 0x7B, "'{' has value 0x7B"); ++static_assert(!IsAsciiAlpha('{'), "'{' isn't ASCII alpha"); ++ ++// char16_t ++ ++static_assert(!IsAsciiAlpha(u'@'), "u'@' isn't ASCII alpha"); ++static_assert(u'@' == 0x40, "u'@' has value 0x40"); ++ ++static_assert(u'A' == 0x41, "u'A' has value 0x41"); ++static_assert(IsAsciiAlpha(u'A'), "u'A' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'B'), "u'B' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'M'), "u'M' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'Y'), "u'Y' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'Z'), "u'Z' is ASCII alpha"); ++ ++static_assert(u'Z' == 0x5A, "u'Z' has value 0x5A"); ++static_assert(u'[' == 0x5B, "u'[' has value 0x5B"); ++static_assert(!IsAsciiAlpha(u'['), "u'[' isn't ASCII alpha"); ++ ++static_assert(!IsAsciiAlpha(u'`'), "u'`' isn't ASCII alpha"); ++static_assert(u'`' == 0x60, "u'`' has value 0x60"); ++ ++static_assert(u'a' == 0x61, "u'a' has value 0x61"); ++static_assert(IsAsciiAlpha(u'a'), "u'a' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'b'), "u'b' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'm'), "u'm' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'y'), "u'y' is ASCII alpha"); ++static_assert(IsAsciiAlpha(u'z'), "u'z' is ASCII alpha"); ++ ++static_assert(u'z' == 0x7A, "u'z' has value 0x7A"); ++static_assert(u'{' == 0x7B, "u'{' has value 0x7B"); ++static_assert(!IsAsciiAlpha(u'{'), "u'{' isn't ASCII alpha"); ++ ++// char32_t ++ ++static_assert(!IsAsciiAlpha(U'@'), "U'@' isn't ASCII alpha"); ++static_assert(U'@' == 0x40, "U'@' has value 0x40"); ++ ++static_assert(U'A' == 0x41, "U'A' has value 0x41"); ++static_assert(IsAsciiAlpha(U'A'), "U'A' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'B'), "U'B' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'M'), "U'M' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'Y'), "U'Y' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'Z'), "U'Z' is ASCII alpha"); ++ ++static_assert(U'Z' == 0x5A, "U'Z' has value 0x5A"); ++static_assert(U'[' == 0x5B, "U'[' has value 0x5B"); ++static_assert(!IsAsciiAlpha(U'['), "U'[' isn't ASCII alpha"); ++ ++static_assert(!IsAsciiAlpha(U'`'), "U'`' isn't ASCII alpha"); ++static_assert(U'`' == 0x60, "U'`' has value 0x60"); ++ ++static_assert(U'a' == 0x61, "U'a' has value 0x61"); ++static_assert(IsAsciiAlpha(U'a'), "U'a' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'b'), "U'b' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'm'), "U'm' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'y'), "U'y' is ASCII alpha"); ++static_assert(IsAsciiAlpha(U'z'), "U'z' is ASCII alpha"); ++ ++static_assert(U'z' == 0x7A, "U'z' has value 0x7A"); ++static_assert(U'{' == 0x7B, "U'{' has value 0x7B"); ++static_assert(!IsAsciiAlpha(U'{'), "U'{' isn't ASCII alpha"); ++ ++int ++main() ++{ ++ return 0; ++} +diff --git mfbt/tests/moz.build mfbt/tests/moz.build +index f96117e038d9..bd25ab1d0b0d 100644 +--- mfbt/tests/moz.build ++++ mfbt/tests/moz.build +@@ -42,6 +42,7 @@ CppUnitTests([ + 'TestSHA1', + 'TestSplayTree', + 'TestTemplateLib', ++ 'TestTextUtils', + 'TestTuple', + 'TestTypedEnum', + 'TestTypeTraits', diff --git a/www/waterfox/files/patch-bug1453127 b/www/waterfox/files/patch-bug1453127 new file mode 100644 index 000000000000..b16f94f241be --- /dev/null +++ b/www/waterfox/files/patch-bug1453127 @@ -0,0 +1,605 @@ +commit 890e77744a2a +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Tue May 29 10:13:14 2018 +0200 + + Bug 1453127 - Make sure decoder-captured tracks end when changing src. r=jya, a=RyanVM +--- + dom/html/HTMLMediaElement.cpp | 18 ++++++++++++++++++ + dom/html/HTMLMediaElement.h | 5 +++++ + 2 files changed, 23 insertions(+) + +diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp +index b0e787fbf9278..d1502cecfb237 100644 +--- dom/html/HTMLMediaElement.cpp ++++ dom/html/HTMLMediaElement.cpp +@@ -1429,6 +1429,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(HTMLMediaElement, nsGenericHTM + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mErrorSink->mError) + for (uint32_t i = 0; i < tmp->mOutputStreams.Length(); ++i) { + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mStream); ++ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputStreams[i].mPreCreatedTracks) + } + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlayed); + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTextTrackManager) +@@ -3494,6 +3495,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, + RefPtr<MediaStreamTrack> track = + out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO, + trackSource); ++ out->mPreCreatedTracks.AppendElement(track); + out->mStream->AddTrackInternal(track); + LOG(LogLevel::Debug, + ("Created audio track %d for captured decoder", audioTrackId)); +@@ -3505,6 +3507,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, + RefPtr<MediaStreamTrack> track = + out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO, + trackSource); ++ out->mPreCreatedTracks.AppendElement(track); + out->mStream->AddTrackInternal(track); + LOG(LogLevel::Debug, + ("Created video track %d for captured decoder", videoTrackId)); +@@ -7526,6 +7529,21 @@ HTMLMediaElement::RemoveMediaTracks() + } + + mMediaTracksConstructed = false; ++ ++ for (OutputMediaStream& ms : mOutputStreams) { ++ if (!ms.mCapturingDecoder) { ++ continue; ++ } ++ for (RefPtr<MediaStreamTrack>& t : ms.mPreCreatedTracks) { ++ if (t->Ended()) { ++ continue; ++ } ++ mAbstractMainThread->Dispatch(NewRunnableMethod( ++ "dom::HTMLMediaElement::RemoveMediaTracks", ++ t, &MediaStreamTrack::OverrideEnded)); ++ } ++ ms.mPreCreatedTracks.Clear(); ++ } + } + + class MediaElementGMPCrashHelper : public GMPCrashHelper +diff --git dom/html/HTMLMediaElement.h dom/html/HTMLMediaElement.h +index a81a2dfb22f39..126aaee2ae655 100644 +--- dom/html/HTMLMediaElement.h ++++ dom/html/HTMLMediaElement.h +@@ -843,6 +843,11 @@ protected: + bool mCapturingDecoder; + bool mCapturingMediaStream; + ++ // The following members are keeping state for a captured MediaDecoder. ++ // Tracks that were created on main thread before MediaDecoder fed them ++ // to the MediaStreamGraph. ++ nsTArray<RefPtr<MediaStreamTrack>> mPreCreatedTracks; ++ + // The following members are keeping state for a captured MediaStream. + TrackID mNextAvailableTrackID; + nsTArray<Pair<nsString, RefPtr<MediaInputPort>>> mTrackPorts; + +commit dee1e1ec98be +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Tue May 29 10:21:51 2018 +0200 + + Bug 1453127 - Ensure TrackID uniqueness for captured MediaDecoder. r=jya, a=RyanVM +--- + dom/html/HTMLMediaElement.cpp | 22 +++++++--- + dom/html/HTMLMediaElement.h | 2 +- + dom/media/MediaDecoder.cpp | 13 +++++- + dom/media/MediaDecoder.h | 3 ++ + dom/media/MediaDecoderStateMachine.cpp | 10 ++++- + dom/media/MediaDecoderStateMachine.h | 5 ++- + dom/media/mediasink/DecodedStream.cpp | 11 +++-- + dom/media/mediasink/OutputStreamManager.cpp | 68 ++++++++++++++++++++++------- + dom/media/mediasink/OutputStreamManager.h | 33 ++++++++++---- + 9 files changed, 131 insertions(+), 36 deletions(-) + +diff --git dom/html/HTMLMediaElement.cpp dom/html/HTMLMediaElement.cpp +index d1502cecfb237..d11c9d03a7e52 100644 +--- dom/html/HTMLMediaElement.cpp ++++ dom/html/HTMLMediaElement.cpp +@@ -1710,6 +1710,14 @@ void HTMLMediaElement::ShutdownDecoder() + if (mMediaSource) { + mMediaSource->CompletePendingTransactions(); + } ++ for (OutputMediaStream& out : mOutputStreams) { ++ if (!out.mCapturingDecoder) { ++ continue; ++ } ++ out.mNextAvailableTrackID = std::max<TrackID>( ++ mDecoder->NextAvailableTrackIDFor(out.mStream->GetInputStream()), ++ out.mNextAvailableTrackID); ++ } + mDecoder->Shutdown(); + mDecoder = nullptr; + } +@@ -3476,6 +3484,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, + if (mDecoder) { + out->mCapturingDecoder = true; + mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(), ++ out->mNextAvailableTrackID, + aFinishWhenEnded); + } else if (mSrcStream) { + out->mCapturingMediaStream = true; +@@ -3489,11 +3498,12 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, + + if (mDecoder) { + if (HasAudio()) { +- TrackID audioTrackId = mMediaInfo.mAudio.mTrackId; ++ TrackID audioTrackId = out->mNextAvailableTrackID++; + RefPtr<MediaStreamTrackSource> trackSource = + getter->GetMediaStreamTrackSource(audioTrackId); + RefPtr<MediaStreamTrack> track = +- out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO, ++ out->mStream->CreateDOMTrack(audioTrackId, ++ MediaSegment::AUDIO, + trackSource); + out->mPreCreatedTracks.AppendElement(track); + out->mStream->AddTrackInternal(track); +@@ -3501,7 +3511,7 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded, + ("Created audio track %d for captured decoder", audioTrackId)); + } + if (IsVideo() && HasVideo() && !out->mCapturingAudioOnly) { +- TrackID videoTrackId = mMediaInfo.mVideo.mTrackId; ++ TrackID videoTrackId = out->mNextAvailableTrackID++; + RefPtr<MediaStreamTrackSource> trackSource = + getter->GetMediaStreamTrackSource(videoTrackId); + RefPtr<MediaStreamTrack> track = +@@ -4241,11 +4251,12 @@ HTMLMediaElement::WakeLockRelease() + } + + HTMLMediaElement::OutputMediaStream::OutputMediaStream() +- : mFinishWhenEnded(false) ++ : mNextAvailableTrackID(1) ++ , mFinishWhenEnded(false) + , mCapturingAudioOnly(false) + , mCapturingDecoder(false) + , mCapturingMediaStream(false) +- , mNextAvailableTrackID(1) {} ++{} + + HTMLMediaElement::OutputMediaStream::~OutputMediaStream() + { +@@ -4844,6 +4855,7 @@ HTMLMediaElement::FinishDecoderSetup(MediaDecoder* aDecoder) + + ms.mCapturingDecoder = true; + aDecoder->AddOutputStream(ms.mStream->GetInputStream()->AsProcessedStream(), ++ ms.mNextAvailableTrackID, + ms.mFinishWhenEnded); + } + +diff --git dom/html/HTMLMediaElement.h dom/html/HTMLMediaElement.h +index 126aaee2ae655..aeccfa5ba221d 100644 +--- dom/html/HTMLMediaElement.h ++++ dom/html/HTMLMediaElement.h +@@ -838,6 +838,7 @@ protected: + ~OutputMediaStream(); + + RefPtr<DOMMediaStream> mStream; ++ TrackID mNextAvailableTrackID; + bool mFinishWhenEnded; + bool mCapturingAudioOnly; + bool mCapturingDecoder; +@@ -849,7 +850,6 @@ protected: + nsTArray<RefPtr<MediaStreamTrack>> mPreCreatedTracks; + + // The following members are keeping state for a captured MediaStream. +- TrackID mNextAvailableTrackID; + nsTArray<Pair<nsString, RefPtr<MediaInputPort>>> mTrackPorts; + }; + +diff --git dom/media/MediaDecoder.cpp dom/media/MediaDecoder.cpp +index c4bf14d1206fd..11d48fb9921c1 100644 +--- dom/media/MediaDecoder.cpp ++++ dom/media/MediaDecoder.cpp +@@ -322,11 +322,13 @@ MediaDecoder::SetVolume(double aVolume) + + void + MediaDecoder::AddOutputStream(ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID, + bool aFinishWhenEnded) + { + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load()."); +- mDecoderStateMachine->AddOutputStream(aStream, aFinishWhenEnded); ++ mDecoderStateMachine->AddOutputStream( ++ aStream, aNextAvailableTrackID, aFinishWhenEnded); + } + + void +@@ -337,6 +339,14 @@ MediaDecoder::RemoveOutputStream(MediaStream* aStream) + mDecoderStateMachine->RemoveOutputStream(aStream); + } + ++TrackID ++MediaDecoder::NextAvailableTrackIDFor(MediaStream* aOutputStream) const ++{ ++ MOZ_ASSERT(NS_IsMainThread()); ++ MOZ_ASSERT(mDecoderStateMachine, "Must be called after Load()."); ++ return mDecoderStateMachine->NextAvailableTrackIDFor(aOutputStream); ++} ++ + double + MediaDecoder::GetDuration() + { +diff --git dom/media/MediaDecoder.h dom/media/MediaDecoder.h +index a8708b390433a..357f87ef8e0e8 100644 +--- dom/media/MediaDecoder.h ++++ dom/media/MediaDecoder.h +@@ -183,9 +183,12 @@ public: + // The stream is initially blocked. The decoder is responsible for unblocking + // it while it is playing back. + virtual void AddOutputStream(ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID, + bool aFinishWhenEnded); + // Remove an output stream added with AddOutputStream. + virtual void RemoveOutputStream(MediaStream* aStream); ++ // The next TrackID that can be used without risk of a collision. ++ virtual TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; + + // Return the duration of the video in seconds. + virtual double GetDuration(); +diff --git dom/media/MediaDecoderStateMachine.cpp dom/media/MediaDecoderStateMachine.cpp +index cea333f5d9a05..fef3b318b48cb 100644 +--- dom/media/MediaDecoderStateMachine.cpp ++++ dom/media/MediaDecoderStateMachine.cpp +@@ -3973,11 +3973,12 @@ MediaDecoderStateMachine::RequestDebugInfo() + } + + void MediaDecoderStateMachine::AddOutputStream(ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID, + bool aFinishWhenEnded) + { + MOZ_ASSERT(NS_IsMainThread()); + LOG("AddOutputStream aStream=%p!", aStream); +- mOutputStreamManager->Add(aStream, aFinishWhenEnded); ++ mOutputStreamManager->Add(aStream, aNextAvailableTrackID, aFinishWhenEnded); + nsCOMPtr<nsIRunnable> r = + NewRunnableMethod<bool>("MediaDecoderStateMachine::SetAudioCaptured", + this, +@@ -4001,6 +4002,13 @@ void MediaDecoderStateMachine::RemoveOutputStream(MediaStream* aStream) + } + } + ++TrackID ++MediaDecoderStateMachine::NextAvailableTrackIDFor(MediaStream* aOutputStream) const ++{ ++ MOZ_ASSERT(NS_IsMainThread()); ++ return mOutputStreamManager->NextAvailableTrackIDFor(aOutputStream); ++} ++ + class VideoQueueMemoryFunctor : public nsDequeFunctor + { + public: +diff --git dom/media/MediaDecoderStateMachine.h dom/media/MediaDecoderStateMachine.h +index 6f7fcf825ea83..b59bcca7dc70a 100644 +--- dom/media/MediaDecoderStateMachine.h ++++ dom/media/MediaDecoderStateMachine.h +@@ -175,9 +175,12 @@ public: + + RefPtr<MediaDecoder::DebugInfoPromise> RequestDebugInfo(); + +- void AddOutputStream(ProcessedMediaStream* aStream, bool aFinishWhenEnded); ++ void AddOutputStream(ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID, ++ bool aFinishWhenEnded); + // Remove an output stream added with AddOutputStream. + void RemoveOutputStream(MediaStream* aStream); ++ TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; + + // Seeks to the decoder to aTarget asynchronously. + RefPtr<MediaDecoder::SeekPromise> InvokeSeek(const SeekTarget& aTarget); +diff --git dom/media/mediasink/DecodedStream.cpp dom/media/mediasink/DecodedStream.cpp +index 5244a087c77e7..b5c40b9067e57 100644 +--- dom/media/mediasink/DecodedStream.cpp ++++ dom/media/mediasink/DecodedStream.cpp +@@ -193,17 +193,22 @@ DecodedStreamData::DecodedStreamData(OutputStreamManager* aOutputStreamManager, + , mAbstractMainThread(aMainThread) + { + mStream->AddListener(mListener); +- mOutputStreamManager->Connect(mStream); ++ TrackID audioTrack = TRACK_NONE; ++ TrackID videoTrack = TRACK_NONE; + + // Initialize tracks. + if (aInit.mInfo.HasAudio()) { +- mStream->AddAudioTrack(aInit.mInfo.mAudio.mTrackId, ++ audioTrack = aInit.mInfo.mAudio.mTrackId; ++ mStream->AddAudioTrack(audioTrack, + aInit.mInfo.mAudio.mRate, + 0, new AudioSegment()); + } + if (aInit.mInfo.HasVideo()) { +- mStream->AddTrack(aInit.mInfo.mVideo.mTrackId, 0, new VideoSegment()); ++ videoTrack = aInit.mInfo.mVideo.mTrackId; ++ mStream->AddTrack(videoTrack, 0, new VideoSegment()); + } ++ ++ mOutputStreamManager->Connect(mStream, audioTrack, videoTrack); + } + + DecodedStreamData::~DecodedStreamData() +diff --git dom/media/mediasink/OutputStreamManager.cpp dom/media/mediasink/OutputStreamManager.cpp +index d5685837a6783..b3ec8936d435e 100644 +--- dom/media/mediasink/OutputStreamManager.cpp ++++ dom/media/mediasink/OutputStreamManager.cpp +@@ -13,29 +13,41 @@ OutputStreamData::~OutputStreamData() + { + MOZ_ASSERT(NS_IsMainThread()); + // Break the connection to the input stream if necessary. +- if (mPort) { +- mPort->Destroy(); ++ for (RefPtr<MediaInputPort>& port : mPorts) { ++ port->Destroy(); + } + } + + void +-OutputStreamData::Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream) ++OutputStreamData::Init(OutputStreamManager* aOwner, ++ ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID) + { + mOwner = aOwner; + mStream = aStream; ++ mNextAvailableTrackID = aNextAvailableTrackID; + } + + bool +-OutputStreamData::Connect(MediaStream* aStream) ++OutputStreamData::Connect(MediaStream* aStream, ++ TrackID aInputAudioTrackID, ++ TrackID aInputVideoTrackID) + { + MOZ_ASSERT(NS_IsMainThread()); +- MOZ_ASSERT(!mPort, "Already connected?"); ++ MOZ_ASSERT(mPorts.IsEmpty(), "Already connected?"); + + if (mStream->IsDestroyed()) { + return false; + } + +- mPort = mStream->AllocateInputPort(aStream); ++ for (TrackID tid : {aInputAudioTrackID, aInputVideoTrackID}) { ++ if (tid == TRACK_NONE) { ++ continue; ++ } ++ MOZ_ASSERT(IsTrackIDExplicit(tid)); ++ mPorts.AppendElement(mStream->AllocateInputPort( ++ aStream, tid, mNextAvailableTrackID++)); ++ } + return true; + } + +@@ -51,11 +63,11 @@ OutputStreamData::Disconnect() + return false; + } + +- // Disconnect the existing port if necessary. +- if (mPort) { +- mPort->Destroy(); +- mPort = nullptr; ++ // Disconnect any existing port. ++ for (RefPtr<MediaInputPort>& port : mPorts) { ++ port->Destroy(); + } ++ mPorts.Clear(); + return true; + } + +@@ -71,8 +83,16 @@ OutputStreamData::Graph() const + return mStream->Graph(); + } + ++TrackID ++OutputStreamData::NextAvailableTrackID() const ++{ ++ return mNextAvailableTrackID; ++} ++ + void +-OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded) ++OutputStreamManager::Add(ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID, ++ bool aFinishWhenEnded) + { + MOZ_ASSERT(NS_IsMainThread()); + // All streams must belong to the same graph. +@@ -84,12 +104,12 @@ OutputStreamManager::Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded) + } + + OutputStreamData* p = mStreams.AppendElement(); +- p->Init(this, aStream); ++ p->Init(this, aStream, aNextAvailableTrackID); + + // Connect to the input stream if we have one. Otherwise the output stream + // will be connected in Connect(). + if (mInputStream) { +- p->Connect(mInputStream); ++ p->Connect(mInputStream, mInputAudioTrackID, mInputVideoTrackID); + } + } + +@@ -105,13 +125,29 @@ OutputStreamManager::Remove(MediaStream* aStream) + } + } + ++TrackID ++OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const ++{ ++ MOZ_ASSERT(NS_IsMainThread()); ++ for (const OutputStreamData& out : mStreams) { ++ if (out.Equals(aOutputStream)) { ++ return out.NextAvailableTrackID(); ++ } ++ } ++ return TRACK_INVALID; ++} ++ + void +-OutputStreamManager::Connect(MediaStream* aStream) ++OutputStreamManager::Connect(MediaStream* aStream, ++ TrackID aAudioTrackID, ++ TrackID aVideoTrackID) + { + MOZ_ASSERT(NS_IsMainThread()); + mInputStream = aStream; ++ mInputAudioTrackID = aAudioTrackID; ++ mInputVideoTrackID = aVideoTrackID; + for (int32_t i = mStreams.Length() - 1; i >= 0; --i) { +- if (!mStreams[i].Connect(aStream)) { ++ if (!mStreams[i].Connect(aStream, mInputAudioTrackID, mInputVideoTrackID)) { + // Probably the DOMMediaStream was GCed. Clean up. + mStreams.RemoveElementAt(i); + } +@@ -123,6 +159,8 @@ OutputStreamManager::Disconnect() + { + MOZ_ASSERT(NS_IsMainThread()); + mInputStream = nullptr; ++ mInputAudioTrackID = TRACK_INVALID; ++ mInputVideoTrackID = TRACK_INVALID; + for (int32_t i = mStreams.Length() - 1; i >= 0; --i) { + if (!mStreams[i].Disconnect()) { + // Probably the DOMMediaStream was GCed. Clean up. +diff --git dom/media/mediasink/OutputStreamManager.h dom/media/mediasink/OutputStreamManager.h +index 7f91a60c1e9dd..8e89878e45090 100644 +--- dom/media/mediasink/OutputStreamManager.h ++++ dom/media/mediasink/OutputStreamManager.h +@@ -9,6 +9,7 @@ + + #include "mozilla/RefPtr.h" + #include "nsTArray.h" ++#include "MediaSegment.h" + + namespace mozilla { + +@@ -21,11 +22,13 @@ class ProcessedMediaStream; + class OutputStreamData { + public: + ~OutputStreamData(); +- void Init(OutputStreamManager* aOwner, ProcessedMediaStream* aStream); ++ void Init(OutputStreamManager* aOwner, ++ ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID); + +- // Connect mStream to the input stream. ++ // Connect the given input stream's audio and video tracks to mStream. + // Return false is mStream is already destroyed, otherwise true. +- bool Connect(MediaStream* aStream); ++ bool Connect(MediaStream* aStream, TrackID aAudioTrackID, TrackID aVideoTrackID); + // Disconnect mStream from its input stream. + // Return false is mStream is already destroyed, otherwise true. + bool Disconnect(); +@@ -34,12 +37,16 @@ public: + bool Equals(MediaStream* aStream) const; + // Return the graph mStream belongs to. + MediaStreamGraph* Graph() const; ++ // The next TrackID that will not cause a collision in mStream. ++ TrackID NextAvailableTrackID() const; + + private: + OutputStreamManager* mOwner; + RefPtr<ProcessedMediaStream> mStream; +- // mPort connects our mStream to an input stream. +- RefPtr<MediaInputPort> mPort; ++ // mPort connects an input stream to our mStream. ++ nsTArray<RefPtr<MediaInputPort>> mPorts; ++ // For guaranteeing TrackID uniqueness in our mStream. ++ TrackID mNextAvailableTrackID = TRACK_INVALID; + }; + + class OutputStreamManager { +@@ -47,18 +54,24 @@ class OutputStreamManager { + + public: + // Add the output stream to the collection. +- void Add(ProcessedMediaStream* aStream, bool aFinishWhenEnded); ++ void Add(ProcessedMediaStream* aStream, ++ TrackID aNextAvailableTrackID, ++ bool aFinishWhenEnded); + // Remove the output stream from the collection. + void Remove(MediaStream* aStream); ++ // The next TrackID that will not cause a collision in aOutputStream. ++ TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; + // Return true if the collection empty. + bool IsEmpty() const + { + MOZ_ASSERT(NS_IsMainThread()); + return mStreams.IsEmpty(); + } +- // Connect all output streams in the collection to the input stream. +- void Connect(MediaStream* aStream); +- // Disconnect all output streams from the input stream. ++ // Connect the given input stream's tracks to all output streams. ++ void Connect(MediaStream* aStream, ++ TrackID aAudioTrackID, ++ TrackID aVideoTrackID); ++ // Disconnect the input stream to all output streams. + void Disconnect(); + // Return the graph these streams belong to or null if empty. + MediaStreamGraph* Graph() const +@@ -72,6 +85,8 @@ private: + // Keep the input stream so we can connect the output streams that + // are added after Connect(). + RefPtr<MediaStream> mInputStream; ++ TrackID mInputAudioTrackID = TRACK_INVALID; ++ TrackID mInputVideoTrackID = TRACK_INVALID; + nsTArray<OutputStreamData> mStreams; + }; + + +commit 91317ba976c8 +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Wed May 30 10:44:56 2018 +0200 + + Bug 1453127 - Clear output streams on shutdown. r=jya, a=RyanVM +--- + dom/media/MediaDecoderStateMachine.cpp | 4 ++++ + dom/media/mediasink/OutputStreamManager.cpp | 7 +++++++ + dom/media/mediasink/OutputStreamManager.h | 2 ++ + 3 files changed, 13 insertions(+) + +diff --git dom/media/MediaDecoderStateMachine.cpp dom/media/MediaDecoderStateMachine.cpp +index fef3b318b48cb..582fe7ba995fe 100644 +--- dom/media/MediaDecoderStateMachine.cpp ++++ dom/media/MediaDecoderStateMachine.cpp +@@ -3564,6 +3564,10 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame() + RefPtr<ShutdownPromise> + MediaDecoderStateMachine::BeginShutdown() + { ++ MOZ_ASSERT(NS_IsMainThread()); ++ if (mOutputStreamManager) { ++ mOutputStreamManager->Clear(); ++ } + return InvokeAsync(OwnerThread(), this, __func__, + &MediaDecoderStateMachine::Shutdown); + } +diff --git dom/media/mediasink/OutputStreamManager.cpp dom/media/mediasink/OutputStreamManager.cpp +index b3ec8936d435e..7ecc203ed8309 100644 +--- dom/media/mediasink/OutputStreamManager.cpp ++++ dom/media/mediasink/OutputStreamManager.cpp +@@ -125,6 +125,13 @@ OutputStreamManager::Remove(MediaStream* aStream) + } + } + ++void ++OutputStreamManager::Clear() ++{ ++ MOZ_ASSERT(NS_IsMainThread()); ++ mStreams.Clear(); ++} ++ + TrackID + OutputStreamManager::NextAvailableTrackIDFor(MediaStream* aOutputStream) const + { +diff --git dom/media/mediasink/OutputStreamManager.h dom/media/mediasink/OutputStreamManager.h +index 8e89878e45090..ec5040178ee0b 100644 +--- dom/media/mediasink/OutputStreamManager.h ++++ dom/media/mediasink/OutputStreamManager.h +@@ -59,6 +59,8 @@ public: + bool aFinishWhenEnded); + // Remove the output stream from the collection. + void Remove(MediaStream* aStream); ++ // Clear all output streams from the collection. ++ void Clear(); + // The next TrackID that will not cause a collision in aOutputStream. + TrackID NextAvailableTrackIDFor(MediaStream* aOutputStream) const; + // Return true if the collection empty. diff --git a/www/waterfox/files/patch-bug1453339 b/www/waterfox/files/patch-bug1453339 new file mode 100644 index 000000000000..82edbe708de6 --- /dev/null +++ b/www/waterfox/files/patch-bug1453339 @@ -0,0 +1,172 @@ +commit b1ce2aee618c +Author: Boris Zbarsky <bzbarsky@mit.edu> +Date: Fri Apr 13 19:31:42 2018 -0400 + + Bug 1453339 - Make it harder to mess up Promise::All. r=peterv, a=abillings + + MozReview-Commit-ID: UO4wssYHj7 + + --HG-- + extra : source : 438494d2d17bec92e4f4e38661a85b60680ab087 +--- + dom/base/nsFrameLoader.cpp | 4 +--- + dom/cache/Cache.cpp | 2 +- + dom/promise/Promise.cpp | 27 +++++++++++++++------------ + dom/promise/Promise.h | 19 +++++++++++-------- + layout/style/FontFaceSet.cpp | 12 +----------- + 5 files changed, 29 insertions(+), 35 deletions(-) + +diff --git dom/base/nsFrameLoader.cpp dom/base/nsFrameLoader.cpp +index 705779d87b80..f2730dac80b3 100644 +--- dom/base/nsFrameLoader.cpp ++++ dom/base/nsFrameLoader.cpp +@@ -409,8 +409,6 @@ nsFrameLoader::FireWillChangeProcessEvent() + return nullptr; + } + JSContext* cx = jsapi.cx(); +- GlobalObject global(cx, mOwnerContent->GetOwnerGlobal()->GetGlobalJSObject()); +- MOZ_ASSERT(!global.Failed()); + + // Set our mBrowserChangingProcessBlockers property to refer to the blockers + // list. We will synchronously dispatch a DOM event to collect this list of +@@ -433,7 +431,7 @@ nsFrameLoader::FireWillChangeProcessEvent() + mBrowserChangingProcessBlockers = nullptr; + + ErrorResult rv; +- RefPtr<Promise> allPromise = Promise::All(global, blockers, rv); ++ RefPtr<Promise> allPromise = Promise::All(cx, blockers, rv); + return allPromise.forget(); + } + +diff --git dom/cache/Cache.cpp dom/cache/Cache.cpp +index 06df0f2a7cb9..3fb8b6c36040 100644 +--- dom/cache/Cache.cpp ++++ dom/cache/Cache.cpp +@@ -630,7 +630,7 @@ Cache::AddAll(const GlobalObject& aGlobal, + new FetchHandler(mActor->GetWorkerHolder(), this, + Move(aRequestList), promise); + +- RefPtr<Promise> fetchPromise = Promise::All(aGlobal, fetchList, aRv); ++ RefPtr<Promise> fetchPromise = Promise::All(aGlobal.Context(), fetchList, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } +diff --git dom/promise/Promise.cpp dom/promise/Promise.cpp +index d259d6cedfcb..88f026b26976 100644 +--- dom/promise/Promise.cpp ++++ dom/promise/Promise.cpp +@@ -134,37 +134,40 @@ Promise::Reject(nsIGlobalObject* aGlobal, JSContext* aCx, + + // static + already_AddRefed<Promise> +-Promise::All(const GlobalObject& aGlobal, ++Promise::All(JSContext* aCx, + const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv) + { +- nsCOMPtr<nsIGlobalObject> global; +- global = do_QueryInterface(aGlobal.GetAsSupports()); +- if (!global) { ++ JS::Rooted<JSObject*> globalObj(aCx, JS::CurrentGlobalOrNull(aCx)); ++ if (!globalObj) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + +- JSContext* cx = aGlobal.Context(); ++ nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(globalObj); ++ if (!global) { ++ aRv.Throw(NS_ERROR_UNEXPECTED); ++ return nullptr; ++ } + +- JS::AutoObjectVector promises(cx); ++ JS::AutoObjectVector promises(aCx); + if (!promises.reserve(aPromiseList.Length())) { +- aRv.NoteJSContextException(cx); ++ aRv.NoteJSContextException(aCx); + return nullptr; + } + + for (auto& promise : aPromiseList) { +- JS::Rooted<JSObject*> promiseObj(cx, promise->PromiseObj()); ++ JS::Rooted<JSObject*> promiseObj(aCx, promise->PromiseObj()); + // Just in case, make sure these are all in the context compartment. +- if (!JS_WrapObject(cx, &promiseObj)) { +- aRv.NoteJSContextException(cx); ++ if (!JS_WrapObject(aCx, &promiseObj)) { ++ aRv.NoteJSContextException(aCx); + return nullptr; + } + promises.infallibleAppend(promiseObj); + } + +- JS::Rooted<JSObject*> result(cx, JS::GetWaitForAllPromise(cx, promises)); ++ JS::Rooted<JSObject*> result(aCx, JS::GetWaitForAllPromise(aCx, promises)); + if (!result) { +- aRv.NoteJSContextException(cx); ++ aRv.NoteJSContextException(aCx); + return nullptr; + } + +diff --git dom/promise/Promise.h dom/promise/Promise.h +index 447a2a195152..2c13d0146c40 100644 +--- dom/promise/Promise.h ++++ dom/promise/Promise.h +@@ -111,23 +111,26 @@ public: + return mGlobal; + } + +- // Do the equivalent of Promise.resolve in the current compartment of aCx. +- // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this +- // function MUST return a non-null value. ++ // Do the equivalent of Promise.resolve in the compartment of aGlobal. The ++ // compartment of aCx is ignored. Errors are reported on the ErrorResult; if ++ // aRv comes back !Failed(), this function MUST return a non-null value. + static already_AddRefed<Promise> + Resolve(nsIGlobalObject* aGlobal, JSContext* aCx, + JS::Handle<JS::Value> aValue, ErrorResult& aRv); + +- // Do the equivalent of Promise.reject in the current compartment of aCx. +- // Errorrs are reported on the ErrorResult; if aRv comes back !Failed(), this +- // function MUST return a non-null value. ++ // Do the equivalent of Promise.reject in the compartment of aGlobal. The ++ // compartment of aCx is ignored. Errors are reported on the ErrorResult; if ++ // aRv comes back !Failed(), this function MUST return a non-null value. + static already_AddRefed<Promise> + Reject(nsIGlobalObject* aGlobal, JSContext* aCx, + JS::Handle<JS::Value> aValue, ErrorResult& aRv); + ++ // Do the equivalent of Promise.all in the current compartment of aCx. Errors ++ // are reported on the ErrorResult; if aRv comes back !Failed(), this function ++ // MUST return a non-null value. + static already_AddRefed<Promise> +- All(const GlobalObject& aGlobal, +- const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv); ++ All(JSContext* aCx, const nsTArray<RefPtr<Promise>>& aPromiseList, ++ ErrorResult& aRv); + + void + Then(JSContext* aCx, +diff --git layout/style/FontFaceSet.cpp layout/style/FontFaceSet.cpp +index 280bf30d96aa..f9038c8c4b14 100644 +--- layout/style/FontFaceSet.cpp ++++ layout/style/FontFaceSet.cpp +@@ -401,17 +401,7 @@ FontFaceSet::Load(JSContext* aCx, + } + } + +- nsIGlobalObject* globalObject = GetParentObject(); +- if (!globalObject) { +- aRv.Throw(NS_ERROR_FAILURE); +- return nullptr; +- } +- +- JS::Rooted<JSObject*> jsGlobal(aCx, globalObject->GetGlobalJSObject()); +- GlobalObject global(aCx, jsGlobal); +- +- RefPtr<Promise> result = Promise::All(global, promises, aRv); +- return result.forget(); ++ return Promise::All(aCx, promises, aRv); + } + + bool diff --git a/www/waterfox/files/patch-bug1453555 b/www/waterfox/files/patch-bug1453555 new file mode 100644 index 000000000000..b7b617a68fe6 --- /dev/null +++ b/www/waterfox/files/patch-bug1453555 @@ -0,0 +1,34 @@ +commit 5b6c49ed5c8d +Author: James Teh <jteh@mozilla.com> +Date: Thu Apr 12 16:32:19 2018 +1000 + + Bug 1453555: Fix accessibility group info for <select size="1"> options. r=surkov a=jcristau + + In the e10s implementation, Accessible::NativeState for the options doesn't include the invisible state. (It does with e10s disabled.) + In HTMLSelectOptionAccessible::NativeState, rather than just flipping (xor) the invisible state, absolutely ensure it gets removed. We don't want to *add* the invisible state if it isn't there. + This allows group position info to be calculated correctly. + + MozReview-Commit-ID: LPEVhOOm2NT + + --HG-- + extra : source : f52a56dc215cfd8ea7310c168632d33531fc8c90 +--- + accessible/html/HTMLSelectAccessible.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git accessible/html/HTMLSelectAccessible.cpp accessible/html/HTMLSelectAccessible.cpp +index 0cbe7ac89dce..efa05c1adfc1 100644 +--- accessible/html/HTMLSelectAccessible.cpp ++++ accessible/html/HTMLSelectAccessible.cpp +@@ -198,7 +198,10 @@ HTMLSelectOptionAccessible::NativeState() + // visible option + if (!selected) { + state |= states::OFFSCREEN; +- state ^= states::INVISIBLE; ++ // Ensure the invisible state is removed. Otherwise, group info will skip ++ // this option. Furthermore, this gets cached and this doesn't get ++ // invalidated even once the select is expanded. ++ state &= ~states::INVISIBLE; + } else { + // Clear offscreen and invisible for currently showing option + state &= ~(states::OFFSCREEN | states::INVISIBLE); diff --git a/www/waterfox/files/patch-bug1453740 b/www/waterfox/files/patch-bug1453740 new file mode 100644 index 000000000000..d8cacc24ef1e --- /dev/null +++ b/www/waterfox/files/patch-bug1453740 @@ -0,0 +1,35 @@ +commit 926d7ea39507 +Author: Dan Minor <dminor@mozilla.com> +Date: Thu Apr 12 11:31:59 2018 -0700 + + Bug 1453740 - Allow 1x1 windows in VP8EncoderImpl::InitEncode; r=pehrsons a=jcristau + + A minimized window has a resolution of 1x1. Although we removed minimized windows from the list + of available windows to share, nothing prevents the user from minimizing it during a call. With + the current code, this will cause InitEncode to fail, resulting in a fatal release assert. + + I tested this patch with window sharing on meet.google.com and I was able to minimize and restore + the window several times without problem. While minimized, the window appears as a black screen + to the other meeting participants. It renders normally when restored. + + MozReview-Commit-ID: LE2NBiEy8nw + + --HG-- + extra : source : 1cece7d5df170946f822705ac7b28e2e57c0fd00 +--- + media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc +index 36f8552ad8d1..0fe2c6953868 100644 +--- media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc ++++ media/webrtc/trunk/webrtc/modules/video_coding/codecs/vp8/vp8_impl.cc +@@ -300,7 +300,7 @@ int VP8EncoderImpl::InitEncode(const VideoCodec* inst, + if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; + } +- if (inst->width <= 1 || inst->height <= 1) { ++ if (inst->width < 1 || inst->height < 1) { + return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; + } + if (number_of_cores < 1) { diff --git a/www/waterfox/files/patch-bug1454285 b/www/waterfox/files/patch-bug1454285 new file mode 100644 index 000000000000..f5f38eca6411 --- /dev/null +++ b/www/waterfox/files/patch-bug1454285 @@ -0,0 +1,713 @@ +commit 58db23895d95 +Author: Tooru Fujisawa <arai_a@mac.com> +Date: Tue May 22 18:10:28 2018 +0900 + + Bug 1454285 - Part 1: Specify the current scope when emitting await and .generator. r=jwalden, a=RyanVM + + --HG-- + extra : source : 6ca6ced5189a5760c96afa31a6575cd3d3f56639 +--- + js/src/frontend/BytecodeEmitter.cpp | 104 +++++++++++++++++++++--------------- + js/src/frontend/BytecodeEmitter.h | 25 ++++++--- + 2 files changed, 81 insertions(+), 48 deletions(-) + +diff --git js/src/frontend/BytecodeEmitter.cpp js/src/frontend/BytecodeEmitter.cpp +index df999dfb2b0dc..e8edc66658804 100644 +--- js/src/frontend/BytecodeEmitter.cpp ++++ js/src/frontend/BytecodeEmitter.cpp +@@ -2004,6 +2004,8 @@ class MOZ_STACK_CLASS IfThenElseEmitter + + class ForOfLoopControl : public LoopControl + { ++ using EmitterScope = BytecodeEmitter::EmitterScope; ++ + // The stack depth of the iterator. + int32_t iterDepth_; + +@@ -2096,8 +2098,8 @@ class ForOfLoopControl : public LoopControl + MOZ_ASSERT(slotFromTop == unsigned(bce->stackDepth - iterDepth_)); + if (!bce->emitDupAt(slotFromTop)) // ITER ... EXCEPTION ITER + return false; +- if (!emitIteratorClose(bce, CompletionKind::Throw)) // ITER ... EXCEPTION +- return false; ++ if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Throw)) ++ return false; // ITER ... EXCEPTION + + if (!ifIteratorIsNotClosed.emitEnd()) // ITER ... EXCEPTION + return false; +@@ -2120,8 +2122,8 @@ class ForOfLoopControl : public LoopControl + return false; + if (!bce->emitDupAt(slotFromTop + 1)) // ITER ... FTYPE FVALUE ITER + return false; +- if (!emitIteratorClose(bce, CompletionKind::Normal)) // ITER ... FTYPE FVALUE +- return false; ++ if (!emitIteratorCloseInInnermostScope(bce, CompletionKind::Normal)) ++ return false; // ITER ... FTYPE FVALUE + if (!ifGeneratorClosing.emitEnd()) // ITER ... FTYPE FVALUE + return false; + } +@@ -2135,16 +2137,27 @@ class ForOfLoopControl : public LoopControl + return true; + } + +- bool emitIteratorClose(BytecodeEmitter* bce, +- CompletionKind completionKind = CompletionKind::Normal) { ++ bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce, ++ CompletionKind completionKind = CompletionKind::Normal) { ++ return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind); ++ } ++ ++ bool emitIteratorCloseInScope(BytecodeEmitter* bce, ++ EmitterScope& currentScope, ++ CompletionKind completionKind = CompletionKind::Normal) { + ptrdiff_t start = bce->offset(); +- if (!bce->emitIteratorClose(iterKind_, completionKind, allowSelfHosted_)) ++ if (!bce->emitIteratorCloseInScope(currentScope, iterKind_, completionKind, ++ allowSelfHosted_)) ++ { + return false; ++ } + ptrdiff_t end = bce->offset(); + return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end); + } + +- bool emitPrepareForNonLocalJump(BytecodeEmitter* bce, bool isTarget) { ++ bool emitPrepareForNonLocalJumpFromScope(BytecodeEmitter* bce, ++ EmitterScope& currentScope, ++ bool isTarget) { + // Pop unnecessary value from the stack. Effectively this means + // leaving try-catch block. However, the performing IteratorClose can + // reach the depth for try-catch, and effectively re-enter the +@@ -2159,7 +2172,7 @@ class ForOfLoopControl : public LoopControl + if (!bce->emit1(JSOP_SWAP)) // UNDEF ITER + return false; + +- if (!emitIteratorClose(bce)) // UNDEF ++ if (!emitIteratorCloseInScope(bce, currentScope, CompletionKind::Normal)) // UNDEF + return false; + + if (isTarget) { +@@ -2843,8 +2856,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta + return false; + + ForOfLoopControl& loopinfo = control->as<ForOfLoopControl>(); +- if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ false)) // ... ++ if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es, ++ /* isTarget = */ false)) ++ { // ... + return false; ++ } + } else { + npops += 2; + } +@@ -2871,8 +2887,9 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta + + if (target && emitIteratorCloseAtTarget && target->is<ForOfLoopControl>()) { + ForOfLoopControl& loopinfo = target->as<ForOfLoopControl>(); +- if (!loopinfo.emitPrepareForNonLocalJump(bce_, /* isTarget = */ true)) // ... UNDEF UNDEF ++ if (!loopinfo.emitPrepareForNonLocalJumpFromScope(bce_, *es, /* isTarget = */ true)) { // ... UNDEF UNDEF + return false; ++ } + } + + EmitterScope* targetEmitterScope = target ? target->emitterScope() : bce_->varEmitterScope; +@@ -5325,7 +5342,7 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter + return false; + + if (iterKind == IteratorKind::Async) { +- if (!emitAwait()) // ... RESULT ++ if (!emitAwaitInInnermostScope()) // ... RESULT + return false; + } + +@@ -5336,9 +5353,10 @@ BytecodeEmitter::emitIteratorNext(ParseNode* pn, IteratorKind iterKind /* = Iter + } + + bool +-BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync */, +- CompletionKind completionKind /* = CompletionKind::Normal */, +- bool allowSelfHosted /* = false */) ++BytecodeEmitter::emitIteratorCloseInScope(EmitterScope& currentScope, ++ IteratorKind iterKind /* = IteratorKind::Sync */, ++ CompletionKind completionKind /* = CompletionKind::Normal */, ++ bool allowSelfHosted /* = false */) + { + MOZ_ASSERT(allowSelfHosted || emitterMode != BytecodeEmitter::SelfHosting, + ".close() on iterators is prohibited in self-hosted code because it " +@@ -5430,7 +5448,7 @@ BytecodeEmitter::emitIteratorClose(IteratorKind iterKind /* = IteratorKind::Sync + if (!emit1(JSOP_SWAP)) // ... ... RVAL RESULT + return false; + } +- if (!emitAwait()) // ... ... RVAL? RESULT ++ if (!emitAwaitInScope(currentScope)) // ... ... RVAL? RESULT + return false; + } + +@@ -5690,7 +5708,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav + // For an empty pattern [], call IteratorClose unconditionally. Nothing + // else needs to be done. + if (!pattern->pn_head) +- return emitIteratorClose(); // ... OBJ ++ return emitIteratorCloseInInnermostScope(); // ... OBJ + + // Push an initial FALSE value for DONE. + if (!emit1(JSOP_FALSE)) // ... OBJ ITER FALSE +@@ -5886,7 +5904,7 @@ BytecodeEmitter::emitDestructuringOpsArray(ParseNode* pattern, DestructuringFlav + return false; + if (!ifDone.emitElse()) // ... OBJ ITER + return false; +- if (!emitIteratorClose()) // ... OBJ ++ if (!emitIteratorCloseInInnermostScope()) // ... OBJ + return false; + if (!ifDone.emitEnd()) + return false; +@@ -8682,9 +8700,9 @@ BytecodeEmitter::emitReturn(ParseNode* pn) + } + + bool +-BytecodeEmitter::emitGetDotGenerator() ++BytecodeEmitter::emitGetDotGeneratorInScope(EmitterScope& currentScope) + { +- NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator); ++ NameLocation loc = *locationOfNameBoundInFunctionScope(cx->names().dotGenerator, ¤tScope); + return emitGetNameAtLocation(cx->names().dotGenerator, loc); + } + +@@ -8726,7 +8744,7 @@ BytecodeEmitter::emitYield(ParseNode* pn) + return false; + } + +- if (!emitGetDotGenerator()) ++ if (!emitGetDotGeneratorInInnermostScope()) + return false; + + if (!emitYieldOp(JSOP_YIELD)) +@@ -8736,24 +8754,24 @@ BytecodeEmitter::emitYield(ParseNode* pn) + } + + bool +-BytecodeEmitter::emitAwait() ++BytecodeEmitter::emitAwaitInInnermostScope(ParseNode* pn) + { +- if (!emitGetDotGenerator()) +- return false; +- if (!emitYieldOp(JSOP_AWAIT)) ++ MOZ_ASSERT(sc->isFunctionBox()); ++ MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); ++ ++ if (!emitTree(pn->pn_kid)) + return false; +- return true; ++ return emitAwaitInInnermostScope(); + } + + bool +-BytecodeEmitter::emitAwait(ParseNode* pn) ++BytecodeEmitter::emitAwaitInScope(EmitterScope& currentScope) + { +- MOZ_ASSERT(sc->isFunctionBox()); +- MOZ_ASSERT(pn->getOp() == JSOP_AWAIT); +- +- if (!emitTree(pn->pn_kid)) ++ if (!emitGetDotGeneratorInScope(currentScope)) + return false; +- return emitAwait(); ++ if (!emitYieldOp(JSOP_AWAIT)) ++ return false; ++ return true; + } + + bool +@@ -8794,7 +8812,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + MOZ_ASSERT(this->stackDepth == startDepth); + + // Load the generator object. +- if (!emitGetDotGenerator()) // ITER RESULT GENOBJ ++ if (!emitGetDotGeneratorInInnermostScope()) // ITER RESULT GENOBJ + return false; + + // Yield RESULT as-is, without re-boxing. +@@ -8831,7 +8849,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + // If the iterator does not have a "throw" method, it calls IteratorClose + // and then throws a TypeError. + IteratorKind iterKind = isAsyncGenerator ? IteratorKind::Async : IteratorKind::Sync; +- if (!emitIteratorClose(iterKind)) // ITER RESULT EXCEPTION ++ if (!emitIteratorCloseInInnermostScope(iterKind)) // ITER RESULT EXCEPTION + return false; + if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ITERATOR_NO_THROW)) // throw + return false; +@@ -8849,7 +8867,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + checkTypeSet(JSOP_CALL); + + if (isAsyncGenerator) { +- if (!emitAwait()) // ITER OLDRESULT RESULT ++ if (!emitAwaitInInnermostScope()) // ITER OLDRESULT RESULT + return false; + } + +@@ -8920,7 +8938,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + checkTypeSet(JSOP_CALL); + + if (iterKind == IteratorKind::Async) { +- if (!emitAwait()) // ... FTYPE FVALUE RESULT ++ if (!emitAwaitInInnermostScope()) // ... FTYPE FVALUE RESULT + return false; + } + +@@ -8943,7 +8961,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + return false; + + if (isAsyncGenerator) { +- if (!emitAwait()) // ITER OLDRESULT FTYPE FVALUE VALUE ++ if (!emitAwaitInInnermostScope()) // ITER OLDRESULT FTYPE FVALUE VALUE + return false; + } + +@@ -9005,7 +9023,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + checkTypeSet(JSOP_CALL); + + if (isAsyncGenerator) { +- if (!emitAwait()) // ITER RESULT RESULT ++ if (!emitAwaitInInnermostScope()) // ITER RESULT RESULT + return false; + } + +@@ -9038,7 +9056,7 @@ BytecodeEmitter::emitYieldStar(ParseNode* iter) + return false; + + if (isAsyncGenerator) { +- if (!emitAwait()) // VALUE ++ if (!emitAwaitInInnermostScope()) // VALUE + return false; + } + +@@ -10592,7 +10610,7 @@ BytecodeEmitter::emitFunctionBody(ParseNode* funBody) + if (!emit1(JSOP_SETRVAL)) + return false; + +- if (!emitGetDotGenerator()) ++ if (!emitGetDotGeneratorInInnermostScope()) + return false; + + // No need to check for finally blocks, etc as in EmitReturn. +@@ -10954,7 +10972,7 @@ BytecodeEmitter::emitTree(ParseNode* pn, ValueUsage valueUsage /* = ValueUsage:: + break; + + case PNK_AWAIT: +- if (!emitAwait(pn)) ++ if (!emitAwaitInInnermostScope(pn)) + return false; + break; + +diff --git js/src/frontend/BytecodeEmitter.h js/src/frontend/BytecodeEmitter.h +index f238cc12c0247..039d271e4d965 100644 +--- js/src/frontend/BytecodeEmitter.h ++++ js/src/frontend/BytecodeEmitter.h +@@ -634,14 +634,20 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool iteratorResultShape(unsigned* shape); + MOZ_MUST_USE bool emitToIteratorResult(bool done); + +- MOZ_MUST_USE bool emitGetDotGenerator(); ++ MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() { ++ return emitGetDotGeneratorInScope(*innermostEmitterScope); ++ } ++ MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope); + + MOZ_MUST_USE bool emitInitialYield(ParseNode* pn); + MOZ_MUST_USE bool emitYield(ParseNode* pn); + MOZ_MUST_USE bool emitYieldOp(JSOp op); + MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); +- MOZ_MUST_USE bool emitAwait(); +- MOZ_MUST_USE bool emitAwait(ParseNode* pn); ++ MOZ_MUST_USE bool emitAwaitInInnermostScope() { ++ return emitAwaitInScope(*innermostEmitterScope); ++ } ++ MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); ++ MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); + + MOZ_MUST_USE bool emitPropLHS(ParseNode* pn); + MOZ_MUST_USE bool emitPropOp(ParseNode* pn, JSOp op); +@@ -738,9 +744,16 @@ struct MOZ_STACK_CLASS BytecodeEmitter + // onto the stack. + MOZ_MUST_USE bool emitIteratorNext(ParseNode* pn, IteratorKind kind = IteratorKind::Sync, + bool allowSelfHosted = false); +- MOZ_MUST_USE bool emitIteratorClose(IteratorKind iterKind = IteratorKind::Sync, +- CompletionKind completionKind = CompletionKind::Normal, +- bool allowSelfHosted = false); ++ MOZ_MUST_USE bool emitIteratorCloseInScope(EmitterScope& currentScope, ++ IteratorKind iterKind = IteratorKind::Sync, ++ CompletionKind completionKind = CompletionKind::Normal, ++ bool allowSelfHosted = false); ++ MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync, ++ CompletionKind completionKind = CompletionKind::Normal, ++ bool allowSelfHosted = false) { ++ return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind, ++ allowSelfHosted); ++ } + + template <typename InnerEmitter> + MOZ_MUST_USE bool wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth, + +commit 0cd861187fc0 +Author: Tooru Fujisawa <arai_a@mac.com> +Date: Tue May 22 18:10:28 2018 +0900 + + Bug 1454285 - Part 2: Disallow using innermostEmitterScope while the value does not match the bytecode environment. r=jwalden, a=RyanVM + + --HG-- + extra : source : 567757b97ff0f511bb142b966f5b5777bad7fdc2 +--- + js/src/frontend/BytecodeEmitter.cpp | 59 ++++++++++++++++++++----------------- + js/src/frontend/BytecodeEmitter.h | 49 ++++++++++++++++++++++++++---- + 2 files changed, 76 insertions(+), 32 deletions(-) + +diff --git js/src/frontend/BytecodeEmitter.cpp js/src/frontend/BytecodeEmitter.cpp +index e8edc66658804..e13f5bfdd243b 100644 +--- js/src/frontend/BytecodeEmitter.cpp ++++ js/src/frontend/BytecodeEmitter.cpp +@@ -102,7 +102,7 @@ class BytecodeEmitter::NestableControl : public Nestable<BytecodeEmitter::Nestab + NestableControl(BytecodeEmitter* bce, StatementKind kind) + : Nestable<NestableControl>(&bce->innermostNestableControl), + kind_(kind), +- emitterScope_(bce->innermostEmitterScope) ++ emitterScope_(bce->innermostEmitterScopeNoCheck()) + { } + + public: +@@ -436,7 +436,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc + // enclosing BCE. + if ((*bce)->parent) { + *bce = (*bce)->parent; +- return (*bce)->innermostEmitterScope; ++ return (*bce)->innermostEmitterScopeNoCheck(); + } + + return nullptr; +@@ -470,7 +470,7 @@ class BytecodeEmitter::EmitterScope : public Nestable<BytecodeEmitter::EmitterSc + + public: + explicit EmitterScope(BytecodeEmitter* bce) +- : Nestable<EmitterScope>(&bce->innermostEmitterScope), ++ : Nestable<EmitterScope>(&bce->innermostEmitterScope_), + nameCache_(bce->cx->frontendCollectionPool()), + hasEnvironment_(false), + environmentChainLength_(0), +@@ -879,7 +879,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind + Handle<LexicalScope::Data*> bindings) + { + MOZ_ASSERT(kind != ScopeKind::NamedLambda && kind != ScopeKind::StrictNamedLambda); +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + if (!ensureCache(bce)) + return false; +@@ -948,7 +948,7 @@ BytecodeEmitter::EmitterScope::enterLexical(BytecodeEmitter* bce, ScopeKind kind + bool + BytecodeEmitter::EmitterScope::enterNamedLambda(BytecodeEmitter* bce, FunctionBox* funbox) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + MOZ_ASSERT(funbox->namedLambdaBindings()); + + if (!ensureCache(bce)) +@@ -1015,7 +1015,7 @@ BytecodeEmitter::EmitterScope::enterComprehensionFor(BytecodeEmitter* bce, + bool + BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + if (!ensureCache(bce)) + return false; +@@ -1048,7 +1048,7 @@ BytecodeEmitter::EmitterScope::enterParameterExpressionVar(BytecodeEmitter* bce) + bool + BytecodeEmitter::EmitterScope::enterFunction(BytecodeEmitter* bce, FunctionBox* funbox) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + // If there are parameter expressions, there is an extra var scope. + if (!funbox->hasExtraBodyVarScope()) +@@ -1139,7 +1139,7 @@ BytecodeEmitter::EmitterScope::enterFunctionExtraBodyVar(BytecodeEmitter* bce, F + MOZ_ASSERT(funbox->hasParameterExprs); + MOZ_ASSERT(funbox->extraVarScopeBindings() || + funbox->needsExtraBodyVarEnvironmentRegardlessOfBindings()); +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + // The extra var scope is never popped once it's entered. It replaces the + // function scope as the var emitter scope. +@@ -1225,7 +1225,7 @@ class DynamicBindingIter : public BindingIter + bool + BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedContext* globalsc) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + bce->setVarEmitterScope(this); + +@@ -1285,7 +1285,7 @@ BytecodeEmitter::EmitterScope::enterGlobal(BytecodeEmitter* bce, GlobalSharedCon + bool + BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext* evalsc) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + bce->setVarEmitterScope(this); + +@@ -1340,7 +1340,7 @@ BytecodeEmitter::EmitterScope::enterEval(BytecodeEmitter* bce, EvalSharedContext + bool + BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedContext* modulesc) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + bce->setVarEmitterScope(this); + +@@ -1397,7 +1397,7 @@ BytecodeEmitter::EmitterScope::enterModule(BytecodeEmitter* bce, ModuleSharedCon + bool + BytecodeEmitter::EmitterScope::enterWith(BytecodeEmitter* bce) + { +- MOZ_ASSERT(this == bce->innermostEmitterScope); ++ MOZ_ASSERT(this == bce->innermostEmitterScopeNoCheck()); + + if (!ensureCache(bce)) + return false; +@@ -1425,7 +1425,7 @@ BytecodeEmitter::EmitterScope::leave(BytecodeEmitter* bce, bool nonLocal) + { + // If we aren't leaving the scope due to a non-local jump (e.g., break), + // we must be the innermost scope. +- MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScope); ++ MOZ_ASSERT_IF(!nonLocal, this == bce->innermostEmitterScopeNoCheck()); + + ScopeKind kind = scope(bce)->kind(); + switch (kind) { +@@ -2139,7 +2139,7 @@ class ForOfLoopControl : public LoopControl + + bool emitIteratorCloseInInnermostScope(BytecodeEmitter* bce, + CompletionKind completionKind = CompletionKind::Normal) { +- return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope, completionKind); ++ return emitIteratorCloseInScope(bce, *bce->innermostEmitterScope(), completionKind); + } + + bool emitIteratorCloseInScope(BytecodeEmitter* bce, +@@ -2213,8 +2213,11 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent, + bodyScopeIndex(UINT32_MAX), + varEmitterScope(nullptr), + innermostNestableControl(nullptr), +- innermostEmitterScope(nullptr), ++ innermostEmitterScope_(nullptr), + innermostTDZCheckCache(nullptr), ++#ifdef DEBUG ++ unstableEmitterScope(false), ++#endif + constList(cx), + scopeList(cx), + tryNoteList(cx), +@@ -2271,13 +2274,13 @@ BytecodeEmitter::findInnermostNestableControl(Predicate predicate) const + NameLocation + BytecodeEmitter::lookupName(JSAtom* name) + { +- return innermostEmitterScope->lookup(this, name); ++ return innermostEmitterScope()->lookup(this, name); + } + + Maybe<NameLocation> + BytecodeEmitter::locationOfNameBoundInScope(JSAtom* name, EmitterScope* target) + { +- return innermostEmitterScope->locationBoundInScope(this, name, target); ++ return innermostEmitterScope()->locationBoundInScope(this, name, target); + } + + Maybe<NameLocation> +@@ -2757,7 +2760,7 @@ class NonLocalExitControl + : bce_(bce), + savedScopeNoteIndex_(bce->scopeNoteList.length()), + savedDepth_(bce->stackDepth), +- openScopeNoteIndex_(bce->innermostEmitterScope->noteIndex()), ++ openScopeNoteIndex_(bce->innermostEmitterScope()->noteIndex()), + kind_(kind) + { } + +@@ -2803,9 +2806,11 @@ NonLocalExitControl::prepareForNonLocalJump(BytecodeEmitter::NestableControl* ta + using NestableControl = BytecodeEmitter::NestableControl; + using EmitterScope = BytecodeEmitter::EmitterScope; + +- EmitterScope* es = bce_->innermostEmitterScope; ++ EmitterScope* es = bce_->innermostEmitterScope(); + int npops = 0; + ++ AutoCheckUnstableEmitterScope cues(bce_); ++ + // For 'continue', 'break', and 'return' statements, emit IteratorClose + // bytecode inline. 'continue' statements do not call IteratorClose for + // the loop they are continuing. +@@ -2924,7 +2929,7 @@ BytecodeEmitter::emitGoto(NestableControl* target, JumpList* jumplist, SrcNoteTy + Scope* + BytecodeEmitter::innermostScope() const + { +- return innermostEmitterScope->scope(this); ++ return innermostEmitterScope()->scope(this); + } + + bool +@@ -3585,7 +3590,7 @@ BytecodeEmitter::needsImplicitThis() + return true; + + // Otherwise see if the current point is under a 'with'. +- for (EmitterScope* es = innermostEmitterScope; es; es = es->enclosingInFrame()) { ++ for (EmitterScope* es = innermostEmitterScope(); es; es = es->enclosingInFrame()) { + if (es->scope(this)->kind() == ScopeKind::With) + return true; + } +@@ -5262,7 +5267,7 @@ BytecodeEmitter::emitSetOrInitializeDestructuring(ParseNode* target, Destructuri + // destructuring declaration needs to initialize the name in + // the function scope. The innermost scope is the var scope, + // and its enclosing scope is the function scope. +- EmitterScope* funScope = innermostEmitterScope->enclosingInFrame(); ++ EmitterScope* funScope = innermostEmitterScope()->enclosingInFrame(); + NameLocation paramLoc = *locationOfNameBoundInScope(name, funScope); + if (!emitSetOrInitializeNameAtLocation(name, paramLoc, emitSwapScopeAndRhs, true)) + return false; +@@ -7304,7 +7309,7 @@ BytecodeEmitter::emitForOf(ParseNode* forOfLoop, EmitterScope* headLexicalEmitte + // bindings inducing an environment, recreate the current environment. + DebugOnly<ParseNode*> forOfTarget = forOfHead->pn_kid1; + MOZ_ASSERT(forOfTarget->isKind(PNK_LET) || forOfTarget->isKind(PNK_CONST)); +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -7502,7 +7507,7 @@ BytecodeEmitter::emitForIn(ParseNode* forInLoop, EmitterScope* headLexicalEmitte + // it must be the innermost one. If that scope has closed-over + // bindings inducing an environment, recreate the current environment. + MOZ_ASSERT(forInTarget->isKind(PNK_LET) || forInTarget->isKind(PNK_CONST)); +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -7635,7 +7640,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc + // exists for the head, it must be the innermost one. If that scope + // has closed-over bindings inducing an environment, recreate the + // current environment. +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -7683,7 +7688,7 @@ BytecodeEmitter::emitCStyleFor(ParseNode* pn, EmitterScope* headLexicalEmitterSc + + // ES 13.7.4.8 step 3.e. The per-iteration freshening. + if (forLoopRequiresFreshening) { +- MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope); ++ MOZ_ASSERT(headLexicalEmitterScope == innermostEmitterScope()); + MOZ_ASSERT(headLexicalEmitterScope->scope(this)->kind() == ScopeKind::Lexical); + + if (headLexicalEmitterScope->hasEnvironment()) { +@@ -10410,7 +10415,7 @@ BytecodeEmitter::emitFunctionFormalParameters(ParseNode* pn) + { + ParseNode* funBody = pn->last(); + FunctionBox* funbox = sc->asFunctionBox(); +- EmitterScope* funScope = innermostEmitterScope; ++ EmitterScope* funScope = innermostEmitterScope(); + + bool hasParameterExprs = funbox->hasParameterExprs; + bool hasRest = funbox->hasRest(); +diff --git js/src/frontend/BytecodeEmitter.h js/src/frontend/BytecodeEmitter.h +index 039d271e4d965..91826f27bf9fd 100644 +--- js/src/frontend/BytecodeEmitter.h ++++ js/src/frontend/BytecodeEmitter.h +@@ -232,9 +232,23 @@ struct MOZ_STACK_CLASS BytecodeEmitter + + EmitterScope* varEmitterScope; + NestableControl* innermostNestableControl; +- EmitterScope* innermostEmitterScope; ++ EmitterScope* innermostEmitterScope_; + TDZCheckCache* innermostTDZCheckCache; + ++#ifdef DEBUG ++ bool unstableEmitterScope; ++ ++ friend class AutoCheckUnstableEmitterScope; ++#endif ++ ++ EmitterScope* innermostEmitterScope() const { ++ MOZ_ASSERT(!unstableEmitterScope); ++ return innermostEmitterScopeNoCheck(); ++ } ++ EmitterScope* innermostEmitterScopeNoCheck() const { ++ return innermostEmitterScope_; ++ } ++ + CGConstList constList; /* constants to be included with the script */ + CGObjectList objectList; /* list of emitted objects */ + CGScopeList scopeList; /* list of emitted scopes */ +@@ -339,7 +353,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + EmitterScope* source); + + mozilla::Maybe<NameLocation> locationOfNameBoundInFunctionScope(JSAtom* name) { +- return locationOfNameBoundInFunctionScope(name, innermostEmitterScope); ++ return locationOfNameBoundInFunctionScope(name, innermostEmitterScope()); + } + + void setVarEmitterScope(EmitterScope* emitterScope) { +@@ -635,7 +649,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitToIteratorResult(bool done); + + MOZ_MUST_USE bool emitGetDotGeneratorInInnermostScope() { +- return emitGetDotGeneratorInScope(*innermostEmitterScope); ++ return emitGetDotGeneratorInScope(*innermostEmitterScope()); + } + MOZ_MUST_USE bool emitGetDotGeneratorInScope(EmitterScope& currentScope); + +@@ -644,7 +658,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitYieldOp(JSOp op); + MOZ_MUST_USE bool emitYieldStar(ParseNode* iter); + MOZ_MUST_USE bool emitAwaitInInnermostScope() { +- return emitAwaitInScope(*innermostEmitterScope); ++ return emitAwaitInScope(*innermostEmitterScope()); + } + MOZ_MUST_USE bool emitAwaitInInnermostScope(ParseNode* pn); + MOZ_MUST_USE bool emitAwaitInScope(EmitterScope& currentScope); +@@ -751,7 +765,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitIteratorCloseInInnermostScope(IteratorKind iterKind = IteratorKind::Sync, + CompletionKind completionKind = CompletionKind::Normal, + bool allowSelfHosted = false) { +- return emitIteratorCloseInScope(*innermostEmitterScope, iterKind, completionKind, ++ return emitIteratorCloseInScope(*innermostEmitterScope(), iterKind, completionKind, + allowSelfHosted); + } + +@@ -852,6 +866,31 @@ struct MOZ_STACK_CLASS BytecodeEmitter + MOZ_MUST_USE bool emitSuperElemOp(ParseNode* pn, JSOp op, bool isCall = false); + }; + ++class MOZ_RAII AutoCheckUnstableEmitterScope { ++#ifdef DEBUG ++ bool prev_; ++ BytecodeEmitter* bce_; ++#endif ++ ++ public: ++ AutoCheckUnstableEmitterScope() = delete; ++ explicit AutoCheckUnstableEmitterScope(BytecodeEmitter* bce) ++#ifdef DEBUG ++ : bce_(bce) ++#endif ++ { ++#ifdef DEBUG ++ prev_ = bce_->unstableEmitterScope; ++ bce_->unstableEmitterScope = true; ++#endif ++ } ++ ~AutoCheckUnstableEmitterScope() { ++#ifdef DEBUG ++ bce_->unstableEmitterScope = prev_; ++#endif ++ } ++}; ++ + } /* namespace frontend */ + } /* namespace js */ + diff --git a/www/waterfox/files/patch-bug1454572 b/www/waterfox/files/patch-bug1454572 new file mode 100644 index 000000000000..c84eae5e9da7 --- /dev/null +++ b/www/waterfox/files/patch-bug1454572 @@ -0,0 +1,43 @@ +commit 6c5f29ecc4a3 +Author: James Teh <jteh@mozilla.com> +Date: Thu Apr 19 15:53:25 2018 +1000 + + Bug 1454572: nsComputedDOMStyle: Don't crash when used on a detached pseudo-element. r=emilio,xidorn:emilio a=RyanVM + + This shouldn't normally happen, but it does in some rare cases; e.g. if an accessibility client queries info for a node that is being removed. + + MozReview-Commit-ID: 3nac9ITN66f + + --HG-- + extra : source : 0fcbe086a09ba9e9684f43706290b3e0f2226103 +--- + layout/style/nsComputedDOMStyle.cpp | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git layout/style/nsComputedDOMStyle.cpp layout/style/nsComputedDOMStyle.cpp +index 2ab4b28ad42a..f55675ee8ba4 100644 +--- layout/style/nsComputedDOMStyle.cpp ++++ layout/style/nsComputedDOMStyle.cpp +@@ -686,6 +686,7 @@ nsComputedDOMStyle::DoGetStyleContextNoFlush(Element* aElement, + AnimationFlag aAnimationFlag) + { + MOZ_ASSERT(aElement, "NULL element"); ++ + // If the content has a pres shell, we must use it. Otherwise we'd + // potentially mix rule trees by using the wrong pres shell's style + // set. Using the pres shell from the content also means that any +@@ -728,6 +729,14 @@ nsComputedDOMStyle::DoGetStyleContextNoFlush(Element* aElement, + } + } + ++ if (aElement->IsInNativeAnonymousSubtree() && !aElement->IsInComposedDoc()) { ++ // Normal web content can't access NAC, but Accessibility, DevTools and ++ // Editor use this same API and this may get called for anonymous content. ++ // Computing the style of a pseudo-element that doesn't have a parent doesn't ++ // really make sense. ++ return nullptr; ++ } ++ + // XXX the !aElement->IsHTMLElement(nsGkAtoms::area) + // check is needed due to bug 135040 (to avoid using + // mPrimaryFrame). Remove it once that's fixed. diff --git a/www/waterfox/files/patch-bug1455235 b/www/waterfox/files/patch-bug1455235 new file mode 100644 index 000000000000..4cf753496b54 --- /dev/null +++ b/www/waterfox/files/patch-bug1455235 @@ -0,0 +1,67 @@ +commit 7d43e67e661a +Author: Jan Horak <jhorak@redhat.com> +Date: Thu Apr 19 12:39:57 2018 +0200 + + Bug 1455235 [gtk] Don't start moving window before mousemove event, r=dao a=lizzard + + We need to start moving the window in GTK after mousemove event arrives, + not with mousedown, because the drag area can also process doubleclick + event to restore/maximize window. This also match to the GTK implementation, + see gedit behaviour for example. + + MozReview-Commit-ID: WXP3D2wIp0 + + --HG-- + extra : source : cc0d7de218cb0c260c8ba0cf6637845ad2222f49 +--- + toolkit/modules/WindowDraggingUtils.jsm | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +diff --git toolkit/modules/WindowDraggingUtils.jsm toolkit/modules/WindowDraggingUtils.jsm +index 465747e736f2..595d501ff7ec 100644 +--- toolkit/modules/WindowDraggingUtils.jsm ++++ toolkit/modules/WindowDraggingUtils.jsm +@@ -61,26 +61,29 @@ WindowDraggingElement.prototype = { + case "mousedown": + if (!this.shouldDrag(aEvent)) + return; +- +- if (/^gtk/i.test(AppConstants.MOZ_WIDGET_TOOLKIT)) { +- // On GTK, there is a toolkit-level function which handles +- // window dragging, which must be used. +- this._window.beginWindowMove(aEvent, isPanel ? this._elem : null); +- break; +- } +- if (isPanel) { +- let screenRect = this._elem.getOuterScreenRect(); +- this._deltaX = aEvent.screenX - screenRect.left; +- this._deltaY = aEvent.screenY - screenRect.top; +- } else { +- this._deltaX = aEvent.screenX - this._window.screenX; +- this._deltaY = aEvent.screenY - this._window.screenY; ++ if (!/^gtk/i.test(AppConstants.MOZ_WIDGET_TOOLKIT)) { ++ if (isPanel) { ++ let screenRect = this._elem.getOuterScreenRect(); ++ this._deltaX = aEvent.screenX - screenRect.left; ++ this._deltaY = aEvent.screenY - screenRect.top; ++ } else { ++ this._deltaX = aEvent.screenX - this._window.screenX; ++ this._deltaY = aEvent.screenY - this._window.screenY; ++ } + } + this._draggingWindow = true; + this._window.addEventListener("mousemove", this); + this._window.addEventListener("mouseup", this); + break; + case "mousemove": ++ if (/^gtk/i.test(AppConstants.MOZ_WIDGET_TOOLKIT)) { ++ // On GTK, there is a toolkit-level function which handles ++ // window dragging. We want to start moving the window ++ // on the first mousemove event after mousedown. ++ this._window.beginWindowMove(aEvent, isPanel ? this._elem : null); ++ this._window.removeEventListener("mousemove", this); ++ break; ++ } + if (this._draggingWindow) { + let toDrag = this.isPanel() ? this._elem : this._window; + toDrag.moveTo(aEvent.screenX - this._deltaX, aEvent.screenY - this._deltaY); diff --git a/www/waterfox/files/patch-bug1455261 b/www/waterfox/files/patch-bug1455261 new file mode 100644 index 000000000000..0ea9cb5b80ed --- /dev/null +++ b/www/waterfox/files/patch-bug1455261 @@ -0,0 +1,27 @@ +commit 24c2adf0cbd4 +Author: Michael Kaply <mozilla@kaply.com> +Date: Fri Jun 1 16:59:03 2018 -0500 + + Bug 1455261 - Check for null metadata to workaround broken search.json. r=adw, a=RyanVM + + MozReview-Commit-ID: 4D2F30MHaqE + + --HG-- + extra : source : 9a5f5fa5cfa0a6fe45eb7685fb1798529e8f406a +--- + toolkit/components/search/nsSearchService.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git toolkit/components/search/nsSearchService.js toolkit/components/search/nsSearchService.js +index 6c153c5e29cdf..86a286819f02b 100644 +--- toolkit/components/search/nsSearchService.js ++++ toolkit/components/search/nsSearchService.js +@@ -2074,7 +2074,7 @@ Engine.prototype = { + }, + + getAttr(name) { +- return this._metaData[name] || undefined; ++ return (this._metaData && this._metaData[name]) || undefined; + }, + + // nsISearchEngine diff --git a/www/waterfox/files/patch-bug1456512 b/www/waterfox/files/patch-bug1456512 new file mode 100644 index 000000000000..4f52fe92bdf5 --- /dev/null +++ b/www/waterfox/files/patch-bug1456512 @@ -0,0 +1,144 @@ +commit 501094be302c +Author: Steve Fink <sfink@mozilla.com> +Date: Tue May 22 16:08:40 2018 -0700 + + Bug 1456512 - Fixes for unwanted read barriers during minor GC: move JS::operator==(GCCellPtr,GCCellPtr) to the global scope to avoid shadowing, and add a dynamic check. r=jonco, a=RyanVM +--- + js/public/HeapAPI.h | 27 +++++++++++--------- + js/src/gc/Cell.h | 2 +- + .../regress/regress-1456512-greyreadbarrier.js | 7 ++++++ + js/src/tests/non262/regress/regress-1456512.js | 19 ++++++++++++++ + js/src/tests/non262/regress/regress-1463421.js | 29 ++++++++++++++++++++++ + 5 files changed, 71 insertions(+), 13 deletions(-) + +diff --git js/public/HeapAPI.h js/public/HeapAPI.h +index 34a3e156e66da..a14e1a813adfd 100644 +--- js/public/HeapAPI.h ++++ js/public/HeapAPI.h +@@ -269,18 +269,6 @@ class JS_FRIEND_API(GCCellPtr) + uintptr_t ptr; + }; + +-inline bool +-operator==(const GCCellPtr& ptr1, const GCCellPtr& ptr2) +-{ +- return ptr1.asCell() == ptr2.asCell(); +-} +- +-inline bool +-operator!=(const GCCellPtr& ptr1, const GCCellPtr& ptr2) +-{ +- return !(ptr1 == ptr2); +-} +- + // Unwraps the given GCCellPtr and calls the given functor with a template + // argument of the actual type of the pointer. + template <typename F, typename... Args> +@@ -301,6 +289,21 @@ DispatchTyped(F f, GCCellPtr thing, Args&&... args) + + } /* namespace JS */ + ++// These are defined in the toplevel namespace instead of within JS so that ++// they won't shadow other operator== overloads (see bug 1456512.) ++ ++inline bool ++operator==(const JS::GCCellPtr& ptr1, const JS::GCCellPtr& ptr2) ++{ ++ return ptr1.asCell() == ptr2.asCell(); ++} ++ ++inline bool ++operator!=(const JS::GCCellPtr& ptr1, const JS::GCCellPtr& ptr2) ++{ ++ return !(ptr1 == ptr2); ++} ++ + namespace js { + namespace gc { + namespace detail { +diff --git js/src/gc/Heap.h js/src/gc/Heap.h +index c14f8bfc2005e..340287e8322e9 100644 +--- js/src/gc/Heap.h ++++ js/src/gc/Heap.h +@@ -1381,7 +1381,7 @@ TenuredCell::readBarrier(TenuredCell* thing) + if (thing->isMarkedGray()) { + // There shouldn't be anything marked grey unless we're on the active thread. + MOZ_ASSERT(CurrentThreadCanAccessRuntime(thing->runtimeFromAnyThread())); +- if (!RuntimeFromActiveCooperatingThreadIsHeapMajorCollecting(shadowZone)) ++ if (!JS::CurrentThreadIsHeapCollecting()) + JS::UnmarkGrayGCThingRecursively(JS::GCCellPtr(thing, thing->getTraceKind())); + } + } +diff --git js/src/tests/non262/regress/regress-1456512-greyreadbarrier.js js/src/tests/non262/regress/regress-1456512-greyreadbarrier.js +new file mode 100644 +index 0000000000000..bb883eeffbeab +--- /dev/null ++++ js/src/tests/non262/regress/regress-1456512-greyreadbarrier.js +@@ -0,0 +1,7 @@ ++var wm = new WeakMap(); ++grayRoot().map = wm; ++wm = null; ++gczeal(13, 7); ++var lfOffThreadGlobal = newGlobal(); ++ ++reportCompare('do not crash', 'do not crash', 'did not crash!'); +diff --git js/src/tests/non262/regress/regress-1456512.js js/src/tests/non262/regress/regress-1456512.js +new file mode 100644 +index 0000000000000..87faeca39ad15 +--- /dev/null ++++ js/src/tests/non262/regress/regress-1456512.js +@@ -0,0 +1,19 @@ ++/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++var BUGNUMBER = 1456512; ++var summary = 'rogue read barrier'; ++ ++printBugNumber(BUGNUMBER); ++printStatus (summary); ++ ++var wm = new WeakMap(); ++grayRoot().map = wm; ++wm = null; ++gczeal(13, 7); ++var lfOffThreadGlobal = newGlobal(); ++ ++if (typeof reportCompare == 'function') ++ reportCompare(true, true, "ok"); +diff --git js/src/tests/non262/regress/regress-1463421.js js/src/tests/non262/regress/regress-1463421.js +new file mode 100644 +index 0000000000000..e037ade3b9fd0 +--- /dev/null ++++ js/src/tests/non262/regress/regress-1463421.js +@@ -0,0 +1,29 @@ ++/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++var BUGNUMBER = 1463421; ++var summary = 'rogue read barrier'; ++ ++printBugNumber(BUGNUMBER); ++printStatus (summary); ++ ++var exc; ++try { ++var __v_1173 = new WeakMap(); ++ grayRoot().map = __v_1173; ++ __v_1173 = null; ++ gczeal(13, 7); ++if (!isNaN()) { ++} ++ (function __f_252() { ++ ( { ++ })() ++ })(); ++} catch (e) { ++ exc = e; ++} ++ ++if (typeof reportCompare == 'function') ++ reportCompare("" + exc, "TypeError: ({}) is not a function", "ok"); diff --git a/www/waterfox/files/patch-bug1456524 b/www/waterfox/files/patch-bug1456524 new file mode 100644 index 000000000000..8c6c89dc9379 --- /dev/null +++ b/www/waterfox/files/patch-bug1456524 @@ -0,0 +1,122 @@ +commit 7813b28f0e98 +Author: Sean Stangl <sstangl@mozilla.com> +Date: Thu May 17 14:06:00 2018 -0400 + + Bug 1456524 - Maintain MoveResolver invariants. r=jandem, a=RyanVM + + The MoveResolver is a persistent data structure that requires + state to not leak between borrowers. An early-exit optimization + in the case of OOM allows for state to leak, leading to impossible + move list inputs, tripping assertions. + + --HG-- + extra : rebase_source : 38c5d7afaa4b6394ced3266b90032b8e3bdba351 +--- + js/src/jit/MacroAssembler.h | 5 +++++ + js/src/jit/MoveResolver.cpp | 7 +++++++ + js/src/jit/MoveResolver.h | 3 +++ + js/src/jit/arm/MacroAssembler-arm.cpp | 2 +- + js/src/jit/mips32/MacroAssembler-mips32.cpp | 2 +- + js/src/jit/mips64/MacroAssembler-mips64.cpp | 2 +- + 6 files changed, 18 insertions(+), 3 deletions(-) + +diff --git js/src/jit/MacroAssembler.h js/src/jit/MacroAssembler.h +index b2cc464aafcc4..cef8c094b70c5 100644 +--- js/src/jit/MacroAssembler.h ++++ js/src/jit/MacroAssembler.h +@@ -334,6 +334,11 @@ class MacroAssembler : public MacroAssemblerSpecific + + public: + MoveResolver& moveResolver() { ++ // As an optimization, the MoveResolver is a persistent data structure ++ // shared between visitors in the CodeGenerator. This assertion ++ // checks that state is not leaking from visitor to visitor ++ // via an unresolved addMove(). ++ MOZ_ASSERT(moveResolver_.hasNoPendingMoves()); + return moveResolver_; + } + +diff --git js/src/jit/MoveResolver.cpp js/src/jit/MoveResolver.cpp +index bd71d0acea44d..d79af5053b79c 100644 +--- js/src/jit/MoveResolver.cpp ++++ js/src/jit/MoveResolver.cpp +@@ -7,6 +7,7 @@ + #include "jit/MoveResolver.h" + + #include "mozilla/Attributes.h" ++#include "mozilla/ScopeExit.h" + + #include "jit/MacroAssembler.h" + #include "jit/RegisterSets.h" +@@ -178,12 +179,18 @@ SplitIntoUpperHalf(const MoveOperand& move) + } + #endif + ++// Resolves the pending_ list to a list in orderedMoves_. + bool + MoveResolver::resolve() + { + resetState(); + orderedMoves_.clear(); + ++ // Upon return from this function, the pending_ list must be cleared. ++ auto clearPending = mozilla::MakeScopeExit([this]() { ++ pending_.clear(); ++ }); ++ + #ifdef JS_CODEGEN_ARM + // Some of ARM's double registers alias two of its single registers, + // but the algorithm below assumes that every register can participate +diff --git js/src/jit/MoveResolver.h js/src/jit/MoveResolver.h +index d9a9415488704..d094ee1307563 100644 +--- js/src/jit/MoveResolver.h ++++ js/src/jit/MoveResolver.h +@@ -333,6 +333,9 @@ class MoveResolver + uint32_t numCycles() const { + return numCycles_; + } ++ bool hasNoPendingMoves() const { ++ return pending_.empty(); ++ } + void setAllocator(TempAllocator& alloc) { + movePool_.setAllocator(alloc); + } +diff --git js/src/jit/arm/MacroAssembler-arm.cpp js/src/jit/arm/MacroAssembler-arm.cpp +index a3985f2c24d1f..86e86310cc129 100644 +--- js/src/jit/arm/MacroAssembler-arm.cpp ++++ js/src/jit/arm/MacroAssembler-arm.cpp +@@ -4593,7 +4593,7 @@ MacroAssembler::callWithABIPre(uint32_t* stackAdjust, bool callFromWasm) + + // Position all arguments. + { +- enoughMemory_ = enoughMemory_ && moveResolver_.resolve(); ++ enoughMemory_ &= moveResolver_.resolve(); + if (!enoughMemory_) + return; + +diff --git js/src/jit/mips32/MacroAssembler-mips32.cpp js/src/jit/mips32/MacroAssembler-mips32.cpp +index 8f2fec7948b75..ef0a9136f4e39 100644 +--- js/src/jit/mips32/MacroAssembler-mips32.cpp ++++ js/src/jit/mips32/MacroAssembler-mips32.cpp +@@ -2191,7 +2191,7 @@ MacroAssembler::callWithABIPre(uint32_t* stackAdjust, bool callFromWasm) + + // Position all arguments. + { +- enoughMemory_ = enoughMemory_ && moveResolver_.resolve(); ++ enoughMemory_ &= moveResolver_.resolve(); + if (!enoughMemory_) + return; + +diff --git js/src/jit/mips64/MacroAssembler-mips64.cpp js/src/jit/mips64/MacroAssembler-mips64.cpp +index c944b0427aaee..8eec6bac047e4 100644 +--- js/src/jit/mips64/MacroAssembler-mips64.cpp ++++ js/src/jit/mips64/MacroAssembler-mips64.cpp +@@ -2040,7 +2040,7 @@ MacroAssembler::callWithABIPre(uint32_t* stackAdjust, bool callFromWasm) + + // Position all arguments. + { +- enoughMemory_ = enoughMemory_ && moveResolver_.resolve(); ++ enoughMemory_ &= moveResolver_.resolve(); + if (!enoughMemory_) + return; + diff --git a/www/waterfox/files/patch-bug1457912 b/www/waterfox/files/patch-bug1457912 new file mode 100644 index 000000000000..8c6c39491eea --- /dev/null +++ b/www/waterfox/files/patch-bug1457912 @@ -0,0 +1,169 @@ +commit 695328ac742d +Author: Xidorn Quan <me@upsuper.org> +Date: Mon May 7 10:40:34 2018 +1000 + + Bug 1457912 - Don't disable scrollbars when the window feature isn't listed explicitly. r=smaug, a=RyanVM + + MozReview-Commit-ID: CB0PVroA86L + + --HG-- + extra : source : f8876cbee5fa17c374115ed04404a3a3fc61ba40 +--- + .../components/windowwatcher/nsWindowWatcher.cpp | 5 +- + .../test/browser_new_content_window_chromeflags.js | 100 ++++++++++++++------- + 2 files changed, 73 insertions(+), 32 deletions(-) + +diff --git toolkit/components/windowwatcher/nsWindowWatcher.cpp toolkit/components/windowwatcher/nsWindowWatcher.cpp +index 44f06554b26fd..34706cd92b44e 100644 +--- toolkit/components/windowwatcher/nsWindowWatcher.cpp ++++ toolkit/components/windowwatcher/nsWindowWatcher.cpp +@@ -1700,9 +1700,12 @@ nsWindowWatcher::CalculateChromeFlagsHelper(uint32_t aInitialFlags, + nsIWebBrowserChrome::CHROME_WINDOW_MIN); + + // default scrollbar to "on," unless explicitly turned off +- if (WinHasOption(aFeatures, "scrollbars", 1, &presenceFlag) || !presenceFlag) { ++ bool scrollbarsPresent = false; ++ if (WinHasOption(aFeatures, "scrollbars", 1, &scrollbarsPresent) || ++ !scrollbarsPresent) { + chromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS; + } ++ presenceFlag = presenceFlag || scrollbarsPresent; + + return chromeFlags; + } +diff --git toolkit/components/windowwatcher/test/browser_new_content_window_chromeflags.js toolkit/components/windowwatcher/test/browser_new_content_window_chromeflags.js +index 871a4376f5671..2ea08da989467 100644 +--- toolkit/components/windowwatcher/test/browser_new_content_window_chromeflags.js ++++ toolkit/components/windowwatcher/test/browser_new_content_window_chromeflags.js +@@ -126,18 +126,6 @@ const DISALLOWED = { + }, + }; + +-// Construct a features string that flips all DISALLOWED features +-// to not be their defaults. +-const DISALLOWED_STRING = Object.keys(DISALLOWED).map(feature => { +- let toValue = DISALLOWED[feature].defaults_to ? "no" : "yes"; +- return `${feature}=${toValue}`; +-}).join(","); +- +-const FEATURES = [ALLOWED_STRING, DISALLOWED_STRING].join(","); +- +-const SCRIPT_PAGE = `data:text/html,<script>window.open("about:blank", "_blank", "${FEATURES}");</script>`; +-const SCRIPT_PAGE_FOR_CHROME_ALL = `data:text/html,<script>window.open("about:blank", "_blank", "all");</script>`; +- + // This magic value of 2 means that by default, when content tries + // to open a new window, it'll actually open in a new window instead + // of a new tab. +@@ -165,6 +153,35 @@ function getParentChromeFlags(win) { + .chromeFlags; + } + ++/** ++ * Given some nsIDOMWindow for a window running in the parent process, ++ * asynchronously return the nsIWebBrowserChrome chrome flags for the ++ * associated content window. ++ * ++ * @param win (nsIDOMWindow) ++ * @returns int ++ */ ++function getContentChromeFlags(win) { ++ let b = win.gBrowser.selectedBrowser; ++ return ContentTask.spawn(b, null, async function() { ++ // Content scripts provide docShell as a global. ++ /* global docShell */ ++ docShell.QueryInterface(Ci.nsIInterfaceRequestor); ++ try { ++ // This will throw if we're not a remote browser. ++ return docShell.getInterface(Ci.nsITabChild) ++ .QueryInterface(Ci.nsIWebBrowserChrome) ++ .chromeFlags; ++ } catch (e) { ++ // This must be a non-remote browser... ++ return docShell.QueryInterface(Ci.nsIDocShellTreeItem) ++ .treeOwner ++ .QueryInterface(Ci.nsIWebBrowserChrome) ++ .chromeFlags; ++ } ++ }); ++} ++ + /** + * For some chromeFlags, ensures that flags that are in the + * ALLOWED group were modified, and that flags in the DISALLOWED +@@ -214,6 +231,18 @@ function assertContentFlags(chromeFlags) { + * default. + */ + add_task(async function test_new_remote_window_flags() { ++ // Construct a features string that flips all DISALLOWED features ++ // to not be their defaults. ++ const DISALLOWED_STRING = Object.keys(DISALLOWED).map(feature => { ++ let toValue = DISALLOWED[feature].defaults_to ? "no" : "yes"; ++ return `${feature}=${toValue}`; ++ }).join(","); ++ ++ const FEATURES = [ALLOWED_STRING, DISALLOWED_STRING].join(","); ++ ++ const SCRIPT_PAGE = `data:text/html,<script>window.open("about:blank", "_blank", "${FEATURES}");</script>`; ++ const SCRIPT_PAGE_FOR_CHROME_ALL = `data:text/html,<script>window.open("about:blank", "_blank", "all");</script>`; ++ + let newWinPromise = BrowserTestUtils.waitForNewWindow(); + + await BrowserTestUtils.withNewTab({ +@@ -236,25 +265,7 @@ add_task(async function test_new_remote_window_flags() { + + // Confusingly, chromeFlags also exist in the content process + // as part of the TabChild, so we have to check those too. +- let b = win.gBrowser.selectedBrowser; +- let contentChromeFlags = await ContentTask.spawn(b, null, async function() { +- // Content scripts provide docShell as a global. +- /* global docShell */ +- docShell.QueryInterface(Ci.nsIInterfaceRequestor); +- try { +- // This will throw if we're not a remote browser. +- return docShell.getInterface(Ci.nsITabChild) +- .QueryInterface(Ci.nsIWebBrowserChrome) +- .chromeFlags; +- } catch (e) { +- // This must be a non-remote browser... +- return docShell.QueryInterface(Ci.nsIDocShellTreeItem) +- .treeOwner +- .QueryInterface(Ci.nsIWebBrowserChrome) +- .chromeFlags; +- } +- }); +- ++ let contentChromeFlags = await getContentChromeFlags(win); + assertContentFlags(contentChromeFlags); + Assert.ok(!(contentChromeFlags & + Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW), +@@ -279,3 +290,30 @@ add_task(async function test_new_remote_window_flags() { + await BrowserTestUtils.closeWindow(win); + }); + }); ++ ++/** ++ * Opens a window with some chrome flags specified, which should not affect ++ * scrollbars flag which defaults to true when not disabled explicitly. ++ */ ++add_task(async function test_scrollbars_flag() { ++ const SCRIPT = 'window.open("about:blank", "_blank", "toolbar=0");'; ++ const SCRIPT_PAGE = `data:text/html,<script>${SCRIPT}</script>`; ++ ++ let newWinPromise = BrowserTestUtils.waitForNewWindow(); ++ await BrowserTestUtils.withNewTab({ ++ gBrowser, ++ url: SCRIPT_PAGE, ++ }, async function(browser) { ++ let win = await newWinPromise; ++ ++ let parentChromeFlags = getParentChromeFlags(win); ++ Assert.ok(parentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS, ++ "Should have scrollbars when not disabled explicitly"); ++ ++ let contentChromeFlags = await getContentChromeFlags(win); ++ Assert.ok(contentChromeFlags & Ci.nsIWebBrowserChrome.CHROME_SCROLLBARS, ++ "Should have scrollbars when not disabled explicitly"); ++ ++ await BrowserTestUtils.closeWindow(win); ++ }); ++}); diff --git a/www/waterfox/files/patch-bug1458166 b/www/waterfox/files/patch-bug1458166 new file mode 100644 index 000000000000..be3522e6ef66 --- /dev/null +++ b/www/waterfox/files/patch-bug1458166 @@ -0,0 +1,75 @@ +commit 64082ca923f8 +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Mon May 7 11:33:07 2018 +0200 + + Bug 1458166 - Clear out tracks while destroying MediaStream. r=bryce, a=RyanVM + + MediaStream::Destroy() is part of a controlled shutdown sequence. + If there are still tracks with content beyond Destroy() they will + only get caught by the dtor, which may be on CC shutdown and too late. + + MozReview-Commit-ID: GV6XRiTCIRk + + --HG-- + extra : source : da84235630724b32d2e619c4ae6b7ae34a4c5c2d +--- + dom/media/MediaStreamGraph.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git dom/media/MediaStreamGraph.cpp dom/media/MediaStreamGraph.cpp +index 1c6683c966084..9cdb50e8abc98 100644 +--- dom/media/MediaStreamGraph.cpp ++++ dom/media/MediaStreamGraph.cpp +@@ -2054,6 +2054,7 @@ MediaStream::DestroyImpl() + for (int32_t i = mConsumers.Length() - 1; i >= 0; --i) { + mConsumers[i]->Disconnect(); + } ++ mTracks.Clear(); + mGraph = nullptr; + } + +commit d18fab7f3fa9 +Author: Andreas Pehrson <pehrsons@mozilla.com> +Date: Mon May 7 11:36:35 2018 +0200 + + Bug 1458166 - Remove listeners before destroying MediaStreams. r=bryce, a=RyanVM + + If listeners are still registered to a MediaStream on MediaStream::Destroy + (triggered by MediaStream::UnregisterUser below), they will catch and act + on further events from the MediaStream (such as a track ending). + + This may dispatch runnables that are unnecessary since we know we are + shutting down. + + If we first remove the listeners from the MediaStream we will never see + said events. + + MozReview-Commit-ID: IZ1kENqL2C8 + + --HG-- + extra : source : 8dc7d2696a29c0752066ebe67962b1ad323c4153 +--- + dom/media/DOMMediaStream.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git dom/media/DOMMediaStream.cpp dom/media/DOMMediaStream.cpp +index f69324d416a8f..febb527556701 100644 +--- dom/media/DOMMediaStream.cpp ++++ dom/media/DOMMediaStream.cpp +@@ -455,10 +455,16 @@ DOMMediaStream::Destroy() + { + LOG(LogLevel::Debug, ("DOMMediaStream %p Being destroyed.", this)); + if (mOwnedListener) { ++ if (mOwnedStream) { ++ mOwnedStream->RemoveListener(mOwnedListener); ++ } + mOwnedListener->Forget(); + mOwnedListener = nullptr; + } + if (mPlaybackListener) { ++ if (mPlaybackStream) { ++ mPlaybackStream->RemoveListener(mPlaybackListener); ++ } + mPlaybackListener->Forget(); + mPlaybackListener = nullptr; + } diff --git a/www/waterfox/files/patch-bug1458720 b/www/waterfox/files/patch-bug1458720 new file mode 100644 index 000000000000..680608ca23f7 --- /dev/null +++ b/www/waterfox/files/patch-bug1458720 @@ -0,0 +1,99 @@ +commit ba437f08694c +Author: David Keeler <dkeeler@mozilla.com> +Date: Wed May 2 16:42:51 2018 -0700 + + Bug 1458720 - Make RunOnAllContentParents runnable from any thread. r=Ehsan, r=jcj, a=RyanVM + + In bug 1215723 RunOnAllContentParents was added to the DataStorage + implementation so we could make more security state information available in + child processes. It uses IPC APIs, which in general are not thread-safe. We need + to make sure that these APIs are only accessed on the main thread, which means + we have to copy any necessary data, create a runnable, and send it to the main + thread to do the actual work. Note that the IPC APIs are async, so this dispatch + can be async as well. + + MozReview-Commit-ID: HwkgSX1iORU + + --HG-- + extra : source : 38e60f49b316258b72f8453387049c16d2005867 +--- + security/manager/ssl/DataStorage.cpp | 34 +++++++++++++++++++++++----------- + 1 file changed, 23 insertions(+), 11 deletions(-) + +diff --git security/manager/ssl/DataStorage.cpp security/manager/ssl/DataStorage.cpp +index e93f7f50a0b39..00e43f298aae3 100644 +--- security/manager/ssl/DataStorage.cpp ++++ security/manager/ssl/DataStorage.cpp +@@ -707,6 +707,8 @@ DataStorage::MaybeEvictOneEntry(DataStorageType aType, + } + } + ++// NB: Because this may cross a thread boundary, any variables captured by the ++// Functor must be captured by copy and not by reference. + template <class Functor> + static + void +@@ -716,11 +718,16 @@ RunOnAllContentParents(Functor func) + return; + } + using dom::ContentParent; +- nsTArray<ContentParent*> parents; +- ContentParent::GetAll(parents); +- for (auto& parent: parents) { +- func(parent); +- } ++ ++ nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("RunOnAllContentParents", ++ [func] () { ++ nsTArray<ContentParent*> parents; ++ ContentParent::GetAll(parents); ++ for (auto& parent: parents) { ++ func(parent); ++ } ++ }); ++ MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(r)); + } + + nsresult +@@ -749,12 +756,14 @@ DataStorage::Put(const nsCString& aKey, const nsCString& aValue, + return rv; + } + +- RunOnAllContentParents([&](dom::ContentParent* aParent) { ++ nsString filename(mFilename); ++ RunOnAllContentParents( ++ [aKey, aValue, aType, filename] (dom::ContentParent* aParent) { + DataStorageItem item; + item.key() = aKey; + item.value() = aValue; + item.type() = aType; +- Unused << aParent->SendDataStoragePut(mFilename, item); ++ Unused << aParent->SendDataStoragePut(filename, item); + }); + + return NS_OK; +@@ -788,8 +797,10 @@ DataStorage::Remove(const nsCString& aKey, DataStorageType aType) + Unused << AsyncSetTimer(lock); + } + +- RunOnAllContentParents([&](dom::ContentParent* aParent) { +- Unused << aParent->SendDataStorageRemove(mFilename, aKey, aType); ++ nsString filename(mFilename); ++ RunOnAllContentParents( ++ [filename, aKey, aType] (dom::ContentParent* aParent) { ++ Unused << aParent->SendDataStorageRemove(filename, aKey, aType); + }); + } + +@@ -914,8 +925,9 @@ DataStorage::Clear() + } + } + +- RunOnAllContentParents([&](dom::ContentParent* aParent) { +- Unused << aParent->SendDataStorageClear(mFilename); ++ nsString filename(mFilename); ++ RunOnAllContentParents([filename] (dom::ContentParent* aParent) { ++ Unused << aParent->SendDataStorageClear(filename); + }); + + return NS_OK; diff --git a/www/waterfox/files/patch-bug1461203 b/www/waterfox/files/patch-bug1461203 new file mode 100644 index 000000000000..8401b81fb47b --- /dev/null +++ b/www/waterfox/files/patch-bug1461203 @@ -0,0 +1,41 @@ +commit c0a881204f3a +Author: Martin Stransky <stransky@redhat.com> +Date: Thu May 17 14:40:21 2018 +0200 + + Bug 1461203 - Use GetScrollbarMetrics() to access scrollbar metrics. r=jhorak, a=RyanVM + + MozReview-Commit-ID: 3gnFNfxQJZi + + --HG-- + extra : source : bdfce06ecdb44275214caa0c8333d3112bbb4d16 +--- + widget/gtk/gtk3drawing.cpp | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git widget/gtk/gtk3drawing.cpp widget/gtk/gtk3drawing.cpp +index 8efc4f70d1be2..71ddd1e9d4bb7 100644 +--- widget/gtk/gtk3drawing.cpp ++++ widget/gtk/gtk3drawing.cpp +@@ -888,16 +888,14 @@ moz_gtk_scrollbar_button_paint(cairo_t *cr, const GdkRectangle* aRect, + // in case of horizontal scrollbars). + GtkOrientation orientation = flags & MOZ_GTK_STEPPER_VERTICAL ? + GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL; +- const auto& metrics = sScrollbarMetrics[orientation]; +- if (!metrics.initialized) { +- NS_WARNING("Didn't measure before drawing?"); +- } ++ ++ const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); + if (flags & MOZ_GTK_STEPPER_VERTICAL) { +- rect.x += metrics.border.track.left; +- rect.width = metrics.size.thumb.width; ++ rect.x += metrics->border.track.left; ++ rect.width = metrics->size.thumb.width; + } else { +- rect.y += metrics.border.track.top; +- rect.height = metrics.size.thumb.height; ++ rect.y += metrics->border.track.top; ++ rect.height = metrics->size.thumb.height; + } + } + diff --git a/www/waterfox/files/patch-bug1461448 b/www/waterfox/files/patch-bug1461448 new file mode 100644 index 000000000000..a75780e8b564 --- /dev/null +++ b/www/waterfox/files/patch-bug1461448 @@ -0,0 +1,80 @@ +commit cd48fc1a4518 +Author: Jon Coppeard <jcoppeard@mozilla.com> +Date: Fri May 18 10:29:00 2018 +0100 + + Bug 1461448 - Add gray marking phase to delayed marking phase. r=sfink, a=RyanVM + + --HG-- + extra : source : ff105a4cff4eb85a9e50a4ccf8144069412521e5 +--- + js/src/gc/GenerateStatsPhases.py | 6 +++-- + js/src/jit-test/tests/gc/bug-1461448.js | 40 +++++++++++++++++++++++++++++++++ + 2 files changed, 44 insertions(+), 2 deletions(-) + +diff --git js/src/gc/GenerateStatsPhases.py js/src/gc/GenerateStatsPhases.py +index ece873dc05004..2daf83555e33b 100644 +--- js/src/gc/GenerateStatsPhases.py ++++ js/src/gc/GenerateStatsPhases.py +@@ -88,12 +88,14 @@ PhaseKindGraphRoots = [ + PhaseKind("PURGE", "Purge", 5), + PhaseKind("PURGE_SHAPE_TABLES", "Purge ShapeTables", 60), + JoinParallelTasksPhaseKind +- ]), ++ ]), + PhaseKind("MARK", "Mark", 6, [ + MarkRootsPhaseKind, + UnmarkGrayPhaseKind, +- PhaseKind("MARK_DELAYED", "Mark Delayed", 8) ++ PhaseKind("MARK_DELAYED", "Mark Delayed", 8, [ ++ UnmarkGrayPhaseKind, + ]), ++ ]), + PhaseKind("SWEEP", "Sweep", 9, [ + PhaseKind("SWEEP_MARK", "Mark During Sweeping", 10, [ + UnmarkGrayPhaseKind, +diff --git js/src/jit-test/tests/gc/bug-1461448.js js/src/jit-test/tests/gc/bug-1461448.js +new file mode 100644 +index 0000000000000..3b9e69df89101 +--- /dev/null ++++ js/src/jit-test/tests/gc/bug-1461448.js +@@ -0,0 +1,40 @@ ++if (helperThreadCount() === 0) ++ quit(); ++ ++gczeal(0); ++ ++let lfPreamble = ` ++ var lfOffThreadGlobal = newGlobal(); ++ for (lfLocal in this) ++ try {} catch(lfVare5) {} ++`; ++evaluate(lfPreamble); ++evaluate(` ++ var g = newGlobal(); ++ var dbg = new Debugger; ++ var gw = dbg.addDebuggee(g); ++ for (lfLocal in this) ++ if (!(lfLocal in lfOffThreadGlobal)) ++ try { ++ lfOffThreadGlobal[lfLocal] = this[lfLocal]; ++ } catch(lfVare5) {} ++ var g = newGlobal(); ++ var gw = dbg.addDebuggee(g); ++`); ++lfOffThreadGlobal.offThreadCompileScript(` ++ gcparam("markStackLimit", 1); ++ grayRoot()[0] = "foo"; ++`); ++lfOffThreadGlobal.runOffThreadScript(); ++eval(` ++ var lfOffThreadGlobal = newGlobal(); ++ try { evaluate(\` ++ gczeal(18, 1); ++ grayRoot()[0] = "foo"; ++ let inst = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary( ++ \\\`(module ++ (memory (export "memory") 1 1) ++ )\\\` ++ ))); ++\`); } catch(exc) {} ++`); diff --git a/www/waterfox/files/patch-bug1464872 b/www/waterfox/files/patch-bug1464872 new file mode 100644 index 000000000000..ced4eb742a48 --- /dev/null +++ b/www/waterfox/files/patch-bug1464872 @@ -0,0 +1,96 @@ +commit c5d9b6fb8b07 +Author: Jon Coppeard <jcoppeard@mozilla.com> +Date: Thu May 31 09:27:29 2018 +0100 + + Bug 1464872 - Add forward zone edge for debugger object when calculating sweep groups. r=sfink, a=RyanVM + + --HG-- + extra : rebase_source : 4bef781c44aec09e4e8cd13b4131f26548a9f5dc + extra : source : 2d1e3d80489de3ac0ab0fef04f20cee5b117cbac +--- + js/src/jit-test/tests/gc/bug-1464872.js | 14 ++++++++++ + js/src/vm/Debugger.cpp | 47 +++++++++++++++++++++------------ + 2 files changed, 44 insertions(+), 17 deletions(-) + +diff --git js/src/jit-test/tests/gc/bug-1464872.js js/src/jit-test/tests/gc/bug-1464872.js +new file mode 100644 +index 0000000000000..433e4a1314ce5 +--- /dev/null ++++ js/src/jit-test/tests/gc/bug-1464872.js +@@ -0,0 +1,14 @@ ++var g = newGlobal(); ++var dbg = Debugger(g); ++dbg.onEnterFrame = function(frame) {}; ++ ++var g2 = newGlobal(); ++g2[g] = g; ++g2.evaluate("grayRoot()") ++g2 = undefined; ++ ++g = undefined; ++dbg = undefined; ++ ++gc(); ++startgc(100000); +diff --git js/src/vm/Debugger.cpp js/src/vm/Debugger.cpp +index 09b82b9a60d48..26afc6e84f4b4 100644 +--- js/src/vm/Debugger.cpp ++++ js/src/vm/Debugger.cpp +@@ -3282,26 +3282,39 @@ Debugger::detachAllDebuggersFromGlobal(FreeOp* fop, GlobalObject* global) + /* static */ void + Debugger::findZoneEdges(Zone* zone, js::gc::ZoneComponentFinder& finder) + { +- /* +- * For debugger cross compartment wrappers, add edges in the opposite +- * direction to those already added by JSCompartment::findOutgoingEdges. +- * This ensure that debuggers and their debuggees are finalized in the same +- * group. +- */ + for (ZoneGroupsIter group(zone->runtimeFromActiveCooperatingThread()); !group.done(); group.next()) { + for (Debugger* dbg : group->debuggerList()) { +- Zone* w = dbg->object->zone(); +- if (w == zone || !w->isGCMarking()) +- continue; +- if (dbg->debuggeeZones.has(zone) || +- dbg->scripts.hasKeyInZone(zone) || +- dbg->sources.hasKeyInZone(zone) || +- dbg->objects.hasKeyInZone(zone) || +- dbg->environments.hasKeyInZone(zone) || +- dbg->wasmInstanceScripts.hasKeyInZone(zone) || +- dbg->wasmInstanceSources.hasKeyInZone(zone)) +- { +- finder.addEdgeTo(w); ++ Zone* debuggerZone = dbg->object->zone(); ++ if (!debuggerZone->isGCMarking()) ++ continue; ++ ++ if (debuggerZone == zone) { ++ /* ++ * Add edges to debuggee zones. These are weak references that are ++ * not in the cross compartment wrapper map. ++ */ ++ for (auto e = dbg->debuggeeZones.all(); !e.empty(); e.popFront()) { ++ Zone* debuggeeZone = e.front(); ++ if (debuggeeZone->isGCMarking()) ++ finder.addEdgeTo(debuggeeZone); ++ } ++ } else { ++ /* ++ * For debugger cross compartment wrappers, add edges in the ++ * opposite direction to those already added by ++ * JSCompartment::findOutgoingEdges and above. This ensure that ++ * debuggers and their debuggees are finalized in the same group. ++ */ ++ if (dbg->debuggeeZones.has(zone) || ++ dbg->scripts.hasKeyInZone(zone) || ++ dbg->sources.hasKeyInZone(zone) || ++ dbg->objects.hasKeyInZone(zone) || ++ dbg->environments.hasKeyInZone(zone) || ++ dbg->wasmInstanceScripts.hasKeyInZone(zone) || ++ dbg->wasmInstanceSources.hasKeyInZone(zone)) ++ { ++ finder.addEdgeTo(debuggerZone); ++ } + } + } + } diff --git a/www/waterfox/files/patch-bug1465108 b/www/waterfox/files/patch-bug1465108 new file mode 100644 index 000000000000..66095c395a44 --- /dev/null +++ b/www/waterfox/files/patch-bug1465108 @@ -0,0 +1,520 @@ +commit ef14efabf364 +Author: Jon Coppeard <jcoppeard@mozilla.com> +Date: Thu May 10 10:09:23 2018 +0100 + + Bug 1465108 - Fix count of compacting update tasks started r=sfink a=abillings a=RyanVM +--- + js/src/gc/GC.cpp | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git js/src/jsgc.cpp js/src/jsgc.cpp +index 194e6e82e2a80..2f552a14b5582 100644 +--- js/src/jsgc.cpp ++++ js/src/jsgc.cpp +@@ -2818,7 +2818,7 @@ GCRuntime::updateCellPointers(Zone* zone, AllocKinds kinds, size_t bgTaskCount) + for (size_t i = 0; i < bgTaskCount && !bgArenas.done(); i++) { + bgTasks[i].emplace(rt, &bgArenas, lock); + startTask(*bgTasks[i], gcstats::PhaseKind::COMPACT_UPDATE_CELLS, lock); +- tasksStarted = i; ++ tasksStarted++; + } + } + +@@ -2829,6 +2829,8 @@ GCRuntime::updateCellPointers(Zone* zone, AllocKinds kinds, size_t bgTaskCount) + + for (size_t i = 0; i < tasksStarted; i++) + joinTask(*bgTasks[i], gcstats::PhaseKind::COMPACT_UPDATE_CELLS, lock); ++ for (size_t i = tasksStarted; i < MaxCellUpdateBackgroundTasks; i++) ++ MOZ_ASSERT(bgTasks[i].isNothing()); + } + } + +commit 72fb9a19590e +Author: Jon Coppeard <jcoppeard@mozilla.com> +Date: Thu May 10 10:09:31 2018 +0100 + + Bug 1465108 - Use function pointers rather than virtual run method for GC parallel tasks r=sfink a=abillings a=RyanVM +--- + js/src/gc/Allocator.cpp | 2 +- + js/src/gc/GC.cpp | 75 +++++++++++++++++++++++---------------------- + js/src/gc/GCParallelTask.h | 44 ++++++++++++++++++++++---- + js/src/gc/GCRuntime.h | 18 +++++------ + js/src/gc/Nursery.cpp | 12 +++++--- + js/src/gc/Statistics.h | 3 -- + js/src/vm/HelperThreads.cpp | 4 +-- + 7 files changed, 95 insertions(+), 63 deletions(-) + +diff --git js/src/gc/Allocator.cpp js/src/gc/Allocator.cpp +index ba0acc392ae8d..62da83637238e 100644 +--- js/src/gc/Allocator.cpp ++++ js/src/gc/Allocator.cpp +@@ -643,7 +643,7 @@ GCRuntime::pickChunk(AutoLockGCBgAlloc& lock) + } + + BackgroundAllocTask::BackgroundAllocTask(JSRuntime* rt, ChunkPool& pool) +- : GCParallelTask(rt), ++ : GCParallelTaskHelper(rt), + chunkPool_(pool), + enabled_(CanUseExtraThreads() && GetCPUCount() >= 2) + { +diff --git js/src/gc/GCRuntime.h js/src/gc/GCRuntime.h +index 63d202a0eda1b..32c77d9167de2 100644 +--- js/src/gc/GCRuntime.h ++++ js/src/gc/GCRuntime.h +@@ -106,7 +106,7 @@ class ChunkPool + + // Performs extra allocation off thread so that when memory is required on the + // active thread it will already be available and waiting. +-class BackgroundAllocTask : public GCParallelTask ++class BackgroundAllocTask : public GCParallelTaskHelper<BackgroundAllocTask> + { + // Guarded by the GC lock. + GCLockData<ChunkPool&> chunkPool_; +@@ -117,21 +117,19 @@ class BackgroundAllocTask : public GCParallelTask + BackgroundAllocTask(JSRuntime* rt, ChunkPool& pool); + bool enabled() const { return enabled_; } + +- protected: +- void run() override; ++ void run(); + }; + + // Search the provided Chunks for free arenas and decommit them. +-class BackgroundDecommitTask : public GCParallelTask ++class BackgroundDecommitTask : public GCParallelTaskHelper<BackgroundDecommitTask> + { + public: + using ChunkVector = mozilla::Vector<Chunk*>; + +- explicit BackgroundDecommitTask(JSRuntime *rt) : GCParallelTask(rt) {} ++ explicit BackgroundDecommitTask(JSRuntime *rt) : GCParallelTaskHelper(rt) {} + void setChunksToScan(ChunkVector &chunks); + +- protected: +- void run() override; ++ void run(); + + private: + MainThreadOrGCTaskData<ChunkVector> toDecommit; +@@ -492,8 +490,10 @@ class GCRuntime + /* + * Concurrent sweep infrastructure. + */ +- void startTask(GCParallelTask& task, gcstats::PhaseKind phase, AutoLockHelperThreadState& locked); +- void joinTask(GCParallelTask& task, gcstats::PhaseKind phase, AutoLockHelperThreadState& locked); ++ void startTask(GCParallelTask& task, gcstats::PhaseKind phase, ++ AutoLockHelperThreadState& locked); ++ void joinTask(GCParallelTask& task, gcstats::PhaseKind phase, ++ AutoLockHelperThreadState& locked); + + void mergeCompartments(JSCompartment* source, JSCompartment* target); + +diff --git js/src/jsgc.cpp js/src/jsgc.cpp +index 2f552a14b5582..482c6bdbaecb3 100644 +--- js/src/jsgc.cpp ++++ js/src/jsgc.cpp +@@ -2307,7 +2307,7 @@ ArenasToUpdate::getArenasToUpdate(AutoLockHelperThreadState& lock, unsigned maxL + return { begin, last->next }; + } + +-struct UpdatePointersTask : public GCParallelTask ++struct UpdatePointersTask : public GCParallelTaskHelper<UpdatePointersTask> + { + // Maximum number of arenas to update in one block. + #ifdef DEBUG +@@ -2317,19 +2317,18 @@ struct UpdatePointersTask : public GCParallelTask + #endif + + UpdatePointersTask(JSRuntime* rt, ArenasToUpdate* source, AutoLockHelperThreadState& lock) +- : GCParallelTask(rt), source_(source) ++ : GCParallelTaskHelper(rt), source_(source) + { + arenas_.begin = nullptr; + arenas_.end = nullptr; + } + +- ~UpdatePointersTask() override { join(); } ++ void run(); + + private: + ArenasToUpdate* source_; + ArenaListSegment arenas_; + +- virtual void run() override; + bool getArenasToUpdate(); + void updateArenas(); + }; +@@ -3618,17 +3617,13 @@ ArenaLists::checkEmptyArenaList(AllocKind kind) + + class MOZ_RAII js::gc::AutoRunParallelTask : public GCParallelTask + { +- using Func = void (*)(JSRuntime*); +- +- Func func_; + gcstats::PhaseKind phase_; + AutoLockHelperThreadState& lock_; + + public: +- AutoRunParallelTask(JSRuntime* rt, Func func, gcstats::PhaseKind phase, ++ AutoRunParallelTask(JSRuntime* rt, TaskFunc func, gcstats::PhaseKind phase, + AutoLockHelperThreadState& lock) +- : GCParallelTask(rt), +- func_(func), ++ : GCParallelTask(rt, func), + phase_(phase), + lock_(lock) + { +@@ -3638,10 +3633,6 @@ class MOZ_RAII js::gc::AutoRunParallelTask : public GCParallelTask + ~AutoRunParallelTask() { + runtime()->gc.joinTask(*this, phase_, lock_); + } +- +- void run() override { +- func_(runtime()); +- } + }; + + void +@@ -3946,8 +3937,9 @@ PurgeShapeTablesForShrinkingGC(JSRuntime* rt) + } + + static void +-UnmarkCollectedZones(JSRuntime* rt) ++UnmarkCollectedZones(GCParallelTask* task) + { ++ JSRuntime* rt = task->runtime(); + for (GCZonesIter zone(rt); !zone.done(); zone.next()) { + /* Unmark everything in the zones being collected. */ + zone->arenas.unmarkAll(); +@@ -3960,9 +3952,9 @@ UnmarkCollectedZones(JSRuntime* rt) + } + + static void +-BufferGrayRoots(JSRuntime* rt) ++BufferGrayRoots(GCParallelTask* task) + { +- rt->gc.bufferGrayRoots(); ++ task->runtime()->gc.bufferGrayRoots(); + } + + bool +@@ -4976,7 +4968,7 @@ GCRuntime::endMarkingSweepGroup() + } + + // Causes the given WeakCache to be swept when run. +-class ImmediateSweepWeakCacheTask : public GCParallelTask ++class ImmediateSweepWeakCacheTask : public GCParallelTaskHelper<ImmediateSweepWeakCacheTask> + { + JS::detail::WeakCacheBase& cache; + +@@ -4984,21 +4976,23 @@ class ImmediateSweepWeakCacheTask : public GCParallelTask + + public: + ImmediateSweepWeakCacheTask(JSRuntime* rt, JS::detail::WeakCacheBase& wc) +- : GCParallelTask(rt), cache(wc) ++ : GCParallelTaskHelper(rt), cache(wc) + {} + + ImmediateSweepWeakCacheTask(ImmediateSweepWeakCacheTask&& other) +- : GCParallelTask(Move(other)), cache(other.cache) ++ : GCParallelTaskHelper(Move(other)), cache(other.cache) + {} + +- void run() override { ++ void run() { + cache.sweep(); + } + }; + + static void +-UpdateAtomsBitmap(JSRuntime* runtime) ++UpdateAtomsBitmap(GCParallelTask* task) + { ++ JSRuntime* runtime = task->runtime(); ++ + DenseBitmap marked; + if (runtime->gc.atomMarking.computeBitmapFromChunkMarkBits(runtime, marked)) { + for (GCZonesIter zone(runtime); !zone.done(); zone.next()) +@@ -5019,15 +5013,17 @@ UpdateAtomsBitmap(JSRuntime* runtime) + } + + static void +-SweepCCWrappers(JSRuntime* runtime) ++SweepCCWrappers(GCParallelTask* task) + { ++ JSRuntime* runtime = task->runtime(); + for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) + c->sweepCrossCompartmentWrappers(); + } + + static void +-SweepObjectGroups(JSRuntime* runtime) ++SweepObjectGroups(GCParallelTask* task) + { ++ JSRuntime* runtime = task->runtime(); + for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) + c->objectGroups.sweep(runtime->defaultFreeOp()); + } +@@ -5040,8 +5036,9 @@ SweepRegExps(JSRuntime* runtime) + } + + static void +-SweepMisc(JSRuntime* runtime) ++SweepMisc(GCParallelTask* task) + { ++ JSRuntime* runtime = task->runtime(); + for (GCCompartmentGroupIter c(runtime); !c.done(); c.next()) { + c->sweepGlobalObject(); + c->sweepTemplateObjects(); +@@ -5054,17 +5051,19 @@ SweepMisc(JSRuntime* runtime) + } + + static void +-SweepCompressionTasks(JSRuntime* runtime) ++SweepCompressionTasks(GCParallelTask* task) + { ++ JSRuntime* runtime = task->runtime(); ++ + AutoLockHelperThreadState lock; + + // Attach finished compression tasks. + auto& finished = HelperThreadState().compressionFinishedList(lock); + for (size_t i = 0; i < finished.length(); i++) { + if (finished[i]->runtimeMatches(runtime)) { +- UniquePtr<SourceCompressionTask> task(Move(finished[i])); ++ UniquePtr<SourceCompressionTask> compressionTask(Move(finished[i])); + HelperThreadState().remove(finished, &i); +- task->complete(); ++ compressionTask->complete(); + } + } + +@@ -5077,8 +5076,9 @@ SweepCompressionTasks(JSRuntime* runtime) + } + + static void +-SweepWeakMaps(JSRuntime* runtime) ++SweepWeakMaps(GCParallelTask* task) + { ++ JSRuntime* runtime = task->runtime(); + for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next()) { + /* Clear all weakrefs that point to unmarked things. */ + for (auto edge : zone->gcWeakRefs()) { +@@ -5098,15 +5098,16 @@ SweepWeakMaps(JSRuntime* runtime) + } + + static void +-SweepUniqueIds(JSRuntime* runtime) ++SweepUniqueIds(GCParallelTask* task) + { + FreeOp fop(nullptr); +- for (GCSweepGroupIter zone(runtime); !zone.done(); zone.next()) ++ for (GCSweepGroupIter zone(task->runtime()); !zone.done(); zone.next()) + zone->sweepUniqueIds(&fop); + } + + void +-GCRuntime::startTask(GCParallelTask& task, gcstats::PhaseKind phase, AutoLockHelperThreadState& locked) ++GCRuntime::startTask(GCParallelTask& task, gcstats::PhaseKind phase, ++ AutoLockHelperThreadState& locked) + { + if (!task.startWithLockHeld(locked)) { + AutoUnlockHelperThreadState unlock(locked); +@@ -5116,7 +5117,8 @@ GCRuntime::startTask(GCParallelTask& task, gcstats::PhaseKind phase, AutoLockHel + } + + void +-GCRuntime::joinTask(GCParallelTask& task, gcstats::PhaseKind phase, AutoLockHelperThreadState& locked) ++GCRuntime::joinTask(GCParallelTask& task, gcstats::PhaseKind phase, ++ AutoLockHelperThreadState& locked) + { + { + gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::JOIN_PARALLEL_TASKS); +@@ -5681,7 +5683,7 @@ class js::gc::WeakCacheSweepIterator + } + }; + +-class IncrementalSweepWeakCacheTask : public GCParallelTask ++class IncrementalSweepWeakCacheTask : public GCParallelTaskHelper<IncrementalSweepWeakCacheTask> + { + WeakCacheSweepIterator& work_; + SliceBudget& budget_; +@@ -5691,7 +5693,7 @@ class IncrementalSweepWeakCacheTask : public GCParallelTask + public: + IncrementalSweepWeakCacheTask(JSRuntime* rt, WeakCacheSweepIterator& work, SliceBudget& budget, + AutoLockHelperThreadState& lock) +- : GCParallelTask(rt), work_(work), budget_(budget), lock_(lock), ++ : GCParallelTaskHelper(rt), work_(work), budget_(budget), lock_(lock), + cache_(work.next(lock)) + { + MOZ_ASSERT(cache_); +@@ -5702,8 +5704,7 @@ class IncrementalSweepWeakCacheTask : public GCParallelTask + runtime()->gc.joinTask(*this, gcstats::PhaseKind::SWEEP_WEAK_CACHES, lock_); + } + +- private: +- void run() override { ++ void run() { + do { + MOZ_ASSERT(cache_->needsIncrementalBarrier()); + size_t steps = cache_->sweep(); +diff --git js/src/jsgc.h js/src/jsgc.h +index 68c9205aeb1a6..738b324f592f3 100644 +--- js/src/jsgc.h ++++ js/src/jsgc.h +@@ -12,6 +12,7 @@ + #include "mozilla/Atomics.h" + #include "mozilla/EnumeratedArray.h" + #include "mozilla/MemoryReporting.h" ++#include "mozilla/Move.h" + #include "mozilla/TimeStamp.h" + #include "mozilla/TypeTraits.h" + +@@ -937,11 +938,19 @@ class GCHelperState + }; + + // A generic task used to dispatch work to the helper thread system. +-// Users should derive from GCParallelTask add what data they need and +-// override |run|. ++// Users supply a function pointer to call. ++// ++// Note that we don't use virtual functions here because destructors can write ++// the vtable pointer on entry, which can causes races if synchronization ++// happens there. + class GCParallelTask + { ++ public: ++ using TaskFunc = void (*)(GCParallelTask*); ++ ++ private: + JSRuntime* const runtime_; ++ TaskFunc func_; + + // The state of the parallel computation. + enum TaskState { +@@ -960,12 +969,11 @@ class GCParallelTask + // A flag to signal a request for early completion of the off-thread task. + mozilla::Atomic<bool> cancel_; + +- virtual void run() = 0; +- + public: +- explicit GCParallelTask(JSRuntime* runtime) : runtime_(runtime), state(NotStarted), duration_(nullptr) {} ++ explicit GCParallelTask(JSRuntime* runtime, TaskFunc func) : runtime_(runtime), func_(func), state(NotStarted), duration_(nullptr) {} + GCParallelTask(GCParallelTask&& other) + : runtime_(other.runtime_), ++ func_(other.func_), + state(other.state), + duration_(nullptr), + cancel_(false) +@@ -973,7 +981,7 @@ class GCParallelTask + + // Derived classes must override this to ensure that join() gets called + // before members get destructed. +- virtual ~GCParallelTask(); ++ ~GCParallelTask(); + + JSRuntime* runtime() { return runtime_; } + +@@ -1004,12 +1012,34 @@ class GCParallelTask + bool isRunningWithLockHeld(const AutoLockHelperThreadState& locked) const; + bool isRunning() const; + ++ void runTask() { ++ func_(this); ++ } ++ + // This should be friended to HelperThread, but cannot be because it + // would introduce several circular dependencies. + public: + void runFromHelperThread(AutoLockHelperThreadState& locked); + }; + ++// CRTP template to handle cast to derived type when calling run(). ++template <typename Derived> ++class GCParallelTaskHelper : public GCParallelTask ++{ ++ public: ++ explicit GCParallelTaskHelper(JSRuntime* runtime) ++ : GCParallelTask(runtime, &runTaskTyped) ++ {} ++ GCParallelTaskHelper(GCParallelTaskHelper&& other) ++ : GCParallelTask(mozilla::Move(other)) ++ {} ++ ++ private: ++ static void runTaskTyped(GCParallelTask* task) { ++ static_cast<Derived*>(task)->run(); ++ } ++}; ++ + typedef void (*IterateChunkCallback)(JSRuntime* rt, void* data, gc::Chunk* chunk); + typedef void (*IterateZoneCallback)(JSRuntime* rt, void* data, JS::Zone* zone); + typedef void (*IterateArenaCallback)(JSRuntime* rt, void* data, gc::Arena* arena, +diff --git js/src/gc/Nursery.cpp js/src/gc/Nursery.cpp +index f7aa9ffd0ae2e..218124069c2f6 100644 +--- js/src/gc/Nursery.cpp ++++ js/src/gc/Nursery.cpp +@@ -43,19 +43,21 @@ using mozilla::TimeStamp; + + constexpr uintptr_t CanaryMagicValue = 0xDEADB15D; + +-struct js::Nursery::FreeMallocedBuffersTask : public GCParallelTask ++struct js::Nursery::FreeMallocedBuffersTask : public GCParallelTaskHelper<FreeMallocedBuffersTask> + { +- explicit FreeMallocedBuffersTask(FreeOp* fop) : GCParallelTask(fop->runtime()), fop_(fop) {} ++ explicit FreeMallocedBuffersTask(FreeOp* fop) ++ : GCParallelTaskHelper(fop->runtime()), ++ fop_(fop) {} + bool init() { return buffers_.init(); } + void transferBuffersToFree(MallocedBuffersSet& buffersToFree, + const AutoLockHelperThreadState& lock); +- ~FreeMallocedBuffersTask() override { join(); } ++ ~FreeMallocedBuffersTask() { join(); } ++ ++ void run(); + + private: + FreeOp* fop_; + MallocedBuffersSet buffers_; +- +- virtual void run() override; + }; + + #ifdef JS_GC_ZEAL +diff --git js/src/gc/Statistics.h js/src/gc/Statistics.h +index 7775e3e71e394..9db8427ff790a 100644 +--- js/src/gc/Statistics.h ++++ js/src/gc/Statistics.h +@@ -25,9 +25,6 @@ + #include "vm/JSONPrinter.h" + + namespace js { +- +-class GCParallelTask; +- + namespace gcstats { + + // Phase data is generated by a script. If you need to add phases, edit +diff --git js/src/vm/HelperThreads.cpp js/src/vm/HelperThreads.cpp +index 2263b53808935..b9cd88d63a988 100644 +--- js/src/vm/HelperThreads.cpp ++++ js/src/vm/HelperThreads.cpp +@@ -1521,7 +1521,7 @@ js::GCParallelTask::runFromMainThread(JSRuntime* rt) + assertNotStarted(); + MOZ_ASSERT(js::CurrentThreadCanAccessRuntime(rt)); + TimeStamp timeStart = TimeStamp::Now(); +- run(); ++ runTask(); + duration_ = TimeSince(timeStart); + } + +@@ -1537,7 +1537,7 @@ js::GCParallelTask::runFromHelperThread(AutoLockHelperThreadState& lock) + AutoUnlockHelperThreadState parallelSection(lock); + TimeStamp timeStart = TimeStamp::Now(); + TlsContext.get()->heapState = JS::HeapState::MajorCollecting; +- run(); ++ runTask(); + TlsContext.get()->heapState = JS::HeapState::Idle; + duration_ = TimeSince(timeStart); + } diff --git a/www/waterfox/files/patch-bug1466606 b/www/waterfox/files/patch-bug1466606 new file mode 100644 index 000000000000..86bdbdd5c6d0 --- /dev/null +++ b/www/waterfox/files/patch-bug1466606 @@ -0,0 +1,124 @@ +commit 2314357d5b26 +Author: Jean-Yves Avenard <jyavenard@mozilla.com> +Date: Wed Jun 6 15:14:24 2018 +0200 + + Bug 1466606 - Calculate the current GetSample index when needed. r=bryce, a=RyanVM + + The assumption that when calling GetNextRandomAccessPoint the next GetSample index would always be known was incorrect. It assumed that the call to GetNextRandomAccessPoint would always be preceded by a call to GetSample. + This is not always how the MediaSourceDemuxer called it. + + MozReview-Commit-ID: H1MyPpDEytk + + --HG-- + extra : source : 1bdee3c3ca7cc92b1dd7a6d80cb33c313d2a5e59 +--- + dom/media/mediasource/TrackBuffersManager.cpp | 60 +++++++++++++++++++++------ + dom/media/mediasource/TrackBuffersManager.h | 9 ++++ + 2 files changed, 56 insertions(+), 13 deletions(-) + +diff --git dom/media/mediasource/TrackBuffersManager.cpp dom/media/mediasource/TrackBuffersManager.cpp +index 3de834a1e29aa..12df3d5461ff0 100644 +--- dom/media/mediasource/TrackBuffersManager.cpp ++++ dom/media/mediasource/TrackBuffersManager.cpp +@@ -2362,18 +2362,8 @@ TrackBuffersManager::SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack, + // SkipToNextRandomAccessPoint can only be called if aTimeThreadshold is known + // to be buffered. + +- // So first determine the current position in the track buffer if necessary. +- if (trackData.mNextGetSampleIndex.isNothing()) { +- if (trackData.mNextSampleTimecode == TimeUnit()) { +- // First demux, get first sample. +- trackData.mNextGetSampleIndex = Some(0u); +- } else { +- int32_t pos = FindCurrentPosition(aTrack, aFuzz); +- if (pos < 0) { +- return 0; +- } +- trackData.mNextGetSampleIndex = Some(uint32_t(pos)); +- } ++ if (NS_FAILED(SetNextGetSampleIndexIfNeeded(aTrack, aFuzz))) { ++ return 0; + } + + TimeUnit nextSampleTimecode = trackData.mNextSampleTimecode; +@@ -2639,8 +2629,13 @@ TrackBuffersManager::GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, + const TimeUnit& aFuzz) + { + MOZ_ASSERT(OnTaskQueue()); ++ ++ // So first determine the current position in the track buffer if necessary. ++ if (NS_FAILED(SetNextGetSampleIndexIfNeeded(aTrack, aFuzz))) { ++ return TimeUnit::FromInfinity(); ++ } ++ + auto& trackData = GetTracksData(aTrack); +- MOZ_ASSERT(trackData.mNextGetSampleIndex.isSome()); + const TrackBuffersManager::TrackBuffer& track = GetTrackBuffer(aTrack); + + uint32_t i = trackData.mNextGetSampleIndex.ref(); +@@ -2662,6 +2657,45 @@ TrackBuffersManager::GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, + return TimeUnit::FromInfinity(); + } + ++nsresult ++TrackBuffersManager::SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack, ++ const TimeUnit& aFuzz) ++{ ++ auto& trackData = GetTracksData(aTrack); ++ const TrackBuffer& track = GetTrackBuffer(aTrack); ++ ++ if (trackData.mNextGetSampleIndex.isSome()) { ++ // We already know the next GetSample index. ++ return NS_OK; ++ } ++ ++ if (!track.Length()) { ++ // There's nothing to find yet. ++ return NS_ERROR_DOM_MEDIA_END_OF_STREAM; ++ } ++ ++ if (trackData.mNextSampleTimecode == TimeUnit()) { ++ // First demux, get first sample. ++ trackData.mNextGetSampleIndex = Some(0u); ++ return NS_OK; ++ } ++ ++ if (trackData.mNextSampleTimecode > ++ track.LastElement()->mTimecode + track.LastElement()->mDuration) { ++ // The next element is past our last sample. We're done. ++ trackData.mNextGetSampleIndex = Some(uint32_t(track.Length())); ++ return NS_ERROR_DOM_MEDIA_END_OF_STREAM; ++ } ++ ++ int32_t pos = FindCurrentPosition(aTrack, aFuzz); ++ if (pos < 0) { ++ // Not found, must wait for more data. ++ return NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA; ++ } ++ trackData.mNextGetSampleIndex = Some(uint32_t(pos)); ++ return NS_OK; ++} ++ + void + TrackBuffersManager::TrackData::AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const + { +diff --git dom/media/mediasource/TrackBuffersManager.h dom/media/mediasource/TrackBuffersManager.h +index 9c7d191fc55cf..f8a47b2eeca58 100644 +--- dom/media/mediasource/TrackBuffersManager.h ++++ dom/media/mediasource/TrackBuffersManager.h +@@ -160,6 +160,15 @@ public: + MediaResult& aResult); + int32_t FindCurrentPosition(TrackInfo::TrackType aTrack, + const media::TimeUnit& aFuzz) const; ++ ++ // Will set the next GetSample index if needed. This information is determined ++ // through the value of mNextSampleTimecode. Return false if the index ++ // couldn't be determined or if there's nothing more that could be demuxed. ++ // This occurs if either the track buffer doesn't contain the required ++ // timecode or is empty. ++ nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack, ++ const media::TimeUnit& aFuzz); ++ + media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, + const media::TimeUnit& aFuzz); + diff --git a/www/waterfox/files/patch-bug1466863 b/www/waterfox/files/patch-bug1466863 new file mode 100644 index 000000000000..96eba510c515 --- /dev/null +++ b/www/waterfox/files/patch-bug1466863 @@ -0,0 +1,36 @@ +commit 99e541f257fd +Author: Michael Kaply <mozilla@kaply.com> +Date: Wed Jun 6 15:58:24 2018 -0500 + + Bug 1466863 - Just use empty metadata if invalid. r=florian, a=RyanVM + + MozReview-Commit-ID: 30Q5Sdi5ZRt + + --HG-- + extra : source : 5404016c6d164a29c8dccdce58363d5b893af565 +--- + toolkit/components/search/nsSearchService.js | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git toolkit/components/search/nsSearchService.js toolkit/components/search/nsSearchService.js +index 86a286819f02b..6af0f3e64f39a 100644 +--- toolkit/components/search/nsSearchService.js ++++ toolkit/components/search/nsSearchService.js +@@ -2074,7 +2074,7 @@ Engine.prototype = { + }, + + getAttr(name) { +- return (this._metaData && this._metaData[name]) || undefined; ++ return this._metaData[name] || undefined; + }, + + // nsISearchEngine +@@ -3191,7 +3191,7 @@ SearchService.prototype = { + let name = engine._name; + if (name in this._engines) { + LOG("_loadEnginesMetadataFromCache, transfering metadata for " + name); +- this._engines[name]._metaData = engine._metaData; ++ this._engines[name]._metaData = engine._metaData || {}; + } + } + }, diff --git a/www/waterfox/files/patch-bug1467882 b/www/waterfox/files/patch-bug1467882 new file mode 100644 index 000000000000..3047e0c9c068 --- /dev/null +++ b/www/waterfox/files/patch-bug1467882 @@ -0,0 +1,74 @@ +--- media/libcubeb/src/cubeb_sndio.c.orig 2018-06-29 17:19:53 UTC ++++ media/libcubeb/src/cubeb_sndio.c +@@ -49,17 +49,33 @@ struct cubeb_stream { + cubeb_data_callback data_cb; /* cb to preapare data */ + cubeb_state_callback state_cb; /* cb to notify about state changes */ + void *arg; /* user arg to {data,state}_cb */ ++ float volume; /* current volume */ + }; + + static void +-float_to_s16(void *ptr, long nsamp) ++s16_setvol(void *ptr, long nsamp, float volume) ++{ ++ int16_t *dst = ptr; ++ int32_t mult = volume * 32768; ++ int32_t s; ++ ++ while (nsamp-- > 0) { ++ s = *dst; ++ s = (s * mult) >> 15; ++ *(dst++) = s; ++ } ++} ++ ++static void ++float_to_s16(void *ptr, long nsamp, float volume) + { + int16_t *dst = ptr; + float *src = ptr; ++ float mult = volume * 32768; + int s; + + while (nsamp-- > 0) { +- s = lrintf(*(src++) * 32768); ++ s = lrintf(*(src++) * mult); + if (s < -32768) + s = -32768; + else if (s > 32767) +@@ -167,8 +183,12 @@ sndio_mainloop(void *arg) + if (prime > 0) + prime--; + +- if ((s->mode & SIO_PLAY) && s->conv) +- float_to_s16(s->pbuf, nfr * s->pchan); ++ if (s->mode & SIO_PLAY) { ++ if (s->conv) ++ float_to_s16(s->pbuf, nfr * s->pchan, s->volume); ++ else ++ s16_setvol(s->pbuf, nfr * s->pchan, s->volume); ++ } + + if (s->mode & SIO_REC) + rstart = 0; +@@ -362,6 +382,7 @@ sndio_stream_init(cubeb * context, + if (s->rbuf == NULL) + goto err; + } ++ s->volume = 1.; + *stream = s; + DPR("sndio_stream_init() end, ok\n"); + (void)context; +@@ -466,7 +487,11 @@ sndio_stream_set_volume(cubeb_stream *s, float volume) + { + DPR("sndio_stream_set_volume(%f)\n", volume); + pthread_mutex_lock(&s->mtx); +- sio_setvol(s->hdl, SIO_MAXVOL * volume); ++ if (volume < 0.) ++ volume = 0.; ++ else if (volume > 1.0) ++ volume = 1.; ++ s->volume = volume; + pthread_mutex_unlock(&s->mtx); + return CUBEB_OK; + } diff --git a/www/waterfox/files/patch-bug1467938 b/www/waterfox/files/patch-bug1467938 new file mode 100644 index 000000000000..468cb744cedb --- /dev/null +++ b/www/waterfox/files/patch-bug1467938 @@ -0,0 +1,43 @@ +commit e390e1f2e6b3 +Author: Nils Ohlmeier [:drno] <drno@ohlmeier.org> +Date: Fri Jun 8 19:49:40 2018 -0700 + + Bug 1467938 - Fix out-of-bounds memory access in WebRTC VP9 Missing Frame Processing. r=ng, a=RyanVM + + --HG-- + extra : source : 44ae071a453f285f841d4c3cc13e0b21427ace92 +--- + .../modules/video_coding/rtp_frame_reference_finder.cc | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git media/webrtc/trunk/webrtc/modules/video_coding/rtp_frame_reference_finder.cc media/webrtc/trunk/webrtc/modules/video_coding/rtp_frame_reference_finder.cc +index 3d5283378fb57..c7b893cdd4565 100644 +--- media/webrtc/trunk/webrtc/modules/video_coding/rtp_frame_reference_finder.cc ++++ media/webrtc/trunk/webrtc/modules/video_coding/rtp_frame_reference_finder.cc +@@ -434,8 +434,11 @@ void RtpFrameReferenceFinder::ManageFrameVp9( + LOG(LS_WARNING) << "Received keyframe without scalability structure"; + + frame->num_references = 0; +- GofInfo info = gof_info_.find(codec_header.tl0_pic_idx)->second; +- FrameReceivedVp9(frame->picture_id, &info); ++ auto gof_info_it = gof_info_.find(codec_header.tl0_pic_idx); ++ if (gof_info_it == gof_info_.end()) ++ return; ++ ++ FrameReceivedVp9(frame->picture_id, &gof_info_it->second); + CompletedFrameVp9(std::move(frame)); + return; + } +@@ -508,6 +511,12 @@ bool RtpFrameReferenceFinder::MissingRequiredFrameVp9(uint16_t picture_id, + size_t gof_idx = diff % info.gof->num_frames_in_gof; + size_t temporal_idx = info.gof->temporal_idx[gof_idx]; + ++ if (temporal_idx >= kMaxTemporalLayers) { ++ LOG(LS_WARNING) << "At most " << kMaxTemporalLayers << " temporal " ++ << "layers are supported."; ++ return true; ++ } ++ + // For every reference this frame has, check if there is a frame missing in + // the interval (|ref_pid|, |picture_id|) in any of the lower temporal + // layers. If so, we are missing a required frame. diff --git a/www/waterfox/files/patch-bug1469257 b/www/waterfox/files/patch-bug1469257 new file mode 100644 index 000000000000..a99461eef667 --- /dev/null +++ b/www/waterfox/files/patch-bug1469257 @@ -0,0 +1,50 @@ +commit 6717d9afef42 +Author: Jean-Yves Avenard <jyavenard@mozilla.com> +Date: Wed Jun 20 19:24:34 2018 +0000 + + Bug 1469257 - [H264] Only check for SPS changes on keyframe. r=bryce, a=RyanVM + + Some invalid streams contain SPS changes and those appear to only occur on non-keyframe, this cause all frames to be dropped until the next keyframe is found. This result in apparent freezes. + + While it is theoretically possible to have SPS changes inband on non-keyframe those should be very rare (I've never seen one). The content would have been invalid anyway in an non-fragmented mp4. + + So we now only check for a SPS change on keyframe. This would cause no affect on either windows, android or ffmpeg as those decoders handle format change fine. The mac decoder could however show garbled frames temporarily. + + Differential Revision: https://phabricator.services.mozilla.com/D1733 + + --HG-- + extra : source : ddde6ad6d9e6c4069632e195613bcd53a39883e4 +--- + dom/media/platforms/wrappers/H264Converter.cpp | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git dom/media/platforms/wrappers/H264Converter.cpp dom/media/platforms/wrappers/H264Converter.cpp +index 32b1abf179937..5c04c075664c3 100644 +--- dom/media/platforms/wrappers/H264Converter.cpp ++++ dom/media/platforms/wrappers/H264Converter.cpp +@@ -392,7 +392,7 @@ MediaResult + H264Converter::CheckForSPSChange(MediaRawData* aSample) + { + RefPtr<MediaByteBuffer> extra_data = +- mp4_demuxer::H264::ExtractExtraData(aSample); ++ aSample->mKeyframe ? mp4_demuxer::H264::ExtractExtraData(aSample) : nullptr; + if (!mp4_demuxer::H264::HasSPS(extra_data)) { + MOZ_ASSERT(mCanRecycleDecoder.isSome()); + if (!*mCanRecycleDecoder) { +@@ -406,14 +406,12 @@ H264Converter::CheckForSPSChange(MediaRawData* aSample) + // This scenario can only occur on Android with devices that can recycle a + // decoder. + if (!mp4_demuxer::H264::HasSPS(aSample->mExtraData) || +- mp4_demuxer::H264::CompareExtraData(aSample->mExtraData, +- mOriginalExtraData)) { ++ mp4_demuxer::H264::CompareExtraData(aSample->mExtraData, mOriginalExtraData)) { + return NS_OK; + } + extra_data = mOriginalExtraData = aSample->mExtraData; + } +- if (mp4_demuxer::H264::CompareExtraData(extra_data, +- mCurrentConfig.mExtraData)) { ++ if (mp4_demuxer::H264::CompareExtraData(extra_data, mCurrentConfig.mExtraData)) { + return NS_OK; + } + diff --git a/www/waterfox/files/patch-bug1469879 b/www/waterfox/files/patch-bug1469879 new file mode 100644 index 000000000000..f47953ff129c --- /dev/null +++ b/www/waterfox/files/patch-bug1469879 @@ -0,0 +1,44 @@ +commit 9d9ab00e672b +Author: Kyle Machulis <kyle@nonpolynomial.com> +Date: Mon Jun 25 16:59:08 2018 -0700 + + Bug 1469879 - Add check for closed socket on Multicast IPC parent funcs. r=baku, a=lizzard + + MozReview-Commit-ID: CaNYPtgFz87 + + --HG-- + extra : source : ca98b6f47b4e33673291a4dc2a4ebca28ce6db00 +--- + dom/network/UDPSocketParent.cpp | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git dom/network/UDPSocketParent.cpp dom/network/UDPSocketParent.cpp +index 5198c4be50c06..174d1e87b13e1 100644 +--- dom/network/UDPSocketParent.cpp ++++ dom/network/UDPSocketParent.cpp +@@ -450,6 +450,12 @@ mozilla::ipc::IPCResult + UDPSocketParent::RecvJoinMulticast(const nsCString& aMulticastAddress, + const nsCString& aInterface) + { ++ if (!mSocket) { ++ NS_WARNING("multicast socket is closed"); ++ FireInternalError(__LINE__); ++ return IPC_OK(); ++ } ++ + nsresult rv = mSocket->JoinMulticast(aMulticastAddress, aInterface); + + if (NS_WARN_IF(NS_FAILED(rv))) { +@@ -463,6 +469,12 @@ mozilla::ipc::IPCResult + UDPSocketParent::RecvLeaveMulticast(const nsCString& aMulticastAddress, + const nsCString& aInterface) + { ++ if (!mSocket) { ++ NS_WARNING("multicast socket is closed"); ++ FireInternalError(__LINE__); ++ return IPC_OK(); ++ } ++ + nsresult rv = mSocket->LeaveMulticast(aMulticastAddress, aInterface); + + if (NS_WARN_IF(NS_FAILED(rv))) { diff --git a/www/waterfox/files/patch-bug1473041 b/www/waterfox/files/patch-bug1473041 new file mode 100644 index 000000000000..ac9ab31ba0a0 --- /dev/null +++ b/www/waterfox/files/patch-bug1473041 @@ -0,0 +1,30 @@ +commit 9bfdb471cdb0 +Author: Lee Salzman <lsalzman@mozilla.com> +Date: Thu Jul 12 14:19:07 2018 -0400 + + Bug 1473041 - save and restore PermitSubpixelAA state for basic layer paint callback. r=mstange a=lizzard + + --HG-- + extra : source : e6698ef51a7e2f049350b09d67fa7338d2bd405a +--- + gfx/layers/basic/BasicPaintedLayer.cpp | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git gfx/layers/basic/BasicPaintedLayer.cpp gfx/layers/basic/BasicPaintedLayer.cpp +index 7fae4e2e78a67..431a328da95ed 100644 +--- gfx/layers/basic/BasicPaintedLayer.cpp ++++ gfx/layers/basic/BasicPaintedLayer.cpp +@@ -90,9 +90,12 @@ BasicPaintedLayer::PaintThebes(gfxContext* aContext, + context = aContext; + } + if (context) { +- SetAntialiasingFlags(this, context->GetDrawTarget()); ++ DrawTarget* target = context->GetDrawTarget(); ++ bool oldAA = target->GetPermitSubpixelAA(); ++ SetAntialiasingFlags(this, target); + aCallback(this, context, toDraw, toDraw, DrawRegionClip::NONE, + nsIntRegion(), aCallbackData); ++ target->SetPermitSubpixelAA(oldAA); + } + if (needsGroup && availableGroup) { + BasicManager()->PopGroupForLayer(group); diff --git a/www/waterfox/files/patch-bug702179 b/www/waterfox/files/patch-bug702179 new file mode 100644 index 000000000000..0c998526736e --- /dev/null +++ b/www/waterfox/files/patch-bug702179 @@ -0,0 +1,12 @@ +Don't build static JS lib to make sure DTrace probes are picked up. + +--- js/src/build/moz.build.orig 2017-04-16 18:00:50 UTC ++++ js/src/build/moz.build +@@ -71,7 +71,3 @@ if CONFIG['OS_ARCH'] == 'SunOS': + ] + + OS_LIBS += CONFIG['REALTIME_LIBS'] +- +-NO_EXPAND_LIBS = True +- +-DIST_INSTALL = True diff --git a/www/waterfox/files/patch-bug712130 b/www/waterfox/files/patch-bug712130 new file mode 100644 index 000000000000..aaa845735f45 --- /dev/null +++ b/www/waterfox/files/patch-bug712130 @@ -0,0 +1,481 @@ +commit a5892fdff0c9 +Author: decltype <mozilla@decltype.org> +Date: Wed Jan 10 00:40:13 2018 +0100 + + Bug 712130 - Add reftest to ensure the first autofocus elements gets picked. r=bz + + MozReview-Commit-ID: 6UAUbqwVhTm + + --HG-- + extra : rebase_source : 7ade8a42489bbf0be97894c18a38bd765a1da891 +--- + layout/reftests/bugs/712130-1-ref.html | 5 +++++ + layout/reftests/bugs/712130-1.html | 5 +++++ + layout/reftests/bugs/reftest.list | 1 + + 3 files changed, 11 insertions(+) + +diff --git layout/reftests/bugs/712130-1-ref.html layout/reftests/bugs/712130-1-ref.html +new file mode 100644 +index 000000000000..6d07ca048250 +--- /dev/null ++++ layout/reftests/bugs/712130-1-ref.html +@@ -0,0 +1,5 @@ ++<!DOCTYPE html> ++<html class="reftest-wait"> ++<link rel="stylesheet" href="nothing"><!-- Empty stylesheet to delay PresShell init --> ++<input type="text" autofocus="" onfocus="document.documentElement.removeAttribute('class')"> ++<input type="text"> +diff --git layout/reftests/bugs/712130-1.html layout/reftests/bugs/712130-1.html +new file mode 100644 +index 000000000000..ffbc82309366 +--- /dev/null ++++ layout/reftests/bugs/712130-1.html +@@ -0,0 +1,5 @@ ++<!DOCTYPE html> ++<html class="reftest-wait"> ++<link rel="stylesheet" href="nothing"><!-- Empty stylesheet to delay PresShell init --> ++<input type="text" autofocus="" onfocus="document.documentElement.removeAttribute('class')"> ++<input type="text" autofocus="" onfocus="document.documentElement.removeAttribute('class')"> +diff --git layout/reftests/bugs/reftest.list layout/reftests/bugs/reftest.list +index 764d3dbd5b3c..79e5df14fcff 100644 +--- layout/reftests/bugs/reftest.list ++++ layout/reftests/bugs/reftest.list +@@ -1707,6 +1707,7 @@ needs-focus == 703186-1.html 703186-1-ref.html + needs-focus == 703186-2.html 703186-2-ref.html + needs-focus != 703186-1.html 703186-2.html + == 711359-1.html 711359-1-ref.html ++fuzzy-if(skiaContent,1,3) needs-focus == 712130-1.html 712130-1-ref.html + == 712849-1.html 712849-1-ref.html + == 713856-static.html 713856-ref.html + == 713856-dynamic.html 713856-ref.html + +commit 5269d4159ca0 +Author: decltype <mozilla@decltype.org> +Date: Wed Jan 10 19:07:21 2018 +0100 + + Bug 712130 - Add reftest in case autofocus element is seen after PresShell init. r=bz + + MozReview-Commit-ID: 75IKOqiqBhL + + --HG-- + extra : rebase_source : ec679c6f6b6c48aa88dd6c5fa6b6970e6cfa1314 +--- + layout/reftests/bugs/712130-2-ref.html | 3 +++ + layout/reftests/bugs/712130-2.html | 4 ++++ + layout/reftests/bugs/reftest.list | 1 + + 3 files changed, 8 insertions(+) + +diff --git layout/reftests/bugs/712130-2-ref.html layout/reftests/bugs/712130-2-ref.html +new file mode 100644 +index 000000000000..919ac05704ae +--- /dev/null ++++ layout/reftests/bugs/712130-2-ref.html +@@ -0,0 +1,3 @@ ++<!DOCTYPE html> ++<html class="reftest-wait"> ++<input type="text" autofocus="" onfocus="document.documentElement.removeAttribute('class')"> +diff --git layout/reftests/bugs/712130-2.html layout/reftests/bugs/712130-2.html +new file mode 100644 +index 000000000000..232bef484917 +--- /dev/null ++++ layout/reftests/bugs/712130-2.html +@@ -0,0 +1,4 @@ ++<!DOCTYPE html> ++<html class="reftest-wait"> ++<link rel="stylesheet" href="nothing"><!-- Empty stylesheet to delay PresShell init --> ++<input type="text" autofocus="" onfocus="document.documentElement.removeAttribute('class')"> +diff --git layout/reftests/bugs/reftest.list layout/reftests/bugs/reftest.list +index 79e5df14fcff..7978c54a5ea2 100644 +--- layout/reftests/bugs/reftest.list ++++ layout/reftests/bugs/reftest.list +@@ -1708,6 +1708,7 @@ needs-focus == 703186-2.html 703186-2-ref.html + needs-focus != 703186-1.html 703186-2.html + == 711359-1.html 711359-1-ref.html + fuzzy-if(skiaContent,1,3) needs-focus == 712130-1.html 712130-1-ref.html ++fuzzy-if(skiaContent,1,3) needs-focus == 712130-2.html 712130-2-ref.html + == 712849-1.html 712849-1-ref.html + == 713856-static.html 713856-ref.html + == 713856-dynamic.html 713856-ref.html + +commit dd080e9ebacf +Author: decltype <mozilla@decltype.org> +Date: Mon Jan 8 22:35:00 2018 +0100 + + Bug 712130 - Defer autofocus until after frame construction. r=bz + + The autofocus attribute on form elements forces layout in CheckIfFocusable. + To avoid unpleasant FOUCs, defer autofocus processing until frames are + constructed in PresShell::Initialize. + + Resolve the race between nsAutoFocusEvent running and page load by checking the + readystate at time of event posting. Skip autofocus if the element moved to a + different window in the meantime. + + MozReview-Commit-ID: 90jiJYJWmRg + + --HG-- + extra : rebase_source : f94b479075df3e37ec1a658d71596c03930bab92 +--- + dom/base/nsDocument.cpp | 128 ++++++++++++++++++++++++++++++++++++++ + dom/base/nsDocument.h | 6 ++ + dom/base/nsFocusManager.cpp | 2 +- + dom/base/nsIDocument.h | 3 + + dom/html/nsGenericHTMLElement.cpp | 64 +------------------ + layout/base/PresShell.cpp | 2 + + 6 files changed, 142 insertions(+), 63 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 4ecc537eb54e..3ed0e93222ec 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -1500,6 +1500,7 @@ nsDocument::nsDocument(const char* aContentType) + #ifdef DEBUG + , mWillReparent(false) + #endif ++ , mAutoFocusFired(false) + { + SetContentTypeInternal(nsDependentCString(aContentType)); + +@@ -9444,6 +9445,133 @@ nsDocument::GetTemplateContentsOwner() + return mTemplateContentsOwner; + } + ++static already_AddRefed<nsPIDOMWindowOuter> ++FindTopWindowForElement(Element* element) ++{ ++ nsIDocument* document = element->OwnerDoc(); ++ if (!document) { ++ return nullptr; ++ } ++ ++ nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow(); ++ if (!window) { ++ return nullptr; ++ } ++ ++ // Trying to find the top window (equivalent to window.top). ++ if (nsCOMPtr<nsPIDOMWindowOuter> top = window->GetTop()) { ++ window = top.forget(); ++ } ++ return window.forget(); ++} ++ ++/** ++ * nsAutoFocusEvent is used to dispatch a focus event for an ++ * nsGenericHTMLFormElement with the autofocus attribute enabled. ++ */ ++class nsAutoFocusEvent : public Runnable ++{ ++public: ++ explicit nsAutoFocusEvent(already_AddRefed<Element>&& aElement, ++ already_AddRefed<nsPIDOMWindowOuter>&& aTopWindow) ++ : mozilla::Runnable("nsAutoFocusEvent") ++ , mElement(aElement) ++ , mTopWindow(aTopWindow) ++ { ++ } ++ ++ NS_IMETHOD Run() override ++ { ++ nsCOMPtr<nsPIDOMWindowOuter> currentTopWindow = ++ FindTopWindowForElement(mElement); ++ if (currentTopWindow != mTopWindow) { ++ // The element's top window changed from when the event was queued. ++ // Don't take away focus from an unrelated window. ++ return NS_OK; ++ } ++ ++ nsFocusManager* fm = nsFocusManager::GetFocusManager(); ++ if (!fm) { ++ return NS_ERROR_NULL_POINTER; ++ } ++ ++ nsIDocument* document = mElement->OwnerDoc(); ++ ++ // Don't steal focus from the user. ++ if (mTopWindow->GetFocusedNode()) { ++ return NS_OK; ++ } ++ ++ // If something is focused in the same document, ignore autofocus. ++ if (!fm->GetFocusedContent() || ++ fm->GetFocusedContent()->OwnerDoc() != document) { ++ mozilla::ErrorResult rv; ++ mElement->Focus(rv); ++ return rv.StealNSResult(); ++ } ++ ++ return NS_OK; ++ } ++private: ++ nsCOMPtr<Element> mElement; ++ nsCOMPtr<nsPIDOMWindowOuter> mTopWindow; ++}; ++ ++void ++nsDocument::SetAutoFocusElement(Element* aAutoFocusElement) ++{ ++ if (mAutoFocusFired) { ++ // Too late. ++ return; ++ } ++ ++ if (mAutoFocusElement) { ++ // The spec disallows multiple autofocus elements, so we consider only the ++ // first one to preserve the old behavior. ++ return; ++ } ++ ++ mAutoFocusElement = do_GetWeakReference(aAutoFocusElement); ++ TriggerAutoFocus(); ++} ++ ++void ++nsDocument::TriggerAutoFocus() ++{ ++ if (mAutoFocusFired) { ++ return; ++ } ++ ++ if (!mPresShell || !mPresShell->DidInitialize()) { ++ // Delay autofocus until frames are constructed so that we don't thrash ++ // style and layout calculations. ++ return; ++ } ++ ++ nsCOMPtr<Element> autoFocusElement = do_QueryReferent(mAutoFocusElement); ++ if (autoFocusElement && autoFocusElement->OwnerDoc() == this) { ++ mAutoFocusFired = true; ++ ++ nsCOMPtr<nsPIDOMWindowOuter> topWindow = ++ FindTopWindowForElement(autoFocusElement); ++ if (!topWindow) { ++ return; ++ } ++ ++ // NOTE: This may be removed in the future since the spec technically ++ // allows autofocus after load. ++ nsCOMPtr<nsIDocument> topDoc = topWindow->GetExtantDoc(); ++ if (topDoc && topDoc->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE) { ++ return; ++ } ++ ++ nsCOMPtr<nsIRunnable> event = ++ new nsAutoFocusEvent(autoFocusElement.forget(), topWindow.forget()); ++ nsresult rv = NS_DispatchToCurrentThread(event.forget()); ++ NS_ENSURE_SUCCESS_VOID(rv); ++ } ++} ++ + void + nsDocument::SetScrollToRef(nsIURI *aDocumentURI) + { +diff --git dom/base/nsDocument.h dom/base/nsDocument.h +index a25c4b417861..d015aae0bc8f 100644 +--- dom/base/nsDocument.h ++++ dom/base/nsDocument.h +@@ -804,6 +804,9 @@ public: + // Only BlockOnload should call this! + void AsyncBlockOnload(); + ++ virtual void SetAutoFocusElement(Element* aAutoFocusElement) override; ++ virtual void TriggerAutoFocus() override; ++ + virtual void SetScrollToRef(nsIURI *aDocumentURI) override; + virtual void ScrollToRef() override; + virtual void ResetScrolledToRefAlready() override; +@@ -1306,6 +1309,8 @@ private: + + RefPtr<nsContentList> mImageMaps; + ++ nsWeakPtr mAutoFocusElement; ++ + nsCString mScrollToRef; + uint8_t mScrolledToRefAlready : 1; + uint8_t mChangeScrollPosWhenScrollingToRef : 1; +@@ -1431,6 +1436,9 @@ private: + public: + bool mWillReparent; + #endif ++ ++private: ++ bool mAutoFocusFired : 1; + }; + + class nsDocumentOnStack +diff --git dom/base/nsFocusManager.cpp dom/base/nsFocusManager.cpp +index dfec30f7da13..a8faa46fff3c 100644 +--- dom/base/nsFocusManager.cpp ++++ dom/base/nsFocusManager.cpp +@@ -1603,7 +1603,7 @@ nsFocusManager::CheckIfFocusable(nsIContent* aContent, uint32_t aFlags) + } + + // Make sure that our frames are up to date while ensuring the presshell is +- // also initialized in case we come from an autofocus event. ++ // also initialized in case we come from a script calling focus() early. + mEventHandlingNeedsFlush = false; + doc->FlushPendingNotifications(FlushType::EnsurePresShellInitAndFrames); + +diff --git dom/base/nsIDocument.h dom/base/nsIDocument.h +index 53ef3746ffc7..98d5b0d2ed15 100644 +--- dom/base/nsIDocument.h ++++ dom/base/nsIDocument.h +@@ -2637,6 +2637,9 @@ public: + + virtual nsISupports* GetCurrentContentSink() = 0; + ++ virtual void SetAutoFocusElement(Element* aAutoFocusElement) = 0; ++ virtual void TriggerAutoFocus() = 0; ++ + virtual void SetScrollToRef(nsIURI *aDocumentURI) = 0; + virtual void ScrollToRef() = 0; + virtual void ResetScrolledToRefAlready() = 0; +diff --git dom/html/nsGenericHTMLElement.cpp dom/html/nsGenericHTMLElement.cpp +index 334c80ace636..775ec887ba2c 100644 +--- dom/html/nsGenericHTMLElement.cpp ++++ dom/html/nsGenericHTMLElement.cpp +@@ -111,64 +111,6 @@ + using namespace mozilla; + using namespace mozilla::dom; + +-/** +- * nsAutoFocusEvent is used to dispatch a focus event when a +- * nsGenericHTMLFormElement is binded to the tree with the autofocus attribute +- * enabled. +- */ +-class nsAutoFocusEvent : public Runnable +-{ +-public: +- explicit nsAutoFocusEvent(nsGenericHTMLFormElement* aElement) +- : mozilla::Runnable("nsAutoFocusEvent") +- , mElement(aElement) +- { +- } +- +- NS_IMETHOD Run() override { +- nsFocusManager* fm = nsFocusManager::GetFocusManager(); +- if (!fm) { +- return NS_ERROR_NULL_POINTER; +- } +- +- nsIDocument* document = mElement->OwnerDoc(); +- +- nsPIDOMWindowOuter* window = document->GetWindow(); +- if (!window) { +- return NS_OK; +- } +- +- // Trying to found the top window (equivalent to window.top). +- if (nsCOMPtr<nsPIDOMWindowOuter> top = window->GetTop()) { +- window = top; +- } +- +- if (window->GetFocusedNode()) { +- return NS_OK; +- } +- +- nsCOMPtr<nsIDocument> topDoc = window->GetExtantDoc(); +- if (topDoc && topDoc->GetReadyStateEnum() == nsIDocument::READYSTATE_COMPLETE) { +- return NS_OK; +- } +- +- // If something is focused in the same document, ignore autofocus. +- if (!fm->GetFocusedContent() || +- fm->GetFocusedContent()->OwnerDoc() != document) { +- mozilla::ErrorResult rv; +- mElement->Focus(rv); +- return rv.StealNSResult(); +- } +- +- return NS_OK; +- } +-private: +- // NOTE: nsGenericHTMLFormElement is saved as a nsGenericHTMLElement +- // because AddRef/Release are ambiguous with nsGenericHTMLFormElement +- // and Focus() is declared (and defined) in nsGenericHTMLElement class. +- RefPtr<nsGenericHTMLElement> mElement; +-}; +- + NS_IMPL_ADDREF_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase) + NS_IMPL_RELEASE_INHERITED(nsGenericHTMLElement, nsGenericHTMLElementBase) + +@@ -1882,10 +1824,8 @@ nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument, + // the document should not be already loaded and the "browser.autofocus" + // preference should be 'true'. + if (IsAutofocusable() && HasAttr(kNameSpaceID_None, nsGkAtoms::autofocus) && +- nsContentUtils::AutoFocusEnabled()) { +- nsCOMPtr<nsIRunnable> event = new nsAutoFocusEvent(this); +- rv = NS_DispatchToCurrentThread(event); +- NS_ENSURE_SUCCESS(rv, rv); ++ nsContentUtils::AutoFocusEnabled() && aDocument) { ++ aDocument->SetAutoFocusElement(this); + } + + // If @form is set, the element *has* to be in a document, otherwise it +diff --git layout/base/PresShell.cpp layout/base/PresShell.cpp +index 0c94f8516271..f851f9c7df2c 100644 +--- layout/base/PresShell.cpp ++++ layout/base/PresShell.cpp +@@ -1817,6 +1817,8 @@ PresShell::Initialize(nscoord aWidth, nscoord aHeight) + NS_ENSURE_STATE(!mHaveShutDown); + } + ++ mDocument->TriggerAutoFocus(); ++ + NS_ASSERTION(rootFrame, "How did that happen?"); + + // Note: when the frame was created above it had the NS_FRAME_IS_DIRTY bit + +commit 0c31aff36b45 +Author: decltype <mozilla@decltype.org> +Date: Fri Jan 12 00:17:58 2018 +0100 + + Bug 712130 - Simplify focus stealing prevention for autofocus. r=bz + + Remove redundant check already implied by earlier condition: If the focus + manager's focused content is in our document, all parent windows including the + root window must have their focused node set to non-null. + + MozReview-Commit-ID: CryGb6mfczK + + --HG-- + extra : rebase_source : ed5c452f68b76a656512026b5d162d8782083c2c +--- + dom/base/nsDocument.cpp | 19 +++---------------- + 1 file changed, 3 insertions(+), 16 deletions(-) + +diff --git dom/base/nsDocument.cpp dom/base/nsDocument.cpp +index 3ed0e93222ec..18b81abe599a 100644 +--- dom/base/nsDocument.cpp ++++ dom/base/nsDocument.cpp +@@ -9490,27 +9490,14 @@ public: + return NS_OK; + } + +- nsFocusManager* fm = nsFocusManager::GetFocusManager(); +- if (!fm) { +- return NS_ERROR_NULL_POINTER; +- } +- +- nsIDocument* document = mElement->OwnerDoc(); +- + // Don't steal focus from the user. + if (mTopWindow->GetFocusedNode()) { + return NS_OK; + } + +- // If something is focused in the same document, ignore autofocus. +- if (!fm->GetFocusedContent() || +- fm->GetFocusedContent()->OwnerDoc() != document) { +- mozilla::ErrorResult rv; +- mElement->Focus(rv); +- return rv.StealNSResult(); +- } +- +- return NS_OK; ++ mozilla::ErrorResult rv; ++ mElement->Focus(rv); ++ return rv.StealNSResult(); + } + private: + nsCOMPtr<Element> mElement; diff --git a/www/waterfox/files/patch-bug730495 b/www/waterfox/files/patch-bug730495 new file mode 100644 index 000000000000..ba1dbc83afde --- /dev/null +++ b/www/waterfox/files/patch-bug730495 @@ -0,0 +1,545 @@ +commit 47d3b3ac0b24 +Author: Kai Engert <kaie@kuix.de> +Date: Fri Sep 29 13:25:06 2017 +0200 + + Bug 730495, guarantee that sqlite3_config is called before any other SQLite function, r=asuth, r=froydnj, r=mak +--- + security/manager/ssl/nsNSSComponent.cpp | 9 -- + storage/TelemetryVFS.cpp | 7 +- + storage/mozStorageConnection.cpp | 8 +- + storage/mozStorageService.cpp | 149 +--------------------------- + toolkit/xre/AutoSQLiteLifetime.cpp | 167 ++++++++++++++++++++++++++++++++ + toolkit/xre/AutoSQLiteLifetime.h | 24 +++++ + toolkit/xre/Bootstrap.cpp | 4 + + toolkit/xre/moz.build | 3 +- + 8 files changed, 212 insertions(+), 159 deletions(-) + +diff --git security/manager/ssl/nsNSSComponent.cpp security/manager/ssl/nsNSSComponent.cpp +index 8c250e15eed1..a5749a0c69c5 100644 +--- security/manager/ssl/nsNSSComponent.cpp ++++ security/manager/ssl/nsNSSComponent.cpp +@@ -13,7 +13,6 @@ + #include "SharedSSLState.h" + #include "cert.h" + #include "certdb.h" +-#include "mozStorageCID.h" + #include "mozilla/ArrayUtils.h" + #include "mozilla/Assertions.h" + #include "mozilla/Casting.h" +@@ -2263,14 +2262,6 @@ nsNSSComponent::Init() + return NS_ERROR_NOT_AVAILABLE; + } + +- // To avoid a sqlite3_config race in NSS init, as a workaround for +- // bug 730495, we require the storage service to get initialized first. +- nsCOMPtr<nsISupports> storageService = +- do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID); +- if (!storageService) { +- return NS_ERROR_NOT_AVAILABLE; +- } +- + MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("Beginning NSS initialization\n")); + + nsresult rv = InitializePIPNSSBundle(); +diff --git storage/TelemetryVFS.cpp storage/TelemetryVFS.cpp +index 58b412c26dc8..9416772a78cf 100644 +--- storage/TelemetryVFS.cpp ++++ storage/TelemetryVFS.cpp +@@ -834,6 +834,11 @@ xNextSystemCall(sqlite3_vfs *vfs, const char *zName) + namespace mozilla { + namespace storage { + ++const char *GetVFSName() ++{ ++ return "telemetry-vfs"; ++} ++ + sqlite3_vfs* ConstructTelemetryVFS() + { + #if defined(XP_WIN) +@@ -867,7 +872,7 @@ sqlite3_vfs* ConstructTelemetryVFS() + MOZ_ASSERT(vfs->iVersion <= LAST_KNOWN_VFS_VERSION); + tvfs->szOsFile = sizeof(telemetry_file) - sizeof(sqlite3_file) + vfs->szOsFile; + tvfs->mxPathname = vfs->mxPathname; +- tvfs->zName = "telemetry-vfs"; ++ tvfs->zName = GetVFSName(); + tvfs->pAppData = vfs; + tvfs->xOpen = xOpen; + tvfs->xDelete = xDelete; +diff --git storage/mozStorageConnection.cpp storage/mozStorageConnection.cpp +index aa49bbbaa90e..f3391776f574 100644 +--- storage/mozStorageConnection.cpp ++++ storage/mozStorageConnection.cpp +@@ -73,6 +73,8 @@ namespace storage { + + using mozilla::dom::quota::QuotaObject; + ++const char *GetVFSName(); ++ + namespace { + + int +@@ -627,7 +629,7 @@ Connection::initialize() + AUTO_PROFILER_LABEL("Connection::initialize", STORAGE); + + // in memory database requested, sqlite uses a magic file name +- int srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags, nullptr); ++ int srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags, GetVFSName()); + if (srv != SQLITE_OK) { + mDBConn = nullptr; + return convertResultCode(srv); +@@ -660,7 +662,7 @@ Connection::initialize(nsIFile *aDatabaseFile) + #else + static const char* sIgnoreLockingVFS = "unix-none"; + #endif +- const char* vfs = mIgnoreLockingMode ? sIgnoreLockingVFS : nullptr; ++ const char* vfs = mIgnoreLockingMode ? sIgnoreLockingVFS : GetVFSName(); + + int srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, + mFlags, vfs); +@@ -694,7 +696,7 @@ Connection::initialize(nsIFileURL *aFileURL) + rv = aFileURL->GetSpec(spec); + NS_ENSURE_SUCCESS(rv, rv); + +- int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, nullptr); ++ int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, GetVFSName()); + if (srv != SQLITE_OK) { + mDBConn = nullptr; + return convertResultCode(srv); +diff --git storage/mozStorageService.cpp storage/mozStorageService.cpp +index 7c3cba8c1533..6439e60261cb 100644 +--- storage/mozStorageService.cpp ++++ storage/mozStorageService.cpp +@@ -24,6 +24,7 @@ + #include "mozIStoragePendingStatement.h" + + #include "sqlite3.h" ++#include "mozilla/AutoSQLiteLifetime.h" + + #ifdef SQLITE_OS_WIN + // "windows.h" was included and it can #define lots of things we care about... +@@ -32,13 +33,6 @@ + + #include "nsIPromptService.h" + +-#ifdef MOZ_STORAGE_MEMORY +-# include "mozmemory.h" +-# ifdef MOZ_DMD +-# include "DMD.h" +-# endif +-#endif +- + //////////////////////////////////////////////////////////////////////////////// + //// Defines + +@@ -282,12 +276,6 @@ Service::~Service() + if (rc != SQLITE_OK) + NS_WARNING("Failed to unregister sqlite vfs wrapper."); + +- // Shutdown the sqlite3 API. Warn if shutdown did not turn out okay, but +- // there is nothing actionable we can do in that case. +- rc = ::sqlite3_shutdown(); +- if (rc != SQLITE_OK) +- NS_WARNING("sqlite3 did not shutdown cleanly."); +- + shutdown(); // To release sXPConnect. + + gService = nullptr; +@@ -400,121 +388,7 @@ Service::shutdown() + } + + sqlite3_vfs *ConstructTelemetryVFS(); +- +-#ifdef MOZ_STORAGE_MEMORY +- +-namespace { +- +-// By default, SQLite tracks the size of all its heap blocks by adding an extra +-// 8 bytes at the start of the block to hold the size. Unfortunately, this +-// causes a lot of 2^N-sized allocations to be rounded up by jemalloc +-// allocator, wasting memory. For example, a request for 1024 bytes has 8 +-// bytes added, becoming a request for 1032 bytes, and jemalloc rounds this up +-// to 2048 bytes, wasting 1012 bytes. (See bug 676189 for more details.) +-// +-// So we register jemalloc as the malloc implementation, which avoids this +-// 8-byte overhead, and thus a lot of waste. This requires us to provide a +-// function, sqliteMemRoundup(), which computes the actual size that will be +-// allocated for a given request. SQLite uses this function before all +-// allocations, and may be able to use any excess bytes caused by the rounding. +-// +-// Note: the wrappers for malloc, realloc and moz_malloc_usable_size are +-// necessary because the sqlite_mem_methods type signatures differ slightly +-// from the standard ones -- they use int instead of size_t. But we don't need +-// a wrapper for free. +- +-#ifdef MOZ_DMD +- +-// sqlite does its own memory accounting, and we use its numbers in our memory +-// reporters. But we don't want sqlite's heap blocks to show up in DMD's +-// output as unreported, so we mark them as reported when they're allocated and +-// mark them as unreported when they are freed. +-// +-// In other words, we are marking all sqlite heap blocks as reported even +-// though we're not reporting them ourselves. Instead we're trusting that +-// sqlite is fully and correctly accounting for all of its heap blocks via its +-// own memory accounting. Well, we don't have to trust it entirely, because +-// it's easy to keep track (while doing this DMD-specific marking) of exactly +-// how much memory SQLite is using. And we can compare that against what +-// SQLite reports it is using. +- +-MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(SqliteMallocSizeOfOnAlloc) +-MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(SqliteMallocSizeOfOnFree) +- +-#endif +- +-static void *sqliteMemMalloc(int n) +-{ +- void* p = ::malloc(n); +-#ifdef MOZ_DMD +- gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p); +-#endif +- return p; +-} +- +-static void sqliteMemFree(void *p) +-{ +-#ifdef MOZ_DMD +- gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p); +-#endif +- ::free(p); +-} +- +-static void *sqliteMemRealloc(void *p, int n) +-{ +-#ifdef MOZ_DMD +- gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p); +- void *pnew = ::realloc(p, n); +- if (pnew) { +- gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(pnew); +- } else { +- // realloc failed; undo the SqliteMallocSizeOfOnFree from above +- gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p); +- } +- return pnew; +-#else +- return ::realloc(p, n); +-#endif +-} +- +-static int sqliteMemSize(void *p) +-{ +- return ::moz_malloc_usable_size(p); +-} +- +-static int sqliteMemRoundup(int n) +-{ +- n = malloc_good_size(n); +- +- // jemalloc can return blocks of size 2 and 4, but SQLite requires that all +- // allocations be 8-aligned. So we round up sub-8 requests to 8. This +- // wastes a small amount of memory but is obviously safe. +- return n <= 8 ? 8 : n; +-} +- +-static int sqliteMemInit(void *p) +-{ +- return 0; +-} +- +-static void sqliteMemShutdown(void *p) +-{ +-} +- +-const sqlite3_mem_methods memMethods = { +- &sqliteMemMalloc, +- &sqliteMemFree, +- &sqliteMemRealloc, +- &sqliteMemSize, +- &sqliteMemRoundup, +- &sqliteMemInit, +- &sqliteMemShutdown, +- nullptr +-}; +- +-} // namespace +- +-#endif // MOZ_STORAGE_MEMORY ++const char *GetVFSName(); + + static const char* sObserverTopics[] = { + "memory-pressure", +@@ -527,28 +401,13 @@ Service::initialize() + { + MOZ_ASSERT(NS_IsMainThread(), "Must be initialized on the main thread"); + +- int rc; +- +-#ifdef MOZ_STORAGE_MEMORY +- rc = ::sqlite3_config(SQLITE_CONFIG_MALLOC, &memMethods); +- if (rc != SQLITE_OK) +- return convertResultCode(rc); +-#endif +- +- // TODO (bug 1191405): do not preallocate the connections caches until we +- // have figured the impact on our consumers and memory. +- sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0); +- +- // Explicitly initialize sqlite3. Although this is implicitly called by +- // various sqlite3 functions (and the sqlite3_open calls in our case), +- // the documentation suggests calling this directly. So we do. +- rc = ::sqlite3_initialize(); ++ int rc = AutoSQLiteLifetime::getInitResult(); + if (rc != SQLITE_OK) + return convertResultCode(rc); + + mSqliteVFS = ConstructTelemetryVFS(); + if (mSqliteVFS) { +- rc = sqlite3_vfs_register(mSqliteVFS, 1); ++ rc = sqlite3_vfs_register(mSqliteVFS, 0); + if (rc != SQLITE_OK) + return convertResultCode(rc); + } else { +diff --git toolkit/xre/AutoSQLiteLifetime.cpp toolkit/xre/AutoSQLiteLifetime.cpp +new file mode 100644 +index 000000000000..a122c4900530 +--- /dev/null ++++ toolkit/xre/AutoSQLiteLifetime.cpp +@@ -0,0 +1,167 @@ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "nsDebug.h" ++#include "AutoSQLiteLifetime.h" ++#include "sqlite3.h" ++ ++#ifdef MOZ_STORAGE_MEMORY ++# include "mozmemory.h" ++# ifdef MOZ_DMD ++# include "DMD.h" ++# endif ++ ++namespace { ++ ++// By default, SQLite tracks the size of all its heap blocks by adding an extra ++// 8 bytes at the start of the block to hold the size. Unfortunately, this ++// causes a lot of 2^N-sized allocations to be rounded up by jemalloc ++// allocator, wasting memory. For example, a request for 1024 bytes has 8 ++// bytes added, becoming a request for 1032 bytes, and jemalloc rounds this up ++// to 2048 bytes, wasting 1012 bytes. (See bug 676189 for more details.) ++// ++// So we register jemalloc as the malloc implementation, which avoids this ++// 8-byte overhead, and thus a lot of waste. This requires us to provide a ++// function, sqliteMemRoundup(), which computes the actual size that will be ++// allocated for a given request. SQLite uses this function before all ++// allocations, and may be able to use any excess bytes caused by the rounding. ++// ++// Note: the wrappers for malloc, realloc and moz_malloc_usable_size are ++// necessary because the sqlite_mem_methods type signatures differ slightly ++// from the standard ones -- they use int instead of size_t. But we don't need ++// a wrapper for free. ++ ++#ifdef MOZ_DMD ++ ++// sqlite does its own memory accounting, and we use its numbers in our memory ++// reporters. But we don't want sqlite's heap blocks to show up in DMD's ++// output as unreported, so we mark them as reported when they're allocated and ++// mark them as unreported when they are freed. ++// ++// In other words, we are marking all sqlite heap blocks as reported even ++// though we're not reporting them ourselves. Instead we're trusting that ++// sqlite is fully and correctly accounting for all of its heap blocks via its ++// own memory accounting. Well, we don't have to trust it entirely, because ++// it's easy to keep track (while doing this DMD-specific marking) of exactly ++// how much memory SQLite is using. And we can compare that against what ++// SQLite reports it is using. ++ ++MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(SqliteMallocSizeOfOnAlloc) ++MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(SqliteMallocSizeOfOnFree) ++ ++#endif ++ ++static void *sqliteMemMalloc(int n) ++{ ++ void* p = ::malloc(n); ++#ifdef MOZ_DMD ++ gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p); ++#endif ++ return p; ++} ++ ++static void sqliteMemFree(void *p) ++{ ++#ifdef MOZ_DMD ++ gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p); ++#endif ++ ::free(p); ++} ++ ++static void *sqliteMemRealloc(void *p, int n) ++{ ++#ifdef MOZ_DMD ++ gSqliteMemoryUsed -= SqliteMallocSizeOfOnFree(p); ++ void *pnew = ::realloc(p, n); ++ if (pnew) { ++ gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(pnew); ++ } else { ++ // realloc failed; undo the SqliteMallocSizeOfOnFree from above ++ gSqliteMemoryUsed += SqliteMallocSizeOfOnAlloc(p); ++ } ++ return pnew; ++#else ++ return ::realloc(p, n); ++#endif ++} ++ ++static int sqliteMemSize(void *p) ++{ ++ return ::moz_malloc_usable_size(p); ++} ++ ++static int sqliteMemRoundup(int n) ++{ ++ n = malloc_good_size(n); ++ ++ // jemalloc can return blocks of size 2 and 4, but SQLite requires that all ++ // allocations be 8-aligned. So we round up sub-8 requests to 8. This ++ // wastes a small amount of memory but is obviously safe. ++ return n <= 8 ? 8 : n; ++} ++ ++static int sqliteMemInit(void *p) ++{ ++ return 0; ++} ++ ++static void sqliteMemShutdown(void *p) ++{ ++} ++ ++const sqlite3_mem_methods memMethods = { ++ &sqliteMemMalloc, ++ &sqliteMemFree, ++ &sqliteMemRealloc, ++ &sqliteMemSize, ++ &sqliteMemRoundup, ++ &sqliteMemInit, ++ &sqliteMemShutdown, ++ nullptr ++}; ++ ++} // namespace ++ ++#endif // MOZ_STORAGE_MEMORY ++ ++namespace mozilla { ++ ++AutoSQLiteLifetime::AutoSQLiteLifetime() ++{ ++ if (++AutoSQLiteLifetime::sSingletonEnforcer != 1) { ++ NS_RUNTIMEABORT("multiple instances of AutoSQLiteLifetime constructed!"); ++ } ++ ++#ifdef MOZ_STORAGE_MEMORY ++ sResult = ::sqlite3_config(SQLITE_CONFIG_MALLOC, &memMethods); ++#else ++ sResult = SQLITE_OK; ++#endif ++ ++ if (sResult == SQLITE_OK) { ++ // TODO (bug 1191405): do not preallocate the connections caches until we ++ // have figured the impact on our consumers and memory. ++ sqlite3_config(SQLITE_CONFIG_PAGECACHE, NULL, 0, 0); ++ ++ // Explicitly initialize sqlite3. Although this is implicitly called by ++ // various sqlite3 functions (and the sqlite3_open calls in our case), ++ // the documentation suggests calling this directly. So we do. ++ sResult = ::sqlite3_initialize(); ++ } ++} ++ ++AutoSQLiteLifetime::~AutoSQLiteLifetime() ++{ ++ // Shutdown the sqlite3 API. Warn if shutdown did not turn out okay, but ++ // there is nothing actionable we can do in that case. ++ sResult = ::sqlite3_shutdown(); ++ NS_WARNING_ASSERTION(sResult == SQLITE_OK, ++ "sqlite3 did not shutdown cleanly."); ++} ++ ++int AutoSQLiteLifetime::sSingletonEnforcer = 0; ++int AutoSQLiteLifetime::sResult = SQLITE_MISUSE; ++ ++} // namespace mozilla +diff --git toolkit/xre/AutoSQLiteLifetime.h toolkit/xre/AutoSQLiteLifetime.h +new file mode 100644 +index 000000000000..b62963622ea1 +--- /dev/null ++++ toolkit/xre/AutoSQLiteLifetime.h +@@ -0,0 +1,24 @@ ++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#ifndef mozilla_AutoSQLiteLifetime_h ++#define mozilla_AutoSQLiteLifetime_h ++ ++namespace mozilla { ++ ++class AutoSQLiteLifetime final ++{ ++private: ++ static int sSingletonEnforcer; ++ static int sResult; ++public: ++ AutoSQLiteLifetime(); ++ ~AutoSQLiteLifetime(); ++ static int getInitResult() { return AutoSQLiteLifetime::sResult; } ++}; ++ ++} // namespace mozilla ++ ++#endif +diff --git toolkit/xre/Bootstrap.cpp toolkit/xre/Bootstrap.cpp +index bd80732fdf51..c19f0498d08f 100644 +--- toolkit/xre/Bootstrap.cpp ++++ toolkit/xre/Bootstrap.cpp +@@ -6,11 +6,15 @@ + #include "mozilla/Bootstrap.h" + #include "nsXPCOM.h" + ++#include "AutoSQLiteLifetime.h" ++ + namespace mozilla { + + class BootstrapImpl final : public Bootstrap + { + protected: ++ AutoSQLiteLifetime mSQLLT; ++ + virtual void Dispose() override + { + delete this; +diff --git toolkit/xre/moz.build toolkit/xre/moz.build +index 7a65cd5d296b..08bf452980b5 100644 +--- toolkit/xre/moz.build ++++ toolkit/xre/moz.build +@@ -30,7 +30,7 @@ EXPORTS += [ + 'nsIAppStartupNotifier.h', + ] + +-EXPORTS.mozilla += ['Bootstrap.h'] ++EXPORTS.mozilla += ['AutoSQLiteLifetime.h', 'Bootstrap.h'] + + if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']: + EXPORTS += ['EventTracer.h'] +@@ -91,6 +91,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': + ] + + UNIFIED_SOURCES += [ ++ 'AutoSQLiteLifetime.cpp', + 'Bootstrap.cpp', + 'CreateAppData.cpp', + 'nsAppStartupNotifier.cpp', diff --git a/www/waterfox/files/patch-bug826985 b/www/waterfox/files/patch-bug826985 new file mode 100644 index 000000000000..8e9e7d24a024 --- /dev/null +++ b/www/waterfox/files/patch-bug826985 @@ -0,0 +1,171 @@ +commit 8024d93 +Author: Henrik Gulbrandsen <henrik@gulbra.net> +Date: Fri Jan 4 13:49:22 2013 +0100 + + Bug 826985 - Support more video formats for WebRTC via libv4l2 on Linux. +--- + config/system-headers | 1 + + old-configure.in | 7 +++++++ + media/webrtc/signaling/test/Makefile.in | 1 + + .../modules/video_capture/linux/device_info_linux.cc | 17 +++++++++++++++++ + .../modules/video_capture/linux/video_capture_linux.cc | 16 +++++++++++++++- + .../webrtc/modules/video_capture/video_capture.gypi | 11 +++++++++++ + toolkit/library/Makefile.in | 1 + + 6 files changed, 52 insertions(+), 1 deletion(-) + +diff --git config/system-headers config/system-headers +index 55e4cd1..76567b3 100644 +--- config/system-headers ++++ config/system-headers +@@ -624,6 +624,7 @@ libgnome/libgnome.h + libgnomeui/gnome-icon-lookup.h + libgnomeui/gnome-icon-theme.h + libgnomeui/gnome-ui-init.h ++libv4l2.h + limits.h + link.h + #ifdef ANDROID +diff --git old-configure.in configure.in +index 55e4cd1..76567b3 100644 +--- old-configure.in ++++ old-configure.in +@@ -5309,6 +5309,9 @@ if test -n "$MOZ_WEBRTC"; then + MOZ_VP8_ENCODER=1 + MOZ_VP8_ERROR_CONCEALMENT=1 + ++ dnl with libv4l2 we can support more cameras ++ PKG_CHECK_MODULES(MOZ_LIBV4L2, libv4l2) ++ + dnl enable once Signaling lands + MOZ_WEBRTC_SIGNALING=1 + AC_DEFINE(MOZ_WEBRTC_SIGNALING) +diff --git build/gyp.mozbuild build/gyp.mozbuild +index b483cd1..f1dd1f0 100644 +--- build/gyp.mozbuild ++++ build/gyp.mozbuild +@@ -11,6 +11,7 @@ gyp_vars = { + 'have_ethtool_cmd_speed_hi': 1 if CONFIG['MOZ_WEBRTC_HAVE_ETHTOOL_SPEED_HI'] else 0, + 'include_alsa_audio': 1 if CONFIG['MOZ_ALSA'] else 0, + 'include_pulse_audio': 1 if CONFIG['MOZ_PULSEAUDIO'] else 0, ++ 'use_libv4l2': 1 if CONFIG['MOZ_LIBV4L2_LIBS'] else 0, + # basic stuff for everything + 'include_internal_video_render': 0, + 'clang_use_chrome_plugins': 0, +diff --git media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc +index 239a292..bab496c 100644 +--- media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc ++++ media/webrtc/trunk/webrtc/modules/video_capture/linux/device_info_linux.cc +@@ -25,6 +25,9 @@ + #else + #include <linux/videodev2.h> + #endif ++#ifdef HAVE_LIBV4L2 ++#include <libv4l2.h> ++#endif + + #include "webrtc/system_wrappers/interface/ref_count.h" + #include "webrtc/system_wrappers/interface/trace.h" +@@ -34,6 +37,15 @@ + #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) + #endif + ++#ifdef HAVE_LIBV4L2 ++#define open v4l2_open ++#define close v4l2_close ++#define dup v4l2_dup ++#define ioctl v4l2_ioctl ++#define mmap v4l2_mmap ++#define munmap v4l2_munmap ++#endif ++ + namespace webrtc + { + namespace videocapturemodule +@@ -274,6 +286,11 @@ int32_t DeviceInfoLinux::GetDeviceName( + memset(deviceNameUTF8, 0, deviceNameLength); + memcpy(cameraName, cap.card, sizeof(cap.card)); + ++ if (cameraName[0] == '\0') ++ { ++ sprintf(cameraName, "Camera at /dev/video%d", deviceNumber); ++ } ++ + if (deviceNameLength >= strlen(cameraName)) + { + memcpy(deviceNameUTF8, cameraName, strlen(cameraName)); +diff --git media/webrtc/trunk/webrtc/modules/video_capture/linux/video_capture_linux.cc media/webrtc/trunk/webrtc/modules/video_capture/linux/video_capture_linux.cc +index 12df1b3..e9863ba 100644 +--- media/webrtc/trunk/webrtc/modules/video_capture/linux/video_capture_linux.cc ++++ media/webrtc/trunk/webrtc/modules/video_capture/linux/video_capture_linux.cc +@@ -25,6 +25,9 @@ + #else + #include <linux/videodev2.h> + #endif ++#ifdef HAVE_LIBV4L2 ++#include <libv4l2.h> ++#endif + + #include <new> + +@@ -32,6 +35,15 @@ + #include "webrtc/modules/video_capture/linux/video_capture_linux.h" + #include "webrtc/system_wrappers/include/critical_section_wrapper.h" + #include "webrtc/system_wrappers/include/trace.h" ++ ++#ifdef HAVE_LIBV4L2 ++#define open v4l2_open ++#define close v4l2_close ++#define dup v4l2_dup ++#define ioctl v4l2_ioctl ++#define mmap v4l2_mmap ++#define munmap v4l2_munmap ++#endif + + namespace webrtc { + namespace videocapturemodule { +diff --git media/webrtc/trunk/webrtc/modules/video_capture/video_capture.gypi media/webrtc/trunk/webrtc/modules/video_capture/video_capture.gypi +index d46b5aa..e452223 100644 +--- media/webrtc/trunk/webrtc/modules/video_capture/video_capture.gypi ++++ media/webrtc/trunk/webrtc/modules/video_capture/video_capture.gypi +@@ -7,6 +7,9 @@ + # be found in the AUTHORS file in the root of the source tree. + + { ++ 'variables': { ++ 'use_libv4l2%': 0, ++ }, + 'targets': [ + { + 'target_name': 'video_capture_module', +@@ -76,6 +76,19 @@ + 'linux/video_capture_linux.cc', + 'linux/video_capture_linux.h', + ], ++ 'conditions': [ ++ ['use_libv4l2==1', { ++ 'defines': [ ++ 'HAVE_LIBV4L2', ++ ], ++ 'cflags_mozilla': [ ++ '$(MOZ_LIBV4L2_CFLAGS)', ++ ], ++ 'libraries': [ ++ '-lv4l2', ++ ], ++ }], ++ ], + }], + ['OS=="mac"', { + 'sources': [ +diff --git toolkit/library/moz.build toolkit/library/moz.build +index 9c16ffa..1db3794 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -163,6 +163,7 @@ if CONFIG['OS_ARCH'] == 'Linux' and CONF + ] + + OS_LIBS += CONFIG['MOZ_CAIRO_OSLIBS'] ++OS_LIBS += CONFIG['MOZ_LIBV4L2_LIBS'] + OS_LIBS += CONFIG['MOZ_WEBRTC_X11_LIBS'] + OS_LIBS += CONFIG['MOZ_APP_EXTRA_LIBS'] + diff --git a/www/waterfox/files/patch-bug847568 b/www/waterfox/files/patch-bug847568 new file mode 100644 index 000000000000..da3f3d6b4c08 --- /dev/null +++ b/www/waterfox/files/patch-bug847568 @@ -0,0 +1,271 @@ +# Allow building against system-wide graphite2/harfbuzz. + +diff --git config/Makefile.in config/Makefile.in +index e2e11dc0e27e..a6206bb0ff30 100644 +--- config/Makefile.in ++++ config/Makefile.in +@@ -41,6 +41,8 @@ export:: $(export-preqs) + $(PYTHON) -m mozbuild.action.preprocessor $(DEFINES) $(ACDEFINES) \ + -DMOZ_TREE_CAIRO=$(MOZ_TREE_CAIRO) \ + -DMOZ_TREE_PIXMAN=$(MOZ_TREE_PIXMAN) \ ++ -DMOZ_SYSTEM_GRAPHITE2=$(MOZ_SYSTEM_GRAPHITE2) \ ++ -DMOZ_SYSTEM_HARFBUZZ=$(MOZ_SYSTEM_HARFBUZZ) \ + -DMOZ_SYSTEM_HUNSPELL=$(MOZ_SYSTEM_HUNSPELL) \ + -DMOZ_SYSTEM_BZ2=$(MOZ_SYSTEM_BZ2) \ + -DMOZ_SYSTEM_ZLIB=$(MOZ_SYSTEM_ZLIB) \ +diff --git config/system-headers config/system-headers +index a0c53c651a3e..5ee7f71f9634 100644 +--- config/system-headers ++++ config/system-headers +@@ -1269,6 +1269,15 @@ libsn/sn-launcher.h + libsn/sn-monitor.h + libsn/sn-util.h + #endif ++#if MOZ_SYSTEM_GRAPHITE2==1 ++graphite2/Font.h ++graphite2/Segment.h ++#endif ++#if MOZ_SYSTEM_HARFBUZZ==1 ++harfbuzz/hb-glib.h ++harfbuzz/hb-ot.h ++harfbuzz/hb.h ++#endif + #if MOZ_SYSTEM_HUNSPELL==1 + hunspell.hxx + #endif +diff --git dom/base/moz.build dom/base/moz.build +index 8e19020315ae..2fcdbb6f7b42 100644 +--- dom/base/moz.build ++++ dom/base/moz.build +@@ -464,6 +464,9 @@ if CONFIG['MOZ_BUILD_APP'] in ['browser', 'mobile/android', 'xulrunner']: + if CONFIG['MOZ_X11']: + CXXFLAGS += CONFIG['TK_CFLAGS'] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + GENERATED_FILES += [ + 'PropertyUseCounterMap.inc', + 'UseCounterList.h', +diff --git gfx/graphite2/moz-gr-update.sh gfx/graphite2/moz-gr-update.sh +index faaab1b17971..04eff5f09882 100644 +--- gfx/graphite2/moz-gr-update.sh ++++ gfx/graphite2/moz-gr-update.sh +@@ -1,6 +1,7 @@ + #!/bin/bash + + # Script used to update the Graphite2 library in the mozilla source tree ++# and bump version for --with-system-graphite2 + + # This script lives in gfx/graphite2, along with the library source, + # but must be run from the top level of the mozilla-central tree. +@@ -37,12 +38,16 @@ echo "See" $0 "for update procedure." >> gfx/graphite2/README.mozilla + #find gfx/graphite2/ -name "*.cpp" -exec perl -p -i -e "s/<cstdio>/<stdio.h>/;s/Windows.h/windows.h/;" {} \; + #find gfx/graphite2/ -name "*.h" -exec perl -p -i -e "s/<cstdio>/<stdio.h>/;s/Windows.h/windows.h/;" {} \; + ++# chase version for --with-system-graphite2 ++perl -p -i -e "s/[0-9]+\,[0-9]+\,[0-9]+/$RELEASE/ and tr/./,/ \ ++ if /GR2_VERSION_REQUIRE/" old-configure.in ++ + # summarize what's been touched + echo Updated to $RELEASE. + echo Here is what changed in the gfx/graphite2 directory: + echo + +-hg stat gfx/graphite2 ++hg stat old-configure.in gfx/graphite2 + + echo + echo If gfx/graphite2/src/files.mk has changed, please make corresponding +diff --git gfx/harfbuzz/README-mozilla gfx/harfbuzz/README-mozilla +index 22c76a7df020..a01490bd49ee 100644 +--- gfx/harfbuzz/README-mozilla ++++ gfx/harfbuzz/README-mozilla +@@ -19,3 +19,8 @@ the mozilla tree. + + If the collection of source files changes, manual updates to moz.build may be + needed, as we don't use the upstream makefiles. ++ ++The in-tree copy may be omitted during build by --with-system-harfbuzz. ++Make sure to keep pkg-config version check within toolkit/moz.configure in sync ++with checkout version or increment latest tag by one if it's not based ++on upstream release. +diff --git gfx/moz.build gfx/moz.build +index 771f652e837a..3b358d84e384 100644 +--- gfx/moz.build ++++ gfx/moz.build +@@ -10,6 +10,12 @@ with Files('**'): + if CONFIG['MOZ_TREE_CAIRO']: + DIRS += ['cairo'] + ++if not CONFIG['MOZ_SYSTEM_GRAPHITE2']: ++ DIRS += ['graphite2/src' ] ++ ++if not CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ DIRS += ['harfbuzz/src'] ++ + DIRS += [ + '2d', + 'ycbcr', +@@ -18,8 +24,6 @@ DIRS += [ + 'qcms', + 'gl', + 'layers', +- 'graphite2/src', +- 'harfbuzz/src', + 'ots/src', + 'thebes', + 'ipc', +diff --git gfx/skia/generate_mozbuild.py gfx/skia/generate_mozbuild.py +index e06ae3457a47..93faa61594a3 100755 +--- gfx/skia/generate_mozbuild.py ++++ gfx/skia/generate_mozbuild.py +@@ -148,6 +148,9 @@ if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): + '-Wno-unused-private-field', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk3', 'android'): + CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] + CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS'] +diff --git gfx/skia/moz.build gfx/skia/moz.build +index 2118677ca3a8..e4978b413784 100644 +--- gfx/skia/moz.build ++++ gfx/skia/moz.build +@@ -822,6 +822,9 @@ if CONFIG['CC_TYPE'] in ('clang', 'clang-cl'): + '-Wno-unused-private-field', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk3', 'android'): + CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS'] + CXXFLAGS += CONFIG['CAIRO_FT_CFLAGS'] +diff --git gfx/thebes/moz.build gfx/thebes/moz.build +index 56f1b9fe3f4b..0ac1100b0df3 100644 +--- gfx/thebes/moz.build ++++ gfx/thebes/moz.build +@@ -269,7 +269,13 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3'): + + LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES'] + +-DEFINES['GRAPHITE2_STATIC'] = True ++if CONFIG['MOZ_SYSTEM_GRAPHITE2']: ++ CXXFLAGS += CONFIG['MOZ_GRAPHITE2_CFLAGS'] ++else: ++ DEFINES['GRAPHITE2_STATIC'] = True ++ ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] + + if CONFIG['CLANG_CXX']: + # Suppress warnings from Skia header files. +diff --git intl/unicharutil/util/moz.build intl/unicharutil/util/moz.build +index cb1233c56d7e..06fb1f9f174b 100644 +--- intl/unicharutil/util/moz.build ++++ intl/unicharutil/util/moz.build +@@ -29,4 +29,7 @@ if CONFIG['ENABLE_INTL_API']: + 'ICUUtils.cpp', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + FINAL_LIBRARY = 'xul' +diff --git netwerk/dns/moz.build netwerk/dns/moz.build +index 79c26e3e7001..c4d93bc5f7dc 100644 +--- netwerk/dns/moz.build ++++ netwerk/dns/moz.build +@@ -69,6 +69,9 @@ LOCAL_INCLUDES += [ + '/netwerk/base', + ] + ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ CXXFLAGS += CONFIG['MOZ_HARFBUZZ_CFLAGS'] ++ + if CONFIG['ENABLE_INTL_API']: + DEFINES['IDNA2008'] = True + USE_LIBS += ['icu'] +diff --git old-configure.in old-configure.in +index 95a58b634593..b614eef85c89 100644 +--- old-configure.in ++++ old-configure.in +@@ -4888,6 +4888,27 @@ dnl ======================================================== + AC_SUBST(MOZ_LINUX_32_SSE2_STARTUP_ERROR) + + dnl ======================================================== ++dnl Check for graphite2 ++dnl ======================================================== ++if test -n "$MOZ_SYSTEM_GRAPHITE2"; then ++ dnl graphite2.pc has bogus version, check manually ++ _SAVE_CFLAGS=$CFLAGS ++ CFLAGS="$CFLAGS $MOZ_GRAPHITE2_CFLAGS" ++ AC_TRY_COMPILE([ #include <graphite2/Font.h> ++ #define GR2_VERSION_REQUIRE(major,minor,bugfix) \ ++ ( GR2_VERSION_MAJOR * 10000 + GR2_VERSION_MINOR \ ++ * 100 + GR2_VERSION_BUGFIX >= \ ++ (major) * 10000 + (minor) * 100 + (bugfix) ) ++ ], [ ++ #if !GR2_VERSION_REQUIRE(1,3,10) ++ #error "Insufficient graphite2 version." ++ #endif ++ ], [], ++ [AC_MSG_ERROR([--with-system-graphite2 requested but no working libgraphite2 found])]) ++ CFLAGS=$_SAVE_CFLAGS ++fi ++ ++dnl ======================================================== + dnl Check for pixman and cairo + dnl ======================================================== + +diff --git toolkit/library/moz.build toolkit/library/moz.build +index 24f940e1ed7e..079a575adec3 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -224,6 +224,12 @@ if CONFIG['MOZ_SYSTEM_JPEG']: + if CONFIG['MOZ_SYSTEM_PNG']: + OS_LIBS += CONFIG['MOZ_PNG_LIBS'] + ++if CONFIG['MOZ_SYSTEM_GRAPHITE2']: ++ OS_LIBS += CONFIG['MOZ_GRAPHITE2_LIBS'] ++ ++if CONFIG['MOZ_SYSTEM_HARFBUZZ']: ++ OS_LIBS += CONFIG['MOZ_HARFBUZZ_LIBS'] ++ + if CONFIG['MOZ_SYSTEM_HUNSPELL']: + OS_LIBS += CONFIG['MOZ_HUNSPELL_LIBS'] + +diff --git toolkit/moz.configure toolkit/moz.configure +index 9297e4d6f501..d8e273887e4b 100644 +--- toolkit/moz.configure ++++ toolkit/moz.configure +@@ -356,6 +356,26 @@ add_old_configure_assignment('FT2_LIBS', + add_old_configure_assignment('FT2_CFLAGS', + delayed_getattr(ft2_info, 'cflags')) + ++# Graphite2 ++# ============================================================== ++option('--with-system-graphite2', ++ help="Use system graphite2 (located with pkgconfig)") ++ ++system_graphite2 = pkg_check_modules('MOZ_GRAPHITE2', 'graphite2', ++ when='--with-system-graphite2') ++ ++set_config('MOZ_SYSTEM_GRAPHITE2', depends_if(system_graphite2)(lambda _: True)) ++ ++# HarfBuzz ++# ============================================================== ++option('--with-system-harfbuzz', ++ help="Use system harfbuzz (located with pkgconfig)") ++ ++system_harfbuzz = pkg_check_modules('MOZ_HARFBUZZ', 'harfbuzz >= 1.4.7', ++ when='--with-system-harfbuzz') ++ ++set_config('MOZ_SYSTEM_HARFBUZZ', depends_if(system_harfbuzz)(lambda _: True)) ++ + # Apple platform decoder support + # ============================================================== + @depends(toolkit) diff --git a/www/waterfox/files/patch-bug991253 b/www/waterfox/files/patch-bug991253 new file mode 100644 index 000000000000..a9931030e915 --- /dev/null +++ b/www/waterfox/files/patch-bug991253 @@ -0,0 +1,17 @@ +--- extensions/spellcheck/hunspell/glue/mozHunspell.cpp~ ++++ extensions/spellcheck/hunspell/glue/mozHunspell.cpp +@@ -392,6 +392,14 @@ mozHunspell::LoadDictionaryList(bool aNo + } + } + ++ // load system hunspell dictionaries ++ nsCOMPtr<nsIFile> hunDir; ++ NS_NewNativeLocalFile(NS_LITERAL_CSTRING("%%LOCALBASE%%/share/hunspell"), ++ true, getter_AddRefs(hunDir)); ++ if (hunDir) { ++ LoadDictionariesFromDir(hunDir); ++ } ++ + // find dictionaries from extensions requiring restart + nsCOMPtr<nsISimpleEnumerator> dictDirs; + rv = dirSvc->Get(DICTIONARY_SEARCH_DIRECTORY_LIST, diff --git a/www/waterfox/files/patch-config-baseconfig.mk b/www/waterfox/files/patch-config-baseconfig.mk new file mode 100644 index 000000000000..40a81f4587f4 --- /dev/null +++ b/www/waterfox/files/patch-config-baseconfig.mk @@ -0,0 +1,17 @@ +--- config/baseconfig.mk~ ++++ config/baseconfig.mk +@@ -2,10 +2,10 @@ + # directly in python/mozbuild/mozbuild/base.py for gmake validation. + # We thus use INCLUDED_AUTOCONF_MK to enable/disable some parts depending + # whether a normal build is happening or whether the check is running. +-includedir := $(includedir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION) +-idldir = $(datadir)/idl/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION) +-installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_VERSION) +-sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_VERSION) ++includedir := $(includedir)/%%MOZILLA%% ++idldir = $(datadir)/idl/%%MOZILLA%% ++installdir = $(libdir)/%%MOZILLA%% ++sdkdir = $(libdir)/%%MOZILLA%% + ifeq (.,$(DEPTH)) + DIST = dist + else diff --git a/www/waterfox/files/patch-env-api-keys b/www/waterfox/files/patch-env-api-keys new file mode 100644 index 000000000000..e20b012f27cf --- /dev/null +++ b/www/waterfox/files/patch-env-api-keys @@ -0,0 +1,21 @@ +# Accept API keys from environment like before bug 1294585 + +--- build/moz.configure/keyfiles.configure ++++ build/moz.configure/keyfiles.configure +@@ -18,6 +18,7 @@ def keyfile(desc, help=None, callback=lambda x: x): + @checking('for the %s key' % desc, lambda x: x and x is not no_key) + @imports(_from='__builtin__', _import='open') + @imports(_from='__builtin__', _import='IOError') ++ @imports(_from='os', _import='environ') + def keyfile(value): + if value: + try: +@@ -28,7 +29,7 @@ def keyfile(desc, help=None, callback=lambda x: x): + raise FatalCheckError("'%s' is empty." % value[0]) + except IOError as e: + raise FatalCheckError("'%s': %s." % (value[0], e.strerror)) +- return no_key ++ return environ.get('MOZ_%s_KEY' % desc.upper().replace(' ', '_')) or no_key + + return keyfile + diff --git a/www/waterfox/files/patch-ijg-libjpeg b/www/waterfox/files/patch-ijg-libjpeg new file mode 100644 index 000000000000..b6788adc0f84 --- /dev/null +++ b/www/waterfox/files/patch-ijg-libjpeg @@ -0,0 +1,383 @@ +# Partially revert bug 791305 to allow building with system IJG jpeg library + +diff --git old-configure.in configure.in +index f0aeb5d..1c01010 100644 +--- old-configure.in ++++ old-configure.in +@@ -4027,11 +4027,7 @@ if test "$MOZ_SYSTEM_JPEG" = 1; then + #include <jpeglib.h> ], + [ #if JPEG_LIB_VERSION < $MOZJPEG + #error "Insufficient JPEG library version ($MOZJPEG required)." +- #endif +- #ifndef JCS_EXTENSIONS +- #error "libjpeg-turbo JCS_EXTENSIONS required" +- #endif +- ], ++ #endif ], + MOZ_SYSTEM_JPEG=1, + AC_MSG_ERROR([Insufficient JPEG library version for --with-system-jpeg])) + fi +diff --git image/decoders/nsJPEGDecoder.cpp image/decoders/nsJPEGDecoder.cpp +index 8fa8200..1d2a259 100644 +--- image/decoders/nsJPEGDecoder.cpp ++++ image/decoders/nsJPEGDecoder.cpp +@@ -21,13 +21,28 @@ + + extern "C" { + #include "iccjpeg.h" +-} + ++#ifdef JCS_EXTENSIONS + #if MOZ_BIG_ENDIAN + #define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_XRGB + #else + #define MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB JCS_EXT_BGRX + #endif ++#else ++/* Colorspace conversion (copied from jpegint.h) */ ++struct jpeg_color_deconverter { ++ JMETHOD(void, start_pass, (j_decompress_ptr cinfo)); ++ JMETHOD(void, color_convert, (j_decompress_ptr cinfo, ++ JSAMPIMAGE input_buf, JDIMENSION input_row, ++ JSAMPARRAY output_buf, int num_rows)); ++}; ++ ++METHODDEF(void) ++ycc_rgb_convert_argb (j_decompress_ptr cinfo, ++ JSAMPIMAGE input_buf, JDIMENSION input_row, ++ JSAMPARRAY output_buf, int num_rows); ++#endif ++} + + static void cmyk_convert_rgb(JSAMPROW row, JDIMENSION width); + +@@ -367,6 +382,7 @@ nsJPEGDecoder::WriteInternal(const char* + case JCS_GRAYSCALE: + case JCS_RGB: + case JCS_YCbCr: ++#ifdef JCS_EXTENSIONS + // if we're not color managing we can decode directly to + // MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB + if (mCMSMode != eCMSMode_All) { +@@ -375,6 +391,9 @@ nsJPEGDecoder::WriteInternal(const char* + } else { + mInfo.out_color_space = JCS_RGB; + } ++#else ++ mInfo.out_color_space = JCS_RGB; ++#endif + break; + case JCS_CMYK: + case JCS_YCCK: +@@ -448,6 +467,16 @@ nsJPEGDecoder::WriteInternal(const char* + return; // I/O suspension + } + ++#ifndef JCS_EXTENSIONS ++ /* Force to use our YCbCr to Packed RGB converter when possible */ ++ if (!mTransform && (mCMSMode != eCMSMode_All) && ++ mInfo.jpeg_color_space == JCS_YCbCr && mInfo.out_color_space == JCS_RGB) { ++ /* Special case for the most common case: transform from YCbCr direct into packed ARGB */ ++ mInfo.out_color_components = 4; /* Packed ARGB pixels are always 4 bytes...*/ ++ mInfo.cconvert->color_convert = ycc_rgb_convert_argb; ++ } ++#endif ++ + // If this is a progressive JPEG ... + mState = mInfo.buffered_image ? + JPEG_DECOMPRESS_PROGRESSIVE : JPEG_DECOMPRESS_SEQUENTIAL; +@@ -605,7 +633,11 @@ nsJPEGDecoder::OutputScanlines(bool* sus + uint32_t* imageRow = ((uint32_t*)mImageData) + + (mInfo.output_scanline * mInfo.output_width); + ++#ifdef JCS_EXTENSIONS + if (mInfo.out_color_space == MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB) { ++#else ++ if (mInfo.cconvert->color_convert == ycc_rgb_convert_argb) { ++#endif + // Special case: scanline will be directly converted into packed ARGB + if (jpeg_read_scanlines(&mInfo, (JSAMPARRAY)&imageRow, 1) != 1) { + *suspend = true; // suspend +@@ -920,6 +952,282 @@ term_source (j_decompress_ptr jd) + } // namespace mozilla + + ++#ifndef JCS_EXTENSIONS ++/**************** YCbCr -> Cairo's RGB24/ARGB32 conversion: most common case **************/ ++ ++/* ++ * YCbCr is defined per CCIR 601-1, except that Cb and Cr are ++ * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. ++ * The conversion equations to be implemented are therefore ++ * R = Y + 1.40200 * Cr ++ * G = Y - 0.34414 * Cb - 0.71414 * Cr ++ * B = Y + 1.77200 * Cb ++ * where Cb and Cr represent the incoming values less CENTERJSAMPLE. ++ * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) ++ * ++ * To avoid floating-point arithmetic, we represent the fractional constants ++ * as integers scaled up by 2^16 (about 4 digits precision); we have to divide ++ * the products by 2^16, with appropriate rounding, to get the correct answer. ++ * Notice that Y, being an integral input, does not contribute any fraction ++ * so it need not participate in the rounding. ++ * ++ * For even more speed, we avoid doing any multiplications in the inner loop ++ * by precalculating the constants times Cb and Cr for all possible values. ++ * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); ++ * for 12-bit samples it is still acceptable. It's not very reasonable for ++ * 16-bit samples, but if you want lossless storage you shouldn't be changing ++ * colorspace anyway. ++ * The Cr=>R and Cb=>B values can be rounded to integers in advance; the ++ * values for the G calculation are left scaled up, since we must add them ++ * together before rounding. ++ */ ++ ++#define SCALEBITS 16 /* speediest right-shift on some machines */ ++ ++/* Use static tables for color processing. */ ++/* Four tables, each 256 entries of 4 bytes totals 4K which is not bad... */ ++ ++const int Cr_r_tab[(MAXJSAMPLE+1) * sizeof(int)] ={ ++ -0xb3, -0xb2, -0xb1, -0xaf, -0xae, -0xac, ++ -0xab, -0xaa, -0xa8, -0xa7, -0xa5, -0xa4, ++ -0xa3, -0xa1, -0xa0, -0x9e, -0x9d, -0x9c, ++ -0x9a, -0x99, -0x97, -0x96, -0x95, -0x93, ++ -0x92, -0x90, -0x8f, -0x8e, -0x8c, -0x8b, ++ -0x89, -0x88, -0x87, -0x85, -0x84, -0x82, ++ -0x81, -0x80, -0x7e, -0x7d, -0x7b, -0x7a, ++ -0x79, -0x77, -0x76, -0x74, -0x73, -0x72, ++ -0x70, -0x6f, -0x6d, -0x6c, -0x6b, -0x69, ++ -0x68, -0x66, -0x65, -0x64, -0x62, -0x61, ++ -0x5f, -0x5e, -0x5d, -0x5b, -0x5a, -0x58, ++ -0x57, -0x56, -0x54, -0x53, -0x51, -0x50, ++ -0x4f, -0x4d, -0x4c, -0x4a, -0x49, -0x48, ++ -0x46, -0x45, -0x43, -0x42, -0x40, -0x3f, ++ -0x3e, -0x3c, -0x3b, -0x39, -0x38, -0x37, ++ -0x35, -0x34, -0x32, -0x31, -0x30, -0x2e, ++ -0x2d, -0x2b, -0x2a, -0x29, -0x27, -0x26, ++ -0x24, -0x23, -0x22, -0x20, -0x1f, -0x1d, ++ -0x1c, -0x1b, -0x19, -0x18, -0x16, -0x15, ++ -0x14, -0x12, -0x11, -0x0f, -0x0e, -0x0d, ++ -0x0b, -0x0a, -0x08, -0x07, -0x06, -0x04, ++ -0x03, -0x01, 0x00, 0x01, 0x03, 0x04, ++ 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0d, ++ 0x0e, 0x0f, 0x11, 0x12, 0x14, 0x15, ++ 0x16, 0x18, 0x19, 0x1b, 0x1c, 0x1d, ++ 0x1f, 0x20, 0x22, 0x23, 0x24, 0x26, ++ 0x27, 0x29, 0x2a, 0x2b, 0x2d, 0x2e, ++ 0x30, 0x31, 0x32, 0x34, 0x35, 0x37, ++ 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x3f, ++ 0x40, 0x42, 0x43, 0x45, 0x46, 0x48, ++ 0x49, 0x4a, 0x4c, 0x4d, 0x4f, 0x50, ++ 0x51, 0x53, 0x54, 0x56, 0x57, 0x58, ++ 0x5a, 0x5b, 0x5d, 0x5e, 0x5f, 0x61, ++ 0x62, 0x64, 0x65, 0x66, 0x68, 0x69, ++ 0x6b, 0x6c, 0x6d, 0x6f, 0x70, 0x72, ++ 0x73, 0x74, 0x76, 0x77, 0x79, 0x7a, ++ 0x7b, 0x7d, 0x7e, 0x80, 0x81, 0x82, ++ 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, ++ 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, ++ 0x95, 0x96, 0x97, 0x99, 0x9a, 0x9c, ++ 0x9d, 0x9e, 0xa0, 0xa1, 0xa3, 0xa4, ++ 0xa5, 0xa7, 0xa8, 0xaa, 0xab, 0xac, ++ 0xae, 0xaf, 0xb1, 0xb2, ++ }; ++ ++const int Cb_b_tab[(MAXJSAMPLE+1) * sizeof(int)] ={ ++ -0xe3, -0xe1, -0xdf, -0xde, -0xdc, -0xda, ++ -0xd8, -0xd6, -0xd5, -0xd3, -0xd1, -0xcf, ++ -0xce, -0xcc, -0xca, -0xc8, -0xc6, -0xc5, ++ -0xc3, -0xc1, -0xbf, -0xbe, -0xbc, -0xba, ++ -0xb8, -0xb7, -0xb5, -0xb3, -0xb1, -0xaf, ++ -0xae, -0xac, -0xaa, -0xa8, -0xa7, -0xa5, ++ -0xa3, -0xa1, -0x9f, -0x9e, -0x9c, -0x9a, ++ -0x98, -0x97, -0x95, -0x93, -0x91, -0x90, ++ -0x8e, -0x8c, -0x8a, -0x88, -0x87, -0x85, ++ -0x83, -0x81, -0x80, -0x7e, -0x7c, -0x7a, ++ -0x78, -0x77, -0x75, -0x73, -0x71, -0x70, ++ -0x6e, -0x6c, -0x6a, -0x69, -0x67, -0x65, ++ -0x63, -0x61, -0x60, -0x5e, -0x5c, -0x5a, ++ -0x59, -0x57, -0x55, -0x53, -0x52, -0x50, ++ -0x4e, -0x4c, -0x4a, -0x49, -0x47, -0x45, ++ -0x43, -0x42, -0x40, -0x3e, -0x3c, -0x3a, ++ -0x39, -0x37, -0x35, -0x33, -0x32, -0x30, ++ -0x2e, -0x2c, -0x2b, -0x29, -0x27, -0x25, ++ -0x23, -0x22, -0x20, -0x1e, -0x1c, -0x1b, ++ -0x19, -0x17, -0x15, -0x13, -0x12, -0x10, ++ -0x0e, -0x0c, -0x0b, -0x09, -0x07, -0x05, ++ -0x04, -0x02, 0x00, 0x02, 0x04, 0x05, ++ 0x07, 0x09, 0x0b, 0x0c, 0x0e, 0x10, ++ 0x12, 0x13, 0x15, 0x17, 0x19, 0x1b, ++ 0x1c, 0x1e, 0x20, 0x22, 0x23, 0x25, ++ 0x27, 0x29, 0x2b, 0x2c, 0x2e, 0x30, ++ 0x32, 0x33, 0x35, 0x37, 0x39, 0x3a, ++ 0x3c, 0x3e, 0x40, 0x42, 0x43, 0x45, ++ 0x47, 0x49, 0x4a, 0x4c, 0x4e, 0x50, ++ 0x52, 0x53, 0x55, 0x57, 0x59, 0x5a, ++ 0x5c, 0x5e, 0x60, 0x61, 0x63, 0x65, ++ 0x67, 0x69, 0x6a, 0x6c, 0x6e, 0x70, ++ 0x71, 0x73, 0x75, 0x77, 0x78, 0x7a, ++ 0x7c, 0x7e, 0x80, 0x81, 0x83, 0x85, ++ 0x87, 0x88, 0x8a, 0x8c, 0x8e, 0x90, ++ 0x91, 0x93, 0x95, 0x97, 0x98, 0x9a, ++ 0x9c, 0x9e, 0x9f, 0xa1, 0xa3, 0xa5, ++ 0xa7, 0xa8, 0xaa, 0xac, 0xae, 0xaf, ++ 0xb1, 0xb3, 0xb5, 0xb7, 0xb8, 0xba, ++ 0xbc, 0xbe, 0xbf, 0xc1, 0xc3, 0xc5, ++ 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xcf, ++ 0xd1, 0xd3, 0xd5, 0xd6, 0xd8, 0xda, ++ 0xdc, 0xde, 0xdf, 0xe1, ++ }; ++ ++const int Cr_g_tab[(MAXJSAMPLE+1) * sizeof(int)] ={ ++ 0x5b6900, 0x5ab22e, 0x59fb5c, 0x59448a, 0x588db8, 0x57d6e6, ++ 0x572014, 0x566942, 0x55b270, 0x54fb9e, 0x5444cc, 0x538dfa, ++ 0x52d728, 0x522056, 0x516984, 0x50b2b2, 0x4ffbe0, 0x4f450e, ++ 0x4e8e3c, 0x4dd76a, 0x4d2098, 0x4c69c6, 0x4bb2f4, 0x4afc22, ++ 0x4a4550, 0x498e7e, 0x48d7ac, 0x4820da, 0x476a08, 0x46b336, ++ 0x45fc64, 0x454592, 0x448ec0, 0x43d7ee, 0x43211c, 0x426a4a, ++ 0x41b378, 0x40fca6, 0x4045d4, 0x3f8f02, 0x3ed830, 0x3e215e, ++ 0x3d6a8c, 0x3cb3ba, 0x3bfce8, 0x3b4616, 0x3a8f44, 0x39d872, ++ 0x3921a0, 0x386ace, 0x37b3fc, 0x36fd2a, 0x364658, 0x358f86, ++ 0x34d8b4, 0x3421e2, 0x336b10, 0x32b43e, 0x31fd6c, 0x31469a, ++ 0x308fc8, 0x2fd8f6, 0x2f2224, 0x2e6b52, 0x2db480, 0x2cfdae, ++ 0x2c46dc, 0x2b900a, 0x2ad938, 0x2a2266, 0x296b94, 0x28b4c2, ++ 0x27fdf0, 0x27471e, 0x26904c, 0x25d97a, 0x2522a8, 0x246bd6, ++ 0x23b504, 0x22fe32, 0x224760, 0x21908e, 0x20d9bc, 0x2022ea, ++ 0x1f6c18, 0x1eb546, 0x1dfe74, 0x1d47a2, 0x1c90d0, 0x1bd9fe, ++ 0x1b232c, 0x1a6c5a, 0x19b588, 0x18feb6, 0x1847e4, 0x179112, ++ 0x16da40, 0x16236e, 0x156c9c, 0x14b5ca, 0x13fef8, 0x134826, ++ 0x129154, 0x11da82, 0x1123b0, 0x106cde, 0x0fb60c, 0x0eff3a, ++ 0x0e4868, 0x0d9196, 0x0cdac4, 0x0c23f2, 0x0b6d20, 0x0ab64e, ++ 0x09ff7c, 0x0948aa, 0x0891d8, 0x07db06, 0x072434, 0x066d62, ++ 0x05b690, 0x04ffbe, 0x0448ec, 0x03921a, 0x02db48, 0x022476, ++ 0x016da4, 0x00b6d2, 0x000000, -0x00b6d2, -0x016da4, -0x022476, ++ -0x02db48, -0x03921a, -0x0448ec, -0x04ffbe, -0x05b690, -0x066d62, ++ -0x072434, -0x07db06, -0x0891d8, -0x0948aa, -0x09ff7c, -0x0ab64e, ++ -0x0b6d20, -0x0c23f2, -0x0cdac4, -0x0d9196, -0x0e4868, -0x0eff3a, ++ -0x0fb60c, -0x106cde, -0x1123b0, -0x11da82, -0x129154, -0x134826, ++ -0x13fef8, -0x14b5ca, -0x156c9c, -0x16236e, -0x16da40, -0x179112, ++ -0x1847e4, -0x18feb6, -0x19b588, -0x1a6c5a, -0x1b232c, -0x1bd9fe, ++ -0x1c90d0, -0x1d47a2, -0x1dfe74, -0x1eb546, -0x1f6c18, -0x2022ea, ++ -0x20d9bc, -0x21908e, -0x224760, -0x22fe32, -0x23b504, -0x246bd6, ++ -0x2522a8, -0x25d97a, -0x26904c, -0x27471e, -0x27fdf0, -0x28b4c2, ++ -0x296b94, -0x2a2266, -0x2ad938, -0x2b900a, -0x2c46dc, -0x2cfdae, ++ -0x2db480, -0x2e6b52, -0x2f2224, -0x2fd8f6, -0x308fc8, -0x31469a, ++ -0x31fd6c, -0x32b43e, -0x336b10, -0x3421e2, -0x34d8b4, -0x358f86, ++ -0x364658, -0x36fd2a, -0x37b3fc, -0x386ace, -0x3921a0, -0x39d872, ++ -0x3a8f44, -0x3b4616, -0x3bfce8, -0x3cb3ba, -0x3d6a8c, -0x3e215e, ++ -0x3ed830, -0x3f8f02, -0x4045d4, -0x40fca6, -0x41b378, -0x426a4a, ++ -0x43211c, -0x43d7ee, -0x448ec0, -0x454592, -0x45fc64, -0x46b336, ++ -0x476a08, -0x4820da, -0x48d7ac, -0x498e7e, -0x4a4550, -0x4afc22, ++ -0x4bb2f4, -0x4c69c6, -0x4d2098, -0x4dd76a, -0x4e8e3c, -0x4f450e, ++ -0x4ffbe0, -0x50b2b2, -0x516984, -0x522056, -0x52d728, -0x538dfa, ++ -0x5444cc, -0x54fb9e, -0x55b270, -0x566942, -0x572014, -0x57d6e6, ++ -0x588db8, -0x59448a, -0x59fb5c, -0x5ab22e, ++ }; ++ ++const int Cb_g_tab[(MAXJSAMPLE+1) * sizeof(int)] ={ ++ 0x2c8d00, 0x2c34e6, 0x2bdccc, 0x2b84b2, 0x2b2c98, 0x2ad47e, ++ 0x2a7c64, 0x2a244a, 0x29cc30, 0x297416, 0x291bfc, 0x28c3e2, ++ 0x286bc8, 0x2813ae, 0x27bb94, 0x27637a, 0x270b60, 0x26b346, ++ 0x265b2c, 0x260312, 0x25aaf8, 0x2552de, 0x24fac4, 0x24a2aa, ++ 0x244a90, 0x23f276, 0x239a5c, 0x234242, 0x22ea28, 0x22920e, ++ 0x2239f4, 0x21e1da, 0x2189c0, 0x2131a6, 0x20d98c, 0x208172, ++ 0x202958, 0x1fd13e, 0x1f7924, 0x1f210a, 0x1ec8f0, 0x1e70d6, ++ 0x1e18bc, 0x1dc0a2, 0x1d6888, 0x1d106e, 0x1cb854, 0x1c603a, ++ 0x1c0820, 0x1bb006, 0x1b57ec, 0x1affd2, 0x1aa7b8, 0x1a4f9e, ++ 0x19f784, 0x199f6a, 0x194750, 0x18ef36, 0x18971c, 0x183f02, ++ 0x17e6e8, 0x178ece, 0x1736b4, 0x16de9a, 0x168680, 0x162e66, ++ 0x15d64c, 0x157e32, 0x152618, 0x14cdfe, 0x1475e4, 0x141dca, ++ 0x13c5b0, 0x136d96, 0x13157c, 0x12bd62, 0x126548, 0x120d2e, ++ 0x11b514, 0x115cfa, 0x1104e0, 0x10acc6, 0x1054ac, 0x0ffc92, ++ 0x0fa478, 0x0f4c5e, 0x0ef444, 0x0e9c2a, 0x0e4410, 0x0debf6, ++ 0x0d93dc, 0x0d3bc2, 0x0ce3a8, 0x0c8b8e, 0x0c3374, 0x0bdb5a, ++ 0x0b8340, 0x0b2b26, 0x0ad30c, 0x0a7af2, 0x0a22d8, 0x09cabe, ++ 0x0972a4, 0x091a8a, 0x08c270, 0x086a56, 0x08123c, 0x07ba22, ++ 0x076208, 0x0709ee, 0x06b1d4, 0x0659ba, 0x0601a0, 0x05a986, ++ 0x05516c, 0x04f952, 0x04a138, 0x04491e, 0x03f104, 0x0398ea, ++ 0x0340d0, 0x02e8b6, 0x02909c, 0x023882, 0x01e068, 0x01884e, ++ 0x013034, 0x00d81a, 0x008000, 0x0027e6, -0x003034, -0x00884e, ++ -0x00e068, -0x013882, -0x01909c, -0x01e8b6, -0x0240d0, -0x0298ea, ++ -0x02f104, -0x03491e, -0x03a138, -0x03f952, -0x04516c, -0x04a986, ++ -0x0501a0, -0x0559ba, -0x05b1d4, -0x0609ee, -0x066208, -0x06ba22, ++ -0x07123c, -0x076a56, -0x07c270, -0x081a8a, -0x0872a4, -0x08cabe, ++ -0x0922d8, -0x097af2, -0x09d30c, -0x0a2b26, -0x0a8340, -0x0adb5a, ++ -0x0b3374, -0x0b8b8e, -0x0be3a8, -0x0c3bc2, -0x0c93dc, -0x0cebf6, ++ -0x0d4410, -0x0d9c2a, -0x0df444, -0x0e4c5e, -0x0ea478, -0x0efc92, ++ -0x0f54ac, -0x0facc6, -0x1004e0, -0x105cfa, -0x10b514, -0x110d2e, ++ -0x116548, -0x11bd62, -0x12157c, -0x126d96, -0x12c5b0, -0x131dca, ++ -0x1375e4, -0x13cdfe, -0x142618, -0x147e32, -0x14d64c, -0x152e66, ++ -0x158680, -0x15de9a, -0x1636b4, -0x168ece, -0x16e6e8, -0x173f02, ++ -0x17971c, -0x17ef36, -0x184750, -0x189f6a, -0x18f784, -0x194f9e, ++ -0x19a7b8, -0x19ffd2, -0x1a57ec, -0x1ab006, -0x1b0820, -0x1b603a, ++ -0x1bb854, -0x1c106e, -0x1c6888, -0x1cc0a2, -0x1d18bc, -0x1d70d6, ++ -0x1dc8f0, -0x1e210a, -0x1e7924, -0x1ed13e, -0x1f2958, -0x1f8172, ++ -0x1fd98c, -0x2031a6, -0x2089c0, -0x20e1da, -0x2139f4, -0x21920e, ++ -0x21ea28, -0x224242, -0x229a5c, -0x22f276, -0x234a90, -0x23a2aa, ++ -0x23fac4, -0x2452de, -0x24aaf8, -0x250312, -0x255b2c, -0x25b346, ++ -0x260b60, -0x26637a, -0x26bb94, -0x2713ae, -0x276bc8, -0x27c3e2, ++ -0x281bfc, -0x287416, -0x28cc30, -0x29244a, -0x297c64, -0x29d47e, ++ -0x2a2c98, -0x2a84b2, -0x2adccc, -0x2b34e6, ++ }; ++ ++ ++/* We assume that right shift corresponds to signed division by 2 with ++ * rounding towards minus infinity. This is correct for typical "arithmetic ++ * shift" instructions that shift in copies of the sign bit. But some ++ * C compilers implement >> with an unsigned shift. For these machines you ++ * must define RIGHT_SHIFT_IS_UNSIGNED. ++ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity. ++ * It is only applied with constant shift counts. SHIFT_TEMPS must be ++ * included in the variables of any routine using RIGHT_SHIFT. ++ */ ++ ++#ifdef RIGHT_SHIFT_IS_UNSIGNED ++#define SHIFT_TEMPS INT32 shift_temp; ++#define RIGHT_SHIFT(x,shft) \ ++ ((shift_temp = (x)) < 0 ? \ ++ (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \ ++ (shift_temp >> (shft))) ++#else ++#define SHIFT_TEMPS ++#define RIGHT_SHIFT(x,shft) ((x) >> (shft)) ++#endif ++ ++ ++METHODDEF(void) ++ycc_rgb_convert_argb (j_decompress_ptr cinfo, ++ JSAMPIMAGE input_buf, JDIMENSION input_row, ++ JSAMPARRAY output_buf, int num_rows) ++{ ++ JDIMENSION num_cols = cinfo->output_width; ++ JSAMPLE * range_limit = cinfo->sample_range_limit; ++ ++ SHIFT_TEMPS ++ ++ /* This is used if we don't have SSE2 */ ++ ++ while (--num_rows >= 0) { ++ JSAMPROW inptr0 = input_buf[0][input_row]; ++ JSAMPROW inptr1 = input_buf[1][input_row]; ++ JSAMPROW inptr2 = input_buf[2][input_row]; ++ input_row++; ++ uint32_t *outptr = (uint32_t *) *output_buf++; ++ for (JDIMENSION col = 0; col < num_cols; col++) { ++ int y = GETJSAMPLE(inptr0[col]); ++ int cb = GETJSAMPLE(inptr1[col]); ++ int cr = GETJSAMPLE(inptr2[col]); ++ JSAMPLE * range_limit_y = range_limit + y; ++ /* Range-limiting is essential due to noise introduced by DCT losses. */ ++ outptr[col] = 0xFF000000 | ++ ( range_limit_y[Cr_r_tab[cr]] << 16 ) | ++ ( range_limit_y[((int) RIGHT_SHIFT(Cb_g_tab[cb] + Cr_g_tab[cr], SCALEBITS))] << 8 ) | ++ ( range_limit_y[Cb_b_tab[cb]] ); ++ } ++ } ++} ++#endif ++ ++ + ///*************** Inverted CMYK -> RGB conversion ************************* + /// Input is (Inverted) CMYK stored as 4 bytes per pixel. + /// Output is RGB stored as 3 bytes per pixel. diff --git a/www/waterfox/files/patch-ipc_glue_MessageChannel.cpp b/www/waterfox/files/patch-ipc_glue_MessageChannel.cpp new file mode 100644 index 000000000000..9f6881a64620 --- /dev/null +++ b/www/waterfox/files/patch-ipc_glue_MessageChannel.cpp @@ -0,0 +1,16 @@ +To be removed after FreeBSD 10.* EOL + +--- ipc/glue/MessageChannel.cpp.orig 2017-11-02 16:16:32 UTC ++++ ipc/glue/MessageChannel.cpp +@@ -685,6 +685,11 @@ MessageChannel::WillDestroyCurrentMessageLoop() + mWorkerLoop = nullptr; + } + ++#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 4000 ++// Work around UB in __tree crashing mPendingPromises.clear() ++// http://llvm.org/viewvc/llvm-project?view=revision&revision=276003 ++[[clang::optnone]] ++#endif + void + MessageChannel::Clear() + { diff --git a/www/waterfox/files/patch-modules_libpref_init_all.js b/www/waterfox/files/patch-modules_libpref_init_all.js new file mode 100644 index 000000000000..75f08e466645 --- /dev/null +++ b/www/waterfox/files/patch-modules_libpref_init_all.js @@ -0,0 +1,17 @@ +- ffvpx is based on ffmpeg n3.2-65-gee56777, so prefer system ffmpeg in case + of vulnerabilites. FreeBSD package depends on ffmpeg by default, anyway. + +--- modules/libpref/init/all.js.orig 2017-11-30 00:13:43 UTC ++++ modules/libpref/init/all.js +@@ -407,7 +407,11 @@ pref("media.ffmpeg.enabled", true); + pref("media.libavcodec.allow-obsolete", false); + #endif + #if defined(MOZ_FFVPX) ++#if defined(MOZ_FFMPEG) ++pref("media.ffvpx.enabled", false); ++#else + pref("media.ffvpx.enabled", true); ++#endif + #endif + #if defined(MOZ_FFMPEG) || defined(MOZ_FFVPX) + pref("media.ffmpeg.low-latency.enabled", false); diff --git a/www/waterfox/files/patch-revert-bug1393954 b/www/waterfox/files/patch-revert-bug1393954 new file mode 100644 index 000000000000..e6200b000c49 --- /dev/null +++ b/www/waterfox/files/patch-revert-bug1393954 @@ -0,0 +1,36 @@ +Safe Browsing V2 is deprecated, switch to V4 by reverting FF56-only fix + +diff --git browser/app/profile/firefox.js browser/app/profile/firefox.js +index 276ed7dd30bb..b22d17c999a5 100644 +--- browser/app/profile/firefox.js ++++ browser/app/profile/firefox.js +@@ -1709,6 +1709,14 @@ + // Whether or not to restore a session with lazy-browser tabs. + pref("browser.sessionstore.restore_tabs_lazily", true); + ++// Enable safebrowsing v4 tables (suffixed by "-proto") update. ++pref("urlclassifier.malwareTable", "goog-malware-proto,goog-unwanted-proto,test-malware-simple,test-unwanted-simple"); ++#ifdef MOZILLA_OFFICIAL ++pref("urlclassifier.phishTable", "goog-phish-proto,test-phish-simple"); ++#else ++pref("urlclassifier.phishTable", "googpub-phish-proto,test-phish-simple"); ++#endif ++ + pref("browser.suppress_first_window_animation", true); + + // Preferences for Photon onboarding system extension +diff --git modules/libpref/init/all.js modules/libpref/init/all.js +index 5c0d1a999ff8..d95b0bcfc79e 100644 +--- modules/libpref/init/all.js ++++ modules/libpref/init/all.js +@@ -5331,8 +5331,8 @@ + #endif + + // Tables for application reputation. +-pref("urlclassifier.downloadAllowTable", "goog-downloadwhite-digest256"); +-pref("urlclassifier.downloadBlockTable", "goog-badbinurl-shavar"); ++pref("urlclassifier.downloadAllowTable", "goog-downloadwhite-proto"); ++pref("urlclassifier.downloadBlockTable", "goog-badbinurl-proto"); + + pref("urlclassifier.disallow_completions", "test-malware-simple,test-phish-simple,test-unwanted-simple,test-track-simple,test-trackwhite-simple,test-block-simple,goog-downloadwhite-digest256,base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,except-flashinfobar-digest256"); + diff --git a/www/waterfox/files/patch-sample-type b/www/waterfox/files/patch-sample-type new file mode 100644 index 000000000000..cf460a0f84dc --- /dev/null +++ b/www/waterfox/files/patch-sample-type @@ -0,0 +1,13 @@ +# Let ports handle default sample type + +--- old-configure.in~ ++++ old-configure.in +@@ -5144,7 +5144,7 @@ dnl Use integers over floats for audio o + dnl (regarless of the CPU architecture, because audio + dnl backends for those platforms don't support floats. We also + dnl use integers on ARM with other OS, because it's more efficient. +-if test "$OS_TARGET" = "Android" -o "$CPU_ARCH" = "arm"; then ++if test -n "$MOZ_INTEGER_SAMPLES"; then + MOZ_SAMPLE_TYPE_S16=1 + AC_DEFINE(MOZ_SAMPLE_TYPE_S16) + AC_SUBST(MOZ_SAMPLE_TYPE_S16) diff --git a/www/waterfox/files/patch-waterfox286 b/www/waterfox/files/patch-waterfox286 new file mode 100644 index 000000000000..9af014dc19d1 --- /dev/null +++ b/www/waterfox/files/patch-waterfox286 @@ -0,0 +1,15 @@ +Revert 3e46c9b52447 as it has the opposite effect + +--- browser/branding/unofficial/configure.sh.orig 2017-11-30 00:13:43 UTC ++++ browser/branding/unofficial/configure.sh +@@ -12,10 +12,3 @@ elif test "$OS_ARCH" = "Darwin"; then + else + MOZ_APP_PROFILE=Waterfox + fi +- +-MOZ_TELEMETRY_REPORTING=0 +-MOZ_REQUIRE_SIGNING=0 +-MOZ_ADOBE_EME=0 +-MOZ_SERVICES_HEALTHREPORT=0 +-MOZ_CRASHREPORTER=0 +-MOZ_DATA_REPORTING=0 diff --git a/www/waterfox/files/patch-z-bug1355143 b/www/waterfox/files/patch-z-bug1355143 new file mode 100644 index 000000000000..5199912ff774 --- /dev/null +++ b/www/waterfox/files/patch-z-bug1355143 @@ -0,0 +1,384 @@ +commit ebd5363fd4ff +Author: Martin Stransky <stransky@redhat.com> +Date: Wed Apr 18 11:03:39 2018 +0200 + + Bug 1355143 - Implement CreateStyleContextWithStates to style with fully stated css path, r=jhorak a=lizzard + + MozReview-Commit-ID: ENWBekzq4Oq + + --HG-- + extra : source : 8683842b60582c60de0226d1398c335a7e1a7b3f +--- + widget/gtk/WidgetStyleCache.cpp | 30 ++++++++++++++++++++++++++++++ + widget/gtk/WidgetStyleCache.h | 19 ++++++++++++++++++- + widget/gtk/mozgtk/mozgtk.c | 1 + + 3 files changed, 49 insertions(+), 1 deletion(-) + +diff --git widget/gtk/WidgetStyleCache.cpp widget/gtk/WidgetStyleCache.cpp +index 0b69b6c83f24..8ee7e49ee48d 100644 +--- widget/gtk/WidgetStyleCache.cpp ++++ widget/gtk/WidgetStyleCache.cpp +@@ -1514,3 +1514,33 @@ GetStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection, + } + return style; + } ++ ++GtkStyleContext* ++CreateStyleContextWithStates(WidgetNodeType aNodeType, GtkTextDirection aDirection, ++ GtkStateFlags aStateFlags) ++{ ++ GtkStyleContext* style = GetStyleContext(aNodeType, aDirection, aStateFlags); ++ GtkWidgetPath *path = gtk_widget_path_copy(gtk_style_context_get_path(style)); ++ ++ if (gtk_check_version(3, 14, 0) == nullptr) { ++ ++ static auto sGtkWidgetPathIterGetState = ++ (GtkStateFlags (*)(const GtkWidgetPath*, gint)) ++ dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_get_state"); ++ static auto sGtkWidgetPathIterSetState = ++ (void (*)(GtkWidgetPath*, gint, GtkStateFlags)) ++ dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_set_state"); ++ ++ int pathLength = gtk_widget_path_length(path); ++ for(int i = 0; i < pathLength; i++) { ++ unsigned state = aStateFlags | sGtkWidgetPathIterGetState(path, i); ++ sGtkWidgetPathIterSetState(path, i, GtkStateFlags(state)); ++ } ++ } ++ ++ style = gtk_style_context_new(); ++ gtk_style_context_set_path(style, path); ++ gtk_widget_path_unref(path); ++ ++ return style; ++} +diff --git widget/gtk/WidgetStyleCache.h widget/gtk/WidgetStyleCache.h +index 1e7748dfb17c..e434bc8230b0 100644 +--- widget/gtk/WidgetStyleCache.h ++++ widget/gtk/WidgetStyleCache.h +@@ -38,7 +38,13 @@ CreateCSSNode(const char* aName, + + /* + * Returns a pointer to a style context for the specified node and state. +- * The context is owned by WidgetStyleCache. Do not unref. ++ * aStateFlags is applied only to last widget in css style path, ++ * for instance GetStyleContext(MOZ_GTK_BUTTON, .., GTK_STATE_FLAG_HOVER) ++ * you get "window button:hover" css selector. ++ * If you want aStateFlags applied to all path elements use ++ * CreateStyleContextWithStates(). ++ * ++ * The context is owned by WidgetStyleCache. Do not unref. + */ + GtkStyleContext* + GetStyleContext(WidgetNodeType aNodeType, +@@ -46,6 +52,17 @@ GetStyleContext(WidgetNodeType aNodeType, + GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL, + StyleFlags aFlags = NO_STYLE_FLAGS); + ++/* ++ * Returns a pointer to a style context for the specified node ++ * and state applied to all elements at widget style path. ++ * ++ * The context is owned by caller and must be released by g_object_unref(). ++ */ ++GtkStyleContext* ++CreateStyleContextWithStates(WidgetNodeType aNodeType, ++ GtkTextDirection aDirection = GTK_TEXT_DIR_NONE, ++ GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL); ++ + void + ResetWidgetCache(void); + +diff --git widget/gtk/mozgtk/mozgtk.c widget/gtk/mozgtk/mozgtk.c +index 8ed3d7eae82c..b29154a101bf 100644 +--- widget/gtk/mozgtk/mozgtk.c ++++ widget/gtk/mozgtk/mozgtk.c +@@ -601,6 +601,7 @@ STUB(gtk_widget_path_copy) + STUB(gtk_widget_path_free) + STUB(gtk_widget_path_iter_add_class) + STUB(gtk_widget_path_get_object_type) ++STUB(gtk_widget_path_length) + STUB(gtk_widget_path_new) + STUB(gtk_widget_path_unref) + STUB(gtk_widget_set_valign) + +commit b807309b6108 +Author: Martin Stransky <stransky@redhat.com> +Date: Wed Apr 18 11:05:46 2018 +0200 + + Bug 1355143 - Provide ScrollbarGTKMetrics for active (mouse over) scrollbars, r=jhorak a=lizzard + + MozReview-Commit-ID: 95d1jeQ8mXd + + --HG-- + extra : source : 111bb4416a8541abbe481459c6c3f6189dc2eb56 +--- + widget/gtk/gtk3drawing.cpp | 67 +++++++++++++++++++++++++++++++++++++--------- + widget/gtk/gtkdrawing.h | 10 ++++++- + 2 files changed, 63 insertions(+), 14 deletions(-) + +diff --git widget/gtk/gtk3drawing.cpp widget/gtk/gtk3drawing.cpp +index 357d8a5ce5b9..3df564b05d0e 100644 +--- widget/gtk/gtk3drawing.cpp ++++ widget/gtk/gtk3drawing.cpp +@@ -24,6 +24,7 @@ static gboolean checkbox_check_state; + static gboolean notebook_has_tab_gap; + + static ScrollbarGTKMetrics sScrollbarMetrics[2]; ++static ScrollbarGTKMetrics sScrollbarMetricsActive[2]; + static ToggleGTKMetrics sCheckboxMetrics; + static ToggleGTKMetrics sRadioMetrics; + static ToolbarGTKMetrics sToolbarMetrics; +@@ -182,6 +183,8 @@ moz_gtk_refresh() + + sScrollbarMetrics[GTK_ORIENTATION_HORIZONTAL].initialized = false; + sScrollbarMetrics[GTK_ORIENTATION_VERTICAL].initialized = false; ++ sScrollbarMetricsActive[GTK_ORIENTATION_HORIZONTAL].initialized = false; ++ sScrollbarMetricsActive[GTK_ORIENTATION_VERTICAL].initialized = false; + sCheckboxMetrics.initialized = false; + sRadioMetrics.initialized = false; + sToolbarMetrics.initialized = false; +@@ -740,10 +743,9 @@ GetMinContentBox(GtkStyleContext* style) + * min-width/min-height. + */ + static void +-moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, ++moz_gtk_get_widget_min_size(GtkStyleContext* style, int* width, + int* height) + { +- GtkStyleContext* style = GetStyleContext(aGtkWidgetType); + GtkStateFlags state_flags = gtk_style_context_get_state(style); + gtk_style_context_get(style, state_flags, + "min-height", height, +@@ -762,10 +764,10 @@ moz_gtk_get_widget_min_size(WidgetNodeType aGtkWidgetType, int* width, + } + + static MozGtkSize +-GetMinMarginBox(WidgetNodeType aNodeType) ++GetMinMarginBox(GtkStyleContext* style) + { + gint width, height; +- moz_gtk_get_widget_min_size(aNodeType, &width, &height); ++ moz_gtk_get_widget_min_size(style, &width, &height); + return {width, height}; + } + +@@ -947,7 +949,7 @@ moz_gtk_scrollbar_trough_paint(WidgetNodeType widget, + WidgetNodeType thumb = widget == MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL ? + MOZ_GTK_SCROLLBAR_THUMB_VERTICAL : + MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL; +- MozGtkSize thumbSize = GetMinMarginBox(thumb); ++ MozGtkSize thumbSize = GetMinMarginBox(GetStyleContext(thumb)); + style = GetStyleContext(widget, direction); + MozGtkSize trackSize = GetMinContentBox(style); + trackSize.Include(thumbSize); +@@ -2765,7 +2767,8 @@ moz_gtk_get_scale_metrics(GtkOrientation orient, gint* scale_width, + WidgetNodeType widget = (orient == GTK_ORIENTATION_HORIZONTAL) ? + MOZ_GTK_SCALE_TROUGH_HORIZONTAL : + MOZ_GTK_SCALE_TROUGH_VERTICAL; +- moz_gtk_get_widget_min_size(widget, scale_width, scale_height); ++ moz_gtk_get_widget_min_size(GetStyleContext(widget), ++ scale_width, scale_height); + } + } + +@@ -2884,9 +2887,10 @@ GetToggleMetrics(bool isRadio) + } + + const ScrollbarGTKMetrics* +-GetScrollbarMetrics(GtkOrientation aOrientation) ++GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive) + { +- auto metrics = &sScrollbarMetrics[aOrientation]; ++ auto metrics = aActive ? &sScrollbarMetricsActive[aOrientation] : ++ &sScrollbarMetrics[aOrientation]; + if (metrics->initialized) + return metrics; + +@@ -2896,7 +2900,9 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + MOZ_GTK_SCROLLBAR_HORIZONTAL : MOZ_GTK_SCROLLBAR_VERTICAL; + + gboolean backward, forward, secondary_backward, secondary_forward; +- GtkStyleContext* style = GetStyleContext(scrollbar); ++ GtkStyleContext* style = GetStyleContext(scrollbar, GTK_TEXT_DIR_NONE, ++ aActive ? GTK_STATE_FLAG_PRELIGHT : ++ GTK_STATE_FLAG_NORMAL); + gtk_style_context_get_style(style, + "has-backward-stepper", &backward, + "has-forward-stepper", &forward, +@@ -2963,16 +2969,48 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + track = MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL; + thumb = MOZ_GTK_SCROLLBAR_THUMB_VERTICAL; + } ++ ++ /* GetStyleContext() sets GtkStateFlags to the latest widget name ++ * in css selector string. When we call: ++ * ++ * GetStyleContext(thumb, GTK_STATE_FLAG_PRELIGHT) ++ * ++ * we get: ++ * ++ * "scrollbar contents trough slider:hover" ++ * ++ * Some themes (Ubuntu Ambiance) styles trough/thumb by scrollbar, ++ * the Gtk+ css rule looks like: ++ * ++ * "scrollbar:hover contents trough slider" ++ * ++ * So we need to apply GtkStateFlags to each widgets in style path. ++ */ ++ + // thumb +- metrics->size.thumb = GetMinMarginBox(thumb); ++ style = CreateStyleContextWithStates(thumb, GTK_TEXT_DIR_NONE, ++ aActive ? GTK_STATE_FLAG_PRELIGHT : ++ GTK_STATE_FLAG_NORMAL); ++ metrics->size.thumb = GetMinMarginBox(style); ++ g_object_unref(style); ++ + // track +- style = GetStyleContext(track); ++ style = CreateStyleContextWithStates(track, GTK_TEXT_DIR_NONE, ++ aActive ? GTK_STATE_FLAG_PRELIGHT : ++ GTK_STATE_FLAG_NORMAL); + metrics->border.track = GetMarginBorderPadding(style); + MozGtkSize trackMinSize = GetMinContentBox(style) + metrics->border.track; + MozGtkSize trackSizeForThumb = metrics->size.thumb + metrics->border.track; ++ g_object_unref(style); ++ + // button + if (hasButtons) { +- metrics->size.button = GetMinMarginBox(MOZ_GTK_SCROLLBAR_BUTTON); ++ style = CreateStyleContextWithStates(MOZ_GTK_SCROLLBAR_BUTTON, ++ GTK_TEXT_DIR_NONE, ++ aActive ? GTK_STATE_FLAG_PRELIGHT : ++ GTK_STATE_FLAG_NORMAL); ++ metrics->size.button = GetMinMarginBox(style); ++ g_object_unref(style); + } else { + metrics->size.button = {0, 0}; + } +@@ -3006,8 +3044,11 @@ GetScrollbarMetrics(GtkOrientation aOrientation) + } + } + +- style = GetStyleContext(contents); ++ style = CreateStyleContextWithStates(contents, GTK_TEXT_DIR_NONE, ++ aActive ? GTK_STATE_FLAG_PRELIGHT : ++ GTK_STATE_FLAG_NORMAL); + GtkBorder contentsBorder = GetMarginBorderPadding(style); ++ g_object_unref(style); + + metrics->size.scrollbar = + trackSizeForThumb + contentsBorder + metrics->border.scrollbar; +diff --git widget/gtk/gtkdrawing.h widget/gtk/gtkdrawing.h +index 2ce31a3dc68a..47da7c1ccaac 100644 +--- widget/gtk/gtkdrawing.h ++++ widget/gtk/gtkdrawing.h +@@ -53,6 +53,11 @@ struct MozGtkSize { + MozGtkSize result = *this; + return result += aBorder; + } ++ bool operator<(const MozGtkSize &aOther) const ++ { ++ return (width < aOther.width && height <= aOther.height) || ++ (width <= aOther.width && height < aOther.height); ++ } + void Include(MozGtkSize aOther) + { + width = std::max(width, aOther.width); +@@ -491,9 +496,12 @@ moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* + + /** + * Get the metrics in GTK pixels for a scrollbar. ++ * aOrientation: [IN] the scrollbar orientation ++ * aActive: [IN] Metricts for scrollbar with mouse pointer over it. ++ * + */ + const ScrollbarGTKMetrics* +-GetScrollbarMetrics(GtkOrientation aOrientation); ++GetScrollbarMetrics(GtkOrientation aOrientation, bool aActive = false); + + /** + * Get the desired size of a dropdown arrow button + +commit e31268bc56be +Author: Martin Stransky <stransky@redhat.com> +Date: Wed Apr 18 11:09:19 2018 +0200 + + Bug 1355143 - Size scrollbars with 'hover' Gtk+ state, r=jhorak a=lizzard + + Ubuntu/Ambiance has tiny scrollbars when it's not hovered by mouse and large + ones when it's hovered/active. Our current Gtk+ toolkit code does not support such scrollbar + resize on the fly. + + We use a workaround as we get size of active (hovered) scrollbar only and that + we pass to gecko. Then we draw scrolbar smaller when it's not hovered and full sized + when it's hovered. + + MozReview-Commit-ID: mxt9q5Bcg9 + + --HG-- + extra : source : 4405d1c4673b0b1eb415b528c5e252585094b150 +--- + widget/gtk/nsNativeThemeGTK.cpp | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git widget/gtk/nsNativeThemeGTK.cpp widget/gtk/nsNativeThemeGTK.cpp +index 059bd38f69cd..25b6105cd5f4 100644 +--- widget/gtk/nsNativeThemeGTK.cpp ++++ widget/gtk/nsNativeThemeGTK.cpp +@@ -1287,7 +1287,7 @@ nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); ++ const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); + + const GtkBorder& border = metrics->border.scrollbar; + aResult->top = border.top; +@@ -1302,7 +1302,7 @@ nsNativeThemeGTK::GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame, + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBARTRACK_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); ++ const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); + + const GtkBorder& border = metrics->border.track; + aResult->top = border.top; +@@ -1457,7 +1457,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, + case NS_THEME_SCROLLBARBUTTON_DOWN: + { + const ScrollbarGTKMetrics* metrics = +- GetScrollbarMetrics(GTK_ORIENTATION_VERTICAL); ++ GetScrollbarMetrics(GTK_ORIENTATION_VERTICAL, true); + + aResult->width = metrics->size.button.width; + aResult->height = metrics->size.button.height; +@@ -1468,7 +1468,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, + case NS_THEME_SCROLLBARBUTTON_RIGHT: + { + const ScrollbarGTKMetrics* metrics = +- GetScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL); ++ GetScrollbarMetrics(GTK_ORIENTATION_HORIZONTAL, true); + + aResult->width = metrics->size.button.width; + aResult->height = metrics->size.button.height; +@@ -1501,7 +1501,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); ++ const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); + + aResult->width = metrics->size.scrollbar.width; + aResult->height = metrics->size.scrollbar.height; +@@ -1513,7 +1513,7 @@ nsNativeThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext, + GtkOrientation orientation = + aWidgetType == NS_THEME_SCROLLBARTHUMB_HORIZONTAL ? + GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; +- const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation); ++ const ScrollbarGTKMetrics* metrics = GetScrollbarMetrics(orientation, true); + + aResult->width = metrics->size.thumb.width; + aResult->height = metrics->size.thumb.height; diff --git a/www/waterfox/files/patch-z-bug1382366 b/www/waterfox/files/patch-z-bug1382366 new file mode 100644 index 000000000000..bdc3afee6f63 --- /dev/null +++ b/www/waterfox/files/patch-z-bug1382366 @@ -0,0 +1,159 @@ +commit bc308d794057 +Author: Karl Tomlinson <karlt+@karlt.net> +Date: Sat Nov 4 19:00:46 2017 +1300 + + Bug 1382366 - Disable AudioCallback -> SystemClockDriver fallback before disowning graph. f=pehrsons, r=padenot, a=gchang + + MozReview-Commit-ID: ESr6yxjPVWf + + --HG-- + extra : rebase_source : 6ed3093ab9dec68515f39353dc46ab40780cd161 + extra : source : 53f055298fa9d2446fd90ad8a51fefd3b15b16c1 +--- + dom/media/GraphDriver.cpp | 38 +++++++++++--------------------------- + dom/media/GraphDriver.h | 14 ++++++++------ + 2 files changed, 19 insertions(+), 33 deletions(-) + +diff --git dom/media/GraphDriver.cpp dom/media/GraphDriver.cpp +index 13944338e3d7..62c847e90155 100644 +--- dom/media/GraphDriver.cpp ++++ dom/media/GraphDriver.cpp +@@ -33,8 +33,7 @@ GraphDriver::GraphDriver(MediaStreamGraphImpl* aGraphImpl) + mWaitState(WAITSTATE_RUNNING), + mCurrentTimeStamp(TimeStamp::Now()), + mPreviousDriver(nullptr), +- mNextDriver(nullptr), +- mScheduled(false) ++ mNextDriver(nullptr) + { } + + void GraphDriver::SetGraphTime(GraphDriver* aPreviousDriver, +@@ -121,12 +120,6 @@ void GraphDriver::SetPreviousDriver(GraphDriver* aPreviousDriver) + mPreviousDriver = aPreviousDriver; + } + +-bool GraphDriver::Scheduled() +-{ +- GraphImpl()->GetMonitor().AssertCurrentThreadOwns(); +- return mScheduled; +-} +- + ThreadedDriver::ThreadedDriver(MediaStreamGraphImpl* aGraphImpl) + : GraphDriver(aGraphImpl) + { } +@@ -216,8 +209,7 @@ ThreadedDriver::Start() + // Note: mThread may be null during event->Run() if we pass to NewNamedThread! See AudioInitTask + nsresult rv = NS_NewNamedThread("MediaStreamGrph", getter_AddRefs(mThread)); + if (NS_SUCCEEDED(rv)) { +- rv = mThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL); +- mScheduled = NS_SUCCEEDED(rv); ++ mThread->EventTarget()->Dispatch(event.forget(), NS_DISPATCH_NORMAL); + } + } + } +@@ -545,6 +537,7 @@ AudioCallbackDriver::AudioCallbackDriver(MediaStreamGraphImpl* aGraphImpl) + , mAddedMixer(false) + , mInCallback(false) + , mMicrophoneActive(false) ++ , mShouldFallbackIfError(false) + , mFromFallback(false) + { + LOG(LogLevel::Debug, ("AudioCallbackDriver ctor for graph %p", aGraphImpl)); +@@ -765,13 +758,13 @@ AudioCallbackDriver::Start() + "to ensure it runs after previous shutdown.")); + RefPtr<AsyncCubebTask> initEvent = + new AsyncCubebTask(AsAudioCallbackDriver(), AsyncCubebOperation::INIT); +- nsresult rv = initEvent->Dispatch(); +- mScheduled = NS_SUCCEEDED(rv); ++ initEvent->Dispatch(); + } + + bool + AudioCallbackDriver::StartStream() + { ++ mShouldFallbackIfError = true; + if (cubeb_stream_start(mAudioStream) != CUBEB_OK) { + NS_WARNING("Could not start cubeb stream for MSG."); + return false; +@@ -1015,6 +1008,10 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, + mSampleRate, mOutputChannels); + + if (!stillProcessing) { ++ // About to hand over control of the graph. Do not start a new driver if ++ // StateCallback() receives an error for this stream while the main thread ++ // or another driver has control of the graph. ++ mShouldFallbackIfError = false; + // Enter shutdown mode. The stable-state handler will detect this + // and complete shutdown if the graph does not get restarted. + mGraphImpl->SignalMainThreadCleanup(); +@@ -1028,6 +1025,7 @@ AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer, + } + + if (switching) { ++ mShouldFallbackIfError = false; + // If the audio stream has not been started by the previous driver or + // the graph itself, keep it alive. + MonitorAutoLock mon(mGraphImpl->GetMonitor()); +@@ -1052,22 +1050,8 @@ AudioCallbackDriver::StateCallback(cubeb_state aState) + { + LOG(LogLevel::Debug, ("AudioCallbackDriver State: %d", aState)); + +- if (aState == CUBEB_STATE_ERROR) { +- if (!mAudioStream) { +- // If we don't have an audio stream here, this means that the stream +- // initialization has failed. A fallback on a SystemCallDriver will happen at +- // the callsite of `cubeb_stream_init`. +- return; +- } +- ++ if (aState == CUBEB_STATE_ERROR && mShouldFallbackIfError) { + MonitorAutoLock lock(GraphImpl()->GetMonitor()); +- +- if (NextDriver() && NextDriver()->Scheduled()) { +- // We are switching to another driver that has already been scheduled +- // to be initialized and started. There's nothing for us to do here. +- return; +- } +- + // Fall back to a driver using a normal thread. If needed, + // the graph will try to re-open an audio stream later. + SystemClockDriver* nextDriver = new SystemClockDriver(GraphImpl()); +diff --git dom/media/GraphDriver.h dom/media/GraphDriver.h +index 4857d74b114a..1f8b9386c6fa 100644 +--- dom/media/GraphDriver.h ++++ dom/media/GraphDriver.h +@@ -146,9 +146,6 @@ public: + void SetNextDriver(GraphDriver* aNextDriver); + void SetPreviousDriver(GraphDriver* aPreviousDriver); + +- /* Return whether we have been scheduled to start. */ +- bool Scheduled(); +- + /** + * If we are running a real time graph, get the current time stamp to schedule + * video frames. This has to be reimplemented by real time drivers. +@@ -252,9 +249,6 @@ protected: + // driver at the end of this iteration. + // This must be accessed using the {Set,Get}NextDriver methods. + RefPtr<GraphDriver> mNextDriver; +- // This is initially false, but set to true as soon the driver has been +- // scheduled to start through GraphDriver::Start(). +- bool mScheduled; + virtual ~GraphDriver() + { } + }; +@@ -558,6 +552,14 @@ private: + * True if microphone is being used by this process. This is synchronized by + * the graph's monitor. */ + Atomic<bool> mMicrophoneActive; ++ /* Indication of whether a fallback SystemClockDriver should be started if ++ * StateCallback() receives an error. No mutex need be held during access. ++ * The transition to true happens before cubeb_stream_start() is called. ++ * After transitioning to false on the last DataCallback(), the stream is ++ * not accessed from another thread until the graph thread either signals ++ * main thread cleanup or dispatches an event to switch to another ++ * driver. */ ++ bool mShouldFallbackIfError; + /* True if this driver was created from a driver created because of a previous + * AudioCallbackDriver failure. */ + bool mFromFallback; diff --git a/www/waterfox/files/patch-z-bug1392739 b/www/waterfox/files/patch-z-bug1392739 new file mode 100644 index 000000000000..48c8d1b43ce2 --- /dev/null +++ b/www/waterfox/files/patch-z-bug1392739 @@ -0,0 +1,28 @@ +commit ef5f80343490 +Author: Valentin Gosu <valentin.gosu@gmail.com> +Date: Mon Jun 4 13:57:51 2018 +0200 + + Bug 1392739 - Use CheckedInt in nsStandardURL::Deserialize(). r=mayhemer, a=RyanVM + + --HG-- + extra : source : 5c47f8a1bad20a61a1ec699cc6508e21f39a7a98 +--- + netwerk/base/nsStandardURL.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git netwerk/base/nsStandardURL.cpp netwerk/base/nsStandardURL.cpp +index db7bf74f31812..4d3da91f88b20 100644 +--- netwerk/base/nsStandardURL.cpp ++++ netwerk/base/nsStandardURL.cpp +@@ -3552,8 +3551,10 @@ FromIPCSegment(const nsACString& aSpec, const ipc::StandardURLSegment& aSegment, + return false; + } + ++ CheckedInt<uint32_t> segmentLen = aSegment.position(); ++ segmentLen += aSegment.length(); + // Make sure the segment does not extend beyond the spec. +- if (NS_WARN_IF(aSegment.position() + aSegment.length() > aSpec.Length())) { ++ if (NS_WARN_IF(!segmentLen.isValid() || segmentLen.value() > aSpec.Length())) { + return false; + } + diff --git a/www/waterfox/files/patch-z-bug1436267 b/www/waterfox/files/patch-z-bug1436267 new file mode 100644 index 000000000000..2dcf0fb4ae40 --- /dev/null +++ b/www/waterfox/files/patch-z-bug1436267 @@ -0,0 +1,37 @@ +commit fde373d05f1a +Author: Karl Tomlinson <karlt+@karlt.net> +Date: Wed Feb 7 20:16:01 2018 +1300 + + bug 1436267 fallback from audio callback to system clock driver on error only once r=padenot a=ritu + + Usually, mShouldFallbackIfError has been reset to false in DataCallback() + before Stop() is called. However, if fallback to a system clock driver due to + cubeb error had already occurred, then mShouldFallbackIfError would not have + been reset, and Stop() is still called. With mShouldFallbackIfError still + true, a cubeb error in stop would have created another fallback thread. + + I expect that resetting mShouldFallbackIfError in Stop() would also be an + effective alternative solution, but resetting on StateCallback() happens + earlier, which would be an advantage if any additional errors could possibly + be reported to StateCallback(). + + MozReview-Commit-ID: E9j7PQmS3O4 + + --HG-- + extra : source : c96fdc3e0d635b2036996f30ecf5d667d1d62027 +--- + dom/media/GraphDriver.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git dom/media/GraphDriver.cpp dom/media/GraphDriver.cpp +index f37568e21816..54e46fa81e69 100644 +--- dom/media/GraphDriver.cpp ++++ dom/media/GraphDriver.cpp +@@ -1039,6 +1039,7 @@ AudioCallbackDriver::StateCallback(cubeb_state aState) + LOG(LogLevel::Debug, ("AudioCallbackDriver State: %d", aState)); + + if (aState == CUBEB_STATE_ERROR && mShouldFallbackIfError) { ++ mShouldFallbackIfError = false; + MonitorAutoLock lock(GraphImpl()->GetMonitor()); + RemoveCallback(); + FallbackToSystemClockDriver(); diff --git a/www/waterfox/files/patch-z-bug1461619 b/www/waterfox/files/patch-z-bug1461619 new file mode 100644 index 000000000000..cc7c7748ec98 --- /dev/null +++ b/www/waterfox/files/patch-z-bug1461619 @@ -0,0 +1,151 @@ +commit 9a87f28720d2 +Author: Jon Coppeard <jcoppeard@mozilla.com> +Date: Mon Jun 4 11:18:27 2018 +0100 + + Bug 1461619 - Don't update atoms marking bitmaps in parallel due to potential races. r=sfink, a=RyanVM +--- + js/src/gc/AtomMarking.cpp | 20 +++++++++++--------- + js/src/gc/AtomMarking.h | 6 +++--- + js/src/gc/GC.cpp | 26 ++++++++++++++------------ + 3 files changed, 28 insertions(+), 24 deletions(-) + +diff --git js/src/gc/AtomMarking.cpp js/src/gc/AtomMarking.cpp +index 64348293f0eac..fbe005a43a46a 100644 +--- js/src/gc/AtomMarking.cpp ++++ js/src/gc/AtomMarking.cpp +@@ -28,12 +28,12 @@ namespace gc { + // is done by manipulating the mark bitmaps in the chunks used for the atoms. + // When the atoms zone is being collected, the mark bitmaps for the chunk(s) + // used by the atoms are updated normally during marking. After marking +-// finishes, the chunk mark bitmaps are translated to a more efficient atom +-// mark bitmap (see below) that is stored on the zones which the GC collected ++// finishes, the chunk mark bitmaps are translated to a more efficient atom mark ++// bitmap (see below) that is stored on the zones which the GC collected + // (computeBitmapFromChunkMarkBits). Before sweeping begins, the chunk mark + // bitmaps are updated with any atoms that might be referenced by zones which +-// weren't collected (updateChunkMarkBits). The GC sweeping will then release +-// all atoms which are not marked by any zone. ++// weren't collected (markAtomsUsedByUncollectedZones). The GC sweeping will ++// then release all atoms which are not marked by any zone. + // + // The representation of atom mark bitmaps is as follows: + // +@@ -95,8 +95,10 @@ AtomMarkingRuntime::computeBitmapFromChunkMarkBits(JSRuntime* runtime, DenseBitm + } + + void +-AtomMarkingRuntime::updateZoneBitmap(Zone* zone, const DenseBitmap& bitmap) ++AtomMarkingRuntime::refineZoneBitmapForCollectedZone(Zone* zone, const DenseBitmap& bitmap) + { ++ MOZ_ASSERT(zone->isCollectingFromAnyThread()); ++ + if (zone->isAtomsZone()) + return; + +@@ -109,7 +111,7 @@ AtomMarkingRuntime::updateZoneBitmap(Zone* zone, const DenseBitmap& bitmap) + // Set any bits in the chunk mark bitmaps for atoms which are marked in bitmap. + template <typename Bitmap> + static void +-AddBitmapToChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap) ++BitwiseOrIntoChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap) + { + // Make sure that by copying the mark bits for one arena in word sizes we + // do not affect the mark bits for other arenas. +@@ -127,7 +129,7 @@ AddBitmapToChunkMarkBits(JSRuntime* runtime, Bitmap& bitmap) + } + + void +-AtomMarkingRuntime::updateChunkMarkBits(JSRuntime* runtime) ++AtomMarkingRuntime::markAtomsUsedByUncollectedZones(JSRuntime* runtime) + { + MOZ_ASSERT(runtime->currentThreadHasExclusiveAccess()); + +@@ -143,11 +145,11 @@ AtomMarkingRuntime::updateChunkMarkBits(JSRuntime* runtime) + if (!zone->isCollectingFromAnyThread()) + zone->markedAtoms().bitwiseOrInto(markedUnion); + } +- AddBitmapToChunkMarkBits(runtime, markedUnion); ++ BitwiseOrIntoChunkMarkBits(runtime, markedUnion); + } else { + for (ZonesIter zone(runtime, SkipAtoms); !zone.done(); zone.next()) { + if (!zone->isCollectingFromAnyThread()) +- AddBitmapToChunkMarkBits(runtime, zone->markedAtoms()); ++ BitwiseOrIntoChunkMarkBits(runtime, zone->markedAtoms()); + } + } + } +diff --git js/src/gc/AtomMarking.h js/src/gc/AtomMarking.h +index 78aa612f79c9a..3a2c22c1d4d7e 100644 +--- js/src/gc/AtomMarking.h ++++ js/src/gc/AtomMarking.h +@@ -52,11 +52,11 @@ class AtomMarkingRuntime + + // Update the atom marking bitmap in |zone| according to another + // overapproximation of the reachable atoms in |bitmap|. +- void updateZoneBitmap(Zone* zone, const DenseBitmap& bitmap); ++ void refineZoneBitmapForCollectedZone(Zone* zone, const DenseBitmap& bitmap); + + // Set any bits in the chunk mark bitmaps for atoms which are marked in any +- // zone in the runtime. +- void updateChunkMarkBits(JSRuntime* runtime); ++ // uncollected zone in the runtime. ++ void markAtomsUsedByUncollectedZones(JSRuntime* runtime); + + // Mark an atom or id as being newly reachable by the context's zone. + template <typename T> void markAtom(JSContext* cx, T* thing); +diff --git js/src/jsgc.cpp js/src/jsgc.cpp +index b5bbac865cfdf..f0d9d3e95e8a3 100644 +--- js/src/jsgc.cpp ++++ js/src/jsgc.cpp +@@ -4989,21 +4989,19 @@ class ImmediateSweepWeakCacheTask : public GCParallelTaskHelper<ImmediateSweepWe + }; + + static void +-UpdateAtomsBitmap(GCParallelTask* task) ++UpdateAtomsBitmap(JSRuntime* runtime) + { +- JSRuntime* runtime = task->runtime(); +- + DenseBitmap marked; + if (runtime->gc.atomMarking.computeBitmapFromChunkMarkBits(runtime, marked)) { + for (GCZonesIter zone(runtime); !zone.done(); zone.next()) +- runtime->gc.atomMarking.updateZoneBitmap(zone, marked); ++ runtime->gc.atomMarking.refineZoneBitmapForCollectedZone(zone, marked); + } else { +- // Ignore OOM in computeBitmapFromChunkMarkBits. The updateZoneBitmap +- // call can only remove atoms from the zone bitmap, so it is +- // conservative to just not call it. ++ // Ignore OOM in computeBitmapFromChunkMarkBits. The ++ // refineZoneBitmapForCollectedZone call can only remove atoms from the ++ // zone bitmap, so it is conservative to just not call it. + } + +- runtime->gc.atomMarking.updateChunkMarkBits(runtime); ++ runtime->gc.atomMarking.markAtomsUsedByUncollectedZones(runtime); + + // For convenience sweep these tables non-incrementally as part of bitmap + // sweeping; they are likely to be much smaller than the main atoms table. +@@ -5305,15 +5303,19 @@ GCRuntime::beginSweepingSweepGroup() + callFinalizeCallbacks(&fop, JSFINALIZE_GROUP_START); + } + ++ // Updating the atom marking bitmaps. This marks atoms referenced by ++ // uncollected zones so cannot be done in parallel with the other sweeping ++ // work below. ++ if (sweepingAtoms) { ++ AutoPhase ap(stats(), PhaseKind::UPDATE_ATOMS_BITMAP); ++ UpdateAtomsBitmap(rt); ++ } ++ + sweepDebuggerOnMainThread(&fop); + + { + AutoLockHelperThreadState lock; + +- Maybe<AutoRunParallelTask> updateAtomsBitmap; +- if (sweepingAtoms) +- updateAtomsBitmap.emplace(rt, UpdateAtomsBitmap, PhaseKind::UPDATE_ATOMS_BITMAP, lock); +- + AutoPhase ap(stats(), PhaseKind::SWEEP_COMPARTMENTS); + + AutoRunParallelTask sweepCCWrappers(rt, SweepCCWrappers, PhaseKind::SWEEP_CC_WRAPPER, lock); diff --git a/www/waterfox/files/patch-z-bug517422 b/www/waterfox/files/patch-z-bug517422 new file mode 100644 index 000000000000..debf8d5a7afd --- /dev/null +++ b/www/waterfox/files/patch-z-bug517422 @@ -0,0 +1,502 @@ +# Allow more config/external/ libs built against system-wide version. + +diff --git build/moz.configure/old.configure build/moz.configure/old.configure +index d0fe7accffe6..c46bdd023225 100644 +--- build/moz.configure/old.configure ++++ build/moz.configure/old.configure +@@ -288,7 +288,12 @@ def old_configure_options(*options): + '--with-system-libvpx', + '--with-system-nspr', + '--with-system-nss', ++ '--with-system-ogg', + '--with-system-png', ++ '--with-system-soundtouch', ++ '--with-system-theora', ++ '--with-system-tremor', ++ '--with-system-vorbis', + '--with-system-zlib', + '--with-thumb', + '--with-thumb-interwork', +diff --git config/Makefile.in config/Makefile.in +index a6206bb0ff30..f20987c61754 100644 +--- config/Makefile.in ++++ config/Makefile.in +@@ -51,6 +51,11 @@ export:: $(export-preqs) + -DMOZ_SYSTEM_LIBEVENT=$(MOZ_SYSTEM_LIBEVENT) \ + -DMOZ_SYSTEM_LIBVPX=$(MOZ_SYSTEM_LIBVPX) \ + -DMOZ_SYSTEM_ICU=$(MOZ_SYSTEM_ICU) \ ++ -DMOZ_SYSTEM_OGG=$(MOZ_SYSTEM_OGG) \ ++ -DMOZ_SYSTEM_THEORA=$(MOZ_SYSTEM_THEORA) \ ++ -DMOZ_SYSTEM_VORBIS=$(MOZ_SYSTEM_VORBIS) \ ++ -DMOZ_SYSTEM_TREMOR=$(MOZ_SYSTEM_TREMOR) \ ++ -DMOZ_SYSTEM_SOUNDTOUCH=$(MOZ_SYSTEM_SOUNDTOUCH) \ + $(srcdir)/system-headers $(srcdir)/stl-headers | $(PERL) $(topsrcdir)/nsprpub/config/make-system-wrappers.pl system_wrappers + $(INSTALL) system_wrappers $(DIST) + +diff --git config/external/moz.build config/external/moz.build +index 029ff8504795..2c3a40caa1ba 100644 +--- config/external/moz.build ++++ config/external/moz.build +@@ -21,12 +21,21 @@ if CONFIG['MOZ_UPDATER']: + external_dirs += ['modules/brotli'] + external_dirs += ['modules/woff2'] + +-if CONFIG['MOZ_VORBIS']: ++if not CONFIG['MOZ_SYSTEM_OGG']: ++ external_dirs += ['media/libogg'] ++ ++if CONFIG['MOZ_VORBIS'] and not CONFIG['MOZ_SYSTEM_VORBIS']: + external_dirs += ['media/libvorbis'] + +-if CONFIG['MOZ_TREMOR']: ++if CONFIG['MOZ_TREMOR'] and not CONFIG['MOZ_SYSTEM_TREMOR']: + external_dirs += ['media/libtremor'] + ++if not CONFIG['MOZ_SYSTEM_THEORA']: ++ external_dirs += ['media/libtheora'] ++ ++if not CONFIG['MOZ_SYSTEM_SOUNDTOUCH']: ++ external_dirs += ['media/libsoundtouch'] ++ + if CONFIG['MOZ_WEBM_ENCODER']: + external_dirs += ['media/libmkv'] + +@@ -52,12 +61,9 @@ external_dirs += [ + 'media/kiss_fft', + 'media/libcubeb', + 'media/libnestegg', +- 'media/libogg', + 'media/libopus', +- 'media/libtheora', + 'media/libspeex_resampler', + 'media/libstagefright', +- 'media/libsoundtouch', + 'media/psshparser' + ] + +diff --git config/system-headers config/system-headers +index 5ee7f71f9634..13178ac3b3ab 100644 +--- config/system-headers ++++ config/system-headers +@@ -1348,3 +1348,17 @@ unicode/utypes.h + libutil.h + unwind.h + fenv.h ++#if MOZ_SYSTEM_OGG==1 ++ogg/ogg.h ++ogg/os_types.h ++#endif ++#if MOZ_SYSTEM_THEORA==1 ++theora/theoradec.h ++#endif ++#if MOZ_SYSTEM_VORBIS==1 ++vorbis/codec.h ++vorbis/vorbisenc.h ++#endif ++#if MOZ_SYSTEM_TREMOR==1 ++tremor/ivorbiscodec.h ++#endif +diff --git dom/media/AudioStream.cpp dom/media/AudioStream.cpp +index 93ecda4319af..ff674c64ea07 100644 +--- dom/media/AudioStream.cpp ++++ dom/media/AudioStream.cpp +@@ -115,7 +115,9 @@ AudioStream::AudioStream(DataSource& aSource) + : mMonitor("AudioStream") + , mChannels(0) + , mOutChannels(0) ++#ifndef MOZ_SYSTEM_SOUNDTOUCH + , mTimeStretcher(nullptr) ++#endif + , mDumpFile(nullptr) + , mState(INITIALIZED) + , mDataSource(aSource) +@@ -135,9 +137,11 @@ AudioStream::~AudioStream() + if (mDumpFile) { + fclose(mDumpFile); + } ++#ifndef MOZ_SYSTEM_SOUNDTOUCH + if (mTimeStretcher) { + soundtouch::destroySoundTouchObj(mTimeStretcher); + } ++#endif + #if defined(XP_WIN) + if (XRE_IsContentProcess()) { + audio::AudioNotificationReceiver::Unregister(this); +@@ -151,7 +155,11 @@ nsresult AudioStream::EnsureTimeStretcherInitializedUnlocked() + { + mMonitor.AssertCurrentThreadOwns(); + if (!mTimeStretcher) { ++#ifdef MOZ_SYSTEM_SOUNDTOUCH ++ mTimeStretcher = new soundtouch::SoundTouch(); ++#else + mTimeStretcher = soundtouch::createSoundTouchObj(); ++#endif + mTimeStretcher->setSampleRate(mAudioClock.GetInputRate()); + mTimeStretcher->setChannels(mOutChannels); + mTimeStretcher->setPitch(1.0); +diff --git dom/media/AudioStream.h dom/media/AudioStream.h +index 7dc1f60f95cc..67d402a4117f 100644 +--- dom/media/AudioStream.h ++++ dom/media/AudioStream.h +@@ -16,7 +16,11 @@ + #include "mozilla/TimeStamp.h" + #include "mozilla/UniquePtr.h" + #include "CubebUtils.h" ++#ifdef MOZ_SYSTEM_SOUNDTOUCH ++#include "soundtouch/SoundTouch.h" ++#else + #include "soundtouch/SoundTouchFactory.h" ++#endif + + namespace mozilla { + +@@ -287,7 +291,11 @@ private: + uint32_t mChannels; + uint32_t mOutChannels; + AudioClock mAudioClock; ++#ifdef MOZ_SYSTEM_SOUNDTOUCH ++ nsAutoPtr<soundtouch::SoundTouch> mTimeStretcher; ++#else + soundtouch::SoundTouch* mTimeStretcher; ++#endif + + // Output file for dumping audio + FILE* mDumpFile; +diff --git dom/media/moz.build dom/media/moz.build +index 86b051c58d33..fb6186dce78b 100644 +--- dom/media/moz.build ++++ dom/media/moz.build +@@ -308,6 +308,21 @@ if CONFIG['MOZ_WEBRTC']: + + DEFINES['MOZILLA_INTERNAL_API'] = True + ++if CONFIG['MOZ_SYSTEM_OGG']: ++ CXXFLAGS += CONFIG['MOZ_OGG_CFLAGS'] ++ ++if CONFIG['MOZ_SYSTEM_THEORA']: ++ CXXFLAGS += CONFIG['MOZ_THEORA_CFLAGS'] ++ ++if CONFIG['MOZ_SYSTEM_VORBIS']: ++ CXXFLAGS += CONFIG['MOZ_VORBIS_CFLAGS'] ++ ++if CONFIG['MOZ_SYSTEM_TREMOR']: ++ CXXFLAGS += CONFIG['MOZ_TREMOR_CFLAGS'] ++ ++if CONFIG['MOZ_SYSTEM_SOUNDTOUCH']: ++ CXXFLAGS += CONFIG['MOZ_SOUNDTOUCH_CFLAGS'] ++ + if CONFIG['OS_TARGET'] == 'WINNT': + DEFINES['WEBRTC_WIN'] = True + else: +diff --git dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp +index 078f6ea5ef60..c600db067539 100644 +--- dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp ++++ dom/media/platforms/ffmpeg/ffvpx/FFVPXRuntimeLinker.cpp +@@ -11,9 +11,13 @@ + #include "prmem.h" + #include "prlink.h" + ++#ifdef MOZ_SYSTEM_SOUNDTOUCH ++#include "nsXPCOMPrivate.h" // for XUL_DLL ++#else + // We use a known symbol located in lgpllibs to determine its location. + // soundtouch happens to be always included in lgpllibs + #include "soundtouch/SoundTouch.h" ++#endif + + namespace mozilla { + +@@ -50,6 +54,12 @@ FFVPXRuntimeLinker::Init() + + sLinkStatus = LinkStatus_FAILED; + ++#ifdef MOZ_SYSTEM_SOUNDTOUCH ++ // We retrieve the path of the XUL library as this is where mozavcodec and ++ // mozavutil libs are located. ++ char* path = ++ PR_GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&FFVPXRuntimeLinker::Init); ++#else + // We retrieve the path of the lgpllibs library as this is where mozavcodec + // and mozavutil libs are located. + char* lgpllibsname = PR_GetLibraryName(nullptr, "lgpllibs"); +@@ -60,6 +70,7 @@ FFVPXRuntimeLinker::Init() + PR_GetLibraryFilePathname(lgpllibsname, + (PRFuncPtr)&soundtouch::SoundTouch::getVersionId); + PR_FreeLibraryName(lgpllibsname); ++#endif + if (!path) { + return false; + } +diff --git media/libogg/README_MOZILLA media/libogg/README_MOZILLA +index 6213fdc7770c..ada799916a17 100644 +--- media/libogg/README_MOZILLA ++++ media/libogg/README_MOZILLA +@@ -6,3 +6,6 @@ package downloaded from xiph.org and copied using the update.sh script. + The int-types.patch address a bug that config_types.h generated from + Linux platform can't be used on OpenSolaris directly see Mozilla bug + 449754 ++ ++The in-tree copy may be omitted during build by --with-system-ogg. ++Keep version in old-configure.in in sync on updates. +diff --git media/libsoundtouch/README_MOZILLA media/libsoundtouch/README_MOZILLA +index dc0dbe8f6886..ea73b55e3e39 100644 +--- media/libsoundtouch/README_MOZILLA ++++ media/libsoundtouch/README_MOZILLA +@@ -6,3 +6,5 @@ The whole library is not used, only the relevant files are imported in the tree, + using the script `update.sh`. Some changes have been made to the files, using + the patch `moz-libsoundtouch.patch`. We also use a custom soundtouch_config.h. + ++The in-tree copy may be omitted during build by --with-system-soundtouch. ++Keep version in old-configure.in in sync on updates. +diff --git media/libsoundtouch/src/soundtouch_perms.h media/libsoundtouch/src/soundtouch_perms.h +index 0af2fe618311..10973564e7a4 100644 +--- media/libsoundtouch/src/soundtouch_perms.h ++++ media/libsoundtouch/src/soundtouch_perms.h +@@ -12,7 +12,9 @@ + + #pragma GCC visibility push(default) + #include "SoundTouch.h" ++#ifndef MOZ_SYSTEM_SOUNDTOUCH + #include "SoundTouchFactory.h" ++#endif + #pragma GCC visibility pop + + #endif // MOZILLA_SOUNDTOUCH_PERMS_H +diff --git media/libtheora/README_MOZILLA media/libtheora/README_MOZILLA +index d48dbfa6f63d..6f30f250220e 100644 +--- media/libtheora/README_MOZILLA ++++ media/libtheora/README_MOZILLA +@@ -3,3 +3,6 @@ using the update.sh script. The changes made were those applied by update.sh, + the addition/update of Makefile.in files for the Mozilla build system. + + The subversion revision used was r17578. ++ ++The in-tree copy may be omitted during build by --with-system-theora. ++Keep version in old-configure.in in sync on updates. +diff --git media/libtheora/moz.build media/libtheora/moz.build +index c7f85eebff95..aae7b814adb5 100644 +--- media/libtheora/moz.build ++++ media/libtheora/moz.build +@@ -21,6 +21,9 @@ FINAL_LIBRARY = 'gkmedias' + # The encoder is currently not included. + DEFINES['THEORA_DISABLE_ENCODE'] = True + ++if CONFIG['MOZ_SYSTEM_OGG']: ++ CFLAGS += CONFIG['MOZ_OGG_CFLAGS'] ++ + # Suppress warnings in third-party code. + if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: + CFLAGS += ['-Wno-type-limits'] +diff --git media/libtremor/README_MOZILLA media/libtremor/README_MOZILLA +index ee67b53a05c5..81c971773d55 100644 +--- media/libtremor/README_MOZILLA ++++ media/libtremor/README_MOZILLA +@@ -5,3 +5,6 @@ Makefile.in files for the Mozilla build system. + + The upstream release used was http://svn.xiph.org/trunk/Tremor/ + The subversion revision used was r17547. ++ ++The in-tree copy may be omitted during build by --with-system-tremor. ++Keep version in old-configure.in in sync on updates. +diff --git media/libtremor/moz.build media/libtremor/moz.build +index 83afc8e37c64..71ef159da3d7 100644 +--- media/libtremor/moz.build ++++ media/libtremor/moz.build +@@ -9,3 +9,5 @@ with Files('*'): + + DIRS += ['include/tremor', 'lib'] + ++if CONFIG['MOZ_SYSTEM_OGG']: ++ CFLAGS += CONFIG['MOZ_OGG_CFLAGS'] +diff --git media/libvorbis/README_MOZILLA media/libvorbis/README_MOZILLA +index 1211ac074b33..eb31084aed25 100644 +--- media/libvorbis/README_MOZILLA ++++ media/libvorbis/README_MOZILLA +@@ -8,3 +8,6 @@ https://svn.xiph.org/tags/vorbis/libvorbis-1.3.5@19464 + + Some files are renamed during the copy to prevent clashes with object + file names with other Mozilla libraries. ++ ++The in-tree copy may be omitted during build by --with-system-vorbis. ++Keep version in old-configure.in in sync on updates. +diff --git media/libvorbis/moz.build media/libvorbis/moz.build +index adf393782cc9..923b76231107 100644 +--- media/libvorbis/moz.build ++++ media/libvorbis/moz.build +@@ -56,3 +56,6 @@ FINAL_LIBRARY = 'gkmedias' + # Suppress warnings in third-party code. + if CONFIG['GNU_CC']: + CFLAGS += ['-Wno-uninitialized'] ++ ++if CONFIG['MOZ_SYSTEM_OGG']: ++ CFLAGS += CONFIG['MOZ_OGG_CFLAGS'] +diff --git old-configure.in old-configure.in +index b614eef85c89..85f9099dba4d 100644 +--- old-configure.in ++++ old-configure.in +@@ -2941,6 +2941,111 @@ if test -n "$MOZ_OMX_PLUGIN"; then + fi + fi + ++dnl ======================================================== ++dnl Check for libogg ++dnl ======================================================== ++ ++MOZ_ARG_WITH_BOOL(system-ogg, ++[ --with-system-ogg Use system libogg (located with pkgconfig)], ++MOZ_SYSTEM_OGG=1, ++MOZ_SYSTEM_OGG=) ++ ++if test -n "$MOZ_SYSTEM_OGG"; then ++ PKG_CHECK_MODULES(MOZ_OGG, ogg >= 1.3.0) ++ ++ _SAVE_LIBS=$LIBS ++ LIBS="$LIBS $MOZ_OGG_LIBS" ++ AC_CHECK_FUNC(ogg_set_mem_functions, [], ++ [AC_DEFINE(MOZ_OGG_NO_MEM_REPORTING)]) ++ LIBS=$_SAVE_LIBS ++fi ++ ++AC_SUBST(MOZ_SYSTEM_OGG) ++ ++dnl ======================================================== ++dnl Check for libvorbis ++dnl ======================================================== ++ ++MOZ_ARG_WITH_BOOL(system-vorbis, ++[ --with-system-vorbis Use system libvorbis (located with pkgconfig)], ++MOZ_SYSTEM_VORBIS=1, ++MOZ_SYSTEM_VORBIS=) ++ ++if test -n "$MOZ_SYSTEM_VORBIS"; then ++ PKG_CHECK_MODULES(MOZ_VORBIS, vorbis vorbisenc >= 1.3.5) ++fi ++ ++AC_SUBST(MOZ_SYSTEM_VORBIS) ++ ++dnl ======================================================== ++dnl Check for integer-only libvorbis aka tremor ++dnl ======================================================== ++ ++MOZ_ARG_WITH_BOOL(system-tremor, ++[ --with-system-tremor Use system libtremor (located with pkgconfig)], ++MOZ_SYSTEM_TREMOR=1, ++MOZ_SYSTEM_TREMOR=) ++ ++if test -n "$MOZ_SYSTEM_TREMOR"; then ++ PKG_CHECK_MODULES(MOZ_TREMOR, vorbisidec >= 1.2.1) ++fi ++ ++AC_SUBST(MOZ_SYSTEM_TREMOR) ++ ++dnl ======================================================== ++dnl Check for libtheora ++dnl ======================================================== ++ ++MOZ_ARG_WITH_BOOL(system-theora, ++[ --with-system-theora Use system libtheora (located with pkgconfig)], ++MOZ_SYSTEM_THEORA=1, ++MOZ_SYSTEM_THEORA=) ++ ++if test -n "$MOZ_SYSTEM_THEORA"; then ++ PKG_CHECK_MODULES(MOZ_THEORA, theora >= 1.2) ++fi ++ ++AC_SUBST(MOZ_SYSTEM_THEORA) ++ ++dnl ======================================================== ++dnl Check for libSoundTouch ++dnl ======================================================== ++ ++MOZ_ARG_WITH_BOOL(system-soundtouch, ++[ --with-system-soundtouch Use system libSoundTouch (located with pkgconfig)], ++MOZ_SYSTEM_SOUNDTOUCH=1, ++MOZ_SYSTEM_SOUNDTOUCH=) ++ ++if test -n "$MOZ_SYSTEM_SOUNDTOUCH"; then ++ PKG_CHECK_MODULES(MOZ_SOUNDTOUCH, soundtouch >= 1.9.0) ++ ++ AC_LANG_SAVE ++ AC_LANG_CPLUSPLUS ++ _SAVE_CXXFLAGS=$CXXFLAGS ++ CXXFLAGS="$CXXFLAGS $MOZ_SOUNDTOUCH_CFLAGS" ++ AC_CACHE_CHECK(for soundtouch sample type, ++ ac_cv_soundtouch_sample_type, ++ [AC_TRY_COMPILE([#include <SoundTouch.h> ++ #ifndef SOUNDTOUCH_INTEGER_SAMPLES ++ #error soundtouch expects float samples ++ #endif], ++ [], ++ [ac_cv_soundtouch_sample_type=short], ++ [ac_cv_soundtouch_sample_type=float])]) ++ CXXFLAGS=$_SAVE_CXXFLAGS ++ AC_LANG_RESTORE ++ ++ if test \( -n "$MOZ_SAMPLE_TYPE_S16" -a "$ac_cv_soundtouch_sample_type" != short \) \ ++ -o \( -n "$MOZ_SAMPLE_TYPE_FLOAT32" -a "$ac_cv_soundtouch_sample_type" != float \) ; then ++ AC_MSG_ERROR([SoundTouch library is built with incompatible sample type. Either rebuild the library with/without --enable-integer-samples, chase default Mozilla sample type or remove --with-system-soundtouch.]) ++ fi ++fi ++ ++if test -n "$MOZ_SYSTEM_SOUNDTOUCH"; then ++ AC_DEFINE(MOZ_SYSTEM_SOUNDTOUCH) ++fi ++AC_SUBST(MOZ_SYSTEM_SOUNDTOUCH) ++ + dnl system libvpx Support + dnl ======================================================== + MOZ_ARG_WITH_BOOL(system-libvpx, +diff --git toolkit/library/moz.build toolkit/library/moz.build +index 079a575adec3..514d901195de 100644 +--- toolkit/library/moz.build ++++ toolkit/library/moz.build +@@ -237,6 +237,21 @@ if CONFIG['MOZ_SYSTEM_HARFBUZZ']: + if CONFIG['MOZ_SYSTEM_HUNSPELL']: + OS_LIBS += CONFIG['MOZ_HUNSPELL_LIBS'] + ++if CONFIG['MOZ_SYSTEM_OGG']: ++ OS_LIBS += CONFIG['MOZ_OGG_LIBS'] ++ ++if CONFIG['MOZ_SYSTEM_THEORA']: ++ OS_LIBS += CONFIG['MOZ_THEORA_LIBS'] ++ ++if CONFIG['MOZ_SYSTEM_VORBIS']: ++ OS_LIBS += CONFIG['MOZ_VORBIS_LIBS'] ++ ++if CONFIG['MOZ_SYSTEM_TREMOR']: ++ OS_LIBS += CONFIG['MOZ_TREMOR_LIBS'] ++ ++if CONFIG['MOZ_SYSTEM_SOUNDTOUCH']: ++ OS_LIBS += CONFIG['MOZ_SOUNDTOUCH_LIBS'] ++ + if CONFIG['MOZ_SYSTEM_LIBEVENT']: + OS_LIBS += CONFIG['MOZ_LIBEVENT_LIBS'] + +diff --git xpcom/build/XPCOMInit.cpp xpcom/build/XPCOMInit.cpp +index c083ab4bc4f3..62b917043a2c 100644 +--- xpcom/build/XPCOMInit.cpp ++++ xpcom/build/XPCOMInit.cpp +@@ -154,7 +154,9 @@ extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**); + + #include "mozilla/ipc/GeckoChildProcessHost.h" + ++#ifndef MOZ_OGG_NO_MEM_REPORTING + #include "ogg/ogg.h" ++#endif + #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) + #if defined(HAVE_STDINT_H) + // mozilla-config.h defines HAVE_STDINT_H, and then it's defined *again* in +@@ -664,11 +666,13 @@ NS_InitXPCOM2(nsIServiceManager** aResult, + // this oddness. + mozilla::SetICUMemoryFunctions(); + ++#ifndef MOZ_OGG_NO_MEM_REPORTING + // Do the same for libogg. + ogg_set_mem_functions(OggReporter::CountingMalloc, + OggReporter::CountingCalloc, + OggReporter::CountingRealloc, + OggReporter::CountingFree); ++#endif + + #if defined(MOZ_VPX) && !defined(MOZ_VPX_NO_MEM_REPORTING) + // And for VPX. diff --git a/www/waterfox/pkg-descr b/www/waterfox/pkg-descr new file mode 100644 index 000000000000..12f87eec88f3 --- /dev/null +++ b/www/waterfox/pkg-descr @@ -0,0 +1,24 @@ +The Waterfox source code is a specialised modification of the Mozilla +platform, designed for privacy and user choice in mind. You should be +able to install it and compile Waterfox without any issues. Other +modifications and patches that are more upstream have been implemented +as well to fix any compatibility/security issues that Mozilla may lag +behind in implementing (usually due to not being high priority). High +request features removed by Mozilla but wanted by users are retained +(if they aren't removed due to security). + +Features: + + o Disabled Encrypted Media Extensions (EME) + o Disabled Web Runtime (deprecated as of 2015) + o Removed Pocket + o Removed Telemetry + o Removed data collection + o Removed startup profiling + o Allow running of all 64-Bit NPAPI plugins + o Allow running of unsigned extensions + o Removal of Sponsored Tiles on New Tab Page + o Addition of Duplicate Tab option (toggle with browser.tabs.duplicateTab) + o Locale selector in about:preferences > General + +WWW: https://www.waterfoxproject.org/ diff --git a/www/waterfox/pkg-message b/www/waterfox/pkg-message new file mode 100644 index 000000000000..8c9a791e8092 --- /dev/null +++ b/www/waterfox/pkg-message @@ -0,0 +1,41 @@ +====================================================================== + +Some features available on other platforms are not implemented: +- Native audio (OSS backend is incomplete, doesn't support WebRTC) +- Encrypted Media Extensions (requires Widevine CDM binary) +- Process sandboxing (requires Capsicum backend) +- Reduced memory usage (requires mozjemalloc) +- Performance profiling (requires GeckoProfiler) +- Gamepad API (requires libusbhid backend) +- WebVR (requires open source runtime) +- TCP fast open + +====================================================================== + +On FreeBSD < 11.3 Web Content process may frequently crash due to bug 181741. +If you cannot upgrade try applying the following workaround: + +$ sysctl net.local.stream.recvspace=16384 + +====================================================================== + +To select non-default audio backend open about:config page and create +media.cubeb.backend preference. Supported values are: alsa, jack, +pulse, pulse-rust, oss, sndio. Currently used backend can be inspected +on about:support page. + +====================================================================== + +smb:// issues (Gvfs/GIO option): +Network group, machine, and share browsing does not work correctly. + +sftp:// (Gvfs/GIO option): +Only sftp access using public key authentication works. To easily +setup public key authentication to "remote_host": + +ssh-keygen +cat ~/.ssh/id_rsa.pub | ssh remote_host "cat >> .ssh/authorized_keys" + +The SSH server on remote_host must allow pub key authentication. + +====================================================================== |
