11import browser from 'webextension-polyfill' ;
2- import { RULE_MATCH_TYPE , RULE_TYPE } from '@/share/core/constant' ;
2+ import { RULE_MATCH_TYPE , RULE_TYPE , TABLE_NAMES } from '@/share/core/constant' ;
33import emitter from '@/share/core/emitter' ;
44import { prefs } from '@/share/core/prefs' ;
55import { detectRunner } from '@/share/core/rule-utils' ;
66import type { Rule , RULE_ACTION_OBJ } from '@/share/core/types' ;
7- import { getVirtualKey } from '@/share/core/utils' ;
8- import { getAll } from '../core/rules' ;
7+ import { getTableName } from '@/share/core/utils' ;
8+ import { getAll , waitLoad } from '../core/rules' ;
99import type { DeclarativeNetRequest } from 'webextension-polyfill/namespaces/declarativeNetRequest' ;
1010
1111type DNRRule = DeclarativeNetRequest . Rule ;
@@ -98,9 +98,20 @@ function createDNR(rule: Rule, id: number) {
9898 return res ;
9999}
100100
101+ function getRuleId ( id : number , table ?: TABLE_NAMES , ruleType ?: RULE_TYPE ) {
102+ const list = {
103+ [ TABLE_NAMES . request ] : 0 ,
104+ [ TABLE_NAMES . sendHeader ] : 10000 ,
105+ [ TABLE_NAMES . receiveHeader ] : 20000 ,
106+ [ TABLE_NAMES . receiveBody ] : 30000 ,
107+ } ;
108+
109+ const t = table || getTableName ( ruleType || RULE_TYPE . REDIRECT ) ;
110+
111+ return Number ( id ) + list [ t ] ;
112+ }
113+
101114class DNRRequestHandler {
102- private lastRuleId = 1 ;
103- private ruleIdMap : Map < string , number > = new Map ( ) ;
104115 private _disableAll = false ;
105116
106117 constructor ( ) {
@@ -126,45 +137,31 @@ class DNRRequestHandler {
126137 }
127138
128139 private async clearRules ( ) {
129- const ids = Array . from ( this . ruleIdMap . values ( ) ) ;
140+ const current = await browser . declarativeNetRequest . getSessionRules ( ) ;
130141 await browser . declarativeNetRequest . updateSessionRules ( {
131- removeRuleIds : ids ,
142+ removeRuleIds : current . map ( ( x ) => x . id ) ,
132143 } ) ;
133- this . ruleIdMap . clear ( ) ;
134144 }
135145
136146 private async initRules ( ) {
137- const v = Object . values ( getAll ( ) ) ;
147+ await waitLoad ( ) ;
138148
139- if ( v . some ( ( x ) => x === null ) ) {
140- // rule not ready
141- setTimeout ( ( ) => this . initRules ( ) ) ;
142- return ;
143- }
149+ const v = Object . values ( getAll ( ) ) ;
144150
145151 // if service worker restart, get exists rules
146- if ( MANIFEST_VER === 'v3' ) {
147- const data : any = ( await browser . storage . session . get ( 'dnr_handler' ) ) . dnr_handler ;
148- if ( data ) {
149- this . lastRuleId = data . lastRuleId || 1 ;
150- Object . entries ( data . ruleIdMap || { } ) . forEach ( ( [ key , val ] ) => {
151- this . ruleIdMap . set ( key , Number ( val ) ) ;
152- } ) ;
153- } else {
154- // clear all exists rules
155- await this . clearRules ( ) ;
156- }
157- }
158-
152+ const current = ( await browser . declarativeNetRequest . getSessionRules ( ) ) . map ( ( x ) => x . id ) ;
159153 const allRules = v . reduce ( ( a , b ) => [ ...a ! , ...b ! ] , [ ] ) || [ ] ;
160154 const addRules : DNRRule [ ] = [ ] ;
161155 allRules . forEach ( ( rule ) => {
162156 if ( rule . _runner !== 'dnr' ) {
163157 return ;
164158 }
165- const newRuleId = this . lastRuleId ++ ;
166- this . ruleIdMap . set ( getVirtualKey ( rule ) , newRuleId ) ;
167- addRules . push ( createDNR ( rule , newRuleId ) ) ;
159+ const ruleId = getRuleId ( rule . id , undefined , rule . ruleType ) ;
160+ if ( current . includes ( ruleId ) ) {
161+ // rule exists
162+ return ;
163+ }
164+ addRules . push ( createDNR ( rule , ruleId ) ) ;
168165 } ) ;
169166 if ( IS_DEV ) {
170167 console . log ( 'init dnr rules' , addRules ) ;
@@ -173,43 +170,33 @@ class DNRRequestHandler {
173170 browser . declarativeNetRequest . updateSessionRules ( {
174171 addRules,
175172 } ) ;
176- this . updateStorage ( ) ;
177173 }
178174 }
179175
180176 private initHook ( ) {
181177 emitter . on ( emitter . INNER_RULE_REMOVE , ( { table, id } ) => {
182- const old = this . ruleIdMap . get ( `${ table } -${ id } ` ) ;
183- if ( typeof old === 'number' ) {
184- browser . declarativeNetRequest . updateSessionRules ( {
185- removeRuleIds : [ old ] ,
186- } ) ;
187- this . ruleIdMap . delete ( `${ table } -${ id } ` ) ;
188- this . updateStorage ( ) ;
189- }
178+ const old = getRuleId ( id , table ) ;
179+ browser . declarativeNetRequest . updateSessionRules ( {
180+ removeRuleIds : [ old ] ,
181+ } ) ;
190182 } ) ;
191183
192- emitter . on ( emitter . INNER_RULE_UPDATE , ( { from, target } ) => {
184+ emitter . on ( emitter . INNER_RULE_UPDATE , ( { from, target } : { from : Rule ; target : Rule } ) => {
193185 const command : DeclarativeNetRequest . UpdateSessionRulesOptionsType = {
194186 removeRuleIds : [ ] ,
195187 addRules : [ ] ,
196188 } ;
197189 if ( from ) {
198- const old = this . ruleIdMap . get ( getVirtualKey ( from ) ) ;
199- if ( typeof old === 'number' ) {
200- command . removeRuleIds ! . push ( old ) ;
201- }
190+ const old = getRuleId ( from . id , undefined , from . ruleType ) ;
191+ command . removeRuleIds ! . push ( old ) ;
202192 }
203193 // detect new rule is DNR or not
204194 if ( detectRunner ( target ) === 'dnr' ) {
205- const newRuleId = this . lastRuleId ++ ;
206- this . ruleIdMap . set ( getVirtualKey ( target ) , newRuleId ) ;
207- command . addRules ! . push ( createDNR ( target , newRuleId ) ) ;
195+ command . addRules ! . push ( createDNR ( target , getRuleId ( target . id , undefined , target . ruleType ) ) ) ;
208196 }
209197 if ( IS_DEV ) {
210198 console . log ( 'dnr rules update' , command ) ;
211199 }
212- this . updateStorage ( ) ;
213200 browser . declarativeNetRequest . updateSessionRules ( command ) ;
214201 } ) ;
215202 }
@@ -229,17 +216,6 @@ class DNRRequestHandler {
229216 this . disableAll = Boolean ( prefs . get ( 'disable-all' ) ) ;
230217 } ) ;
231218 }
232-
233- private updateStorage ( ) {
234- if ( MANIFEST_VER === 'v3' ) {
235- browser . storage . session . set ( {
236- dnr_handler : {
237- lastRuleId : this . lastRuleId ,
238- ruleIdMap : Object . fromEntries ( this . ruleIdMap ) ,
239- } ,
240- } ) ;
241- }
242- }
243219}
244220
245221export const createDNRHandler = ( ) => new DNRRequestHandler ( ) ;
0 commit comments