mirror of
https://github.com/yaklang/yaklang-chrome-extension.git
synced 2026-09-26 05:01:53 +08:00
182 lines
7.4 KiB
TypeScript
182 lines
7.4 KiB
TypeScript
import type {
|
|
BrowserTransformExecuteInput,
|
|
BrowserTransformPacket,
|
|
BrowserTransformValidationExecuteInput,
|
|
BrowserTransformProfileInput,
|
|
} from '@/types/models';
|
|
import type { CapabilityDomainHandler } from '../capability-context';
|
|
import { allowedTarget, requireScope } from '../capability-context';
|
|
import {
|
|
captureBrowserTransformRecovery,
|
|
confirmBrowserTransformRecovery,
|
|
deleteBrowserTransformProfile,
|
|
executeBrowserTransform,
|
|
getBrowserTransformProfile,
|
|
getBrowserTransformRecovery,
|
|
listBrowserTransformProfiles,
|
|
saveBrowserTransformProfile,
|
|
resetBrowserTransformRecovery,
|
|
startBrowserTransformRecovery,
|
|
validateBrowserTransformRecovery,
|
|
} from '@/features/browser-transform/service';
|
|
import {
|
|
compareBrowserPackets,
|
|
browserTransformValidationById,
|
|
executeBrowserTransformValidation,
|
|
latestBrowserTransformValidation,
|
|
prepareCapturedBrowserTransformProfile,
|
|
proposeBrowserTransformProfile,
|
|
validateInferredBrowserTransformProfile,
|
|
} from '@/features/browser-analysis/service';
|
|
import { TRANSFORM_CAPABILITY_DOMAIN } from '../capability-domains';
|
|
|
|
export const transformCapabilityHandler: CapabilityDomainHandler = {
|
|
...TRANSFORM_CAPABILITY_DOMAIN,
|
|
async handle({ method, input, grant }) {
|
|
if (method === 'browser.transform.profile.save') {
|
|
const profile = input as unknown as BrowserTransformProfileInput;
|
|
await allowedTarget(grant, profile.target);
|
|
return saveBrowserTransformProfile(profile);
|
|
}
|
|
if (method === 'browser.transform.validation.get') {
|
|
const draft = await browserTransformValidationById(String(input.validationId || ''));
|
|
await allowedTarget(grant, draft.profile.target);
|
|
return {
|
|
id: draft.id, expiresAt: draft.expiresAt,
|
|
directions: { request: draft.profile.request.enabled, response: draft.profile.response.enabled },
|
|
};
|
|
}
|
|
if (method === 'browser.transform.prepare') {
|
|
requireScope(grant, 'browser.recording.read');
|
|
requireScope(grant, 'browser.callable.execute');
|
|
return prepareCapturedBrowserTransformProfile(
|
|
await allowedTarget(grant, input),
|
|
String(input.candidateId || ''),
|
|
input.packet as BrowserTransformPacket,
|
|
Array.isArray(input.inputPaths) ? input.inputPaths.map(String) : undefined,
|
|
typeof input.name === 'string' ? input.name : undefined,
|
|
{
|
|
owner: { kind: 'grant', grantId: grant.id, expiresAt: grant.expiresAt },
|
|
trigger: input.trigger as { captureId: string; nodeId: string } | undefined,
|
|
authorize: () => {
|
|
requireScope(grant, 'browser.debugger.control');
|
|
requireScope(grant, 'browser.dom.read');
|
|
requireScope(grant, 'browser.dom.write');
|
|
},
|
|
},
|
|
);
|
|
}
|
|
if (method === 'browser.packet.compare') {
|
|
await allowedTarget(grant, input);
|
|
return compareBrowserPackets(
|
|
input.actual as BrowserTransformPacket,
|
|
input.expected as BrowserTransformPacket,
|
|
input.mode === 'exact' ? 'exact' : 'structure',
|
|
);
|
|
}
|
|
if (method === 'browser.profile.propose') {
|
|
requireScope(grant, 'browser.recording.read');
|
|
const target = await allowedTarget(grant, input);
|
|
return proposeBrowserTransformProfile(
|
|
target,
|
|
String(input.candidateId || ''),
|
|
String(input.callableId || ''),
|
|
Array.isArray(input.inputPaths) ? input.inputPaths.map(String) : undefined,
|
|
typeof input.name === 'string' ? input.name : undefined,
|
|
);
|
|
}
|
|
if (method === 'browser.profile.validation.latest') {
|
|
return latestBrowserTransformValidation(await allowedTarget(grant, input));
|
|
}
|
|
if (method === 'browser.profile.validate') {
|
|
requireScope(grant, 'browser.recording.read');
|
|
const target = await allowedTarget(grant, input);
|
|
return validateInferredBrowserTransformProfile(
|
|
target,
|
|
String(input.candidateId || ''),
|
|
String(input.callableId || ''),
|
|
input.packet as BrowserTransformPacket,
|
|
Array.isArray(input.inputPaths) ? input.inputPaths.map(String) : undefined,
|
|
typeof input.name === 'string' ? input.name : undefined,
|
|
input.observed as BrowserTransformPacket | undefined,
|
|
input.comparisonMode === 'exact' ? 'exact' : 'structure',
|
|
);
|
|
}
|
|
|
|
if (method.startsWith('browser.transform.recovery.')) {
|
|
const profile = await getBrowserTransformProfile(String(input.id || ''));
|
|
const resolveInPage = method !== 'browser.transform.recovery.capture'
|
|
&& method !== 'browser.transform.recovery.reset';
|
|
const target = await allowedTarget(grant, {
|
|
tabId: profile.target.tabId,
|
|
frameId: profile.target.frameId,
|
|
...(typeof input.documentId === 'string' ? { documentId: input.documentId } : {}),
|
|
}, resolveInPage);
|
|
const owner = { kind: 'grant' as const, grantId: grant.id, expiresAt: grant.expiresAt };
|
|
if (method === 'browser.transform.recovery.get') {
|
|
return getBrowserTransformRecovery(profile.id);
|
|
}
|
|
if (method === 'browser.transform.recovery.start') {
|
|
requireScope(grant, 'browser.debugger.control');
|
|
return startBrowserTransformRecovery(profile.id, owner);
|
|
}
|
|
if (method === 'browser.transform.recovery.capture') {
|
|
requireScope(grant, 'browser.debugger.control');
|
|
requireScope(grant, 'browser.callable.execute');
|
|
return captureBrowserTransformRecovery(
|
|
profile.id,
|
|
target,
|
|
String(input.callFrameId || ''),
|
|
input.strategy === 'request-transaction'
|
|
? 'request-transaction'
|
|
: 'selected-frame',
|
|
owner,
|
|
);
|
|
}
|
|
if (method === 'browser.transform.recovery.validate') {
|
|
return validateBrowserTransformRecovery(
|
|
profile.id,
|
|
input.packet as BrowserTransformPacket,
|
|
);
|
|
}
|
|
if (method === 'browser.transform.recovery.confirm') {
|
|
return confirmBrowserTransformRecovery(profile.id, String(input.validationId || ''));
|
|
}
|
|
return resetBrowserTransformRecovery(profile.id, owner);
|
|
}
|
|
|
|
if (method === 'browser.transform.profile.list') {
|
|
const profiles = await listBrowserTransformProfiles();
|
|
const visible = await Promise.all(profiles.map(async (profile) => {
|
|
try {
|
|
await allowedTarget(grant, profile.target);
|
|
return profile;
|
|
} catch {
|
|
return undefined;
|
|
}
|
|
}));
|
|
return visible.filter(Boolean);
|
|
}
|
|
if (method === 'browser.transform.profile.delete') {
|
|
const profile = await getBrowserTransformProfile(String(input.id || ''));
|
|
await allowedTarget(grant, profile.target);
|
|
return deleteBrowserTransformProfile(profile.id);
|
|
}
|
|
if (method === 'browser.transform.validation.execute') {
|
|
requireScope(grant, 'browser.transform.execute');
|
|
const executeValidationInput = input as unknown as BrowserTransformValidationExecuteInput;
|
|
const draft = await browserTransformValidationById(executeValidationInput.validationId);
|
|
await allowedTarget(grant, draft.profile.target);
|
|
return executeBrowserTransformValidation(
|
|
executeValidationInput.validationId,
|
|
executeValidationInput.direction,
|
|
executeValidationInput.packet,
|
|
);
|
|
}
|
|
const executeInput = input as unknown as BrowserTransformExecuteInput;
|
|
const profile = await getBrowserTransformProfile(executeInput.profileId);
|
|
await allowedTarget(grant, profile.target);
|
|
return executeBrowserTransform(executeInput);
|
|
},
|
|
};
|