Mozilla Nederland LogoDe Nederlandse

Mike Hommey: Announcing git-cinnabar 0.3.2

Mozilla planet - do, 28/04/2016 - 00:42

Git-cinnabar is a git remote helper to interact with mercurial repositories. It allows to clone, pull and push from/to mercurial remote repositories, using git.

Get it on github.

These release notes are also available on the git-cinnabar wiki.

This is mostly a bug and regression-fixing release.

What’s new since 0.3.1?
  • Fixed a performance regression when cloning big repositories on OSX.
  • git configuration items with line breaks are now supported.
  • Fixed a number of issues with corner cases in mercurial data (such as, but not limited to nodes with no first parent, malformed .hgtags, etc.)
  • Fixed a stack overflow, a buffer overflow and a use-after free in cinnabar-helper.
  • Better work with git worktrees, or when called from subdirectories.
  • Updated git to 2.7.4 for cinnabar-helper.
  • Properly remove all refs meant to be removed when using git version lower than 2.1.
Categorieën: Mozilla-nl planet

Mozilla Firefox 46.0 Lands in All Supported Ubuntu OSes with GTK3 Integration - Softpedia News

Nieuws verzameld via Google - do, 28/04/2016 - 00:23

Softpedia News

Mozilla Firefox 46.0 Lands in All Supported Ubuntu OSes with GTK3 Integration
Softpedia News
We reported the other day that Mozilla released version 46.0 of its Firefox web browser, which happens to be a very important milestone for GNU/Linux users, as it finally brings the long-anticipated GTK3 integration. Mozilla Firefox 46.0 is a pretty ...
Mozilla patches 4 critical vulnerabilities with the release of Firefox
Google Chrome VS Mozilla FirefoxThe World Beast (blog)
Firefox 46 Tackles Security Issues, Improves
Threatpost -VentureBeat -Android Headlines - Android News
alle 15 nieuwsartikelen »
Categorieën: Mozilla-nl planet

Mozilla Addons Blog: Join the Featured Add-ons Community Board

Mozilla planet - do, 28/04/2016 - 00:14

Are you a big fan of add-ons? Think you can help help identify the best content to spotlight on AMO? Then let’s talk!

All the add-ons featured on (AMO) are selected by a board of community members. Each board consists of 5-8 members who nominate and select featured add-ons once a month for six months. Featured add-ons help users discover what’s new and useful, and downloads increase dramatically in the months they’re featured, so your participation really makes an impact.

And now the time has come to assemble a new board for the months July – December.

Anyone from the add-ons community is welcome to apply: power users, theme designers, developers, and evangelists. Priority will be given to applicants who have not served on the board before, followed by those from previous boards, and finally from the outgoing board. This page provides more information on the duties of a board member. To be considered, please email us at with your name, and tell us how you’re involved with AMO. The deadline is Friday, May 10, 2016 at 23:59 PDT. The new board will be announced about a week after.

We look forward to hearing from you!

Categorieën: Mozilla-nl planet

What’s New in Firefox Beta

Mozilla Futurereleases - wo, 27/04/2016 - 22:55

Today’s beta release of Firefox features a tool to view the open tabs that are synced across your desktop and mobile instances of Firefox.

Updates to Firefox for Android focus on a set of design changes that will make browsing safer and simpler for our users.

More information:

Categorieën: Mozilla-nl planet

Michael Kaply: Broken Add-ons in Firefox 46

Mozilla planet - wo, 27/04/2016 - 19:59

A lot of add-ons are being broken by a subtle change in Firefox 46, in particular the removal of legacy array/generator comprehension.

Most of these add-ons (including mine) did not use array comprehension intentionally, but they copied some code from this page on for doing an md5 hash of a string. It looked like this:

var s = [toHexString(hash.charCodeAt(i)) for (i in hash)].join("");

You should search through your source code for toHexString and make sure you aren’t using this. MDN was updated in January to fix this. Here’s what the new code looks like:

var s = Array.from(hash, (c, i) => toHexString(hash.charCodeAt(i))).join("");

