diff options
author | Martin Stransky <stransky@redhat.com> | 2020-05-29 11:31:41 +0200 |
---|---|---|
committer | Martin Stransky <stransky@redhat.com> | 2020-05-29 11:31:41 +0200 |
commit | 5116ef14ae33365e43aa45375df466917fbda054 (patch) | |
tree | 8ca517d917d299d216e15e20fb965748960de7d8 | |
parent | Added fix for mozbz#1632456 (diff) | |
download | librewolf-fedora-ff-5116ef14ae33365e43aa45375df466917fbda054.tar.gz librewolf-fedora-ff-5116ef14ae33365e43aa45375df466917fbda054.tar.bz2 librewolf-fedora-ff-5116ef14ae33365e43aa45375df466917fbda054.zip |
Updated to 77.0
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | firefox.spec | 32 | ||||
-rw-r--r-- | kiosk-workaround.patch | 12 | ||||
-rw-r--r-- | mozilla-1619543.patch | 97 | ||||
-rw-r--r-- | mozilla-1619882-1.patch | 216 | ||||
-rw-r--r-- | mozilla-1619882-2.patch | 123 | ||||
-rw-r--r-- | mozilla-1628690.patch | 67 | ||||
-rw-r--r-- | mozilla-1630754.patch | 298 | ||||
-rw-r--r-- | mozilla-1632059.patch | 41 | ||||
-rw-r--r-- | mozilla-1634293.patch | 406 | ||||
-rw-r--r-- | mozilla-1639197.patch | 15 | ||||
-rw-r--r-- | mozilla-gnome-shell-search-fixes.patch | 157 | ||||
-rw-r--r-- | mozilla-gnome-shell-search-provider-icons.patch | 453 | ||||
-rw-r--r-- | mozilla-gnome-shell-search-provider.patch | 786 | ||||
-rw-r--r-- | sources | 1 |
15 files changed, 625 insertions, 2080 deletions
@@ -397,3 +397,4 @@ firefox-3.6.4.source.tar.bz2 /firefox-langpacks-76.0-20200502.tar.xz /firefox-76.0.1.source.tar.xz /firefox-langpacks-76.0.1-20200508.tar.xz +/firefox-77.0.source.tar.xz diff --git a/firefox.spec b/firefox.spec index 94dff39..fc9c3db 100644 --- a/firefox.spec +++ b/firefox.spec @@ -117,13 +117,13 @@ ExcludeArch: s390x Summary: Mozilla Firefox Web browser Name: firefox -Version: 76.0.1 -Release: 7%{?nss_tag}%{?dist} +Version: 77.0 +Release: 1%{?nss_tag}%{?dist} URL: https://www.mozilla.org/firefox/ License: MPLv1.1 or GPLv2+ or LGPLv2+ Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz %if %{with langpacks} -Source1: firefox-langpacks-%{version}%{?pre_version}-20200508.tar.xz +Source1: firefox-langpacks-%{version}%{?pre_version}-20200529.tar.xz %endif Source2: cbindgen-vendor.tar.xz Source10: firefox-mozconfig @@ -172,10 +172,6 @@ Patch224: mozilla-1170092.patch #ARM run-time patch Patch226: rhbz-1354671.patch Patch227: firefox-locale-debug.patch -Patch239: mozilla-gnome-shell-search-provider.patch -Patch240: mozilla-gnome-shell-search-provider-icons.patch -Patch241: kiosk-workaround.patch -Patch242: mozilla-gnome-shell-search-fixes.patch # Upstream patches Patch402: mozilla-1196777.patch @@ -183,6 +179,8 @@ Patch412: mozilla-1337988.patch Patch415: Bug-1238661---fix-mozillaSignalTrampoline-to-work-.patch Patch417: bug1375074-save-restore-x28.patch Patch422: mozilla-1580174-webrtc-popup.patch +Patch500: mozilla-1634293.patch +Patch501: mozilla-1639197.patch # Wayland specific upstream patches Patch574: firefox-pipewire-0-2.patch @@ -190,10 +188,6 @@ Patch575: firefox-pipewire-0-3.patch #VA-API patches Patch579: mozilla-1625431.patch -Patch580: mozilla-1628690.patch -Patch581: mozilla-1630754.patch -Patch582: mozilla-1619543.patch -Patch583: mozilla-1632059.patch Patch584: firefox-disable-ffvpx-with-vapi.patch Patch585: firefox-vaapi-extra-frames.patch Patch586: mozilla-1619882-1.patch @@ -388,18 +382,15 @@ This package contains results of tests executed during build. %patch226 -p1 -b .1354671 %endif %patch227 -p1 -b .locale-debug -%patch239 -p1 -b .gnome-shell-search-provider -%patch240 -p1 -b .gnome-shell-search-provider-icons -# Workaround for kiosk mode -# https://bugzilla.mozilla.org/show_bug.cgi?id=1594738 -#%patch241 -p1 -b .kiosk-workaround -%patch242 -p1 -b .gnome-shell-search-fixes %patch402 -p1 -b .1196777 %ifarch %{arm} %patch415 -p1 -b .1238661 %endif +%patch500 -p1 -b .mozilla-1634293 +%patch501 -p1 -b .mozilla-1639197 + # Wayland specific upstream patches %if 0%{?fedora} < 32 %patch574 -p1 -b .firefox-pipewire-0-2 @@ -407,11 +398,7 @@ This package contains results of tests executed during build. %patch575 -p1 -b .firefox-pipewire-0-3 %endif -%patch580 -p1 -b .mozilla-1628690 -%patch582 -p1 -b .mozilla-1619543 %patch579 -p1 -b .mozilla-1625431 -%patch581 -p1 -b .mozilla-1630754 -%patch583 -p1 -b .mozilla-1632059 %patch584 -p1 -b .firefox-disable-ffvpx-with-vapi %patch585 -p1 -b .firefox-vaapi-extra-frames %patch586 -p1 -b .mozilla-1619882-1 @@ -993,6 +980,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Fri May 29 2020 Martin Stransky <stransky@redhat.com> - 77.0-1 +- Updated to Firefox 77.0 + * Mon May 25 2020 Martin Stransky <stransky@redhat.com> - 76.0.1-7 - Added fix for mozbz#1632456 diff --git a/kiosk-workaround.patch b/kiosk-workaround.patch deleted file mode 100644 index 085ea29..0000000 --- a/kiosk-workaround.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-71.0/browser/base/content/browser.css.old firefox-71.0/browser/base/content/browser.css ---- firefox-71.0/browser/base/content/browser.css.old 2019-12-04 18:15:20.059908708 +0100 -+++ firefox-71.0/browser/base/content/browser.css 2019-12-04 18:15:23.181905115 +0100 -@@ -841,7 +841,7 @@ window[chromehidden~="toolbar"] toolbar: - /* Full Screen UI */ - - #fullscr-toggler { -- height: 1px; -+ height: 0px; - background: black; - } - diff --git a/mozilla-1619543.patch b/mozilla-1619543.patch deleted file mode 100644 index 7dc1e86..0000000 --- a/mozilla-1619543.patch +++ /dev/null @@ -1,97 +0,0 @@ -diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp -@@ -101,17 +101,22 @@ - : LinkResult::UnknownFutureLibAVVersion; - } - --#define AV_FUNC_OPTION(func, ver) \ -+#define AV_FUNC_OPTION_SILENT(func, ver) \ - if ((ver)&version) { \ - if (!(func = (decltype(func))PR_FindSymbol( \ - ((ver)&AV_FUNC_AVUTIL_MASK) ? mAVUtilLib : mAVCodecLib, \ - #func))) { \ -- FFMPEG_LOG("Couldn't load function " #func); \ - } \ - } else { \ - func = (decltype(func)) nullptr; \ - } - -+#define AV_FUNC_OPTION(func, ver) \ -+ AV_FUNC_OPTION_SILENT(func, ver) \ -+ if ((ver)&version && (func) == (decltype(func)) nullptr) { \ -+ FFMPEG_LOG("Couldn't load function " #func); \ -+ } -+ - #define AV_FUNC(func, ver) \ - AV_FUNC_OPTION(func, ver) \ - if ((ver)&version && !func) { \ -@@ -153,30 +158,29 @@ - AV_FUNC_OPTION(av_frame_get_colorspace, AV_FUNC_AVUTIL_ALL) - AV_FUNC_OPTION(av_frame_get_color_range, AV_FUNC_AVUTIL_ALL) - #ifdef MOZ_WAYLAND -- AV_FUNC_OPTION(avcodec_get_hw_config, AV_FUNC_58) -- AV_FUNC_OPTION(av_hwdevice_ctx_create, AV_FUNC_58) -- AV_FUNC_OPTION(av_buffer_ref, AV_FUNC_AVUTIL_58) -- AV_FUNC_OPTION(av_buffer_unref, AV_FUNC_AVUTIL_58) -- AV_FUNC_OPTION(av_hwframe_transfer_get_formats, AV_FUNC_58) -- AV_FUNC_OPTION(av_hwdevice_ctx_create_derived, AV_FUNC_58) -- AV_FUNC_OPTION(av_hwframe_ctx_alloc, AV_FUNC_58) -- AV_FUNC_OPTION(av_dict_set, AV_FUNC_58) -- AV_FUNC_OPTION(av_dict_free, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(avcodec_get_hw_config, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_create, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_buffer_ref, AV_FUNC_AVUTIL_58) -+ AV_FUNC_OPTION_SILENT(av_buffer_unref, AV_FUNC_AVUTIL_58) -+ AV_FUNC_OPTION_SILENT(av_hwframe_transfer_get_formats, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_create_derived, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_hwframe_ctx_alloc, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_dict_set, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_dict_free, AV_FUNC_58) - #endif - #undef AV_FUNC - #undef AV_FUNC_OPTION - - #ifdef MOZ_WAYLAND --# define VA_FUNC_OPTION(func) \ -+# define VA_FUNC_OPTION_SILENT(func) \ - if (!(func = (decltype(func))PR_FindSymbol(mVALib, #func))) { \ -- FFMPEG_LOG("Couldn't load function " #func); \ - func = (decltype(func)) nullptr; \ - } - - // mVALib is optional and may not be present. - if (mVALib) { -- VA_FUNC_OPTION(vaExportSurfaceHandle) -- VA_FUNC_OPTION(vaSyncSurface) -+ VA_FUNC_OPTION_SILENT(vaExportSurfaceHandle) -+ VA_FUNC_OPTION_SILENT(vaSyncSurface) - } - # undef VA_FUNC_OPTION - #endif -diff --git a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp -@@ -66,6 +66,9 @@ - PR_UnloadLibrary(sLibAV.mVALib); - sLibAV.mVALib = nullptr; - } -+ if (!sLibAV.mVALib) { -+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib); -+ } - } - #endif - -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -173,7 +173,7 @@ - FFMPEG_LOG("Initialising VA-API FFmpeg decoder"); - - if (!mLib->IsVAAPIAvailable()) { -- FFMPEG_LOG("libva library is missing"); -+ FFMPEG_LOG("libva library or symbols are missing."); - return NS_ERROR_NOT_AVAILABLE; - } - - diff --git a/mozilla-1619882-1.patch b/mozilla-1619882-1.patch index 25ff321..3f4cbda 100644 --- a/mozilla-1619882-1.patch +++ b/mozilla-1619882-1.patch @@ -13,60 +13,75 @@ diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces diff --git a/widget/gtk/WaylandDMABufSurface.h b/widget/gtk/WaylandDMABufSurface.h --- a/widget/gtk/WaylandDMABufSurface.h +++ b/widget/gtk/WaylandDMABufSurface.h -@@ -40,6 +40,23 @@ +@@ -49,9 +49,14 @@ + SURFACE_NV12, + }; - class WaylandDMABufSurfaceRGBA; ++ // Import surface from SurfaceDescriptor. This is usually ++ // used to copy surface from another process over IPC. ++ // When a global reference counter was created for the surface ++ // (see bellow) it's automatically referenced. + static already_AddRefed<WaylandDMABufSurface> CreateDMABufSurface( + const mozilla::layers::SurfaceDescriptor& aDesc); -+class DMABufRefcount { -+ public: -+ DMABufRefcount(); -+ DMABufRefcount(int aFd); -+ -+ bool Created() { return mFd > 0; }; -+ int GetFD() { return mFd; } -+ uint64_t GetRefcount(); -+ void RefAdd(); -+ void Release(); -+ -+ ~DMABufRefcount(); -+ -+ private: -+ int mFd; -+}; -+ - class WaylandDMABufSurface { - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WaylandDMABufSurface) -@@ -82,6 +99,14 @@ ++ // Export surface to another process via. SurfaceDescriptor. + virtual bool Serialize( + mozilla::layers::SurfaceDescriptor& aOutDescriptor) = 0; + +@@ -82,6 +87,35 @@ void FenceWait(); void FenceDelete(); ++ // Set and get a global surface UID. The UID is shared across process ++ // and it's used to track surface lifetime in various parts of rendering ++ // engine. + void SetUID(uint32_t aUID) { mUID = aUID; }; -+ uint32_t GetUID() { return mUID; }; ++ uint32_t GetUID() const { return mUID; }; + ++ // Creates a global reference counter objects attached to the surface. ++ // It's created as unreferenced, i.e. IsGlobalRefSet() returns false ++ // right after GlobalRefCountCreate() call. ++ // ++ // The counter is shared by all surface instances across processes ++ // so it tracks global surface usage. ++ // ++ // The counter is automatically referenced when a new surface instance is ++ // created with SurfaceDescriptor (usually copied to another process over IPC) ++ // and it's unreferenced when surface is deleted. ++ // ++ // So without any additional GlobalRefAdd()/GlobalRefRelease() calls ++ // the IsGlobalRefSet() returns true if any other process use the surface. + void GlobalRefCountCreate(); -+ bool IsGlobalRefSet(); ++ ++ // If global reference counter was created by GlobalRefCountCreate() ++ // returns true when there's an active surface reference. ++ bool IsGlobalRefSet() const; ++ ++ // Add/Remove additional reference to the surface global reference counter. + void GlobalRefAdd(); + void GlobalRefRelease(); + WaylandDMABufSurface(SurfaceType aSurfaceType); protected: -@@ -89,6 +114,8 @@ +@@ -89,7 +123,10 @@ virtual void ReleaseSurface() = 0; bool FenceCreate(int aFd); -+ bool GlobalRefCountImport(int aFd); +- virtual ~WaylandDMABufSurface() { FenceDelete(); }; ++ void GlobalRefCountImport(int aFd); ++ void GlobalRefCountDelete(); + - virtual ~WaylandDMABufSurface() { FenceDelete(); }; ++ virtual ~WaylandDMABufSurface(); SurfaceType mSurfaceType; -@@ -102,6 +129,9 @@ + uint64_t mBufferModifier; +@@ -102,6 +139,9 @@ EGLSyncKHR mSync; RefPtr<mozilla::gl::GLContext> mGL; + -+ mozilla::UniquePtr<DMABufRefcount> mGlobalRefCount; ++ int mGlobalRefCountFd; + uint32_t mUID; }; @@ -74,101 +89,100 @@ diff --git a/widget/gtk/WaylandDMABufSurface.h b/widget/gtk/WaylandDMABufSurface diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurface.cpp --- a/widget/gtk/WaylandDMABufSurface.cpp +++ b/widget/gtk/WaylandDMABufSurface.cpp -@@ -17,6 +17,8 @@ +@@ -17,6 +17,9 @@ #include <unistd.h> #include <sys/time.h> #include <dlfcn.h> +#include <sys/mman.h> +#include <sys/eventfd.h> ++#include <poll.h> #include "mozilla/widget/gbm.h" #include "mozilla/widget/va_drmcommon.h" -@@ -57,6 +59,73 @@ +@@ -57,6 +60,61 @@ # define VA_FOURCC_NV12 0x3231564E #endif -+void DMABufRefcount::RefAdd() { -+ uint64_t counter; -+ read(mFd, &counter, sizeof(counter)); -+ counter++; -+ write(mFd, &counter, sizeof(counter)); -+} -+ -+void DMABufRefcount::Release() { -+ uint64_t counter; -+ read(mFd, &counter, sizeof(counter)); -+ counter--; -+ write(mFd, &counter, sizeof(counter)); ++bool WaylandDMABufSurface::IsGlobalRefSet() const { ++ if (!mGlobalRefCountFd) { ++ return false; ++ } ++ struct pollfd pfd; ++ pfd.fd = mGlobalRefCountFd; ++ pfd.events = POLLIN; ++ return poll(&pfd, 1, 0) == 1; +} + -+uint64_t DMABufRefcount::GetRefcount() { ++void WaylandDMABufSurface::GlobalRefRelease() { ++ MOZ_ASSERT(mGlobalRefCountFd); + uint64_t counter; -+ read(mFd, &counter, sizeof(counter)); -+ write(mFd, &counter, sizeof(counter)); -+ return counter; ++ if (read(mGlobalRefCountFd, &counter, sizeof(counter)) != sizeof(counter)) { ++ // EAGAIN means the refcount is already zero. It happens when we release ++ // last reference to the surface. ++ if (errno != EAGAIN) { ++ NS_WARNING("Failed to unref dmabuf global ref count!"); ++ } ++ } +} + -+DMABufRefcount::DMABufRefcount() -+ : mFd(eventfd(1, EFD_CLOEXEC | EFD_NONBLOCK)) {} -+ -+DMABufRefcount::DMABufRefcount(int aFd) : mFd(aFd) {} -+ -+DMABufRefcount::~DMABufRefcount() { -+ if (mFd > 0) { -+ close(mFd); ++void WaylandDMABufSurface::GlobalRefAdd() { ++ MOZ_ASSERT(mGlobalRefCountFd); ++ uint64_t counter = 1; ++ if (write(mGlobalRefCountFd, &counter, sizeof(counter)) != sizeof(counter)) { ++ NS_WARNING("Failed to ref dmabuf global ref count!"); + } +} + +void WaylandDMABufSurface::GlobalRefCountCreate() { -+ MOZ_ASSERT(!mGlobalRefCount); -+ mGlobalRefCount = MakeUnique<DMABufRefcount>(); -+ if (!mGlobalRefCount->Created()) { ++ MOZ_ASSERT(!mGlobalRefCountFd); ++ mGlobalRefCountFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK | EFD_SEMAPHORE); ++ if (mGlobalRefCountFd < 0) { + NS_WARNING("Failed to create dmabuf global ref count!"); -+ mGlobalRefCount = nullptr; ++ mGlobalRefCountFd = 0; ++ return; + } +} + -+bool WaylandDMABufSurface::GlobalRefCountImport(int aFd) { -+ MOZ_ASSERT(!mGlobalRefCount); -+ mGlobalRefCount = MakeUnique<DMABufRefcount>(aFd); -+ if (!mGlobalRefCount->Created()) { -+ NS_WARNING("Failed to import dmabuf global ref count!"); -+ mGlobalRefCount = nullptr; -+ return false; -+ } -+ return true; -+} -+ -+bool WaylandDMABufSurface::IsGlobalRefSet() { -+ MOZ_ASSERT(mGlobalRefCount); -+ return mGlobalRefCount->GetRefcount() > 1; -+} -+ -+void WaylandDMABufSurface::GlobalRefAdd() { -+ MOZ_ASSERT(mGlobalRefCount); -+ mGlobalRefCount->RefAdd(); ++void WaylandDMABufSurface::GlobalRefCountImport(int aFd) { ++ MOZ_ASSERT(!mGlobalRefCountFd); ++ mGlobalRefCountFd = aFd; ++ GlobalRefAdd(); +} + -+void WaylandDMABufSurface::GlobalRefRelease() { -+ MOZ_ASSERT(mGlobalRefCount); -+ mGlobalRefCount->Release(); ++void WaylandDMABufSurface::GlobalRefCountDelete() { ++ MOZ_ASSERT(mGlobalRefCountFd); ++ if (mGlobalRefCountFd) { ++ GlobalRefRelease(); ++ close(mGlobalRefCountFd); ++ mGlobalRefCountFd = 0; ++ } +} + WaylandDMABufSurface::WaylandDMABufSurface(SurfaceType aSurfaceType) : mSurfaceType(aSurfaceType), mBufferModifier(DRM_FORMAT_MOD_INVALID), -@@ -64,7 +133,9 @@ +@@ -64,12 +122,19 @@ mDrmFormats(), mStrides(), mOffsets(), - mSync(0) { + mSync(0), -+ mGlobalRefCount(nullptr), ++ mGlobalRefCountFd(0), + mUID(0) { for (auto& slot : mDmabufFds) { slot = -1; } -@@ -316,6 +387,7 @@ + } + ++WaylandDMABufSurface::~WaylandDMABufSurface() { ++ FenceDelete(); ++ GlobalRefCountDelete(); ++} ++ + already_AddRefed<WaylandDMABufSurface> + WaylandDMABufSurface::CreateDMABufSurface( + const mozilla::layers::SurfaceDescriptor& aDesc) { +@@ -316,6 +381,7 @@ mBufferPlaneCount = desc.fds().Length(); mGbmBufferFlags = desc.flags(); MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES); @@ -176,21 +190,18 @@ diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurfa for (int i = 0; i < mBufferPlaneCount; i++) { mDmabufFds[i] = desc.fds()[i].ClonePlatformHandle().release(); -@@ -329,6 +401,13 @@ +@@ -329,6 +395,10 @@ close(fd); } } + + if (desc.refCount().Length() > 0) { -+ int fd = desc.refCount()[0].ClonePlatformHandle().release(); -+ if (!GlobalRefCountImport(fd)) { -+ close(fd); -+ } ++ GlobalRefCountImport(desc.refCount()[0].ClonePlatformHandle().release()); + } } bool WaylandDMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) { -@@ -346,6 +425,7 @@ +@@ -346,6 +416,7 @@ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> offsets; AutoTArray<uintptr_t, DMABUF_BUFFER_PLANES> images; AutoTArray<ipc::FileDescriptor, 1> fenceFDs; @@ -198,15 +209,15 @@ diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurfa width.AppendElement(mWidth); height.AppendElement(mHeight); -@@ -362,9 +442,14 @@ +@@ -362,9 +433,14 @@ egl->fDupNativeFenceFDANDROID(egl->Display(), mSync))); } - aOutDescriptor = SurfaceDescriptorDMABuf( - mSurfaceType, mBufferModifier, mGbmBufferFlags, fds, width, height, - format, strides, offsets, GetYUVColorSpace(), fenceFDs); -+ if (mGlobalRefCount) { -+ refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCount->GetFD())); ++ if (mGlobalRefCountFd) { ++ refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCountFd)); + } + + aOutDescriptor = @@ -216,7 +227,7 @@ diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurfa return true; } -@@ -693,6 +778,7 @@ +@@ -693,6 +769,7 @@ mBufferPlaneCount = aDesc.fds().Length(); mBufferModifier = aDesc.modifier(); mColorSpace = aDesc.yUVColorSpace(); @@ -224,21 +235,18 @@ diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurfa MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES); for (int i = 0; i < mBufferPlaneCount; i++) { -@@ -710,6 +796,13 @@ +@@ -710,6 +787,10 @@ close(fd); } } + + if (aDesc.refCount().Length() > 0) { -+ int fd = aDesc.refCount()[0].ClonePlatformHandle().release(); -+ if (!GlobalRefCountImport(fd)) { -+ close(fd); -+ } ++ GlobalRefCountImport(aDesc.refCount()[0].ClonePlatformHandle().release()); + } } bool WaylandDMABufSurfaceNV12::Serialize( -@@ -721,6 +814,7 @@ +@@ -721,6 +802,7 @@ AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> strides; AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> offsets; AutoTArray<ipc::FileDescriptor, 1> fenceFDs; @@ -246,12 +254,12 @@ diff --git a/widget/gtk/WaylandDMABufSurface.cpp b/widget/gtk/WaylandDMABufSurfa for (int i = 0; i < mBufferPlaneCount; i++) { width.AppendElement(mWidth[i]); -@@ -737,9 +831,13 @@ +@@ -737,9 +819,13 @@ egl->fDupNativeFenceFDANDROID(egl->Display(), mSync))); } -+ if (mGlobalRefCount) { -+ refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCount->GetFD())); ++ if (mGlobalRefCountFd) { ++ refCountFDs.AppendElement(ipc::FileDescriptor(mGlobalRefCountFd)); + } + aOutDescriptor = SurfaceDescriptorDMABuf( diff --git a/mozilla-1619882-2.patch b/mozilla-1619882-2.patch index 2733186..dc3ab77 100644 --- a/mozilla-1619882-2.patch +++ b/mozilla-1619882-2.patch @@ -1,7 +1,7 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -@@ -10,17 +10,26 @@ +@@ -10,21 +10,45 @@ #include "FFmpegLibWrapper.h" #include "FFmpegDataDecoder.h" #include "SimpleMap.h" @@ -13,31 +13,56 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platfor namespace mozilla { #ifdef MOZ_WAYLAND_USE_VAAPI +-class VAAPIFrameHolder { ++// When VA-API decoding is running, ffmpeg allocates AVHWFramesContext - a pool ++// of "hardware" frames. Every "hardware" frame (VASurface) is backed ++// by actual piece of GPU memory which holds the decoded image data. ++// ++// The VASurface is wrapped by WaylandDMABufSurface and transferred to ++// rendering queue by WaylandDMABUFSurfaceImage, where TextureClient is ++// created and VASurface is used as a texture there. ++// ++// As there's a limited number of VASurfaces, ffmpeg reuses them to decode ++// next frames ASAP even if they are still attached to WaylandDMABufSurface ++// and used as a texture in our rendering engine. ++// ++// Unfortunately there isn't any obvious way how to mark particular VASurface ++// as used. The best we can do is to hold a reference to particular AVBuffer ++// from decoded AVFrame and AVHWFramesContext which owns the AVBuffer. + - class VAAPIFrameHolder { ++class VAAPIFrameHolder final { public: - VAAPIFrameHolder(FFmpegLibWrapper* aLib, AVBufferRef* aVAAPIDeviceContext, -+ VAAPIFrameHolder(RefPtr<WaylandDMABufSurface> aSurface, -+ FFmpegLibWrapper* aLib, AVBufferRef* aVAAPIDeviceContext, - AVBufferRef* aAVHWFramesContext, AVBufferRef* aHWFrame); +- AVBufferRef* aAVHWFramesContext, AVBufferRef* aHWFrame); ++ VAAPIFrameHolder(FFmpegLibWrapper* aLib, WaylandDMABufSurface* aSurface, ++ AVCodecContext* aAVCodecContext, AVFrame* aAVFrame); ~VAAPIFrameHolder(); -+ bool IsUsed() { return mSurface->IsGlobalRefSet(); } ++ // Check if WaylandDMABufSurface is used by any gecko rendering process ++ // (WebRender or GL compositor) or by WaylandDMABUFSurfaceImage/VideoData. ++ bool IsUsed() const { return mSurface->IsGlobalRefSet(); } + private: -+ RefPtr<WaylandDMABufSurface> mSurface; - FFmpegLibWrapper* mLib; - AVBufferRef* mVAAPIDeviceContext; +- FFmpegLibWrapper* mLib; +- AVBufferRef* mVAAPIDeviceContext; ++ const FFmpegLibWrapper* mLib; ++ const RefPtr<WaylandDMABufSurface> mSurface; AVBufferRef* mAVHWFramesContext; -@@ -97,6 +106,7 @@ +- AVBufferRef* mHWFrame; ++ AVBufferRef* mHWAVBuffer; + }; + #endif + +@@ -97,6 +121,8 @@ MediaResult CreateImageVAAPI(int64_t aOffset, int64_t aPts, int64_t aDuration, MediaDataDecoder::DecodedData& aResults); + void ReleaseUnusedVAAPIFrames(); ++ void ReleaseAllVAAPIFrames(); #endif /** -@@ -112,6 +122,7 @@ +@@ -112,6 +138,7 @@ AVBufferRef* mVAAPIDeviceContext; const bool mDisableHardwareDecoding; VADisplay mDisplay; @@ -48,41 +73,43 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platfor diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -122,19 +122,30 @@ - return AV_PIX_FMT_NONE; +@@ -123,18 +123,27 @@ } --VAAPIFrameHolder::VAAPIFrameHolder(FFmpegLibWrapper* aLib, -+VAAPIFrameHolder::VAAPIFrameHolder(RefPtr<WaylandDMABufSurface> aSurface, -+ FFmpegLibWrapper* aLib, - AVBufferRef* aVAAPIDeviceContext, - AVBufferRef* aAVHWFramesContext, - AVBufferRef* aHWFrame) -- : mLib(aLib), -+ : mSurface(aSurface), -+ mLib(aLib), - mVAAPIDeviceContext(mLib->av_buffer_ref(aVAAPIDeviceContext)), - mAVHWFramesContext(mLib->av_buffer_ref(aAVHWFramesContext)), + VAAPIFrameHolder::VAAPIFrameHolder(FFmpegLibWrapper* aLib, +- AVBufferRef* aVAAPIDeviceContext, +- AVBufferRef* aAVHWFramesContext, +- AVBufferRef* aHWFrame) ++ WaylandDMABufSurface* aSurface, ++ AVCodecContext* aAVCodecContext, ++ AVFrame* aAVFrame) + : mLib(aLib), +- mVAAPIDeviceContext(mLib->av_buffer_ref(aVAAPIDeviceContext)), +- mAVHWFramesContext(mLib->av_buffer_ref(aAVHWFramesContext)), - mHWFrame(mLib->av_buffer_ref(aHWFrame)){}; -+ mHWFrame(mLib->av_buffer_ref(aHWFrame)) { ++ mSurface(aSurface), ++ mAVHWFramesContext(mLib->av_buffer_ref(aAVCodecContext->hw_frames_ctx)), ++ mHWAVBuffer(mLib->av_buffer_ref(aAVFrame->buf[0])) { + FFMPEG_LOG("VAAPIFrameHolder is adding dmabuf surface UID = %d\n", + mSurface->GetUID()); ++ + // Create global refcount object to track mSurface usage over -+ // processes. ++ // gects rendering engine. We can't release it until it's used ++ // by GL compositor / WebRender. + mSurface->GlobalRefCountCreate(); +} VAAPIFrameHolder::~VAAPIFrameHolder() { +- mLib->av_buffer_unref(&mHWFrame); + FFMPEG_LOG("VAAPIFrameHolder is releasing dmabuf surface UID = %d\n", + mSurface->GetUID()); - mLib->av_buffer_unref(&mHWFrame); ++ mLib->av_buffer_unref(&mHWAVBuffer); mLib->av_buffer_unref(&mAVHWFramesContext); - mLib->av_buffer_unref(&mVAAPIDeviceContext); -+ mSurface = nullptr; +- mLib->av_buffer_unref(&mVAAPIDeviceContext); } AVCodec* FFmpegVideoDecoder<LIBAV_VER>::FindVAAPICodec() { -@@ -418,6 +428,13 @@ +@@ -422,6 +431,13 @@ NS_WARNING("FFmpeg h264 decoder failed to allocate frame."); return MediaResult(NS_ERROR_OUT_OF_MEMORY, __func__); } @@ -96,7 +123,7 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf res = mLib->avcodec_receive_frame(mCodecContext, mFrame); if (res == int(AVERROR_EOF)) { return NS_ERROR_DOM_MEDIA_END_OF_STREAM; -@@ -624,9 +641,16 @@ +@@ -628,9 +644,20 @@ } #ifdef MOZ_WAYLAND_USE_VAAPI @@ -113,10 +140,14 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + holder++; + } + } ++} ++ ++void FFmpegVideoDecoder<LIBAV_VER>::ReleaseAllVAAPIFrames() { ++ mFrameHolders.clear(); } MediaResult FFmpegVideoDecoder<LIBAV_VER>::CreateImageVAAPI( -@@ -663,20 +687,28 @@ +@@ -667,20 +694,20 @@ RESULT_DETAIL("Unable to allocate WaylandDMABufSurfaceNV12.")); } @@ -128,28 +159,32 @@ diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platf + surface->SetYUVColorSpace(GetFrameColorSpace()); - // mFrame->buf[0] is a reference to H264 VASurface for this mFrame. +- // mFrame->buf[0] is a reference to H264 VASurface for this mFrame. - // We need create WaylandDMABUFSurfaceImage on top of it, -+ // We need create WaylandDMABUFSurface on top of it, - // create EGLImage/Texture on top of it and render it by GL. +- // create EGLImage/Texture on top of it and render it by GL. ++ // Store reference to the decoded HW buffer, see VAAPIFrameHolder struct. ++ auto holder = ++ MakeUnique<VAAPIFrameHolder>(mLib, surface, mCodecContext, mFrame); ++ mFrameHolders.push_back(std::move(holder)); - // FFmpeg tends to reuse the particual VASurface for another frame - // even when the mFrame is not released. To keep VASurface as is +- // FFmpeg tends to reuse the particual VASurface for another frame +- // even when the mFrame is not released. To keep VASurface as is - // we explicitly reference it and keep until WaylandDMABUFSurfaceImage - // is live. - RefPtr<layers::Image> im = new layers::WaylandDMABUFSurfaceImage( - surface, VAAPIFrameReleaseCallback, - new VAAPIFrameHolder(mLib, mVAAPIDeviceContext, - mCodecContext->hw_frames_ctx, mFrame->buf[0])); -+ // we explicitly reference it and keep until there's any reference to -+ // attached WaylandDMABUFSurface. -+ auto holder = MakeUnique<VAAPIFrameHolder>(surface, mLib, mVAAPIDeviceContext, -+ mCodecContext->hw_frames_ctx, -+ mFrame->buf[0]); -+ mFrameHolders.push_back(std::move(holder)); -+ + RefPtr<layers::Image> im = new layers::WaylandDMABUFSurfaceImage(surface); RefPtr<VideoData> vp = VideoData::CreateFromImage( mInfo.mDisplay, aOffset, TimeUnit::FromMicroseconds(aPts), +@@ -732,6 +759,7 @@ + void FFmpegVideoDecoder<LIBAV_VER>::ProcessShutdown() { + #ifdef MOZ_WAYLAND_USE_VAAPI + if (mVAAPIDeviceContext) { ++ ReleaseAllVAAPIFrames(); + mLib->av_buffer_unref(&mVAAPIDeviceContext); + } + #endif diff --git a/mozilla-1628690.patch b/mozilla-1628690.patch deleted file mode 100644 index 3a1757d..0000000 --- a/mozilla-1628690.patch +++ /dev/null @@ -1,67 +0,0 @@ -diff --git a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h ---- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h -+++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h -@@ -49,7 +49,9 @@ - RefPtr<MediaDataDecoder> decoder = new FFmpegVideoDecoder<V>( - mLib, aParams.mTaskQueue, aParams.VideoConfig(), - aParams.mKnowsCompositor, aParams.mImageContainer, -- aParams.mOptions.contains(CreateDecoderParams::Option::LowLatency)); -+ aParams.mOptions.contains(CreateDecoderParams::Option::LowLatency), -+ aParams.mOptions.contains( -+ CreateDecoderParams::Option::HardwareDecoderNotAllowed)); - return decoder.forget(); - } - -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -@@ -48,7 +48,8 @@ - public: - FFmpegVideoDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue, - const VideoInfo& aConfig, KnowsCompositor* aAllocator, -- ImageContainer* aImageContainer, bool aLowLatency); -+ ImageContainer* aImageContainer, bool aLowLatency, -+ bool aDisableHardwareDecoding); - - RefPtr<InitPromise> Init() override; - void InitCodecContext() override; -@@ -109,6 +110,7 @@ - - #ifdef MOZ_WAYLAND_USE_VAAPI - AVBufferRef* mVAAPIDeviceContext; -+ const bool mDisableHardwareDecoding; - #endif - RefPtr<KnowsCompositor> mImageAllocator; - RefPtr<ImageContainer> mImageContainer; -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -270,10 +270,11 @@ - FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder( - FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue, const VideoInfo& aConfig, - KnowsCompositor* aAllocator, ImageContainer* aImageContainer, -- bool aLowLatency) -+ bool aLowLatency, bool aDisableHardwareDecoding) - : FFmpegDataDecoder(aLib, aTaskQueue, GetCodecId(aConfig.mMimeType)), - #ifdef MOZ_WAYLAND_USE_VAAPI - mVAAPIDeviceContext(nullptr), -+ mDisableHardwareDecoding(aDisableHardwareDecoding), - #endif - mImageAllocator(aAllocator), - mImageContainer(aImageContainer), -@@ -289,9 +290,11 @@ - MediaResult rv; - - #ifdef MOZ_WAYLAND_USE_VAAPI -- rv = InitVAAPIDecoder(); -- if (NS_SUCCEEDED(rv)) { -- return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__); -+ if (!mDisableHardwareDecoding) { -+ rv = InitVAAPIDecoder(); -+ if (NS_SUCCEEDED(rv)) { -+ return InitPromise::CreateAndResolve(TrackInfo::kVideoTrack, __func__); -+ } - } - #endif - - diff --git a/mozilla-1630754.patch b/mozilla-1630754.patch deleted file mode 100644 index b8b9922..0000000 --- a/mozilla-1630754.patch +++ /dev/null @@ -1,298 +0,0 @@ -diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h ---- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h -+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.h -@@ -116,9 +116,9 @@ - #ifdef MOZ_WAYLAND - const AVCodecHWConfig* (*avcodec_get_hw_config)(const AVCodec* codec, - int index); -- int (*av_hwdevice_ctx_create)(AVBufferRef** device_ctx, int type, -- const char* device, AVDictionary* opts, -- int flags); -+ AVBufferRef* (*av_hwdevice_ctx_alloc)(int); -+ int (*av_hwdevice_ctx_init)(AVBufferRef* ref); -+ - AVBufferRef* (*av_buffer_ref)(AVBufferRef* buf); - void (*av_buffer_unref)(AVBufferRef** buf); - int (*av_hwframe_transfer_get_formats)(AVBufferRef* hwframe_ctx, int dir, -@@ -132,12 +132,16 @@ - - int (*vaExportSurfaceHandle)(void*, unsigned int, uint32_t, uint32_t, void*); - int (*vaSyncSurface)(void*, unsigned int); -+ int (*vaInitialize)(void* dpy, int* major_version, int* minor_version); -+ int (*vaTerminate)(void* dpy); -+ void* (*vaGetDisplayWl)(struct wl_display* display); - #endif - - PRLibrary* mAVCodecLib; - PRLibrary* mAVUtilLib; - #ifdef MOZ_WAYLAND - PRLibrary* mVALib; -+ PRLibrary* mVALibWayland; - #endif - - private: -diff --git a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegLibWrapper.cpp -@@ -159,7 +159,8 @@ - AV_FUNC_OPTION(av_frame_get_color_range, AV_FUNC_AVUTIL_ALL) - #ifdef MOZ_WAYLAND - AV_FUNC_OPTION_SILENT(avcodec_get_hw_config, AV_FUNC_58) -- AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_create, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_init, AV_FUNC_58) -+ AV_FUNC_OPTION_SILENT(av_hwdevice_ctx_alloc, AV_FUNC_58) - AV_FUNC_OPTION_SILENT(av_buffer_ref, AV_FUNC_AVUTIL_58) - AV_FUNC_OPTION_SILENT(av_buffer_unref, AV_FUNC_AVUTIL_58) - AV_FUNC_OPTION_SILENT(av_hwframe_transfer_get_formats, AV_FUNC_58) -@@ -181,8 +182,21 @@ - if (mVALib) { - VA_FUNC_OPTION_SILENT(vaExportSurfaceHandle) - VA_FUNC_OPTION_SILENT(vaSyncSurface) -+ VA_FUNC_OPTION_SILENT(vaInitialize) -+ VA_FUNC_OPTION_SILENT(vaTerminate) - } --# undef VA_FUNC_OPTION -+# undef VA_FUNC_OPTION_SILENT -+ -+# define VAW_FUNC_OPTION_SILENT(func) \ -+ if (!(func = (decltype(func))PR_FindSymbol(mVALibWayland, #func))) { \ -+ FFMPEG_LOG("Couldn't load function " #func); \ -+ } -+ -+ // mVALibWayland is optional and may not be present. -+ if (mVALibWayland) { -+ VAW_FUNC_OPTION_SILENT(vaGetDisplayWl) -+ } -+# undef VAW_FUNC_OPTION_SILENT - #endif - - avcodec_register_all(); -@@ -218,6 +232,9 @@ - if (mVALib) { - PR_UnloadLibrary(mVALib); - } -+ if (mVALibWayland) { -+ PR_UnloadLibrary(mVALibWayland); -+ } - #endif - PodZero(this); - } -@@ -226,13 +243,16 @@ - bool FFmpegLibWrapper::IsVAAPIAvailable() { - # define VA_FUNC_LOADED(func) (func != nullptr) - return VA_FUNC_LOADED(avcodec_get_hw_config) && -- VA_FUNC_LOADED(av_hwdevice_ctx_create) && -+ VA_FUNC_LOADED(av_hwdevice_ctx_alloc) && -+ VA_FUNC_LOADED(av_hwdevice_ctx_init) && - VA_FUNC_LOADED(av_buffer_ref) && VA_FUNC_LOADED(av_buffer_unref) && - VA_FUNC_LOADED(av_hwframe_transfer_get_formats) && - VA_FUNC_LOADED(av_hwdevice_ctx_create_derived) && - VA_FUNC_LOADED(av_hwframe_ctx_alloc) && VA_FUNC_LOADED(av_dict_set) && - VA_FUNC_LOADED(av_dict_free) && -- VA_FUNC_LOADED(vaExportSurfaceHandle) && VA_FUNC_LOADED(vaSyncSurface); -+ VA_FUNC_LOADED(vaExportSurfaceHandle) && -+ VA_FUNC_LOADED(vaSyncSurface) && VA_FUNC_LOADED(vaInitialize) && -+ VA_FUNC_LOADED(vaTerminate) && VA_FUNC_LOADED(vaGetDisplayWl); - } - #endif - -diff --git a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegRuntimeLinker.cpp -@@ -9,6 +9,9 @@ - #include "mozilla/ArrayUtils.h" - #include "FFmpegLog.h" - #include "prlink.h" -+#ifdef MOZ_WAYLAND -+# include "gfxPlatformGtk.h" -+#endif - - namespace mozilla { - -@@ -54,21 +57,33 @@ - } - - #ifdef MOZ_WAYLAND -- { -- const char* lib = "libva.so.2"; -+ if (gfxPlatformGtk::GetPlatform()->UseWaylandHardwareVideoDecoding()) { -+ const char* libWayland = "libva-wayland.so.2"; - PRLibSpec lspec; - lspec.type = PR_LibSpec_Pathname; -- lspec.value.pathname = lib; -- sLibAV.mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -- // Don't use libva when it's missing vaExportSurfaceHandle. -- if (sLibAV.mVALib && -- !PR_FindSymbol(sLibAV.mVALib, "vaExportSurfaceHandle")) { -- PR_UnloadLibrary(sLibAV.mVALib); -- sLibAV.mVALib = nullptr; -+ lspec.value.pathname = libWayland; -+ sLibAV.mVALibWayland = -+ PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -+ if (!sLibAV.mVALibWayland) { -+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", libWayland); - } -- if (!sLibAV.mVALib) { -- FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib); -+ -+ if (sLibAV.mVALibWayland) { -+ const char* lib = "libva.so.2"; -+ lspec.value.pathname = lib; -+ sLibAV.mVALib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL); -+ // Don't use libva when it's missing vaExportSurfaceHandle. -+ if (sLibAV.mVALib && -+ !PR_FindSymbol(sLibAV.mVALib, "vaExportSurfaceHandle")) { -+ PR_UnloadLibrary(sLibAV.mVALib); -+ sLibAV.mVALib = nullptr; -+ } -+ if (!sLibAV.mVALib) { -+ FFMPEG_LOG("VA-API support: Missing or old %s library.\n", lib); -+ } - } -+ } else { -+ FFMPEG_LOG("VA-API FFmpeg is disabled by platform"); - } - #endif - -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -@@ -111,6 +111,7 @@ - #ifdef MOZ_WAYLAND_USE_VAAPI - AVBufferRef* mVAAPIDeviceContext; - const bool mDisableHardwareDecoding; -+ VADisplay mDisplay; - #endif - RefPtr<KnowsCompositor> mImageAllocator; - RefPtr<ImageContainer> mImageContainer; -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -154,14 +154,44 @@ - return nullptr; - } - -+class VAAPIDisplayHolder { -+ public: -+ VAAPIDisplayHolder(FFmpegLibWrapper* aLib, VADisplay aDisplay) -+ : mLib(aLib), mDisplay(aDisplay){}; -+ ~VAAPIDisplayHolder() { mLib->vaTerminate(mDisplay); } -+ -+ private: -+ FFmpegLibWrapper* mLib; -+ VADisplay mDisplay; -+}; -+ -+static void VAAPIDisplayReleaseCallback(struct AVHWDeviceContext* hwctx) { -+ auto displayHolder = static_cast<VAAPIDisplayHolder*>(hwctx->user_opaque); -+ delete displayHolder; -+} -+ - bool FFmpegVideoDecoder<LIBAV_VER>::CreateVAAPIDeviceContext() { -- AVDictionary* opts = nullptr; -- mLib->av_dict_set(&opts, "connection_type", "drm", 0); -- bool ret = -- (mLib->av_hwdevice_ctx_create( -- &mVAAPIDeviceContext, AV_HWDEVICE_TYPE_VAAPI, NULL, NULL, 0) == 0); -- mLib->av_dict_free(&opts); -- if (!ret) { -+ mVAAPIDeviceContext = mLib->av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI); -+ if (!mVAAPIDeviceContext) { -+ return false; -+ } -+ AVHWDeviceContext* hwctx = (AVHWDeviceContext*)mVAAPIDeviceContext->data; -+ AVVAAPIDeviceContext* vactx = (AVVAAPIDeviceContext*)hwctx->hwctx; -+ -+ mDisplay = mLib->vaGetDisplayWl(widget::WaylandDisplayGet()->GetDisplay()); -+ -+ hwctx->user_opaque = new VAAPIDisplayHolder(mLib, mDisplay); -+ hwctx->free = VAAPIDisplayReleaseCallback; -+ -+ int major, minor; -+ int status = mLib->vaInitialize(mDisplay, &major, &minor); -+ if (status != VA_STATUS_SUCCESS) { -+ return false; -+ } -+ -+ vactx->display = mDisplay; -+ -+ if (mLib->av_hwdevice_ctx_init(mVAAPIDeviceContext) < 0) { - return false; - } - -@@ -172,6 +202,11 @@ - MediaResult FFmpegVideoDecoder<LIBAV_VER>::InitVAAPIDecoder() { - FFMPEG_LOG("Initialising VA-API FFmpeg decoder"); - -+ if (!mLib->IsVAAPIAvailable()) { -+ FFMPEG_LOG("libva library or symbols are missing."); -+ return NS_ERROR_NOT_AVAILABLE; -+ } -+ - auto layersBackend = mImageAllocator - ? mImageAllocator->GetCompositorBackendType() - : layers::LayersBackend::LAYERS_BASIC; -@@ -181,16 +216,6 @@ - return NS_ERROR_NOT_AVAILABLE; - } - -- if (!mLib->IsVAAPIAvailable()) { -- FFMPEG_LOG("libva library or symbols are missing."); -- return NS_ERROR_NOT_AVAILABLE; -- } -- -- if (!gfxPlatformGtk::GetPlatform()->UseWaylandHardwareVideoDecoding()) { -- FFMPEG_LOG("VA-API FFmpeg is disabled by platform"); -- return NS_ERROR_NOT_AVAILABLE; -- } -- - AVCodec* codec = FindVAAPICodec(); - if (!codec) { - FFMPEG_LOG("Couldn't find ffmpeg VA-API decoder"); -@@ -275,6 +300,7 @@ - #ifdef MOZ_WAYLAND_USE_VAAPI - mVAAPIDeviceContext(nullptr), - mDisableHardwareDecoding(aDisableHardwareDecoding), -+ mDisplay(nullptr), - #endif - mImageAllocator(aAllocator), - mImageContainer(aImageContainer), -@@ -606,16 +632,10 @@ - " duration=%" PRId64 " opaque=%" PRId64, - aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque); - -- AVHWDeviceContext* device_ctx = (AVHWDeviceContext*)mVAAPIDeviceContext->data; -- AVVAAPIDeviceContext* VAAPIDeviceContext = -- (AVVAAPIDeviceContext*)device_ctx->hwctx; - VADRMPRIMESurfaceDescriptor va_desc; -- - VASurfaceID surface_id = (VASurfaceID)(uintptr_t)mFrame->data[3]; -- - VAStatus vas = mLib->vaExportSurfaceHandle( -- VAAPIDeviceContext->display, surface_id, -- VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, -+ mDisplay, surface_id, VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, - VA_EXPORT_SURFACE_READ_ONLY | VA_EXPORT_SURFACE_SEPARATE_LAYERS, - &va_desc); - if (vas != VA_STATUS_SUCCESS) { -@@ -623,7 +643,7 @@ - NS_ERROR_OUT_OF_MEMORY, - RESULT_DETAIL("Unable to get frame by vaExportSurfaceHandle()")); - } -- vas = mLib->vaSyncSurface(VAAPIDeviceContext->display, surface_id); -+ vas = mLib->vaSyncSurface(mDisplay, surface_id); - if (vas != VA_STATUS_SUCCESS) { - NS_WARNING("vaSyncSurface() failed."); - } -diff --git a/dom/media/platforms/ffmpeg/moz.build b/dom/media/platforms/ffmpeg/moz.build ---- a/dom/media/platforms/ffmpeg/moz.build -+++ b/dom/media/platforms/ffmpeg/moz.build -@@ -20,4 +20,7 @@ - 'FFmpegRuntimeLinker.cpp', - ] - -+if CONFIG['MOZ_WAYLAND']: -+ include('/ipc/chromium/chromium-config.mozbuild') -+ - FINAL_LIBRARY = 'xul' - diff --git a/mozilla-1632059.patch b/mozilla-1632059.patch deleted file mode 100644 index b051e98..0000000 --- a/mozilla-1632059.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -178,7 +178,12 @@ - AVHWDeviceContext* hwctx = (AVHWDeviceContext*)mVAAPIDeviceContext->data; - AVVAAPIDeviceContext* vactx = (AVVAAPIDeviceContext*)hwctx->hwctx; - -- mDisplay = mLib->vaGetDisplayWl(widget::WaylandDisplayGet()->GetDisplay()); -+ wl_display* display = widget::WaylandDisplayGetWLDisplay(); -+ if (!display) { -+ FFMPEG_LOG("Can't get default wayland display."); -+ return false; -+ } -+ mDisplay = mLib->vaGetDisplayWl(display); - - hwctx->user_opaque = new VAAPIDisplayHolder(mLib, mDisplay); - hwctx->free = VAAPIDisplayReleaseCallback; -diff --git a/widget/gtk/nsWaylandDisplay.cpp b/widget/gtk/nsWaylandDisplay.cpp ---- a/widget/gtk/nsWaylandDisplay.cpp -+++ b/widget/gtk/nsWaylandDisplay.cpp -@@ -35,6 +35,9 @@ - wl_display* WaylandDisplayGetWLDisplay(GdkDisplay* aGdkDisplay) { - if (!aGdkDisplay) { - aGdkDisplay = gdk_display_get_default(); -+ if (!aGdkDisplay || GDK_IS_X11_DISPLAY(aGdkDisplay)) { -+ return nullptr; -+ } - } - - // Available as of GTK 3.8+ -@@ -537,8 +540,7 @@ - StaticPrefs::widget_wayland_dmabuf_webgl_enabled(); - } - bool nsWaylandDisplay::IsDMABufVAAPIEnabled() { -- return IsDMABufEnabled() && -- StaticPrefs::widget_wayland_dmabuf_vaapi_enabled(); -+ return StaticPrefs::widget_wayland_dmabuf_vaapi_enabled(); - } - - void* nsGbmLib::sGbmLibHandle = nullptr; - diff --git a/mozilla-1634293.patch b/mozilla-1634293.patch new file mode 100644 index 0000000..09a3274 --- /dev/null +++ b/mozilla-1634293.patch @@ -0,0 +1,406 @@ +diff --git a/browser/components/shell/nsGNOMEShellDBusHelper.h b/browser/components/shell/nsGNOMEShellDBusHelper.h +--- a/browser/components/shell/nsGNOMEShellDBusHelper.h ++++ b/browser/components/shell/nsGNOMEShellDBusHelper.h +@@ -19,6 +19,8 @@ + #define DBUS_BUS_NAME "org.mozilla.Firefox.SearchProvider" + #define DBUS_OBJECT_PATH "/org/mozilla/Firefox/SearchProvider" + ++class nsGNOMEShellHistorySearchResult; ++ + DBusHandlerResult DBusIntrospect(DBusConnection* aConnection, + DBusMessage* aMsg); + DBusHandlerResult DBusHandleInitialResultSet( +diff --git a/browser/components/shell/nsGNOMEShellDBusHelper.cpp b/browser/components/shell/nsGNOMEShellDBusHelper.cpp +--- a/browser/components/shell/nsGNOMEShellDBusHelper.cpp ++++ b/browser/components/shell/nsGNOMEShellDBusHelper.cpp +@@ -6,7 +6,6 @@ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "nsGNOMEShellSearchProvider.h" +-#include "nsGNOMEShellDBusHelper.h" + + #include "nsPrintfCString.h" + #include "RemoteUtils.h" +@@ -174,6 +173,49 @@ + dbus_message_iter_close_container(aIter, &iterDict); + } + ++/* ++ "icon-data": a tuple of type (iiibiiay) describing a pixbuf with width, ++ height, rowstride, has-alpha, ++ bits-per-sample, channels, ++ image data ++*/ ++static void DBusAppendIcon(GnomeHistoryIcon* aIcon, DBusMessageIter* aIter) { ++ DBusMessageIter iterDict, iterVar, iterStruct; ++ dbus_message_iter_open_container(aIter, DBUS_TYPE_DICT_ENTRY, nullptr, ++ &iterDict); ++ const char* key = "icon-data"; ++ dbus_message_iter_append_basic(&iterDict, DBUS_TYPE_STRING, &key); ++ dbus_message_iter_open_container(&iterDict, DBUS_TYPE_VARIANT, "(iiibiiay)", ++ &iterVar); ++ dbus_message_iter_open_container(&iterVar, DBUS_TYPE_STRUCT, nullptr, ++ &iterStruct); ++ ++ int width = aIcon->GetWidth(); ++ int height = aIcon->GetHeight(); ++ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &width); ++ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &height); ++ int rowstride = width * 4; ++ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &rowstride); ++ int hasAlpha = true; ++ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_BOOLEAN, &hasAlpha); ++ int bitsPerSample = 8; ++ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &bitsPerSample); ++ int channels = 4; ++ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &channels); ++ ++ DBusMessageIter iterArray; ++ dbus_message_iter_open_container(&iterStruct, DBUS_TYPE_ARRAY, "y", ++ &iterArray); ++ unsigned char* array = aIcon->GetData(); ++ dbus_message_iter_append_fixed_array(&iterArray, DBUS_TYPE_BYTE, &array, ++ width * height * 4); ++ dbus_message_iter_close_container(&iterStruct, &iterArray); ++ ++ dbus_message_iter_close_container(&iterVar, &iterStruct); ++ dbus_message_iter_close_container(&iterDict, &iterVar); ++ dbus_message_iter_close_container(aIter, &iterDict); ++} ++ + /* Appends history search results to the DBUS reply. + + We can return those fields at GetResultMetas: +@@ -188,11 +230,14 @@ + "description": an optional short description (1-2 lines) + */ + static void DBusAppendResultID( +- nsCOMPtr<nsINavHistoryContainerResultNode> aHistResultContainer, ++ RefPtr<nsGNOMEShellHistorySearchResult> aSearchResult, + DBusMessageIter* aIter, const char* aID) { ++ nsCOMPtr<nsINavHistoryContainerResultNode> container = ++ aSearchResult->GetSearchResultContainer(); ++ ++ int index = DBusGetIndexFromIDKey(aID); + nsCOMPtr<nsINavHistoryResultNode> child; +- aHistResultContainer->GetChild(DBusGetIndexFromIDKey(aID), +- getter_AddRefs(child)); ++ container->GetChild(index, getter_AddRefs(child)); + nsAutoCString title; + if (NS_FAILED(child->GetTitle(title))) { + return; +@@ -207,7 +252,13 @@ + const char* titleStr = title.get(); + appendStringDictionary(aIter, "id", aID); + appendStringDictionary(aIter, "name", titleStr); +- appendStringDictionary(aIter, "gicon", "text-html"); ++ ++ GnomeHistoryIcon* icon = aSearchResult->GetHistoryIcon(index); ++ if (icon) { ++ DBusAppendIcon(icon, aIter); ++ } else { ++ appendStringDictionary(aIter, "gicon", "text-html"); ++ } + } + + /* Search the web for: "searchTerm" to the DBUS reply. +@@ -265,8 +316,7 @@ + KEYWORD_SEARCH_STRING_LEN) == 0) { + DBusAppendSearchID(&iterArray2, stringArray[i]); + } else { +- DBusAppendResultID(aSearchResult->GetSearchResultContainer(), +- &iterArray2, stringArray[i]); ++ DBusAppendResultID(aSearchResult, &iterArray2, stringArray[i]); + } + dbus_message_iter_close_container(&iterArray, &iterArray2); + } +diff --git a/browser/components/shell/nsGNOMEShellSearchProvider.h b/browser/components/shell/nsGNOMEShellSearchProvider.h +--- a/browser/components/shell/nsGNOMEShellSearchProvider.h ++++ b/browser/components/shell/nsGNOMEShellSearchProvider.h +@@ -12,9 +12,37 @@ + #include "nsINavHistoryService.h" + #include "nsUnixRemoteServer.h" + #include "nsCOMPtr.h" ++#include "mozilla/UniquePtr.h" ++#include "nsGNOMEShellDBusHelper.h" + + class nsGNOMEShellSearchProvider; + ++class GnomeHistoryIcon { ++ public: ++ GnomeHistoryIcon() : mTimeStamp(-1), mWidth(0), mHeight(0){}; ++ ++ // From which search is this icon ++ void Set(int aTimeStamp, mozilla::UniquePtr<uint8_t[]> aData, int aWidth, ++ int aHeight) { ++ mTimeStamp = aTimeStamp; ++ mWidth = aWidth; ++ mHeight = aHeight; ++ mData = std::move(aData); ++ } ++ ++ bool IsLoaded() { return mData && mWidth > 0 && mHeight > 0; } ++ int GetTimeStamp() { return mTimeStamp; } ++ uint8_t* GetData() { return mData.get(); } ++ int GetWidth() { return mWidth; } ++ int GetHeight() { return mHeight; } ++ ++ private: ++ int mTimeStamp; ++ mozilla::UniquePtr<uint8_t[]> mData; ++ int mWidth; ++ int mHeight; ++}; ++ + // nsGNOMEShellHistorySearchResult is a container with contains search results + // which are files asynchronously by nsGNOMEShellHistoryService. + // The search results can be opened by Firefox then. +@@ -34,11 +62,16 @@ + mSearchTerm = nsAutoCString(aSearchTerm); + } + DBusConnection* GetDBusConnection() { return mConnection; } ++ void SetTimeStamp(int aTimeStamp) { mTimeStamp = aTimeStamp; } + int GetTimeStamp() { return mTimeStamp; } +- void SetTimeStamp(int aTimeStamp) { mTimeStamp = aTimeStamp; } + nsAutoCString& GetSearchTerm() { return mSearchTerm; } +- void SetSearchResultContainer( ++ ++ // Receive (asynchronously) history search results from history service. ++ // This is called asynchronously by nsGNOMEShellHistoryService ++ // when we have search results available. ++ void ReceiveSearchResultContainer( + nsCOMPtr<nsINavHistoryContainerResultNode> aHistResultContainer); ++ + nsCOMPtr<nsINavHistoryContainerResultNode> GetSearchResultContainer() { + return mHistResultContainer; + } +@@ -46,8 +79,12 @@ + nsUnixRemoteServer::HandleCommandLine(aBuffer, aTimestamp); + } + ++ void SetHistoryIcon(int aTimeStamp, mozilla::UniquePtr<uint8_t[]> aData, ++ int aWidth, int aHeight, int aIconIndex); ++ GnomeHistoryIcon* GetHistoryIcon(int aIconIndex); ++ + private: +- void SendDBusSearchResultReply(); ++ void HandleSearchResultReply(); + + ~nsGNOMEShellHistorySearchResult() = default; + +@@ -58,6 +95,7 @@ + DBusMessage* mReply; + DBusConnection* mConnection; + int mTimeStamp; ++ GnomeHistoryIcon mHistoryIcons[MAX_SEARCH_RESULTS_NUM]; + }; + + class nsGNOMEShellHistoryService { +diff --git a/browser/components/shell/nsGNOMEShellSearchProvider.cpp b/browser/components/shell/nsGNOMEShellSearchProvider.cpp +--- a/browser/components/shell/nsGNOMEShellSearchProvider.cpp ++++ b/browser/components/shell/nsGNOMEShellSearchProvider.cpp +@@ -6,7 +6,6 @@ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "nsGNOMEShellSearchProvider.h" +-#include "nsGNOMEShellDBusHelper.h" + + #include "nsIWidget.h" + #include "nsToolkitCompsCID.h" +@@ -14,10 +13,113 @@ + #include "RemoteUtils.h" + #include "base/message_loop.h" // for MessageLoop + #include "base/task.h" // for NewRunnableMethod, etc ++#include "nsIServiceManager.h" ++#include "nsNetCID.h" ++#include "nsIIOService.h" + + #include <dbus/dbus.h> + #include <dbus/dbus-glib-lowlevel.h> + ++#include "imgIContainer.h" ++#include "imgITools.h" ++#include "mozilla/gfx/DataSurfaceHelpers.h" ++ ++using namespace mozilla; ++using namespace mozilla::gfx; ++ ++class AsyncFaviconDataReady final : public nsIFaviconDataCallback { ++ public: ++ NS_DECL_ISUPPORTS ++ NS_DECL_NSIFAVICONDATACALLBACK ++ ++ AsyncFaviconDataReady(RefPtr<nsGNOMEShellHistorySearchResult> aSearchResult, ++ int aIconIndex, int aTimeStamp) ++ : mSearchResult(aSearchResult), ++ mIconIndex(aIconIndex), ++ mTimeStamp(aTimeStamp){}; ++ ++ private: ++ ~AsyncFaviconDataReady() {} ++ ++ RefPtr<nsGNOMEShellHistorySearchResult> mSearchResult; ++ int mIconIndex; ++ int mTimeStamp; ++}; ++ ++NS_IMPL_ISUPPORTS(AsyncFaviconDataReady, nsIFaviconDataCallback) ++ ++// Inspired by SurfaceToPackedBGRA ++static UniquePtr<uint8_t[]> SurfaceToPackedRGBA(DataSourceSurface* aSurface) { ++ IntSize size = aSurface->GetSize(); ++ CheckedInt<size_t> bufferSize = ++ CheckedInt<size_t>(size.width * 4) * CheckedInt<size_t>(size.height); ++ if (!bufferSize.isValid()) { ++ return nullptr; ++ } ++ UniquePtr<uint8_t[]> imageBuffer(new (std::nothrow) ++ uint8_t[bufferSize.value()]); ++ if (!imageBuffer) { ++ return nullptr; ++ } ++ ++ DataSourceSurface::MappedSurface map; ++ if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) { ++ return nullptr; ++ } ++ ++ // Convert BGRA to RGBA ++ uint32_t* aSrc = (uint32_t*)map.mData; ++ uint32_t* aDst = (uint32_t*)imageBuffer.get(); ++ for (int i = 0; i < size.width * size.height; i++, aDst++, aSrc++) { ++ *aDst = *aSrc & 0xff00ff00; ++ *aDst |= (*aSrc & 0xff) << 16; ++ *aDst |= (*aSrc & 0xff0000) >> 16; ++ } ++ ++ aSurface->Unmap(); ++ ++ return imageBuffer; ++} ++ ++NS_IMETHODIMP ++AsyncFaviconDataReady::OnComplete(nsIURI* aFaviconURI, uint32_t aDataLen, ++ const uint8_t* aData, ++ const nsACString& aMimeType, ++ uint16_t aWidth) { ++ // This is a callback from some previous search so we don't want it ++ if (mTimeStamp != mSearchResult->GetTimeStamp() || !aData || !aDataLen) { ++ return NS_ERROR_FAILURE; ++ } ++ ++ // Decode the image from the format it was returned to us in (probably PNG) ++ nsCOMPtr<imgIContainer> container; ++ nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1"); ++ nsresult rv = imgtool->DecodeImageFromBuffer( ++ reinterpret_cast<const char*>(aData), aDataLen, aMimeType, ++ getter_AddRefs(container)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ ++ RefPtr<SourceSurface> surface = container->GetFrame( ++ imgIContainer::FRAME_FIRST, ++ imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY); ++ ++ if (!surface || surface->GetFormat() != SurfaceFormat::B8G8R8A8) { ++ return NS_ERROR_FAILURE; ++ } ++ ++ // Allocate a new buffer that we own. ++ RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface(); ++ UniquePtr<uint8_t[]> data = SurfaceToPackedRGBA(dataSurface); ++ if (!data) { ++ return NS_ERROR_OUT_OF_MEMORY; ++ } ++ ++ mSearchResult->SetHistoryIcon(mTimeStamp, std::move(data), ++ surface->GetSize().width, ++ surface->GetSize().height, mIconIndex); ++ return NS_OK; ++} ++ + DBusHandlerResult nsGNOMEShellSearchProvider::HandleSearchResultSet( + DBusMessage* aMsg, bool aInitialSearch) { + // Discard any existing search results. +@@ -179,7 +281,7 @@ + static void DispatchSearchResults( + RefPtr<nsGNOMEShellHistorySearchResult> aSearchResult, + nsCOMPtr<nsINavHistoryContainerResultNode> aHistResultContainer) { +- aSearchResult->SetSearchResultContainer(aHistResultContainer); ++ aSearchResult->ReceiveSearchResultContainer(aHistResultContainer); + } + + nsresult nsGNOMEShellHistoryService::QueryHistory( +@@ -242,7 +344,7 @@ + aIDKey = nsPrintfCString("%.2d:%s", aIndex, aUri.get()); + } + +-void nsGNOMEShellHistorySearchResult::SendDBusSearchResultReply() { ++void nsGNOMEShellHistorySearchResult::HandleSearchResultReply() { + MOZ_ASSERT(mReply); + + uint32_t childCount = 0; +@@ -254,6 +356,11 @@ + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iterArray); + + if (NS_SUCCEEDED(rv) && childCount > 0) { ++ // Obtain the favicon service and get the favicon for the specified page ++ nsCOMPtr<nsIFaviconService> favIconSvc( ++ do_GetService("@mozilla.org/browser/favicon-service;1")); ++ nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID)); ++ + if (childCount > MAX_SEARCH_RESULTS_NUM) { + childCount = MAX_SEARCH_RESULTS_NUM; + } +@@ -271,6 +378,12 @@ + nsAutoCString uri; + child->GetUri(uri); + ++ nsCOMPtr<nsIURI> iconIri; ++ ios->NewURI(uri, nullptr, nullptr, getter_AddRefs(iconIri)); ++ nsCOMPtr<nsIFaviconDataCallback> callback = ++ new AsyncFaviconDataReady(this, i, mTimeStamp); ++ favIconSvc->GetFaviconDataForPage(iconIri, callback, 0); ++ + nsAutoCString idKey; + DBusGetIDKeyForURI(i, uri, idKey); + +@@ -292,14 +405,36 @@ + mReply = nullptr; + } + +-void nsGNOMEShellHistorySearchResult::SetSearchResultContainer( ++void nsGNOMEShellHistorySearchResult::ReceiveSearchResultContainer( + nsCOMPtr<nsINavHistoryContainerResultNode> aHistResultContainer) { ++ // Propagate search results to nsGNOMEShellSearchProvider. ++ // SetSearchResult() checks this is up-to-date search (our time stamp matches ++ // latest requested search timestamp). + if (mSearchProvider->SetSearchResult(this)) { + mHistResultContainer = aHistResultContainer; +- SendDBusSearchResultReply(); ++ HandleSearchResultReply(); + } + } + ++void nsGNOMEShellHistorySearchResult::SetHistoryIcon(int aTimeStamp, ++ UniquePtr<uint8_t[]> aData, ++ int aWidth, int aHeight, ++ int aIconIndex) { ++ MOZ_ASSERT(mTimeStamp == aTimeStamp); ++ MOZ_RELEASE_ASSERT(aIconIndex < MAX_SEARCH_RESULTS_NUM); ++ mHistoryIcons[aIconIndex].Set(mTimeStamp, std::move(aData), aWidth, aHeight); ++} ++ ++GnomeHistoryIcon* nsGNOMEShellHistorySearchResult::GetHistoryIcon( ++ int aIconIndex) { ++ MOZ_RELEASE_ASSERT(aIconIndex < MAX_SEARCH_RESULTS_NUM); ++ if (mHistoryIcons[aIconIndex].GetTimeStamp() == mTimeStamp && ++ mHistoryIcons[aIconIndex].IsLoaded()) { ++ return mHistoryIcons + aIconIndex; ++ } ++ return nullptr; ++} ++ + nsGNOMEShellHistoryService* GetGNOMEShellHistoryService() { + static nsGNOMEShellHistoryService gGNOMEShellHistoryService; + return &gGNOMEShellHistoryService; + diff --git a/mozilla-1639197.patch b/mozilla-1639197.patch new file mode 100644 index 0000000..edb2664 --- /dev/null +++ b/mozilla-1639197.patch @@ -0,0 +1,15 @@ +diff --git a/browser/components/shell/nsGNOMEShellDBusHelper.cpp b/browser/components/shell/nsGNOMEShellDBusHelper.cpp +--- a/browser/components/shell/nsGNOMEShellDBusHelper.cpp ++++ b/browser/components/shell/nsGNOMEShellDBusHelper.cpp +@@ -285,7 +285,9 @@ + nsAutoCString gnomeSearchTitle; + if (GetGnomeSearchTitle(searchTerm.get(), gnomeSearchTitle)) { + appendStringDictionary(aIter, "name", gnomeSearchTitle.get()); +- appendStringDictionary(aIter, "gicon", "org.mozilla.Firefox"); ++ // TODO: When running on flatpak/snap we may need to use ++ // icon like org.mozilla.Firefox or so. ++ appendStringDictionary(aIter, "gicon", "firefox"); + } + } + + diff --git a/mozilla-gnome-shell-search-fixes.patch b/mozilla-gnome-shell-search-fixes.patch deleted file mode 100644 index 41a11e8..0000000 --- a/mozilla-gnome-shell-search-fixes.patch +++ /dev/null @@ -1,157 +0,0 @@ -diff -up firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp.gnome-shell-search-fixes firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp ---- firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp.gnome-shell-search-fixes 2020-04-07 08:01:50.587124776 +0200 -+++ firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp 2020-04-07 10:14:02.530380225 +0200 -@@ -26,6 +26,8 @@ - #include "nsIStringBundle.h" - #include "imgIContainer.h" - #include "imgITools.h" -+#include "nsNetCID.h" -+#include "nsIIOService.h" - - #include "mozilla/gfx/DataSurfaceHelpers.h" - -@@ -289,20 +291,12 @@ AsyncFaviconDataReady::OnComplete(nsIURI - } - - void nsGNOMEShellSearchProvider::ComposeSearchResultReply( -- DBusMessage* reply, const char* aSearchTerm) { -+ DBusMessage* reply, const char* aSearchTerm, bool aSearchOnly) { - uint32_t childCount = 0; -- nsresult rv = mHistResultContainer->GetChildCount(&childCount); -- if (NS_FAILED(rv) || childCount == 0) { -- return; -- } -- -- // Obtain the favicon service and get the favicon for the specified page -- nsCOMPtr<nsIFaviconService> favIconSvc( -- do_GetService("@mozilla.org/browser/favicon-service;1")); -- nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID)); -+ nsresult rv = NS_OK; - -- if (childCount > MAX_SEARCH_RESULTS_NUM) { -- childCount = MAX_SEARCH_RESULTS_NUM; -+ if (!aSearchOnly) { -+ nsresult rv = mHistResultContainer->GetChildCount(&childCount); - } - - DBusMessageIter iter; -@@ -310,30 +304,41 @@ void nsGNOMEShellSearchProvider::Compose - DBusMessageIter iterArray; - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iterArray); - -- for (uint32_t i = 0; i < childCount; i++) { -- nsCOMPtr<nsINavHistoryResultNode> child; -- mHistResultContainer->GetChild(i, getter_AddRefs(child)); -- if (NS_WARN_IF(NS_FAILED(rv))) { -- continue; -- } -- if (!IsHistoryResultNodeURI(child)) { -- continue; -+ if (NS_SUCCEEDED(rv) && childCount > 0) { -+ // Obtain the favicon service and get the favicon for the specified page -+ nsCOMPtr<nsIFaviconService> favIconSvc( -+ do_GetService("@mozilla.org/browser/favicon-service;1")); -+ nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID)); -+ -+ if (childCount > MAX_SEARCH_RESULTS_NUM) { -+ childCount = MAX_SEARCH_RESULTS_NUM; - } - -- nsAutoCString uri; -- child->GetUri(uri); -+ for (uint32_t i = 0; i < childCount; i++) { -+ nsCOMPtr<nsINavHistoryResultNode> child; -+ mHistResultContainer->GetChild(i, getter_AddRefs(child)); -+ if (NS_WARN_IF(NS_FAILED(rv))) { -+ continue; -+ } -+ if (!child || !IsHistoryResultNodeURI(child)) { -+ continue; -+ } - -- nsCOMPtr<nsIURI> iconIri; -- ios->NewURI(uri, nullptr, nullptr, getter_AddRefs(iconIri)); -- nsCOMPtr<nsIFaviconDataCallback> callback = -- new AsyncFaviconDataReady(this, i, mSearchSerial); -- favIconSvc->GetFaviconDataForPage(iconIri, callback, 0); -+ nsAutoCString uri; -+ child->GetUri(uri); - -- nsAutoCString idKey; -- GetIDKeyForURI(i, uri, idKey); -+ nsCOMPtr<nsIURI> iconIri; -+ ios->NewURI(uri, nullptr, nullptr, getter_AddRefs(iconIri)); -+ nsCOMPtr<nsIFaviconDataCallback> callback = -+ new AsyncFaviconDataReady(this, i, mSearchSerial); -+ favIconSvc->GetFaviconDataForPage(iconIri, callback, 0); - -- const char* id = idKey.get(); -- dbus_message_iter_append_basic(&iterArray, DBUS_TYPE_STRING, &id); -+ nsAutoCString idKey; -+ GetIDKeyForURI(i, uri, idKey); -+ -+ const char* id = idKey.get(); -+ dbus_message_iter_append_basic(&iterArray, DBUS_TYPE_STRING, &id); -+ } - } - - nsPrintfCString searchString("%s:%s", KEYWORD_SEARCH_STRING, aSearchTerm); -@@ -346,7 +351,7 @@ void nsGNOMEShellSearchProvider::Compose - DBusHandlerResult nsGNOMEShellSearchProvider::GetInitialResultSet( - DBusMessage* aMsg) { - DBusMessage* reply; -- char** stringArray; -+ char** stringArray = nullptr; - int elements; - - if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, -@@ -356,9 +361,10 @@ DBusHandlerResult nsGNOMEShellSearchProv - } else { - reply = dbus_message_new_method_return(aMsg); - nsresult rv = NewHistorySearch(stringArray[0]); -- if (NS_SUCCEEDED(rv)) { -- ComposeSearchResultReply(reply, stringArray[0]); -- } -+ ComposeSearchResultReply(reply, stringArray[0], -+ /* search only */ NS_FAILED(rv)); -+ } -+ if (stringArray) { - dbus_free_string_array(stringArray); - } - -@@ -384,9 +390,8 @@ DBusHandlerResult nsGNOMEShellSearchProv - } else { - reply = dbus_message_new_method_return(aMsg); - nsresult rv = NewHistorySearch(stringArray[0]); -- if (NS_SUCCEEDED(rv)) { -- ComposeSearchResultReply(reply, stringArray[0]); -- } -+ ComposeSearchResultReply(reply, stringArray[0], -+ /* search only */ NS_FAILED(rv)); - } - - if (unusedArray) { -@@ -556,6 +561,10 @@ void nsGNOMEShellSearchProvider::LaunchW - nsCOMPtr<nsINavHistoryResultNode> child; - mHistResultContainer->GetChild(keyIndex, getter_AddRefs(child)); - -+ if (!child) { -+ return; -+ } -+ - nsAutoCString uri; - nsresult rv = child->GetUri(uri); - if (NS_FAILED(rv)) { -diff -up firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.h.gnome-shell-search-fixes firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.h ---- firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.h.gnome-shell-search-fixes 2020-04-07 08:01:50.587124776 +0200 -+++ firefox-75.0/browser/components/shell/nsGNOMEShellSearchProvider.h 2020-04-07 09:56:30.857553820 +0200 -@@ -70,7 +70,8 @@ class nsGNOMEShellSearchProvider : publi - bool IsHistoryResultNodeURI(nsINavHistoryResultNode* aHistoryNode); - void AppendResultID(DBusMessageIter* aIter, const char* aID); - void AppendSearchID(DBusMessageIter* aIter, const char* aID); -- void ComposeSearchResultReply(DBusMessage* aReply, const char* aSearchTerm); -+ void ComposeSearchResultReply(DBusMessage* aReply, const char* aSearchTerm, -+ bool aSearchOnly); - void LaunchWithID(const char* aID, uint32_t aTimeStamp); - void LaunchWithAllResults(uint32_t aTimeStamp); - diff --git a/mozilla-gnome-shell-search-provider-icons.patch b/mozilla-gnome-shell-search-provider-icons.patch deleted file mode 100644 index fd9dbe8..0000000 --- a/mozilla-gnome-shell-search-provider-icons.patch +++ /dev/null @@ -1,453 +0,0 @@ -changeset: 504680:441b26f2d4f4 -parent: 504674:5a55ac856fc4 -user: Martin Stransky <stransky@redhat.com> -date: Mon Dec 02 12:21:08 2019 +0100 -files: browser/components/shell/nsGNOMEShellSearchProvider.cpp browser/components/shell/nsGNOMEShellSearchProvider.h -description: -Bug 1239694 Use history icons with Gnome shell search provider, r?jhorak - -Differential Revision: https://phabricator.services.mozilla.com/D55434 - - -diff --git a/browser/components/shell/nsGNOMEShellSearchProvider.cpp b/browser/components/shell/nsGNOMEShellSearchProvider.cpp ---- a/browser/components/shell/nsGNOMEShellSearchProvider.cpp -+++ b/browser/components/shell/nsGNOMEShellSearchProvider.cpp -@@ -19,21 +19,27 @@ - #include "nsPrintfCString.h" - #include "nsCOMPtr.h" - #include "nsGTKToolkit.h" - #include "nsINavHistoryService.h" - #include "nsToolkitCompsCID.h" - #include "nsIFaviconService.h" - #include "RemoteUtils.h" - #include "nsIStringBundle.h" -+#include "imgIContainer.h" -+#include "imgITools.h" -+ -+#include "mozilla/gfx/DataSurfaceHelpers.h" - - #include <dbus/dbus.h> - #include <dbus/dbus-glib-lowlevel.h> - --#define MAX_SEARCH_RESULTS_NUM 9 -+using namespace mozilla; -+using namespace mozilla::gfx; -+ - #define KEYWORD_SEARCH_STRING "special:search" - #define KEYWORD_SEARCH_STRING_LEN 14 - - #define DBUS_BUS_NAME "org.mozilla.Firefox.SearchProvider" - #define DBUS_OBJECT_PATH "/org/mozilla/Firefox/SearchProvider" - - static const char* introspect_template = - "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection " -@@ -81,17 +87,35 @@ DBusHandlerResult nsGNOMEShellSearchProv - DBUS_TYPE_INVALID); - - dbus_connection_send(mConnection, reply, nullptr); - dbus_message_unref(reply); - - return DBUS_HANDLER_RESULT_HANDLED; - } - --nsresult nsGNOMEShellSearchProvider::QueryHistory(const char* aSearchTerm) { -+nsGNOMEShellSearchProvider::nsGNOMEShellSearchProvider() -+ : mConnection(nullptr), mSearchSerial(0) { -+ memset(mHistoryIcons, 0, sizeof(mHistoryIcons)); -+} -+ -+void nsGNOMEShellSearchProvider::SetHistoryIcon(int aSearchSerial, -+ UniquePtr<uint8_t[]> aData, -+ int aWidth, int aHeight, -+ int aIconIndex) { -+ MOZ_ASSERT(mSearchSerial == aSearchSerial); -+ MOZ_ASSERT(aIconIndex < MAX_SEARCH_RESULTS_NUM); -+ mHistoryIcons[aIconIndex].Set(aSearchSerial, std::move(aData), aWidth, -+ aHeight); -+} -+ -+nsresult nsGNOMEShellSearchProvider::NewHistorySearch(const char* aSearchTerm) { -+ // Initialize new search which invalidates all preview ones -+ mSearchSerial++; -+ - nsresult rv; - nsCOMPtr<nsINavHistoryQuery> histQuery; - rv = mHistoryService->GetNewQuery(getter_AddRefs(histQuery)); - NS_ENSURE_SUCCESS(rv, rv); - - nsAutoCString searchTerm(aSearchTerm); - rv = histQuery->SetSearchTerms(NS_ConvertUTF8toUTF16(searchTerm)); - NS_ENSURE_SUCCESS(rv, rv); -@@ -165,24 +189,123 @@ void nsGNOMEShellSearchProvider::GetIDKe - - int nsGNOMEShellSearchProvider::GetIndexFromIDKey(const char* aIDKey) { - // ID is NN:URL where NN is index to our current history - // result container. - char tmp[] = {aIDKey[0], aIDKey[1], '\0'}; - return atoi(tmp); - } - -+class AsyncFaviconDataReady final : public nsIFaviconDataCallback { -+ public: -+ NS_DECL_ISUPPORTS -+ NS_DECL_NSIFAVICONDATACALLBACK -+ -+ AsyncFaviconDataReady(nsGNOMEShellSearchProvider* aSearchProvider, -+ int aIconIndex, int aSearchSerial) -+ : mSearchProvider(aSearchProvider), -+ mIconIndex(aIconIndex), -+ mSearchSerial(aSearchSerial){}; -+ -+ private: -+ ~AsyncFaviconDataReady() {} -+ -+ nsGNOMEShellSearchProvider* mSearchProvider; -+ int mIconIndex; -+ int mSearchSerial; -+}; -+ -+NS_IMPL_ISUPPORTS(AsyncFaviconDataReady, nsIFaviconDataCallback) -+ -+// Inspired by SurfaceToPackedBGRA -+static UniquePtr<uint8_t[]> SurfaceToPackedRGBA(DataSourceSurface* aSurface) { -+ IntSize size = aSurface->GetSize(); -+ CheckedInt<size_t> bufferSize = -+ CheckedInt<size_t>(size.width * 4) * CheckedInt<size_t>(size.height); -+ if (!bufferSize.isValid()) { -+ return nullptr; -+ } -+ UniquePtr<uint8_t[]> imageBuffer(new (std::nothrow) -+ uint8_t[bufferSize.value()]); -+ if (!imageBuffer) { -+ return nullptr; -+ } -+ -+ DataSourceSurface::MappedSurface map; -+ if (!aSurface->Map(DataSourceSurface::MapType::READ, &map)) { -+ return nullptr; -+ } -+ -+ // Convert BGRA to RGBA -+ uint32_t* aSrc = (uint32_t*)map.mData; -+ uint32_t* aDst = (uint32_t*)imageBuffer.get(); -+ for (int i = 0; i < size.width * size.height; i++, aDst++, aSrc++) { -+ *aDst = *aSrc & 0xff00ff00; -+ *aDst |= (*aSrc & 0xff) << 16; -+ *aDst |= (*aSrc & 0xff0000) >> 16; -+ } -+ -+ aSurface->Unmap(); -+ -+ return imageBuffer; -+} -+ -+NS_IMETHODIMP -+AsyncFaviconDataReady::OnComplete(nsIURI* aFaviconURI, uint32_t aDataLen, -+ const uint8_t* aData, -+ const nsACString& aMimeType, -+ uint16_t aWidth) { -+ // This is a callback from some previous search so we don't want it -+ if (mSearchSerial != mSearchProvider->GetSearchSerial() || !aData || -+ !aDataLen) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ // Decode the image from the format it was returned to us in (probably PNG) -+ nsCOMPtr<imgIContainer> container; -+ nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1"); -+ nsresult rv = imgtool->DecodeImageFromBuffer( -+ reinterpret_cast<const char*>(aData), aDataLen, aMimeType, -+ getter_AddRefs(container)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ RefPtr<SourceSurface> surface = container->GetFrame( -+ imgIContainer::FRAME_FIRST, -+ imgIContainer::FLAG_SYNC_DECODE | imgIContainer::FLAG_ASYNC_NOTIFY); -+ -+ if (!surface || surface->GetFormat() != SurfaceFormat::B8G8R8A8) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ // Allocate a new buffer that we own. -+ RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface(); -+ UniquePtr<uint8_t[]> data = SurfaceToPackedRGBA(dataSurface); -+ if (!data) { -+ return NS_ERROR_OUT_OF_MEMORY; -+ } -+ -+ mSearchProvider->SetHistoryIcon(mSearchSerial, std::move(data), -+ surface->GetSize().width, -+ surface->GetSize().height, mIconIndex); -+ return NS_OK; -+} -+ - void nsGNOMEShellSearchProvider::ComposeSearchResultReply( - DBusMessage* reply, const char* aSearchTerm) { - uint32_t childCount = 0; - nsresult rv = mHistResultContainer->GetChildCount(&childCount); - if (NS_FAILED(rv) || childCount == 0) { - return; - } - -+ // Obtain the favicon service and get the favicon for the specified page -+ nsCOMPtr<nsIFaviconService> favIconSvc( -+ do_GetService("@mozilla.org/browser/favicon-service;1")); -+ nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID)); -+ - if (childCount > MAX_SEARCH_RESULTS_NUM) { - childCount = MAX_SEARCH_RESULTS_NUM; - } - - DBusMessageIter iter; - dbus_message_iter_init_append(reply, &iter); - DBusMessageIter iterArray; - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iterArray); -@@ -195,16 +318,22 @@ void nsGNOMEShellSearchProvider::Compose - } - if (!IsHistoryResultNodeURI(child)) { - continue; - } - - nsAutoCString uri; - child->GetUri(uri); - -+ nsCOMPtr<nsIURI> iconIri; -+ ios->NewURI(uri, nullptr, nullptr, getter_AddRefs(iconIri)); -+ nsCOMPtr<nsIFaviconDataCallback> callback = -+ new AsyncFaviconDataReady(this, i, mSearchSerial); -+ favIconSvc->GetFaviconDataForPage(iconIri, callback, 0); -+ - nsAutoCString idKey; - GetIDKeyForURI(i, uri, idKey); - - const char* id = idKey.get(); - dbus_message_iter_append_basic(&iterArray, DBUS_TYPE_STRING, &id); - } - - nsPrintfCString searchString("%s:%s", KEYWORD_SEARCH_STRING, aSearchTerm); -@@ -221,17 +350,17 @@ DBusHandlerResult nsGNOMEShellSearchProv - int elements; - - if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &stringArray, &elements, DBUS_TYPE_INVALID) || - elements == 0) { - reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); - } else { - reply = dbus_message_new_method_return(aMsg); -- nsresult rv = QueryHistory(stringArray[0]); -+ nsresult rv = NewHistorySearch(stringArray[0]); - if (NS_SUCCEEDED(rv)) { - ComposeSearchResultReply(reply, stringArray[0]); - } - dbus_free_string_array(stringArray); - } - - dbus_connection_send(mConnection, reply, nullptr); - dbus_message_unref(reply); -@@ -249,17 +378,17 @@ DBusHandlerResult nsGNOMEShellSearchProv - if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, - &unusedArray, &unusedNum, DBUS_TYPE_ARRAY, - DBUS_TYPE_STRING, &stringArray, &elements, - DBUS_TYPE_INVALID) || - elements == 0) { - reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); - } else { - reply = dbus_message_new_method_return(aMsg); -- nsresult rv = QueryHistory(stringArray[0]); -+ nsresult rv = NewHistorySearch(stringArray[0]); - if (NS_SUCCEEDED(rv)) { - ComposeSearchResultReply(reply, stringArray[0]); - } - } - - if (unusedArray) { - dbus_free_string_array(unusedArray); - } -@@ -280,45 +409,88 @@ static void appendStringDictionary(DBusM - &iterDict); - dbus_message_iter_append_basic(&iterDict, DBUS_TYPE_STRING, &aKey); - dbus_message_iter_open_container(&iterDict, DBUS_TYPE_VARIANT, "s", &iterVar); - dbus_message_iter_append_basic(&iterVar, DBUS_TYPE_STRING, &aValue); - dbus_message_iter_close_container(&iterDict, &iterVar); - dbus_message_iter_close_container(aIter, &iterDict); - } - -+/* -+ "icon-data": a tuple of type (iiibiiay) describing a pixbuf with width, -+ height, rowstride, has-alpha, -+ bits-per-sample, channels, -+ image data -+*/ -+void GnomeHistoryIcon::AppendIcon(DBusMessageIter* aIter) { -+ DBusMessageIter iterDict, iterVar, iterStruct; -+ dbus_message_iter_open_container(aIter, DBUS_TYPE_DICT_ENTRY, nullptr, -+ &iterDict); -+ const char* key = "icon-data"; -+ dbus_message_iter_append_basic(&iterDict, DBUS_TYPE_STRING, &key); -+ dbus_message_iter_open_container(&iterDict, DBUS_TYPE_VARIANT, "(iiibiiay)", -+ &iterVar); -+ dbus_message_iter_open_container(&iterVar, DBUS_TYPE_STRUCT, nullptr, -+ &iterStruct); -+ -+ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &mWidth); -+ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &mHeight); -+ int rowstride = mWidth * 4; -+ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &rowstride); -+ int hasAlpha = true; -+ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_BOOLEAN, &hasAlpha); -+ int bitsPerSample = 8; -+ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &bitsPerSample); -+ int channels = 4; -+ dbus_message_iter_append_basic(&iterStruct, DBUS_TYPE_INT32, &channels); -+ -+ DBusMessageIter iterArray; -+ dbus_message_iter_open_container(&iterStruct, DBUS_TYPE_ARRAY, "y", -+ &iterArray); -+ unsigned char* array = mData.get(); -+ dbus_message_iter_append_fixed_array(&iterArray, DBUS_TYPE_BYTE, &array, -+ mWidth * mHeight * 4); -+ dbus_message_iter_close_container(&iterStruct, &iterArray); -+ -+ dbus_message_iter_close_container(&iterVar, &iterStruct); -+ dbus_message_iter_close_container(&iterDict, &iterVar); -+ dbus_message_iter_close_container(aIter, &iterDict); -+} -+ - /* We can return those fields at GetResultMetas: - "id": the result ID - "name": the display name for the result - "icon": a serialized GIcon (see g_icon_serialize()), or alternatively, - "gicon": a textual representation of a GIcon (see g_icon_to_string()), - or alternativly, - "icon-data": a tuple of type (iiibiiay) describing a pixbuf with width, - height, rowstride, has-alpha, bits-per-sample, and image data - "description": an optional short description (1-2 lines) - */ - void nsGNOMEShellSearchProvider::AppendResultID(DBusMessageIter* aIter, - const char* aID) { -+ int index = GetIndexFromIDKey(aID); - nsCOMPtr<nsINavHistoryResultNode> child; -- mHistResultContainer->GetChild(GetIndexFromIDKey(aID), getter_AddRefs(child)); -+ mHistResultContainer->GetChild(index, getter_AddRefs(child)); - nsAutoCString title; -- if (NS_FAILED(child->GetTitle(title))) { -- return; -- } -+ nsAutoCString uri; -+ child->GetTitle(title); -+ child->GetUri(uri); - -- if (title.IsEmpty()) { -- if (NS_FAILED(child->GetUri(title)) || title.IsEmpty()) { -- return; -- } -- } -+ const char* titleStr = !(title.IsEmpty()) ? title.get() : uri.get(); -+ const char* descStr = uri.get(); - -- const char* titleStr = title.get(); - appendStringDictionary(aIter, "id", aID); - appendStringDictionary(aIter, "name", titleStr); -- appendStringDictionary(aIter, "gicon", "text-html"); -+ appendStringDictionary(aIter, "description", descStr); -+ if (mHistoryIcons[index].GetSearchSerial() == mSearchSerial) { -+ mHistoryIcons[index].AppendIcon(aIter); -+ } else { -+ appendStringDictionary(aIter, "gicon", "text-html"); -+ } - } - - void nsGNOMEShellSearchProvider::AppendSearchID(DBusMessageIter* aIter, - const char* aID) { - if (strlen(aID) < KEYWORD_SEARCH_STRING_LEN + 2) { - return; - } - appendStringDictionary(aIter, "id", KEYWORD_SEARCH_STRING); -diff --git a/browser/components/shell/nsGNOMEShellSearchProvider.h b/browser/components/shell/nsGNOMEShellSearchProvider.h ---- a/browser/components/shell/nsGNOMEShellSearchProvider.h -+++ b/browser/components/shell/nsGNOMEShellSearchProvider.h -@@ -7,49 +7,81 @@ - - #ifndef __nsGNOMEShellSearchProvider_h__ - #define __nsGNOMEShellSearchProvider_h__ - - #include "mozilla/DBusHelpers.h" - #include "nsINavHistoryService.h" - #include "nsUnixRemoteServer.h" - #include "nsCOMPtr.h" -+#include "mozilla/UniquePtr.h" -+ -+#define MAX_SEARCH_RESULTS_NUM 9 -+ -+class GnomeHistoryIcon { -+ public: -+ GnomeHistoryIcon() : mSearchSerial(-1), mWidth(0), mHeight(0){}; -+ -+ // From which search is this icon -+ void Set(int aSearchSerial, mozilla::UniquePtr<uint8_t[]> aData, int aWidth, -+ int aHeight) { -+ mSearchSerial = aSearchSerial; -+ mWidth = aWidth; -+ mHeight = aHeight; -+ mData = std::move(aData); -+ } -+ -+ int GetSearchSerial() { return mSearchSerial; } -+ void AppendIcon(DBusMessageIter* aIter); -+ -+ private: -+ int mSearchSerial; -+ mozilla::UniquePtr<uint8_t[]> mData; -+ int mWidth; -+ int mHeight; -+}; - - class nsGNOMEShellSearchProvider : public nsUnixRemoteServer { - public: -- nsGNOMEShellSearchProvider() : mConnection(nullptr) {} -+ nsGNOMEShellSearchProvider(); - ~nsGNOMEShellSearchProvider() { Shutdown(); } - - nsresult Startup(); - void Shutdown(); - - DBusHandlerResult HandleDBusMessage(DBusConnection* aConnection, - DBusMessage* msg); - void UnregisterDBusInterface(DBusConnection* aConnection); - -+ int GetSearchSerial() { return mSearchSerial; } -+ void SetHistoryIcon(int aSearchSerial, mozilla::UniquePtr<uint8_t[]> aData, -+ int aWidth, int aHeight, int aIconIndex); -+ - private: - DBusHandlerResult Introspect(DBusMessage* msg); - - DBusHandlerResult GetInitialResultSet(DBusMessage* msg); - DBusHandlerResult GetSubsearchResultSet(DBusMessage* msg); - DBusHandlerResult GetResultMetas(DBusMessage* msg); - DBusHandlerResult ActivateResult(DBusMessage* msg); - DBusHandlerResult LaunchSearch(DBusMessage* msg); - -- nsresult QueryHistory(const char* aSearchTerm); -+ nsresult NewHistorySearch(const char* aSearchTerm); - void GetIDKeyForURI(int aIndex, nsAutoCString& aUri, nsAutoCString& aIDKey); - int GetIndexFromIDKey(const char* aIDKey); - bool IsHistoryResultNodeURI(nsINavHistoryResultNode* aHistoryNode); - void AppendResultID(DBusMessageIter* aIter, const char* aID); - void AppendSearchID(DBusMessageIter* aIter, const char* aID); - void ComposeSearchResultReply(DBusMessage* aReply, const char* aSearchTerm); - void LaunchWithID(const char* aID, uint32_t aTimeStamp); - void LaunchWithAllResults(uint32_t aTimeStamp); - - // The connection is owned by DBus library - RefPtr<DBusConnection> mConnection; - nsCOMPtr<nsINavHistoryContainerResultNode> mHistResultContainer; - nsCOMPtr<nsINavHistoryService> mHistoryService; - nsAutoCStringN<32> mSearchTerm; - nsAutoCString mGnomeSearchTitle; -+ int mSearchSerial; -+ GnomeHistoryIcon mHistoryIcons[MAX_SEARCH_RESULTS_NUM]; - }; - - #endif // __nsGNOMEShellSearchProvider_h__ - diff --git a/mozilla-gnome-shell-search-provider.patch b/mozilla-gnome-shell-search-provider.patch deleted file mode 100644 index 4660128..0000000 --- a/mozilla-gnome-shell-search-provider.patch +++ /dev/null @@ -1,786 +0,0 @@ -diff -up firefox-73.0/browser/components/shell/moz.build.gnome-shell-search-provider firefox-73.0/browser/components/shell/moz.build ---- firefox-73.0/browser/components/shell/moz.build.gnome-shell-search-provider 2020-02-07 22:12:59.000000000 +0100 -+++ firefox-73.0/browser/components/shell/moz.build 2020-02-11 09:03:31.638803105 +0100 -@@ -34,6 +34,11 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gt - SOURCES += [ - 'nsGNOMEShellService.cpp', - ] -+ if CONFIG['MOZ_ENABLE_DBUS']: -+ SOURCES += [ -+ 'nsGNOMEShellSearchProvider.cpp', -+ ] -+ - elif CONFIG['OS_ARCH'] == 'WINNT': - XPIDL_SOURCES += [ - 'nsIWindowsShellService.idl', -@@ -60,6 +65,8 @@ for var in ('MOZ_APP_NAME', 'MOZ_APP_VER - DEFINES[var] = '"%s"' % CONFIG[var] - - CXXFLAGS += CONFIG['TK_CFLAGS'] -+if CONFIG['MOZ_ENABLE_DBUS']: -+ CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] - - with Files('**'): - BUG_COMPONENT = ('Firefox', 'Shell Integration') -diff -up firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp.gnome-shell-search-provider firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp ---- firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp.gnome-shell-search-provider 2020-02-11 09:00:59.350512802 +0100 -+++ firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.cpp 2020-02-11 09:00:59.350512802 +0100 -@@ -0,0 +1,621 @@ -+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* vim:expandtab:shiftwidth=2:tabstop=2: -+ */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include "nsGNOMEShellSearchProvider.h" -+ -+#include "nsIBaseWindow.h" -+#include "nsIDocShell.h" -+#include "nsPIDOMWindow.h" -+#include "mozilla/ModuleUtils.h" -+#include "mozilla/Base64.h" -+#include "nsIServiceManager.h" -+#include "nsIWidget.h" -+#include "nsIAppShellService.h" -+#include "nsAppShellCID.h" -+#include "nsPrintfCString.h" -+#include "nsCOMPtr.h" -+#include "nsGTKToolkit.h" -+#include "nsINavHistoryService.h" -+#include "nsToolkitCompsCID.h" -+#include "nsIFaviconService.h" -+#include "RemoteUtils.h" -+#include "nsIStringBundle.h" -+ -+#include <dbus/dbus.h> -+#include <dbus/dbus-glib-lowlevel.h> -+ -+#define MAX_SEARCH_RESULTS_NUM 9 -+#define KEYWORD_SEARCH_STRING "special:search" -+#define KEYWORD_SEARCH_STRING_LEN 14 -+ -+#define DBUS_BUS_NAME "org.mozilla.Firefox.SearchProvider" -+#define DBUS_OBJECT_PATH "/org/mozilla/Firefox/SearchProvider" -+ -+static const char* introspect_template = -+ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection " -+ "1.0//EN\"\n" -+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\";>\n" -+ "<node>\n" -+ " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" -+ " <method name=\"Introspect\">\n" -+ " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n" -+ " </method>\n" -+ " </interface>\n" -+ " <interface name=\"org.gnome.Shell.SearchProvider2\">\n" -+ " <method name=\"GetInitialResultSet\">\n" -+ " <arg type=\"as\" name=\"terms\" direction=\"in\" />\n" -+ " <arg type=\"as\" name=\"results\" direction=\"out\" />\n" -+ " </method>\n" -+ " <method name=\"GetSubsearchResultSet\">\n" -+ " <arg type=\"as\" name=\"previous_results\" direction=\"in\" />\n" -+ " <arg type=\"as\" name=\"terms\" direction=\"in\" />\n" -+ " <arg type=\"as\" name=\"results\" direction=\"out\" />\n" -+ " </method>\n" -+ " <method name=\"GetResultMetas\">\n" -+ " <arg type=\"as\" name=\"identifiers\" direction=\"in\" />\n" -+ " <arg type=\"aa{sv}\" name=\"metas\" direction=\"out\" />\n" -+ " </method>\n" -+ " <method name=\"ActivateResult\">\n" -+ " <arg type=\"s\" name=\"identifier\" direction=\"in\" />\n" -+ " <arg type=\"as\" name=\"terms\" direction=\"in\" />\n" -+ " <arg type=\"u\" name=\"timestamp\" direction=\"in\" />\n" -+ " </method>\n" -+ " <method name=\"LaunchSearch\">\n" -+ " <arg type=\"as\" name=\"terms\" direction=\"in\" />\n" -+ " <arg type=\"u\" name=\"timestamp\" direction=\"in\" />\n" -+ " </method>\n" -+ "</interface>\n" -+ "</node>\n"; -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::Introspect(DBusMessage* aMsg) { -+ DBusMessage* reply; -+ -+ reply = dbus_message_new_method_return(aMsg); -+ if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; -+ -+ dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspect_template, -+ DBUS_TYPE_INVALID); -+ -+ dbus_connection_send(mConnection, reply, nullptr); -+ dbus_message_unref(reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+nsresult nsGNOMEShellSearchProvider::QueryHistory(const char* aSearchTerm) { -+ nsresult rv; -+ nsCOMPtr<nsINavHistoryQuery> histQuery; -+ rv = mHistoryService->GetNewQuery(getter_AddRefs(histQuery)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ nsAutoCString searchTerm(aSearchTerm); -+ rv = histQuery->SetSearchTerms(NS_ConvertUTF8toUTF16(searchTerm)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ nsCOMPtr<nsINavHistoryQueryOptions> histQueryOpts; -+ rv = mHistoryService->GetNewQueryOptions(getter_AddRefs(histQueryOpts)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ // We want to get the URIs for every item in the user's history with the -+ // given host -+ rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ rv = histQueryOpts->SetSortingMode( -+ nsINavHistoryQueryOptions::SORT_BY_VISITCOUNT_DESCENDING); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ rv = histQueryOpts->SetMaxResults(MAX_SEARCH_RESULTS_NUM); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ // We only search history, because searching both bookmarks and history -+ // is not supported, and history tends to be more comprehensive. -+ rv = histQueryOpts->SetQueryType( -+ nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ nsCOMPtr<nsINavHistoryResult> histResult; -+ rv = mHistoryService->ExecuteQuery(histQuery, histQueryOpts, -+ getter_AddRefs(histResult)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ // Delete former search results -+ mHistResultContainer = nullptr; -+ -+ rv = histResult->GetRoot(getter_AddRefs(mHistResultContainer)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ rv = mHistResultContainer->SetContainerOpen(true); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ uint32_t childCount = 0; -+ rv = mHistResultContainer->GetChildCount(&childCount); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ return childCount != 0 ? NS_OK : NS_ERROR_FAILURE; -+} -+ -+bool nsGNOMEShellSearchProvider::IsHistoryResultNodeURI( -+ nsINavHistoryResultNode* aHistoryNode) { -+ uint32_t type; -+ nsresult rv = aHistoryNode->GetType(&type); -+ if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) -+ return false; -+ -+ nsAutoCString title; -+ rv = aHistoryNode->GetTitle(title); -+ if (NS_SUCCEEDED(rv) && !title.IsEmpty()) { -+ return true; -+ } -+ -+ rv = aHistoryNode->GetUri(title); -+ return NS_SUCCEEDED(rv) && !title.IsEmpty(); -+} -+ -+void nsGNOMEShellSearchProvider::GetIDKeyForURI(int aIndex, nsAutoCString& aUri, -+ nsAutoCString& aIDKey) { -+ // Compose ID as NN:URL where NN is index to our current history -+ // result container. -+ aIDKey = nsPrintfCString("%.2d:%s", aIndex, aUri.get()); -+} -+ -+int nsGNOMEShellSearchProvider::GetIndexFromIDKey(const char* aIDKey) { -+ // ID is NN:URL where NN is index to our current history -+ // result container. -+ char tmp[] = {aIDKey[0], aIDKey[1], '\0'}; -+ return atoi(tmp); -+} -+ -+void nsGNOMEShellSearchProvider::ComposeSearchResultReply( -+ DBusMessage* reply, const char* aSearchTerm) { -+ uint32_t childCount = 0; -+ nsresult rv = mHistResultContainer->GetChildCount(&childCount); -+ if (NS_FAILED(rv) || childCount == 0) { -+ return; -+ } -+ -+ if (childCount > MAX_SEARCH_RESULTS_NUM) { -+ childCount = MAX_SEARCH_RESULTS_NUM; -+ } -+ -+ DBusMessageIter iter; -+ dbus_message_iter_init_append(reply, &iter); -+ DBusMessageIter iterArray; -+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iterArray); -+ -+ for (uint32_t i = 0; i < childCount; i++) { -+ nsCOMPtr<nsINavHistoryResultNode> child; -+ mHistResultContainer->GetChild(i, getter_AddRefs(child)); -+ if (NS_WARN_IF(NS_FAILED(rv))) { -+ continue; -+ } -+ if (!IsHistoryResultNodeURI(child)) { -+ continue; -+ } -+ -+ nsAutoCString uri; -+ child->GetUri(uri); -+ -+ nsAutoCString idKey; -+ GetIDKeyForURI(i, uri, idKey); -+ -+ const char* id = idKey.get(); -+ dbus_message_iter_append_basic(&iterArray, DBUS_TYPE_STRING, &id); -+ } -+ -+ nsPrintfCString searchString("%s:%s", KEYWORD_SEARCH_STRING, aSearchTerm); -+ const char* search = searchString.get(); -+ dbus_message_iter_append_basic(&iterArray, DBUS_TYPE_STRING, &search); -+ -+ dbus_message_iter_close_container(&iter, &iterArray); -+} -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::GetInitialResultSet( -+ DBusMessage* aMsg) { -+ DBusMessage* reply; -+ char** stringArray; -+ int elements; -+ -+ if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, -+ &stringArray, &elements, DBUS_TYPE_INVALID) || -+ elements == 0) { -+ reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); -+ } else { -+ reply = dbus_message_new_method_return(aMsg); -+ nsresult rv = QueryHistory(stringArray[0]); -+ if (NS_SUCCEEDED(rv)) { -+ ComposeSearchResultReply(reply, stringArray[0]); -+ } -+ dbus_free_string_array(stringArray); -+ } -+ -+ dbus_connection_send(mConnection, reply, nullptr); -+ dbus_message_unref(reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::GetSubsearchResultSet( -+ DBusMessage* aMsg) { -+ DBusMessage* reply; -+ -+ char **unusedArray = nullptr, **stringArray = nullptr; -+ int unusedNum, elements; -+ -+ if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, -+ &unusedArray, &unusedNum, DBUS_TYPE_ARRAY, -+ DBUS_TYPE_STRING, &stringArray, &elements, -+ DBUS_TYPE_INVALID) || -+ elements == 0) { -+ reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); -+ } else { -+ reply = dbus_message_new_method_return(aMsg); -+ nsresult rv = QueryHistory(stringArray[0]); -+ if (NS_SUCCEEDED(rv)) { -+ ComposeSearchResultReply(reply, stringArray[0]); -+ } -+ } -+ -+ if (unusedArray) { -+ dbus_free_string_array(unusedArray); -+ } -+ if (stringArray) { -+ dbus_free_string_array(stringArray); -+ } -+ -+ dbus_connection_send(mConnection, reply, nullptr); -+ dbus_message_unref(reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+static void appendStringDictionary(DBusMessageIter* aIter, const char* aKey, -+ const char* aValue) { -+ DBusMessageIter iterDict, iterVar; -+ dbus_message_iter_open_container(aIter, DBUS_TYPE_DICT_ENTRY, nullptr, -+ &iterDict); -+ dbus_message_iter_append_basic(&iterDict, DBUS_TYPE_STRING, &aKey); -+ dbus_message_iter_open_container(&iterDict, DBUS_TYPE_VARIANT, "s", &iterVar); -+ dbus_message_iter_append_basic(&iterVar, DBUS_TYPE_STRING, &aValue); -+ dbus_message_iter_close_container(&iterDict, &iterVar); -+ dbus_message_iter_close_container(aIter, &iterDict); -+} -+ -+/* We can return those fields at GetResultMetas: -+ "id": the result ID -+ "name": the display name for the result -+ "icon": a serialized GIcon (see g_icon_serialize()), or alternatively, -+ "gicon": a textual representation of a GIcon (see g_icon_to_string()), -+ or alternativly, -+ "icon-data": a tuple of type (iiibiiay) describing a pixbuf with width, -+ height, rowstride, has-alpha, bits-per-sample, and image data -+ "description": an optional short description (1-2 lines) -+*/ -+void nsGNOMEShellSearchProvider::AppendResultID(DBusMessageIter* aIter, -+ const char* aID) { -+ nsCOMPtr<nsINavHistoryResultNode> child; -+ mHistResultContainer->GetChild(GetIndexFromIDKey(aID), getter_AddRefs(child)); -+ nsAutoCString title; -+ if (NS_FAILED(child->GetTitle(title))) { -+ return; -+ } -+ -+ if (title.IsEmpty()) { -+ if (NS_FAILED(child->GetUri(title)) || title.IsEmpty()) { -+ return; -+ } -+ } -+ -+ const char* titleStr = title.get(); -+ appendStringDictionary(aIter, "id", aID); -+ appendStringDictionary(aIter, "name", titleStr); -+ appendStringDictionary(aIter, "gicon", "text-html"); -+} -+ -+void nsGNOMEShellSearchProvider::AppendSearchID(DBusMessageIter* aIter, -+ const char* aID) { -+ if (strlen(aID) < KEYWORD_SEARCH_STRING_LEN + 2) { -+ return; -+ } -+ appendStringDictionary(aIter, "id", KEYWORD_SEARCH_STRING); -+ mSearchTerm = nsAutoCStringN<32>(aID + KEYWORD_SEARCH_STRING_LEN + 1); -+ nsPrintfCString searchString(mGnomeSearchTitle.get(), mSearchTerm.get()); -+ appendStringDictionary(aIter, "name", searchString.get()); -+ appendStringDictionary(aIter, "gicon", "org.mozilla.Firefox"); -+} -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::GetResultMetas( -+ DBusMessage* aMsg) { -+ DBusMessage* reply; -+ char** stringArray; -+ int elements; -+ -+ if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, -+ &stringArray, &elements, DBUS_TYPE_INVALID) || -+ elements == 0) { -+ reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); -+ } else { -+ reply = dbus_message_new_method_return(aMsg); -+ -+ DBusMessageIter iter; -+ dbus_message_iter_init_append(reply, &iter); -+ DBusMessageIter iterArray; -+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "a{sv}", -+ &iterArray); -+ -+ DBusMessageIter iterArray2; -+ for (int i = 0; i < elements; i++) { -+ dbus_message_iter_open_container(&iterArray, DBUS_TYPE_ARRAY, "{sv}", -+ &iterArray2); -+ if (strncmp(stringArray[i], KEYWORD_SEARCH_STRING, -+ KEYWORD_SEARCH_STRING_LEN) == 0) { -+ AppendSearchID(&iterArray2, stringArray[i]); -+ } else { -+ AppendResultID(&iterArray2, stringArray[i]); -+ } -+ dbus_message_iter_close_container(&iterArray, &iterArray2); -+ } -+ -+ dbus_message_iter_close_container(&iter, &iterArray); -+ dbus_free_string_array(stringArray); -+ } -+ -+ dbus_connection_send(mConnection, reply, nullptr); -+ dbus_message_unref(reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+void nsGNOMEShellSearchProvider::LaunchWithID(const char* aID, -+ uint32_t aTimeStamp) { -+ char* commandLine = nullptr; -+ int tmp; -+ -+ if (strncmp(aID, KEYWORD_SEARCH_STRING, KEYWORD_SEARCH_STRING_LEN) == 0) { -+ nsPrintfCString searchString("search:%s", mSearchTerm.get()); -+ const char* urlList[2] = {"unused", searchString.get()}; -+ commandLine = ConstructCommandLine(2, (char**)urlList, 0, &tmp); -+ } else { -+ int keyIndex = atoi(aID); -+ nsCOMPtr<nsINavHistoryResultNode> child; -+ mHistResultContainer->GetChild(keyIndex, getter_AddRefs(child)); -+ -+ nsAutoCString uri; -+ nsresult rv = child->GetUri(uri); -+ if (NS_FAILED(rv)) { -+ return; -+ } -+ -+ const char* urlList[2] = {"unused", uri.get()}; -+ commandLine = ConstructCommandLine(2, (char**)urlList, 0, &tmp); -+ } -+ -+ if (commandLine) { -+ HandleCommandLine(commandLine, aTimeStamp); -+ free(commandLine); -+ } -+} -+ -+void nsGNOMEShellSearchProvider::LaunchWithAllResults(uint32_t aTimeStamp) { -+ uint32_t childCount = 0; -+ nsresult rv = mHistResultContainer->GetChildCount(&childCount); -+ if (NS_FAILED(rv) || childCount == 0) { -+ return; -+ } -+ -+ if (childCount > MAX_SEARCH_RESULTS_NUM) { -+ childCount = MAX_SEARCH_RESULTS_NUM; -+ } -+ -+ char** urlList = (char**)moz_xmalloc(sizeof(char*) * (childCount + 2)); -+ int urlListElements = 0; -+ -+ urlList[urlListElements++] = strdup("unused"); -+ -+ for (uint32_t i = 0; i < childCount; i++) { -+ nsCOMPtr<nsINavHistoryResultNode> child; -+ mHistResultContainer->GetChild(i, getter_AddRefs(child)); -+ -+ if (!IsHistoryResultNodeURI(child)) { -+ continue; -+ } -+ -+ nsAutoCString uri; -+ nsresult rv = child->GetUri(uri); -+ if (NS_FAILED(rv)) { -+ continue; -+ } -+ urlList[urlListElements++] = strdup(uri.get()); -+ } -+ -+ nsPrintfCString searchString("search:%s", mSearchTerm.get()); -+ urlList[urlListElements++] = strdup(searchString.get()); -+ -+ int tmp; -+ char* commandLine = ConstructCommandLine(urlListElements, urlList, 0, &tmp); -+ if (commandLine) { -+ HandleCommandLine(commandLine, aTimeStamp); -+ free(commandLine); -+ } -+ -+ for (int i = 0; i < urlListElements; i++) { -+ free(urlList[i]); -+ } -+ free(urlList); -+} -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::ActivateResult( -+ DBusMessage* aMsg) { -+ DBusMessage* reply; -+ char* resultID; -+ char** stringArray; -+ int elements; -+ uint32_t timestamp; -+ -+ if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_STRING, &resultID, -+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &stringArray, -+ &elements, DBUS_TYPE_UINT32, ×tamp, -+ DBUS_TYPE_INVALID) || -+ resultID == nullptr) { -+ reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); -+ } else { -+ reply = dbus_message_new_method_return(aMsg); -+ LaunchWithID(resultID, timestamp); -+ dbus_free_string_array(stringArray); -+ } -+ -+ dbus_connection_send(mConnection, reply, nullptr); -+ dbus_message_unref(reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::LaunchSearch(DBusMessage* aMsg) { -+ DBusMessage* reply; -+ char** stringArray; -+ int elements; -+ uint32_t timestamp; -+ -+ if (!dbus_message_get_args(aMsg, nullptr, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, -+ &stringArray, &elements, DBUS_TYPE_UINT32, -+ ×tamp, DBUS_TYPE_INVALID) || -+ elements == 0) { -+ reply = dbus_message_new_error(aMsg, DBUS_BUS_NAME, "Wrong argument"); -+ } else { -+ reply = dbus_message_new_method_return(aMsg); -+ LaunchWithAllResults(timestamp); -+ dbus_free_string_array(stringArray); -+ } -+ -+ dbus_connection_send(mConnection, reply, nullptr); -+ dbus_message_unref(reply); -+ -+ return DBUS_HANDLER_RESULT_HANDLED; -+} -+ -+DBusHandlerResult nsGNOMEShellSearchProvider::HandleDBusMessage( -+ DBusConnection* aConnection, DBusMessage* aMsg) { -+ NS_ASSERTION(mConnection == aConnection, "Wrong D-Bus connection."); -+ -+ const char* method = dbus_message_get_member(aMsg); -+ const char* iface = dbus_message_get_interface(aMsg); -+ -+ if ((strcmp("Introspect", method) == 0) && -+ (strcmp("org.freedesktop.DBus.Introspectable", iface) == 0)) { -+ return Introspect(aMsg); -+ } -+ -+ if (strcmp("org.gnome.Shell.SearchProvider2", iface) == 0) { -+ if (strcmp("GetInitialResultSet", method) == 0) { -+ return GetInitialResultSet(aMsg); -+ } -+ if (strcmp("GetSubsearchResultSet", method) == 0) { -+ return GetSubsearchResultSet(aMsg); -+ } -+ if (strcmp("GetResultMetas", method) == 0) { -+ return GetResultMetas(aMsg); -+ } -+ if (strcmp("ActivateResult", method) == 0) { -+ return ActivateResult(aMsg); -+ } -+ if (strcmp("LaunchSearch", method) == 0) { -+ return LaunchSearch(aMsg); -+ } -+ } -+ -+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -+} -+ -+void nsGNOMEShellSearchProvider::UnregisterDBusInterface( -+ DBusConnection* aConnection) { -+ NS_ASSERTION(mConnection == aConnection, "Wrong D-Bus connection."); -+ // Not implemented -+} -+ -+static DBusHandlerResult message_handler(DBusConnection* conn, -+ DBusMessage* aMsg, void* user_data) { -+ auto interface = static_cast<nsGNOMEShellSearchProvider*>(user_data); -+ return interface->HandleDBusMessage(conn, aMsg); -+} -+ -+static void unregister(DBusConnection* conn, void* user_data) { -+ auto interface = static_cast<nsGNOMEShellSearchProvider*>(user_data); -+ interface->UnregisterDBusInterface(conn); -+} -+ -+static DBusObjectPathVTable remoteHandlersTable = { -+ .unregister_function = unregister, -+ .message_function = message_handler, -+}; -+ -+nsresult nsGNOMEShellSearchProvider::Startup() { -+ if (mConnection && dbus_connection_get_is_connected(mConnection)) { -+ // We're already connected so we don't need to reconnect -+ return NS_ERROR_ALREADY_INITIALIZED; -+ } -+ -+ nsCOMPtr<nsIStringBundleService> sbs = -+ do_GetService(NS_STRINGBUNDLE_CONTRACTID); -+ if (NS_WARN_IF(!sbs)) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ nsCOMPtr<nsIStringBundle> bundle; -+ sbs->CreateBundle("chrome://browser/locale/browser.properties", -+ getter_AddRefs(bundle)); -+ if (NS_WARN_IF(!bundle)) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ nsAutoString searchTitle; -+ bundle->GetStringFromName("gnomeSearchProviderSearch", searchTitle); -+ mGnomeSearchTitle = NS_ConvertUTF16toUTF8(searchTitle); -+ -+ mHistoryService = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID); -+ if (!mHistoryService) { -+ return NS_ERROR_FAILURE; -+ } -+ -+ mConnection = -+ already_AddRefed<DBusConnection>(dbus_bus_get(DBUS_BUS_SESSION, nullptr)); -+ if (!mConnection) { -+ return NS_ERROR_FAILURE; -+ } -+ dbus_connection_set_exit_on_disconnect(mConnection, false); -+ dbus_connection_setup_with_g_main(mConnection, nullptr); -+ -+ DBusError err; -+ dbus_error_init(&err); -+ dbus_bus_request_name(mConnection, DBUS_BUS_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, -+ &err); -+ // The interface is already owned - there is another application/profile -+ // instance already running. -+ if (dbus_error_is_set(&err)) { -+ dbus_error_free(&err); -+ mConnection = nullptr; -+ return NS_ERROR_FAILURE; -+ } -+ -+ if (!dbus_connection_register_object_path(mConnection, DBUS_OBJECT_PATH, -+ &remoteHandlersTable, this)) { -+ mConnection = nullptr; -+ return NS_ERROR_FAILURE; -+ } -+ -+ return NS_OK; -+} -+ -+void nsGNOMEShellSearchProvider::Shutdown() { -+ if (!mConnection) { -+ return; -+ } -+ -+ dbus_connection_unregister_object_path(mConnection, DBUS_OBJECT_PATH); -+ -+ // dbus_connection_unref() will be called by RefPtr here. -+ mConnection = nullptr; -+} -diff -up firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.h.gnome-shell-search-provider firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.h ---- firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.h.gnome-shell-search-provider 2020-02-11 09:00:59.350512802 +0100 -+++ firefox-73.0/browser/components/shell/nsGNOMEShellSearchProvider.h 2020-02-11 09:00:59.350512802 +0100 -@@ -0,0 +1,55 @@ -+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* vim:expandtab:shiftwidth=2:tabstop=2: -+ */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#ifndef __nsGNOMEShellSearchProvider_h__ -+#define __nsGNOMEShellSearchProvider_h__ -+ -+#include "mozilla/DBusHelpers.h" -+#include "nsINavHistoryService.h" -+#include "nsUnixRemoteServer.h" -+#include "nsCOMPtr.h" -+ -+class nsGNOMEShellSearchProvider : public nsUnixRemoteServer { -+ public: -+ nsGNOMEShellSearchProvider() : mConnection(nullptr) {} -+ ~nsGNOMEShellSearchProvider() { Shutdown(); } -+ -+ nsresult Startup(); -+ void Shutdown(); -+ -+ DBusHandlerResult HandleDBusMessage(DBusConnection* aConnection, -+ DBusMessage* msg); -+ void UnregisterDBusInterface(DBusConnection* aConnection); -+ -+ private: -+ DBusHandlerResult Introspect(DBusMessage* msg); -+ -+ DBusHandlerResult GetInitialResultSet(DBusMessage* msg); -+ DBusHandlerResult GetSubsearchResultSet(DBusMessage* msg); -+ DBusHandlerResult GetResultMetas(DBusMessage* msg); -+ DBusHandlerResult ActivateResult(DBusMessage* msg); -+ DBusHandlerResult LaunchSearch(DBusMessage* msg); -+ -+ nsresult QueryHistory(const char* aSearchTerm); -+ void GetIDKeyForURI(int aIndex, nsAutoCString& aUri, nsAutoCString& aIDKey); -+ int GetIndexFromIDKey(const char* aIDKey); -+ bool IsHistoryResultNodeURI(nsINavHistoryResultNode* aHistoryNode); -+ void AppendResultID(DBusMessageIter* aIter, const char* aID); -+ void AppendSearchID(DBusMessageIter* aIter, const char* aID); -+ void ComposeSearchResultReply(DBusMessage* aReply, const char* aSearchTerm); -+ void LaunchWithID(const char* aID, uint32_t aTimeStamp); -+ void LaunchWithAllResults(uint32_t aTimeStamp); -+ -+ // The connection is owned by DBus library -+ RefPtr<DBusConnection> mConnection; -+ nsCOMPtr<nsINavHistoryContainerResultNode> mHistResultContainer; -+ nsCOMPtr<nsINavHistoryService> mHistoryService; -+ nsAutoCStringN<32> mSearchTerm; -+ nsAutoCString mGnomeSearchTitle; -+}; -+ -+#endif // __nsGNOMEShellSearchProvider_h__ -diff -up firefox-73.0/browser/components/shell/nsGNOMEShellService.cpp.gnome-shell-search-provider firefox-73.0/browser/components/shell/nsGNOMEShellService.cpp ---- firefox-73.0/browser/components/shell/nsGNOMEShellService.cpp.gnome-shell-search-provider 2020-02-07 22:12:59.000000000 +0100 -+++ firefox-73.0/browser/components/shell/nsGNOMEShellService.cpp 2020-02-11 09:00:59.350512802 +0100 -@@ -89,6 +89,14 @@ nsresult nsGNOMEShellService::Init() { - - if (!giovfs && !gsettings) return NS_ERROR_NOT_AVAILABLE; - -+#ifdef MOZ_ENABLE_DBUS -+ const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP"); -+ if (currentDesktop && strstr(currentDesktop, "GNOME") != nullptr && -+ Preferences::GetBool("browser.gnome-search-provider.enabled", false)) { -+ mSearchProvider.Startup(); -+ } -+#endif -+ - // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use - // the locale encoding. If it's not set, they use UTF-8. - mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nullptr; -diff -up firefox-73.0/browser/components/shell/nsGNOMEShellService.h.gnome-shell-search-provider firefox-73.0/browser/components/shell/nsGNOMEShellService.h ---- firefox-73.0/browser/components/shell/nsGNOMEShellService.h.gnome-shell-search-provider 2020-02-07 22:12:59.000000000 +0100 -+++ firefox-73.0/browser/components/shell/nsGNOMEShellService.h 2020-02-11 09:00:59.350512802 +0100 -@@ -10,6 +10,9 @@ - #include "nsToolkitShellService.h" - #include "nsString.h" - #include "mozilla/Attributes.h" -+#ifdef MOZ_ENABLE_DBUS -+# include "nsGNOMEShellSearchProvider.h" -+#endif - - class nsGNOMEShellService final : public nsIGNOMEShellService, - public nsToolkitShellService { -@@ -28,6 +31,9 @@ class nsGNOMEShellService final : public - bool KeyMatchesAppName(const char* aKeyValue) const; - bool CheckHandlerMatchesAppName(const nsACString& handler) const; - -+#ifdef MOZ_ENABLE_DBUS -+ nsGNOMEShellSearchProvider mSearchProvider; -+#endif - bool GetAppPathFromLauncher(); - bool mUseLocaleFilenames; - nsCString mAppPath; -diff -up firefox-73.0/browser/locales/en-US/chrome/browser/browser.properties.gnome-shell-search-provider firefox-73.0/browser/locales/en-US/chrome/browser/browser.properties ---- firefox-73.0/browser/locales/en-US/chrome/browser/browser.properties.gnome-shell-search-provider 2020-02-07 22:13:00.000000000 +0100 -+++ firefox-73.0/browser/locales/en-US/chrome/browser/browser.properties 2020-02-11 09:00:59.350512802 +0100 -@@ -1047,3 +1047,7 @@ confirmationHint.breakageReport.label = - # Used by the export of user's live bookmarks to an OPML file as a title for the file. - # %S will be replaced with brandShortName - livebookmarkMigration.title = %S Live Bookmarks -+ -+# LOCALIZATION NOTE (gnomeSearchProviderSearch): -+# Used for search by Gnome Shell activity screen, %s is a searched string. -+gnomeSearchProviderSearch=Search the web for ā%sā -diff -up firefox-73.0/toolkit/components/remote/moz.build.gnome-shell-search-provider firefox-73.0/toolkit/components/remote/moz.build ---- firefox-73.0/toolkit/components/remote/moz.build.gnome-shell-search-provider 2020-02-07 22:13:54.000000000 +0100 -+++ firefox-73.0/toolkit/components/remote/moz.build 2020-02-11 09:00:59.351512811 +0100 -@@ -25,6 +25,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk' - 'nsDBusRemoteServer.cpp', - ] - CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS'] -+ EXPORTS += [ -+ 'nsUnixRemoteServer.h', -+ 'RemoteUtils.h', -+ ] - CXXFLAGS += CONFIG['TK_CFLAGS'] - - if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': -diff -up firefox-73.0/toolkit/components/remote/nsDBusRemoteServer.cpp.gnome-shell-search-provider firefox-73.0/toolkit/components/remote/nsDBusRemoteServer.cpp ---- firefox-73.0/toolkit/components/remote/nsDBusRemoteServer.cpp.gnome-shell-search-provider 2020-02-07 22:13:54.000000000 +0100 -+++ firefox-73.0/toolkit/components/remote/nsDBusRemoteServer.cpp 2020-02-11 09:00:59.351512811 +0100 -@@ -23,7 +23,7 @@ - - #include <dlfcn.h> - --const char* introspect_template = -+static const char* introspect_template = - "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection " - "1.0//EN\"\n" - "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\";>\n" @@ -1,3 +1,4 @@ SHA512 (cbindgen-vendor.tar.xz) = a12d9dd45301614f3a7fcd77f61e3f731718fc418fcf84b0ac7363ef4ddd8ff60e057febef917620ac89d2d47d76b8dccfa71405935e346b849b93425732016a SHA512 (firefox-76.0.1.source.tar.xz) = 188d7dc51200662048f808e32eced55979a69059bf88eac8386307f9371adad4ca524819d99a001b6d900147b8f216d5d330430f15f11eae0b01cccf8f39681f SHA512 (firefox-langpacks-76.0.1-20200508.tar.xz) = 86ff8486282914fdb6203bd099f6bcaf266c4453dd56c1876768c26d281ab0089ad0f141f86f912bfebc9677cc0b82583f86231bb2612ae2d5820078666fc9dc +SHA512 (firefox-77.0.source.tar.xz) = 5d530d936786019a27c6bd057e01c303f58728d11927ba5c40be6f23718c206d4d1691a91c3d46bd5dce3050d32f728bb7c94d6385819a744af44aa18cbc561b |