otsukare by Karl Dubost at

So on January 7, 2019, I wrote the first edition of "They Fixed It!"

This is a new chapter. I'll try to move forward in a semi-regular basis.

Let's see what are the cool things which have been fixed since that last report and helps webcompat to be better on the Web.

Thanks to them!


Mike Taylor's Web Log by Mike Taylor at

Happy new years.

We got really, really close to being able to ship window.event, but had to back that out from shipping to Firefox 65 release in Bug 1520756 (like we had to do in 63).

Back in 2014's classic post "Why FF says that window.event is undefined? (call function with added event listener)*" I mentioned the global event that Gecko never supported (because it was a non-standard IE-ism). Years passed and things didn't get better—mostly because WebKit and thus Blink inherited said IE-ism—so we added some hot legacy garbage to the DOM Standard and got it implemented in Firefox.

Things looked really promising on mobile until our desktop beta population started reporting bugs against banks and government sites (especially in India). Like, "can't type in this input" kinds of bugs.

Bug 1479964 has the details, but the basic gist is as follows (inside a keypress event handler):

var keyCode = window.event ? event.keyCode : event.which;

The presence of window.event presumes you can get a non-zero keyCode from the event object, and then you can take that and do something amazing on your bank and government login form.

Let's look at the Blink source to see how they handle keyCode inside a keypress handler:

  // Firefox: 0 for keydown/keyup events, character code for keypress
  // We match Firefox
  if (type() == EventTypeNames::keypress)
    char_code_ = key.text[0];

  if (type() == EventTypeNames::keydown || type() == EventTypeNames::keyup)
    key_code_ = key.windows_key_code;
    key_code_ = char_code_;

For keypress, they set charCode to something meaningful, but also set keyCode to charCode. So that's what we're trying to do now. Like most things that break websites, there isn't like, a spec for any of this stuff yet (but if someone wants to take care of that, be my guest, probably good to read over JavaScript Madness: Keyboard Events as you tackle that).

But like I wrote in the title, everything is terrible. We discovered late in the 65 beta cycle that Atlassian Confluence was busted. Like, "can't type the period in a comment" busted.

The reason it's broken there is due to some code that tries to handle delete and backspace key presses in selections, and sometimes prevent that from happening (I guess?).

// Webkit will fire keyDown and keyUp for backspace and delete (even if one is suppressed).
tinymce.isGecko && ed.onKeyPress.add(deleteAndBackspaceKeyHandling);

So you've got 3 event listeners trying to do the same thing, but only Firefox sees the keypress one.

