Adding complex HTML using a Chrome content script

Malharhak picture Malharhak · Apr 8, 2013 · Viewed 16.5k times · Source

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.

Answer

Brock Adams picture Brock Adams · Apr 8, 2013

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>');
}