Unable to send message from context menu to content script

I want to send a message to the content script, when the user selects a context menu item. The content script will then, based on the message, format the webpage as required.

I was unable to do so and I have been able to locate the problem to the code responsible for sending the message (in the context menu script) or the one responsible for receiving message (in the content script). Below, I try to present a simplified version of the code that tries to duplicate the problem:

backgroundContextMenus.js:

chrome.runtime.onInstalled.addListener(function(){
    chrome.contextMenus.create({"title": "Testing",
                                "contexts": ["selection"],
                                "id": "testing"});
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
    console.log("testing works");
    console.log("Before sending the bold message");
    chrome.tabs.sendMessage(tab.id, {changeParameter: "bold"});
    console.log("After sending the bold message");
});

markr.js:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse){
        console.log("Text toggled bold");
    }); 

Upon selecting the context menu item, the console shows these messages:

backgroundContextMenus.js:75 testing..
backgroundContextMenus.js:77 Before sending the bold message
backgroundContextMenus.js:79 After sending the bold message

So, as you may notice, there is no log saying “Text toggled bold”. Therefore, I suspect that there must be something wrong with the code responsible for sending message (chrome.tabs.sendMessage(tabs[0].id, {changeParameter: "bold"});)

I tried to follow this answer but it gives the same problem.

I am unable to figure out what exactly is wrong with it. It would be of great help if you could help me figure it out.

Reference to popup window in Chrome content script gets lost

In the content script of chrome extension, I would like to open a popup window and get the reference, so that I could send messages to the window, and close it in the onbeforeunload event.

However, it seems the reference only exists in the local scope, and it gets lost in any other closures.

e.g. If I use the following code in the content script:

var popup = window.open("https://example.com/", 'popwin');
console.log("@1", popup);
setTimeout(function(){
  console.log("@2", popup);
}, 2000);

Here is what I see in the console window

@1 Window {window: Window, self: Window, location: Location, closed: false, frames: Window, …}

@2 global {}


And it’s even the same if I use a global window property to store the reference, i.e.

window.popup = window.open("https://example.com/", 'popwin');
console.log("@1", window.popup);
setTimeout(function(){
  console.log("@2", window.popup);
}, 2000);

@1 Window {window: Window, self: Window, location: Location, closed: false, frames: Window, …}

@2 global {}

How do I run Chrome extension content script after a site’s javascript has finished building page?

I know that I can use run_at: document end to run a script after a page is loaded, but most sites now inject most of their content through some kind of js framework. From what I can tell the content.js script is running before those can finish.

I have some ideas on how to do this, but I’m not really if they really make sense, or even how to do them if they did.

  1. Run my script every time the DOM updates so that if a hyperlink is added I can just remove the hrefs again.

    I found this domwatcher thing in uBlock origin, I assume he’s doing something like this in order to remove any ads that show up, but it’s really complex and I’m not sure what things I would or wouldn’t need.

  2. Run the extension every second or two. This seems really clumsy, but maybe it’s a standard thing? I’m not sure. I also don’t know how I would get a content script to repeat, something this simple couldn’t cause performance issues right?

  3. Javascript scripts are executed in order when they are listed in html right? So maybe I add the script to the end of all those? But they run asynchronously anyway right so that probably wouldn’t work. Either way, some way to run my script after all the others are done. Can I put them in promises?

Also here is my GitHub page with all the code.

The relevant manifest:

 "content_scripts": [
    {
    "matches": [
        "http://*/*",
        "https://*/*"
        ],
    "js": ["content.js"],
    "run_at": "document_end"
    }
]

And content.js:

chrome.storage.sync.get('isEnabled', function (data) {
    if(!data.isEnabled) {
        return;
    }

    for (let link of document.links) {
        link.removeAttribute('href');
        console.log(link);
    }
});

can chrome extension content script use a module loader?

I’ve looked into ES6 modules and require.js but both need a “script” tag on the executing page to be able to use them.

In content scripts we just specify the list of js files to be injected on the webpage and no script tag is used. Is there a module loader i am not aware of that doesn’t have dependency on the script tag? Currently i am just using IIFE and global scope to access the required objects but it would be really convenient if i could use a module loader since the size of my extension code is growing day by day.

Note – I am aware of this answer here How to import ES6 modules in content script for Chrome Extension but it suggests to do it via web_accessible_resources but that’s not an ideal option cause all scripts injected to page this way have to use message passing to access anything from extension or content script (kind of a workaround).

How to fix UTF-8 Firebase Error for Content Script w/ Chrome Extension Manifest.json?

I made a Chrome Extension and am using Firebase to authenticate users. I downloaded the Firebase.js from https://www.gstatic.com/firebasejs/4.11.0/firebase.js, hoping to add the firebase code to my chrome extension manifest. The Firebase auth is happening in a content script, so it needs to be included in the “js” under “content_scripts”.

Manifest.json Content Script Example

Instead, I’m getting a UTF-8 error when putting firebase.js.

Error:
Could not load file ‘js/lib/firebase.js’ for content script. It isn’t UTF-8 encoded.
Could not load manifest.

