用户导航时,如何通过页面到页面传递流? Chrome扩展清单V3
我正在开发一个清单V3 Google Chrome扩展程序,旨在进行屏幕截图并记录用户浏览。
问题:当我在屏幕共享流时从一个页面导航到另一页时。
问题1:如何通过导航页面之间的流?
问题2:如何存储流,以便在加载下一页时保持流?
注意:
在服务工作者中,我使用chrome.desktopcapture.choosedesktopmedia来启动屏幕共享窗口,然后我将获得流ID,然后将其发送到页面上的内容脚本,我使用Navigator.Mediadevices.mediadevices.getusermedia to to to to to to获取然后将其放在视频元素中的流。这个视频对象使我可以使用画布进行屏幕截图。
使用明显的V2查看一些扩展,使用背景页面存储视频对象和创建流的脚本。但是现在有了Sustest V3中的服务人员,我该怎么办?
我的代码:
服务工作者:
chrome.runtime.onConnect.addListener(function (port) {
port.onMessage.addListener(function (msg) {
if (msg.type === 'SS_UI_REQUEST') {
requestScreenSharing(port, msg)
}
if (msg.type === 'SS_UI_TAKESCREENSHOT') {
console.log(msg.top);
StartCountDown(port, msg);
}
});
});
// const sources = ['screen', 'window', 'tab', 'audio'];
async function requestScreenSharing(port, msg) {
const sources = ['screen'];
const tab = port.sender.tab;
chrome.desktopCapture.chooseDesktopMedia(
sources,
port.sender.tab,
streamId => {
if (streamId) {
msg.type = 'SS_DIALOG_SUCCESS';
msg.streamId = streamId;
msg.text = "sharing";
} else {
msg.type = 'SS_DIALOG_CANCEL';
msg.text = "cancel";
}
var tab = getTabId();
tab.then((value) => {
const respuesta = chrome.tabs.connect(value.id, {
name: "respuesta",
});
respuesta.postMessage(msg);
});
}
);
}
let seconds = 3;
let id;
async function StartCountDown(port, msg) {
const css1 = 'body::after{ display: flex; height: 100vh;justify-content: center;align-items: center; background:rgb(76,76,76); opacity: 0.7; content: "Capturando pantalla.. 3"; color:white;font-size: 50px;font-weight: 500; width:100%; position: absolute;top:'+msg.top+'px;left: 0; z-index: 2040;}'
const css2 = 'body::after{ content: "Capturando pantalla.. 2";}'
const css3 = 'body::after{ content: "Capturando pantalla.. 1";}'
myIntervalId = setInterval(function () {
IntervalId = myIntervalId;
if (seconds > 0) {
chrome.action.setBadgeBackgroundColor({
color: [255, 0, 0, 255]
});
chrome.action.setBadgeText({
text: seconds.toString()
});
if (seconds == 3) {
var csstab = getTabId();
csstab.then((value) => {
chrome.scripting.insertCSS({
target: {
tabId: value.id
},
css: css1,
});
});
}
if (seconds == 2) {
var csstab = getTabId();
csstab.then((value) => {
chrome.scripting.insertCSS({
target: {
tabId: value.id
},
css: css2,
});
});
}
if (seconds == 1) {
var csstab = getTabId();
csstab.then((value) => {
chrome.scripting.insertCSS({
target: {
tabId: value.id
},
css: css3,
});
});
}
seconds--;
} else {
chrome.action.setBadgeText({
'text': ''
});
seconds = 3;
clearInterval(IntervalId);
msg.type = 'SS_UI_TAKESCREENSHOT_SUCCESS';
msg.text = "takingScreenShot";
var tab = getTabId();
tab.then((value) => {
chrome.scripting.removeCSS({
target: {
tabId: value.id
},
css: css1,
});
chrome.scripting.removeCSS({
target: {
tabId: value.id
},
css: css2,
});
chrome.scripting.removeCSS({
target: {
tabId: value.id
},
css: css3,
});
const respuesta = chrome.tabs.connect(value.id, {
name: "respuesta",
});
respuesta.postMessage(msg);
});
}
}, 1000);
}
async function getTabId() {
let queryOptions = {
active: true,
currentWindow: true
};
let [tab] = await chrome.tabs.query(queryOptions);
return tab;
}
content-script
chrome.runtime.onConnect.addListener(function (port) {
port.onMessage.addListener(function(msg){
if (msg.type === 'SS_UI_REQUEST') {
console.log(msg);
if(!window.stream)
{
var messenger = chrome.runtime.connect();
messenger.postMessage(msg);
}else
{
console.log(msg);
var messenger = chrome.runtime.connect();
messenger.postMessage({ type: 'SS_UI_TAKESCREENSHOT', top: window.scrollY.toString() },'*');
}
}
if (msg.type === 'SS_DIALOG_SUCCESS') {
startScreenStreamFrom(msg.streamId);
console.log(msg);
var messenger = chrome.runtime.connect();
messenger.postMessage({ type: 'SS_UI_TAKESCREENSHOT', top: window.scrollY.toString() },'*');
}
if (msg.type === 'SS_UI_CHANGE_CSS') {
console.log(msg);
}
if (msg.type === 'SS_DIALOG_CANCEL') {
console.log(msg);
}
if(msg.type === "SS_UI_TAKESCREENSHOT_SUCCESS")
{
console.log(msg);
setTimeout(function() {
TakeScreenShot();
}, 300);
}
if(msg.type === "SS_UI_RECORDSCREEN")
{
console.log("Grabar pantalla");
RecordScreen();
}
});
});
function startScreenStreamFrom(streamId) {
console.log("compartiendo pantalla");
navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: streamId
}
}
})
.then(stream => {
var video = document.getElementById("ElementNotExist");
if(video)
{
video.remove();
}
window.stream = stream;
window.stream.getVideoTracks()[0].onended = function () {
window.stream = null;
};
var video = document.createElement('video');
video.srcObject = stream;
video.type = 'video/ogg';
video.autoplay = true;
video.setAttribute("id","ElementNotExist");
video.style.display = "none";
document.body.appendChild(video);
});
}
index.js扩展脚本。
document.getElementById("btn-capture").addEventListener("click", function () {
var tab = getTabId();
tab.then((value) => {
chrome.storage.local.set({ 'pestaña': value.id });
const port = chrome.tabs.connect(value.id, {
name: "conexion",
});
port.postMessage({ type: 'SS_UI_REQUEST', text: 'start' }, '*');
window.close();
chrome.action.setPopup({popup: "capture.html"});
});
})
async function getTabId() {
let queryOptions = { active: true, currentWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
return tab;
}
I'm developing a manifest v3 Google Chrome extension that aims to take screenshots and record user browsing.
Problem: When I navigate from one page to another while screen sharing the stream is lost.
Question 1: how to pass the stream between navigation pages?
Question 2: how to store the stream so that when loading the next page the stream is maintained?
Note:
In the service worker I use chrome.desktopCapture.chooseDesktopMedia to bring up the screen sharing window, with this I get the stream id which is then sent to the content script found on the page, where I use navigator.mediaDevices.getUserMedia to get the stream which I then place inside a video element. This video object allows me to take screenshots with canvas.
Viewing some extensions with manifest v2 use the background pages to store the video object and the scripts that create the stream. But now with the service worker in manifest v3, how could I do it?
My code:
Service worker:
chrome.runtime.onConnect.addListener(function (port) {
port.onMessage.addListener(function (msg) {
if (msg.type === 'SS_UI_REQUEST') {
requestScreenSharing(port, msg)
}
if (msg.type === 'SS_UI_TAKESCREENSHOT') {
console.log(msg.top);
StartCountDown(port, msg);
}
});
});
// const sources = ['screen', 'window', 'tab', 'audio'];
async function requestScreenSharing(port, msg) {
const sources = ['screen'];
const tab = port.sender.tab;
chrome.desktopCapture.chooseDesktopMedia(
sources,
port.sender.tab,
streamId => {
if (streamId) {
msg.type = 'SS_DIALOG_SUCCESS';
msg.streamId = streamId;
msg.text = "sharing";
} else {
msg.type = 'SS_DIALOG_CANCEL';
msg.text = "cancel";
}
var tab = getTabId();
tab.then((value) => {
const respuesta = chrome.tabs.connect(value.id, {
name: "respuesta",
});
respuesta.postMessage(msg);
});
}
);
}
let seconds = 3;
let id;
async function StartCountDown(port, msg) {
const css1 = 'body::after{ display: flex; height: 100vh;justify-content: center;align-items: center; background:rgb(76,76,76); opacity: 0.7; content: "Capturando pantalla.. 3"; color:white;font-size: 50px;font-weight: 500; width:100%; position: absolute;top:'+msg.top+'px;left: 0; z-index: 2040;}'
const css2 = 'body::after{ content: "Capturando pantalla.. 2";}'
const css3 = 'body::after{ content: "Capturando pantalla.. 1";}'
myIntervalId = setInterval(function () {
IntervalId = myIntervalId;
if (seconds > 0) {
chrome.action.setBadgeBackgroundColor({
color: [255, 0, 0, 255]
});
chrome.action.setBadgeText({
text: seconds.toString()
});
if (seconds == 3) {
var csstab = getTabId();
csstab.then((value) => {
chrome.scripting.insertCSS({
target: {
tabId: value.id
},
css: css1,
});
});
}
if (seconds == 2) {
var csstab = getTabId();
csstab.then((value) => {
chrome.scripting.insertCSS({
target: {
tabId: value.id
},
css: css2,
});
});
}
if (seconds == 1) {
var csstab = getTabId();
csstab.then((value) => {
chrome.scripting.insertCSS({
target: {
tabId: value.id
},
css: css3,
});
});
}
seconds--;
} else {
chrome.action.setBadgeText({
'text': ''
});
seconds = 3;
clearInterval(IntervalId);
msg.type = 'SS_UI_TAKESCREENSHOT_SUCCESS';
msg.text = "takingScreenShot";
var tab = getTabId();
tab.then((value) => {
chrome.scripting.removeCSS({
target: {
tabId: value.id
},
css: css1,
});
chrome.scripting.removeCSS({
target: {
tabId: value.id
},
css: css2,
});
chrome.scripting.removeCSS({
target: {
tabId: value.id
},
css: css3,
});
const respuesta = chrome.tabs.connect(value.id, {
name: "respuesta",
});
respuesta.postMessage(msg);
});
}
}, 1000);
}
async function getTabId() {
let queryOptions = {
active: true,
currentWindow: true
};
let [tab] = await chrome.tabs.query(queryOptions);
return tab;
}
content-script
chrome.runtime.onConnect.addListener(function (port) {
port.onMessage.addListener(function(msg){
if (msg.type === 'SS_UI_REQUEST') {
console.log(msg);
if(!window.stream)
{
var messenger = chrome.runtime.connect();
messenger.postMessage(msg);
}else
{
console.log(msg);
var messenger = chrome.runtime.connect();
messenger.postMessage({ type: 'SS_UI_TAKESCREENSHOT', top: window.scrollY.toString() },'*');
}
}
if (msg.type === 'SS_DIALOG_SUCCESS') {
startScreenStreamFrom(msg.streamId);
console.log(msg);
var messenger = chrome.runtime.connect();
messenger.postMessage({ type: 'SS_UI_TAKESCREENSHOT', top: window.scrollY.toString() },'*');
}
if (msg.type === 'SS_UI_CHANGE_CSS') {
console.log(msg);
}
if (msg.type === 'SS_DIALOG_CANCEL') {
console.log(msg);
}
if(msg.type === "SS_UI_TAKESCREENSHOT_SUCCESS")
{
console.log(msg);
setTimeout(function() {
TakeScreenShot();
}, 300);
}
if(msg.type === "SS_UI_RECORDSCREEN")
{
console.log("Grabar pantalla");
RecordScreen();
}
});
});
function startScreenStreamFrom(streamId) {
console.log("compartiendo pantalla");
navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSourceId: streamId
}
}
})
.then(stream => {
var video = document.getElementById("ElementNotExist");
if(video)
{
video.remove();
}
window.stream = stream;
window.stream.getVideoTracks()[0].onended = function () {
window.stream = null;
};
var video = document.createElement('video');
video.srcObject = stream;
video.type = 'video/ogg';
video.autoplay = true;
video.setAttribute("id","ElementNotExist");
video.style.display = "none";
document.body.appendChild(video);
});
}
Index.js Extension script.
document.getElementById("btn-capture").addEventListener("click", function () {
var tab = getTabId();
tab.then((value) => {
chrome.storage.local.set({ 'pestaña': value.id });
const port = chrome.tabs.connect(value.id, {
name: "conexion",
});
port.postMessage({ type: 'SS_UI_REQUEST', text: 'start' }, '*');
window.close();
chrome.action.setPopup({popup: "capture.html"});
});
})
async function getTabId() {
let queryOptions = { active: true, currentWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
return tab;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论