The new code will only work in Firefox 32 and beyond. If for some reason you need an older version, you can go through the history of the page to find the array based version.

Using this old code will cause a syntax error, so it will cause much more breakage than you realize. You’ll want to get it fixed sooner than later because Firefox 46 started rolling out yesterday.

As a side note, Giorgio Maone caught this in January, but unfortunately all that was updated was the MDN page.

Categorieën: Mozilla-nl planet

Air Mozilla: The Joy of Coding - Episode 55

Mozilla planet - wo, 27/04/2016 - 19:00

The Joy of Coding - Episode 55 mconley livehacks on real Firefox bugs while thinking aloud.

Categorieën: Mozilla-nl planet

Air Mozilla: April 2016 Speaker Series: When Change is the Only Constant, Org Structure Doesn't Matter - Kirsten Wolberg

Mozilla planet - wo, 27/04/2016 - 19:00

 When Change is the Only Constant, Org Structure Doesn't Matter - Kirsten Wolberg Regardless of whether an organization is decentralized or command & control, large-scale changes are never simple nor straightforward. There's no silver bullets. And yet, when...

Categorieën: Mozilla-nl planet

Rail Aliiev: Firefox 46.0 and SHA512SUMS

Mozilla planet - wo, 27/04/2016 - 18:47

In my previous post I introduced the new release process we have been adopting in the 46.0 release cycle.

Release build promotion has been in production since Firefox 46.0 Beta 1. We have discovered some minor issues; some of them are already fixed, some still waiting.

One of the visible bugs is Bug 1260892. We generate a big SHA512SUMS file, which should contain all important checksums. With numerous changes to the process the file doesn't represent all required files anymore. Some files are missing, some have different names.

We are working on fixing the bug, but you can use the following work around to verify the files.

For example, if you want to verify, you need use the following 2 files:

Example commands:

# download all required files $ wget -q $ wget -q $ wget -q $ wget -q # Import Mozilla Releng key into a temporary GPG directory $ mkdir .tmp-gpg-home && chmod 700 .tmp-gpg-home $ gpg --homedir .tmp-gpg-home --import KEY # verify the signature of the checksums file $ gpg --homedir .tmp-gpg-home --verify firefox-46.0.checksums.asc && echo "OK" || echo "Not OK" # calculate the SHA512 checksum of the file $ sha512sum "Firefox Setup 46.0.exe" c2ed64298ac2140d8dbdaed28cabc90b38dd9444e9c0d6dd335a2a32cf043a35314945536a5c75124a88bf418a4e2ba77256be223425380e7fcc45a97da8f479 Firefox Setup 46.0.exe # lookup for the checksum in the checksums file $ grep c2ed64298ac2140d8dbdaed28cabc90b38dd9444e9c0d6dd335a2a32cf043a35314945536a5c75124a88bf418a4e2ba77256be223425380e7fcc45a97da8f479 firefox-46.0.checksums c2ed64298ac2140d8dbdaed28cabc90b38dd9444e9c0d6dd335a2a32cf043a35314945536a5c75124a88bf418a4e2ba77256be223425380e7fcc45a97da8f479 sha512 46275456 install/sea/firefox-46.0.ach.win64.installer.exe

This is just a temporary work around and the bug will be fixed ASAP.

Categorieën: Mozilla-nl planet

Air Mozilla: SuMo Community Call 27th April 2016

Mozilla planet - wo, 27/04/2016 - 18:00

SuMo Community Call 27th April 2016 This is the sumo weekly call We meet as a community every Wednesday 17:00 - 17:30 UTC The etherpad is here:

Categorieën: Mozilla-nl planet

Niko Matsakis: Non-lexical lifetimes: introduction

Mozilla planet - wo, 27/04/2016 - 16:52

Over the last few weeks, I’ve been devoting my free time to fleshing out the theory behind non-lexical lifetimes (NLL). I think I’ve arrived at a pretty good point and I plan to write various posts talking about it. Before getting into the details, though, I wanted to start out with a post that lays out roughly how today’s lexical lifetimes work and gives several examples of problem cases that we would like to solve.

