diff --git a/.gitignore b/.gitignore
index d139924..f22940f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,12 @@
 SOURCES/Python-2.7.13.tar.xz
-SOURCES/Python-3.6.8.tar.xz
+SOURCES/cbindgen-vendor-0.14.3.tar.xz
 SOURCES/cbindgen-vendor.tar.xz
 SOURCES/gtk3-private-3.22.26-1.el6.src.rpm
 SOURCES/libffi-3.0.13-18.el7_3.src.rpm
-SOURCES/lightning-langpacks-68.11.0.tar.xz
-SOURCES/nodejs-8.11.4-1.3.fc27.src.rpm
+SOURCES/nodejs-10.21.0-4.fc32.src.rpm
+SOURCES/nspr-4.25.0-1.el8_0.src.rpm
+SOURCES/nss-3.53.1-3.fc32.src.rpm
 SOURCES/openssl-1.0.2k-19.6.bundle.el7_7.src.rpm
-SOURCES/thunderbird-68.11.0.source.tar.xz
-SOURCES/thunderbird-langpacks-68.11.0-20200804.tar.xz
+SOURCES/thunderbird-78.2.1.source.tar.xz
+SOURCES/thunderbird-langpacks-78.2.1-20200908.tar.xz
 SOURCES/yasm-1.2.0-3.el5.src.rpm
diff --git a/.thunderbird.metadata b/.thunderbird.metadata
index fa1d651..baa22d6 100644
--- a/.thunderbird.metadata
+++ b/.thunderbird.metadata
@@ -1,11 +1,12 @@
 18a8f30a0356c751b8d0ea6f76e764cab13ee046 SOURCES/Python-2.7.13.tar.xz
-ee55acedef049268307633cbc9c7ff0610d1244f SOURCES/Python-3.6.8.tar.xz
+a9effcc06cf80eaa22f12c1f7d6aa4266a1c4966 SOURCES/cbindgen-vendor-0.14.3.tar.xz
 e86c38c48960b95353503b78e1de9ddca1ed34d7 SOURCES/cbindgen-vendor.tar.xz
 0de63f863b158454b9429234b52ed28a397ec45c SOURCES/gtk3-private-3.22.26-1.el6.src.rpm
 e188ab1a444697bc649e223c28389d82ca94c472 SOURCES/libffi-3.0.13-18.el7_3.src.rpm
-8476c6e7c27eba1836581ad86fc504e4853f077b SOURCES/lightning-langpacks-68.11.0.tar.xz
-4f8d3bf2483d95261ff90742ecec82d6a899eca3 SOURCES/nodejs-8.11.4-1.3.fc27.src.rpm
+5715f987bc0024ce5d72993cb101b8268350033b SOURCES/nodejs-10.21.0-4.fc32.src.rpm
+07d67c90367c3ec0d6cebc1a5793c21076d34b78 SOURCES/nspr-4.25.0-1.el8_0.src.rpm
+223c02166b1cb9863b9f453ef687d7805a93e7af SOURCES/nss-3.53.1-3.fc32.src.rpm
 a379070abf5000cde61411c97af7e733b267a4d3 SOURCES/openssl-1.0.2k-19.6.bundle.el7_7.src.rpm
-7b5764677819ca27af51b5e9b4be0d8180a8bfed SOURCES/thunderbird-68.11.0.source.tar.xz
-627fbe742a97fcfa7b4b08c8e9688b95a043bcba SOURCES/thunderbird-langpacks-68.11.0-20200804.tar.xz
+a08e673de7c008e4725b4157f25b44482e0be54e SOURCES/thunderbird-78.2.1.source.tar.xz
+8405170c497a835ecb0daa496cb064f6d3f7b4ad SOURCES/thunderbird-langpacks-78.2.1-20200908.tar.xz
 77fd30f7ebc12a629a31c1e252cec06af55a71fe SOURCES/yasm-1.2.0-3.el5.src.rpm
