Skip to content

Commit 8fb7cec

Browse files
committed
feat: optimize tab reload system for improved UX
- Only reload newly enabled sites instead of all masked sites - Skip reload for disabled sites (graceful degradation) - Make Linux spoof toggle non-disruptive by default - Add configurable reload behavior for power users - Maintain legacy fallback for edge cases - Eliminate unnecessary tab refreshes while preserving full functionality
1 parent 4c367bd commit 8fb7cec

File tree

4 files changed

+224
-10
lines changed

4 files changed

+224
-10
lines changed

Changelog.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,47 @@
11
# Changelog - Chrome Mask for Opera
22

3+
## 1.4.0 (Smart Tab Reload Optimization) - July 2025
4+
5+
**🚀 Performance & User Experience Enhancement**
6+
7+
Implemented intelligent tab reload system that significantly reduces unnecessary tab refreshes while maintaining full spoofing functionality.
8+
9+
### ✨ Key Improvements
10+
11+
- **Smart Tab Reload**: Only reloads specific sites being toggled, not all masked sites
12+
- **Immediate Spoofing Effect**: Sites being enabled get reloaded so spoofing takes effect instantly
13+
- **Graceful Disabling**: Sites being disabled continue without disruption
14+
- **Optimized Linux Spoof**: Platform changes apply to new requests without disrupting current tabs
15+
- **Configurable Reload Behavior**: Advanced users can control when tabs get reloaded
16+
- **Legacy Mode Option**: Advanced users can enable `forceLegacyTabReload` in storage for original behavior if needed
17+
18+
### 🔧 Technical Details
19+
20+
- **Adding Sites**: Automatically reloads only the newly added site so headers update immediately
21+
- **Removing Sites**: No reload needed - sites continue normally without spoofing
22+
- **Linux Platform Toggle**: Headers updated immediately, optional reload via `linuxSpoofReloadAllTabs` setting
23+
- **UA String Changes**: Smart reload only when User-Agent actually changes (version updates)
24+
- **Fallback Behavior**: Maintains legacy reload functionality for critical scenarios
25+
- **Enhanced Logging**: Better debugging information for reload decisions
26+
27+
### 🎯 Benefits
28+
29+
- **Instant Effect**: Toggling a site on immediately applies spoofing (no manual refresh needed)
30+
- **No More Disruption**: Other sites remain untouched when toggling unrelated sites
31+
- **Faster Operations**: Only affected sites reload, others continue uninterrupted
32+
- **Same Functionality**: All spoofing capabilities remain fully intact
33+
34+
### 🔄 Behavior Comparison
35+
36+
| Action | Old Behavior | New Behavior |
37+
|--------|-------------|--------------|
38+
| Enable site A | Reload ALL masked sites | Reload only site A |
39+
| Disable site A | Reload ALL masked sites | No reload (graceful) |
40+
| Linux spoof toggle | Reload ALL sites | No reload (headers update immediately)* |
41+
| Chrome version update | Always reload | Reload only if UA changed |
42+
43+
*_Set `linuxSpoofReloadAllTabs: true` in storage for immediate reload if needed_
44+
345
## 1.3.0 (Robust Enhancement) - July 2025
446

547
**🚀 Enhanced Robustness & Performance**

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "chrome-mask-for-opera",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "Makes Opera wear a Chrome mask for better website compatibility.",
55
"author": "mr-september",
66
"license": "MIT",

src/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "__MSG_extensionDescription__",
55
"author": "mr-september",
66
"homepage_url": "https://github.com/mr-september/chrome-mask-for-opera",
7-
"version": "1.3.0",
7+
"version": "1.4.0",
88
"default_locale": "en",
99
"permissions": [
1010
"storage",

src/service-worker.js

Lines changed: 180 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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() {
245268
async 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

264293
async 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

280323
async 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

Comments
 (0)