Chrome inject script inconsistency issue - javascript

Below function I did was to redirect user to a login page, and then inject a js to login the user. The code below worked well but not consistent, I hardly can debug it because the flow contain refresh of the whole page.
in my setLogin.js I try to debug with alert() wrap within $(function(){}); I found that sometime it run sometime it doesn't. So I suspect the script sometime got injected sometime not, but why is it like so?
chrome.tabs.update(null, {
url: 'https://example.com/index.php?act=Login'
}, function () {
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
chrome.tabs.executeScript(null, {
file: "jquery.js"
}, function () {
chrome.tabs.executeScript(null, {
code: 'var passedData = {username:"' + username + '",pass:"' + pass+'"}'
}, function () {
chrome.tabs.executeScript(null, {
file: "setLogin.js"
}, function () {
window.close(); //close my popup
});
});
});
}
});
});

By default scripts are injected at document_idle which doesn't work consistently with jQuery, probably because it's big or uses some asynchronous initialization.
Solution: explicitly specify that the injected scripts should run immediately.
chrome.tabs.executeScript({file: "jquery.js", runAt: "document_start"}, function(result) {
});

Related

How to pass Data between files Chrome Extension?

Currently, I mainly work with two files, background.js and popup.js.
In background.js
I have a bunch of functions that let me store data in an IndexedDB. And in popup.js I call the functions like this:
chrome.runtime.sendMessage({
message: "insert",
payload: [
{
url: form_data.get("message"),
text: form_data.get("message"),
},
],
});
Depending on the message, a certain function is called. When the function has successfully executed I do this from the background.js file:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === "insert") {
let insert_request = insert_records(request.payload);
insert_request.then((res) => {
chrome.runtime.sendMessage({
message: "insert_success",
payload: res,
});
});
});
This is my problem:
How do I send data from background.js to popup.js. What I want is to get the URL of the current page, and then send it to popup.js and store it in the Database.
I have already looked at already existing posts, but none of them really helped.
Can someone please help me out.
Update
Currently I use this is in background.js to get the current URL. It works just fine. But how can I pass the tab.url to my popup.js file?:
let activeTabId, lastUrl, lastTitle;
function getTabInfo(tabId) {
chrome.tabs.get(tabId, function (tab) {
if (lastUrl != tab.url || lastTitle != tab.title)
console.log((lastUrl = tab.url), (lastTitle = tab.title));
});
}
chrome.tabs.onActivated.addListener(function (activeInfo) {
getTabInfo((activeTabId = activeInfo.tabId));
});
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (activeTabId == tabId) {
getTabInfo(tabId);
}
});

Chrome extension content script not being injected sometimes

I have a chrome extension for fillling forms on certain websites. This all works well, however sporadically the content script for filling the form doesn't get injected anymore, then I have to reinstall the extension to remediate the problem. This is the code I use for injecting the content script:
chrome.tabs.create({ url: url, active: true }, function (tab) { //create tab
chrome.tabs.onUpdated.addListener(function listener(tabId, info) {
if (info.status === 'complete' && tabId === tab.id) {
chrome.tabs.onUpdated.removeListener(listener);
chrome.tabs.executeScript(tab.id, { file: 'library.js', allFrames: true, runAt: "document_end" }, function () {
chrome.tabs.executeScript(tab.id, { file: 'fillForm.js', allFrames: true, runAt: "document_end" }, function () {
//inject content script
chrome.tabs.sendMessage(tab.id, { formData }); //send message to content script
});
});
}
});
});
I suppose it's some kind of a timing issue or something that changed in the Chrome api? Because the problem only occured recently.

Chrome extension run js in new tab

My popup.js:
chrome.tabs.create({ url: "https://mywebsite.com" })
How i can run this js in the new created tab?
chrome.tabs.executeScript(null, {
code: "document.getElementById('test').value='test';"
});
When you create a tab, you can pass a callback function that receives the newly created tab for manipulation. This tab has an id which can be used to specify which tab the script should be executed in. Unless you specify a tab ID, the script will be executed in the current tab instead of the newly created one.
Therefore what you want is roughly
chrome.tabs.create({ url: "https://mywebsite.com" }, tab => {
chrome.tabs.executeScript(tab.id, {
code: "document.getElementById('test').value='test';"
});
});
Or more elegantly
function createTab(options) {
return new Promise(resolve => {
chrome.tabs.create(options, resolve);
});
}
async function main() {
const tab = await createTab({ url: "https://mywebsite.com" });
chrome.tabs.executeScript(tab.id, {
code: "document.getElementById('test').value='test';"
});
}
main();
See the Chrome Tab API documentation for details.