diff --git a/SOURCES/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch b/SOURCES/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch
deleted file mode 100644
index 6dfe2ad..0000000
--- a/SOURCES/Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -up firefox-60.0/mfbt/LinuxSignal.h.mozilla-1238661 firefox-60.0/mfbt/LinuxSignal.h
---- firefox-60.0/mfbt/LinuxSignal.h.mozilla-1238661	2018-04-27 08:55:38.848241768 +0200
-+++ firefox-60.0/mfbt/LinuxSignal.h	2018-04-27 09:06:47.946769859 +0200
-@@ -22,7 +22,7 @@ __attribute__((naked)) void SignalTrampo
-                                              void* aContext) {
-   asm volatile("nop; nop; nop; nop" : : : "memory");
- 
--  asm volatile("b %0" : : "X"(H) : "memory");
-+  asm volatile("bx %0" : : "r"(H), "l"(aSignal), "l"(aInfo), "l"(aContext) : "memory");
- }
- 
- #  define MOZ_SIGNAL_TRAMPOLINE(h) (mozilla::SignalTrampoline<h>)
diff --git a/SOURCES/Bug-1526653---fix_user_vfp_armv7.patch b/SOURCES/Bug-1526653---fix_user_vfp_armv7.patch
deleted file mode 100644
index 3f84f95..0000000
--- a/SOURCES/Bug-1526653---fix_user_vfp_armv7.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From fd6847c9416f9eebde636e21d794d25d1be8791d Mon Sep 17 00:00:00 2001
-From: Mike Hommey <mh@glandium.org>
-Date: Sat, 1 Jun 2019 09:06:01 +0900
-Subject: [PATCH] Bug 1526653 - Include struct definitions for user_vfp and
- user_vfp_exc.
-
----
- js/src/wasm/WasmSignalHandlers.cpp | 11 ++++++++++-
- 1 file changed, 10 insertions(+), 1 deletion(-)
-
-diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp
-index 636537f8478..383c380f04c 100644
---- a/js/src/wasm/WasmSignalHandlers.cpp
-+++ b/js/src/wasm/WasmSignalHandlers.cpp
-@@ -248,7 +248,16 @@ using mozilla::DebugOnly;
- #endif
- 
- #ifdef WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS
--#  include <sys/user.h>
-+struct user_vfp {
-+  unsigned long long fpregs[32];
-+  unsigned long fpscr;
-+};
-+
-+struct user_vfp_exc {
-+  unsigned long fpexc;
-+  unsigned long fpinst;
-+  unsigned long fpinst2;
-+};
- #endif
- 
- #if defined(ANDROID)
--- 
-2.20.1
-
diff --git a/SOURCES/D87019-thin-vec-big-endian.diff b/SOURCES/D87019-thin-vec-big-endian.diff
new file mode 100644
index 0000000..bc8589b
--- /dev/null
+++ b/SOURCES/D87019-thin-vec-big-endian.diff
@@ -0,0 +1,767 @@
+diff -up firefox-78.1.0/Cargo.lock.D87019-thin-vec-big-endian.diff firefox-78.1.0/Cargo.lock
+--- firefox-78.1.0/Cargo.lock.D87019-thin-vec-big-endian.diff	2020-07-22 19:56:54.000000000 +0200
++++ firefox-78.1.0/Cargo.lock	2020-08-17 17:04:24.133598583 +0200
+@@ -4792,12 +4792,9 @@ checksum = "8eaa81235c7058867fa8c0e7314f
+ 
+ [[package]]
+ name = "thin-vec"
+-version = "0.1.0"
++version = "0.2.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "73fdf4b84c65a85168477b7fb6c498e0716bc9487fba24623389ea7f51708044"
+-dependencies = [
+- "libc",
+-]
++checksum = "dcc760ada4a9f56fc6d0e81bd143984ebc7bb1b875a6891aa2fa613ca7394fc0"
+ 
+ [[package]]
+ name = "thiserror"
+diff -up firefox-78.1.0/gfx/webrender_bindings/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/gfx/webrender_bindings/Cargo.toml
+--- firefox-78.1.0/gfx/webrender_bindings/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-08-17 17:04:24.133598583 +0200
++++ firefox-78.1.0/gfx/webrender_bindings/Cargo.toml	2020-08-17 17:05:26.984805590 +0200
+@@ -20,7 +20,7 @@ nsstring = { path = "../../xpcom/rust/ns
+ bincode = "1.0"
+ uuid = { version = "0.8", features = ["v4"] }
+ fxhash = "0.2.1"
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ swgl = { path = "../wr/swgl" }
+ 
+ [dependencies.webrender]
+diff -up firefox-78.1.0/intl/l10n/rust/fluent-ffi/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/intl/l10n/rust/fluent-ffi/Cargo.toml
+--- firefox-78.1.0/intl/l10n/rust/fluent-ffi/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:20.000000000 +0200
++++ firefox-78.1.0/intl/l10n/rust/fluent-ffi/Cargo.toml	2020-08-17 17:04:24.134598587 +0200
+@@ -10,4 +10,4 @@ fluent-pseudo = "0.2"
+ intl-memoizer = "0.4"
+ unic-langid = "0.8"
+ nsstring = { path = "../../../../xpcom/rust/nsstring" }
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+diff -up firefox-78.1.0/intl/locale/rust/fluent-langneg-ffi/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/intl/locale/rust/fluent-langneg-ffi/Cargo.toml
+--- firefox-78.1.0/intl/locale/rust/fluent-langneg-ffi/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:20.000000000 +0200
++++ firefox-78.1.0/intl/locale/rust/fluent-langneg-ffi/Cargo.toml	2020-08-17 17:04:24.134598587 +0200
+@@ -9,7 +9,7 @@ edition = "2018"
+ nserror = { path = "../../../../xpcom/rust/nserror" }
+ nsstring = { path = "../../../../xpcom/rust/nsstring" }
+ xpcom = { path = "../../../../xpcom/rust/xpcom" }
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ fluent-langneg = { version = "0.12.1", features = ["cldr"] }
+ unic-langid = "0.8"
+ unic-langid-ffi = { path = "../unic-langid-ffi" }
+diff -up firefox-78.1.0/intl/locale/rust/unic-langid-ffi/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/intl/locale/rust/unic-langid-ffi/Cargo.toml
+--- firefox-78.1.0/intl/locale/rust/unic-langid-ffi/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:20.000000000 +0200
++++ firefox-78.1.0/intl/locale/rust/unic-langid-ffi/Cargo.toml	2020-08-17 17:04:24.134598587 +0200
+@@ -9,5 +9,5 @@ edition = "2018"
+ nserror = { path = "../../../../xpcom/rust/nserror" }
+ nsstring = { path = "../../../../xpcom/rust/nsstring" }
+ xpcom = { path = "../../../../xpcom/rust/xpcom" }
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ unic-langid = { version = "0.8", features = ["likelysubtags"] }
+diff -up firefox-78.1.0/netwerk/socket/neqo_glue/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/netwerk/socket/neqo_glue/Cargo.toml
+--- firefox-78.1.0/netwerk/socket/neqo_glue/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-08-17 17:04:24.134598587 +0200
++++ firefox-78.1.0/netwerk/socket/neqo_glue/Cargo.toml	2020-08-17 17:05:10.352750807 +0200
+@@ -14,7 +14,7 @@ neqo-common = { tag = "v0.2.4", git = "h
+ nserror = { path = "../../../xpcom/rust/nserror" }
+ nsstring = { path = "../../../xpcom/rust/nsstring" }
+ xpcom = { path = "../../../xpcom/rust/xpcom" }
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ 
+ [dependencies.neqo-crypto]
+ tag = "v0.2.4"
+diff -up firefox-78.1.0/security/manager/ssl/cert_storage/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/security/manager/ssl/cert_storage/Cargo.toml
+--- firefox-78.1.0/security/manager/ssl/cert_storage/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 19:56:55.000000000 +0200
++++ firefox-78.1.0/security/manager/ssl/cert_storage/Cargo.toml	2020-08-17 17:04:24.134598587 +0200
+@@ -18,6 +18,6 @@ rust_cascade = "0.6.0"
+ sha2 = "^0.8"
+ storage_variant = { path = "../../../../storage/variant" }
+ tempfile = "3"
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ time = "0.1"
+ xpcom = { path = "../../../../xpcom/rust/xpcom" }
+diff -up firefox-78.1.0/services/fxaccounts/rust-bridge/firefox-accounts-bridge/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/services/fxaccounts/rust-bridge/firefox-accounts-bridge/Cargo.toml
+--- firefox-78.1.0/services/fxaccounts/rust-bridge/firefox-accounts-bridge/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-08-17 17:04:24.134598587 +0200
++++ firefox-78.1.0/services/fxaccounts/rust-bridge/firefox-accounts-bridge/Cargo.toml	2020-08-17 17:04:52.432691786 +0200
+@@ -20,5 +20,5 @@ nserror = { path = "../../../../xpcom/ru
+ nsstring = { path = "../../../../xpcom/rust/nsstring" }
+ xpcom = { path = "../../../../xpcom/rust/xpcom" }
+ storage_variant = { path = "../../../../storage/variant" }
+-thin-vec = { version = "0.1", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ fxa-client = { git = "https://github.com/mozilla/application-services", rev = "61dcc364ac0d6d0816ab88a494bbf20d824b009b", features = ["gecko"] }
+diff -up firefox-78.1.0/services/sync/golden_gate/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/services/sync/golden_gate/Cargo.toml
+--- firefox-78.1.0/services/sync/golden_gate/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:24.000000000 +0200
++++ firefox-78.1.0/services/sync/golden_gate/Cargo.toml	2020-08-17 17:04:24.134598587 +0200
+@@ -19,5 +19,5 @@ sync15-traits = { git = "https://github.
+ xpcom = { path = "../../../xpcom/rust/xpcom" }
+ 
+ [dependencies.thin-vec]
+-version = "0.1.0"
++version = "0.2.1"
+ features = ["gecko-ffi"]
+diff -up firefox-78.1.0/third_party/rust/thin-vec/.cargo-checksum.json.D87019-thin-vec-big-endian.diff firefox-78.1.0/third_party/rust/thin-vec/.cargo-checksum.json
+--- firefox-78.1.0/third_party/rust/thin-vec/.cargo-checksum.json.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:29.000000000 +0200
++++ firefox-78.1.0/third_party/rust/thin-vec/.cargo-checksum.json	2020-08-17 17:04:24.134598587 +0200
+@@ -1 +1 @@
+-{"files":{"Cargo.toml":"fb96cad605ae48215811808c1cc1b9a50248f2b14542058094b23983e2f8d8a0","README.md":"c26d7101e3031e7dd8890ce938e50cad7a1e6adf7fc2f2b0d3c36b03afe68c0b","src/heap.rs":"fe84a4ff433568d5713685456d87597ac5dcdb9d5190061a3da8074240ba1bc3","src/lib.rs":"ce36db8e3464dddade7c1ddbe3ee1f5e525af5be492ea51a0d8a0776c1adfc28","src/range.rs":"bac59bcb6230367a39c7e28ac15263e4526f966cd8c72015873017f17c115aaa"},"package":"73fdf4b84c65a85168477b7fb6c498e0716bc9487fba24623389ea7f51708044"}
+\ No newline at end of file
++{"files":{"Cargo.toml":"754c05523d17eb7591c3ea2c9294e47c05fbb257fed04b78546fb2ec7cafa8b4","README.md":"c26d7101e3031e7dd8890ce938e50cad7a1e6adf7fc2f2b0d3c36b03afe68c0b","src/lib.rs":"627c6094c3f0286dba25bc73f5672c06c5061c25b01c513d213cbdda100673a2"},"package":"dcc760ada4a9f56fc6d0e81bd143984ebc7bb1b875a6891aa2fa613ca7394fc0"}
+\ No newline at end of file
+diff -up firefox-78.1.0/third_party/rust/thin-vec/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/third_party/rust/thin-vec/Cargo.toml
+--- firefox-78.1.0/third_party/rust/thin-vec/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:29.000000000 +0200
++++ firefox-78.1.0/third_party/rust/thin-vec/Cargo.toml	2020-08-17 17:04:24.135598590 +0200
+@@ -3,7 +3,7 @@
+ # When uploading crates to the registry Cargo will automatically
+ # "normalize" Cargo.toml files for maximal compatibility
+ # with all versions of Cargo and also rewrite `path` dependencies
+-# to registry (e.g. crates.io) dependencies
++# to registry (e.g., crates.io) dependencies
+ #
+ # If you believe there's an error in this file please file an
+ # issue against the rust-lang/cargo repository. If you're
+@@ -11,16 +11,17 @@
+ # will likely look very different (and much more reasonable)
+ 
+ [package]
++edition = "2018"
+ name = "thin-vec"
+-version = "0.1.0"
++version = "0.2.1"
+ authors = ["Alexis Beingessner <a.beingessner@gmail.com>"]
+ description = "a vec that takes up less space on the stack"
+ homepage = "https://github.com/gankro/thin-vec"
+ readme = "README.md"
+ license = "MIT/Apache-2.0"
+ repository = "https://github.com/gankro/thin-vec"
+-[dependencies.libc]
+-version = "0.2"
++
++[dependencies]
+ 
+ [features]
+ default = []
+diff -up firefox-78.1.0/third_party/rust/thin-vec/src/heap.rs.D87019-thin-vec-big-endian.diff firefox-78.1.0/third_party/rust/thin-vec/src/heap.rs
+diff -up firefox-78.1.0/third_party/rust/thin-vec/src/lib.rs.D87019-thin-vec-big-endian.diff firefox-78.1.0/third_party/rust/thin-vec/src/lib.rs
+--- firefox-78.1.0/third_party/rust/thin-vec/src/lib.rs.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:28.000000000 +0200
++++ firefox-78.1.0/third_party/rust/thin-vec/src/lib.rs	2020-08-17 17:04:24.135598590 +0200
+@@ -1,50 +1,252 @@
+-mod range;
++//! ThinVec is exactly the same as Vec, except that it stores its `len` and `capacity` in the buffer
++//! it allocates.
++//!
++//! This makes the memory footprint of ThinVecs lower; notably in cases where space is reserved for
++//! a non-existence ThinVec<T>. So `Vec<ThinVec<T>>` and `Option<ThinVec<T>>::None` will waste less
++//! space. Being pointer-sized also means it can be passed/stored in registers.
++//!
++//! Of course, any actually constructed ThinVec will theoretically have a bigger allocation, but
++//! the fuzzy nature of allocators means that might not actually be the case.
++//!
++//! Properties of Vec that are preserved:
++//! * `ThinVec::new()` doesn't allocate (it points to a statically allocated singleton)
++//! * reallocation can be done in place
++//! * `size_of::<ThinVec<T>>()` == `size_of::<Option<ThinVec<T>>>()`
++//!
++//! Properties of Vec that aren't preserved:
++//! * `ThinVec<T>` can't ever be zero-cost roundtripped to a `Box<[T]>`, `String`, or `*mut T`
++//! * `from_raw_parts` doesn't exist
++//! * ThinVec currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
++//!   but it could be done if someone cared enough to implement it.
++//!
++//!
++//!
++//! # Gecko FFI
++//!
++//! If you enable the gecko-ffi feature, ThinVec will verbatim bridge with the nsTArray type in
++//! Gecko (Firefox). That is, ThinVec and nsTArray have identical layouts *but not ABIs*, 
++//! so nsTArrays/ThinVecs an be natively manipulated by C++ and Rust, and ownership can be 
++//! transferred across the FFI boundary (**IF YOU ARE CAREFUL, SEE BELOW!!**).
++//!
++//! While this feature is handy, it is also inherently dangerous to use because Rust and C++ do not
++//! know about eachother. Specifically, this can be an issue with non-POD types (types which
++//! have destructors, move constructors, or are `!Copy`).
++//!
++//! ## Do Not Pass By Value
++//!
++//! The biggest thing to keep in mind is that **FFI functions cannot pass ThinVec/nsTArray 
++//! by-value**. That is, these are busted APIs:
++//!
++//! ```rust,ignore
++//! // BAD WRONG
++//! extern fn process_data(data: ThinVec<u32>) { ... }
++//! // BAD WRONG
++//! extern fn get_data() -> ThinVec<u32> { ... }
++//! ```
++//!
++//! You must instead pass by-reference:
++//!
++//! ```rust
++//! # use thin_vec::*;
++//! # use std::mem;
++//!
++//! // Read-only access, ok!
++//! extern fn process_data(data: &ThinVec<u32>) {
++//!     for val in data {
++//!         println!("{}", val);
++//!     }
++//! }
++//! 
++//! // Replace with empty instance to take ownership, ok!
++//! extern fn consume_data(data: &mut ThinVec<u32>) {
++//!     let owned = mem::replace(data, ThinVec::new());
++//!     mem::drop(owned);
++//! }
++//! 
++//! // Mutate input, ok!
++//! extern fn add_data(dataset: &mut ThinVec<u32>) {
++//!     dataset.push(37);
++//!     dataset.push(12);
++//! }
++//! 
++//! // Return via out-param, usually ok!
++//! //
++//! // WARNING: output must be initialized! (Empty nsTArrays are free, so just do it!)
++//! extern fn get_data(output: &mut ThinVec<u32>) {
++//!     *output = thin_vec![1, 2, 3, 4, 5];
++//! }
++//! ```
++//!
++//! Ignorable Explanation For Those Who Really Want To Know Why:
++//!
++//! > The fundamental issue is that Rust and C++ can't currently communicate about destructors, and
++//! > the semantics of C++ require destructors of function arguments to be run when the function
++//! > returns. Whether the callee or caller is responsible for this is also platform-specific, so
++//! > trying to hack around it manually would be messy. 
++//! >
++//! > Also a type having a destructor changes its C++ ABI, because that type must actually exist 
++//! > in memory (unlike a trivial struct, which is often passed in registers). We don't currently
++//! > have a way to communicate to Rust that this is happening, so even if we worked out the
++//! > destructor issue with say, MaybeUninit, it would still be a non-starter without some RFCs
++//! > to add explicit rustc support.
++//! >
++//! > Realistically, the best answer here is to have a "heavier" bindgen that can secretly
++//! > generate FFI glue so we can pass things "by value" and have it generate by-reference code
++//! > behind our back (like the cxx crate does). This would muddy up debugging/searchfox though.
++//!
++//! ## Types Should Be Trivially Relocatable
++//!
++//! Types in Rust are always trivially relocatable (unless suitably borrowed/[pinned][]/hidden).
++//! This means all Rust types are legal to relocate with a bitwise copy, you cannot provide
++//! copy or move constructors to execute when this happens, and the old location won't have its
++//! destructor run. This will cause problems for types which have a significant location
++//! (types that intrusively point into themselves or have their location registered with a service).
++//!
++//! While relocations are generally predictable if you're very careful, **you should avoid using
++//! types with significant locations with Rust FFI**.
++//!
++//! Specifically, ThinVec will trivially relocate its contents whenever it needs to reallocate its
++//! buffer to change its capacity. This is the default reallocation strategy for nsTArray, and is
++//! suitable for the vast majority of types. Just be aware of this limitation!
++//!
++//! ## Auto Arrays Are Dangerous
++//!
++//! ThinVec has *some* support for handling auto arrays which store their buffer on the stack, 
++//! but this isn't well tested.
++//!
++//! Regardless of how much support we provide, Rust won't be aware of the buffer's limited lifetime,
++//! so standard auto array safety caveats apply about returning/storing them! ThinVec won't ever
++//! produce an auto array on its own, so this is only an issue for transferring an nsTArray into
++//! Rust.
++//!
++//! ## Other Issues
++//!
++//! Standard FFI caveats also apply: 
++//!
++//!  * Rust is more strict about POD types being initialized (use MaybeUninit if you must)
++//!  * `ThinVec<T>` has no idea if the C++ version of `T` has move/copy/assign/delete overloads
++//!  * `nsTArray<T>` has no idea if the Rust version of `T` has a Drop/Clone impl
++//!  * C++ can do all sorts of unsound things that Rust can't catch
++//!  * C++ and Rust don't agree on how zero-sized/empty types should be handled
++//!
++//! The gecko-ffi feature will not work if you aren't linking with code that has nsTArray
++//! defined. Specifically, we must share the symbol for nsTArray's empty singleton. You will get
++//! linking errors if that isn't defined.
++//!
++//! The gecko-ffi feature also limits ThinVec to the legacy behaviors of nsTArray. Most notably,
++//! nsTArray has a maximum capacity of i32::MAX (~2.1 billion items). Probably not an issue.
++//! Probably.
++//!
++//! [pinned]: https://doc.rust-lang.org/std/pin/index.html
+ 
+ use std::{fmt, io, ptr, mem, slice};
+ use std::collections::Bound;
+ use std::iter::FromIterator;
+ use std::slice::IterMut;
+-use std::ops::{Deref, DerefMut};
++use std::ops::{Deref, DerefMut, RangeBounds};
+ use std::marker::PhantomData;
++use std::alloc::*;
+ use std::cmp::*;
+ use std::hash::*;
+ use std::borrow::*;
+-use range::RangeArgument;
+ use std::ptr::NonNull;
+ 
+-// Heap shimming because reasons. This doesn't unfortunately match the heap api
+-// right now because reasons.
+-mod heap;
++use impl_details::*;
+ 
+-#[cfg(not(feature = "gecko-ffi"))]
+-type SizeType = usize;
+-#[cfg(feature = "gecko-ffi")]
+-type SizeType = u32;
+-
+-#[cfg(feature = "gecko-ffi")]
+-const AUTO_MASK: u32 = 1 << 31;
+-#[cfg(feature = "gecko-ffi")]
+-const CAP_MASK: u32 = !AUTO_MASK;
++// modules: a simple way to cfg a whole bunch of impl details at once
+ 
+ #[cfg(not(feature = "gecko-ffi"))]
+-const MAX_CAP: usize = !0;
+-#[cfg(feature = "gecko-ffi")]
+-const MAX_CAP: usize = i32::max_value() as usize;
++mod impl_details {
++    pub type SizeType = usize;
++    pub const MAX_CAP: usize = !0;
+ 
+-#[cfg(not(feature = "gecko-ffi"))]
+-#[inline(always)]
+-fn assert_size(x: usize) -> SizeType { x }
++    #[inline(always)]
++    pub fn assert_size(x: usize) -> SizeType { x }
++}
+ 
+ #[cfg(feature = "gecko-ffi")]
+-#[inline]
+-fn assert_size(x: usize) -> SizeType {
+-    if x > MAX_CAP as usize {
+-        panic!("nsTArray size may not exceed the capacity of a 32-bit sized int");
++mod impl_details {
++    // Support for briding a gecko nsTArray verbatim into a ThinVec.
++    //
++    // ThinVec can't see copy/move/delete implementations
++    // from C++
++    //
++    // The actual layout of an nsTArray is:
++    //
++    // ```cpp
++    // struct {
++    //   uint32_t mLength;
++    //   uint32_t mCapacity: 31;
++    //   uint32_t mIsAutoArray: 1;
++    // }
++    // ```
++    //
++    // Rust doesn't natively support bit-fields, so we manually mask
++    // and shift the bit. When the "auto" bit is set, the header and buffer
++    // are actually on the stack, meaning the ThinVec pointer-to-header
++    // is essentially an "owned borrow", and therefore dangerous to handle.
++    // There are no safety guards for this situation.
++    //
++    // On little-endian platforms, the auto bit will be the high-bit of
++    // our capacity u32. On big-endian platforms, it will be the low bit.
++    // Hence we need some platform-specific CFGs for the necessary masking/shifting.
++    // 
++    // ThinVec won't ever construct an auto array. They only happen when
++    // bridging from C++. This means we don't need to ever set/preserve the bit.
++    // We just need to be able to read and handle it if it happens to be there.
++    //
++    // Handling the auto bit mostly just means not freeing/reallocating the buffer.
++
++    pub type SizeType = u32;
++
++    pub const MAX_CAP: usize = i32::max_value() as usize;
++
++    // Little endian: the auto bit is the high bit, and the capacity is
++    // verbatim. So we just need to mask off the high bit. Note that
++    // this masking is unnecessary when packing, because assert_size
++    // guards against the high bit being set.
++    #[cfg(target_endian = "little")]
++    pub fn pack_capacity(cap: SizeType) -> SizeType {
++        cap as SizeType
++    }
++    #[cfg(target_endian = "little")]
++    pub fn unpack_capacity(cap: SizeType) -> usize {
++        (cap as usize) & !(1 << 31)
++    }
++    #[cfg(target_endian = "little")]
++    pub fn is_auto(cap: SizeType) -> bool {
++        (cap & (1 << 31)) != 0
++    }
++
++    // Big endian: the auto bit is the low bit, and the capacity is
++    // shifted up one bit. Masking out the auto bit is unnecessary,
++    // as rust shifts always shift in 0's for unsigned integers.
++    #[cfg(target_endian = "big")]
++    pub fn pack_capacity(cap: SizeType) -> SizeType {
++        (cap as SizeType) << 1
++    }
++    #[cfg(target_endian = "big")]
++    pub fn unpack_capacity(cap: SizeType) -> usize {
++        (cap >> 1) as usize
++    }
++    #[cfg(target_endian = "big")]
++    pub fn is_auto(cap: SizeType) -> bool {
++        (cap & 1) != 0
++    }
++
++    #[inline]
++    pub fn assert_size(x: usize) -> SizeType {
++        if x > MAX_CAP as usize {
++            panic!("nsTArray size may not exceed the capacity of a 32-bit sized int");
++        }
++        x as SizeType
+     }
+-    x as SizeType
++
+ }
+ 
+-/// The header of a ThinVec
++/// The header of a ThinVec.
++///
++/// The _cap can be a bitfield, so use accessors to avoid trouble.
+ #[repr(C)]
+ struct Header {
+     _len: SizeType,
+@@ -56,38 +258,10 @@ impl Header {
+         self._len as usize
+     }
+ 
+-    #[cfg(feature = "gecko-ffi")]
+-    fn cap(&self) -> usize {
+-        (self._cap & CAP_MASK) as usize
+-    }
+-
+-    #[cfg(not(feature = "gecko-ffi"))]
+-    fn cap(&self) -> usize {
+-        self._cap as usize
+-    }
+-
+     fn set_len(&mut self, len: usize) {
+         self._len = assert_size(len);
+     }
+ 
+-    #[cfg(feature = "gecko-ffi")]
+-    fn set_cap(&mut self, cap: usize) {
+-        debug_assert!(cap & (CAP_MASK as usize) == cap);
+-        // FIXME: this is busted because it reads uninit memory
+-        // debug_assert!(!self.uses_stack_allocated_buffer());
+-        self._cap = assert_size(cap) & CAP_MASK;
+-    }
+-
+-    #[cfg(feature = "gecko-ffi")]
+-    fn uses_stack_allocated_buffer(&self) -> bool {
+-        self._cap & AUTO_MASK != 0
+-    }
+-
+-    #[cfg(not(feature = "gecko-ffi"))]
+-    fn set_cap(&mut self, cap: usize) {
+-        self._cap = assert_size(cap);
+-    }
+-
+     fn data<T>(&self) -> *mut T {
+         let header_size = mem::size_of::<Header>();
+         let padding = padding::<T>();
+@@ -105,6 +279,41 @@ impl Header {
+     }
+ }
+ 
++
++#[cfg(feature = "gecko-ffi")]
++impl Header {
++    fn cap(&self) -> usize {
++        unpack_capacity(self._cap)
++    }
++
++    fn set_cap(&mut self, cap: usize) {
++        // debug check that our packing is working
++        debug_assert_eq!(unpack_capacity(pack_capacity(cap as SizeType)), cap);
++        // FIXME: this assert is busted because it reads uninit memory
++        // debug_assert!(!self.uses_stack_allocated_buffer());
++
++        // NOTE: this always stores a cleared auto bit, because set_cap
++        // is only invoked by Rust, and Rust doesn't create auto arrays.
++        self._cap = pack_capacity(assert_size(cap));
++    }
++
++    fn uses_stack_allocated_buffer(&self) -> bool {
++        is_auto(self._cap)
++    }
++}
++
++#[cfg(not(feature = "gecko-ffi"))]
++impl Header {
++    fn cap(&self) -> usize {
++        self._cap as usize
++    }
++
++    fn set_cap(&mut self, cap: usize) {
++        self._cap = assert_size(cap);
++    }
++}
++
++
+ /// Singleton that all empty collections share.
+ /// Note: can't store non-zero ZSTs, we allocate in that case. We could
+ /// optimize everything to not do that (basically, make ptr == len and branch
+@@ -121,9 +330,7 @@ extern {
+ 
+ // TODO: overflow checks everywhere
+ 
+-// Utils
+-
+-fn oom() -> ! { std::process::abort() }
++// Utils for computing layouts of allocations
+ 
+ fn alloc_size<T>(cap: usize) -> usize {
+     // Compute "real" header size with pointer math
+@@ -156,15 +363,22 @@ fn alloc_align<T>() -> usize {
+     max(mem::align_of::<T>(), mem::align_of::<Header>())
+ }
+ 
+-fn header_with_capacity<T>(cap: usize) -> NonNull<Header> {
+-    debug_assert!(cap > 0);
++fn layout<T>(cap: usize) -> Layout {
+     unsafe {
+-        let header = heap::allocate(
++        Layout::from_size_align_unchecked(
+             alloc_size::<T>(cap),
+             alloc_align::<T>(),
+-        ) as *mut Header;
++        )
++    }
++}
+ 
+-        if header.is_null() { oom() }
++fn header_with_capacity<T>(cap: usize) -> NonNull<Header> {
++    debug_assert!(cap > 0);
++    unsafe {
++        let layout = layout::<T>(cap);
++        let header = alloc(layout) as *mut Header;
++
++        if header.is_null() { handle_alloc_error(layout) }
+ 
+         // "Infinite" capacity for zero-sized types:
+         (*header).set_cap(if mem::size_of::<T>() == 0 { MAX_CAP } else { cap });
+@@ -176,28 +390,8 @@ fn header_with_capacity<T>(cap: usize) -
+ 
+ 
+ 
+-/// ThinVec is exactly the same as Vec, except that it stores its `len` and `capacity` in the buffer
+-/// it allocates.
+-///
+-/// This makes the memory footprint of ThinVecs lower; notably in cases where space is reserved for
+-/// a non-existence ThinVec<T>. So `Vec<ThinVec<T>>` and `Option<ThinVec<T>>::None` will waste less
+-/// space. Being pointer-sized also means it can be passed/stored in registers.
+-///
+-/// Of course, any actually constructed ThinVec will theoretically have a bigger allocation, but
+-/// the fuzzy nature of allocators means that might not actually be the case.
+-///
+-/// Properties of Vec that are preserved:
+-/// * `ThinVec::new()` doesn't allocate (it points to a statically allocated singleton)
+-/// * reallocation can be done in place
+-/// * `size_of::<ThinVec<T>>()` == `size_of::<Option<ThinVec<T>>>()`
+-///   * NOTE: This is only possible when the `unstable` feature is used.
+-///
+-/// Properties of Vec that aren't preserved:
+-/// * `ThinVec<T>` can't ever be zero-cost roundtripped to a `Box<[T]>`, `String`, or `*mut T`
+-/// * `from_raw_parts` doesn't exist
+-/// * ThinVec currently doesn't bother to not-allocate for Zero Sized Types (e.g. `ThinVec<()>`),
+-///   but it could be done if someone cared enough to implement it.
+-#[cfg_attr(feature = "gecko-ffi", repr(C))]
++/// See the crate's top level documentation for a description of this type.
++#[repr(C)]
+ pub struct ThinVec<T> {
+     ptr: NonNull<Header>,
+     boo: PhantomData<T>,
+@@ -627,15 +821,15 @@ impl<T> ThinVec<T> {
+     }
+ 
+     pub fn drain<R>(&mut self, range: R) -> Drain<T>
+-        where R: RangeArgument<usize>
++        where R: RangeBounds<usize>
+     {
+         let len = self.len();
+-        let start = match range.start() {
++        let start = match range.start_bound() {
+             Bound::Included(&n) => n,
+             Bound::Excluded(&n) => n + 1,
+             Bound::Unbounded => 0,
+         };
+-        let end = match range.end() {
++        let end = match range.end_bound() {
+             Bound::Included(&n) => n + 1,
+             Bound::Excluded(&n) => n,
+             Bound::Unbounded => len,
+@@ -666,9 +860,10 @@ impl<T> ThinVec<T> {
+ 
+     unsafe fn deallocate(&mut self) {
+         if self.has_allocation() {
+-            heap::deallocate(self.ptr() as *mut u8,
+-                alloc_size::<T>(self.capacity()),
+-                alloc_align::<T>());
++            dealloc(
++                self.ptr() as *mut u8,
++                layout::<T>(self.capacity()),
++            )
+         }
+     }
+ 
+@@ -678,15 +873,36 @@ impl<T> ThinVec<T> {
+         debug_assert!(new_cap > 0);
+         if self.has_allocation() {
+             let old_cap = self.capacity();
+-            let ptr = heap::reallocate(self.ptr() as *mut u8,
+-                                       alloc_size::<T>(old_cap),
+-                                       alloc_size::<T>(new_cap),
+-                                       alloc_align::<T>()) as *mut Header;
+-            if ptr.is_null() { oom() }
++            let ptr = realloc(
++                self.ptr() as *mut u8,
++                layout::<T>(old_cap),
++                alloc_size::<T>(new_cap),
++            ) as *mut Header;
++
++            if ptr.is_null() { handle_alloc_error(layout::<T>(new_cap)) }
+             (*ptr).set_cap(new_cap);
+             self.ptr = NonNull::new_unchecked(ptr);
+         } else {
+-            self.ptr = header_with_capacity::<T>(new_cap);
++            let mut new_header = header_with_capacity::<T>(new_cap);
++
++            // If we get here and have a non-zero len, then we must be handling
++            // a gecko auto array, and we have items in a stack buffer. We shouldn't
++            // free it, but we should memcopy the contents out of it and mark it as empty.
++            //
++            // T is assumed to be trivially relocatable, as this is ~required
++            // for Rust compatibility anyway. Furthermore, we assume C++ won't try
++            // to unconditionally destroy the contents of the stack allocated buffer
++            // (i.e. it's obfuscated behind a union).
++            //
++            // In effect, we are partially reimplementing the auto array move constructor
++            // by leaving behind a valid empty instance.
++            let len = self.len();
++            if cfg!(feature = "gecko-ffi") && len > 0 {
++                new_header.as_mut().data::<T>().copy_from_nonoverlapping(self.data_raw(), len);
++                self.set_len(0);
++            }
++            
++            self.ptr = new_header;
+         }
+     }
+ 
+@@ -1087,10 +1303,7 @@ mod tests {
+         use std::mem::size_of;
+         assert_eq!(size_of::<ThinVec<u8>>(), size_of::<&u8>());
+ 
+-        // We don't perform the null-pointer optimization on stable rust.
+-        if cfg!(feature = "unstable") {
+-            assert_eq!(size_of::<Option<ThinVec<u8>>>(), size_of::<&u8>());
+-        }
++        assert_eq!(size_of::<Option<ThinVec<u8>>>(), size_of::<&u8>());
+     }
+ 
+     #[test]
+@@ -1725,7 +1938,6 @@ mod std_tests {
+         assert_eq!(v, &[(), ()]);
+     }
+ 
+-/* TODO: support inclusive ranges
+     #[test]
+     fn test_drain_inclusive_range() {
+         let mut v = thin_vec!['a', 'b', 'c', 'd', 'e'];
+@@ -1755,6 +1967,7 @@ mod std_tests {
+     }
+ 
+     #[test]
++    #[cfg(not(feature = "gecko-ffi"))]
+     fn test_drain_max_vec_size() {
+         let mut v = ThinVec::<()>::with_capacity(usize::max_value());
+         unsafe { v.set_len(usize::max_value()); }
+@@ -1775,7 +1988,6 @@ mod std_tests {
+         let mut v = thin_vec![1, 2, 3, 4, 5];
+         v.drain(5..=5);
+     }
+-*/
+ 
+ /* TODO: implement splice?
+     #[test]
+@@ -2181,7 +2393,7 @@ mod std_tests {
+         assert!(v.capacity() >= 33)
+     }
+ 
+-/* TODO: implement try_reserve 
++/* TODO: implement try_reserve
+     #[test]
+     fn test_try_reserve() {
+ 
+diff -up firefox-78.1.0/third_party/rust/thin-vec/src/range.rs.D87019-thin-vec-big-endian.diff firefox-78.1.0/third_party/rust/thin-vec/src/range.rs
+diff -up firefox-78.1.0/toolkit/components/cascade_bloom_filter/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/toolkit/components/cascade_bloom_filter/Cargo.toml
+--- firefox-78.1.0/toolkit/components/cascade_bloom_filter/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:29.000000000 +0200
++++ firefox-78.1.0/toolkit/components/cascade_bloom_filter/Cargo.toml	2020-08-17 17:04:24.135598590 +0200
+@@ -8,5 +8,5 @@ nserror = { path = "../../../xpcom/rust/
+ nsstring = { path = "../../../xpcom/rust/nsstring" }
+ rental = "0.5.5"
+ rust_cascade = "0.6.0"
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ xpcom = { path = "../../../xpcom/rust/xpcom" }
+diff -up firefox-78.1.0/toolkit/components/extensions/storage/webext_storage_bridge/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/toolkit/components/extensions/storage/webext_storage_bridge/Cargo.toml
+--- firefox-78.1.0/toolkit/components/extensions/storage/webext_storage_bridge/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:30.000000000 +0200
++++ firefox-78.1.0/toolkit/components/extensions/storage/webext_storage_bridge/Cargo.toml	2020-08-17 17:04:24.135598590 +0200
+@@ -13,7 +13,7 @@ moz_task = { path = "../../../../../xpco
+ nserror = { path = "../../../../../xpcom/rust/nserror" }
+ nsstring = { path = "../../../../../xpcom/rust/nsstring" }
+ once_cell = "1"
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ xpcom = { path = "../../../../../xpcom/rust/xpcom" }
+ serde = "1"
+ serde_json = "1"
+diff -up firefox-78.1.0/toolkit/components/kvstore/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/toolkit/components/kvstore/Cargo.toml
+--- firefox-78.1.0/toolkit/components/kvstore/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:30.000000000 +0200
++++ firefox-78.1.0/toolkit/components/kvstore/Cargo.toml	2020-08-17 17:04:24.135598590 +0200
+@@ -18,7 +18,7 @@ rkv = "0.10.2"
+ storage_variant = { path = "../../../storage/variant" }
+ xpcom = { path = "../../../xpcom/rust/xpcom" }
+ tempfile = "3"
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+ 
+ # Get rid of failure's dependency on backtrace. Eventually
+ # backtrace will move into Rust core, but we don't need it here.
+diff -up firefox-78.1.0/toolkit/components/places/bookmark_sync/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/toolkit/components/places/bookmark_sync/Cargo.toml
+--- firefox-78.1.0/toolkit/components/places/bookmark_sync/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:30.000000000 +0200
++++ firefox-78.1.0/toolkit/components/places/bookmark_sync/Cargo.toml	2020-08-17 17:04:24.135598590 +0200
+@@ -19,5 +19,5 @@ url = "2.0"
+ xpcom = { path = "../../../../xpcom/rust/xpcom" }
+ 
+ [dependencies.thin-vec]
+-version = "0.1.0"
++version = "0.2.1"
+ features = ["gecko-ffi"]
+diff -up firefox-78.1.0/tools/profiler/rust-helper/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/tools/profiler/rust-helper/Cargo.toml
+--- firefox-78.1.0/tools/profiler/rust-helper/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:30.000000000 +0200
++++ firefox-78.1.0/tools/profiler/rust-helper/Cargo.toml	2020-08-17 17:04:24.135598590 +0200
+@@ -23,7 +23,7 @@ features = ["endian_fd", "elf32", "elf64
+ default-features = false
+ 
+ [dependencies.thin-vec]
+-version = "0.1.0"
++version = "0.2.1"
+ features = ["gecko-ffi"]
+ 
+ [features]
+diff -up firefox-78.1.0/xpcom/rust/xpcom/Cargo.toml.D87019-thin-vec-big-endian.diff firefox-78.1.0/xpcom/rust/xpcom/Cargo.toml
+--- firefox-78.1.0/xpcom/rust/xpcom/Cargo.toml.D87019-thin-vec-big-endian.diff	2020-07-22 17:56:30.000000000 +0200
++++ firefox-78.1.0/xpcom/rust/xpcom/Cargo.toml	2020-08-17 17:04:24.136598593 +0200
+@@ -9,4 +9,4 @@ nsstring = { path = "../nsstring" }
+ nserror = { path = "../nserror" }
+ threadbound = "0.1"
+ xpcom_macros = { path = "xpcom_macros" }
+-thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
++thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
diff --git a/SOURCES/build-debug-qcms.patch b/SOURCES/build-debug-qcms.patch
deleted file mode 100644
index a65223a..0000000
--- a/SOURCES/build-debug-qcms.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-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
deleted file mode 100644
index a54814e..0000000
--- a/SOURCES/build-disable-elfhack.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -up thunderbird-68.1.1/toolkit/moz.configure.elfhack thunderbird-68.1.1/toolkit/moz.configure
---- thunderbird-68.1.1/toolkit/moz.configure.elfhack	2019-10-04 08:33:32.881241826 +0200
-+++ thunderbird-68.1.1/toolkit/moz.configure	2019-10-04 08:38:35.422159976 +0200
-@@ -1130,7 +1130,7 @@ with only_when('--enable-compile-environ
-                help='{Enable|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-icu-big-endian.patch b/SOURCES/build-icu-big-endian.patch
deleted file mode 100644
index b0a4a09..0000000
--- a/SOURCES/build-icu-big-endian.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -up thunderbird-68.1.1/build/autoconf/icu.m4.icu thunderbird-68.1.1/build/autoconf/icu.m4
---- thunderbird-68.1.1/build/autoconf/icu.m4.icu	2019-10-04 09:48:47.337041046 +0200
-+++ thunderbird-68.1.1/build/autoconf/icu.m4	2019-10-04 09:52:32.046670353 +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"
- fi
- 
- AC_SUBST(MOZ_ICU_VERSION)
diff --git a/SOURCES/build-icu-make.patch b/SOURCES/build-icu-make.patch
new file mode 100644
index 0000000..6a04091
--- /dev/null
+++ b/SOURCES/build-icu-make.patch
@@ -0,0 +1,13 @@
+diff -up firefox-68.8.0/intl/icu_sources_data.py.icu-makefile firefox-68.8.0/intl/icu_sources_data.py
+--- firefox-68.8.0/intl/icu_sources_data.py.icu-makefile	2020-05-11 17:00:03.642605718 +0200
++++ firefox-68.8.0/intl/icu_sources_data.py	2020-05-11 17:00:37.774642749 +0200
+@@ -246,8 +246,7 @@ def update_data_file(topsrcdir):
+     if not try_run(
+             'icu-make',
+             ['make',
+-             '--jobs=%d' % multiprocessing.cpu_count(),
+-             '--output-sync'],
++             '--jobs=1'],
+             cwd=objdir):
+         return False
+     print('Copying ICU data file...')
diff --git a/SOURCES/build-nss-version.patch b/SOURCES/build-nss-version.patch
index b8dfc04..7847090 100644
--- a/SOURCES/build-nss-version.patch
+++ b/SOURCES/build-nss-version.patch
@@ -1,6 +1,6 @@
-diff -up thunderbird-68.2.0/old-configure.in.nss-version thunderbird-68.2.0/old-configure.in
---- thunderbird-68.2.0/old-configure.in.nss-version	2019-10-22 14:50:42.649086398 +0200
-+++ thunderbird-68.2.0/old-configure.in	2019-10-22 14:51:11.567171593 +0200
+diff -up firefox-68.3.0/old-configure.in.nss-version firefox-68.3.0/old-configure.in
+--- firefox-68.3.0/old-configure.in.nss-version	2019-11-27 19:48:01.045677621 +0100
++++ firefox-68.3.0/old-configure.in	2019-11-27 19:59:52.856894047 +0100
 @@ -1537,7 +1537,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
      _USE_SYSTEM_NSS=1 )
  
diff --git a/SOURCES/fedora-shebang-build.patch b/SOURCES/fedora-shebang-build.patch
new file mode 100644
index 0000000..9ade86c
--- /dev/null
+++ b/SOURCES/fedora-shebang-build.patch
@@ -0,0 +1,9 @@
+diff -up firefox-73.0/build/unix/run-mozilla.sh.old firefox-73.0/build/unix/run-mozilla.sh
+--- firefox-73.0/build/unix/run-mozilla.sh.old	2020-02-12 09:58:00.150895904 +0100
++++ firefox-73.0/build/unix/run-mozilla.sh	2020-02-12 09:58:06.505860696 +0100
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/usr/bin/sh
+ #
+ # This Source Code Form is subject to the terms of the Mozilla Public
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
diff --git a/SOURCES/firefox-dont-check-binary.patch b/SOURCES/firefox-dont-check-binary.patch
deleted file mode 100644
index c498034..0000000
--- a/SOURCES/firefox-dont-check-binary.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-diff -up firefox-68.0/config/rules.mk.old firefox-68.0/config/rules.mk
---- firefox-68.0/config/rules.mk.old	2019-06-26 09:36:58.537034443 +0200
-+++ firefox-68.0/config/rules.mk	2019-06-26 09:37:38.004970573 +0200
-@@ -569,7 +569,6 @@ ifdef MOZ_PROFILE_GENERATE
- endif
- else # !WINNT || GNU_CC
- 	$(call EXPAND_CC_OR_CXX,$@) -o $@ $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) $($(notdir $@)_$(OBJS_VAR_SUFFIX)) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
--	$(call py_action,check_binary,--target $@)
- endif # WINNT && !GNU_CC
- 
- ifdef ENABLE_STRIP
-@@ -604,9 +603,6 @@ else
- 	$(HOST_CC) -o $@ $(HOST_C_LDFLAGS) $(HOST_LDFLAGS) $($(notdir $@)_OBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
- endif # HOST_CPP_PROG_LINK
- endif
--ifndef CROSS_COMPILE
--	$(call py_action,check_binary,--host $@)
--endif
- 
- #
- # This is an attempt to support generation of multiple binaries
-@@ -630,7 +626,6 @@ ifdef MSMANIFEST_TOOL
- endif	# MSVC with manifest tool
- else
- 	$(call EXPAND_CC_OR_CXX,$@) $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) -o $@ $($@_$(OBJS_VAR_SUFFIX)) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
--	$(call py_action,check_binary,--target $@)
- endif # WINNT && !GNU_CC
- 
- ifdef ENABLE_STRIP
-@@ -651,9 +646,6 @@ else
- 	$(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_C_LDFLAGS) $($(notdir $@)_OBJS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
- endif
- endif
--ifndef CROSS_COMPILE
--	$(call py_action,check_binary,--host $@)
--endif
- 
- $(LIBRARY): $(OBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
- 	$(REPORT_BUILD)
-@@ -691,7 +683,6 @@ ifndef INCREMENTAL_LINKER
- 	$(RM) $@
- endif
- 	$(MKSHLIB) $($@_$(OBJS_VAR_SUFFIX)) $(RESFILE) $(LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(OS_LIBS)
--	$(call py_action,check_binary,--target $@)
- 
- ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
- ifdef MSMANIFEST_TOOL
diff --git a/SOURCES/firefox-pipewire-0-3.patch b/SOURCES/firefox-pipewire-0-3.patch
new file mode 100644
index 0000000..0844209
--- /dev/null
+++ b/SOURCES/firefox-pipewire-0-3.patch
@@ -0,0 +1,846 @@
+diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild
+index 2081d0c683a4..641133bf1ea4 100644
+--- a/config/system-headers.mozbuild
++++ b/config/system-headers.mozbuild
+@@ -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 --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn
+index ba885217b3ba..201d3b755221 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn
+@@ -158,7 +158,7 @@ if (rtc_include_tests) {
+ if (is_linux) {
+   if (rtc_use_pipewire) {
+     pkg_config("pipewire") {
+-      packages = [ "libpipewire-0.2" ]
++      packages = [ "libpipewire-0.3" ]
+ 
+       defines = [ "WEBRTC_USE_PIPEWIRE" ]
+     }
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build
+index 90b40431c7e4..d844aa79d591 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build
+@@ -194,6 +194,30 @@ if CONFIG["OS_TARGET"] == "Linux":
+         "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc"
+     ]
+ 
++# PipeWire specific files
++if CONFIG["OS_TARGET"] == "Linux":
++
++    DEFINES["WEBRTC_USE_PIPEWIRE"] = "1"
++
++    OS_LIBS += [
++        "rt",
++        "pipewire-0.3",
++        "glib-2.0",
++        "gio-2.0",
++        "gobject-2.0"
++    ]
++
++    CXXFLAGS += CONFIG['TK_CFLAGS']
++    CXXFLAGS += [ "-I/usr/include/pipewire-0.3" ]
++    CXXFLAGS += [ "-I/usr/include/spa-0.2" ]
++
++    UNIFIED_SOURCES += [
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc"
++    ]
++
++
+ if CONFIG["OS_TARGET"] == "NetBSD":
+ 
+     DEFINES["USE_X11"] = "1"
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h
+index 1eb8ead26efa..316468eed1fc 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h
+@@ -141,7 +141,7 @@ class DesktopCaptureOptions {
+   bool disable_effects_ = true;
+   bool detect_updated_region_ = false;
+ #if defined(WEBRTC_USE_PIPEWIRE)
+-  bool allow_pipewire_ = false;
++  bool allow_pipewire_ = true;
+ #endif
+ };
+ 
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc
+index 379341c833de..76349f1fbd4d 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc
+@@ -15,8 +15,11 @@
+ 
+ #include <spa/param/format-utils.h>
+ #include <spa/param/props.h>
+-#include <spa/param/video/raw-utils.h>
+-#include <spa/support/type-map.h>
++
++#include <linux/dma-buf.h>
++#include <sys/mman.h>
++#include <sys/ioctl.h>
++#include <sys/syscall.h>
+ 
+ #include <memory>
+ #include <utility>
+@@ -36,31 +39,36 @@ const char kSessionInterfaceName[] = "org.freedesktop.portal.Session";
+ const char kRequestInterfaceName[] = "org.freedesktop.portal.Request";
+ const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast";
+ 
+-// static
+-void BaseCapturerPipeWire::OnStateChanged(void* data,
+-                                          pw_remote_state old_state,
+-                                          pw_remote_state state,
+-                                          const char* error_message) {
+-  BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
+-  RTC_DCHECK(that);
+ 
+-  switch (state) {
+-    case PW_REMOTE_STATE_ERROR:
+-      RTC_LOG(LS_ERROR) << "PipeWire remote state error: " << error_message;
+-      break;
+-    case PW_REMOTE_STATE_CONNECTED:
+-      RTC_LOG(LS_INFO) << "PipeWire remote state: connected.";
+-      that->CreateReceivingStream();
+-      break;
+-    case PW_REMOTE_STATE_CONNECTING:
+-      RTC_LOG(LS_INFO) << "PipeWire remote state: connecting.";
++// static
++void BaseCapturerPipeWire::SyncDmaBuf(int fd, uint64_t start_or_end) {
++  struct dma_buf_sync sync = { 0 };
++
++  sync.flags = start_or_end | DMA_BUF_SYNC_READ;
++
++  while(true) {
++    int ret;
++    ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync);
++    if (ret == -1 && errno == EINTR) {
++      continue;
++    } else if (ret == -1) {
++      RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " << g_strerror(errno);
+       break;
+-    case PW_REMOTE_STATE_UNCONNECTED:
+-      RTC_LOG(LS_INFO) << "PipeWire remote state: unconnected.";
++    } else {
+       break;
++    }
+   }
+ }
+ 
++// static
++void BaseCapturerPipeWire::OnCoreError(void *data,
++                                       uint32_t id,
++                                       int seq,
++                                       int res,
++                                       const char *message) {
++  RTC_LOG(LS_ERROR) << "core error: " << message;
++}
++
+ // static
+ void BaseCapturerPipeWire::OnStreamStateChanged(void* data,
+                                                 pw_stream_state old_state,
+@@ -73,76 +81,54 @@ void BaseCapturerPipeWire::OnStreamStateChanged(void* data,
+     case PW_STREAM_STATE_ERROR:
+       RTC_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:
++    case PW_STREAM_STATE_UNCONNECTED:
++    case PW_STREAM_STATE_CONNECTING:
+       break;
+   }
+ }
+ 
+ // static
+-void BaseCapturerPipeWire::OnStreamFormatChanged(void* data,
+-                                                 const struct spa_pod* format) {
++void BaseCapturerPipeWire::OnStreamParamChanged(void *data, uint32_t id,
++                                                const struct spa_pod *format) {
+   BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
+   RTC_DCHECK(that);
+ 
+-  RTC_LOG(LS_INFO) << "PipeWire stream format changed.";
++  RTC_LOG(LS_INFO) << "PipeWire stream param changed.";
+ 
+-  if (!format) {
+-    pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr,
+-                            /*n_params=*/0);
++  if (!format || id != SPA_PARAM_Format) {
+     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);
++  spa_format_video_raw_parse(format, &that->spa_video_format_);
+ 
+-  auto width = that->spa_video_format_->size.width;
+-  auto height = that->spa_video_format_->size.height;
++  auto width = that->spa_video_format_.size.width;
++  auto height = that->spa_video_format_.size.height;
+   auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4);
+   auto size = height * stride;
+ 
++  that->desktop_size_ = DesktopSize(width, height);
++
+   uint8_t buffer[1024] = {};
+   auto builder = spa_pod_builder{buffer, sizeof(buffer)};
+ 
+   // Setup buffers and meta header for new format.
+-  const struct spa_pod* params[2];
+-  params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object(
+-      &builder,
+-      // id to enumerate buffer requirements
+-      that->pw_core_type_->param.idBuffers,
+-      that->pw_core_type_->param_buffers.Buffers,
+-      // Size: specified as integer (i) and set to specified size
+-      ":", that->pw_core_type_->param_buffers.size, "i", size,
+-      // Stride: specified as integer (i) and set to specified stride
+-      ":", that->pw_core_type_->param_buffers.stride, "i", stride,
+-      // Buffers: specifies how many buffers we want to deal with, set as
+-      // integer (i) where preferred number is 8, then allowed number is defined
+-      // as range (r) from min and max values and it is undecided (u) to allow
+-      // negotiation
+-      ":", that->pw_core_type_->param_buffers.buffers, "iru", 8,
+-      SPA_POD_PROP_MIN_MAX(1, 32),
+-      // Align: memory alignment of the buffer, set as integer (i) to specified
+-      // value
+-      ":", that->pw_core_type_->param_buffers.align, "i", 16));
+-  params[1] = reinterpret_cast<spa_pod*>(spa_pod_builder_object(
+-      &builder,
+-      // id to enumerate supported metadata
+-      that->pw_core_type_->param.idMeta, that->pw_core_type_->param_meta.Meta,
+-      // Type: specified as id or enum (I)
+-      ":", that->pw_core_type_->param_meta.type, "I",
+-      that->pw_core_type_->meta.Header,
+-      // Size: size of the metadata, specified as integer (i)
+-      ":", that->pw_core_type_->param_meta.size, "i",
+-      sizeof(struct spa_meta_header)));
+-
+-  pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/2);
++  const struct spa_pod* params[3];
++  params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
++              SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
++              SPA_PARAM_BUFFERS_size, SPA_POD_Int(size),
++              SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride),
++              SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32)));
++  params[1] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
++              SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
++              SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header),
++              SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))));
++  params[2] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
++              SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
++              SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop),
++              SPA_PARAM_META_size, SPA_POD_Int (sizeof(struct spa_meta_region))));
++  pw_stream_update_params(that->pw_stream_, params, 3);
+ }
+ 
+ // static
+@@ -150,15 +136,25 @@ void BaseCapturerPipeWire::OnStreamProcess(void* data) {
+   BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data);
+   RTC_DCHECK(that);
+ 
+-  pw_buffer* buf = nullptr;
++  struct pw_buffer *next_buffer;
++  struct pw_buffer *buffer = nullptr;
++
++  next_buffer = pw_stream_dequeue_buffer(that->pw_stream_);
++  while (next_buffer) {
++    buffer = next_buffer;
++    next_buffer = pw_stream_dequeue_buffer(that->pw_stream_);
+ 
+-  if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) {
++    if (next_buffer)
++      pw_stream_queue_buffer (that->pw_stream_, buffer);
++  }
++
++  if (!buffer) {
+     return;
+   }
+ 
+-  that->HandleBuffer(buf);
++  that->HandleBuffer(buffer);
+ 
+-  pw_stream_queue_buffer(that->pw_stream_, buf);
++  pw_stream_queue_buffer(that->pw_stream_, buffer);
+ }
+ 
+ BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type)
+@@ -169,38 +165,22 @@ BaseCapturerPipeWire::~BaseCapturerPipeWire() {
+     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_disconnect(pw_core_);
+   }
+ 
+-  if (pw_core_) {
+-    pw_core_destroy(pw_core_);
++  if (pw_context_) {
++    pw_context_destroy(pw_context_);
+   }
+ 
+   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_);
+   }
+@@ -250,27 +230,35 @@ void BaseCapturerPipeWire::InitPortal() {
+ 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);
++  pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr);
++  pw_context_ = pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0);
++  if (!pw_context_) {
++    RTC_LOG(LS_ERROR) << "Failed to create PipeWire context";
++    return;
++  }
+ 
+-  InitPipeWireTypes();
++  pw_core_ = pw_context_connect(pw_context_, nullptr, 0);
++  if (!pw_core_) {
++    RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context";
++    return;
++  }
+ 
+   // Initialize event handlers, remote end and stream-related.
+-  pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS;
+-  pw_remote_events_.state_changed = &OnStateChanged;
++  pw_core_events_.version = PW_VERSION_CORE_EVENTS;
++  pw_core_events_.error = &OnCoreError;
+ 
+   pw_stream_events_.version = PW_VERSION_STREAM_EVENTS;
+   pw_stream_events_.state_changed = &OnStreamStateChanged;
+-  pw_stream_events_.format_changed = &OnStreamFormatChanged;
++  pw_stream_events_.param_changed = &OnStreamParamChanged;
+   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_);
++  pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, this);
++
++  pw_stream_ = CreateReceivingStream();
++  if (!pw_stream_) {
++    RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream";
++    return;
++  }
+ 
+   if (pw_thread_loop_start(pw_main_loop_) < 0) {
+     RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop";
+@@ -278,81 +266,132 @@ void BaseCapturerPipeWire::InitPipeWire() {
+   }
+ }
+ 
+-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() {
++pw_stream* BaseCapturerPipeWire::CreateReceivingStream() {
+   spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1};
+-  spa_rectangle pwScreenBounds =
+-      spa_rectangle{static_cast<uint32_t>(desktop_size_.width()),
+-                    static_cast<uint32_t>(desktop_size_.height())};
++  spa_rectangle pwMaxScreenBounds = spa_rectangle{INT32_MAX, INT32_MAX};
+ 
+-  spa_fraction pwFrameRateMin = spa_fraction{0, 1};
+-  spa_fraction pwFrameRateMax = spa_fraction{60, 1};
++  auto stream = pw_stream_new(pw_core_, "webrtc-pipewire-stream", nullptr);
+ 
+-  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);
++  if (!stream) {
++    RTC_LOG(LS_ERROR) << "Could not create receiving stream.";
++    return nullptr;
++  }
+ 
+   uint8_t buffer[1024] = {};
+-  const spa_pod* params[1];
+-  spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)};
+-  params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object(
+-      &builder,
+-      // id to enumerate formats
+-      pw_core_type_->param.idEnumFormat, pw_core_type_->spa_format, "I",
+-      pw_type_->media_type.video, "I", pw_type_->media_subtype.raw,
+-      // Video format: specified as id or enum (I), preferred format is BGRx,
+-      // then allowed formats are enumerated (e) and the format is undecided (u)
+-      // to allow negotiation
+-      ":", pw_type_->format_video.format, "Ieu", pw_type_->video_format.BGRx,
+-      SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx,
+-                        pw_type_->video_format.BGRx),
+-      // Video size: specified as rectangle (R), preferred size is specified as
+-      // first parameter, then allowed size is defined as range (r) from min and
+-      // max values and the format is undecided (u) to allow negotiation
+-      ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2,
+-      &pwMinScreenBounds, &pwScreenBounds,
+-      // Frame rate: specified as fraction (F) and set to minimum frame rate
+-      // value
+-      ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin,
+-      // Max frame rate: specified as fraction (F), preferred frame rate is set
+-      // to maximum value, then allowed frame rate is defined as range (r) from
+-      // min and max values and it is undecided (u) to allow negotiation
+-      ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2,
+-      &pwFrameRateMin, &pwFrameRateMax));
+-
+-  pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_,
+-                         this);
++  const spa_pod* params[2];
++  spa_pod_builder builder = SPA_POD_BUILDER_INIT(buffer, sizeof (buffer));
++
++  params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder,
++              SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
++              SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video),
++              SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
++              SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA,
++                                                                 SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_BGRA),
++              SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMinScreenBounds,
++                                                                    &pwMinScreenBounds,
++                                                                    &pwMaxScreenBounds),
++              0));
++  pw_stream_add_listener(stream, &spa_stream_listener_, &pw_stream_events_, this);
++
+   pw_stream_flags flags = static_cast<pw_stream_flags>(
+-      PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE |
+-      PW_STREAM_FLAG_MAP_BUFFERS);
+-  if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, /*port_path=*/nullptr,
+-                        flags, params,
+-                        /*n_params=*/1) != 0) {
++      PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE);
++
++  if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pw_stream_node_id_, PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) {
+     RTC_LOG(LS_ERROR) << "Could not connect receiving stream.";
+     portal_init_failed_ = true;
+-    return;
+   }
++
++  return stream;
+ }
+ 
+ void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) {
++  struct spa_meta_region* video_crop;
+   spa_buffer* spaBuffer = buffer->buffer;
+-  void* src = nullptr;
++  uint8_t *map = nullptr;
++  uint8_t* src = nullptr;
++  uint8_t* dst = nullptr;
++
++  if (spaBuffer->datas[0].chunk->size == 0) {
++    map = nullptr;
++    src = nullptr;
++  } else if (spaBuffer->datas[0].type == SPA_DATA_MemFd) {
++    map = static_cast<uint8_t*>(mmap(
++        nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset,
++        PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0));
++
++    if (map == MAP_FAILED) {
++      RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno);
++      return;
++    }
++
++    src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t);
++  } else if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) {
++    int fd;
++    fd = spaBuffer->datas[0].fd;
+ 
+-  if (!(src = spaBuffer->datas[0].data)) {
++    map = static_cast<uint8_t*>(mmap(
++        nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset,
++        PROT_READ, MAP_PRIVATE, fd, 0));
++
++    if (map == MAP_FAILED) {
++      RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno);
++      return;
++    }
++
++    SyncDmaBuf(fd, DMA_BUF_SYNC_START);
++
++    src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t);
++  } else if (spaBuffer->datas[0].type == SPA_DATA_MemPtr) {
++    map = nullptr;
++    src = static_cast<uint8_t*>(spaBuffer->datas[0].data);
++  } else {
+     return;
+   }
+ 
+-  uint32_t maxSize = spaBuffer->datas[0].maxsize;
+-  int32_t srcStride = spaBuffer->datas[0].chunk->stride;
++  if (!src) {
++    return;
++  }
++
++  DesktopSize prev_crop_size = DesktopSize(0, 0);
++  if (video_crop_size_initialized_) {
++    prev_crop_size = video_crop_size_;
++  }  
++
++  if ((video_crop = static_cast<struct spa_meta_region*>(
++           spa_buffer_find_meta_data(spaBuffer, SPA_META_VideoCrop, sizeof(*video_crop))))) {
++    RTC_DCHECK(video_crop->region.size.width <= desktop_size_.width() &&
++               video_crop->region.size.height <= desktop_size_.height());
++    if ((video_crop->region.size.width != desktop_size_.width() ||
++        video_crop->region.size.height != desktop_size_.height()) && video_crop->region.size.width && video_crop->region.size.height) {
++      video_crop_size_ = DesktopSize(video_crop->region.size.width, video_crop->region.size.height);
++      video_crop_size_initialized_ = true;
++    } else {
++      video_crop_size_initialized_ = false;
++    }
++  } else {
++    video_crop_size_initialized_ = false;
++  }
++
++  size_t frame_size;
++  if (video_crop_size_initialized_) {
++    frame_size =
++        video_crop_size_.width() * video_crop_size_.height() * kBytesPerPixel;
++  } else {
++    frame_size =
++        desktop_size_.width() * desktop_size_.height() * kBytesPerPixel;
++  }
++
++  if (!current_frame_ ||
++      (video_crop_size_initialized_ && !video_crop_size_.equals(prev_crop_size))) {
++    current_frame_ = std::make_unique<uint8_t[]>(frame_size);
++  }
++  RTC_DCHECK(current_frame_ != nullptr);
++
++  const int32_t dstStride = video_crop_size_initialized_
++                                ? video_crop_size_.width() * kBytesPerPixel
++                                : desktop_size_.width() * kBytesPerPixel;
++  const int32_t srcStride = spaBuffer->datas[0].chunk->stride;
++
+   if (srcStride != (desktop_size_.width() * kBytesPerPixel)) {
+     RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: "
+                       << srcStride
+@@ -361,21 +400,40 @@ void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) {
+     return;
+   }
+ 
+-  if (!current_frame_) {
+-    current_frame_ = static_cast<uint8_t*>(malloc(maxSize));
++  dst = current_frame_.get();
++
++  // Adjust source content based on crop video position
++  if (video_crop_size_initialized_ &&
++      (video_crop->region.position.y + video_crop_size_.height() <= desktop_size_.height())) {
++    for (int i = 0; i < video_crop->region.position.y; ++i) {
++      src += srcStride;
++    }
++  }
++  const int xOffset =
++      video_crop_size_initialized_ && (video_crop->region.position.x + video_crop_size_.width() <=
++                           desktop_size_.width())
++          ? video_crop->region.position.x * kBytesPerPixel
++          : 0;
++  const int height = video_crop_size_initialized_ ? video_crop_size_.height() : desktop_size_.height();
++  for (int i = 0; i < height; ++i) {
++    // Adjust source content based on crop video position if needed
++    src += xOffset;
++    std::memcpy(dst, src, dstStride);
++    // 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 == SPA_VIDEO_FORMAT_RGBx ||
++        spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) {
++      ConvertRGBxToBGRx(dst, dstStride);
++    }
++    src += srcStride - xOffset;
++    dst += dstStride;
+   }
+-  RTC_DCHECK(current_frame_ != nullptr);
+ 
+-  // If both sides decided to go with the RGBx format we need to convert it to
+-  // BGRx to match color format expected by WebRTC.
+-  if (spa_video_format_->format == pw_type_->video_format.RGBx) {
+-    uint8_t* tempFrame = static_cast<uint8_t*>(malloc(maxSize));
+-    std::memcpy(tempFrame, src, maxSize);
+-    ConvertRGBxToBGRx(tempFrame, maxSize);
+-    std::memcpy(current_frame_, tempFrame, maxSize);
+-    free(tempFrame);
+-  } else {
+-    std::memcpy(current_frame_, src, maxSize);
++  if (map) {
++    if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) {
++      SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_END);
++    }
++    munmap(map, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset);
+   }
+ }
+ 
+@@ -725,10 +783,7 @@ void BaseCapturerPipeWire::OnStartRequestResponseSignal(
+       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);
+-
++      that->pw_stream_node_id_ = stream_id;
+       g_variant_unref(options);
+       g_variant_unref(variant);
+     }
+@@ -813,10 +868,15 @@ void BaseCapturerPipeWire::CaptureFrame() {
+     return;
+   }
+ 
+-  std::unique_ptr<DesktopFrame> result(new BasicDesktopFrame(desktop_size_));
++  DesktopSize frame_size = desktop_size_;
++  if (video_crop_size_initialized_) {
++    frame_size = video_crop_size_;
++  }
++  
++  std::unique_ptr<DesktopFrame> result(new BasicDesktopFrame(frame_size));
+   result->CopyPixelsFrom(
+-      current_frame_, (desktop_size_.width() * kBytesPerPixel),
+-      DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height()));
++      current_frame_.get(), (frame_size.width() * kBytesPerPixel),
++      DesktopRect::MakeWH(frame_size.width(), frame_size.height()));
+   if (!result) {
+     callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
+     return;
+@@ -837,4 +897,22 @@ bool BaseCapturerPipeWire::SelectSource(SourceId id) {
+   return true;
+ }
+ 
++// static
++std::unique_ptr<DesktopCapturer>
++BaseCapturerPipeWire::CreateRawScreenCapturer(
++    const DesktopCaptureOptions& options) {
++  std::unique_ptr<BaseCapturerPipeWire> capturer =
++      std::make_unique<BaseCapturerPipeWire>(BaseCapturerPipeWire::CaptureSourceType::kAny);
++  return std::move(capturer);}
++
++// static
++std::unique_ptr<DesktopCapturer>
++BaseCapturerPipeWire::CreateRawWindowCapturer(
++    const DesktopCaptureOptions& options) {
++
++  std::unique_ptr<BaseCapturerPipeWire> capturer =
++      std::make_unique<BaseCapturerPipeWire>(BaseCapturerPipeWire::CaptureSourceType::kAny);
++  return std::move(capturer);
++}
++
+ }  // namespace webrtc
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h
+index 56b101acbaa6..de54157d1a2a 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h
+@@ -22,17 +22,13 @@
+ 
+ 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 };
++  enum CaptureSourceType : uint32_t {
++    kScreen = 0b01,
++    kWindow = 0b10,
++    kAny = 0b11
++  };
+ 
+   explicit BaseCapturerPipeWire(CaptureSourceType source_type);
+   ~BaseCapturerPipeWire() override;
+@@ -43,28 +39,32 @@ class BaseCapturerPipeWire : public DesktopCapturer {
+   bool GetSourceList(SourceList* sources) override;
+   bool SelectSource(SourceId id) override;
+ 
++  static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer(
++      const DesktopCaptureOptions& options);
++
++  static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer(
++      const DesktopCaptureOptions& options);
++
+  private:
+   // PipeWire types -->
++  pw_context* pw_context_ = nullptr;
+   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_core_listener_ = {};
+   spa_hook spa_stream_listener_ = {};
+-  spa_hook spa_remote_listener_ = {};
+ 
++  pw_core_events pw_core_events_ = {};
+   pw_stream_events pw_stream_events_ = {};
+-  pw_remote_events pw_remote_events_ = {};
+ 
+-  spa_video_info_raw* spa_video_format_ = nullptr;
++  struct spa_video_info_raw spa_video_format_;
+ 
++  guint32 pw_stream_node_id_ = 0;
+   gint32 pw_fd_ = -1;
+ 
+   CaptureSourceType capture_source_type_ =
+-      BaseCapturerPipeWire::CaptureSourceType::Screen;
++      BaseCapturerPipeWire::CaptureSourceType::kAny;
+ 
+   // <-- end of PipeWire types
+ 
+@@ -78,33 +78,37 @@ class BaseCapturerPipeWire : public DesktopCapturer {
+   guint sources_request_signal_id_ = 0;
+   guint start_request_signal_id_ = 0;
+ 
++  bool video_crop_size_initialized_ = false;
++  DesktopSize video_crop_size_;;
+   DesktopSize desktop_size_ = {};
+   DesktopCaptureOptions options_ = {};
+ 
+-  uint8_t* current_frame_ = nullptr;
++  std::unique_ptr<uint8_t[]> current_frame_;
+   Callback* callback_ = nullptr;
+ 
+   bool portal_init_failed_ = false;
+ 
+   void InitPortal();
+   void InitPipeWire();
+-  void InitPipeWireTypes();
+ 
+-  void CreateReceivingStream();
++  pw_stream* 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 SyncDmaBuf(int fd, uint64_t start_or_end);
++  static void OnCoreError(void *data,
++                          uint32_t id,
++                          int seq,
++                          int res,
++                          const char *message);
++  static void OnStreamParamChanged(void *data,
++                                   uint32_t id,
++                                   const struct spa_pod *format);
+   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);
+ 
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc
+index 26956fc67dc8..3813d697bb38 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc
+@@ -15,7 +15,7 @@
+ namespace webrtc {
+ 
+ ScreenCapturerPipeWire::ScreenCapturerPipeWire()
+-    : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {}
++    : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kScreen) {}
+ ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {}
+ 
+ // static
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc
+index 35436475cb4d..c43a1f1a0c4e 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc
+@@ -15,7 +15,7 @@
+ namespace webrtc {
+ 
+ WindowCapturerPipeWire::WindowCapturerPipeWire()
+-    : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {}
++    : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kWindow) {}
+ WindowCapturerPipeWire::~WindowCapturerPipeWire() {}
+ 
+ // static
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc
+index cf8a9dd0e0db..d27fab8d28d9 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc
+@@ -26,7 +26,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
+     const DesktopCaptureOptions& options) {
+ #if defined(WEBRTC_USE_PIPEWIRE)
+   if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) {
+-    return ScreenCapturerPipeWire::CreateRawScreenCapturer(options);
++    return BaseCapturerPipeWire::CreateRawScreenCapturer(options);
+   }
+ #endif  // defined(WEBRTC_USE_PIPEWIRE)
+ 
+diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc
+index 82359e50c2db..bb9724cf7cc2 100644
+--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc
++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc
+@@ -26,7 +26,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer(
+     const DesktopCaptureOptions& options) {
+ #if defined(WEBRTC_USE_PIPEWIRE)
+   if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) {
+-    return WindowCapturerPipeWire::CreateRawWindowCapturer(options);
++    return BaseCapturerPipeWire::CreateRawWindowCapturer(options);
+   }
+ #endif  // defined(WEBRTC_USE_PIPEWIRE)
+ 
diff --git a/SOURCES/firefox-pipewire.patch b/SOURCES/firefox-pipewire.patch
new file mode 100644
index 0000000..7233a73
--- /dev/null
+++ b/SOURCES/firefox-pipewire.patch
@@ -0,0 +1,63 @@
+diff -up firefox-68.0/config/system-headers.mozbuild.firefox-pipewire firefox-68.0/config/system-headers.mozbuild
+--- firefox-68.0/config/system-headers.mozbuild.firefox-pipewire	2019-07-01 22:30:26.000000000 +0200
++++ firefox-68.0/config/system-headers.mozbuild	2019-07-08 15:26:15.397161627 +0200
+@@ -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-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build.firefox-pipewire firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build
+--- firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build.firefox-pipewire	2019-07-01 22:30:33.000000000 +0200
++++ firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build	2019-07-08 15:26:15.397161627 +0200
+@@ -194,6 +194,28 @@ if CONFIG["OS_TARGET"] == "Linux":
+         "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.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/linux/base_capturer_pipewire.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc",
++        "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc"
++    ]
++
++
+ if CONFIG["OS_TARGET"] == "NetBSD":
+ 
+     DEFINES["USE_X11"] = "1"
+diff -up firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h.firefox-pipewire firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h
+--- firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h.firefox-pipewire	2019-07-08 16:42:13.936254926 +0200
++++ firefox-68.0/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h	2019-07-08 16:42:17.509264974 +0200
+@@ -141,7 +141,7 @@ class DesktopCaptureOptions {
+   bool disable_effects_ = true;
+   bool detect_updated_region_ = false;
+ #if defined(WEBRTC_USE_PIPEWIRE)
+-  bool allow_pipewire_ = false;
++  bool allow_pipewire_ = true;
+ #endif
+ };
+ 
diff --git a/SOURCES/mozilla-1005640-accept-lang.patch b/SOURCES/mozilla-1005640-accept-lang.patch
deleted file mode 100644
index 29d3833..0000000
--- a/SOURCES/mozilla-1005640-accept-lang.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-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
index 65f833f..40db2c6 100644
--- a/SOURCES/mozilla-1170092.patch
+++ b/SOURCES/mozilla-1170092.patch
@@ -1,7 +1,7 @@
-diff -up firefox-71.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092 firefox-71.0/extensions/pref/autoconfig/src/nsReadConfig.cpp
---- firefox-71.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092	2019-11-26 01:02:21.000000000 +0100
-+++ firefox-71.0/extensions/pref/autoconfig/src/nsReadConfig.cpp	2019-11-26 10:47:04.316154398 +0100
-@@ -246,8 +246,20 @@ nsresult nsReadConfig::openAndEvaluateJS
+diff -up firefox-78.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092 firefox-78.0/extensions/pref/autoconfig/src/nsReadConfig.cpp
+--- firefox-78.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092	2020-06-17 04:18:58.000000000 +0200
++++ firefox-78.0/extensions/pref/autoconfig/src/nsReadConfig.cpp	2020-06-25 13:45:28.816999491 +0200
+@@ -244,8 +244,20 @@ nsresult nsReadConfig::openAndEvaluateJS
      if (NS_FAILED(rv)) return rv;
  
      rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile);
