mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 01:56:16 -08:00
175 lines
5.9 KiB
TypeScript
175 lines
5.9 KiB
TypeScript
import type {
|
|
RendererProcessRssCapture,
|
|
RendererProcessRssCaptureApi,
|
|
} from './renderer-process-rss-capture';
|
|
|
|
export interface RendererWindowIdentity {
|
|
readonly browserWindowId: number;
|
|
readonly webContentsId: number;
|
|
}
|
|
|
|
export interface RendererWindowRssSessionMetrics {
|
|
readonly responsiveEvents: number;
|
|
readonly rss: RendererProcessRssCapture;
|
|
readonly unresponsiveEvents: number;
|
|
readonly windowIdentity: RendererWindowIdentity;
|
|
}
|
|
|
|
export interface RendererWindowWebContents {
|
|
readonly id: number;
|
|
getOSProcessId(): number;
|
|
}
|
|
|
|
export interface RendererWindow {
|
|
readonly id: number;
|
|
readonly webContents: RendererWindowWebContents;
|
|
off(event: 'responsive' | 'unresponsive', listener: () => void): unknown;
|
|
on(event: 'responsive' | 'unresponsive', listener: () => void): unknown;
|
|
}
|
|
|
|
export interface RendererWindowRssSession {
|
|
detach(): void;
|
|
sample(): RendererWindowRssSessionMetrics;
|
|
snapshot(): RendererWindowRssSessionMetrics;
|
|
}
|
|
|
|
export interface RendererWindowRssSessionCreateInput {
|
|
readonly browserWindowFromId: (
|
|
browserWindowId: number
|
|
) => RendererWindow | null;
|
|
readonly browserWindowId: number;
|
|
readonly getAppMetrics: () => readonly unknown[];
|
|
readonly rendererRssApi: RendererProcessRssCaptureApi;
|
|
readonly webContentsId: number;
|
|
}
|
|
|
|
export interface RendererWindowRssSessionApi {
|
|
create(
|
|
input: RendererWindowRssSessionCreateInput
|
|
): RendererWindowRssSession;
|
|
}
|
|
|
|
export function createRendererWindowRssSessionApi(): RendererWindowRssSessionApi {
|
|
const helpers = {
|
|
isValidIdentityId(value: unknown): value is number {
|
|
return Number.isSafeInteger(value) && Number(value) > 0;
|
|
},
|
|
|
|
create(
|
|
input: RendererWindowRssSessionCreateInput
|
|
): RendererWindowRssSession {
|
|
if (!helpers.isValidIdentityId(input.browserWindowId)) {
|
|
throw new Error('renderer-browser-window-id-invalid');
|
|
}
|
|
if (!helpers.isValidIdentityId(input.webContentsId)) {
|
|
throw new Error('renderer-web-contents-id-invalid');
|
|
}
|
|
|
|
let browserWindow: RendererWindow | null = null;
|
|
try {
|
|
browserWindow = input.browserWindowFromId(
|
|
input.browserWindowId
|
|
);
|
|
} catch {
|
|
throw new Error('renderer-browser-window-missing');
|
|
}
|
|
if (browserWindow === null) {
|
|
throw new Error('renderer-browser-window-missing');
|
|
}
|
|
if (browserWindow.id !== input.browserWindowId) {
|
|
throw new Error('renderer-browser-window-identity-mismatch');
|
|
}
|
|
const webContents = browserWindow.webContents;
|
|
if (
|
|
webContents === null ||
|
|
typeof webContents !== 'object' ||
|
|
webContents.id !== input.webContentsId
|
|
) {
|
|
throw new Error('renderer-web-contents-identity-mismatch');
|
|
}
|
|
|
|
const windowIdentity = Object.freeze({
|
|
browserWindowId: input.browserWindowId,
|
|
webContentsId: input.webContentsId,
|
|
});
|
|
let rendererRss = input.rendererRssApi.create(
|
|
helpers.readOsProcessId(webContents),
|
|
helpers.readAppMetrics(input.getAppMetrics)
|
|
);
|
|
let responsiveEvents = 0;
|
|
let unresponsiveEvents = 0;
|
|
let detached = false;
|
|
const callbacks = {
|
|
onResponsive(): void {
|
|
if (!detached) {
|
|
responsiveEvents += 1;
|
|
}
|
|
},
|
|
onUnresponsive(): void {
|
|
if (!detached) {
|
|
unresponsiveEvents += 1;
|
|
}
|
|
},
|
|
snapshot(): RendererWindowRssSessionMetrics {
|
|
return Object.freeze({
|
|
responsiveEvents,
|
|
rss: rendererRss,
|
|
unresponsiveEvents,
|
|
windowIdentity,
|
|
});
|
|
},
|
|
};
|
|
browserWindow.on('unresponsive', callbacks.onUnresponsive);
|
|
try {
|
|
browserWindow.on('responsive', callbacks.onResponsive);
|
|
} catch (error) {
|
|
browserWindow.off('unresponsive', callbacks.onUnresponsive);
|
|
throw error;
|
|
}
|
|
|
|
return Object.freeze({
|
|
detach(): void {
|
|
if (detached) {
|
|
return;
|
|
}
|
|
detached = true;
|
|
browserWindow.off('unresponsive', callbacks.onUnresponsive);
|
|
browserWindow.off('responsive', callbacks.onResponsive);
|
|
},
|
|
sample(): RendererWindowRssSessionMetrics {
|
|
if (!detached) {
|
|
rendererRss = input.rendererRssApi.sample(
|
|
rendererRss,
|
|
helpers.readOsProcessId(webContents),
|
|
helpers.readAppMetrics(input.getAppMetrics)
|
|
);
|
|
}
|
|
return callbacks.snapshot();
|
|
},
|
|
snapshot: callbacks.snapshot,
|
|
});
|
|
},
|
|
|
|
readAppMetrics(
|
|
getAppMetrics: () => readonly unknown[]
|
|
): readonly unknown[] {
|
|
try {
|
|
const metrics = getAppMetrics();
|
|
return Array.isArray(metrics) ? metrics : [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
},
|
|
|
|
readOsProcessId(webContents: RendererWindowWebContents): unknown {
|
|
try {
|
|
return webContents.getOSProcessId();
|
|
} catch {
|
|
return null;
|
|
}
|
|
},
|
|
};
|
|
|
|
return Object.freeze({ create: helpers.create });
|
|
}
|