@@ -38,11 +38,25 @@ chrome.alarms.onAlarm.addListener(async (alarm) => {
3838 if ( alarm . name === "version-check" ) {
3939 console . log ( "Version check alarm fired" ) ;
4040 if ( chromeUAStringManager ) {
41+ const previousUA = chromeUAStringManager . getUAString ( ) ;
42+
4143 await chromeUAStringManager . maybeRefreshRemote ( ) ;
4244 // Store updated spoofing data
4345 await chromeUAStringManager . storeSpoofingData ( ) ;
46+
47+ const newUA = chromeUAStringManager . getUAString ( ) ;
48+
4449 // After updating UA string, refresh DNR rules
4550 await updateDeclarativeNetRequestRules ( ) ;
51+
52+ // Only reload tabs if the UA string actually changed
53+ if ( previousUA !== newUA ) {
54+ console . log ( "UA string changed during version check, reloading affected tabs" ) ;
55+ const currentHostnames = new Set ( enabledHostnames . get_values ( ) ) ;
56+ await reloadAffectedTabsSelectively ( currentHostnames , currentHostnames , 'version_update' ) ;
57+ } else {
58+ console . log ( "UA string unchanged during version check, no reload needed" ) ;
59+ }
4660 }
4761 }
4862} ) ;
@@ -121,7 +135,16 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
121135 await chromeUAStringManager . setLinuxSpoofAsWindows ( msg . enabled ) ;
122136 await updateDeclarativeNetRequestRules ( ) ;
123137 await updateContentScriptRegistration ( ) ;
124- await reloadAffectedTabs ( ) ;
138+
139+ // Use the same logic as handleLinuxSpoofChanged for consistency
140+ const storage = await chrome . storage . local . get ( "linuxSpoofReloadAllTabs" ) ;
141+ if ( storage . linuxSpoofReloadAllTabs === true ) {
142+ console . log ( "Linux spoof reload all tabs enabled - reloading all enabled sites" ) ;
143+ const currentHostnames = new Set ( enabledHostnames . get_values ( ) ) ;
144+ await reloadAffectedTabsSelectively ( currentHostnames , currentHostnames , 'ua_change' ) ;
145+ } else {
146+ console . log ( "Linux spoof changed via message - headers updated, no reload" ) ;
147+ }
125148 }
126149 sendResponse ( { success : true } ) ;
127150 return ;
@@ -245,9 +268,15 @@ async function init() {
245268async function handleEnabledHostnamesChanged ( ) {
246269 console . log ( "Handling enabled hostnames changed" ) ;
247270
271+ // Get the previous hostname list before reloading
272+ const previousHostnames = new Set ( enabledHostnames . get_values ( ) ) ;
273+
248274 // Reload the hostnames list
249275 await enabledHostnames . load ( ) ;
250276
277+ // Get the new hostname list
278+ const currentHostnames = new Set ( enabledHostnames . get_values ( ) ) ;
279+
251280 // Refresh spoofing data in case UA string changed
252281 await chromeUAStringManager . storeSpoofingData ( ) ;
253282
@@ -257,13 +286,16 @@ async function handleEnabledHostnamesChanged() {
257286 // Update content script registration
258287 await updateContentScriptRegistration ( ) ;
259288
260- // Reload affected tabs
261- await reloadAffectedTabs ( ) ;
289+ // Use targeted reload strategy - reload only the specific sites that changed
290+ await reloadAffectedTabsSelectively ( previousHostnames , currentHostnames , 'hostname_change' ) ;
262291}
263292
264293async function handleLinuxSpoofChanged ( ) {
265294 console . log ( "Handling Linux spoof setting changed" ) ;
266295
296+ // Get current hostnames for selective reload
297+ const currentHostnames = new Set ( enabledHostnames . get_values ( ) ) ;
298+
267299 // Refresh spoofing data with new settings
268300 await chromeUAStringManager . storeSpoofingData ( ) ;
269301
@@ -273,8 +305,19 @@ async function handleLinuxSpoofChanged() {
273305 // Update content script registration
274306 await updateContentScriptRegistration ( ) ;
275307
276- // Reload affected tabs
277- await reloadAffectedTabs ( ) ;
308+ // For Linux spoof changes, we could be more conservative:
309+ // Most modern sites will pick up the new headers on subsequent requests
310+ // Only reload if user specifically wants immediate effect for all sites
311+ const storage = await chrome . storage . local . get ( "linuxSpoofReloadAllTabs" ) ;
312+ if ( storage . linuxSpoofReloadAllTabs === true ) {
313+ console . log ( "Linux spoof reload all tabs enabled - reloading all enabled sites" ) ;
314+ await reloadAffectedTabsSelectively ( currentHostnames , currentHostnames , 'ua_change' ) ;
315+ } else {
316+ console . log ( "Linux spoof change - headers updated, no tab reload (new requests will use new platform)" ) ;
317+ console . log ( " Benefits: No disruption to current browsing session" ) ;
318+ console . log ( " Effect: New requests and JavaScript will use updated platform info" ) ;
319+ console . log ( " Note: Set 'linuxSpoofReloadAllTabs' to true in storage for immediate reload behavior" ) ;
320+ }
278321}
279322
280323async function updateDeclarativeNetRequestRules ( ) {
@@ -693,7 +736,136 @@ async function updateBadgeStatus(tab) {
693736 }
694737}
695738
696- async function reloadAffectedTabs ( ) {
739+ /**
740+ * Selectively reload tabs based on the type of change that occurred.
741+ * This optimized approach reduces unnecessary tab reloads while maintaining spoofing functionality.
742+ *
743+ * @param {Set } previousHostnames - The hostname list before the change
744+ * @param {Set } currentHostnames - The hostname list after the change
745+ * @param {string } changeType - Type of change: 'hostname_change', 'ua_change', 'version_update', 'critical_update'
746+ */
747+ async function reloadAffectedTabsSelectively ( previousHostnames , currentHostnames , changeType ) {
748+ try {
749+ console . log ( `Selective tab reload for ${ changeType } :` , {
750+ previous : Array . from ( previousHostnames || [ ] ) ,
751+ current : Array . from ( currentHostnames || [ ] ) ,
752+ } ) ;
753+
754+ // Check for legacy reload mode preference (for advanced users who might need it)
755+ const storage = await chrome . storage . local . get ( "forceLegacyTabReload" ) ;
756+ if ( storage . forceLegacyTabReload === true ) {
757+ console . log ( "Legacy tab reload mode enabled - using original behavior" ) ;
758+ await reloadAffectedTabsLegacy ( ) ;
759+ return ;
760+ }
761+
762+ // For hostname changes, we only need to reload in specific scenarios
763+ if ( changeType === 'hostname_change' ) {
764+ // Calculate which hostnames were added or removed
765+ const added = new Set ( [ ...currentHostnames ] . filter ( x => ! previousHostnames . has ( x ) ) ) ;
766+ const removed = new Set ( [ ...previousHostnames ] . filter ( x => ! currentHostnames . has ( x ) ) ) ;
767+
768+ console . log ( "Hostname changes detected:" , {
769+ added : Array . from ( added ) ,
770+ removed : Array . from ( removed )
771+ } ) ;
772+
773+ // For sites being enabled (added), we need to reload them so spoofing takes effect immediately
774+ if ( added . size > 0 ) {
775+ const addedHostnames = Array . from ( added ) ;
776+ const matchPatterns = addedHostnames . map ( ( hostname ) => `*://${ hostname } /*` ) ;
777+
778+ const tabs = await chrome . tabs . query ( {
779+ url : matchPatterns ,
780+ } ) ;
781+
782+ for ( const tab of tabs ) {
783+ if ( tab . id !== chrome . tabs . TAB_ID_NONE ) {
784+ console . log ( `Reloading newly enabled site: ${ new URL ( tab . url ) . hostname } ` ) ;
785+ await chrome . tabs . reload ( tab . id , { bypassCache : true } ) ;
786+ }
787+ }
788+
789+ console . log ( `✅ Reloaded ${ tabs . length } tabs for newly enabled sites` ) ;
790+ }
791+
792+ // For sites being disabled (removed), no reload needed - they can continue as normal
793+ if ( removed . size > 0 ) {
794+ console . log ( `✅ ${ removed . size } sites disabled - no reload needed (graceful degradation)` ) ;
795+ }
796+
797+ // If no actual changes, skip entirely
798+ if ( added . size === 0 && removed . size === 0 ) {
799+ console . log ( "✅ No hostname changes detected - skipping reload" ) ;
800+ }
801+
802+ console . log ( " Benefits: Only affected sites reloaded, others remain undisturbed" ) ;
803+ return ;
804+ }
805+
806+ // For UA changes (like Linux spoof toggle), reload all currently enabled sites
807+ if ( changeType === 'ua_change' ) {
808+ const hostnames = Array . from ( currentHostnames ) ;
809+ if ( hostnames . length === 0 ) {
810+ console . log ( "No enabled hostnames for UA change reload" ) ;
811+ return ;
812+ }
813+
814+ const matchPatterns = hostnames . map ( ( hostname ) => `*://${ hostname } /*` ) ;
815+
816+ // Query for tabs that match our patterns
817+ const tabs = await chrome . tabs . query ( {
818+ url : matchPatterns ,
819+ } ) ;
820+
821+ // Reload each affected tab
822+ for ( const tab of tabs ) {
823+ if ( tab . id !== chrome . tabs . TAB_ID_NONE ) {
824+ await chrome . tabs . reload ( tab . id , { bypassCache : true } ) ;
825+ }
826+ }
827+
828+ console . log ( `Reloaded ${ tabs . length } tabs due to UA string change` ) ;
829+ return ;
830+ }
831+
832+ // For version updates or other critical changes, reload all enabled sites
833+ if ( changeType === 'version_update' || changeType === 'critical_update' ) {
834+ const hostnames = Array . from ( currentHostnames ) ;
835+ if ( hostnames . length === 0 ) {
836+ console . log ( "No enabled hostnames for version update reload" ) ;
837+ return ;
838+ }
839+
840+ const matchPatterns = hostnames . map ( ( hostname ) => `*://${ hostname } /*` ) ;
841+
842+ // Query for tabs that match our patterns
843+ const tabs = await chrome . tabs . query ( {
844+ url : matchPatterns ,
845+ } ) ;
846+
847+ // Reload each affected tab
848+ for ( const tab of tabs ) {
849+ if ( tab . id !== chrome . tabs . TAB_ID_NONE ) {
850+ await chrome . tabs . reload ( tab . id , { bypassCache : true } ) ;
851+ }
852+ }
853+
854+ console . log ( `Reloaded ${ tabs . length } tabs due to ${ changeType } ` ) ;
855+ return ;
856+ }
857+
858+ console . log ( `Unknown change type: ${ changeType } , skipping reload` ) ;
859+ } catch ( error ) {
860+ console . error ( "Error in selective tab reload:" , error ) ;
861+ // Fallback to legacy behavior on error
862+ console . log ( "Falling back to legacy reload behavior" ) ;
863+ await reloadAffectedTabsLegacy ( ) ;
864+ }
865+ }
866+
867+ // Keep the original function as a fallback for critical scenarios
868+ async function reloadAffectedTabsLegacy ( ) {
697869 try {
698870 const hostnames = Array . from ( enabledHostnames . get_values ( ) ) ;
699871 if ( hostnames . length === 0 ) {
@@ -714,9 +886,9 @@ async function reloadAffectedTabs() {
714886 }
715887 }
716888
717- console . log ( `Reloaded ${ tabs . length } affected tabs` ) ;
889+ console . log ( `Legacy reload: Reloaded ${ tabs . length } affected tabs` ) ;
718890 } catch ( error ) {
719- console . error ( "Error reloading affected tabs:" , error ) ;
891+ console . error ( "Error reloading affected tabs (legacy) :" , error ) ;
720892 }
721893}
722894
0 commit comments