@@ -58,28 +58,31 @@ const RECONNECT_CONFIG = {
58
58
} ;
59
59
60
60
const SENSITIVE_KEYWORDS = [
61
- 'apikey' , // Covers apiKey, customApiKey, claudeApiKey, etc.
62
- 'token' , // Covers accessToken, refreshToken, etc.
61
+ 'apikey' ,
62
+ 'token' ,
63
63
'secret' ,
64
64
'password' ,
65
65
'kimimoonshotrefreshtoken' ,
66
+ 'auth' ,
67
+ 'key' ,
68
+ 'credential' ,
66
69
] ;
67
70
68
- function redactSensitiveFields ( obj , recursionDepth = 0 , maxDepth = 5 ) {
71
+ function redactSensitiveFields ( obj , recursionDepth = 0 , maxDepth = 5 , seen = new WeakSet ( ) ) {
69
72
if ( recursionDepth > maxDepth ) {
70
- // Prevent infinite recursion on circular objects or excessively deep structures
71
73
return 'REDACTED_TOO_DEEP' ;
72
74
}
73
- // Handle null, primitives, and functions directly
74
75
if ( obj === null || typeof obj !== 'object' ) {
75
76
return obj ;
76
77
}
77
78
78
- // Create a new object or array to store redacted fields, ensuring original is not modified
79
- const redactedObj = Array . isArray ( obj ) ? [ ] : { } ;
79
+ if ( seen . has ( obj ) ) {
80
+ return 'REDACTED_CIRCULAR_REFERENCE' ;
81
+ }
82
+ seen . add ( obj ) ;
80
83
84
+ const redactedObj = Array . isArray ( obj ) ? [ ] : { } ;
81
85
for ( const key in obj ) {
82
- // Ensure we're only processing own properties
83
86
if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) {
84
87
const lowerKey = key . toLowerCase ( ) ;
85
88
let isSensitive = false ;
@@ -89,14 +92,11 @@ function redactSensitiveFields(obj, recursionDepth = 0, maxDepth = 5) {
89
92
break ;
90
93
}
91
94
}
92
-
93
95
if ( isSensitive ) {
94
96
redactedObj [ key ] = 'REDACTED' ;
95
97
} else if ( typeof obj [ key ] === 'object' ) {
96
- // If the value is an object (or array), recurse
97
- redactedObj [ key ] = redactSensitiveFields ( obj [ key ] , recursionDepth + 1 , maxDepth ) ;
98
+ redactedObj [ key ] = redactSensitiveFields ( obj [ key ] , recursionDepth + 1 , maxDepth , seen ) ;
98
99
} else {
99
- // Otherwise, copy the value as is
100
100
redactedObj [ key ] = obj [ key ] ;
101
101
}
102
102
}
@@ -108,7 +108,6 @@ function setPortProxy(port, proxyTabId) {
108
108
try {
109
109
console . debug ( `[background] Attempting to connect to proxy tab: ${ proxyTabId } ` )
110
110
111
- // Ensure old listeners on port.proxy are removed if it exists
112
111
if ( port . proxy ) {
113
112
try {
114
113
if ( port . _proxyOnMessage ) port . proxy . onMessage . removeListener ( port . _proxyOnMessage ) ;
@@ -117,14 +116,12 @@ function setPortProxy(port, proxyTabId) {
117
116
console . warn ( '[background] Error removing old listeners from previous port.proxy instance:' , e ) ;
118
117
}
119
118
}
120
- // Also remove listeners from the main port object that this function might have added in a previous call for this port instance
121
119
if ( port . _portOnMessage ) port . onMessage . removeListener ( port . _portOnMessage ) ;
122
120
if ( port . _portOnDisconnect ) port . onDisconnect . removeListener ( port . _portOnDisconnect ) ;
123
121
124
-
125
122
port . proxy = Browser . tabs . connect ( proxyTabId , { name : 'background-to-content-script-proxy' } )
126
123
console . debug ( `[background] Successfully connected to proxy tab: ${ proxyTabId } ` )
127
- port . _reconnectAttempts = 0 // Reset retry count on successful connection
124
+ port . _reconnectAttempts = 0
128
125
129
126
port . _proxyOnMessage = ( msg ) => {
130
127
console . debug ( '[background] Message from proxy tab:' , msg )
@@ -142,18 +139,19 @@ function setPortProxy(port, proxyTabId) {
142
139
port . _proxyOnDisconnect = ( ) => {
143
140
console . warn ( `[background] Proxy tab ${ proxyTabId } disconnected.` )
144
141
145
- // Cleanup this specific proxy's listeners before setting port.proxy to null
146
- if ( port . proxy ) { // Check if port.proxy is still valid
142
+ const proxyRef = port . proxy ;
143
+ port . proxy = null
144
+
145
+ if ( proxyRef ) {
147
146
if ( port . _proxyOnMessage ) {
148
- try { port . proxy . onMessage . removeListener ( port . _proxyOnMessage ) ; }
149
- catch ( e ) { console . warn ( "[background] Error removing _proxyOnMessage from disconnected port.proxy :" , e ) ; }
147
+ try { proxyRef . onMessage . removeListener ( port . _proxyOnMessage ) ; }
148
+ catch ( e ) { console . warn ( "[background] Error removing _proxyOnMessage from disconnected proxyRef :" , e ) ; }
150
149
}
151
- if ( port . _proxyOnDisconnect ) { // port._proxyOnDisconnect is this function itself
152
- try { port . proxy . onDisconnect . removeListener ( port . _proxyOnDisconnect ) ; }
153
- catch ( e ) { console . warn ( "[background] Error removing _proxyOnDisconnect from disconnected port.proxy :" , e ) ; }
150
+ if ( port . _proxyOnDisconnect ) {
151
+ try { proxyRef . onDisconnect . removeListener ( port . _proxyOnDisconnect ) ; }
152
+ catch ( e ) { console . warn ( "[background] Error removing _proxyOnDisconnect from disconnected proxyRef :" , e ) ; }
154
153
}
155
154
}
156
- port . proxy = null // Clear the old proxy
157
155
158
156
port . _reconnectAttempts = ( port . _reconnectAttempts || 0 ) + 1 ;
159
157
if ( port . _reconnectAttempts > RECONNECT_CONFIG . MAX_ATTEMPTS ) {
@@ -162,7 +160,6 @@ function setPortProxy(port, proxyTabId) {
162
160
try { port . onMessage . removeListener ( port . _portOnMessage ) ; }
163
161
catch ( e ) { console . warn ( "[background] Error removing _portOnMessage on max retries:" , e ) ; }
164
162
}
165
- // Note: _portOnDisconnect on the main port should remain to handle its eventual disconnection.
166
163
return ;
167
164
}
168
165
@@ -171,7 +168,7 @@ function setPortProxy(port, proxyTabId) {
171
168
172
169
setTimeout ( ( ) => {
173
170
console . debug ( `[background] Retrying connection to tab ${ proxyTabId } , attempt ${ port . _reconnectAttempts } .` ) ;
174
- setPortProxy ( port , proxyTabId ) ; // Reconnect
171
+ setPortProxy ( port , proxyTabId ) ;
175
172
} , delay ) ;
176
173
}
177
174
@@ -181,23 +178,24 @@ function setPortProxy(port, proxyTabId) {
181
178
try { port . onMessage . removeListener ( port . _portOnMessage ) ; }
182
179
catch ( e ) { console . warn ( "[background] Error removing _portOnMessage on main port disconnect:" , e ) ; }
183
180
}
184
- if ( port . proxy ) {
181
+ const proxyRef = port . proxy ;
182
+ if ( proxyRef ) {
185
183
if ( port . _proxyOnMessage ) {
186
- try { port . proxy . onMessage . removeListener ( port . _proxyOnMessage ) ; }
187
- catch ( e ) { console . warn ( "[background] Error removing _proxyOnMessage from port.proxy on main port disconnect:" , e ) ; }
184
+ try { proxyRef . onMessage . removeListener ( port . _proxyOnMessage ) ; }
185
+ catch ( e ) { console . warn ( "[background] Error removing _proxyOnMessage from proxyRef on main port disconnect:" , e ) ; }
188
186
}
189
187
if ( port . _proxyOnDisconnect ) {
190
- try { port . proxy . onDisconnect . removeListener ( port . _proxyOnDisconnect ) ; }
191
- catch ( e ) { console . warn ( "[background] Error removing _proxyOnDisconnect from port.proxy on main port disconnect:" , e ) ; }
188
+ try { proxyRef . onDisconnect . removeListener ( port . _proxyOnDisconnect ) ; }
189
+ catch ( e ) { console . warn ( "[background] Error removing _proxyOnDisconnect from proxyRef on main port disconnect:" , e ) ; }
192
190
}
193
191
try {
194
- port . proxy . disconnect ( ) ;
192
+ proxyRef . disconnect ( ) ;
195
193
} catch ( e ) {
196
- console . warn ( '[background] Error disconnecting port.proxy on main port disconnect:' , e ) ;
194
+ console . warn ( '[background] Error disconnecting proxyRef on main port disconnect:' , e ) ;
197
195
}
198
196
port . proxy = null ;
199
197
}
200
- if ( port . _portOnDisconnect ) { // Remove self from main port
198
+ if ( port . _portOnDisconnect ) {
201
199
try { port . onDisconnect . removeListener ( port . _portOnDisconnect ) ; }
202
200
catch ( e ) { console . warn ( "[background] Error removing _portOnDisconnect on main port disconnect:" , e ) ; }
203
201
}
@@ -218,10 +216,8 @@ async function executeApi(session, port, config) {
218
216
console . log (
219
217
`[background] executeApi called for model: ${ session . modelName } , apiMode: ${ session . apiMode } ` ,
220
218
)
221
- // Use the new helper function for session and config details
222
219
console . debug ( '[background] Full session details (redacted):' , redactSensitiveFields ( session ) )
223
220
console . debug ( '[background] Full config details (redacted):' , redactSensitiveFields ( config ) )
224
- // Specific redaction for session.apiMode if it exists, as it's part of the session object
225
221
if ( session . apiMode ) {
226
222
console . debug ( '[background] Session apiMode details (redacted):' , redactSensitiveFields ( session . apiMode ) )
227
223
}
@@ -481,9 +477,7 @@ Browser.runtime.onMessage.addListener(async (message, sender) => {
481
477
'Original message:' ,
482
478
message ,
483
479
)
484
- // Consider if a response is expected and how to send an error response
485
480
if ( message . type === 'FETCH' ) {
486
- // FETCH expects a response
487
481
return [ null , { message : error . message , stack : error . stack } ]
488
482
}
489
483
}
@@ -540,13 +534,15 @@ try {
540
534
const headers = details . requestHeaders
541
535
let modified = false
542
536
for ( let i = 0 ; i < headers . length ; i ++ ) {
543
- const headerNameLower = headers [ i ] ?. name ?. toLowerCase ( ) ; // Apply optional chaining
544
- if ( headerNameLower === 'origin' ) {
545
- headers [ i ] . value = 'https://www.bing.com'
546
- modified = true
547
- } else if ( headerNameLower === 'referer' ) {
548
- headers [ i ] . value = 'https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx'
549
- modified = true
537
+ if ( headers [ i ] ) {
538
+ const headerNameLower = headers [ i ] . name ?. toLowerCase ( ) ;
539
+ if ( headerNameLower === 'origin' ) {
540
+ headers [ i ] . value = 'https://www.bing.com'
541
+ modified = true
542
+ } else if ( headerNameLower === 'referer' ) {
543
+ headers [ i ] . value = 'https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx'
544
+ modified = true
545
+ }
550
546
}
551
547
}
552
548
if ( modified ) {
@@ -559,45 +555,73 @@ try {
559
555
error ,
560
556
details ,
561
557
)
562
- return { requestHeaders : details . requestHeaders } // Return original headers on error
558
+ return { requestHeaders : details . requestHeaders }
563
559
}
564
560
} ,
565
561
{
566
562
urls : [ 'wss://sydney.bing.com/*' , 'https://www.bing.com/*' ] ,
567
563
types : [ 'xmlhttprequest' , 'websocket' ] ,
568
564
} ,
569
- // Use 'blocking' for modifying request headers, and ensure permissions are set in manifest
570
565
[ 'blocking' , 'requestHeaders' ] ,
571
566
)
572
567
573
568
Browser . tabs . onUpdated . addListener ( async ( tabId , info , tab ) => {
569
+ const outerTryCatchError = ( error ) => { // Renamed to avoid conflict with inner error
570
+ console . error ( '[background] Error in tabs.onUpdated listener callback (outer):' , error , tabId , info ) ;
571
+ } ;
574
572
try {
575
- // Refined condition: Ensure URL exists and tab loading is complete.
576
573
if ( ! tab . url || ( info . status && info . status !== 'complete' ) ) {
577
574
console . debug (
578
575
`[background] Skipping side panel update for tabId: ${ tabId } . Tab URL: ${ tab . url } , Info Status: ${ info . status } ` ,
579
- )
580
- return
576
+ ) ;
577
+ return ;
581
578
}
582
579
console . debug (
583
580
`[background] tabs.onUpdated event for tabId: ${ tabId } , status: ${ info . status } , url: ${ tab . url } . Proceeding with side panel update.` ,
584
- )
585
- // Use Browser.sidePanel from webextension-polyfill for consistency and cross-browser compatibility
586
- if ( Browser . sidePanel ) {
587
- await Browser . sidePanel . setOptions ( {
588
- tabId,
589
- path : 'IndependentPanel.html' ,
590
- enabled : true ,
591
- } )
592
- console . debug ( `[background] Side panel options set for tab ${ tabId } using Browser.sidePanel` )
593
- } else {
594
- // Log if Browser.sidePanel is somehow not available (polyfill should generally handle this)
595
- console . warn ( '[background] Browser.sidePanel API not available. Side panel options not set.' )
581
+ ) ;
582
+
583
+ let sidePanelSet = false ;
584
+ try {
585
+ if ( Browser . sidePanel && typeof Browser . sidePanel . setOptions === 'function' ) {
586
+ await Browser . sidePanel . setOptions ( {
587
+ tabId,
588
+ path : 'IndependentPanel.html' ,
589
+ enabled : true ,
590
+ } ) ;
591
+ console . debug ( `[background] Side panel options set for tab ${ tabId } using Browser.sidePanel` ) ;
592
+ sidePanelSet = true ;
593
+ }
594
+ } catch ( browserError ) {
595
+ console . warn ( '[background] Browser.sidePanel.setOptions failed:' , browserError . message ) ;
596
+ // Fallback will be attempted below if sidePanelSet is still false
597
+ }
598
+
599
+ if ( ! sidePanelSet ) {
600
+ // eslint-disable-next-line no-undef
601
+ if ( typeof chrome !== 'undefined' && chrome . sidePanel && typeof chrome . sidePanel . setOptions === 'function' ) {
602
+ console . debug ( '[background] Attempting chrome.sidePanel.setOptions as fallback.' ) ;
603
+ try {
604
+ // eslint-disable-next-line no-undef
605
+ await chrome . sidePanel . setOptions ( {
606
+ tabId,
607
+ path : 'IndependentPanel.html' ,
608
+ enabled : true ,
609
+ } ) ;
610
+ console . debug ( `[background] Side panel options set for tab ${ tabId } using chrome.sidePanel` ) ;
611
+ sidePanelSet = true ;
612
+ } catch ( chromeError ) {
613
+ console . error ( '[background] chrome.sidePanel.setOptions also failed:' , chromeError . message ) ;
614
+ }
615
+ }
596
616
}
597
- } catch ( error ) {
598
- console . error ( '[background] Error in tabs.onUpdated listener callback:' , error , tabId , info )
617
+
618
+ if ( ! sidePanelSet ) {
619
+ console . warn ( '[background] SidePanel API (Browser.sidePanel or chrome.sidePanel) not available or setOptions failed in this browser. Side panel options not set for tab:' , tabId ) ;
620
+ }
621
+ } catch ( error ) { // This is the outer try-catch from the original code
622
+ outerTryCatchError ( error ) ;
599
623
}
600
- } )
624
+ } ) ;
601
625
} catch ( error ) {
602
626
console . error ( '[background] Error setting up webRequest or tabs listeners:' , error )
603
627
}
0 commit comments