diff options
Diffstat (limited to 'mozilla-gnome-shell-search-provider-icons.patch')
-rw-r--r-- | mozilla-gnome-shell-search-provider-icons.patch | 453 |
1 files changed, 453 insertions, 0 deletions
diff --git a/mozilla-gnome-shell-search-provider-icons.patch b/mozilla-gnome-shell-search-provider-icons.patch new file mode 100644 index 0000000..fd9dbe8 --- /dev/null +++ b/mozilla-gnome-shell-search-provider-icons.patch @@ -0,0 +1,453 @@ +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__ + |