The basic idea of the borrow checker is that values may not be mutated or moved while they are borrowed. But how do we know whether a value is borrowed? The idea is quite simple: whenever you create a borrow, the compiler assigns the resulting reference a lifetime. This lifetime corresponds to the span of the code where the reference may be used. The compiler will infer this lifetime to be the smallest lifetime that it can that still encompasses all the uses of the reference.

Note that Rust uses the term lifetime in a very particular way. In everyday speech, the word lifetime can be used in two distinct – but similar – ways:

  1. The lifetime of a reference, corresponding to the span of time in which that reference is used.
  2. The lifetime of a value, corresponding to the span of time before that value gets freed (or, put another way, before the destructor for the value runs).

This second span of time, which describes how long a value is valid, is of course very important. We refer to that span of time as the value’s scope. Naturally, lifetimes and scopes are linked to one another. Specifically, if you make a reference to a value, the lifetime of that reference cannot outlive the scope of that value, Otherwise your reference would be pointing into free memory.

To better see the distinction between lifetime and scope, let’s consider a simple example. In this example, the vector data is borrowed (mutably) and the resulting reference is passed to a function capitalize. Since capitalize does not return the reference back, the lifetime of this borrow will be confined to just that call. The scope of data, in contrast, is much larger, and corresponds to a suffix of the fn body, stretching from the let until the end of the enclosing scope.

