Hitin Hitin - 19 days ago 7
Javascript Question

Calling webpage JavaScript methods from browser extension

I am developing an firefox extension using webExtensions that would help me ease my work with the scenario below.

I have to click around 50-60 buttons on the site that update the task status. On click of this button, the web page is calling the webpage's

updTask(id)
JavaScript function that is then making a web-service call to update the task.

I am not able to do this from my content script using the code below:

manifest.json:

"permissions": [
"activeTab",
"cross-domain-content": ["http://workdomain.com/","http://workdomain.org/","http://www.workdomain.com/","http://www.workdomain.org/"]
]


Content-Script code:

function taskUpdate(request, sender, sendResponse) {
console.log(request.start + 'inside task update');
updateTask(45878);
chrome.runtime.onMessage.removeListener(taskUpdate);
}

function updateTask(id) {
//TODO: code to get all buttons and task id's
updTask(id); // Not working
}


Plugin Script:

document.addEventListener("click", function(e) {
if (e.target.classList.contains("startButton")) {

chrome.tabs.executeScript(null, {
file: "/content_scripts/taskUpdate.js"
});

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {start: "start"});
});
return;
}
else if (e.target.classList.contains("clear")) {
chrome.tabs.reload();
window.close();
return;
}
});


Could someone point me in the right direction, what am I missing here??

Answer

Your content script is in a different context/scope from that of page scripts (scripts that already exist in the webpage). Your content script has higher privileges than are granted to page scripts. Keeping content scripts separate from page scripts is a normal architecture for browser extensions which is done for security reasons.

In order to execute code in the page script context, you have create and insert a <script> element into the page's DOM.

You could do something like:

function updateTask(id) {
    let newScript = document.createElement('script');
    newScript.innerHTML='updTask(' + id + ');';
    document.head.appendChild(newScript);
    //newScript.remove(); //Can be removed, if desired.
}

The added script gets run in the page context because it is now a <script> element in the DOM. The browser recognizes that a <script> element was added and evaluates it (executes the code contained) as soon as the script which inserted it is no longer processing. It does basically the same thing for any other element you add to the DOM. Because it is part of the page, the code inside the gets run in the page script context/scope.

The text for this answer was largely taken from my other answers: this one and this one.

Comments