I have been working on a chrome extension for some time now.
I have a background JS file which is not persistent. While testing the extension locally the background.js file was properly printing results to the console and firing when necessary.
However, once uploaded, it seems that background.js no longer executes when it is supposed to and does not print anything to the console.
Here is the background.js code:
chrome.runtime.onInstalled.addListener(function() {
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){ // listener for when first loading the page
var url = tab.url;
console.log(url);
if(url != undefined && changeInfo.status == "complete"){ // if the page is done loading, this is done bc .onUpdated has issues with multiple misfires
console.log(url);
var sites = [];
chrome.storage.sync.get({list:[]}, function(data){ // retrieve list of blackListed sites
sites = data.list;
console.log(sites);
for(var i = 0; i < sites.length; i++){
if(tab.url.includes(sites[i])){
chrome.storage.sync.get(['time'], function(data){
if(data.time != null){ // if we are in an active session
chrome.storage.sync.get(['userCausedHours'], function(data2) {
console.log(data2.userCausedHours)
chrome.storage.sync.set({'userCausedHours': data2.userCausedHours + 1}, function() {
console.log('hours = ' + data2.userCausedHours + 1) ;
})
});
}
})
}
}
})
}
});
chrome.tabs.onActivated.addListener(function(activeInfo) { // listener for when flipping back and forth between pages
var sites = [];
chrome.storage.sync.get({list:[]}, function(data){ // retrieve list of blackListed sites
sites = data.list;
console.log(sites);
// how to fetch tab url using activeInfo.tabid
chrome.tabs.get(activeInfo.tabId, function(tab){
console.log(tab.url);
for(var i = 0; i < sites.length; i++){
if(tab.url.includes(sites[i])){
chrome.storage.sync.get(['time'], function(data){
if(data.time != null){ // if we are in an active session
chrome.storage.sync.get(['userCausedHours'], function(data2) {
console.log(data2.userCausedHours)
chrome.storage.sync.set({'userCausedHours': data2.userCausedHours + 1}, function() {
console.log('hours = ' + data2.userCausedHours + 1) ;
})
});
}
})
}
}
});
})
});
});
and here is my manifest:
{
"name": "Serenity",
"version": "1.01",
"description": "Productivity made fun",
"permissions" :["tabs","storage"],
"background" :{
"scripts": ["background.js"],
"persistent": false
},
"options_page": "options.html",
"browser_action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images2/favicon-16x16.png",
"32": "images2/favicon-32x32.png",
"128": "images2/favicon-128.png"
}
},
"icons": {
"16": "images2/favicon-16x16.png",
"32": "images2/favicon-32x32.png",
"128": "images2/favicon-128.png"
},
"manifest_version": 2
}
As stated in the comments, the issue was the fact that I left the .onInstalled around the two listeners for tabs. Moving these listeners into a global context fixed the problem, the .onInstalled isn't necessary for my extension
Related
I can find plenty of questions for sending a message from Bbackground to content scripts or from popup to background scripts, but I can't find any on how to send a message from options.js (triggered from my options page) to background.js for my Chrome extension
manifest.js
{
...
"manifest_version": 3,
"permissions": [
"alarms",
"contextMenus",
"notifications",
"storage"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
},
"options_page": "options.html",
"icons": {
"48": "/assets/icons/icon-48.png",
"128": "/assets/icons/icon-128.png"
}
}
Code in options.js
// Save options
document.querySelector('#save').addEventListener('click', ()=> {
// Check for selected regions
let selectedRegions = [];
regionChecks.forEach(elm => {
if (elm.checked)
selectedRegions.push(elm.id.replace('region-', ''))
});
// Save selections
chrome.storage.sync.set({ 'regions': selectedRegions });
// Check for refresh period
let refreshPeriod = document.querySelector('#refresh');
if (refreshPeriod) {
refreshPeriod = parseInt(refreshPeriod.value);
if (refreshPeriod === NaN) {
refreshPeriod = 5;
} else if(refreshPeriod < 2) {
refreshPeriod = 2;
} else if (refreshPeriod > 120) {
refreshPeriod = 120;
}
// Save period
chrome.storage.sync.set({ 'refresh': refreshPeriod });
}
// Loop through features and remove if region gone
chrome.storage.local.get(['features'], featuresData => {
let featureCount = 0;
if (featuresData.features) {
featureSet = featuresData.features;
Object.keys(featureSet).forEach(key => {
if (!selectedRegions.includes(featureSet[key].Region)) {
delete featureSet[key];
} else if (featureSet[key].Status !== "read") {
featureCount = featureCount + 1;
}
});
// Update features data
chrome.storage.local.set({ 'features': featureSet });
// Update the badge
if (featureCount > 0) {
chrome.action.setBadgeText({ text: featureCount.toString() });
} else {
chrome.action.setBadgeText({ text: '' });
}
}
});
// Trigger an update
chrome.runtime.sendMessage('', {
type: 'update'
});
// Close the options page
close();
});
Code in background.js
// Listen for messages
chrome.runtime.onMessage.addListener(data => {
console.log(data);
if (data.type === 'update') {
scheduleRequest();
}
});
But nothing is happening
I've tried using tabs.sendMessage, but even if I put tabs in permissions it tells me that it isn't defined when I add it to the function chrome.tabs.sendMessage(tabs[0].id, {...
My test results contradict your claim.
manifest.json
{
"manifest_version": 3,
"name": "hoge",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"options_page": "options.html"
}
background.js
// Listen for messages
chrome.runtime.onMessage.addListener(data => {
console.log(data);
if (data.type === 'update') {
console.log("hoge")
// scheduleRequest();
}
});
options.js
// Trigger an update
chrome.runtime.sendMessage('', {
type: 'update'
});
options.html
<html>
<body>
options page
<script src="options.js"></script>
</body>
</html>
After some input from #woxxom and #Norio, and a little bit more troubleshooting, this is how I managed to get it to work
option.js:
// Trigger an update
chrome.runtime.sendMessage({ type: 'update' }, result => {
// Close the options page
close();
});
I had to move the close(); event into the return function so it didn't prematurely close off the code. I also had to have a paramter in the return function for some reason otherwise it wouldn't run with an empty arrow function.
background.js:
// Listen for messages
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'update') {
startRequest(true).then(sendResponse);
return true;
}
});
My function to be triggered in the background.js file was already an async promise function, so I had to add a .then() for the onMessage response function to trigger once it had run. It also wouldn't work without having return true; in there.
I am trying to build a simple chrome extension to get a value from a page and populate a second page after.
I'm new to chrome extensions, and I'm really only doing this to make something I have to do often simpler.
So I got the part where I open the first page, get the value I need and then I open the second page in another tab. Now I'm not sure how to populate the field.
Since I already have the value on content.js, is it possible to know when the other tab has loaded to just look for the field where i need to put that value in? Or is there another way to do it? I can't get it to work.. I also tried to listen to page loads, but I don't think that will help me, as I'm only interested in one particular page.
Manifest:
{
"manifest_version": 2,
"name": "my Extension",
"version": "1",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery-3.2.1.min.js", "content.js"]
}
],
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"scripts": ["background.js"]
}
}
background.js
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
// Send a message to the active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
});
});
//
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "open_new_tab" ) {
chrome.tabs.create({"url": request.url},
function(tab){ alert(tab.id) });
}
}
);
chrome.tabs.onUpdated.addListener(function (tabId , info) {
if (info.status === 'complete') {
chrome.tabs.sendMessage(activeTab.id, {"message": "page_loaded"});
}
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
var myUrl = "http://www.google.com";
var myValue = document.getElementById("thisId").value;
if(myValue ) {
chrome.runtime.sendMessage({
"message": "open_new_tab",
"url": myUrl,
"myValue ": myValue
});
}
}
if( request.message === "page_loaded" ) {
alert("hi");
}
});
I am working with a webpage which have an <iframe> to hold the university website.
However, some of the link in the university website will open a new tab inside the browser, normally it is not a problem but my webpage is going to be display on a 55" touchscreen in full screen mode . Therefore, my webpage will be blocked by the new tabs.
So, now I am using Chrome Extension to handle the new tabs. I modified one of the Extension from internet to close and redirect the new tabs back to <iframe> by using contentscript and background. And it WORK for most of the new tabs. (not all new tabs)
Because some of the <a>s' href is using javascript like this one :
High Hybrid Reinforced Soil Slope as Runway Support - Tana Toraja Airport Case Study
tab.url didn't return anything (it return empty string). The alert() like
alert('link:'+tab.url)
this. Will become this :
alert('link:'+'')
Anyway to tackle this problem?
----Code for reference----
manifest.json
{
https://clients2.google.com/service/update2/crx",
"manifest_version": 2,
"name": "Inteset Chrome Kiosk Helper",
"short_name": "Kiosk Helper",
"description": "Traps network errors. Shows user friendly error page allowing user to return to previous page. Blocks new windows and new tabs.",
"version": "1.1.12",
"options_page": "options.html",
"options_ui": {
"page": "options.html",
"chrome_style": true
},
"content_scripts": [
{
"matches": ["http://localhost/newyear/index.php"],
"js": ["myjs.js"]
}
],
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"web_accessible_resources": [
"style.css",
"popup.js",
"options.js"
],
"permissions": [
"webNavigation",
"tabs",
"http://*/*", "https://*/*",
"history",
"activeTab",
"storage"
],
"icons": {
"16" : "Logo16x16.png",
"48" : "Logo48x48.png",
"128": "Logo128x128.png"
}
}
background.js I only modify the code inside : chrome.tabs.onCreated.addListener(...)
chrome.webNavigation.onErrorOccurred.addListener(function (data) {
var errs = "net::ERR_BLOCKED_BY_ADMINISTRATOR;net::ERR_NAME_NOT_RESOLVED;net::ERR_CONNECTION_FAILED;net::ERR_CONNECTION_RESET;net::ERR_EMPTY_RESPONSE;net::ERR_FAILED;net::ERR_CONNECTION_REFUSED;net::ERR_INTERNET_DISCONNECTED";
if (errs.indexOf(data.error) != -1) {
var Page = GetPageName( data.error )
chrome.tabs.update(data.tabId, {
url: Page
});
}
});
chrome.tabs.onCreated.addListener(function (tab) {
chrome.tabs.query(
{ currentWindow: true },
function (tabs) {
if (tabs.length > 1) {
chrome.storage.local.get({
blockWindows: false,
blockTabs: false
}, function (items) {
chrome.windows.getCurrent({}, function (window) {
if (window.state == "fullscreen"||true) {
if (items.blockTabs) {
setTimeout(function(){
var _url = tabs[tabs.length - 1].url;
alert("New tabs [" + tabs.length + "] { " + _url + " }");
for(var i=0;i<tabs.length;i++){
// alert(tabs[i].url);
if(tabs[i].url == "http://localhost/UST_VW_web/index.php"){
alert('bg found url ' + tabs[i].url + '\n' + _url);
chrome.tabs.sendMessage(tabs[i].id, {new_link:_url }, function(response) {
//alert('bg response ');
});
}
}
chrome.tabs.remove(tab.id);
},10000);
}
}
});
});
}
}
);
});
chrome.windows.onCreated.addListener(function (window) {
chrome.windows.getAll({populate: true}, function (windows) {
if (windows.length > 1) {
chrome.storage.local.get({
blockWindows: false,
blockTabs: false
}, function (items) {
if (items.blockWindows) {
// check if at least one window is in full screen
for (var i = 0; i < windows.length; i++) {
if (windows[i].state == "fullscreen") {
chrome.windows.remove(window.id);
alert("New windows are not allowed by administrator. :)");
RedirectNewPage("new Win", window.url);
break;
}
}
}
});
}
});
});
function RedirectNewPage(caller,url){
alert("RedirectNewPage");
var tabs_str = "";
chrome.windows.getAll({populate:true},function(windows){
windows.forEach(function(window){
window.tabs.forEach(function(tab){
//collect all of the urls here, I will just log them instead
console.log(tab.url);
});
});
});
chrome.windows.getAll({populate: true}, function (windows) {
windows.forEach(function(window){
window.tabs.forEach(function(tab){
console.log(tab.url);
tabs_str += (tab.id + "\t");
});
});
});
alert("tabs "+tabs_str);
}
function GetPageName( error ) {
var ErrText = new String(error);
if (ErrText.indexOf("net::ERR_BLOCKED_BY_ADMINISTRATOR") >= 0)
return "Error-Blocked-by-Administrator.html";
if (ErrText.indexOf("net::ERR_NAME_NOT_RESOLVED") >= 0)
return "Error-Name-not-Resolved.html";
if (ErrText.indexOf("net::ERR_CONNECTION_FAILED") >= 0)
return "Error-Connectoin-Failed.html";
if (ErrText.indexOf("net::ERR_CONNECTION_RESET") >= 0)
return "Error-Connection-Reset.html";
if (ErrText.indexOf("net::ERR_EMPTY_RESPONSE") >= 0)
return "Error-Empty-Response.html";
if (ErrText.indexOf("net::ERR_FAILED") >= 0)
return "Error.html";
if (ErrText.indexOf("net::ERR_CONNECTION_REFUSED") >= 0)
return "Error-Connection-Refused.html";
if (ErrText.indexOf("net::ERR_INTERNET_DISCONNECTED") >= 0)
return "Error-Internet-Disconnected.html";
return "Error.html";
}
myjs.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
document.getElementById("mainframe").src = request.new_link;
alert("GET 2 --- " + document.getElementById("mainframe").name);
alert(request.new_link);
//sendResponse(myFunc(request.args));
});
I am making a chrome extension with two buttons : Start and Stop. On click of start button the html page, should start refreshing after a particular timer, and on click of stop it should stop refreshing.
The HTML page has a table in it say with id myTable.So after every refresh, I want to have row count of this table.
To get this I did something like this :
First for pop up, I made popup.js
window.onload = function() {
document.getElementById("startbutton").onclick = function() {
chrome.extension.sendMessage({
type: "table-row-count_start"
});
}
document.getElementById("stopbutton").onclick = function() {
chrome.extension.sendMessage({
type: "table-row-count_stop"
});
}
}
In background.js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
switch(request.type) {
case "table-row-count_start":
alert("Refershing started");
RefreshAndCount();
break;
case "table-row-count_stop":
alert("Stop Refershing");
break;
}
return true;
});
var RefreshAndCount = function(){
chrome.tabs.getSelected(null, function(tab){
chrome.tabs.sendMessage(tab.id, {type: "table-row-count"});
chrome.browserAction.setBadgeText({text: "Counting!"});
});
}
This will make call to content.js as we need to interact with DOM of HTML page. In this script I did something like this :
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) {
switch(message.type) {
case "table-row-count":
var x = document.getElementById("myTable").rows.length;
alert("Row count = " + x);
var Refresh = confirm("Do you want to refresh the page?");
if (Refresh)
{
setTimeout("location.reload(true);",5000);
}
break;
}
});
The script content.js is never called. I don't know why so. Please help.
Also it will be refreshing only once, how to keep refershing after fixed timer.
Here is manifest.json
{
"name": "Refresher",
"version": "0.0.1",
"manifest_version": 2,
"description" : "Refresh the site contents after a while",
"icons": { "32": "icon.jpg" },
"browser_action": {
"default_icon": { "32": "icon.jpg" },
"default_title": "Refersher",
"default_popup": "browseraction/popup.html"
},
"background": {
"scripts": ["background.js"],
"persistent": true
},
"content_scripts": [{
"matches": ["http://www.w3schools.com/html/tryit.asp?filename=tryhtml_table"],
"js": ["content.js"]
}]
}
In this case you've used a deprecated chrome.tabs.getSelected which returned the wrong tab with id -1 so the message was never delivered and an error was displayed in the console.
Use chrome.tabs.query:
var RefreshAndCount = function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {type: "table-row-count"});
chrome.browserAction.setBadgeText({tabId: tabs[0].id, text: "Counting!"});
});
};
Also note how setBadgeText was used just for the specified tab.
N.B. Always, always use the debugger to check what's wrong. Thus you can stop using alert and start using console.log or inspect/watch the variables in the debugger.
I am writing my first chrome extension and I am kind of new in this field.
My goal is sending url and email to a PHP server, but for now I send them to console.
My problem is saving the last email that user has entered to my extension.
Right now when I close the browser the value of email will change to undefined.
I put entire code of my extension, but I think the problem must be in getemail function.
background.js
//variables defenitions:
var email;
var urll;
//functions:
function getemail(){
email = window.prompt("Pleas enter your Email address:");
chrome.storage.sync.set({'email':email}, function() {
alert('You entered \n[' + email + "]\n as Email address.\nThank you for registration." );
});
var id = chrome.contextMenus.create({"title": "Submit your url","onclick":consollog });
var id = chrome.contextMenus.create({"title": email+"/Change" ,"onclick":getemail });
chrome.contextMenus.remove("1", null);
chrome.contextMenus.remove("2", null);
var id = chrome.contextMenus.create({"id":"2","title": "SUPPORT","onclick":support});
}
function create(){
var id = chrome.contextMenus.create({"title": "Submit your url","onclick":consollog });
var id = chrome.contextMenus.create({"title": email+"/Change" ,"onclick":getemail });
chrome.contextMenus.remove("1", null);
chrome.contextMenus.remove("2", null);
var id = chrome.contextMenus.create({"id":"2","title": "SUPPORT","onclick":support});
}
function support(){
alert("Contact ways:\nPhone number:+989378114692\nEmail address:amukiarash#gmail.com");
}
function consollog(info, tab) {
chrome.tabs.query({
'active':true,"currentWindow": true,
}, function(lTabs) {
urll=lTabs[0].url;
console.log(urll)
console.log(email)
alert('You sent "' + urll + '" to our server');
});
}
//menu items:
if(email==undefined){
var id = chrome.contextMenus.create({"id":"1","title": "Register Email","onclick":getemail });
}
else {create();}
var id = chrome.contextMenus.create({"id":"2","title": "SUPPORT","onclick":support});
manifest.json:
{
"name": "Jenco",
"description": "This extension helps you to send url",
"version": "0.9",
"browser_action":{
"default_icon":"32.png",
"default_popup":"mypopup.html"},
"permissions": ["contextMenus","tabs","activeTab", "http://*/*", "https://*/*","storage"],
"background": {
"scripts": ["background.js"]
},
"manifest_version": 2,
"icons": { "16": "16.png",
"32": "32.png",
"48": "48.png" },
"commands": {
"send-url": {
"suggested_key": { "default": "Ctrl+Shift+Z" },
"description": "Send an url"
}
}
}
My codes to save a variable and to load a variable:
// Saving
chrome.storage.sync.set({"variableName": value});
// Loading 1 thing
chrome.storage.sync.get("variableName", function(result){
// Showing the requested variable value
alert(result.variableName);
});
// Loading more things
chrome.storage.sync.get(["variableName", "variableNameTheSecond"], function(result){
// Showing first the first one and then the second one
alert(result.variablename);
alert(result.variableNameTheSecond);
});
I hope this helps you, greets
Ebbe