Chrome扩展程序 - 页面更新两次,然后在YouTube上删除

Chrome extension - page update twice then removed on YouTube

本文关键字:两次 然后 删除 YouTube 程序 扩展 更新 Chrome      更新时间:2023-09-26

我想做一个小扩展,将一个简单的html注入到视频正下方的YouTube页面中。如果我简单地访问 youtube 网址,它可以正常工作。但是,如果我从 youtube 优惠中选择视频,那么我的 html 代码会注入两次但被删除。我可以看到它几乎立即出现然后消失。

我的代码是:

背景.js

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if ( changeInfo.status == 'complete' && tab.status == 'complete' && tab.url != undefined ) {
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {method: "reDraw"}, function(response) {
                console.log("Injection ready!");
            });
        });
    }
});

内容.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
        if (request.method == "reDraw") {
            $.get(chrome.extension.getURL('/mytest.html'), function(data) {
                $(data).insertAfter('#placeholder-player');
            });   
        } 
    }
);  

chrome.tabs.onUpdated也会触发iframes,对于YouTube,有很多iframe会触发此事件,除此之外,当您从一个视频转到另一个视频时,YouTube不会重新加载页面。有关YouTube问题的更多详细信息,您可以查看以下线程:

  • https://bugs.chromium.org/p/chromium/issues/detail?id=165854
  • Chrome webNavigation.onComplete不起作用?
  • chrome扩展程序chome.tabs.on更新运行两次?

所以我的建议是使用chrome.webNavigation api,并将webNavigation.onCompletedwebNavigation.onHistoryStateUpdated相结合,示例代码如下所示

考虑到您正在检测YouTube视频页面,我建议您使用chrome.webNavigation.onHistoryStateUpdated

// To handle youtube video page
chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
    if(details.frameId === 0) {
        // Fires only when details.url === currentTab.url
        chrome.tabs.get(details.tabId, function(tab) {
            if(tab.url === details.url) {
                console.log("onHistoryStateUpdated");
            }
        });
    }
});

这是一种使用 chrome.webNavigation.onHistoryStateUpdated 只触发一次的方法

// background.js
'use strict';
console.log('QboAudit Background Script');
chrome.runtime.onInstalled.addListener(details => {
  console.log('QboAudit previousVersion', details.previousVersion);
})
chrome.webNavigation.onHistoryStateUpdated.addListener( (details) => {
  console.log('QboAudit Page uses History API and we heard a pushSate/replaceState.')
  if(typeof chrome._LAST_RUN === 'undefined' || notRunWithinTheLastSecond(details.timeStamp)){
    chrome._LAST_RUN = details.timeStamp
    chrome.tabs.getSelected(null, function (tab) { 
      if(tab.url.match(/.*'/app'/auditlog$/)){
        chrome.tabs.sendRequest(tab.id, 'runQboAuditLog')
      }
    })
  }
})
const notRunWithinTheLastSecond = (dt) => {
  const diff = dt - chrome._LAST_RUN
  if (diff < 1000){
    return false
  } else {
    return true
  }
}

简而言之,您创建一个全局变量chrome._LAST_RUN来跟踪此事件是否在不到一秒前已经触发。

// contentscript.js
chrome.extension.onRequest.addListener((request, sender, sendResponse) => {
  //console.log('request', request)
  if (request == 'runQboAuditLog')
    new QboAuditLog()
});

我猜 youTube 在某些页面上使用 Ajax 调用来加载内容,因此您的代码被替换为 Ajax 响应。

使用 setTimeout() 函数在几秒钟后检查您的代码是否在页面上,如果没有,请再次添加它。