I'm learning chrome extension development and I'm trying to get the required tabs using chrome.tabs.query. Inside that I'm executing a script and passing a callback function, but when code reaches the callback it throws an exception, see below:
chrome.tabs.query({active: true , currentWindow: true,lastFocusedWindow: true}, function(tabs)
{
console.log(tabs);
var tab = tabs[0];
console.log(tab);
var check_url = tab.url
console.log(check_url);
var check_importers = check_url.split("/");
console.log(check_importers);
try {
console.log("line 111");
if(check_importers[3].includes("tbm=lcl"))
{
console.log("line 122")
chrome.tabs.executeScript(tab.id, {
code: console.log("Hello world")
},passDetails);
}
else
{
console.log("line 199");
console.log("Search Importers of Spices");
}
}//try end
catch (err)
{
console.log("URL not found")
}
}
This is what I tried by following documentation and blogs I found.
Related
I'm working on on tool that gives desktop notifications when page content has specific change. When I launch extension I have error in console that says " Cannot read properties of null (reading 'innerHTML') at snowAlerts (contentScript.js:26:69)".
When I paste same code in chrome snippets code works fine. Also what is worth to mention is that when I paste document.getElementById("3e731e79875e4d5089360d830cbb3517").innerHTML
in console I receive same error, but when I click on the selector and copy this "3e731e79875e4d5089360d830cbb3517" from elements and replace it in document.getElementById("3e731e79875e4d5089360d830cbb3517").innerHTML I receive correct output. I have no idea what may cause this problem, here is code for notification:
function snowAlerts() {
if (document.getElementById("3e731e79875e4d5089360d830cbb3517").innerHTML != '0') {
console.log("Do something");
function showNotification() {
if (Notification.permission !== 'granted') {
Notification.requestPermission();
} else {
const options = {
body: 'New Alert on SNOW',
dir: 'ltr',
};
const notification = new Notification('SNOW INCIDENT', options);
notification.onclick = function () {
window.open('MY SITE');
};
}
}
showNotification();
}
else {
console.log("Do nothing")
}
}
setInterval(snowAlerts, 5000);
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);
}
});
How do I get the URL of the current tab in the background service worker in MV3?
Here's what I have:
let currentURL;
chrome.action.onClicked.addListener(handleBrowserActionClicked);
chrome.commands.onCommand.addListener(function(command) {
console.log("Command:", command);
handleBrowserActionClicked();
});
function handleBrowserActionClicked() {
togglePlugin();
}
function togglePlugin() {
console.log("toggle plugin");
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, { greeting: "activateFeedback" });
});
}
// Fires when the active tab in a window changes.
chrome.tabs.onActivated.addListener(function () {
console.log("TAB CHANGED")
//firstTimeRunning = true
//feedbackActivated = false
currentURL = getTab()
.then(console.log("Current URL: " + currentURL))
})
// Fired when a tab is updated.
chrome.tabs.onUpdated.addListener(function () {
console.log("TAB UPDATED")
currentURL = getTab() // line 32
.then(console.log("Current URL: " + currentURL))
})
async function getTab() {
let queryOptions = { active: true, currentWindow: true };
let [tab] = await chrome.tabs.query(chrome.tabs[0].url); // line 38
return tab;
}
Right now the service worker is logging "Current URL: [object Promise]" instead of, for example, "https://www.google.com"
It is also giving an error in the console (see comments above for line numbers)
background.js:38 Uncaught (in promise) TypeError: Cannot read property 'url' of undefined
at getTab (background.js:38)
at background.js:32
I think it may be something to do with my limited knowledge of promises!
Please help.
Thank you in advance.
You function getTab seems not right, you are currently trying to query on the url. Not on the query options. The following function should work.
async function getTab() {
let queryOptions = { active: true, currentWindow: true };
let tabs = await chrome.tabs.query(queryOptions);
return tabs[0].url;
}
Also make sure you have the tabs permission.
In the listener you also don't use the correct async/promise method two examples using Promise.then and await.
Promise.then:
chrome.tabs.onUpdated.addListener(function () {
console.log("TAB UPDATED")
getTab().then(url => {
console.log(url);
})
})
await:
chrome.tabs.onUpdated.addListener(async function () {
console.log("TAB UPDATED")
let url = await getTab()
console.log(url)
})
For the "Error: Tabs cannot be queried right now (user may be dragging a tab)." error you can look at this answer, which suggest a small delay before querying the tab url.
const tab = (await chrome.tabs.query({ active: true }))[0]
Simply use "activeTab" permission in manifest.json
Add activeTab in your manifest.json.
"permissions": [
"activeTab",
],
And In Background.js
chrome.action.onClicked.addListener((tab) => {
console.log(tab.url);
});
I'm sure It will help you to get the current tab URL.
useful links - ActiveTab
Seems like i can send message, but can't receive response. Everything works fine when i use sendMessage from another context (popup, content script, etc).
Is it bug?
event-page.js
(function (chrome, undefined) {
'use strict';
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
console.info('onMessage: ' + message.method);
switch (message.method) {
case 'withResponseAsync':
setTimeout(function () {
sendResponse({some: 'response'});
}, 1000);
return true;
break;
case 'withResponse':
sendResponse({some: 'response'});
break;
}
});
var showResponse = function (response) {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
}
console.info(response);
};
// ok. onMessage: noResponse
chrome.runtime.sendMessage({method: 'noResponse'});
// fail. Could not establish connection. Receiving end does not exist.
chrome.runtime.sendMessage({method: 'withResponse'}, showResponse);
// fail. Could not establish connection. Receiving end does not exist.
chrome.runtime.sendMessage({method: 'withResponseAsync'}, showResponse);
})(chrome);
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.