diff --git a/.firefox.metadata b/.firefox.metadata new file mode 100644 index 0000000..49c7dde --- /dev/null +++ b/.firefox.metadata @@ -0,0 +1,7 @@ +18a8f30a0356c751b8d0ea6f76e764cab13ee046 SOURCES/Python-2.7.13.tar.xz +733187de6b20f8902fa207f08ec85f952a2c2e40 SOURCES/firefox-60.7.0esr.source.tar.xz +7078da81de13917fa6c4e85f1395552bff67f056 SOURCES/firefox-langpacks-60.7.0esr-20190515.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..09d4148 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +SOURCES/Python-2.7.13.tar.xz +SOURCES/firefox-60.7.0esr.source.tar.xz +SOURCES/firefox-langpacks-60.7.0esr-20190515.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..87d1efc --- /dev/null +++ b/SOURCES/firefox-mozconfig @@ -0,0 +1,30 @@ +. $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-location-service-api-keyfile=../google-api-key +ac_add_options --with-google-safebrowsing-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::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 + #include +@@ -21,80 +18,19 @@ + + #include + ++#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 GetFrame() { return std::move(frame_); } +- +- // Callback interface +- virtual void OnCaptureResult(DesktopCapturer::Result result, +- std::unique_ptr frame) { +- frame_ = std::move(frame); +- } +- +-protected: +- std::unique_ptr screen_capturer_; +- std::unique_ptr 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(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 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::CreateRawAppCapturer( ++std::unique_ptr AppCapturerX11::CreateRawAppCapturer( + const DesktopCaptureOptions& options) { + + if (!options.x_display()) + return nullptr; + +- std::unique_ptr capturer(new AppCapturerLinux(options)); ++ std::unique_ptr capturer(new AppCapturerX11(options)); + + return std::unique_ptr(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 ++#include ++#include ++#include ++ ++#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 GetFrame() { return std::move(frame_); } ++ ++ // Callback interface ++ virtual void OnCaptureResult(DesktopCapturer::Result result, ++ std::unique_ptr frame) { ++ frame_ = std::move(frame); ++ } ++ ++protected: ++ std::unique_ptr screen_capturer_; ++ std::unique_ptr frame_; ++}; ++ ++class AppCapturerX11 : public AppCapturer { ++public: ++ AppCapturerX11(const DesktopCaptureOptions& options); ++ virtual ~AppCapturerX11(); ++ ++ static AppCapturer* Create(const DesktopCaptureOptions& options); ++ static std::unique_ptr 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(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 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 ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#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(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(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(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_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_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(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(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(desktop_size_.width()), ++ static_cast(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_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_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(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(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(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(OnSessionRequested), this); ++} ++ ++// static ++void BaseCapturerPipeWire::OnSessionRequested(GDBusConnection* connection, ++ GAsyncResult* result, ++ gpointer user_data) { ++ BaseCapturerPipeWire* that = ++ static_cast(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(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(OnSourcesRequested), this); ++} ++ ++// static ++void BaseCapturerPipeWire::OnSourcesRequested(GDBusConnection* connection, ++ GAsyncResult* result, ++ gpointer user_data) { ++ BaseCapturerPipeWire* that = ++ static_cast(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(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(OnStartRequested), this); ++} ++ ++// static ++void BaseCapturerPipeWire::OnStartRequested(GDBusConnection* connection, ++ GAsyncResult* result, ++ gpointer user_data) { ++ BaseCapturerPipeWire* that = ++ static_cast(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(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 . ++ 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(OnOpenPipeWireRemoteRequested), ++ this); ++} ++ ++// static ++void BaseCapturerPipeWire::OnOpenPipeWireRemoteRequested( ++ GDBusConnection* connection, ++ GAsyncResult* result, ++ gpointer user_data) { ++ BaseCapturerPipeWire* that = ++ static_cast(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 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 ++#define typeof __typeof__ ++#include ++#include ++ ++#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 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 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 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 + #include + ++#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 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 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 ++#include ++ ++#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 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 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::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 ++ ++namespace webrtc { ++ ++ScreenCapturerPipeWire::ScreenCapturerPipeWire() ++ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} ++ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} ++ ++// static ++std::unique_ptr ++ScreenCapturerPipeWire::CreateRawScreenCapturer( ++ const DesktopCaptureOptions& options) { ++ std::unique_ptr 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 ++ ++#include "webrtc/modules/desktop_capture/base_capturer_pipewire.h" ++ ++namespace webrtc { ++ ++class ScreenCapturerPipeWire : public BaseCapturerPipeWire { ++ public: ++ ScreenCapturerPipeWire(); ++ ~ScreenCapturerPipeWire() override; ++ ++ static std::unique_ptr 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 + #include + ++#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 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 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 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(&event); +@@ -295,7 +211,7 @@ bool ScreenCapturerLinux::HandleXEvent(c + return false; + } + +-std::unique_ptr ScreenCapturerLinux::CaptureScreen() { ++std::unique_ptr ScreenCapturerX11::CaptureScreen() { + std::unique_ptr frame = queue_.current_frame()->Share(); + RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size())); + +@@ -345,14 +261,15 @@ std::unique_ptr 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::CreateRawScreenCapturer( ++std::unique_ptr ScreenCapturerX11::CreateRawScreenCapturer( + const DesktopCaptureOptions& options) { + if (!options.x_display()) + return nullptr; + +- std::unique_ptr capturer(new ScreenCapturerLinux()); ++ std::unique_ptr capturer(new ScreenCapturerX11()); + if (!capturer.get()->Init(options)) { + return nullptr; + } + +- return std::unique_ptr(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 ++#include ++#include ++#include ++#include ++ ++#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 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 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 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::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 ++WindowCapturerPipeWire::CreateRawWindowCapturer( ++ const DesktopCaptureOptions& options) { ++ std::unique_ptr 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 ++ ++#include "webrtc/modules/desktop_capture/base_capturer_pipewire.h" ++ ++namespace webrtc { ++ ++class WindowCapturerPipeWire : public BaseCapturerPipeWire { ++ public: ++ WindowCapturerPipeWire(); ++ ~WindowCapturerPipeWire() override; ++ ++ static std::unique_ptr 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 + ++#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 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 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 process_id(display(), window, process_atom); +@@ -401,11 +350,11 @@ int WindowCapturerLinux::GetWindowProces + } + + // static +-std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( ++std::unique_ptr WindowCapturerX11::CreateRawWindowCapturer( + const DesktopCaptureOptions& options) { + if (!options.x_display()) + return nullptr; +- return std::unique_ptr(new WindowCapturerLinux(options)); ++ return std::unique_ptr(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 ++#include ++#include ++#include ++ ++#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 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 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]=نْو پرایوٹ وینڈو& +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//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 ++#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 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//pref/ directory if it exists ++ nsCOMPtr 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 +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 +# 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-526293.patch b/SOURCES/mozilla-526293.patch new file mode 100644 index 0000000..a03796a --- /dev/null +++ b/SOURCES/mozilla-526293.patch @@ -0,0 +1,14 @@ +diff -up firefox-60.6.0/widget/gtk/nsFilePicker.cpp.old firefox-60.6.0/widget/gtk/nsFilePicker.cpp +--- firefox-60.6.0/widget/gtk/nsFilePicker.cpp.old 2019-03-27 10:29:47.918560620 +0100 ++++ firefox-60.6.0/widget/gtk/nsFilePicker.cpp 2019-03-27 10:30:08.384491717 +0100 +@@ -366,9 +366,7 @@ nsFilePicker::Open(nsIFilePickerShownCal + // If we have --enable-proxy-bypass-protection, then don't allow + // remote URLs to be used. + #ifndef MOZ_PROXY_BYPASS_PROTECTION +- if (mAllowURLs) { +- gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(file_chooser), FALSE); +- } ++ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(file_chooser), FALSE); + #endif + + if (action == GTK_FILE_CHOOSER_ACTION_OPEN || 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..25b7f82 --- /dev/null +++ b/SPECS/firefox.spec @@ -0,0 +1,1408 @@ +# 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.7.0 +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}-20190515.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 +Patch232: mozilla-526293.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 +%patch232 -p1 -b .mozilla-526293 + +# 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 < + + + + firefox.desktop + CC0-1.0 + +

