Reputation: 109
I am trying to pass a message triggered by an alarm from background.js to loader.js. Here is my code:
manifest.json:
{
"update_url": "https://clients2.google.com/service/update2/crx",
"manifest_version": 2,
"name": "DubX",
"short_name": "DubX",
"author": "Al3366",
"description": "Automatically loads DubX on dubtrack.fm",
"homepage_url": "https://dubx.net/",
"version": "0",
"browser_action": {
"default_icon": "icons/48.png"
},
"permissions": ["background","alarms","tabs"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [{
"matches": ["*://www.dubtrack.fm/*"],
"js": ["jquery.js","loader.js"],
"run_at": "document_end"
}],
"icons": {
"16": "icons/16.png",
"19": "icons/19.png",
"38": "icons/38.png",
"48": "icons/48.png",
"128": "icons/128.png"
}
}
background.js
chrome.alarms.create('hello',{delayInMinutes: 0.25});
chrome.alarms.onAlarm.addListener(function(alarm) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
var content = {greeting: 'foo'};
chrome.tabs.sendMessage(tabs[0].id, content);
});
});
loader.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === 'foo') {
hello();
};
}
);
$('body').prepend('<div class="cake" style=" z-index: 2147483647; color: white; position: fixed; bottom: 54px; left: 27px; background: #222; padding: 13px; -webkit-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75); -moz-box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75); box-shadow: 0px 0px 5px 0px rgba(0,0,0,0.75); border-radius: 5px;">Waiting for Dubtrack...</div>');
function hello() {
$.getScript('https://rawgit.com/sinfulBA/DubX-Script/master/beta.js');
$('.cake').remove();
};
It keeps firing the hello(); function every 4 seconds. I can't find out what I'm doing wrong. Thanks in advance for your reply.
Upvotes: 3
Views: 5776
Reputation: 77581
Please note: it's impossible to use chrome.alarms
to do things with a granularity less than a minute.
Quoting the docs:
In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more. That is, setting
delayInMinutes
orperiodInMinutes
to less than 1 will not be honored and will cause a warning.
So in a production environment, your alarm won't fire at all or will be delayed. You're observing the development environment effect:
To help you debug your app or extension, when you've loaded it unpacked, there's no limit to how often the alarm can fire.
Despite wOxxOm's remark that a persistent background page is a "bad" solution, it's actually the optimal solution for tasks that require frequent repeated events. Reloading the event page every couple of minutes (or more frequently) is going to be a worse wastage of resources - event pages are for things that you know will not happen regularly or frequently.
You should switch to a persistent background page and use good old setInterval
.
Ah, sorry, I did not immediately understand that you had a delay and not an interval. Then wOxxOm's answer fully applies.
UPDATE as of chrome 120, setting an alarm with less than 1 minute interval is possible. the docs says:
Chrome 120: Starting in Chrome 120, the minimum alarm interval has been reduced from 1 minute to 30 seconds. For an alarm to trigger in 30 seconds, set periodInMinutes: 0.5.
Upvotes: 2
Reputation: 73846
You're using an event page (non-persistent background page), which is unloaded after approximately 5 seconds of inactivity. Then some activity in the browser causes the background page to re-initialize and set a new alarm. So each 5 seconds that new alarm fires the handler that sends a message which makes the content script call hello()
.
Solution 1: check for some condition before invoking chrome.alarms.create
.
For example, if the real objective is to fire an alarm one time after the browser starts use onStartup event and set the alarm time with when
key:
chrome.runtime.onStartup.addListener(function() {
chrome.alarms.create('hello', {when: Date.now() + 60*1000});
});
Note that in a published extension the interval between the next alarm and the last fired alarm is at least 1 minute even if you specify a smaller value like 15 seconds (15*1000).
Solution 2 (a bad one): make the background page persistent by using "persistent": true
. It's bad because a persistent background page hogs the memory. However, as explained in Xan's answer, it's a perfect one in case you actually need to fire the alarm each 15 seconds.
Upvotes: 7
Reputation: 11
I think you need to specify the alarm name for onAlarm
.
chrome.alarms.create('hello', { periodInMinutes: 2.0 });
chrome.alarms.onAlarm.addListener(function(alarm) {
if (alarm.name == 'hello') {
// do your thing
}
}
Upvotes: 1