I tried using TextEdit on Mac to save the file as UTF-8 – still not luck.

What am I doing wrong?

Web Extension – Content Security Policy Error when Iframe Source Executes Script

I have a chrome/firefox web extension that uses a content script to inject HTML into a webpage when a button is clicked. The HTML that is injected consists of an iFrame nested within several divs.

Here’s the relevant portion of the content script:

var iFrame = document.createElement("iFrame");
iFrame.id = "contentFrame";
iFrame.style.cssText = "width: 100%; height: 100%; border: none;";
iFrame.src = browser.extension.getURL("inject-content/inject.html");

var boxDiv = document.createElement("div");
boxDiv.style.cssText = "left: calc(100% - 390px); position: fixed; top: 0px; width: 390px; z-index: 1;"

var zeroDiv = document.createElement("div");
zeroDiv.style.cssText = "position: fixed; width: 0px; height: 0px; top: 0px; left: 0px; z-index: 2147483647;";

var outerDiv = document.createElement("div");
outerDiv.id = outerDivID;

boxDiv.appendChild(iFrame);
zeroDiv.appendChild(boxDiv);
outerDiv.appendChild(zeroDiv);
document.body.appendChild(outerDiv);

As indicated by the code, the source of the iFrame is a file called “inject.html”. Two important features of inject.html are:

1) A script tag (inside the header) that refers to the file for a javascript library in the same directory.


2) A piece of inline javascript that uses “perfect-scrollbar.js”. Also, for reference, here is the library itself: https://github.com/utatti/perfect-scrollbar


When I directly open the file from my computer (i.e – right-click, open with Chrome), it works fine. However, when I use my extension in Firefox, I get the following error:

Content Security Policy: The page’s settings blocked the loading of a resource at self (“script-src”).

Source:
console.log(“hello world”);

va….

I read through the documentation and it seems like in-line javascript is not allowed by the default content security policy.

Relevant documentation:

The default content security policy for extensions is:

"script-src 'self'; object-src 'self';"

This will be applied to any extension that has not explicitly set its own content security policy using the content_security_policy manifest.json key. It has the following consequences:

You may only load and resources that are local to the extension.

The extension is not allowed to evaluate strings as JavaScript.

Inline JavaScript is not executed.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#Unsafe_inline_script

I would solve the problem of inline javascript by using import statements, but according to Mozilla, those are not supported in Firefox right now: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

According to the documentation, it is possible to allow some inline Javascript by creating a sha-256 hash of your script.

https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/content_security_policy

Allow the extension to execute inline scripts, by supplying the hash of the script in the “script-src” directive.

Allow the inline script: :

"content_security_policy": "script-src 'self' 'sha256-qznLcsROx4GACP2dm0UCKCzCG+HiZ1guq6ZZDob/Tng='; object-src 'self'"

and this

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#Unsafe_inline_script

Alternatively, you can create hashes from your inline scripts. CSP supports sha256, sha384 and sha512.

Content-Security-Policy: script-src 'sha256-B2yPHKaXnvFWtRChIbabYmUBFZdVfKKXHbWtWidDVF8='

When generating the hash, don’t include the

send message to content script from background with delay ? chrome extension

I want to senMessage from background to content script , however the I want the background to send the message after a specific time , here is my code :

background :

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
    if (msg.id == "openUrl") {
        var tabId = sender.tab.id;
        var url = msg.url;
        openUrl(tabId, url);
    } else if (msg.id == "background") {
        setTimeout(function() {
            chrome.tabs.query({
                active : true,
                currentWindow : true
            }, function(tabs) {
                chrome.tabs.sendMessage(tabs[0].id, {}, null);
            });
        }, 5000);
    }
});

I am receiving the bellow error :

**Error in response to tabs.query: TypeError: Cannot read property 'id' of undefined**

I am not sure , why the chrome api can get the selected tab ?

You can download the source file here :

https://drive.google.com/open?id=1_Hkedx8ldAeRWiFKTj4YEv_bXFUt-3CY

Thank you .

How to run callback function from content script after loading page ? chrome extension

I want to run a callback function from content script after tab loading new page .

Here is my code :

content_script.js

chrome.runtime.onMessage.addListener(function(request, sender, callback) {
    if (request.id == "content_script") {
        // open google.com
        chrome.runtime.sendMessage({
            "id" : "openUrl",
            "url" : "https://google.com"
        }, function(response) {
        });
        // call background script
        // go to the claim code page
        chrome.runtime.sendMessage({
            "id" : "background"
        }, function() {
            alert("test");
        });
    }
});

background.js

chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
    if (msg.id == "openUrl") {
        var tabId = sender.tab.id;
        var url = msg.url;
        openUrl(tabId, url);

    } else if (msg.id == "background") {
        setTimeout(function() {
            sendResponse();
        }, 5000);
    }

});

function openUrl(tabId, url) {
    chrome.tabs.update(tabId, {
        url : url,
        active : false
    }, function() {
        console.log("open tab url callback");
    });
};

