Florian Quèze

To content | To menu | To search

Tuesday, December 5 2017

Catching flickering regressions

For Firefox 57, as part of the Photon Performance project, one of the things we worked on was dramatically reducing flickering in the main browser window. We focused especially on what happens when opening the first browser window during startup, and when opening new browser windows.

To identify bugs, we looked frame by frame at video recordings. This was good enough to file bugs for an initial exploration, but was time consuming, and won't help us to keep these interactions flicker free going forward.

I'm happy to announce that these two interactions are now covered by automated flickering tests that will catch any regression there:
https://searchfox.org/mozilla-central/source/browser/base/content/test/performance/browser_startup_flicker.js
https://searchfox.org/mozilla-central/source/browser/base/content/test/performance/browser_windowopen_flicker.js

These tests currently contain whitelists of known bugs (blocking bug 1421456).

Here is how these tests work:
  • as soon as the window we care about is created, we add a MozAfterPaint event listener to it.
  • for each received MozAfterPaint event, we capture a screenshot of the window using CanvasRenderingContext2D.drawWindow().
  • remove the event listener after the window is done loading and after several Services.tm.idleDispatchToMainThread callbacks to ensure that the window has settled.
  • compare the pixel data of each of the captured frames to identify areas that have changed.
  • for changed areas, see if they are whitelisted, if not make the test fail and dump base64 encoded data urls of the before/after screenshots, so that the test failure can be visually debugged.
We currently cover only the startup and window opening cases, but I expect us to add similar tests to more areas in the future. Each time we spend effort reducing flickering in some area of our UI, we should add tests for it to prevent regression.

Wednesday, October 18 2017

Thunderbird is the next version of Instantbird

Ten years ago, on October 18th 2007, I released Instantbird 0.1. I was soon joined by a team of enthusiastic hackers, and I hoped we could make a better IM client that would replace the painfully broken ones that were dominant at the time.

The Internet has changed a lot since then. Messaging has moved significantly toward mobile apps. The clients we were competing with mostly died themselves. Even the services we were connecting to are closing down (AOL, MSN, ...), or moved away from standard protocols (Facebook).

While we made a pretty good product, we never managed to attract a critical mass of users, and we lost half of them when the Facebook XMPP gateway was closed. Instantbird still has some uses (especially as an IRC client), but its user interface has aged significantly.

I don't think maintaining our infrastructure to support only a few thousand users is a good use of my time, and I've lost motivation to do it. While Instantbird regularly received code contributions from several people and had a nice and friendly community, nobody stood up to replace me and take care of our build infrastructure. This means we haven't been able to produce nightly builds for the last couple months, and are extremely unlikely to be able to ship a new release any time soon. It's time to announce that we are stopping development of Instantbird as a standalone product.

The code base isn't dying though! A large part of it is shared with Thunderbird (since it received chat support in 2012). Thunderbird is actively maintained, and has lots of users.

Instead of working on Instantbird, we'll refocus our energy on improving the chat features in Thunderbird, so that it becomes friendly for users who loved Instantbird and will seek a replacement. This should allow us to focus on features and not worry about infrastructure that was sapping our energy and time. Thunderbird is the spiritual successor to Instantbird!

Monday, February 8 2016

Project ideas wanted for Summer of Code 2016

Google is running Summer of Code again in 2016. Mozilla has had the pleasure of participating many years so far, and even though we weren't selected last year, we are hoping to participate again this year. In the next few weeks, we need to prepare a list of suitable projects to support our application.

Can you think of a 3-month coding project you would love to guide a student through? This is your chance to get a student focusing on it for 3 months! Summer of Code is a great opportunity to introduce new people to your team and have them work on projects you care about but that aren't on the critical path to shipping your next release.

Here are the conditions for the projects:

  • completing the project should take roughly 3 months of effort for a student;
  • any part of the Mozilla project (Firefox, Firefox OS, Thunderbird, Instantbird, SeaMonkey, Bugzilla, L10n, NSS, IT, and many more) can submit ideas, as long as they require coding work;
  • there is a clearly identified mentor who can guide the student through the project.

If you have an idea, please put it on the Brainstorming page, which is our idea development scratchpad. Please follow the instructions at the top.

The deadline to submit project ideas and help us be selected by Google is February 19th.

Note for students: the student application period starts on March 14th, but the sooner you start discussing project ideas with potential mentors, the better.

Tuesday, November 3 2015

What about search hijacking?

Some people may have noticed that lately my work has been concentrated on bugs with 'hijacking' in the status whiteboard, but we never really took the time to explain what the goals of this work are, or aren't.

