26
26
import cacheStorage from './cachestorage.js' ;
27
27
import logger from './logger.js' ;
28
28
import µb from './background.js' ;
29
+ import { ubolog } from './console.js' ;
29
30
import { i18n$ } from './i18n.js' ;
30
31
import * as sfp from './static-filtering-parser.js' ;
31
- import { ubolog } from './console .js' ;
32
+ import { orphanizeString , } from './text-utils .js' ;
32
33
33
34
/******************************************************************************/
34
35
@@ -47,6 +48,8 @@ let remoteServerFriendly = false;
47
48
48
49
/******************************************************************************/
49
50
51
+ const stringIsNotEmpty = s => typeof s === 'string' && s !== '' ;
52
+
50
53
const parseExpires = s => {
51
54
const matches = s . match ( / ( \d + ) \s * ( [ d h ] ) ? / i) ;
52
55
if ( matches === null ) { return 0 ; }
@@ -71,7 +74,7 @@ const extractMetadataFromList = (content, fields) => {
71
74
field = field . toLowerCase ( ) . replace (
72
75
/ - [ a - z ] / g, s => s . charAt ( 1 ) . toUpperCase ( )
73
76
) ;
74
- out [ field ] = value ;
77
+ out [ field ] = value && orphanizeString ( value ) ;
75
78
}
76
79
// Pre-process known fields
77
80
if ( out . lastModified ) {
@@ -169,7 +172,44 @@ const isDiffUpdatableAsset = content => {
169
172
/ ^ [ ^ % ] .* [ ^ % ] $ / . test ( data . diffPath ) ;
170
173
} ;
171
174
172
- const stringIsNotEmpty = s => typeof s === 'string' && s !== '' ;
175
+ /******************************************************************************/
176
+
177
+ // favorLocal: avoid making network requests whenever possible
178
+ // favorOrigin: avoid using CDN URLs whenever possible
179
+
180
+ const getContentURLs = ( assetKey , options = { } ) => {
181
+ const contentURLs = [ ] ;
182
+ const entry = assetSourceRegistry [ assetKey ] ;
183
+ if ( entry instanceof Object === false ) { return contentURLs ; }
184
+ if ( typeof entry . contentURL === 'string' ) {
185
+ contentURLs . push ( entry . contentURL ) ;
186
+ } else if ( Array . isArray ( entry . contentURL ) ) {
187
+ contentURLs . push ( ...entry . contentURL ) ;
188
+ } else if ( reIsExternalPath . test ( assetKey ) ) {
189
+ contentURLs . push ( assetKey ) ;
190
+ }
191
+ if ( options . favorLocal ) {
192
+ contentURLs . sort ( ( a , b ) => {
193
+ if ( reIsExternalPath . test ( a ) ) { return 1 ; }
194
+ if ( reIsExternalPath . test ( b ) ) { return - 1 ; }
195
+ return 0 ;
196
+ } ) ;
197
+ }
198
+ if ( Array . isArray ( entry . cdnURLs ) ) {
199
+ const cdnURLs = entry . cdnURLs . slice ( ) ;
200
+ for ( let i = 0 , n = cdnURLs . length ; i < n ; i ++ ) {
201
+ const j = Math . floor ( Math . random ( ) * n ) ;
202
+ if ( j === i ) { continue ; }
203
+ [ cdnURLs [ j ] , cdnURLs [ i ] ] = [ cdnURLs [ i ] , cdnURLs [ j ] ] ;
204
+ }
205
+ if ( options . favorLocal || options . favorOrigin ) {
206
+ contentURLs . push ( ...cdnURLs ) ;
207
+ } else {
208
+ contentURLs . unshift ( ...cdnURLs ) ;
209
+ }
210
+ }
211
+ return contentURLs ;
212
+ } ;
173
213
174
214
/******************************************************************************/
175
215
@@ -917,28 +957,17 @@ assets.get = async function(assetKey, options = {}) {
917
957
}
918
958
919
959
const assetRegistry = await getAssetSourceRegistry ( ) ;
960
+
920
961
assetDetails = assetRegistry [ assetKey ] || { } ;
921
- const contentURLs = [ ] ;
922
- if ( typeof assetDetails . contentURL === 'string' ) {
923
- contentURLs . push ( assetDetails . contentURL ) ;
924
- } else if ( Array . isArray ( assetDetails . contentURL ) ) {
925
- contentURLs . push ( ...assetDetails . contentURL ) ;
926
- } else if ( reIsExternalPath . test ( assetKey ) ) {
962
+
963
+ const contentURLs = getContentURLs ( assetKey , options ) ;
964
+ if ( contentURLs . length === 0 && reIsExternalPath . test ( assetKey ) ) {
927
965
assetDetails . content = 'filters' ;
928
966
contentURLs . push ( assetKey ) ;
929
967
}
930
968
931
- // https://github.com/uBlockOrigin/uBlock-issues/issues/1566#issuecomment-826473517
932
- // Use CDN URLs as fall back URLs.
933
- if ( Array . isArray ( assetDetails . cdnURLs ) ) {
934
- contentURLs . push ( ...assetDetails . cdnURLs ) ;
935
- }
936
-
937
969
let error = 'ENOTFOUND' ;
938
970
for ( const contentURL of contentURLs ) {
939
- if ( reIsExternalPath . test ( contentURL ) && assetDetails . hasLocalURL ) {
940
- continue ;
941
- }
942
971
const details = assetDetails . content === 'filters'
943
972
? await assets . fetchFilterList ( contentURL )
944
973
: await assets . fetchText ( contentURL ) ;
@@ -966,7 +995,7 @@ assets.get = async function(assetKey, options = {}) {
966
995
967
996
/******************************************************************************/
968
997
969
- async function getRemote ( assetKey ) {
998
+ async function getRemote ( assetKey , options = { } ) {
970
999
const [
971
1000
assetDetails = { } ,
972
1001
cacheDetails = { } ,
@@ -978,56 +1007,19 @@ async function getRemote(assetKey) {
978
1007
let error ;
979
1008
let stale = false ;
980
1009
981
- const reportBack = function ( content , err ) {
982
- const details = { assetKey, content } ;
983
- if ( err ) {
1010
+ const reportBack = function ( content , url = '' , err = '' ) {
1011
+ const details = { assetKey, content, url } ;
1012
+ if ( err !== '' ) {
984
1013
details . error = assetDetails . lastError = err ;
985
1014
} else {
986
1015
assetDetails . lastError = undefined ;
987
1016
}
988
1017
return details ;
989
1018
} ;
990
1019
991
- const contentURLs = [ ] ;
992
- if ( typeof assetDetails . contentURL === 'string' ) {
993
- contentURLs . push ( assetDetails . contentURL ) ;
994
- } else if ( Array . isArray ( assetDetails . contentURL ) ) {
995
- contentURLs . push ( ...assetDetails . contentURL ) ;
996
- }
997
-
998
- // If asked to be gentle on remote servers, favour using dedicated CDN
999
- // servers. If more than one CDN server is present, randomly shuffle the
1000
- // set of servers so as to spread the bandwidth burden.
1001
- //
1002
- // https://github.com/uBlockOrigin/uBlock-issues/issues/1566#issuecomment-826473517
1003
- // In case of manual update, use CDNs URLs as fall back URLs.
1004
- if ( Array . isArray ( assetDetails . cdnURLs ) ) {
1005
- const cdnURLs = assetDetails . cdnURLs . slice ( ) ;
1006
- for ( let i = 0 , n = cdnURLs . length ; i < n ; i ++ ) {
1007
- const j = Math . floor ( Math . random ( ) * n ) ;
1008
- if ( j === i ) { continue ; }
1009
- [ cdnURLs [ j ] , cdnURLs [ i ] ] = [ cdnURLs [ i ] , cdnURLs [ j ] ] ;
1010
- }
1011
- if ( remoteServerFriendly ) {
1012
- contentURLs . unshift ( ...cdnURLs ) ;
1013
- } else {
1014
- contentURLs . push ( ...cdnURLs ) ;
1015
- }
1016
- }
1017
-
1018
- for ( let contentURL of contentURLs ) {
1020
+ for ( const contentURL of getContentURLs ( assetKey , options ) ) {
1019
1021
if ( reIsExternalPath . test ( contentURL ) === false ) { continue ; }
1020
1022
1021
- // This will force uBO to fetch the proper version according to whether
1022
- // the dev build is being used. This can be removed when execution of
1023
- // this code path is widespread for dev build revisions of uBO.
1024
- if ( assetKey === 'assets.json' ) {
1025
- contentURL = contentURL . replace (
1026
- / \/ a s s e t s \/ a s s e t s \. j s o n $ / ,
1027
- µb . assetsJsonPath
1028
- ) ;
1029
- }
1030
-
1031
1023
const result = assetDetails . content === 'filters'
1032
1024
? await assets . fetchFilterList ( contentURL )
1033
1025
: await assets . fetchText ( contentURL ) ;
@@ -1066,12 +1058,12 @@ async function getRemote(assetKey) {
1066
1058
}
1067
1059
1068
1060
registerAssetSource ( assetKey , { birthtime : undefined , error : undefined } ) ;
1069
- return reportBack ( result . content ) ;
1061
+ return reportBack ( result . content , contentURL ) ;
1070
1062
}
1071
1063
1072
1064
if ( error !== undefined ) {
1073
1065
registerAssetSource ( assetKey , { error : { time : Date . now ( ) , error } } ) ;
1074
- return reportBack ( '' , 'ENOTFOUND' ) ;
1066
+ return reportBack ( '' , '' , ' ENOTFOUND') ;
1075
1067
}
1076
1068
1077
1069
if ( stale ) {
@@ -1194,6 +1186,8 @@ const getAssetDiffDetails = assetKey => {
1194
1186
} ;
1195
1187
1196
1188
async function diffUpdater ( ) {
1189
+ if ( updaterAuto === false ) { return ; }
1190
+ if ( µb . hiddenSettings . differentialUpdate === false ) { return ; }
1197
1191
const toUpdate = await getUpdateCandidates ( ) ;
1198
1192
const now = Date . now ( ) ;
1199
1193
const toHardUpdate = [ ] ;
@@ -1298,6 +1292,7 @@ async function diffUpdater() {
1298
1292
1299
1293
function updateFirst ( ) {
1300
1294
ubolog ( 'Updater: cycle start' ) ;
1295
+ ubolog ( 'Updater: Fetch from ' , updaterAuto ? 'CDNs' : 'origin' ) ;
1301
1296
updaterStatus = 'updating' ;
1302
1297
updaterFetched . clear ( ) ;
1303
1298
updaterUpdated . length = 0 ;
@@ -1367,7 +1362,7 @@ async function updateNext() {
1367
1362
1368
1363
let result ;
1369
1364
if ( assetKey !== 'assets.json' || µb . hiddenSettings . debugAssetsJson !== true ) {
1370
- result = await getRemote ( assetKey ) ;
1365
+ result = await getRemote ( assetKey , { favorOrigin : updaterAuto === false } ) ;
1371
1366
} else {
1372
1367
result = await assets . fetchText ( µb . assetsJsonPath ) ;
1373
1368
result . assetKey = 'assets.json' ;
@@ -1396,6 +1391,7 @@ function updateDone() {
1396
1391
updaterFetched . clear ( ) ;
1397
1392
updaterUpdated . length = 0 ;
1398
1393
updaterStatus = undefined ;
1394
+ updaterAuto = false ;
1399
1395
updaterAssetDelay = updaterAssetDelayDefault ;
1400
1396
ubolog ( 'Updater: cycle end' ) ;
1401
1397
if ( assetKeys . length ) {
0 commit comments