21 lines
1.5 KiB
JavaScript
21 lines
1.5 KiB
JavaScript
'use strict';
|
|
const {guardedScreenshot}=require('./page-clipboard-guard.cjs');
|
|
function bounded(operation,ms){let timer;return Promise.race([operation,new Promise((_,reject)=>{timer=setTimeout(()=>reject(Error('Visual capture timed out')),ms);})]).finally(()=>clearTimeout(timer));}
|
|
async function capturePNG(contents,rect){
|
|
if(rect&&(!['x','y','width','height'].every(key=>Number.isInteger(rect[key]))||rect.x<0||rect.y<0||rect.width<16||rect.height<16||rect.width*rect.height>8*1024*1024))throw Error('Visual capture region invalid');
|
|
// Use Chromium's current render surface: Windows native capture can return a stale frame.
|
|
// Share the verified internal page-security connection when present; never detach it.
|
|
// No debugger endpoint or general command interface is exposed to sites or agents.
|
|
const parameters={format:'png',fromSurface:true,captureBeyondViewport:false,...(rect?{clip:{...rect,scale:1}}:{})};
|
|
const owned=guardedScreenshot(contents,parameters);
|
|
const debuggerAPI=contents.debugger;if(!debuggerAPI||!owned&&debuggerAPI.isAttached())throw Error('Visual capture unavailable');
|
|
let attached=false;
|
|
try{
|
|
if(!owned){debuggerAPI.attach('1.3');attached=true;}
|
|
const result=await bounded(owned||debuggerAPI.sendCommand('Page.captureScreenshot',parameters),3000);
|
|
if(typeof result?.data!=='string'||result.data.length>14*1024*1024||!/^[A-Za-z0-9+/]+={0,2}$/.test(result.data))throw Error('Visual capture bytes invalid');
|
|
return Buffer.from(result.data,'base64');
|
|
}finally{if(attached)debuggerAPI.detach();}
|
|
}
|
|
module.exports={capturePNG};
|