What we call "search hijacking" is when a user's default search engine is changed without the user's intent, typically while the user is installing some other software on his system. Search hijacking is a very common phenomenon, and is causing a severely degraded user experience for the affected users; sometimes leading users to switch to another browser to stop searching with a search engine they never wanted and don't know how to change.

When the search service (the back-end code handling search engines) was initially created about a decade ago, search hijacking wasn't a thing. Things were designed for maximum user customizability. Unfortunately, these days the ease of customization combined with the monetary incentives offered has made search a hijacking target.

The current situation is untenable for Firefox users, so we had to do something. Deciding what to do wasn't obvious, because the difference between the user customizing something and unwanted software writing things to disk isn't always as clear as we would like it to be.

Whatever we do, hijackers will be able to change their code to workaround our changes. In some way, this is an arms race. We can make changes every 6 weeks if needed. We have reasons to believe that it takes most hijackers several months to update their hacks and deploy them, as they need to be bundled with other software for downloads. Our first approach to the problem, especially while our resources to tackle this were very limited, was to do tiny changes every once in a while to breaks some hijacks and help our users for a few months. We didn't want to do pointless changes, but we could find a few things that didn't feel right in our code, and fixed them.

For example, we had some evidence that a significant number of users had modified yahoo.xml files in their application folder. Being able to hijack the default engine by just changing an URL in a plain XML file on the disk was just ridiculous, especially when almost every other non-binary file used by the browser is packed inside the omni.ja file. We fixed this in bug 1162569 for Firefox 40. Similarly, it was possible to change the default engine by dropping in the user's profile a file redefining the same engine. There is no way to end up in this situation 'naturally', because we refuse to install duplicate engines. The logical fix was to ensure that engines in the profile can't override built-in engines. We fixed this in bug 1109354, also for Firefox 40. This was also a good opportunity to add lots of tests about how engines are loaded.

Something seriously limiting our ability to correctly attack the problem was the lack of good data. We found the evidence of modified yahoo.xml files in the wild almost by accident, while looking at incoherent default engine data we received in FHR. In parallel to the fixes mentioned above, we also introduced a better data collection mechanism, with the addition of a telemetry probe recording details about how the current default engine has been loaded.

I haven't been able to look at release-user data collected through this new telemetry probe yet (I intend to do so soon!), but a quick analysis of the early data we got from nightly and aurora users revealed that a non-trivial amount of users had no engine at all, resulting in search features being completely broken for them. This situation can happen if the hijackers removed all the other 'competing' engines to ensure they are the only one, and then got removed themselves, eg. due to one of our previous fixes. We addressed this problem in bug 438599 for Firefox 43, by unhiding automatically the original default engine when no visible engine is left.

A major change that is coming soon to Firefox is required add-on signing. This is a game changer for hijacking, because now anything that lets malware with disk access insert unsigned-code that changes Firefox's behavior is explicitly a bug. This means we are now in a position to close lots of doors that were wide open, to ensure the control is in the hands of our users, not hijackers. There are 2 supported ways to install new engines: either the user does it through the Firefox UI (eg. using OpenSearch discovery on a website), or it's done by a signed add-on. Any other way left to install a search engine and set it as the default is something we need to look into.

In order to better enforce this, we need to be reasonably confident that the data from the user's profile has actually been written due to intentional user actions. The next step of our hijacking remediation work is to cleanup the way search-related data is stored in user profiles. We used to store 2 JSON files (one cache file dismissed after each update, and one file with metadata), in addition to a plain xml file for each user-installed engine. This made it easy to mess either with the xml files (just dropping in the folder an xml file in the open search format was enough to install an engine) or with the metadata. In bug 1203167 (just landed on nightly), I'm changing the profile storage so that everything is in a single file. The data is stored in a JSON format, but the file is written to disk using OS.File's compression feature, which in addition to reducing the file size on disk will also make the file resistant to dumb search & replace attacks. The important data stored in the file (eg. the name of the user-selected default engine) is protected from tampering using verification hashes. While these hashes are by no way meant to be cryptographically secure, they should be unique to each profile, and so make tampering harder. Changing the storage format was also an opportunity to save slightly more data about how users installed engines. For example, if an engine was installed from OpenSearch discovery, we will remember the hostname of the website from which it was downloaded.

We are not done. We have a few more doors to close. We also don't expect to ever be completely resistant to hijacking, as an attacker with local admin access can do whatever. We mostly aim to make hijacking hard enough that it will require some (minimal) engineering skills to do it. Dropping a file on disk or doing a search & replace on the default engine's URL shouldn't be enough. It should require running local code. We can’t protect users from all their mistakes, but we can draw a line between malware-behavior and user-customization that's clear enough for antivirus vendors to enforce it for their users.

