开发者

Loading html into page element (chrome extension)

I'm trying to write a Chrome extension that will have a bar at the top of certain webpages. If I have my content script like this:

$('body').prepend('<div id="topbar"><h1>test</h1></div>');

everything looks good, but what I ultimately want is something like this:

$('body').prepend('<div id="topbar"></div>');
$('#topbar').load('topbar.html');

where topbar.html is:

<h1>test</h1>

When I ch开发者_运维问答ange it to this, though, the webpage is clobbered. Most of the content disappears, and I just end up seeing some of the ads. I can't even see the 'test' header. I've checked to make sure there's no other 'topbar' id on the page. What's wrong?


URL of a file inside an extenion folder has the following format:

chrome-extension://<ID>/topbar.html

You can get this path by running:

chrome.extension.getURL("topbar.html")

Now if you try to do:

$('#topbar').load(chrome.extension.getURL("topbar.html"));

it wouldn't let you because of cross-origin policy. Background pages don't have this limitation, so you would need to load HTML there and pass result to a content script:

content_script.js:

chrome.extension.sendRequest({cmd: "read_file"}, function(html){
    $("#topbar").html(html);
});

background.html:

chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
    if(request.cmd == "read_file") {
        $.ajax({
            url: chrome.extension.getURL("topbar.html"),
            dataType: "html",
            success: sendResponse
        });
    }
})

In a real world you probably would read topbar.html only once and then reuse it.


While the above solution does work, one thing to pay attention to is that you need to return true from the event handler so that the communication port can still be available after the $.ajax call succeeds.

see below for more information. https://code.google.com/p/chromium/issues/detail?id=307034


Pure js solution.

In your manifest.json:

{
  "manifest_version": 3,
  # [...]
  "web_accessible_resources": [{
      "matches": ["<all_urls>"],
      "resources": ["topbar.html"]
  }]
}

In your content.js:

async function load_toolbar() {
  let newElement = new DOMParser().parseFromString('<div id="toolbar"></div>', 'text/html').body.childNodes[0];
  let toolbar_url = chrome.runtime.getURL("toolbar.html");

  document.querySelector("body").appendChild(newElement);
  document.getElementById("toolbar").innerHTML = await (await fetch(toolbar_url)).text();
}

load_toolbar();


FYI, now in 2020, chrome.extension.onRequest is deprecated and causes an error when loading the extension. Instead, chrome.runtime.sendMessage should be used. For content.js, the code would now be:

chrome.runtime.sendMessage({cmd: "read_file"}, function(html){
    $("#topbar").html(html);
});

and for background.js the code would now be:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if(request.cmd == "read_file") {
        $.ajax({
            url: chrome.extension.getURL("topbar.html"),
            dataType: "html",
            success: sendResponse
        });
       return true;
    }
})

be sure to note the 'return true' after the ajax, that tripped me up

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