I am currently making a Google Chrome extension, and in the options I want the user to be able to choose between it being always on or only activating when clicked. To do this, I need an options.js and a background.js file, which I have. However, I am having a lot of trouble getting them to communicate properly. I tried using the chrome.storage api, but it won't do anything.
Here is my code for background.js:
chrome.browserAction.onClicked.addListener(function() {
// Send a message to the active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {"message": tabs[0].url}, function(response));
});
});
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete') {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
// console.log(tabs.length);
chrome.tabs.sendMessage(tabs[0].id, {"message": tabs[0].url}, function(response) {});
});
}
});
And here is my code for options.js:
// Saves options to chrome.storage
function save_options() {
var behavior = document.getElementById('behavior').value;
chrome.storage.sync.set({
extensionBehavior: behavior
}, function() {
// Update status to let user know options were saved.
var status = document.getElementById('status');
status.textContent = 'Options saved!';
setTimeout(function() {
status.textContent = '';
}, 1000);
});
}
// Restores select box and checkbox state using the preferences
// stored in chrome.storage.
function restore_options() {
// Use default value color = 'red' and likesColor = true.
chrome.storage.sync.get({
extensionBehavior: 'onClick'
}, function(items) {
document.getElementById('behavior').value = items.extensionBehavior;
});
}
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click',
save_options);
If the behavior is set to "onClick", I only want the chrome.browserAction.onClicked.addListener portion to be executed. If the behavior is set to 'alwaysOn', then I only want the chrome.tabs.onUpdated.addListener portion to be executed. As far as debugging goes, both of those chunks work the way they're supposed to. I just need to know how to get one or the other to run based on the current options.
For the communication between option and background, it would be quite easy when you choose the localStorage to pass info between them. http://www.w3schools.com/html/html5_webstorage.asp
Related
I have been researching asynchronous function calls and how to set variables to values from them and have had a lot of trouble with it. I want to create a port to message with my file content.js on the extension.
To do this I need to receive the tab of the window that I have open, and use its attribute id in the chrome.tabs.connect() function.
This implementation fails to reach any console.log() calls but I don't understand asynchronous programming well enough to understand. Can anyone help with this? My problem is that the two files aren't communicating, so the port isn't opening.
<script language = "Javascript">
function foo(callback){
var port = chrome.tabs.connect(chrome.tabs.query({ currentWindow: true, active: true }, function(tabs) {
//sets curTab to current tab
console.log(tabs[0]);
var curTab;
setTimeout(function(tabs) {
curTab = tabs[0];
console.log(curTab);
}, 5000);
}),{name: "mode"})
//both files are preset to this so no need to message
var mode = "on";
document.getElementById("stop").onclick = function(){
if(mode === "off")
mode = "on";
else
mode = "off";
setMode();
console.log("clikityclik");
};
console.log(mode);
function setMode(){
/*sends message to port*/
if(port)
port.postMessage({newMode: mode});
else{
console.log("error: port not created");
}
}
}
the relevant code from my content.js file is below. I call this function once
function getMode(){
/*receives message from port
**communicates with sandboxed.html
*/
chrome.runtime.onConnect.addListener(function(port) {
console.assert(port.name == "mode");
port.onMessage.addListener(function(msg) {
if (msg.newMode){
mode = msg.newMode;
console.log("Mesage received: "+mode);
}
else
console.log("error receiving new mode, last mode was: " + mode);
});
});
}
The goal of this program is for the first script to send messages to the content.js when a div is clicked and for the 'content.js' file to receive those messages whenever they are sent.
the solution was to make a function that creates the port, with an input of tab. Basically, getTab will try to get the the value of the tab, and if we do have a tab it will run the callback function which is createPort which contains the information necessary to create the port and also the event handler for the click on the div.
function getTab(callback){
chrome.tabs.query({ currentWindow: true, active: true }, function(tabs) {
console.log(tabs[0]);
callback(tabs[0]);
});
}
function createPort(tab){
var port = chrome.tabs.connect(tab.id,{name: "mode"});
document.getElementById("stop").onclick = function(){
if(mode === "off")
mode = "on";
else
mode = "off";
setMode(port);
console.log("clikityclik");
};
}
var mode = "on"; //mode is preset to on in content.js
getTab(createPort);
I have a chrome extension with options set through the options_ui tag in manifest.json. I can save options however I noticed the options modal has to be closed for the chrome.storage.sync.set function to complete saving the options. How do I force saving of the options upon clicking "save" even if the options modal is not closed?
options.js:
function save_options() {
var hideAds = document.getElementById('hideAds').checked;
chrome.storage.sync.set({
hideAds: hideAds
}, function() {
// Update status to let user know options were saved
var status = document.getElementById('status');
status.textContent = 'Options successfully saved...';
setTimeout(function() {
status.textContent = '';
}, 1000);
});
}
// Restores checkbox state using the preferences stored in chrome.storage.
function restore_options() {
// Use default values
chrome.storage.sync.get({
hideAds: false
}, function(items) {
document.getElementById('hideAds').checked = items.hideAds;
});
}
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click', save_options);
manifest.json:
{
"name": "Redesign",
"version": "1.0",
"manifest_version": 2,
"options_ui": {
"page": "options.html",
"chrome_style": true
}
}
EDIT: Adding background.js code below that doesn't get latest options (after clicking save button on the options page) unless options modal is closed. The alert line below outputs the old saved option value...and the new saved value only after the options modal is closed.
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
if (info.status == 'complete') {
chrome.storage.sync.get(['hideAds'], function(items) {
if(typeof items.hideAds !== 'undefined') {
hideAds = items.hideAds;
alert(hideAds);
}
})
doSomething(tab);
}
});
You could listen to chrome.storage.onChanged event in background page ( you would never need to listen to chrome.tabs.onUpdated for getting storage value), which fires when one or more items change:
chrome.storage.onChanged.addListener(function(changes, areaName) {
if(areaName === 'sync') {
const hideAdsChange = changes['hideAds'];
if(typeof hideAdsChange !== 'undefined') {
const newValue = hideAdsChange.newValue;
console.log(newValue);
}
}
});
I am making a chrome extension to keep refreshing a page unless stop button is chosen. But i am able to do it only once. Here is my code for 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.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!"});
});
};
In content.js I did this :
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) {
alert(message.type);
switch(message.type) {
case "table-row-count":
var x = document.querySelector('table').rows.length;
chrome.storage.sync.set({'value': x}, function() {
console.log('Settings saved');
});
chrome.storage.sync.get(["value"], function(items){
console.log(items);
});
alert("Row count = " + x);
setTimeout(function(){
location.reload();
},100);
break;
}
});
chrome.storage.onChanged.addListener(function(changes, namespace) {
for (key in changes) {
if(key=='value'){
var storageChange = changes[key];
console.log('Storage key "%s" in namespace "%s" changed. ' +
'Old value was "%s", new value is "%s".',
key,
namespace,
storageChange.oldValue,
storageChange.newValue);
}
}
});
After refresh I want to print the current row count alert everytime. Please help how to do this .
This work fine, for a single refresh but after that I again had to choose the start button from popup.
I want some way that I need not click start button again and the whole process repeats, storing the previous row count in cache or something.
popup.js
window.onload = function() {
document.getElementById("mystartbutton").onclick = function() {
chrome.extension.sendMessage({
type: "table-row-count_start"
});
}
document.getElementById("mystopbutton").onclick = function() {
chrome.extension.sendMessage({
type: "table-row-count_stop"
});
}
}
Also help me How to keep on refershing that page even if I switch to other tab or minimise my chrome ?
You can use the chrome.storage.local to store data that will be saved over time and over context where you use it. You can set a boolean to true or false to enable or disable autoreload. Then you only have to set it at click on browser action and check it in the content-script to know if you have to reload.
A possible and simple implemtation should be like this : (It depends of the expected behavior)
content.js (have to be injected in the page to autoreload)
var reloadDuration = 5000;
function autoreload()
{
chrome.local.storage.get("autoreload_enabled", function(result)
{
if(result.autoreload_enabled)
{
chrome.runtime.sendMessage({type: "table-row-count"});
window.location.reload();
}
}
}
setTimeout(autoreload, reloadDuration);
This will reload your page every reloadDuration if the boolean set in chrome local storage named autoreload_enabled is true.
I have a function called in popup.html that creates a tab, inserts a mailto to trigger a local (or gmail) mail event. It's my desire for it to then close itself. I've tried numerous things, but it seems like I need something that does the equivalent of:
tabId = chrome.tabs.query(I DON'T KNOW!);
chrome.tabs.remove(tabId);
here's the current code:
var query = { active: true, currentWindow: true };
function callback(tabs) {
var currentTab = tabs[0];
console.log(currentTab);
}
chrome.tabs.remove(chrome.tabs.query(query, callback));
but it's not working.
if useful, here's how I create the tab (which does work as desired):
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
getTabs(tabs, function(full_mail_link){
chrome.tabs.create({ url: full_mail_link });
});
});
any help would be greatly appreciated!
I don't know what your getTabs function does. Yet if you know how to find the tab id of the tab you want all you need to do is
chrome.tabs.remove(tabId, optionalCallback);
this must be work:
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.remove(tab.id);
});
This should work:
//create the tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
getTabs(tabs, function(full_mail_link){
chrome.tabs.create({ url: full_mail_link }, callBackOnCreate);
});
});
function callBackOnCreate(tab)
{
globalCreatedTab = tab.id;
}
chrome.tabs.query({'active': true}, function(tabs) {
for (var i = 0; i < tabs.length; ++i)
{
if (tabs[i].id === globalCreatedTab)
{
chrome.tabs.remove(tabs[i].id, [optional callback]);
}
}
});
Solution: use the query function with the callback and execute the remove function in the callback.
It looks like normal window.open and window.close() should also work,
The tab-id is an integer or an array containing integers.
I try to make some changes on a Chrome extension. I need the extension checks the value and if it is true, then execute a script. If false, then do nothing. I wrote something like this:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(localStorage["statusOfSomething"]){
chrome.tabs.executeScript(tabId, {file: "file.js" ,runAt:'document_end'});
}
});
But this takes the initial value of localStorage["statusOfSomething"] always. So there is an async function to register a listener for "onUpdated". But I need to check the localStorage["statusOfSomething"] value of "now", not the value of the time by registering the listener.
How can I do this?
Edit:
Actually I was trying to check two things:
if the website is in the site list of extension
if this website is enabled for the extension
Now here the full story;
There are some websites, I defined them on background.js file. Let's say;
a.com, b.com ... etc.
var sites = [{
name : "a",
wildcard : ["*://a.com/*"],
js : "a.js"
},{
name : "b",
wildcard : ["*://b.com/*"],
js : "b.js"
}]
and there are statuses of the sites (enable/ disable; true/false)
I think it was good to store statuses by localStorage, so I write as initial value true:
for(var i = 0; i<sites.length; i++){
localStorage[sites[i].name] =true;
}
As option; it was needed to addListener for changes:
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if(request.method == "setSite"){
var name = request.site;
var status = request.active;
localStorage[name] = status;
}
return true;
});
If user checks the checkbox for status option of the website, then options.js sends message:
$('#' + name).change(function(){
var status = $(this).is(':checked');
chrome.extension.sendMessage({method: "setSite", site: this.id, active: status}, function(response) {
console.log(response.data);
});
});
Now, back to background.js , for every update of the tab, I need to check these two things together:
1. am I interested in this website?
2. is it enable for me now?
So I wrote:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.status === 'complete') {
var url = tab.url;
for(var i = 0; i<sites.length; i++){
var site = sites[i];
var name = site.name;
var wildcard = site.wildcard;
if(localStorage[name] && testUrl(url,wildcard)){
chrome.tabs.executeScript(tabId, {file: site['js'] ,runAt:'document_end'});
break;
}
}
}
});
Here, I get the value of localStorage[sitename] true
If you are more interested, you can see the code on github (the version)