Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding complex HTML using a Chrome content script

I am working with Chrome extension's content script to create a complex display that is added on web pages.

I have first tested it directly integrated on a website, but now I need to put it in an extension.

The thing is that the content script API for Chrome only allows to inject javascript. That means that, to inject complex HTML layouts I would need to write it entirely with JS objects, which is long to write, hard to maintain and absolutely not designer-friendly.

I'm wondering if anyone know or can think of a clever way to get a better workflow on this.

like image 758
nialna2 Avatar asked Apr 08 '13 07:04

nialna2


People also ask

Can Chrome extensions edit HTML?

Page Edit is an extension that let you make changes to any HTML webpage. To work with this add-on, simply open the toolbar popup UI and then click on the big toggle button at the left side.

What is content script Chrome extension?

A content script is a part of your extension that runs in the context of a particular web page (as opposed to background scripts which are part of the extension, or scripts which are part of the website itself, such as those loaded using the <script> element).

Can you run scripts on Chrome?

You can use the chrome. scripting API to inject JavaScript and CSS into websites. This is similar to what you can do with content scripts, but by using the chrome.


3 Answers

It's relatively easy to add whole web pages by having your content script inject them in an iframe. Just follow these guidelines:

  1. Place the *.htm or *.html files in your extension's source folder(s).

  2. Place any *.css and *.js files, that the HTML uses, in the extension folder(s) too.

  3. Declare the HTML file(s) as resources. EG:

    "web_accessible_resources": ["Embedded_Hello_world.htm"]
    


  4. Do not use any inline, or external server, javascript in your HTML files. This avoids problems with the Content Security Policy (CSP).

  5. This question doesn't cover communicating with the page/iframe, but if you want to do that, it is a bit more involved. Search here on SO; it's been covered many times.


Example:

You can see this in action by:

  1. Creating a new extension folder.
  2. Download jQuery into it.
  3. Create the 5 files as specified below.
  4. Load the unpacked extension (You can see similar steps in this answer.)
  5. Reload this page in Chrome; you'll see the "Hello World" page, embedded at the top.

Create these files in the extension folder:

manifest.json:

{
    "manifest_version":         2,
    "content_scripts":          [ {
        "js":       [ "iframeInjector.js" ],
        "matches":  [   "https://stackoverflow.com/questions/*"
        ]
    } ],
    "description":              "Inject a complete, premade web page",
    "name":                     "Inject whole web page",
    "version":                  "1",
    "web_accessible_resources": ["Embedded_Hello_world.htm"]
}


iframeInjector.js:

var iFrame  = document.createElement ("iframe");
iFrame.src  = chrome.extension.getURL ("Embedded_Hello_world.htm");

document.body.insertBefore (iFrame, document.body.firstChild);


Embedded_Hello_world.htm:

<!DOCTYPE html>
<html><head>
    <title>Embedded Hello World</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <link href="HelloWorld.css" rel="stylesheet" type="text/css">

    <script type="text/javascript" src="jquery.min.js"></script>
    <script type="text/javascript" src="HelloWorld.js"></script>
</head><body>
<p>Hello World!</p>
</body></html>


HelloWorld.css:

body {
    color:              red;
    background-color:   lightgreen;
}


HelloWorld.js:

$(document).ready (jQueryMain);

function jQueryMain () {
    $("body").append ('<p>Added by jQuery</p>');
}
like image 83
Brock Adams Avatar answered Oct 20 '22 08:10

Brock Adams


This may be better, no external library and no iframe. Is nearly the same as iautomation solution.

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        var div = document.createElement('div');
        div.innerHTML = this.responseText;
        document.body.insertBefore(div, document.body.firstChild);
    } else {
        console.log('files not found');
    }
};
xhttp.open("GET", chrome.extension.getURL("/content.htm"), true);
xhttp.send();
like image 44
Photonic Avatar answered Oct 20 '22 10:10

Photonic


I had the same issue, that my extension heavily relies on script templates

Here's what I did:

  • create templates.html to store script templates in
  • add templates.html to the web_accessible_resources as in the the above answer^^
  • access templates.html from content.js with xhr and parse with jQuery

manifest.json

"web_accessible_resources": ["templates.html"]

templates.html

<script id="template1" type="text/template">
    <div class="template1">template1</div>
</script>
<script id="template2" type="text/template">
    <div class="template2">template2</div>
</script>

content.js

function getTemplates(){
    return new Promise(function(resolve){
        $.ajax({
            url: chrome.extension.getURL('/templates.html'),
            success: function(data) {
                var $templates = $('<div></div>').append($.parseHTML(data)).find('script'),
                    templates = {};
                $templates.each(function(){
                    templates[this.id] = this.innerHTML;
                });
                return resolve(templates);
            }
        });
    });
}
getTemplates().then(function(templates){
    console.log(templates.template1); //<div class="template1">template1</div>
});
like image 25
iautomation Avatar answered Oct 20 '22 10:10

iautomation