@@ -23,23 +23,22 @@ diff -up firefox-71.0/extensions/pref/autoconfig/src/nsReadConfig.cpp.1170092 fi
    } else {
      nsAutoCString location("resource://gre/defaults/autoconfig/");
      location += aFileName;
-diff -up firefox-71.0/modules/libpref/Preferences.cpp.1170092 firefox-71.0/modules/libpref/Preferences.cpp
---- firefox-71.0/modules/libpref/Preferences.cpp.1170092	2019-11-26 01:02:25.000000000 +0100
-+++ firefox-71.0/modules/libpref/Preferences.cpp	2019-11-26 10:47:04.316154398 +0100
-@@ -4472,6 +4472,9 @@ nsresult Preferences::InitInitialObjects
+diff -up firefox-78.0/modules/libpref/Preferences.cpp.1170092 firefox-78.0/modules/libpref/Preferences.cpp
+--- firefox-78.0/modules/libpref/Preferences.cpp.1170092	2020-06-25 13:45:28.818999498 +0200
++++ firefox-78.0/modules/libpref/Preferences.cpp	2020-06-25 13:48:45.996708102 +0200
+@@ -4499,6 +4499,8 @@ nsresult Preferences::InitInitialObjects
    //
    // 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 = NS_ERROR_FAILURE;
-   nsZipFind* findPtr;
-diff -up firefox-71.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-71.0/toolkit/xre/nsXREDirProvider.cpp
---- firefox-71.0/toolkit/xre/nsXREDirProvider.cpp.1170092	2019-11-26 01:02:29.000000000 +0100
-+++ firefox-71.0/toolkit/xre/nsXREDirProvider.cpp	2019-11-26 10:49:40.076095714 +0100
-@@ -61,6 +61,7 @@
+   UniquePtr<nsZipFind> find;
+diff -up firefox-78.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-78.0/toolkit/xre/nsXREDirProvider.cpp
+--- firefox-78.0/toolkit/xre/nsXREDirProvider.cpp.1170092	2020-06-17 04:20:11.000000000 +0200
++++ firefox-78.0/toolkit/xre/nsXREDirProvider.cpp	2020-06-25 13:48:28.613645633 +0200
+@@ -60,6 +60,7 @@
  #endif
  #ifdef XP_UNIX
  #  include <ctype.h>
@@ -47,7 +46,7 @@ diff -up firefox-71.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-71.0/tool
  #endif
  #ifdef XP_IOS
  #  include "UIKitDirProvider.h"
-@@ -526,6 +527,21 @@ nsXREDirProvider::GetFile(const char* aP
+@@ -533,6 +534,21 @@ nsXREDirProvider::GetFile(const char* aP
        }
      }
    }
