Updated to 77.0

This commit is contained in:
Martin Stransky 2020-05-29 11:31:41 +02:00
parent 41962ee4b4
commit 5116ef14ae
15 changed files with 626 additions and 2081 deletions

1
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));
+bool WaylandDMABufSurface::IsGlobalRefSet() const {
+ if (!mGlobalRefCountFd) {
+ return false;
+ }
+ struct pollfd pfd;
+ pfd.fd = mGlobalRefCountFd;
+ pfd.events = POLLIN;
+ return poll(&pfd, 1, 0) == 1;
+}
+
+void DMABufRefcount::Release() {
+void WaylandDMABufSurface::GlobalRefRelease() {
+ MOZ_ASSERT(mGlobalRefCountFd);
+ uint64_t counter;
+ read(mFd, &counter, sizeof(counter));
+ counter--;
+ write(mFd, &counter, sizeof(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!");
+ }
+ }
+}
+
+uint64_t DMABufRefcount::GetRefcount() {
+ uint64_t counter;
+ read(mFd, &counter, sizeof(counter));
+ write(mFd, &counter, sizeof(counter));
+ return counter;
+}
+
+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;
+void WaylandDMABufSurface::GlobalRefCountImport(int aFd) {
+ MOZ_ASSERT(!mGlobalRefCountFd);
+ mGlobalRefCountFd = aFd;
+ GlobalRefAdd();
+}
+
+void WaylandDMABufSurface::GlobalRefCountDelete() {
+ MOZ_ASSERT(mGlobalRefCountFd);
+ if (mGlobalRefCountFd) {
+ GlobalRefRelease();
+ close(mGlobalRefCountFd);
+ mGlobalRefCountFd = 0;
+ }
+ return true;
+}
+
+bool WaylandDMABufSurface::IsGlobalRefSet() {
+ MOZ_ASSERT(mGlobalRefCount);
+ return mGlobalRefCount->GetRefcount() > 1;
+}
+
+void WaylandDMABufSurface::GlobalRefAdd() {
+ MOZ_ASSERT(mGlobalRefCount);
+ mGlobalRefCount->RefAdd();
+}
+
+void WaylandDMABufSurface::GlobalRefRelease() {
+ MOZ_ASSERT(mGlobalRefCount);
+ mGlobalRefCount->Release();
+}
+
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(

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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;

406
mozilla-1634293.patch Normal file
View File

@ -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;

15
mozilla-1639197.patch Normal file
View File

@ -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");
}
}

View File

@ -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);

View File

@ -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__

View File

@ -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, &timestamp,
+ 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,
+ &timestamp, 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"

View File

@ -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