diff --git a/.firefox.metadata b/.firefox.metadata
new file mode 100644
index 0000000..b84b811
--- /dev/null
+++ b/.firefox.metadata
@@ -0,0 +1,7 @@
+18a8f30a0356c751b8d0ea6f76e764cab13ee046 SOURCES/Python-2.7.13.tar.xz
+9d3f90807f716943bc5f32220f73ee07635e595d SOURCES/firefox-60.5.1esr.source.tar.xz
+5e08c187d9949f71efee7de41166e934c8265422 SOURCES/firefox-langpacks-60.5.1esr-20190213.tar.xz
+6724218efbb1f3fa14541cb2f255970b98446a45 SOURCES/firefox-symbolic.svg
+0de63f863b158454b9429234b52ed28a397ec45c SOURCES/gtk3-private-3.22.26-1.el6.src.rpm
+e188ab1a444697bc649e223c28389d82ca94c472 SOURCES/libffi-3.0.13-18.el7_3.src.rpm
+77fd30f7ebc12a629a31c1e252cec06af55a71fe SOURCES/yasm-1.2.0-3.el5.src.rpm
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..304f8a5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+SOURCES/Python-2.7.13.tar.xz
+SOURCES/firefox-60.5.1esr.source.tar.xz
+SOURCES/firefox-langpacks-60.5.1esr-20190213.tar.xz
+SOURCES/firefox-symbolic.svg
+SOURCES/gtk3-private-3.22.26-1.el6.src.rpm
+SOURCES/libffi-3.0.13-18.el7_3.src.rpm
+SOURCES/yasm-1.2.0-3.el5.src.rpm
diff --git a/SOURCES/build-aarch64-skia.patch b/SOURCES/build-aarch64-skia.patch
new file mode 100644
index 0000000..1ecad24
--- /dev/null
+++ b/SOURCES/build-aarch64-skia.patch
@@ -0,0 +1,12 @@
+diff -up firefox-61.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia firefox-61.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp
+--- firefox-61.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp.aarch64-skia	2018-06-20 09:19:11.411939714 +0200
++++ firefox-61.0/gfx/skia/skia/src/jumper/SkJumper_stages.cpp	2018-06-20 09:23:36.831919894 +0200
+@@ -686,7 +686,7 @@ SI F from_half(U16 h) {
+ }
+ 
+ SI U16 to_half(F f) {
+-#if defined(JUMPER_IS_NEON) && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3)  // Temporary workaround for some Google3 builds.
++#if 0 && defined(__aarch64__) && !defined(SK_BUILD_FOR_GOOGLE3)  // Temporary workaround for some Google3 builds.
+     return vcvt_f16_f32(f);
+ 
+ #elif defined(JUMPER_IS_HSW) || defined(JUMPER_IS_AVX512)
diff --git a/SOURCES/build-big-endian.patch b/SOURCES/build-big-endian.patch
new file mode 100644
index 0000000..e8ec439
--- /dev/null
+++ b/SOURCES/build-big-endian.patch
@@ -0,0 +1,84 @@
+diff -up firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h.big-endian firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h
+--- firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h.big-endian	2018-04-09 22:50:48.000000000 +0200
++++ firefox-60.0/gfx/skia/skia/include/core/SkColorPriv.h	2018-04-18 11:51:38.748680174 +0200
+@@ -54,18 +54,19 @@ static inline U8CPU SkUnitScalarClampToB
+  *
+  *  Here we enforce this constraint.
+  */
+-
++/*
+ #ifdef SK_CPU_BENDIAN
+     #define SK_RGBA_R32_SHIFT   24
+     #define SK_RGBA_G32_SHIFT   16
+     #define SK_RGBA_B32_SHIFT   8
+     #define SK_RGBA_A32_SHIFT   0
+ #else
++*/
+     #define SK_RGBA_R32_SHIFT   0
+     #define SK_RGBA_G32_SHIFT   8
+     #define SK_RGBA_B32_SHIFT   16
+     #define SK_RGBA_A32_SHIFT   24
+-#endif
++/*#endif*/
+ 
+ #define SkGetPackedA32(packed)      ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
+ #define SkGetPackedR32(packed)      ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
+diff -up firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h.big-endian firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h
+--- firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h.big-endian	2018-04-09 22:50:48.000000000 +0200
++++ firefox-60.0/gfx/skia/skia/include/core/SkImageInfo.h	2018-04-18 11:51:38.748680174 +0200
+@@ -84,7 +84,8 @@ enum SkColorType {
+ #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
+     kN32_SkColorType = kRGBA_8888_SkColorType,
+ #else
+-    #error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order"
++    //#error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order"
++    kN32_SkColorType = kBGRA_8888_SkColorType
+ #endif
+ };
+ 
+diff -up firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h.big-endian firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h
+--- firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h.big-endian	2018-04-09 22:50:48.000000000 +0200
++++ firefox-60.0/gfx/skia/skia/include/gpu/GrTypes.h	2018-04-18 11:51:38.748680174 +0200
+@@ -344,15 +344,13 @@ enum GrPixelConfig {
+ static const int kGrPixelConfigCnt = kLast_GrPixelConfig + 1;
+ 
+ // Aliases for pixel configs that match skia's byte order.
+-#ifndef SK_CPU_LENDIAN
+-    #error "Skia gpu currently assumes little endian"
+-#endif
+ #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
+     static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig;
+ #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
+     static const GrPixelConfig kSkia8888_GrPixelConfig = kRGBA_8888_GrPixelConfig;
+ #else
+-    #error "SK_*32_SHIFT values must correspond to GL_BGRA or GL_RGBA format."
++    static const GrPixelConfig kSkia8888_GrPixelConfig = kBGRA_8888_GrPixelConfig;
++    static const GrPixelConfig kSkiaGamma8888_GrPixelConfig = kSBGRA_8888_GrPixelConfig;
+ #endif
+ 
+ /**
+diff -up firefox-60.0/gfx/skia/skia/src/core/SkColorData.h.big-endian firefox-60.0/gfx/skia/skia/src/core/SkColorData.h
+--- firefox-60.0/gfx/skia/skia/src/core/SkColorData.h.big-endian	2018-04-18 13:42:06.980476156 +0200
++++ firefox-60.0/gfx/skia/skia/src/core/SkColorData.h	2018-04-18 13:42:50.493520552 +0200
+@@ -31,18 +31,19 @@
+  *
+  *  Here we enforce this constraint.
+  */
+-
++/*
+ #ifdef SK_CPU_BENDIAN
+     #define SK_BGRA_B32_SHIFT   24
+     #define SK_BGRA_G32_SHIFT   16
+     #define SK_BGRA_R32_SHIFT   8
+     #define SK_BGRA_A32_SHIFT   0
+ #else
++*/
+     #define SK_BGRA_B32_SHIFT   0
+     #define SK_BGRA_G32_SHIFT   8
+     #define SK_BGRA_R32_SHIFT   16
+     #define SK_BGRA_A32_SHIFT   24
+-#endif
++//#endif
+ 
+ #if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA)
+     #error "can't define PMCOLOR to be RGBA and BGRA"
diff --git a/SOURCES/build-debug-qcms.patch b/SOURCES/build-debug-qcms.patch
new file mode 100644
index 0000000..a65223a
--- /dev/null
+++ b/SOURCES/build-debug-qcms.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.0/gfx/qcms/transform-altivec.c.debug firefox-60.0/gfx/qcms/transform-altivec.c
+--- firefox-60.0/gfx/qcms/transform-altivec.c.debug	2018-05-15 09:26:43.603043100 +0200
++++ firefox-60.0/gfx/qcms/transform-altivec.c	2018-05-15 09:28:57.302385632 +0200
+@@ -30,7 +30,7 @@
+ static const ALIGN float floatScaleX4 = FLOATSCALE;
+ static const ALIGN float clampMaxValueX4 = CLAMPMAXVAL;
+ 
+-inline vector float load_aligned_float(float *dataPtr)
++static vector float load_aligned_float(float *dataPtr)
+ {
+ 	vector float data = vec_lde(0, dataPtr);
+ 	vector unsigned char moveToStart = vec_lvsl(0, dataPtr);
diff --git a/SOURCES/build-disable-elfhack.patch b/SOURCES/build-disable-elfhack.patch
new file mode 100644
index 0000000..1db9bdf
--- /dev/null
+++ b/SOURCES/build-disable-elfhack.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.4.0/toolkit/moz.configure.disable-elfhack firefox-60.4.0/toolkit/moz.configure
+--- firefox-60.4.0/toolkit/moz.configure.disable-elfhack	2019-01-03 14:47:00.566556623 +0100
++++ firefox-60.4.0/toolkit/moz.configure	2019-01-03 14:49:14.243887620 +0100
+@@ -1192,7 +1192,7 @@ with only_when(has_elfhack):
+     option('--disable-elf-hack', help='Disable elf hacks')
+ 
+     set_config('USE_ELF_HACK',
+-               depends_if('--enable-elf-hack')(lambda _: True))
++               depends_if('--enable-elf-hack')(lambda _: False))
+ 
+ 
+ @depends(check_build_environment)
diff --git a/SOURCES/build-gdk-version.patch b/SOURCES/build-gdk-version.patch
new file mode 100644
index 0000000..a25b255
--- /dev/null
+++ b/SOURCES/build-gdk-version.patch
@@ -0,0 +1,19 @@
+diff -up mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/old-configure.in.gdk-version mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/old-configure.in
+--- mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/old-configure.in.gdk-version	2018-03-10 03:54:17.000000000 +0100
++++ mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/old-configure.in	2018-03-28 13:11:06.294873487 +0200
+@@ -61,6 +61,7 @@ CAIRO_VERSION=1.10
+ GTK2_VERSION=2.18.0
+ GTK3_VERSION=3.4.0
+ GDK_VERSION_MAX_ALLOWED=GDK_VERSION_3_4
++GDK_VERSION_MIN_REQUIRED=GDK_VERSION_3_4
+ WINDRES_VERSION=2.14.90
+ W32API_VERSION=3.14
+ GCONF_VERSION=1.2.1
+@@ -2173,6 +2174,7 @@ if test "$COMPILE_ENVIRONMENT"; then
+     dnl GDK_VERSION_MIN_REQUIRED is not set here as GDK3 deprecated warnings
+     dnl are suppressed by widget/gtk/compat-gtk3/gdk/gdkversionmacros.h.
+     AC_DEFINE_UNQUOTED(GDK_VERSION_MAX_ALLOWED,$GDK_VERSION_MAX_ALLOWED)
++    AC_DEFINE_UNQUOTED(GDK_VERSION_MIN_REQUIRED,$GDK_VERSION_MIN_REQUIRED)
+     GLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_32
+   fi
+   if test "$MOZ_WIDGET_TOOLKIT" = gtk2; then
diff --git a/SOURCES/build-icu-big-endian.patch b/SOURCES/build-icu-big-endian.patch
new file mode 100644
index 0000000..c26a4d4
--- /dev/null
+++ b/SOURCES/build-icu-big-endian.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.0/build/autoconf/icu.m4.icu firefox-60.0/build/autoconf/icu.m4
+--- firefox-60.0/build/autoconf/icu.m4.icu	2018-04-17 15:11:54.100644119 +0200
++++ firefox-60.0/build/autoconf/icu.m4	2018-04-17 15:12:50.740686636 +0200
+@@ -78,7 +78,7 @@ if test -n "$USE_ICU"; then
+     # TODO: the l is actually endian-dependent
+     # We could make this set as 'l' or 'b' for little or big, respectively,
+     # but we'd need to check in a big-endian version of the file.
+-    ICU_DATA_FILE="icudt${version}l.dat"
++    ICU_DATA_FILE="icudt${version}b.dat"
+ 
+     MOZ_ICU_DATA_ARCHIVE=
+ fi
diff --git a/SOURCES/build-jit-atomic-always-lucky.patch b/SOURCES/build-jit-atomic-always-lucky.patch
new file mode 100644
index 0000000..ab99524
--- /dev/null
+++ b/SOURCES/build-jit-atomic-always-lucky.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.5.0/js/src/jit/AtomicOperations.h.jit-atomic-lucky firefox-60.5.0/js/src/jit/AtomicOperations.h
+--- firefox-60.5.0/js/src/jit/AtomicOperations.h.jit-atomic-lucky	2019-01-22 10:20:27.993697161 +0100
++++ firefox-60.5.0/js/src/jit/AtomicOperations.h	2019-01-22 10:23:15.337873762 +0100
+@@ -394,7 +394,7 @@ inline bool AtomicOperations::isLockfree
+ #elif defined(__s390__) || defined(__s390x__)
+ #include "jit/none/AtomicOperations-feeling-lucky.h"
+ #else
+-#error "No AtomicOperations support provided for this platform"
++#include "jit/none/AtomicOperations-feeling-lucky.h"
+ #endif
+ 
+ #endif  // jit_AtomicOperations_h
diff --git a/SOURCES/build-mozconfig-fix.patch b/SOURCES/build-mozconfig-fix.patch
new file mode 100644
index 0000000..91dffb1
--- /dev/null
+++ b/SOURCES/build-mozconfig-fix.patch
@@ -0,0 +1,12 @@
+diff -up mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/python/mozbuild/mozbuild/mozconfig.py.mozconfig-fix mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/python/mozbuild/mozbuild/mozconfig.py
+--- mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/python/mozbuild/mozbuild/mozconfig.py.mozconfig-fix	2018-03-13 17:22:19.018466884 +0100
++++ mozilla-release-c61f5f5ead48c78a80c80db5c489bdc7cfaf8175/python/mozbuild/mozbuild/mozconfig.py	2018-03-13 17:23:57.379559640 +0100
+@@ -446,7 +446,7 @@ class MozconfigLoader(object):
+                             value = value[1:]
+ 
+                         # Lines with a quote not ending in a quote are multi-line.
+-                        if has_quote and not value.endswith("'"):
++                        if has_quote and not value.endswith(("'", ";")):
+                             in_variable = name
+                             current.append(value)
+                             continue
diff --git a/SOURCES/build-nss-version.patch b/SOURCES/build-nss-version.patch
new file mode 100644
index 0000000..94947f2
--- /dev/null
+++ b/SOURCES/build-nss-version.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.1.0/old-configure.in.nss-version firefox-60.1.0/old-configure.in
+--- firefox-60.1.0/old-configure.in.nss-version	2018-06-20 14:24:55.204158540 +0200
++++ firefox-60.1.0/old-configure.in	2018-06-20 14:30:19.517004230 +0200
+@@ -1768,7 +1768,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
+     _USE_SYSTEM_NSS=1 )
+ 
+ if test -n "$_USE_SYSTEM_NSS"; then
+-    AM_PATH_NSS(3.36.7, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
++    AM_PATH_NSS(3.36.0, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
+ fi
+ 
+ if test -z "$MOZ_SYSTEM_NSS"; then
diff --git a/SOURCES/distribution.ini b/SOURCES/distribution.ini
new file mode 100644
index 0000000..8bf461e
--- /dev/null
+++ b/SOURCES/distribution.ini
@@ -0,0 +1,9 @@
+[Global]
+id=redhat
+version=1.0
+about=Mozilla Firefox for Red Hat Enterprise Linux
+
+[Preferences]
+app.distributor=redhat
+app.distributor.channel=redhat
+app.partner.fedora=redhat
diff --git a/SOURCES/firefox-enable-addons.patch b/SOURCES/firefox-enable-addons.patch
new file mode 100644
index 0000000..15d0707
--- /dev/null
+++ b/SOURCES/firefox-enable-addons.patch
@@ -0,0 +1,13 @@
+diff -up firefox-55.0/browser/app/profile/firefox.js.addons firefox-55.0/browser/app/profile/firefox.js
+--- firefox-55.0/browser/app/profile/firefox.js.addons	2017-08-02 10:58:30.566363833 +0200
++++ firefox-55.0/browser/app/profile/firefox.js	2017-08-02 10:59:15.377216959 +0200
+@@ -65,7 +65,8 @@ pref("extensions.systemAddon.update.url"
+ 
+ // Disable add-ons that are not installed by the user in all scopes by default.
+ // See the SCOPE constants in AddonManager.jsm for values to use here.
+-pref("extensions.autoDisableScopes", 15);
++pref("extensions.autoDisableScopes", 0);
++pref("extensions.showMismatchUI", false);
+ // Scopes to scan for changes at startup.
+ pref("extensions.startupScanScopes", 0);
+ 
diff --git a/SOURCES/firefox-mozconfig b/SOURCES/firefox-mozconfig
new file mode 100644
index 0000000..7501abc
--- /dev/null
+++ b/SOURCES/firefox-mozconfig
@@ -0,0 +1,29 @@
+. $topsrcdir/browser/config/mozconfig
+
+ac_add_options --enable-default-toolkit=cairo-gtk3
+
+ac_add_options --prefix="$PREFIX"
+ac_add_options --libdir="$LIBDIR"
+ac_add_options --with-system-zlib
+ac_add_options --with-system-bz2
+ac_add_options --with-pthreads
+ac_add_options --disable-strip
+ac_add_options --disable-tests
+#ac_add_options --enable-libnotify
+ac_add_options --enable-necko-wifi
+ac_add_options --enable-startup-notification
+ac_add_options --disable-updater
+ac_add_options --enable-chrome-format=omni
+ac_add_options --enable-pulseaudio
+ac_add_options --with-system-icu
+ac_add_options --with-mozilla-api-keyfile=../mozilla-api-key
+ac_add_options --with-google-api-keyfile=../google-api-key
+ac_add_options --enable-release
+ac_add_options --enable-pie
+
+export BUILD_OFFICIAL=1
+export MOZILLA_OFFICIAL=1
+export MOZ_TELEMETRY_REPORTING=1
+mk_add_options BUILD_OFFICIAL=1
+mk_add_options MOZILLA_OFFICIAL=1
+mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/objdir
diff --git a/SOURCES/firefox-pipewire.patch b/SOURCES/firefox-pipewire.patch
new file mode 100644
index 0000000..57bf8b4
--- /dev/null
+++ b/SOURCES/firefox-pipewire.patch
@@ -0,0 +1,2572 @@
+diff -up firefox-60.3.0/config/system-headers.mozbuild.pipewire firefox-60.3.0/config/system-headers.mozbuild
+--- firefox-60.3.0/config/system-headers.mozbuild.pipewire	2018-10-17 22:39:27.000000000 +0200
++++ firefox-60.3.0/config/system-headers.mozbuild	2019-01-07 14:53:17.200061752 +0100
+@@ -314,6 +314,7 @@ system_headers = [
+     'Gestalt.h',
+     'getopt.h',
+     'gio/gio.h',
++    'gio/gunixfdlist.h',
+     'glibconfig.h',
+     'glib.h',
+     'glib-object.h',
+@@ -607,6 +608,7 @@ system_headers = [
+     'Pgenerr.h',
+     'PGenErr.h',
+     'Ph.h',
++    'pipewire/pipewire.h',
+     'pixman.h',
+     'pk11func.h',
+     'pk11pqg.h',
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc.pipewire	2019-01-07 14:53:17.200061752 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc	2019-01-07 14:53:17.200061752 +0100
+@@ -0,0 +1,39 @@
++/*
++ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++
++#if defined(USE_X11)
++#include "webrtc/modules/desktop_capture/app_capturer_x11.h"
++#endif // defined(USE_X11)
++
++namespace webrtc {
++
++// static
++AppCapturer* AppCapturer::Create(const DesktopCaptureOptions& options) {
++#if defined(USE_X11)
++    return AppCapturerX11::Create(options);
++#endif // defined(USE_X11)
++
++  return nullptr;
++}
++
++// static
++std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawAppCapturer(
++    const DesktopCaptureOptions& options) {
++#if defined(USE_X11)
++  return AppCapturerX11::CreateRawAppCapturer(options);
++#endif // defined(USE_X11)
++
++  return nullptr;
++}
++
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc	2019-01-07 14:53:17.201061764 +0100
+@@ -7,9 +7,6 @@
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+-#include "webrtc/modules/desktop_capture/app_capturer.h"
+-#include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
+-#include "webrtc/modules/desktop_capture/x11/shared_x_util.h"
+ 
+ #include <assert.h>
+ #include <string.h>
+@@ -21,80 +18,19 @@
+ 
+ #include <algorithm>
+ 
++#include "webrtc/modules/desktop_capture/app_capturer_x11.h"
++
+ #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
+ #include "webrtc/modules/desktop_capture/desktop_frame.h"
+ #include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
++#include "webrtc/modules/desktop_capture/x11/shared_x_util.h"
+ #include "webrtc/modules/desktop_capture/x11/x_error_trap.h"
+ #include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
+ #include "webrtc/system_wrappers/include/logging.h"
+ 
+ namespace webrtc {
+ 
+-namespace {
+-
+-class ScreenCapturerProxy : DesktopCapturer::Callback {
+-public:
+-  ScreenCapturerProxy()
+-    : screen_capturer_(DesktopCapturer::CreateScreenCapturer(DesktopCaptureOptions::CreateDefault())) {
+-    screen_capturer_->SelectSource(kFullDesktopScreenId);
+-    screen_capturer_->Start(this);
+-  }
+-  void CaptureFrame() { screen_capturer_->CaptureFrame(); }
+-  std::unique_ptr<DesktopFrame> GetFrame() { return std::move(frame_); }
+-
+-   // Callback interface
+-  virtual void OnCaptureResult(DesktopCapturer::Result result,
+-                               std::unique_ptr<DesktopFrame> frame) {
+-    frame_ = std::move(frame);
+-  }
+-
+-protected:
+-  std::unique_ptr<DesktopCapturer> screen_capturer_;
+-  std::unique_ptr<DesktopFrame> frame_;
+-};
+-
+-class AppCapturerLinux : public AppCapturer {
+-public:
+-  AppCapturerLinux(const DesktopCaptureOptions& options);
+-  virtual ~AppCapturerLinux();
+-
+-  // AppCapturer interface.
+-  virtual bool GetAppList(AppList* apps) override;
+-  virtual bool SelectApp(ProcessId processId) override;
+-  virtual bool BringAppToFront() override;
+-
+-  // DesktopCapturer interface.
+-  virtual void Start(Callback* callback) override;
+-  virtual void Stop() override;
+-  virtual void CaptureFrame() override;
+-  virtual bool SelectSource(SourceId id) override
+-  {
+-    return SelectApp(static_cast<ProcessId>(id));
+-  }
+-
+-protected:
+-  Display* GetDisplay() { return x_display_->display(); }
+-  bool UpdateRegions();
+-
+-  void FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame,Region rgn, uint32_t color);
+-private:
+-  Callback* callback_;
+-  ProcessId selected_process_;
+-
+-  // Sample Mode
+-  ScreenCapturerProxy screen_capturer_proxy_;
+-  // Mask of foreground (non-app windows in front of selected)
+-  Region rgn_mask_;
+-  // Region of selected windows
+-  Region rgn_visual_;
+-  // Mask of background (desktop, non-app windows behind selected)
+-  Region rgn_background_;
+-
+-  rtc::scoped_refptr<SharedXDisplay> x_display_;
+-  RTC_DISALLOW_COPY_AND_ASSIGN(AppCapturerLinux);
+-};
+-
+-AppCapturerLinux::AppCapturerLinux(const DesktopCaptureOptions& options)
++AppCapturerX11::AppCapturerX11(const DesktopCaptureOptions& options)
+     : callback_(NULL),
+       selected_process_(0),
+       x_display_(options.x_display()) {
+@@ -103,7 +39,7 @@ AppCapturerLinux::AppCapturerLinux(const
+   rgn_background_ = XCreateRegion();
+ }
+ 
+-AppCapturerLinux::~AppCapturerLinux() {
++AppCapturerX11::~AppCapturerX11() {
+   if (rgn_mask_) {
+     XDestroyRegion(rgn_mask_);
+   }
+@@ -116,32 +52,32 @@ AppCapturerLinux::~AppCapturerLinux() {
+ }
+ 
+ // AppCapturer interface.
+-bool AppCapturerLinux::GetAppList(AppList* apps) {
++bool AppCapturerX11::GetAppList(AppList* apps) {
+   // Implemented in DesktopDeviceInfo
+   return true;
+ }
+-bool AppCapturerLinux::SelectApp(ProcessId processId) {
++bool AppCapturerX11::SelectApp(ProcessId processId) {
+   selected_process_ = processId;
+   return true;
+ }
+-bool AppCapturerLinux::BringAppToFront() {
++bool AppCapturerX11::BringAppToFront() {
+   // Not implemented yet: See Bug 1036653
+   return true;
+ }
+ 
+ // DesktopCapturer interface.
+-void AppCapturerLinux::Start(Callback* callback) {
++void AppCapturerX11::Start(Callback* callback) {
+   assert(!callback_);
+   assert(callback);
+ 
+   callback_ = callback;
+ }
+ 
+-void AppCapturerLinux::Stop() {
++void AppCapturerX11::Stop() {
+   callback_ = NULL;
+ }
+ 
+-void AppCapturerLinux::CaptureFrame() {
++void AppCapturerX11::CaptureFrame() {
+   XErrorTrap error_trap(GetDisplay());
+ 
+   //Capture screen >> set root window as capture window
+@@ -169,7 +105,7 @@ void AppCapturerLinux::CaptureFrame() {
+   }
+ }
+ 
+-void AppCapturerLinux::FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame, Region rgn, uint32_t color) {
++void AppCapturerX11::FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame, Region rgn, uint32_t color) {
+   XErrorTrap error_trap(GetDisplay());
+ 
+   if (!pDesktopFrame) {
+@@ -192,7 +128,7 @@ void AppCapturerLinux::FillDesktopFrameR
+   }
+ }
+ 
+-bool AppCapturerLinux::UpdateRegions() {
++bool AppCapturerX11::UpdateRegions() {
+   XErrorTrap error_trap(GetDisplay());
+ 
+   XSubtractRegion(rgn_visual_, rgn_visual_, rgn_visual_);
+@@ -269,21 +205,19 @@ bool AppCapturerLinux::UpdateRegions() {
+   return true;
+ }
+ 
+-}  // namespace
+-
+ // static
+-AppCapturer* AppCapturer::Create(const DesktopCaptureOptions& options) {
+-  return new AppCapturerLinux(options);
++AppCapturer* AppCapturerX11::Create(const DesktopCaptureOptions& options) {
++  return new AppCapturerX11(options);
+ }
+ 
+ // static
+-std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawAppCapturer(
++std::unique_ptr<DesktopCapturer> AppCapturerX11::CreateRawAppCapturer(
+     const DesktopCaptureOptions& options) {
+ 
+   if (!options.x_display())
+     return nullptr;
+ 
+-  std::unique_ptr<AppCapturerLinux> capturer(new AppCapturerLinux(options));
++  std::unique_ptr<AppCapturerX11> capturer(new AppCapturerX11(options));
+ 
+   return std::unique_ptr<DesktopCapturer>(std::move(capturer));
+ }
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.h.pipewire	2019-01-07 14:53:17.201061764 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.h	2019-01-07 14:53:17.201061764 +0100
+@@ -0,0 +1,98 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_APP_CAPTURER_X11_H_
++#define MODULES_DESKTOP_CAPTURE_APP_CAPTURER_X11_H_
++
++#include <X11/X.h>
++#include <X11/Xlib.h>
++#include <memory>
++#include <string>
++
++#include "webrtc/modules/desktop_capture/app_capturer.h"
++#include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++#include "webrtc/modules/desktop_capture/desktop_geometry.h"
++#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
++#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
++#include "webrtc/base/constructormagic.h"
++#include "webrtc/base/scoped_ref_ptr.h"
++
++namespace webrtc {
++
++class ScreenCapturerProxy : DesktopCapturer::Callback {
++public:
++  ScreenCapturerProxy()
++    : screen_capturer_(DesktopCapturer::CreateScreenCapturer(DesktopCaptureOptions::CreateDefault())) {
++    screen_capturer_->SelectSource(kFullDesktopScreenId);
++    screen_capturer_->Start(this);
++  }
++  void CaptureFrame() { screen_capturer_->CaptureFrame(); }
++  std::unique_ptr<DesktopFrame> GetFrame() { return std::move(frame_); }
++
++   // Callback interface
++  virtual void OnCaptureResult(DesktopCapturer::Result result,
++                               std::unique_ptr<DesktopFrame> frame) {
++    frame_ = std::move(frame);
++  }
++
++protected:
++  std::unique_ptr<DesktopCapturer> screen_capturer_;
++  std::unique_ptr<DesktopFrame> frame_;
++};
++
++class AppCapturerX11 : public AppCapturer {
++public:
++  AppCapturerX11(const DesktopCaptureOptions& options);
++  virtual ~AppCapturerX11();
++
++  static AppCapturer* Create(const DesktopCaptureOptions& options);
++  static std::unique_ptr<DesktopCapturer> CreateRawAppCapturer(const DesktopCaptureOptions& options);
++
++  // AppCapturer interface.
++  virtual bool GetAppList(AppList* apps) override;
++  virtual bool SelectApp(ProcessId processId) override;
++  virtual bool BringAppToFront() override;
++
++  // DesktopCapturer interface.
++  virtual void Start(Callback* callback) override;
++  virtual void Stop() override;
++  virtual void CaptureFrame() override;
++  virtual bool SelectSource(SourceId id) override
++  {
++    return SelectApp(static_cast<ProcessId>(id));
++  }
++
++protected:
++  Display* GetDisplay() { return x_display_->display(); }
++  bool UpdateRegions();
++
++  void FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame,Region rgn, uint32_t color);
++private:
++  Callback* callback_;
++  ProcessId selected_process_;
++
++  // Sample Mode
++  ScreenCapturerProxy screen_capturer_proxy_;
++  // Mask of foreground (non-app windows in front of selected)
++  Region rgn_mask_;
++  // Region of selected windows
++  Region rgn_visual_;
++  // Mask of background (desktop, non-app windows behind selected)
++  Region rgn_background_;
++
++  rtc::scoped_refptr<SharedXDisplay> x_display_;
++  RTC_DISALLOW_COPY_AND_ASSIGN(AppCapturerX11);
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_APP_CAPTURER_X11_H_
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc.pipewire	2019-01-07 14:53:17.201061764 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc	2019-01-07 14:53:17.201061764 +0100
+@@ -0,0 +1,849 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include <cstring>
++#include <gio/gunixfdlist.h>
++#include <glib-object.h>
++
++#include <spa/param/format-utils.h>
++#include <spa/param/props.h>
++#include <spa/param/video/raw-utils.h>
++#include <spa/support/type-map.h>
++
++#include "webrtc/modules/desktop_capture/base_capturer_pipewire.h"
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++#include "webrtc/base/checks.h"
++#include "webrtc/base/logging.h"
++
++namespace webrtc {
++
++const char kDesktopBusName[] = "org.freedesktop.portal.Desktop";
++const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop";
++const char kDesktopRequestObjectPath[] =
++    "/org/freedesktop/portal/desktop/request";
++const char kSessionInterfaceName[] = "org.freedesktop.portal.Session";
++const char kRequestInterfaceName[] = "org.freedesktop.portal.Request";
++const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast";
++
++const int kBytesPerPixelPw = 4;
++
++// static
++void BaseCapturerPipeWire::OnStateChanged(void* data,
++                                            pw_remote_state old_state,
++                                            pw_remote_state state,
++                                            const char* error_message) {
++  BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
++  RTC_DCHECK(that);
++
++  switch (state) {
++    case PW_REMOTE_STATE_ERROR:
++      LOG(LS_ERROR) << "PipeWire remote state error: " << error_message;
++      break;
++    case PW_REMOTE_STATE_CONNECTED:
++      LOG(LS_INFO) << "PipeWire remote state: connected.";
++      that->CreateReceivingStream();
++      break;
++    case PW_REMOTE_STATE_CONNECTING:
++      LOG(LS_INFO) << "PipeWire remote state: connecting.";
++      break;
++    case PW_REMOTE_STATE_UNCONNECTED:
++      LOG(LS_INFO) << "PipeWire remote state: unconnected.";
++      break;
++  }
++}
++
++// static
++void BaseCapturerPipeWire::OnStreamStateChanged(void* data,
++                                                  pw_stream_state old_state,
++                                                  pw_stream_state state,
++                                                  const char* error_message) {
++  BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
++  RTC_DCHECK(that);
++
++  switch (state) {
++    case PW_STREAM_STATE_ERROR:
++      LOG(LS_ERROR) << "PipeWire stream state error: " << error_message;
++      break;
++    case PW_STREAM_STATE_CONFIGURE:
++      pw_stream_set_active(that->pw_stream_, true);
++      break;
++    case PW_STREAM_STATE_UNCONNECTED:
++    case PW_STREAM_STATE_CONNECTING:
++    case PW_STREAM_STATE_READY:
++    case PW_STREAM_STATE_PAUSED:
++    case PW_STREAM_STATE_STREAMING:
++      break;
++  }
++}
++
++// static
++void BaseCapturerPipeWire::OnStreamFormatChanged(
++    void* data,
++    const struct spa_pod* format) {
++  BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
++  RTC_DCHECK(that);
++
++  LOG(LS_INFO) << "PipeWire stream format changed.";
++
++  if (!format) {
++    pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr,
++                            /*n_params=*/0);
++    return;
++  }
++
++  that->spa_video_format_ = new spa_video_info_raw();
++  spa_format_video_raw_parse(format, that->spa_video_format_,
++                             &that->pw_type_->format_video);
++
++  auto width = that->spa_video_format_->size.width;
++  auto height = that->spa_video_format_->size.height;
++  auto stride = SPA_ROUND_UP_N(width * kBytesPerPixelPw, 4);
++  auto size = height * stride;
++
++  uint8_t buffer[1024] = {};
++  auto builder = spa_pod_builder{buffer, sizeof(buffer)};
++
++  // Setup buffers and meta header for new format.
++  const struct spa_pod* params[2];
++  params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object(
++      &builder,
++      // id to enumerate buffer requirements
++      that->pw_core_type_->param.idBuffers,
++      that->pw_core_type_->param_buffers.Buffers,
++      // Size: specified as integer (i) and set to specified size
++      ":", that->pw_core_type_->param_buffers.size, "i", size,
++      // Stride: specified as integer (i) and set to specified stride
++      ":", that->pw_core_type_->param_buffers.stride, "i", stride,
++      // Buffers: specifies how many buffers we want to deal with, set as
++      // integer (i) where preferred number is 8, then allowed number is defined
++      // as range (r) from min and max values and it is undecided (u) to allow
++      // negotiation
++      ":", that->pw_core_type_->param_buffers.buffers, "iru", 8,
++      SPA_POD_PROP_MIN_MAX(1, 32),
++      // Align: memory alignment of the buffer, set as integer (i) to specified
++      // value
++      ":", that->pw_core_type_->param_buffers.align, "i", 16));
++  params[1] = reinterpret_cast<spa_pod*>(spa_pod_builder_object(
++      &builder,
++      // id to enumerate supported metadata
++      that->pw_core_type_->param.idMeta, that->pw_core_type_->param_meta.Meta,
++      // Type: specified as id or enum (I)
++      ":", that->pw_core_type_->param_meta.type, "I",
++      that->pw_core_type_->meta.Header,
++      // Size: size of the metadata, specified as integer (i)
++      ":", that->pw_core_type_->param_meta.size, "i",
++      sizeof(struct spa_meta_header)));
++
++  pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/2);
++}
++
++// static
++void BaseCapturerPipeWire::OnStreamProcess(void* data) {
++  BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
++  RTC_DCHECK(that);
++
++  pw_buffer* buf = nullptr;
++
++  if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) {
++    return;
++  }
++
++  that->HandleBuffer(buf);
++
++  pw_stream_queue_buffer(that->pw_stream_, buf);
++}
++
++BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type)
++    : capture_source_type_(source_type) {}
++
++BaseCapturerPipeWire::~BaseCapturerPipeWire() {
++  if (pw_main_loop_) {
++    pw_thread_loop_stop(pw_main_loop_);
++  }
++
++  if (pw_type_) {
++    delete pw_type_;
++  }
++
++  if (spa_video_format_) {
++    delete spa_video_format_;
++  }
++
++  if (pw_stream_) {
++    pw_stream_destroy(pw_stream_);
++  }
++
++  if (pw_remote_) {
++    pw_remote_destroy(pw_remote_);
++  }
++
++  if (pw_core_) {
++    pw_core_destroy(pw_core_);
++  }
++
++  if (pw_main_loop_) {
++    pw_thread_loop_destroy(pw_main_loop_);
++  }
++
++  if (pw_loop_) {
++    pw_loop_destroy(pw_loop_);
++  }
++
++  if (current_frame_) {
++    free(current_frame_);
++  }
++
++  if (start_request_signal_id_) {
++    g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_);
++  }
++  if (sources_request_signal_id_) {
++    g_dbus_connection_signal_unsubscribe(connection_,
++                                         sources_request_signal_id_);
++  }
++  if (session_request_signal_id_) {
++    g_dbus_connection_signal_unsubscribe(connection_,
++                                         session_request_signal_id_);
++  }
++
++  if (session_handle_) {
++    GDBusMessage* message = g_dbus_message_new_method_call(
++        kDesktopBusName, session_handle_, kSessionInterfaceName, "Close");
++    if (message) {
++      GError* error = nullptr;
++      g_dbus_connection_send_message(connection_, message,
++                                     G_DBUS_SEND_MESSAGE_FLAGS_NONE,
++                                     /*out_serial=*/nullptr, &error);
++      if (error) {
++        LOG(LS_ERROR) << "Failed to close the session: " << error->message;
++        g_error_free(error);
++      }
++      g_object_unref(message);
++    }
++  }
++
++  g_free(start_handle_);
++  g_free(sources_handle_);
++  g_free(session_handle_);
++  g_free(portal_handle_);
++
++  if (proxy_) {
++    g_clear_object(&proxy_);
++  }
++}
++
++void BaseCapturerPipeWire::InitPortals() {
++  g_dbus_proxy_new_for_bus(
++      G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, /*info=*/nullptr,
++      kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName,
++      /*cancellable=*/nullptr,
++      reinterpret_cast<GAsyncReadyCallback>(OnProxyRequested), this);
++}
++
++void BaseCapturerPipeWire::InitPipeWire() {
++  pw_init(/*argc=*/nullptr, /*argc=*/nullptr);
++
++  pw_loop_ = pw_loop_new(/*properties=*/nullptr);
++  pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop");
++
++  pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr);
++  pw_core_type_ = pw_core_get_type(pw_core_);
++  pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0);
++
++  InitPipeWireTypes();
++
++  // Initialize event handlers, remote end and stream-related.
++  pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS;
++  pw_remote_events_.state_changed = &OnStateChanged;
++
++  pw_stream_events_.version = PW_VERSION_STREAM_EVENTS;
++  pw_stream_events_.state_changed = &OnStreamStateChanged;
++  pw_stream_events_.format_changed = &OnStreamFormatChanged;
++  pw_stream_events_.process = &OnStreamProcess;
++
++  pw_remote_add_listener(pw_remote_, &spa_remote_listener_, &pw_remote_events_,
++                         this);
++  pw_remote_connect_fd(pw_remote_, pw_fd_);
++
++  if (pw_thread_loop_start(pw_main_loop_) < 0) {
++    LOG(LS_ERROR) << "Failed to start main PipeWire loop";
++    portal_init_failed_ = true;
++  }
++}
++
++void BaseCapturerPipeWire::InitPipeWireTypes() {
++  spa_type_map* map = pw_core_type_->map;
++  pw_type_ = new PipeWireType();
++
++  spa_type_media_type_map(map, &pw_type_->media_type);
++  spa_type_media_subtype_map(map, &pw_type_->media_subtype);
++  spa_type_format_video_map(map, &pw_type_->format_video);
++  spa_type_video_format_map(map, &pw_type_->video_format);
++}
++
++void BaseCapturerPipeWire::CreateReceivingStream() {
++  spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1};
++  spa_rectangle pwScreenBounds =
++      spa_rectangle{static_cast<uint32_t>(desktop_size_.width()),
++                    static_cast<uint32_t>(desktop_size_.height())};
++
++  spa_fraction pwFrameRateMin = spa_fraction{0, 1};
++  spa_fraction pwFrameRateMax = spa_fraction{60, 1};
++
++  pw_properties* reuseProps = pw_properties_new("pipewire.client.reuse", "1",
++                                                /*end of varargs*/ nullptr);
++  pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps);
++
++  uint8_t buffer[1024] = {};
++  const spa_pod* params[1];
++  spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)};
++  params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object(
++      &builder,
++      // id to enumerate formats
++      pw_core_type_->param.idEnumFormat, pw_core_type_->spa_format, "I",
++      pw_type_->media_type.video, "I", pw_type_->media_subtype.raw,
++      // Video format: specified as id or enum (I), preferred format is BGRx,
++      // then allowed formats are enumerated (e) and the format is undecided (u)
++      // to allow negotiation
++      ":", pw_type_->format_video.format, "Ieu", pw_type_->video_format.BGRx,
++      SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx,
++                        pw_type_->video_format.BGRx),
++      // Video size: specified as rectangle (R), preferred size is specified as
++      // first parameter, then allowed size is defined as range (r) from min and
++      // max values and the format is undecided (u) to allow negotiation
++      ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2,
++      &pwMinScreenBounds, &pwScreenBounds,
++      // Frame rate: specified as fraction (F) and set to minimum frame rate
++      // value
++      ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin,
++      // Max frame rate: specified as fraction (F), preferred frame rate is set
++      // to maximum value, then allowed frame rate is defined as range (r) from
++      // min and max values and it is undecided (u) to allow negotiation
++      ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2,
++      &pwFrameRateMin, &pwFrameRateMax));
++
++  pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_,
++                         this);
++  pw_stream_flags flags = static_cast<pw_stream_flags>(
++      PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE |
++      PW_STREAM_FLAG_MAP_BUFFERS);
++  if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, /*port_path=*/nullptr,
++                        flags, params,
++                        /*n_params=*/1) != 0) {
++    LOG(LS_ERROR) << "Could not connect receiving stream.";
++    portal_init_failed_ = true;
++    return;
++  }
++}
++
++void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) {
++  spa_buffer* spaBuffer = buffer->buffer;
++  void* src = nullptr;
++
++  if (!(src = spaBuffer->datas[0].data)) {
++    return;
++  }
++
++  uint32_t maxSize = spaBuffer->datas[0].maxsize;
++  int32_t srcStride = spaBuffer->datas[0].chunk->stride;
++  if (srcStride != (desktop_size_.width() * kBytesPerPixelPw)) {
++    LOG(LS_ERROR) << "Got buffer with stride different from screen stride: "
++                      << srcStride
++                      << " != " << (desktop_size_.width() * kBytesPerPixelPw);
++    portal_init_failed_ = true;
++    return;
++  }
++
++  if (!current_frame_) {
++    current_frame_ = static_cast<uint8_t*>(malloc(maxSize));
++  }
++  RTC_DCHECK(current_frame_ != nullptr);
++
++  // If both sides decided to go with the RGBx format we need to convert it to
++  // BGRx to match color format expected by WebRTC.
++  if (spa_video_format_->format == pw_type_->video_format.RGBx) {
++    uint8_t* tempFrame = static_cast<uint8_t*>(malloc(maxSize));
++    std::memcpy(tempFrame, src, maxSize);
++    ConvertRGBxToBGRx(tempFrame, maxSize);
++    std::memcpy(current_frame_, tempFrame, maxSize);
++    free(tempFrame);
++  } else {
++    std::memcpy(current_frame_, src, maxSize);
++  }
++}
++
++void BaseCapturerPipeWire::ConvertRGBxToBGRx(uint8_t* frame, uint32_t size) {
++  // Change color format for KDE KWin which uses RGBx and not BGRx
++  for (uint32_t i = 0; i < size; i += 4) {
++    uint8_t tempR = frame[i];
++    uint8_t tempB = frame[i + 2];
++    frame[i] = tempB;
++    frame[i + 2] = tempR;
++  }
++}
++
++guint BaseCapturerPipeWire::SetupRequestResponseSignal(
++    const gchar* object_path,
++    GDBusSignalCallback callback) {
++  return g_dbus_connection_signal_subscribe(
++      connection_, kDesktopBusName, kRequestInterfaceName, "Response",
++      object_path, /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
++      callback, this, /*user_data_free_func=*/nullptr);
++}
++
++// static
++void BaseCapturerPipeWire::OnProxyRequested(GObject* /*object*/,
++                                              GAsyncResult* result,
++                                              gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  GError* error = nullptr;
++  that->proxy_ = g_dbus_proxy_new_finish(result, &error);
++  if (!that->proxy_) {
++    LOG(LS_ERROR) << "Failed to create a proxy for the screen cast portal: "
++                      << error->message;
++    g_error_free(error);
++    that->portal_init_failed_ = true;
++    return;
++  }
++  that->connection_ = g_dbus_proxy_get_connection(that->proxy_);
++
++  LOG(LS_INFO) << "Created proxy for the screen cast portal.";
++  that->SessionRequest();
++}
++
++// static
++gchar* BaseCapturerPipeWire::PrepareSignalHandle(GDBusConnection* connection,
++                                                   const gchar* token) {
++  gchar* sender = g_strdup(g_dbus_connection_get_unique_name(connection) + 1);
++  for (int i = 0; sender[i]; i++) {
++    if (sender[i] == '.') {
++      sender[i] = '_';
++    }
++  }
++
++  gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender, "/",
++                              token, /*end of varargs*/ nullptr);
++  g_free(sender);
++
++  return handle;
++}
++
++void BaseCapturerPipeWire::SessionRequest() {
++  GVariantBuilder builder;
++  gchar* variant_string;
++
++  g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
++  variant_string =
++      g_strdup_printf("webrtc_session%d", g_random_int_range(0, G_MAXINT));
++  g_variant_builder_add(&builder, "{sv}", "session_handle_token",
++                        g_variant_new_string(variant_string));
++  g_free(variant_string);
++  variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT));
++  g_variant_builder_add(&builder, "{sv}", "handle_token",
++                        g_variant_new_string(variant_string));
++
++  portal_handle_ = PrepareSignalHandle(connection_, variant_string);
++  session_request_signal_id_ = SetupRequestResponseSignal(
++      portal_handle_, OnSessionRequestResponseSignal);
++  g_free(variant_string);
++
++  LOG(LS_INFO) << "Screen cast session requested.";
++  g_dbus_proxy_call(
++      proxy_, "CreateSession", g_variant_new("(a{sv})", &builder),
++      G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*cancellable=*/nullptr,
++      reinterpret_cast<GAsyncReadyCallback>(OnSessionRequested), this);
++}
++
++// static
++void BaseCapturerPipeWire::OnSessionRequested(GDBusConnection* connection,
++                                                GAsyncResult* result,
++                                                gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  GError* error = nullptr;
++  GVariant* variant = g_dbus_proxy_call_finish(that->proxy_, result, &error);
++  if (!variant) {
++    LOG(LS_ERROR) << "Failed to create a screen cast session: "
++                      << error->message;
++    g_error_free(error);
++    that->portal_init_failed_ = true;
++    return;
++  }
++  LOG(LS_INFO) << "Initializing the screen cast session.";
++
++  gchar* handle = nullptr;
++  g_variant_get_child(variant, 0, "o", &handle);
++  g_variant_unref(variant);
++  if (!handle) {
++    LOG(LS_ERROR) << "Failed to initialize the screen cast session.";
++    if (that->session_request_signal_id_) {
++      g_dbus_connection_signal_unsubscribe(connection,
++                                           that->session_request_signal_id_);
++      that->session_request_signal_id_ = 0;
++    }
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  g_free(handle);
++
++  LOG(LS_INFO) << "Subscribing to the screen cast session.";
++}
++
++// static
++void BaseCapturerPipeWire::OnSessionRequestResponseSignal(
++    GDBusConnection* connection,
++    const gchar* sender_name,
++    const gchar* object_path,
++    const gchar* interface_name,
++    const gchar* signal_name,
++    GVariant* parameters,
++    gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++
++  LOG(LS_INFO)
++      << "Received response for the screen cast session subscription.";
++
++  guint32 portal_response;
++  GVariant* response_data;
++  g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data);
++  g_variant_lookup(response_data, "session_handle", "s",
++                   &that->session_handle_);
++  g_variant_unref(response_data);
++
++  if (!that->session_handle_ || portal_response) {
++    LOG(LS_ERROR)
++        << "Failed to request the screen cast session subscription.";
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  that->SourcesRequest();
++}
++
++void BaseCapturerPipeWire::SourcesRequest() {
++  GVariantBuilder builder;
++  gchar* variant_string;
++
++  g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
++  // We want to record monitor content.
++  g_variant_builder_add(&builder, "{sv}", "types",
++                        g_variant_new_uint32(capture_source_type_));
++  // We don't want to allow selection of multiple sources.
++  g_variant_builder_add(&builder, "{sv}", "multiple",
++                        g_variant_new_boolean(false));
++  variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT));
++  g_variant_builder_add(&builder, "{sv}", "handle_token",
++                        g_variant_new_string(variant_string));
++
++  sources_handle_ = PrepareSignalHandle(connection_, variant_string);
++  sources_request_signal_id_ = SetupRequestResponseSignal(
++      sources_handle_, OnSourcesRequestResponseSignal);
++  g_free(variant_string);
++
++  LOG(LS_INFO) << "Requesting sources from the screen cast session.";
++  g_dbus_proxy_call(
++      proxy_, "SelectSources",
++      g_variant_new("(oa{sv})", session_handle_, &builder),
++      G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*cancellable=*/nullptr,
++      reinterpret_cast<GAsyncReadyCallback>(OnSourcesRequested), this);
++}
++
++// static
++void BaseCapturerPipeWire::OnSourcesRequested(GDBusConnection* connection,
++                                                GAsyncResult* result,
++                                                gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  GError* error = nullptr;
++  GVariant* variant = g_dbus_proxy_call_finish(that->proxy_, result, &error);
++  if (!variant) {
++    LOG(LS_ERROR) << "Failed to request the sources: " << error->message;
++    g_error_free(error);
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  LOG(LS_INFO) << "Sources requested from the screen cast session.";
++
++  gchar* handle = nullptr;
++  g_variant_get_child(variant, 0, "o", &handle);
++  g_variant_unref(variant);
++  if (!handle) {
++    LOG(LS_ERROR) << "Failed to initialize the screen cast session.";
++    if (that->sources_request_signal_id_) {
++      g_dbus_connection_signal_unsubscribe(connection,
++                                           that->sources_request_signal_id_);
++      that->sources_request_signal_id_ = 0;
++    }
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  g_free(handle);
++
++  LOG(LS_INFO) << "Subscribed to sources signal.";
++}
++
++// static
++void BaseCapturerPipeWire::OnSourcesRequestResponseSignal(
++    GDBusConnection* connection,
++    const gchar* sender_name,
++    const gchar* object_path,
++    const gchar* interface_name,
++    const gchar* signal_name,
++    GVariant* parameters,
++    gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  guint32 portal_response;
++  g_variant_get(parameters, "(u@a{sv})", &portal_response, nullptr);
++  if (portal_response) {
++    LOG(LS_ERROR)
++        << "Failed to select sources for the screen cast session.";
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  LOG(LS_INFO) << "Received sources signal from session.";
++  that->StartRequest();
++}
++
++void BaseCapturerPipeWire::StartRequest() {
++  GVariantBuilder builder;
++  gchar* variant_string;
++
++  g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
++  variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT));
++  g_variant_builder_add(&builder, "{sv}", "handle_token",
++                        g_variant_new_string(variant_string));
++
++  start_handle_ = PrepareSignalHandle(connection_, variant_string);
++  start_request_signal_id_ =
++      SetupRequestResponseSignal(start_handle_, OnStartRequestResponseSignal);
++  g_free(variant_string);
++
++  // "Identifier for the application window", this is Wayland, so not "x11:...".
++  const gchar parent_window[] = "";
++
++  LOG(LS_INFO) << "Starting the screen cast session.";
++  g_dbus_proxy_call(
++      proxy_, "Start",
++      g_variant_new("(osa{sv})", session_handle_, parent_window, &builder),
++      G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*cancellable=*/nullptr,
++      reinterpret_cast<GAsyncReadyCallback>(OnStartRequested), this);
++}
++
++// static
++void BaseCapturerPipeWire::OnStartRequested(GDBusConnection* connection,
++                                              GAsyncResult* result,
++                                              gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  GError* error = nullptr;
++  GVariant* variant = g_dbus_proxy_call_finish(that->proxy_, result, &error);
++  if (!variant) {
++    LOG(LS_ERROR) << "Failed to start the screen cast session: "
++                      << error->message;
++    g_error_free(error);
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  LOG(LS_INFO) << "Initializing the start of the screen cast session.";
++
++  gchar* handle = nullptr;
++  g_variant_get_child(variant, 0, "o", &handle);
++  g_variant_unref(variant);
++  if (!handle) {
++    LOG(LS_ERROR)
++        << "Failed to initialize the start of the screen cast session.";
++    if (that->start_request_signal_id_) {
++      g_dbus_connection_signal_unsubscribe(connection,
++                                           that->start_request_signal_id_);
++      that->start_request_signal_id_ = 0;
++    }
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  g_free(handle);
++
++  LOG(LS_INFO) << "Subscribed to the start signal.";
++}
++
++// static
++void BaseCapturerPipeWire::OnStartRequestResponseSignal(
++    GDBusConnection* connection,
++    const gchar* sender_name,
++    const gchar* object_path,
++    const gchar* interface_name,
++    const gchar* signal_name,
++    GVariant* parameters,
++    gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  LOG(LS_INFO) << "Start signal received.";
++  guint32 portal_response;
++  GVariant* response_data;
++  GVariantIter* iter = nullptr;
++  g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data);
++  if (portal_response || !response_data) {
++    LOG(LS_ERROR) << "Failed to start the screen cast session.";
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  // Array of PipeWire streams. See
++  // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml
++  // documentation for <method name="Start">.
++  if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) {
++    GVariant* variant;
++
++    while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) {
++      guint32 stream_id;
++      gint32 width;
++      gint32 height;
++      GVariant* options;
++
++      g_variant_get(variant, "(u@a{sv})", &stream_id, &options);
++      RTC_DCHECK(options != nullptr);
++
++      g_variant_lookup(options, "size", "(ii)", &width, &height);
++
++      that->desktop_size_.set(width, height);
++
++      g_variant_unref(options);
++      g_variant_unref(variant);
++    }
++  }
++  g_variant_iter_free(iter);
++  g_variant_unref(response_data);
++
++  that->OpenPipeWireRemote();
++}
++
++void BaseCapturerPipeWire::OpenPipeWireRemote() {
++  GVariantBuilder builder;
++  g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
++
++  LOG(LS_INFO) << "Opening the PipeWire remote.";
++
++  g_dbus_proxy_call_with_unix_fd_list(
++      proxy_, "OpenPipeWireRemote",
++      g_variant_new("(oa{sv})", session_handle_, &builder),
++      G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*fd_list=*/nullptr,
++      /*cancellable=*/nullptr,
++      reinterpret_cast<GAsyncReadyCallback>(OnOpenPipeWireRemoteRequested),
++      this);
++}
++
++// static
++void BaseCapturerPipeWire::OnOpenPipeWireRemoteRequested(
++    GDBusConnection* connection,
++    GAsyncResult* result,
++    gpointer user_data) {
++  BaseCapturerPipeWire* that =
++      static_cast<BaseCapturerPipeWire*>(user_data);
++  RTC_DCHECK(that);
++
++  GError* error = nullptr;
++  GUnixFDList* outlist = nullptr;
++  GVariant* variant = g_dbus_proxy_call_with_unix_fd_list_finish(
++      that->proxy_, &outlist, result, &error);
++  if (!variant) {
++    LOG(LS_ERROR) << "Failed to open the PipeWire remote: "
++                      << error->message;
++    g_error_free(error);
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  gint32 index;
++  g_variant_get(variant, "(h)", &index);
++
++  if ((that->pw_fd_ = g_unix_fd_list_get(outlist, index, &error)) == -1) {
++    LOG(LS_ERROR) << "Failed to get file descriptor from the list: "
++                      << error->message;
++    g_error_free(error);
++    g_variant_unref(variant);
++    that->portal_init_failed_ = true;
++    return;
++  }
++
++  g_variant_unref(variant);
++  g_object_unref(outlist);
++
++  that->InitPipeWire();
++  LOG(LS_INFO) << "PipeWire remote opened.";
++}
++
++void BaseCapturerPipeWire::Start(Callback* callback) {
++  RTC_DCHECK(!callback_);
++  RTC_DCHECK(callback);
++
++  InitPortals();
++
++  callback_ = callback;
++}
++
++void BaseCapturerPipeWire::CaptureFrame() {
++  if (portal_init_failed_) {
++    callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
++    return;
++  }
++
++  if (!current_frame_) {
++    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
++    return;
++  }
++
++  std::unique_ptr<DesktopFrame> result(new BasicDesktopFrame(desktop_size_));
++  result->CopyPixelsFrom(
++      current_frame_, (desktop_size_.width() * kBytesPerPixelPw),
++      DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height()));
++  if (!result) {
++    callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
++    return;
++  }
++  callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
++}
++
++bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) {
++  RTC_DCHECK(sources->size() == 0);
++  // List of available screens is already presented by the xdg-desktop-portal.
++  // But we have to add an empty source as the code expects it.
++  sources->push_back({0});
++  return true;
++}
++
++bool BaseCapturerPipeWire::SelectSource(SourceId id) {
++  // Screen selection is handled by the xdg-desktop-portal.
++  return true;
++}
++
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h.pipewire	2019-01-07 14:53:17.201061764 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h	2019-01-07 14:53:17.201061764 +0100
+@@ -0,0 +1,167 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_BASE_CAPTURER_PIPEWIRE_H_
++#define MODULES_DESKTOP_CAPTURE_BASE_CAPTURER_PIPEWIRE_H_
++
++#include <gio/gio.h>
++#define typeof __typeof__
++#include <pipewire/pipewire.h>
++#include <spa/param/video/format-utils.h>
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++
++namespace webrtc {
++
++class PipeWireType {
++ public:
++  spa_type_media_type media_type;
++  spa_type_media_subtype media_subtype;
++  spa_type_format_video format_video;
++  spa_type_video_format video_format;
++};
++
++class BaseCapturerPipeWire : public DesktopCapturer {
++ public:
++  enum CaptureSourceType { Screen = 1, Window };
++
++  explicit BaseCapturerPipeWire(CaptureSourceType source_type);
++  ~BaseCapturerPipeWire() override;
++
++  // DesktopCapturer interface.
++  void Start(Callback* delegate) override;
++  void Stop() override { callback_ = nullptr; }
++  void CaptureFrame() override;
++  bool GetSourceList(SourceList* sources) override;
++  bool SelectSource(SourceId id) override;
++
++ private:
++  // PipeWire types -->
++  pw_core* pw_core_ = nullptr;
++  pw_type* pw_core_type_ = nullptr;
++  pw_stream* pw_stream_ = nullptr;
++  pw_remote* pw_remote_ = nullptr;
++  pw_loop* pw_loop_ = nullptr;
++  pw_thread_loop* pw_main_loop_ = nullptr;
++  PipeWireType* pw_type_ = nullptr;
++
++  spa_hook spa_stream_listener_ = {};
++  spa_hook spa_remote_listener_ = {};
++
++  pw_stream_events pw_stream_events_ = {};
++  pw_remote_events pw_remote_events_ = {};
++
++  spa_video_info_raw* spa_video_format_ = nullptr;
++
++  gint32 pw_fd_ = -1;
++
++  CaptureSourceType capture_source_type_ =
++      BaseCapturerPipeWire::CaptureSourceType::Screen;
++
++  // <-- end of PipeWire types
++
++  GDBusConnection* connection_ = nullptr;
++  GDBusProxy* proxy_ = nullptr;
++  gchar* portal_handle_ = nullptr;
++  gchar* session_handle_ = nullptr;
++  gchar* sources_handle_ = nullptr;
++  gchar* start_handle_ = nullptr;
++  guint session_request_signal_id_ = 0;
++  guint sources_request_signal_id_ = 0;
++  guint start_request_signal_id_ = 0;
++
++  DesktopSize desktop_size_ = {};
++  DesktopCaptureOptions options_ = {};
++
++  uint8_t* current_frame_ = nullptr;
++  Callback* callback_ = nullptr;
++
++  bool portal_init_failed_ = false;
++
++  void InitPortals();
++  void InitPipeWire();
++  void InitPipeWireTypes();
++
++  void CreateReceivingStream();
++  void HandleBuffer(pw_buffer* buffer);
++
++  void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size);
++
++  static void OnStateChanged(void* data,
++                             pw_remote_state old_state,
++                             pw_remote_state state,
++                             const char* error);
++  static void OnStreamStateChanged(void* data,
++                                   pw_stream_state old_state,
++                                   pw_stream_state state,
++                                   const char* error_message);
++
++  static void OnStreamFormatChanged(void* data, const struct spa_pod* format);
++  static void OnStreamProcess(void* data);
++  static void OnNewBuffer(void* data, uint32_t id);
++
++  guint SetupRequestResponseSignal(const gchar* object_path,
++                                   GDBusSignalCallback callback);
++
++  static void OnProxyRequested(GObject* object,
++                               GAsyncResult* result,
++                               gpointer user_data);
++
++  static gchar* PrepareSignalHandle(GDBusConnection* connection,
++                                    const gchar* token);
++
++  void SessionRequest();
++  static void OnSessionRequested(GDBusConnection* connection,
++                                 GAsyncResult* result,
++                                 gpointer user_data);
++  static void OnSessionRequestResponseSignal(GDBusConnection* connection,
++                                             const gchar* sender_name,
++                                             const gchar* object_path,
++                                             const gchar* interface_name,
++                                             const gchar* signal_name,
++                                             GVariant* parameters,
++                                             gpointer user_data);
++
++  void SourcesRequest();
++  static void OnSourcesRequested(GDBusConnection* connection,
++                                 GAsyncResult* result,
++                                 gpointer user_data);
++  static void OnSourcesRequestResponseSignal(GDBusConnection* connection,
++                                             const gchar* sender_name,
++                                             const gchar* object_path,
++                                             const gchar* interface_name,
++                                             const gchar* signal_name,
++                                             GVariant* parameters,
++                                             gpointer user_data);
++
++  void StartRequest();
++  static void OnStartRequested(GDBusConnection* connection,
++                               GAsyncResult* result,
++                               gpointer user_data);
++  static void OnStartRequestResponseSignal(GDBusConnection* connection,
++                                           const gchar* sender_name,
++                                           const gchar* object_path,
++                                           const gchar* interface_name,
++                                           const gchar* signal_name,
++                                           GVariant* parameters,
++                                           gpointer user_data);
++
++  void OpenPipeWireRemote();
++  static void OnOpenPipeWireRemoteRequested(GDBusConnection* connection,
++                                            GAsyncResult* result,
++                                            gpointer user_data);
++
++  RTC_DISALLOW_COPY_AND_ASSIGN(BaseCapturerPipeWire);
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_BASE_CAPTURER_PIPEWIRE_H_
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build.pipewire	2019-01-07 14:53:17.201061764 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build	2019-01-07 14:56:57.674544724 +0100
+@@ -144,14 +144,26 @@ if CONFIG["OS_TARGET"] == "FreeBSD":
+         "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc"
+     ]
+ 
++# Common Linux stuff between X11 and PipeWire
+ if CONFIG["OS_TARGET"] == "Linux":
+ 
+     DEFINES["USE_NSS_CERTS"] = "1"
+-    DEFINES["USE_X11"] = "1"
+     DEFINES["WEBRTC_LINUX"] = True
+     DEFINES["WEBRTC_POSIX"] = True
+     DEFINES["_FILE_OFFSET_BITS"] = "64"
+ 
++    UNIFIED_SOURCES += [
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc",
++    ]
++
++# X11 specific files
++if CONFIG["OS_TARGET"] == "Linux":
++
++    DEFINES["USE_X11"] = "1"
++
+     OS_LIBS += [
+         "rt",
+         "X11",
+@@ -178,6 +190,28 @@ if CONFIG["OS_TARGET"] == "Linux":
+         "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc"
+     ]
+ 
++# PipeWire specific files
++if CONFIG["OS_TARGET"] == "Linux":
++
++    DEFINES["WEBRTC_USE_PIPEWIRE"] = "1"
++
++    OS_LIBS += [
++        "rt",
++        "pipewire-0.2",
++        "glib-2.0",
++        "gio-2.0",
++        "gobject-2.0"
++    ]
++
++    CXXFLAGS += CONFIG['TK_CFLAGS']
++
++    UNIFIED_SOURCES += [
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc"
++    ]
++
++
+ if CONFIG["OS_TARGET"] == "NetBSD":
+ 
+     DEFINES["USE_X11"] = "1"
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h	2019-01-07 14:53:17.202061775 +0100
+@@ -107,6 +107,11 @@ class DesktopCaptureOptions {
+   }
+ #endif
+ 
++#if defined(WEBRTC_USE_PIPEWIRE)
++  bool allow_pipewire() const { return allow_pipewire_; }
++  void set_allow_pipewire(bool allow) { allow_pipewire_ = allow; }
++#endif
++
+  private:
+ #if defined(USE_X11)
+   rtc::scoped_refptr<SharedXDisplay> x_display_;
+@@ -129,6 +134,9 @@ class DesktopCaptureOptions {
+ #endif
+   bool disable_effects_ = true;
+   bool detect_updated_region_ = false;
++#if defined(WEBRTC_USE_PIPEWIRE)
++  bool allow_pipewire_ = true;
++#endif
+ };
+ 
+ }  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc	2019-01-07 14:53:17.202061775 +0100
+@@ -66,4 +66,17 @@ std::unique_ptr<DesktopCapturer> Desktop
+   return capturer;
+ }
+ 
++#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11)
++bool DesktopCapturer::IsRunningUnderWayland() {
++  const char* xdg_session_type = getenv("XDG_SESSION_TYPE");
++  if (!xdg_session_type || strncmp(xdg_session_type, "wayland", 7) != 0)
++    return false;
++
++  if (!(getenv("WAYLAND_DISPLAY")))
++    return false;
++
++  return true;
++}
++#endif
++
+ }  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h	2019-01-07 14:53:17.202061775 +0100
+@@ -129,6 +129,10 @@ class DesktopCapturer {
+   static std::unique_ptr<DesktopCapturer> CreateAppCapturer(
+       const DesktopCaptureOptions& options);
+ 
++#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11)
++  static bool IsRunningUnderWayland();
++#endif
++
+  protected:
+   // CroppingWindowCapturer needs to create raw capturers without wrappers, so
+   // the following two functions are protected.
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc.pipewire	2019-01-07 14:53:17.202061775 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc	2019-01-07 14:53:17.202061775 +0100
+@@ -0,0 +1,40 @@
++/*
++ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
++
++#if defined(USE_X11)
++#include "webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.h"
++#endif // defined(USE_X11)
++
++namespace webrtc {
++
++// static
++MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
++    const DesktopCaptureOptions& options, WindowId window) {
++#if defined(USE_X11)
++  return MouseCursorMonitorX11::CreateForWindow(options, window);
++#else
++  return nullptr;
++#endif // defined(USE_X11)
++}
++
++// static
++MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
++    const DesktopCaptureOptions& options,
++    ScreenId screen) {
++#if defined(USE_X11)
++  return MouseCursorMonitorX11::CreateForScreen(options, screen);
++#else
++  return nullptr;
++#endif // defined(USE_X11)
++}
++
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc	2019-01-07 14:53:17.202061775 +0100
+@@ -16,6 +16,8 @@
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ 
++#include "webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.h"
++
+ #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
+ #include "webrtc/modules/desktop_capture/desktop_frame.h"
+ #include "webrtc/modules/desktop_capture/mouse_cursor.h"
+@@ -59,38 +61,6 @@ Window GetTopLevelWindow(Display* displa
+ 
+ namespace webrtc {
+ 
+-class MouseCursorMonitorX11 : public MouseCursorMonitor,
+-                              public SharedXDisplay::XEventHandler {
+- public:
+-  MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window, Window inner_window);
+-  ~MouseCursorMonitorX11() override;
+-
+-  void Start(Callback* callback, Mode mode) override;
+-  void Stop() override;
+-  void Capture() override;
+-
+- private:
+-  // SharedXDisplay::XEventHandler interface.
+-  bool HandleXEvent(const XEvent& event) override;
+-
+-  Display* display() { return x_display_->display(); }
+-
+-  // Captures current cursor shape and stores it in |cursor_shape_|.
+-  void CaptureCursor();
+-
+-  rtc::scoped_refptr<SharedXDisplay> x_display_;
+-  Callback* callback_;
+-  Mode mode_;
+-  Window window_;
+-  Window inner_window_;
+-
+-  bool have_xfixes_;
+-  int xfixes_event_base_;
+-  int xfixes_error_base_;
+-
+-  std::unique_ptr<MouseCursor> cursor_shape_;
+-};
+-
+ MouseCursorMonitorX11::MouseCursorMonitorX11(
+     const DesktopCaptureOptions& options,
+     Window window, Window inner_window)
+@@ -244,7 +214,7 @@ void MouseCursorMonitorX11::CaptureCurso
+ }
+ 
+ // static
+-MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
++MouseCursorMonitor* MouseCursorMonitorX11::CreateForWindow(
+     const DesktopCaptureOptions& options, WindowId window) {
+   if (!options.x_display())
+     return NULL;
+@@ -254,7 +224,7 @@ MouseCursorMonitor* MouseCursorMonitor::
+   return new MouseCursorMonitorX11(options, outer_window, window);
+ }
+ 
+-MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
++MouseCursorMonitor* MouseCursorMonitorX11::CreateForScreen(
+     const DesktopCaptureOptions& options,
+     ScreenId screen) {
+   if (!options.x_display())
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.h.pipewire	2019-01-07 14:53:17.202061775 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.h	2019-01-07 14:53:17.202061775 +0100
+@@ -0,0 +1,63 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_MONITOR_X11_H_
++#define MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_MONITOR_X11_H_
++
++#include <X11/X.h>
++#include <memory>
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capture_types.h"
++#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
++#include "webrtc/modules/desktop_capture/mouse_cursor.h"
++#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
++#include "webrtc/base/scoped_ref_ptr.h"
++
++namespace webrtc {
++
++class MouseCursorMonitorX11 : public MouseCursorMonitor,
++                              public SharedXDisplay::XEventHandler {
++ public:
++  MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window, Window inner_window);
++  ~MouseCursorMonitorX11() override;
++
++  void Start(Callback* callback, Mode mode) override;
++  void Stop() override;
++  void Capture() override;
++
++  static MouseCursorMonitor* CreateForWindow(const DesktopCaptureOptions& options, WindowId window);
++  static MouseCursorMonitor* CreateForScreen(const DesktopCaptureOptions& options, ScreenId screen);
++
++ private:
++  // SharedXDisplay::XEventHandler interface.
++  bool HandleXEvent(const XEvent& event) override;
++
++  Display* display() { return x_display_->display(); }
++
++  // Captures current cursor shape and stores it in |cursor_shape_|.
++  void CaptureCursor();
++
++  rtc::scoped_refptr<SharedXDisplay> x_display_;
++  Callback* callback_;
++  Mode mode_;
++  Window window_;
++  Window inner_window_;
++
++  bool have_xfixes_;
++  int xfixes_event_base_;
++  int xfixes_error_base_;
++
++  std::unique_ptr<MouseCursor> cursor_shape_;
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_MOUSE_CURSOR_MONITOR_X11_H_
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc.pipewire	2019-01-07 14:53:17.203061786 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc	2019-01-07 14:53:17.203061786 +0100
+@@ -0,0 +1,40 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++
++#if defined(WEBRTC_USE_PIPEWIRE)
++#include "webrtc/modules/desktop_capture/screen_capturer_pipewire.h"
++#endif  // defined(WEBRTC_USE_PIPEWIRE)
++
++#if defined(USE_X11)
++#include "webrtc/modules/desktop_capture/screen_capturer_x11.h"
++#endif  // defined(USE_X11)
++
++namespace webrtc {
++
++// static
++std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
++    const DesktopCaptureOptions& options) {
++#if defined(WEBRTC_USE_PIPEWIRE)
++  if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) {
++    return ScreenCapturerPipeWire::CreateRawScreenCapturer(options);
++  }
++#endif  // defined(WEBRTC_USE_PIPEWIRE)
++
++#if defined(USE_X11)
++  return ScreenCapturerX11::CreateRawScreenCapturer(options);
++#endif  // defined(USE_X11)
++
++  return nullptr;
++}
++
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc.pipewire	2019-01-07 14:53:17.203061786 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc	2019-01-07 14:53:17.203061786 +0100
+@@ -0,0 +1,31 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "webrtc/modules/desktop_capture/screen_capturer_pipewire.h"
++
++#include <memory>
++
++namespace webrtc {
++
++ScreenCapturerPipeWire::ScreenCapturerPipeWire()
++    : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {}
++ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {}
++
++// static
++std::unique_ptr<DesktopCapturer>
++ScreenCapturerPipeWire::CreateRawScreenCapturer(
++    const DesktopCaptureOptions& options) {
++  std::unique_ptr<ScreenCapturerPipeWire> capturer(
++      new ScreenCapturerPipeWire());
++
++  return std::move(capturer);
++}
++
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h.pipewire	2019-01-07 14:53:17.203061786 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h	2019-01-07 14:53:17.203061786 +0100
+@@ -0,0 +1,33 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_PIPEWIRE_H_
++#define MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_PIPEWIRE_H_
++
++#include <memory>
++
++#include "webrtc/modules/desktop_capture/base_capturer_pipewire.h"
++
++namespace webrtc {
++
++class ScreenCapturerPipeWire : public BaseCapturerPipeWire {
++ public:
++  ScreenCapturerPipeWire();
++  ~ScreenCapturerPipeWire() override;
++
++  static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer(
++      const DesktopCaptureOptions& options);
++
++  RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerPipeWire);
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_PIPEWIRE_H_
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc	2019-01-07 14:53:17.203061786 +0100
+@@ -19,6 +19,8 @@
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ 
++#include "webrtc/modules/desktop_capture/screen_capturer_x11.h"
++
+ #include "webrtc/base/checks.h"
+ #include "webrtc/base/constructormagic.h"
+ #include "webrtc/base/timeutils.h"
+@@ -32,100 +34,12 @@
+ #include "webrtc/system_wrappers/include/logging.h"
+ 
+ namespace webrtc {
+-namespace {
+-
+-// A class to perform video frame capturing for Linux.
+-//
+-// If XDamage is used, this class sets DesktopFrame::updated_region() according
+-// to the areas reported by XDamage. Otherwise this class does not detect
+-// DesktopFrame::updated_region(), the field is always set to the entire frame
+-// rectangle. ScreenCapturerDifferWrapper should be used if that functionality
+-// is necessary.
+-class ScreenCapturerLinux : public DesktopCapturer,
+-                            public SharedXDisplay::XEventHandler {
+- public:
+-  ScreenCapturerLinux();
+-  ~ScreenCapturerLinux() override;
+-
+-  // TODO(ajwong): Do we really want this to be synchronous?
+-  bool Init(const DesktopCaptureOptions& options);
+-
+-  // DesktopCapturer interface.
+-  void Start(Callback* delegate) override;
+-  void Stop() override;
+-  void CaptureFrame() override;
+-  bool GetSourceList(SourceList* sources) override;
+-  bool SelectSource(SourceId id) override;
+-
+- private:
+-  Display* display() { return options_.x_display()->display(); }
+-
+-  // SharedXDisplay::XEventHandler interface.
+-  bool HandleXEvent(const XEvent& event) override;
+-
+-  void InitXDamage();
+-
+-  // Capture screen pixels to the current buffer in the queue. In the DAMAGE
+-  // case, the ScreenCapturerHelper already holds the list of invalid rectangles
+-  // from HandleXEvent(). In the non-DAMAGE case, this captures the
+-  // whole screen, then calculates some invalid rectangles that include any
+-  // differences between this and the previous capture.
+-  std::unique_ptr<DesktopFrame> CaptureScreen();
+-
+-  // Called when the screen configuration is changed.
+-  void ScreenConfigurationChanged();
+-
+-  // Synchronize the current buffer with |last_buffer_|, by copying pixels from
+-  // the area of |last_invalid_rects|.
+-  // Note this only works on the assumption that kNumBuffers == 2, as
+-  // |last_invalid_rects| holds the differences from the previous buffer and
+-  // the one prior to that (which will then be the current buffer).
+-  void SynchronizeFrame();
+-
+-  void DeinitXlib();
+-
+-  DesktopCaptureOptions options_;
+-
+-  Callback* callback_ = nullptr;
+-
+-  // X11 graphics context.
+-  GC gc_ = nullptr;
+-  Window root_window_ = BadValue;
+-
+-  // XFixes.
+-  bool has_xfixes_ = false;
+-  int xfixes_event_base_ = -1;
+-  int xfixes_error_base_ = -1;
+-
+-  // XDamage information.
+-  bool use_damage_ = false;
+-  Damage damage_handle_ = 0;
+-  int damage_event_base_ = -1;
+-  int damage_error_base_ = -1;
+-  XserverRegion damage_region_ = 0;
+-
+-  // Access to the X Server's pixel buffer.
+-  XServerPixelBuffer x_server_pixel_buffer_;
+-
+-  // A thread-safe list of invalid rectangles, and the size of the most
+-  // recently captured screen.
+-  ScreenCapturerHelper helper_;
+-
+-  // Queue of the frames buffers.
+-  ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
+-
+-  // Invalid region from the previous capture. This is used to synchronize the
+-  // current with the last buffer used.
+-  DesktopRegion last_invalid_region_;
+ 
+-  RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux);
+-};
+-
+-ScreenCapturerLinux::ScreenCapturerLinux() {
++ScreenCapturerX11::ScreenCapturerX11() {
+   helper_.SetLogGridSize(4);
+ }
+ 
+-ScreenCapturerLinux::~ScreenCapturerLinux() {
++ScreenCapturerX11::~ScreenCapturerX11() {
+   options_.x_display()->RemoveEventHandler(ConfigureNotify, this);
+   if (use_damage_) {
+     options_.x_display()->RemoveEventHandler(
+@@ -134,7 +48,7 @@ ScreenCapturerLinux::~ScreenCapturerLinu
+   DeinitXlib();
+ }
+ 
+-bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) {
++bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) {
+   options_ = options;
+ 
+   root_window_ = RootWindow(display(), DefaultScreen(display()));
+@@ -177,7 +91,7 @@ bool ScreenCapturerLinux::Init(const Des
+   return true;
+ }
+ 
+-void ScreenCapturerLinux::InitXDamage() {
++void ScreenCapturerX11::InitXDamage() {
+   // Our use of XDamage requires XFixes.
+   if (!has_xfixes_) {
+     return;
+@@ -218,18 +132,18 @@ void ScreenCapturerLinux::InitXDamage()
+   LOG(LS_INFO) << "Using XDamage extension.";
+ }
+ 
+-void ScreenCapturerLinux::Start(Callback* callback) {
++void ScreenCapturerX11::Start(Callback* callback) {
+   RTC_DCHECK(!callback_);
+   RTC_DCHECK(callback);
+ 
+   callback_ = callback;
+ }
+ 
+-void ScreenCapturerLinux::Stop() {
++void ScreenCapturerX11::Stop() {
+   callback_ = NULL;
+ }
+ 
+-void ScreenCapturerLinux::CaptureFrame() {
++void ScreenCapturerX11::CaptureFrame() {
+   int64_t capture_start_time_nanos = rtc::TimeNanos();
+ 
+   queue_.MoveToNextFrame();
+@@ -243,6 +157,7 @@ void ScreenCapturerLinux::CaptureFrame()
+   // in a good shape.
+   if (!x_server_pixel_buffer_.is_initialized()) {
+      // We failed to initialize pixel buffer.
++     LOG(LS_ERROR) << "Pixel buffer is not initialized.";
+      callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
+      return;
+   }
+@@ -258,6 +173,7 @@ void ScreenCapturerLinux::CaptureFrame()
+ 
+   std::unique_ptr<DesktopFrame> result = CaptureScreen();
+   if (!result) {
++    LOG(LS_WARNING) << "Temporarily failed to capture screen.";
+     callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
+     return;
+   }
+@@ -268,19 +184,19 @@ void ScreenCapturerLinux::CaptureFrame()
+   callback_->OnCaptureResult(Result::SUCCESS, std::move(result));
+ }
+ 
+-bool ScreenCapturerLinux::GetSourceList(SourceList* sources) {
++bool ScreenCapturerX11::GetSourceList(SourceList* sources) {
+   RTC_DCHECK(sources->size() == 0);
+   // TODO(jiayl): implement screen enumeration.
+   sources->push_back({0});
+   return true;
+ }
+ 
+-bool ScreenCapturerLinux::SelectSource(SourceId id) {
++bool ScreenCapturerX11::SelectSource(SourceId id) {
+   // TODO(jiayl): implement screen selection.
+   return true;
+ }
+ 
+-bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) {
++bool ScreenCapturerX11::HandleXEvent(const XEvent& event) {
+   if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) {
+     const XDamageNotifyEvent* damage_event =
+         reinterpret_cast<const XDamageNotifyEvent*>(&event);
+@@ -295,7 +211,7 @@ bool ScreenCapturerLinux::HandleXEvent(c
+   return false;
+ }
+ 
+-std::unique_ptr<DesktopFrame> ScreenCapturerLinux::CaptureScreen() {
++std::unique_ptr<DesktopFrame> ScreenCapturerX11::CaptureScreen() {
+   std::unique_ptr<SharedDesktopFrame> frame = queue_.current_frame()->Share();
+   RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size()));
+ 
+@@ -345,14 +261,15 @@ std::unique_ptr<DesktopFrame> ScreenCapt
+     // Doing full-screen polling, or this is the first capture after a
+     // screen-resolution change.  In either case, need a full-screen capture.
+     DesktopRect screen_rect = DesktopRect::MakeSize(frame->size());
+-    x_server_pixel_buffer_.CaptureRect(screen_rect, frame.get());
++    if (!x_server_pixel_buffer_.CaptureRect(screen_rect, frame.get()))
++      return nullptr;
+     updated_region->SetRect(screen_rect);
+   }
+ 
+   return std::move(frame);
+ }
+ 
+-void ScreenCapturerLinux::ScreenConfigurationChanged() {
++void ScreenCapturerX11::ScreenConfigurationChanged() {
+   // Make sure the frame buffers will be reallocated.
+   queue_.Reset();
+ 
+@@ -363,7 +280,7 @@ void ScreenCapturerLinux::ScreenConfigur
+   }
+ }
+ 
+-void ScreenCapturerLinux::SynchronizeFrame() {
++void ScreenCapturerX11::SynchronizeFrame() {
+   // Synchronize the current buffer with the previous one since we do not
+   // capture the entire desktop. Note that encoder may be reading from the
+   // previous buffer at this time so thread access complaints are false
+@@ -383,7 +300,7 @@ void ScreenCapturerLinux::SynchronizeFra
+   }
+ }
+ 
+-void ScreenCapturerLinux::DeinitXlib() {
++void ScreenCapturerX11::DeinitXlib() {
+   if (gc_) {
+     XFreeGC(display(), gc_);
+     gc_ = nullptr;
+@@ -404,20 +321,18 @@ void ScreenCapturerLinux::DeinitXlib() {
+   }
+ }
+ 
+-}  // namespace
+-
+ // static
+-std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
++std::unique_ptr<DesktopCapturer> ScreenCapturerX11::CreateRawScreenCapturer(
+     const DesktopCaptureOptions& options) {
+   if (!options.x_display())
+     return nullptr;
+ 
+-  std::unique_ptr<ScreenCapturerLinux> capturer(new ScreenCapturerLinux());
++  std::unique_ptr<ScreenCapturerX11> capturer(new ScreenCapturerX11());
+   if (!capturer.get()->Init(options)) {
+     return nullptr;
+   }
+ 
+-  return std::unique_ptr<DesktopCapturer>(capturer.release());
++  return std::move(capturer);
+ }
+ 
+ }  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.h.pipewire	2019-01-07 14:53:17.203061786 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.h	2019-01-07 14:53:17.203061786 +0100
+@@ -0,0 +1,124 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_X11_H_
++#define MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_X11_H_
++
++#include <X11/X.h>
++#include <X11/Xlib.h>
++#include <X11/extensions/Xdamage.h>
++#include <X11/extensions/Xfixes.h>
++#include <memory>
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++#include "webrtc/modules/desktop_capture/desktop_frame.h"
++#include "webrtc/modules/desktop_capture/desktop_region.h"
++#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
++#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
++#include "webrtc/modules/desktop_capture/screen_capture_frame_queue.h"
++#include "webrtc/modules/desktop_capture/screen_capturer_helper.h"
++#include "webrtc/modules/desktop_capture/shared_desktop_frame.h"
++#include "webrtc/base/constructormagic.h"
++
++namespace webrtc {
++
++// A class to perform video frame capturing for Linux on X11.
++//
++// If XDamage is used, this class sets DesktopFrame::updated_region() according
++// to the areas reported by XDamage. Otherwise this class does not detect
++// DesktopFrame::updated_region(), the field is always set to the entire frame
++// rectangle. ScreenCapturerDifferWrapper should be used if that functionality
++// is necessary.
++class ScreenCapturerX11 : public DesktopCapturer,
++                          public SharedXDisplay::XEventHandler {
++ public:
++  ScreenCapturerX11();
++  ~ScreenCapturerX11() override;
++
++  static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer(const DesktopCaptureOptions& options);
++
++  // TODO(ajwong): Do we really want this to be synchronous?
++  bool Init(const DesktopCaptureOptions& options);
++
++  // DesktopCapturer interface.
++  void Start(Callback* delegate) override;
++  void Stop() override;
++  void CaptureFrame() override;
++  bool GetSourceList(SourceList* sources) override;
++  bool SelectSource(SourceId id) override;
++
++ private:
++  Display* display() { return options_.x_display()->display(); }
++
++  // SharedXDisplay::XEventHandler interface.
++  bool HandleXEvent(const XEvent& event) override;
++
++  void InitXDamage();
++
++  // Capture screen pixels to the current buffer in the queue. In the DAMAGE
++  // case, the ScreenCapturerHelper already holds the list of invalid rectangles
++  // from HandleXEvent(). In the non-DAMAGE case, this captures the
++  // whole screen, then calculates some invalid rectangles that include any
++  // differences between this and the previous capture.
++  std::unique_ptr<DesktopFrame> CaptureScreen();
++
++  // Called when the screen configuration is changed.
++  void ScreenConfigurationChanged();
++
++  // Synchronize the current buffer with |last_buffer_|, by copying pixels from
++  // the area of |last_invalid_rects|.
++  // Note this only works on the assumption that kNumBuffers == 2, as
++  // |last_invalid_rects| holds the differences from the previous buffer and
++  // the one prior to that (which will then be the current buffer).
++  void SynchronizeFrame();
++
++  void DeinitXlib();
++
++  DesktopCaptureOptions options_;
++
++  Callback* callback_ = nullptr;
++
++  // X11 graphics context.
++  GC gc_ = nullptr;
++  Window root_window_ = BadValue;
++
++  // XFixes.
++  bool has_xfixes_ = false;
++  int xfixes_event_base_ = -1;
++  int xfixes_error_base_ = -1;
++
++  // XDamage information.
++  bool use_damage_ = false;
++  Damage damage_handle_ = 0;
++  int damage_event_base_ = -1;
++  int damage_error_base_ = -1;
++  XserverRegion damage_region_ = 0;
++
++  // Access to the X Server's pixel buffer.
++  XServerPixelBuffer x_server_pixel_buffer_;
++
++  // A thread-safe list of invalid rectangles, and the size of the most
++  // recently captured screen.
++  ScreenCapturerHelper helper_;
++
++  // Queue of the frames buffers.
++  ScreenCaptureFrameQueue<SharedDesktopFrame> queue_;
++
++  // Invalid region from the previous capture. This is used to synchronize the
++  // current with the last buffer used.
++  DesktopRegion last_invalid_region_;
++
++  RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerX11);
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_SCREEN_CAPTURER_X11_H_
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc.pipewire	2019-01-07 14:53:17.203061786 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc	2019-01-07 14:53:17.203061786 +0100
+@@ -0,0 +1,40 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++
++#if defined(WEBRTC_USE_PIPEWIRE)
++#include "webrtc/modules/desktop_capture/window_capturer_pipewire.h"
++#endif  // defined(WEBRTC_USE_PIPEWIRE)
++
++#if defined(USE_X11)
++#include "webrtc/modules/desktop_capture/window_capturer_x11.h"
++#endif  // defined(USE_X11)
++
++namespace webrtc {
++
++// static
++std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
++    const DesktopCaptureOptions& options) {
++#if defined(WEBRTC_USE_PIPEWIRE)
++  if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) {
++    return WindowCapturerPipeWire::CreateRawWindowCapturer(options);
++  }
++#endif  // defined(WEBRTC_USE_PIPEWIRE)
++
++#if defined(USE_X11)
++  return WindowCapturerX11::CreateRawWindowCapturer(options);
++#endif  // defined(USE_X11)
++
++  return nullptr;
++}
++
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc.pipewire	2019-01-07 14:53:17.204061797 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc	2019-01-07 14:53:17.204061797 +0100
+@@ -0,0 +1,28 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#include "webrtc/modules/desktop_capture/window_capturer_pipewire.h"
++
++namespace webrtc {
++
++WindowCapturerPipeWire::WindowCapturerPipeWire()
++    : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {}
++WindowCapturerPipeWire::~WindowCapturerPipeWire() {}
++
++// static
++std::unique_ptr<DesktopCapturer>
++WindowCapturerPipeWire::CreateRawWindowCapturer(
++    const DesktopCaptureOptions& options) {
++  std::unique_ptr<WindowCapturerPipeWire> capturer(
++      new WindowCapturerPipeWire());
++
++  return std::move(capturer);
++}
++}  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h.pipewire	2019-01-07 14:53:17.204061797 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h	2019-01-07 14:53:17.204061797 +0100
+@@ -0,0 +1,33 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_PIPEWIRE_H_
++#define MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_PIPEWIRE_H_
++
++#include <memory>
++
++#include "webrtc/modules/desktop_capture/base_capturer_pipewire.h"
++
++namespace webrtc {
++
++class WindowCapturerPipeWire : public BaseCapturerPipeWire {
++ public:
++  WindowCapturerPipeWire();
++  ~WindowCapturerPipeWire() override;
++
++  static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer(
++      const DesktopCaptureOptions& options);
++
++  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerPipeWire);
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_PIPEWIRE_H_
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc.pipewire	2018-10-17 22:39:32.000000000 +0200
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc	2019-01-07 14:53:17.204061797 +0100
+@@ -17,6 +17,8 @@
+ 
+ #include <algorithm>
+ 
++#include "webrtc/modules/desktop_capture/window_capturer_x11.h"
++
+ #include "webrtc/base/constructormagic.h"
+ #include "webrtc/base/scoped_ref_ptr.h"
+ #include "webrtc/modules/desktop_capture/desktop_capturer.h"
+@@ -30,58 +32,7 @@
+ 
+ namespace webrtc {
+ 
+-namespace {
+-
+-class WindowCapturerLinux : public DesktopCapturer,
+-                            public SharedXDisplay::XEventHandler {
+- public:
+-  WindowCapturerLinux(const DesktopCaptureOptions& options);
+-  ~WindowCapturerLinux() override;
+-
+-  // DesktopCapturer interface.
+-  void Start(Callback* callback) override;
+-  void Stop() override;
+-  void CaptureFrame() override;
+-  bool GetSourceList(SourceList* sources) override;
+-  bool SelectSource(SourceId id) override;
+-  bool FocusOnSelectedSource() override;
+-
+-  // SharedXDisplay::XEventHandler interface.
+-  bool HandleXEvent(const XEvent& event) override;
+-
+- private:
+-  Display* display() { return x_display_->display(); }
+-
+-  // Iterates through |window| hierarchy to find first visible window, i.e. one
+-  // that has WM_STATE property set to NormalState.
+-  // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
+-  ::Window GetApplicationWindow(::Window window);
+-
+-  // Returns true if the |window| is a desktop element.
+-  bool IsDesktopElement(::Window window);
+-
+-  // Returns window title for the specified X |window|.
+-  bool GetWindowTitle(::Window window, std::string* title);
+-
+-  // Returns the id of the owning process.
+-  int GetWindowProcessID(::Window window);
+-
+-  Callback* callback_ = nullptr;
+-
+-  rtc::scoped_refptr<SharedXDisplay> x_display_;
+-
+-  Atom wm_state_atom_;
+-  Atom window_type_atom_;
+-  Atom normal_window_type_atom_;
+-  bool has_composite_extension_ = false;
+-
+-  ::Window selected_window_ = 0;
+-  XServerPixelBuffer x_server_pixel_buffer_;
+-
+-  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux);
+-};
+-
+-WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options)
++WindowCapturerX11::WindowCapturerX11(const DesktopCaptureOptions& options)
+     : x_display_(options.x_display()) {
+   // Create Atoms so we don't need to do it every time they are used.
+   wm_state_atom_ = XInternAtom(display(), "WM_STATE", True);
+@@ -102,11 +53,11 @@ WindowCapturerLinux::WindowCapturerLinux
+   x_display_->AddEventHandler(ConfigureNotify, this);
+ }
+ 
+-WindowCapturerLinux::~WindowCapturerLinux() {
++WindowCapturerX11::~WindowCapturerX11() {
+   x_display_->RemoveEventHandler(ConfigureNotify, this);
+ }
+ 
+-bool WindowCapturerLinux::GetSourceList(SourceList* sources) {
++bool WindowCapturerX11::GetSourceList(SourceList* sources) {
+   SourceList result;
+ 
+   XErrorTrap error_trap(display());
+@@ -159,7 +110,7 @@ bool WindowCapturerLinux::GetSourceList(
+   return true;
+ }
+ 
+-bool WindowCapturerLinux::SelectSource(SourceId id) {
++bool WindowCapturerX11::SelectSource(SourceId id) {
+   if (!x_server_pixel_buffer_.Init(display(), id))
+     return false;
+ 
+@@ -180,7 +131,7 @@ bool WindowCapturerLinux::SelectSource(S
+   return true;
+ }
+ 
+-bool WindowCapturerLinux::FocusOnSelectedSource() {
++bool WindowCapturerX11::FocusOnSelectedSource() {
+   if (!selected_window_)
+     return false;
+ 
+@@ -229,18 +180,18 @@ bool WindowCapturerLinux::FocusOnSelecte
+   return true;
+ }
+ 
+-void WindowCapturerLinux::Start(Callback* callback) {
++void WindowCapturerX11::Start(Callback* callback) {
+   assert(!callback_);
+   assert(callback);
+ 
+   callback_ = callback;
+ }
+ 
+-void WindowCapturerLinux::Stop() {
++void WindowCapturerX11::Stop() {
+   callback_ = NULL;
+ }
+ 
+-void WindowCapturerLinux::CaptureFrame() {
++void WindowCapturerX11::CaptureFrame() {
+   x_display_->ProcessPendingXEvents();
+ 
+   if (!x_server_pixel_buffer_.IsWindowValid()) {
+@@ -274,7 +225,7 @@ void WindowCapturerLinux::CaptureFrame()
+   callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
+ }
+ 
+-bool WindowCapturerLinux::HandleXEvent(const XEvent& event) {
++bool WindowCapturerX11::HandleXEvent(const XEvent& event) {
+   if (event.type == ConfigureNotify) {
+     XConfigureEvent xce = event.xconfigure;
+     if (!DesktopSize(xce.width, xce.height).equals(
+@@ -288,7 +239,7 @@ bool WindowCapturerLinux::HandleXEvent(c
+   return false;
+ }
+ 
+-::Window WindowCapturerLinux::GetApplicationWindow(::Window window) {
++::Window WindowCapturerX11::GetApplicationWindow(::Window window) {
+   // Get WM_STATE property of the window.
+   XWindowProperty<uint32_t> window_state(display(), window, wm_state_atom_);
+ 
+@@ -326,7 +277,7 @@ bool WindowCapturerLinux::HandleXEvent(c
+   return app_window;
+ }
+ 
+-bool WindowCapturerLinux::IsDesktopElement(::Window window) {
++bool WindowCapturerX11::IsDesktopElement(::Window window) {
+   if (window == 0)
+     return false;
+ 
+@@ -361,7 +312,7 @@ bool WindowCapturerLinux::IsDesktopEleme
+   return result;
+ }
+ 
+-bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) {
++bool WindowCapturerX11::GetWindowTitle(::Window window, std::string* title) {
+   int status;
+   bool result = false;
+   XTextProperty window_name;
+@@ -390,9 +341,7 @@ bool WindowCapturerLinux::GetWindowTitle
+   return result;
+ }
+ 
+-}  // namespace
+-
+-int WindowCapturerLinux::GetWindowProcessID(::Window window) {
++int WindowCapturerX11::GetWindowProcessID(::Window window) {
+   // Get _NET_WM_PID property of the window.
+   Atom process_atom = XInternAtom(display(), "_NET_WM_PID", True);
+   XWindowProperty<uint32_t> process_id(display(), window, process_atom);
+@@ -401,11 +350,11 @@ int WindowCapturerLinux::GetWindowProces
+ }
+ 
+ // static
+-std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
++std::unique_ptr<DesktopCapturer> WindowCapturerX11::CreateRawWindowCapturer(
+     const DesktopCaptureOptions& options) {
+   if (!options.x_display())
+     return nullptr;
+-  return std::unique_ptr<DesktopCapturer>(new WindowCapturerLinux(options));
++  return std::unique_ptr<DesktopCapturer>(new WindowCapturerX11(options));
+ }
+ 
+ }  // namespace webrtc
+diff -up firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.h.pipewire firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.h
+--- firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.h.pipewire	2019-01-07 14:53:17.204061797 +0100
++++ firefox-60.3.0/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.h	2019-01-07 14:53:17.204061797 +0100
+@@ -0,0 +1,83 @@
++/*
++ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
++ *
++ *  Use of this source code is governed by a BSD-style license
++ *  that can be found in the LICENSE file in the root of the source
++ *  tree. An additional intellectual property rights grant can be found
++ *  in the file PATENTS.  All contributing project authors may
++ *  be found in the AUTHORS file in the root of the source tree.
++ */
++
++#ifndef MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_X11_H_
++#define MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_X11_H_
++
++#include <X11/X.h>
++#include <X11/Xlib.h>
++#include <memory>
++#include <string>
++
++#include "webrtc/modules/desktop_capture/desktop_capture_options.h"
++#include "webrtc/modules/desktop_capture/desktop_capturer.h"
++#include "webrtc/modules/desktop_capture/desktop_geometry.h"
++#include "webrtc/modules/desktop_capture/x11/shared_x_display.h"
++#include "webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.h"
++#include "webrtc/base/constructormagic.h"
++#include "webrtc/base/scoped_ref_ptr.h"
++
++namespace webrtc {
++
++class WindowCapturerX11 : public DesktopCapturer,
++                          public SharedXDisplay::XEventHandler {
++ public:
++  explicit WindowCapturerX11(const DesktopCaptureOptions& options);
++  ~WindowCapturerX11() override;
++
++  static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer(
++      const DesktopCaptureOptions& options);
++
++  // DesktopCapturer interface.
++  void Start(Callback* callback) override;
++  void Stop() override;
++  void CaptureFrame() override;
++  bool GetSourceList(SourceList* sources) override;
++  bool SelectSource(SourceId id) override;
++  bool FocusOnSelectedSource() override;
++
++  // SharedXDisplay::XEventHandler interface.
++  bool HandleXEvent(const XEvent& event) override;
++
++ private:
++  Display* display() { return x_display_->display(); }
++
++  // Iterates through |window| hierarchy to find first visible window, i.e. one
++  // that has WM_STATE property set to NormalState.
++  // See http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1 .
++  ::Window GetApplicationWindow(::Window window);
++
++  // Returns true if the |window| is a desktop element.
++  bool IsDesktopElement(::Window window);
++
++  // Returns window title for the specified X |window|.
++  bool GetWindowTitle(::Window window, std::string* title);
++
++  // Returns the id of the owning process.
++  int GetWindowProcessID(::Window window);
++
++  Callback* callback_ = nullptr;
++
++  rtc::scoped_refptr<SharedXDisplay> x_display_;
++
++  Atom wm_state_atom_;
++  Atom window_type_atom_;
++  Atom normal_window_type_atom_;
++  bool has_composite_extension_ = false;
++
++  ::Window selected_window_ = 0;
++  XServerPixelBuffer x_server_pixel_buffer_;
++
++  RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerX11);
++};
++
++}  // namespace webrtc
++
++#endif  // MODULES_DESKTOP_CAPTURE_WINDOW_CAPTURER_X11_H_
diff --git a/SOURCES/firefox-redhat-default-prefs.js b/SOURCES/firefox-redhat-default-prefs.js
new file mode 100644
index 0000000..607a132
--- /dev/null
+++ b/SOURCES/firefox-redhat-default-prefs.js
@@ -0,0 +1,35 @@
+pref("app.update.auto",                     false);
+pref("app.update.enabled",                  false);
+pref("app.update.autoInstallEnabled",       false);
+pref("general.smoothScroll",                true);
+pref("intl.locale.matchOS",                 true);
+pref("toolkit.storage.synchronous",         0);
+pref("toolkit.networkmanager.disable",      false);
+pref("offline.autoDetect",                  true);
+pref("browser.backspace_action",            2);
+pref("browser.display.use_system_colors",   true);
+pref("browser.download.folderList",         1);
+pref("browser.link.open_external",          3);
+pref("browser.shell.checkDefaultBrowser",   false);
+pref("network.manage-offline-status",       true);
+pref("extensions.shownSelectionUI",         true);
+pref("ui.SpellCheckerUnderlineStyle",       1);
+pref("startup.homepage_override_url",       "http://www.redhat.com");
+pref("startup.homepage_welcome_url",        "http://www.redhat.com");
+pref("browser.startup.homepage",            "data:text/plain,browser.startup.homepage=file:///usr/share/doc/HTML/index.html");
+pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
+pref("media.gmp-gmpopenh264.provider.enabled",false);
+pref("media.gmp-gmpopenh264.autoupdate",false);
+pref("media.gmp-gmpopenh264.enabled",false);
+pref("media.gmp-gmpopenh264.enabled",false);
+pref("plugins.notifyMissingFlash", false);
+/* See https://bugzilla.redhat.com/show_bug.cgi?id=1226489 */
+pref("browser.display.use_system_colors", false);
+pref("layers.use-image-offscreen-surfaces", false);
+/* Allow sending credetials to all https:// sites */
+pref("network.negotiate-auth.trusted-uris", "https://");
+pref("security.use_sqldb", false);
+/* Use OS settings for UI language */
+pref("intl.locale.requested", "");
+/* See https://bugzilla.redhat.com/show_bug.cgi?id=1672424 */
+pref("storage.nfs_filesystem", true);
\ No newline at end of file
diff --git a/SOURCES/firefox.1 b/SOURCES/firefox.1
new file mode 100644
index 0000000..4311322
--- /dev/null
+++ b/SOURCES/firefox.1
@@ -0,0 +1,141 @@
+.TH FIREFOX 1 "November 30, 2017" firefox "Linux User's Manual"
+.SH NAME
+firefox \- a Web browser for X11 derived from the Mozilla browser
+
+.SH SYNOPSIS
+.B firefox
+[\fIOPTIONS\fR ...] [\fIURL\fR]
+
+.B firefox-bin
+[\fIOPTIONS\fR] [\fIURL\fR]
+
+.SH DESCRIPTION
+\fBMozilla Firefox\fR is an open-source web browser, designed for
+standards compliance, performance and portability.
+
+.SH USAGE
+\fBfirefox\fR is a simple shell script that will set up the
+environment for the actual executable, \fBfirefox-bin\fR.
+
+.SH OPTIONS
+A summary of the options supported by \fBfirefox\fR is included below.
+
+.SS "X11 options"
+.TP
+.BI \-\-display= DISPLAY
+X display to use
+.TP
+.B \--sync
+Make X calls synchronous
+.TP
+.B \-\-g-fatal-warnings
+Make all warnings fatal
+
+.SS "Firefox options"
+.TP
+.B \-h, \-help
+Show summary of options.
+.TP
+.B \-v, \-version
+Print Firefox version.
+.TP
+\fB\-P\fR \fIprofile\fR
+Start with \fIprofile\fR.
+.TP
+\fB\-\-profile\fR \fIpath\fR
+Start with profile at \fIpath\fR.
+.TP
+\fB\-\-migration\fR
+Start with migration wizard.
+.TP
+.B \-\-ProfileManager
+Start with ProfileManager.
+.TP
+\fB\-\-no\-remote\fR
+Do not accept or send remote commands; implies \fB--new-instance\fR.
+.TP
+\fB\-\-new\-instance\fR
+Open new instance, not a new window in running instance.
+.TP
+\fB\-\-UILocale\fR \fIlocale\fR
+Start with \fIlocale\fR resources as UI Locale.
+.TP
+\fB\-\-save\-mode\fR
+Disables extensions and themes for this session.
+.TP
+\fB\-\-headless\fR
+Run without a GUI.
+.TP
+\fB\-\-marionette\fR
+Enable remote control server.
+.TP
+\fB\-\-browser\fR
+Open a browser window.
+.TP
+\fB\-\-new-window\fR \fIurl\fR
+Open \fIurl\fR in a new window.
+.TP
+\fB\-\-new-tab\fR \fIurl\fR
+Open \fIurl\fR in a new tab.
+.TP
+\fB\-\-private-window\fR \fIurl\fR
+Open \fIurl\fR in a new private window.
+.TP
+\fB\-\-preferences\fR
+Open Preferences dialog.
+.TP
+\fB\-\-screenshot\fR [\fIpath\fR]
+Save screenshot to \fIpath\fR or in working directory.
+.TP
+\fB\-\-window-size\fR \fIwidth\fR[,\fIheight\fR]
+Width and optionally height of screenshot.
+.TP
+\fB\-\-search\fR \fIterm\fR
+Search \fIterm\fR with your default search engine.
+.TP
+
+
+\fB\-\-jsconsole\fR
+Open the Browser Console.
+.TP
+\fB\-\-jsdebugger\fR
+Open the Browser Toolbox.
+.TP
+\fB\-\-wait-for-jsdebugger\fR
+Spin event loop until JS debugger connects.  Enables debugging (some) application startup code paths.  Only has an effect when \fI--jsdebugger\fR is also supplied.
+.TP
+\fB\-\-devtools\fR
+Open DevTools on initial load.
+.TP
+\fB\-\-start-debugger-server\fR [ws:][\fIport\fR|\fIpath\fR]
+Start the debugger server on a TCP port or Unix domain socket path. Defaults to TCP port 6000. Use WebSocket protocol if ws: prefix is specified.
+.TP
+\fB\-\-recording\fR \fIfile\fR
+Record drawing for a given URL.
+.TP
+\fB\-\-recording-output\fR \fIfile\fR
+Specify destination file for a drawing recording.
+.TP
+\fB\-\-setDefaultBrowser\fR
+Set this app as the default browser.
+
+.SH FILES
+\fI/usr/bin/firefox\fR - shell script wrapping
+\fBfirefox\fR
+.br
+\fI/usr/lib64/firefox/firefox-bin\fR - \fBfirefox\fR
+executable
+
+.SH VERSION
+57.0
+
+.SH BUGS
+To report a bug, please visit \fIhttp://bugzilla.mozilla.org/\fR
+
+.SH AUTHORS
+.TP
+.B The Mozilla Organization
+.I http://www.mozilla.org/about.html
+.TP
+.B Tobias Girstmair
+.I https://gir.st/
diff --git a/SOURCES/firefox.desktop b/SOURCES/firefox.desktop
new file mode 100644
index 0000000..f13e600
--- /dev/null
+++ b/SOURCES/firefox.desktop
@@ -0,0 +1,272 @@
+[Desktop Entry]
+Version=1.0
+Name=Firefox
+GenericName=Web Browser
+GenericName[ca]=Navegador web
+GenericName[cs]=Webový prohlížeč
+GenericName[es]=Navegador web
+GenericName[fa]=مرورگر اینترنتی
+GenericName[fi]=WWW-selain
+GenericName[fr]=Navigateur Web
+GenericName[hu]=Webböngésző
+GenericName[it]=Browser Web
+GenericName[ja]=ウェブ・ブラウザ
+GenericName[ko]=웹 브라우저
+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[sk]=Internetový prehliadač
+GenericName[sv]=Webbläsare
+Comment=Browse the Web
+Comment[ca]=Navegueu per el web
+Comment[cs]=Prohlížení stránek World Wide Webu
+Comment[de]=Im Internet surfen
+Comment[es]=Navegue por la web
+Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید
+Comment[fi]=Selaa Internetin WWW-sivuja
+Comment[fr]=Navigue sur Internet
+Comment[hu]=A világháló böngészése
+Comment[it]=Esplora il web
+Comment[ja]=ウェブを閲覧します
+Comment[ko]=웹을 돌아 다닙니다
+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[sk]=Prehliadanie internetu
+Comment[sv]=Surfa på webben
+Exec=firefox %u
+Icon=firefox
+Terminal=false
+Type=Application
+MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https;
+StartupNotify=true
+Categories=Network;WebBrowser;
+Keywords=web;browser;internet;
+Actions=new-window;new-private-window;
+
+[Desktop Action new-window]
+Name=Open a New Window
+Name[ach]=Dirica manyen
+Name[af]=Nuwe venster
+Name[an]=Nueva finestra
+Name[ar]=نافذة جديدة
+Name[as]=নতুন উইন্ডো
+Name[ast]=Ventana nueva
+Name[az]=Yeni Pəncərə
+Name[be]=Новае акно
+Name[bg]=Нов прозорец
+Name[bn-BD]=নতুন উইন্ডো (N)
+Name[bn-IN]=নতুন উইন্ডো
+Name[br]=Prenestr nevez
+Name[brx]=गोदान उइन्ड'(N)
+Name[bs]=Novi prozor
+Name[ca]=Finestra nova
+Name[cak]=K'ak'a' tzuwäch
+Name[cs]=Nové okno
+Name[cy]=Ffenestr Newydd
+Name[da]=Nyt vindue
+Name[de]=Neues Fenster
+Name[dsb]=Nowe wokno
+Name[el]=Νέο παράθυρο
+Name[en-GB]=New Window
+Name[en-US]=New Window
+Name[en-ZA]=New Window
+Name[eo]=Nova fenestro
+Name[es-AR]=Nueva ventana
+Name[es-CL]=Nueva ventana
+Name[es-ES]=Nueva ventana
+Name[es-MX]=Nueva ventana
+Name[et]=Uus aken
+Name[eu]=Leiho berria
+Name[fa]=پنجره جدید‌
+Name[ff]=Henorde Hesere
+Name[fi]=Uusi ikkuna
+Name[fr]=Nouvelle fenêtre
+Name[fy-NL]=Nij finster
+Name[ga-IE]=Fuinneog Nua
+Name[gd]=Uinneag ùr
+Name[gl]=Nova xanela
+Name[gn]=Ovetã pyahu
+Name[gu-IN]=નવી વિન્ડો
+Name[he]=חלון חדש
+Name[hi-IN]=नया विंडो
+Name[hr]=Novi prozor
+Name[hsb]=Nowe wokno
+Name[hu]=Új ablak
+Name[hy-AM]=Նոր Պատուհան
+Name[id]=Jendela Baru
+Name[is]=Nýr gluggi
+Name[it]=Nuova finestra
+Name[ja]=新しいウィンドウ
+Name[ja-JP-mac]=新規ウインドウ
+Name[ka]=ახალი ფანჯარა
+Name[kk]=Жаңа терезе
+Name[km]=បង្អួច​​​ថ្មី
+Name[kn]=ಹೊಸ ಕಿಟಕಿ
+Name[ko]=새 창
+Name[kok]=नवें जनेल
+Name[ks]=نئئ وِنڈو
+Name[lij]=Neuvo barcon
+Name[lo]=ຫນ້າຕ່າງໃຫມ່
+Name[lt]=Naujas langas
+Name[ltg]=Jauns lūgs
+Name[lv]=Jauns logs
+Name[mai]=नव विंडो
+Name[mk]=Нов прозорец
+Name[ml]=പുതിയ ജാലകം
+Name[mr]=नवीन पटल
+Name[ms]=Tetingkap Baru
+Name[my]=ဝင်းဒိုးအသစ်
+Name[nb-NO]=Nytt vindu
+Name[ne-NP]=नयाँ सञ्झ्याल
+Name[nl]=Nieuw venster
+Name[nn-NO]=Nytt vindauge
+Name[or]=ନୂତନ ୱିଣ୍ଡୋ
+Name[pa-IN]=ਨਵੀਂ ਵਿੰਡੋ
+Name[pl]=Nowe okno
+Name[pt-BR]=Nova janela
+Name[pt-PT]=Nova janela
+Name[rm]=Nova fanestra
+Name[ro]=Fereastră nouă
+Name[ru]=Новое окно
+Name[sat]=नावा विंडो (N)
+Name[si]=නව කවුළුවක්
+Name[sk]=Nové okno
+Name[sl]=Novo okno
+Name[son]=Zanfun taaga
+Name[sq]=Dritare e Re
+Name[sr]=Нови прозор
+Name[sv-SE]=Nytt fönster
+Name[ta]=புதிய சாளரம்
+Name[te]=కొత్త విండో
+Name[th]=หน้าต่างใหม่
+Name[tr]=Yeni pencere
+Name[tsz]=Eraatarakua jimpani
+Name[uk]=Нове вікно
+Name[ur]=نیا دریچہ
+Name[uz]=Yangi oyna
+Name[vi]=Cửa sổ mới
+Name[wo]=Palanteer bu bees
+Name[xh]=Ifestile entsha
+Name[zh-CN]=新建窗口
+Name[zh-TW]=開新視窗
+
+
+Exec=firefox %u
+
+[Desktop Action new-private-window]
+Name=Open a New Private Window
+Name[ach]=Dirica manyen me mung
+Name[af]=Nuwe privaatvenster
+Name[an]=Nueva finestra 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[brx]=गोदान प्राइभेट उइन्ड'
+Name[bs]=Novi privatni prozor
+Name[ca]=Finestra privada nova
+Name[cak]=K'ak'a' ichinan tzuwäch
+Name[cs]=Nové anonymní okno
+Name[cy]=Ffenestr Breifat Newydd
+Name[da]=Nyt privat vindue
+Name[de]=Neues privates Fenster
+Name[dsb]=Nowe priwatne wokno
+Name[el]=Νέο παράθυρο ιδιωτικής περιήγησης
+Name[en-GB]=New Private Window
+Name[en-US]=New Private Window
+Name[en-ZA]=New Private Window
+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[fa]=پنجره ناشناس جدید
+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[gn]=Ovetã ñemi pyahu
+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 huliðsgluggi
+Name[it]=Nuova finestra anonima
+Name[ja]=新しいプライベートウィンドウ
+Name[ja-JP-mac]=新規プライベートウインドウ
+Name[ka]=ახალი პირადი ფანჯარა
+Name[kk]=Жаңа жекелік терезе
+Name[km]=បង្អួច​ឯកជន​ថ្មី
+Name[kn]=ಹೊಸ ಖಾಸಗಿ ಕಿಟಕಿ
+Name[ko]=새 사생활 보호 모드
+Name[kok]=नवो खाजगी विंडो
+Name[ks]=نْو پرایوٹ وینڈو&amp;
+Name[lij]=Neuvo barcon privou
+Name[lo]=ເປີດຫນ້າຕ່າງສວນຕົວຂື້ນມາໃຫມ່
+Name[lt]=Naujas privataus naršymo langas
+Name[ltg]=Jauns privatais lūgs
+Name[lv]=Jauns privātais logs
+Name[mai]=नया निज विंडो (W)
+Name[mk]=Нов приватен прозорец
+Name[ml]=പുതിയ സ്വകാര്യ ജാലകം
+Name[mr]=नवीन वैयक्तिक पटल
+Name[ms]=Tetingkap Persendirian Baharu
+Name[my]=New Private Window
+Name[nb-NO]=Nytt privat vindu
+Name[ne-NP]=नयाँ निजी सञ्झ्याल
+Name[nl]=Nieuw privévenster
+Name[nn-NO]=Nytt privat vindauge
+Name[or]=ନୂତନ ବ୍ୟକ୍ତିଗତ ୱିଣ୍ଡୋ
+Name[pa-IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ
+Name[pl]=Nowe okno prywatne
+Name[pt-BR]=Nova janela privativa
+Name[pt-PT]=Nova janela privada
+Name[rm]=Nova fanestra privata
+Name[ro]=Fereastră privată nouă
+Name[ru]=Новое приватное окно
+Name[sat]=नावा निजेराक् विंडो (W )
+Name[si]=නව පුද්ගලික කවුළුව (W)
+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[tsz]=Juchiiti eraatarakua jimpani
+Name[uk]=Приватне вікно
+Name[ur]=نیا نجی دریچہ
+Name[uz]=Yangi maxfiy oyna
+Name[vi]=Cửa sổ riêng tư mới
+Name[wo]=Panlanteeru biir bu bees
+Name[xh]=Ifestile yangasese entsha
+Name[zh-CN]=新建隐私浏览窗口
+Name[zh-TW]=新增隱私視窗
+Exec=firefox --private-window %u
+
diff --git a/SOURCES/firefox.sh.in b/SOURCES/firefox.sh.in
new file mode 100644
index 0000000..0e5214e
--- /dev/null
+++ b/SOURCES/firefox.sh.in
@@ -0,0 +1,277 @@
+#!/bin/bash
+#
+# The contents of this file are subject to the Netscape Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation.  Portions created by Netscape are
+# Copyright (C) 1998 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s): 
+#
+
+## 
+## Usage:
+##
+## $ firefox
+##
+## This script is meant to run a mozilla program from the mozilla
+## rpm installation.
+##
+## The script will setup all the environment voodoo needed to make
+## mozilla work.
+
+cmdname=`basename $0`
+
+##
+## Variables
+##
+MOZ_ARCH=$(uname -m)
+case $MOZ_ARCH in
+	x86_64 | s390x | sparc64)
+		MOZ_LIB_DIR="/usr/lib64"
+		SECONDARY_LIB_DIR="/usr/lib"
+		;;
+	* )
+		MOZ_LIB_DIR="/usr/lib"
+		SECONDARY_LIB_DIR="/usr/lib64"
+		;;
+esac
+
+MOZ_FIREFOX_FILE="firefox"
+
+if [ ! -r $MOZ_LIB_DIR/firefox/$MOZ_FIREFOX_FILE ]; then
+    if [ ! -r $SECONDARY_LIB_DIR/firefox/$MOZ_FIREFOX_FILE ]; then
+	echo "Error: $MOZ_LIB_DIR/firefox/$MOZ_FIREFOX_FILE not found"
+	if [ -d $SECONDARY_LIB_DIR ]; then
+	    echo "       $SECONDARY_LIB_DIR/firefox/$MOZ_FIREFOX_FILE not found"
+	fi
+	exit 1
+    fi
+    MOZ_LIB_DIR="$SECONDARY_LIB_DIR"
+fi
+MOZ_DIST_BIN="$MOZ_LIB_DIR/firefox"
+MOZ_LANGPACKS_DIR="$MOZ_DIST_BIN/langpacks"
+MOZ_EXTENSIONS_PROFILE_DIR="$HOME/.mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
+MOZ_PROGRAM="$MOZ_DIST_BIN/$MOZ_FIREFOX_FILE"
+MOZ_LAUNCHER="$MOZ_DIST_BIN/run-mozilla.sh"
+
+##
+## Set MOZ_GRE_CONF
+##
+MOZ_GRE_CONF=/etc/gre.d/gre.conf
+if [ "$MOZ_LIB_DIR" == "/usr/lib64" ]; then
+  MOZ_GRE_CONF=/etc/gre.d/gre64.conf
+fi
+export MOZ_GRE_CONF
+
+##
+## Set MOZILLA_FIVE_HOME
+##
+MOZILLA_FIVE_HOME="$MOZ_DIST_BIN"
+
+export MOZILLA_FIVE_HOME
+
+##
+## Make sure that we set the plugin path
+##
+MOZ_PLUGIN_DIR="plugins"
+
+if [ "$MOZ_PLUGIN_PATH" ]
+then
+  MOZ_PLUGIN_PATH=$MOZ_PLUGIN_PATH:$MOZ_LIB_DIR/mozilla/$MOZ_PLUGIN_DIR:$MOZ_DIST_BIN/$MOZ_PLUGIN_DIR
+else
+  MOZ_PLUGIN_PATH=$MOZ_LIB_DIR/mozilla/$MOZ_PLUGIN_DIR:$MOZ_DIST_BIN/$MOZ_PLUGIN_DIR
+fi
+export MOZ_PLUGIN_PATH
+
+##
+## Set MOZ_APP_LAUNCHER for gnome-session
+##
+export MOZ_APP_LAUNCHER="/usr/bin/firefox"
+
+##
+## Set FONTCONFIG_PATH for Xft/fontconfig
+##
+FONTCONFIG_PATH="/etc/fonts:${MOZILLA_FIVE_HOME}/res/Xft"
+export FONTCONFIG_PATH
+
+##
+## In order to better support certain scripts (such as Indic and some CJK 
+## scripts), Fedora builds its Firefox, with permission from the Mozilla 
+## Corporation, with the Pango system as its text renderer.  This change 
+## may negatively impact performance on some pages.  To disable the use of
+## Pango, set MOZ_DISABLE_PANGO=1 in your environment before launching
+## Firefox.
+##
+#
+# MOZ_DISABLE_PANGO=1
+# export MOZ_DISABLE_PANGO
+#
+
+##
+## Disable the GNOME crash dialog, Moz has it's own
+##
+GNOME_DISABLE_CRASH_DIALOG=1
+export GNOME_DISABLE_CRASH_DIALOG
+
+##
+## Disable the SLICE allocator (rhbz#1014858)
+##
+export G_SLICE=always-malloc
+
+##
+## Enable Xinput2 (mozbz#1207973)
+##
+export MOZ_USE_XINPUT2=1
+
+# OK, here's where all the real work gets done
+
+
+##
+## To disable the use of Firefox localization, set MOZ_DISABLE_LANGPACKS=1
+## in your environment before launching Firefox.
+##
+#
+# MOZ_DISABLE_LANGPACKS=1
+# export MOZ_DISABLE_LANGPACKS
+#
+
+##
+## Automatically installed langpacks are tracked by .fedora-langpack-install
+## config file.
+##
+FEDORA_LANGPACK_CONFIG="$MOZ_EXTENSIONS_PROFILE_DIR/.fedora-langpack-install"
+
+# Since Firefox 60 the installation of individual langpack cannot be done by
+# copying xpi file to the home directory, because the langpack is loaded
+# as to the available languages after the language has been decided and
+# for the first run it won't be in language according to the locale.
+#
+# The current workaround is to put all langpacks to the location
+# for system wide extensions. So we set MOZ_DISABLE_LANGPACKS=1 for this moment
+export MOZ_DISABLE_LANGPACKS=1
+# MOZ_DISABLE_LANGPACKS disables language packs completely
+MOZILLA_DOWN=0
+if ! [ $MOZ_DISABLE_LANGPACKS ] || [ $MOZ_DISABLE_LANGPACKS -eq 0 ]; then
+    if [ -x $MOZ_DIST_BIN/$MOZ_FIREFOX_FILE ]; then
+        # Is firefox running?
+        /usr/bin/pidof firefox > /dev/null 2>&1
+        MOZILLA_DOWN=$?
+    fi
+fi
+
+# Modify language pack configuration only when firefox is not running 
+# and language packs are not disabled
+if [ $MOZILLA_DOWN -ne 0 ]; then
+
+    # Clear already installed langpacks
+    mkdir -p $MOZ_EXTENSIONS_PROFILE_DIR
+    if [ -f $FEDORA_LANGPACK_CONFIG ]; then
+        rm `cat $FEDORA_LANGPACK_CONFIG` > /dev/null 2>&1
+        rm $FEDORA_LANGPACK_CONFIG > /dev/null 2>&1
+        # remove all empty langpacks dirs while they block installation of langpacks
+        rmdir $MOZ_EXTENSIONS_PROFILE_DIR/langpack* > /dev/null 2>&1
+    fi
+
+    # Get locale from system
+    CURRENT_LOCALE=$LC_ALL
+    CURRENT_LOCALE=${CURRENT_LOCALE:-$LC_MESSAGES}
+    CURRENT_LOCALE=${CURRENT_LOCALE:-$LANG}
+
+    # Try with a local variant first, then without a local variant
+    SHORTMOZLOCALE=`echo $CURRENT_LOCALE | sed "s|_\([^.]*\).*||g"`
+    MOZLOCALE=`echo $CURRENT_LOCALE | sed "s|_\([^.]*\).*|-\1|g"`
+
+    function create_langpack_link() {
+        local language=$*
+        local langpack=langpack-${language}@firefox.mozilla.org.xpi
+        if [ -f $MOZ_LANGPACKS_DIR/$langpack ]; then
+            rm -rf $MOZ_EXTENSIONS_PROFILE_DIR/$langpack
+            # If the target file is a symlink (the fallback langpack), 
+            # install the original file instead of the fallback one
+            if [ -h $MOZ_LANGPACKS_DIR/$langpack ]; then
+                langpack=`readlink $MOZ_LANGPACKS_DIR/$langpack`
+            fi
+            ln -s $MOZ_LANGPACKS_DIR/$langpack \
+                  $MOZ_EXTENSIONS_PROFILE_DIR/$langpack
+            echo $MOZ_EXTENSIONS_PROFILE_DIR/$langpack > $FEDORA_LANGPACK_CONFIG
+            return 0
+        fi
+        return 1
+    }
+
+    create_langpack_link $MOZLOCALE || create_langpack_link $SHORTMOZLOCALE || true
+fi
+
+# BEAST fix (rhbz#1005611)
+NSS_SSL_CBC_RANDOM_IV=${NSS_SSL_CBC_RANDOM_IV-1}
+export NSS_SSL_CBC_RANDOM_IV
+
+# Prepare command line arguments
+script_args=""
+pass_arg_count=0
+while [ $# -gt $pass_arg_count ]
+do
+  case "$1" in
+    -g | --debug)
+      script_args="$script_args -g"
+      debugging=1
+      shift
+      ;;
+    -d | --debugger)
+      if [ $# -gt 1 ]; then
+        script_args="$script_args -d $2"
+        shift 2
+      else
+        shift
+      fi
+      ;;
+    *)
+      # Move the unrecognized argument to the end of the list.
+      arg="$1"
+      shift
+      set -- "$@" "$arg"
+      pass_arg_count=`expr $pass_arg_count + 1`
+      ;;
+  esac
+done
+
+# Linux version specific environment variables
+%RHEL_ENV_VARS%
+
+# Make sure at-spi-bus is running
+if ! dbus-send --session            \
+     --dest=org.freedesktop.DBus    \
+     --type=method_call             \
+     --print-reply                  \
+     /org/freedesktop/DBus          \
+     org.freedesktop.DBus.ListNames \
+     | grep org.a11y.Bus > /dev/null; then
+    if [ -f "$MOZ_LIB_DIR/firefox/bundled/libexec/at-spi-bus-launcher" ]; then
+        echo "Starting a11y dbus service..."
+        $MOZ_LIB_DIR/firefox/bundled/libexec/at-spi-bus-launcher &
+    else
+        echo "Running without a11y support!"
+    fi
+fi
+
+# Run the browser
+debugging=0
+if [ $debugging = 1 ]
+then
+  echo $MOZ_LAUNCHER $script_args $MOZ_PROGRAM "$@"
+fi
+
+
+exec $MOZ_LAUNCHER $script_args $MOZ_PROGRAM "$@"
diff --git a/SOURCES/google-api-key b/SOURCES/google-api-key
new file mode 100644
index 0000000..b95d189
--- /dev/null
+++ b/SOURCES/google-api-key
@@ -0,0 +1 @@
+AIzaSyBPGXa4AYD4FC3HJK7LnIKxm4fDusVuuco
diff --git a/SOURCES/gtk3-private-3.22.26-1-files.inc b/SOURCES/gtk3-private-3.22.26-1-files.inc
new file mode 100644
index 0000000..cf89c66
--- /dev/null
+++ b/SOURCES/gtk3-private-3.22.26-1-files.inc
@@ -0,0 +1,53 @@
+%dir %{gtk3_install_path}/bin
+%{gtk3_install_path}/bin/gdk-pixbuf-query-loaders-%{__isa_bits}
+%{gtk3_install_path}/bin/gdk-pixbuf-thumbnailer
+%{gtk3_install_path}/bin/gio-querymodules-%{__isa_bits}
+%{gtk3_install_path}/bin/glib-compile-schemas
+%{gtk3_install_path}/bin/gtk-query-immodules-3.0-%{__isa_bits}
+%{gtk3_install_path}/bin/gtk-update-icon-cache
+%{gtk3_install_path}/bin/fc-cache
+
+%{gtk3_install_path}/etc
+
+%dir %{gtk3_install_path}/%{_lib}
+%{gtk3_install_path}/%{_lib}/libatk-1.0.so.*
+%{gtk3_install_path}/%{_lib}/libatk-bridge-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libatspi.so.*
+%{gtk3_install_path}/%{_lib}/libcairo.so.*
+%{gtk3_install_path}/%{_lib}/libcairo-gobject.so.*
+%{gtk3_install_path}/%{_lib}/libfontconfig.so.*
+%{gtk3_install_path}/%{_lib}/libfreetype.so.*
+%{gtk3_install_path}/%{_lib}/libgdk-3.so.*
+%{gtk3_install_path}/%{_lib}/libgdk_pixbuf-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libgio-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libglib-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libgmodule-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libgobject-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libgthread-2.0.so.*
+%{gtk3_install_path}/%{_lib}/libgtk-3.so.*
+%{gtk3_install_path}/%{_lib}/libharfbuzz.so.*
+%{gtk3_install_path}/%{_lib}/libpango-1.0.so.*
+%{gtk3_install_path}/%{_lib}/libpangocairo-1.0.so.*
+%{gtk3_install_path}/%{_lib}/libpangoft2-1.0.so.*
+%{gtk3_install_path}/%{_lib}/libpcre.so.*
+%{gtk3_install_path}/%{_lib}/librsvg-2.so.*
+%dir %{gtk3_install_path}/%{_lib}/cairo
+%{gtk3_install_path}/%{_lib}/cairo/cairo-fdr.so.*
+%{gtk3_install_path}/%{_lib}/cairo/cairo-sphinx.so.*
+%{gtk3_install_path}/%{_lib}/cairo/libcairo-trace.so.*
+%{gtk3_install_path}/%{_lib}/gdk-pixbuf-2.0
+%ghost %attr(644, root, root) %{gtk3_install_path}/%{_lib}/gdk-pixbuf-2.0/2.10.0/loaders.cache
+%{gtk3_install_path}/%{_lib}/gio
+%ghost %attr(644, root, root) %{gtk3_install_path}/%{_lib}/gio/modules/giomodule.cache
+%{gtk3_install_path}/%{_lib}/gtk-3.0
+
+%{gtk3_install_path}/libexec
+
+%{gtk3_install_path}/share
+%ghost %attr(644, root, root) %{gtk3_install_path}/share/icons/Adwaita/icon-theme.cache
+%ghost %attr(644, root, root) %{gtk3_install_path}/share/icons/hicolor/icon-theme.cache
+%ghost %attr(644, root, root) %{gtk3_install_path}/share/glib-2.0/schemas/gschemas.compiled
+
+%{gtk3_install_path}/var
+%dir %{gtk3_install_path}/var/cache/fontconfig
+
diff --git a/SOURCES/gtk3-private-3.22.26-1-post.inc b/SOURCES/gtk3-private-3.22.26-1-post.inc
new file mode 100644
index 0000000..04acf06
--- /dev/null
+++ b/SOURCES/gtk3-private-3.22.26-1-post.inc
@@ -0,0 +1,23 @@
+# adwaita-icon-theme
+touch --no-create %{gtk3_install_path}/share/icons/Adwaita &>/dev/null || :
+touch --no-create %{gtk3_install_path}/share/icons/hicolor &>/dev/null || :
+%{gtk3_install_path}/bin/gdk-pixbuf-query-loaders-%{__isa_bits} --update-cache || :
+
+# glib2
+%{gtk3_install_path}/bin/gio-querymodules-%{__isa_bits} %{gtk3_install_path}/%{_lib}/gio/modules
+
+# gtk3
+%{gtk3_install_path}/bin/gtk-query-immodules-3.0-%{__isa_bits} --update-cache
+%{gtk3_install_path}/bin/glib-compile-schemas %{gtk3_install_path}/share/glib-2.0/schemas &> /dev/null || :
+
+# fontconfig
+umask 0022
+
+# Force regeneration of all fontconfig cache files
+# The check for existance is needed on dual-arch installs (the second
+#  copy of fontconfig might install the binary instead of the first)
+# The HOME setting is to avoid problems if HOME hasn't been reset
+# FIXME hardcoded version !
+if [ -x %{gtk3_install_path}/bin/fc-cache ] && %{gtk3_install_path}/bin/fc-cache --version 2>&1 | grep -q 2.10.95 ; then
+  HOME=/root %{gtk3_install_path}/bin/fc-cache -f
+fi
diff --git a/SOURCES/gtk3-private-3.22.26-1-posttrans.inc b/SOURCES/gtk3-private-3.22.26-1-posttrans.inc
new file mode 100644
index 0000000..8c5f2d7
--- /dev/null
+++ b/SOURCES/gtk3-private-3.22.26-1-posttrans.inc
@@ -0,0 +1,3 @@
+%{gtk3_install_path}/gtk-update-icon-cache %{gtk3_install_path}/share/icons/hicolor &>/dev/null || :
+# adwaita
+%{gtk3_install_path}/gtk-update-icon-cache %{gtk3_install_path}/share/icons/Adwaita &>/dev/null || :
diff --git a/SOURCES/gtk3-private-3.22.26-1-postun.inc b/SOURCES/gtk3-private-3.22.26-1-postun.inc
new file mode 100644
index 0000000..3b5df73
--- /dev/null
+++ b/SOURCES/gtk3-private-3.22.26-1-postun.inc
@@ -0,0 +1,27 @@
+# adwaita
+if [ $1 -eq 0 ] ; then
+    touch --no-create %{gtk3_install_path}/share/icons/Adwaita &>/dev/null
+    touch --no-create %{gtk3_install_path}/share/icons/hicolor &>/dev/null
+    %{gtk3_install_path}/bin/gtk-update-icon-cache %{gtk3_install_path}/share/icons/Adwaita &>/dev/null || :
+    %{gtk3_install_path}/bin/gtk-update-icon-cache %{gtk3_install_path}/share/icons/hicolor &>/dev/null || :
+fi
+
+# gdk-pixbuf2
+if [ $1 -gt 0 ]; then
+  %{gtk3_install_path}/bin/gdk-pixbuf-query-loaders-%{__isa_bits} --update-cache || :
+fi
+
+# glib2
+[ ! -x %{gtk3_install_path}/bin/gio-querymodules-%{__isa_bits} ] || \
+%{gtk3_install_path}/bin/gio-querymodules-%{__isa_bits} %{gtk3_install_path}/%{_lib}/gio/modules
+
+# gtk3
+if [ $1 -gt 0 ]; then
+  %{gtk3_install_path}/bin/gtk-query-immodules-3.0-%{__isa_bits} --update-cache
+fi
+
+if [ $1 -eq 0 ] ; then
+    rm -rf %{gtk3_install_path}/var/cache/fontconfig/* &>/dev/null || :
+fi
+
+%{gtk3_install_path}/bin/glib-compile-schemas %{gtk3_install_path}/share/glib-2.0/schemas &> /dev/null || :
diff --git a/SOURCES/gtk3-private-3.22.26-1-requires-provides-filter.inc b/SOURCES/gtk3-private-3.22.26-1-requires-provides-filter.inc
new file mode 100644
index 0000000..f5fa495
--- /dev/null
+++ b/SOURCES/gtk3-private-3.22.26-1-requires-provides-filter.inc
@@ -0,0 +1,26 @@
+%filter_provides_in %{gtk3_install_path}/%{_lib}
+%filter_requires_in %{gtk3_install_path}/%{_lib}
+
+%filter_from_requires /libgdk-3.*/d
+%filter_from_requires /libatk-1.0.so.*/d
+%filter_from_requires /libatk-bridge-2.0.so.*/d
+%filter_from_requires /libatspi.so.*/d
+%filter_from_requires /libcairo.so.*/d
+%filter_from_requires /libcairo-gobject.so.*/d
+%filter_from_requires /libfontconfig.so.*/d
+%filter_from_requires /libfreetype.so.*/d
+%filter_from_requires /libgdk-3.so.*/d
+%filter_from_requires /libgdk_pixbuf-2.0.so.*/d
+%filter_from_requires /libgio-2.0.so.*/d
+%filter_from_requires /libglib-2.0.so.*/d
+%filter_from_requires /libgmodule-2.0.so.*/d
+%filter_from_requires /libgobject-2.0.so.*/d
+%filter_from_requires /libgthread-2.0.so.*/d
+%filter_from_requires /libgtk-3.so.*/d
+%filter_from_requires /libharfbuzz.so.*/d
+%filter_from_requires /libpango-1.0.so.*/d
+%filter_from_requires /libpangocairo-1.0.so.*/d
+%filter_from_requires /libpangoft2-1.0.so.*/d
+%filter_from_requires /libpcre.so.*/d
+
+# Don't forget to call %%filter_setup from the consumer!
diff --git a/SOURCES/gtk3-private-3.22.26-1-setup-flags-env.inc b/SOURCES/gtk3-private-3.22.26-1-setup-flags-env.inc
new file mode 100644
index 0000000..eb54164
--- /dev/null
+++ b/SOURCES/gtk3-private-3.22.26-1-setup-flags-env.inc
@@ -0,0 +1,34 @@
+%if "%{name}" == "gtk3-private"
+    function prepend_buildroot_include_path_to_compiler_flags() {
+        export CFLAGS="-I%{_buildrootdir}%{gtk3_install_path}/$@ $CFLAGS" \
+        export CXXFLAGS="-I%{_buildrootdir}%{gtk3_install_path}/$@ $CXXFLAGS"
+    }
+    
+    prepend_buildroot_include_path_to_compiler_flags include
+    prepend_buildroot_include_path_to_compiler_flags include/glib-2.0
+    prepend_buildroot_include_path_to_compiler_flags include/glib-2.0
+    prepend_buildroot_include_path_to_compiler_flags include/gio-unix-2.0
+    prepend_buildroot_include_path_to_compiler_flags %{_lib}/glib-2.0/include
+    prepend_buildroot_include_path_to_compiler_flags include/freetype2
+    prepend_buildroot_include_path_to_compiler_flags include/fontconfig
+    prepend_buildroot_include_path_to_compiler_flags include/harfbuzz
+    prepend_buildroot_include_path_to_compiler_flags include/gdk-pixbuf-2.0
+    prepend_buildroot_include_path_to_compiler_flags include/atk-1.0
+    prepend_buildroot_include_path_to_compiler_flags include/at-spi-2.0
+    prepend_buildroot_include_path_to_compiler_flags include/at-spi2-atk/2.0
+    prepend_buildroot_include_path_to_compiler_flags include/cairo
+    prepend_buildroot_include_path_to_compiler_flags include/pango-1.0
+    prepend_buildroot_include_path_to_compiler_flags include/librsvg-2.0
+    prepend_buildroot_include_path_to_compiler_flags include/cairo
+    prepend_buildroot_include_path_to_compiler_flags include/gtk-3.0
+    prepend_buildroot_include_path_to_compiler_flags include/gtk-3.0/unix-print
+    prepend_buildroot_include_path_to_compiler_flags include/librsvg-2.0
+%else
+    sed -i 's@%{gtk3_install_path}@%{_buildrootdir}%{gtk3_install_path}@g' %{_buildrootdir}%{gtk3_install_path}/%{_lib}/pkgconfig/*.pc
+%endif
+
+export LDFLAGS="-L%{_buildrootdir}%{gtk3_install_path}/%{_lib} $LDFLAGS"
+export LDFLAGS="-Wl,-rpath,%{gtk3_install_path}/%{_lib} $LDFLAGS"
+export LDFLAGS="-Wl,-rpath-link,%{_buildrootdir}%{gtk3_install_path}/%{_lib} $LDFLAGS"
+
+export PKG_CONFIG_PATH=%{_buildrootdir}%{gtk3_install_path}/%{_lib}/pkgconfig
diff --git a/SOURCES/mozilla-1005640-accept-lang.patch b/SOURCES/mozilla-1005640-accept-lang.patch
new file mode 100644
index 0000000..29d3833
--- /dev/null
+++ b/SOURCES/mozilla-1005640-accept-lang.patch
@@ -0,0 +1,30 @@
+diff -up firefox-51.0/toolkit/mozapps/extensions/internal/XPIProvider.jsm.1005640-accept-lang firefox-51.0/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+--- firefox-51.0/toolkit/mozapps/extensions/internal/XPIProvider.jsm.1005640-accept-lang	2017-01-16 17:16:52.000000000 +0100
++++ firefox-51.0/toolkit/mozapps/extensions/internal/XPIProvider.jsm	2017-01-18 12:35:29.380394216 +0100
+@@ -2852,6 +2852,11 @@ this.XPIProvider = {
+         this.addAddonsToCrashReporter();
+       }
+ 
++      // Save locale settings to compare it later to check whenever some addon
++      // changed it.
++      var previousLocale = Cc["@mozilla.org/chrome/chrome-registry;1"]
++                          .getService(Ci.nsIXULChromeRegistry).getSelectedLocale("global");
++
+       try {
+         AddonManagerPrivate.recordTimestamp("XPI_bootstrap_addons_begin");
+ 
+@@ -2880,6 +2885,14 @@ this.XPIProvider = {
+         AddonManagerPrivate.recordException("XPI-BOOTSTRAP", "startup failed", e);
+       }
+ 
++      var currentLocale = Cc["@mozilla.org/chrome/chrome-registry;1"]
++                         .getService(Ci.nsIXULChromeRegistry).getSelectedLocale("global");
++      if (currentLocale != previousLocale) {
++        // We have to flush string cache if the locale was changed during loading
++        // of addons
++        Services.obs.notifyObservers(null, "chrome-flush-caches", null);
++      }
++
+       // Let these shutdown a little earlier when they still have access to most
+       // of XPCOM
+       Services.obs.addObserver({
diff --git a/SOURCES/mozilla-1170092.patch b/SOURCES/mozilla-1170092.patch
new file mode 100644
index 0000000..b182d64
--- /dev/null
+++ b/SOURCES/mozilla-1170092.patch
@@ -0,0 +1,98 @@
+diff -up firefox-60.5.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092 firefox-60.5.0/extensions/pref/autoconfig/src/nsReadConfig.cpp
+--- firefox-60.5.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092	2019-01-22 10:48:38.187383614 +0100
++++ firefox-60.5.0/extensions/pref/autoconfig/src/nsReadConfig.cpp	2019-01-22 11:26:11.027108692 +0100
+@@ -225,8 +225,20 @@ nsresult nsReadConfig::openAndEvaluateJS
+     if (NS_FAILED(rv)) return rv;
+ 
+     rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile);
+-    if (NS_FAILED(rv)) return rv;
++    if (NS_FAILED(rv)) {
++      // Look for cfg file in /etc/<application>/pref
++      rv = NS_GetSpecialDirectory(NS_APP_PREFS_SYSTEM_CONFIG_DIR,
++                                  getter_AddRefs(jsFile));
++      NS_ENSURE_SUCCESS(rv, rv);
++
++      rv = jsFile->AppendNative(NS_LITERAL_CSTRING("pref"));
++      NS_ENSURE_SUCCESS(rv, rv);
++      rv = jsFile->AppendNative(nsDependentCString(aFileName));
++      NS_ENSURE_SUCCESS(rv, rv);
+ 
++      rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile);
++      NS_ENSURE_SUCCESS(rv, rv);
++    }
+   } else {
+     nsAutoCString location("resource://gre/defaults/autoconfig/");
+     location += aFileName;
+diff -up firefox-60.5.0/modules/libpref/Preferences.cpp.1170092 firefox-60.5.0/modules/libpref/Preferences.cpp
+--- firefox-60.5.0/modules/libpref/Preferences.cpp.1170092	2019-01-21 17:38:16.000000000 +0100
++++ firefox-60.5.0/modules/libpref/Preferences.cpp	2019-01-22 10:48:38.187383614 +0100
+@@ -3459,6 +3459,8 @@ static nsresult pref_ReadPrefFromJar(nsZ
+   //
+   // Thus, in the omni.jar case, we always load app-specific default
+   // preferences from omni.jar, whether or not `$app == $gre`.
++  // At very end load configuration from system config location:
++  // - /etc/firefox/pref/*.js
+ 
+   nsresult rv;
+   nsZipFind* findPtr;
+diff -up firefox-60.5.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-60.5.0/toolkit/xre/nsXREDirProvider.cpp
+--- firefox-60.5.0/toolkit/xre/nsXREDirProvider.cpp.1170092	2019-01-21 17:38:51.000000000 +0100
++++ firefox-60.5.0/toolkit/xre/nsXREDirProvider.cpp	2019-01-22 11:37:01.868896974 +0100
+@@ -58,6 +58,7 @@
+ #endif
+ #ifdef XP_UNIX
+ #include <ctype.h>
++#include "nsIXULAppInfo.h"
+ #endif
+ #ifdef XP_IOS
+ #include "UIKitDirProvider.h"
+@@ -491,6 +492,21 @@ nsXREDirProvider::GetFile(const char* aP
+       }
+     }
+   }
++
++#if defined(XP_UNIX)
++  if (!strcmp(aProperty, NS_APP_PREFS_SYSTEM_CONFIG_DIR)) {
++    nsCString sysConfigDir = NS_LITERAL_CSTRING("/etc/");
++    nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
++    if (!appInfo)
++      return NS_ERROR_NOT_AVAILABLE;
++    nsCString appName;
++    appInfo->GetName(appName);
++    ToLowerCase(appName);
++    sysConfigDir.Append(appName);
++    return NS_NewNativeLocalFile(sysConfigDir, false, aFile);
++  }
++#endif
++
+   if (NS_FAILED(rv) || !file) return NS_ERROR_FAILURE;
+ 
+   if (ensureFilePermissions) {
+@@ -796,6 +812,16 @@ nsresult nsXREDirProvider::GetFilesInter
+     LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
+     LoadDirsIntoArray(mAppBundleDirectories, kAppendPrefDir, directories);
+ 
++    // Add /etc/<application>/pref/ directory if it exists
++    nsCOMPtr<nsIFile> systemPrefDir;
++    rv = NS_GetSpecialDirectory(NS_APP_PREFS_SYSTEM_CONFIG_DIR,
++                                getter_AddRefs(systemPrefDir));
++    if (NS_SUCCEEDED(rv)) {
++      rv = systemPrefDir->AppendNative(NS_LITERAL_CSTRING("pref"));
++      if (NS_SUCCEEDED(rv))
++        directories.AppendObject(systemPrefDir);
++    }
++
+     rv = NS_NewArrayEnumerator(aResult, directories);
+   } else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) {
+     // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons
+diff -up firefox-60.5.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092 firefox-60.5.0/xpcom/io/nsAppDirectoryServiceDefs.h
+--- firefox-60.5.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092	2019-01-22 10:48:38.188383609 +0100
++++ firefox-60.5.0/xpcom/io/nsAppDirectoryServiceDefs.h	2019-01-22 11:08:12.068459480 +0100
+@@ -62,6 +62,7 @@
+ #define NS_APP_PREFS_DEFAULTS_DIR_LIST "PrefDL"
+ #define NS_APP_PREFS_OVERRIDE_DIR \
+   "PrefDOverride"  // Directory for per-profile defaults
++#define NS_APP_PREFS_SYSTEM_CONFIG_DIR          "PrefSysConf"   // Directory with system-wide configuration
+ 
+ #define NS_APP_USER_PROFILE_50_DIR "ProfD"
+ #define NS_APP_USER_PROFILE_LOCAL_50_DIR "ProfLD"
diff --git a/SOURCES/mozilla-1196777.patch b/SOURCES/mozilla-1196777.patch
new file mode 100644
index 0000000..c28cf94
--- /dev/null
+++ b/SOURCES/mozilla-1196777.patch
@@ -0,0 +1,13 @@
+diff -up firefox-60.5.0/widget/gtk/nsWindow.cpp.1196777 firefox-60.5.0/widget/gtk/nsWindow.cpp
+--- firefox-60.5.0/widget/gtk/nsWindow.cpp.1196777	2019-01-22 11:41:58.630469400 +0100
++++ firefox-60.5.0/widget/gtk/nsWindow.cpp	2019-01-22 11:42:50.134227448 +0100
+@@ -152,7 +152,8 @@ const gint kEvents =
+ #if GTK_CHECK_VERSION(3, 4, 0)
+     GDK_SMOOTH_SCROLL_MASK | GDK_TOUCH_MASK |
+ #endif
+-    GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK;
++    GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK |
++    GDK_FOCUS_CHANGE_MASK;
+ 
+ /* utility functions */
+ static bool is_mouse_in_window(GdkWindow *aWindow, gdouble aMouseX,
diff --git a/SOURCES/mozilla-1353817.patch b/SOURCES/mozilla-1353817.patch
new file mode 100644
index 0000000..dc8d8f8
--- /dev/null
+++ b/SOURCES/mozilla-1353817.patch
@@ -0,0 +1,27 @@
+From 1cc652f5525f458b0b4ceb12af24bf5a4367db32 Mon Sep 17 00:00:00 2001
+From: Nicolas Dufresne <nicolas.dufresne@collabora.com>
+Date: Tue, 23 May 2017 13:09:48 -0400
+Subject: [PATCH] Bug 1353817: Include SkNx_neon.h for ARM64 too
+
+This fixes build errors as arm_neon.h was missing along with some
+missing converters.
+---
+ gfx/skia/skia/src/core/SkNx.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/gfx/skia/skia/src/core/SkNx.h b/gfx/skia/skia/src/core/SkNx.h
+index 6bca856..b0427aa 100644
+--- a/gfx/skia/skia/src/core/SkNx.h
++++ b/gfx/skia/skia/src/core/SkNx.h
+@@ -299,7 +299,7 @@ typedef SkNx<4, uint32_t> Sk4u;
+ // Include platform specific specializations if available.
+ #if !defined(SKNX_NO_SIMD) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
+     #include "../opts/SkNx_sse.h"
+-#elif !defined(SKNX_NO_SIMD) && defined(SK_ARM_HAS_NEON)
++#elif !defined(SKNX_NO_SIMD) && (defined(SK_ARM_HAS_NEON) || defined(SK_CPU_ARM64))
+     #include "../opts/SkNx_neon.h"
+ #else
+ 
+-- 
+2.9.4
+
diff --git a/SOURCES/mozilla-1436242.patch b/SOURCES/mozilla-1436242.patch
new file mode 100644
index 0000000..570b7c5
--- /dev/null
+++ b/SOURCES/mozilla-1436242.patch
@@ -0,0 +1,56 @@
+
+# HG changeset patch
+# User Jed Davis <jld@mozilla.com>
+# Date 1526943705 21600
+# Node ID 6bb3adfa15c6877f7874429462dad88f8c978c4f
+# Parent  4c71c8454879c841871ecf3afb7dbdc96bad97fc
+Bug 1436242 - Avoid undefined behavior in IPC fd-passing code.  r=froydnj
+
+MozReview-Commit-ID: 3szIPUssgF5
+
+diff --git a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+--- a/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
++++ b/ipc/chromium/src/chrome/common/ipc_channel_posix.cc
+@@ -418,20 +418,37 @@ bool Channel::ChannelImpl::ProcessIncomi
+     const int* fds;
+     unsigned num_fds;
+     unsigned fds_i = 0;  // the index of the first unused descriptor
+ 
+     if (input_overflow_fds_.empty()) {
+       fds = wire_fds;
+       num_fds = num_wire_fds;
+     } else {
+-      const size_t prev_size = input_overflow_fds_.size();
+-      input_overflow_fds_.resize(prev_size + num_wire_fds);
+-      memcpy(&input_overflow_fds_[prev_size], wire_fds,
+-             num_wire_fds * sizeof(int));
++      // This code may look like a no-op in the case where
++      // num_wire_fds == 0, but in fact:
++      //
++      // 1. wire_fds will be nullptr, so passing it to memcpy is
++      // undefined behavior according to the C standard, even though
++      // the memcpy length is 0.
++      //
++      // 2. prev_size will be an out-of-bounds index for
++      // input_overflow_fds_; this is undefined behavior according to
++      // the C++ standard, even though the element only has its
++      // pointer taken and isn't accessed (and the corresponding
++      // operation on a C array would be defined).
++      //
++      // UBSan makes #1 a fatal error, and assertions in libstdc++ do
++      // the same for #2 if enabled.
++      if (num_wire_fds > 0) {
++        const size_t prev_size = input_overflow_fds_.size();
++        input_overflow_fds_.resize(prev_size + num_wire_fds);
++        memcpy(&input_overflow_fds_[prev_size], wire_fds,
++               num_wire_fds * sizeof(int));
++      }
+       fds = &input_overflow_fds_[0];
+       num_fds = input_overflow_fds_.size();
+     }
+ 
+     // The data for the message we're currently reading consists of any data
+     // stored in incoming_message_ followed by data in input_buf_ (followed by
+     // other messages).
+ 
+
diff --git a/SOURCES/mozilla-256180.patch b/SOURCES/mozilla-256180.patch
new file mode 100644
index 0000000..4b61b5f
--- /dev/null
+++ b/SOURCES/mozilla-256180.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.5.0/layout/generic/nsIFrame.h.256180 firefox-60.5.0/layout/generic/nsIFrame.h
+--- firefox-60.5.0/layout/generic/nsIFrame.h.256180	2019-01-22 11:44:10.849848268 +0100
++++ firefox-60.5.0/layout/generic/nsIFrame.h	2019-01-22 11:44:53.918645941 +0100
+@@ -13,7 +13,7 @@
+ #error This header/class should only be used within Mozilla code. It should not be used by extensions.
+ #endif
+ 
+-#define MAX_REFLOW_DEPTH 200
++#define MAX_REFLOW_DEPTH 1000
+ 
+ /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is
+    eventually going to be eliminated, and all callers will use nsFrame instead.
diff --git a/SOURCES/mozilla-api-key b/SOURCES/mozilla-api-key
new file mode 100644
index 0000000..81877bc
--- /dev/null
+++ b/SOURCES/mozilla-api-key
@@ -0,0 +1 @@
+9008bb7e-1e22-4038-94fe-047dd48ccc0b
diff --git a/SOURCES/mozilla-build-arm.patch b/SOURCES/mozilla-build-arm.patch
new file mode 100644
index 0000000..e390a28
--- /dev/null
+++ b/SOURCES/mozilla-build-arm.patch
@@ -0,0 +1,14 @@
+diff -up firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h.arm firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h
+--- firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h.arm	2017-03-03 13:53:52.480754536 +0100
++++ firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h	2017-03-03 13:56:01.476018102 +0100
+@@ -203,6 +203,10 @@
+     #define SK_ARM_HAS_CRC32
+ #endif
+ 
++#if defined(__aarch64__)
++    #undef SK_ARM_HAS_NEON
++#endif
++
+ //////////////////////////////////////////////////////////////////////
+ 
+ #if !defined(SKIA_IMPLEMENTATION)
diff --git a/SOURCES/rhbz-1173156.patch b/SOURCES/rhbz-1173156.patch
new file mode 100644
index 0000000..c35d901
--- /dev/null
+++ b/SOURCES/rhbz-1173156.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp.rhbz-1173156 firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp
+--- firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp.rhbz-1173156	2019-01-22 10:36:09.284069020 +0100
++++ firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp	2019-01-22 10:37:12.669757744 +0100
+@@ -161,7 +161,7 @@ nsresult nsAuthSambaNTLM::SpawnNTLMAuthH
+   const char* username = PR_GetEnv("USER");
+   if (!username) return NS_ERROR_FAILURE;
+ 
+-  const char* const args[] = {"ntlm_auth",
++  const char* const args[] = {"/usr/bin/ntlm_auth",
+                               "--helper-protocol",
+                               "ntlmssp-client-1",
+                               "--use-cached-creds",
diff --git a/SOURCES/rhbz-1354671.patch b/SOURCES/rhbz-1354671.patch
new file mode 100644
index 0000000..7660f14
--- /dev/null
+++ b/SOURCES/rhbz-1354671.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.5.0/layout/base/nsIPresShell.h.1354671 firefox-60.5.0/layout/base/nsIPresShell.h
+--- firefox-60.5.0/layout/base/nsIPresShell.h.1354671	2019-01-22 16:08:40.796539950 +0100
++++ firefox-60.5.0/layout/base/nsIPresShell.h	2019-01-22 16:10:25.106069228 +0100
+@@ -204,7 +204,7 @@ class nsIPresShell : public nsStubDocume
+    * to the same aSize value.  AllocateFrame is infallible and will abort
+    * on out-of-memory.
+    */
+-  void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) {
++  void* __attribute__((optimize("no-lifetime-dse"))) AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) {
+     void* result = mFrameArena.AllocateByFrameID(aID, aSize);
+     RecordAlloc(result);
+     return result;
diff --git a/SOURCES/rhbz-1503632-nss.patch b/SOURCES/rhbz-1503632-nss.patch
new file mode 100644
index 0000000..f7a26d3
--- /dev/null
+++ b/SOURCES/rhbz-1503632-nss.patch
@@ -0,0 +1,19 @@
+diff -up firefox-60.5.0/security/certverifier/NSSCertDBTrustDomain.cpp.1503632-nss firefox-60.5.0/security/certverifier/NSSCertDBTrustDomain.cpp
+--- firefox-60.5.0/security/certverifier/NSSCertDBTrustDomain.cpp.1503632-nss	2019-01-22 11:38:49.484365928 +0100
++++ firefox-60.5.0/security/certverifier/NSSCertDBTrustDomain.cpp	2019-01-22 11:40:52.694779150 +0100
+@@ -1077,13 +1077,11 @@ SECStatus InitializeNSS(const nsACString
+   if (!loadPKCS11Modules) {
+     flags |= NSS_INIT_NOMODDB;
+   }
+-  nsAutoCString dbTypeAndDirectory("sql:");
+-  dbTypeAndDirectory.Append(dir);
+   MOZ_LOG(gCertVerifierLog, LogLevel::Debug,
+-          ("InitializeNSS(%s, %d, %d)", dbTypeAndDirectory.get(), readOnly,
++          ("InitializeNSS(%s, %d, %d)", PromiseFlatCString(dir).get(), readOnly,
+            loadPKCS11Modules));
+   SECStatus srv =
+-      NSS_Initialize(dbTypeAndDirectory.get(), "", "", SECMOD_DB, flags);
++      NSS_Initialize(PromiseFlatCString(dir).get(), "", "", SECMOD_DB, flags);
+   if (srv != SECSuccess) {
+     return srv;
+   }
diff --git a/SOURCES/xulrunner-24.0-jemalloc-ppc.patch b/SOURCES/xulrunner-24.0-jemalloc-ppc.patch
new file mode 100644
index 0000000..c8fe421
--- /dev/null
+++ b/SOURCES/xulrunner-24.0-jemalloc-ppc.patch
@@ -0,0 +1,12 @@
+diff -up firefox-60.5.0/memory/build/mozjemalloc.cpp.jemalloc-ppc firefox-60.5.0/memory/build/mozjemalloc.cpp
+--- firefox-60.5.0/memory/build/mozjemalloc.cpp.jemalloc-ppc	2019-01-22 10:25:30.764207480 +0100
++++ firefox-60.5.0/memory/build/mozjemalloc.cpp	2019-01-22 10:28:48.352235343 +0100
+@@ -180,7 +180,7 @@ using namespace mozilla;
+ // Debug builds are opted out too, for test coverage.
+ #ifndef MOZ_DEBUG
+ #if !defined(__ia64__) && !defined(__sparc__) && !defined(__mips__) && \
+-    !defined(__aarch64__)
++    !defined(__aarch64__) && !defined(__powerpc__)
+ #define MALLOC_STATIC_PAGESIZE 1
+ #endif
+ #endif
diff --git a/SPECS/firefox.spec b/SPECS/firefox.spec
new file mode 100644
index 0000000..bc1e7fc
--- /dev/null
+++ b/SPECS/firefox.spec
@@ -0,0 +1,1382 @@
+# Set for local builds only
+%global disable_toolsets  0
+
+# Use system nspr/nss? FIXME
+%global system_nss        1
+%define use_bundled_ffi   0
+%define use_bundled_python 1
+%define bundle_gnome_extension 0
+
+# Don't use system hunspell for now
+%global system_hunspell   0
+%global system_sqlite     0
+%global use_llvmts        1
+
+%if 0%{?rhel} > 6
+%global system_ffi        1
+%else
+%global system_ffi        0
+%global use_llvmts        0
+%endif
+%if 0%{?rhel} < 8
+%global use_dts           1
+%endif
+
+%if 0%{?rhel} == 7
+%define use_bundled_python 0
+%endif
+
+%if 0%{?rhel} < 8
+%global use_rustts        1
+%endif
+%global dts_version       7
+%global rst_version       7
+%global llvm_version      7
+%if 0%{?rhel} == 8
+%global rst_version       1.26
+%global llvm_version      6.0
+%endif
+
+%if 0%{?disable_toolsets}
+%global use_rustts        0
+%global use_dts           0
+%global use_llvmts        0
+%endif
+
+# Use system cairo?
+%global system_cairo      0
+
+# Use system libvpx?
+%global system_libvpx     0
+
+# Use system libicu?
+%global system_libicu     0
+
+# Big endian platforms
+%ifarch ppc64 s390x
+# Javascript Intl API is not supported on big endian platforms right now:
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1322212
+%global big_endian        1
+%endif
+
+# Hardened build?
+%global hardened_build    1
+
+%global system_jpeg       1
+
+%ifarch %{ix86} x86_64
+%global run_tests         0
+%else
+%global run_tests         0
+%endif
+
+# Build as a debug package?
+%global debug_build       0
+
+%global default_bookmarks_file  %{_datadir}/bookmarks/default-bookmarks.html
+%global firefox_app_id  \{ec8030f7-c20a-464f-9b0e-13a3a9e97384\}
+# Minimal required versions
+%global cairo_version 1.13.1
+%global freetype_version 2.1.9
+%if %{?system_libvpx}
+%global libvpx_version 1.4.0
+%endif
+
+%if %{?system_nss}
+%global nspr_version 4.19.0
+# NSS/NSPR quite often ends in build override, so as requirement the version
+# we're building against could bring us some broken dependencies from time to time.
+#%global nspr_build_version %(pkg-config --silence-errors --modversion nspr 2>/dev/null || echo 65536)
+%global nspr_build_version %{nspr_version}
+%global nss_version 3.36.0
+#%global nss_build_version %(pkg-config --silence-errors --modversion nss 2>/dev/null || echo 65536)
+%global nss_build_version %{nss_version}
+%endif
+
+%if %{?system_sqlite}
+%global sqlite_version 3.8.4.2
+# The actual sqlite version (see #480989):
+%global sqlite_build_version %(pkg-config --silence-errors --modversion sqlite3 2>/dev/null || echo 65536)
+%endif
+
+%define bundled_python_version 2.7.13
+%define use_bundled_yasm        1
+
+# GTK3 bundling
+%define avoid_bundled_rebuild 0
+%if 0%{?rhel} == 6
+%define bundle_gtk3             1
+# In-tree libffi is able to build on following platforms, we have to bundle it for the rest
+%ifnarch x86_64 i686 aarch64
+%define use_bundled_ffi         1
+%endif
+%endif
+
+%define gtk3_nvr 3.22.26-1
+%define gtk3_install_path %{mozappdir}/bundled
+
+%if 0%{?bundle_gtk3}
+# We could use %%include, but in %%files, %%post and other sections, but in these
+# sections it could lead to syntax errors about unclosed %%if. Work around it by
+# using the following macro
+%define include_file() %{expand:%(cat '%1')}
+%endif
+
+
+%global mozappdir     %{_libdir}/%{name}
+%global mozappdirdev  %{_libdir}/%{name}-devel-%{version}
+%global langpackdir   %{mozappdir}/distribution/extensions
+%global tarballdir    %{name}-%{version}
+%global pre_version   esr
+
+%global official_branding       1
+%global build_langpacks         1
+
+%global enable_mozilla_crashreporter       0
+%if !%{debug_build}
+%ifarch %{ix86} x86_64
+%global enable_mozilla_crashreporter       0
+%endif
+%endif
+
+Summary:        Mozilla Firefox Web browser
+Name:           firefox
+Version:        60.5.1
+Release:        1%{?pre_tag}%{?dist}
+URL:            https://www.mozilla.org/firefox/
+License:        MPLv1.1 or GPLv2+ or LGPLv2+
+%if 0%{?rhel} == 7
+ExcludeArch:    s390 ppc
+%endif
+%if 0%{?rhel} == 6
+ExclusiveArch:  i686 x86_64 ppc64 s390x
+%endif
+
+Source0:        https://hg.mozilla.org/releases/mozilla-release/archive/firefox-%{version}%{?pre_version}.source.tar.xz
+%if %{build_langpacks}
+Source1:        firefox-langpacks-%{version}%{?pre_version}-20190213.tar.xz
+%endif
+Source10:       firefox-mozconfig
+Source12:       firefox-redhat-default-prefs.js
+Source20:       firefox.desktop
+Source21:       firefox.sh.in
+Source23:       firefox.1
+Source24:       mozilla-api-key
+Source25:       firefox-symbolic.svg
+Source26:       distribution.ini
+Source27:       google-api-key
+
+Source200:      gtk3-private-%{gtk3_nvr}.el6.src.rpm
+Source201:      gtk3-private-%{gtk3_nvr}-post.inc
+Source202:      gtk3-private-%{gtk3_nvr}-postun.inc
+Source203:      gtk3-private-%{gtk3_nvr}-posttrans.inc
+Source204:      gtk3-private-%{gtk3_nvr}-files.inc
+Source205:      gtk3-private-%{gtk3_nvr}-setup-flags-env.inc
+Source206:      gtk3-private-%{gtk3_nvr}-requires-provides-filter.inc
+Source301:      yasm-1.2.0-3.el5.src.rpm
+Source303:      libffi-3.0.13-18.el7_3.src.rpm
+
+#Python 2.7
+Source100:      https://www.python.org/ftp/python/%{bundled_python_version}/Python-%{bundled_python_version}.tar.xz
+# Build patches
+Patch3:         mozilla-build-arm.patch
+Patch4:         build-mozconfig-fix.patch
+Patch5:         build-gdk-version.patch
+Patch6:         build-nss-version.patch
+Patch26:        build-icu-big-endian.patch
+# Also fixes s390x: https://bugzilla.mozilla.org/show_bug.cgi?id=1376268
+Patch29:        build-big-endian.patch
+# Always feel lucky for unsupported platforms:
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1347128
+Patch37:        build-jit-atomic-always-lucky.patch
+Patch40:        build-aarch64-skia.patch
+Patch41:        build-debug-qcms.patch
+Patch43:        xulrunner-24.0-jemalloc-ppc.patch
+#Patch44:        firefox-disable-dbus-remote.patch
+Patch45:        build-disable-elfhack.patch
+
+# Fedora/RHEL specific patches
+Patch215:        firefox-enable-addons.patch
+Patch219:        rhbz-1173156.patch
+Patch224:        mozilla-1170092.patch
+Patch225:        mozilla-1005640-accept-lang.patch
+#ARM run-time patch
+Patch226:        rhbz-1354671.patch
+Patch230:        rhbz-1503632-nss.patch
+Patch231:        firefox-pipewire.patch
+
+# Upstream patches
+Patch402:        mozilla-1196777.patch
+Patch406:        mozilla-256180.patch
+Patch413:        mozilla-1353817.patch
+Patch415:        mozilla-1436242.patch
+
+# Debian patches
+
+%if %{?system_nss}
+BuildRequires:  pkgconfig(nspr) >= %{nspr_version}
+BuildRequires:  pkgconfig(nss) >= %{nss_version}
+BuildRequires:  nss-static >= %{nss_version}
+%endif
+%if %{?system_cairo}
+BuildRequires:  pkgconfig(cairo) >= %{cairo_version}
+%endif
+BuildRequires:  pkgconfig(libpng)
+BuildRequires:  xz
+BuildRequires:  libXt-devel
+BuildRequires:  mesa-libGL-devel
+Requires:       liberation-fonts-common
+Requires:       liberation-sans-fonts
+%if %{?system_jpeg}
+BuildRequires:  libjpeg-devel
+%endif
+BuildRequires:  zip
+BuildRequires:  bzip2-devel
+BuildRequires:  pkgconfig(zlib)
+BuildRequires:  pkgconfig(libIDL-2.0)
+BuildRequires:  pkgconfig(gtk+-2.0)
+BuildRequires:  krb5-devel
+BuildRequires:  pkgconfig(pango)
+BuildRequires:  pkgconfig(freetype2) >= %{freetype_version}
+BuildRequires:  pkgconfig(xt)
+BuildRequires:  pkgconfig(xrender)
+%if %{?system_hunspell}
+BuildRequires:  hunspell-devel
+%endif
+BuildRequires:  pkgconfig(libstartup-notification-1.0)
+BuildRequires:  pkgconfig(libnotify)
+BuildRequires:  pkgconfig(dri)
+BuildRequires:  pkgconfig(libcurl)
+BuildRequires:  dbus-glib-devel
+%if %{?system_libvpx}
+BuildRequires:  libvpx-devel >= %{libvpx_version}
+%endif
+BuildRequires:  autoconf213
+BuildRequires:  pkgconfig(libpulse)
+BuildRequires:  pkgconfig(gconf-2.0)
+
+%if 0%{?use_dts}
+BuildRequires:  devtoolset-%{dts_version}-gcc-c++
+BuildRequires:  devtoolset-%{dts_version}-gcc
+BuildRequires:  devtoolset-%{dts_version}-binutils
+BuildRequires:  devtoolset-%{dts_version}-libatomic-devel
+%if 0%{?use_llvmts}
+BuildRequires:  llvm-toolset-%{llvm_version}
+BuildRequires:  llvm-toolset-%{llvm_version}-llvm-devel
+%endif
+%endif
+
+%if 0%{?rhel} == 8
+BuildRequires:  cargo
+BuildRequires:  rust >= 1.24
+BuildRequires:  llvm >= %{llvm_version}
+BuildRequires:  llvm-devel >= %{llvm_version}
+BuildRequires:  clang >= %{llvm_version}
+%else
+%if 0%{?use_rustts}
+BuildRequires:  rust-toolset-%{rst_version}-cargo
+BuildRequires:  rust-toolset-%{rst_version}-rust >= 1.24
+%endif
+%if 0%{?use_llvmts}
+BuildRequires:  llvm-toolset-%{llvm_version}
+BuildRequires:  llvm-toolset-%{llvm_version}-llvm-devel
+%endif
+%endif
+
+%if 0%{?use_bundled_python}
+#%if 0%{?rhel} == 6
+# Needed for Python in RHEL6
+BuildRequires:  openssl-devel
+#%endif
+%endif
+
+%if 0%{?rhel} == 8
+BuildRequires:  pipewire-devel
+%endif
+
+%if 0%{?bundle_gtk3}
+BuildRequires:        automake
+BuildRequires:        autoconf
+BuildRequires:        cups-devel
+BuildRequires:        dbus-devel
+BuildRequires:        desktop-file-utils
+BuildRequires:        expat-devel
+BuildRequires:        fontpackages-devel
+BuildRequires:        gamin-devel
+BuildRequires:        gettext-devel
+BuildRequires:        git
+BuildRequires:        intltool
+BuildRequires:        jasper-devel
+BuildRequires:        libepoxy-devel
+BuildRequires:        libcroco-devel
+BuildRequires:        libffi-devel
+BuildRequires:        libpng-devel
+BuildRequires:        libtiff-devel
+BuildRequires:        libtool
+BuildRequires:        libxml2-devel
+BuildRequires:        libX11-devel
+BuildRequires:        libXcomposite-devel
+BuildRequires:        libXcursor-devel
+BuildRequires:        libXinerama-devel
+BuildRequires:        libXevie-devel
+BuildRequires:        libXrandr-devel
+BuildRequires:        libXrender-devel
+BuildRequires:        libXtst-devel
+BuildRequires:        mesa-libGL-devel
+BuildRequires:        mesa-libEGL-devel
+BuildRequires:        pixman-devel
+BuildRequires:        rest-devel
+BuildRequires:        readline-devel
+# TODO: We miss that dependency in our bundled gtk3 package.
+# As a hotfix we put it here and fix gtk3 in next release.
+Requires:             mesa-libEGL%{?_isa}
+Requires:             libcroco%{?_isa}
+Requires:             mesa-libGL%{?_isa}
+Requires:             bzip2-libs%{?_isa}
+Requires:             libXtst%{?_isa}
+%else
+BuildRequires:        gtk3-devel
+BuildRequires:        glib2-devel
+%endif
+
+Requires:       mozilla-filesystem
+Requires:       p11-kit-trust
+%if %{?system_nss}
+Requires:       nspr >= %{nspr_build_version}
+Requires:       nss >= %{nss_build_version}
+%endif
+
+%if 0%{?rhel} < 8
+BuildRequires:  python2-devel
+%endif
+
+BuildRequires:  desktop-file-utils
+BuildRequires:  system-bookmarks
+Requires:       redhat-indexhtml
+%if %{?system_sqlite}
+BuildRequires:  pkgconfig(sqlite3) >= %{sqlite_version}
+Requires:       sqlite >= %{sqlite_build_version}
+%endif
+
+
+%if %{?run_tests}
+BuildRequires:  xorg-x11-server-Xvfb
+%endif
+
+%if %{?system_ffi}
+  %if !%{use_bundled_ffi}0
+BuildRequires:  pkgconfig(libffi)
+  %endif
+%endif
+
+Obsoletes:      mozilla <= 37:1.7.13
+Provides:       webclient
+
+%description
+Mozilla Firefox is an open-source web browser, designed for standards
+compliance, performance and portability.
+
+%if %{enable_mozilla_crashreporter}
+%global moz_debug_prefix %{_prefix}/lib/debug
+%global moz_debug_dir %{moz_debug_prefix}%{mozappdir}
+%global uname_m %(uname -m)
+%global symbols_file_name %{name}-%{version}.en-US.%{_os}-%{uname_m}.crashreporter-symbols.zip
+%global symbols_file_path %{moz_debug_dir}/%{symbols_file_name}
+%global _find_debuginfo_opts -p %{symbols_file_path} -o debugcrashreporter.list
+%global crashreporter_pkg_name mozilla-crashreporter-%{name}-debuginfo
+%package -n %{crashreporter_pkg_name}
+Summary: Debugging symbols used by Mozilla's crash reporter servers
+%description -n %{crashreporter_pkg_name}
+This package provides debug information for Firefox, for use by
+Mozilla's crash reporter servers.  If you are trying to locally
+debug %{name}, you want to install %{name}-debuginfo instead.
+%files -n %{crashreporter_pkg_name} -f debugcrashreporter.list
+%endif
+
+%if %{run_tests}
+%global testsuite_pkg_name mozilla-%{name}-testresults
+%package -n %{testsuite_pkg_name}
+Summary: Results of testsuite
+%description -n %{testsuite_pkg_name}
+This package contains results of tests executed during build.
+%files -n %{testsuite_pkg_name}
+/test_results
+%endif
+
+#---------------------------------------------------------------------
+
+%if %{?bundle_gnome_extension}
+%package        -n firefox-gnome-shell-extension
+%global         firefox_gnome_shell_addon_name addon-751081-latest.xpi
+Summary:        Support for managing GNOME Shell Extensions through web browsers
+Requires:       %{name}%{?_isa} = %{version}-%{release}
+
+License:        GPLv3+
+URL:            https://wiki.gnome.org/Projects/GnomeShellIntegrationForChrome
+Source2:        https://addons.mozilla.org/firefox/downloads/latest/gnome-shell-integration/platform:2/%{firefox_gnome_shell_addon_name}
+
+Requires:       dbus
+Requires:       gnome-icon-theme
+Requires:       gnome-shell
+Requires:       hicolor-icon-theme
+Requires:       mozilla-filesystem
+
+%description -n firefox-gnome-shell-extension
+Browser extension for Firefox and native host messaging connector that provides 
+integration with GNOME Shell and the corresponding extensions repository 
+https://extensions.gnome.org.
+
+%files -n firefox-gnome-shell-extension
+%{mozappdir}/distribution/extensions/chrome-gnome-shell@gnome.org.xpi
+%endif # bundle_gnome_extension
+
+%prep
+%setup -q -T -c -n python -a 100
+%setup -q -n %{tarballdir}
+# Build patches, can't change backup suffix from default because during build
+# there is a compare of config and js/config directories and .orig suffix is
+# ignored during this compare.
+
+%patch29 -p1 -b .big-endian
+%patch37 -p1 -b .jit-atomic-lucky
+%patch40 -p1 -b .aarch64-skia
+%if %{?debug_build}
+%patch41 -p1 -b .build-debug-qcms
+%endif
+%patch43 -p1 -b .jemalloc-ppc
+# Disable DBus remote on RHEL6 as it does not build here.
+#%if 0%{?rhel} == 6
+#%patch44 -p1 -b .disable-dbus-remote
+#%endif
+%if 0%{?rhel} == 8
+%patch45 -p1 -b .disable-elfhack
+%endif
+
+%patch3  -p1 -b .arm
+%patch4  -p1 -b .build-mozconfig-fix
+%patch5  -p1 -b .gdk-version
+%patch6  -p1 -b .nss-version
+
+# Fedora patches
+%patch215 -p1 -b .addons
+%patch219 -p1 -b .rhbz-1173156
+%patch224 -p1 -b .1170092
+%patch225 -p1 -b .1005640-accept-lang
+%if 0%{?rhel} == 8
+%patch231 -p1 -b .pipewire
+%endif
+
+# This ensures no migration of certdb to sqlite on the RHEL6 and RHEL7.
+# This needs to stay for the future releases
+%if 0%{?rhel} < 8
+%patch230 -p1 -b .1503632-nss
+%endif
+
+#ARM run-time patch
+%ifarch aarch64
+%patch226 -p1 -b .1354671
+%endif
+
+%patch402 -p1 -b .1196777
+%patch406 -p1 -b .256180
+%patch413 -p1 -b .1353817
+%patch415 -p1 -b .1436242
+
+
+# Patch for big endian platforms only
+%if 0%{?big_endian}
+%patch26 -p1 -b .icu
+%endif
+
+%{__rm} -f .mozconfig
+%{__cp} %{SOURCE10} .mozconfig
+%if %{official_branding}
+echo "ac_add_options --enable-official-branding" >> .mozconfig
+%endif
+%{__cp} %{SOURCE24} mozilla-api-key
+%{__cp} %{SOURCE27} google-api-key
+
+%if %{?system_nss}
+echo "ac_add_options --with-system-nspr" >> .mozconfig
+echo "ac_add_options --with-system-nss" >> .mozconfig
+%else
+echo "ac_add_options --without-system-nspr" >> .mozconfig
+echo "ac_add_options --without-system-nss" >> .mozconfig
+%endif
+
+%if %{?system_sqlite}
+echo "ac_add_options --enable-system-sqlite" >> .mozconfig
+%else
+echo "ac_add_options --disable-system-sqlite" >> .mozconfig
+%endif
+
+%if %{?system_cairo}
+echo "ac_add_options --enable-system-cairo" >> .mozconfig
+%else
+echo "ac_add_options --disable-system-cairo" >> .mozconfig
+%endif
+
+%if 0%{?use_bundled_ffi}
+echo "ac_add_options --enable-system-ffi" >> .mozconfig
+%endif
+%if 0%{?system_ffi}
+echo "ac_add_options --enable-system-ffi" >> .mozconfig
+%endif
+
+%ifarch %{arm}
+echo "ac_add_options --disable-elf-hack" >> .mozconfig
+%endif
+
+%if %{?system_hunspell}
+echo "ac_add_options --enable-system-hunspell" >> .mozconfig
+%else
+echo "ac_add_options --disable-system-hunspell" >> .mozconfig
+%endif
+
+%if %{?debug_build}
+echo "ac_add_options --enable-debug" >> .mozconfig
+echo "ac_add_options --disable-optimize" >> .mozconfig
+%else
+%global optimize_flags "none"
+%ifnarch s390 s390x
+%global optimize_flags "-g -O2"
+%endif
+%ifarch armv7hl
+# ARMv7 need that (rhbz#1426850)
+%global optimize_flags "-g -O2 -fno-schedule-insns"
+%endif
+%ifarch ppc64le aarch64
+%global optimize_flags "-g -O2"
+%endif
+%if %{optimize_flags} != "none"
+echo 'ac_add_options --enable-optimize=%{?optimize_flags}' >> .mozconfig
+%else
+echo 'ac_add_options --enable-optimize' >> .mozconfig
+%endif
+echo "ac_add_options --disable-debug" >> .mozconfig
+%endif
+
+# Second arches fail to start with jemalloc enabled
+%ifnarch %{ix86} x86_64
+echo "ac_add_options --disable-jemalloc" >> .mozconfig
+%endif
+
+%ifnarch %{ix86} x86_64
+echo "ac_add_options --disable-webrtc" >> .mozconfig
+%endif
+
+%if !%{enable_mozilla_crashreporter}
+echo "ac_add_options --disable-crashreporter" >> .mozconfig
+%endif
+
+%if %{?run_tests}
+echo "ac_add_options --enable-tests" >> .mozconfig
+%endif
+
+%if !%{?system_jpeg}
+echo "ac_add_options --without-system-jpeg" >> .mozconfig
+%else
+echo "ac_add_options --with-system-jpeg" >> .mozconfig
+%endif
+
+%if %{?system_libvpx}
+echo "ac_add_options --with-system-libvpx" >> .mozconfig
+%else
+echo "ac_add_options --without-system-libvpx" >> .mozconfig
+%endif
+
+%if %{?system_libicu}
+echo "ac_add_options --with-system-icu" >> .mozconfig
+%else
+echo "ac_add_options --without-system-icu" >> .mozconfig
+%endif
+%ifarch s390 s390x
+echo "ac_add_options --disable-ion" >> .mozconfig
+%endif
+
+%ifarch %{ix86}
+echo "ac_add_options --disable-stylo" >> .mozconfig
+%endif
+%if 0%{?rhel} == 6
+echo "ac_add_options --disable-stylo" >> .mozconfig
+%endif
+
+# Remove executable bit to make brp-mangle-shebangs happy.
+chmod -x third_party/rust/itertools/src/lib.rs
+
+#---------------------------------------------------------------------
+
+%build
+
+#GTK3 >>
+%if ! 0%{?avoid_bundled_rebuild}
+    rm -rf %{_buildrootdir}/*
+%endif
+export PATH="%{_buildrootdir}/bin:$PATH"
+
+function install_rpms_to_current_dir() {
+    PACKAGE_RPM=$(eval echo $1)
+    PACKAGE_DIR=%{_rpmdir}
+
+    if [ ! -f $PACKAGE_DIR/$PACKAGE_RPM ]; then
+        # Hack for tps tests
+        ARCH_STR=%{_arch}
+        %ifarch i386 i686
+            ARCH_STR="i?86"
+        %endif
+        PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+     fi
+
+     for package in $(ls $PACKAGE_DIR/$PACKAGE_RPM)
+     do
+         echo "$package"
+         rpm2cpio "$package" | cpio -idu
+     done
+}
+
+function build_bundled_package() {
+  PACKAGE_RPM=$1
+  PACKAGE_FILES=$2
+  PACKAGE_SOURCE=$3
+  PACKAGE_DIR="%{_topdir}/RPMS"
+
+  PACKAGE_ALREADY_BUILD=0
+  %if %{?avoid_bundled_rebuild}
+    if ls $PACKAGE_DIR/$PACKAGE_RPM; then
+      PACKAGE_ALREADY_BUILD=1
+    fi
+    if ls $PACKAGE_DIR/%{_arch}/$PACKAGE_RPM; then
+      PACKAGE_ALREADY_BUILD=1
+    fi
+  %endif
+  if [ $PACKAGE_ALREADY_BUILD == 0 ]; then
+    echo "Rebuilding $PACKAGE_RPM from $PACKAGE_SOURCE"; echo "==============================="
+    rpmbuild --nodeps --rebuild $PACKAGE_SOURCE
+  fi
+
+  if [ ! -f $PACKAGE_DIR/$PACKAGE_RPM ]; then
+    # Hack for tps tests
+    ARCH_STR=%{_arch}
+    %ifarch i386 i686
+    ARCH_STR="i?86"
+    %endif
+    PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+  fi
+  pushd $PACKAGE_DIR
+  echo "Installing $PACKAGE_DIR/$PACKAGE_RPM"; echo "==============================="
+  rpm2cpio $PACKAGE_DIR/$PACKAGE_RPM | cpio -iduv
+  # Clean rpms to avoid including them to package
+  %if ! 0%{?avoid_bundled_rebuild}
+    rm -f $PACKAGE_FILES
+  %endif
+
+  PATH=$PACKAGE_DIR/usr/bin:$PATH
+  export PATH
+  LD_LIBRARY_PATH=$PACKAGE_DIR/usr/%{_lib}
+  export LD_LIBRARY_PATH
+  popd
+}
+
+# Build and install local yasm if needed
+# ======================================
+%if %{use_bundled_yasm}
+  build_bundled_package 'yasm-1*.rpm' 'yasm-*.rpm' '%{SOURCE301}'
+%endif
+
+
+%if 0%{?bundle_gtk3}
+   %if ! 0%{?avoid_bundled_rebuild}
+    rpm -ivh %{SOURCE200}
+    rpmbuild --nodeps --define '_prefix %{gtk3_install_path}' -ba %{_specdir}/gtk3-private.spec
+   %endif
+   rm -rf %{_buildrootdir}/*
+   pushd %{_buildrootdir}
+   install_rpms_to_current_dir gtk3-private-%{gtk3_nvr}*.rpm
+   install_rpms_to_current_dir gtk3-private-devel-%{gtk3_nvr}*.rpm
+   install_rpms_to_current_dir gtk3-private-rpm-scripts-%{gtk3_nvr}*.rpm
+   popd
+%endif
+
+# If needed build the bundled python 2.7 and put it in the PATH
+%if 0%{?use_bundled_python}
+    pushd %{_builddir}/python/Python-%{bundled_python_version}
+    #if ! 0%{?avoid_bundled_rebuild}
+        # Build Python 2.7 and set environment
+        # Pydebug set optimization to level 0, -O3 crashes on gcc 8 ATM
+        ./configure --with-pydebug --prefix="%{_buildrootdir}" --exec-prefix="%{_buildrootdir}" --libdir="%{_buildrootdir}/lib"
+    #endif
+    make %{?_smp_mflags} install V=1
+    popd
+%endif
+
+%if 0%{?bundle_gtk3}
+# gtk3-private-3.22.26.el6-1-requires-provides-filter.inc
+%include_file %{SOURCE206}
+%endif
+%if 0%{use_bundled_ffi}
+  # Install libraries to the predefined location to later add them to the Firefox libraries
+  rpm -ivh %{SOURCE303}
+  rpmbuild --nodeps --define '_prefix %{gtk3_install_path}' -ba %{_specdir}/libffi.spec
+  pushd %{_buildrootdir}
+  install_rpms_to_current_dir 'libffi*.rpm'
+  popd
+  %filter_from_requires /libffi.so.6/d
+%endif
+%filter_setup
+
+# GTK3 <<
+
+%if %{?system_sqlite}
+# Do not proceed with build if the sqlite require would be broken:
+# make sure the minimum requirement is non-empty, ...
+sqlite_version=$(expr "%{sqlite_version}" : '\([0-9]*\.\)[0-9]*\.') || exit 1
+# ... and that major number of the computed build-time version matches:
+case "%{sqlite_build_version}" in
+  "$sqlite_version"*) ;;
+  *) exit 1 ;;
+esac
+%endif
+
+# We need to disable exit on error temporarily for the following scripts:
+set +e
+%if 0%{?use_dts}
+source scl_source enable devtoolset-%{dts_version}
+%endif
+%if 0%{?use_rustts}
+source scl_source enable rust-toolset-%{rst_version}
+%endif
+
+set -e
+# Hack for missing shell when building in brew on RHEL6
+%if 0%{?rhel} == 6
+export SHELL=/bin/sh
+%endif
+
+echo "Generate big endian version of config/external/icu/data/icud58l.dat"
+%if 0%{?big_endian}
+  ./mach python intl/icu_sources_data.py .
+  ls -l config/external/icu/data
+  rm -f config/external/icu/data/icudt*l.dat
+%endif
+
+# Update the various config.guess to upstream release for aarch64 support
+find ./ -name config.guess -exec cp /usr/lib/rpm/config.guess {} ';'
+
+# -fpermissive is needed to build with gcc 4.6+ which has become stricter
+#
+# Mozilla builds with -Wall with exception of a few warnings which show up
+# everywhere in the code; so, don't override that.
+#
+# Disable C++ exceptions since Mozilla code is not exception-safe
+#
+MOZ_OPT_FLAGS=$(echo "%{optflags}" | %{__sed} -e 's/-Wall//')
+#rhbz#1037063
+# -Werror=format-security causes build failures when -Wno-format is explicitly given
+# for some sources
+# Explicitly force the hardening flags for Firefox so it passes the checksec test;
+# See also https://fedoraproject.org/wiki/Changes/Harden_All_Packages
+MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -Wformat-security -Wformat -Werror=format-security"
+%if 0%{?fedora} > 23
+# Disable null pointer gcc6 optimization in gcc6 (rhbz#1328045)
+MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fno-delete-null-pointer-checks"
+%endif
+# Use hardened build?
+%if %{?hardened_build}
+MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fPIC -Wl,-z,relro -Wl,-z,now"
+%endif
+%if %{?debug_build}
+MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
+%endif
+%ifarch s390
+MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g1/')
+# If MOZ_DEBUG_FLAGS is empty, firefox's build will default it to "-g" which
+# overrides the -g1 from line above and breaks building on s390
+# (OOM when linking, rhbz#1238225)
+export MOZ_DEBUG_FLAGS=" "
+%endif
+%ifarch s390 %{arm} ppc aarch64 i686
+MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
+%endif
+%ifarch %{arm}
+export RUSTFLAGS="-Cdebuginfo=0"
+%endif
+export CFLAGS=$MOZ_OPT_FLAGS
+export CXXFLAGS=$MOZ_OPT_FLAGS
+export LDFLAGS=$MOZ_LINK_FLAGS
+
+export PREFIX='%{_prefix}'
+export LIBDIR='%{_libdir}'
+
+MOZ_SMP_FLAGS=-j1
+# On x86 architectures, Mozilla can build up to 4 jobs at once in parallel,
+# however builds tend to fail on other arches when building in parallel.
+%ifarch %{ix86} x86_64 ppc ppc64 ppc64le aarch64
+[ -z "$RPM_BUILD_NCPUS" ] && \
+     RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j4
+[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j8
+%endif
+
+%if 0%{?bundle_gtk3}
+# gtk3-private-setup-flags-env.inc
+%include_file %{SOURCE205}
+%endif
+
+#make -f client.mk build STRIP="/bin/true" MOZ_MAKE_FLAGS="$MOZ_SMP_FLAGS" MOZ_SERVICES_SYNC="1"
+export MOZ_MAKE_FLAGS="$MOZ_SMP_FLAGS"
+export MOZ_SERVICES_SYNC="1"
+export STRIP=/bin/true
+%if 0%{?rhel} == 8
+export LLVM_CONFIG=/usr/bin/llvm-config-64
+%endif
+./mach build -v
+
+# create debuginfo for crash-stats.mozilla.com
+%if %{enable_mozilla_crashreporter}
+#cd %{moz_objdir}
+make -C objdir buildsymbols
+%endif
+
+%if %{?run_tests}
+%if %{?system_nss}
+ln -s /usr/bin/certutil objdir/dist/bin/certutil
+ln -s /usr/bin/pk12util objdir/dist/bin/pk12util
+
+%endif
+mkdir test_results
+./mach --log-no-times check-spidermonkey &> test_results/check-spidermonkey || true
+./mach --log-no-times check-spidermonkey &> test_results/check-spidermonkey-2nd-run || true
+./mach --log-no-times cppunittest &> test_results/cppunittest || true
+xvfb-run ./mach --log-no-times crashtest &> test_results/crashtest || true
+./mach --log-no-times gtest &> test_results/gtest || true
+xvfb-run ./mach --log-no-times jetpack-test &> test_results/jetpack-test || true
+# not working right now ./mach marionette-test &> test_results/marionette-test || true
+xvfb-run ./mach --log-no-times mochitest-a11y &> test_results/mochitest-a11y || true
+xvfb-run ./mach --log-no-times mochitest-browser &> test_results/mochitest-browser || true
+xvfb-run ./mach --log-no-times mochitest-chrome &> test_results/mochitest-chrome || true
+xvfb-run ./mach --log-no-times mochitest-devtools &> test_results/mochitest-devtools || true
+xvfb-run ./mach --log-no-times mochitest-plain &> test_results/mochitest-plain || true
+xvfb-run ./mach --log-no-times reftest &> test_results/reftest || true
+xvfb-run ./mach --log-no-times webapprt-test-chrome &> test_results/webapprt-test-chrome || true
+xvfb-run ./mach --log-no-times webapprt-test-content &> test_results/webapprt-test-content || true
+./mach --log-no-times webidl-parser-test &> test_results/webidl-parser-test || true
+xvfb-run ./mach --log-no-times xpcshell-test &> test_results/xpcshell-test || true
+%if %{?system_nss}
+rm -f  objdir/dist/bin/certutil
+rm -f  objdir/dist/bin/pk12util
+%endif
+
+%endif
+#---------------------------------------------------------------------
+
+%install
+%if 0%{?rhel} == 6
+export SHELL=/bin/sh
+%endif
+
+%if 0%{?bundle_gtk3}
+function install_rpms_to_current_dir() {
+    PACKAGE_RPM=$(eval echo $1)
+    PACKAGE_DIR=%{_rpmdir}
+
+    if [ ! -f $PACKAGE_DIR/$PACKAGE_RPM ]; then
+        # Hack for tps tests
+        ARCH_STR=%{_arch}
+        %ifarch i386 i686
+            ARCH_STR="i?86"
+        %endif
+        PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+     fi
+
+     for package in $(ls $PACKAGE_DIR/$PACKAGE_RPM)
+     do
+         echo "$package"
+         rpm2cpio "$package" | cpio -idu
+     done
+}
+
+pushd %{buildroot}
+# Install gtk3-private again to the buildroot, but without devel subpackage
+install_rpms_to_current_dir gtk3-private-%{gtk3_nvr}*.rpm
+install_rpms_to_current_dir gtk3-private-rpm-scripts-%{gtk3_nvr}*.rpm
+popd
+%endif
+
+# Install bundled libffi
+%if %{use_bundled_ffi}
+  pushd %{buildroot}
+  install_rpms_to_current_dir libffi-3*.rpm
+  popd
+%endif
+
+# set up our default bookmarks
+%{__cp} -p %{default_bookmarks_file} objdir/dist/bin/browser/chrome/en-US/locale/browser/bookmarks.html
+
+# Make sure locale works for langpacks
+%{__cat} > objdir/dist/bin/browser/defaults/preferences/firefox-l10n.js << EOF
+pref("general.useragent.locale", "chrome://global/locale/intl.properties");
+EOF
+
+DESTDIR=%{buildroot} make -C objdir install
+
+%{__mkdir_p} %{buildroot}{%{_libdir},%{_bindir},%{_datadir}/applications}
+
+desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE20}
+
+# set up the firefox start script
+%{__rm} -rf %{buildroot}%{_bindir}/firefox
+%{__cat} %{SOURCE21} > %{buildroot}%{_bindir}/firefox
+%if 0%{?bundle_gtk3}
+sed -i -e 's|%RHEL_ENV_VARS%|export XDG_DATA_DIRS="$MOZ_LIB_DIR/firefox/bundled/share:/usr/share:$XDG_DATA_DIRS"\nexport FONTCONFIG_FILE="$MOZ_LIB_DIR/firefox/bundled/etc/fonts/fonts.conf"|' %{buildroot}%{_bindir}/firefox
+%else
+sed -i -e 's|%RHEL_ENV_VARS%||' %{buildroot}%{_bindir}/firefox
+%endif
+
+%{__chmod} 755 %{buildroot}%{_bindir}/firefox
+
+%{__install} -p -D -m 644 %{SOURCE23} %{buildroot}%{_mandir}/man1/firefox.1
+
+%{__rm} -f %{buildroot}/%{mozappdir}/firefox-config
+%{__rm} -f %{buildroot}/%{mozappdir}/update-settings.ini
+
+for s in 16 22 24 32 48 256; do
+    %{__mkdir_p} %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps
+    %{__cp} -p browser/branding/official/default${s}.png \
+               %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps/firefox.png
+done
+
+# Install hight contrast icon
+%{__mkdir_p} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps
+%{__cp} -p %{SOURCE25} \
+           %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps
+
+# Register as an application to be visible in the software center
+#
+# NOTE: It would be *awesome* if this file was maintained by the upstream
+# project, translated and installed into the right place during `make install`.
+#
+# See http://www.freedesktop.org/software/appstream/docs/ for more details.
+#
+%{__mkdir_p} %{buildroot}%{_datadir}/appdata
+cat > %{buildroot}%{_datadir}/appdata/%{name}.appdata.xml <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2014 Richard Hughes <richard@hughsie.com> -->
+<!--
+BugReportURL: https://bugzilla.mozilla.org/show_bug.cgi?id=1071061
+SentUpstream: 2014-09-22
+-->
+<application>
+  <id type="desktop">firefox.desktop</id>
+  <metadata_license>CC0-1.0</metadata_license>
+  <description>
+    <p>
+      Bringing together all kinds of awesomeness to make browsing better for you.
+      Get to your favorite sites quickly – even if you don’t remember the URLs.
+      Type your term into the location bar (aka the Awesome Bar) and the autocomplete
+      function will include possible matches from your browsing history, bookmarked
+      sites and open tabs.
+    </p>
+    <!-- FIXME: Needs another couple of paragraphs -->
+  </description>
+  <url type="homepage">http://www.mozilla.org/</url>
+  <screenshots>
+    <screenshot type="default">https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/a.png</screenshot>
+    <screenshot>https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/b.png</screenshot>
+    <screenshot>https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/c.png</screenshot>
+  </screenshots>
+  <!-- FIXME: change this to an upstream email address for spec updates
+  <updatecontact>someone_who_cares@upstream_project.org</updatecontact>
+   -->
+</application>
+EOF
+
+echo > %{name}.lang
+%if %{build_langpacks}
+# Extract langpacks, make any mods needed, repack the langpack, and install it.
+%{__mkdir_p} %{buildroot}%{langpackdir}
+%{__tar} xf %{SOURCE1}
+for langpack in `ls firefox-langpacks/*.xpi`; do
+  language=`basename $langpack .xpi`
+  extensionID=langpack-$language@firefox.mozilla.org
+  %{__mkdir_p} $extensionID
+  unzip -qq $langpack -d $extensionID
+  find $extensionID -type f | xargs chmod 644
+
+  cd $extensionID
+  zip -qq -r9mX ../${extensionID}.xpi *
+  cd -
+
+  %{__install} -m 644 ${extensionID}.xpi %{buildroot}%{langpackdir}
+  language=`echo $language | sed -e 's/-/_/g'`
+  echo "%%lang($language) %{langpackdir}/${extensionID}.xpi" >> %{name}.lang
+done
+%{__rm} -rf firefox-langpacks
+
+# Install langpack workaround (see #707100, #821169)
+function create_default_langpack() {
+language_long=$1
+language_short=$2
+cd %{buildroot}%{langpackdir}
+ln -s langpack-$language_long@firefox.mozilla.org.xpi langpack-$language_short@firefox.mozilla.org.xpi
+cd -
+echo "%%lang($language_short) %{langpackdir}/langpack-$language_short@firefox.mozilla.org.xpi" >> %{name}.lang
+}
+
+# Table of fallbacks for each language
+# please file a bug at bugzilla.redhat.com if the assignment is incorrect
+create_default_langpack "bn-IN" "bn"
+create_default_langpack "es-AR" "es"
+create_default_langpack "fy-NL" "fy"
+create_default_langpack "ga-IE" "ga"
+create_default_langpack "gu-IN" "gu"
+create_default_langpack "hi-IN" "hi"
+create_default_langpack "hy-AM" "hy"
+create_default_langpack "nb-NO" "nb"
+create_default_langpack "nn-NO" "nn"
+create_default_langpack "pa-IN" "pa"
+create_default_langpack "pt-PT" "pt"
+create_default_langpack "sv-SE" "sv"
+create_default_langpack "zh-TW" "zh"
+%endif # build_langpacks
+
+# Keep compatibility with the old preference location.
+%{__mkdir_p} %{buildroot}%{mozappdir}/defaults/preferences
+%{__mkdir_p} %{buildroot}%{mozappdir}/browser/defaults
+ln -s %{mozappdir}/defaults/preferences $RPM_BUILD_ROOT/%{mozappdir}/browser/defaults/preferences
+# Default preferences
+%{__cp} %{SOURCE12} %{buildroot}%{mozappdir}/defaults/preferences/all-redhat.js
+
+# System config dir
+%{__mkdir_p} %{buildroot}/%{_sysconfdir}/%{name}/pref
+
+# System extensions
+%{__mkdir_p} %{buildroot}%{_datadir}/mozilla/extensions/%{firefox_app_id}
+%{__mkdir_p} %{buildroot}%{_libdir}/mozilla/extensions/%{firefox_app_id}
+
+# Copy over the LICENSE
+%{__install} -p -c -m 644 LICENSE %{buildroot}/%{mozappdir}
+
+# Use the system hunspell dictionaries
+%{__rm} -rf %{buildroot}%{mozappdir}/dictionaries
+ln -s %{_datadir}/myspell %{buildroot}%{mozappdir}/dictionaries
+
+# Enable crash reporter for Firefox application
+%if %{enable_mozilla_crashreporter}
+sed -i -e "s/\[Crash Reporter\]/[Crash Reporter]\nEnabled=1/" %{buildroot}/%{mozappdir}/application.ini
+# Add debuginfo for crash-stats.mozilla.com
+%{__mkdir_p} %{buildroot}/%{moz_debug_dir}
+%{__cp} objdir/dist/%{symbols_file_name} %{buildroot}/%{moz_debug_dir}
+%endif
+
+%if %{run_tests}
+# Add debuginfo for crash-stats.mozilla.com
+%{__mkdir_p} %{buildroot}/test_results
+%{__cp} test_results/* %{buildroot}/test_results
+%endif
+
+
+# Copy over run-mozilla.sh
+%{__cp} build/unix/run-mozilla.sh %{buildroot}%{mozappdir}
+
+# Add distribution.ini
+%{__mkdir_p} %{buildroot}%{mozappdir}/distribution
+%{__cp} %{SOURCE26} %{buildroot}%{mozappdir}/distribution
+
+# Remove copied libraries to speed up build
+rm -f %{buildroot}%{mozappdirdev}/sdk/lib/libmozjs.so
+rm -f %{buildroot}%{mozappdirdev}/sdk/lib/libmozalloc.so
+rm -f %{buildroot}%{mozappdirdev}/sdk/lib/libxul.so
+
+%if %{bundle_gnome_extension}
+# Gnome extension
+%{__mkdir_p} %{buildroot}%{mozappdir}/distribution/extensions
+%{__cp} -p %{SOURCE2} %{buildroot}%{mozappdir}/distribution/extensions/chrome-gnome-shell@gnome.org.xpi
+chmod 644 %{buildroot}%{mozappdir}/distribution/extensions/chrome-gnome-shell@gnome.org.xpi
+%endif
+#---------------------------------------------------------------------
+
+
+
+%preun
+# is it a final removal?
+if [ $1 -eq 0 ]; then
+  %{__rm} -rf %{mozappdir}/components
+  %{__rm} -rf %{mozappdir}/extensions
+  %{__rm} -rf %{mozappdir}/plugins
+  %{__rm} -rf %{langpackdir}
+fi
+
+%clean
+rm -rf %{_srcrpmdir}/gtk3-private-%{gtk3_nvr}*.src.rpm
+find %{_rpmdir} -name "gtk3-private-*%{gtk3_nvr}*.rpm" -delete
+rm -rf %{_srcrpmdir}/libffi*.src.rpm
+find %{_rpmdir} -name "libffi*.rpm" -delete
+
+%post
+update-desktop-database &> /dev/null || :
+touch --no-create %{_datadir}/icons/hicolor &>/dev/null || :
+%if 0%{?bundle_gtk3}
+# gtk3-private-post.inc
+%include_file %{SOURCE201}
+%endif
+
+%postun
+update-desktop-database &> /dev/null || :
+if [ $1 -eq 0 ] ; then
+    touch --no-create %{_datadir}/icons/hicolor &>/dev/null
+    gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
+fi
+%if 0%{?bundle_gtk3}
+# gtk3-private-postun.inc
+%include_file %{SOURCE202}
+%endif
+
+%posttrans
+gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
+%if 0%{?bundle_gtk3}
+# gtk3-private-posttrans.inc
+%include_file %{SOURCE203}
+%endif
+
+%files -f %{name}.lang
+%{_bindir}/firefox
+%{mozappdir}/firefox
+%{mozappdir}/firefox-bin
+%doc %{_mandir}/man1/*
+%dir %{_sysconfdir}/%{name}
+%dir %{_sysconfdir}/%{name}/*
+%dir %{_datadir}/mozilla/extensions/*
+%dir %{_libdir}/mozilla/extensions/*
+%{_datadir}/appdata/*.appdata.xml
+%{_datadir}/applications/*.desktop
+%dir %{mozappdir}
+%doc %{mozappdir}/LICENSE
+%{mozappdir}/browser/chrome
+%{mozappdir}/browser/chrome.manifest
+%{mozappdir}/defaults/preferences/*
+%{mozappdir}/browser/defaults/preferences
+%{mozappdir}/browser/features/*.xpi
+%{mozappdir}/distribution/distribution.ini
+# That's Windows only
+%ghost %{mozappdir}/browser/features/aushelper@mozilla.org.xpi
+%attr(644, root, root) %{mozappdir}/browser/blocklist.xml
+%dir %{mozappdir}/browser/extensions
+%{mozappdir}/browser/extensions/*
+%if %{build_langpacks}
+%dir %{langpackdir}
+%endif
+%{mozappdir}/browser/omni.ja
+%{mozappdir}/chrome.manifest
+%{mozappdir}/run-mozilla.sh
+%{mozappdir}/application.ini
+%{mozappdir}/pingsender
+%exclude %{mozappdir}/removed-files
+%{_datadir}/icons/hicolor/16x16/apps/firefox.png
+%{_datadir}/icons/hicolor/22x22/apps/firefox.png
+%{_datadir}/icons/hicolor/24x24/apps/firefox.png
+%{_datadir}/icons/hicolor/256x256/apps/firefox.png
+%{_datadir}/icons/hicolor/32x32/apps/firefox.png
+%{_datadir}/icons/hicolor/48x48/apps/firefox.png
+%{_datadir}/icons/hicolor/symbolic/apps/firefox-symbolic.svg
+%if %{enable_mozilla_crashreporter}
+%{mozappdir}/crashreporter
+%{mozappdir}/crashreporter.ini
+%{mozappdir}/minidump-analyzer
+%{mozappdir}/Throbber-small.gif
+%{mozappdir}/browser/crashreporter-override.ini
+%endif
+%{mozappdir}/*.so
+%{mozappdir}/gtk2/*.so
+%{mozappdir}/defaults/pref/channel-prefs.js
+%{mozappdir}/dependentlibs.list
+%{mozappdir}/dictionaries
+%{mozappdir}/omni.ja
+%{mozappdir}/platform.ini
+%{mozappdir}/plugin-container
+%{mozappdir}/gmp-clearkey
+%{mozappdir}/fonts/EmojiOneMozilla.ttf
+%if !%{?system_libicu}
+#%{mozappdir}/icudt*.dat
+%endif
+%if !%{?system_nss}
+%{mozappdir}/libfreeblpriv3.chk
+%{mozappdir}/libnssdbm3.chk
+%{mozappdir}/libsoftokn3.chk
+%exclude %{mozappdir}/libnssckbi.so
+%endif
+%if 0%{use_bundled_ffi}
+%{mozappdir}/bundled/%{_lib}/libffi.so*
+%exclude %{_datadir}/doc/libffi*
+%endif
+
+%if 0%{?bundle_gtk3}
+# gtk3-private-files.inc
+%include_file %{SOURCE204}
+%endif
+
+
+#---------------------------------------------------------------------
+
+%changelog
+* Wed Feb 13 2019 Jan Horak <jhorak@redhat.com> - 60.5.1-1
+- Update to 60.5.1 ESR
+
+* Wed Feb 6 2019 Martin Stransky <stransky@redhat.com> - 60.5.0-3
+- Added fix for rhbz#1672424 - Firefox crashes on NFS drives.
+
+* Fri Jan 25 2019 Martin Stransky <stransky@redhat.com> - 60.5.0-2
+- Updated to 60.5.0 ESR build2
+
+* Tue Jan 22 2019 Martin Stransky <stransky@redhat.com> - 60.5.0-1
+- Updated to 60.5.0 ESR build1
+
+* Thu Jan 10 2019 Jan Horak <jhorak@redhat.com> - 60.4.0-3
+- Fixing fontconfig warnings (rhbz#1601475)
+
+* Wed Jan  9 2019 Jan Horak <jhorak@redhat.com> - 60.4.0-2
+- Added pipewire patch from Tomas Popela (rhbz#1664270)
+
+* Wed Dec  5 2018 Jan Horak <jhorak@redhat.com> - 60.4.0-1
+- Update to 60.4.0 ESR
+
+* Tue Dec  4 2018 Jan Horak <jhorak@redhat.com> - 60.3.0-2
+- Added firefox-gnome-shell-extension
+
+* Fri Oct 19 2018 Jan Horak <jhorak@redhat.com> - 60.3.0-1
+- Update to 60.3.0 ESR
+
+* Wed Oct 10 2018 Jan Horak <jhorak@redhat.com> - 60.2.2-2
+- Added patch for rhbz#1633932
+
+* Tue Oct  2 2018 Jan Horak <jhorak@redhat.com> - 60.2.2-1
+- Update to 60.2.2 ESR
+
+* Mon Sep 24 2018 Jan Horak <jhorak@redhat.com> - 60.2.1-1
+- Update to 60.2.1 ESR
+
+* Fri Aug 31 2018 Jan Horak <jhorak@redhat.com> - 60.2.0-1
+- Update to 60.2.0 ESR
+
+* Tue Aug 28 2018 Jan Horak <jhorak@redhat.com> - 60.1.0-9
+- Do not set user agent (rhbz#1608065)
+- GTK dialogs are localized now (rhbz#1619373)
+- JNLP association works again (rhbz#1607457)
+
+* Thu Aug 16 2018 Jan Horak <jhorak@redhat.com> - 60.1.0-8
+- Fixed homepage and bookmarks (rhbz#1606778)
+- Fixed missing file associations in RHEL6 (rhbz#1613565)
+
+* Thu Jul 12 2018 Jan Horak <jhorak@redhat.com> - 60.1.0-7
+- Run at-spi-bus if not running already (for the bundled gtk3)
+
+* Mon Jul  9 2018 Jan Horak <jhorak@redhat.com> - 60.1.0-6
+- Fix for missing schemes for bundled gtk3
+
+* Mon Jun 25 2018 Martin Stransky <stransky@redhat.com> - 60.1.0-5
+- Added mesa-libEGL dependency to gtk3/rhel6
+
+* Sun Jun 24 2018 Martin Stransky <stransky@redhat.com> - 60.1.0-4
+- Disabled jemalloc on all second arches
+
+* Fri Jun 22 2018 Martin Stransky <stransky@redhat.com> - 60.1.0-3
+- Updated to 60.1.0 ESR build2
+
+* Thu Jun 21 2018 Martin Stransky <stransky@redhat.com> - 60.1.0-2
+- Disabled jemalloc on second arches
+
+* Wed Jun 20 2018 Martin Stransky <stransky@redhat.com> - 60.1.0-1
+- Updated to 60.1.0 ESR
+
+* Wed Jun 13 2018 Jan Horak <jhorak@redhat.com> - 60.0-12
+- Fixing bundled libffi issues
+- Readded some requirements
+
+* Mon Jun 11 2018 Martin Stransky <stransky@redhat.com> - 60.0-10
+- Added fix for mozilla BZ#1436242 - IPC crashes.
+
+* Mon Jun 11 2018 Jan Horak <jhorak@redhat.com> - 60.0-9
+- Bundling libffi for the sec-arches
+- Added openssl-devel for the Python
+- Fixing bundled gtk3
+
+* Fri May 18 2018 Martin Stransky <stransky@redhat.com> - 60.0-8
+- Added fix for mozilla BZ#1458492
+
+* Wed May 16 2018 Martin Stransky <stransky@redhat.com> - 60.0-7
+- Added patch from rhbz#1498561 to fix ppc64(le) crashes.
+
+* Wed May 16 2018 Martin Stransky <stransky@redhat.com> - 60.0-6
+- Disabled jemalloc on second arches
+
+* Sun May  6 2018 Jan Horak <jhorak@redhat.com> - 60.0-4
+- Update to 60.0 ESR
+
+* Thu Mar  8 2018 Jan Horak <jhorak@redhat.com> - 52.7.0-1
+- Update to 52.7.0 ESR
+
+* Mon Jan 29 2018 Martin Stransky <stransky@redhat.com> - 52.6.0-2
+- Build Firefox for desktop arches only (x86_64 and ppc64le)
+
+* Thu Jan 18 2018 Martin Stransky <stransky@redhat.com> - 52.6.0-1
+- Update to 52.6.0 ESR
+
+* Thu Nov  9 2017 Jan Horak <jhorak@redhat.com> - 52.5.0-1
+- Update to 52.5.0 ESR
+
+* Mon Sep 25 2017 Jan Horak <jhorak@redhat.com> - 52.4.0-1
+- Update to 52.4.0 ESR
+
+* Thu Aug  3 2017 Jan Horak <jhorak@redhat.com> - 52.3.0-3
+- Update to 52.3.0 ESR (b2)
+- Require correct nss version
+
+* Tue Jun 13 2017 Jan Horak <jhorak@redhat.com> - 52.2.0-1
+- Update to 52.2.0 ESR
+
+* Wed May 24 2017 Jan Horak <jhorak@redhat.com> - 52.1.2-1
+- Update to 52.1.2 ESR
+
+* Wed May 24 2017 Jan Horak <jhorak@redhat.com> - 52.0-7
+- Added fix for accept language (rhbz#1454322)
+
+* Wed Mar 22 2017 Jan Horak <jhorak@redhat.com> - 52.0-6
+- Removing patch required for older NSS from RHEL 7.3
+- Added patch for rhbz#1414564
+
+* Fri Mar 17 2017 Martin Stransky <stransky@redhat.com> - 52.0-5
+- Added fix for mozbz#1348168/CVE-2017-5428
+
+* Mon Mar  6 2017 Jan Horak <jhorak@redhat.com> - 52.0-4
+- Update to 52.0 ESR (b4)
+
+* Thu Mar 2 2017 Martin Stransky <stransky@redhat.com> - 52.0-3
+- Added fix for rhbz#1423012 - ppc64 gfx crashes
+
+* Wed Mar  1 2017 Jan Horak <jhorak@redhat.com> - 52.0-2
+- Enable system nss
+
+* Tue Feb 28 2017 Martin Stransky <stransky@redhat.com> - 52.0-1
+- Update to 52.0ESR (B1)
+- Build RHEL7 package for Gtk3
+
+* Mon Feb 27 2017 Martin Stransky <stransky@redhat.com> - 52.0-0.13
+- Added fix for rhbz#1414535
+
+* Tue Feb 21 2017 Jan Horak <jhorak@redhat.com> - 52.0-0.12
+- Update to 52.0b8
+
+* Tue Feb  7 2017 Jan Horak <jhorak@redhat.com> - 52.0-0.11
+- Readded addons patch
+
+* Mon Feb  6 2017 Jan Horak <jhorak@redhat.com> - 52.0-0.10
+- Update to 52.0b3
+
+* Tue Jan 31 2017 Jan Horak <jhorak@redhat.com> - 52.0-0.9
+- Update to 52.0b2
+
+* Fri Jan 27 2017 Jan Horak <jhorak@redhat.com> - 52.0-0.8
+- Update to 52.0b1
+
+* Thu Dec  8 2016 Jan Horak <jhorak@redhat.com> - 52.0-0.5
+- Firefox Aurora 52 testing build