我正在尝试创建一个 Chrome 扩展程序,通过显示倒数计时器(下面内容脚本中的
timer
变量)暂时阻止特定网站(例如 YouTube)。在倒计时结束时,会出现几个按钮向用户显示一些选项。我的后台脚本有一个 onUpdated
事件侦听器,并在向我的内容脚本发送消息以插入 HTML 元素(timer
、按钮等)之前检查网站 URL。
如果用户尝试刷新页面,我希望再次触发倒计时,到目前为止它一直在工作。 (即,对于我的
onUpdated
事件侦听器,我不检查 changeInfo.url
因为刷新时没有 url 更改)。当内容脚本随后被重新注入时,我包括检查以尝试在重新插入之前删除与我的扩展相关的任何 DOM 元素。
(不确定是否相关)我使用错误处理来发送消息,因为有时在加载内容脚本之前会有延迟,这需要在我发送消息之前发生。
我已经尝试寻找检测自动重定向(不是用户启动)的方法,但似乎没有任何明显的答案。
虽然我的代码在大多数情况下都有效,但这是迄今为止唯一的例外:当我使用例如此链接打开 YouTube 视频时:https://www.youtube.com/watch?v=ghz71MyzSto&ab_channel=cosmic_drifter_007,YouTube 自动重定向页面并修改 URL 以删除
ab_channel
参数。这会导致在短时间内将多条消息发送到内容脚本。发生这种情况时,应该出现的按钮会响应倒计时值的第一个实例,因此会在可见倒计时(倒计时元素的最终实例)达到零之前弹出。
在这种情况下,最佳行为是在 URL 重定向的短时间内仅触发一次倒计时/扩展体验(我已经看到它可能在其他 chrome 扩展程序上,如 one sec),但我很高兴听取任何建议!
// background.js
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (tab.active && changeInfo.status=="complete" && tab.url.startsWith("https://www.youtube.com") {
// try sending a message to content-script.js to start intervention
try {
const response = chrome.tabs.sendMessage(tab.id, {greeting: "start intervention"});
}
catch {
setTimeout(() => {
const response = chrome.tabs.sendMessage(tab.id, {greeting: "start intervention"});
}, 3000); // try sending a message to content-script.js
}
// try injecting some CSS code
}
});
// content-script.js
chrome.runtime.onMessage.addListener(
function(request, sender) {
if (request.greeting === "start intervention")
// remove existing time management banner, appears to work fine
if (document.getElementById("time-management-banner")){
document.getElementById("time-management-banner"). textContent = '';
document.getElementById("time-management-banner").remove();
console.log("time-management-banner removed");
}
else {console.log("time-management-banner not detected")}
// create and insert all elements
banner = document.createElement("div");
banner.id = 'time-management-banner';
banner.className = 'time-management';
banner.innerHTML = "<b>Stop and take a deep breath.</b>";
document.body.appendChild(banner);
// remove existing countdown and replace to reset timer, appears to work fine
if (document.getElementById("time-management-timer")){
document.getElementById("time-management-timer").remove();
console.log("removed timer element");
}
else {console.log("timer element not detected");}
// set up timer
const timer = document.createElement("div");
timer.className = "time-management";
timer.id = "time-management-timer";
var secondsLeft = 3;
banner.appendChild(timer);
var downloadTimer = setInterval(
() => {
// when timer runs out
if (secondsLeft <= 0) {
// reset timer
clearInterval(downloadTimer);
// try removing existing buttons, appears to work fine
if (document.getElementsByClassName("time-management-button")){
const elements = document.getElementsByClassName("time-management-button");
while(elements.length>0){
elements[0].parentNode.removeChild(elements[0]);
}
}
else {console.log("buttons did not need to be removed")};
const proceed_button = document.createElement("button");
const exit_button = document.createElement("button");
// add button text
// set class to time-management for CSS and removal
proceed_button.className = "time-management-button";
exit_button.className = "time-management-button";
// set id (truncated)
// insert buttons
banner.appendChild(proceed_button);
banner.appendChild(exit_button);
// add button actions (truncated)
}
timer.textContent = secondsLeft;
timer.value = secondsLeft;
secondsLeft -= 1;
},
timeout=1000 // interval of 1 second
)
}
)
我已尝试遵循堆栈溢出指南,但未成功查找类似问题,如果我应该修改我的问题,请告诉我!