How to pass Data between files Chrome Extension? - javascript

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);
}
});

Related

Why sendMessage from the background script in a Chrome extension doesn't reach the needed tab?

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?

Send message from background.js to popup

I want to implement FCM in my chrome extension.
At the mement after a lot of research I've found that the quick and best way to implement fcm is using the old API chrome.gcm. At the moment this solution seems working fine and when the extension is loaded I'm able to get an fcm token.
Now what I want to do is to pass the token to the popup that is powered by vue.js I'm trying with this code but without success.
background.js
const openPopup = () => {
chrome.windows.create({
type: 'popup',
height: 520,
width: 440,
url: chrome.runtime.getURL('popup.html')
})
}
const registeredToken = (registrationId) => {
console.log('FCM Token')
console.log(registrationId)
openPopup()
chrome.runtime.sendMessage({fcmToken: registrationId})
if( chrome.runtime.lastError ) {
console.log('error')
}
}
const notificationId = (id) => {
if(chrome.runtime.lastError) {
console.log(chrome.runtime.lastError)
}
console.log(id)
}
chrome.runtime.onInstalled.addListener( () => {
console.log('FCM extension installed')
})
chrome.action.onClicked.addListener( (tab) => {
console.log(tab)
openPopup()
})
chrome.gcm.register(['my_sender_id'], registeredToken)
chrome.gcm.onMessage.addListener( (message) => {
console.log(message, message.data["gcm.notification.title"])
chrome.notifications.create('', {
type: 'basic',
iconUrl: 'letter.png',
title: message.data["gcm.notification.title"],
message: message.data["gcm.notification.body"],
buttons: [
{ title: 'Dismiss' },
{ title: 'Reply' }
]
}, notificationId)
})
chrome.notifications.onButtonClicked.addListener( (notificationId, buttonIndex) => {
console.log('button clicked')
console.log(notificationId, buttonIndex)
})
popup.vue file
<template>
<div class="main_app">
<h1>Hello {{msg}}</h1>
</div>
</template>
<script>
export default {
name: 'popupView',
data () {
return {
msg: ''
}
},
mounted() {
chrome.runtime.onMessage( (message, sender, sendResponse) => {
console.log(message, sender, sendResponse)
this.msg = message
})
},
methods: {
}
}
</script>
What I've noticed is that the chrome.runtime.sendMessage({fcmToken: registrationId}) will not work and on the popup side I'm unable to send or get messages from background
How I can pass messages between the vue.js powered popup and the background.js file of the extension?
Is better to use firebase client library to get push messages or the gcm is fine for this scope?
You can use the chrome.tabs.query and chrome.tabs.sendMessage APIs to send a message from the background to the Popup.
chrome.tabs.query({}, function (tabs) {
tabs.forEach((tab) => {
chrome.tabs.sendMessage(
tab.id,
youtPayload,
function (response) {
// do something here if you want
}
);
});
});
That's it!
I spend lots of hours to finding solution to the same proble and still not find any.
My current understanding is, that we are trying to do and use method for the purpose, they wasnt ment to be used for.
Key information leading to this:
popup.js can share the same. Js file and objects with background.js
documentation primarely is talking about passing data between web page (content.js) and others (popup.js or background.js)

How to get current tab URL using Manifest v3?

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

chrome extension - issue with propertie "active" of chrome.tabs.create

I am creating a new tab and and injecting some code in it straight after.
But the problem is that the code to be injected is not injected properly when using the property active:true(which I need to use) on tabs.create.
Here is the code in popup.js:
chrome.tabs.create({url: "http://localhost:3000/", index: newTabId, active: false}, (newTab) => {
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
// check status so that it sends only one message, and not one for each status change
if(changeInfo.status === "loading") {
if (tab.id === newTab.id) {
chrome.tabs.sendMessage(newTab.id, {message: "watch_video", videoData: selectedVideoData},
function (resp) {
console.log("Resp",resp);
return true;
}
);
}
}
});
})
Here is the problematic line: chrome.tabs.create({url: "http://localhost:3000/", index: newTabId, active: false}. When active is false, the code is injected, but when it is true, nothing seems to happen.
inject.js:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.message === "watch_video") {
console.log("inject soon")
injectScript(request.videoData);
sendResponse("watch_video script is to be injected in " + window.location.href)
}
});
function injectScript(videoData) {
console.log("injected")
$(document).ready(function() {
document.test = "ABCDE"
const checkState = setInterval(() => {
$(".bkg").css({ "background-color": "#ffffff"})
}, 100)
})
}
Here I tried something with setInterval(), it does not work when active is true.
However it does work with a timeout. But does not not work without any timeout or interval when active is set to true.
I could use just use a timeout, but it is not really clean, I would prefer to understand why it behaves like it does. I am using react btw.
Here is what it is said about the active property:
Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see windows.update). Defaults to true.
Source: https://developer.chrome.com/extensions/tabs#method-create

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.

Categories

Resources