@browserless.io/browserless 2.23.0 → 2.24.0-beta-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/build/routes/chrome/http/pdf.post.body.json +8 -8
  2. package/build/routes/chromium/http/content.post.body.json +8 -8
  3. package/build/routes/chromium/http/pdf.post.body.json +8 -8
  4. package/build/routes/chromium/http/scrape.post.body.json +8 -8
  5. package/build/routes/chromium/http/screenshot.post.body.json +8 -8
  6. package/docker/base/Dockerfile +1 -1
  7. package/docker/multi/Dockerfile +2 -1
  8. package/docker/webkit/Dockerfile +2 -1
  9. package/extensions/ublock/_locales/ar/messages.json +5 -1
  10. package/extensions/ublock/_locales/az/messages.json +4 -0
  11. package/extensions/ublock/_locales/be/messages.json +5 -1
  12. package/extensions/ublock/_locales/bg/messages.json +4 -0
  13. package/extensions/ublock/_locales/bn/messages.json +4 -0
  14. package/extensions/ublock/_locales/br_FR/messages.json +4 -0
  15. package/extensions/ublock/_locales/bs/messages.json +4 -0
  16. package/extensions/ublock/_locales/ca/messages.json +4 -0
  17. package/extensions/ublock/_locales/cs/messages.json +6 -2
  18. package/extensions/ublock/_locales/cv/messages.json +4 -0
  19. package/extensions/ublock/_locales/cy/messages.json +15 -11
  20. package/extensions/ublock/_locales/da/messages.json +4 -0
  21. package/extensions/ublock/_locales/de/messages.json +8 -4
  22. package/extensions/ublock/_locales/el/messages.json +4 -0
  23. package/extensions/ublock/_locales/en/messages.json +4 -0
  24. package/extensions/ublock/_locales/en_GB/messages.json +4 -0
  25. package/extensions/ublock/_locales/eo/messages.json +4 -0
  26. package/extensions/ublock/_locales/es/messages.json +5 -1
  27. package/extensions/ublock/_locales/et/messages.json +4 -0
  28. package/extensions/ublock/_locales/eu/messages.json +4 -0
  29. package/extensions/ublock/_locales/fa/messages.json +14 -10
  30. package/extensions/ublock/_locales/fi/messages.json +7 -3
  31. package/extensions/ublock/_locales/fil/messages.json +4 -0
  32. package/extensions/ublock/_locales/fr/messages.json +5 -1
  33. package/extensions/ublock/_locales/fy/messages.json +4 -0
  34. package/extensions/ublock/_locales/gl/messages.json +4 -0
  35. package/extensions/ublock/_locales/gu/messages.json +4 -0
  36. package/extensions/ublock/_locales/he/messages.json +4 -0
  37. package/extensions/ublock/_locales/hi/messages.json +4 -0
  38. package/extensions/ublock/_locales/hr/messages.json +4 -0
  39. package/extensions/ublock/_locales/hu/messages.json +4 -0
  40. package/extensions/ublock/_locales/hy/messages.json +4 -0
  41. package/extensions/ublock/_locales/id/messages.json +4 -0
  42. package/extensions/ublock/_locales/it/messages.json +4 -0
  43. package/extensions/ublock/_locales/ja/messages.json +6 -2
  44. package/extensions/ublock/_locales/ka/messages.json +5 -1
  45. package/extensions/ublock/_locales/kk/messages.json +4 -0
  46. package/extensions/ublock/_locales/kn/messages.json +4 -0
  47. package/extensions/ublock/_locales/ko/messages.json +5 -1
  48. package/extensions/ublock/_locales/lt/messages.json +4 -0
  49. package/extensions/ublock/_locales/lv/messages.json +4 -0
  50. package/extensions/ublock/_locales/mk/messages.json +4 -0
  51. package/extensions/ublock/_locales/ml/messages.json +4 -0
  52. package/extensions/ublock/_locales/mr/messages.json +4 -0
  53. package/extensions/ublock/_locales/ms/messages.json +4 -0
  54. package/extensions/ublock/_locales/nb/messages.json +4 -0
  55. package/extensions/ublock/_locales/nl/messages.json +4 -0
  56. package/extensions/ublock/_locales/no/messages.json +4 -0
  57. package/extensions/ublock/_locales/oc/messages.json +4 -0
  58. package/extensions/ublock/_locales/pa/messages.json +5 -1
  59. package/extensions/ublock/_locales/pl/messages.json +4 -0
  60. package/extensions/ublock/_locales/pt_BR/messages.json +4 -0
  61. package/extensions/ublock/_locales/pt_PT/messages.json +4 -0
  62. package/extensions/ublock/_locales/ro/messages.json +4 -0
  63. package/extensions/ublock/_locales/ru/messages.json +5 -1
  64. package/extensions/ublock/_locales/si/messages.json +4 -0
  65. package/extensions/ublock/_locales/sk/messages.json +4 -0
  66. package/extensions/ublock/_locales/sl/messages.json +4 -0
  67. package/extensions/ublock/_locales/so/messages.json +4 -0
  68. package/extensions/ublock/_locales/sq/messages.json +4 -0
  69. package/extensions/ublock/_locales/sr/messages.json +4 -0
  70. package/extensions/ublock/_locales/sv/messages.json +5 -1
  71. package/extensions/ublock/_locales/sw/messages.json +4 -0
  72. package/extensions/ublock/_locales/ta/messages.json +4 -0
  73. package/extensions/ublock/_locales/te/messages.json +4 -0
  74. package/extensions/ublock/_locales/th/messages.json +4 -0
  75. package/extensions/ublock/_locales/tr/messages.json +4 -0
  76. package/extensions/ublock/_locales/uk/messages.json +7 -3
  77. package/extensions/ublock/_locales/ur/messages.json +4 -0
  78. package/extensions/ublock/_locales/vi/messages.json +4 -0
  79. package/extensions/ublock/_locales/zh_CN/messages.json +4 -0
  80. package/extensions/ublock/_locales/zh_TW/messages.json +4 -0
  81. package/extensions/ublock/assets/assets.json +14 -14
  82. package/extensions/ublock/assets/resources/run-at.js +80 -0
  83. package/extensions/ublock/assets/resources/safe-self.js +218 -0
  84. package/extensions/ublock/assets/resources/scriptlets.js +461 -538
  85. package/extensions/ublock/assets/resources/set-attr.js +201 -0
  86. package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +4002 -11582
  87. package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +257 -83
  88. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +22 -38
  89. package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +102 -110
  90. package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +2776 -3613
  91. package/extensions/ublock/assets/ublock/badware.min.txt +581 -382
  92. package/extensions/ublock/assets/ublock/filters.min.txt +997 -990
  93. package/extensions/ublock/assets/ublock/privacy.min.txt +145 -26
  94. package/extensions/ublock/assets/ublock/quick-fixes.min.txt +134 -83
  95. package/extensions/ublock/assets/ublock/unbreak.min.txt +69 -46
  96. package/extensions/ublock/css/document-blocked.css +28 -1
  97. package/extensions/ublock/document-blocked.html +9 -7
  98. package/extensions/ublock/js/assets.js +15 -11
  99. package/extensions/ublock/js/benchmarks.js +13 -9
  100. package/extensions/ublock/js/biditrie.js +1 -1
  101. package/extensions/ublock/js/document-blocked.js +41 -5
  102. package/extensions/ublock/js/hntrie.js +1 -1
  103. package/extensions/ublock/js/i18n.js +2 -4
  104. package/extensions/ublock/js/pagestore.js +61 -43
  105. package/extensions/ublock/js/s14e-serializer.js +47 -22
  106. package/extensions/ublock/js/scriptlet-filtering.js +21 -18
  107. package/extensions/ublock/js/scriptlets/load-large-media-interactive.js +61 -48
  108. package/extensions/ublock/js/scriptlets/should-inject-contentscript.js +1 -3
  109. package/extensions/ublock/js/static-dnr-filtering.js +9 -7
  110. package/extensions/ublock/js/static-filtering-parser.js +87 -54
  111. package/extensions/ublock/js/static-net-filtering.js +118 -42
  112. package/extensions/ublock/js/traffic.js +37 -18
  113. package/extensions/ublock/js/vapi-background-ext.js +21 -49
  114. package/extensions/ublock/js/vapi-background.js +8 -0
  115. package/extensions/ublock/manifest.json +1 -1
  116. package/extensions/ublock/web_accessible_resources/googlesyndication_adsbygoogle.js +3 -1
  117. package/package.json +16 -16
  118. package/static/docs/swagger.json +1 -1
  119. package/static/docs/swagger.min.json +1 -1
