Category Archives: mozilla

Mozilla addons: jQuery Injection / Script File Injection

UPDATE: @ZER0 suggested to use data.url instead of data.load

In my last blog post I described different ways of interaction between content scripts and pages. One of them was to inject inline scripts in the page. Today I describe a way to inject scripts files such as jQuery in a page.

If the value or function you want to insert in the page is not dynamically generated (i.e. it never changes), you’d better put it in its own file. To do that, you simply need to retrieve the url of the script file from the addon code, pass it to the content script and then inject it.

Passing The URL

The script that you want to inject in the page should be stored in the “data” folder, just like a content script. The URL is retrieved with the usual data.url utility and then passed to a content script using “port.emit” / “port.on“.

// in main.js
require("page-mod").PageMod({
  include: "http://example.com/",
  contentScriptWhen: "start",
  contentScriptFile: data.url( "injecter.js" ),
  onAttach: function( worker ) {
    	worker.port.emit( "init", data.url( "toBeInjected.js" ) );
  }
});
// in injecter.js
...
self.port.on("init", function( scriptURL ) {
  // use the URL
  ...
});

Using an “init” event just to pass a value is rather annoying, but a “contentScriptGlobals” should be added to a future version of the SDK to simplify this, see bug 688127.

Injecting the Script

The code of the injecter is pretty straightforward.

// injecter.js
var script = document.createElement( "script" );
script.type = "text/javascript";

self.port.on("init", function( scriptURL ) {
  script.src = scriptURL;
  window.document.body.appendChild( script );
});

If you have a cleaner way to inject a script in a page, I’d love to hear from it!

Mozilla addons: Interactions between Content Scripts and pages

Addons created with Mozilla’s Addon SDK have a secure mean of communication with web pages: Content Scripts. Although the interaction between addons and content scripts is fairly well documented, this doc lacks some details about the range of possible interactions between content scripts and the page itself.

The window Wrapper

Content scripts have access to a window object which is actually only a wrapper around the DOM of the page. The entire DOM API is available, so you can manipulate the page at will, but variables and functions stored in the global scope of the page aren’t available:

// inline script in example.com/index.html
window.test = "value";
// main.js, our addon
require("page-mod").PageMod({
  include: ["*"],
  contentScriptWhen: "end",
  contentScript: "console.log( 'test: ' + window.test );"
});

When loading example.com/index.html, the previous page-mod will display “test: undefined” in the error console. Likewise, it is impossible to create a variable in the content script, and access it in the page.

// main.js, our addon
require("page-mod").PageMod({
  include: ["*"],
  contentScriptWhen: "start",
  contentScript: "window.test = 'value';"
});
// inline script in example.com/index.html
console.log( "test: " + window.test );

Again, the inline script will log “test: undefined“.

The SDK docs also demonstrates how easy it is to listen to mouse events in the page and pass them to the addon:

// content script loaded by the page-mod
contentScript =
  "window.addEventListener('click', function( event ) {"+
  "  self.port.emit('click', event.target.toString());"+
  "});";

Moar Interaction Pliz

Manipulating the DOM and waiting for mouse or key events is good, but what if you want to pass data to your page or receive data from it? what if you absolutely need to create variables or functions in the page?

The wrong way of doing so is to use the undocumented unsafeWindow object instead of the wrapped and secure window one. This completely defeats the security model of the addon SDK, and since it’s an undocumented feature, it could well disappear in a future update of the SDK.

The right way of doing so is to inject inline scripts in the page and/or use customEvents:

Inline Script Injection

Inline scripts are a third level of scripts (where 1O hours are a minute) that can be used to create variables or functions in the global scope:

// Quotes nesting would be a real mess now,
// let's use a separate file loaded as a contentScriptFile
var script = document.createElement( "script" );
script.innerHTML = "var test =" + JSON.stringify( anyValue )+";";
document.body.appendChild( script );

Validation of this code will output warnings, as addons shouldn’t create script tags. But this is still the safest alternative to the unsafeWindow.

customEvents

customEvents are very similar to mouse events, except that they are programmatically triggered, and that they can transport arbitrary (jsonable) data between content scripts and pages, in both directions:

// inline script in example.com/index.html
var evt = document.createEvent("CustomEvent");
evt.initCustomEvent( "transData", true, false, jsonableValue );
window.dispatchEvent(evt);
// in contentScript.js
window.addEventListener( "transData", function( event ) {
  // the data is available in the detail property of the event
  self.port.emit( "transData", event.detail );
});

I had to use both of these technics in my geolocation debugging addon (geo-devtool) to interact with the Google Maps API, and I’m pretty sure there are much more use cases.

PS: I’m willing to propose improvements to the SDK docs on this topic once the content of this blog post is validated by someone in the addon team.

Firefox Aurora: With Great Power Comes Great Freedom

This is a more detailed version of the article posted today on hacks, aimed at a more knowledgeable audience.

Aurora Logo
New features can only become stable and usable if you test them and push them to their limits. And you can only have fun playing with new features if it’s in a hassle- and risk-free way. You deserve better than a beta, you deserve Aurora.

What is Aurora?

Up to Firefox 4, Web authors only had limited options: either live in the quiet comfort of stable releases and wait months for new features to appear; or play Russian roulette with the nightly builds, exciting but painful. Beta releases aren’t filling the gap if we want to deliver features more often and increase their quality at the same time: we need more people to give us feedback and report bugs earlier. This implies to provide a safer environment to test features and a simpler way to switch to a more stable version of the browser (we call them channels).

Aurora is this safer environment.

6 Week Release Cycles!

