Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using third party libraries

I want to integrate a Timeline in a chrome extension of mine. I already downloaded the js files and css files of this addon and put them in the root directory of my chrome extension.

The chrome extension itself is just the injection of a JS to an existing page and modifying the html code. However when I try to use the library I will get the error message:

Uncaught ReferenceError: vis is not defined
    at addTimeLine (ui.js:230)
    at createClientBox (ui.js:270)
    at ui.js:62

Here is my manifest.json:

  "content_scripts": [{
    "matches": ["https://web.whatsapp.com/*"],
    "css":["vis.min.css"],
    "js": ["content.js","jquery-3.2.1.min.js","vis.min.js"],
    "run_at": "document_end"
  }],
  "permissions": [
    "activeTab"
  ],

Here the content.js:

function injectJs(link) {
        var scr = document.createElement("script");
        scr.type="text/javascript";
        scr.src=link;
        (document.head || document.body || document.documentElement).appendChild(scr);
}

//injectJs(chrome.extension.getURL("/vis.min.js"));
injectJs(chrome.extension.getURL("/ui.js"));

After the content.js is executed the ui.js is successfully injected to the page and I see my added button on the page. Now when I want to use the library like this:

    var addTimeLine = function () {
        var visualization = document.createElement('div');
        visualization.id = 'visualization';
        // Get the conatiner where the timeline should be displayed
        var container = document.getElementById('visualization');

        // Create a DataSet (allows two way data-binding)
        var items = new vis.DataSet([{
                id: 1,
                content: 'item 1',
                start: '2013-04-20'
            },
            {
                id: 2,
                content: 'item 2',
                start: '2013-04-14'
            },
            {
                id: 3,
                content: 'item 3',
                start: '2013-04-18'
            },
            {
                id: 4,
                content: 'item 4',
                start: '2013-04-16',
                end: '2013-04-19'
            },
            {
                id: 5,
                content: 'item 5',
                start: '2013-04-25'
            },
            {
                id: 6,
                content: 'item 6',
                start: '2013-04-27'
            }
        ]);

        // Configuration for the Timeline
        var options = {};

        // Create a Timeline
        var timeline = new vis.Timeline(container, items, options);
    };

    addTimeLine();

I will get the above error message.

What point am I missing to successfully use third party libraries in a chrome extension?

like image 465
Nico Avatar asked Nov 18 '25 12:11

Nico


1 Answers

You're missing the point of isolated contexts and how it interacts with dynamic <script> elements.

Each page contains a DOM structure and its own JavaScript execution context, the "page" context.

When an extension is adding a content script to a page, it creates a separate JavaScript context, attached to the same DOM. The two contexts don't see each other: if you have a variable in one, it's not present in the other. This includes global objects such as window: each context gets its own copy.

The main reason for this isolation are:

  • Security: the page can't interfere with a higher-privilege content script context and can't detect its presence directly.
  • Convenience: the page context and the extension can use different incompatible libraries; a page context can use any names without clashes; etc.

Your code creates a content script context and adds content.js, jquery-3.2.1.min.js and vis.min.js to it (in that specific order, which may be a problem in itself if content.js expects any of the libraries).

But what happens next is that you create a new DOM script node and add your script there. This gets executed in the page context instead.

So, in your situation, ui.js loads somewhere that vis.min.js isn't loaded, leading to the error; likewise, if you try to use ui.js from the content script context, it won't be loaded there.

If the problem you were originally trying to solve was dynamic content script injection, you have 2 options:

  1. Employ a background page, which can execute chrome.tabs.executeScript on demand from content.js - this adds to the same context.
  2. (Nuclear option) Get contents of your script and eval() them, which is allowed in content scripts (but may cause problems with review when publishing).

If you need to access data from the page context, you will need to cross the boundary, but you need to be aware about it and how to pass messages through it.

like image 198
Xan Avatar answered Nov 20 '25 02:11

Xan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!