mirror of
https://github.com/webadderallorg/Recordly.git
synced 2026-09-24 14:55:37 +00:00
158 lines
3.9 KiB
TypeScript
158 lines
3.9 KiB
TypeScript
const CAPTURE_WINDOW_TYPE = "hud-overlay";
|
|
const TRUSTED_RENDERER_PROTOCOLS = new Set(["http:", "https:", "file:"]);
|
|
const FILE_SECURITY_ORIGINS = new Set(["null", "file://", "file:///"]);
|
|
|
|
export interface MediaPermissionPolicyRequest {
|
|
permission: string;
|
|
isTrustedCaptureWindow: boolean;
|
|
isMainFrame: boolean;
|
|
currentDocumentUrl: string;
|
|
requestingUrl: string;
|
|
securityOrigins: readonly string[];
|
|
}
|
|
|
|
export interface DisplayCapturePolicyRequest {
|
|
isTrustedCaptureWindow: boolean;
|
|
isMainFrame: boolean;
|
|
currentDocumentUrl: string;
|
|
securityOrigin: string;
|
|
videoRequested: boolean;
|
|
}
|
|
|
|
function parseUrl(value: string): URL | null {
|
|
try {
|
|
return new URL(value);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function hasExactCaptureWindowQuery(url: URL): boolean {
|
|
const entries = [...url.searchParams.entries()];
|
|
return (
|
|
entries.length === 1 &&
|
|
entries[0]?.[0] === "windowType" &&
|
|
entries[0][1] === CAPTURE_WINDOW_TYPE
|
|
);
|
|
}
|
|
|
|
function isValidTrustedBaseUrl(url: URL): boolean {
|
|
return (
|
|
TRUSTED_RENDERER_PROTOCOLS.has(url.protocol) &&
|
|
url.username === "" &&
|
|
url.password === "" &&
|
|
url.search === "" &&
|
|
url.hash === ""
|
|
);
|
|
}
|
|
|
|
function hasSameBaseLocation(candidate: URL, trustedBase: URL): boolean {
|
|
return (
|
|
candidate.protocol === trustedBase.protocol &&
|
|
candidate.hostname === trustedBase.hostname &&
|
|
candidate.port === trustedBase.port &&
|
|
candidate.pathname === trustedBase.pathname
|
|
);
|
|
}
|
|
|
|
export function isTrustedCaptureDocumentUrl(
|
|
candidateUrl: string,
|
|
trustedDocumentBaseUrls: readonly string[],
|
|
): boolean {
|
|
const candidate = parseUrl(candidateUrl);
|
|
if (
|
|
!candidate ||
|
|
!TRUSTED_RENDERER_PROTOCOLS.has(candidate.protocol) ||
|
|
candidate.username !== "" ||
|
|
candidate.password !== "" ||
|
|
!hasExactCaptureWindowQuery(candidate)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
return trustedDocumentBaseUrls.some((trustedBaseUrl) => {
|
|
const trustedBase = parseUrl(trustedBaseUrl);
|
|
return Boolean(
|
|
trustedBase &&
|
|
isValidTrustedBaseUrl(trustedBase) &&
|
|
hasSameBaseLocation(candidate, trustedBase),
|
|
);
|
|
});
|
|
}
|
|
|
|
function isSameDocument(firstUrl: string, secondUrl: string): boolean {
|
|
const first = parseUrl(firstUrl);
|
|
const second = parseUrl(secondUrl);
|
|
if (!first || !second) {
|
|
return false;
|
|
}
|
|
|
|
first.hash = "";
|
|
second.hash = "";
|
|
return first.href === second.href;
|
|
}
|
|
|
|
function isSecurityOriginForDocument(securityOrigin: string, documentUrl: string): boolean {
|
|
const document = parseUrl(documentUrl);
|
|
if (!document) {
|
|
return false;
|
|
}
|
|
|
|
if (document.protocol === "file:") {
|
|
return FILE_SECURITY_ORIGINS.has(securityOrigin);
|
|
}
|
|
|
|
const origin = parseUrl(securityOrigin);
|
|
return Boolean(
|
|
origin &&
|
|
(origin.protocol === "http:" || origin.protocol === "https:") &&
|
|
origin.username === "" &&
|
|
origin.password === "" &&
|
|
origin.origin === document.origin &&
|
|
origin.pathname === "/" &&
|
|
origin.search === "" &&
|
|
origin.hash === "",
|
|
);
|
|
}
|
|
|
|
export function shouldGrantMediaPermission(
|
|
request: MediaPermissionPolicyRequest,
|
|
trustedDocumentBaseUrls: readonly string[],
|
|
): boolean {
|
|
if (
|
|
request.permission !== "media" ||
|
|
!request.isTrustedCaptureWindow ||
|
|
!request.isMainFrame ||
|
|
!isTrustedCaptureDocumentUrl(request.currentDocumentUrl, trustedDocumentBaseUrls)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
if (
|
|
!isTrustedCaptureDocumentUrl(request.requestingUrl, trustedDocumentBaseUrls) ||
|
|
!isSameDocument(request.currentDocumentUrl, request.requestingUrl)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
return (
|
|
request.securityOrigins.length > 0 &&
|
|
request.securityOrigins.every((securityOrigin) =>
|
|
isSecurityOriginForDocument(securityOrigin, request.currentDocumentUrl),
|
|
)
|
|
);
|
|
}
|
|
|
|
export function shouldGrantDisplayCapture(
|
|
request: DisplayCapturePolicyRequest,
|
|
trustedDocumentBaseUrls: readonly string[],
|
|
): boolean {
|
|
return (
|
|
request.isTrustedCaptureWindow &&
|
|
request.isMainFrame &&
|
|
request.videoRequested &&
|
|
isTrustedCaptureDocumentUrl(request.currentDocumentUrl, trustedDocumentBaseUrls) &&
|
|
isSecurityOriginForDocument(request.securityOrigin, request.currentDocumentUrl)
|
|
);
|
|
}
|