Updating an extension button dynamically - inspiration required - google-chrome-extension

I am building an extension where I want to be able to add a signifier to the extension button when the extension in the code has been activated. I was hoping I could add text to the extension button (top right)
Here is a simple scenario. Let's say my extension monitors browsing and gets the tab url, in my extension I have a list of domains to watch for.
Watch for these domains
www.website1.com
www.website2.com
If a user visits a domain in the watched list I want to indicate this somehow, by adding some text somewhere - I was hoping in the top right of the browser where the extensions buttons are. I don't really want to use a notification window as I want something unobtrusive. The text that I want to display would just be a few letters but different for different urls.
Does anyone have any inspiration?
Thanks

You may change the extension icon like this:
chrome.browserAction.setIcon({path: icon});
There is also a 'badge' - small box over the extension icon that shows ie. number of unread messages in gmail extension. You can manipulate it like this:
chrome.browserAction.setBadgeBackgroundColor({color:[190, 190, 190, 230]});
chrome.browserAction.setBadgeText({text:"?"});
It is also possible to generate icon dynamically on a canvas element and then display it like this:
chrome.browserAction.setIcon({imageData:canvasContext.getImageData(0, 0, canvas.width,canvas.height)});
Note that you must call this from your background script, since the content script will not have permission!

tl;dr: Call it from background.js
I googled around this comment because I was trying to call a chrome.browserActions function from my content script
It's only accessible to scripts that are running as part of a chrome extension, since content_scripts are the same as client scripts you'd have to access them through the chrome.* api's
and to fix some addition headaches I had the call for setBadge text needs to look like:
chrome.browserAction.setBadgeText({text: 'ASDF'});
You can put as many characters as you want, but only 4 or so will appear. I got hung up on what the object property needed to be.

You can also set a timeout to check changes on the system every x minutes, and then update de badge.
On my extension, I have an task counter called inside a notification function. Something like :
$.getJSON(
"http://mydomain/notifications?ajax=1&callback=?",
function(data){
var result = data.retorno;
if(result.length > 0){
var totalItens = result[0].total
} else {
var totalItens = 0;
}
chrome.browserAction.setIcon({path: '19.png'});
chrome.browserAction.setBadgeText({text:''+totalItens+''});
for(var i=0; i<result.length; i++){
var imagem = 'http://mydomain/myimage';
var titulo = 'mytitle';
var desciption = 'mydescription';
var urlNot = 'http://mydomain/mypageOnclick';
var not = new Notifier(urlNot);
not.Notify(
imagem, // The image.
titulo, // The title.
desciption // The body.
);
}
}
);

You have to change in 3 files.
manifest.json
Check this code added
"background": { "scripts": ["background.js"], "persistent": false }
script.js
Add the following code:
const msg = 'updateIcon'
chrome.runtime.sendMessage({ message: msg }, function(response) {
});
background.js
Add the following code:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request);
// Callback for that request
chrome.browserAction.setIcon({path: "/assets/icon.png"});
});

Related

How to add contents of HTML file to page dynamically from a Chrome extension?

From withing a Chrome extension, what's the best way to conditionally add the contents of an .html file to a page. Like you don't want to always add it, only if certain conditions are met. I see ways to conditionally inject script, but how can I conditionally add HTML from a file in the extension into the page?
If I have an option turned on, I want to add a block of code.
read option:
this.get_options = function ()
{
chrome.storage.sync.get({
mytopics: true,
friendtopics: true
}, function(items) {
self.settings = items;
scan_page();
});
}
this.scan_page = function()
{
if (!(self.settings.mytopics || self.settings.friendtopics))
return;
// want to add in a decent amount of HTML from a file, here.
// don't really want to construct it all via createnode calles
}
Figured this out.
$('body').append('<div id="containerName"></div>');
$('#containerName').load(chrome.extension.getURL("markup/notification.html"));

Need to modify browser action popup contents upon tab change

