11import { canInjectScript } from '../background/utils/extension-api' ;
22import { createFileLoader } from './utils/network' ;
33import type { FetchRequestParameters } from './utils/network' ;
4- import type { MessageBGtoCS , MessageCStoBG , MessageUItoBG , documentId , frameId , scriptId , tabId } from '../definitions' ;
4+ import type { MessageBGtoCS , MessageCStoBG , MessageUItoBG } from '../definitions' ;
55import { isFirefox } from '../utils/platform' ;
66import { MessageTypeCStoBG , MessageTypeBGtoCS , MessageTypeUItoBG } from '../utils/message' ;
77import { ASSERT , logInfo , logWarn } from './utils/log' ;
@@ -16,14 +16,14 @@ declare const __CHROMIUM_MV3__: boolean;
1616declare const __THUNDERBIRD__ : boolean ;
1717
1818interface TabManagerOptions {
19- getConnectionMessage : ( tabURl : string , url : string , isTopFrame : boolean ) => Promise < MessageBGtoCS > ;
19+ getConnectionMessage : ( tabURl : string , url : string , isTopFrame : boolean , topFrameHasDarkTheme ?: boolean ) => Promise < MessageBGtoCS > ;
2020 getTabMessage : ( tabURL : string , url : string , isTopFrame : boolean ) => MessageBGtoCS ;
2121 onColorSchemeChange : ( isDark : boolean ) => void ;
2222}
2323
2424interface DocumentInfo {
25- scriptId : scriptId ;
26- documentId : documentId | null ;
25+ scriptId : string ;
26+ documentId : string | null ;
2727 isTop : true | undefined ;
2828 url : string | null ;
2929 state : DocumentState ;
@@ -32,7 +32,7 @@ interface DocumentInfo {
3232}
3333
3434interface TabManagerState extends Record < string , unknown > {
35- tabs : { [ tabId : tabId ] : { [ frameId : frameId ] : DocumentInfo } } ;
35+ tabs : { [ tabId : number ] : { [ frameId : number ] : DocumentInfo } } ;
3636 timestamp : number ;
3737}
3838
@@ -52,7 +52,7 @@ enum DocumentState {
5252
5353/**
5454 * Note: On Chromium builds, we use documentId if it is available.
55- * We avoid messaging using farmeId entirely since when document is prerendered , it gets a temporary frameId
55+ * We avoid messaging using frameId entirely since when document is pre-rendered , it gets a temporary frameId
5656 * and if we attempt to send to {frameId, documentId} with old frameId, then the message will be dropped.
5757 */
5858export default class TabManager {
@@ -78,8 +78,8 @@ export default class TabManager {
7878 case MessageTypeCStoBG . DOCUMENT_CONNECT : {
7979 TabManager . onColorSchemeMessage ( message , sender ) ;
8080 await TabManager . stateManager . loadState ( ) ;
81- const reply = ( tabURL : string , url : string , isTopFrame : boolean ) => {
82- getConnectionMessage ( tabURL , url , isTopFrame ) . then ( ( response ) => {
81+ const reply = ( tabURL : string , url : string , isTopFrame : boolean , topFrameHasDarkTheme ?: boolean ) => {
82+ getConnectionMessage ( tabURL , url , isTopFrame , topFrameHasDarkTheme ) . then ( ( response ) => {
8383 if ( ! response ) {
8484 return ;
8585 }
@@ -113,14 +113,15 @@ export default class TabManager {
113113 const url = sender . url ! ;
114114 const tabId = sender . tab ! . id ! ;
115115 const scriptId = message . scriptId ! ;
116+ const topFrameHasDarkTheme = isTopFrame ? false : TabManager . tabs [ tabId ] ?. [ 0 ] ?. darkThemeDetected ;
116117 // Chromium 106+ may prerender frames resulting in top-level frames with chrome.runtime.MessageSender.tab.url
117118 // set to chrome://newtab/ and positive chrome.runtime.MessageSender.frameId
118119 const tabURL = ( ( __CHROMIUM_MV2__ || __CHROMIUM_MV3__ ) && isTopFrame ) ? url : sender . tab ! . url ! ;
119- const documentId : documentId | null = __CHROMIUM_MV3__ ? sender . documentId ! : ( sender . documentId || null ) ;
120+ const documentId : string | null = __CHROMIUM_MV3__ ? sender . documentId ! : ( sender . documentId || null ) ;
120121
121122 TabManager . addFrame ( tabId , frameId ! , documentId , scriptId , url , isTopFrame ) ;
122123
123- reply ( tabURL , url , isTopFrame ) ;
124+ reply ( tabURL , url , isTopFrame , topFrameHasDarkTheme ) ;
124125 TabManager . stateManager . saveState ( ) ;
125126 break ;
126127 }
@@ -150,7 +151,7 @@ export default class TabManager {
150151 const tabURL = sender . tab ! . url ! ;
151152 const frameId = sender . frameId ! ;
152153 const url = sender . url ! ;
153- const documentId : documentId | null = __CHROMIUM_MV3__ ? sender . documentId ! : ( sender . documentId ! || null ) ;
154+ const documentId : string | null = __CHROMIUM_MV3__ ? sender . documentId ! : ( sender . documentId ! || null ) ;
154155 const isTopFrame : boolean = ( __CHROMIUM_MV2__ || __CHROMIUM_MV3__ ) ? ( frameId === 0 || message . data . isTopFrame ) : frameId === 0 ;
155156 if ( TabManager . tabs [ tabId ] [ frameId ] . timestamp < TabManager . timestamp ) {
156157 const response = TabManager . getTabMessage ( tabURL , url , isTopFrame ) ;
@@ -171,9 +172,23 @@ export default class TabManager {
171172 }
172173
173174 case MessageTypeCStoBG . DARK_THEME_DETECTED :
174- const frames = TabManager . tabs [ sender . tab ! . id ! ] ;
175- for ( const frame of Object . values ( frames ) ) {
175+ const tabId = sender . tab ! . id ! ;
176+ const frames = TabManager . tabs [ tabId ] ;
177+ if ( ! frames ) {
178+ break ;
179+ }
180+ for ( const entry of Object . entries ( frames ) ) {
181+ const frameId = Number ( entry [ 0 ] ) ;
182+ const frame = entry [ 1 ] ;
176183 frame . darkThemeDetected = true ;
184+ const { documentId, scriptId} = frame ;
185+ if ( sender . frameId === 0 && ! frame . isTop && frameId && documentId ) {
186+ const message = {
187+ type : MessageTypeBGtoCS . CLEAN_UP ,
188+ scriptId,
189+ } ;
190+ TabManager . sendDocumentMessage ( tabId , documentId , message , frameId ) ;
191+ }
177192 }
178193 break ;
179194
@@ -221,16 +236,16 @@ export default class TabManager {
221236 chrome . tabs . onRemoved . addListener ( async ( tabId ) => TabManager . removeFrame ( tabId , 0 ) ) ;
222237 }
223238
224- private static sendDocumentMessage ( tabId : tabId , documentId : documentId , message : MessageBGtoCS , frameId : frameId ) {
239+ private static sendDocumentMessage ( tabId : number , documentId : string , message : MessageBGtoCS , frameId : number ) {
225240 if ( __CHROMIUM_MV3__ ) {
226- // On MV3, Chromium has a bug which prevents sending messages to prerendered frames without specifying frameId
227- // Furethermore , if we send a message addressed to a temporary frameId after the document exits prerender state,
241+ // On MV3, Chromium has a bug which prevents sending messages to pre-rendered frames without specifying frameId
242+ // Furthermore , if we send a message addressed to a temporary frameId after the document exits prerender state,
228243 // the message will also fail to be delivered.
229244 //
230245 // To work around this:
231246 // 1. Attempt to send the message by documentId. If this fails, this means the document is in prerender state.
232- // 2. Attempt to send the message by dicumentId and temporary frameId. If this fails, this means the document
233- // either alteady exited prerendred state or was discarded.
247+ // 2. Attempt to send the message by documentId and temporary frameId. If this fails, this means the document
248+ // either already exited pre-rendered state or was discarded.
234249 // 3. Attempt to send the message by documentId (omitting the permanent frameId which is 0).If this fails, this
235250 // means the document was already discarded.
236251 //
@@ -262,8 +277,8 @@ export default class TabManager {
262277 }
263278 }
264279
265- private static addFrame ( tabId : tabId , frameId : frameId , documentId : documentId | null , scriptId : scriptId , url : string , isTop : boolean ) {
266- let frames : { [ frameId : frameId ] : DocumentInfo } ;
280+ private static addFrame ( tabId : number , frameId : number , documentId : string | null , scriptId : string , url : string , isTop : boolean ) {
281+ let frames : { [ frameId : number ] : DocumentInfo } ;
267282 if ( TabManager . tabs [ tabId ] ) {
268283 frames = TabManager . tabs [ tabId ] ;
269284 } else {
@@ -281,7 +296,7 @@ export default class TabManager {
281296 } ;
282297 }
283298
284- private static async removeFrame ( tabId : tabId , frameId : frameId ) {
299+ private static async removeFrame ( tabId : number , frameId : number ) {
285300 await TabManager . stateManager . loadState ( ) ;
286301
287302 if ( frameId === 0 ) {
@@ -300,7 +315,7 @@ export default class TabManager {
300315 static async getTabURL ( tab : chrome . tabs . Tab | null ) : Promise < string > {
301316 if ( __CHROMIUM_MV3__ ) {
302317 if ( ! tab ) {
303- return 'abou :blank' ;
318+ return 'about :blank' ;
304319 }
305320 try {
306321 if ( TabManager . tabs [ tab . id ! ] && TabManager . tabs [ tab . id ! ] [ 0 ] ) {
@@ -404,7 +419,7 @@ export default class TabManager {
404419 return tab && Boolean ( TabManager . tabs [ tab . id ! ] ) || false ;
405420 }
406421
407- static getTabDocumentId ( tab : chrome . tabs . Tab | null ) : documentId | null {
422+ static getTabDocumentId ( tab : chrome . tabs . Tab | null ) : string | null {
408423 return tab && TabManager . tabs [ tab . id ! ] && TabManager . tabs [ tab . id ! ] [ 0 ] && TabManager . tabs [ tab . id ! ] [ 0 ] . documentId ;
409424 }
410425
0 commit comments