最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - chrome extension content script not working when url change but only works after refresh - Stack Overflow

programmeradmin6浏览0评论

I'm developing a chrome extension to make some changes on Github site while the URL postfix matches the source code type (for example, xxx.cpp)

I expect the content.js will run every time the tab finishes loading the DOM elements. However, it only runs when I press the refresh button. If I click the hyperlinks and go to another URL, content.js won't run.

What did I do wrong? Thanks.

Following are the code.

manifest.json

{
    "name": "My Chrome Ext",
    "description": "change appearance of source code on Github",
    "version": "0.1",
    "manifest_version": 3,
    "permissions": ["storage", "activeTab"],
    "action": {},
    "content_scripts": [
        {
            "matches": ["*://github/*cpp"],
            "all_frames": true,
            "js": ["content.js"],
            "run_at": "document_end"
        }
    ]
}

content.js

window.alert("start running content.js");

I'm developing a chrome extension to make some changes on Github site while the URL postfix matches the source code type (for example, xxx.cpp)

I expect the content.js will run every time the tab finishes loading the DOM elements. However, it only runs when I press the refresh button. If I click the hyperlinks and go to another URL, content.js won't run.

What did I do wrong? Thanks.

Following are the code.

manifest.json

{
    "name": "My Chrome Ext",
    "description": "change appearance of source code on Github",
    "version": "0.1",
    "manifest_version": 3,
    "permissions": ["storage", "activeTab"],
    "action": {},
    "content_scripts": [
        {
            "matches": ["*://github./*cpp"],
            "all_frames": true,
            "js": ["content.js"],
            "run_at": "document_end"
        }
    ]
}

content.js

window.alert("start running content.js");
Share Improve this question asked Apr 20, 2022 at 7:24 QiaoQiao 5127 silver badges18 bronze badges 1
  • Remove cpp from matches and use MutationObserver to detect changes, more info. – woxxom Commented Apr 20, 2022 at 8:43
Add a ment  | 

2 Answers 2

Reset to default 12

The Chrome extension content script will only load when a pletely new webpage matching the URL specified in your manifest is loaded. In this era of single page web applications, many websites, including GitHub, use Javascript frameworks and Ajax calls to only update parts of the existing webpage content as the user navigates around the site. Even though the address bar is being updated, most of the time no actual page loads are being executed, so your chrome extension won't trigger.

This improves the performance of the website, but it does mean that browser extensions can't always depend on their content scripts being loaded even if the browser is displaying a matching URL.

My solution? Enable the extension for the entire site and the gate the content script functionality behind a MutationObserver that checks window.location.href every time the callback is called:

function addLocationObserver(callback) {

  // Options for the observer (which mutations to observe)
  const config = { attributes: false, childList: true, subtree: false }

  // Create an observer instance linked to the callback function
  const observer = new MutationObserver(callback)

  // Start observing the target node for configured mutations
  observer.observe(document.body, config)
}

function observerCallback() {

  if (window.location.href.startsWith('https://github.')) {
    initContentScript()
  }
}

addLocationObserver(observerCallback)
observerCallback()

I also invoke the callback immediately the content script is called to ensure the script triggers correctly on a page reload. You might have to play with the observer configuration to ensure the observer triggers the callback at all the right times.

Note, the target node for the observer be one that remains in the document unless the entire page is refreshed. If it's overwritten, you will lose the observer and your script won't be triggered. In my case the document.body works just fine.

After fighting this for days, I found a solution that works reliably when the history state is updated, but it requires many permissions to run.

This requires the following permissions for manifest v3

"permissions: [
  "tabs",
  "scripting",
  "webNavigation"]

and

"host_permissions":[ "https://github./*"]

Add the following code to service-worker.js

//This seems to force the content-script to be reloaded when the history changes
chrome.webNavigation.onHistoryStateUpdated.addListener( async (details) =>  {
   
    const getCurrentTab = async () => {
        let queryOptions = { active: true, lastFocusedWindow: true };     
        let [tab] = await chrome.tabs.query(queryOptions);
        return tab;
      }
    
    let tab = await getCurrentTab();

    chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: () => {} //this literally will execute an empty function in the current tab which seems to be enough to reload or reconnect the content-script
      });
});

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论