Reputation: 1075
I'm having problems getting some setup code executed when my extension is installed. I'm using chrome.runtime.onInstalled as suggested by Chrome Developers' page, but it is not firing. It seems that the issue is related with the use of Require.JS. This is my code:
requirejs.config({...});// i'll not reproduce the whole config here for brevity
// Define the Global Object that will hold the extension functionality
var EXT = EXT || {};
// Start the main app logic.
requirejs(['chrome.storage', 'chrome.settings', 'chrome.tabs'],
function (chromeStorage, chromeSettings, chromeTabs) {
'use strict';
var getLocalRepos;
/**
* Executes the callback with an array of repositories as the parameter.
* @param {function} callback
*/
getLocalRepos = function (callback) {
'use strict';
chromeStorage.get('localRepos', callback);
};
// Take care of the extension lifecycle.
chrome.runtime.onInstalled.addListener(function (details) {
"use strict";
// Create dummy data to populate the local storage for testing purposes.
var dummyData = [
{
name: 'repo1',
description: 'description1',
username: 'reydel',
age: 'theAge'
},
{
name: 'repo2',
description: 'description2',
username: 'reydel',
age: 'theAge'
}
];
switch (details.reason) {
case 'install':
chromeStorage.set({ localRepos: dummyData }, function () {
// Do nothing
});
break;
}
});
// Bind all functions to an object in the Global Space to make them accessible from the outside scripts
// referencing the BackgroundPage object
window.EXT.getLocalRepos = getLocalRepos;
});
I have used the code inside the listener's callback in the console and it works, it's just that the event is not being triggered.
Any ideas on how to solve this? Someone have done it before?
Upvotes: 4
Views: 2389
Reputation: 348992
The chrome.runtime.onInstalled
event is fired directly after loading your code. When you add an event listener asynchronously, then the onInstalled
event has already been dispatched when you add the event listener.
To solve this issue, you have to make the initialization of your app synchronous. Unfortunately, require.js is designed to be an asynchronous script loader. Modifying this library to make it synchronous is possible, but a waste of efforts without any benefits.
To use require-style modules (AMD) in a Chrome extension, I strongly recommend to use an intermediate build step that combines the scripts (such as r.js or grunt-contrib-requirejs), and almond.js as script loader. Contrary to require.js, almond.js does support synchronous loading.
Here's an example of a config that you can use to build a single file called all.js
that contains almond.js (as script loader), and uses mymain.js
as entry point (main script):
({
name: 'mymain',
out: 'all.js',
include: [
'almond'
],
skipModuleInsertion: true,
wrap: {
start: '(function(){',
// true = load synchronously. This is a feature of almond.js
end: 'require(["mymain"], null, null, true);})();'
}
})
To avoid namespace pollution, I've wrapped the code in a n immediately-invoked function expression. If you want the modules to be available in the global namespace (e.g. for debugging), just remove the (function(){
and })();
.
For documentation of these configuration options (and more), see https://github.com/jrburke/r.js/blob/master/build/example.build.js.
To try out the previous example:
r.js
: npm install -g requirejs
myfancyname.build.js
mymain.js
: define(function() { ... });
.r.js -o myfancyname.build.js
all.js
that can be loaded, e.g. by using "background": { "scripts": ["all.js"] }
in the manifest file of your Chrome extension.Upvotes: 6