We are still working on preventative measures. But a few releases from now, we can expect to start offering curative measures. With Firefox 45 we'll start recording information about engines origin. At some point (currently targeting Firefox 46), we could offer users who have non-default engines of unknown origin an opportunity to check their search settings and revert to the original default if they don't remember changing their default engine themselves. UX is currently thinking this through.

Saturday, October 17 2015

The World's Biggest Eye Contact Experiment - Lille

Hier soir j'ai passé la soirée à l'édition de Lille du World's Biggest Eye Contact Experiment.

Malgré la pluie, je suis resté toute la soirée. De 17h30 à plus de 20h30. J'ai eu de très nombreux contacts visuels avec de nombreux-ses inconnu-e-s. Je n'ai pas vu le temps passer, et ai rarement attendu plus de 2 ou 3 minutes entre 2 personnes s'asseyant en face de moi. Les gens sont incroyablement beaux quand on prend le temps de les regarder.
Chaque contact visuel a été différent. Chaque regard exprime quelque chose d'unique. Ce qui passe dans un regard est souvent difficile à exprimer avec des mots. Parfois le contact est très intense sans qu'il y ait de mots échangés entre nous sauf "bonjour" et "merci". Parfois il se termine par une petite discussion. Quelques exemples ont été plus marquants que d'autres.
En voici un :
Je m'installe en face de J., qui demande aussitôt à toucher mes genoux ; elle dit qu'elle est plus à l'aise avec un contact tactile en plus du contact visuel. J'accepte, puis change d'avis et décide de lui prendre les mains au lieu de la laisser les poser sur mes genoux. Nous nous regardons. Elle semble apprécier, même si quelque chose semble la perturber un peu. Elle me dit :
- ton regard est bizarre. Il y a quelque chose d'inhabituel.
- ah ?
- oui, j'arrive pas à trouver quoi.
- si tu trouves tu me diras.
Le silence revient. Nous restons perdus dans le regard l'un de l'autre. Soudain son visage s'illumine : elle a trouvé. Elle dit "Ton regard est doux." et quelques secondes plus tard, elle ajoute "il est vrai." Notre échange visuel se termine bientôt lorsqu'elle dit "Je peux avoir un câlin ?". On se lève. On s'enlace. C'est le câlin le plus tendre que j'ai reçu (et donné ?) depuis très longtemps.

Merci à J., qui se reconnaîtra ou pas.

Merci à tous les autres, nombreux. Merci aux organisateurs.

Tuesday, March 3 2015

Mozilla not accepted for Google Summer of Code 2015

As you may have already seen, Mozilla is not in the list of organizations accepted for Google Summer of Code 2015.

People who have observed the list carefully may have noticed that there are fewer accepted organizations this year: 137 (down from 190 in 2014 and 177 in 2013). Other organizations that have participated successfully several times are also not in the 2015 list (eg. Linux Foundation, Tor, ...).

After a quick email exchange with Google last night, here is the additional information I have:
  • not accepting Mozilla was a difficult decision for them. It is not the result of a mistake on our part or an accident on their side.
  • there's an assumption that not participating for one year would not be as damaging for us as it would be for some other organizations, due to us having already participated many times.
  • this event doesn't affect negatively our chances of being selected next year, and we are encouraged to apply again.

This news has been a surprise for me. I am disappointed, and I'm sure lots of people reading this are disappointed too. I would like to thank all the people who considered participating this year with Mozilla, and especially all the Mozillians who volunteered to mentor and contributed great project ideas. I would also like to remind students that while Summer of Code is a great opportunity to contribute to Mozilla, it's not the only one. Feel free to contact mentors if you would like to work on some of the suggested ideas anyway.

Let's try again next year!

Wednesday, February 11 2015

FOSDEM 2015 slides - What's new in Firefox?

This year at FOSDEM I talked about Firefox. I summarized the major changes that have been made to Firefox in 2014, and what our plans are for 2015.

Here are the slides of my FOSDEM presentation:
What's new in Firefox? What happened in 2014? What's the plan for 2015? FOSDEM 2015, by Florian Quèze

Thursday, January 22 2015

Project ideas wanted for Summer of Code 2015

Google is running Summer of Code again in 2015. Mozilla has had the pleasure of participating every year so far, and we are hoping to participate again this year. In the next few weeks, we need to prepare a list of suitable projects to support our application.

Can you think of a 3-month coding project you would love to guide a student through? This is your chance to get a student focusing on it for 3 months! Summer of Code is a great opportunity to introduce new people to your team and have them work on projects you care about but that aren't on the critical path to shipping your next release.

