Background code runs on any popup click - javascript

I'm trying to get login code in background page to run only once on browser start. But it seems global code in bgpage runs every time on popup clicked. Also it runs in different scope. Is it possible to solve this?
// background.js
var someCustomType = new SomeCustomType();
function SomeCustomType() {
this.firstProperty;
}
function thisShouldBeCalledOnce() {
someCustomType.firstProperty = 'defined';
alert('someCustomType.firstProperty=' + someCustomType.firstProperty);
console.log('thisShouldBeCalledOnce');
}
if (true) {
// Alwase 'undefined'
alert('someCustomType.firstProperty=' + someCustomType.firstProperty);
thisShouldBeCalledOnce();
}

Simple code example:
manifest.json
{
"name": "My First Extension",
"version": "1.0",
"manifest_version": 2,
"description": "The first extension that I made.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"]
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*"
]
}
popup.html: just some dummy code:
<html>
<head>
</head>
<body>
<div>
<p> sometext</p>
<button type="button">Click Me</button>
</div>
</body>
</html>
background.js:
var someCustomType = new SomeCustomType();
function SomeCustomType() {
this.firstProperty;
}
function thisShouldBeCalledOnce() {
someCustomType.firstProperty = 'defined';
alert('someCustomType.firstProperty=' + someCustomType.firstProperty);
console.log('thisShouldBeCalledOnce');
}
thisShouldBeCalledOnce();
In this case, alert was fired once, when you load your extension, when you open popup no alert will be shown. Regards.

Related

Chrome extension message listener fires twice

I'm working on Chrome extensions. I try to learn messaging between content and background. I develop simple project for this. But I have issue.
Basic idea is
User click button on extension popup
A function (bot.js) find image from content of tab then extension (background.js) will download it.
The issue is port.onMessage.addListener() in background.js fired twice.
When background.js sends message to contentscript.js there are two same messages in console or when I try to download in background.js (the code line "Do Something") it download the file twice.
How can I solve this problem?
popup.html
<!doctype html>
<html>
<head>
<title>Test Plugin</title>
<script src="background.js"></script>
<script src="popup.js"></script>
</head>
<body>
<h1>Test Plugin</h1>
<button id="btnStart">Button</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('btnStart');
checkPageButton.addEventListener('click', function() {
GetImages("Some URL");
}, false);
}, false);
var tab_title = '';
function GetImages(pageURL){
// Tab match for pageURL and return index
chrome.tabs.query({}, function(tabs) {
var tab=null;
for(var i=0;i<tabs.length;i++){
if(tabs[i].url==undefined || tabs[i].url=="" || tabs[i]==null){}
else{
if(tabs[i].url.includes(pageURL)){
tab=tabs[i];
break;
}
}
}
if(tab!=null){
chrome.tabs.executeScript(tab.id, {
file: "bot.js"
}, function(results){
console.log(results);
});
}
});
}
bot.js
var thumbImagesCount = document.querySelectorAll('.classifiedDetailThumbList .thmbImg').length;
var megaImageURL=document.querySelectorAll('.mega-photo-img img')[0].src;
console.log(megaImageURL + " from bot.js");
port.postMessage({key:"download", text: megaImageURL});
background.js
chrome.runtime.onConnect.addListener(function (port) {
console.assert(port.name == "content-script");
port.onMessage.addListener(function(message) {
console.log(message);
if(message.key=="download"){
// Do Something
// Event fires twice
port.postMessage({key:"download", text: "OK"});
}
})
});
contentscript.js
console.log("content script loaded!");
var port = chrome.runtime.connect({name: "content-script"});
port.onMessage.addListener(function(message){
console.log(message);
});
manifest.json
{
"manifest_version": 2,
"name": "Test Extension",
"description": "This extension will download images from gallery",
"version": "1.0",
"icons": {
"16": "bot16.png",
"48": "bot48.png",
"128": "bot128.png" },
"browser_action": {
"default_icon": "bot48.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"downloads",
"http://*/",
"https://*/"
],
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["contentscript.js"]
}
]
}
The background script declared in manifest.json already has its own page, a hidden background page where it runs, so you should not load it in the popup as it makes no sense in case there are listeners for API events, the background page is already listening for them. In this case the copy also creates the second listener while the popup is open.
Solution: don't load background.js in popup.
See also Accessing console and devtools of extension's background.js.

How can I run a extension with Google Chrome for Youtube?

