Skip to content

Commit bae28ee

Browse files
committed
feat: address PR feedback #2:
- wire up the remote config setting - replace querying by root with querying by captcha container - remove hcaptcha and cloudflare providers
1 parent 313d090 commit bae28ee

File tree

15 files changed

+132
-143
lines changed

15 files changed

+132
-143
lines changed

injected/src/features/broker-protection.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ export default class BrokerProtection extends ContentFeature {
5858
*/
5959
async exec(action, data) {
6060
const retryConfig = this.retryConfigFor(action);
61-
const { result, exceptions } = await retry(() => execute(action, data), retryConfig);
61+
const options = { useEnhancedCaptchaSystem: this.getFeatureSettingEnabled('useEnhancedCaptchaSystem') };
62+
const { result, exceptions } = await retry(() => execute(action, data, document, options), retryConfig);
6263

6364
if (result) {
6465
if ('success' in result && Array.isArray(result.success.next)) {

injected/src/features/broker-protection/actions/actions.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ import * as captchaHandlers from '../captcha-services/captcha.service';
88
import * as deprecatedCaptchaHandlers from './captcha-deprecated';
99

1010
/**
11-
* Returns the captcha handlers based on the useNewActionHandlers flag
11+
* Returns the captcha handlers based on the useEnhancedCaptchaSystem flag
1212
* @param {Object} params
13-
* @param {boolean} params.useNewActionHandlers
13+
* @param {boolean} params.useEnhancedCaptchaSystem
1414
*/
15-
export function resolveActionHandlers({ useNewActionHandlers }) {
15+
export function resolveActionHandlers({ useEnhancedCaptchaSystem }) {
1616
return {
1717
extract,
1818
fillForm,
1919
click,
2020
expectation,
21-
...(useNewActionHandlers
21+
...(useEnhancedCaptchaSystem
2222
? {
2323
navigate,
2424
...captchaHandlers,

injected/src/features/broker-protection/captcha-services/captcha.service.js

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ import { getCaptchaProvider, getCaptchaSolveProvider } from './get-captcha-provi
55
import { captchaFactory } from './providers/registry.js';
66
import { getCaptchaInfo as getCaptchaInfoDeprecated, solveCaptcha as solveCaptchaDeprecated } from '../actions/captcha-deprecated';
77

8+
/**
9+
*
10+
* @param {Document | HTMLElement} root
11+
* @param {import('../types.js').PirAction['selector']} [selector]
12+
* @returns {HTMLElement | import('../types.js').PirError}
13+
*/
14+
const getCaptchaContainer = (root, selector) => {
15+
if (!selector) {
16+
return PirError.create('missing selector');
17+
}
18+
19+
const captchaContainer = getElement(root, selector);
20+
if (!captchaContainer) {
21+
return PirError.create(`could not find captcha container with selector ${selector}`);
22+
}
23+
24+
return captchaContainer;
25+
};
26+
827
/**
928
* Returns the supporting code to inject for the given captcha type
1029
*
@@ -35,20 +54,17 @@ export function getSupportingCodeToInject(action) {
3554
* @return {import('../types.js').ActionResponse}
3655
*/
3756
export function getCaptchaInfo(action, root = document) {
38-
const { id: actionID, selector, actionType, captchaType } = action;
57+
const { id: actionID, actionType, captchaType, selector } = action;
3958
if (!captchaType) {
4059
// ensures backward compatibility with old actions
4160
return getCaptchaInfoDeprecated(action, root);
4261
}
4362

4463
const createError = ErrorResponse.generateErrorResponseFunction({ actionID, context: `[getCaptchaInfo] captchaType: ${captchaType}` });
45-
if (!selector) {
46-
return createError('missing selector');
47-
}
4864

49-
const captchaContainer = getElement(root, selector);
50-
if (!captchaContainer) {
51-
return createError(`could not find captcha container with selector ${selector}`);
65+
const captchaContainer = getCaptchaContainer(root, selector);
66+
if (PirError.isError(captchaContainer)) {
67+
return createError(captchaContainer.error.message);
5268
}
5369

5470
const captchaProvider = getCaptchaProvider(captchaContainer, captchaType);
@@ -79,24 +95,29 @@ export function getCaptchaInfo(action, root = document) {
7995
* @return {import('../types.js').ActionResponse}
8096
*/
8197
export function solveCaptcha(action, token, root = document) {
82-
const { id: actionID, actionType, captchaType } = action;
98+
const { id: actionID, actionType, captchaType, selector } = action;
8399
if (!captchaType) {
84100
// ensures backward compatibility with old actions
85101
return solveCaptchaDeprecated(action, token, root);
86102
}
87103

88104
const createError = ErrorResponse.generateErrorResponseFunction({ actionID, context: `[solveCaptcha] captchaType: ${captchaType}` });
89-
const captchaSolveProvider = getCaptchaSolveProvider(root, captchaType);
90105

106+
const captchaContainer = getCaptchaContainer(root, selector);
107+
if (PirError.isError(captchaContainer)) {
108+
return createError(captchaContainer.error.message);
109+
}
110+
111+
const captchaSolveProvider = getCaptchaSolveProvider(captchaContainer, captchaType);
91112
if (PirError.isError(captchaSolveProvider)) {
92113
return createError(captchaSolveProvider.error.message);
93114
}
94115

95-
if (!captchaSolveProvider.canSolve(root)) {
116+
if (!captchaSolveProvider.canSolve(captchaContainer)) {
96117
return createError('cannot solve captcha');
97118
}
98119

99-
const tokenResponse = captchaSolveProvider.injectToken(root, token);
120+
const tokenResponse = captchaSolveProvider.injectToken(captchaContainer, token);
100121
if (PirError.isError(tokenResponse)) {
101122
return createError(tokenResponse.error.message);
102123
}

injected/src/features/broker-protection/captcha-services/factory.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ export class CaptchaFactory {
3434

3535
/**
3636
* Detect the captcha provider based on the root document
37-
* @param {Document} root - The root document
37+
* @param {HTMLElement} element - The element to check
3838
* @returns {import('./providers/provider.interface').CaptchaProvider|null}
3939
*/
40-
detectSolveProvider(root) {
41-
return this._getAllProviders().find((provider) => provider.canSolve(root)) || null;
40+
detectSolveProvider(element) {
41+
return this._getAllProviders().find((provider) => provider.canSolve(element)) || null;
4242
}
4343

4444
/**
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { getElement } from '../utils/utils.js';
2+
import { PirError } from '../types';
3+
4+
/**
5+
*
6+
* @param {Document | HTMLElement} root
7+
* @param {import('../types.js').PirAction['selector']} [selector]
8+
* @returns {HTMLElement | PirError}
9+
*/
10+
export function getCaptchaContainer(root, selector) {
11+
if (!selector) {
12+
return PirError.create('missing selector');
13+
}
14+
15+
const captchaContainer = getElement(root, selector);
16+
if (!captchaContainer) {
17+
return PirError.create(`could not find captcha container with selector ${selector}`);
18+
}
19+
20+
return captchaContainer;
21+
}

injected/src/features/broker-protection/captcha-services/get-captcha-provider.js

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,62 @@ import { captchaFactory } from './providers/registry';
44
/**
55
* Gets the captcha provider for the getCaptchaInfo action
66
*
7-
* @param {HTMLElement} captchaDiv
7+
* @param {HTMLElement} captchaContainer
88
* @param {string} captchaType
99
*/
10-
export function getCaptchaProvider(captchaDiv, captchaType) {
10+
export function getCaptchaProvider(captchaContainer, captchaType) {
1111
const captchaProvider = captchaFactory.getProviderByType(captchaType);
1212
if (!captchaProvider) {
13-
return PirError.create(`[getCaptchaProvider] could not find captchaProvider with type ${captchaType}`);
13+
return PirError.create(`[getCaptchaProvider] could not find captcha provider with type ${captchaType}`);
1414
}
1515

16-
if (captchaProvider.isSupportedForElement(captchaDiv)) {
16+
if (captchaProvider.isSupportedForElement(captchaContainer)) {
1717
return captchaProvider;
1818
}
1919

20-
// TODO fire a pixel
21-
// if the captcha provider type is different from the expected type, log a warning
22-
console.warn(
23-
`[getCaptchaProvider] mismatch between expected captha type ${captchaType} and detected type ${captchaProvider.getType()}`,
24-
);
25-
const detectedProvider = captchaFactory.detectProvider(captchaDiv);
20+
const detectedProvider = captchaFactory.detectProvider(captchaContainer);
2621
if (!detectedProvider) {
2722
return PirError.create(
28-
`[getCaptchaProvider] could not detect captcha provider for ${captchaType} captcha and element ${captchaDiv}`,
23+
`[getCaptchaProvider] could not detect captcha provider for ${captchaType} captcha and element ${captchaContainer}`,
2924
);
3025
}
3126

27+
// TODO fire a pixel
28+
// if the captcha provider type is different from the expected type, log a warning
29+
console.warn(
30+
`[getCaptchaProvider] mismatch between expected capctha type ${captchaType} and detected type ${detectedProvider.getType()}`,
31+
);
32+
3233
return detectedProvider;
3334
}
3435

3536
/**
3637
* Gets the captcha provider for the solveCaptcha action
37-
* @param {Document} root
38+
* @param {HTMLElement} captchaContainer
3839
* @param {string} captchaType
3940
*/
40-
export function getCaptchaSolveProvider(root, captchaType) {
41+
export function getCaptchaSolveProvider(captchaContainer, captchaType) {
4142
const captchaProvider = captchaFactory.getProviderByType(captchaType);
4243
if (!captchaProvider) {
43-
return PirError.create(`[getCaptchaSolveProvider] could not find captchaProvider with type ${captchaType}`);
44+
return PirError.create(`[getCaptchaSolveProvider] could not find captcha provider with type ${captchaType}`);
4445
}
4546

46-
if (captchaProvider.canSolve(root)) {
47+
if (captchaProvider.canSolve(captchaContainer)) {
4748
return captchaProvider;
4849
}
4950

50-
// TODO fire a pixel
51-
// if the captcha provider type is different from the expected type, log a warning
52-
console.warn(
53-
`[getCaptchaSolveProvider] mismatch between expected captha type ${captchaType} and detected type ${captchaProvider.getType()}`,
54-
);
55-
const detectedProvider = captchaFactory.detectSolveProvider(root);
51+
const detectedProvider = captchaFactory.detectSolveProvider(captchaContainer);
5652
if (!detectedProvider) {
5753
return PirError.create(
58-
`[getCaptchaSolveProvider] could not detect captcha provider for ${captchaType} captcha and element ${root}`,
54+
`[getCaptchaSolveProvider] could not detect captcha provider for ${captchaType} captcha and element ${captchaContainer}`,
5955
);
6056
}
6157

58+
// TODO fire a pixel
59+
// if the captcha provider type is different from the expected type, log a warning
60+
console.warn(
61+
`[getCaptchaSolveProvider] mismatch between expected captha type ${captchaType} and detected type ${detectedProvider.getType()}`,
62+
);
63+
6264
return detectedProvider;
6365
}

injected/src/features/broker-protection/captcha-services/providers/cloudflare-turnstile.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ export class CloudFlareTurnstileProvider {
3131
}
3232

3333
/**
34-
* @param {Document} root - The document root to search for captchas
34+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
3535
*/
36-
canSolve(root) {
36+
canSolve(captchaContainerElement) {
3737
// TODO: Implement
3838
return false;
3939
}
4040

4141
/**
42-
* @param {Document} root - The document root containing the captcha
42+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
4343
* @param {string} token - The solved captcha token
4444
*/
45-
injectToken(root, token) {
45+
injectToken(captchaContainerElement, token) {
4646
// TODO: Implement
4747
return PirError.create('Not implemented');
4848
}
Lines changed: 17 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,10 @@
11
import { PirError } from '../../types';
2-
import { getUrlHashParameter, getUrlParameter } from '../../utils/url';
3-
import { getElementByName, getElementWithSrcStart } from '../../utils/utils';
4-
import { stringifyFunction } from '../utils/stringify-function';
5-
import { injectTokenIntoElement } from '../utils/token';
62

73
/**
84
* @import { CaptchaProvider } from './provider.interface';
95
* @implements {CaptchaProvider}
106
*/
117
export class HCaptchaProvider {
12-
#CAPTCHA_URL = 'https://newassets.hcaptcha.com/captcha';
13-
#CAPTCHA_RESPONSE_ELEMENT_NAME = 'h-captcha-response';
14-
158
getType() {
169
return 'hcaptcha';
1710
}
@@ -20,90 +13,44 @@ export class HCaptchaProvider {
2013
* @param {HTMLElement} captchaContainerElement - The element to check
2114
*/
2215
isSupportedForElement(captchaContainerElement) {
23-
return !!this._getCaptchaElement(captchaContainerElement);
16+
// TODO: Implement
17+
return false;
2418
}
2519

2620
/**
27-
* @param {HTMLElement} captchaContainerElement - The element to check
21+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
2822
*/
2923
getCaptchaIdentifier(captchaContainerElement) {
30-
const captchaElement = this._getCaptchaElement(captchaContainerElement);
31-
if (!captchaElement) {
32-
return PirError.create('[getCaptchaIdentifier] could not find captcha');
33-
}
34-
35-
const siteKey = this._getSiteKeyFromElement(captchaElement) || this._getSiteKeyFromUrl(captchaElement);
36-
if (!siteKey) {
37-
return PirError.create('[HCaptchaProvider.getCaptchaIdentifier] could not extract site key');
38-
}
39-
40-
return siteKey;
24+
// TODO: Implement
25+
return null;
4126
}
4227

4328
getSupportingCodeToInject() {
29+
// TODO: Implement
4430
return null;
4531
}
4632

4733
/**
48-
* @param {string} token - The solved captcha token
49-
*/
50-
getSolveCallback(token) {
51-
return stringifyFunction({
52-
functionBody: hCaptchaCallback,
53-
functionName: 'hCaptchaCallback',
54-
args: { token },
55-
});
56-
}
57-
58-
/**
59-
* @param {Document} root - The document root
60-
* @returns {boolean}
34+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
6135
*/
62-
canSolve(root) {
63-
return !!getElementByName(root, this.#CAPTCHA_RESPONSE_ELEMENT_NAME);
36+
canSolve(captchaContainerElement) {
37+
// TODO: Implement
38+
return false;
6439
}
6540

6641
/**
67-
* Injects the token to solve the captcha
68-
* @param {Document} root - The document root
42+
* @param {HTMLElement} captchaContainerElement - The element containing the captcha
6943
* @param {string} token - The solved captcha token
7044
*/
71-
injectToken(root, token) {
72-
return injectTokenIntoElement({ root, elementName: this.#CAPTCHA_RESPONSE_ELEMENT_NAME, token });
73-
}
74-
75-
/**
76-
* @private
77-
* @param {HTMLElement} root - The root element to search from
78-
* @returns {HTMLElement|null}
79-
*/
80-
_getCaptchaElement(root) {
81-
return getElementWithSrcStart(root, this.#CAPTCHA_URL);
82-
}
83-
84-
/**
85-
* @private
86-
* @param {HTMLElement} captchaElement
87-
* @returns {string|null} The site key or null if not found
88-
*/
89-
_getSiteKeyFromElement(captchaElement) {
90-
return captchaElement instanceof Element ? captchaElement.getAttribute('data-sitekey') : null;
45+
injectToken(captchaContainerElement, token) {
46+
// TODO: Implement
47+
return PirError.create('Not implemented');
9148
}
9249

9350
/**
94-
* @private
95-
* @param {HTMLElement} captchaElement
51+
* @param {string} token - The solved captcha token
9652
*/
97-
_getSiteKeyFromUrl(captchaElement) {
98-
if (!('src' in captchaElement)) {
99-
return null;
100-
}
101-
102-
const captchaUrl = String(captchaElement.src);
103-
return getUrlParameter(captchaUrl, 'sitekey') || getUrlHashParameter(captchaUrl, 'sitekey');
53+
getSolveCallback(token) {
54+
return null;
10455
}
10556
}
106-
107-
const hCaptchaCallback = () => {
108-
// TODO: Implementation
109-
};

0 commit comments

Comments
 (0)