Here are the conditions for the projects:

  • completing the project should take roughly 3 months of effort for a student;
  • any part of the Mozilla project (Firefox, Firefox OS, Thunderbird, Instantbird, SeaMonkey, Bugzilla, L10n, NSS, IT, and many more) can submit ideas, as long as they require coding work;
  • there is a clearly identified mentor who can guide the student through the project.


If you have an idea, please put it on the Brainstorming page, which is our idea development scratchpad. Please read the instructions at the top – following them vastly increases chances of your idea getting added to the formal Ideas page.

The deadline to submit project ideas and help us be selected by Google is February 20th.

Note for students: the student application period starts on March 16th, but the sooner you start discussing project ideas with potential mentors, the better.

Please feel free to discuss with me any question you may have related to Mozilla's participation in Summer of Code. Generic Summer of Code questions are likely already answered in the FAQ.

Sunday, July 27 2014

Firefox is awesome

"Hey, you know what? Firefox is awesome!" someone exclaimed at the other end of the coworking space a few weeks ago. This piqued my curiosity, and I moved closer to see what she was so excited about.

When I saw the feature she was delighted of finding, it reminded me a similar situation several years ago. In high school, I was trying to convince a friend to switch from IE to Mozilla. The arguments about respecting web standards didn't convince him. He tried Mozilla anyway to please me, and found one feature that excited him.
He had been trying to save some images from webpages, and for some reason it was difficult to do (possibly because of context menu hijacking, which was common at the time, or maybe because the images were displayed as a background, …). He had even written some Visual Basic code to parse the saved HTML source code and find the image urls, and then downloaded them, but the results weren't entirely satisfying.
Now with Mozilla, he could just right click, select "View Page Info", click on the "Media" tab, and find a list of all the images of the page. I remember how excited he looked for one second, until he clicked a background image in the list and the preview stayed blank; he then clicked the "Save as" button anyway and… nothing happened. Turns out that "Save as" button was just producing an error in the Error Console. He then looked at me, very disappointed, and said that my Mozilla isn't ready yet.
After that disappointment, I didn't insist much on him using Mozilla instead of IE (I think he did switch anyway a few weeks or months later).