function deleteAndBackspaceKeyHandling(ed, e) {
    var keyCode = e.keyCode;

    if (!ed.selection.isCollapsed()) {
    } else if (keyCode === KEY_CODE.BACKSPACE && someOtherJunk()) {
    } else if (keyCode === KEY_CODE.DELETE && someOtherJunk()) {
    return true;

KEY_CODE.BACKSPACE is 46. 46 is the code for a PERIOD in a keypress event, but the code for BACKSPACE in keydown/keyup events. So in Firefox, and Firefox only, it thinks it's seeing a backspace and prevents the default action (which is to let the user type the period).

Confluence is especially tricky because they offer a self-hosted version in addition to their cloud-hosted thing. Breaking intranet webapps is a non-starter, so we've prevented this set of changes from shipping to release (again). And we'll try to come up with some creative hack so we can fix a ton of mobile sites but not break outdated intranet Confluence instances.

Anyways, like I said, happy new years or whatever.

otsukare by Karl Dubost at

This is a new chapter. I'll try to move forward in a semi-regular basis. The work done by the awesome core engineers of Mozilla is essential. Some of the things they fix or explain have direct impact on the web compatibility work. A couple of years ago at Mozilla Hands. I gave a lightning talk called "They fixed it". I quickly put forward to the audience all the (webcompat) cool bugs which had been fixed by Core engineers.

  • The site Channel NewsAsia is using a transform with a rotation for their headers when scrolling the content. The headers had a wider gap in Firefox than Chrome. An issue was reported. Brian Birtles digged into the isssue. He explained in details why the interpolation looks worse in Firefox than Chrome. Firefox has implemented the new specification. Web developers rely on an old version of the algorithm in Chrome. Chrome will change soon(?) and it will be equally broken. That was quite cool, Brian. Thanks!
  • I will probably write often about the Virtual Viewport and associated issues. Basically to make it short, Chrome/Safari have the notion of a virtual viewport in addition to the device viewport. This creates a series of different behavior for websites on Chrome vs Firefox on Android. We had a lot of webcompat issues about it. So as I said I will talk more about it in the future. In the mean time big big shout out to Hiroyuki Ikezoe and Botond Ballo
  • Orthogonal to the Virtual viewport I just mentionned, there's work to expose the Visual Viewport API. Jan Henning just before christmas 2018 fixed Implement event handlers of the Visual Viewport API. This is part of the Visual Viewport interface. Thanks.

otsukare by Karl Dubost at

Identifying the origin of the issue

On webcompat, we try to diagnose bugs reported about sites, we do not have the original sources. If we are lucky, web developers have included a way to reach the original JavaScript source files (through sourcemap). But modern websites have often a series of optimization layers (with multiple minifications).

To check during the investigation, that we thought was right we need to play with the code. With real CSS files (as opposed to CSS in JavaScript), it is easy to hand make a working solution. With JavaScript it's near impossible apart of just observing why it fails and guessing how it could work.

How do we overcome the lack of access to JavaScript?

One possible solution is to create a local proxy on your laptop and to use a man in the middle technique to capture the HTTP requests and replace the website JavaScript HTTP request by a call to a local file of your choice. On macOs for example, you could use Charles Proxy or on Unix you may want to use MITM

This is tedious and not always successful, specifically when JavaScript is written and minified on the fly.

Last week, a lunch in Tokyo

During a lunch with Jason Laster (@jasonlaster11), Brian Birtles (@brianskold) and Arai-san (@arai_unmht), I was specifically discussing about my woes when debugging websites and how cool it would be to just be able edit the JavaScript file inside the devtools debugger. Arai-san said « Oh but I have something a bit similar to this. » So I told them… « Ship it! »

The afternoon went on with the current work in the Mozilla Tokyo office. But just before dinner, Arai-san decided to be my hero. They worked during the afternoon on packaging properly their tool and makes it an add-on for the Firefox devtools.

And indeed it was shipped by the end of the day! Discover Developer In The Middle. You can select a resource, prettify it in your favorite editor, change some logic, save it inside the UI and just reload the page. Magical and so much more practical.

This is the first version, please do use it! Try it and send feedback about the tool.

Thanks Arai-san!


I never stop to be amazed by the quality, expertise and kindness of the Mozilla Japan team. I'm coming to the office once a week, because I live a bit far from the Tokyo office, but I'm definitely blessed to meet them every week.


When Can I Use updates by Alexis Deveria at

CSS overflow property: Originally a single property for controlling overflowing content in both horizontal & vertical directions, the `overflow` property is now a shorthand for `overflow-x` & `overflow-y`. The latest version of the specification also introduces the `clip` value that blocks programmatic scrolling.

Mike Taylor's Web Log by Mike Taylor at

Over in Bug 1359822, the fine folks on the JS team tried to make error messages for null or undefined property keys nicer in Firefox. So rather than something super lame (and sometimes confusing) like:

TypeError: window.pogs is undefined

You'd get something more helpful like:

TypeError: win.pogs is undefined, can't access property "slammer" of it

This was supposed to land in the Firefox 64 release cycle, but we ran into a few snags.

It turns out that sites (big ones like Flipkart) and libraries depend on the exact shape of an error message, and will fail is craptastic ways if their regular expressions expectations are not met. Like, blank pages and non-stop loading loops.

Facebook's idx's library is an example:

const nullPattern = /^null | null$|^[^(]* null /i;
const undefinedPattern = /^undefined | undefined$|^[^(]* undefined /i;

Bug 1359822 adds a comma to the error message, so undefinedPattern doesn't match anymore.

And yeah, you can't really break the sixth biggest site in India and expect to have users, so we backed out the error improvements patches.

But what does the spec say?, you ask, because you're like, really smart and care about specs and stuff (obviously, because you're reading this blog for and by really smart people™).

ECMAScript® 3000, in section 19.5.6 says:

When an ECMAScript implementation detects a runtime error, it throws a new instance of one of the NativeError objects defined in 19.5.5. Each of these objects has the structure described below, differing only in the name used as the constructor name instead of NativeError, in the name property of the prototype object, and in the implementation-defined message property of the prototype object.

That's spec-talk for "these error messages can be different between browsers, and there's no guarantee they won't change, so attempting to rely on them is harmful to making things better in the future" (approximately).

I filed a bug, but getting upstream open source libraries fixed is way less hard than getting downstream sites to update.

A kid doing pog math

(Almost as hard as pog math.)

The moral of the story is: don't write regular expressions against unstandardized browser-specific messages. Or maybe just never write regular expressions ever again. Seems easier?

When Can I Use updates by Alexis Deveria at

The following changes have been made to the way support tables appear on

1. "Show all" now combines consecutive versions with the same support information.

Before, "show all" would show every single version as its own cell, resulting in huge lists of versions to be scrolled through. Combining them means a much easier overview of when support changed.

2. The default view has been changed to the new "Show all" view. This means support for all browsers & versions tracked on the site is visible, not just versions with significant usage.

3. Default views can now be defined in the Settings side panel. To revert back to the previous default, use the "Filtered" mode. Settings here will be applied on new search results or site reload.

Mike Taylor's Web Log by Mike Taylor at

Back by popular demand*, here's a follow-up to my blog post on Firefox Desktop UA string changes.

(*actual demand for this blog post asymptotically approaches zero the further you read)

Early versions of Firefox for Android used a Linux desktop UA string with a Fennec/<fennecversion> product token appended to the end.

Since version 41, Firefox for Android has (generally) followed the following UA string format:

Mozilla/5.0 (Android <androidversion>; <devicecompat>; rv: <geckoversion>) Gecko/<geckoversion> Firefox/<firefoxversion>

Gecko Version Sample Firefox for Android UA string
4 Mozilla/5.0 (Android; Linux armv7l; rv:2.1.1) Gecko/20110415 Firefox/4.0.2pre Fennec/4.0.1
11 Mozilla/5.0 (Android; Tablet1; rv:11.0) Gecko/11.0 Firefox/11.0 Fennec/11.0
11 Mozilla/5.0 (Android; Tablet; rv:11.0) Gecko/11.0 Firefox/11.02
41 Mozilla/5.0 (Android 4.4.43; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0
46 Mozilla/5.0 (Android 4.4.4; Mobile; CoolDevice4; rv:46.0) Gecko/46.0 Firefox/46.0
46 Mozilla/5.0 (Android 4.4.4; Mobile; Custom CoolDevice/ABCDEFG5; rv:46.0) Gecko/46.0 Firefox/46.0

Footnotes: 1. Version 11 added the notion of a <devicecompat> token to distinguish between Tablet and Mobile.

2. Version 11 also dropped the Fennec/<version> token for Native UI (non-XUL) builds.

3. For versions running on Android older than KitKat (v4), the Android version number is set to 4.41 to avoid UA sniffing assumptions tied to the Android platform capabilities. 4. Version 46 also added the ability to add the Android device name, controlled by the pref general.useragent.use_device. This is probably not widely used, if at all.

5. Version 46 added the ability to add a custom device string, with optional device ID, controlled by the pref general.useragent.device_string. This is also probably not widely used, if at all.

Footnotes to the Footnotes: 1. If I had to write this patch again, I would choose an obviously non-real 4.4.99, so it would be sniffable as a spoofed value. Yes, I am familiar with the concept of irony.

Mike Taylor's Web Log by Mike Taylor at

I'm sure everyone remembers this super great blog post from 2010 about changes in the Firefox 4 user agent string. In terms of "blog posts about UA string changes", it's, well, one of them.

The final post-v4 release desktop UA string is as follows:

Mozilla/5.0 (<platform>; rv:<geckoversion>) Gecko/20100101 Firefox/<firefoxversion>

As sort of a companion piece (that nobody asked for), I wrote up the following table of minor changes to the pre-release desktop UA string between then and now.

(You know, in case you or I find ourselves needing to know them one day—apologies in advance for whatever crappy future scenario we ended up in where we need to re-visit this blog post.)

Version Sample Windows 10 pre-release UA string
5 Mozilla/5.0 (Windows NT 6.2; rv:2.2a1pre) Gecko/20110412 Firefox/4.2a1pre
6 Mozilla/5.0 (Windows NT 6.2; rv:6.0a1) Gecko/20110524 Firefox/6.0a1
13 Mozilla/5.0 (Windows NT 6.2; rv:13.01) Gecko/20120313 Firefox/13.0a1
15 Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/16.02 Firefox/16.0a1
16 Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/16.0 Firefox/16.03
20 Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/201301074 Firefox/20.0
25 Mozilla/5.0 (Windows NT 6.3; rv:25.0) Gecko/201001015 Firefox/25.0

Footnotes: 1. In 572659 we dropped pre-release indicators and patch level version numbers from geckoversion 2. In 588909 we replaced Gecko/<builddate> with Gecko/<geckoversion> 3. In 572659 we dropped pre-release indicators and patch level version numbers from firefoxversion 4. In 815743 we reverted the changes from 588909 (because it broke too many sites, mostly banks) 5. In 728773 we began using the frozen 201001011 builddate for all releases

Apocryphal Footnotes to the Footnotes: 1. It's widely believed Jan 1, 2010 was chosen as the frozen build date because it marked the day that North Korea pledged lasting peace and a nuclear free Korean peninsula. That only happens once in a lifetime. Probably.

Mike Taylor's Web Log by Mike Taylor at

Late last week we quietly landed a Nightly-only addon that spoofs the Chrome Mobile user agent string for Google Search (well, Facebook too, but that's another blog post).


Bug 975444 is one of the most-duped web compat bugs, which documents the fact that the version of Google Search that Firefox for Android users receive is a less rich version than the one served to Chrome Mobile. And people notice (hence all the dupes).

In order to turn this situation around, we've been working on a number of platform interop bugs (in collaboration with some friendly members of the Blink team) and have hopes in making progress towards receiving Tier 1 search by default.

Part of the plan is to sniff out bugs we don't know about (or new bugs, as the site changes very quickly) by exposing the Nightly population to the spoofed Tier 1 version for 4 weeks (which should be July 27, 2018). If things get too bad, we can back out the addon earlier.

If you've found a bug, please report it at

And in the meantime, if the bugs are too annoying to deal with, you can disable it by going to about:config and setting extensions.gws-and-facebook-chrome-spoof.enabled to false (just search for gws).

Note: don't hit reset; instead, tap the true/false value and then hit toggle when that appears.

(yeah, yeah, I'll go charge my phone now.)