@browserless.io/browserless 2.25.0-beta-2 → 2.25.0
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.
- package/CHANGELOG.md +39 -3
- package/README.md +4 -5
- package/build/browserless.js +3 -1
- package/build/browsers/browsers.cdp.d.ts +3 -0
- package/build/browsers/browsers.cdp.js +4 -1
- package/build/browsers/browsers.playwright.d.ts +4 -0
- package/build/browsers/browsers.playwright.js +11 -2
- package/build/browsers/index.js +4 -3
- package/build/http.d.ts +9 -0
- package/build/http.js +9 -0
- package/build/routes/chrome/http/content.post.body.json +8 -8
- package/build/routes/chrome/http/pdf.post.body.json +8 -8
- package/build/routes/chrome/http/scrape.post.body.json +8 -8
- package/build/routes/chrome/http/screenshot.post.body.json +8 -8
- package/build/routes/chrome/tests/kill-sessions.spec.js +1 -1
- package/build/routes/chromium/http/content.post.body.json +8 -8
- package/build/routes/chromium/http/pdf.post.body.json +8 -8
- package/build/routes/chromium/http/scrape.post.body.json +8 -8
- package/build/routes/chromium/http/screenshot.post.body.json +8 -8
- package/build/routes/chromium/tests/kill-sessions.spec.js +1 -1
- package/build/routes/edge/http/content.post.body.json +579 -0
- package/build/routes/edge/http/content.post.d.ts +8 -0
- package/build/routes/edge/http/content.post.js +7 -0
- package/build/routes/edge/http/content.post.query.json +183 -0
- package/build/routes/edge/http/content.post.response.json +5 -0
- package/build/routes/edge/http/download.post.body.json +32 -0
- package/build/routes/edge/http/download.post.d.ts +8 -0
- package/build/routes/edge/http/download.post.js +7 -0
- package/build/routes/edge/http/download.post.query.json +120 -0
- package/build/routes/edge/http/download.post.response.json +4 -0
- package/build/routes/edge/http/function.post.body.json +32 -0
- package/build/routes/edge/http/function.post.d.ts +8 -0
- package/build/routes/edge/http/function.post.js +7 -0
- package/build/routes/edge/http/function.post.query.json +120 -0
- package/build/routes/edge/http/function.post.response.json +4 -0
- package/build/routes/edge/http/json-list.get.d.ts +5 -0
- package/build/routes/edge/http/json-list.get.js +5 -0
- package/build/routes/edge/http/json-list.get.response.json +52 -0
- package/build/routes/edge/http/json-new.put.d.ts +5 -0
- package/build/routes/edge/http/json-new.put.js +5 -0
- package/build/routes/edge/http/json-new.put.response.json +44 -0
- package/build/routes/edge/http/json-protocol.get.d.ts +5 -0
- package/build/routes/edge/http/json-protocol.get.js +5 -0
- package/build/routes/edge/http/json-protocol.get.response.json +6 -0
- package/build/routes/edge/http/json-version.get.d.ts +5 -0
- package/build/routes/edge/http/json-version.get.js +5 -0
- package/build/routes/edge/http/json-version.get.response.json +44 -0
- package/build/routes/edge/http/pdf.post.body.json +724 -0
- package/build/routes/edge/http/pdf.post.d.ts +8 -0
- package/build/routes/edge/http/pdf.post.js +7 -0
- package/build/routes/edge/http/pdf.post.query.json +120 -0
- package/build/routes/edge/http/pdf.post.response.json +5 -0
- package/build/routes/edge/http/performance.post.body.json +26 -0
- package/build/routes/edge/http/performance.post.d.ts +8 -0
- package/build/routes/edge/http/performance.post.js +7 -0
- package/build/routes/edge/http/performance.post.query.json +120 -0
- package/build/routes/edge/http/performance.post.response.json +7 -0
- package/build/routes/edge/http/scrape.post.body.json +626 -0
- package/build/routes/edge/http/scrape.post.d.ts +8 -0
- package/build/routes/edge/http/scrape.post.js +7 -0
- package/build/routes/edge/http/scrape.post.query.json +183 -0
- package/build/routes/edge/http/scrape.post.response.json +334 -0
- package/build/routes/edge/http/screenshot.post.body.json +669 -0
- package/build/routes/edge/http/screenshot.post.d.ts +8 -0
- package/build/routes/edge/http/screenshot.post.js +7 -0
- package/build/routes/edge/http/screenshot.post.query.json +120 -0
- package/build/routes/edge/http/screenshot.post.response.json +5 -0
- package/build/routes/edge/tests/content.spec.d.ts +1 -0
- package/build/routes/edge/tests/content.spec.js +312 -0
- package/build/routes/edge/tests/download.spec.d.ts +1 -0
- package/build/routes/edge/tests/download.spec.js +67 -0
- package/build/routes/edge/tests/function.spec.d.ts +1 -0
- package/build/routes/edge/tests/function.spec.js +277 -0
- package/build/routes/edge/tests/json-version.spec.d.ts +1 -0
- package/build/routes/edge/tests/json-version.spec.js +37 -0
- package/build/routes/edge/tests/kill-sessions.spec.d.ts +1 -0
- package/build/routes/edge/tests/kill-sessions.spec.js +80 -0
- package/build/routes/edge/tests/page-websocket.spec.d.ts +1 -0
- package/build/routes/edge/tests/page-websocket.spec.js +97 -0
- package/build/routes/edge/tests/pdf.spec.d.ts +1 -0
- package/build/routes/edge/tests/pdf.spec.js +345 -0
- package/build/routes/edge/tests/performance.spec.d.ts +1 -0
- package/build/routes/edge/tests/performance.spec.js +124 -0
- package/build/routes/edge/tests/scrape.spec.d.ts +1 -0
- package/build/routes/edge/tests/scrape.spec.js +354 -0
- package/build/routes/edge/tests/screenshot.spec.d.ts +1 -0
- package/build/routes/edge/tests/screenshot.spec.js +339 -0
- package/build/routes/edge/tests/websocket.spec.d.ts +1 -0
- package/build/routes/edge/tests/websocket.spec.js +384 -0
- package/build/routes/edge/ws/browser.d.ts +7 -0
- package/build/routes/edge/ws/browser.js +6 -0
- package/build/routes/edge/ws/browser.query.json +120 -0
- package/build/routes/edge/ws/cdp.d.ts +8 -0
- package/build/routes/edge/ws/cdp.js +7 -0
- package/build/routes/edge/ws/cdp.query.json +120 -0
- package/build/routes/edge/ws/page.d.ts +8 -0
- package/build/routes/edge/ws/page.js +7 -0
- package/build/routes/edge/ws/page.query.json +120 -0
- package/build/routes/edge/ws/playwright.d.ts +8 -0
- package/build/routes/edge/ws/playwright.js +7 -0
- package/build/routes/edge/ws/playwright.query.json +100 -0
- package/build/routes/firefox/tests/kill-sessions.spec.js +1 -1
- package/build/routes/management/http/meta.get.js +3 -1
- package/build/routes/webkit/tests/kill-sessions.spec.js +1 -1
- package/build/sdk-utils.js +1 -1
- package/build/shared/scrape.http.js +2 -2
- package/build/types.d.ts +32 -0
- package/build/types.js +18 -0
- package/build/utils.d.ts +1 -0
- package/build/utils.js +16 -2
- package/docker/chrome/Dockerfile +14 -14
- package/docker/chromium/Dockerfile +14 -14
- package/docker/edge/.dockerignore +16 -0
- package/docker/edge/Dockerfile +43 -0
- package/docker/firefox/Dockerfile +14 -14
- package/docker/multi/Dockerfile +18 -18
- package/docker/sdk/Dockerfile +10 -0
- package/extensions/ublock/_locales/ar/messages.json +3 -3
- package/extensions/ublock/_locales/bg/messages.json +1 -1
- package/extensions/ublock/_locales/br_FR/messages.json +2 -2
- package/extensions/ublock/_locales/cy/messages.json +11 -11
- package/extensions/ublock/_locales/el/messages.json +2 -2
- package/extensions/ublock/_locales/hu/messages.json +1 -1
- package/extensions/ublock/_locales/id/messages.json +1 -1
- package/extensions/ublock/_locales/lv/messages.json +4 -4
- package/extensions/ublock/_locales/mk/messages.json +130 -130
- package/extensions/ublock/_locales/oc/messages.json +1 -1
- package/extensions/ublock/_locales/pt_BR/messages.json +1 -1
- package/extensions/ublock/_locales/pt_PT/messages.json +2 -2
- package/extensions/ublock/_locales/si/messages.json +100 -100
- package/extensions/ublock/_locales/sr/messages.json +4 -4
- package/extensions/ublock/_locales/vi/messages.json +19 -19
- package/extensions/ublock/_locales/zh_TW/messages.json +28 -28
- package/extensions/ublock/assets/assets.json +33 -29
- package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +2984 -3287
- package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +150 -171
- package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +37 -27
- package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +802 -888
- package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +2355 -2071
- package/extensions/ublock/assets/ublock/badlists.txt +9 -1
- package/extensions/ublock/assets/ublock/badware.min.txt +354 -243
- package/extensions/ublock/assets/ublock/filters.min.txt +5837 -5737
- package/extensions/ublock/assets/ublock/privacy.min.txt +151 -38
- package/extensions/ublock/assets/ublock/quick-fixes.min.txt +83 -127
- package/extensions/ublock/assets/ublock/unbreak.min.txt +66 -50
- package/extensions/ublock/css/codemirror.css +4 -0
- package/extensions/ublock/document-blocked.html +3 -1
- package/extensions/ublock/js/arglist-parser.js +116 -0
- package/extensions/ublock/js/background.js +1 -1
- package/extensions/ublock/js/logger-ui.js +1 -1
- package/extensions/ublock/js/messaging.js +9 -2
- package/extensions/ublock/js/pagestore.js +3 -1
- package/extensions/ublock/js/redirect-engine.js +3 -1
- package/extensions/ublock/{assets/resources/set-attr.js → js/resources/attribute.js} +115 -11
- package/extensions/ublock/js/resources/base.js +38 -0
- package/extensions/ublock/js/resources/cookie.js +419 -0
- package/extensions/ublock/js/resources/href-sanitizer.js +188 -0
- package/extensions/ublock/js/resources/localstorage.js +235 -0
- package/extensions/ublock/js/resources/parse-replace.js +54 -0
- package/extensions/ublock/js/resources/prevent-settimeout.js +236 -0
- package/extensions/ublock/js/resources/proxy-apply.js +109 -0
- package/extensions/ublock/js/resources/replace-argument.js +120 -0
- package/extensions/ublock/{assets → js}/resources/run-at.js +20 -4
- package/extensions/ublock/{assets → js}/resources/safe-self.js +5 -4
- package/extensions/ublock/{assets → js}/resources/scriptlets.js +90 -1589
- package/extensions/ublock/js/resources/set-constant.js +287 -0
- package/extensions/ublock/js/resources/shared.js +44 -0
- package/extensions/ublock/js/resources/spoof-css.js +163 -0
- package/extensions/ublock/js/s14e-serializer.js +2 -1
- package/extensions/ublock/js/scriptlet-filtering-core.js +1 -1
- package/extensions/ublock/js/scriptlet-filtering.js +1 -31
- package/extensions/ublock/js/static-dnr-filtering.js +143 -129
- package/extensions/ublock/js/static-filtering-parser.js +27 -117
- package/extensions/ublock/js/static-net-filtering.js +53 -141
- package/extensions/ublock/js/traffic.js +1 -1
- package/extensions/ublock/js/urlskip.js +166 -0
- package/extensions/ublock/js/vapi-background-ext.js +38 -14
- package/extensions/ublock/manifest.json +1 -1
- package/package.json +22 -22
- package/src/browserless.ts +4 -0
- package/src/browsers/browsers.cdp.ts +5 -0
- package/src/browsers/browsers.playwright.ts +14 -1
- package/src/browsers/index.ts +5 -2
- package/src/http.ts +9 -0
- package/src/routes/chrome/tests/kill-sessions.spec.ts +1 -1
- package/src/routes/chromium/tests/kill-sessions.spec.ts +1 -1
- package/src/routes/edge/http/content.post.ts +20 -0
- package/src/routes/edge/http/download.post.ts +20 -0
- package/src/routes/edge/http/function.post.ts +20 -0
- package/src/routes/edge/http/json-list.get.ts +7 -0
- package/src/routes/edge/http/json-new.put.ts +7 -0
- package/src/routes/edge/http/json-protocol.get.ts +7 -0
- package/src/routes/edge/http/json-version.get.ts +7 -0
- package/src/routes/edge/http/pdf.post.ts +20 -0
- package/src/routes/edge/http/performance.post.ts +20 -0
- package/src/routes/edge/http/scrape.post.ts +20 -0
- package/src/routes/edge/http/screenshot.post.ts +20 -0
- package/src/routes/edge/tests/content.spec.ts +376 -0
- package/src/routes/edge/tests/download.spec.ts +77 -0
- package/src/routes/edge/tests/function.spec.ts +317 -0
- package/src/routes/edge/tests/json-version.spec.ts +52 -0
- package/src/routes/edge/tests/kill-sessions.spec.ts +99 -0
- package/src/routes/edge/tests/page-websocket.spec.ts +129 -0
- package/src/routes/edge/tests/pdf.spec.ts +389 -0
- package/src/routes/edge/tests/performance.spec.ts +155 -0
- package/src/routes/edge/tests/scrape.spec.ts +417 -0
- package/src/routes/edge/tests/screenshot.spec.ts +387 -0
- package/src/routes/edge/tests/websocket.spec.ts +510 -0
- package/src/routes/edge/ws/browser.ts +10 -0
- package/src/routes/edge/ws/cdp.ts +17 -0
- package/src/routes/edge/ws/page.ts +10 -0
- package/src/routes/edge/ws/playwright.ts +17 -0
- package/src/routes/firefox/tests/kill-sessions.spec.ts +1 -1
- package/src/routes/management/http/meta.get.ts +6 -1
- package/src/routes/management/http/static.get.ts +1 -1
- package/src/routes/webkit/tests/kill-sessions.spec.ts +1 -1
- package/src/sdk-utils.ts +1 -1
- package/src/shared/scrape.http.ts +2 -2
- package/src/types.ts +19 -0
- package/src/utils.ts +38 -16
- package/static/docs/swagger.json +2097 -10
- package/static/docs/swagger.min.json +2096 -9
- package/static/function/client.js +141 -253
- package/static/function/index.html +141 -253
|
@@ -18,16 +18,16 @@
|
|
|
18
18
|
|
|
19
19
|
Home: https://github.com/gorhill/uBlock
|
|
20
20
|
|
|
21
|
-
The scriptlets below are meant to be injected only into a
|
|
22
|
-
web page context.
|
|
23
21
|
*/
|
|
24
22
|
|
|
23
|
+
import { registerScriptlet } from './base.js';
|
|
25
24
|
import { runAt } from './run-at.js';
|
|
26
25
|
import { safeSelf } from './safe-self.js';
|
|
27
26
|
|
|
28
27
|
/******************************************************************************/
|
|
29
28
|
|
|
30
29
|
export function setAttrFn(
|
|
30
|
+
trusted = false,
|
|
31
31
|
logPrefix,
|
|
32
32
|
selector = '',
|
|
33
33
|
attr = '',
|
|
@@ -37,7 +37,7 @@ export function setAttrFn(
|
|
|
37
37
|
if ( attr === '' ) { return; }
|
|
38
38
|
|
|
39
39
|
const safe = safeSelf();
|
|
40
|
-
const copyFrom = /^\[.+\]$/.test(value)
|
|
40
|
+
const copyFrom = trusted === false && /^\[.+\]$/.test(value)
|
|
41
41
|
? value.slice(1, -1)
|
|
42
42
|
: '';
|
|
43
43
|
|
|
@@ -95,13 +95,13 @@ export function setAttrFn(
|
|
|
95
95
|
};
|
|
96
96
|
runAt(( ) => { start(); }, 'idle');
|
|
97
97
|
}
|
|
98
|
-
setAttrFn
|
|
98
|
+
registerScriptlet(setAttrFn, {
|
|
99
99
|
name: 'set-attr.fn',
|
|
100
100
|
dependencies: [
|
|
101
101
|
runAt,
|
|
102
102
|
safeSelf,
|
|
103
103
|
],
|
|
104
|
-
};
|
|
104
|
+
});
|
|
105
105
|
|
|
106
106
|
/**
|
|
107
107
|
* @scriptlet set-attr
|
|
@@ -147,16 +147,16 @@ export function setAttr(
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
setAttrFn(logPrefix, selector, attr, value);
|
|
150
|
+
setAttrFn(false, logPrefix, selector, attr, value);
|
|
151
151
|
}
|
|
152
|
-
setAttr
|
|
152
|
+
registerScriptlet(setAttr, {
|
|
153
153
|
name: 'set-attr.js',
|
|
154
154
|
dependencies: [
|
|
155
155
|
safeSelf,
|
|
156
156
|
setAttrFn,
|
|
157
157
|
],
|
|
158
158
|
world: 'ISOLATED',
|
|
159
|
-
};
|
|
159
|
+
});
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
162
|
* @trustedScriptlet trusted-set-attr
|
|
@@ -186,9 +186,9 @@ export function trustedSetAttr(
|
|
|
186
186
|
) {
|
|
187
187
|
const safe = safeSelf();
|
|
188
188
|
const logPrefix = safe.makeLogPrefix('trusted-set-attr', selector, attr, value);
|
|
189
|
-
setAttrFn(logPrefix, selector, attr, value);
|
|
189
|
+
setAttrFn(true, logPrefix, selector, attr, value);
|
|
190
190
|
}
|
|
191
|
-
trustedSetAttr
|
|
191
|
+
registerScriptlet(trustedSetAttr, {
|
|
192
192
|
name: 'trusted-set-attr.js',
|
|
193
193
|
requiresTrust: true,
|
|
194
194
|
dependencies: [
|
|
@@ -196,6 +196,110 @@ trustedSetAttr.details = {
|
|
|
196
196
|
setAttrFn,
|
|
197
197
|
],
|
|
198
198
|
world: 'ISOLATED',
|
|
199
|
-
};
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* @scriptlet remove-attr
|
|
203
|
+
*
|
|
204
|
+
* @description
|
|
205
|
+
* Remove one or more attributes from a set of elements.
|
|
206
|
+
*
|
|
207
|
+
* @param attribute
|
|
208
|
+
* The name of the attribute(s) to remove. This can be a list of space-
|
|
209
|
+
* separated attribute names.
|
|
210
|
+
*
|
|
211
|
+
* @param [selector]
|
|
212
|
+
* Optional. A CSS selector for the elements to target. Default to
|
|
213
|
+
* `[attribute]`, or `[attribute1],[attribute2],...` if more than one
|
|
214
|
+
* attribute name is specified.
|
|
215
|
+
*
|
|
216
|
+
* @param [behavior]
|
|
217
|
+
* Optional. Space-separated tokens which modify the default behavior.
|
|
218
|
+
* - `asap`: Try to remove the attribute as soon as possible. Default behavior
|
|
219
|
+
* is to remove the attribute(s) asynchronously.
|
|
220
|
+
* - `stay`: Keep trying to remove the specified attribute(s) on DOM mutations.
|
|
221
|
+
* */
|
|
222
|
+
|
|
223
|
+
export function removeAttr(
|
|
224
|
+
rawToken = '',
|
|
225
|
+
rawSelector = '',
|
|
226
|
+
behavior = ''
|
|
227
|
+
) {
|
|
228
|
+
if ( typeof rawToken !== 'string' ) { return; }
|
|
229
|
+
if ( rawToken === '' ) { return; }
|
|
230
|
+
const safe = safeSelf();
|
|
231
|
+
const logPrefix = safe.makeLogPrefix('remove-attr', rawToken, rawSelector, behavior);
|
|
232
|
+
const tokens = safe.String_split.call(rawToken, /\s*\|\s*/);
|
|
233
|
+
const selector = tokens
|
|
234
|
+
.map(a => `${rawSelector}[${CSS.escape(a)}]`)
|
|
235
|
+
.join(',');
|
|
236
|
+
if ( safe.logLevel > 1 ) {
|
|
237
|
+
safe.uboLog(logPrefix, `Target selector:\n\t${selector}`);
|
|
238
|
+
}
|
|
239
|
+
const asap = /\basap\b/.test(behavior);
|
|
240
|
+
let timerId;
|
|
241
|
+
const rmattrAsync = ( ) => {
|
|
242
|
+
if ( timerId !== undefined ) { return; }
|
|
243
|
+
timerId = safe.onIdle(( ) => {
|
|
244
|
+
timerId = undefined;
|
|
245
|
+
rmattr();
|
|
246
|
+
}, { timeout: 17 });
|
|
247
|
+
};
|
|
248
|
+
const rmattr = ( ) => {
|
|
249
|
+
if ( timerId !== undefined ) {
|
|
250
|
+
safe.offIdle(timerId);
|
|
251
|
+
timerId = undefined;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const nodes = document.querySelectorAll(selector);
|
|
255
|
+
for ( const node of nodes ) {
|
|
256
|
+
for ( const attr of tokens ) {
|
|
257
|
+
if ( node.hasAttribute(attr) === false ) { continue; }
|
|
258
|
+
node.removeAttribute(attr);
|
|
259
|
+
safe.uboLog(logPrefix, `Removed attribute '${attr}'`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} catch(ex) {
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const mutationHandler = mutations => {
|
|
266
|
+
if ( timerId !== undefined ) { return; }
|
|
267
|
+
let skip = true;
|
|
268
|
+
for ( let i = 0; i < mutations.length && skip; i++ ) {
|
|
269
|
+
const { type, addedNodes, removedNodes } = mutations[i];
|
|
270
|
+
if ( type === 'attributes' ) { skip = false; }
|
|
271
|
+
for ( let j = 0; j < addedNodes.length && skip; j++ ) {
|
|
272
|
+
if ( addedNodes[j].nodeType === 1 ) { skip = false; break; }
|
|
273
|
+
}
|
|
274
|
+
for ( let j = 0; j < removedNodes.length && skip; j++ ) {
|
|
275
|
+
if ( removedNodes[j].nodeType === 1 ) { skip = false; break; }
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if ( skip ) { return; }
|
|
279
|
+
asap ? rmattr() : rmattrAsync();
|
|
280
|
+
};
|
|
281
|
+
const start = ( ) => {
|
|
282
|
+
rmattr();
|
|
283
|
+
if ( /\bstay\b/.test(behavior) === false ) { return; }
|
|
284
|
+
const observer = new MutationObserver(mutationHandler);
|
|
285
|
+
observer.observe(document, {
|
|
286
|
+
attributes: true,
|
|
287
|
+
attributeFilter: tokens,
|
|
288
|
+
childList: true,
|
|
289
|
+
subtree: true,
|
|
290
|
+
});
|
|
291
|
+
};
|
|
292
|
+
runAt(( ) => { start(); }, safe.String_split.call(behavior, /\s+/));
|
|
293
|
+
}
|
|
294
|
+
registerScriptlet(removeAttr, {
|
|
295
|
+
name: 'remove-attr.js',
|
|
296
|
+
aliases: [
|
|
297
|
+
'ra.js',
|
|
298
|
+
],
|
|
299
|
+
dependencies: [
|
|
300
|
+
runAt,
|
|
301
|
+
safeSelf,
|
|
302
|
+
],
|
|
303
|
+
});
|
|
200
304
|
|
|
201
305
|
/******************************************************************************/
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
|
|
3
|
+
uBlock Origin - a comprehensive, efficient content blocker
|
|
4
|
+
Copyright (C) 2019-present Raymond Hill
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
18
|
+
|
|
19
|
+
Home: https://github.com/gorhill/uBlock
|
|
20
|
+
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const registeredScriptlets = [];
|
|
24
|
+
|
|
25
|
+
export const registerScriptlet = (fn, details) => {
|
|
26
|
+
if ( typeof details !== 'object' ) {
|
|
27
|
+
throw new ReferenceError('Missing scriptlet details');
|
|
28
|
+
}
|
|
29
|
+
details.fn = fn;
|
|
30
|
+
fn.details = details;
|
|
31
|
+
if ( Array.isArray(details.dependencies) ) {
|
|
32
|
+
details.dependencies.forEach((fn, i, array) => {
|
|
33
|
+
if ( typeof fn !== 'function' ) { return; }
|
|
34
|
+
array[i] = fn.details.name;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
registeredScriptlets.push(details);
|
|
38
|
+
};
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/*******************************************************************************
|
|
2
|
+
|
|
3
|
+
uBlock Origin - a comprehensive, efficient content blocker
|
|
4
|
+
Copyright (C) 2019-present Raymond Hill
|
|
5
|
+
|
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
|
7
|
+
it under the terms of the GNU General Public License as published by
|
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
(at your option) any later version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful,
|
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
GNU General Public License for more details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License
|
|
17
|
+
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
|
18
|
+
|
|
19
|
+
Home: https://github.com/gorhill/uBlock
|
|
20
|
+
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { registerScriptlet } from './base.js';
|
|
24
|
+
import { safeSelf } from './safe-self.js';
|
|
25
|
+
|
|
26
|
+
/******************************************************************************/
|
|
27
|
+
|
|
28
|
+
export function getSafeCookieValuesFn() {
|
|
29
|
+
return [
|
|
30
|
+
'accept', 'reject',
|
|
31
|
+
'accepted', 'rejected', 'notaccepted',
|
|
32
|
+
'allow', 'disallow', 'deny',
|
|
33
|
+
'allowed', 'denied',
|
|
34
|
+
'approved', 'disapproved',
|
|
35
|
+
'checked', 'unchecked',
|
|
36
|
+
'dismiss', 'dismissed',
|
|
37
|
+
'enable', 'disable',
|
|
38
|
+
'enabled', 'disabled',
|
|
39
|
+
'essential', 'nonessential',
|
|
40
|
+
'forbidden', 'forever',
|
|
41
|
+
'hide', 'hidden',
|
|
42
|
+
'necessary', 'required',
|
|
43
|
+
'ok',
|
|
44
|
+
'on', 'off',
|
|
45
|
+
'true', 't', 'false', 'f',
|
|
46
|
+
'yes', 'y', 'no', 'n',
|
|
47
|
+
'all', 'none', 'functional',
|
|
48
|
+
'granted', 'done',
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
registerScriptlet(getSafeCookieValuesFn, {
|
|
52
|
+
name: 'get-safe-cookie-values.fn',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
/******************************************************************************/
|
|
56
|
+
|
|
57
|
+
export function getAllCookiesFn() {
|
|
58
|
+
const safe = safeSelf();
|
|
59
|
+
return safe.String_split.call(document.cookie, /\s*;\s*/).map(s => {
|
|
60
|
+
const pos = s.indexOf('=');
|
|
61
|
+
if ( pos === 0 ) { return; }
|
|
62
|
+
if ( pos === -1 ) { return `${s.trim()}=`; }
|
|
63
|
+
const key = s.slice(0, pos).trim();
|
|
64
|
+
const value = s.slice(pos+1).trim();
|
|
65
|
+
return { key, value };
|
|
66
|
+
}).filter(s => s !== undefined);
|
|
67
|
+
}
|
|
68
|
+
registerScriptlet(getAllCookiesFn, {
|
|
69
|
+
name: 'get-all-cookies.fn',
|
|
70
|
+
dependencies: [
|
|
71
|
+
safeSelf,
|
|
72
|
+
],
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
/******************************************************************************/
|
|
76
|
+
|
|
77
|
+
export function getCookieFn(
|
|
78
|
+
name = ''
|
|
79
|
+
) {
|
|
80
|
+
const safe = safeSelf();
|
|
81
|
+
for ( const s of safe.String_split.call(document.cookie, /\s*;\s*/) ) {
|
|
82
|
+
const pos = s.indexOf('=');
|
|
83
|
+
if ( pos === -1 ) { continue; }
|
|
84
|
+
if ( s.slice(0, pos) !== name ) { continue; }
|
|
85
|
+
return s.slice(pos+1).trim();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
registerScriptlet(getCookieFn, {
|
|
89
|
+
name: 'get-cookie.fn',
|
|
90
|
+
dependencies: [
|
|
91
|
+
safeSelf,
|
|
92
|
+
],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/******************************************************************************/
|
|
96
|
+
|
|
97
|
+
export function setCookieFn(
|
|
98
|
+
trusted = false,
|
|
99
|
+
name = '',
|
|
100
|
+
value = '',
|
|
101
|
+
expires = '',
|
|
102
|
+
path = '',
|
|
103
|
+
options = {},
|
|
104
|
+
) {
|
|
105
|
+
// https://datatracker.ietf.org/doc/html/rfc2616#section-2.2
|
|
106
|
+
// https://github.com/uBlockOrigin/uBlock-issues/issues/2777
|
|
107
|
+
if ( trusted === false && /[^!#$%&'*+\-.0-9A-Z[\]^_`a-z|~]/.test(name) ) {
|
|
108
|
+
name = encodeURIComponent(name);
|
|
109
|
+
}
|
|
110
|
+
// https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1
|
|
111
|
+
// The characters [",] are given a pass from the RFC requirements because
|
|
112
|
+
// apparently browsers do not follow the RFC to the letter.
|
|
113
|
+
if ( /[^ -:<-[\]-~]/.test(value) ) {
|
|
114
|
+
value = encodeURIComponent(value);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const cookieBefore = getCookieFn(name);
|
|
118
|
+
if ( cookieBefore !== undefined && options.dontOverwrite ) { return; }
|
|
119
|
+
if ( cookieBefore === value && options.reload ) { return; }
|
|
120
|
+
|
|
121
|
+
const cookieParts = [ name, '=', value ];
|
|
122
|
+
if ( expires !== '' ) {
|
|
123
|
+
cookieParts.push('; expires=', expires);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if ( path === '' ) { path = '/'; }
|
|
127
|
+
else if ( path === 'none' ) { path = ''; }
|
|
128
|
+
if ( path !== '' && path !== '/' ) { return; }
|
|
129
|
+
if ( path === '/' ) {
|
|
130
|
+
cookieParts.push('; path=/');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if ( trusted ) {
|
|
134
|
+
if ( options.domain ) {
|
|
135
|
+
cookieParts.push(`; domain=${options.domain}`);
|
|
136
|
+
}
|
|
137
|
+
cookieParts.push('; Secure');
|
|
138
|
+
} else if ( /^__(Host|Secure)-/.test(name) ) {
|
|
139
|
+
cookieParts.push('; Secure');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
document.cookie = cookieParts.join('');
|
|
144
|
+
} catch(_) {
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const done = getCookieFn(name) === value;
|
|
148
|
+
if ( done && options.reload ) {
|
|
149
|
+
window.location.reload();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return done;
|
|
153
|
+
}
|
|
154
|
+
registerScriptlet(setCookieFn, {
|
|
155
|
+
name: 'set-cookie.fn',
|
|
156
|
+
dependencies: [
|
|
157
|
+
getCookieFn,
|
|
158
|
+
],
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @scriptlet set-cookie
|
|
163
|
+
*
|
|
164
|
+
* @description
|
|
165
|
+
* Set a cookie to a safe value.
|
|
166
|
+
*
|
|
167
|
+
* @param name
|
|
168
|
+
* The name of the cookie to set.
|
|
169
|
+
*
|
|
170
|
+
* @param value
|
|
171
|
+
* The value of the cookie to set. Must be a safe value. Unsafe values will be
|
|
172
|
+
* ignored and no cookie will be set. See getSafeCookieValuesFn() helper above.
|
|
173
|
+
*
|
|
174
|
+
* @param [path]
|
|
175
|
+
* Optional. The path of the cookie to set. Default to `/`.
|
|
176
|
+
*
|
|
177
|
+
* Reference:
|
|
178
|
+
* https://github.com/AdguardTeam/Scriptlets/blob/master/src/scriptlets/set-cookie.js
|
|
179
|
+
* */
|
|
180
|
+
|
|
181
|
+
export function setCookie(
|
|
182
|
+
name = '',
|
|
183
|
+
value = '',
|
|
184
|
+
path = ''
|
|
185
|
+
) {
|
|
186
|
+
if ( name === '' ) { return; }
|
|
187
|
+
const safe = safeSelf();
|
|
188
|
+
const logPrefix = safe.makeLogPrefix('set-cookie', name, value, path);
|
|
189
|
+
const normalized = value.toLowerCase();
|
|
190
|
+
const match = /^("?)(.+)\1$/.exec(normalized);
|
|
191
|
+
const unquoted = match && match[2] || normalized;
|
|
192
|
+
const validValues = getSafeCookieValuesFn();
|
|
193
|
+
if ( validValues.includes(unquoted) === false ) {
|
|
194
|
+
if ( /^-?\d+$/.test(unquoted) === false ) { return; }
|
|
195
|
+
const n = parseInt(value, 10) || 0;
|
|
196
|
+
if ( n < -32767 || n > 32767 ) { return; }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const done = setCookieFn(
|
|
200
|
+
false,
|
|
201
|
+
name,
|
|
202
|
+
value,
|
|
203
|
+
'',
|
|
204
|
+
path,
|
|
205
|
+
safe.getExtraArgs(Array.from(arguments), 3)
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
if ( done ) {
|
|
209
|
+
safe.uboLog(logPrefix, 'Done');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
registerScriptlet(setCookie, {
|
|
213
|
+
name: 'set-cookie.js',
|
|
214
|
+
world: 'ISOLATED',
|
|
215
|
+
dependencies: [
|
|
216
|
+
getSafeCookieValuesFn,
|
|
217
|
+
safeSelf,
|
|
218
|
+
setCookieFn,
|
|
219
|
+
],
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// For compatibility with AdGuard
|
|
223
|
+
export function setCookieReload(name, value, path, ...args) {
|
|
224
|
+
setCookie(name, value, path, 'reload', '1', ...args);
|
|
225
|
+
}
|
|
226
|
+
registerScriptlet(setCookieReload, {
|
|
227
|
+
name: 'set-cookie-reload.js',
|
|
228
|
+
world: 'ISOLATED',
|
|
229
|
+
dependencies: [
|
|
230
|
+
setCookie,
|
|
231
|
+
],
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* @trustedScriptlet trusted-set-cookie
|
|
236
|
+
*
|
|
237
|
+
* @description
|
|
238
|
+
* Set a cookie to any value. This scriptlet can be used only from a trusted
|
|
239
|
+
* source.
|
|
240
|
+
*
|
|
241
|
+
* @param name
|
|
242
|
+
* The name of the cookie to set.
|
|
243
|
+
*
|
|
244
|
+
* @param value
|
|
245
|
+
* The value of the cookie to set. Must be a safe value. Unsafe values will be
|
|
246
|
+
* ignored and no cookie will be set. See getSafeCookieValuesFn() helper above.
|
|
247
|
+
*
|
|
248
|
+
* @param [offsetExpiresSec]
|
|
249
|
+
* Optional. The path of the cookie to set. Default to `/`.
|
|
250
|
+
*
|
|
251
|
+
* @param [path]
|
|
252
|
+
* Optional. The path of the cookie to set. Default to `/`.
|
|
253
|
+
*
|
|
254
|
+
* Reference:
|
|
255
|
+
* https://github.com/AdguardTeam/Scriptlets/blob/master/src/scriptlets/set-cookie.js
|
|
256
|
+
* */
|
|
257
|
+
|
|
258
|
+
export function trustedSetCookie(
|
|
259
|
+
name = '',
|
|
260
|
+
value = '',
|
|
261
|
+
offsetExpiresSec = '',
|
|
262
|
+
path = ''
|
|
263
|
+
) {
|
|
264
|
+
if ( name === '' ) { return; }
|
|
265
|
+
|
|
266
|
+
const safe = safeSelf();
|
|
267
|
+
const logPrefix = safe.makeLogPrefix('set-cookie', name, value, path);
|
|
268
|
+
const time = new Date();
|
|
269
|
+
|
|
270
|
+
if ( value.includes('$now$') ) {
|
|
271
|
+
value = value.replaceAll('$now$', time.getTime());
|
|
272
|
+
}
|
|
273
|
+
if ( value.includes('$currentDate$') ) {
|
|
274
|
+
value = value.replaceAll('$currentDate$', time.toUTCString());
|
|
275
|
+
}
|
|
276
|
+
if ( value.includes('$currentISODate$') ) {
|
|
277
|
+
value = value.replaceAll('$currentISODate$', time.toISOString());
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let expires = '';
|
|
281
|
+
if ( offsetExpiresSec !== '' ) {
|
|
282
|
+
if ( offsetExpiresSec === '1day' ) {
|
|
283
|
+
time.setDate(time.getDate() + 1);
|
|
284
|
+
} else if ( offsetExpiresSec === '1year' ) {
|
|
285
|
+
time.setFullYear(time.getFullYear() + 1);
|
|
286
|
+
} else {
|
|
287
|
+
if ( /^\d+$/.test(offsetExpiresSec) === false ) { return; }
|
|
288
|
+
time.setSeconds(time.getSeconds() + parseInt(offsetExpiresSec, 10));
|
|
289
|
+
}
|
|
290
|
+
expires = time.toUTCString();
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const done = setCookieFn(
|
|
294
|
+
true,
|
|
295
|
+
name,
|
|
296
|
+
value,
|
|
297
|
+
expires,
|
|
298
|
+
path,
|
|
299
|
+
safeSelf().getExtraArgs(Array.from(arguments), 4)
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
if ( done ) {
|
|
303
|
+
safe.uboLog(logPrefix, 'Done');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
registerScriptlet(trustedSetCookie, {
|
|
307
|
+
name: 'trusted-set-cookie.js',
|
|
308
|
+
requiresTrust: true,
|
|
309
|
+
world: 'ISOLATED',
|
|
310
|
+
dependencies: [
|
|
311
|
+
safeSelf,
|
|
312
|
+
setCookieFn,
|
|
313
|
+
],
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// For compatibility with AdGuard
|
|
317
|
+
export function trustedSetCookieReload(name, value, offsetExpiresSec, path, ...args) {
|
|
318
|
+
trustedSetCookie(name, value, offsetExpiresSec, path, 'reload', '1', ...args);
|
|
319
|
+
}
|
|
320
|
+
registerScriptlet(trustedSetCookieReload, {
|
|
321
|
+
name: 'trusted-set-cookie-reload.js',
|
|
322
|
+
requiresTrust: true,
|
|
323
|
+
world: 'ISOLATED',
|
|
324
|
+
dependencies: [
|
|
325
|
+
trustedSetCookie,
|
|
326
|
+
],
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* @scriptlet remove-cookie
|
|
331
|
+
*
|
|
332
|
+
* @description
|
|
333
|
+
* Removes current site cookies specified by name. The removal operation occurs
|
|
334
|
+
* immediately when the scriptlet is injected, then when the page is unloaded.
|
|
335
|
+
*
|
|
336
|
+
* @param needle
|
|
337
|
+
* A string or a regex matching the name of the cookie(s) to remove.
|
|
338
|
+
*
|
|
339
|
+
* @param ['when', token]
|
|
340
|
+
* Vararg, optional. The parameter following 'when' tells when extra removal
|
|
341
|
+
* operations should take place.
|
|
342
|
+
* - `scroll`: when the page is scrolled
|
|
343
|
+
* - `keydown`: when a keyboard touch is pressed
|
|
344
|
+
*
|
|
345
|
+
* */
|
|
346
|
+
|
|
347
|
+
export function removeCookie(
|
|
348
|
+
needle = ''
|
|
349
|
+
) {
|
|
350
|
+
if ( typeof needle !== 'string' ) { return; }
|
|
351
|
+
const safe = safeSelf();
|
|
352
|
+
const reName = safe.patternToRegex(needle);
|
|
353
|
+
const extraArgs = safe.getExtraArgs(Array.from(arguments), 1);
|
|
354
|
+
const throttle = (fn, ms = 500) => {
|
|
355
|
+
if ( throttle.timer !== undefined ) { return; }
|
|
356
|
+
throttle.timer = setTimeout(( ) => {
|
|
357
|
+
throttle.timer = undefined;
|
|
358
|
+
fn();
|
|
359
|
+
}, ms);
|
|
360
|
+
};
|
|
361
|
+
const remove = ( ) => {
|
|
362
|
+
safe.String_split.call(document.cookie, ';').forEach(cookieStr => {
|
|
363
|
+
const pos = cookieStr.indexOf('=');
|
|
364
|
+
if ( pos === -1 ) { return; }
|
|
365
|
+
const cookieName = cookieStr.slice(0, pos).trim();
|
|
366
|
+
if ( reName.test(cookieName) === false ) { return; }
|
|
367
|
+
const part1 = cookieName + '=';
|
|
368
|
+
const part2a = '; domain=' + document.location.hostname;
|
|
369
|
+
const part2b = '; domain=.' + document.location.hostname;
|
|
370
|
+
let part2c, part2d;
|
|
371
|
+
const domain = document.domain;
|
|
372
|
+
if ( domain ) {
|
|
373
|
+
if ( domain !== document.location.hostname ) {
|
|
374
|
+
part2c = '; domain=.' + domain;
|
|
375
|
+
}
|
|
376
|
+
if ( domain.startsWith('www.') ) {
|
|
377
|
+
part2d = '; domain=' + domain.replace('www', '');
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
const part3 = '; path=/';
|
|
381
|
+
const part4 = '; Max-Age=-1000; expires=Thu, 01 Jan 1970 00:00:00 GMT';
|
|
382
|
+
document.cookie = part1 + part4;
|
|
383
|
+
document.cookie = part1 + part2a + part4;
|
|
384
|
+
document.cookie = part1 + part2b + part4;
|
|
385
|
+
document.cookie = part1 + part3 + part4;
|
|
386
|
+
document.cookie = part1 + part2a + part3 + part4;
|
|
387
|
+
document.cookie = part1 + part2b + part3 + part4;
|
|
388
|
+
if ( part2c !== undefined ) {
|
|
389
|
+
document.cookie = part1 + part2c + part3 + part4;
|
|
390
|
+
}
|
|
391
|
+
if ( part2d !== undefined ) {
|
|
392
|
+
document.cookie = part1 + part2d + part3 + part4;
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
};
|
|
396
|
+
remove();
|
|
397
|
+
window.addEventListener('beforeunload', remove);
|
|
398
|
+
if ( typeof extraArgs.when !== 'string' ) { return; }
|
|
399
|
+
const supportedEventTypes = [ 'scroll', 'keydown' ];
|
|
400
|
+
const eventTypes = safe.String_split.call(extraArgs.when, /\s/);
|
|
401
|
+
for ( const type of eventTypes ) {
|
|
402
|
+
if ( supportedEventTypes.includes(type) === false ) { continue; }
|
|
403
|
+
document.addEventListener(type, ( ) => {
|
|
404
|
+
throttle(remove);
|
|
405
|
+
}, { passive: true });
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
registerScriptlet(removeCookie, {
|
|
409
|
+
name: 'remove-cookie.js',
|
|
410
|
+
aliases: [
|
|
411
|
+
'cookie-remover.js',
|
|
412
|
+
],
|
|
413
|
+
world: 'ISOLATED',
|
|
414
|
+
dependencies: [
|
|
415
|
+
safeSelf,
|
|
416
|
+
],
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
/******************************************************************************/
|