From 78b4c7db855a2daee98e830613a3f331ba89395e Mon Sep 17 00:00:00 2001 From: dcog989 Date: Mon, 14 Jul 2025 00:43:39 +0100 Subject: [PATCH 1/5] Fix BrowserBookmark '100% CPU' issue # Fix BrowserBookmark plugin locking threads at 100% CPU The following files were modified to implement this fix: 1. /Flow.Launcher.Plugin.BrowserBookmark.csproj - packages SkiaSharp and Svg.Skia added to output WEBP 2. /Helper/FaviconHelper.cs - new method, TryConvertToWebp, added to take any image data and encode to WEBP 3. /FirefoxBookmarkLoader.cs - LoadFaviconsFromDb to use the new helper which ensures only safe WEBP files are used by the UI, which resolves the CPU-locking. It was GZIPped SVGs that were causing the thread / CPU lock. --- .../FirefoxBookmarkLoader.cs | 48 +++++++------- ...low.Launcher.Plugin.BrowserBookmark.csproj | 2 + .../Helper/FaviconHelper.cs | 62 ++++++++++++++++--- 3 files changed, 82 insertions(+), 30 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index ec3b867ea81..f933fa2bb76 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -2,6 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using Flow.Launcher.Plugin.BrowserBookmark.Helper; @@ -134,10 +135,6 @@ private void LoadFaviconsFromDb(string dbPath, List bookmarks) try { - if (string.IsNullOrEmpty(bookmark.Url)) - return; - - // Extract domain from URL if (!Uri.TryCreate(bookmark.Url, UriKind.Absolute, out Uri uri)) return; @@ -146,43 +143,48 @@ private void LoadFaviconsFromDb(string dbPath, List bookmarks) // Query for latest Firefox version favicon structure using var cmd = connection.CreateCommand(); cmd.CommandText = @" - SELECT i.data + SELECT i.id, i.data FROM moz_icons i JOIN moz_icons_to_pages ip ON i.id = ip.icon_id JOIN moz_pages_w_icons p ON ip.page_id = p.id - WHERE p.page_url LIKE @url - AND i.data IS NOT NULL - ORDER BY i.width DESC -- Select largest icon available + WHERE p.page_url LIKE @domain + ORDER BY i.width DESC LIMIT 1"; - cmd.Parameters.AddWithValue("@url", $"%{domain}%"); + cmd.Parameters.AddWithValue("@domain", $"%{domain}%"); using var reader = cmd.ExecuteReader(); - if (!reader.Read() || reader.IsDBNull(0)) + if (!reader.Read() || reader.IsDBNull(1)) return; + var iconId = reader.GetInt64(0).ToString(); var imageData = (byte[])reader["data"]; if (imageData is not { Length: > 0 }) return; - - string faviconPath; - if (FaviconHelper.IsSvgData(imageData)) + + if (imageData.Length > 2 && imageData[0] == 0x1f && imageData[1] == 0x8b) { - faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.svg"); + using var inputStream = new MemoryStream(imageData); + using var gZipStream = new GZipStream(inputStream, CompressionMode.Decompress); + using var outputStream = new MemoryStream(); + gZipStream.CopyTo(outputStream); + imageData = outputStream.ToArray(); } - else + + var webpData = FaviconHelper.TryConvertToWebp(imageData); + + if (webpData != null) { - faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png"); - } + var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}_{iconId}.webp"); - // Filter out duplicate favicons - if (savedPaths.TryAdd(faviconPath, true)) - { - FaviconHelper.SaveBitmapData(imageData, faviconPath); - } + if (savedPaths.TryAdd(faviconPath, true)) + { + FaviconHelper.SaveBitmapData(webpData, faviconPath); + } - bookmark.FaviconPath = faviconPath; + bookmark.FaviconPath = faviconPath; + } } catch (Exception ex) { diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 3fb0fa46f64..7b2fb47f843 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -97,6 +97,8 @@ + + diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs index a879dcefd1b..bd8492408da 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using SkiaSharp; +using Svg.Skia; namespace Flow.Launcher.Plugin.BrowserBookmark.Helper; @@ -65,12 +67,58 @@ public static void SaveBitmapData(byte[] imageData, string outputPath) } } - public static bool IsSvgData(byte[] data) + public static byte[] TryConvertToWebp(byte[] data) { - if (data.Length < 5) - return false; - string start = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(100, data.Length)); - return start.Contains(" Date: Mon, 14 Jul 2025 09:01:59 +0800 Subject: [PATCH 2/5] Add code comments --- .../FirefoxBookmarkLoader.cs | 7 ++++--- .../Helper/FaviconHelper.cs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs index f933fa2bb76..ef029809a19 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs @@ -162,7 +162,8 @@ ORDER BY i.width DESC if (imageData is not { Length: > 0 }) return; - + + // Check if the image data is compressed (GZip) if (imageData.Length > 2 && imageData[0] == 0x1f && imageData[1] == 0x8b) { using var inputStream = new MemoryStream(imageData); @@ -171,9 +172,9 @@ ORDER BY i.width DESC gZipStream.CopyTo(outputStream); imageData = outputStream.ToArray(); } - + + // Convert the image data to WebP format var webpData = FaviconHelper.TryConvertToWebp(imageData); - if (webpData != null) { var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}_{iconId}.webp"); diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs index bd8492408da..72cb15b3396 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs @@ -121,4 +121,4 @@ public static byte[] TryConvertToWebp(byte[] data) return null; } -} \ No newline at end of file +} From 2a5ac092f0a175d80f9a0298bbb1e02da10e7ec4 Mon Sep 17 00:00:00 2001 From: dcog989 <89043002+dcog989@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:46:25 +0100 Subject: [PATCH 3/5] Update Flow.Launcher.Plugin.BrowserBookmark.csproj bump Microsoft.Data.Sqlite --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 615d89f0900..6840af5d264 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -96,7 +96,7 @@ - + From dcc0866de1f5857a50c1343239f331032327f627 Mon Sep 17 00:00:00 2001 From: dcog989 <89043002+dcog989@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:58:36 +0100 Subject: [PATCH 4/5] Update Flow.Launcher.Plugin.BrowserBookmark.csproj bump Svg.Skia --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index 6840af5d264..fb5d4df5ebb 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -97,7 +97,7 @@ - + From 8f88998d34a2ce544958b017f651d81f4aca44e9 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Thu, 7 Aug 2025 08:57:21 +0800 Subject: [PATCH 5/5] Remove more unnecessary runtimes --- .../Flow.Launcher.Plugin.BrowserBookmark.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj index fb5d4df5ebb..7d3cf164c8a 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj @@ -45,12 +45,14 @@ $(OutputPath)runtimes\linux-musl-arm; $(OutputPath)runtimes\linux-musl-arm64; $(OutputPath)runtimes\linux-musl-x64; + $(OutputPath)runtimes\linux-musl-s390x; $(OutputPath)runtimes\linux-ppc64le; $(OutputPath)runtimes\linux-s390x; $(OutputPath)runtimes\linux-x64; $(OutputPath)runtimes\linux-x86; $(OutputPath)runtimes\maccatalyst-arm64; $(OutputPath)runtimes\maccatalyst-x64; + $(OutputPath)runtimes\osx; $(OutputPath)runtimes\osx-arm64; $(OutputPath)runtimes\osx-x64"/> @@ -64,12 +66,14 @@ $(PublishDir)runtimes\linux-musl-arm; $(PublishDir)runtimes\linux-musl-arm64; $(PublishDir)runtimes\linux-musl-x64; + $(PublishDir)runtimes\linux-musl-s390x; $(PublishDir)runtimes\linux-ppc64le; $(PublishDir)runtimes\linux-s390x; $(PublishDir)runtimes\linux-x64; $(PublishDir)runtimes\linux-x86; $(PublishDir)runtimes\maccatalyst-arm64; $(PublishDir)runtimes\maccatalyst-x64; + $(PublishDir)runtimes\osx; $(PublishDir)runtimes\osx-arm64; $(PublishDir)runtimes\osx-x64"/>