FireFox AddOn SDK close current tab

I am porting a Chrome Extension for FireFox using the Add-On SDK. I am using require("sdk/page-mod") to run a content script at the start of the document.
In the code, I need to close the current tab if some condition is met. In Chrome, I can send a message to the background.js file to have it close the current tab, but I am not able to figure this out for Firefox.
window.close() is very unreliable and I need to figure out a way to call a function in the main.js file from my content script.
Appreciate your help.
EDIT:
Below is my Chrome code, I need to port the same to FF AddOn SDK (FF Extension).
//in the content.js file
function closeCurrTab() {
chrome.runtime.sendMessage({action: "closeTab"}, function() {});
}
//below in the background.js file
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
switch (request.action) {
case 'closeTab':
try {
chrome.tabs.getSelected(function(tab) {removeTab(tab.id);});
} catch (e) {
alert(e);
}
break;
}
}
);
function removeTab(tabId) {
try {
chrome.tabs.remove(tabId, function() {});
} catch (e) {
alert(e);
}
}
in content script:
self.port.emit("close-tab");
in main.js
PageMod({
include: "*",
contentScriptFile: "./content-script.js",
onAttach: function(worker) {
worker.port.on("close-tab", function() {
tabs.activeTab.close();
});
}
});
The following might help if you are developing an extension of firefox:
function onError(error) {
console.log(`Error: ${error}`);
}
function onRemoved() {
console.log(`Removed`);
}
function closeTabs(tabIds) {
removing = browser.tabs.remove(tabIds);
removing.then(onRemoved, onError);
}
var querying = browser.tabs.query({currentWindow: true});
querying.than(closeTabs, onError);
This will close the current tab:
require("sdk/tabs").activeTab.close();
Here's an expanded example that implements a toolbar button that closes the current tab ( silly example, I know ):
var ActionButton = require("sdk/ui/button/action").ActionButton;
var button = ActionButton({
id: "my-button-id",
label: "Close this tab",
icon: {
"16": "chrome://mozapps/skin/extensions/extensionGeneric.png"
},
onClick: function(state) {
require('sdk/tabs').activeTab.close();
}
});
For more info, please see the documentation for the tabs module.

browserAction.setBadgeText isn't being executed when used in tabs.executeScript callback

I'm working on my first Chrome extension. I have a default popup popup.html which loads popup.js.
I used serg's answer to Chrome's tabs.executeScript - passing parameters and using libraries? as inspiration for the popup->page interaction.
The problem is that the following click handler in popup.js works:
function click(e) {
chrome.browserAction.setBadgeText ( { text: "loading" } );
chrome.tabs.executeScript(null,
{code:"globalVarName = {'scriptOptions': {...}};" },
chrome.tabs.executeScript(null, {file: "js/script.js"},
chrome.browserAction.setBadgeText ( { text: "done" } ))
);
window.close();
}
But the following does not:
function click(e) {
chrome.browserAction.setBadgeText ( { text: "loading" } );
chrome.tabs.executeScript(null,
{code:"globalVarName = {'scriptOptions': {...}};" },
chrome.tabs.executeScript(null, {file: "js/script.js"},
function(){chrome.browserAction.setBadgeText ( { text: "done" } );})
);
window.close();
}
I want to be able to do more than one thing on completion.
Edit:
I've realised that the first case immediately executes chrome.browserAction.setBadgeText(), not when the script has finished executing. So that case can be ignored. I've reworded the question title to reflect this.
What I'm looking for is why the second case's callback doesn't execute at all.
I'm pretty sure the culprit here is window.close() which closes the popup. The same popup in which this code is executing (except script.js, that's executing on the actual page).
Therefore, the callback was never being executed. I'm only talking of course about case 2 here (see my edit to the question).
My latest fully working code for any future visitors:
var tabId = null;
function click(e) {
chrome.browserAction.setBadgeText ( { text: "..." } );
chrome.tabs.executeScript(tabId,
{code:"globalVarName= {...}" },
function(){
chrome.tabs.executeScript(tabId, {file: "js/script.js"},
function(){chrome.browserAction.setBadgeText ( { text: "done" } );
setTimeout(function() {
chrome.browserAction.setBadgeText ( { text: "" } );
}, 1000);
}
);
}
);
}
Also note that the path to the script (script.js here) is relative to the extension source root, i.e. where the manifest.json is.

Categories

Resources