I need to modify the contents of browser Action popup on tab change.
I am detecting change of tab in background.js script
var tabHandler={
processChange:function(tab){
var parser = document.createElement('a');//To extract the hostname, we create dom element
parser.href = tab.url;
var regex=/^(www\.)?([^\.]+)/
var matches=regex.exec(parser.hostname)//This gives us the hostname, we extract the website name
var website=matches[2];
function getWebsiteCoupons(site){
var coupons=cache.pull(site)
if(!coupons){
couponfetcher(site)
coupons=cache.pull(site);
}
return coupons;
}
var coupons=getWebsiteCoupons(website);
//NEED TO UPDATE THE POPUP HERE
chrome.browserAction.setBadgeText({text:coupons.coupons.length+coupons.deals.length+""})
},
onTabUpdate:function(tabId, changeInfo, dtab){
chrome.tabs.get(tabId,tabHandler.processChange);
},
tabChanged:function(activeInfo) {
console.log(this) ;
chrome.tabs.get(activeInfo.tabId,tabHandler.processChange);
},
init:function(){
chrome.tabs.onActivated.addListener(this.tabChanged);
}
}
tabHandler.init();
So I tried to detect a click action on the browser action, but this doesn't work when I have a popup already defined.
function BrowserActionClicked(tab){
alert("hello");
}
chrome.browserAction.onClicked.addListener(BrowserActionClicked)
If I remove the popup from manifest, the script works. But I don't know how to get instance of the manifest's contents
I also tried getting the views. The view however is an empty view, doesn't contain the contents of the popup.
var view=chrome.extension.getViews();
$(view.document).append("Hello");
this didn't work either. How do I update the contents of the browser popup from background script?
I am in a bit of a fix here, to be honest

wrong current url in google chrome extension

