From 42a91fb3a05e6cf0e0e75fe67861974c2a838b4b Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 30 Dec 2025 16:23:43 +0800 Subject: [PATCH] Refactor tab tracking for thread safety and nullability Replaced object locks with a custom Lock class for clearer thread synchronization in TabsCache and TabsTracker. Enabled nullable reference types in TabsTracker and updated method signatures and variables to use nullable types where appropriate. Modernized collection initializations and refactored methods for improved readability. Cleaned up using directives. These changes enhance thread safety, code clarity, and nullability handling in browser tab management. --- .../Tabs/TabsCache.cs | 11 +++++++--- .../Tabs/TabsTracker.cs | 22 ++++++++++--------- .../Tabs/TabsWalker.cs | 16 ++++++++------ 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsCache.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsCache.cs index 47446e5ec..3e2d73aa8 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsCache.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsCache.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Windows.Automation; using static Flow.Launcher.Plugin.BrowserBookmark.Main; @@ -13,11 +14,15 @@ internal class TabsCache { private static readonly string ClassName = nameof(TabsCache); private readonly HashSet _knownTabs = []; - private readonly object _sync = new(); + private readonly Lock _sync = new(); - public static string RuntimeIdToKey(int[] runtimeId) => string.Join("-", runtimeId); + public static string RuntimeIdToKey(int[] runtimeId) + { + return string.Join("-", runtimeId); + } - public static string RuntimeIdToKey(AutomationElement elem) { + public static string RuntimeIdToKey(AutomationElement elem) + { try { return elem != null ? RuntimeIdToKey(elem.GetRuntimeId()) : null; diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsTracker.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsTracker.cs index 588bc44c5..300770737 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsTracker.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsTracker.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; +using System.Threading; using System.Windows.Automation; using BrowserTabs; using Flow.Launcher.Plugin.BrowserBookmark.Models; @@ -9,6 +9,8 @@ using static Flow.Launcher.Plugin.BrowserBookmark.Main; namespace Flow.Launcher.Plugin.BrowserBookmark.Tabs; +#nullable enable + /// /// TabsTracker maps initial URLs into existing browser's tabs. /// The sequence of events: @@ -19,14 +21,14 @@ namespace Flow.Launcher.Plugin.BrowserBookmark.Tabs; public class TabsTracker : IDisposable { private static readonly string ClassName = nameof(TabsTracker); - private static readonly HashSet chromiumProcessNames = new HashSet(["msedge", "chrome", "brave", "vivaldi", "opera", "chromium"], StringComparer.OrdinalIgnoreCase); - private static readonly HashSet firefoxProcessNames = new HashSet(["firefox"], StringComparer.OrdinalIgnoreCase); + private static readonly HashSet chromiumProcessNames = new(["msedge", "chrome", "brave", "vivaldi", "opera", "chromium"], StringComparer.OrdinalIgnoreCase); + private static readonly HashSet firefoxProcessNames = new(["firefox"], StringComparer.OrdinalIgnoreCase); private readonly TabsWalker _walker = new(); private readonly Queue _expectedUrls = []; private Dictionary UrlToBrowserTab { get; } = []; - private readonly object _sync = new(); + private readonly Lock _sync = new(); - private TabsFocusEventDispatcher _focusHandlerDispatcher; + private TabsFocusEventDispatcher? _focusHandlerDispatcher; private AutomationFocusChangedEventHandler? _focusHandler; private readonly HashSet _browserWindowsTracked = []; private bool _initialized; @@ -87,7 +89,7 @@ public class TabsTracker : IDisposable List windowsToUnsubscribe; lock (_sync) { - windowsToUnsubscribe = _browserWindowsTracked.ToList(); + windowsToUnsubscribe = [.. _browserWindowsTracked]; } foreach (var wnd in windowsToUnsubscribe) @@ -111,7 +113,7 @@ public class TabsTracker : IDisposable } } - private BrowserTab GetExistingTab(string url) + private BrowserTab? GetExistingTab(string url) { lock (_sync) { @@ -144,7 +146,7 @@ public class TabsTracker : IDisposable if (sender is not AutomationElement element) return; - int pid = 0; + var pid = 0; try { pid = element.Current.ProcessId; @@ -215,7 +217,7 @@ public class TabsTracker : IDisposable // break; case StructureChangeType.ChildRemoved: case StructureChangeType.ChildrenBulkRemoved: - AutomationElement foundWindow = null; + AutomationElement? foundWindow = null; lock (_sync) { foreach (var window in _browserWindowsTracked) @@ -245,7 +247,7 @@ public class TabsTracker : IDisposable private void UnsubscribeStructureChangedForWindow(AutomationElement wnd) { - bool contains = false; + var contains = false; lock (_sync) { contains = _browserWindowsTracked.Contains(wnd); diff --git a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsWalker.cs b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsWalker.cs index 346b3b4f7..6b1060e78 100644 --- a/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsWalker.cs +++ b/Plugins/Flow.Launcher.Plugin.BrowserBookmark/Tabs/TabsWalker.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; -using System.Threading.Tasks; using System.Windows.Automation; using BrowserTabs; using static Flow.Launcher.Plugin.BrowserBookmark.Main; @@ -45,13 +44,16 @@ internal class TabsWalker } } - private static BrowserTab InitiateTab(Process process, AutomationElement tab) => new() + private static BrowserTab InitiateTab(Process process, AutomationElement tab) { - Title = tab.Current.Name, - BrowserName = process.ProcessName, - Hwnd = process.MainWindowHandle, - AutomationElement = tab - }; + return new() + { + Title = tab.Current.Name, + BrowserName = process.ProcessName, + Hwnd = process.MainWindowHandle, + AutomationElement = tab + }; + } public BrowserTab GetCurrentTabFromWindow(AutomationElement mainWindow, Process process, CancellationToken cancellationToken) {