chrome.tabs.onUpdated.addListener() is called twice - google-chrome

I'm writing a chrome extension and in some web sites chrome.tabs.onUpdated.addListener() is called twice.
It mostly happens if i click on a link and not when i type in a URL by myself.
From what i found on the web and from many questions asked on StackOverflow there was a bug on chrome but it was fixed several years ago.
Some people claim it happens if there are several iframes in the page, but in my case there are no iframes in my page.
This is my code:
var storage = chrome.storage.local;
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete' && tab.status == 'complete' && tab.url != undefined) {
storage.get('URLs', function(URLs){
for (var item in URLs)
{
if (tab.url == item)
{
return;
}
else
{
//alert ("tab load complete");
storage.set({URLs: [tab.url]});
chrome.tabs.executeScript(tab.id, {
"file": "flashblocker.js"
}, function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
}
}
});
}
});
How can i make it run only once?
Thanks.

Use a variable and add a check inside the listener to check the value of this variable before executing the alert. You can do something like this:
var tabUpdated = false;
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete' && tab.status == 'complete' && tab.url != undefined) {
if (!tabUpdated) {
alert("tab load complete");
tabUpdated = true;
}
}
});
But this will fail if the content script is actually loading twice as the tabUpdated variable will again be initialized to false. In that case you can use the chrome's Storage API and store the URL for which the listener has been already invoked. Simply add a check for this, if the URL is there in storage, the alert wont be invoked, else it will invoke. You can then clear the storage at the browser start or close.
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status == 'complete' && tab.status == 'complete' && tab.url != undefined) {
chrome.local.storage.get('URLs', function(URL's) {
// Iterate through this list here and match with tab.url, if the match is found, just return.
if (url is there in list) {return;}
else {
alert("tab load complete");
chrome.local.set({URLs: [tab.url]});
}
});
}
});
This is just an example of how you can achieve it. Tweak it according to your needs.
I hope this helps.

Related

Running small snippets of code persistently in Chrome (eg. tiny extensions)

Can I run small script snippets in Chrome all the time, as they were mini extensions? Without the manifest and packaging involved with a regular extension?
I basically want to "hack" Chrome to send events when I press media keys. A script like so:
sendRequest = function(action) {
return chrome.extension.sendRequest({
action: action
}, (function() {}));
};
document.addEventListener("keydown", function(e) {
if (e.keyCode === 32) {
return sendRequest("pause");
} else if (e.keyCode === 37) {
return sendRequest("previous");
} else if (e.keyCode === 39) {
return sendRequest("next");
}
});
I'm imagining this can be added via the Sources tab and some of the new magic there, but not sure.
The extensions API (chrome.extension.sendRequest) is not available to non-extensions, obviously. A real mini-extension should do the job.

web notifications not working

I'm tring to use the web notifications API like in this example:
http://www.inserthtml.com/2013/10/notification-api/?utm_source=html5weekly&utm_medium=email
When i'm in this website, everything is working great, in the console i'm writing "Notification.permission" and gets "granted".
But if i'm trying to do the same in my website, i'm getting error about the Notification object and when i'm trying to print "Notification.permission" i've noticed that the Notification object doesn't have this property and other properties like "requestPermition".
This happening in all the browsers and they all updated to the last version.
i've tried to open console in other websites, like cnn.com for example, and inspect the Notifications object, and also there are missing properties.
Any idea why?? and how its working the website above??
thanks.
this is my code:
window.addEventListener('load', function(){
var button = document.getElementById( "notifications" );
function theNotification() {
var n = new Notification("Hi!", {
});
}
// When the button is clicked
button.addEventListener('click', function () {
// If they are not denied (i.e. default)
if (Notification && Notification.permission !== "denied") {
// Request permission
Notification.requestPermission( function( status ){
// Change based on user's decision
if (Notification.permission !== status)
Notification.permission = status;
});
}
});
$(button).click();
var socket = io.connect('http://localhost:3000', {query : "user=343"});
socket.on('notification', function (data) {
console.log( data );
if (Notification && Notification.permission === "granted") {
theNotification();
} else {
alert(data);
}
});
});

Check existence of variable in webpage via content scrips

I want to conditionally insert few javascript files inside the DOM of the webpage. I also want to add a dependency.
var load = function(filename, callback) {
fileref = document.createElement("script")
fileref.setAttribute "type", "text/javascript"
fileref.setAttribute "src", filename
document.getElementsByTagName("head")[0].appendChild fileref
if (typeof callback !== "undefined" && callback !== null) {
callback();
}
}
load("http://www.myserver.com/lib.js",
function() { load("http://www.myserver.com/core.js") }
)
But I want to check whether the 'lib.js' is actually executed. For that, I would want to wait till a variable inside lib.js is available. How do I do it?
Don't run your callback immediately. Because content scripts share the DOM with their page, you can wait for the load event on the DOM <script> element:
var load = function(filename, callback) {
fileref = document.createElement("script");
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filename);
// fire callback when script loads
fileref.addEventListener("load", function() {
if (typeof callback !== "undefined" && callback !== null) {
callback();
}
});
document.getElementsByTagName("head")[0].appendChild(fileref);
}
load("http://www.myserver.com/lib.js",
// this callback will run only after lib.js has fully loaded
function() { load("http://www.myserver.com/core.js") }
)

Webkit Notifications on Multiple Tabs