@@ -19,8 +19,6 @@
19
19
  Home: https://github.com/gorhill/uBlock
20
20
  */
21
21
 
22
- 'use strict';
23
-
24
22
  /******************************************************************************/
25
23
 
26
24
  const i18n =
@@ -168,14 +166,14 @@ if ( isBackgroundProcess !== true ) {
168
166
  const re = /\{\{\w+\}\}/g;
169
167
  let textout = '';
170
168
  for (;;) {
171
- let match = re.exec(textin);
169
+ const match = re.exec(textin);
172
170
  if ( match === null ) {
173
171
  textout += textin;
174
172
  break;
175
173
  }
176
174
  textout += textin.slice(0, match.index);
177
175
  let prop = match[0].slice(2, -2);
178
- if ( dict.hasOwnProperty(prop) ) {
176
+ if ( Object.prototype.hasOwnProperty.call(dict, prop) ) {
179
177
  textout += dict[prop].replace(/</g, '&lt;')
180
178
  .replace(/>/g, '&gt;');
181
179
  } else {
@@ -925,8 +925,11 @@ const PageStore = class {
925
925
  }
926
926
 
927
927
  redirectBlockedRequest(fctxt) {
928
- const directives = staticNetFilteringEngine.redirectRequest(redirectEngine, fctxt);
929
- if ( directives === undefined ) { return; }
928
+ const directives = staticNetFilteringEngine.redirectRequest(redirectEngine, fctxt) || [];
929
+ if ( this.urlSkippableResources.has(fctxt.itype) ) {
930
+ staticNetFilteringEngine.urlSkip(fctxt, true, directives);
931
+ }
932
+ if ( directives.length === 0 ) { return; }
930
933
  if ( logger.enabled !== true ) { return; }
931
934
  fctxt.pushFilters(directives.map(a => a.logData()));
932
935
  if ( fctxt.redirectURL === undefined ) { return; }
@@ -942,6 +945,9 @@ const PageStore = class {
942
945
  if ( staticNetFilteringEngine.hasQuery(fctxt) ) {
943
946
  staticNetFilteringEngine.filterQuery(fctxt, directives);
944
947
  }
948
+ if ( this.urlSkippableResources.has(fctxt.itype) ) {
949
+ staticNetFilteringEngine.urlSkip(fctxt, false, directives);
950
+ }
945
951
  if ( directives.length === 0 ) { return; }
946
952
  if ( logger.enabled !== true ) { return; }
947
953
  fctxt.pushFilters(directives.map(a => a.logData()));
@@ -952,8 +958,8 @@ const PageStore = class {
952
958
  });
953
959
  }
954
960
 
955
- skipMainDocument(fctxt) {
956
- const directives = staticNetFilteringEngine.urlSkip(fctxt);
961
+ skipMainDocument(fctxt, blocked) {
962
+ const directives = staticNetFilteringEngine.urlSkip(fctxt, blocked);
957
963
  if ( directives === undefined ) { return; }
958
964
  if ( logger.enabled !== true ) { return; }
959
965
  fctxt.pushFilters(directives.map(a => a.logData()));
@@ -1019,48 +1025,51 @@ const PageStore = class {
1019
1025
  }
1020
1026
 
1021
1027
  // The caller is responsible to check whether filtering is enabled or not.
1022
- filterLargeMediaElement(fctxt, size) {
1028
+ filterLargeMediaElement(fctxt, headers) {
1023
1029
  fctxt.filter = undefined;
1024
-
1025
- if ( this.allowLargeMediaElementsUntil === 0 ) {
1030
+ if ( this.allowLargeMediaElementsUntil === 0 ) { return 0; }
1031
+ if ( sessionSwitches.evaluateZ('no-large-media', fctxt.getTabHostname() ) !== true ) {
1032
+ this.allowLargeMediaElementsUntil = 0;
1026
1033
  return 0;
1027
1034
  }
1028
- // Disregard large media elements previously allowed: for example, to
1029
- // seek inside a previously allowed audio/video.
1030
- if (
1031
- this.allowLargeMediaElementsRegex instanceof RegExp &&
1032
- this.allowLargeMediaElementsRegex.test(fctxt.url)
1033
- ) {
1035
+ // XHR-based streaming is never blocked but we want to prevent autoplay
1036
+ if ( fctxt.itype === fctxt.XMLHTTPREQUEST ) {
1037
+ const ctype = headers.contentType;
1038
+ if ( ctype.startsWith('audio/') || ctype.startsWith('video/') ) {
1039
+ this.largeMediaTimer.on(500);
1040
+ }
1034
1041
  return 0;
1035
1042
  }
1036
1043
  if ( Date.now() < this.allowLargeMediaElementsUntil ) {
1037
- const sources = this.allowLargeMediaElementsRegex instanceof RegExp
1038
- ? [ this.allowLargeMediaElementsRegex.source ]
1039
- : [];
1040
- sources.push('^' + µb.escapeRegex(fctxt.url));
1041
- this.allowLargeMediaElementsRegex = new RegExp(sources.join('|'));
1044
+ if ( fctxt.itype === fctxt.MEDIA ) {
1045
+ const sources = this.allowLargeMediaElementsRegex instanceof RegExp
1046
+ ? [ this.allowLargeMediaElementsRegex.source ]
1047
+ : [];
1048
+ sources.push('^' + µb.escapeRegex(fctxt.url));
1049
+ this.allowLargeMediaElementsRegex = new RegExp(sources.join('|'));
1050
+ }
1042
1051
  return 0;
1043
1052
  }
1053
+ // Disregard large media elements previously allowed: for example, to
1054
+ // seek inside a previously allowed audio/video.
1044
1055
  if (
1045
- sessionSwitches.evaluateZ(
1046
- 'no-large-media',
1047
- fctxt.getTabHostname()
1048
- ) !== true
1056
+ this.allowLargeMediaElementsRegex instanceof RegExp &&
1057
+ this.allowLargeMediaElementsRegex.test(fctxt.url)
1049
1058
  ) {
1050
- this.allowLargeMediaElementsUntil = 0;
1051
1059
  return 0;
1052
1060
  }
1053
- if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
1054
- return 0;
1061
+ // Regardless of whether a media is blocked, we want to prevent autoplay
1062
+ if ( fctxt.itype === fctxt.MEDIA ) {
1063
+ this.largeMediaTimer.on(500);
1055
1064
  }
1056
-
1065
+ const size = headers.contentLength;
1066
+ if ( isNaN(size) ) { return 0; }
1067
+ if ( (size >>> 10) < µb.userSettings.largeMediaSize ) { return 0; }
1057
1068
  this.largeMediaCount += 1;
1058
1069
  this.largeMediaTimer.on(500);
1059
-
1060
1070
  if ( logger.enabled ) {
1061
1071
  fctxt.filter = sessionSwitches.toLogData();
1062
1072
  }
1063
-
1064
1073
  return 1;
1065
1074
  }
1066
1075
 
@@ -1129,22 +1138,31 @@ const PageStore = class {
1129
1138
  response.blockedResources =
1130
1139
  this.netFilteringCache.lookupAllBlocked(fctxt.getDocHostname());
1131
1140
  }
1132
- };
1133
-
1134
- PageStore.prototype.cacheableResults = new Set([
1135
- µb.FilteringContext.SUB_FRAME,
1136
- ]);
1137
1141
 
1138
- PageStore.prototype.collapsibleResources = new Set([
1139
- µb.FilteringContext.IMAGE,
1140
- µb.FilteringContext.MEDIA,
1141
- µb.FilteringContext.OBJECT,
1142
- µb.FilteringContext.SUB_FRAME,
1143
- ]);
1144
-
1145
- // To mitigate memory churning
1146
- PageStore.junkyard = [];
1147
- PageStore.junkyardMax = 10;
1142
+ cacheableResults = new Set([
1143
+ µb.FilteringContext.SUB_FRAME
1144
+ ]);
1145
+
1146
+ collapsibleResources = new Set([
1147
+ µb.FilteringContext.IMAGE,
1148
+ µb.FilteringContext.MEDIA,
1149
+ µb.FilteringContext.OBJECT,
1150
+ µb.FilteringContext.SUB_FRAME,
1151
+ ]);
1152
+
1153
+ urlSkippableResources = new Set([
1154
+ µb.FilteringContext.IMAGE,
1155
+ µb.FilteringContext.MAIN_FRAME,
1156
+ µb.FilteringContext.MEDIA,
1157
+ µb.FilteringContext.OBJECT,
1158
+ µb.FilteringContext.OTHER,
1159
+ µb.FilteringContext.SUB_FRAME,
1160
+ ]);
1161
+
1162
+ // To mitigate memory churning
1163
+ static junkyard = [];
1164
+ static junkyardMax = 10;
1165
+ };
1148
1166
 
1149
1167
  /******************************************************************************/
1150
1168
 
@@ -249,8 +249,29 @@ const toArrayBufferViewConstructor = {
249
249
 
250
250
  /******************************************************************************/
251
251
 
252
- const textDecoder = new TextDecoder();
253
- const textEncoder = new TextEncoder();
252
+ const textCodec = {
253
+ decoder: null,
254
+ encoder: null,
255
+ decode(...args) {
256
+ if ( this.decoder === null ) {
257
+ this.decoder = new globalThis.TextDecoder();
258
+ }
259
+ return this.decoder.decode(...args);
260
+ },
261
+ encode(...args) {
262
+ if ( this.encoder === null ) {
263
+ this.encoder = new globalThis.TextEncoder();
264
+ }
265
+ return this.encoder.encode(...args);
266
+ },
267
+ encodeInto(...args) {
268
+ if ( this.encoder === null ) {
269
+ this.encoder = new globalThis.TextEncoder();
270
+ }
271
+ return this.encoder.encodeInto(...args);
272
+ },
273
+ };
274
+
254
275
  const isInteger = Number.isInteger;
255
276
 
256
277
  const writeRefs = new Map();
@@ -269,7 +290,7 @@ const uint8InputFromAsciiStr = s => {
269
290
  if ( uint8Input === null || uint8Input.length < s.length ) {
270
291
  uint8Input = new Uint8Array(s.length + 0x03FF & ~0x03FF);
271
292
  }
272
- textEncoder.encodeInto(s, uint8Input);
293
+ textCodec.encodeInto(s, uint8Input);
273
294
  return uint8Input;
274
295
  };
275
296
 
@@ -407,7 +428,7 @@ const denseArrayBufferToStr = (arrbuf, details) => {
407
428
  }
408
429
  }
409
430
  }
410
- return textDecoder.decode(output);
431
+ return textCodec.decode(output);
411
432
  };
412
433
 
413
434
  const BASE88_POW1 = NUMSAFECHARS;
@@ -489,7 +510,7 @@ const sparseArrayBufferToStr = (arrbuf, details) => {
489
510
  uint8out[j++] = SEPARATORCHARCODE;
490
511
  }
491
512
  }
492
- return textDecoder.decode(uint8out);
513
+ return textCodec.decode(uint8out);
493
514
  };
494
515
 
495
516
  const sparseArrayBufferFromStr = (sparseStr, arrbuf) => {
@@ -1060,7 +1081,7 @@ export const serialize = (data, options = {}) => {
1060
1081
  writeBuffer.length = 0;
1061
1082
  if ( shouldCompress(s, options) === false ) { return s; }
1062
1083
  const lz4Util = new LZ4BlockJS();
1063
- const uint8ArrayBefore = textEncoder.encode(s);
1084
+ const uint8ArrayBefore = textCodec.encode(s);
1064
1085
  const uint8ArrayAfter = lz4Util.encode(uint8ArrayBefore, 0);
1065
1086
  const lz4 = {
1066
1087
  size: uint8ArrayBefore.length,
@@ -1076,32 +1097,36 @@ export const serialize = (data, options = {}) => {
1076
1097
  return ratio <= 0.85 ? t : s;
1077
1098
  };
1078
1099
 
1079
- export const deserialize = s => {
1080
- if ( s.startsWith(MAGICLZ4PREFIX) ) {
1081
- refCounter = 1;
1082
- readStr = s;
1083
- readEnd = s.length;
1084
- readPtr = MAGICLZ4PREFIX.length;
1085
- const lz4 = _deserialize();
1086
- readRefs.clear();
1087
- readStr = '';
1088
- const lz4Util = new LZ4BlockJS();
1089
- const uint8ArrayAfter = lz4Util.decode(lz4.data, 0, lz4.size);
1090
- s = textDecoder.decode(new Uint8Array(uint8ArrayAfter));
1091
- }
1092
- if ( s.startsWith(MAGICPREFIX) === false ) { return; }
1100
+ const deserializeById = (blockid, s) => {
1093
1101
  refCounter = 1;
1094
1102
  readStr = s;
1095
1103
  readEnd = s.length;
1096
- readPtr = MAGICPREFIX.length;
1104
+ readPtr = blockid.length;
1097
1105
  const data = _deserialize();
1098
1106
  readRefs.clear();
1099
1107
  readStr = '';
1100
- uint8Input = null;
1101
1108
  if ( readPtr === FAILMARK ) { return; }
1102
1109
  return data;
1103
1110
  };
1104
1111
 
1112
+ export const deserialize = s => {
1113
+ if ( s.startsWith(MAGICLZ4PREFIX) ) {
1114
+ const lz4 = deserializeById(MAGICLZ4PREFIX, s);
1115
+ if ( lz4 ) {
1116
+ const lz4Util = new LZ4BlockJS();
1117
+ const uint8ArrayAfter = lz4Util.decode(lz4.data, 0, lz4.size);
1118
+ if ( uint8ArrayAfter ) {
1119
+ s = textCodec.decode(new Uint8Array(uint8ArrayAfter));
1120
+ }
1121
+ }
1122
+ }
1123
+ const data = s.startsWith(MAGICPREFIX)
1124
+ ? deserializeById(MAGICPREFIX, s)
1125
+ : undefined;
1126
+ uint8Input = null;
1127
+ return data;
1128
+ };
1129
+
1105
1130
  export const isSerialized = s =>
1106
1131
  typeof s === 'string' &&
1107
1132
  (s.startsWith(MAGICLZ4PREFIX) || s.startsWith(MAGICPREFIX));
@@ -176,25 +176,28 @@ const onScriptletMessageInjector = (( ) => {
176
176
  '(',
177
177
  function(name) {
178
178
  if ( self.uBO_bcSecret ) { return; }
179
- const bcSecret = new self.BroadcastChannel(name);
180
- bcSecret.onmessage = ev => {
181
- const msg = ev.data;
182
- switch ( typeof msg ) {
183
- case 'string':
184
- if ( msg !== 'areyouready?' ) { break; }
185
- bcSecret.postMessage('iamready!');
186
- break;
187
- case 'object':
188
- if ( self.vAPI && self.vAPI.messaging ) {
189
- self.vAPI.messaging.send('contentscript', msg);
190
- } else {
191
- console.log(`[uBO][${msg.type}]${msg.text}`);
179
+ try {
180
+ const bcSecret = new self.BroadcastChannel(name);
181
+ bcSecret.onmessage = ev => {
182
+ const msg = ev.data;
183
+ switch ( typeof msg ) {
184
+ case 'string':
185
+ if ( msg !== 'areyouready?' ) { break; }
186
+ bcSecret.postMessage('iamready!');
187
+ break;
188
+ case 'object':
189
+ if ( self.vAPI && self.vAPI.messaging ) {
190
+ self.vAPI.messaging.send('contentscript', msg);
191
+ } else {
192
+ console.log(`[uBO][${msg.type}]${msg.text}`);
193
+ }
194
+ break;
192
195
  }
193
- break;
194
- }
195
- };
196
- bcSecret.postMessage('iamready!');
197
- self.uBO_bcSecret = bcSecret;
196
+ };
197
+ bcSecret.postMessage('iamready!');
198
+ self.uBO_bcSecret = bcSecret;
199
+ } catch(_) {
200
+ }
198
201
  }.toString(),
199
202
  ')(',
200
203
  'bcSecret-slot',
@@ -19,10 +19,6 @@
19
19
  Home: https://github.com/gorhill/uBlock
20
20
  */
21
21
 
22
- 'use strict';
23
-
24
- /******************************************************************************/
25
-
26
22
  (( ) => {
27
23
 
28
24
  /******************************************************************************/
@@ -32,8 +28,6 @@ if ( typeof vAPI !== 'object' || vAPI.loadAllLargeMedia instanceof Function ) {
32
28
  return;
33
29
  }
34
30
 
35
- /******************************************************************************/
36
-
37
31
  const largeMediaElementAttribute = 'data-' + vAPI.sessionId;
38
32
  const largeMediaElementSelector =
39
33
  ':root audio[' + largeMediaElementAttribute + '],\n' +
@@ -41,25 +35,19 @@ const largeMediaElementSelector =
41
35
  ':root picture[' + largeMediaElementAttribute + '],\n' +
42
36
  ':root video[' + largeMediaElementAttribute + ']';
43
37
 
44
- /******************************************************************************/
38
+ const isMediaElement = elem =>
39
+ (/^(?:audio|img|picture|video)$/.test(elem.localName));
45
40
 
46
- const isMediaElement = function(elem) {
47
- return /^(?:audio|img|picture|video)$/.test(elem.localName);
48
- };
41
+ const isPlayableMediaElement = elem =>
42
+ (/^(?:audio|video)$/.test(elem.localName));
49
43
 
50
44
  /******************************************************************************/
51
45
 
52
46
  const mediaNotLoaded = function(elem) {
53
47
  switch ( elem.localName ) {
54
48
  case 'audio':
55
- case 'video': {
56
- const src = elem.src || '';
57
- if ( src.startsWith('blob:') ) {
58
- elem.autoplay = false;
59
- elem.pause();
60
- }
49
+ case 'video':
61
50
  return elem.readyState === 0 || elem.error !== null;
62
- }
63
51
  case 'img': {
64
52
  if ( elem.naturalWidth !== 0 || elem.naturalHeight !== 0 ) {
65
53
  break;
@@ -103,44 +91,41 @@ const surveyMissingMediaElements = function() {
103
91
  return largeMediaElementCount;
104
92
  };
105
93
 
106
- if ( surveyMissingMediaElements() === 0 ) { return; }
107
-
108
- // Insert CSS to highlight blocked media elements.
109
- if ( vAPI.largeMediaElementStyleSheet === undefined ) {
110
- vAPI.largeMediaElementStyleSheet = [
111
- largeMediaElementSelector + ' {',
112
- 'border: 2px dotted red !important;',
113
- 'box-sizing: border-box !important;',
114
- 'cursor: zoom-in !important;',
115
- 'display: inline-block;',
116
- 'filter: none !important;',
117
- 'font-size: 1rem !important;',
118
- 'min-height: 1em !important;',
119
- 'min-width: 1em !important;',
120
- 'opacity: 1 !important;',
121
- 'outline: none !important;',
122
- 'transform: none !important;',
123
- 'visibility: visible !important;',
124
- 'z-index: 2147483647',
125
- '}',
126
- ].join('\n');
127
- vAPI.userStylesheet.add(vAPI.largeMediaElementStyleSheet);
128
- vAPI.userStylesheet.apply();
94
+ if ( surveyMissingMediaElements() ) {
95
+ // Insert CSS to highlight blocked media elements.
96
+ if ( vAPI.largeMediaElementStyleSheet === undefined ) {
97
+ vAPI.largeMediaElementStyleSheet = [
98
+ largeMediaElementSelector + ' {',
99
+ 'border: 2px dotted red !important;',
100
+ 'box-sizing: border-box !important;',
101
+ 'cursor: zoom-in !important;',
102
+ 'display: inline-block;',
103
+ 'filter: none !important;',
104
+ 'font-size: 1rem !important;',
105
+ 'min-height: 1em !important;',
106
+ 'min-width: 1em !important;',
107
+ 'opacity: 1 !important;',
108
+ 'outline: none !important;',
109
+ 'transform: none !important;',
110
+ 'visibility: visible !important;',
111
+ 'z-index: 2147483647',
112
+ '}',
113
+ ].join('\n');
114
+ vAPI.userStylesheet.add(vAPI.largeMediaElementStyleSheet);
115
+ vAPI.userStylesheet.apply();
116
+ }
129
117
  }
130
118
 
131
119
  /******************************************************************************/
132
120
 
133
121
  const loadMedia = async function(elem) {
134
122
  const src = elem.getAttribute('src') || '';
123
+ if ( src === '' ) { return; }
135
124
  elem.removeAttribute('src');
136
-
137
125
  await vAPI.messaging.send('scriptlets', {
138
126
  what: 'temporarilyAllowLargeMediaElement',
139
127
  });
140
-
141
- if ( src !== '' ) {
142
- elem.setAttribute('src', src);
143
- }
128
+ elem.setAttribute('src', src);
144
129
  elem.load();
145
130
  };
146
131
 
@@ -148,14 +133,21 @@ const loadMedia = async function(elem) {
148
133
 
149
134
  const loadImage = async function(elem) {
150
135
  const src = elem.getAttribute('src') || '';
151
- elem.removeAttribute('src');
152
-
136
+ const srcset = src === '' && elem.getAttribute('srcset') || '';
137
+ if ( src === '' && srcset === '' ) { return; }
138
+ if ( src !== '' ) {
139
+ elem.removeAttribute('src');
140
+ }
141
+ if ( srcset !== '' ) {
142
+ elem.removeAttribute('srcset');
143
+ }
153
144
  await vAPI.messaging.send('scriptlets', {
154
145
  what: 'temporarilyAllowLargeMediaElement',
155
146
  });
156
-
157
147
  if ( src !== '' ) {
158
148
  elem.setAttribute('src', src);
149
+ } else if ( srcset !== '' ) {
150
+ elem.setAttribute('srcset', srcset);
159
151
  }
160
152
  };
161
153
 
@@ -258,6 +250,27 @@ document.addEventListener('error', onLoadError, true);
258
250
 
259
251
  /******************************************************************************/
260
252
 
253
+ const autoPausedMedia = new WeakMap();
254
+
255
+ for ( const elem of document.querySelectorAll('audio,video') ) {
256
+ elem.setAttribute('autoplay', 'false');
257
+ }
258
+
259
+ const preventAutoplay = function(ev) {
260
+ const elem = ev.target;
261
+ if ( isPlayableMediaElement(elem) === false ) { return; }
262
+ const currentSrc = elem.getAttribute('src') || '';
263
+ const pausedSrc = autoPausedMedia.get(elem);
264
+ if ( pausedSrc === currentSrc ) { return; }
265
+ autoPausedMedia.set(elem, currentSrc);
266
+ elem.setAttribute('autoplay', 'false');
267
+ elem.pause();
268
+ };
269
+
270
+ document.addEventListener('timeupdate', preventAutoplay, true);
271
+
272
+ /******************************************************************************/
273
+
261
274
  vAPI.loadAllLargeMedia = function() {
262
275
  document.removeEventListener('click', onMouseClick, true);
263
276
  document.removeEventListener('loadeddata', onLoadedData, true);
@@ -19,8 +19,6 @@
19
19
  Home: https://github.com/gorhill/uBlock
20
20
  */
21
21
 
22
- 'use strict';
23
-
24
22
  // If content scripts are already injected, we need to respond with `false`,
25
23
  // to "should inject content scripts?"
26
24
  //
@@ -31,7 +29,7 @@
31
29
  try {
32
30
  const status = vAPI.uBO !== true;
33
31
  if ( status === false && vAPI.bootstrap ) {
34
- self.requestIdleCallback(( ) => vAPI && vAPI.bootstrap());
32
+ self.requestIdleCallback(( ) => vAPI?.bootstrap?.());
35
33
  }
36
34
  return status;
37
35
  } catch(ex) {
@@ -19,12 +19,6 @@
19
19
  Home: https://github.com/gorhill/uBlock
20
20
  */
21
21
 
22
- 'use strict';
23
-
24
- /******************************************************************************/
25
-
26
- import staticNetFilteringEngine from './static-net-filtering.js';
27
- import { LineIterator } from './text-utils.js';
28
22
  import * as sfp from './static-filtering-parser.js';
29
23
 
30
24
  import {
@@ -32,6 +26,9 @@ import {
32
26
  CompiledListWriter,
33
27
  } from './static-filtering-io.js';
34
28
 
29
+ import { LineIterator } from './text-utils.js';
30
+ import staticNetFilteringEngine from './static-net-filtering.js';
31
+
35
32
  /******************************************************************************/
36
33
 
37
34
  // http://www.cse.yorku.ca/~oz/hash.html#djb2
@@ -47,13 +44,15 @@ const hashFromStr = (type, s) => {
47
44
  return hash & 0xFFFFFF;
48
45
  };
49
46
 
47
+ const isRegex = hn => hn.startsWith('/') && hn.endsWith('/');
48
+
50
49
  /******************************************************************************/
51
50
 
52
51
  // Copied from cosmetic-filter.js for the time being to avoid unwanted
53
52
  // dependencies
54
53
 
55
54
  const rePlainSelector = /^[#.][\w\\-]+/;
56
- const rePlainSelectorEx = /^[^#.\[(]+([#.][\w-]+)|([#.][\w-]+)$/;
55
+ const rePlainSelectorEx = /^[^#.[(]+([#.][\w-]+)|([#.][\w-]+)$/;
57
56
  const rePlainSelectorEscaped = /^[#.](?:\\[0-9A-Fa-f]+ |\\.|\w|-)+/;
58
57
  const reEscapeSequence = /\\([0-9A-Fa-f]+ |.)/g;
59
58
 
@@ -106,6 +105,7 @@ function addExtendedToDNR(context, parser) {
106
105
  for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) {
107
106
  if ( bad ) { continue; }
108
107
  if ( exception ) { continue; }
108
+ if ( isRegex(hn) ) { continue; }
109
109
  let details = context.scriptletFilters.get(argsToken);
110
110
  if ( details === undefined ) {
111
111
  context.scriptletFilters.set(argsToken, details = { args });
@@ -163,6 +163,7 @@ function addExtendedToDNR(context, parser) {
163
163
  };
164
164
  for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) {
165
165
  if ( bad ) { continue; }
166
+ if ( isRegex(hn) ) { continue; }
166
167
  if ( not ) {
167
168
  if ( rule.condition.excludedInitiatorDomains === undefined ) {
168
169
  rule.condition.excludedInitiatorDomains = [];
@@ -235,6 +236,7 @@ function addExtendedToDNR(context, parser) {
235
236
  }
236
237
  for ( const { hn, not, bad } of parser.getExtFilterDomainIterator() ) {
237
238
  if ( bad ) { continue; }
239
+ if ( isRegex(hn) ) { continue; }
238
240
  let { compiled, exception, raw } = parser.result;
239
241
  if ( exception ) { continue; }
240
242
  let rejected;