I have a google chrome extension that is shown onclick in a popup. There is a context menu with some options that need the current / active tab url. The extension has a problem described below.
Old code:
function menuCallback(info, tab) {
var currentUrl = tab.url;
With old code: If you right-click inside the popup, the current url returned is "chrome-extension..." and so on.
New Code: (i tried to fix the issue with)
chrome.tabs.query({'active': true, 'windowId': chrome.windows.WINDOW_ID_CURRENT},
function(tabs){
currentUrl = tabs[0].url;
}
);
This works, as it returns the tab url even if the click comes from inside the popup. But if i have like 10 open tabs and switch between two, always the old one is returned. For example i'm at google.de first, url returned is google.de. Now i switch to an already open tab like "heise.de" and right-click, it's still google.de. Next attempt / try the url is correct.
You probably want to use the onUpdated listener.
chrome.tabs.onUpdated.addListener(doSomething);
Which gives you the tabId, changeInfo and tab metadata. You then can do as you please:
var doSomething = function (tabId, changeInfo, tab) {
var match = /http:\/\/www.google.com/.exec(tab.url);
if(match && changeInfo.status == 'complete') {
... do something ...
}
}
EDIT: After reading again your question, what you probably want is the onHighlighted event listener. It returns an object with an array of tabsIds and the window as soon as you select a tab.
chrome.tabs.onHighlighted.addListener(function(o) { tabId = o.tabIds[0]; })
You can then use get in order to obtain more information about that specific tab.
chrome.tabs.get(tabId, function(tab) { ... })
I'm leaving the onUpdated code in case anyone wants the tab information whenever a page changes.
Using the query parameters the simplest solution to finding the URL of the active tab in the currently focused window would be the following.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
currentUrl = tabs[0].url;
});
chrome.tabs.getSelected(null, function(tab) {
var currentURL= tab.url;
alert(currentURL); // this should give you current url.
}

modified innerHTML does not show on page

I am writing a Google extension. Here my content script modifies a page based on a list of keywords requested from background. But the new innerHTML does not show up on the screen. I've kluged it with an alert so I can see the keywords before deciding to actually send a message, but it is not how the routine should work. Here's the code:
// MESSAGE.JS //
//alert("Message Page");
var keyWordList= new Array();
var firstMessage="Hello!";
var contentMessage=document.getElementById("message");
contentMessage.value=firstMessage;
var msgComments=document.getElementsByClassName("comment");
msgComments[1].value="Hello Worlds!";//marker to see what happens
chrome.extension.sendRequest({cmd: "sendKeyWords"}, function(response) {
keyWordList=response.keyWordsFound;
//alert(keyWordList.length+" key words.");//did we get any keywords back?
var keyWords="";
for (var i = 0; i<keyWordList.length; ++i)
{
keyWords=keyWords+" "+keyWordList[i];
}
//alert (keyWords);//let's see what we got
document.getElementsByClassName("comment")[1].firstChild.innerHTML=keyWords;
alert (document.getElementsByClassName("comment")[1].firstChild.innerHTML);// this is a band aid - keyWords does not show up in tab
});
document.onclick= function(event) {
//only one button to click in page
document.onload=self.close();
};
What do I have to do so that the text area that is modified actually appears in the tab?
(Answering my own question) This problem really has two parts. The simplest part is that I was trying to modify a text node by setting its value like this:
msgComments1.value="Hello Worlds!"; //marker to see what happens
To make it work, simply set the innerHTML to a string value like this:
msgComment1.innerHTML="Hello Worlds!"; //now it works.
The second part of the problem is that the asynchronous call to chrome.extension.sendRequest requires a callback to update the innerHTML when the reply is received. I posted a question in this regard earlier and have answered it myself after finding a solution in an previous post by #serg.

Chrome Extension iframe dom reference disqus

How do I get a reference to the dom of a cross domain iframe/frame?
I want to do some stuff to disqus comments with an extension.
My manifest has the following:
"all_frames": true,
"matches": ["*://*.disqus.com/*","*://disqus.com/*", "http://somesite.com"]
I am not trying to communicate outside of the frame - that is the js will take care of the work without needing to 'tell' me anything.
all_frames should inject the listed js files into every frame, no?
When I do this:
if (window != window.top){
alert('In an IFRAME: ' + window.location.href);
}
...I get the expected disqus URLs.
But when I do this:
var btnCommentBlock = document.getElementsByClassName('dsq-comment-buttons');
alert('btnCommentBlock length: ' + $(btnCommentBlock).length);
...I get 0 for length.
I updated my answer to Javascript to access Disqus comment textbox?
Basically, Disqus changed the selector. They no longer use textarea, they use contenteditable divs.
Something like this should work:
// We just need to check if the IFrame origin is from discus.com
if (location.hostname.indexOf('.disqus.com') != -1) {
// Extract the textarea (there must be exactly one)
var commentBox = document.querySelector('#comment');
if (commentBox) {
// Inject some text!
commentBox.innerText = 'Google Chrome Injected!';
}
}
Source Code:
https://gist.github.com/1034305
Woohoo! I found the answer on github:
https://gist.github.com/471999
The working code is:
$(document).ready(function() {
window.disqus_no_style = true;
$.getScript('http://sitename.disqus.com/embed.js', function() {
var loader = setInterval(function() {
if($('#disqus_thread').html().length) {
clearInterval(loader);
disqusReady();
}
}, 1000);
});
function disqusReady() {
//whatever you can imagine
}
});
I put this in the disqusReady() function:
var aTestHere = document.getElementsByClassName('dsq-comment-body');
alert(aTestHere[0].innerHTML);
...and got back the innerHTML as expected.
Mohamed, I'd really like to thank you for taking the time to interact with my question. If you hadn't posted that link to github there's no telling when if ever I'd have figured it out or found the other code.
edit: After a few minutes of experimenting it looks like it is not necessary to call getScript so you should be able to comment that out.
Also unnecessary is window.disqus_no_style so I commented that out too.
I'll experiment some more and update the answer later. One of those two things prevented me from being able to actually post a comment at the disqus site I use. //them out still allows access to the dom and the ability to post.

Resources