verify-desktop-runtime.mjs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. import {execFileSync} from 'node:child_process'
  2. import {readFileSync} from 'node:fs'
  3. import {join} from 'node:path'
  4. import {verifyRuntimePackage} from '../bin/lib/runtime-release.mjs'
  5. /** Run before signing: a valid build directory does not prove extraResources
  6. * retained the Runner's external packages in the actual application. */
  7. export function verifyDesktopRuntime(runtime,version){
  8. const service=join(runtime,'web-service'),identity=verifyRuntimePackage(service)
  9. const probe=String.raw`
  10. import {createRequire} from 'node:module';
  11. import {readFileSync,realpathSync,statSync} from 'node:fs';
  12. import {dirname,join,relative,isAbsolute} from 'node:path';
  13. import {pathToFileURL} from 'node:url';
  14. const {runtime,version}=JSON.parse(process.argv[1]);
  15. for(const [base,entry] of [[runtime,'runner.mjs'],[join(runtime,'web-service'),'server.mjs']]){
  16. if(!statSync(join(base,entry)).isFile())throw new Error('应用内执行入口缺失:'+entry);
  17. const require=createRequire(join(base,entry));
  18. for(const name of ['playwright','playwright-core']){
  19. const path=realpathSync(require.resolve(name+'/package.json'));
  20. const local=relative(realpathSync(join(base,'node_modules',name)),path);
  21. if(local.startsWith('..')||isAbsolute(local))throw new Error('浏览器依赖解析到了应用外部:'+name);
  22. const pkg=JSON.parse(readFileSync(path,'utf8'));
  23. if(pkg.version!==version)throw new Error('浏览器运行包版本不一致:'+name);
  24. if(name==='playwright'){
  25. const {chromium}=await import(pathToFileURL(join(dirname(path),'index.mjs')).href);
  26. if(!chromium?.executablePath())throw new Error('浏览器运行包无法加载');
  27. }else if(!JSON.parse(readFileSync(join(dirname(path),'browsers.json'),'utf8')).browsers?.length){
  28. throw new Error('浏览器运行包缺少安装清单');
  29. }
  30. }
  31. }
  32. `
  33. execFileSync(join(service,'node'),['--input-type=module','-e',probe,JSON.stringify({runtime,version})],{cwd:runtime,stdio:['ignore','pipe','pipe'],timeout:30000})
  34. return identity
  35. }
  36. export default async function verifyPackagedDesktop(context){
  37. if(context.electronPlatformName!=='darwin')return
  38. const version=JSON.parse(readFileSync(new URL('../package.json',import.meta.url),'utf8')).dependencies.playwright
  39. const runtime=join(context.appOutDir,context.packager.appInfo.productFilename+'.app','Contents','Resources','runtime')
  40. verifyDesktopRuntime(runtime,version)
  41. console.log('签名前验证通过:应用内 Runner / Web 浏览器依赖与服务完整性。')
  42. }