+ 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. +

+ +
+ http://www.mozilla.org/ + + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/a.png + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/b.png + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/c.png + + +
+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 May 15 2019 Martin Stransky - 60.7.0-1 +- Updated to 60.7.0 ESR + +* Thu May 9 2019 Martin Stransky - 60.6.3-1 +- Updated to 60.6.3 ESR + +* Tue May 7 2019 Martin Stransky - 60.6.2-1 +- Updated to 60.6.2 ESR + +* Mon Mar 27 2019 Martin Stransky - 60.6.1-2 +- Added fix for mozbz#526293 - show remote locations on file chooser dialog. + +* Mon Mar 25 2019 Martin Stransky - 60.6.1-1 +- Update to 60.6.1 ESR (Build 1) + +* Fri Mar 15 2019 Martin Stransky - 60.6.0-3 +- Added Google API keys (mozbz#1531176) + +* Thu Mar 14 2019 Martin Stransky - 60.6.0-2 +- Update to 60.6.0 ESR (Build 2) + +* Wed Mar 13 2019 Martin Stransky - 60.6.0-1 +- Update to 60.6.0 ESR (Build 1) + +* Wed Feb 13 2019 Jan Horak - 60.5.1-1 +- Update to 60.5.1 ESR + +* Wed Feb 6 2019 Martin Stransky - 60.5.0-3 +- Added fix for rhbz#1672424 - Firefox crashes on NFS drives. + +* Fri Jan 25 2019 Martin Stransky - 60.5.0-2 +- Updated to 60.5.0 ESR build2 + +* Tue Jan 22 2019 Martin Stransky - 60.5.0-1 +- Updated to 60.5.0 ESR build1 + +* Thu Jan 10 2019 Jan Horak - 60.4.0-3 +- Fixing fontconfig warnings (rhbz#1601475) + +* Wed Jan 9 2019 Jan Horak - 60.4.0-2 +- Added pipewire patch from Tomas Popela (rhbz#1664270) + +* Wed Dec 5 2018 Jan Horak - 60.4.0-1 +- Update to 60.4.0 ESR + +* Tue Dec 4 2018 Jan Horak - 60.3.0-2 +- Added firefox-gnome-shell-extension + +* Fri Oct 19 2018 Jan Horak - 60.3.0-1 +- Update to 60.3.0 ESR + +* Wed Oct 10 2018 Jan Horak - 60.2.2-2 +- Added patch for rhbz#1633932 + +* Tue Oct 2 2018 Jan Horak - 60.2.2-1 +- Update to 60.2.2 ESR + +* Mon Sep 24 2018 Jan Horak - 60.2.1-1 +- Update to 60.2.1 ESR + +* Fri Aug 31 2018 Jan Horak - 60.2.0-1 +- Update to 60.2.0 ESR + +* Tue Aug 28 2018 Jan Horak - 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 - 60.1.0-8 +- Fixed homepage and bookmarks (rhbz#1606778) +- Fixed missing file associations in RHEL6 (rhbz#1613565) + +* Thu Jul 12 2018 Jan Horak - 60.1.0-7 +- Run at-spi-bus if not running already (for the bundled gtk3) + +* Mon Jul 9 2018 Jan Horak - 60.1.0-6 +- Fix for missing schemes for bundled gtk3 + +* Mon Jun 25 2018 Martin Stransky - 60.1.0-5 +- Added mesa-libEGL dependency to gtk3/rhel6 + +* Sun Jun 24 2018 Martin Stransky - 60.1.0-4 +- Disabled jemalloc on all second arches + +* Fri Jun 22 2018 Martin Stransky - 60.1.0-3 +- Updated to 60.1.0 ESR build2 + +* Thu Jun 21 2018 Martin Stransky - 60.1.0-2 +- Disabled jemalloc on second arches + +* Wed Jun 20 2018 Martin Stransky - 60.1.0-1 +- Updated to 60.1.0 ESR + +* Wed Jun 13 2018 Jan Horak - 60.0-12 +- Fixing bundled libffi issues +- Readded some requirements + +* Mon Jun 11 2018 Martin Stransky - 60.0-10 +- Added fix for mozilla BZ#1436242 - IPC crashes. + +* Mon Jun 11 2018 Jan Horak - 60.0-9 +- Bundling libffi for the sec-arches +- Added openssl-devel for the Python +- Fixing bundled gtk3 + +* Fri May 18 2018 Martin Stransky - 60.0-8 +- Added fix for mozilla BZ#1458492 + +* Wed May 16 2018 Martin Stransky - 60.0-7 +- Added patch from rhbz#1498561 to fix ppc64(le) crashes. + +* Wed May 16 2018 Martin Stransky - 60.0-6 +- Disabled jemalloc on second arches + +* Sun May 6 2018 Jan Horak - 60.0-4 +- Update to 60.0 ESR + +* Thu Mar 8 2018 Jan Horak - 52.7.0-1 +- Update to 52.7.0 ESR + +* Mon Jan 29 2018 Martin Stransky - 52.6.0-2 +- Build Firefox for desktop arches only (x86_64 and ppc64le) + +* Thu Jan 18 2018 Martin Stransky - 52.6.0-1 +- Update to 52.6.0 ESR + +* Thu Nov 9 2017 Jan Horak - 52.5.0-1 +- Update to 52.5.0 ESR + +* Mon Sep 25 2017 Jan Horak - 52.4.0-1 +- Update to 52.4.0 ESR + +* Thu Aug 3 2017 Jan Horak - 52.3.0-3 +- Update to 52.3.0 ESR (b2) +- Require correct nss version + +* Tue Jun 13 2017 Jan Horak - 52.2.0-1 +- Update to 52.2.0 ESR + +* Wed May 24 2017 Jan Horak - 52.1.2-1 +- Update to 52.1.2 ESR + +* Wed May 24 2017 Jan Horak - 52.0-7 +- Added fix for accept language (rhbz#1454322) + +* Wed Mar 22 2017 Jan Horak - 52.0-6 +- Removing patch required for older NSS from RHEL 7.3 +- Added patch for rhbz#1414564 + +* Fri Mar 17 2017 Martin Stransky - 52.0-5 +- Added fix for mozbz#1348168/CVE-2017-5428 + +* Mon Mar 6 2017 Jan Horak - 52.0-4 +- Update to 52.0 ESR (b4) + +* Thu Mar 2 2017 Martin Stransky - 52.0-3 +- Added fix for rhbz#1423012 - ppc64 gfx crashes + +* Wed Mar 1 2017 Jan Horak - 52.0-2 +- Enable system nss + +* Tue Feb 28 2017 Martin Stransky - 52.0-1 +- Update to 52.0ESR (B1) +- Build RHEL7 package for Gtk3 + +* Mon Feb 27 2017 Martin Stransky - 52.0-0.13 +- Added fix for rhbz#1414535 + +* Tue Feb 21 2017 Jan Horak - 52.0-0.12 +- Update to 52.0b8 + +* Tue Feb 7 2017 Jan Horak - 52.0-0.11 +- Readded addons patch + +* Mon Feb 6 2017 Jan Horak - 52.0-0.10 +- Update to 52.0b3 + +* Tue Jan 31 2017 Jan Horak - 52.0-0.9 +- Update to 52.0b2 + +* Fri Jan 27 2017 Jan Horak - 52.0-0.8 +- Update to 52.0b1 + +* Thu Dec 8 2016 Jan Horak - 52.0-0.5 +- Firefox Aurora 52 testing build