Skip to content

Commit b0694e9

Browse files
authored
Merge pull request #3826 from dcog989/Fix-'100%-CPU'-BrowserBookmark-issue
Fix BrowserBookmark '100% CPU' issue
2 parents dfe9616 + 8f88998 commit b0694e9

File tree

3 files changed

+85
-28
lines changed

3 files changed

+85
-28
lines changed

Plugins/Flow.Launcher.Plugin.BrowserBookmark/FirefoxBookmarkLoader.cs

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
44
using System.IO;
5+
using System.IO.Compression;
56
using System.Linq;
67
using System.Threading.Tasks;
78
using Flow.Launcher.Plugin.BrowserBookmark.Helper;
@@ -134,10 +135,6 @@ private void LoadFaviconsFromDb(string dbPath, List<Bookmark> bookmarks)
134135

135136
try
136137
{
137-
if (string.IsNullOrEmpty(bookmark.Url))
138-
return;
139-
140-
// Extract domain from URL
141138
if (!Uri.TryCreate(bookmark.Url, UriKind.Absolute, out Uri uri))
142139
return;
143140

@@ -146,43 +143,49 @@ private void LoadFaviconsFromDb(string dbPath, List<Bookmark> bookmarks)
146143
// Query for latest Firefox version favicon structure
147144
using var cmd = connection.CreateCommand();
148145
cmd.CommandText = @"
149-
SELECT i.data
146+
SELECT i.id, i.data
150147
FROM moz_icons i
151148
JOIN moz_icons_to_pages ip ON i.id = ip.icon_id
152149
JOIN moz_pages_w_icons p ON ip.page_id = p.id
153-
WHERE p.page_url LIKE @url
154-
AND i.data IS NOT NULL
155-
ORDER BY i.width DESC -- Select largest icon available
150+
WHERE p.page_url LIKE @domain
151+
ORDER BY i.width DESC
156152
LIMIT 1";
157153

158-
cmd.Parameters.AddWithValue("@url", $"%{domain}%");
154+
cmd.Parameters.AddWithValue("@domain", $"%{domain}%");
159155

160156
using var reader = cmd.ExecuteReader();
161-
if (!reader.Read() || reader.IsDBNull(0))
157+
if (!reader.Read() || reader.IsDBNull(1))
162158
return;
163159

160+
var iconId = reader.GetInt64(0).ToString();
164161
var imageData = (byte[])reader["data"];
165162

166163
if (imageData is not { Length: > 0 })
167164
return;
168165

169-
string faviconPath;
170-
if (FaviconHelper.IsSvgData(imageData))
171-
{
172-
faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.svg");
173-
}
174-
else
166+
// Check if the image data is compressed (GZip)
167+
if (imageData.Length > 2 && imageData[0] == 0x1f && imageData[1] == 0x8b)
175168
{
176-
faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}.png");
169+
using var inputStream = new MemoryStream(imageData);
170+
using var gZipStream = new GZipStream(inputStream, CompressionMode.Decompress);
171+
using var outputStream = new MemoryStream();
172+
gZipStream.CopyTo(outputStream);
173+
imageData = outputStream.ToArray();
177174
}
178175

179-
// Filter out duplicate favicons
180-
if (savedPaths.TryAdd(faviconPath, true))
176+
// Convert the image data to WebP format
177+
var webpData = FaviconHelper.TryConvertToWebp(imageData);
178+
if (webpData != null)
181179
{
182-
FaviconHelper.SaveBitmapData(imageData, faviconPath);
183-
}
180+
var faviconPath = Path.Combine(_faviconCacheDir, $"firefox_{domain}_{iconId}.webp");
181+
182+
if (savedPaths.TryAdd(faviconPath, true))
183+
{
184+
FaviconHelper.SaveBitmapData(webpData, faviconPath);
185+
}
184186

