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.
Related
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);
}
});
In my Chrome extension I want:
Send a certain "pageURL" from the active tab to the content script.
Send "pageURL" from the content script to the background script.
From the background script browse all tabs in the window, choose one of them (different from the tab, from which "pageURL" has been sent) and send "pageURL" to the content script in this different tab.
In the chosen tab open the received "pageURL" from the content script.
The fragments of the source code I used:
main.js:
window.postMessage({"pageURL": "https://www.mytarget.com"}, window.origin);
It worked.
content_script.js:
addEventListener("message", (event) => {
console.log(`Event data is received in content_script.js`);
chrome.runtime.sendMessage(
{"request": "getTabs", "pageURL": event.data.pageURL}
}
});
chrome.runtime.onMessage.addListener( (message, sendResponse) => {
console.log(`Message is received in runtime listener for content_script.js`);
/* Something useful */
}
It worked.
background.js:
chrome.runtime.onMessage.addListener( (message) => {
if (message.request == "getTabs") {
chrome.tabs.query(
{ currentWindow: true }
).then(tabs => {
let targetTab = (() => {/* Something to find target tab */})();
if (targetTab) {
console.log(`Page URL in background.js is about to return`);
chrome.tabs.sendMessage(targetTab.id, { "pageURL": message.pageURL });
}
});
}
});
It worked too, but no message had been registered by either listener in the content script.
What is wrong with my approach?
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.
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.
I have my Chrome extension and website that host button for navigation to my extension.
There are plenty of solutions online, but none of them worked for me as well for some other people.
I've tried an inline installation which is awesome but it will be deprecated next month.
What is the easiest way to find out is my Chrome extension already installed so I can hide the installation button?
Here is some latest thing I have tried, but all the time I'm getting the false value:
Background.js
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request) {
if (request.message) {
if (request.message == "version") {
sendResponse({version: 1.0});
}
}
}
return true;
});
Here is my website component:
window.chrome.runtime.sendMessage('kgpphmdamkaepmgiepihmihoohflolkf', { message: 'version' },
function (reply) {
if (reply) {
if (reply.version) {
if (reply.version >= requiredVersion) {
console.log('true');
}
}
}
else {
console.log('false');
}
});
manifest.json :
"externally_connectable": {
"matches": ["*://localhos:8080/*", "*://search.call.com/*"]
}
How about creating an element on your page and hiding it from your extension ?
In your website:
<div id="prompt-insall-YOUR_CHROME_EXTENSION_ID">
<button>Install</button>
</div>
In your extension:
document.getElementById(`prompt-install-${chrome.runtime.id}`).style.display = 'none';