Hello there,
I want to remove thumbnail images that appear on YouTube. I am using the following code for this.
while (true) {
$("ytd-thumbnail").remove()
}
When I paste this code into console, all thumbnail images are removed. I want it to work on the backplane by adding an extension. The code for the plug-in I'm preparing is below.
manifest.json;
{
"manifest_version": 2,
"name": "test",
"description": "test extension",
"version": "1.0",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>TEST</title>
<script src="popup.js"></script>
</head>
<body>
<h1>TEST</h1>
<button id="checkPage">Check !</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
chrome.tabs.getSelected(null, function(tab) {
d = document;
while (true) {
$("ytd-thumbnail").remove()
}
});
}, false);
}, false);
When I press the checkPage button nothing happens. But this code works when I add a console. What is the problem? Thanks in advance.
There are several issues with the extension :
You are trying to use $ i.e. jquery which is not available in your
popup.js
You are trying to access "ytd-thumbnail" dom elements which belong
to youtube page and not your popup.html. So, even if you replace $
with document.querySelector , you won't find those elements.
I created a working version that looks something like this. I have not included popup.html which is same as yours.
manifest.json
{
"manifest_version": 2,
"name": "Hello Extensions",
"description" : "Base Level Extension",
"version": "1.0",
"browser_action": {
"default_icon": "hello_extensions.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["background.js"],
"all_frames" : true
}
],
"permissions": [
"activeTab",
"tabs"
]
}
2.popup.js
document.addEventListener('DOMContentLoaded', function()
{
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function()
{
chrome.tabs.query({"active":true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, "removeThumbnails", function (response) {
});
});
});
});
When the button is clicked, retrieve the active tab and send it a "removeThumbnails" message.
3.background.js
chrome.runtime.onMessage.addListener(function(message, callback) {
if (message == "removeThumbnails")
{
var elements = document.querySelectorAll("ytd-thumbnail");
elements.forEach(a => a.parentNode.removeChild(a));
}
});
background.js is content script and runs in youtube page. It can now access all the dom elements in youtube page. When we receive a "removeThumbnails" message , get all ytd-thumbnail elements and remove them from page.

Injecting javascript to each tab

I am working on a chrome browser extension which will inject a fixed js script in active tab.
As a beginner in javascript don't know how to do it. I tried to follow this tutorial. Copy-pasting the source code didn't worked in my browser.
However the javascript code I wrote for my extension - if I add that script in a html page and run that on browser - it works fine. That means no error in the script. But when I add that script in a file to be injected alike the tutorial - nothing happens.
There is no console output about "something error". Maybe I'm missing something or this should be done in another way(s). Help needed.
Here are the files for the tutorial link provided above.
manifest.json
{
"name": "Injecta",
"version": "0.0.1",
"manifest_version": 2,
"description": "Injecting stuff",
"homepage_url": "http://danharper.me",
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"browser_action": {
"default_title": "Inject!"
},
"permissions": [
"https://*/*",
"http://*/*",
"tabs"
]
}
inject.js
(function(){
var div = document.createElement('div');
div.style.position = 'fixed';
div.style.top = 0;
div.style.right = 0;
div.textContent = 'Injected!';
document.body.appendChild(div);
alert('inserted self... giggity');
})();
background.js
chrome.browserAction.onClicked.addListener(function(tab){
chrome.tabs.executeScript(tab.ib,{
file: 'inject.js'
});
});
I loaded the files in chrome as unpacked extension. Then in a new tab, I opened www.google.com. As per the code, there should be the word "Injected!", but there was nothing like this.
What I am trying to do is if the loaded page has javascript like this:
<script>
var a=1;
</script>
And my inject.js
var b=2;
Then after loading the page's script should be:
<script>
var a=1;
var b=2;
</script>
**For this I wrote the following files **
My manifest.json
{
"name": "Injector",
"version": "1.0",
"description":"Inject some code",
"permissions":[
"http://*/*",
"https://*/*",
"tabs"
],
"background":{
"scripts":["background.js"]
},
"browser_action":{
"default_title": "Injector",
"default_icon": "icon.png",
"default_popup": "background.html"
},
"manifest_version": 2
}
My background.html
<html>
<head>
</head>
<body> Injector
</body>
</html>
My background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript(tab.id, {
file: 'inject.js'
});
});
My inject.js
function test(){
var b=2;
console.log(b);
}
test();

Chrome Extension Content Script Never Run

