Skip to content

Commit ab56a3e

Browse files
brianhallgithub-actions[bot]
authored andcommitted
Release build 8.17.0 [ci release]
1 parent ddc78d8 commit ab56a3e

File tree

27 files changed

+840
-81
lines changed

27 files changed

+840
-81
lines changed

.github/workflows/tests.yml

+6
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ jobs:
7171
name: playwright-report-pages
7272
path: special-pages/playwright-report
7373
retention-days: 5
74+
- uses: actions/upload-artifact@v4
75+
if: always()
76+
with:
77+
name: playwright-report-injected
78+
path: injected/playwright-report
79+
retention-days: 5
7480
- name: Build docs
7581
run: npm run docs
7682

CHANGELOG.txt

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
- include tests in codeowners for broker-protection (#1634)
2-
- ntp: improve styling on favorites tiles (#1637)
3-
- Support navigation based conditional matching (#1610)
1+
- Add Cloudflare Turnstile Support (#1633)
2+
- [ConfigFeature] config feature docs update (#1647)
3+
- build(deps-dev): bump typedoc in the typescript group (#1645)
4+
- injected: fixing flaky duckplayer tests (#1639)

Sources/ContentScopeScripts/dist/contentScopeIsolated.js

+134-8
Original file line numberDiff line numberDiff line change
@@ -9617,11 +9617,12 @@
96179617
}
96189618
/**
96199619
* Detect the captcha provider based on the element
9620+
* @param {Document | HTMLElement} root
96209621
* @param {HTMLElement} element - The element to check
96219622
* @returns {import('./providers/provider.interface').CaptchaProvider|null}
96229623
*/
9623-
detectProvider(element) {
9624-
return this._getAllProviders().find((provider) => provider.isSupportedForElement(element)) || null;
9624+
detectProvider(root, element) {
9625+
return this._getAllProviders().find((provider) => provider.isSupportedForElement(root, element)) || null;
96259626
}
96269627
/**
96279628
* Detect the captcha provider based on the root document
@@ -9782,9 +9783,10 @@
97829783
return __privateGet(this, _config).type;
97839784
}
97849785
/**
9786+
* @param {Document | HTMLElement} _root
97859787
* @param {HTMLElement} captchaContainerElement
97869788
*/
9787-
isSupportedForElement(captchaContainerElement) {
9789+
isSupportedForElement(_root, captchaContainerElement) {
97889790
return !!this._getCaptchaElement(captchaContainerElement);
97899791
}
97909792
/**
@@ -9885,9 +9887,10 @@
98859887
return "image";
98869888
}
98879889
/**
9890+
* @param {Document | HTMLElement} _root
98889891
* @param {HTMLElement} captchaImageElement - The captcha image element
98899892
*/
9890-
isSupportedForElement(captchaImageElement) {
9893+
isSupportedForElement(_root, captchaImageElement) {
98919894
if (!captchaImageElement) {
98929895
return false;
98939896
}
@@ -9943,6 +9946,125 @@
99439946
return isElementType(element, "img");
99449947
}
99459948

9949+
// src/features/broker-protection/captcha-services/providers/cloudflare-turnstile.js
9950+
init_define_import_meta_trackerLookup();
9951+
9952+
// src/features/broker-protection/captcha-services/utils/attribute.js
9953+
init_define_import_meta_trackerLookup();
9954+
function getAttributeValue({ element, attrName }) {
9955+
if (!element) {
9956+
throw Error("[getAttributeValue] element parameter is required");
9957+
}
9958+
const attributeValue = element.getAttribute(attrName);
9959+
if (!attributeValue) {
9960+
throw Error(`[getAttributeValue] ${attrName} is not defined or has no value`);
9961+
}
9962+
return attributeValue;
9963+
}
9964+
9965+
// src/features/broker-protection/captcha-services/providers/cloudflare-turnstile.js
9966+
var _config2;
9967+
var CloudFlareTurnstileProvider = class {
9968+
constructor() {
9969+
/**
9970+
* @type {CloudFlareTurnstileProviderConfig}
9971+
*/
9972+
__privateAdd(this, _config2);
9973+
__privateSet(this, _config2, {
9974+
providerUrl: "https://challenges.cloudflare.com/turnstile/v0",
9975+
responseElementName: "cf-turnstile-response"
9976+
});
9977+
}
9978+
getType() {
9979+
return "cloudFlareTurnstile";
9980+
}
9981+
/**
9982+
* @param {Document | HTMLElement} root
9983+
* @param {HTMLElement} _captchaContainerElement
9984+
* @returns {boolean} Whether the captcha is supported for the element
9985+
*/
9986+
isSupportedForElement(root, _captchaContainerElement) {
9987+
return !!this._getCaptchaScript(root);
9988+
}
9989+
/**
9990+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
9991+
*/
9992+
getCaptchaIdentifier(captchaContainerElement) {
9993+
const sitekeyAttribute = "data-sitekey";
9994+
return Promise.resolve(
9995+
safeCallWithError(() => getAttributeValue({ element: captchaContainerElement, attrName: sitekeyAttribute }), {
9996+
errorMessage: `[CloudFlareTurnstileProvider.getCaptchaIdentifier] could not extract site key from attribute: ${sitekeyAttribute}`
9997+
})
9998+
);
9999+
}
10000+
getSupportingCodeToInject() {
10001+
return null;
10002+
}
10003+
/**
10004+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
10005+
* @returns {boolean} Whether the captcha can be solved
10006+
*/
10007+
canSolve(captchaContainerElement) {
10008+
const callbackAttribute = "data-callback";
10009+
const hasCallback = safeCallWithError(() => getAttributeValue({ element: captchaContainerElement, attrName: callbackAttribute }), {
10010+
errorMessage: `[CloudFlareTurnstileProvider.canSolve] could not extract callback function name from attribute: ${callbackAttribute}`
10011+
});
10012+
if (PirError.isError(hasCallback)) {
10013+
return false;
10014+
}
10015+
const hasResponseElement = safeCallWithError(() => getElementByTagName(captchaContainerElement, __privateGet(this, _config2).responseElementName), {
10016+
errorMessage: `[CloudFlareTurnstileProvider.canSolve] could not find response element: ${__privateGet(this, _config2).responseElementName}`
10017+
});
10018+
if (PirError.isError(hasResponseElement)) {
10019+
return false;
10020+
}
10021+
return true;
10022+
}
10023+
/**
10024+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
10025+
* @param {string} token - The solved captcha token
10026+
*/
10027+
injectToken(captchaContainerElement, token) {
10028+
return injectTokenIntoElement({ captchaContainerElement, elementName: __privateGet(this, _config2).responseElementName, token });
10029+
}
10030+
/**
10031+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
10032+
* @param {string} token - The solved captcha token
10033+
*/
10034+
getSolveCallback(captchaContainerElement, token) {
10035+
const callbackAttribute = "data-callback";
10036+
const callbackFunctionName = safeCallWithError(
10037+
() => getAttributeValue({ element: captchaContainerElement, attrName: callbackAttribute }),
10038+
{
10039+
errorMessage: `[CloudFlareTurnstileProvider.getSolveCallback] could not extract callback function name from attribute: ${callbackAttribute}`
10040+
}
10041+
);
10042+
if (PirError.isError(callbackFunctionName)) {
10043+
return callbackFunctionName;
10044+
}
10045+
return stringifyFunction({
10046+
/**
10047+
* @param {Object} args - The arguments passed to the function
10048+
* @param {string} args.callbackFunctionName - The callback function name
10049+
* @param {string} args.token - The solved captcha token
10050+
*/
10051+
functionBody: function cloudflareCaptchaCallback(args) {
10052+
window[args.callbackFunctionName](args.token);
10053+
},
10054+
functionName: "cloudflareCaptchaCallback",
10055+
args: { callbackFunctionName, token }
10056+
});
10057+
}
10058+
/**
10059+
* @private
10060+
* @param {Document | HTMLElement} root - The root element to search in
10061+
*/
10062+
_getCaptchaScript(root) {
10063+
return getElementWithSrcStart(root, __privateGet(this, _config2).providerUrl);
10064+
}
10065+
};
10066+
_config2 = new WeakMap();
10067+
994610068
// src/features/broker-protection/captcha-services/providers/registry.js
994710069
var captchaFactory = new CaptchaFactory();
994810070
captchaFactory.registerProvider(
@@ -9959,18 +10081,19 @@
995910081
responseElementName: "g-recaptcha-response"
996010082
})
996110083
);
10084+
captchaFactory.registerProvider(new CloudFlareTurnstileProvider());
996210085
captchaFactory.registerProvider(new ImageProvider());
996310086

996410087
// src/features/broker-protection/captcha-services/get-captcha-provider.js
9965-
function getCaptchaProvider(captchaContainer, captchaType) {
10088+
function getCaptchaProvider(root, captchaContainer, captchaType) {
996610089
const captchaProvider = captchaFactory.getProviderByType(captchaType);
996710090
if (!captchaProvider) {
996810091
return PirError.create(`[getCaptchaProvider] could not find captcha provider with type ${captchaType}`);
996910092
}
9970-
if (captchaProvider.isSupportedForElement(captchaContainer)) {
10093+
if (captchaProvider.isSupportedForElement(root, captchaContainer)) {
997110094
return captchaProvider;
997210095
}
9973-
const detectedProvider = captchaFactory.detectProvider(captchaContainer);
10096+
const detectedProvider = captchaFactory.detectProvider(root, captchaContainer);
997410097
if (!detectedProvider) {
997510098
return PirError.create(
997610099
`[getCaptchaProvider] could not detect captcha provider for ${captchaType} captcha and element ${captchaContainer}`
@@ -10118,14 +10241,17 @@
1011810241
if (PirError.isError(captchaContainer)) {
1011910242
return createError(captchaContainer.error.message);
1012010243
}
10121-
const captchaProvider = getCaptchaProvider(captchaContainer, captchaType);
10244+
const captchaProvider = getCaptchaProvider(root, captchaContainer, captchaType);
1012210245
if (PirError.isError(captchaProvider)) {
1012310246
return createError(captchaProvider.error.message);
1012410247
}
1012510248
const captchaIdentifier = await captchaProvider.getCaptchaIdentifier(captchaContainer);
1012610249
if (!captchaIdentifier) {
1012710250
return createError(`could not extract captcha identifier from the container with selector ${selector}`);
1012810251
}
10252+
if (PirError.isError(captchaIdentifier)) {
10253+
return createError(captchaIdentifier.error.message);
10254+
}
1012910255
const response = {
1013010256
url: removeUrlQueryParams(window.location.href),
1013110257
// query params (which may include PII)

0 commit comments

Comments
 (0)