1 import { parse } from 'tldts';
2 import type { Runtime } from 'webextension-polyfill';
4 import { sanitizeURL } from './sanitize';
5 import type { ParsedSender, ParsedUrl } from './types';
6 import { isSupportedSenderUrl } from './utils';
8 export const parseUrl = (url?: string): ParsedUrl => {
9 const check = sanitizeURL(url ?? '');
19 isTopLevelDomain: false,
25 const { domain, subdomain, domainWithoutSuffix, hostname, isPrivate } = parse(url ?? '', {
26 allowIcannDomains: true,
27 allowPrivateDomains: true,
32 displayName: domainWithoutSuffix ?? hostname,
33 domain: domain ?? hostname /* fallback on hostname for localhost support */,
34 subdomain: subdomain && subdomain !== 'www' ? hostname : null,
35 protocol: check.protocol,
38 isTopLevelDomain: !subdomain || subdomain === 'www',
39 isPrivate: isPrivate ?? subdomain !== null,
40 isSecure: check.url.startsWith('https://'),
44 /* Safely parses the sender information, providing compatibility
45 * for non-Chromium browsers: if available, uses the MessageSender origin
46 * property for enhanced protection against compromised renderer spoofing. */
47 export const parseSender = (sender: Runtime.MessageSender): ParsedSender => {
48 const origin = (sender as any)?.origin;
49 const { url, tab } = sender;
50 const parsedUrl = parseUrl(origin ?? url ?? '');
51 const tabId = tab?.id;
53 if (!isSupportedSenderUrl(parsedUrl) || !tabId) throw new Error('Unsupported sender');
55 return { tabId, url: parsedUrl };