35 lines
2.8 KiB
JavaScript
35 lines
2.8 KiB
JavaScript
'use strict';
|
|
const path=require('node:path');
|
|
const {spawn}=require('node:child_process');
|
|
const {EventEmitter}=require('node:events');
|
|
const {createBrokerSupervisor}=require('./broker-supervisor.cjs');
|
|
const {createFramedChannel}=require('../network-broker/framed-channel.cjs');
|
|
// Privileged browser construction only. Installation verification covers the
|
|
// fixed native client as well as the signed broker payload. No renderer-supplied
|
|
// command, path, pipe name, environment or identity enters this transport.
|
|
function createServiceBrokerSupervisor({installationRoot,verifyInstallation,verifyPackage,persistAudit,acceptCertificate,onQuarantine,launch=spawn,deadlineMs,shutdownMs,traceOperation}={}){
|
|
if(!path.isAbsolute(installationRoot||'')||typeof verifyInstallation!=='function'||typeof launch!=='function'||typeof verifyPackage!=='function')throw Error('broker-supervisor-invalid');
|
|
const root=path.resolve(installationRoot),resourceRoot=path.join(root,'resources','broker');
|
|
function connect(){
|
|
const env={};for(const name of ['SystemRoot','WINDIR','TEMP','TMP','USERPROFILE','LOCALAPPDATA','APPDATA'])if(process.env[name])env[name]=process.env[name];
|
|
// --client-stdio authenticates the retained actual browser parent and the
|
|
// connected service pipe handle in native code, before forwarding frames.
|
|
const child=launch(path.join(root,'safetynet-service-host.exe'),['--client-stdio'],{cwd:root,env,windowsHide:true,shell:false,stdio:['pipe','pipe','ignore']});
|
|
if(!child||!child.stdin||!child.stdout||typeof child.kill!=='function')throw Error('broker-supervisor-unavailable');
|
|
const transport=new EventEmitter();
|
|
const channel=createFramedChannel({readable:child.stdout,writable:child.stdin,inboundFirstLimit:65536,outboundFirstLimit:2097152});
|
|
Object.defineProperties(transport,{exitCode:{get:()=>child.exitCode},signalCode:{get:()=>child.signalCode}});
|
|
channel.on('message',message=>transport.emit('message',message));
|
|
channel.once('disconnect',()=>transport.emit('disconnect'));
|
|
child.once('error',()=>{channel.disconnect();transport.emit('error',Error('broker-supervisor-unavailable'));});
|
|
child.once('exit',(code,signal)=>{channel.disconnect();transport.emit('exit',code,signal);});
|
|
transport.send=(message,callback)=>channel.send(message,callback);
|
|
// Only the retained child handle is terminated. The service owns the broker
|
|
// Job; losing this connection causes its generation to close independently.
|
|
transport.kill=signal=>{channel.disconnect();return child.kill(signal);};
|
|
return transport;
|
|
}
|
|
return createBrokerSupervisor({resourceRoot,verifyPackage:async location=>await verifyInstallation(root)===true&&await verifyPackage(location)===true,persistAudit,acceptCertificate,onQuarantine,spawn:connect,deadlineMs,shutdownMs,traceOperation});
|
|
}
|
|
module.exports={createServiceBrokerSupervisor};
|