@@ -69,7 +68,7 @@ diff -up firefox-71.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-71.0/tool
    if (NS_FAILED(rv) || !file) return NS_ERROR_FAILURE;
  
    if (ensureFilePermissions) {
-@@ -842,6 +858,16 @@ nsresult nsXREDirProvider::GetFilesInter
+@@ -845,6 +861,17 @@ nsresult nsXREDirProvider::GetFilesInter
  
      LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories);
  
@@ -79,16 +78,17 @@ diff -up firefox-71.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-71.0/tool
 +                                getter_AddRefs(systemPrefDir));
 +    if (NS_SUCCEEDED(rv)) {
 +      rv = systemPrefDir->AppendNative(NS_LITERAL_CSTRING("pref"));
-+      if (NS_SUCCEEDED(rv))
++      if (NS_SUCCEEDED(rv)) {
 +        directories.AppendObject(systemPrefDir);
++      }
 +    }
 +
      rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile));
    } 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-71.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092 firefox-71.0/xpcom/io/nsAppDirectoryServiceDefs.h
---- firefox-71.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092	2019-11-26 01:02:30.000000000 +0100
-+++ firefox-71.0/xpcom/io/nsAppDirectoryServiceDefs.h	2019-11-26 10:47:04.317154398 +0100
+diff -up firefox-78.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092 firefox-78.0/xpcom/io/nsAppDirectoryServiceDefs.h
+--- firefox-78.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092	2020-06-17 04:20:17.000000000 +0200
++++ firefox-78.0/xpcom/io/nsAppDirectoryServiceDefs.h	2020-06-25 13:45:28.819999502 +0200
 @@ -60,6 +60,7 @@
  #define NS_APP_PREFS_DEFAULTS_DIR_LIST "PrefDL"
  #define NS_APP_PREFS_OVERRIDE_DIR \
diff --git a/SOURCES/mozilla-1196777.patch b/SOURCES/mozilla-1196777.patch
index c28cf94..7fa1595 100644
--- a/SOURCES/mozilla-1196777.patch
+++ b/SOURCES/mozilla-1196777.patch
@@ -1,7 +1,7 @@
-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 =
+diff -up firefox-68.0/widget/gtk/nsWindow.cpp.1196777 firefox-68.0/widget/gtk/nsWindow.cpp
+--- firefox-68.0/widget/gtk/nsWindow.cpp.1196777	2019-05-21 11:29:55.833376744 +0200
++++ firefox-68.0/widget/gtk/nsWindow.cpp	2019-05-21 12:15:35.446089316 +0200
+@@ -156,7 +156,8 @@ const gint kEvents =
  #if GTK_CHECK_VERSION(3, 4, 0)
      GDK_SMOOTH_SCROLL_MASK | GDK_TOUCH_MASK |
  #endif
@@ -9,5 +9,5 @@ diff -up firefox-60.5.0/widget/gtk/nsWindow.cpp.1196777 firefox-60.5.0/widget/gt
 +    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,