185-
bookmark.FaviconPath = faviconPath;
187+
bookmark.FaviconPath = faviconPath;
188+
}
186189
}
187190
catch (Exception ex)
188191
{

Plugins/Flow.Launcher.Plugin.BrowserBookmark/Flow.Launcher.Plugin.BrowserBookmark.csproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,14 @@
4545
$(OutputPath)runtimes\linux-musl-arm;
4646
$(OutputPath)runtimes\linux-musl-arm64;
4747
$(OutputPath)runtimes\linux-musl-x64;
48+
$(OutputPath)runtimes\linux-musl-s390x;
4849
$(OutputPath)runtimes\linux-ppc64le;
4950
$(OutputPath)runtimes\linux-s390x;
5051
$(OutputPath)runtimes\linux-x64;
5152
$(OutputPath)runtimes\linux-x86;
5253
$(OutputPath)runtimes\maccatalyst-arm64;
5354
$(OutputPath)runtimes\maccatalyst-x64;
55+
$(OutputPath)runtimes\osx;
5456
$(OutputPath)runtimes\osx-arm64;
5557
$(OutputPath)runtimes\osx-x64"/>
5658
</Target>
@@ -64,12 +66,14 @@
6466
$(PublishDir)runtimes\linux-musl-arm;
6567
$(PublishDir)runtimes\linux-musl-arm64;
6668
$(PublishDir)runtimes\linux-musl-x64;
69+
$(PublishDir)runtimes\linux-musl-s390x;
6770
$(PublishDir)runtimes\linux-ppc64le;
6871
$(PublishDir)runtimes\linux-s390x;
6972
$(PublishDir)runtimes\linux-x64;
7073
$(PublishDir)runtimes\linux-x86;
7174
$(PublishDir)runtimes\maccatalyst-arm64;
7275
$(PublishDir)runtimes\maccatalyst-x64;
76+
$(PublishDir)runtimes\osx;
7377
$(PublishDir)runtimes\osx-arm64;
7478
$(PublishDir)runtimes\osx-x64"/>
7579
</Target>
@@ -97,6 +101,8 @@
97101
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
98102
<PackageReference Include="Flow.Launcher.Localization" Version="0.0.4" />
99103
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.8" />
104+
<PackageReference Include="Svg.Skia" Version="3.0.4" />
105+
<PackageReference Include="SkiaSharp" Version="3.119.0" />
100106
</ItemGroup>
101107

102108
</Project>

Plugins/Flow.Launcher.Plugin.BrowserBookmark/Helper/FaviconHelper.cs

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.IO;
3+
using SkiaSharp;
4+
using Svg.Skia;
35

46
namespace Flow.Launcher.Plugin.BrowserBookmark.Helper;
57

@@ -65,12 +67,58 @@ public static void SaveBitmapData(byte[] imageData, string outputPath)
6567
}
6668
}
6769

68-
public static bool IsSvgData(byte[] data)
70+
public static byte[] TryConvertToWebp(byte[] data)
6971
{
70-
if (data.Length < 5)
71-
return false;
72-
string start = System.Text.Encoding.ASCII.GetString(data, 0, Math.Min(100, data.Length));
73-
return start.Contains("<svg") ||
74-
(start.StartsWith("<?xml") && start.Contains("<svg"));
72+
if (data == null || data.Length == 0)
73+
return null;
74+
75+
SKBitmap bitmap = null;
76+
77+
try
78+
{
79+
using (var ms = new MemoryStream(data))
80+
{
81+
var svg = new SKSvg();
82+
if (svg.Load(ms) != null && svg.Picture != null)
83+
{
84+
bitmap = new SKBitmap((int)svg.Picture.CullRect.Width, (int)svg.Picture.CullRect.Height);
85+
using (var canvas = new SKCanvas(bitmap))
86+
{
87+
canvas.Clear(SKColors.Transparent);
88+
canvas.DrawPicture(svg.Picture);
89+
canvas.Flush();
90+
}
91+
}
92+
}
93+
}
94+
catch { /* Not an SVG */ }
95+
96+
if (bitmap == null)
97+
{
98+
try
99+
{
100+
bitmap = SKBitmap.Decode(data);
101+
}
102+
catch { /* Not a decodable bitmap */ }
103+
}
104+
105+
if (bitmap != null)
106+
{
107+
try
108+
{
109+
using (var image = SKImage.FromBitmap(bitmap))
110+
using (var webp = image.Encode(SKEncodedImageFormat.Webp, 65))
111+
{
112+
if (webp != null)
113+
return webp.ToArray();
114+
}
115+
}
116+
finally
117+
{
118+
bitmap.Dispose();
119+
}
120+
}
121+
122+
return null;
75123
}
76124
}

0 commit comments

Comments
 (0)