Hello, I am writing a simple chrome extension which will be used to:
1. open new webpage
2. fill timesheet form based on pasted string array
3. submit timesheet (just clicking "ok" button in the form)
4. open new webpage
For this to work my extension needs to contain:
1. popup.html Browser Action popup, with input textfield for string array, and submit button.
2. timesheet.js - javascript file to add logic to popup.html
3. background.js - background page to take care of filling form, after clicking submit button
4. content_script.js - to access newly opened webpage DOM, to fill the form.
For now, I made a simplified version, which is supposed to:
1. open www.google.com in new tab
2. wait few seconds (optionally, wait or page to finish loading)
3. change background color
Everything seems to be woring fine, except for content_script.js listener doesn't react to message send by background.js
Here is the code:
manifest.json:
{
"manifest_version": 2,
"name": "Timesheet Filler",
"description": "Description.",
"version": "1.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["http://www.google.com/*"],
"js": ["content_script.js"]
}],
"browser_action": {
"default_title": "Timesheet Filler",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"activeTab",
"http://www.google.com/*"
]
}
popup.html:
<!DOCTYPE html>
<html>
<body>
<button id="btn" >Click Me!</button>
<script src="timesheet.js"></script>
</body>
</html>
timesheet.js:
document.addEventListener('DOMContentLoaded', function(){
init();
});
function init(){
var btn = document.getElementById('btn');
btn.onclick = function() { onBtnClick(); }
}
function onBtnClick(){
chrome.runtime.sendMessage({action:"btnClick"}, btnClickCallback);
}
function btnClickCallback(any){
alert(any);
}
background.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if(message.action == "btnClick"){
chrome.tabs.create({url: "http://www.google.com", active:true});
setTimeout(function(){ delayed(); }, 3000);
}
});
function delayed(){
chrome.tabs.query({active:true}, queryCallback);
}
function queryCallback(arr){
var tabId = arr[0].id;
console.log("message shown 3 second after clicking button") // THIS IS WORKING
chrome.tabs.sendMessage(tabId, {action:"doSomething"}); // CONTENT SCRIPT DOESNT REACT TO THIS
}
function contentScriptCallback(any){
alert(any);
}
content_script.js:
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if( message.action == "doSomething"){
document.body.style.backgroundColor='#000000';
alert("do something");
}
});
Download all files in one ZIP here
How to make content_script.js react to to message and change webpage bg color?
SOLUTION: (thanks to #wOxxOm)
Content script wasn't called since matches in content_scripts section as well as permisions of manifest.json was defined wrong.
Easiest fix was to change URL range to: <all_urls>
(for precise urls matches see this link)
Fixed manifest.json:
{
"manifest_version": 2,
"name": "Timesheet Filler",
"description": "Description.",
"version": "1.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content_script.js"]
}],
"browser_action": {
"default_title": "Timesheet Filler",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"activeTab",
"<all_urls>"
]
}

How to show the content of an url on an extension's popup?

I'm trying to make a Chrome extension that gets the current page's URL and uses it to create and show a QR code that links to it with the below Google API.
This is my popup.js
chrome.tabs.getSelected(null,function(tab) {
var tablink = tab.url;
});
document.write('https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=' + tablink);
and this is my manifest.json
{
"name": "Qrit",
"version": "1.0",
"manifest_version": 2,
"description": "Instantly creates a QR Code that links to the current page.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs"
]
}
The problem is that the popup is simply blank.
I know almost nothing about Javascript, nor Json.
As Tom said, with manifest version 2 you cant have inline scripts. Also, chrome.tabs.getSelected is decapitated and you should use chrome.tabs.query.
Here's something to get you started....
manifest.json
{
"name": "Qrit",
"version": "1.0",
"manifest_version": 2,
"description": "Instantly creates a QR Code that links to the current page.",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs"
]
}
popup.html
<!DOCTYPE html>
<html>
<head>
<script src='popup.js'></script>
</head>
<body>
<div id='message'>Getting Image....</div>
</body>
</html>
popup.js
function onImageLoad() {
var message = document.querySelector('#message');
message.parentNode.removeChild(message);
}
function onImageError(e) {
var message = document.querySelector('#message');
message.innerText = 'Error getting image';
e.srcElement.parentNode.removeChild(e.srcElement);
}
function onWindowLoad() {
chrome.tabs.query({
'active': true,
'windowId': chrome.windows.WINDOW_ID_CURRENT
}, function(tab) {
var image = document.createElement('IMG');
image.src = 'https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=' + tab[0].url;
document.body.appendChild(image);
image.onload = onImageLoad;
image.onerror = onImageError;
});
}
window.onload = onWindowLoad;
First you write "manifest_version": 2,it doesn't allow inline script.Second,your popup code should write like this
chrome.tabs.getSelected(null,function(tab) {
var tablink = tab.url;
document.write('https://chart.googleapis.com/chart?chs=100x100&cht=qr&chl=' + tablink);
});

Categories