import { WebLimitBlockType, WebLimitParams } from '@lenovo-software/lsa-clients-common/dist/models/limitingModels'; import { WebLimitBlockPage } from './webLimitBlockPage'; import { extensionComm } from '../extensionComm'; import { Logger } from '../../common/logger'; const WEB_LIMIT_DISABLE_DOTTEDECIMALS = 0x00400000; const WEB_LIMIT_DISABLE_PRIVATE_BROWSE = 0x000004e0; const WEB_LIMIT_ALLOW_ALL = '0'; const WEB_LIMIT_BLOCK_ALL = '1'; const WEB_LIMIT_ALLOW_SPECIFIC = '2'; const WEB_LIMIT_BLOCK_SPECIFIC = '3'; const WH_FLAGS_PERIOD = 5000; export class WebLimiter { private static instance: WebLimiter; private limitingParams: WebLimitParams | null = null; private whFlagsSendTimerId: NodeJS.Timer | null = null; private logger = Logger.getInstance(); public static getInstance(): WebLimiter { if (!WebLimiter.instance) { WebLimiter.instance = new WebLimiter(); } return WebLimiter.instance; } public async start(params: WebLimitParams): Promise { this.logger.logMessage('WebLimiter | start'); this.clearFlagsIntervalTimer(); this.limitingParams = params; const { webLimitingFlags, webLimitingFlagsWithSuffix, blockPage, blockPageToIgnore } = await this.updateWebLimitingFlags(true); const webLimitingList = { listType: WEB_LIMIT_ALLOW_ALL, entries: params.sites }; if (params.blockType === WebLimitBlockType.Block) { webLimitingList.listType = WEB_LIMIT_BLOCK_SPECIFIC; } if (webLimitingFlags !== 0) { webLimitingList.listType = WEB_LIMIT_BLOCK_SPECIFIC; } if (params.blockType === WebLimitBlockType.BlockAll) { webLimitingList.listType = WEB_LIMIT_BLOCK_ALL; } else if (params.blockType === WebLimitBlockType.Allow) { // LSA-950: An empty array of "allowed" websites should block all sites const allowedSitesLength = params.sites?.length || 0; webLimitingList.listType = allowedSitesLength > 0 ? WEB_LIMIT_ALLOW_SPECIFIC : WEB_LIMIT_BLOCK_ALL; } this.whFlagsSendTimerId = setInterval(() => { this.handleWebLimitingFlags(webLimitingFlagsWithSuffix, blockPage, blockPageToIgnore); this.handleWebLimitingList( JSON.stringify({ listType: webLimitingList.listType, entries: webLimitingList.entries }) ); }, WH_FLAGS_PERIOD); } public async stop(): Promise { this.logger.logMessage('WebLimiter.stop'); this.clearFlagsIntervalTimer(); await this.updateWebLimitingFlags(false); const webLimitingList = { listType: WEB_LIMIT_ALLOW_ALL, entries: [] }; await this.handleWebLimitingList(JSON.stringify(webLimitingList)); } private async handleWebLimitingList(data: any): Promise { this.logger.logMessage('WebLimiter | handleWebLimitingList: ' + data); const options = { message: 'WebLimitURLList', value: data }; await extensionComm.sendToWebHelper(options); } private async handleWebLimitingFlags(flags: string, blockPage: any, blockPageToIgnore: any): Promise { this.logger.logMessage( 'WebLimiter | handleWebLimitingFlags: ' + flags + ', blockPage: ' + blockPage + ', blockPageToIgnore: ' + blockPageToIgnore ); await extensionComm.sendToWebHelper({ message: 'WebLimitFlagsEx', value: flags, blockPage: blockPage, blockPageToIgnore: blockPageToIgnore }); } private async updateWebLimitingFlags(limit = true): Promise<{ webLimitingFlags: number; webLimitingFlagsWithSuffix: string; blockPage: string; blockPageToIgnore: string; }> { this.logger.logMessage('WebLimiter | updateWebLimitingFlags'); this.clearFlagsIntervalTimer(); const params = this.limitingParams as WebLimitParams; const webLimitingFlags = this.getWebLimitingFlags(params); const webLimitingFlagsWithSuffix = JSON.stringify(webLimitingFlags) + this.getWebLimitingFlagsSuffix(limit); const blockPage = new WebLimitBlockPage().getWebLimitBlockPage(params); const blockPageToIgnore = new WebLimitBlockPage().getBlockPageToIgnore(); await this.handleWebLimitingFlags(webLimitingFlagsWithSuffix, blockPage, blockPageToIgnore); return { webLimitingFlags, webLimitingFlagsWithSuffix, blockPage, blockPageToIgnore }; } private getWebLimitingFlags(params: WebLimitParams): number { this.logger.logMessage('WebLimiter | getWebLimitingFlags'); let flags = 0; if (params?.blockIPAddresses) { flags |= WEB_LIMIT_DISABLE_DOTTEDECIMALS; } if (params?.blockIncognito) { flags |= WEB_LIMIT_DISABLE_PRIVATE_BROWSE; } return flags; } private getWebLimitingFlagsSuffix(limit: boolean): string { this.logger.logMessage('WebLimiter | getWebLimitingFlagsSuffix'); return limit ? '::0' : '::1'; } private clearFlagsIntervalTimer(): void { this.logger.logMessage('WebLimiter | clearFlagsIntervalTimer'); if (this.whFlagsSendTimerId) { clearInterval(this.whFlagsSendTimerId); } this.whFlagsSendTimerId = null; } }