The KeyboardEvent.code property represents a physical key, that is value not changed neither by the modifier state, nor by keyboard layout. Summary: KeyboardEvent.code may allow fingerprinting of keyboard layout to KeyboardEvent may allow fingerprinting of keyboard layout Cc: N/Ato gk Keywords: N/Adeleted, ff38-esr, tbb-fingerprinting added Priority: minor to major
It turns out that not only does the new property, KeyboardEvent.code, allow fingerprinting of keyboard layout, so does the old (deprecated but still retained) KeyboardEvent.keyCode. For example, here are keyCode values I get for the ? character, for layouts targeted to different languages on OS X:
English (US)
191
German
63
French
188
Spanish
190
Italian
222
Swedish
171
So I'm looking into how to create a map from commonly typed unicode characters to a consensus code and a consensuskeyCode.
To summarize: I provide consensus (US-English-style) fake properties for KeyboardEvent, namely code, keyCode, location and shiftKey. So, for example, if the user types ?, the result will be code = 'Slash', keyCode = 191, shiftKey = true, location = 0, regardless of the keyboard layout. Numbers are always reported as arriving from the keys located above "QWERTY", even if they are typed on the NumPad.
Note that for now I have focused on ASCII (US English) characters and standard keyboard control keys. Characters from other languages will simply return a KeyboardEvent.keyCode of 0 and an empty Keyboard.code. It should be straightforward to spoof .keyCode and .code for higher unicode points, but I think it makes sense to postpone that for another ticket while this approach is reviewed and perhaps tested by users in an alpha.
I can't get your patch to compile on Linux:
{{{
/home/ubuntu/build/tor-browser/dom/events/KeyCodeConsensus.h:7:30: fatal error: nsClassHashTable.h: No such file or directory
#include "nsClassHashTable.h"
^
compilation terminated.
make[5]: *** [Unified_cpp_dom_events1.o] Error 1
}
I can't get your patch to compile on Linux:
{{{
/home/ubuntu/build/tor-browser/dom/events/KeyCodeConsensus.h:7:30: fatal error: nsClassHashTable.h: No such file or directory
#include "nsClassHashTable.h"
^
compilation terminated.
make[5]: *** [Unified_cpp_dom_events1.o] Error 1
}
Oops -- that file has a capitalization error (unfortunately ignored by OS X), but, in any case, the file should be "nsDataHashtable.h". Here's a corrected version that built for me on Ubuntu:
To summarize: I provide consensus (US-English-style) fake properties for KeyboardEvent, namely code, keyCode, location and shiftKey. So, for example, if the user types ?, the result will be code = 'Slash', keyCode = 191, shiftKey = true, location = 0, regardless of the keyboard layout. Numbers are always reported as arriving from the keys located above "QWERTY", even if they are typed on the NumPad.
The ? test with en-US bundles
On a Windows 7 machine with a german keyboard and german keyboard layout I get
I took a look at this code and it seems good enough to include in 5.0a3. From a pedantic correctness standpoint, I am wary of createKeyCodes()'s setup code being called from the first KeyboardEvent, which could potentially race with a KeyboardEvent from another thread and cause reentrancy issues with the hashtables. This does seem unlikely in practice, though. Perhaps even impossible, if keyboard events can only arrive on the main thread.
[snip]
Thus, I think this needs revision. I am not exactly sure in which regard though: s/63/191/g and s/Minus/Slash/g? What about the keyCode = 0 cases?
Phooey, I think this didn't work because I forgot to add the "privacy.resistFingerprinting" pref to 0001-tor-browser.js. Here's a fixup pref:
I just pushed a Torbutton commit to sync the privacy.resistFingerprinting pref with the torbutton pref.
Leaving this open for GK to test. I'm also wondering if we should move createKeyCodes() into a global static object with its own constructor (which should run at program initialization).
I'm also wondering if we should move createKeyCodes() into a global static object with its own constructor (which should run at program initialization).
Maybe don't listen to me wrt static constructors. Apparently ancient compiler bugs with static constructors used to be a thing (though I'm pretty sure Firefox won't compile with a C++ compiler older than like 5 years anyway). I'm still a bit worried about the potential initialization race here, though. I wonder if anyone at Mozilla might make any suggestions?
This looks better now. But we should give default values for altKey and ctrlKey as well (maybe even metaKey, too?) as not doing so might reveal the underlying keyboard layout (or maybe better: it might exclude possible keyboard layouts) as well:
It seems you wanted to align the backslashes but forgot one whitespace here?
Re: comment:6 I think the approach is okay. Could you take care of filing the new ticket you mentioned there? And a new ticket about investigating the possible initialization race Mike mentioned (or maybe you are already sure that can't bite us?)?
This looks better now. But we should give default values for altKey and ctrlKey as well (maybe even metaKey, too?) as not doing so might reveal the underlying keyboard layout (or maybe better: it might exclude possible keyboard layouts) as well:
I think you're right that we need to spoof the ALT key state. (I've done so in the new patch.) But I'm not so sure about the META and CTRL keys -- aren't these only used for non-printing commands? Correct me if I'm wrong.
Two nits:
{{{
// KEY and SHIFT Assign
}}}
s/Assign/assign
{{{
#define KEY_INTERNAL(key, code, keyCode, shift)
}}}
It seems you wanted to align the backslashes but forgot one whitespace here?
Thanks. I've fixed both nits.
Re: comment:6 I think the approach is okay. Could you take care of filing the new ticket you mentioned there?
I pushed the new patch for 5.0a4. Do we think that wraps up this ticket? Is everything else going to be saved for another ticket or is more testing needed first?
This looks better now. But we should give default values for altKey and ctrlKey as well (maybe even metaKey, too?) as not doing so might reveal the underlying keyboard layout (or maybe better: it might exclude possible keyboard layouts) as well:
I think you're right that we need to spoof the ALT key state. (I've done so in the new patch.) But I'm not so sure about the META and CTRL keys -- aren't these only used for non-printing commands? Correct me if I'm wrong.
Good question. That could be for the META key. I don't know how it works. The funny thing wrt ctrlkey is that I did not press that one in my example above on the german keyboard. I actually just pressed the right ALT key as modifier key, yet still CTRL showed up as true. I had hopes we can avoid that by making the return value for ctrlkey uniform as well in this case by spoofing the CTRL key state. But maybe doing so for the ALT key might already be enough. I'd need to test that with your new patch first.
I am getting
{{{
event = keydown
key = |
charCode = 0
which = 220
code = Backslash
keyCode = 220
location = 0
altKey = false
ctrlKey = true
metaKey = false
shiftKey = true
}}}
with 5.0a4.
Interesting. What keys are you actually pressing to get this result? And what OS is this?
Windows 7 and I press Right ALT + "<".
I think I understand what's happening now: on your keyboard, the Right Alt key is being interpreted as an AltGr key, which is often emulated with Ctrl+Alt. It seems Windows or Firefox is doing the inverse substitution by re-interpreting AltGr as Ctrl+Alt.
So if this understanding is correct, it means that if you use the Left Alt key instead, you should get ctrlKey = false. Is that what you see?
If so, then I will look into how to suppress this Ctrl signal when the Right Alt key is pressed.
I think I understand what's happening now: on your keyboard, the Right Alt key is being interpreted as an AltGr key, which is often emulated with Ctrl+Alt. It seems Windows or Firefox is doing the inverse substitution by re-interpreting AltGr as Ctrl+Alt.
So if this understanding is correct, it means that if you use the Left Alt key instead, you should get ctrlKey = false. Is that what you see?
When using google docs with 5.0a4, I am unable to use hotkeys to switch tabs. I suspect this patch may be at fault?
I don't recall having this issue with 5.0a3...
What key combination and OS did you use here?
Gnome on Linux. Alt+ while in the text edit window of a google doc. This just causes to appear instead of switching tabs.
I just double-checked, and the alt+ breakage was absent in 5.0a3, but backspace was still broken in 5.0a3. Both keys work fine in 4.5.3. For some reason, backspace and alt+ are only broken from within Google Docs. All other web editors/pads I've tested do not have any issues.
Key event not available on some keyboard layouts: key="r" modifiers="accel,alt" browser.xulKey event not available on some keyboard layouts: key="c" modifiers="accel,alt"
on start-up on a Linux box with a german keyborad layout. Is this expected? I am not sure whether this breaks (chrome) stuff yet.
I see:
{{{
Key event not available on some keyboard layouts: key="r" modifiers="accel,alt" browser.xul
Key event not available on some keyboard layouts: key="c" modifiers="accel,alt"
}}}
on start-up on a Linux box with a german keyborad layout. Is this expected? I am not sure whether this breaks (chrome) stuff yet.
Seems to be unrelated to the keyboardevent patch as I see it in a vanilla Firefox as well.