I also uploaded the source code to google drive, you can download it using the bellow link :
https://drive.google.com/open?id=15zSn40z4zYkvCZ8B-gclzixvy6b0C8Zr

as you can see the alert test don’t show !

However if I remove the code which open new url , then alert (“test”) appear !

I am not sure why ! but it looks like javascript lost the reference to the call back function when I open new url .

How can I solve the problem ? what’s the correct way ?

Thank you

script content doesn’t work after loading new page ? chrome extension content script

I have the bellow code:

1. TabLoadingManager listen to tab loads and execute callbacks after tab finish loading .

  chrome.runtime.onMessage.addListener(function(msg, sender, callback) {
        if (msg.id == "onLoad") {
            // var callback = msg.callback;
            tabLoadingManager.onLoad(callback);
        }

    });


var TabLoadingManager = function() {

    /**
     * Holds the functions which should be executed after the page finish
     * loading
     */
    this.call_back__waiting_functions = [];
    /* this tell us wehter the tab is loading or not */
    this.is_tab_loading = false;

    var parent = this;

    // refreshListener();

    this.onLoad = function(callback) {

        refreshListener();

        // it's very important to execute this function asynchroneously , since
        // we need to wait for the listener above to be called
        setTimeout(
                function() {
                    if (parent.is_tab_loading) {// still loading save the
                        // callback to
                        // run it after finsih loading
                        console
                                .log("TabLoadingManager , parent still loading save callback() ");
                        parent.call_back__waiting_functions.push(callback);
                    } else {
                        console
                                .log("TabLoadingManager , page is not loading callback() ");
                        callback();
                    }

                }, 0);

    }

    var listener;
    var if_called = false;
    function refreshListener() {

        if (if_called) {
            return;

        }
        if_called = true;


        // listen to tab status changes , to check if it's loading or not
        chrome.tabs
                .getSelected(
                        null,
                        function(tab) {

                            // remove previous listener
                            if (listener) {
                                chrome.tabs.onUpdated.removeListener(listener);
                            }

                            listener = function(tabId, info) {

                                if (tabId != tab.id)// listen just to
                                    // the
                                    // selected tab
                                    return;
                                if (info.status === 'complete') {
                                    console
                                            .log("TabLoadingManager , tab completed");

                                    parent.is_tab_loading = false;

                                    var call_back_functions_count = parent.call_back__waiting_functions.length;

                                    for (var i = 0; i < call_back_functions_count; i++) {
                                        var mono_call_back = parent.call_back__waiting_functions[i];
                                        mono_call_back();
                                        console
                                                .log("TabLoadingManager , callback() afetr loading ");

                                    }
                                    // delete all call back functions
                                    parent.call_back__waiting_functions = [];
                                } else if (info.status === 'loading') {


                                    console
                                            .log("TabLoadingManager , tab loading");
                                    parent.is_tab_loading = true;
                                }

                            };

                            chrome.tabs.onUpdated.addListener(listener);
                        });

    }

};

var tabLoadingManager = new TabLoadingManager();

2. script content , called when I click on a button in my extension :

chrome.tabs.update(tabId, {
                url : ,
                active : false
            }, function() {
                console.log("open tab url callback");
            });

            chrome.runtime.sendMessage({
                "id" : "onLoad"
            }, function(){

                  alert("test");

           });

        }

my question
I can see the alert("test") is called when the tab end loading , however for some reasons it doesn't show ! If I don't open new url , then it does code will show the alert test !

any help ! Thank you

Firefox/Chrome Web Extension – Security Error When Trying To Inject IFrame Through Content Script

I have the following really simple code in a content script that runs whenever a button in my “popup.html” file is pressed:

Section of code inside “inject.js”

browser.runtime.onMessage.addListener((message) => {
    console.log("Trying to inject iFrame");
    var iframe = document.createElement("iframe");
    iframe.src = browser.extension.getURL("inject.html");
    document.body.appendChild(iframe);
});

The content of “inject.html” is:








    

Hello. This is a Test.

However, when this code runs I get the following output in the console (Using “example.com: as an example URL):

Trying to inject iFrame
Security Error: Content at http://example.com/ may not load or link to moz-extension://218287b3-46eb-4cf6-a27f-45b9369c0cd9/inject.html.

Here is my “manifest.json”

{
"manifest_version": 2,
"name": "Summarizer",
"version": "1.0",

"description": "Summarizes webpages",

"permissions": [
    "activeTab",
    "tabs",
    "storage",
    "downloads",
    "*://*.smmry.com/*"
],

"icons":
{
    "48": "icons/border-48.png"
},

"browser_action":
{
    "browser_style": true,
    "default_popup": "popup/choose_length_page.html",
    "default_icon":
    {
        "16": "icons/summarizer-icon-16.png",
        "32": "icons/summarizer-icon-32.png"
    }
}

"web_accessible_resources": [
    "inject.html"
]
}

And, lastly, here is the top level file structure of my extension:

Extension_File_Structure

How can I fix this security error?

This is not a duplicate of this: Security error in Firefox WebExtension when trying getUrl image because I provided the full path in my manifest.json