A few months later, as I had time during summer vacations, I tried to create an add-on for the last thing I could do with IE but not Firefox: list the hostnames that the browser connects to when loading a page (the add-on, View Dependencies, is on AMO). I used this to maintain a hosts file that was blocking ads on the network's gateway.
Working on this add-on project caused me to look at the existing Page Info code to find ideas about how to look through the resources loaded by the page. While doing this, I stumbled on the problem that was causing background image previews to not be displayed. Exactly 10 years ago, I created a patch, created a bugzilla account (I had been lurking on bugzilla for a while already, but without creating an account as I didn't feel I should have one until I had something to contribute), and attached the patch to the existing bug about this background preview issue.
Two days later, the patch was reviewed (thanks db48x!), I addressed the review comment, attached a new patch, and it was checked-in.
I remember how excited I was to verify the next day that the bug was gone in the next nightly, and how I checked that the code in the new nightly was actually using my patch.

A couple months later, I fixed the "Save as" button too in time for Firefox 1.0.

Back to 2014. The reason why someone in my coworking space was finding Firefox so awesome is that "You can click "View Page Info", and then view all the images of the page and save them." Wow. I hadn't heard anybody talking to me about Page Info in years. I did use it a lot several years ago, but don't use it that much these days. I do agree with her that Firefox is awesome, not really because it can save images (although that's a great feature other browsers don't have), but because anybody can make it better for his/her own use, and by doing so making it awesome for millions of other people now but also in the future. Like I did, ten years ago.

Friday, July 25 2014

Converting old Mac minis into CentOS Instantbird build slaves

A while ago, I received a few retired Mozilla minis. Today 2 of them started their new life as CentOS6 build slaves for Instantbird, which means we now have Linux nightlies again! Our previous Linux build slave, running CentOS5, was no longer able to build nightlies based on the current mozilla-central code, and this is the reason why we haven't had Linux nightlies since March. We know it's been a long wait, but to help our dear Linux testers forgive us, we started offering 64bit nightly builds!

For the curious, and for future reference, here are the steps I followed to install these two new build slaves:

Partition table

The Mac minis came with a GPT partition table and an hfs+ partition that we don't want. While the CentOS installer was able to detect them, the grub it installed there didn't work. The solution was to convert the GPT partition table to the MBR older format. To do this, boot into a modern linux distribution (I used an Ubuntu 13.10 live dvd that I had around), install gdisk (sudo apt-get update && sudo apt-get gdisk) and use it to edit the disk's partition table:

sudo gdisk /dev/sda
Press 'r' to start recovery/transformation, 'g' to convert from GPT to MBR, 'p' to see the resulting partition table, and finally 'w' to write the changes to disk (instructions initially from here).
Exit gdisk.
Now you can check the current partition table using gparted. At this point I deleted the hfs+ partition.

Installing CentOS

The version of CentOS needed to use the current Mozilla build tools is CentOS 6.2. We tried before using another (slightly newer) version, and we never got it to work.

Reboot on a CentOS 6.2 livecd (press the 'c' key at startup to force the mac mini to look for a bootable CD).
Follow the instructions to install CentOS on the hard disk.
I customized the partition table a bit (50000MB for /, 2048MB of swap space, and the rest of the disk for /home).

The only non-obvious part of the CentOS install is that the boot loaded needs to be installed on the MBR rather than on the partition where the system is installed. When the installer asks where grub should be installed, set it to /dev/sda (the default is /dev/sha2, and that won't boot). Of course I got this wrong in my first attempts.

Installing Mozilla build dependencies

First, install an editor that is usable to you. I typically use emacs, so: sudo yum install emacs

The Mozilla Linux build slaves use a specifically tweaked version of gcc so that the produced binaries have low runtime dependencies, but the compiler still has the build time feature set of gcc 4.7. If you want to use something as old as CentOS6.2 to build, you need this specific compiler.

The good thing is, there's a yum repository publicly available where all the customized mozilla packages are available. To install it, create a file named /etc/yum.repos.d/mozilla.repo and make it contain this:

[mozilla]
name=Mozilla
baseurl=http://puppetagain.pub.build.mozilla.org/data/repos/yum/releng/public/CentOS/6/x86_64/
enabled=1
gpgcheck=0

Adapt the baseurl to finish with i386 or x86_64 depending on whether you are making a 32 bit or 64 bit slave.

After saving this file, you can check that it had the intended effect by running this comment to list the packages from the mozilla repository: repoquery -q --repoid=mozilla -a

You want to install the version of gcc473 and the version of mozilla-python27 that appear in that list.

You also need several other build dependencies. MDN has a page listing them:

yum groupinstall 'Development Tools' 'Development Libraries' 'GNOME Software Development'
yum install mercurial autoconf213 glibc-static libstdc++-static yasm wireless-tools-devel mesa-libGL-devel alsa-lib-devel libXt-devel gstreamer-devel gstreamer-plugins-base-devel pulseaudio-libs-devel

Unfortunately, two dependencies were missing on that list (I've now fixed the page):
yum install gtk2-devel dbus-glib-devel

At this point, the machine should be ready to build Firefox.

Instantbird, because of libpurple, depends on a few more packages:
yum install avahi-glib-devel krb5-devel

And it will be useful to have ccache:
yum install ccache

Installing the buildbot slave

First, install the buildslave command, which unfortunately doesn't come as a yum package, so you need to install easy_install first:

yum install python-setuptools python-devel mpfr
easy_install buildbot-slave

python-devel and mpfr here are build time dependencies of the buildbot-slave package, and not having them installed will cause compiling errors while attempting to install buildbot-slave.

We are now ready to actually install the buildbot slave. First let's create a new user for buildbot:

adduser buildbot
su buildbot
cd /home/buildbot

Then the command to create the local slave is:

buildslave create-slave --umask=022 /home/buildbot/buildslave buildbot.instantbird.org:9989 linux-sN password

The buildbot slave will be significantly more useful if it starts automatically when the OS starts, so let's edit the crontab (crontab -e) to add this entry:
@reboot PATH=/usr/local/bin:/usr/bin:/bin /usr/bin/buildslave start /home/buildbot/buildslave

The reason why the PATH environment variable has to be set here is that the default path doesn't contain /usr/local/bin, but that's where the mozilla-python27 packages installs python2.7 (which is required by mach during builds).

One step in the Instantbird builds configured on our buildbot use hg clean --all and this requires the purge mercurial extension to be enabled, so let's edit ~buidlbot/.hgrc to look like this:
$ cat ~/.hgrc
[extensions]
purge =

Finally, ssh needs to be configured so that successful builds can be uploaded automatically. Copy and adapt ~buildbot/.ssh from an existing working build slave. The files that are needed are id_dsa (the ssh private key) and known_hosts (so that ssh doesn't prompt about the server's fingerprint the first time we upload something).

Here we go, working Instantbird linux build slaves! Figuring out all these details for our first CentOS6 slave took me a few evenings, but doing it again on the second slave was really easy.

- page 1 of 14