summaryrefslogtreecommitdiff
path: root/libre-testing
diff options
context:
space:
mode:
authorIsaac David <isacdaavid@isacdaavid.info>2016-08-10 19:29:28 -0500
committerIsaac David <isacdaavid@isacdaavid.info>2016-08-10 19:29:28 -0500
commitc70d9f25e6ef965999cbe977dee5a98b033143b6 (patch)
tree81060e65e6e14d255713e8b800a2e174e1465818 /libre-testing
parent30df3ee262862ab29665f78a487cb81b7ac3c405 (diff)
iceweasel: add experimental armv7h support to [libre-testing]
Diffstat (limited to 'libre-testing')
-rw-r--r--libre-testing/iceweasel/PKGBUILD219
-rw-r--r--libre-testing/iceweasel/drm-free.pngbin0 -> 3213 bytes
-rw-r--r--libre-testing/iceweasel/enable-object-directory-paths.patch13
-rw-r--r--libre-testing/iceweasel/gnu_headshadow.pngbin0 -> 6785 bytes
-rw-r--r--libre-testing/iceweasel/iceweasel-gtk3-20.patch2333
-rw-r--r--libre-testing/iceweasel/iceweasel-install-dir.patch13
-rw-r--r--libre-testing/iceweasel/iceweasel.desktop352
-rw-r--r--libre-testing/iceweasel/libre.patch338
-rw-r--r--libre-testing/iceweasel/mozconfig40
-rw-r--r--libre-testing/iceweasel/mozilla-1253216.patch12
-rw-r--r--libre-testing/iceweasel/mozilla-build-arm.patch24
-rw-r--r--libre-testing/iceweasel/no-libnotify.patch51
-rw-r--r--libre-testing/iceweasel/remove-default-and-shell-icons-in-packaging-manifest.patch34
-rw-r--r--libre-testing/iceweasel/vendor.js213
14 files changed, 3642 insertions, 0 deletions
diff --git a/libre-testing/iceweasel/PKGBUILD b/libre-testing/iceweasel/PKGBUILD
new file mode 100644
index 000000000..e5e1113d9
--- /dev/null
+++ b/libre-testing/iceweasel/PKGBUILD
@@ -0,0 +1,219 @@
+# Maintainer: André Silva <emulatorman@parabola.nu>
+# Contributor: Márcio Silva <coadde@parabola.nu>
+# Contributor (ConnochaetOS): Henry Jensen <hjensen@connochaetos.org>
+# Contributor: Luke Shumaker <lukeshu@sbcglobal.net>
+# Contributor: fauno <fauno@kiwwwi.com.ar>
+# Contributor: vando <facundo@esdebian.org>
+# Contributor (Arch): Jakub Schmidtke <sjakub@gmail.com>
+# Contributor: Figue <ffigue at gmail>
+# Contributor: taro-k <taro-k@movasense_com>
+# Contributor: Michał Masłowski <mtjm@mtjm.eu>
+# Thank you very much to the older contributors:
+# Contributor: evr <evanroman at gmail>
+# Contributor: Muhammad 'MJ' Jassim <UnbreakableMJ@gmail.com>
+
+_pgo=false
+
+# We're getting this from Debian Sid
+_debname=firefox
+_brandingver=48.0
+_brandingrel=1
+_debver=48.0
+_debrel=deb1
+_debrepo=http://ftp.debian.org/debian/pool/main/
+_parabolarepo=https://repo.parabola.nu/other/iceweasel
+debfile() { echo $@|sed -r 's@(.).*@\1/&/&@'; }
+
+_pkgname=firefox
+pkgname=iceweasel
+epoch=1
+pkgver=$_debver.$_debrel
+pkgrel=3
+
+pkgdesc="A libre version of Debian Iceweasel, the standalone web browser based on Mozilla Firefox."
+arch=(i686 x86_64 armv7h)
+license=(MPL GPL LGPL)
+depends=(alsa-lib dbus-glib ffmpeg gtk2 gtk3 hunspell icu=57.1 libevent
+ libvpx=1.6.0 libxt mime-types mozilla-common nss sqlite
+ startup-notification ttf-font)
+makedepends=(autoconf2.13 diffutils gconf imagemagick imake inetutils libidl2
+ libpulse librsvg-stable libxslt mesa mozilla-searchplugins
+ pkg-config python2 quilt unzip yasm zip)
+makedepends_i686=(rust)
+makedepends_x86_64=("${makedepends_i686[@]}")
+options=(!emptydirs !makeflags debug)
+if $_pgo; then
+ makedepends+=(xorg-server-xvfb)
+ options+=(!ccache)
+fi
+optdepends=('networkmanager: Location detection via available WiFi networks'
+ 'upower: Battery API')
+url="https://wiki.parabola.nu/$pkgname"
+replaces=("$pkgname-libre" "$_pkgname")
+conflicts=("$pkgname-libre")
+source=("$_debrepo/`debfile $_debname`_$_debver.orig.tar.xz"
+ "$_debrepo/`debfile $_debname`_$_debver-${_debrel#deb}.debian.tar.xz"
+ "$_parabolarepo/${pkgname}_$_brandingver-$_brandingrel.branding.tar.xz"
+ "$_parabolarepo/${pkgname}_$_brandingver-$_brandingrel.branding.tar.xz.sig"
+ mozconfig
+ libre.patch
+ remove-default-and-shell-icons-in-packaging-manifest.patch
+ gnu_headshadow.png
+ drm-free.png
+ $pkgname.desktop
+ $pkgname-install-dir.patch
+ vendor.js
+ no-libnotify.patch
+ $pkgname-gtk3-20.patch
+ enable-object-directory-paths.patch
+ mozilla-1253216.patch
+ mozilla-build-arm.patch)
+sha256sums=('032cc7c6da26b4336a6e0cea41a2821a149469b5cdeaec66723bf256bbf13ec5'
+ 'bda6131cb58bedfb33ed372ab0b8ad666f8b6b310f4788c7415efb9e3ae30ec6'
+ '0c4ce096711629db4a5f15415b9d752fd77c4eab7bfd22bd3cb6640ed9cbf861'
+ 'SKIP'
+ '6891d6237312914b579c632b71f9e4f613e7b00bbf2fd7ce53b4cf681820f609'
+ '013af398e97da9e855a143582816bf819e0d9d8d2b0e323d6b832f3df1157fdd'
+ '32f1fe3ad4f80d0ae419064db2abe49b97cd7cb18c35d68be1a2befb60172a2a'
+ '93e3001ce152e1d142619e215a9ef07dd429943b99d21726c25da9ceb31e31cd'
+ '56eba484179c7f498076f8dc603d8795e99dce8c6ea1da9736318c59d666bff6'
+ '2257dc69886bd0b72c48675a27c3a88b9cf6b598252c9e9f1c99763180684fc3'
+ '3aea6676f1e53a09673b6ae219d281fc28054beb6002b09973611c02f827651d'
+ 'e1c82f5f683258e17f7b3dba62a938e4efe4d232f45a4b82e74cd2793fd5f7fe'
+ 'e4ebdd14096d177d264a7993dbd5df46463605ff45f783732c26d30b9caa53a7'
+ 'c984c8bda3c173349d98f3fa71ec8ff8e8b74e6ca20a3f39f33596dbb4c4d1e8'
+ 'e260e555b261aabab1e48786dd514eeea056e4402af7cfd4dfd1d32858441484'
+ 'fbb6011501a74a8ea6d01c041870fcefb7ef2859c134aedc676e5f6452833f65'
+ '56eecee8162c138c442773d66483886f1242c8dd2b16eed5711ae5e63d9b0e3a')
+validpgpkeys=(
+ 'C92BAA713B8D53D3CAE63FC9E6974752F9704456' # André Silva
+ '684D54A189305A9CC95446D36B888913DDB59515' # Márcio Silva
+)
+
+prepare() {
+ cd "$srcdir/$_pkgname-$_debver"
+ mv "$srcdir/debian" .
+ mv "$srcdir/$pkgname-$_brandingver/branding" debian
+ mv "$srcdir/$pkgname-$_brandingver/patches/iceweasel-branding" debian/patches
+ cat "$srcdir/$pkgname-$_brandingver/patches/series" >> debian/patches/series
+
+ export QUILT_PATCHES=debian/patches
+ export QUILT_REFRESH_ARGS='-p ab --no-timestamps --no-index'
+ export QUILT_DIFF_ARGS='--no-timestamps'
+
+ quilt push -av
+
+ # Put gnu_headshadow.png and drm-free.png in the source code
+ install -m644 "$srcdir/"{gnu_headshadow,drm-free}.png \
+ browser/base/content/abouthome
+
+ # Useless since we are doing it ourselves
+ patch -Np1 -i "$srcdir/remove-default-and-shell-icons-in-packaging-manifest.patch"
+
+ # Enable object directory paths for Iceweasel rebranding
+ patch -Np1 -i "$srcdir/enable-object-directory-paths.patch"
+
+ # Install to /usr/lib/$pkgname
+ patch -Np1 -i "$srcdir/$pkgname-install-dir.patch"
+
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=1234158
+ patch -Np1 -i "$srcdir/$pkgname-gtk3-20.patch"
+
+ # Notifications with libnotify are broken
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=1236150
+ patch -Np1 -i "$srcdir/no-libnotify.patch"
+
+ # Patch and remove anything that's left
+ patch -Np1 -i "$srcdir/libre.patch"
+ sed -i 's|Adobe Flash|SWF Player|g;
+ ' browser/base/content/pageinfo/permissions.js \
+ browser/base/content/browser-plugins.js
+ sed -i '\|["]displayName["][:] ["]Flash["]| s|Flash|SWF Player|
+ \|["]displayName["][:] ["]Shockwave["]| s|Shockwave|DCR Player|
+ \|["]displayName["][:] ["]QuickTime["]| s|QuickTime|MOV Player|
+ \|installLinux| s|true|false|
+ ' browser/base/content/browser-plugins.js
+
+ # Load our build config, disable SafeSearch
+ cp "$srcdir/mozconfig" .mozconfig
+
+ mkdir "$srcdir/path"
+ ln -s /usr/bin/python2 "$srcdir/path/python"
+
+ # Load our searchplugins
+ rm -rv browser/locales/en-US/searchplugins
+ cp -av /usr/lib/mozilla/searchplugins browser/locales/en-US
+
+ # ARM-specific changes:
+ if [[ "$CARCH" == arm* ]]; then
+ sed -i '/ac_add_options --enable-rust/d' .mozconfig
+ echo "ac_add_options --disable-ion" >> .mozconfig
+ echo "ac_add_options --disable-elf-hack" >> .mozconfig
+ echo "ac_add_options --disable-webrtc" >> .mozconfig
+
+ # Disable gold linker, reduce memory consumption at link time
+ sed -i '/ac_add_options --enable-gold/d' .mozconfig
+ LDFLAGS+=" -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
+ echo "ac_add_options --disable-tests" >> .mozconfig
+ echo "ac_add_options --disable-debug" >> .mozconfig
+
+ patch -p1 -i ../mozilla-1253216.patch
+ patch -p1 -i ../mozilla-build-arm.patch
+ fi
+}
+
+build() {
+ cd "$srcdir/$_pkgname-$_debver"
+
+ # _FORTIFY_SOURCE causes configure failures
+ CPPFLAGS+=" -O2"
+
+ # Hardening
+ LDFLAGS+=" -Wl,-z,now"
+
+ # GCC 6
+ CXXFLAGS+=" -fno-delete-null-pointer-checks -fno-lifetime-dse -fno-schedule-insns2"
+
+ export PATH="$srcdir/path:$PATH"
+
+ if $_pgo; then
+ # Do PGO
+ xvfb-run -a -s "-extension GLX -screen 0 1280x1024x24" \
+ make -f client.mk build MOZ_PGO=1
+ else
+ make -f client.mk build
+ fi
+}
+
+package() {
+ cd "$srcdir/$_pkgname-$_debver"
+ make -f client.mk DESTDIR="$pkgdir" INSTALL_SDK= install
+
+ install -Dm644 ../vendor.js "$pkgdir/usr/lib/$pkgname/browser/defaults/preferences/vendor.js"
+
+ _brandingdir=debian/branding
+ brandingdir=moz-objdir/$_brandingdir
+ icondir="$pkgdir/usr/share/icons/hicolor"
+ for i in 16 22 24 32 48 64 128 192 256 384; do
+ rsvg-convert -w $i -h $i "$_brandingdir/${pkgname}_icon.svg" \
+ -o "$brandingdir/default$i.png"
+ install -Dm644 "$brandingdir/default$i.png" \
+ "$icondir/${i}x${i}/apps/$pkgname.png"
+ done
+
+ install -Dm644 "$_brandingdir/${pkgname}_icon.svg" \
+ "$icondir/scalable/apps/$pkgname.svg"
+
+ install -d "$pkgdir/usr/share/applications"
+ install -m644 "$srcdir/$pkgname.desktop" \
+ "$pkgdir/usr/share/applications"
+
+ # Use system-provided dictionaries
+ rm -rf "$pkgdir/usr/lib/$pkgname/"{dictionaries,hyphenation}
+ ln -s /usr/share/hunspell "$pkgdir/usr/lib/$pkgname/dictionaries"
+ ln -s /usr/share/hyphen "$pkgdir/usr/lib/$pkgname/hyphenation"
+
+ # Replace duplicate binary with symlink
+ # https://bugzilla.mozilla.org/show_bug.cgi?id=658850
+ ln -sf $pkgname "$pkgdir/usr/lib/$pkgname/$pkgname-bin"
+}
diff --git a/libre-testing/iceweasel/drm-free.png b/libre-testing/iceweasel/drm-free.png
new file mode 100644
index 000000000..e30994e67
--- /dev/null
+++ b/libre-testing/iceweasel/drm-free.png
Binary files differ
diff --git a/libre-testing/iceweasel/enable-object-directory-paths.patch b/libre-testing/iceweasel/enable-object-directory-paths.patch
new file mode 100644
index 000000000..bc938c66e
--- /dev/null
+++ b/libre-testing/iceweasel/enable-object-directory-paths.patch
@@ -0,0 +1,13 @@
+diff --git a/python/mozbuild/mozbuild/frontend/context.py b/python/mozbuild/mozbuild/frontend/context.py
+index 41ae8ae..dcc3263 100644
+--- a/python/mozbuild/mozbuild/frontend/context.py
++++ b/python/mozbuild/mozbuild/frontend/context.py
+@@ -408,8 +408,6 @@ class Path(ContextDerivedValue, unicode):
+ class SourcePath(Path):
+ """Like Path, but limited to paths in the source directory."""
+ def __init__(self, context, value):
+- if value.startswith('!'):
+- raise ValueError('Object directory paths are not allowed')
+ if value.startswith('%'):
+ raise ValueError('Filesystem absolute paths are not allowed')
+ super(SourcePath, self).__init__(context, value)
diff --git a/libre-testing/iceweasel/gnu_headshadow.png b/libre-testing/iceweasel/gnu_headshadow.png
new file mode 100644
index 000000000..e0f73a3bf
--- /dev/null
+++ b/libre-testing/iceweasel/gnu_headshadow.png
Binary files differ
diff --git a/libre-testing/iceweasel/iceweasel-gtk3-20.patch b/libre-testing/iceweasel/iceweasel-gtk3-20.patch
new file mode 100644
index 000000000..eccbc5e8d
--- /dev/null
+++ b/libre-testing/iceweasel/iceweasel-gtk3-20.patch
@@ -0,0 +1,2333 @@
+diff -up firefox-48.0/widget/gtk/gtk3drawing.cpp.gtk3-20 firefox-48.0/widget/gtk/gtk3drawing.cpp
+--- firefox-48.0/widget/gtk/gtk3drawing.cpp.gtk3-20 2016-07-25 22:22:07.000000000 +0200
++++ firefox-48.0/widget/gtk/gtk3drawing.cpp 2016-07-29 09:15:11.822285857 +0200
+@@ -18,15 +18,9 @@
+
+ #include <math.h>
+
+-static GtkWidget* gProtoWindow;
+ static GtkWidget* gProtoLayout;
+-static GtkWidget* gButtonWidget;
+-static GtkWidget* gToggleButtonWidget;
+-static GtkWidget* gButtonArrowWidget;
+-static GtkWidget* gSpinWidget;
+ static GtkWidget* gHScaleWidget;
+ static GtkWidget* gVScaleWidget;
+-static GtkWidget* gEntryWidget;
+ static GtkWidget* gComboBoxWidget;
+ static GtkWidget* gComboBoxButtonWidget;
+ static GtkWidget* gComboBoxArrowWidget;
+@@ -35,30 +29,15 @@ static GtkWidget* gComboBoxEntryWidget;
+ static GtkWidget* gComboBoxEntryTextareaWidget;
+ static GtkWidget* gComboBoxEntryButtonWidget;
+ static GtkWidget* gComboBoxEntryArrowWidget;
+-static GtkWidget* gHandleBoxWidget;
+-static GtkWidget* gToolbarWidget;
+-static GtkWidget* gFrameWidget;
+-static GtkWidget* gProgressWidget;
+ static GtkWidget* gTabWidget;
+-static GtkWidget* gTextViewWidget;
+-static GtkWidget* gTooltipWidget;
+-static GtkWidget* gMenuBarWidget;
+-static GtkWidget* gMenuBarItemWidget;
+-static GtkWidget* gMenuPopupWidget;
+-static GtkWidget* gMenuItemWidget;
+ static GtkWidget* gImageMenuItemWidget;
+ static GtkWidget* gCheckMenuItemWidget;
+ static GtkWidget* gTreeViewWidget;
+ static GtkTreeViewColumn* gMiddleTreeViewColumn;
+ static GtkWidget* gTreeHeaderCellWidget;
+ static GtkWidget* gTreeHeaderSortArrowWidget;
+-static GtkWidget* gExpanderWidget;
+-static GtkWidget* gToolbarSeparatorWidget;
+-static GtkWidget* gMenuSeparatorWidget;
+ static GtkWidget* gHPanedWidget;
+ static GtkWidget* gVPanedWidget;
+-static GtkWidget* gScrolledWindowWidget;
+-static GtkWidget* gInfoBar;
+
+ static style_prop_t style_prop_func;
+ static gboolean have_arrow_scaling;
+@@ -94,15 +73,6 @@ GetStateFlagsFromGtkWidgetState(GtkWidge
+ return stateFlags;
+ }
+
+-/* Because we have such an unconventional way of drawing widgets, signal to the GTK theme engine
+- that they are drawing for Mozilla instead of a conventional GTK app so they can do any specific
+- things they may want to do. */
+-static void
+-moz_gtk_set_widget_name(GtkWidget* widget)
+-{
+- gtk_widget_set_name(widget, "MozillaGtkWidget");
+-}
+-
+ gint
+ moz_gtk_enable_style_props(style_prop_t styleGetProp)
+ {
+@@ -111,15 +81,6 @@ moz_gtk_enable_style_props(style_prop_t
+ }
+
+ static gint
+-ensure_window_widget()
+-{
+- if (!gProtoWindow) {
+- gProtoWindow = GetWidget(MOZ_GTK_WINDOW);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+ setup_widget_prototype(GtkWidget* widget)
+ {
+ if (!gProtoLayout) {
+@@ -130,16 +91,6 @@ setup_widget_prototype(GtkWidget* widget
+ }
+
+ static gint
+-ensure_button_widget()
+-{
+- if (!gButtonWidget) {
+- gButtonWidget = gtk_button_new_with_label("M");
+- setup_widget_prototype(gButtonWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+ ensure_hpaned_widget()
+ {
+ if (!gHPanedWidget) {
+@@ -160,40 +111,6 @@ ensure_vpaned_widget()
+ }
+
+ static gint
+-ensure_toggle_button_widget()
+-{
+- if (!gToggleButtonWidget) {
+- gToggleButtonWidget = gtk_toggle_button_new();
+- setup_widget_prototype(gToggleButtonWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_button_arrow_widget()
+-{
+- if (!gButtonArrowWidget) {
+- ensure_toggle_button_widget();
+-
+- gButtonArrowWidget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
+- gtk_container_add(GTK_CONTAINER(gToggleButtonWidget), gButtonArrowWidget);
+- gtk_widget_realize(gButtonArrowWidget);
+- gtk_widget_show(gButtonArrowWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_spin_widget()
+-{
+- if (!gSpinWidget) {
+- gSpinWidget = gtk_spin_button_new(NULL, 1, 0);
+- setup_widget_prototype(gSpinWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+ ensure_scale_widget()
+ {
+ if (!gHScaleWidget) {
+@@ -207,16 +124,6 @@ ensure_scale_widget()
+ return MOZ_GTK_SUCCESS;
+ }
+
+-static gint
+-ensure_entry_widget()
+-{
+- if (!gEntryWidget) {
+- gEntryWidget = gtk_entry_new();
+- setup_widget_prototype(gEntryWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+ /* We need to have pointers to the inner widgets (button, separator, arrow)
+ * of the ComboBox to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+@@ -225,7 +132,7 @@ ensure_entry_widget()
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+- * of weak pointer since they are explicit children of gProtoWindow and as
++ * of weak pointer since they are explicit children of gProtoLayout and as
+ * such GTK holds a strong reference to them. */
+ static void
+ moz_gtk_get_combo_box_inner_button(GtkWidget *widget, gpointer client_data)
+@@ -297,16 +204,14 @@ ensure_combo_box_widgets()
+ /* Shouldn't be reached with current internal gtk implementation; we
+ * use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+- ensure_toggle_button_widget();
+- gComboBoxButtonWidget = gToggleButtonWidget;
++ gComboBoxButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
+ }
+
+ if (!gComboBoxArrowWidget) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+- ensure_button_arrow_widget();
+- gComboBoxArrowWidget = gButtonArrowWidget;
++ gComboBoxArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW);
+ }
+
+ /* We don't test the validity of gComboBoxSeparatorWidget since there
+@@ -316,15 +221,6 @@ ensure_combo_box_widgets()
+ return MOZ_GTK_SUCCESS;
+ }
+
+-static void
+-ensure_info_bar()
+-{
+- if (!gInfoBar) {
+- gInfoBar = gtk_info_bar_new();
+- setup_widget_prototype(gInfoBar);
+- }
+-}
+-
+ /* We need to have pointers to the inner widgets (entry, button, arrow) of
+ * the ComboBoxEntry to get the correct rendering from theme engines which
+ * special cases their look. Since the inner layout can change, we ask GTK
+@@ -333,7 +229,7 @@ ensure_info_bar()
+ * g_object_add_weak_pointer().
+ * Note that if we don't find the inner widgets (which shouldn't happen), we
+ * fallback to use generic "non-inner" widgets, and they don't need that kind
+- * of weak pointer since they are explicit children of gProtoWindow and as
++ * of weak pointer since they are explicit children of gProtoLayout and as
+ * such GTK holds a strong reference to them. */
+ static void
+ moz_gtk_get_combo_box_entry_inner_widgets(GtkWidget *widget,
+@@ -385,8 +281,7 @@ ensure_combo_box_entry_widgets()
+ NULL);
+
+ if (!gComboBoxEntryTextareaWidget) {
+- ensure_entry_widget();
+- gComboBoxEntryTextareaWidget = gEntryWidget;
++ gComboBoxEntryTextareaWidget = GetWidget(MOZ_GTK_ENTRY);
+ }
+
+ if (gComboBoxEntryButtonWidget) {
+@@ -412,68 +307,19 @@ ensure_combo_box_entry_widgets()
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we use a generic toggle button as last resort fallback to avoid
+ * crashing. */
+- ensure_toggle_button_widget();
+- gComboBoxEntryButtonWidget = gToggleButtonWidget;
++ gComboBoxEntryButtonWidget = GetWidget(MOZ_GTK_TOGGLE_BUTTON);
+ }
+
+ if (!gComboBoxEntryArrowWidget) {
+ /* Shouldn't be reached with current internal gtk implementation;
+ * we gButtonArrowWidget as last resort fallback to avoid
+ * crashing. */
+- ensure_button_arrow_widget();
+- gComboBoxEntryArrowWidget = gButtonArrowWidget;
++ gComboBoxEntryArrowWidget = GetWidget(MOZ_GTK_BUTTON_ARROW);
+ }
+
+ return MOZ_GTK_SUCCESS;
+ }
+
+-
+-static gint
+-ensure_handlebox_widget()
+-{
+- if (!gHandleBoxWidget) {
+- gHandleBoxWidget = gtk_handle_box_new();
+- setup_widget_prototype(gHandleBoxWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_toolbar_widget()
+-{
+- if (!gToolbarWidget) {
+- ensure_handlebox_widget();
+- gToolbarWidget = gtk_toolbar_new();
+- gtk_container_add(GTK_CONTAINER(gHandleBoxWidget), gToolbarWidget);
+- gtk_widget_realize(gToolbarWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_toolbar_separator_widget()
+-{
+- if (!gToolbarSeparatorWidget) {
+- ensure_toolbar_widget();
+- gToolbarSeparatorWidget = GTK_WIDGET(gtk_separator_tool_item_new());
+- setup_widget_prototype(gToolbarSeparatorWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_tooltip_widget()
+-{
+- if (!gTooltipWidget) {
+- gTooltipWidget = gtk_window_new(GTK_WINDOW_POPUP);
+- GtkStyleContext* style = gtk_widget_get_style_context(gTooltipWidget);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
+- gtk_widget_realize(gTooltipWidget);
+- moz_gtk_set_widget_name(gTooltipWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+ static gint
+ ensure_tab_widget()
+ {
+@@ -485,81 +331,11 @@ ensure_tab_widget()
+ }
+
+ static gint
+-ensure_progress_widget()
+-{
+- if (!gProgressWidget) {
+- gProgressWidget = gtk_progress_bar_new();
+- setup_widget_prototype(gProgressWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_frame_widget()
+-{
+- if (!gFrameWidget) {
+- gFrameWidget = gtk_frame_new(NULL);
+- setup_widget_prototype(gFrameWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_menu_bar_widget()
+-{
+- if (!gMenuBarWidget) {
+- gMenuBarWidget = gtk_menu_bar_new();
+- setup_widget_prototype(gMenuBarWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_menu_bar_item_widget()
+-{
+- if (!gMenuBarItemWidget) {
+- ensure_menu_bar_widget();
+- gMenuBarItemWidget = gtk_menu_item_new();
+- gtk_menu_shell_append(GTK_MENU_SHELL(gMenuBarWidget),
+- gMenuBarItemWidget);
+- gtk_widget_realize(gMenuBarItemWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_menu_popup_widget()
+-{
+- if (!gMenuPopupWidget) {
+- ensure_window_widget();
+- gMenuPopupWidget = gtk_menu_new();
+- gtk_menu_attach_to_widget(GTK_MENU(gMenuPopupWidget), gProtoWindow,
+- NULL);
+- gtk_widget_realize(gMenuPopupWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_menu_item_widget()
+-{
+- if (!gMenuItemWidget) {
+- ensure_menu_popup_widget();
+- gMenuItemWidget = gtk_menu_item_new_with_label("M");
+- gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+- gMenuItemWidget);
+- gtk_widget_realize(gMenuItemWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+ ensure_image_menu_item_widget()
+ {
+ if (!gImageMenuItemWidget) {
+- ensure_menu_popup_widget();
+ gImageMenuItemWidget = gtk_image_menu_item_new();
+- gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
++ gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
+ gImageMenuItemWidget);
+ gtk_widget_realize(gImageMenuItemWidget);
+ }
+@@ -567,25 +343,11 @@ ensure_image_menu_item_widget()
+ }
+
+ static gint
+-ensure_menu_separator_widget()
+-{
+- if (!gMenuSeparatorWidget) {
+- ensure_menu_popup_widget();
+- gMenuSeparatorWidget = gtk_separator_menu_item_new();
+- gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
+- gMenuSeparatorWidget);
+- gtk_widget_realize(gMenuSeparatorWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+ ensure_check_menu_item_widget()
+ {
+ if (!gCheckMenuItemWidget) {
+- ensure_menu_popup_widget();
+- gCheckMenuItemWidget = gtk_check_menu_item_new_with_label("M");
+- gtk_menu_shell_append(GTK_MENU_SHELL(gMenuPopupWidget),
++ gCheckMenuItemWidget = gtk_check_menu_item_new();
++ gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
+ gCheckMenuItemWidget);
+ gtk_widget_realize(gCheckMenuItemWidget);
+ }
+@@ -646,37 +408,6 @@ ensure_tree_header_cell_widget()
+ return MOZ_GTK_SUCCESS;
+ }
+
+-static gint
+-ensure_expander_widget()
+-{
+- if (!gExpanderWidget) {
+- gExpanderWidget = gtk_expander_new("M");
+- setup_widget_prototype(gExpanderWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static gint
+-ensure_scrolled_window_widget()
+-{
+- if (!gScrolledWindowWidget) {
+- gScrolledWindowWidget = gtk_scrolled_window_new(NULL, NULL);
+- setup_widget_prototype(gScrolledWindowWidget);
+- }
+- return MOZ_GTK_SUCCESS;
+-}
+-
+-static void
+-ensure_text_view_widget()
+-{
+- if (gTextViewWidget)
+- return;
+-
+- gTextViewWidget = gtk_text_view_new();
+- ensure_scrolled_window_widget();
+- gtk_container_add(GTK_CONTAINER(gScrolledWindowWidget), gTextViewWidget);
+-}
+-
+ gint
+ moz_gtk_init()
+ {
+@@ -729,26 +460,21 @@ moz_gtk_get_focus_outline_size(gint* foc
+ {
+ GtkBorder border;
+ GtkBorder padding;
+- GtkStyleContext *style;
+-
+- ensure_entry_widget();
+- style = gtk_widget_get_style_context(gEntryWidget);
+-
++ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_ENTRY);
+ gtk_style_context_get_border(style, GTK_STATE_FLAG_NORMAL, &border);
+ gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
+ *focus_h_width = border.left + padding.left;
+ *focus_v_width = border.top + padding.top;
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+ gint
+ moz_gtk_menuitem_get_horizontal_padding(gint* horizontal_padding)
+ {
+- ensure_menu_item_widget();
+-
+- gtk_style_context_get_style(gtk_widget_get_style_context(gMenuItemWidget),
+- "horizontal-padding", horizontal_padding,
+- NULL);
++ gtk_widget_style_get(GetWidget(MOZ_GTK_MENUITEM),
++ "horizontal-padding", horizontal_padding,
++ nullptr);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -771,10 +497,11 @@ moz_gtk_button_get_default_overflow(gint
+ {
+ GtkBorder* default_outside_border;
+
+- ensure_button_widget();
+- gtk_style_context_get_style(gtk_widget_get_style_context(gButtonWidget),
++ GtkStyleContext *style = ClaimStyleContext(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;
+@@ -794,10 +521,11 @@ moz_gtk_button_get_default_border(gint*
+ {
+ GtkBorder* default_border;
+
+- ensure_button_widget();
+- gtk_style_context_get_style(gtk_widget_get_style_context(gButtonWidget),
++ GtkStyleContext *style = ClaimStyleContext(MOZ_GTK_BUTTON);
++ gtk_style_context_get_style(style,
+ "default-border", &default_border,
+ NULL);
++ ReleaseStyleContext(style);
+
+ if (default_border) {
+ *border_top = default_border->top;
+@@ -831,17 +559,15 @@ static gint
+ moz_gtk_window_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_window_widget();
+- gtk_widget_set_direction(gProtoWindow, direction);
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction);
+
+- style = gtk_widget_get_style_context(gProtoWindow);
+ 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;
+ }
+
+@@ -1118,6 +844,36 @@ moz_gtk_scrollbar_button_paint(cairo_t *
+ return MOZ_GTK_SUCCESS;
+ }
+
++static void
++moz_gtk_update_scrollbar_style(GtkStyleContext* style,
++ WidgetNodeType widget,
++ GtkTextDirection direction)
++{
++ if (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL) {
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_BOTTOM);
++ } else {
++ if (direction == GTK_TEXT_DIR_LTR) {
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_RIGHT);
++ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_LEFT);
++ } else {
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_LEFT);
++ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_RIGHT);
++ }
++ }
++}
++
++static void
++moz_gtk_draw_styled_frame(GtkStyleContext* style, cairo_t *cr,
++ GdkRectangle* rect, bool drawFocus)
++{
++ 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);
++ if (drawFocus) {
++ gtk_render_focus(style, cr,
++ rect->x, rect->y, rect->width, rect->height);
++ }
++}
++
+ static gint
+ moz_gtk_scrollbar_trough_paint(WidgetNodeType widget,
+ cairo_t *cr, GdkRectangle* rect,
+@@ -1126,26 +882,34 @@ moz_gtk_scrollbar_trough_paint(WidgetNod
+ GtkTextDirection direction)
+ {
+ if (flags & MOZ_GTK_TRACK_OPAQUE) {
+- GtkStyleContext* style =
+- gtk_widget_get_style_context(GTK_WIDGET(gProtoWindow));
+- gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_WINDOW, direction);
++ gtk_render_background(style, cr,
++ rect->x, rect->y, rect->width, rect->height);
++ ReleaseStyleContext(style);
+ }
+
+- GtkStyleContext* style =
+- ClaimStyleContext(widget == MOZ_GTK_SCROLLBAR_HORIZONTAL ?
+- MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL :
+- MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
+- direction);
+- // TODO - integate with ClaimStyleContext()?
+- gtk_style_context_set_direction(style, direction);
++ bool isHorizontal = (widget == MOZ_GTK_SCROLLBAR_HORIZONTAL);
++ GtkStyleContext* style;
+
+- 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);
++ // Draw all child CSS Nodes for Gtk >= 3.20
++ if (gtk_check_version(3, 20, 0) == nullptr) {
++ style = ClaimStyleContext(widget, direction);
++ moz_gtk_update_scrollbar_style(style, widget, direction);
++ moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
++ ReleaseStyleContext(style);
+
+- if (state->focused) {
+- gtk_render_focus(style, cr,
+- rect->x, rect->y, rect->width, rect->height);
++ style = ClaimStyleContext(isHorizontal ?
++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL :
++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL,
++ direction);
++ moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
++ ReleaseStyleContext(style);
+ }
++ style = ClaimStyleContext(isHorizontal ?
++ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL :
++ MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
++ direction);
++ moz_gtk_draw_styled_frame(style, cr, rect, state->focused);
+ ReleaseStyleContext(style);
+
+ return MOZ_GTK_SUCCESS;
+@@ -1160,12 +924,7 @@ moz_gtk_scrollbar_thumb_paint(WidgetNode
+ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
+ GtkBorder margin;
+
+- GtkStyleContext* style = ClaimStyleContext(widget, direction);
+-
+- // TODO - integate those with ClaimStyleContext()?
+- gtk_style_context_set_state(style, state_flags);
+- gtk_style_context_set_direction(style, direction);
+-
++ GtkStyleContext* style = ClaimStyleContext(widget, direction, state_flags);
+ gtk_style_context_get_margin (style, state_flags, &margin);
+
+ gtk_render_slider(style, cr,
+@@ -1185,17 +944,10 @@ static gint
+ moz_gtk_spin_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_spin_widget();
+- gtk_widget_set_direction(gSpinWidget, direction);
+- style = gtk_widget_get_style_context(gSpinWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON);
++ GtkStyleContext* style = ClaimStyleContext(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);
+- gtk_style_context_restore(style);
+-
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1204,21 +956,14 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G
+ gboolean isDown, GtkWidgetState* state,
+ GtkTextDirection direction)
+ {
+- GdkRectangle arrow_rect;
+- GtkStyleContext* style;
+-
+- ensure_spin_widget();
+- style = gtk_widget_get_style_context(gSpinWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SPINBUTTON);
+- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
+- gtk_widget_set_direction(gSpinWidget, direction);
++ GtkStyleContext* style = ClaimStyleContext(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;
+ arrow_rect.x = rect->x + (rect->width - arrow_rect.width) / 2;
+@@ -1229,7 +974,8 @@ moz_gtk_spin_updown_paint(cairo_t *cr, G
+ isDown ? ARROW_DOWN : ARROW_UP,
+ arrow_rect.x, arrow_rect.y,
+ arrow_rect.width);
+- gtk_style_context_restore(style);
++
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1295,8 +1041,8 @@ moz_gtk_scale_thumb_paint(cairo_t *cr, G
+ gtk_widget_set_direction(widget, direction);
+
+ style = gtk_widget_get_style_context(widget);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER);
+ gtk_style_context_save(style);
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_SLIDER);
+ gtk_style_context_set_state(style, state_flags);
+ /* determine the thumb size, and position the thumb in the center in the opposite axis
+ */
+@@ -1321,20 +1067,12 @@ moz_gtk_gripper_paint(cairo_t *cr, GdkRe
+ GtkWidgetState* state,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_handlebox_widget();
+- gtk_widget_set_direction(gHandleBoxWidget, direction);
+-
+- style = gtk_widget_get_style_context(gHandleBoxWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP);
+- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
+-
++ GtkStyleContext* style =
++ ClaimStyleContext(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);
+- gtk_style_context_restore(style);
+-
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1435,6 +1173,38 @@ moz_gtk_entry_paint(cairo_t *cr, GdkRect
+ return MOZ_GTK_SUCCESS;
+ }
+
++static gint
++moz_gtk_text_view_paint(cairo_t *cr, GdkRectangle* rect,
++ GtkWidgetState* state,
++ GtkTextDirection direction)
++{
++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
++
++ GtkStyleContext* style_frame =
++ ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction, state_flags);
++ gtk_render_frame(style_frame, cr, rect->x, rect->y, rect->width, rect->height);
++
++ GtkBorder border, padding;
++ gtk_style_context_get_border(style_frame, state_flags, &border);
++ gtk_style_context_get_padding(style_frame, state_flags, &padding);
++ ReleaseStyleContext(style_frame);
++
++ GtkStyleContext* style =
++ ClaimStyleContext(MOZ_GTK_TEXT_VIEW, direction, state_flags);
++
++ gint xthickness = border.left + padding.left;
++ gint ythickness = border.top + padding.top;
++
++ gtk_render_background(style, cr,
++ rect->x + xthickness, rect->y + ythickness,
++ rect->width - 2 * xthickness,
++ rect->height - 2 * ythickness);
++
++ ReleaseStyleContext(style);
++
++ return MOZ_GTK_SUCCESS;
++}
++
+ static gint
+ moz_gtk_treeview_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state,
+@@ -1447,18 +1217,13 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR
+ GtkBorder border;
+
+ ensure_tree_view_widget();
+- ensure_scrolled_window_widget();
+-
+ gtk_widget_set_direction(gTreeViewWidget, direction);
+- gtk_widget_set_direction(gScrolledWindowWidget, direction);
+
+ /* only handle disabled and normal states, otherwise the whole background
+ * area will be painted differently with other states */
+ state_flags = state->disabled ? GTK_STATE_FLAG_INSENSITIVE : GTK_STATE_FLAG_NORMAL;
+
+- style = gtk_widget_get_style_context(gScrolledWindowWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME);
++ style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW, direction);
+ gtk_style_context_get_border(style, state_flags, &border);
+ xthickness = border.left;
+ ythickness = border.top;
+@@ -1473,7 +1238,7 @@ moz_gtk_treeview_paint(cairo_t *cr, GdkR
+ rect->height - 2 * ythickness);
+ gtk_render_frame(style, cr,
+ rect->x, rect->y, rect->width, rect->height);
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+ gtk_style_context_restore(style_tree);
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -1648,20 +1413,9 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRect
+ GtkWidgetState* state,
+ GtkArrowType arrow_type, GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+- GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
+ GdkRectangle arrow_rect;
+ gdouble arrow_angle;
+
+- ensure_button_arrow_widget();
+- style = gtk_widget_get_style_context(gButtonArrowWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_set_state(style, state_flags);
+- gtk_widget_set_direction(gButtonArrowWidget, direction);
+-
+- calculate_arrow_rect(gButtonArrowWidget, rect, &arrow_rect,
+- direction);
+-
+ if (direction == GTK_TEXT_DIR_RTL) {
+ arrow_type = (arrow_type == GTK_ARROW_LEFT) ?
+ GTK_ARROW_RIGHT : GTK_ARROW_LEFT;
+@@ -1680,10 +1434,17 @@ moz_gtk_arrow_paint(cairo_t *cr, GdkRect
+ arrow_angle = ARROW_UP;
+ break;
+ }
+- if (arrow_type != GTK_ARROW_NONE)
+- gtk_render_arrow(style, cr, arrow_angle,
+- arrow_rect.x, arrow_rect.y, arrow_rect.width);
+- gtk_style_context_restore(style);
++ if (arrow_type == GTK_ARROW_NONE)
++ return MOZ_GTK_SUCCESS;
++
++ 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);
++ gtk_render_arrow(style, cr, arrow_angle,
++ arrow_rect.x, arrow_rect.y, arrow_rect.width);
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1776,19 +1537,10 @@ static gint
+ moz_gtk_toolbar_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_toolbar_widget();
+- gtk_widget_set_direction(gToolbarWidget, direction);
+-
+- style = gtk_widget_get_style_context(gToolbarWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLBAR);
+-
++ GtkStyleContext* style = ClaimStyleContext(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);
+- gtk_style_context_restore(style);
+-
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1798,7 +1550,6 @@ static gint
+ moz_gtk_toolbar_separator_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+ gint separator_width;
+ gint paint_width;
+ gboolean wide_separators;
+@@ -1807,16 +1558,14 @@ moz_gtk_toolbar_separator_paint(cairo_t
+ const double start_fraction = 0.2;
+ const double end_fraction = 0.8;
+
+- ensure_toolbar_separator_widget();
+- gtk_widget_set_direction(gToolbarSeparatorWidget, direction);
+-
+- style = gtk_widget_get_style_context(gToolbarSeparatorWidget);
+-
+- gtk_style_context_get_style(gtk_widget_get_style_context(gToolbarWidget),
++ GtkStyleContext* style = ClaimStyleContext(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);
+ if (wide_separators) {
+ if (separator_width > rect->width)
+ separator_width = rect->width;
+@@ -1840,7 +1589,7 @@ moz_gtk_toolbar_separator_paint(cairo_t
+ rect->x + (rect->width - paint_width) / 2,
+ rect->y + rect->height * end_fraction);
+ }
+-
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1848,14 +1597,10 @@ static gint
+ moz_gtk_tooltip_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_tooltip_widget();
+- gtk_widget_set_direction(gTooltipWidget, direction);
+-
+- style = gtk_widget_get_style_context(gTooltipWidget);
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLTIP, 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;
+ }
+
+@@ -1870,14 +1615,11 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe
+ // GTK_STYLE_CLASS_VIEW to match the background with textarea elements.
+ // The resizer is drawn with shaded variants of the background color, and
+ // so a transparent background would lead to a transparent resizer.
+- ensure_text_view_widget();
+- gtk_widget_set_direction(gTextViewWidget, GTK_TEXT_DIR_LTR);
+-
+- style = gtk_widget_get_style_context(gTextViewWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW);
++ style = ClaimStyleContext(MOZ_GTK_TEXT_VIEW, GTK_TEXT_DIR_LTR,
++ GetStateFlagsFromGtkWidgetState(state));
++ // TODO - we need to save/restore style when gtk 3.20 CSS node path
++ // is used
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_GRIP);
+- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
+
+ // Workaround unico not respecting the text direction for resizers.
+ // See bug 1174248.
+@@ -1891,7 +1633,7 @@ moz_gtk_resizer_paint(cairo_t *cr, GdkRe
+
+ gtk_render_handle(style, cr, rect->x, rect->y, rect->width, rect->height);
+ cairo_restore(cr);
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -1900,16 +1642,9 @@ static gint
+ moz_gtk_frame_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_frame_widget();
+- gtk_widget_set_direction(gFrameWidget, direction);
+- style = gtk_widget_get_style_context(gFrameWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME);
+-
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_FRAME, direction);
+ gtk_render_frame(style, cr, rect->x, rect->y, rect->width, rect->height);
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -1917,18 +1652,11 @@ static gint
+ moz_gtk_progressbar_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+-
+- ensure_progress_widget();
+- gtk_widget_set_direction(gProgressWidget, direction);
+-
+- style = gtk_widget_get_style_context(gProgressWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TROUGH);
+-
++ GtkStyleContext* style = ClaimStyleContext(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);
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -1940,13 +1668,15 @@ moz_gtk_progress_chunk_paint(cairo_t *cr
+ {
+ GtkStyleContext* style;
+
+- ensure_progress_widget();
+- gtk_widget_set_direction(gProgressWidget, direction);
+-
+- style = gtk_widget_get_style_context(gProgressWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR);
++ if (gtk_check_version(3, 20, 0) != nullptr) {
++ /* Ask for MOZ_GTK_PROGRESS_TROUGH instead of MOZ_GTK_PROGRESSBAR
++ * because ClaimStyleContext() saves/restores that style */
++ style = ClaimStyleContext(MOZ_GTK_PROGRESS_TROUGH, direction);
++ gtk_style_context_remove_class(style, GTK_STYLE_CLASS_TROUGH);
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_PROGRESSBAR);
++ } else {
++ style = ClaimStyleContext(MOZ_GTK_PROGRESS_CHUNK, direction);
++ }
+
+ if (widget == MOZ_GTK_PROGRESS_CHUNK_INDETERMINATE ||
+ widget == MOZ_GTK_PROGRESS_CHUNK_VERTICAL_INDETERMINATE) {
+@@ -1990,7 +1720,7 @@ moz_gtk_progress_chunk_paint(cairo_t *cr
+ } else {
+ gtk_render_activity(style, cr, rect->x, rect->y, rect->width, rect->height);
+ }
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -2324,10 +2054,10 @@ moz_gtk_menu_bar_paint(cairo_t *cr, GdkR
+ {
+ GtkStyleContext* style;
+
+- ensure_menu_bar_widget();
+- gtk_widget_set_direction(gMenuBarWidget, direction);
++ GtkWidget* widget = GetWidget(MOZ_GTK_MENUBAR);
++ gtk_widget_set_direction(widget, direction);
+
+- style = gtk_widget_get_style_context(gMenuBarWidget);
++ style = gtk_widget_get_style_context(widget);
+ gtk_style_context_save(style);
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
+ gtk_render_background(style, cr, rect->x, rect->y, rect->width, rect->height);
+@@ -2343,14 +2073,14 @@ moz_gtk_menu_popup_paint(cairo_t *cr, Gd
+ {
+ GtkStyleContext* style;
+
+- ensure_menu_popup_widget();
+- gtk_widget_set_direction(gMenuPopupWidget, direction);
++ GtkWidget* widget = GetWidget(MOZ_GTK_MENUPOPUP);
++ gtk_widget_set_direction(widget, direction);
+
+ // Draw a backing toplevel. This fixes themes that don't provide a menu
+ // background, and depend on the GtkMenu's implementation window to provide it.
+ moz_gtk_window_paint(cr, rect, direction);
+
+- style = gtk_widget_get_style_context(gMenuPopupWidget);
++ style = gtk_widget_get_style_context(widget);
+ gtk_style_context_save(style);
+ gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENU);
+
+@@ -2373,12 +2103,10 @@ moz_gtk_menu_separator_paint(cairo_t *cr
+ gint x, y, w;
+ GtkBorder padding;
+
+- ensure_menu_separator_widget();
+- gtk_widget_set_direction(gMenuSeparatorWidget, direction);
+-
+- border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget));
+-
+- style = gtk_widget_get_style_context(gMenuSeparatorWidget);
++ border_width =
++ gtk_container_get_border_width(GTK_CONTAINER(
++ GetWidget(MOZ_GTK_MENUSEPARATOR)));
++ style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR, direction);
+ gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
+
+ x = rect->x + border_width;
+@@ -2408,42 +2136,36 @@ moz_gtk_menu_separator_paint(cairo_t *cr
+ }
+
+ gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+
+ // See gtk_menu_item_draw() for reference.
+ static gint
+-moz_gtk_menu_item_paint(cairo_t *cr, GdkRectangle* rect,
+- GtkWidgetState* state,
+- gint flags, GtkTextDirection direction)
++moz_gtk_menu_item_paint(WidgetNodeType widget, cairo_t *cr, GdkRectangle* rect,
++ GtkWidgetState* state, GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+- GtkWidget* item_widget;
+- guint border_width;
+ gint x, y, w, h;
+
+ if (state->inHover && !state->disabled) {
+- if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
+- ensure_menu_bar_item_widget();
+- item_widget = gMenuBarItemWidget;
+- } else {
+- ensure_menu_item_widget();
+- item_widget = gMenuItemWidget;
+- }
+- style = gtk_widget_get_style_context(item_widget);
+- gtk_style_context_save(style);
++ guint border_width =
++ gtk_container_get_border_width(GTK_CONTAINER(GetWidget(widget)));
++ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
++ GtkStyleContext* style =
++ ClaimStyleContext(widget, direction, state_flags);
+
+- if (flags & MOZ_TOPLEVEL_MENU_ITEM) {
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
++ bool pre_3_6 = gtk_check_version(3, 6, 0) != nullptr;
++ if (pre_3_6) {
++ // GTK+ 3.4 saves the style context and adds the menubar class to
++ // menubar children, but does each of these only when drawing, not
++ // during layout.
++ gtk_style_context_save(style);
++ if (widget == MOZ_GTK_MENUBARITEM) {
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUBAR);
++ }
+ }
+
+- gtk_widget_set_direction(item_widget, direction);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM);
+- gtk_style_context_set_state(style, GetStateFlagsFromGtkWidgetState(state));
+-
+- border_width = gtk_container_get_border_width(GTK_CONTAINER(item_widget));
+-
+ x = rect->x + border_width;
+ y = rect->y + border_width;
+ w = rect->width - border_width * 2;
+@@ -2451,7 +2173,11 @@ moz_gtk_menu_item_paint(cairo_t *cr, Gdk
+
+ gtk_render_background(style, cr, x, y, w, h);
+ gtk_render_frame(style, cr, x, y, w, h);
+- gtk_style_context_restore(style);
++
++ if (pre_3_6) {
++ gtk_style_context_restore(style);
++ }
++ ReleaseStyleContext(style);
+ }
+
+ return MOZ_GTK_SUCCESS;
+@@ -2462,21 +2188,13 @@ moz_gtk_menu_arrow_paint(cairo_t *cr, Gd
+ GtkWidgetState* state,
+ GtkTextDirection direction)
+ {
+- GtkStyleContext* style;
+ GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
+-
+- ensure_menu_item_widget();
+- gtk_widget_set_direction(gMenuItemWidget, direction);
+-
+- style = gtk_widget_get_style_context(gMenuItemWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_MENUITEM);
+- gtk_style_context_set_state(style, state_flags);
++ GtkStyleContext* style = ClaimStyleContext(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);
+- gtk_style_context_restore(style);
+-
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -2494,7 +2212,7 @@ moz_gtk_check_menu_item_paint(cairo_t *c
+ gint indicator_size, horizontal_padding;
+ gint x, y;
+
+- moz_gtk_menu_item_paint(cr, rect, state, FALSE, direction);
++ moz_gtk_menu_item_paint(MOZ_GTK_MENUITEM, cr, rect, state, direction);
+
+ ensure_check_menu_item_widget();
+ gtk_widget_set_direction(gCheckMenuItemWidget, direction);
+@@ -2545,21 +2263,13 @@ static gint
+ moz_gtk_info_bar_paint(cairo_t *cr, GdkRectangle* rect,
+ GtkWidgetState* state)
+ {
+- GtkStateFlags state_flags = GetStateFlagsFromGtkWidgetState(state);
+- GtkStyleContext *style;
+- ensure_info_bar();
+-
+- style = gtk_widget_get_style_context(gInfoBar);
+- gtk_style_context_save(style);
+-
+- gtk_style_context_set_state(style, state_flags);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_INFO);
+-
++ GtkStyleContext *style =
++ ClaimStyleContext(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);
+-
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+
+ return MOZ_GTK_SUCCESS;
+ }
+@@ -2605,18 +2315,18 @@ moz_gtk_get_widget_border(WidgetNodeType
+ case MOZ_GTK_BUTTON:
+ case MOZ_GTK_TOOLBAR_BUTTON:
+ {
+- ensure_button_widget();
+- style = gtk_widget_get_style_context(gButtonWidget);
++ style = ClaimStyleContext(MOZ_GTK_BUTTON);
+
+- *left = *top = *right = *bottom = gtk_container_get_border_width(GTK_CONTAINER(gButtonWidget));
++ *left = *top = *right = *bottom =
++ gtk_container_get_border_width(GTK_CONTAINER(GetWidget(MOZ_GTK_BUTTON)));
+
+ if (widget == MOZ_GTK_TOOLBAR_BUTTON) {
+ gtk_style_context_save(style);
+ gtk_style_context_add_class(style, "image-button");
+ }
+-
++
+ moz_gtk_add_style_padding(style, left, top, right, bottom);
+-
++
+ if (widget == MOZ_GTK_TOOLBAR_BUTTON)
+ gtk_style_context_restore(style);
+
+@@ -2624,12 +2334,13 @@ moz_gtk_get_widget_border(WidgetNodeType
+ // -moz-focus-inner border (Bug 1228281).
+ *left -= 1; *top -= 1; *right -= 1; *bottom -= 1;
+ moz_gtk_add_style_border(style, left, top, right, bottom);
++
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_ENTRY:
+ {
+- ensure_entry_widget();
+- style = gtk_widget_get_style_context(gEntryWidget);
++ style = ClaimStyleContext(MOZ_GTK_ENTRY);
+
+ // XXX: Subtract 1 pixel from the padding to account for the default
+ // padding in forms.css. See bug 1187385.
+@@ -2637,16 +2348,15 @@ moz_gtk_get_widget_border(WidgetNodeType
+ 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:
+ {
+- ensure_scrolled_window_widget();
+- style = gtk_widget_get_style_context(gScrolledWindowWidget);
+- gtk_style_context_save(style);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_FRAME);
++ style = ClaimStyleContext(MOZ_GTK_SCROLLED_WINDOW);
+ moz_gtk_add_style_border(style, left, top, right, bottom);
+- gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_TREE_HEADER_CELL:
+@@ -2726,14 +2436,12 @@ moz_gtk_get_widget_border(WidgetNodeType
+ w = gTabWidget;
+ break;
+ case MOZ_GTK_PROGRESSBAR:
+- ensure_progress_widget();
+- w = gProgressWidget;
++ w = GetWidget(MOZ_GTK_PROGRESSBAR);
+ break;
+ case MOZ_GTK_SPINBUTTON_ENTRY:
+ case MOZ_GTK_SPINBUTTON_UP:
+ case MOZ_GTK_SPINBUTTON_DOWN:
+- ensure_spin_widget();
+- w = gSpinWidget;
++ w = GetWidget(MOZ_GTK_SPINBUTTON);
+ break;
+ case MOZ_GTK_SCALE_HORIZONTAL:
+ ensure_scale_widget();
+@@ -2744,8 +2452,7 @@ moz_gtk_get_widget_border(WidgetNodeType
+ w = gVScaleWidget;
+ break;
+ case MOZ_GTK_FRAME:
+- ensure_frame_widget();
+- w = gFrameWidget;
++ w = GetWidget(MOZ_GTK_FRAME);
+ break;
+ case MOZ_GTK_CHECKBUTTON_CONTAINER:
+ case MOZ_GTK_RADIOBUTTON_CONTAINER:
+@@ -2761,19 +2468,17 @@ moz_gtk_get_widget_border(WidgetNodeType
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_MENUPOPUP:
+- ensure_menu_popup_widget();
+- w = gMenuPopupWidget;
++ w = GetWidget(MOZ_GTK_MENUPOPUP);
+ break;
++ case MOZ_GTK_MENUBARITEM:
+ case MOZ_GTK_MENUITEM:
+ case MOZ_GTK_CHECKMENUITEM:
+ case MOZ_GTK_RADIOMENUITEM:
+ {
+- if (widget == MOZ_GTK_MENUITEM) {
+- ensure_menu_item_widget();
+- ensure_menu_bar_item_widget();
+- w = gMenuItemWidget;
+- }
+- else {
++ if (widget == MOZ_GTK_MENUBARITEM || widget == MOZ_GTK_MENUITEM) {
++ // Bug 1274143 for MOZ_GTK_MENUBARITEM
++ w = GetWidget(MOZ_GTK_MENUITEM);
++ } else {
+ ensure_check_menu_item_widget();
+ w = gCheckMenuItemWidget;
+ }
+@@ -2784,9 +2489,16 @@ moz_gtk_get_widget_border(WidgetNodeType
+ return MOZ_GTK_SUCCESS;
+ }
+ case MOZ_GTK_INFO_BAR:
+- ensure_info_bar();
+- w = gInfoBar;
++ w = GetWidget(MOZ_GTK_INFO_BAR);
+ break;
++ case MOZ_GTK_TOOLTIP:
++ {
++ style = ClaimStyleContext(MOZ_GTK_TOOLTIP);
++ 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;
++ }
+ /* These widgets have no borders, since they are not containers. */
+ case MOZ_GTK_CHECKBUTTON_LABEL:
+ case MOZ_GTK_RADIOBUTTON_LABEL:
+@@ -2810,7 +2522,6 @@ moz_gtk_get_widget_border(WidgetNodeType
+ case MOZ_GTK_MENUSEPARATOR:
+ /* These widgets have no borders.*/
+ case MOZ_GTK_SPINBUTTON:
+- case MOZ_GTK_TOOLTIP:
+ case MOZ_GTK_WINDOW:
+ case MOZ_GTK_RESIZER:
+ case MOZ_GTK_MENUARROW:
+@@ -2908,8 +2619,7 @@ moz_gtk_get_arrow_size(WidgetNodeType wi
+ widget = gComboBoxArrowWidget;
+ break;
+ default:
+- ensure_button_arrow_widget();
+- widget = gButtonArrowWidget;
++ widget = GetWidget(MOZ_GTK_BUTTON_ARROW);
+ break;
+ }
+
+@@ -2924,11 +2634,9 @@ moz_gtk_get_toolbar_separator_width(gint
+ {
+ gboolean wide_separators;
+ gint separator_width;
+- GtkStyleContext* style;
+ GtkBorder border;
+
+- ensure_toolbar_widget();
+- style = gtk_widget_get_style_context(gToolbarWidget);
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_TOOLBAR);
+ gtk_style_context_get_style(style,
+ "space-size", size,
+ "wide-separators", &wide_separators,
+@@ -2937,17 +2645,18 @@ moz_gtk_get_toolbar_separator_width(gint
+ /* 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)
+ {
+- ensure_expander_widget();
+- gtk_style_context_get_style(gtk_widget_get_style_context(gExpanderWidget),
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_EXPANDER);
++ gtk_style_context_get_style(style,
+ "expander-size", size,
+ NULL);
+-
++ ReleaseStyleContext(style);
+ return MOZ_GTK_SUCCESS;
+ }
+
+@@ -2972,11 +2681,11 @@ moz_gtk_get_menu_separator_height(gint *
+ GtkStyleContext* style;
+ guint border_width;
+
+- ensure_menu_separator_widget();
+-
+- border_width = gtk_container_get_border_width(GTK_CONTAINER(gMenuSeparatorWidget));
++ border_width =
++ gtk_container_get_border_width(GTK_CONTAINER(
++ GetWidget(MOZ_GTK_MENUSEPARATOR)));
+
+- style = gtk_widget_get_style_context(gMenuSeparatorWidget);
++ style = ClaimStyleContext(MOZ_GTK_MENUSEPARATOR);
+ gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
+
+ gtk_style_context_save(style);
+@@ -2988,6 +2697,7 @@ moz_gtk_get_menu_separator_height(gint *
+ NULL);
+
+ gtk_style_context_restore(style);
++ ReleaseStyleContext(style);
+
+ *size = padding.top + padding.bottom + border_width*2;
+ *size += (wide_separators) ? separator_height : 1;
+@@ -2998,8 +2708,7 @@ moz_gtk_get_menu_separator_height(gint *
+ void
+ moz_gtk_get_entry_min_height(gint* height)
+ {
+- ensure_entry_widget();
+- GtkStyleContext* style = gtk_widget_get_style_context(gEntryWidget);
++ GtkStyleContext* style = ClaimStyleContext(MOZ_GTK_ENTRY);
+ if (!gtk_check_version(3, 20, 0)) {
+ gtk_style_context_get(style, gtk_style_context_get_state(style),
+ "min-height", height,
+@@ -3014,6 +2723,7 @@ moz_gtk_get_entry_min_height(gint* heigh
+ gtk_style_context_get_padding(style, GTK_STATE_FLAG_NORMAL, &padding);
+
+ *height += (border.top + border.bottom + padding.top + padding.bottom);
++ ReleaseStyleContext(style);
+ }
+
+ void
+@@ -3094,8 +2804,7 @@ moz_gtk_images_in_buttons()
+ gboolean result;
+ GtkSettings* settings;
+
+- ensure_button_widget();
+- settings = gtk_widget_get_settings(gButtonWidget);
++ settings = gtk_widget_get_settings(GetWidget(MOZ_GTK_BUTTON));
+
+ g_object_get(settings, "gtk-button-images", &result, NULL);
+ return result;
+@@ -3116,14 +2825,14 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ case MOZ_GTK_BUTTON:
+ case MOZ_GTK_TOOLBAR_BUTTON:
+ if (state->depressed) {
+- ensure_toggle_button_widget();
+ return moz_gtk_button_paint(cr, rect, state,
+ (GtkReliefStyle) flags,
+- gToggleButtonWidget, direction);
++ GetWidget(MOZ_GTK_TOGGLE_BUTTON),
++ direction);
+ }
+- ensure_button_widget();
+ return moz_gtk_button_paint(cr, rect, state,
+- (GtkReliefStyle) flags, gButtonWidget,
++ (GtkReliefStyle) flags,
++ GetWidget(MOZ_GTK_BUTTON),
+ direction);
+ break;
+ case MOZ_GTK_CHECKBUTTON:
+@@ -3171,9 +2880,9 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ state, direction);
+ break;
+ case MOZ_GTK_SPINBUTTON_ENTRY:
+- ensure_spin_widget();
++ // TODO - use MOZ_GTK_SPINBUTTON_ENTRY style directly
+ return moz_gtk_entry_paint(cr, rect, state,
+- gSpinWidget, direction);
++ GetWidget(MOZ_GTK_SPINBUTTON), direction);
+ break;
+ case MOZ_GTK_GRIPPER:
+ return moz_gtk_gripper_paint(cr, rect, state,
+@@ -3198,9 +2907,11 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ (GtkExpanderStyle) flags, direction);
+ break;
+ case MOZ_GTK_ENTRY:
+- ensure_entry_widget();
+- return moz_gtk_entry_paint(cr, rect, state,
+- gEntryWidget, direction);
++ return moz_gtk_entry_paint(cr, rect, state, GetWidget(MOZ_GTK_ENTRY),
++ direction);
++ break;
++ case MOZ_GTK_TEXT_VIEW:
++ return moz_gtk_text_view_paint(cr, rect, state, direction);
+ break;
+ case MOZ_GTK_DROPDOWN:
+ return moz_gtk_combo_box_paint(cr, rect, state, direction);
+@@ -3271,9 +2982,9 @@ moz_gtk_widget_paint(WidgetNodeType widg
+ return moz_gtk_menu_separator_paint(cr, rect,
+ direction);
+ break;
++ case MOZ_GTK_MENUBARITEM:
+ case MOZ_GTK_MENUITEM:
+- return moz_gtk_menu_item_paint(cr, rect, state, flags,
+- direction);
++ return moz_gtk_menu_item_paint(widget, cr, rect, state, direction);
+ break;
+ case MOZ_GTK_MENUARROW:
+ return moz_gtk_menu_arrow_paint(cr, rect, state,
+@@ -3333,25 +3044,16 @@ gboolean moz_gtk_has_scrollbar_buttons(v
+ gint
+ moz_gtk_shutdown()
+ {
+- if (gTooltipWidget)
+- gtk_widget_destroy(gTooltipWidget);
+ /* This will destroy all of our widgets */
+-
+ ResetWidgetCache();
+
+ /* TODO - replace it with appropriate widget */
+ if (gTreeHeaderSortArrowWidget)
+ gtk_widget_destroy(gTreeHeaderSortArrowWidget);
+
+- gProtoWindow = NULL;
+ gProtoLayout = NULL;
+- gButtonWidget = NULL;
+- gToggleButtonWidget = NULL;
+- gButtonArrowWidget = NULL;
+- gSpinWidget = NULL;
+ gHScaleWidget = NULL;
+ gVScaleWidget = NULL;
+- gEntryWidget = NULL;
+ gComboBoxWidget = NULL;
+ gComboBoxButtonWidget = NULL;
+ gComboBoxSeparatorWidget = NULL;
+@@ -3360,29 +3062,15 @@ moz_gtk_shutdown()
+ gComboBoxEntryButtonWidget = NULL;
+ gComboBoxEntryArrowWidget = NULL;
+ gComboBoxEntryTextareaWidget = NULL;
+- gHandleBoxWidget = NULL;
+- gToolbarWidget = NULL;
+- gFrameWidget = NULL;
+- gProgressWidget = NULL;
+ gTabWidget = NULL;
+- gTextViewWidget = nullptr;
+- gTooltipWidget = NULL;
+- gMenuBarWidget = NULL;
+- gMenuBarItemWidget = NULL;
+- gMenuPopupWidget = NULL;
+- gMenuItemWidget = NULL;
+ gImageMenuItemWidget = NULL;
+ gCheckMenuItemWidget = NULL;
+ gTreeViewWidget = NULL;
+ gMiddleTreeViewColumn = NULL;
+ gTreeHeaderCellWidget = NULL;
+ gTreeHeaderSortArrowWidget = NULL;
+- gExpanderWidget = NULL;
+- gToolbarSeparatorWidget = NULL;
+- gMenuSeparatorWidget = NULL;
+ gHPanedWidget = NULL;
+ gVPanedWidget = NULL;
+- gScrolledWindowWidget = NULL;
+
+ is_initialized = FALSE;
+
+diff -up firefox-48.0/widget/gtk/gtkdrawing.h.gtk3-20 firefox-48.0/widget/gtk/gtkdrawing.h
+--- firefox-48.0/widget/gtk/gtkdrawing.h.gtk3-20 2016-07-25 22:22:07.000000000 +0200
++++ firefox-48.0/widget/gtk/gtkdrawing.h 2016-07-29 09:15:11.822285857 +0200
+@@ -69,12 +69,6 @@ typedef enum {
+ MOZ_GTK_TAB_SELECTED = 1 << 10
+ } GtkTabFlags;
+
+-/** flags for menuitems **/
+-typedef enum {
+- /* menuitem is part of the menubar */
+- MOZ_TOPLEVEL_MENU_ITEM = 1 << 0
+-} GtkMenuItemFlags;
+-
+ /* function type for moz_gtk_enable_style_props */
+ typedef gint (*style_prop_t)(GtkStyle*, const gchar*, gint);
+
+@@ -93,6 +87,10 @@ typedef enum {
+ MOZ_GTK_BUTTON,
+ /* Paints a button with image and no text */
+ MOZ_GTK_TOOLBAR_BUTTON,
++ /* Paints a toggle button */
++ MOZ_GTK_TOGGLE_BUTTON,
++ /* Paints a button arrow */
++ MOZ_GTK_BUTTON_ARROW,
+
+ /* Paints the container part of a GtkCheckButton. */
+ MOZ_GTK_CHECKBUTTON_CONTAINER,
+@@ -115,6 +113,7 @@ typedef enum {
+
+ /* Horizontal GtkScrollbar counterparts */
+ MOZ_GTK_SCROLLBAR_HORIZONTAL,
++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL,
+ /* Paints the trough (track) of a GtkScrollbar. */
+ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL,
+ /* Paints the slider (thumb) of a GtkScrollbar. */
+@@ -122,6 +121,7 @@ typedef enum {
+
+ /* Vertical GtkScrollbar counterparts */
+ MOZ_GTK_SCROLLBAR_VERTICAL,
++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL,
+ MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL,
+ MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
+
+@@ -140,6 +140,10 @@ typedef enum {
+ MOZ_GTK_GRIPPER,
+ /* Paints a GtkEntry. */
+ MOZ_GTK_ENTRY,
++ /* Paints a GtkExpander. */
++ MOZ_GTK_EXPANDER,
++ /* Paints a GtkTextView. */
++ MOZ_GTK_TEXT_VIEW,
+ /* Paints a GtkOptionMenu. */
+ MOZ_GTK_DROPDOWN,
+ /* Paints a dropdown arrow (a GtkButton containing a down GtkArrow). */
+@@ -159,6 +163,8 @@ typedef enum {
+ MOZ_GTK_RESIZER,
+ /* Paints a GtkProgressBar. */
+ MOZ_GTK_PROGRESSBAR,
++ /* Paints a trough (track) of a GtkProgressBar */
++ MOZ_GTK_PROGRESS_TROUGH,
+ /* Paints a progress chunk of a GtkProgressBar. */
+ MOZ_GTK_PROGRESS_CHUNK,
+ /* Paints a progress chunk of an indeterminated GtkProgressBar. */
+@@ -187,7 +193,9 @@ typedef enum {
+ MOZ_GTK_MENUARROW,
+ /* Paints an arrow in a toolbar button. flags is a GtkArrowType. */
+ MOZ_GTK_TOOLBARBUTTON_ARROW,
+- /* Paints items of menubar and popups. */
++ /* Paints items of menubar. */
++ MOZ_GTK_MENUBARITEM,
++ /* Paints items of popup menus. */
+ MOZ_GTK_MENUITEM,
+ MOZ_GTK_CHECKMENUITEM,
+ MOZ_GTK_RADIOMENUITEM,
+@@ -202,6 +210,8 @@ typedef enum {
+ MOZ_GTK_WINDOW_CONTAINER,
+ /* Paints a GtkInfoBar, for notifications. */
+ MOZ_GTK_INFO_BAR,
++ /* Used for scrolled window shell. */
++ MOZ_GTK_SCROLLED_WINDOW,
+
+ MOZ_GTK_WIDGET_NODE_COUNT
+ } WidgetNodeType;
+diff -up firefox-48.0/widget/gtk/mozgtk/mozgtk.c.gtk3-20 firefox-48.0/widget/gtk/mozgtk/mozgtk.c
+--- firefox-48.0/widget/gtk/mozgtk/mozgtk.c.gtk3-20 2016-07-25 22:22:07.000000000 +0200
++++ firefox-48.0/widget/gtk/mozgtk/mozgtk.c 2016-07-29 09:15:11.823285862 +0200
+@@ -517,6 +517,7 @@ STUB(gdk_event_get_source_device)
+ STUB(gdk_window_get_type)
+ STUB(gdk_x11_window_get_xid)
+ STUB(gdk_x11_display_get_type)
++STUB(gtk_box_new)
+ STUB(gtk_cairo_should_draw_window)
+ STUB(gtk_cairo_transform_to_window)
+ STUB(gtk_combo_box_text_append)
+@@ -570,6 +571,7 @@ STUB(gtk_tree_view_column_get_button)
+ STUB(gtk_widget_get_preferred_size)
+ STUB(gtk_widget_get_state_flags)
+ STUB(gtk_widget_get_style_context)
++STUB(gtk_widget_path_append_for_widget)
+ STUB(gtk_widget_path_append_type)
+ STUB(gtk_widget_path_copy)
+ STUB(gtk_widget_path_free)
+@@ -587,6 +589,10 @@ STUB(gtk_color_chooser_get_type)
+ STUB(gtk_color_chooser_set_rgba)
+ STUB(gtk_color_chooser_get_rgba)
+ STUB(gtk_color_chooser_set_use_alpha)
++STUB(gtk_check_menu_item_new)
++STUB(gtk_style_context_get_direction)
++STUB(gtk_style_context_invalidate)
++STUB(gtk_tooltip_get_type)
+ #endif
+
+ #ifdef GTK2_SYMBOLS
+diff -up firefox-48.0/widget/gtk/nsLookAndFeel.cpp.gtk3-20 firefox-48.0/widget/gtk/nsLookAndFeel.cpp
+--- firefox-48.0/widget/gtk/nsLookAndFeel.cpp.gtk3-20 2016-06-01 06:11:44.000000000 +0200
++++ firefox-48.0/widget/gtk/nsLookAndFeel.cpp 2016-07-29 09:15:54.943459700 +0200
+@@ -31,6 +31,7 @@
+
+ #if MOZ_WIDGET_GTK != 2
+ #include <cairo-gobject.h>
++#include "WidgetStyleCache.h"
+ #endif
+
+ using mozilla::LookAndFeel;
+@@ -1135,15 +1136,24 @@ nsLookAndFeel::Init()
+ gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
+ sMozWindowText = GDK_RGBA_TO_NS_RGBA(color);
+ gtk_style_context_restore(style);
++ g_object_unref(style);
+
+ // tooltip foreground and background
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
+- gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
++ style = ClaimStyleContext(MOZ_GTK_TOOLTIP);
+ gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &color);
+ sInfoBackground = GDK_RGBA_TO_NS_RGBA(color);
+- gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &color);
++ {
++ GtkStyleContext* boxStyle =
++ CreateStyleForWidget(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0),
++ style);
++ GtkStyleContext* labelStyle =
++ CreateStyleForWidget(gtk_label_new(nullptr), boxStyle);
++ gtk_style_context_get_color(labelStyle, GTK_STATE_FLAG_NORMAL, &color);
++ g_object_unref(labelStyle);
++ g_object_unref(boxStyle);
++ }
+ sInfoText = GDK_RGBA_TO_NS_RGBA(color);
+- g_object_unref(style);
++ ReleaseStyleContext(style);
+
+ // menu foreground & menu background
+ GtkWidget *accel_label = gtk_accel_label_new("M");
+diff -up firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp
+--- firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp.gtk3-20 2016-07-25 22:22:07.000000000 +0200
++++ firefox-48.0/widget/gtk/nsNativeThemeGTK.cpp 2016-07-29 09:15:11.824285865 +0200
+@@ -354,10 +354,8 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
+
+ if (isTopLevel) {
+ aState->inHover = menuFrame->IsOpen();
+- *aWidgetFlags |= MOZ_TOPLEVEL_MENU_ITEM;
+ } else {
+ aState->inHover = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
+- *aWidgetFlags &= ~MOZ_TOPLEVEL_MENU_ITEM;
+ }
+
+ aState->active = FALSE;
+@@ -510,8 +508,14 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
+ break;
+ case NS_THEME_NUMBER_INPUT:
+ case NS_THEME_TEXTFIELD:
++ aGtkWidgetType = MOZ_GTK_ENTRY;
++ break;
+ case NS_THEME_TEXTFIELD_MULTILINE:
++#if (MOZ_WIDGET_GTK == 3)
++ aGtkWidgetType = MOZ_GTK_TEXT_VIEW;
++#else
+ aGtkWidgetType = MOZ_GTK_ENTRY;
++#endif
+ break;
+ case NS_THEME_LISTBOX:
+ case NS_THEME_TREEVIEW:
+@@ -673,6 +677,13 @@ nsNativeThemeGTK::GetGtkWidgetAndState(u
+ aGtkWidgetType = MOZ_GTK_MENUPOPUP;
+ break;
+ case NS_THEME_MENUITEM:
++ {
++ nsMenuFrame *menuFrame = do_QueryFrame(aFrame);
++ if (menuFrame && menuFrame->IsOnMenuBar()) {
++ aGtkWidgetType = MOZ_GTK_MENUBARITEM;
++ break;
++ }
++ }
+ aGtkWidgetType = MOZ_GTK_MENUITEM;
+ break;
+ case NS_THEME_MENUSEPARATOR:
+diff -up firefox-48.0/widget/gtk/WidgetStyleCache.cpp.gtk3-20 firefox-48.0/widget/gtk/WidgetStyleCache.cpp
+--- firefox-48.0/widget/gtk/WidgetStyleCache.cpp.gtk3-20 2016-07-25 22:22:07.000000000 +0200
++++ firefox-48.0/widget/gtk/WidgetStyleCache.cpp 2016-07-29 09:15:11.825285869 +0200
+@@ -22,7 +22,7 @@ static bool sStyleContextNeedsRestore;
+ static GtkStyleContext* sCurrentStyleContext;
+ #endif
+ static GtkStyleContext*
+-GetStyleInternal(WidgetNodeType aNodeType);
++GetCssNodeStyleInternal(WidgetNodeType aNodeType);
+
+ static GtkWidget*
+ CreateWindowWidget()
+@@ -67,12 +67,175 @@ CreateCheckboxWidget()
+ static GtkWidget*
+ CreateRadiobuttonWidget()
+ {
+- GtkWidget* widget = gtk_radio_button_new_with_label(NULL, "M");
++ GtkWidget* widget = gtk_radio_button_new_with_label(nullptr, "M");
+ AddToWindowContainer(widget);
+ return widget;
+ }
+
+ static GtkWidget*
++CreateMenuBarWidget()
++{
++ GtkWidget* widget = gtk_menu_bar_new();
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateMenuPopupWidget()
++{
++ GtkWidget* widget = gtk_menu_new();
++ gtk_menu_attach_to_widget(GTK_MENU(widget), GetWidget(MOZ_GTK_WINDOW),
++ nullptr);
++ return widget;
++}
++
++static GtkWidget*
++CreateMenuItemWidget(WidgetNodeType aShellType)
++{
++ GtkWidget* widget = gtk_menu_item_new();
++ gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(aShellType)), widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateProgressWidget()
++{
++ GtkWidget* widget = gtk_progress_bar_new();
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateTooltipWidget()
++{
++ MOZ_ASSERT(gtk_check_version(3, 20, 0) != nullptr,
++ "CreateTooltipWidget should be used for Gtk < 3.20 only.");
++ GtkWidget* widget = CreateWindowWidget();
++ GtkStyleContext* style = gtk_widget_get_style_context(widget);
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_TOOLTIP);
++ return widget;
++}
++
++static GtkWidget*
++CreateExpanderWidget()
++{
++ GtkWidget* widget = gtk_expander_new("M");
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateFrameWidget()
++{
++ GtkWidget* widget = gtk_frame_new(nullptr);
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateGripperWidget()
++{
++ GtkWidget* widget = gtk_handle_box_new();
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateToolbarWidget()
++{
++ GtkWidget* widget = gtk_toolbar_new();
++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_GRIPPER)), widget);
++ gtk_widget_realize(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateToolbarSeparatorWidget()
++{
++ GtkWidget* widget = GTK_WIDGET(gtk_separator_tool_item_new());
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateInfoBarWidget()
++{
++ GtkWidget* widget = gtk_info_bar_new();
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateButtonWidget()
++{
++ GtkWidget* widget = gtk_button_new_with_label("M");
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateToggleButtonWidget()
++{
++ GtkWidget* widget = gtk_toggle_button_new();
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateButtonArrowWidget()
++{
++ GtkWidget* widget = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_OUT);
++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_TOGGLE_BUTTON)), widget);
++ gtk_widget_realize(widget);
++ gtk_widget_show(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateSpinWidget()
++{
++ GtkWidget* widget = gtk_spin_button_new(nullptr, 1, 0);
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateEntryWidget()
++{
++ GtkWidget* widget = gtk_entry_new();
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateScrolledWindowWidget()
++{
++ GtkWidget* widget = gtk_scrolled_window_new(nullptr, nullptr);
++ AddToWindowContainer(widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateTextViewWidget()
++{
++ GtkWidget* widget = gtk_text_view_new();
++ gtk_container_add(GTK_CONTAINER(GetWidget(MOZ_GTK_SCROLLED_WINDOW)),
++ widget);
++ return widget;
++}
++
++static GtkWidget*
++CreateMenuSeparatorWidget()
++{
++ GtkWidget* widget = gtk_separator_menu_item_new();
++ gtk_menu_shell_append(GTK_MENU_SHELL(GetWidget(MOZ_GTK_MENUPOPUP)),
++ widget);
++ gtk_widget_realize(widget);
++ return widget;
++}
++
++
++static GtkWidget*
+ CreateWidget(WidgetNodeType aWidgetType)
+ {
+ switch (aWidgetType) {
+@@ -80,16 +243,54 @@ CreateWidget(WidgetNodeType aWidgetType)
+ return CreateWindowWidget();
+ case MOZ_GTK_WINDOW_CONTAINER:
+ return CreateWindowContainerWidget();
++ case MOZ_GTK_CHECKBUTTON_CONTAINER:
++ return CreateCheckboxWidget();
++ case MOZ_GTK_PROGRESSBAR:
++ return CreateProgressWidget();
++ case MOZ_GTK_RADIOBUTTON_CONTAINER:
++ return CreateRadiobuttonWidget();
+ case MOZ_GTK_SCROLLBAR_HORIZONTAL:
+ return CreateScrollbarWidget(aWidgetType,
+ GTK_ORIENTATION_HORIZONTAL);
+ case MOZ_GTK_SCROLLBAR_VERTICAL:
+ return CreateScrollbarWidget(aWidgetType,
+ GTK_ORIENTATION_VERTICAL);
+- case MOZ_GTK_CHECKBUTTON_CONTAINER:
+- return CreateCheckboxWidget();
+- case MOZ_GTK_RADIOBUTTON_CONTAINER:
+- return CreateRadiobuttonWidget();
++ case MOZ_GTK_MENUBAR:
++ return CreateMenuBarWidget();
++ case MOZ_GTK_MENUPOPUP:
++ return CreateMenuPopupWidget();
++ case MOZ_GTK_MENUBARITEM:
++ return CreateMenuItemWidget(MOZ_GTK_MENUBAR);
++ case MOZ_GTK_MENUITEM:
++ return CreateMenuItemWidget(MOZ_GTK_MENUPOPUP);
++ case MOZ_GTK_MENUSEPARATOR:
++ return CreateMenuSeparatorWidget();
++ case MOZ_GTK_EXPANDER:
++ return CreateExpanderWidget();
++ case MOZ_GTK_FRAME:
++ return CreateFrameWidget();
++ case MOZ_GTK_GRIPPER:
++ return CreateGripperWidget();
++ case MOZ_GTK_TOOLBAR:
++ return CreateToolbarWidget();
++ case MOZ_GTK_TOOLBAR_SEPARATOR:
++ return CreateToolbarSeparatorWidget();
++ case MOZ_GTK_INFO_BAR:
++ return CreateInfoBarWidget();
++ case MOZ_GTK_SPINBUTTON:
++ return CreateSpinWidget();
++ case MOZ_GTK_BUTTON:
++ return CreateButtonWidget();
++ case MOZ_GTK_TOGGLE_BUTTON:
++ return CreateToggleButtonWidget();
++ case MOZ_GTK_BUTTON_ARROW:
++ return CreateButtonArrowWidget();
++ case MOZ_GTK_ENTRY:
++ return CreateEntryWidget();
++ case MOZ_GTK_SCROLLED_WINDOW:
++ return CreateScrolledWindowWidget();
++ case MOZ_GTK_TEXT_VIEW:
++ return CreateTextViewWidget();
+ default:
+ /* Not implemented */
+ return nullptr;
+@@ -107,17 +308,42 @@ GetWidget(WidgetNodeType aWidgetType)
+ return widget;
+ }
+
+-static GtkStyleContext*
+-CreateCSSNode(const char* aName, GtkStyleContext *aParentStyle)
++GtkStyleContext*
++CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle)
++{
++ GtkWidgetPath* path = aParentStyle ?
++ gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
++ gtk_widget_path_new();
++
++ // Work around https://bugzilla.gnome.org/show_bug.cgi?id=767312
++ // which exists in GTK+ 3.20.
++ gtk_widget_get_style_context(aWidget);
++
++ gtk_widget_path_append_for_widget(path, aWidget);
++ // Release any floating reference on aWidget.
++ g_object_ref_sink(aWidget);
++ g_object_unref(aWidget);
++
++ GtkStyleContext *context = gtk_style_context_new();
++ gtk_style_context_set_path(context, path);
++ gtk_style_context_set_parent(context, aParentStyle);
++ gtk_widget_path_unref(path);
++
++ return context;
++}
++
++GtkStyleContext*
++CreateCSSNode(const char* aName, GtkStyleContext* aParentStyle, GType aType)
+ {
+ static auto sGtkWidgetPathIterSetObjectName =
+ reinterpret_cast<void (*)(GtkWidgetPath *, gint, const char *)>
+ (dlsym(RTLD_DEFAULT, "gtk_widget_path_iter_set_object_name"));
+
+- GtkWidgetPath* path =
+- gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle));
++ GtkWidgetPath* path = aParentStyle ?
++ gtk_widget_path_copy(gtk_style_context_get_path(aParentStyle)) :
++ gtk_widget_path_new();
+
+- gtk_widget_path_append_type(path, G_TYPE_NONE);
++ gtk_widget_path_append_type(path, aType);
+
+ (*sGtkWidgetPathIterSetObjectName)(path, -1, aName);
+
+@@ -130,95 +356,168 @@ CreateCSSNode(const char* aName, GtkStyl
+ }
+
+ static GtkStyleContext*
+-GetChildNodeStyle(WidgetNodeType aStyleType,
+- WidgetNodeType aWidgetType,
+- const gchar* aStyleClass,
+- WidgetNodeType aParentNodeType)
++CreateChildCSSNode(const char* aName, WidgetNodeType aParentNodeType)
+ {
+- GtkStyleContext* style;
+-
+- if (gtk_check_version(3, 20, 0) != nullptr) {
+- style = gtk_widget_get_style_context(sWidgetStorage[aWidgetType]);
+-
+- gtk_style_context_save(style);
+- MOZ_ASSERT(!sStyleContextNeedsRestore);
+- sStyleContextNeedsRestore = true;
+-
+- gtk_style_context_add_class(style, aStyleClass);
+- }
+- else {
+- style = sStyleStorage[aStyleType];
+- if (!style) {
+- style = CreateCSSNode(aStyleClass, GetStyleInternal(aParentNodeType));
+- MOZ_ASSERT(!sStyleContextNeedsRestore);
+- sStyleStorage[aStyleType] = style;
+- }
+- }
++ return CreateCSSNode(aName, GetCssNodeStyleInternal(aParentNodeType));
++}
+
++static GtkStyleContext*
++GetWidgetStyleWithClass(WidgetNodeType aWidgetType, const gchar* aStyleClass)
++{
++ GtkStyleContext* style = gtk_widget_get_style_context(GetWidget(aWidgetType));
++ gtk_style_context_save(style);
++ MOZ_ASSERT(!sStyleContextNeedsRestore);
++ sStyleContextNeedsRestore = true;
++ gtk_style_context_add_class(style, aStyleClass);
+ return style;
+ }
+
++/* GetCssNodeStyleInternal is used by Gtk >= 3.20 */
+ static GtkStyleContext*
+-GetStyleInternal(WidgetNodeType aNodeType)
++GetCssNodeStyleInternal(WidgetNodeType aNodeType)
+ {
++ GtkStyleContext* style = sStyleStorage[aNodeType];
++ if (style)
++ return style;
++
+ switch (aNodeType) {
+- case MOZ_GTK_SCROLLBAR_HORIZONTAL:
+- /* Root CSS node / widget for scrollbars */
++ case MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL:
++ style = CreateChildCSSNode("contents",
++ MOZ_GTK_SCROLLBAR_HORIZONTAL);
+ break;
+ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_HORIZONTAL,
+- GTK_STYLE_CLASS_TROUGH,
+- MOZ_GTK_SCROLLBAR_HORIZONTAL);
+-
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
++ MOZ_GTK_SCROLLBAR_CONTENTS_HORIZONTAL);
++ break;
+ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_HORIZONTAL,
+- GTK_STYLE_CLASS_SLIDER,
+- MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL);
+-
+- case MOZ_GTK_SCROLLBAR_VERTICAL:
+- /* Root CSS node / widget for scrollbars */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
++ MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL);
++ break;
++ case MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL:
++ style = CreateChildCSSNode("contents",
++ MOZ_GTK_SCROLLBAR_VERTICAL);
+ break;
+ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_VERTICAL,
+- GTK_STYLE_CLASS_TROUGH,
+- MOZ_GTK_SCROLLBAR_VERTICAL);
+-
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
++ MOZ_GTK_SCROLLBAR_CONTENTS_VERTICAL);
++ break;
+ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_SCROLLBAR_VERTICAL,
+- GTK_STYLE_CLASS_SLIDER,
+- MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
+-
+- case MOZ_GTK_RADIOBUTTON_CONTAINER:
+- /* Root CSS node / widget for checkboxes */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_SLIDER,
++ MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL);
+ break;
+ case MOZ_GTK_RADIOBUTTON:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_RADIOBUTTON_CONTAINER,
+- GTK_STYLE_CLASS_RADIO,
+- MOZ_GTK_RADIOBUTTON_CONTAINER);
+- case MOZ_GTK_CHECKBUTTON_CONTAINER:
+- /* Root CSS node / widget for radiobuttons */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_RADIO,
++ MOZ_GTK_RADIOBUTTON_CONTAINER);
+ break;
+ case MOZ_GTK_CHECKBUTTON:
+- return GetChildNodeStyle(aNodeType,
+- MOZ_GTK_CHECKBUTTON_CONTAINER,
+- GTK_STYLE_CLASS_CHECK,
+- MOZ_GTK_CHECKBUTTON_CONTAINER);
+- default:
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_CHECK,
++ MOZ_GTK_CHECKBUTTON_CONTAINER);
++ break;
++ case MOZ_GTK_PROGRESS_TROUGH:
++ /* Progress bar background (trough) */
++ style = CreateChildCSSNode(GTK_STYLE_CLASS_TROUGH,
++ MOZ_GTK_PROGRESSBAR);
++ break;
++ case MOZ_GTK_PROGRESS_CHUNK:
++ style = CreateChildCSSNode("progress",
++ MOZ_GTK_PROGRESS_TROUGH);
+ break;
++ case MOZ_GTK_TOOLTIP:
++ // We create this from the path because GtkTooltipWindow is not public.
++ style = CreateCSSNode("tooltip", nullptr, GTK_TYPE_TOOLTIP);
++ gtk_style_context_add_class(style, GTK_STYLE_CLASS_BACKGROUND);
++ break;
++ case MOZ_GTK_GRIPPER:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
++ GTK_STYLE_CLASS_GRIP);
++ case MOZ_GTK_INFO_BAR:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR,
++ GTK_STYLE_CLASS_INFO);
++ case MOZ_GTK_SPINBUTTON_ENTRY:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON,
++ GTK_STYLE_CLASS_ENTRY);
++ case MOZ_GTK_SCROLLED_WINDOW:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
++ GTK_STYLE_CLASS_FRAME);
++ case MOZ_GTK_TEXT_VIEW:
++ // TODO - create from CSS node
++ return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
++ GTK_STYLE_CLASS_VIEW);
++ default:
++ // TODO - create style from style path
++ GtkWidget* widget = GetWidget(aNodeType);
++ return gtk_widget_get_style_context(widget);
+ }
+
+- GtkWidget* widget = GetWidget(aNodeType);
+- if (widget) {
+- return gtk_widget_get_style_context(widget);
+- }
++ MOZ_ASSERT(style, "missing style context for node type");
++ sStyleStorage[aNodeType] = style;
++ return style;
++}
+
+- MOZ_ASSERT_UNREACHABLE("missing style context for node type");
+- return nullptr;
++/* GetWidgetStyleInternal is used by Gtk < 3.20 */
++static GtkStyleContext*
++GetWidgetStyleInternal(WidgetNodeType aNodeType)
++{
++ switch (aNodeType) {
++ case MOZ_GTK_SCROLLBAR_TROUGH_HORIZONTAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL,
++ GTK_STYLE_CLASS_TROUGH);
++ case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_HORIZONTAL,
++ GTK_STYLE_CLASS_SLIDER);
++ case MOZ_GTK_SCROLLBAR_TROUGH_VERTICAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL,
++ GTK_STYLE_CLASS_TROUGH);
++ case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLBAR_VERTICAL,
++ GTK_STYLE_CLASS_SLIDER);
++ case MOZ_GTK_RADIOBUTTON:
++ return GetWidgetStyleWithClass(MOZ_GTK_RADIOBUTTON_CONTAINER,
++ GTK_STYLE_CLASS_RADIO);
++ case MOZ_GTK_CHECKBUTTON:
++ return GetWidgetStyleWithClass(MOZ_GTK_CHECKBUTTON_CONTAINER,
++ GTK_STYLE_CLASS_CHECK);
++ case MOZ_GTK_PROGRESS_TROUGH:
++ return GetWidgetStyleWithClass(MOZ_GTK_PROGRESSBAR,
++ GTK_STYLE_CLASS_TROUGH);
++ case MOZ_GTK_TOOLTIP: {
++ GtkStyleContext* style = sStyleStorage[aNodeType];
++ if (style)
++ return style;
++
++ // The tooltip style class is added first in CreateTooltipWidget() so
++ // that gtk_widget_path_append_for_widget() in CreateStyleForWidget()
++ // will find it.
++ GtkWidget* tooltipWindow = CreateTooltipWidget();
++ style = CreateStyleForWidget(tooltipWindow, nullptr);
++ gtk_widget_destroy(tooltipWindow); // Release GtkWindow self-reference.
++ sStyleStorage[aNodeType] = style;
++ return style;
++ }
++ case MOZ_GTK_GRIPPER:
++ return GetWidgetStyleWithClass(MOZ_GTK_GRIPPER,
++ GTK_STYLE_CLASS_GRIP);
++ case MOZ_GTK_INFO_BAR:
++ return GetWidgetStyleWithClass(MOZ_GTK_INFO_BAR,
++ GTK_STYLE_CLASS_INFO);
++ case MOZ_GTK_SPINBUTTON_ENTRY:
++ return GetWidgetStyleWithClass(MOZ_GTK_SPINBUTTON,
++ GTK_STYLE_CLASS_ENTRY);
++ case MOZ_GTK_SCROLLED_WINDOW:
++ return GetWidgetStyleWithClass(MOZ_GTK_SCROLLED_WINDOW,
++ GTK_STYLE_CLASS_FRAME);
++ case MOZ_GTK_TEXT_VIEW:
++ return GetWidgetStyleWithClass(MOZ_GTK_TEXT_VIEW,
++ GTK_STYLE_CLASS_VIEW);
++ default:
++ GtkWidget* widget = GetWidget(aNodeType);
++ MOZ_ASSERT(widget);
++ return gtk_widget_get_style_context(widget);
++ }
+ }
+
+ void
+@@ -245,13 +544,39 @@ ResetWidgetCache(void)
+
+ GtkStyleContext*
+ ClaimStyleContext(WidgetNodeType aNodeType, GtkTextDirection aDirection,
+- StyleFlags aFlags)
++ GtkStateFlags aStateFlags, StyleFlags aFlags)
+ {
+- GtkStyleContext* style = GetStyleInternal(aNodeType);
++ MOZ_ASSERT(!sStyleContextNeedsRestore);
++ GtkStyleContext* style;
++ if (gtk_check_version(3, 20, 0) != nullptr) {
++ style = GetWidgetStyleInternal(aNodeType);
++ } else {
++ style = GetCssNodeStyleInternal(aNodeType);
++ }
+ #ifdef DEBUG
+ MOZ_ASSERT(!sCurrentStyleContext);
+ sCurrentStyleContext = style;
+ #endif
++ GtkStateFlags oldState = gtk_style_context_get_state(style);
++ GtkTextDirection oldDirection = gtk_style_context_get_direction(style);
++ if (oldState != aStateFlags || oldDirection != aDirection) {
++ // From GTK 3.8, set_state() will overwrite the direction, so set
++ // direction after state.
++ gtk_style_context_set_state(style, aStateFlags);
++ gtk_style_context_set_direction(style, aDirection);
++
++ // This invalidate is necessary for unsaved style contexts from GtkWidgets
++ // in pre-3.18 GTK, because automatic invalidation of such contexts
++ // was delayed until a resize event runs.
++ //
++ // https://bugzilla.mozilla.org/show_bug.cgi?id=1272194#c7
++ //
++ // Avoid calling invalidate on saved contexts to avoid performing
++ // build_properties() (in 3.16 stylecontext.c) unnecessarily early.
++ if (!sStyleContextNeedsRestore) {
++ gtk_style_context_invalidate(style);
++ }
++ }
+ return style;
+ }
+
+diff -up firefox-48.0/widget/gtk/WidgetStyleCache.h.gtk3-20 firefox-48.0/widget/gtk/WidgetStyleCache.h
+--- firefox-48.0/widget/gtk/WidgetStyleCache.h.gtk3-20 2016-07-25 22:22:07.000000000 +0200
++++ firefox-48.0/widget/gtk/WidgetStyleCache.h 2016-07-29 09:15:11.825285869 +0200
+@@ -21,10 +21,24 @@ enum : StyleFlags {
+ GtkWidget*
+ GetWidget(WidgetNodeType aNodeType);
+
++/*
++ * Return a new style context based on aWidget, as a child of aParentStyle.
++ * If aWidget still has a floating reference, then it is sunk and released.
++ */
++GtkStyleContext*
++CreateStyleForWidget(GtkWidget* aWidget, GtkStyleContext* aParentStyle);
++
++// CreateCSSNode is implemented for gtk >= 3.20 only.
++GtkStyleContext*
++CreateCSSNode(const char* aName,
++ GtkStyleContext* aParentStyle,
++ GType aType = G_TYPE_NONE);
++
+ // Callers must call ReleaseStyleContext() on the returned context.
+ GtkStyleContext*
+ ClaimStyleContext(WidgetNodeType aNodeType,
+ GtkTextDirection aDirection = GTK_TEXT_DIR_LTR,
++ GtkStateFlags aStateFlags = GTK_STATE_FLAG_NORMAL,
+ StyleFlags aFlags = NO_STYLE_FLAGS);
+ void
+ ReleaseStyleContext(GtkStyleContext* style);
diff --git a/libre-testing/iceweasel/iceweasel-install-dir.patch b/libre-testing/iceweasel/iceweasel-install-dir.patch
new file mode 100644
index 000000000..af113fa85
--- /dev/null
+++ b/libre-testing/iceweasel/iceweasel-install-dir.patch
@@ -0,0 +1,13 @@
+diff --git a/config/baseconfig.mk b/config/baseconfig.mk
+index 7ca8e35..6e92846 100644
+--- a/config/baseconfig.mk
++++ b/config/baseconfig.mk
+@@ -5,7 +5,7 @@
+ MOZ_APP_BASE_VERSION = $(firstword $(subst ., ,$(MOZ_APP_VERSION))).$(word 2,$(subst ., ,$(MOZ_APP_VERSION)))
+ includedir := $(includedir)/$(MOZ_APP_NAME)-$(MOZ_APP_BASE_VERSION)
+ idldir = $(datadir)/idl/$(MOZ_APP_NAME)-$(MOZ_APP_BASE_VERSION)
+-installdir = $(libdir)/$(MOZ_APP_NAME)-$(MOZ_APP_BASE_VERSION)
++installdir = $(libdir)/$(MOZ_APP_NAME)
+ sdkdir = $(libdir)/$(MOZ_APP_NAME)-devel-$(MOZ_APP_BASE_VERSION)
+ ifndef TOP_DIST
+ TOP_DIST = dist
diff --git a/libre-testing/iceweasel/iceweasel.desktop b/libre-testing/iceweasel/iceweasel.desktop
new file mode 100644
index 000000000..a3bcb5b79
--- /dev/null
+++ b/libre-testing/iceweasel/iceweasel.desktop
@@ -0,0 +1,352 @@
+[Desktop Entry]
+Name=Iceweasel
+GenericName=Web Browser
+GenericName[ar]=متصفح ويب
+GenericName[ast]=Restolador Web
+GenericName[bn]=ওয়েব ব্রাউজার
+GenericName[ca]=Navegador web
+GenericName[cs]=Webový prohlížeč
+GenericName[da]=Webbrowser
+GenericName[el]=Περιηγητής διαδικτύου
+GenericName[es]=Navegador web
+GenericName[et]=Veebibrauser
+GenericName[fa]=مرورگر اینترنتی
+GenericName[fi]=WWW-selain
+GenericName[fr]=Navigateur Web
+GenericName[gl]=Navegador Web
+GenericName[he]=דפדפן אינטרנט
+GenericName[hr]=Web preglednik
+GenericName[hu]=Webböngésző
+GenericName[it]=Browser web
+GenericName[ja]=ウェブ・ブラウザ
+GenericName[ko]=웹 브라우저
+GenericName[ku]=Geroka torê
+GenericName[lt]=Interneto naršyklė
+GenericName[nb]=Nettleser
+GenericName[nl]=Webbrowser
+GenericName[nn]=Nettlesar
+GenericName[no]=Nettleser
+GenericName[pl]=Przeglądarka WWW
+GenericName[pt]=Navegador Web
+GenericName[pt_BR]=Navegador Web
+GenericName[ro]=Navigator Internet
+GenericName[ru]=Веб-браузер
+GenericName[sk]=Internetový prehliadač
+GenericName[sl]=Spletni brskalnik
+GenericName[sv]=Webbläsare
+GenericName[tr]=Web Tarayıcı
+GenericName[ug]=توركۆرگۈ
+GenericName[uk]=Веб-браузер
+GenericName[vi]=Trình duyệt Web
+GenericName[zh_CN]=网络浏览器
+GenericName[zh_TW]=網路瀏覽器
+Comment=Browse the World Wide Web
+Comment[ar]=تصفح الشبكة العنكبوتية العالمية
+Comment[ast]=Restola pela Rede
+Comment[bn]=ইন্টারনেট ব্রাউজ করুন
+Comment[ca]=Navegueu per la web
+Comment[cs]=Prohlížení stránek World Wide Webu
+Comment[da]=Surf på internettet
+Comment[de]=Im Internet surfen
+Comment[el]=Μπορείτε να περιηγηθείτε στο διαδίκτυο (Web)
+Comment[es]=Navegue por la web
+Comment[et]=Lehitse veebi
+Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید
+Comment[fi]=Selaa Internetin WWW-sivuja
+Comment[fr]=Naviguer sur le Web
+Comment[gl]=Navegar pola rede
+Comment[he]=גלישה ברחבי האינטרנט
+Comment[hr]=Pretražite web
+Comment[hu]=A világháló böngészése
+Comment[it]=Esplora il web
+Comment[ja]=ウェブを閲覧します
+Comment[ko]=웹을 돌아 다닙니다
+Comment[ku]=Li torê bigere
+Comment[lt]=Naršykite internete
+Comment[nb]=Surf på nettet
+Comment[nl]=Verken het internet
+Comment[nn]=Surf på nettet
+Comment[no]=Surf på nettet
+Comment[pl]=Przeglądanie stron WWW
+Comment[pt]=Navegue na Internet
+Comment[pt_BR]=Navegue na Internet
+Comment[ro]=Navigați pe Internet
+Comment[ru]=Доступ в Интернет
+Comment[sk]=Prehliadanie internetu
+Comment[sl]=Brskajte po spletu
+Comment[sv]=Surfa på webben
+Comment[tr]=İnternet'te Gezinin
+Comment[ug]=دۇنيادىكى توربەتلەرنى كۆرگىلى بولىدۇ
+Comment[uk]=Перегляд сторінок Інтернету
+Comment[vi]=Để duyệt các trang web
+Comment[zh_CN]=浏览互联网
+Comment[zh_TW]=瀏覽網際網路
+Exec=iceweasel %u
+Terminal=false
+Type=Application
+Icon=iceweasel
+Categories=Network;WebBrowser;
+MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;
+StartupNotify=true
+Actions=NewTab;NewWindow;NewPrivateWindow;
+
+[Desktop Action NewTab]
+Name=Open new tab
+Name[ach]=Yab dirica matidi manyen
+Name[af]=Open nuwe oortjie
+Name[an]=Ubrir una pestanya nueva
+Name[ar]=افتح لسانًا جديدًا
+Name[as]=নতুন টেব খোলক
+Name[ast]=Abrir llingüeta nueva
+Name[az]=Yeni vərəq aç
+Name[be]=Адкрыць новую ўстаўку
+Name[bg]=Отваряне на нов подпрозорец
+Name[bn_BD]=নতুন ট্যাব খুলুন
+Name[bn_IN]=নতুন ট্যাব খুলুন
+Name[br]=Digeriñ un ivinell nevez
+Name[bs]=Otvori novi tab
+Name[ca]=Obre una pestanya nova
+Name[cs]=Otevřít nový panel
+Name[cy]=Agor tab newydd
+Name[da]=Åbn nyt faneblad
+Name[de]=Neuen Tab öffnen
+Name[dsb]=Nowy rejtark wócyniś
+Name[el]=Άνοιγμα νέας καρτέλας
+Name[eo]=Malfermi novan langeton
+Name[es_AR]=Abrir nueva pestaña
+Name[es_CL]=Abrir nueva pestaña
+Name[es_ES]=Abrir pestaña nueva
+Name[es_MX]=Abrir una pestaña nueva
+Name[et]=Ava uus kaart
+Name[eu]=Ireki fitxa berria
+Name[ff]=Uddit tabbere hesere
+Name[fi]=Avaa uusi välilehti
+Name[fr]=Ouvrir un nouvel onglet
+Name[fy_NL]=Iepenje nij ljepblêd
+Name[ga_IE]=Oscail i gcluaisín nua
+Name[gd]=Fosgail taba ùr
+Name[gl]=Abrir unha nova lapela
+Name[gu_IN]=નવી ટૅબને ખોલો
+Name[he]=פתיחת לשונית חדשה
+Name[hi_IN]=नया टैब खोलें
+Name[hr]=Otvori novu karticu
+Name[hsb]=Nowy rajtark wočinić
+Name[hu]=Új lap megnyitása
+Name[hy_AM]=Բացել նոր ներդիր
+Name[id]=Buka tab baru
+Name[is]=Opna nýjan flipa
+Name[it]=Apri nuova scheda
+Name[ja]=新しいタブ
+Name[kk]=Жаңа бетті ашу
+Name[kn]=ಹೊಸ ಹಾಳೆಯನ್ನು ತೆರೆ
+Name[ko]=새 탭 열기
+Name[lij]=Àrvi nêuvo féuggio
+Name[lt]=Atverti naują kortelę
+Name[mai]=नव टैब खोलू
+Name[mk]=Отвори ново јазиче
+Name[ml]=പുതിയ റ്റാബ് തുറക്കുക
+Name[mr]=नवीन टॅब उघडा
+Name[ms]=Buka tab baru
+Name[nb_NO]=Åpne ny fane
+Name[nl]=Nieuw tabblad openen
+Name[nn_NO]=Opna ny fane
+Name[or]=ନୂତନ ଟ୍ୟାବ ଖୋଲନ୍ତୁ
+Name[pa_IN]=ਨਵੀਂ ਟੈਬ ਖੋਲ੍ਹੋ
+Name[pl]=Otwórz nową kartę
+Name[pt_BR]=Nova aba
+Name[pt_PT]=Abrir novo separador
+Name[rm]=Avrir in nov tab
+Name[ro]=Deschide o filă nouă
+Name[ru]=Открыть новую вкладку
+Name[si]=නව ටැබය විවෘත කරන්න
+Name[sk]=Otvoriť novú kartu
+Name[sl]=Odpri nov zavihek
+Name[son]=Nor loku taaga feeri
+Name[sq]=Hap skedë të re
+Name[sr]=Отвори нови језичак
+Name[sv_SE]=Öppna ny flik
+Name[ta]=புதிய கீற்றைத் திற
+Name[te]=కొత్త టాబ్ తెరువుము
+Name[th]=เปิดแท็บใหม่
+Name[tr]=Yeni sekme aç
+Name[uk]=Відкрити нову вкладку
+Name[uz]=Yangi ichki oyna ochish
+Name[vi]=Mở thẻ mới
+Name[xh]=Vula ithebhu entsha
+Name[zh_CN]=打开新标签页
+Name[zh_TW]=開啟新分頁
+Exec=iceweasel -new-tab about:newtab
+
+[Desktop Action NewWindow]
+Name=Open new window
+Name[ach]=Yab dirica manyen
+Name[af]=Open nuwe venster
+Name[an]=Ubrir una nueva finestra
+Name[ar]=افتح نافذة جديدة
+Name[as]=নতুন উইন্ডো খোলক
+Name[ast]=Abrir ventana nueva
+Name[az]=Yeni pəncərə aç
+Name[be]=Адкрыць новае акно
+Name[bg]=Отваряне на нов прозорец
+Name[bn_BD]=নতুন উইন্ডো খুলুন
+Name[bn_IN]=নতুন উইন্ডো খুলুন
+Name[br]=Digeriñ ur prenestr nevez
+Name[bs]=Otvori novi prozor
+Name[ca]=Obre una finestra nova
+Name[cs]=Otevřít nové okno
+Name[cy]=Agor ffenestr newydd
+Name[da]=Åbn nyt vindue
+Name[de]=Neues Fenster öffnen
+Name[dsb]=Nowe wokno wócyniś
+Name[el]=Άνοιγμα νέου παραθύρου
+Name[eo]=Malfermi novan fenestron
+Name[es_AR]=Abrir nueva ventana
+Name[es_CL]=Abrir nueva ventana
+Name[es_ES]=Abrir nueva ventana
+Name[es_MX]=Abrir nueva ventana
+Name[et]=Ava uus aken
+Name[eu]=Ireki leiho berria
+Name[ff]=Uddit henorde hesere
+Name[fi]=Avaa uusi ikkuna
+Name[fr]=Ouvrir une nouvelle fenêtre
+Name[fy_NL]=Iepenje nij finster
+Name[ga_IE]=Oscail fuinneog nua
+Name[gd]=Fosgail uinneag ùr
+Name[gl]=Abrir unha nova xanela
+Name[gu_IN]=નવી વિન્ડોને ખોલો
+Name[he]=פתח חלון חדש
+Name[hi_IN]=नई विंडो खोलें
+Name[hr]=Otvori novi prozor
+Name[hsb]=Nowe wokno wočinić
+Name[hu]=Új ablak megnyitása
+Name[hy_AM]=Բացել նոր պատուհան
+Name[id]=Buka jendela baru
+Name[is]=Opna nýjan glugga
+Name[it]=Apri nuova finestra
+Name[ja]=新しいウィンドウ
+Name[kk]=Жаңа терезені ашу
+Name[kn]=ಹೊಸ ವಿಂಡೊವನ್ನು ತೆರೆ
+Name[ko]=새 창 열기
+Name[lij]=Àrvi nêuvo barcón
+Name[lt]=Atverti naują langą
+Name[mai]=नई विंडो खोलू
+Name[mk]=Отвори нов прозорец
+Name[ml]=പുതിയ ജാലകം തുറക്കുക
+Name[mr]=नवीन पटल उघडा
+Name[ms]=Buka tetingkap baru
+Name[nb_NO]=Åpne nytt vindu
+Name[nl]=Een nieuw venster openen
+Name[nn_NO]=Opna nytt vindauge
+Name[or]=ନୂତନ ୱିଣ୍ଡୋ ଖୋଲନ୍ତୁ
+Name[pa_IN]=ਨਵੀਂ ਵਿੰਡੋ ਖੋਲ੍ਹੋ
+Name[pl]=Otwórz nowe okno
+Name[pt_BR]=Nova janela
+Name[pt_PT]=Abrir nova janela
+Name[rm]=Avrir ina nova fanestra
+Name[ro]=Deschide o nouă fereastră
+Name[ru]=Открыть новое окно
+Name[si]=නව කවුළුවක් විවෘත කරන්න
+Name[sk]=Otvoriť nové okno
+Name[sl]=Odpri novo okno
+Name[son]=Zanfun taaga feeri
+Name[sq]=Hap dritare të re
+Name[sr]=Отвори нови прозор
+Name[sv_SE]=Öppna nytt fönster
+Name[ta]=புதிய சாளரத்தை திற
+Name[te]=కొత్త విండో తెరువుము
+Name[th]=เปิดหน้าต่างใหม่
+Name[tr]=Yeni pencere aç
+Name[uk]=Відкрити нове вікно
+Name[uz]=Yangi oyna ochish
+Name[vi]=Mở cửa sổ mới
+Name[xh]=Vula iwindow entsha
+Name[zh_CN]=打开新窗口
+Name[zh_TW]=開啟新視窗
+Exec=iceweasel -new-window
+
+[Desktop Action NewPrivateWindow]
+Name=New private window
+Name[ach]=Dirica manyen me mung
+Name[af]=Nuwe privaatvenster
+Name[an]=Nueva finestra de navegación privada
+Name[ar]=نافذة خاصة جديدة
+Name[as]=নতুন ব্যক্তিগত উইন্ডো
+Name[ast]=Ventana privada nueva
+Name[az]=Yeni məxfi pəncərə
+Name[be]=Новае акно адасаблення
+Name[bg]=Нов прозорец за поверително сърфиране
+Name[bn_BD]=নতুন ব্যক্তিগত উইন্ডো
+Name[bn_IN]=নতুন ব্যাক্তিগত উইন্ডো
+Name[br]=Prenestr merdeiñ prevez nevez
+Name[bs]=Novi privatni prozor
+Name[ca]=Finestra privada nova
+Name[cs]=Nové anonymní okno
+Name[cy]=Ffenestr breifat newydd
+Name[da]=Nyt privat vindue
+Name[de]=Neues privates Fenster öffnen
+Name[dsb]=Nowe priwatne wokno
+Name[el]=Νέο παράθυρο ιδιωτικής περιήγησης
+Name[eo]=Nova privata fenestro
+Name[es_AR]=Nueva ventana privada
+Name[es_CL]=Nueva ventana privada
+Name[es_ES]=Nueva ventana privada
+Name[es_MX]=Nueva ventana privada
+Name[et]=Uus privaatne aken
+Name[eu]=Leiho pribatu berria
+Name[ff]=Henorde suturo hesere
+Name[fi]=Uusi yksityinen ikkuna
+Name[fr]=Nouvelle fenêtre de navigation privée
+Name[fy_NL]=Nij priveefinster
+Name[ga_IE]=Fuinneog nua phríobháideach
+Name[gd]=Uinneag phrìobhaideach ùr
+Name[gl]=Nova xanela privada
+Name[gu_IN]=નવી ખાનગી વિન્ડો
+Name[he]=חלון פרטי חדש
+Name[hi_IN]=नया निजी विंडो
+Name[hr]=Novi privatni prozor
+Name[hsb]=Nowe priwatne wokno
+Name[hu]=Új privát ablak
+Name[hy_AM]=Գաղտնի դիտարկում
+Name[id]=Jendela mode pribadi baru
+Name[is]=Nýr einkagluggi
+Name[it]=Nuova finestra anonima
+Name[ja]=新しいプライベートウィンドウ
+Name[kk]=Жаңа жекелік терезе
+Name[kn]=ಹೊಸ ಖಾಸಗಿ ಕಿಟಕಿ
+Name[ko]=새 사생활 보호 창
+Name[lij]=Nêuvo barcón privòu
+Name[lt]=Atverti privačiojo naršymo langą
+Name[mai]=नव निज विंडो
+Name[mk]=Нов прозорец за приватно сурфање
+Name[ml]=പുതിയ സ്വകാര്യ ജാലകം
+Name[mr]=नवीन वैयक्तिक पटल
+Name[ms]=Tetingkap peribadi baharu
+Name[nb_NO]=Nytt privat vindu
+Name[nl]=Nieuw privévenster
+Name[nn_NO]=Nytt privat vindauge
+Name[or]=ନୂତନ ବ୍ୟକ୍ତିଗତ ୱିଣ୍ଡୋ
+Name[pa_IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ
+Name[pl]=Nowe okno w trybie prywatnym
+Name[pt_BR]=Nova janela privativa
+Name[pt_PT]=Nova janela privada
+Name[rm]=Nova fanestra privata
+Name[ro]=Fereastră fără urme nouă
+Name[ru]=Новое приватное окно
+Name[si]=නව පුද්ගලික කවුළුව
+Name[sk]=Nové okno v režime Súkromné prehliadanie
+Name[sl]=Novo zasebno okno
+Name[son]=Sutura zanfun taaga
+Name[sq]=Dritare e re private
+Name[sr]=Нови приватни прозор
+Name[sv_SE]=Nytt privat fönster
+Name[ta]=புதிய தனிப்பட்ட சாளரம்
+Name[te]=కొత్త ఆంతరంగిక విండో
+Name[th]=หน้าต่างท่องเว็บแบบส่วนตัวใหม่
+Name[tr]=Yeni gizli pencere
+Name[uk]=Нове приватне вікно
+Name[uz]=Yangi shaxsiy oyna
+Name[vi]=Cửa sổ riêng tư mới
+Name[xh]=Ifestile yangasese entsha
+Name[zh_CN]=新建隐私浏览窗口
+Name[zh_TW]=新增隱私視窗
+Exec=iceweasel -private-window
diff --git a/libre-testing/iceweasel/libre.patch b/libre-testing/iceweasel/libre.patch
new file mode 100644
index 000000000..a434fef2f
--- /dev/null
+++ b/libre-testing/iceweasel/libre.patch
@@ -0,0 +1,338 @@
+diff --git a/browser/base/content/abouthome/aboutHome.css b/browser/base/content/abouthome/aboutHome.css
+index c1ef3a4..48e1a16 100644
+--- a/browser/base/content/abouthome/aboutHome.css
++++ b/browser/base/content/abouthome/aboutHome.css
+@@ -343,26 +343,46 @@ body[narrow] #restorePreviousSession::before {
+ width: 32px;
+ }
+
+-#aboutMozilla {
++#aboutGNU {
+ display: block;
+- position: relative; /* pin wordmark to edge of document, not of viewport */
+ -moz-box-ordinal-group: 0;
+ opacity: .5;
+ transition: opacity 150ms;
+ }
+
+-#aboutMozilla:hover {
++#aboutGNU:hover {
+ opacity: 1;
+ }
+
+-#aboutMozilla::before {
+- content: url("chrome://browser/content/abouthome/mozilla.png");
++#aboutGNU::before {
++ content: url("chrome://browser/content/abouthome/gnu_headshadow.png");
+ display: block;
+ position: absolute;
+ top: 12px;
+ right: 12px;
+- width: 69px;
+- height: 19px;
++ width: 200px;
++ height: 110px;
++}
++
++#aboutDRMfree {
++ display: block;
++ -moz-box-ordinal-group: 0;
++ opacity: .5;
++ transition: opacity 150ms;
++}
++
++#aboutDRMfree:hover {
++ opacity: 1;
++}
++
++#aboutDRMfree::before {
++ content: url("chrome://browser/content/abouthome/drm-free.png");
++ display: block;
++ position: absolute;
++ top: 12px;
++ left: 12px;
++ width: 120px;
++ height: 120px;
+ }
+
+ /* [HiDPI]
+@@ -435,9 +455,5 @@ body[narrow] #restorePreviousSession::before {
+ transform: scale(-0.5, 0.5) translateX(24px);
+ transform-origin: top center;
+ }
+-
+- #aboutMozilla::before {
+- content: url("chrome://browser/content/abouthome/mozilla@2x.png");
+- }
+ }
+
+diff --git a/browser/base/content/abouthome/aboutHome.js b/browser/base/content/abouthome/aboutHome.js
+index 8943165..cd2efd8 100644
+--- a/browser/base/content/abouthome/aboutHome.js
++++ b/browser/base/content/abouthome/aboutHome.js
+@@ -9,17 +9,13 @@
+ // * add a <span/> for it in aboutHome.xhtml
+ // * add an entry here in the proper ordering (based on spans)
+ // The <a/> part of the snippet will be linked to the corresponding url.
+-const DEFAULT_SNIPPETS_URLS = [
+- "https://www.mozilla.org/firefox/features/?utm_source=snippet&utm_medium=snippet&utm_campaign=default+feature+snippet"
+-, "https://addons.mozilla.org/firefox/?utm_source=snippet&utm_medium=snippet&utm_campaign=addons"
+-];
++const DEFAULT_SNIPPETS_URLS = [ "" ];
+
+-const SNIPPETS_UPDATE_INTERVAL_MS = 14400000; // 4 hours.
++const SNIPPETS_UPDATE_INTERVAL_MS = 86400000; // 1 Day.
+
+ // IndexedDB storage constants.
+ const DATABASE_NAME = "abouthome";
+ const DATABASE_VERSION = 1;
+-const DATABASE_STORAGE = "persistent";
+ const SNIPPETS_OBJECTSTORE_NAME = "snippets";
+ var searchText;
+
+diff --git a/browser/base/content/abouthome/aboutHome.xhtml b/browser/base/content/abouthome/aboutHome.xhtml
+index 655f64b..6dd78e5 100644
+--- a/browser/base/content/abouthome/aboutHome.xhtml
++++ b/browser/base/content/abouthome/aboutHome.xhtml
+@@ -49,10 +49,6 @@
+ </div>
+
+ <div id="snippetContainer">
+- <div id="defaultSnippets" hidden="true">
+- <span id="defaultSnippet1">&abouthome.defaultSnippet1.v1;</span>
+- <span id="defaultSnippet2">&abouthome.defaultSnippet2.v1;</span>
+- </div>
+ <span id="rightsSnippet" hidden="true">&abouthome.rightsSnippet;</span>
+ <div id="snippets"/>
+ </div>
+@@ -74,7 +70,7 @@
+ <button class="launchButton" id="restorePreviousSession">&historyRestoreLastSession.label;</button>
+ </div>
+
+- <a id="aboutMozilla" href="https://www.mozilla.org/about/?utm_source=about-home&amp;utm_medium=Referral"
+- aria-label="&abouthome.aboutMozilla.label;"/>
++ <a id="aboutGNU" href="https://www.gnu.org"></a>
++ <a id="aboutDRMfree" href="https://www.defectivebydesign.org/drm-free"></a>
+ </body>
+ </html>
+diff --git a/browser/base/jar.mn b/browser/base/jar.mn
+index c9a70fc..ab0f1dd 100644
+--- a/browser/base/jar.mn
++++ b/browser/base/jar.mn
+@@ -32,7 +32,8 @@ browser.jar:
+ content/browser/abouthome/settings.png (content/abouthome/settings.png)
+ content/browser/abouthome/restore.png (content/abouthome/restore.png)
+ content/browser/abouthome/restore-large.png (content/abouthome/restore-large.png)
+- content/browser/abouthome/mozilla.png (content/abouthome/mozilla.png)
++ content/browser/abouthome/gnu_headshadow.png (content/abouthome/gnu_headshadow.png)
++ content/browser/abouthome/drm-free.png (content/abouthome/drm-free.png)
+ content/browser/abouthome/snippet1@2x.png (content/abouthome/snippet1@2x.png)
+ content/browser/abouthome/snippet2@2x.png (content/abouthome/snippet2@2x.png)
+ content/browser/abouthome/downloads@2x.png (content/abouthome/downloads@2x.png)
+@@ -43,7 +44,6 @@ browser.jar:
+ content/browser/abouthome/settings@2x.png (content/abouthome/settings@2x.png)
+ content/browser/abouthome/restore@2x.png (content/abouthome/restore@2x.png)
+ content/browser/abouthome/restore-large@2x.png (content/abouthome/restore-large@2x.png)
+- content/browser/abouthome/mozilla@2x.png (content/abouthome/mozilla@2x.png)
+
+ content/browser/aboutNetError.xhtml (content/aboutNetError.xhtml)
+
+diff --git a/browser/locales/en-US/chrome/browser/aboutHome.dtd b/browser/locales/en-US/chrome/browser/aboutHome.dtd
+index 7e3b57a..6edc89d 100644
+--- a/browser/locales/en-US/chrome/browser/aboutHome.dtd
++++ b/browser/locales/en-US/chrome/browser/aboutHome.dtd
+@@ -11,14 +11,6 @@
+
+ <!ENTITY abouthome.pageTitle "&brandFullName; Start Page">
+
+-<!-- LOCALIZATION NOTE (abouthome.defaultSnippet1.v1):
+- text in <a/> will be linked to the Firefox features page on mozilla.com
+--->
+-<!ENTITY abouthome.defaultSnippet1.v1 "Thanks for choosing Firefox! To get the most out of your browser, learn more about the <a>latest features</a>.">
+-<!-- LOCALIZATION NOTE (abouthome.defaultSnippet2.v1):
+- text in <a/> will be linked to the featured add-ons on addons.mozilla.org
+--->
+-<!ENTITY abouthome.defaultSnippet2.v1 "It’s easy to customize your Firefox exactly the way you want it. <a>Choose from thousands of add-ons</a>.">
+ <!-- LOCALIZATION NOTE (abouthome.rightsSnippet): text in <a/> will be linked to about:rights -->
+ <!ENTITY abouthome.rightsSnippet "&brandFullName; is free and open source software from the non-profit Mozilla Foundation. <a>Know your rights…</a>">
+
+diff --git a/browser/locales/en-US/chrome/browser-region/region.properties b/browser/locales/en-US/chrome/browser-region/region.properties
+index e078ed5..ce2c5ed 100644
+--- a/browser/locales/en-US/chrome/browser-region/region.properties
++++ b/browser/locales/en-US/chrome/browser-region/region.properties
+@@ -3,17 +3,12 @@
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ # Default search engine
+-browser.search.defaultenginename=Google
++browser.search.defaultenginename=searx
+
+ # Search engine order (order displayed in the search bar dropdown)s
+-browser.search.order.1=Google
+-browser.search.order.2=Yahoo
+-browser.search.order.3=Bing
+-
+-# This is the default set of web based feed handlers shown in the reader
+-# selection UI
+-browser.contentHandlers.types.0.title=My Yahoo!
+-browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
++browser.search.order.1=searx
++browser.search.order.2=DuckDuckGo HTML
++browser.search.order.3=DuckDuckGo Lite
+
+ # increment this number when anything gets changed in the list below. This will
+ # cause Firefox to re-read these prefs and inject any new handlers into the
+@@ -22,20 +17,10 @@ browser.contentHandlers.types.0.uri=https://add.my.yahoo.com/rss?url=%s
+ # don't make any spelling errors here.
+ gecko.handlerService.defaultHandlersVersion=4
+
+-# The default set of protocol handlers for webcal:
+-gecko.handlerService.schemes.webcal.0.name=30 Boxes
+-gecko.handlerService.schemes.webcal.0.uriTemplate=https://30boxes.com/external/widget?refer=ff&url=%s
+-
+-# The default set of protocol handlers for mailto:
+-gecko.handlerService.schemes.mailto.0.name=Yahoo! Mail
+-gecko.handlerService.schemes.mailto.0.uriTemplate=https://compose.mail.yahoo.com/?To=%s
+-gecko.handlerService.schemes.mailto.1.name=Gmail
+-gecko.handlerService.schemes.mailto.1.uriTemplate=https://mail.google.com/mail/?extsrc=mailto&url=%s
+-
+ # The default set of protocol handlers for irc:
+-gecko.handlerService.schemes.irc.0.name=Mibbit
+-gecko.handlerService.schemes.irc.0.uriTemplate=https://www.mibbit.com/?url=%s
++gecko.handlerService.schemes.irc.0.name=Freenode Web IRC
++gecko.handlerService.schemes.irc.0.uriTemplate=https://webchat.freenode.net
+
+ # The default set of protocol handlers for ircs:
+-gecko.handlerService.schemes.ircs.0.name=Mibbit
+-gecko.handlerService.schemes.ircs.0.uriTemplate=https://www.mibbit.com/?url=%s
++gecko.handlerService.schemes.ircs.0.name=Freenode Web IRC
++gecko.handlerService.schemes.ircs.0.uriTemplate=https://webchat.freenode.net
+diff --git a/browser/locales/generic/profile/bookmarks.html.in b/browser/locales/generic/profile/bookmarks.html.in
+index cba600e..cd4e711 100644
+--- a/browser/locales/generic/profile/bookmarks.html.in
++++ b/browser/locales/generic/profile/bookmarks.html.in
+@@ -20,13 +20,20 @@
+ <DT><H3 PERSONAL_TOOLBAR_FOLDER="true" ID="rdf:#$FvPhC3">@bookmarks_toolbarfolder@</H3>
+ <DD>@bookmarks_toolbarfolder_description@
+ <DL><p>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/central/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAz5JREFUeNpcU0toXFUY/s49596588ikySSmM8rk0UkJEirVTVEjYk1NUdRFFgouXZQI2k2hUCjdiYIuCi4Kuig0DbqQYgU3Yi0iFRuRCBMwaZvMZDTNY95z3/fM8b8jldpzOeeee/i/737n+/+f4ZExf730rkiaZ9NJMx/nmk5HypMqqLr+ZuD4F67N5ZYejmfRsnvhyKsLhSs3zP70SubgYKHSdFENu+gXAprQIGnvBi5ez0m1b6u7M399+PTx+UvtCKtFi2F6195qXK2byir88esy5ksfYND5DhuhRCtUKBNB0Q7w5Z8ee2GgWdjOn250fn5v5j8F5dOHlZD0kWRgAwp3hrKY0S9BJWKIcQ5PShhNG4+1bHx+IocT+RXcrRSDMfFNRvvt3Oyp/icIrRhUl9hoO4kt3F55Bxf3LkLV20jWOohbDjzXxyc/lMH0cRSyCd1xq+dFhu986t7T0CUwIzB8EkW3O5ibhj44ib7NJhiBKRoB/aS4ZWHjbxtjGQYP7nGRTjim1SaQqYiAVAREpHG8vzWJn+6PQ6CF0HPR7nQQczpYeEWHyWMUkwU8MSECGwgJxAWp9xWKNzkuH3oet+JDlIE9Momedh1G4CN0bfhVG9nsS0BQQthJx0V7j3elq7ihqV5ezQTwZmodP9ZGkU/bOPr4Nr53xtDYsaD7Dg4nNqFaH5OCYSSdGhf7daNmuv6wEKqXk/yExKGBHSznFsH6FFpKQ/JAA0ulUejWLt44lkHXsqDaX6C6Nl4Rnq8vK8s/KThDMlJhkI91YOO+iR3XwEelCdTCBLSgijNzd6DLNfhlHfZ6FtWiWBQpq/V2LdSrrNPljBQkoOjuCiPxAMutOIbkPqYSEqeequGZaTLzdhZhS0PlnlB9bvhtr5CuHj3y2Qj8hVQ/kEopxONEEsO/0yATDYXYAdWrE69JEElXq7Hyk0tro+xBU1yZmr4xrIcvptIRCZlJJAYBmRGRkD08aivA7VDvWPqt564Xn41w/AHB1/u7l1/uGxGU8mNcgodUNDIq0JDeLnpzc1uo1Qr76rWbqyf/142PjsXJqdkmN2YDnQ9oGkJNU+t57q7qUv4y9/t64+HYfwQYAN7OczrzUDvGAAAAAElFTkSuQmCC" ID="rdf:#$GvPhC3">@getting_started@</A>
++ <DT><A HREF="https://www.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre</A>
+ </DL><p>
+- <DT><H3 ID="rdf:#$ZvPhC3">@firefox_heading@</H3>
++ <DT><H3 ID="rdf:#$YvPhC3">Parabola GNU/Linux-libre</H3>
+ <DL><p>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/help/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$22iCK1">@firefox_help@</A>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/firefox/customize/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$32iCK1">@firefox_customize@</A>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/contribute/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$42iCK1">@firefox_community@</A>
+- <DT><A HREF="https://www.mozilla.org/@AB_CD@/about/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwMDAsTBZbkNwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABNElEQVQ4y8WSsU0DURBE3yyWIaAJaqAAN4DPSL6AlIACKIEOyJEgRsIgOOkiInJqgAKowNg7BHdn7MOksNl+zZ//dvbDf5cAiklp22BdVtXdeTEpDYDB9m1VzU6OJuVp2NdEQCaI96fH2YHG4+mDduKYNMYINTcjcGbXzQVDEAphG0k48zUsajIbnAiMIXThpW8EICE0RAK4dvoKg9NIcTiQ589otyHOZLnwqK5nLwBFUZ4igc3iM0d1ff8CMC6mZ6Ihiaqq3gi1aUAnArD00SW1fq5OLBg0ymYmSZsR2/t4e/rGyCLW0sbp3oq+yTYqVgytQWui2FS7XYF7GFprY921T4CNQt8zr47dNzCkIX7y/jBtH+v+RGMQrc828W8pApnZbmEVQp/Ae7BlOy2ttib81/UFc+WRWEbjckIAAAAASUVORK5CYII=" ID="rdf:#$52iCK1">@firefox_about@</A>
++ <DT><A HREF="https://www.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre</A>
++ <DT><A HREF="https://www.parabola.nu/packages/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre Packages</A>
++ <DT><A HREF="https://wiki.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre Wiki</A>
++ <DT><A HREF="https://labs.parabola.nu/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABL0lEQVQ4jWNgoCcoq16VU1GzygnEBtEVDWuV8GooKFuhWVG3uiM3d5UokG4qr1szAaa5vGbVt4ralacwNDU0rGIrr10VBVG0+lxhwyqVsqqVtRW1q6eD5IvL19oB2V+B+D9QzQu4xtDQVZylVavygRKHqurWOlbUrknKK12qWlCwWLK8elUFA8N/xvLy5VYVtas+gzWDDVi9E2QjT1XdcufymjWpQJt1cXmnvHwVP1DzR7hmIC6vW+kOtpnYQKysW30arrlm9RVi9cFBRfXKJTADympWJZNsQFnN6rUQA1adAQU2SZqBXmUGBtozUDiU1qxQJtl2oCY3kO2l1avCSdYMAsBAWwyM2plkaS4p6eYGOv1YQ0MDB1kGlFWuDChuWKZBlmYQqK5eJU22ZkIAAEIlnQZQkzITAAAAAElFTkSuQmCC">Parabola GNU/Linux-libre Labs</A>
++ </DL><p>
++ <DT><H3 ID="rdf:#$ZvPhC3">Free Software Foundation</H3>
++ <DL><p>
++ <DT><A HREF="https://www.fsf.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAADG0lEQVQoFQEQA+/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAAAAAAAAAAAAAAAAAAAA2qOp7tTXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAP///wAAAAAAAOCyt7pUXQcSEgcQDwAAAP///wAAAAAAAAD//x9NSDqNhQEBAQQAAAAAAAAAAAAAAAAQJiQGDQ0aPToZPjoAAQEAAAAAAAAAAAABAQEpZV4AAAAAAAAAAAAA////////////////pSIv05KZ////////////////////////////////AAAAAQAAAP///6krNwAAAAAAAPHc3ggSEQcSEQAAAAAAAAAAABY3NEGelQAAAAAAAAEBAQEAAAD///+YARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGDg1g690CBgYAAAABAQEEAAAAAAAAS7etAAAAAAAAwGVtHklFIlJOAAAAAAAAAAAAAAAA+/X2BwYGAAAAAAAABAAAAAAAAB1IQwAAAAAAAAYNDBAmJB1IQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAgL//v4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAQEB//7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAECAv/+/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD////////////////cqK3qzM////////////////////////////////8AAAABAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGuLjDf9F8oBAAAAAElFTkSuQmCC">Free Software Foundation</A>
++ <DT><A HREF="https://www.gnu.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAGFBMVEVFRUV+fn6mpqa/v7/Ozs7Y2Njg4OD8/Pwuhn+TAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEQAACxEBf2RfkQAAAAd0SU1FB9MBDhQ6Gd8s57cAAAEVSURBVBgZBcGxVtpgGADQL9gHSBzqSognzMixmcWWzB6pmRHhnyvku6/fewMAIPD3TwHmQxHs6vr+A16bphNum/vV0x429201hcPjAGBTDZGnR/Kw1U181+u4HXvOdSxjUcztz8jjg1xGVBG9XPYxt4PviKiaWLg168iXtbrq+mPT1utjNcR1U73deRnL43M2sRgj3+oYs8uL3rLphPd2QWmHbMu/VS/cnk6UdtSW657g9yBlcZ0UAkUWzPvyRaAYmfd+HT4IZtvC59ibEJxXiqJjQpBpNEufBYE0McoOAunGhRMEFIPc7h4goJigQEBxk8u7AgEpL3IEAUZfcgAByGFXQACm5+4MAuB19QMEgI8CAgDgP4rivVgoKP6ZAAAAAElFTkSuQmCC">The GNU Operating System and the Free Software Movement</A>
++ <DT><A HREF="https://libreplanet.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACfElEQVQ4jZXTS0hUcRTH8f+9M3fGd0gRRq1a2bZdBAotWtS6TQtB6IHgKzRy0UKqjRaRCAq+R21MDMsUR83JR5fJxhmaK2lzsWAWw+ToEHJxgnFm7reFIgza66z/58P/dzhHcESZpsluIsFPwyCVSmGa5lHPEEIIkdGYTqPPvqUlP4fK8nJ2DINYNEq71YJ3fv4QlAGkUynaj+VRdfUK7580M52rEN/ZYWNjg2GrjEMSPFXsmOn0YcA0TZ4V5tNZUkJTTTWfJiZIJhJ8U1VczwcZs0o4JUHzufM0ZGcf/OQASCaTxGIxDMNA00P8iEbpuXyJ8Tw77+wWJhWZQYuVbiHoFIKwpmUC4XCYzc1NDMMgHo9z8+IFvl6/xsf7D9ArbjOpyAxLEt1C0CUErfvJDwBd14lEImxvb/N9fR1fgY3egmyWsq0sO/poUyw4pb3mLiFolyRM09wDEokEfr+fUChEJBJh4HgBS7kKn92zLIy9ZriqklFZwiEEHfsRRp1O0un0HpDa3cU9M8PKygp3Tp5AzbKgZlmYt1uYtkn02q0MyYKmnBxWNI27Nhtut5tkMrkHmKZJbWkpqqryQpFxKTJTisyEVeaVRWJIlqgpLuZRWRkejwe/34/P58ucwZvWVhYXF5l2uejIzeHGqbM4ZYmB/dy1hUV8mJpibm4On8/H1tbW4T1YXV3F6/WysLDA5Pg4nfsDe5yfz8OiIjweD5qmEQwGf7/KwWCQtbU1NE2jRZbpEoI2SWKqr49lVUXX9T/fAkAgEKC/e5SW6mo6hKD+zGn6e0bw+/x/PyaA9S/rvOwfobGukfpbddyraMDR7iCwHPg34H9KCCF+Abts3KCj/p6aAAAAAElFTkSuQmCC">LibrePlanet</A>
++ <DT><A HREF="https://www.h-node.org/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABgElEQVQ4jaXRz2uSARzHcb0vlRGEzTVWISU1BVkFYTIyjNK1pKcxHA+yhWMWIamHYikFgpoLIi9jwegi3QbL9SzdLmMbM9J+DkJBgm5RDvEPeHeQHOyQz0OH9+V7ePGBr0pqpPmfVPsP8a0AR4MnMEwf48x9K0s/E8oAY9iEMOvD+8yP2qVjrhhRBnSN61n5sIpULqC+pGHh8wNlgEY8jPQXcGh4VXukDND5evYAl46odIuXtYdKAANSudAChO52/XeMZMohecCbcoGdH99Y+7LO72adT9+/4nh8nYOjBl7/SsoB8gBkpHk8T0S2K++pN3fRin3cfnFDHvCuWkI9rEMvHGEo5gbAHnXhnLF1BpZLeRaLOVT2A8Q3A5wMngXgWtKLxX9KPqC+rCWQvYkpeK4NWKcGOgO50ts2MJJ0cPreeQDciTHMchZYIhcwh2wcuqjn+ccwGm9v6wsTxxn0dVgQXZ7Ek3Agpq6QrcaQGmmebtxFSDkRU1fJVmL/BpT2ByV/3eDMhinRAAAAAElFTkSuQmCC">h-node</A>
+ </DL><p>
+ </DL><p>
+diff --git a/devtools/client/locales/en-US/connection-screen.dtd b/devtools/client/locales/en-US/connection-screen.dtd
+index 674a408..d27e97f 100644
+--- a/devtools/client/locales/en-US/connection-screen.dtd
++++ b/devtools/client/locales/en-US/connection-screen.dtd
+@@ -24,7 +24,7 @@
+ <!-- LOCALIZATION NOTE (remoteHelp, remoteDocumentation, remoteHelpSuffix):
+ these strings will be concatenated in a single label, remoteDocumentation will
+ be used as text for a link to MDN. -->
+-<!ENTITY remoteHelp "Firefox Developer Tools can debug remote devices (Firefox for Android and Firefox OS, for example). Make sure that you have turned on the ‘Remote debugging’ option in the remote device. For more, see the ">
++<!ENTITY remoteHelp "Iceweasel Developer Tools can debug remote devices. Make sure that you have turned on the ‘Remote debugging’ option in the remote device. For more, see the ">
+ <!ENTITY remoteDocumentation "documentation">
+ <!ENTITY remoteHelpSuffix ".">
+
+diff --git a/devtools/client/locales/en-US/sourceeditor.properties b/devtools/client/locales/en-US/sourceeditor.properties
+index 01447e3..0bc043e 100644
+--- a/devtools/client/locales/en-US/sourceeditor.properties
++++ b/devtools/client/locales/en-US/sourceeditor.properties
+@@ -4,7 +4,7 @@
+
+ # LOCALIZATION NOTE These strings are used inside the Source Editor component.
+ # This component is used whenever source code is displayed for the purpose of
+-# being edited, inside the Firefox developer tools - current examples are the
++# being edited, inside the Iceweasel developer tools - current examples are the
+ # Scratchpad and the Style Editor tools.
+
+ # LOCALIZATION NOTE The correct localization of this file might be to keep it
+diff --git a/devtools/client/locales/en-US/toolbox.dtd b/devtools/client/locales/en-US/toolbox.dtd
+index 53385de..fb9a95a 100644
+--- a/devtools/client/locales/en-US/toolbox.dtd
++++ b/devtools/client/locales/en-US/toolbox.dtd
+@@ -117,7 +117,7 @@ values from browser.dtd. -->
+ - checkbox that toggles remote debugging, i.e. devtools.debugger.remote-enabled
+ - boolean preference in about:config, in the options panel. -->
+ <!ENTITY options.enableRemote.label3 "Enable remote debugging">
+-<!ENTITY options.enableRemote.tooltip "Turning this option on will allow the developer tools to debug remote Firefox instance like Firefox OS">
++<!ENTITY options.enableRemote.tooltip "Turning this option on will allow the developer tools to debug remote Iceweasel instance like Iceweasel OS">
+
+ <!-- LOCALIZATION NOTE (options.enableWorkers.label): This is the label for the
+ - checkbox that toggles worker debugging, i.e. devtools.debugger.workers
+@@ -146,7 +146,7 @@ values from browser.dtd. -->
+ <!-- LOCALIZATION NOTE (options.selectDefaultTools.label): This is the label for
+ - the heading of group of checkboxes corresponding to the default developer
+ - tools. -->
+-<!ENTITY options.selectDefaultTools.label "Default Firefox Developer Tools">
++<!ENTITY options.selectDefaultTools.label "Default Iceweasel Developer Tools">
+
+ <!-- LOCALIZATION NOTE (options.selectAdditionalTools.label): This is the label for
+ - the heading of group of checkboxes corresponding to the developer tools
+diff --git a/devtools/client/locales/en-US/webide.dtd b/devtools/client/locales/en-US/webide.dtd
+index 5e1a80c..8f375da 100644
+--- a/devtools/client/locales/en-US/webide.dtd
++++ b/devtools/client/locales/en-US/webide.dtd
+@@ -2,7 +2,7 @@
+ - 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/. -->
+
+-<!ENTITY windowTitle "Firefox WebIDE">
++<!ENTITY windowTitle "Iceweasel WebIDE">
+
+ <!ENTITY projectMenu_label "Project">
+ <!ENTITY projectMenu_accesskey "P">
+@@ -59,7 +59,7 @@
+ <!ENTITY projectButton_label "Open App">
+ <!ENTITY runtimeButton_label "Select Runtime">
+
+-<!-- We try to repicate Firefox' bindings: -->
++<!-- We try to repicate Iceweasel' bindings: -->
+ <!-- quit app -->
+ <!ENTITY key_quit "W">
+ <!-- open menu -->
+diff --git a/devtools/client/locales/en-US/webide.properties b/devtools/client/locales/en-US/webide.properties
+index 2368ad7..05e39c7 100644
+--- a/devtools/client/locales/en-US/webide.properties
++++ b/devtools/client/locales/en-US/webide.properties
+@@ -2,8 +2,8 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+-title_noApp=Firefox WebIDE
+-title_app=Firefox WebIDE: %S
++title_noApp=Iceweasel WebIDE
++title_app=Iceweasel WebIDE: %S
+
+ runtimeButton_label=Select Runtime
+ projectButton_label=Open App
+@@ -54,10 +54,10 @@ error_runtimeVersionTooRecent=The connected runtime has a more recent build date
+ addons_stable=stable
+ addons_unstable=unstable
+ # LOCALIZATION NOTE (addons_simulator_label): This label is shown as the name of
+-# a given simulator version in the "Manage Simulators" pane. %1$S: Firefox OS
++# a given simulator version in the "Manage Simulators" pane. %1$S: Iceweasel OS
+ # version in the simulator, ex. 1.3. %2$S: Simulator stability label, ex.
+ # "stable" or "unstable".
+-addons_simulator_label=Firefox OS %1$S Simulator (%2$S)
++addons_simulator_label=Iceweasel OS %1$S Simulator (%2$S)
+ addons_install_button=install
+ addons_uninstall_button=uninstall
+ addons_adb_label=ADB Helper Add-on
diff --git a/libre-testing/iceweasel/mozconfig b/libre-testing/iceweasel/mozconfig
new file mode 100644
index 000000000..b3dde9a7d
--- /dev/null
+++ b/libre-testing/iceweasel/mozconfig
@@ -0,0 +1,40 @@
+. $topsrcdir/browser/config/mozconfig
+
+ac_add_options --prefix=/usr
+ac_add_options --enable-release
+ac_add_options --enable-gold
+ac_add_options --enable-pie
+ac_add_options --enable-rust
+
+# Iceweasel
+ac_add_options --disable-official-branding
+ac_add_options --with-branding=debian/branding
+
+# System libraries
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-icu
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-system-libevent
+ac_add_options --with-system-libvpx
+ac_add_options --enable-system-hunspell
+ac_add_options --enable-system-sqlite
+ac_add_options --enable-system-ffi
+ac_add_options --enable-system-pixman
+
+# Features
+ac_add_options --enable-startup-notification
+ac_add_options --disable-updater
+ac_add_options --disable-crashreporter
+
+STRIP_FLAGS="--strip-debug"
+
+# Parabola features
+ac_add_options --disable-safe-browsing
+ac_add_options --disable-url-classifier
+ac_add_options --disable-eme
+
+# Other
+mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/moz-objdir
diff --git a/libre-testing/iceweasel/mozilla-1253216.patch b/libre-testing/iceweasel/mozilla-1253216.patch
new file mode 100644
index 000000000..c9252da5f
--- /dev/null
+++ b/libre-testing/iceweasel/mozilla-1253216.patch
@@ -0,0 +1,12 @@
+diff -up firefox-48.0/js/src/jit/AtomicOperations.h.old firefox-48.0/js/src/jit/AtomicOperations.h
+--- firefox-48.0/js/src/jit/AtomicOperations.h.old 2016-07-27 09:42:43.148175449 +0200
++++ firefox-48.0/js/src/jit/AtomicOperations.h 2016-07-27 09:41:13.000000000 +0200
+@@ -340,7 +340,7 @@ AtomicOperations::isLockfree(int32_t siz
+ # elif defined(__aarch64__)
+ # include "jit/arm64/AtomicOperations-arm64.h"
+ # else
+-# include "jit/none/AtomicOperations-none.h" // These MOZ_CRASH() always
++# include "jit/none/AtomicOperations-ppc.h"
+ # endif
+ #elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+ # include "jit/x86-shared/AtomicOperations-x86-shared.h"
diff --git a/libre-testing/iceweasel/mozilla-build-arm.patch b/libre-testing/iceweasel/mozilla-build-arm.patch
new file mode 100644
index 000000000..774147bbb
--- /dev/null
+++ b/libre-testing/iceweasel/mozilla-build-arm.patch
@@ -0,0 +1,24 @@
+diff -up firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi.arm firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi
+--- firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi.arm 2016-04-25 12:03:12.486027089 +0200
++++ firefox-46.0/media/webrtc/trunk/webrtc/build/common.gypi 2016-04-25 12:05:55.714644873 +0200
+@@ -312,20 +312,6 @@
+ 'defines': [
+ 'WEBRTC_ARCH_ARM',
+ ],
+- 'conditions': [
+- ['arm_version>=7', {
+- 'defines': ['WEBRTC_ARCH_ARM_V7',
+- 'WEBRTC_BUILD_NEON_LIBS'],
+- 'conditions': [
+- ['arm_neon==1', {
+- 'defines': ['WEBRTC_ARCH_ARM_NEON',],
+- }],
+- ['arm_neon==0 and arm_neon_optional==1', {
+- 'defines': ['WEBRTC_DETECT_ARM_NEON',],
+- }],
+- ],
+- }],
+- ],
+ }],
+ ['os_bsd==1', {
+ 'defines': [
diff --git a/libre-testing/iceweasel/no-libnotify.patch b/libre-testing/iceweasel/no-libnotify.patch
new file mode 100644
index 000000000..8d5845743
--- /dev/null
+++ b/libre-testing/iceweasel/no-libnotify.patch
@@ -0,0 +1,51 @@
+diff --git i/toolkit/system/gnome/moz.build w/toolkit/system/gnome/moz.build
+index 0ecde07..206d6eb 100644
+--- i/toolkit/system/gnome/moz.build
++++ w/toolkit/system/gnome/moz.build
+@@ -5,9 +5,7 @@
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ SOURCES += [
+- 'nsAlertsIconListener.cpp',
+ 'nsGnomeModule.cpp',
+- 'nsSystemAlertsService.cpp',
+ ]
+
+ if CONFIG['MOZ_ENABLE_GCONF']:
+diff --git i/toolkit/system/gnome/nsGnomeModule.cpp w/toolkit/system/gnome/nsGnomeModule.cpp
+index 6ecebcc..2f193a3 100644
+--- i/toolkit/system/gnome/nsGnomeModule.cpp
++++ w/toolkit/system/gnome/nsGnomeModule.cpp
+@@ -20,8 +20,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIOService)
+ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGSettingsService, Init)
+ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPackageKitService, Init)
+ #endif
+-#include "nsSystemAlertsService.h"
+-NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemAlertsService, Init)
+
+ #ifdef MOZ_ENABLE_GCONF
+ NS_DEFINE_NAMED_CID(NS_GCONFSERVICE_CID);
+@@ -31,7 +29,6 @@ NS_DEFINE_NAMED_CID(NS_GIOSERVICE_CID);
+ NS_DEFINE_NAMED_CID(NS_GSETTINGSSERVICE_CID);
+ NS_DEFINE_NAMED_CID(NS_PACKAGEKITSERVICE_CID);
+ #endif
+-NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID);
+
+ static const mozilla::Module::CIDEntry kGnomeCIDs[] = {
+ #ifdef MOZ_ENABLE_GCONF
+@@ -42,7 +39,6 @@ static const mozilla::Module::CIDEntry kGnomeCIDs[] = {
+ { &kNS_GSETTINGSSERVICE_CID, false, nullptr, nsGSettingsServiceConstructor },
+ { &kNS_PACKAGEKITSERVICE_CID, false, nullptr, nsPackageKitServiceConstructor },
+ #endif
+- { &kNS_SYSTEMALERTSSERVICE_CID, false, nullptr, nsSystemAlertsServiceConstructor },
+ { nullptr }
+ };
+
+@@ -55,7 +51,6 @@ static const mozilla::Module::ContractIDEntry kGnomeContracts[] = {
+ { NS_GSETTINGSSERVICE_CONTRACTID, &kNS_GSETTINGSSERVICE_CID },
+ { NS_PACKAGEKITSERVICE_CONTRACTID, &kNS_PACKAGEKITSERVICE_CID },
+ #endif
+- { NS_SYSTEMALERTSERVICE_CONTRACTID, &kNS_SYSTEMALERTSSERVICE_CID },
+ { nullptr }
+ };
+
diff --git a/libre-testing/iceweasel/remove-default-and-shell-icons-in-packaging-manifest.patch b/libre-testing/iceweasel/remove-default-and-shell-icons-in-packaging-manifest.patch
new file mode 100644
index 000000000..6bc67b30a
--- /dev/null
+++ b/libre-testing/iceweasel/remove-default-and-shell-icons-in-packaging-manifest.patch
@@ -0,0 +1,34 @@
+diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
+index cffcff1..85d28cc 100644
+--- a/browser/installer/package-manifest.in
++++ b/browser/installer/package-manifest.in
+@@ -653,11 +653,6 @@
+ @RESPATH@/chrome/toolkit.manifest
+ @RESPATH@/chrome/recording.manifest
+ @RESPATH@/chrome/recording/*
+-#ifdef MOZ_GTK
+-@RESPATH@/browser/chrome/icons/default/default16.png
+-@RESPATH@/browser/chrome/icons/default/default32.png
+-@RESPATH@/browser/chrome/icons/default/default48.png
+-#endif
+ @RESPATH@/browser/features/*
+
+ ; [Webide Files]
+@@ -670,17 +665,10 @@
+ @RESPATH@/browser/chrome/devtools.manifest
+ @RESPATH@/browser/@PREF_DIR@/devtools.js
+
+-; shell icons
+-#ifdef XP_UNIX
+-#ifndef XP_MACOSX
+-; shell icons
+-@RESPATH@/browser/icons/*.png
+ #ifdef MOZ_UPDATER
+ ; updater icon
+ @RESPATH@/icons/updater.png
+ #endif
+-#endif
+-#endif
+
+ ; [Default Preferences]
+ ; All the pref files must be part of base to prevent migration bugs
diff --git a/libre-testing/iceweasel/vendor.js b/libre-testing/iceweasel/vendor.js
new file mode 100644
index 000000000..ab4a9aedb
--- /dev/null
+++ b/libre-testing/iceweasel/vendor.js
@@ -0,0 +1,213 @@
+// Use LANG environment variable to choose locale
+pref("intl.locale.matchOS", true);
+
+// Disable default browser checking.
+pref("browser.shell.checkDefaultBrowser", false);
+
+// Don't disable our bundled extensions in the application directory
+pref("extensions.autoDisableScopes", 11);
+pref("extensions.shownSelectionUI", true);
+
+// Disable "alt" as a shortcut key to open full menu bar. Conflicts with "alt" as a modifier
+pref("ui.key.menuAccessKeyFocuses", false);
+
+// Disable the GeoLocation API for content
+pref("geo.enabled", false);
+
+// Make sure that the request URL of the GeoLocation backend is empty
+pref("geo.wifi.uri", "");
+
+// Disable Pocket and make sure that the request URLs of the Pocket are empty
+pref("browser.pocket.enabled", false);
+pref("browser.pocket.api", "");
+pref("browser.pocket.site", "");
+pref("browser.pocket.oAuthConsumerKey", "");
+pref("browser.pocket.useLocaleList", false);
+pref("browser.pocket.enabledLocales", "");
+
+// Disable Freedom Violating DRM Feature
+pref("browser.eme.ui.enabled", false);
+pref("media.eme.enabled", false);
+pref("media.eme.apiVisible", false);
+
+// Default to classic view for about:newtab
+pref("browser.newtabpage.enhanced", false);
+
+// Override add-on signing
+pref("xpinstall.signatures.required", false);
+
+// Poodle attack
+pref("security.tls.version.min", 1);
+
+// Don't call home for blacklisting
+pref("extensions.blocklist.enabled", false);
+
+// Disable plugin installer
+pref("plugins.hide_infobar_for_missing_plugin", true);
+pref("plugins.hide_infobar_for_outdated_plugin", true);
+pref("plugins.notifyMissingFlash", false);
+
+//https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
+//pref("media.mediasource.enabled",true);
+
+//Speeding it up
+pref("network.http.pipelining", true);
+pref("network.http.proxy.pipelining", true);
+pref("network.http.pipelining.maxrequests", 10);
+pref("nglayout.initialpaint.delay", 0);
+
+// Disable third party cookies
+pref("network.cookie.cookieBehavior", 1);
+
+// Prevent EULA dialog to popup on first run
+pref("browser.EULA.override", true);
+
+// disable app updater url
+pref("app.update.url", "http://127.0.0.1/");"
+
+// Set useragent to Firefox compatible
+//pref("general.useragent.compatMode.firefox", true);
+// Spoof the useragent to a generic one
+pref("general.useragent.compatMode.firefox", true);
+// Spoof the useragent to a generic one
+pref("general.useragent.override", "Mozilla/5.0 (Windows NT 6.1; rv:48.0) Gecko/20100101 Firefox/48.0");
+pref("general.appname.override", "Netscape");
+pref("general.appversion.override", "48.0");
+pref("general.buildID.override", "Gecko/20100101");
+pref("general.oscpu.override", "Windows NT 6.1");
+pref("general.platform.override", "Win32");
+
+// Privacy & Freedom Issues
+// https://webdevelopmentaid.wordpress.com/2013/10/21/customize-privacy-settings-in-mozilla-firefox-part-1-aboutconfig/
+// https://panopticlick.eff.org
+// http://ip-check.info
+// http://browserspy.dk
+// https://wiki.mozilla.org/Fingerprinting
+// http://www.browserleaks.com
+// http://fingerprint.pet-portal.eu
+pref("privacy.donottrackheader.enabled", true);
+pref("privacy.donottrackheader.value", 1);
+pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
+pref("browser.safebrowsing.enabled", false);
+pref("browser.safebrowsing.malware.enabled", false);
+//pref("services.sync.privacyURL", "https://www.gnu.org/software/gnuzilla/");
+pref("social.enabled", false);
+pref("social.remote-install.enabled", false);
+pref("datareporting.healthreport.uploadEnabled", false);
+pref("datareporting.healthreport.about.reportUrl", "127.0.0.1");
+pref("datareporting.healthreport.documentServerURI", "127.0.0.1");
+pref("healthreport.uploadEnabled", false);
+pref("social.toast-notifications.enabled", false);
+pref("datareporting.policy.dataSubmissionEnabled", false);
+pref("datareporting.healthreport.service.enabled", false);
+pref("browser.slowStartup.notificationDisabled", true);
+pref("network.http.sendRefererHeader", 2);
+//pref("network.http.referer.spoofSource", true);
+//http://grack.com/blog/2010/01/06/3rd-party-cookies-dom-storage-and-privacy/
+//pref("dom.storage.enabled", false);
+pref("dom.event.clipboardevents.enabled",false);
+pref("network.prefetch-next", false);
+pref("network.dns.disablePrefetch", true);
+pref("network.http.sendSecureXSiteReferrer", false);
+pref("toolkit.telemetry.enabled", false);
+// Do not tell what plugins do we have enabled: https://mail.mozilla.org/pipermail/firefox-dev/2013-November/001186.html
+pref("plugins.enumerable_names", "");
+pref("plugin.state.flash", 1);
+// Do not autoupdate search engines
+pref("browser.search.update", false);
+// Warn when the page tries to redirect or refresh
+//pref("accessibility.blockautorefresh", true);
+pref("dom.battery.enabled", false);
+pref("device.sensors.enabled", false);
+pref("camera.control.face_detection.enabled", false);
+pref("camera.control.autofocus_moving_callback.enabled", false);
+pref("network.http.speculative-parallel-limit", 0);
+
+// Crypto hardening
+// https://gist.github.com/haasn/69e19fc2fe0e25f3cff5
+//General settings
+//pref("security.tls.unrestricted_rc4_fallback", false);
+//pref("security.tls.insecure_fallback_hosts.use_static_list", false);
+//pref("security.tls.version.min", 1);
+//pref("security.ssl.require_safe_negotiation", true);
+//pref("security.ssl.treat_unsafe_negotiation_as_broken", true);
+//pref("security.ssl3.rsa_seed_sha", true);
+//pref("security.OCSP.enabled", 1);
+//pref("security.OCSP.require", true);
+
+// Disable channel updates
+pref("app.update.enabled", false);
+pref("app.update.auto", false);
+
+pref("font.default.x-western", "sans-serif");
+
+// Preferences for the Get Add-ons panel
+pref ("extensions.webservice.discoverURL", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref ("extensions.getAddons.search.url", "https://directory.fsf.org/wiki/GNU_IceCat");
+
+// Mobile
+pref("privacy.announcements.enabled", false);
+pref("browser.snippets.enabled", false);
+pref("browser.snippets.syncPromo.enabled", false);
+pref("browser.snippets.geoUrl", "http://127.0.0.1/");
+pref("browser.snippets.updateUrl", "http://127.0.0.1/");
+pref("browser.snippets.statsUrl", "http://127.0.0.1/");
+pref("datareporting.policy.firstRunTime", 0);
+pref("datareporting.policy.dataSubmissionPolicyVersion", 2);
+pref("browser.webapps.checkForUpdates", 0);
+pref("browser.webapps.updateCheckUrl", "http://127.0.0.1/");
+pref("app.faqURL", "http://libreplanet.org/wiki/Group:IceCat/FAQ");
+
+// PFS url
+pref("pfs.datasource.url", "http://gnuzilla.gnu.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%");
+pref("pfs.filehint.url", "http://gnuzilla.gnu.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%");
+
+// Disable Gecko media plugins: https://wiki.mozilla.org/GeckoMediaPlugins
+pref("media.gmp-manager.url", "http://127.0.0.1/");
+pref("media.gmp-manager.url.override", "data:text/plain,");
+pref("media.gmp-provider.enabled", false);
+// Don't install openh264 codec
+pref("media.gmp-gmpopenh264.enabled", false);
+
+//Disable heartbeat
+pref("browser.selfsupport.url", "");
+
+//Disable Link to FireFox Marketplace, currently loaded with non-free "apps"
+pref("browser.apps.URL", "");
+
+//Disable Firefox Hello
+pref("loop.enabled",false);
+pref("loop.feedback.baseUrl", "");
+pref("loop.gettingStarted.url", "");
+pref("loop.learnMoreUrl", "");
+pref("loop.legal.ToS_url", "");
+pref("loop.legal.privacy_url", "");
+pref("loop.oauth.google.redirect_uri", "");
+pref("loop.oauth.google.scope", "");
+pref("loop.server", "");
+pref("loop.soft_start_hostname", "");
+pref("loop.support_url", "");
+pref("loop.throttled2",false);
+
+// Use old style preferences, that allow javascript to be disabled
+pref("browser.preferences.inContent",false);
+
+// Don't download ads for the newtab page
+pref("browser.newtabpage.directory.source", "");
+pref("browser.newtabpage.directory.ping", "");
+pref("browser.newtabpage.introShown", true);
+
+// Disable home snippets
+pref("browser.aboutHomeSnippets.updateUrl", "data:text/html");
+
+// Disable hardware acceleration and WebGL
+//pref("layers.acceleration.disabled", false);
+pref("webgl.disabled", false);
+
+// Disable SSDP
+pref("browser.casting.enabled", false);
+
+//Disable directory service
+pref("social.directories", "");
+pref("social.whitelist", "");
+pref("social.shareDirectory", "");