+ #if !GTK_CHECK_VERSION(3, 22, 0)
+ typedef enum {
diff --git a/SOURCES/mozilla-bmo1005535.patch b/SOURCES/mozilla-bmo1005535.patch
new file mode 100644
index 0000000..cab0134
--- /dev/null
+++ b/SOURCES/mozilla-bmo1005535.patch
@@ -0,0 +1,12 @@
+diff -up firefox-78.0/gfx/skia/skia/src/gpu/GrColor.h.mozilla.bmo1005535 firefox-78.0/gfx/skia/skia/src/gpu/GrColor.h
+--- firefox-78.0/gfx/skia/skia/src/gpu/GrColor.h.mozilla.bmo1005535	2020-06-25 16:16:34.459083304 +0200
++++ firefox-78.0/gfx/skia/skia/src/gpu/GrColor.h	2020-06-25 16:17:00.968174743 +0200
+@@ -64,7 +64,7 @@ static inline GrColor GrColorPackRGBA(un
+  *  Since premultiplied means that alpha >= color, we construct a color with
+  *  each component==255 and alpha == 0 to be "illegal"
+  */
+-#define GrColor_ILLEGAL     (~(0xFF << GrColor_SHIFT_A))
++#define GrColor_ILLEGAL     ((uint32_t)(~(0xFF << GrColor_SHIFT_A)))
+ 
+ /** Normalizes and coverts an uint8_t to a float. [0, 255] -> [0.0, 1.0] */
+ static inline float GrNormalizeByteToFloat(uint8_t value) {
diff --git a/SOURCES/mozilla-bmo1504834-part1.patch b/SOURCES/mozilla-bmo1504834-part1.patch
new file mode 100644
index 0000000..01da145
--- /dev/null
+++ b/SOURCES/mozilla-bmo1504834-part1.patch
@@ -0,0 +1,77 @@
+diff -up firefox-78.0/gfx/2d/DrawTargetSkia.cpp.mozilla-bmo1504834-part1 firefox-78.0/gfx/2d/DrawTargetSkia.cpp
+--- firefox-78.0/gfx/2d/DrawTargetSkia.cpp.mozilla-bmo1504834-part1	2020-06-17 04:18:58.000000000 +0200
++++ firefox-78.0/gfx/2d/DrawTargetSkia.cpp	2020-06-25 16:52:29.824532769 +0200
+@@ -135,8 +135,7 @@ static IntRect CalculateSurfaceBounds(co
+   return surfaceBounds.Intersect(bounds);
+ }
+ 
+-static const int kARGBAlphaOffset =
+-    SurfaceFormat::A8R8G8B8_UINT32 == SurfaceFormat::B8G8R8A8 ? 3 : 0;
++static const int kARGBAlphaOffset = 0;  // Skia is always BGRA SurfaceFormat::A8R8G8B8_UINT32 == SurfaceFormat::B8G8R8A8 ? 3 : 0;
+ 
+ static bool VerifyRGBXFormat(uint8_t* aData, const IntSize& aSize,
+                              const int32_t aStride, SurfaceFormat aFormat) {
+diff -up firefox-78.0/gfx/2d/Types.h.mozilla-bmo1504834-part1 firefox-78.0/gfx/2d/Types.h
+--- firefox-78.0/gfx/2d/Types.h.mozilla-bmo1504834-part1	2020-06-25 16:52:29.826532776 +0200
++++ firefox-78.0/gfx/2d/Types.h	2020-06-25 16:55:02.942063616 +0200
+@@ -90,15 +90,8 @@ enum class SurfaceFormat : int8_t {
+ // The following values are endian-independent synonyms. The _UINT32 suffix
+ // indicates that the name reflects the layout when viewed as a uint32_t
+ // value.
+-#if MOZ_LITTLE_ENDIAN()
+   A8R8G8B8_UINT32 = B8G8R8A8,  // 0xAARRGGBB
+   X8R8G8B8_UINT32 = B8G8R8X8,  // 0x00RRGGBB
+-#elif MOZ_BIG_ENDIAN()
+-  A8R8G8B8_UINT32 = A8R8G8B8,  // 0xAARRGGBB
+-  X8R8G8B8_UINT32 = X8R8G8B8,  // 0x00RRGGBB
+-#else
+-#  error "bad endianness"
+-#endif
+ 
+   // The following values are OS and endian-independent synonyms.
+   //
+diff -up firefox-78.0/gfx/skia/skia/third_party/skcms/skcms.cc.mozilla-bmo1504834-part1 firefox-78.0/gfx/skia/skia/third_party/skcms/skcms.cc
+--- firefox-78.0/gfx/skia/skia/third_party/skcms/skcms.cc.mozilla-bmo1504834-part1	2020-06-17 04:18:58.000000000 +0200
++++ firefox-78.0/gfx/skia/skia/third_party/skcms/skcms.cc	2020-06-25 16:54:02.993855444 +0200
+@@ -30,6 +30,8 @@
+         #include <avx512fintrin.h>
+         #include <avx512dqintrin.h>
+     #endif
++#else
++    #define SKCMS_PORTABLE
+ #endif
+ 
+ // sizeof(x) will return size_t, which is 32-bit on some machines and 64-bit on others.
+@@ -280,20 +282,28 @@ enum {
+ static uint16_t read_big_u16(const uint8_t* ptr) {
+     uint16_t be;
+     memcpy(&be, ptr, sizeof(be));
+-#if defined(_MSC_VER)
+-    return _byteswap_ushort(be);
++#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
++    return be;
+ #else
++    #if defined(_MSC_VER)
++    return _byteswap_ushort(be);
++    #else
+     return __builtin_bswap16(be);
++    #endif
+ #endif
+ }
+ 
+ static uint32_t read_big_u32(const uint8_t* ptr) {
+     uint32_t be;
+     memcpy(&be, ptr, sizeof(be));
+-#if defined(_MSC_VER)
+-    return _byteswap_ulong(be);
++#if __BYTE_ORDER == __ORDER_BIG_ENDIAN__
++    return be;
+ #else
++    #if defined(_MSC_VER)
++    return _byteswap_ulong(be);
++    #else
+     return __builtin_bswap32(be);
++    #endif
+ #endif
+ }
+ 
diff --git a/SOURCES/mozilla-bmo1504834-part2.patch b/SOURCES/mozilla-bmo1504834-part2.patch
new file mode 100644
index 0000000..e6e6aa5
--- /dev/null
+++ b/SOURCES/mozilla-bmo1504834-part2.patch
@@ -0,0 +1,88 @@
+# HG changeset patch
+# Parent  36563351309ddbc6c29559ba50a41d005f925abb
+Skia does not support big endian. The places to fix are too numerous and upstream (skia, not Mozilla)
+has no interest in maintaining big endian.
+So here we try to swizzle the input for skia, so that skia always works on LE, and when it comes
+out again, we transform back to BE.
+
+diff -r 36563351309d gfx/2d/ConvolutionFilter.cpp
+--- a/gfx/2d/ConvolutionFilter.cpp	Mon Sep 09 17:59:28 2019 +0200
++++ b/gfx/2d/ConvolutionFilter.cpp	Tue Sep 10 08:25:13 2019 +0200
+@@ -35,9 +35,38 @@
+   return true;
+ }
+ 
++static void ByteSwapArray(uint8_t *u8Array, int32_t size) {
++    uint32_t *array = reinterpret_cast<uint32_t*>(u8Array);
++    for (int pxl = 0; pxl < size; ++pxl) {
++        // Use an endian swap to move the bytes, i.e. BGRA -> ARGB.
++        uint32_t rgba = array[pxl];
++        array[pxl] = NativeEndian::swapToLittleEndian(rgba);
++    }
++}
++
+ void ConvolutionFilter::ConvolveHorizontally(const uint8_t* aSrc, uint8_t* aDst,
+                                              bool aHasAlpha) {
++#if MOZ_BIG_ENDIAN
++    int outputSize = mFilter->numValues();
++
++    // Input size isn't handed in, so we have to calculate it quickly
++    int inputSize = 0;
++    for (int xx = 0; xx < outputSize; ++xx) {
++        // Get the filter that determines the current output pixel.
++        int filterOffset, filterLength;
++        mFilter->FilterForValue(xx, &filterOffset, &filterLength);
++        inputSize = std::max(inputSize, filterOffset + filterLength);
++    }
++
++    ByteSwapArray((uint8_t*)aSrc, inputSize);
++#endif
++
+   SkOpts::convolve_horizontally(aSrc, *mFilter, aDst, aHasAlpha);
++
++#if MOZ_BIG_ENDIAN
++    ByteSwapArray((uint8_t*)aSrc, inputSize);
++    ByteSwapArray(aDst, outputSize);
++#endif
+ }
+ 
+ void ConvolutionFilter::ConvolveVertically(uint8_t* const* aSrc, uint8_t* aDst,
+@@ -49,8 +78,26 @@
+   int32_t filterLength;
+   auto filterValues =
+       mFilter->FilterForValue(aRowIndex, &filterOffset, &filterLength);
++
++#if MOZ_BIG_ENDIAN
++  for (int filterY = 0; filterY < filterLength; filterY++) {
++      // Skia only knows LE, so we have to swizzle the input
++    ByteSwapArray(aSrc[filterY], aRowSize);
++  }
++#endif
++
+   SkOpts::convolve_vertically(filterValues, filterLength, aSrc, aRowSize, aDst,
+                               aHasAlpha);
++
++#if MOZ_BIG_ENDIAN
++  // After skia is finished, we swizzle back to BE, in case
++  // the input is used again somewhere else
++  for (int filterY = 0; filterY < filterLength; filterY++) {
++    ByteSwapArray(aSrc[filterY], aRowSize);
++  }
++  // The destination array as well
++  ByteSwapArray(aDst, aRowSize);
++#endif
+ }
+ 
+ /* ConvolutionFilter::ComputeResizeFactor is derived from Skia's
+diff -r 36563351309d gfx/skia/skia/include/core/SkPreConfig.h
+--- a/gfx/skia/skia/include/core/SkPreConfig.h	Mon Sep 09 17:59:28 2019 +0200
++++ b/gfx/skia/skia/include/core/SkPreConfig.h	Tue Sep 10 08:25:13 2019 +0200
+@@ -73,7 +73,7 @@
+       defined(__ppc__) || defined(__hppa) || \
+       defined(__PPC__) || defined(__PPC64__) || \
+       defined(_MIPSEB) || defined(__ARMEB__) || \
+-      defined(__s390__) || \
++      defined(__s390__) || defined(__s390x__) || \
+       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
+       (defined(__ia64) && defined(__BIG_ENDIAN__))
+          #define SK_CPU_BENDIAN
diff --git a/SOURCES/mozilla-bmo1504834-part3.patch b/SOURCES/mozilla-bmo1504834-part3.patch
new file mode 100644
index 0000000..1a498f8
--- /dev/null
+++ b/SOURCES/mozilla-bmo1504834-part3.patch
@@ -0,0 +1,44 @@
+# HG changeset patch
+# Parent  aecb4600e5da17443b224c79eee178c1d8e155e3
+For FF68, AntiAliasing of XULTexts seem to be broken on big endian (s390x). Text and icons of the sandwich-menu to the
+right of the address bar, as well as plugin-windows appears transparant, which usually means unreadable (white on white).
+
+diff -r aecb4600e5da gfx/skia/skia/include/private/SkNx.h
+--- a/gfx/skia/skia/include/private/SkNx.h	Tue Aug 20 09:46:55 2019 +0200
++++ b/gfx/skia/skia/include/private/SkNx.h	Mon Sep 09 10:04:06 2019 +0200
+@@ -238,7 +238,18 @@
+     AI SkNx operator*(const SkNx& y) const { return fVal * y.fVal; }
+     AI SkNx operator/(const SkNx& y) const { return fVal / y.fVal; }
+ 
++    // On Big endian the commented out variant doesn't work,
++    // and honestly, I have no idea why it exists in the first place.
++    // The reason its broken is, I think, that it defaults to the double-variant of ToBits()
++    // which gets a 64-bit integer, and FromBits returns 32-bit,
++    // cutting off the wrong half again.
++    // Overall, I see no reason to have ToBits and FromBits at all (even for floats/doubles).
++    // Still we are only "fixing" this for big endian and leave little endian alone (never touch a running system)
++#ifdef SK_CPU_BENDIAN
++    AI SkNx operator&(const SkNx& y) const { return fVal & y.fVal; }
++#else
+     AI SkNx operator&(const SkNx& y) const { return FromBits(ToBits(fVal) & ToBits(y.fVal)); }
++#endif
+     AI SkNx operator|(const SkNx& y) const { return FromBits(ToBits(fVal) | ToBits(y.fVal)); }
+     AI SkNx operator^(const SkNx& y) const { return FromBits(ToBits(fVal) ^ ToBits(y.fVal)); }
+ 
+diff -r aecb4600e5da gfx/skia/skia/src/opts/SkBlitMask_opts.h
+--- a/gfx/skia/skia/src/opts/SkBlitMask_opts.h	Tue Aug 20 09:46:55 2019 +0200
++++ b/gfx/skia/skia/src/opts/SkBlitMask_opts.h	Mon Sep 09 10:04:06 2019 +0200
+@@ -203,7 +203,13 @@
+             //   ~~~>
+             // a = 1*aa + d(1-1*aa) = aa + d(1-aa)
+             // c = 0*aa + d(1-1*aa) =      d(1-aa)
++
++            // For big endian we have to swap the alpha-mask from 0,0,0,255 to 255,0,0,0
++#ifdef SK_CPU_BENDIAN
++            return Sk4px(Sk16b(aa) & Sk16b(255,0,0,0, 255,0,0,0, 255,0,0,0, 255,0,0,0))
++#else
+             return Sk4px(Sk16b(aa) & Sk16b(0,0,0,255, 0,0,0,255, 0,0,0,255, 0,0,0,255))
++#endif
+                  + d.approxMulDiv255(aa.inv());
+         };
+         while (h --> 0) {
diff --git a/SOURCES/mozilla-bmo1504834-part4.patch b/SOURCES/mozilla-bmo1504834-part4.patch
new file mode 100644
index 0000000..9d2ffc4
--- /dev/null
+++ b/SOURCES/mozilla-bmo1504834-part4.patch
@@ -0,0 +1,30 @@
+# HG changeset patch
+# Parent  46ea866ca3acb8bb5e1709ceb799b9c94f591dec
+Problem description: Tab-titles that are too long to fit into a tab get faded out.
+                     On big endian this is broken and instead of fading out, the 
+                     tab gets white and the font transparent, leading to an unreadable
+                     tab-title
+Solution: This is not a real solution, but a hack. The real solution would have been
+          to byte-swap the correct buffer, but I could not find it.
+          So the next best thing is to deactivate the fading-effect. Now all tab-titles
+          are readable, albeit not as pretty to look at as they could be. 
+Side-effects: I have not yet found an unwanted side-effect.
+
+diff -r 46ea866ca3ac -r 6ef20eee3f8f gfx/2d/DrawTargetSkia.cpp
+--- a/gfx/2d/DrawTargetSkia.cpp	Tue Oct 22 12:27:22 2019 +0200
++++ b/gfx/2d/DrawTargetSkia.cpp	Thu Oct 31 09:11:56 2019 +0100
+@@ -1861,6 +1861,14 @@
+       SkCanvas::kPreserveLCDText_SaveLayerFlag |
+           (aCopyBackground ? SkCanvas::kInitWithPrevious_SaveLayerFlag : 0));
+ 
++#if MOZ_BIG_ENDIAN
++  // Pushing a layer where an aMask is defined produces wrong output.
++  // We _should_ endian swap the data, but I couldn't find a workable way to do so
++  // Therefore I deactivate those layers in the meantime.
++  // The result is: Tab-titles that are longer than the available space should be faded out.
++  //                The fading doesn't work, so we deactivate the fading-effect here.
++  if (!aMask)
++#endif
+   mCanvas->saveLayer(saveRec);
+ 
+   SetPermitSubpixelAA(aOpaque);
diff --git a/SOURCES/mozilla-bmo1554971.patch b/SOURCES/mozilla-bmo1554971.patch
new file mode 100644
index 0000000..ab25c2d
--- /dev/null
+++ b/SOURCES/mozilla-bmo1554971.patch
@@ -0,0 +1,22 @@
+# HG changeset patch
+# Parent  a25cebecb02d5460b8ad757fe9cb4a9c8d1d7658
+Eliminate startup error message:
+JavaScript error: , line 0: Error: Type error for platformInfo value (Error processing arch: Invalid enumeration value "s390x") for runtime.getPlatformInfo.
+
+Reported here: https://bugzilla.mozilla.org/show_bug.cgi?id=1554971
+
+Uncertain if this is causing real problems or not. Also uncertain if the fix actually fixes anything.
+No response from upstream yet.
+
+diff -r a25cebecb02d -r 378b81b00e73 toolkit/components/extensions/schemas/runtime.json
+--- a/toolkit/components/extensions/schemas/runtime.json	Fri Jul 05 12:42:44 2019 +0200
++++ b/toolkit/components/extensions/schemas/runtime.json	Fri Jul 19 13:19:30 2019 +0200
+@@ -64,7 +64,7 @@
+       {
+         "id": "PlatformArch",
+         "type": "string",
+-        "enum": ["arm", "x86-32", "x86-64"],
++        "enum": ["arm", "x86-32", "x86-64", "s390x", "aarch64", "ppc64le"],
+         "allowedContexts": ["content", "devtools"],
+         "description": "The machine's processor architecture."
+       },
diff --git a/SOURCES/mozilla-bmo1602730.patch b/SOURCES/mozilla-bmo1602730.patch
new file mode 100644
index 0000000..c11f958
--- /dev/null
+++ b/SOURCES/mozilla-bmo1602730.patch
@@ -0,0 +1,28 @@
+diff -r 6ef20eee3f8f gfx/layers/basic/BasicCompositor.cpp
+--- a/gfx/layers/basic/BasicCompositor.cpp	Thu Oct 31 09:11:56 2019 +0100
++++ b/gfx/layers/basic/BasicCompositor.cpp	Wed Dec 11 16:16:09 2019 +0100
+@@ -693,9 +693,13 @@
+ 
+   RefPtr<SourceSurface> sourceMask;
+   Matrix maskTransform;
++  // Setting an alpha-mask here breaks the URL-bar on big endian (s390x)
++  // if the typed URL is too long for the textbox (automatic scrolling needed)
++#if MOZ_LITTLE_ENDIAN
+   if (aTransform.Is2D()) {
+     SetupMask(aEffectChain, dest, offset, sourceMask, maskTransform);
+   }
++#endif
+ 
+   CompositionOp blendMode = CompositionOp::OP_OVER;
+   if (Effect* effect =
+diff -r 6ef20eee3f8f gfx/layers/composite/CompositableHost.cpp
+--- a/gfx/layers/composite/CompositableHost.cpp	Thu Oct 31 09:11:56 2019 +0100
++++ b/gfx/layers/composite/CompositableHost.cpp	Wed Dec 11 16:16:09 2019 +0100
+@@ -91,6 +91,7 @@
+   }
+   MOZ_ASSERT(source);
+ 
++  // Alternatively: Comment out these lines where the alpha-mask is set
+   RefPtr<EffectMask> effect =
+       new EffectMask(source, source->GetSize(), aTransform);
+   aEffects.mSecondaryEffects[EffectTypes::MASK] = effect;
diff --git a/SOURCES/mozilla-bmo1626236.patch b/SOURCES/mozilla-bmo1626236.patch
new file mode 100644
index 0000000..32e3742
--- /dev/null
+++ b/SOURCES/mozilla-bmo1626236.patch
@@ -0,0 +1,86 @@
+# HG changeset patch
+# User msirringhaus@suse.de
+# Date 1582805876 -3600
+#      Thu Feb 27 13:17:56 2020 +0100
+# Node ID cc3d09abea31068e57f1ab918782f9f86fc6a158
+# Parent  9cd90914846f667f18babc491a74c164ae5d6e9f
+imported patch decoder_workaround.patch
+
+diff -r 9cd90914846f image/decoders/nsGIFDecoder2.cpp
+--- a/image/decoders/nsGIFDecoder2.cpp	Thu Feb 27 12:57:14 2020 +0100
++++ b/image/decoders/nsGIFDecoder2.cpp	Fri Mar 27 13:06:18 2020 +0100
+@@ -422,6 +422,9 @@
+   MOZ_ASSERT(mSwizzleFn);
+   uint8_t* data = reinterpret_cast<uint8_t*>(aColormap);
+   mSwizzleFn(data, data, aColors);
++#if MOZ_BIG_ENDIAN()
++  SwizzleRow(SurfaceFormat::A8R8G8B8, SurfaceFormat::B8G8R8A8)(data, data, aColors);
++#endif
+ }
+ 
+ LexerResult nsGIFDecoder2::DoDecode(SourceBufferIterator& aIterator,
+diff -r 9cd90914846f image/decoders/nsJPEGDecoder.cpp
+--- a/image/decoders/nsJPEGDecoder.cpp	Thu Feb 27 12:57:14 2020 +0100
++++ b/image/decoders/nsJPEGDecoder.cpp	Fri Mar 27 13:06:18 2020 +0100
+@@ -263,6 +263,9 @@
+         case JCS_YCbCr:
+           // By default, we will output directly to BGRA. If we need to apply
+           // special color transforms, this may change.
++#if MOZ_BIG_ENDIAN()
++          mInfo.out_color_space = MOZ_JCS_EXT_NATIVE_ENDIAN_XRGB;
++#else
+           switch (SurfaceFormat::OS_RGBX) {
+             case SurfaceFormat::B8G8R8X8:
+               mInfo.out_color_space = JCS_EXT_BGRX;
+@@ -277,6 +280,7 @@
+               mState = JPEG_ERROR;
+               return Transition::TerminateFailure();
+           }
++#endif
+           break;
+         case JCS_CMYK:
+         case JCS_YCCK:
+diff -r 9cd90914846f image/decoders/nsPNGDecoder.cpp
+--- a/image/decoders/nsPNGDecoder.cpp	Thu Feb 27 12:57:14 2020 +0100
++++ b/image/decoders/nsPNGDecoder.cpp	Fri Mar 27 13:06:18 2020 +0100
+@@ -361,7 +361,7 @@
+                                    IResumable* aOnResume) {
+   MOZ_ASSERT(!HasError(), "Shouldn't call DoDecode after error!");
+ 
+-  return mLexer.Lex(aIterator, aOnResume,
++  LexerResult res = mLexer.Lex(aIterator, aOnResume,
+                     [=](State aState, const char* aData, size_t aLength) {
+                       switch (aState) {
+                         case State::PNG_DATA:
+@@ -371,6 +371,14 @@
+                       }
+                       MOZ_CRASH("Unknown State");
+                     });
++
++#if MOZ_BIG_ENDIAN()
++  if(res.is<TerminalState>() && res.as<TerminalState>() == TerminalState::SUCCESS) {
++      NativeEndian::swapToLittleEndianInPlace<uint32_t>((uint32_t*)(mImageData), mImageDataLength / 4);
++  }
++#endif
++
++  return res;
+ }
+ 
+ LexerTransition<nsPNGDecoder::State> nsPNGDecoder::ReadPNGData(
+diff -r 9cd90914846f image/decoders/nsWebPDecoder.cpp
+--- a/image/decoders/nsWebPDecoder.cpp	Thu Feb 27 12:57:14 2020 +0100
++++ b/image/decoders/nsWebPDecoder.cpp	Fri Mar 27 13:06:18 2020 +0100
+@@ -237,7 +237,12 @@
+   // WebP doesn't guarantee that the alpha generated matches the hint in the
+   // header, so we always need to claim the input is BGRA. If the output is
+   // BGRX, swizzling will mask off the alpha channel.
++#if MOZ_BIG_ENDIAN()
++  mBuffer.colorspace = MODE_ARGB;
++  SurfaceFormat inFormat = mFormat;
++#else
+   SurfaceFormat inFormat = SurfaceFormat::OS_RGBA;
++#endif
+ 
+   SurfacePipeFlags pipeFlags = SurfacePipeFlags();
+   if (mFormat == SurfaceFormat::OS_RGBA &&
+
diff --git a/SOURCES/mozilla-bmo849632.patch b/SOURCES/mozilla-bmo849632.patch
new file mode 100644
index 0000000..177fdc3
--- /dev/null
+++ b/SOURCES/mozilla-bmo849632.patch
@@ -0,0 +1,23 @@
+Problem:  webGL sites are displayed in the wrong color (usually blue-ish)
+Solution: Problem is with skia once again. Output of webgl seems endian-correct, but skia only
+          knows how to deal with little endian.
+          So we swizzle the output of webgl after reading it from readpixels()
+Note:     This does not fix all webGL sites, but is a step in the right direction
+diff -r 6b017d3e9733 gfx/gl/GLContext.h
+--- a/gfx/gl/GLContext.h    Mon Sep 09 10:04:05 2019 +0200
++++ b/gfx/gl/GLContext.h    Wed Nov 13 17:13:04 2019 +0100
+@@ -1551,6 +1551,13 @@
+     BEFORE_GL_CALL;
+     mSymbols.fReadPixels(x, y, width, height, format, type, pixels);
+     OnSyncCall();
++#if MOZ_BIG_ENDIAN
++    uint8_t* itr = (uint8_t*)pixels;
++    for (GLsizei i = 0; i < width * height; i++) {
++      NativeEndian::swapToLittleEndianInPlace((uint32_t*)itr, 1);
++      itr += 4;
++    }
++#endif
+     AFTER_GL_CALL;
+     mHeavyGLCallsSinceLastFlush = true;
+   }
+
diff --git a/SOURCES/mozilla-bmo998749.patch b/SOURCES/mozilla-bmo998749.patch
new file mode 100644
index 0000000..4ddde4c
--- /dev/null
+++ b/SOURCES/mozilla-bmo998749.patch
@@ -0,0 +1,30 @@
+# HG changeset patch
+# User msirringhaus@suse.de
+# Date 1583738770 -3600
+#      Mon Mar 09 08:26:10 2020 +0100
+# Node ID 34676feac1a542e409e22acf5b98735f8313b1ce
+# Parent  506857dace0a08d1c9685e3ac264646590b3e27f
+[mq]: mozilla-bmo998749.patch
+
+diff -r 506857dace0a -r 34676feac1a5 gfx/2d/FilterProcessing.h
+--- a/gfx/2d/FilterProcessing.h	Fri Feb 28 12:31:51 2020 +0100
++++ b/gfx/2d/FilterProcessing.h	Mon Mar 09 08:26:10 2020 +0100
+@@ -13,10 +13,17 @@
+ namespace mozilla {
+ namespace gfx {
+ 
++#if MOZ_BIG_ENDIAN()
++const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_B = 3;
++const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_G = 2;
++const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_R = 1;
++const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_A = 0;
++#else
+ const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_B = 0;
+ const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_G = 1;
+ const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_R = 2;
+ const ptrdiff_t B8G8R8A8_COMPONENT_BYTEOFFSET_A = 3;
++#endif
+ 
+ class FilterProcessing {
+  public:
+
diff --git a/SOURCES/mozilla-s390-context.patch b/SOURCES/mozilla-s390-context.patch
new file mode 100644
index 0000000..55bd7a8
--- /dev/null
+++ b/SOURCES/mozilla-s390-context.patch
@@ -0,0 +1,36 @@
+# HG changeset patch
+# User msirringhaus@suse.de
+# Date 1558452408 -7200
+#      Tue May 21 17:26:48 2019 +0200
+# Node ID 602e92722e765a3c238d3b96b26c0c8063b5eeb4
+# Parent  a3cc550d25e3a04d906f516928cbcbe50efd585e
+[mq]: mozilla-s390-context.patch
+
+diff -r a3cc550d25e3 -r 602e92722e76 js/src/wasm/WasmSignalHandlers.cpp
+--- a/js/src/wasm/WasmSignalHandlers.cpp	Tue May 21 17:22:06 2019 +0200
++++ b/js/src/wasm/WasmSignalHandlers.cpp	Tue May 21 17:26:48 2019 +0200
+@@ -154,6 +154,10 @@
+ #    define R01_sig(p) ((p)->uc_mcontext.gp_regs[1])
+ #    define R32_sig(p) ((p)->uc_mcontext.gp_regs[32])
+ #  endif
++#  if defined(__linux__) && defined(__s390x__)
++#    define GR_sig(p,x) ((p)->uc_mcontext.gregs[x])
++#    define PSWa_sig(p) ((p)->uc_mcontext.psw.addr)
++#  endif
+ #elif defined(__NetBSD__)
+ #  define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
+ #  define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
+@@ -385,8 +389,13 @@
+ #  define PC_sig(p) R32_sig(p)
+ #  define SP_sig(p) R01_sig(p)
+ #  define FP_sig(p) R01_sig(p)
++#elif defined(__s390x__)
++# define PC_sig(p) PSWa_sig(p)
++# define SP_sig(p) GR_sig(p, 15)
++# define FP_sig(p) GR_sig(p, 11)
+ #endif
+ 
++
+ static void SetContextPC(CONTEXT* context, uint8_t* pc) {
+ #ifdef PC_sig
+   *reinterpret_cast<uint8_t**>(&PC_sig(context)) = pc;
diff --git a/SOURCES/mozilla-s390x-skia-gradient.patch b/SOURCES/mozilla-s390x-skia-gradient.patch
new file mode 100644
index 0000000..8c0e3bd
--- /dev/null
+++ b/SOURCES/mozilla-s390x-skia-gradient.patch
@@ -0,0 +1,52 @@
+# HG changeset patch
+# Parent  acf59ea86dd1d878b43920832093f082dcfc61c0
+
+diff -r acf59ea86dd1 gfx/skia/skia/src/shaders/gradients/Sk4fLinearGradient.cpp
+--- a/gfx/skia/skia/src/shaders/gradients/Sk4fLinearGradient.cpp	Mon Mar 09 08:26:10 2020 +0100
++++ b/gfx/skia/skia/src/shaders/gradients/Sk4fLinearGradient.cpp	Fri Mar 27 13:30:28 2020 +0100
+@@ -7,7 +7,7 @@
+ 
+ #include "include/core/SkPaint.h"
+ #include "src/shaders/gradients/Sk4fLinearGradient.h"
+-
++#include "src/core/SkEndian.h"
+ #include <cmath>
+ #include <utility>
+ 
+@@ -28,6 +28,9 @@
+ 
+     while (n >= 4) {
+         DstTraits<premul>::store4x(c0, c1, c2, c3, dst, bias0, bias1);
++#ifdef SK_CPU_BENDIAN
++        SkEndianSwap32s(dst, 4);
++#endif
+         dst += 4;
+ 
+         c0 = c0 + dc4;
+@@ -37,12 +40,23 @@
+         n -= 4;
+     }
+     if (n & 2) {
+-        DstTraits<premul>::store(c0, dst++, bias0);
+-        DstTraits<premul>::store(c1, dst++, bias1);
++        DstTraits<premul>::store(c0, dst, bias0);
++#ifdef SK_CPU_BENDIAN
++        *dst = SkEndianSwap32(*dst);
++#endif
++        ++dst;
++        DstTraits<premul>::store(c1, dst, bias1);
++#ifdef SK_CPU_BENDIAN
++        *dst = SkEndianSwap32(*dst);
++#endif
++        ++dst;
+         c0 = c0 + dc2;
+     }
+     if (n & 1) {
+         DstTraits<premul>::store(c0, dst, bias0);
++#ifdef SK_CPU_BENDIAN
++        *dst = SkEndianSwap32(*dst);
++#endif
+     }
+ }
+ 
+
diff --git a/SOURCES/no-rust-lto.patch b/SOURCES/no-rust-lto.patch
deleted file mode 100644
index 227bb9c..0000000
--- a/SOURCES/no-rust-lto.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff -up thunderbird-68.11.0/config/makefiles/rust.mk.no-rust-lto thunderbird-68.11.0/config/makefiles/rust.mk
---- thunderbird-68.11.0/config/makefiles/rust.mk.no-rust-lto	2020-08-04 12:01:08.172071480 +0200
-+++ thunderbird-68.11.0/config/makefiles/rust.mk	2020-08-04 12:26:25.927808414 +0200
-@@ -50,8 +50,8 @@ ifndef MOZ_DEBUG_RUST
- # Pass -Clto for older versions of rust, and CARGO_PROFILE_RELEASE_LTO=true
- # for newer ones that support it. Combining the latter with -Clto works, so
- # set both everywhere.
--cargo_rustc_flags += -C lto
--export CARGO_PROFILE_RELEASE_LTO=true
-+#cargo_rustc_flags += -C lto
-+#export CARGO_PROFILE_RELEASE_LTO=true
- endif
- endif
- 
diff --git a/SOURCES/nss-build-mozilla-1564499.patch b/SOURCES/nss-build-mozilla-1564499.patch
deleted file mode 100644
index 9d5bb5c..0000000
--- a/SOURCES/nss-build-mozilla-1564499.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -up firefox-68.0/security/nss/lib/freebl/mpi/mpcpucache.c.old firefox-68.0/security/nss/lib/freebl/mpi/mpcpucache.c
---- firefox-68.0/security/nss/lib/freebl/mpi/mpcpucache.c.old	2019-07-26 07:09:02.383303420 +0200
-+++ firefox-68.0/security/nss/lib/freebl/mpi/mpcpucache.c	2019-07-26 07:09:27.228193798 +0200
-@@ -727,7 +727,7 @@ static inline void
- dcbzl(char *array)
- {
-     register char *a asm("r2") = array;
--    __asm__ __volatile__("dcbzl %0,r0"
-+    __asm__ __volatile__("dcbzl %0,0"
-                          : "=r"(a)
-                          : "0"(a));
- }
diff --git a/SOURCES/nss-setup-flags-env.inc b/SOURCES/nss-setup-flags-env.inc
new file mode 100644
index 0000000..c3624b1
--- /dev/null
+++ b/SOURCES/nss-setup-flags-env.inc
@@ -0,0 +1,7 @@
+sed -i 's@%{gtk3_install_path}@%{_buildrootdir}%{gtk3_install_path}@g' %{_buildrootdir}%{gtk3_install_path}/%{_lib}/pkgconfig/nss*.pc
+
+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
+export PATH="{_buildrootdir}%{gtk3_install_path}/bin:$PATH"
diff --git a/SOURCES/rhbz-1503632-nss.patch b/SOURCES/rhbz-1503632-nss.patch
deleted file mode 100644
index f7a26d3..0000000
--- a/SOURCES/rhbz-1503632-nss.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-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/rhbz-1821418.patch b/SOURCES/rhbz-1821418.patch
new file mode 100644
index 0000000..8b02dfb
--- /dev/null
+++ b/SOURCES/rhbz-1821418.patch
@@ -0,0 +1,36 @@
+diff -up firefox-78.0/xpcom/base/AvailableMemoryTracker.cpp.rhbz-1821418 firefox-78.0/xpcom/base/AvailableMemoryTracker.cpp
+--- firefox-78.0/xpcom/base/AvailableMemoryTracker.cpp.rhbz-1821418	2020-06-17 04:20:44.000000000 +0200
++++ firefox-78.0/xpcom/base/AvailableMemoryTracker.cpp	2020-06-25 14:50:46.369798294 +0200
+@@ -157,8 +157,12 @@ bool nsAvailableMemoryWatcher::IsVirtual
+ 
+ /* static */
+ bool nsAvailableMemoryWatcher::IsCommitSpaceLow(const MEMORYSTATUSEX& aStat) {
+-  if ((kLowCommitSpaceThreshold != 0) &&
+-      (aStat.ullAvailPageFile < kLowCommitSpaceThreshold)) {
++  const char* threshold = getenv("MOZ_GC_THRESHOLD");
++  if (threshold) {
++    kLowCommitSpaceThreshold = atoi(threshold);
++  }
++
++  if ((kLowCommitSpaceThreshold == 0) || (aStat.ullAvailPageFile < kLowCommitSpaceThreshold)) {
+     sNumLowCommitSpaceEvents++;
+     CrashReporter::AnnotateCrashReport(
+         CrashReporter::Annotation::LowCommitSpaceEvents,
+@@ -210,12 +214,15 @@ void nsAvailableMemoryWatcher::AdjustPol
+ // polling interval accordingly.
+ NS_IMETHODIMP
+ nsAvailableMemoryWatcher::Notify(nsITimer* aTimer) {
++  const char* threshold = getenv("MOZ_GC_THRESHOLD");
++  bool forceLowMem = (threshold && atoi(threshold) == 0);
++
+   MEMORYSTATUSEX stat;
+   stat.dwLength = sizeof(stat);
+   bool success = GlobalMemoryStatusEx(&stat);
+ 
+-  if (success) {
+-    bool lowMemory = IsVirtualMemoryLow(stat) || IsCommitSpaceLow(stat);
++  if (success || forceLowMemory) {
++    bool lowMemory = IsVirtualMemoryLow(stat) || IsCommitSpaceLow(stat || forceLowMem);
+ 
+     if (lowMemory) {
+       SendMemoryPressureEvent();
diff --git a/SOURCES/rust-network-check.patch b/SOURCES/rust-network-check.patch
deleted file mode 100644
index d18f2fe..0000000
--- a/SOURCES/rust-network-check.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-diff -up firefox-68.0/config/makefiles/rust.mk.rust-network-check firefox-68.0/config/makefiles/rust.mk
---- firefox-68.0/config/makefiles/rust.mk.rust-network-check	2019-06-06 10:29:18.984737603 +0200
-+++ firefox-68.0/config/makefiles/rust.mk	2019-06-06 11:39:51.581028835 +0200
-@@ -127,7 +127,7 @@ export RUST_BACKTRACE=full
- export MOZ_TOPOBJDIR=$(topobjdir)
- 
- target_rust_ltoable := force-cargo-library-build
--target_rust_nonltoable := force-cargo-test-run force-cargo-library-check $(foreach b,build check,force-cargo-program-$(b))
-+target_rust_nonltoable := force-cargo-test-run $(foreach b,build check,force-cargo-program-$(b))
- 
- $(target_rust_ltoable): RUSTFLAGS:=$(rustflags_override) $(RUSTFLAGS) $(if $(MOZ_LTO_RUST),-Clinker-plugin-lto)
- $(target_rust_nonltoable): RUSTFLAGS:=$(rustflags_override) $(RUSTFLAGS)
-@@ -238,19 +238,9 @@ force-cargo-library-build:
- 	$(call CARGO_BUILD) --lib $(cargo_target_flag) $(rust_features_flag) -- $(cargo_rustc_flags)
- 
- $(RUST_LIBRARY_FILE): force-cargo-library-build
--# When we are building in --enable-release mode; we add an additional check to confirm
--# that we are not importing any networking-related functions in rust code. This reduces
--# the chance of proxy bypasses originating from rust code.
--ifndef DEVELOPER_OPTIONS
--ifndef MOZ_DEBUG_RUST
--ifeq ($(OS_ARCH), Linux)
--	$(call py_action,check_binary,--target --networking $@)
--endif
--endif
--endif
- 
- force-cargo-library-check:
--	$(call CARGO_CHECK) --lib $(cargo_target_flag) $(rust_features_flag)
-+	@true
- else
- force-cargo-library-check:
- 	@true
-diff -up firefox-68.0/python/mozbuild/mozbuild/action/check_binary.py.rust-network-check firefox-68.0/python/mozbuild/mozbuild/action/check_binary.py
---- firefox-68.0/python/mozbuild/mozbuild/action/check_binary.py.rust-network-check	2019-05-20 18:17:57.000000000 +0200
-+++ firefox-68.0/python/mozbuild/mozbuild/action/check_binary.py	2019-06-06 10:29:18.986737599 +0200
-@@ -250,43 +250,6 @@ def check_mozglue_order(target, binary):
-         raise RuntimeError('Could not parse readelf output?')
- 
- 
--def check_networking(binary):
--    retcode = 0
--    networking_functions = set([
--        # socketpair is not concerning; it is restricted to AF_UNIX
--        "socket", "connect", "accept", "bind", "listen",
--        "getsockname", "getsockopt", "setsockopt",
--        "recv", "recvfrom",
--        "send", "sendto",
--        # We would be concerned by recvmsg and sendmsg; but we believe
--        # they are okay as documented in 1376621#c23
--        "gethostbyname", "gethostbyaddr", "gethostent", "sethostent", "endhostent",
--        "gethostent_r", "gethostbyname2", "gethostbyaddr_r", "gethostbyname_r",
--        "gethostbyname2_r",
--        "getaddrinfo", "getservent", "getservbyname", "getservbyport", "setservent",
--        "getprotoent", "getprotobyname", "getprotobynumber", "setprotoent",
--        "endprotoent"])
--    bad_occurences_names = set()
--
--    try:
--        for sym in at_least_one(iter_symbols(binary)):
--            if sym['addr'] == 0 and sym['name'] in networking_functions:
--                bad_occurences_names.add(sym['name'])
--    except Empty:
--        raise RuntimeError('Could not parse llvm-objdump output?')
--
--    basename = os.path.basename(binary)
--    if bad_occurences_names:
--        s = 'TEST-UNEXPECTED-FAIL | check_networking | {} | Identified {} ' + \
--            'networking function(s) being imported in the rust static library ({})'
--        print(s.format(basename, len(bad_occurences_names),
--            ",".join(sorted(bad_occurences_names))),
--            file=sys.stderr)
--        retcode = 1
--    elif buildconfig.substs.get('MOZ_AUTOMATION'):
--        print('TEST-PASS | check_networking | {}'.format(basename))
--    return retcode
--
- def checks(target, binary):
-     # The clang-plugin is built as target but is really a host binary.
-     # Cheat and pretend we were passed the right argument.
-@@ -330,8 +293,6 @@ def main(args):
-                         help='Perform checks for a host binary')
-     parser.add_argument('--target', action='store_true',
-                         help='Perform checks for a target binary')
--    parser.add_argument('--networking', action='store_true',
--                        help='Perform checks for networking functions')
- 
-     parser.add_argument('binary', metavar='PATH',
-                         help='Location of the binary to check')
-@@ -343,14 +304,7 @@ def main(args):
-               file=sys.stderr)
-         return 1
- 
--    if options.networking and options.host:
--        print('--networking is only valid with --target',
--               file=sys.stderr)
--        return 1
--
--    if options.networking:
--        return check_networking(options.binary)
--    elif options.host:
-+    if options.host:
-         return checks(HOST, options.binary)
-     elif options.target:
-         return checks(TARGET, options.binary)
diff --git a/SOURCES/thunderbird-centos-default-prefs.js.el6 b/SOURCES/thunderbird-centos-default-prefs.js.el6
deleted file mode 100644
index 75de82e..0000000
--- a/SOURCES/thunderbird-centos-default-prefs.js.el6
+++ /dev/null
@@ -1,30 +0,0 @@
-pref("app.update.enabled", false);
-pref("app.update.autoInstallEnabled", false);
-# Allow users to set custom colors
-# pref("browser.display.use_system_colors",   true);
-pref("general.useragent.vendor", "CentOS");
-pref("general.useragent.vendorSub", "THUNDERBIRD_RPM_VR");
-pref("intl.locale.matchOS", true);
-pref("mail.shell.checkDefaultClient", false);
-pref("toolkit.networkmanager.disable", false);
-pref("offline.autoDetect", true);
-
-# Disable global indexing by default
-pref("mailnews.database.global.indexer.enabled", false);
-
-# Do not switch to Smart Folders after upgrade to 3.0b4
-pref("mail.folder.views.version", "1");
-pref("extensions.shownSelectionUI", true);
-pref("extensions.autoDisableScope", 0);
-
-# For rhbz#1024232
-pref("ui.SpellCheckerUnderlineStyle",       1);
-
-/* Workaround for rhbz#1134876 */
-pref("javascript.options.baselinejit",      false);
-/* Workaround for rhbz#1110291 */
-pref("network.negotiate-auth.allow-insecure-ntlm-v1", true);
-/* Workaround for mozbz#1063315 */
-pref("security.use_mozillapkix_verification", false);
-/* Use OS settings for UI language */
-pref("intl.locale.requested", "");
diff --git a/SOURCES/thunderbird-centos-default-prefs.js.el7 b/SOURCES/thunderbird-centos-default-prefs.js.el7
deleted file mode 100644
index 75de82e..0000000
--- a/SOURCES/thunderbird-centos-default-prefs.js.el7
+++ /dev/null
@@ -1,30 +0,0 @@
-pref("app.update.enabled", false);
-pref("app.update.autoInstallEnabled", false);
-# Allow users to set custom colors
-# pref("browser.display.use_system_colors",   true);
-pref("general.useragent.vendor", "CentOS");
-pref("general.useragent.vendorSub", "THUNDERBIRD_RPM_VR");
-pref("intl.locale.matchOS", true);
-pref("mail.shell.checkDefaultClient", false);
-pref("toolkit.networkmanager.disable", false);
-pref("offline.autoDetect", true);
-
-# Disable global indexing by default
-pref("mailnews.database.global.indexer.enabled", false);
-
-# Do not switch to Smart Folders after upgrade to 3.0b4
-pref("mail.folder.views.version", "1");
-pref("extensions.shownSelectionUI", true);
-pref("extensions.autoDisableScope", 0);
-
-# For rhbz#1024232
-pref("ui.SpellCheckerUnderlineStyle",       1);
-
-/* Workaround for rhbz#1134876 */
-pref("javascript.options.baselinejit",      false);
-/* Workaround for rhbz#1110291 */
-pref("network.negotiate-auth.allow-insecure-ntlm-v1", true);
-/* Workaround for mozbz#1063315 */
-pref("security.use_mozillapkix_verification", false);
-/* Use OS settings for UI language */
-pref("intl.locale.requested", "");
diff --git a/SOURCES/thunderbird-mozconfig b/SOURCES/thunderbird-mozconfig
index 559acb8..27091df 100644
--- a/SOURCES/thunderbird-mozconfig
+++ b/SOURCES/thunderbird-mozconfig
@@ -1,25 +1,25 @@
 ac_add_options --enable-application=comm/mail
 
-ac_add_options --disable-crashreporter
-ac_add_options --disable-libjpeg-turbo
-ac_add_options --disable-necko-wifi
+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 --disable-strip
 ac_add_options --disable-tests
+#ac_add_options --enable-libnotify
+ac_add_options --enable-necko-wifi
 ac_add_options --disable-updater
 ac_add_options --enable-calendar
+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-default-toolkit=cairo-gtk3
-ac_add_options --enable-release
-ac_add_options --enable-startup-notification
-ac_add_options --libdir="$LIBDIR"
-ac_add_options --prefix="$PREFIX"
-ac_add_options --without-system-libvpx
-ac_add_options --with-system-jpeg
-ac_add_options --with-system-zlib
-ac_add_options --enable-update-channel=release
 ac_add_options --disable-av1
+ac_add_options --disable-crashreporter
+
 export BUILD_OFFICIAL=1
 export MOZILLA_OFFICIAL=1
 mk_add_options BUILD_OFFICIAL=1
diff --git a/SOURCES/thunderbird-redhat-default-prefs.js.rhel6 b/SOURCES/thunderbird-redhat-default-prefs.js.rhel6
new file mode 100644
index 0000000..c412cb5
--- /dev/null
+++ b/SOURCES/thunderbird-redhat-default-prefs.js.rhel6
@@ -0,0 +1,30 @@
+pref("app.update.enabled", false);
+pref("app.update.autoInstallEnabled", false);
+# Allow users to set custom colors
+# pref("browser.display.use_system_colors",   true);
+pref("general.useragent.vendor", "Red Hat");
+pref("general.useragent.vendorSub", "THUNDERBIRD_RPM_VR");
+pref("intl.locale.matchOS", true);
+pref("mail.shell.checkDefaultClient", false);
+pref("toolkit.networkmanager.disable", false);
+pref("offline.autoDetect", true);
+
+# Disable global indexing by default
+pref("mailnews.database.global.indexer.enabled", false);
+
+# Do not switch to Smart Folders after upgrade to 3.0b4
+pref("mail.folder.views.version", "1");
+pref("extensions.shownSelectionUI", true);
+pref("extensions.autoDisableScope", 0);
+
+# For rhbz#1024232
+pref("ui.SpellCheckerUnderlineStyle",       1);
+
+/* Workaround for rhbz#1134876 */
+pref("javascript.options.baselinejit",      false);
+/* Workaround for rhbz#1110291 */
+pref("network.negotiate-auth.allow-insecure-ntlm-v1", true);
+/* Workaround for mozbz#1063315 */
+pref("security.use_mozillapkix_verification", false);
+/* Use OS settings for UI language */
+pref("intl.locale.requested", "");
diff --git a/SOURCES/thunderbird-redhat-default-prefs.js.rhel7 b/SOURCES/thunderbird-redhat-default-prefs.js.rhel7
new file mode 100644
index 0000000..c412cb5
--- /dev/null
+++ b/SOURCES/thunderbird-redhat-default-prefs.js.rhel7
@@ -0,0 +1,30 @@
+pref("app.update.enabled", false);
+pref("app.update.autoInstallEnabled", false);
+# Allow users to set custom colors
+# pref("browser.display.use_system_colors",   true);
+pref("general.useragent.vendor", "Red Hat");
+pref("general.useragent.vendorSub", "THUNDERBIRD_RPM_VR");
+pref("intl.locale.matchOS", true);
+pref("mail.shell.checkDefaultClient", false);
+pref("toolkit.networkmanager.disable", false);
+pref("offline.autoDetect", true);
+
+# Disable global indexing by default
+pref("mailnews.database.global.indexer.enabled", false);
+
+# Do not switch to Smart Folders after upgrade to 3.0b4
+pref("mail.folder.views.version", "1");
+pref("extensions.shownSelectionUI", true);
+pref("extensions.autoDisableScope", 0);
+
+# For rhbz#1024232
+pref("ui.SpellCheckerUnderlineStyle",       1);
+
+/* Workaround for rhbz#1134876 */
+pref("javascript.options.baselinejit",      false);
+/* Workaround for rhbz#1110291 */
+pref("network.negotiate-auth.allow-insecure-ntlm-v1", true);
+/* Workaround for mozbz#1063315 */
+pref("security.use_mozillapkix_verification", false);
+/* Use OS settings for UI language */
+pref("intl.locale.requested", "");
diff --git a/SPECS/thunderbird.spec b/SPECS/thunderbird.spec
index 85ac4e9..520871e 100644
--- a/SPECS/thunderbird.spec
+++ b/SPECS/thunderbird.spec
@@ -1,55 +1,89 @@
-%ifarch %{arm}
-%if %{defined el8}
-%undefine _debugsource_packages
+# Set for local builds only
+%global disable_toolsets  0
+
+%ifarch i686
+# no debug package for the i686 because oom on i686 with debuginfos
+%global debug_package %{nil}
+%endif
+
+%global rhel_minor_version -1
+%if "%{?dist}" == ".el8"
+%global rhel_minor_version 3
 %endif
+%if "%{?dist}" == ".el8_3"
+%global rhel_minor_version 3
+%endif
+%if "%{?dist}" == ".el8_2"
+%global rhel_minor_version 2
+%endif
+%if "%{?dist}" == ".el8_1"
+%global rhel_minor_version 1
+%endif
+%if "%{?dist}" == ".el8_0"
+%global rhel_minor_version 0
 %endif
 
-%global debug_build             0
-# Set for local builds only
-%global disable_toolsets        0
-%global official_branding       1
-%global system_ffi              1
-%global system_libicu           0
-%global system_libvpx           0
-%global system_nss              1
-%global system_sqlite           0
+%global bundle_nss        0
+# Use system nspr/nss? FIXME
+%global system_nss        0
+%if 0%{?rhel} == 8
+  %if 0%{?rhel_minor_version} < 2
+%global bundle_nss        1
+  %endif
+%endif
+%if 0%{?rhel} == 7
+#FIXME use system nss, just for testing
+%global system_nss        1
+%endif
+%if 0%{?rhel} == 6
+%global bundle_nss        0
+%endif
+
+%define use_bundled_ffi   0
+
+%define use_bundled_python_2 1
+%define use_bundled_python_3 1
+
 %if 0%{?rhel} == 8
 %define use_bundled_python_2 1
 %define use_bundled_python_3 0
-%else
+%endif
+
+%if 0%{?rhel} == 7
+%define use_bundled_python_2 0
+%define use_bundled_python_3 0
+%endif
+
+%if 0%{?flatpak:1}
 %define use_bundled_python_2 1
-%define use_bundled_python_3 1
 %endif
-%define build_langpacks         1
-%define use_bundled_ffi         0
-%define use_bundled_python      1
-%global use_bundled_yasm        1
-%global system_jpeg             1
-%global hardened_build          1
-%global use_dts                 1
+
+# we need python2 because of icu data gen
+%define use_bundled_python_2 1
+# Don't use system hunspell for now
+%global system_hunspell   0
 %if 0%{?rhel} == 8
 %global use_llvmts        0
 %else
 %global use_llvmts        1
 %endif
 
-%define bundled_python_version 2.7.13
-%global cairo_version           1.10.2
-%global ffi_version             3.0.9
-%global freetype_version        2.1.9
-%global gcc_version             4.8.2-16
-%global python_version          2.7.8
-%global sqlite_version          3.8.4.2
-%global nspr_version            4.21
-%global nss_version             3.44
-%if 0%{?rhel} == 7
-%define use_bundled_python 0
+%if 0%{?rhel} > 6
+%global system_ffi        1
+%else
+%global system_ffi        0
+%endif
+%if 0%{?rhel} < 8
+%global use_dts           1
 %endif
 
 %global use_rustts        1
 %global dts_version       8
-%global rust_version         1.31
-%global rust_toolset_version 1.35
+%if 0%{?rhel} == 6
+%global dts_version       8
+%endif
+%global rust_version         1.41
+%global rust_toolset_version 1.41
 %global llvm_version      7.0
 %if 0%{?rhel} == 8
 %global llvm_version      6.0
@@ -61,44 +95,81 @@
 %global use_llvmts        0
 %endif
 
+# Use system cairo?
+%global system_cairo      0
 
+# Use system libvpx?
+%global system_libvpx     0
 
-%if 0%{?rhel} == 8
-%global use_dts           0
-%endif
-
-%define gtk3_nvr 3.22.26-1
-%define gtk3_install_path %{mozappdir}/bundled
-
-
+# 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
-%define big_endian 1
+%global big_endian        1
 %endif
 
-# ============================================================================
+# Hardened build?
+%global hardened_build    1
 
-# Avoid patch failures
-%define _default_patch_fuzz     2
+%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
 
 %define thunderbird_app_id      \{3550f703-e582-4d05-9a08-453d09bdfdc6\}
+# 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_sqlite}
-# The actual sqlite version (see #480989):
-%global sqlite_build_version %(pkg-config --silence-errors --modversion sqlite3 2>/dev/null || echo 65536)
+%if 0%{?system_nss}
+%global nspr_version 4.21
+# 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.44
+#%global nss_build_version %(pkg-config --silence-errors --modversion nss 2>/dev/null || echo 65536)
+%global nss_build_version %{nss_version}
 %endif
 
+
 %define bundled_python_version_2 2.7.13
 %define bundled_python_version_3 3.6.8
 %define use_bundled_openssl     0
 %define use_bundled_nodejs      0
+
+%if 0%{?rhel} == 8
+  %if 0%{?rhel_minor_version} <= 2
+%define use_bundled_nodejs      1
+%define use_bundled_python_2    1
+  %endif
+%endif
+
 %if 0%{?rhel} < 8
 %define use_bundled_nodejs      1
+%define use_bundled_python_2    1
+#TODO DISABLE FOR RHEL7
+%define use_bundled_yasm        0
+%if 0%{?rhel} == 7
+%define use_bundled_nodejs      1
+#TODO DISABLE FOR RHEL7
+%define use_bundled_yasm        1
+%endif
 %if 0%{?rhel} == 6
 %define use_bundled_openssl     1
+%define use_bundled_yasm        1
 %endif
 %endif
 
@@ -107,12 +178,13 @@
 %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
-%global system_ffi              0
 %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
@@ -121,15 +193,18 @@
 %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 mozappdir     %{_libdir}/%{name}
+%global mozappdirdev  %{_libdir}/%{name}-devel-%{version}
+%global langpackdir   %{mozappdir}/distribution/extensions
+%global tarballdir    %{name}-%{version}
+#global pre_tag       alpha
 
+%global official_branding       1
+%global build_langpacks         1
 Summary:        Mozilla Thunderbird mail/newsgroup client
 Name:           thunderbird
-Version:        68.11.0
+Version:        78.2.1
 Release:        1%{?dist}
 URL:            http://www.mozilla.org/projects/thunderbird/
 License:        MPLv1.1 or GPLv2+ or LGPLv2+
@@ -145,10 +220,10 @@ ExclusiveArch:  i686 x86_64 ppc64 s390x
 # From ftp://archive.mozilla.org/pub/thunderbird/releases/%{version}%{?ext_version}/source
 Source0:        https://archive.mozilla.org/pub/thunderbird/releases/%{version}%{?pre_version}/source/thunderbird-%{version}%{?pre_version}.source.tar.xz
 %if %{build_langpacks}
-Source1:        thunderbird-langpacks-%{version}%{?ext_version}-20200804.tar.xz
+Source1:        thunderbird-langpacks-%{version}%{?ext_version}-20200908.tar.xz
 # Locales for lightning
-Source2:        lightning-langpacks-%{version}.tar.xz
 %endif
+Source2:        cbindgen-vendor-0.14.3.tar.xz
 Source3:        get-calendar-langpacks.sh
 Source4:        cbindgen-vendor.tar.xz
 
@@ -158,8 +233,6 @@ Source21:       thunderbird.sh.in
 Source24:       mozilla-api-key
 Source27:       google-api-key
 Source28:       node-stdout-nonblocking-wrapper
-Source100:      https://www.python.org/ftp/python/%{bundled_python_version_2}/Python-%{bundled_python_version_2}.tar.xz
-Source101:      https://www.python.org/ftp/python/%{bundled_python_version_3}/Python-%{bundled_python_version_3}.tar.xz
 Source102:      find-external-requires
 Source200:      gtk3-private-%{gtk3_nvr}.el6.src.rpm
 Source201:      gtk3-private-%{gtk3_nvr}-post.inc
@@ -170,92 +243,115 @@ 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
-Source304:      nodejs-8.11.4-1.3.fc27.src.rpm
+Source304:      nodejs-10.21.0-4.fc32.src.rpm
 Source305:      openssl-1.0.2k-19.6.bundle.el7_7.src.rpm
-Source601:      thunderbird-centos-default-prefs.js.el6
-Source701:      thunderbird-centos-default-prefs.js.el7
+Source601:      thunderbird-redhat-default-prefs.js.rhel6
+Source701:      thunderbird-redhat-default-prefs.js.rhel7
 
 ## Firefox patches
 
+Source403:      nss-3.53.1-3.fc32.src.rpm
+Source401:      nss-setup-flags-env.inc
+Source402:      nspr-4.25.0-1.el8_0.src.rpm 
+#Python
+%if 0%{?use_bundled_python_2}
+Source100:      https://www.python.org/ftp/python/%{bundled_python_version_2}/Python-%{bundled_python_version_2}.tar.xz
+%endif
+%if 0%{?use_bundled_python_3}
+Source101:      https://www.python.org/ftp/python/%{bundled_python_version_3}/Python-%{bundled_python_version_3}.tar.xz
+%endif
 # Build patches
+Patch1000:      python-2.7.patch
 # workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1699374
 Patch1001:      build-ppc64le-inline.patch
 Patch1002:      python-2.7-gcc8-fix.patch
 Patch1003:      python-missing-utimensat.patch
+Patch1004:      build-icu-make.patch
 # workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1699374
-Patch1:         no-rust-lto.patch
-Patch2:         rust-network-check.patch
 Patch4:         build-mozconfig-fix.patch
 Patch6:         build-nss-version.patch
 Patch7:         firefox-debugedits-error.patch
-Patch8:         firefox-dont-check-binary.patch
-Patch9:         nss-build-mozilla-1564499.patch
-Patch26:        build-icu-big-endian.patch
-# Always feel lucky for unsupported platforms:
-# https://bugzilla.mozilla.org/show_bug.cgi?id=1347128
-Patch41:        build-debug-qcms.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
-Patch230:        rhbz-1503632-nss.patch
-Patch1000:       python-2.7.patch
-Patch1004:       firefox-rhel6-nss-tls1.3.patch
+Patch231:        firefox-pipewire.patch
 Patch232:        firefox-rhel6-hugepage.patch
+Patch233:        firefox-rhel6-nss-tls1.3.patch
+Patch234:        rhbz-1821418.patch
+Patch235:        firefox-pipewire-0-3.patch
+Patch236:        fedora-shebang-build.patch
 
 # Upstream patches
 Patch402:        mozilla-1196777.patch
-#Removing this patch would lead to losing user saved credentials in profile!
-
-## Thunderbird patches
 
 Patch501:        python-encode.patch
+Patch503:        mozilla-s390-context.patch
+Patch505:        mozilla-bmo1005535.patch
+Patch506:        mozilla-bmo1504834-part1.patch
+Patch507:        mozilla-bmo1504834-part2.patch
+Patch508:        mozilla-bmo1504834-part3.patch
+Patch509:        mozilla-bmo1504834-part4.patch
+Patch510:        mozilla-bmo1554971.patch
+Patch511:        mozilla-bmo1602730.patch
+Patch512:        mozilla-bmo849632.patch
+Patch513:        mozilla-bmo998749.patch
+Patch514:        mozilla-s390x-skia-gradient.patch
+Patch515:        mozilla-bmo1626236.patch
+Patch516:        D87019-thin-vec-big-endian.diff
+
+# CentOS patches
+%if 0%{?centos}
 Patch10000:      Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch
 Patch10001:      Bug-1526653---fix_user_vfp_armv7.patch
-# ---------------------------------------------------
+%endif
 
-BuildRequires:  autoconf213
-BuildRequires:  bzip2-devel
-BuildRequires:  dbus-glib-devel
-BuildRequires:  desktop-file-utils
-BuildRequires:  krb5-devel
-BuildRequires:  libXt-devel
-BuildRequires:  mesa-libGL-devel
-BuildRequires:  pkgconfig(dri)
-BuildRequires:  pkgconfig(freetype2) >= %{freetype_version}
-BuildRequires:  pkgconfig(gconf-2.0)
-BuildRequires:  pkgconfig(gtk+-2.0)
-BuildRequires:  pkgconfig(libcurl)
-BuildRequires:  pkgconfig(libIDL-2.0)
-BuildRequires:  pkgconfig(libnotify)
+%if %{?system_nss}
+%if !0%{?bundle_nss}
+BuildRequires:  pkgconfig(nspr) >= %{nspr_version}
+BuildRequires:  pkgconfig(nss) >= %{nss_version}
+BuildRequires:  nss-static >= %{nss_version}
+%endif
+%endif
+%if %{?system_cairo}
+BuildRequires:  pkgconfig(cairo) >= %{cairo_version}
+%endif
 BuildRequires:  pkgconfig(libpng)
-BuildRequires:  pkgconfig(libpulse)
-BuildRequires:  pkgconfig(libstartup-notification-1.0)
-BuildRequires:  pkgconfig(pango)
-BuildRequires:  pkgconfig(xrender)
-BuildRequires:  pkgconfig(xt)
-BuildRequires:  pkgconfig(zlib)
 BuildRequires:  xz
+BuildRequires:  libXt-devel
+BuildRequires:  mesa-libGL-devel
 BuildRequires:  zip
 Requires:       liberation-fonts-common
 Requires:       liberation-sans-fonts
-Requires:       mozilla-filesystem
-Requires:       p11-kit-trust
 %if %{?system_jpeg}
 BuildRequires:  libjpeg-devel
 %endif
-%if %{?system_nss}
-BuildRequires:  pkgconfig(nspr) >= %{nspr_version}
-BuildRequires:  pkgconfig(nss) >= %{nss_version}
-BuildRequires:  nss-static >= %{nss_version}
+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++
@@ -267,14 +363,11 @@ BuildRequires:  llvm-toolset-%{llvm_version}
 BuildRequires:  llvm-toolset-%{llvm_version}-llvm-devel
 %endif
 %endif
-%if ! %{use_bundled_yasm}0
-BuildRequires:  yasm
-%endif
+
 BuildRequires:  scl-utils
-%if %{?system_sqlite}
-BuildRequires:  sqlite-devel >= %{sqlite_version}
-Requires:       sqlite >= %{sqlite_build_version}
-%endif
+BuildRequires:  findutils
+
+
 %if 0%{?rhel} == 8
 BuildRequires:  cargo
 BuildRequires:  rust >= %{rust_version}
@@ -282,23 +375,41 @@ BuildRequires:  llvm >= %{llvm_version}
 BuildRequires:  llvm-devel >= %{llvm_version}
 BuildRequires:  clang >= %{llvm_version}
 BuildRequires:  clang-devel >= %{llvm_version}
+BuildRequires:  rustfmt >= %{rust_version}
 BuildRequires:  python3
-BuildRequires:  nodejs >= 8.11
+BuildRequires:  python3-devel
+BuildRequires:  nodejs >= 10.21
 %else
 %if 0%{?use_rustts}
 BuildRequires:  rust-toolset-%{rust_toolset_version}
 %endif
+%if 0%{?rhel} == 7
+#BuildRequires:  rh-nodejs12
+BuildRequires:  python3
+BuildRequires:  python3-devel
+%endif
 %if 0%{?use_llvmts}
 BuildRequires:  llvm-toolset-%{llvm_version}
 BuildRequires:  llvm-toolset-%{llvm_version}-llvm-devel
 %endif
 %endif
 
+%if ! 0%{?use_bundled_yasm}
+BuildRequires:  yasm
+%endif
+
+
 %if 0%{?use_bundled_python_2}
-#%if 0%{?rhel} == 6
 # Needed for Python in RHEL6
 BuildRequires:  openssl-devel
-#%endif
+%endif
+
+%if 0%{?rhel} == 8
+  %if 0%{?rhel_minor_version} >= 3
+BuildRequires:  pkgconfig(libpipewire-0.3)
+  %else
+BuildRequires:  pipewire-devel
+  %endif
 %endif
 
 %if 0%{?bundle_gtk3}
@@ -345,21 +456,60 @@ Requires:             libXtst%{?_isa}
 BuildRequires:        gtk3-devel
 BuildRequires:        glib2-devel
 %endif
+
+# Bundled nss/nspr requirement
+%if 0%{?bundle_nss}
+BuildRequires:    nss-softokn
+BuildRequires:    sqlite-devel
+BuildRequires:    zlib-devel
+BuildRequires:    pkgconfig
+BuildRequires:    gawk
+BuildRequires:    psmisc
+%if 0%{?rhel} == 6
+BuildRequires:    perl
+%else
+BuildRequires:    perl-interpreter
+%endif
+BuildRequires:    gcc-c++
+BuildRequires:    xmlto
+%endif
+
+Requires:       mozilla-filesystem
+Requires:       p11-kit-trust
 %if %{?system_nss}
-Requires:       nspr >= %{nspr_version}
-Requires:       nss >= %{nss_version}
+%if !0%{?bundle_nss}
+Requires:       nspr >= %{nspr_build_version}
+Requires:       nss >= %{nss_build_version}
+%endif
 %endif
 
-%if %{?system_sqlite}
-BuildRequires:  pkgconfig(sqlite3) >= %{sqlite_version}
-Requires:       sqlite >= %{sqlite_build_version}
+BuildRequires:  desktop-file-utils
+BuildRequires:  system-bookmarks
+Requires:       redhat-indexhtml
+#for the python2
+BuildRequires:  pkgconfig(sqlite3)
+
+
+%if %{?run_tests}
+BuildRequires:  xorg-x11-server-Xvfb
 %endif
+
 %if %{?system_ffi}
   %if !%{use_bundled_ffi}0
 BuildRequires:  pkgconfig(libffi)
   %endif
 %endif
 
+%if %{?use_bundled_nodejs}
+#BuildRequires: python3-devel
+BuildRequires: zlib-devel
+#BuildRequires: brotli-devel
+#BuildRequires: gcc >= 4.9.4
+#BuildRequires: gcc-c++ >= 4.9.4
+BuildRequires: chrpath
+BuildRequires: libatomic
+BuildRequires: openssl-devel
+%endif
 Obsoletes:      thunderbird-lightning
 # ==================================================================================
 # Override internal dependency generator to avoid showing libraries provided by this package
@@ -373,6 +523,20 @@ Mozilla Thunderbird is a standalone mail and newsgroup client.
 
 
 %prep
+echo "Build environment"
+echo "dist                  %{?dist}"
+echo "RHEL 8 minor version: %{?rhel_minor_version}"
+echo "use_bundled_ffi       %{?use_bundled_ffi}"
+echo "use_bundled_python_2  %{?use_bundled_python_2}"
+echo "use_bundled_python_3  %{?use_bundled_python_3}"
+echo "bundle_nss            %{?bundle_nss}"
+echo "system_nss            %{?system_nss}"
+echo "use_rustts            %{?use_rustts}"
+echo "use_bundled_nodejs    %{?use_bundled_nodejs}"
+echo "use_bundled_openssl   %{?use_bundled_openssl}"
+echo "use_bundled_yasm      %{?use_bundled_yasm}"
+
+
 %if 0%{?use_bundled_python_2}
 %setup -q -T -c -n python2 -a 100
 %patch1000 -p0 -b .build
@@ -387,57 +551,60 @@ Mozilla Thunderbird is a standalone mail and newsgroup client.
 %setup -q -n %{tarballdir}
 
 # Firefox patches
-%patch1 -p1 -b .no-rust-lto
-%patch2 -p1 -b .rust-network-check
 %patch7 -p1 -b .debugedits-error
 %ifarch %{ix86} %{arm} ppc
 # binary check fails OOM on 32bit arches
-%patch8 -p1 -b .dont-check-binary
-%endif
-%patch9 -p1 -b .nss-build-mozilla-1564499
-
-%if %{?debug_build}
-%patch41 -p1 -b .build-debug-qcms
 %endif
-#%if 0%{?rhel} == 8
-%patch45 -p1 -b .elfhack
-#%endif
 
 %patch4  -p1 -b .build-mozconfig-fix
-%patch6  -p1 -b .nss-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} == 6
-%patch232 -p1 -b .hugepage
-%patch1004 -p1 -b .rhel6-nss-tls1.3
+%if 0%{?rhel} == 8
+  %if 0%{?rhel_minor_version} >= 3
+%patch235 -p1 -b .pipewire-0-3
+  %else
+%patch231 -p1 -b .pipewire
+  %endif
 %endif
 
-# This ensures no migration of certdb to sqlite on the RHEL6 and RHEL7.
-# This needs to stay for the future releases
-%if 0%{?rhel} < 8
-%patch230 -p1 -b .1503632-nss
-%endif
+%patch236 -p1 -b .fedora-shebang-build
 
-#ARM run-time patch
-%ifarch aarch64
+%if 0%{?rhel} == 6
+%patch232 -p1 -b .hugepage
+%patch233 -p1 -b .rhel6-nss-tls1.3
 %endif
+%patch234 -p1 -b .rhbz-1821418
 
 %patch402 -p1 -b .1196777
 
 # Patch for big endian platforms only
 %if 0%{?big_endian}
-%patch26 -p1 -b .icu
 %endif
 
 # Thunderbird patches
 %patch501 -p1 -b .python-encode
+%patch503 -p1 -b .mozilla-s390-context
+%patch505 -p1 -b .mozilla-bmo1005535
+%patch506 -p1 -b .mozilla-bmo1504834-part1
+%patch507 -p1 -b .mozilla-bmo1504834-part2
+%patch508 -p1 -b .mozilla-bmo1504834-part3
+%patch509 -p1 -b .mozilla-bmo1504834-part4
+%patch510 -p1 -b .mozilla-bmo1554971
+%patch511 -p1 -b .mozilla-bmo1602730
+%patch512 -p1 -b .mozilla-bmo849632
+%patch513 -p1 -b .mozilla-bmo998749
+%patch514 -p1 -b .mozilla-s390x-skia-gradient
+%patch515 -p1 -b .mozilla-bmo1626236
+%patch516 -p1 -b .D87019-thin-vec-big-endian.diff
 %patch1001 -p1 -b .ppc64le-inline
+%patch1004 -p1 -b .icu-make
 
-%ifarch %{arm}
+# CentOS patches
+%if 0%{?centos}
 %patch10000 -p1 -b .mozilla-1238661
 %patch10001 -p1 -b .mozilla-1526653
 %endif
@@ -464,11 +631,6 @@ function add_to_mozconfig() {
  add_to_mozconfig "without-system-nss"
 %endif
 
-%if %{?system_sqlite}
- add_to_mozconfig "enable-system-sqlite"
-%else
- add_to_mozconfig "disable-system-sqlite"
-%endif
 %if 0%{?use_bundled_ffi}
  add_to_mozconfig "with-system-ffi"
 %endif
@@ -480,22 +642,25 @@ function add_to_mozconfig() {
  add_to_mozconfig "disable-elf-hack"
 %endif
 
+%if %{?system_hunspell}
+echo "ac_add_options --enable-system-hunspell" >> .mozconfig
+%else
+# not available?
+#echo "ac_add_options --disable-system-hunspell" >> .mozconfig
+%endif
+
 %if %{?debug_build}
  add_to_mozconfig "enable-debug"
  add_to_mozconfig "disable-optimize"
 %else
-%global optimize_flags "none"
-%ifnarch s390 s390x
 %global optimize_flags "-g -O2"
+%ifarch s390 s390x
+%global optimize_flags "-g -O1"
 %endif
 %ifarch armv7hl
 # ARMv7 need that (rhbz#1426850)
-%if %{defined el8}
-%global optimize_flags "-g0 -O2 -fno-schedule-insns -fno-lto"
-%else
 %global optimize_flags "-g -O2 -fno-schedule-insns"
 %endif
-%endif
 %ifarch ppc64le aarch64
 %global optimize_flags "-g -O2"
 %endif
@@ -516,6 +681,12 @@ echo "ac_add_options --disable-jemalloc" >> .mozconfig
 echo "ac_add_options --disable-webrtc" >> .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
@@ -528,18 +699,32 @@ echo "ac_add_options --with-system-icu" >> .mozconfig
 echo "ac_add_options --without-system-icu" >> .mozconfig
 %endif
 %ifarch s390 s390x
-echo "ac_add_options --disable-ion" >> .mozconfig
+echo "ac_add_options --disable-jit" >> .mozconfig
+%endif
+
+%ifnarch %{ix86}
+%if !0%{?debug_build}
+echo "ac_add_options --disable-debug-symbols" >> .mozconfig
+%endif
 %endif
 
 echo 'export NODEJS="%{_buildrootdir}/bin/node-stdout-nonblocking-wrapper"' >> .mozconfig
 
 # Remove executable bit to make brp-mangle-shebangs happy.
 chmod -x third_party/rust/itertools/src/lib.rs
+chmod a-x third_party/rust/gfx-backend-vulkan/src/*.rs
+chmod a-x third_party/rust/gfx-hal/src/*.rs
+chmod a-x third_party/rust/ash/src/extensions/ext/*.rs
+chmod a-x third_party/rust/ash/src/extensions/khr/*.rs
+chmod a-x third_party/rust/ash/src/extensions/mvk/*.rs
+chmod a-x third_party/rust/ash/src/extensions/nv/*.rs
 
 # install lightning langpacks
 
 %build
-set -e
+ulimit -a
+free
+#set -e
 # Hack for missing shell when building in brew on RHEL6
 %if 0%{?rhel} == 6
 export SHELL=/bin/sh
@@ -561,7 +746,9 @@ function install_rpms_to_current_dir() {
         %ifarch i386 i686
             ARCH_STR="i?86"
         %endif
-        PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+        %if 0%{?rhel} > 6
+          PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+        %endif
      fi
 
      for package in $(ls $PACKAGE_DIR/$PACKAGE_RPM)
@@ -575,6 +762,7 @@ function build_bundled_package() {
   PACKAGE_RPM=$1
   PACKAGE_FILES=$2
   PACKAGE_SOURCE=$3
+  PACKAGE_BUILD_OPTIONS=$4
   export PACKAGE_DIR="%{_topdir}/RPMS"
 
   PACKAGE_ALREADY_BUILD=0
@@ -588,20 +776,25 @@ function build_bundled_package() {
   %endif
   if [ $PACKAGE_ALREADY_BUILD == 0 ]; then
     echo "Rebuilding $PACKAGE_RPM from $PACKAGE_SOURCE"; echo "==============================="
-    rpmbuild --nodeps --rebuild $PACKAGE_SOURCE
+    rpmbuild --nodeps $PACKAGE_BUILD_OPTIONS --rebuild $PACKAGE_SOURCE
+    cat /var/tmp/rpm-tmp*
   fi
 
+  find $PACKAGE_DIR
   if [ ! -f $PACKAGE_DIR/$PACKAGE_RPM ]; then
     # Hack for tps tests
     ARCH_STR=%{_arch}
     %ifarch i386 i686
     ARCH_STR="i?86"
     %endif
-    export PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+    %if 0%{?rhel} > 6
+      export PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+        %endif
   fi
   pushd $PACKAGE_DIR
 
   echo "Installing $PACKAGE_DIR/$PACKAGE_RPM"; echo "==============================="
+  pwd
   PACKAGE_LIST=$(echo $PACKAGE_DIR/$PACKAGE_RPM | tr " " "\n")
   for PACKAGE in $PACKAGE_LIST
   do
@@ -623,10 +816,62 @@ function build_bundled_package() {
 
 # Build and install local yasm if needed
 # ======================================
-%if %{use_bundled_yasm}
+%if 0%{?use_bundled_yasm}
   build_bundled_package 'yasm-1*.rpm' 'yasm-*.rpm' '%{SOURCE301}'
 %endif
 
+%if 0%{?bundle_nss}
+   rpm -ivh %{SOURCE402}
+   #rpmbuild --nodeps --define '_prefix %{gtk3_install_path}' --without=tests -ba %{_specdir}/nspr.spec
+   rpmbuild --nodeps --define '_prefix %{gtk3_install_path}' -ba %{_specdir}/nspr.spec
+   pushd %{_buildrootdir}
+   install_rpms_to_current_dir nspr-4*.rpm
+   install_rpms_to_current_dir nspr-devel*.rpm
+   popd
+   #FIXME needs nspr install location and flags
+   echo "Setting nspr flags"
+   # nss-setup-flags-env.inc
+   sed -i 's@%{gtk3_install_path}@%{_buildrootdir}%{gtk3_install_path}@g' %{_buildrootdir}%{gtk3_install_path}/%{_lib}/pkgconfig/nspr*.pc
+
+   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
+   export PATH="{_buildrootdir}%{gtk3_install_path}/bin:$PATH"
+
+   #%include_file %{SOURCE401}
+   export PATH=%{_buildrootdir}/%{gtk3_install_path}/bin:$PATH
+   echo $PKG_CONFIG_PATH
+
+   rpm -ivh %{SOURCE403}
+   #rpmbuild --nodeps --define '_prefix %{gtk3_install_path}' --without=tests -ba %{_specdir}/nss.spec
+   rpmbuild --nodeps --define '_prefix %{gtk3_install_path}' -ba %{_specdir}/nss.spec
+   pushd %{_buildrootdir}
+   #cleanup
+   #rm -rf {_buildrootdir}/usr/lib/debug/*
+   #rm -rf {_buildrootdir}/usr/lib/.build-id
+   #install_rpms_to_current_dir nss-%{gtk3_nvr}*.rpm
+   #install_rpms_to_current_dir nss-devel-%{gtk3_nvr}*.rpm
+   install_rpms_to_current_dir nss-3*.rpm
+   install_rpms_to_current_dir nss-devel*.rpm
+   install_rpms_to_current_dir nss-pkcs11-devel*.rpm
+   install_rpms_to_current_dir nss-softokn-3*.rpm
+   install_rpms_to_current_dir nss-softokn-devel*.rpm
+   install_rpms_to_current_dir nss-softokn-freebl-3*.rpm
+   install_rpms_to_current_dir nss-softokn-freebl-devel*.rpm
+   install_rpms_to_current_dir nss-util-3*.rpm
+   install_rpms_to_current_dir nss-util-devel*.rpm
+   popd
+  %filter_provides_in %{gtk3_install_path}/%{_lib}
+  %filter_requires_in %{gtk3_install_path}/%{_lib}
+  %filter_from_requires /libnss3.so.*/d
+  %filter_from_requires /libsmime3.so.*/d
+  %filter_from_requires /libssl3.so.*/d
+  %filter_from_requires /libnssutil3.so.*/d
+  %filter_from_requires /libnspr4.so.*/d
+
+%endif
+
 %if 0%{?bundle_gtk3}
    %if ! 0%{?avoid_bundled_rebuild}
     rpm -ivh %{SOURCE200}
@@ -666,7 +911,9 @@ function build_bundled_package() {
     pushd %{_builddir}/python2/Python-%{bundled_python_version_2}
     ./configure --prefix="%{_buildrootdir}" --exec-prefix="%{_buildrootdir}" --libdir="%{_buildrootdir}/lib"
     make %{?_smp_mflags} install V=1
-    popd
+    which python2
+    which python
+    popd    
 %endif
 
 function replace_prefix() {
@@ -713,10 +960,15 @@ source scl_source enable devtoolset-%{dts_version}
 source scl_source enable rust-toolset-%{rust_toolset_version}
 %endif
 
+env
+which gcc
+which c++
+which g++
+which ld
 # Build and install local node if needed
 # ======================================
 %if %{use_bundled_nodejs}
-  build_bundled_package 'nodejs-8*.rpm' 'nodejs-*.rpm' %{SOURCE304}
+  build_bundled_package 'nodejs-10*.rpm' 'nodejs-*.rpm npm-*.rpm' %{SOURCE304} "--with bootstrap"
   export MOZ_NODEJS=$PACKAGE_DIR/usr/bin/node
 %else
   export MOZ_NODEJS=/usr/bin/node
@@ -724,7 +976,7 @@ source scl_source enable rust-toolset-%{rust_toolset_version}
 
 mkdir -p my_rust_vendor
 cd my_rust_vendor
-%{__tar} xf %{SOURCE4}
+%{__tar} xf %{SOURCE2}
 cd -
 mkdir -p .cargo
 cat > .cargo/config <<EOL
@@ -741,28 +993,21 @@ export PATH=`pwd`/.cargo/bin:$PATH
 export CBINDGEN=`pwd`/.cargo/bin/cbindgen
 
 
-%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
+# debug missing sqlite3 python module
+./mach python -c "import sys;print(sys.path)"
 
-echo "Building Thunderbird"; echo "==============================="
-echo "Generate big endian version of config/external/icu/data/icud58l.dat"
 %if 0%{?big_endian}
-# ./mach python intl/icu_sources_data.py .
-# rm -f config/external/icu/data/icudt*l.dat
- mv config/external/icu/data/icudt64l.dat config/external/icu/data/icudt64b.dat
+echo "Generate big endian version of config/external/icu/data/icud64l.dat"
+ ./mach python intl/icu_sources_data.py .
+ rm -f config/external/icu/data/icudt*l.dat
+# mv config/external/icu/data/icudt64l.dat config/external/icu/data/icudt64b.dat
  ls -l config/external/icu/data
+ cat /tmp/icu-make*
 %endif
 
 mkdir %{_buildrootdir}/bin || :
 cp %{SOURCE28} %{_buildrootdir}/bin || :
+chmod +x %{_buildrootdir}/bin/node-stdout-nonblocking-wrapper
 
 # Update the various config.guess to upstream release for aarch64 support
 find ./ -name config.guess -exec cp /usr/lib/rpm/config.guess {} ';'
@@ -796,7 +1041,7 @@ MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fno-delete-null-pointer-checks"
 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//')
+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/')
@@ -805,34 +1050,21 @@ MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g1/')
 # (OOM when linking, rhbz#1238225)
 export MOZ_DEBUG_FLAGS=" "
 %endif
-%ifarch %{arm}
-%if %{defined el8}
-MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/')
-export MOZ_DEBUG_FLAGS=" "
-%endif
-%endif
+
+# We don't wantfirefox to use CK_GCM_PARAMS_V3 in nss
+MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -DNSS_PKCS11_3_0_STRICT"
+
 %ifarch s390 %{arm} ppc aarch64 i686 x86_64
 MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
 %endif
-%ifarch %{arm}
-export RUSTFLAGS="-Cdebuginfo=0"
-%if %{defined el8}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory"
+%ifarch %{arm} i686
+MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--strip-debug"
 echo "ac_add_options --enable-linker=gold" >> .mozconfig
 %endif
-%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
-# RHEL6: Cannot find libldap60.so during launch (i686 only?)
-%if 0%{?rhel} == 6
-MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -Wl,-rpath,%{mozappdir}"
-%endif
 
+%ifarch %{arm} i686
+export RUSTFLAGS="-Cdebuginfo=0"
+%endif
 export CFLAGS=$MOZ_OPT_FLAGS
 export CXXFLAGS=$MOZ_OPT_FLAGS
 export LDFLAGS=$MOZ_LINK_FLAGS
@@ -853,20 +1085,54 @@ MOZ_SMP_FLAGS=-j1
 [ -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=-j4
+[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j3
+[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j3
 %endif
 %endif
+#FIXME workaround for oom
+
+cat /proc/meminfo
+# Free memory in kB
+
+MEM_AVAILABLE=$(grep MemAvailable /proc/meminfo | awk '{ print $2 }')
+
+# Usually the compiler processes can take 2 GB of memory at peaks
+TASK_SIZE=4000000
+MEM_CONSTRAINED_JOBS=$(( MEM_AVAILABLE / TASK_SIZE ))
+CPU_AVAILABLE=$(/usr/bin/getconf _NPROCESSORS_ONLN)
+# Pick the minimum from available CPUs or memory constrained number of jobs
+#MOZ_SMP_FLAGS=-j$([ "$CPU_AVAILABLE" -le "$MEM_CONSTRAINED_JOBS" ] && echo "$CPU_AVAILABLE" || echo "$MEM_CONSTRAINED_JOBS")
 
 %if 0%{?bundle_gtk3}
 # gtk3-private-setup-flags-env.inc
 %include_file %{SOURCE205}
 %endif
 
+%if 0%{?bundle_nss}
+echo "Setting nss flags"
+# nss-setup-flags-env.inc
+%include_file %{SOURCE401}
+export PATH=%{_buildrootdir}/%{gtk3_install_path}/bin:$PATH
+echo $PKG_CONFIG_PATH
+%endif
+
 export MOZ_MAKE_FLAGS="$MOZ_SMP_FLAGS"
 #export MOZ_SERVICES_SYNC="1"
+# we need to strip the sources on i686 because to we don't use rpm to generate debugsymbols because of oom
+%ifnarch i686 i386
 export STRIP=/bin/true
+%endif
+which node
+echo 'export NODEJS="%{_buildrootdir}/bin/node-stdout-nonblocking-wrapper"'
+env
+ls %{_buildrootdir}
+
+
+%if 0%{?use_llvmts}
+scl enable llvm-toolset-%{llvm_version} './mach build -v'
+%else
 ./mach build -v
+%endif
 
 #---------------------------------------------------------------------
 
@@ -875,7 +1141,6 @@ export STRIP=/bin/true
 export SHELL=/bin/sh
 %endif
 
-%if 0%{?bundle_gtk3}
 function install_rpms_to_current_dir() {
     PACKAGE_RPM=$(eval echo $1)
     PACKAGE_DIR=%{_rpmdir}
@@ -886,7 +1151,9 @@ function install_rpms_to_current_dir() {
         %ifarch i386 i686
             ARCH_STR="i?86"
         %endif
-        PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+        %if 0%{?rhel} > 6
+          PACKAGE_DIR="$PACKAGE_DIR/$ARCH_STR"
+        %endif
      fi
 
      for package in $(ls $PACKAGE_DIR/$PACKAGE_RPM)
@@ -896,6 +1163,7 @@ function install_rpms_to_current_dir() {
      done
 }
 
+%if 0%{?bundle_gtk3}
 pushd %{buildroot}
 # Install gtk3-private again to the buildroot, but without devel subpackage
 install_rpms_to_current_dir gtk3-private-%{gtk3_nvr}*.rpm
@@ -903,6 +1171,29 @@ install_rpms_to_current_dir gtk3-private-rpm-scripts-%{gtk3_nvr}*.rpm
 popd
 %endif
 
+%if 0%{?bundle_nss}
+  pushd %{buildroot}
+  #install_rpms_to_current_dir nss-*.rpm
+  install_rpms_to_current_dir nspr-4*.rpm
+  install_rpms_to_current_dir nss-3*.rpm
+  install_rpms_to_current_dir nss-softokn-3*.rpm
+  install_rpms_to_current_dir nss-softokn-freebl-3*.rpm
+  install_rpms_to_current_dir nss-util-3*.rpm
+ 
+  # cleanup unecessary nss files
+  #rm -rf %{_buildrootdir}/%{gtk3_install_path}/bin
+  #rm -rf %{_buildrootdir}/%{gtk3_install_path}/include
+  rm -rf %{buildroot}/%{gtk3_install_path}/lib/dracut
+  rm -rf %{buildroot}/%{gtk3_install_path}/%{_lib}/nss
+  #rm -rf %{_buildrootdir}/%{gtk3_install_path}/%{_lib}/pkgconfig
+  rm -rf %{buildroot}/%{gtk3_install_path}/%{_lib}/share
+  rm -rf %{buildroot}/%{gtk3_install_path}/share
+  rm -rf %{buildroot}/etc/pki
+  rm -rf %{buildroot}/usr/lib/.build-id
+  rm -rf %{buildroot}/etc/crypto-policies
+  popd
+%endif
+
 # Install bundled libffi
 %if %{use_bundled_ffi}
   pushd %{buildroot}
@@ -921,7 +1212,7 @@ rm -rf %{buildroot}%{_bindir}/thunderbird
 %{__rm} -rf %{buildroot}%{_bindir}/thunderbird
 %{__cat} %{SOURCE21} > %{buildroot}%{_bindir}/thunderbird
 %if 0%{?bundle_gtk3}
-sed -i -e 's|%RHEL_ENV_VARS%|export XDG_DATA_DIRS="$MOZ_LIB_DIR/thunderbird/bundled/share:/usr/share:$XDG_DATA_DIRS"|' %{buildroot}%{_bindir}/thunderbird
+sed -i -e 's|%RHEL_ENV_VARS%|export XDG_DATA_DIRS="$MOZ_LIB_DIR/thunderbird/bundled/share:/usr/share:$XDG_DATA_DIRS"\nexport FONTCONFIG_FILE="$MOZ_LIB_DIR/thunderbird/bundled/etc/fonts/fonts.conf"|' %{buildroot}%{_bindir}/thunderbird
 %else
 sed -i -e 's|%RHEL_ENV_VARS%||' %{buildroot}%{_bindir}/thunderbird
 %endif
@@ -979,37 +1270,9 @@ for langpack in `ls thunderbird-langpacks/*.xpi`; do
 done
 %{__rm} -rf thunderbird-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@thunderbird.mozilla.org.xpi langpack-$language_short@thunderbird.mozilla.org.xpi
-  cd -
-  echo "%%lang($language_short) %{langpackdir}/langpack-$language_short@thunderbird.mozilla.org.xpi" >> ../%{name}.lang
-}
-
-# Table of fallbacks for each language
-# please file a bug at bugzilla.redhat.com if the assignment is incorrect
-# Because of bug 1341629 we can't do this:
-#create_default_langpack "bn-BD" "bn"
-#create_default_langpack "es-AR" "es"
-#create_default_langpack "fy-NL" "fy"
-#create_default_langpack "ga-IE" "ga"
-#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"
-
-# lightning langpacks install
-cd %{buildroot}%{langpackdir}
-%{__tar} xf %{SOURCE2}
-chmod a+r *.xpi
-cd -
-%endif # build_langpacks
+echo "Adding following langpacks:"
+cat %{name}.lang
+%endif
 
 # Get rid of devel package and its debugsymbols
 %{__rm} -rf %{buildroot}%{_libdir}/%{name}-devel-%{version}
@@ -1030,6 +1293,12 @@ touch %{buildroot}%{mozappdir}/components/xpti.dat
 rm -rf %{_prefix}/lib/debug/lib/%{name}-devel-*
 rm -rf %{_prefix}/lib/debug/lib64/%{name}-devel-*
 
+# Fixing python version
+test -f "%{buildroot}%{mozappdir}/distribution/extensions/unicode-segmentation/scripts/unicode_gen_breaktests.py" && sed -i -e 's|/usr/bin/env python$|/usr/bin/env python2|' %{buildroot}%{mozappdir}/distribution/extensions/unicode-segmentation/scripts/unicode_gen_breaktests.py
+test -f "%{buildroot}%{mozappdir}/distribution/extensions/unicode-segmentation/scripts/unicode.py" && sed -i -e 's|/usr/bin/env python$|/usr/bin/env python2|' %{buildroot}%{mozappdir}/distribution/extensions/unicode-segmentation/scripts/unicode.py
+test -f "%{buildroot}%{mozappdir}/distribution/extensions/unicode-width/scripts/unicode.py" && sed -i -e 's|/usr/bin/env python$|/usr/bin/env python2|' %{buildroot}%{mozappdir}/distribution/extensions/unicode-width/scripts/unicode.py
+
+
 #---------------------------------------------------------------------
 
 %clean
@@ -1039,6 +1308,10 @@ rm -rf %{_srcrpmdir}/libffi*.src.rpm
 find %{_rpmdir} -name "libffi*.rpm" -delete
 rm -rf %{_srcrpmdir}/openssl*.src.rpm
 find %{_rpmdir} -name "openssl*.rpm" -delete
+rm -rf %{_srcrpmdir}/nss*.src.rpm
+find %{_rpmdir} -name "nss*.rpm" -delete
+rm -rf %{_srcrpmdir}/nspr*.src.rpm
+find %{_rpmdir} -name "nspr*.rpm" -delete
 
 %post
 update-desktop-database &> /dev/null || :
@@ -1094,7 +1367,6 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
 %{mozappdir}/*.so
 %{mozappdir}/platform.ini
 %{mozappdir}/application.ini
-%{mozappdir}/blocklist.xml
 %{mozappdir}/features/*.xpi
 %exclude %{mozappdir}/removed-files
 %{_datadir}/icons/hicolor/16x16/apps/thunderbird.png
@@ -1105,21 +1377,14 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
 %{_datadir}/icons/hicolor/48x48/apps/thunderbird.png
 %{mozappdir}/pingsender
 %{mozappdir}/gtk2/libmozgtk.so
-%if !%{?system_nss}
-%{mozappdir}/*.chk
-%endif
 %{mozappdir}/dependentlibs.list
-%{mozappdir}/distribution
-%{mozappdir}/chrome.manifest
+%dir %{mozappdir}/distribution
 %{mozappdir}/fonts/TwemojiMozilla.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}
@@ -1132,10 +1397,28 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
 %include_file %{SOURCE204}
 %endif
 
+%if 0%{?bundle_nss}
+%{mozappdir}/bundled/%{_lib}/libfreebl*
+%{mozappdir}/bundled/%{_lib}/libnss3*
+%{mozappdir}/bundled/%{_lib}/libnssdbm3*
+%{mozappdir}/bundled/%{_lib}/libnssutil3*
+%{mozappdir}/bundled/%{_lib}/libsmime3*
+%{mozappdir}/bundled/%{_lib}/libsoftokn*
+%{mozappdir}/bundled/%{_lib}/libssl3*
+%{mozappdir}/bundled/%{_lib}/libnspr4.so
+%{mozappdir}/bundled/%{_lib}/libplc4.so
+%{mozappdir}/bundled/%{_lib}/libplds4.so
+%endif
 
 #===============================================================================
 
 %changelog
+* Tue Sep 08 2020 Jan Horak <jhorak@redhat.com> - 78.2.1-1
+- Update to 78.2.1 build1
+
+* Wed Sep 02 2020 Jan Horak <jhorak@redhat.com> - 68.12.0-1
+- Update to 68.12.0 build1
+
 * Tue Aug 04 2020 Jan Horak <jhorak@redhat.com> - 68.11.0-1
 - Update to 68.11.0 build1