New features added to Firefox are delivered on a daily basis through the nightly builds. Every six weeks, a new version of Aurora is delivered: it is roughly a nightly build, stripped of the features that are problematic or make Firefox unstable. During six weeks, Aurora will not be updated with new features, but will be updated with bug fixes on a daily basis. After six weeks, the features that are stable enough will land in the Beta channel, which receives weekly bug fixes. Another six weeks later, the features that are ready move from the Beta channel to the stable one: a new Firefox is born. The strictness of the quality control increases as features progress to later channels.

If you’re into fancy charts and technical details, have a look at the process specifics details. If you’re more into metaphors, think about the journey of a feature as the youth of a bird: engineers are our (free range) egg-laying chickens who want to see their features leave the nest, and you can help by watching over and taking care of the features during the gestation, brooding, rearing, and be as proud as we are to see them finally fly their own wings.

Switching between channels

Once you have downloaded and installed Aurora, you can switch to other channels at will. Simply click on the Help menu and open the About window.

Aurora About window

Firefox Aurora currently includes, amongst other nice improvements, CSS3 Animations, window.matchMedia and better tab-closing behavior. Give it a try and tell us what you think.

Busy September

My report was just handed-in, I was starting to feel relieved of all the pressure and the work… when I learned that I was going to give a talk at the jQuery conf in Boston and the MozCamp in Praha (in October actually, but in less than one month from now). I’ll be sponsored by Teesside University for Boston, and for Praha I don’t know but I’ve got good friends living over there, I’m not too worried.

No matter how great those news are, it means that I’ll have to prepare my talks and will thus have less time to work on ToDoSo. It doesn’t even mean that the project is on pause, since I will have to use a presentation software for at least one of these talks, and I’d like to use mine!

In September I’ll also have to move from Middlesbrough to Lyon and start to search for a real job!

You can expect to see new projects for the Open Web on this Blog, I’ll soon introduce the first version of “EventSound: audible jQuery events”.

Interact with your browser using language and signs / Ubiquity and firegesture.

Last Month, Mozilla introduced The design Challenge, an initiative aimed at provoking thought, facilitating discussion, and inspiring future design directions for Firefox, the Mozilla project, and the Web as a whole. The question of the current edition is What would a browser look like if the Web was all there was?. Aza Raskin and Alex Faaborg produced an interesting video to illustrate this question:

The Design Review Episode 2: Chromeless Browsing from Alex Faaborg on Vimeo.

I really liked the idea of a chromeless browser. This is actually what I’m trying to achieve on my own computer: From the browser I’ve removed everything except the menus, the tabs and the address bar, and I’ve moved the address bar next to the menus. Additionally I have removed the window decorations on my Ubuntu (thanks to compiz) as well as the “task bar” usually at the bottom of the screen.

after:

before:

The current solution is much more comfortable: It reduces the need of scrolling and the visual distractions are limited, therefore I can really focus on what is important: the content. You may wonder how I execute the actions that were bound to those buttons. Well, your keyboard and your mouse offer alternatives to those buttons:

  • You may have a “back” and “forward” button on your mouse or alternatively use your key board (respectively [alt +← ] and [alt + → ])
  • You can open a new tab with the [ctrl + T] combination
  • Stop loading the current page by hiting [esc] or refresh it with [F5]
  • Open your home page using [alt + Home/↖]

And the new address bar or Firefox 3.0 (which I hope you are all using), the so called awesome bar, provides a way to tag your favourite Web pages, to search your history and favourites and to search the entire Web using any search engine. I won’t teach you how to do that, and I don’t even expect you to remember those keyboard short-cuts. What I’m trying to show is that non-graphical User Interface (the keyboard and the mouse) are suitable alternative to Graphical User Interface. The user is already familiar with them, and they don’t take any space on the screen :-)

Those peripherals have a lot of potential to provide a flawless chromless browsing experience to the user, but we need to make it natural for the end-user to use them that way. I would never recommend to ship my own customized Firefox to any one else… than myself. Configuring search engines in the awesome bar is still a pain (you probably don’t know how to add a new search engine, and how to assign it a keyword), remembering keyboard short-cuts will always be a pain and you may not have a “back” and “forward” button on your mouse.

What is then the most natural way to use your keyboard to interact with your browser? Wouldn’t it be great if the computer was able to understand what you ask it in your own language? This is exactly what one of the newest project from Mozilla labs has been created for: Ubiquity. Ubiquity is still in an early stage of development and may only appear as a cool command line to create mash-ups for geeks with a twitter and gmail account (if you don’t understand this sentence it means that you are not exactly the target user for this tool). However, the aim of Ubiquity is to allow you to type “search wikipedia in French for ratatouille”, “translate raison d’être from French to English” or even “create mail for Lorenzo”. Currently verbs are not implemented in Ubiquity, therefore a search command looks more like “wikipedia in French ratatouille” (which can also be written “wi in fr raratouille”). But this is a work in progress!

You will soon be able to talk to your browser, how could execute actions such as “forward”, “back” or “home” without any button? Language is an evolved and abstract way of communication, but signs could be sufficient for such simple actions. Good thing is, it is already possible to interact with your browsers using “mouse gestures” thanks to Firegesture. When this extension is installed, you can simply press the right button of your mouse and start to move your mouse to execute an action (move it to the left to go to the previous page for example).

I believe that a chromeless browser needs those two naturals means of communication with the browser: language and signs. I hope I will soon have the time to prototype a browser based on Ubiquity and Firegesture.

PS: By the way I started to develop an Ubiquity command for Wordreference, currently available on etherpad. It’s also a work in progress : )