I am using WebKit Notifications for my app. Say if I am using this code:
var n = window.webkitNotifications.createNotification(
'icon.png',
'New Comment',
'Praveen commented on your post!'
);
n.onclick = function(x) { window.focus(); this.cancel(); };
n.show();
PS 1: The first five lines are actually a single line. Just for readability I have posted this way.
PS 2: For the full code, please see this: Unable to show Desktop Notifications using Google Chrome.
My question is, what if I have more than one tab opened?
Say if this is gonna get fired when a new comment appears on my app. What if I have more than one tab open? Will this generate many notifications? Say, I have 10 - 15 tabs open and I get two notifications fired. How many notifications will be generated, 20 - 30?
If that is the case, how to prevent generation of a single notification multiple times for each opened tab?
You just need to specify "tag" option for notification. Notifications with the same value in tag only shows once even if many tabs are opened.
For example:
var notification = new Notification('Hey!', {
body : 'So nice to hear from you',
tag : 'greeting-notify',
icon : 'https://mysite.com/my_funny_icon.png'
});
A detailed explanation of Tagging notifications so only the last one appears is available
on the MDN docs site
An excerpt of the code [just in case the docs go down]
The HTML
<button>Notify me!</button>
The JS
window.addEventListener('load', function () {
// At first, let's check if we have permission for notification
// If not, let's ask for it
if (Notification && Notification.permission !== "granted") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
});
}
var button = document.getElementsByTagName('button')[0];
button.addEventListener('click', function () {
// If the user agreed to get notified
// Let's try to send ten notifications
if (Notification && Notification.permission === "granted") {
for (var i = 0; i < 10; i++) {
// Thanks to the tag, we should only see the "Hi! 9" notification
var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
}
}
// If the user hasn't told if he wants to be notified or not
// Note: because of Chrome, we are not sure the permission property
// is set, therefore it's unsafe to check for the "default" value.
else if (Notification && Notification.permission !== "denied") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
// If the user said okay
if (status === "granted") {
for (var i = 0; i < 10; i++) {
// Thanks to the tag, we should only see the "Hi! 9" notification
var n = new Notification("Hi! " + i, {tag: 'soManyNotification'});
}
}
// Otherwise, we can fallback to a regular modal alert
else {
alert("Hi!");
}
});
}
// If the user refuses to get notified
else {
// We can fallback to a regular modal alert
alert("Hi!");
}
});
});

How to disable specific keyboard keys on a webpage?

I am developing a webpage using Wordpress 3.04, and I'm experiencing the following issue:
In this webpage, I implemented a script that changes the background image every 10 seconds or so. Now, when users press the Left Arrow and Right Arrow keys, it makes the background picture change back and forth accordingly, and messes up the rotation cycle.
This becomes a problem in the Contact Form section of the site, since users that might need to navigate left and right inside each field might end up changing the background pic instead.
I would also like to disable the "Enter" key, to avoid the form being sent if the users are not done writing their message.
I looked around and found this javascript code that didn't work:
document.onkeydown=function DisableCTRL(e)
{
var val=(document.all)?event.keyCode:event.which;
if(parseInt(val)==17)//CTRL
{
alert('Not Allowed!');
window.event.returnValue=false;
}
}
This JS code didn't work either:
function stopRKey(evt) {
var evt = (evt) ? evt : ((event) ? event : null);
var node = (evt.target) ? evt.target : ((evt.srcElement) ? evt.srcElement : null);
if ((evt.keyCode == 13) && (node.type=="text")) {return false;}
}
document.onkeypress = stopRKey;
Any help will be greatly appreciated. Thanks!
I think, you should call stop() on the passed event, i.e.
document.onkeydown = function(e) {
if (e.keyCode == 17) {
alert('Not Allowed!');
e.stop();
}
};
and maybe use addEventListener(). I am not sure, intercepting the Ctrl key down will actually turn of Ctrl altogether. I guess, you need to intercept cursor left/right with the ctrlKey attribute set. For testing key events, see e.g. http://unixpapa.com/js/testkey.html.
PS. document.all: http://javascript.about.com/od/hintsandtips/a/worst_4.htm
You need to call e.preventDefault() to stop the event from going ahead.. I wrote this function to handle unwanted keys on a site recently:
PreventIllegalKeyPress = function (e) {
if (e.target) t = e.target; //Firefox and others
else if (e.srcElement) t = e.srcElement; //IE
if (e.keyCode == 116) { //prevent F5 for refresh
e.preventDefault();
}
if (e.keyCode == 122) { //F11 leave fullscreen
e.preventDefault();
} else if (e.altKey && e.keyCode == 115) { //Alt + F4
e.preventDefault();
} else if (e.altKey && e.keyCode == 37) { //Alt + left
e.preventDefault();
} else if (e.altKey && e.keyCode == 39) { //Alt + right
e.preventDefault();
} else if (e.ctrlKey && e.keyCode == 82) { //Ctrl + R (reload)
e.preventDefault();
}
if (!(t.tagName == 'INPUT')) {
if (e.keyCode == 13) { //enter
e.preventDefault();
}
if (e.keyCode == 8) { //backspace
e.preventDefault();
}
}};
Note the check for t.tagName == "INPUT". This makes sure that both enter and backspace keys are allowed in input field but no-where else.
Then in $(document).ready, paste the following snippet to call the function:
$(document).keydown(function (e) {
NFS.PreventIllegalKeyPress(e);
});
This works perfectly fine for me.