1 2 3 4 5 6 7 8 9 10 11 12 fn foo() { let mut data = vec!['a', 'b', 'c']; // --+ 'scope capitalize(&mut data[..]); // | // ^~~~~~~~~~~~~~~~~~~~~~~~~ 'lifetime // | data.push('d'); // | data.push('e'); // | data.push('f'); // | } // <---------------------------------------+ fn capitalize(data: &mut [char]) { // do something }

This example also demonstrates something else. Lifetimes in Rust today are quite a bit more flexible than scopes (if not as flexible as we might like, hence this RFC):

  • A scope generally corresponds to some block (or, more specifically, a suffix of a block that stretches from the let until the end of the enclosing block) [1].
  • A lifetime, in contrast, can also span an individual expression, as this example demonstrates. The lifetime of the borrow in the example is confined to just the call to capitalize, and doesn’t extend into the rest of the block. This is why the calls to data.push that come below are legal.

So long as a reference is only used within one statement, today’s lifetimes are typically adequate. Problems arise however when you have a reference that spans multiple statements. In that case, the compiler requires the lifetime to be the innermost expression (which is often a block) that encloses both statements, and that is typically much bigger than is really necessary or desired. Let’s look at some example problem cases. Later on, we’ll see how non-lexical lifetimes fixes these cases.

Problem case #1: references assigned into a variable

One common problem case is when a reference is assigned into a variable. Consider this trivial variation of the previous example, where the &mut data[..] slice is not passed directly to capitalize, but is instead stored into a local variable:

1 2 3 4 5 6 7 8 fn bar() { let mut data = vec!['a', 'b', 'c']; let slice = &mut data[..]; // <-+ 'lifetime capitalize(slice); // | data.push('d'); // ERROR! // | data.push('e'); // ERROR! // | data.push('f'); // ERROR! // | } // <------------------------------+

The way that the compiler currently works, assigning a reference into a variable means that its lifetime must be as large as the entire scope of that variable. In this case, that means the lifetime is now extended all the way until the end of the block. This in turn means that the calls to data.push are now in error, because they occur during the lifetime of slice. It’s logical, but it’s annoying.

In this particular case, you could resolve the problem by putting slice into its own block:

1 2 3 4 5 6 7 8 9 10 fn bar() { let mut data = vec!['a', 'b', 'c']; { let slice = &mut data[..]; // <-+ 'lifetime capitalize(slice); // | } // <------------------------------+ data.push('d'); // OK data.push('e'); // OK data.push('f'); // OK }

Since we introduced a new block, the scope of slice is now smaller, and hence the resulting lifetime is smaller. Of course, introducing a block like this is kind of artificial and also not an entirely obvious solution.

Problem case #2: conditional control flow

Another common problem case is when references are used in only match arm. This most commonly arises around maps. Consider this function, which, given some key, processes the value found in map[key] if it exists, or else inserts a default value:

1 2 3 4 5 6 7 8 9 10 fn process_or_default<K,V:Default>(map: &mut HashMap<K,V>, key: K) { match map.get_mut(&key) { // -------------+ 'lifetime Some(value) => process(value), // | None => { // | map.insert(key, V::default()); // | // ^~~~~~ ERROR. // | } // | } // <------------------------------------+ }

This code will not compile today. The reason is that the map is borrowed as part of the call to get_mut, and that borrow must encompass not only the call to get_mut, but also the Some branch of the match. The innermost expression that encloses both of these expressions is the match itself (as depicted above), and hence the borrow is considered to extend until the end of the match. Unfortunately, the match encloses not only the Some branch, but also the None branch, and hence when we go to insert into the map in the None branch, we get an error that the map is still borrowed.

This particular example is relatively easy to workaround. One can (frequently) move the code for None out from the match like so:

1 2 3 4 5 6 7 8 9 10 11 12 fn process_or_default1<K,V:Default>(map: &mut HashMap<K,V>, key: K) { match map.get_mut(&key) { // -------------+ 'lifetime Some(value) => { // | process(value); // | return; // | } // | None => { // | } // | } // <------------------------------------+ map.insert(key, V::default()); }

When the code is adjusted this way, the call to map.insert is not part of the match, and hence it is not part of the borrow. While this works, it is of course unfortunate to require these sorts of manipulations, just as it was when we introduced an artificial block in the previous example.

Problem case #3: conditional control flow across functions

While we were able to work around problem case #2 in a relatively simple, if irritating, fashion. there are other variations of conditional control flow that cannot be so easily resolved. This is particularly true when you are returning a reference out of a function. Consider the following function, which returns the value for a key if it exists, and inserts a new value otherwise (for the purposes of this section, assume that the entry API for maps does not exist):

1 2 3 4 5 6 7 8 9 10 11 12 fn get_default<'m,K,V:Default>(map: &'m mut HashMap<K,V>, key: K) -> &'m mut V { match map.get_mut(&key) { // -------------+ 'm Some(value) => value, // | None => { // | map.insert(key, V::default()); // | // ^~~~~~ ERROR // | map.get_mut(&key).unwrap() // | } // | } // | } // v

At first glance, this code appears quite similar the code we saw before. And indeed, just as before, it will not compile. But in fact the lifetimes at play are quite different. The reason is that, in the Some branch, the value is being returned out to the caller. Since value is a reference into the map, this implies that the map will remain borrowed until some point in the caller (the point 'm, to be exact). To get a better intuition for what this lifetime parameter 'm represents, consider some hypothetical caller of get_default: the lifetime 'm then represents the span of code in which that caller will use the resulting reference:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fn caller() { let mut map = HashMap::new(); ... { let v = get_default(&mut map, key); // -+ 'm // +-- get_default() -----------+ // | // | match map.get_mut(&key) { | // | // | Some(value) => value, | // | // | None => { | // | // | .. | // | // | } | // | // +----------------------------+ // | process(v); // | } // <--------------------------------------+ ... }

If we attempt the same workaround for this case that we tried in the previous example, we will find that it does not work:

1 2 3 4 5 6 7 8 9 10 11 fn get_default1<'m,K,V:Default>(map: &'m mut HashMap<K,V>, key: K) -> &'m mut V { match map.get_mut(&key) { // -------------+ 'm Some(value) => return value, // | None => { } // | } // | map.insert(key, V::default()); // | // ^~~~~~ ERROR (still) | map.get_mut(&key).unwrap() // | } // v

Whereas before the lifetime of value was confined to the match, this new lifetime extends out into the caller, and therefore the borrow does not end just because we exited the match. Hence it is still in scope when we attempt to call insert after the match.

The workaround for this problem is a bit more involved. It relies on the fact that the borrow checker uses the precise control-flow of the function to determine what borrows are in scope.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fn get_default2<'m,K,V:Default>(map: &'m mut HashMap<K,V>, key: K) -> &'m mut V { if map.contains(&key) { // ^~~~~~~~~~~~~~~~~~ 'n return match map.get_mut(&key) { // + 'm Some(value) => value, // | None => unreachable!() // | }; // v } // At this point, `map.get_mut` was never // called! (As opposed to having been called, // but its result no longer being in use.) map.insert(key, V::default()); // OK now. map.get_mut(&key).unwrap() }

What has changed here is that we moved the call to map.get_mut inside of an if, and we have set things up so that the if body unconditionally returns. What this means is that a borrow begins at the point of get_mut, and that borrow lasts until the point 'm in the caller, but the borrow checker can see that this borrow will not have even started outside of the if. So it does not consider the borrow in scope at the point where we call map.insert.

This workaround is more troublesome than the others, because the resulting code is actually less efficient at runtime, since it must do multiple lookups.

It’s worth noting that Rust’s hashmaps include an entry API that one could use to implement this function today. The resulting code is both nicer to read and more efficient even than the original version, since it avoids extra lookups on the not present path as well:

1 2 3 4 5 6 fn get_default3<'m,K,V:Default>(map: &'m mut HashMap<K,V>, key: K) -> &'m mut V { map.entry(key) .or_insert_with(|| V::default()) }

Regardless, the problem exists for other data structures besides HashMap, so it would be nice if the original code passed the borrow checker, even if in practice using the entry API would be preferable. (Interestingly, the limitation of the borrow checker here was one of the motivations for developing the entry API in the first place!)


This post looked at various examples of Rust code that do not compile today, and showed how they can be fixed using today’s system. While it’s good that workarounds exist, it’d be better if the code just compiled as is. In an upcoming post, I will outline my plan for how to modify the compiler to achieve just that.


1. Scopes always correspond to blocks with one exception: the scope of a temporary value is sometimes the enclosing statement.

Categorieën: Mozilla-nl planet

Mozilla Firefox Co-Creator Says He Can't Visualize Images: What You Need To ... - Tech Times

Nieuws verzameld via Google - wo, 27/04/2016 - 14:47

Tech Times

Mozilla Firefox Co-Creator Says He Can't Visualize Images: What You Need To ...
Tech Times
Internet browser Mozilla Firefox co-creator Blake Ross shared in a Facebook post that he suffers from aphantasia, a condition that renders him unable to picture mental images. Ross penned an essay that detailed the struggles that he had to face. He ...
Living with aphantasiaThe Statesman

alle 3 nieuwsartikelen »
Categorieën: Mozilla-nl planet

Mozilla patches 4 critical vulnerabilities with the release of Firefox 46 -

Nieuws verzameld via Google - wo, 27/04/2016 - 14:17

The World Beast (blog)

Mozilla patches 4 critical vulnerabilities with the release of Firefox 46
Mozilla today released Firefox 46 which fixes 14 vulnerabilities of which 4 have been marked critical. Some of the critical vulnerabilities showed evidence of memory corruption which according to Mozilla would allow them to be exploited to run ...
Google Chrome VS Mozilla FirefoxThe World Beast (blog)
Mozilla Firefox 46.0 Now Available for Download with GTK3 Integration for LinuxSoftpedia News (blog)
Firefox 46 arrives with performance and security improvements, drops support ...VentureBeat
Android Headlines - Android News -BetaNews -OStatic (blog)
alle 10 nieuwsartikelen »Google Nieuws
Categorieën: Mozilla-nl planet

Mozilla Firefox 46.0 - Tweakers

Nieuws verzameld via Google - wo, 27/04/2016 - 12:07


Mozilla Firefox 46.0
Mozilla Firefox 2013 logo (75 pix) Mozilla heeft versie 46 van zijn webbrowser Firefox uitgebracht. In versie 46 zijn onder meer aanpassingen in de Just In Time-compiler aangebracht die de beveiliging ten goede moeten komen, is er gtk3-integratie op de ...

Categorieën: Mozilla-nl planet

Air Mozilla: Bay Area Rust Meetup April 2016

Mozilla planet - wo, 27/04/2016 - 04:00

Bay Area Rust Meetup April 2016 Rust meetup on the subject of operating systems.

Categorieën: Mozilla-nl planet

Air Mozilla: Connected Devices Weekly Program Review, 26 Apr 2016

Mozilla planet - di, 26/04/2016 - 19:00

Connected Devices Weekly Program Review Weekly project updates from the Mozilla Connected Devices team.

Categorieën: Mozilla-nl planet

Richard Newman: Different kinds of storage

Mozilla planet - di, 26/04/2016 - 18:59

I’ve been spending most of my time so far on Project Tofino thinking about how a user agent stores data.

A user agent is software that mediates your interaction with the world. A web browser is one particular kind of user agent: one that fetches parts of the web and shows them to you.

(As a sidenote: browsers are incredibly complicated, not just for the obvious reasons of document rendering and navigation, but also because parts of the web need to run code on your machine and parts of it are actively trying to attack and track you. One of a browser’s responsibilities is to keep you safe from the web.)

Chewing on Redux, separation of concerns, and Electron’s process model led to us drawing a distinction between a kind of ‘profile service’ and the front-end browser itself, with ‘profile’ defined as the data stored and used by a traditional browser window. You can see the guts of this distinction in some of our development docs.

The profile service stores full persistent history and data like it. The front-end, by contrast, has a pure Redux data model that’s much closer to what it needs to show UI — e.g., rather than all of the user’s starred pages, just a list of the user’s five most recent.

The front-end is responsible for fetching pages and showing the UI around them. The back-end service is responsible for storing data and answering questions about it from the front-end.

To build that persistent storage we opted for a mostly event-based model: simple, declarative statements about the user’s activity, stored in SQLite. SQLite gives us durability and known performance characteristics in an embedded database.

On top of this we can layer various views (materialized or not). The profile service takes commands as input and pushes out diffs, and the storage itself handles writes by logging events and answering queries through views. This is the CQRS concept applied to an embedded store: we use different representations for readers and writers, so we can think more clearly about the transformations between them.

Where next?

One of the reasons we have a separate service is to acknowledge that it might stick around when there are no browser windows open, and that it might be doing work other than serving the immediate needs of a browser window. Perhaps the service is pre-fetching pages, or synchronizing your data in the background, or trying to figure out what you want to read next. Perhaps you can interact with the service from something other than a browser window!

Some of those things need different kinds of storage. Ad hoc integrations might be best served by a document store; recommendations might warrant some kind of graph database.

When we look through that lens we no longer have just a profile service wrapping profile storage. We have a more general user agent service, and one of the data sources it manages is your profile data.

Categorieën: Mozilla-nl planet

Mozilla Addons Blog: Migrating Popup ALT Attribute from XUL/XPCOM to WebExtensions

Mozilla planet - di, 26/04/2016 - 18:27

Today’s post comes from Piro, the developer of Popup ALT Attribute, in addition to 40 other add-ons. He shares his thoughts about migrating XUL/XPCOM add-ons to WebExtensions, and shows us how he did it with Popup ALT Attribute. You can see the full text of this post on his personal blog.


Hello, add-on developers. My name is YUKI Hiroshi aka Piro, a developer of Firefox add-ons. For many years I developed Firefox and Thunderbird add-ons personally and for business, based on XUL and XPCOM.

I recently started to research the APIs are required to migrate my add-ons to WebExtensions, because Mozilla announced that XUL/XPCOM add-ons will be deprecated at the end of 2017. I realized that only some add-ons can be migrated with currently available APIs, and
Popup ALT Attribute is one such add-on.

Here is the story of how I migrated it.

What’s the add-on?

Popup ALT Attribute is an ancient add-on started in 2002, to show what is written in the alt attribute of img HTML elements on web pages. By default, Firefox shows only the title attribute as a tooltip.

Initially, the add-on was implemented to replace an internal function FillInHTMLTooltip() of Firefox itself.

In February 2016, I migrated it to be e10s-compatible. It is worth noting that depending on your add-on, if you can migrate it directly to WebExtensions, it will be e10s-compatible by default.

Re-formatting in the WebExtensions style

I read the tutorial on how to build a new simple WebExtensions-based add-on from scratch before migration, and I realized that bootstrapped extensions are similar to WebExtensions add-ons:

  • They are dynamically installed and uninstalled.
  • They are mainly based on JavaScript code and some static manifest files.

My add-on was easily re-formatted as a WebExtensions add-on, because I already migrated it to bootstrapped.

This is the initial version of the manifest.json I wrote. There were no localization and options UI:

{ "manifest_version": 2, "name": "Popup ALT Attribute", "version": "4.0a1", "description": "Popups alternate texts of images or others like NetscapeCommunicator(Navigator) 4.x, and show long descriptions in the multi-row tooltip.", "icons": { "32": "icons/icon.png" }, "applications": { "gecko": { "id": "{61FD08D8-A2CB-46c0-B36D-3F531AC53C12}", "strict_min_version": "48.0a1" } }, "content_scripts": [ { "all_frames": true, "matches": ["<all_urls>"], "js": ["content_scripts/content.js"], "run_at": "document_start" } ] }

I had already separated the main script to a frame script and a loader for it. On the other hand, manifest.json can have some manifest keys to describe how scripts are loaded. It means that I don’t need to put my custom loaders in the package anymore. Actually, a script for any web page can be loaded with the content_scripts rule in the above sample. See the documentation for content_scripts for more details.

So finally only 3 files were left.


+ install.rdf + icon.png + [components] + [modules] + [content] + content-utils.js

And after:

+ manifest.json (migrated from install.rdf) + [icons] | + icon.png (moved) + [content_scripts] + content.js (moved and migrated from content-utils.js)

And I still had to isolate my frame script from XPCOM.

  • The script touched nsIPrefBranch and some XPCOM components via XPConnect, so they were temporarily commented out.
  • User preferences were not available and only default configurations were there as fixed values.
  • Some constant properties accessed, like Ci.nsIDOMNode.ELEMENT_NODE, had to be replaced as Node.ELEMENT_NODE.
  • The listener for mousemove events from web pages was attached to the global namespace for a frame script, but it was re-attached to the document itself of each web page, because the script was now executed on each web page directly.

For the old install.rdf I had a localized description. In WebExtensions add-ons I had to do it in different way. See how to localize messages for details. In short I did the following:

Added files to define localized descriptions:

+ manifest.json + [icons] + [content_scripts] + [_locales] + [en_US] | + messages.json (added) + [ja] + messages.json (added)

Note, en_US is different from en-US in install.rdf.

English locale, _locales/en_US/messages.json was:

{ "name": { "message": "Popup ALT Attribute" }, "description": { "message": "Popups alternate texts of images or others like NetscapeCommunicator(Navigator) 4.x, and show long descriptions in the multi-row tooltip." } }

Japanese locale, _locales/ja/messages.json was also included. And, I had to update my manifest.json to embed localized messages:

{ "manifest_version": 2, "name": "__MSG_name__", "version": "4.0a1", "description": "__MSG_description__", "default_locale": "en_US", ...

__MSG_****__ in string values are automatically replaced to localized messages. You need to specify the default locale manually via the default_locale key.

Sadly, Firefox 45 does not support the localization feature, so you need to use Nightly 48.0a1 or newer to try localization.

User preferences

Currently, WebExtensions does not provide any feature completely compatible to nsIPrefBranch. Instead, there are simple storage APIs. It can be used like an alternative of nsIPrefBranch to set/get user preferences. This add-on had no configuration UI but had some secret preferences to control its advanced features, so I did it for future migrations of my other add-ons, as a trial.

Then I encountered a large limitation: the storage API is not available in content scripts. I had to create a background script just to access the storage, and communicate with it via the inter-sandboxes messaging system. [Updated 4/27/16: bug 1197346 has been fixed on Nightly 49.0a1, so now you don’t need any hack to access the storage system from content scripts anymore. Now, my library (Configs.js) just provides easy access for configuration values instead of the native storage API.]

Finally, I created a tiny library to do that. I don’t describe how I did it here, but if you hope to know details, please see the source. There are just 177 lines.

I had to update my manifest.json to use the library from both the background page and the content script, like:

"background": { "scripts": [ "common/Configs.js", /* the library itself */ "common/common.js" /* codes to use the library */ ] }, "content_scripts": [ { "all_frames": true, "matches": ["<all_urls>"], "js": [ "common/Configs.js", /* the library itself */ "common/common.js", /* codes to use the library */ "content_scripts/content.js" ], "run_at": "document_start" } ]

Scripts listed in the same section share a namespace for the section. I didn’t have to write any code like require() to load a script from others. Instead, I had to be careful about the listing order of scripts, and wrote a script requiring a library after the library itself, in each list.

One last problem was: how to do something like the about:config or the MCD — general methods to control secret preferences across add-ons.

For my business clients, I usually provide add-ons and use MCD to lock their configurations. (There are some common requirements for business use of Firefox, so combinations of add-ons and MCD are more reasonable than creating private builds of Firefox with different configurations for each client.)

I think I still have to research around this point.

Options UI

WebExtensions provides a feature to create options pages for add-ons. It is also not supported on Firefox 45, so you need to use Nightly 48.0a1 for now. As I previously said, this add-on didn’t have its configuration UI, but I implemented it as a trial.

In XUL/XPCOM add-ons, rich UI elements like <checkbox>, <textbox>, <menulist>, and more are available, but these are going away at the end of next year. So I had to implement a custom configuration UI based on pure HTML and JavaScript. (If you need more rich UI elements, some known libraries for web applications will help you.)

On this step I created two libraries:


I’ve successfully migrated my Popup ALT Attribute add-on from XUL/XPCOM to WebExtensions. Now it is just a branch but I’ll release it after Firefox 48 is available.

Here are reasons why I could do it:

  • It was a bootstrapped add-on, so I had already isolated the add-on from all destructive changes.
  • The core implementation of the add-on was similar to a simple user script. Essential actions of the add-on were enclosed inside the content area, and no privilege was required to do that.

However, it is a rare case for me. My other 40+ add-ons require some privilege, and/or they work outside the content area. Most of my cases are such non-typical add-ons.

I have to do triage, plan, and request new APIs not only for me but for other XUL/XPCOM add-on developers also.

Thank you for reading.

Categorieën: Mozilla-nl planet

The Mozilla Blog: Update to Firefox Released Today

Mozilla planet - di, 26/04/2016 - 17:45

The latest version of Firefox was released today. It features an improved look and feel for Linux users, a minor security improvement and additional updates for all Firefox users.

The update to Firefox for Android features minor changes, including an improvement to user notifications and clearer homescreen shortcut icons.

More information:

Categorieën: Mozilla-nl planet

Update to Firefox Released Today

Mozilla Blog - di, 26/04/2016 - 17:45

The latest version of Firefox was released today. It features an improved look and feel for Linux users, a minor security improvement and additional updates for all Firefox users.

The update to Firefox for Android features minor changes, including an improvement to user notifications and clearer homescreen shortcut icons.

More information:

Categorieën: Mozilla-nl planet

Mozilla: Firefox 46 erkennt Webkit-Präfixe -

Nieuws verzameld via Google - di, 26/04/2016 - 17:37

Mozilla: Firefox 46 erkennt Webkit-Präfixe
Firefox umgeht die damit verbundenen Fehler nun, indem einige CSS-Funktionen und DOM-APIs mit Webkit-Präfixen als solche erkannt werden und der Browser dann das gewünschte Ergebnis anzeigt. Die so von Mozilla angestrebte Kompatibilität ist auch ...
Neuer Mozilla Firefox unterstützt Webkit-PräfixeHardwareLuxx

alle 2 nieuwsartikelen »Google Nieuws
Categorieën: Mozilla-nl planet