app
Adom Browser Extension
Public Made by Adomby adom
Your AI's hands in your real, signed-in browser. The Adom Browser Extension (abe) works with both Chrome and Edge: build, drive, and test web apps, and log past vendor walls, in the browser you already use - cookies, SSO, saved logins and captcha trust intact. The nbrowser_* bridge (pup's counterpart) runs in your actual logged-in profile.
// offscreen-record.js — runs MediaRecorder (not available in the MV3 service worker).
// The SW hands us a tabCapture streamId; we record to WebM and return it as base64 on stop.
let recorder = null;
let chunks = [];
let mime = 'video/webm';
chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => {
if (!msg || msg.target !== 'offscreen-record') return;
if (msg.action === 'start') { start(msg).then(sendResponse).catch((e) => sendResponse({ ok: false, error: String((e && e.message) || e) })); return true; }
if (msg.action === 'stop') { stop().then(sendResponse).catch((e) => sendResponse({ ok: false, error: String((e && e.message) || e) })); return true; }
});
async function start(msg) {
const src = msg.source === 'desktop' ? 'desktop' : 'tab'; // desktopCapture vs legacy tabCapture
const fps = Number(msg.fps) || 30;
const stream = await navigator.mediaDevices.getUserMedia({
audio: msg.audio ? { mandatory: { chromeMediaSource: src, chromeMediaSourceId: msg.streamId } } : false,
video: { mandatory: { chromeMediaSource: src, chromeMediaSourceId: msg.streamId, maxFrameRate: fps } },
});
chunks = [];
// vp9 for quality/fps; fall back if unsupported
mime = MediaRecorder.isTypeSupported('video/webm;codecs=vp9') ? 'video/webm;codecs=vp9' : 'video/webm';
recorder = new MediaRecorder(stream, { mimeType: mime, videoBitsPerSecond: msg.bitrate || 6000000 });
recorder.ondataavailable = (e) => { if (e.data && e.data.size) chunks.push(e.data); };
// stop cleanly if the user ends the share from Chrome's "Stop sharing" bar
stream.getVideoTracks()[0].addEventListener('ended', () => { try { if (recorder && recorder.state !== 'inactive') recorder.stop(); } catch (e) {} });
recorder.start(1000); // 1s timeslices
return { ok: true, mimeType: mime, fps };
}
function stop() {
return new Promise((resolve) => {
if (!recorder) return resolve({ ok: false, error: 'not recording' });
recorder.onstop = async () => {
try {
const blob = new Blob(chunks, { type: mime });
const buf = new Uint8Array(await blob.arrayBuffer());
let bin = '';
const CH = 0x8000;
for (let i = 0; i < buf.length; i += CH) bin += String.fromCharCode.apply(null, buf.subarray(i, i + CH));
const out = { ok: true, base64: btoa(bin), mimeType: mime, sizeKB: Math.round(buf.length / 1024) };
recorder.stream.getTracks().forEach((t) => t.stop());
recorder = null;
chunks = [];
resolve(out);
} catch (e) { resolve({ ok: false, error: String((e && e.message) || e) }); }
};
recorder.stop();
});
}