Home

Awesome

Keyboard API

Todo

Rename the API - Chrome have gazumped us.

Quickstart

Install firefox-developer-edition and have it on your PATH.

npm i
npm run run

Or:

Set xpinstall.signatures.required = false in about:config in Firefox Developer Edition or Nightly if you want to install this permanently; otherwise it can be loaded via about:debugging.

All keydown events in your first browser window (regression: only keydown events in about:*, moz-extension://* and on chrome bits work now) will now be logged to the browser console and the test-webextension will toggle suppression of all keydown events if you press its browseraction or press Insert.

For debugging, the API's this is made available as this.keyboard in the browser console of your first window.

Developing

Helpful documentation is located here and here.

Questions for reviewers

Hi, and thanks for reviewing! Here are some particular questions I would like answered, please also give comments on other topics :)

Pre-empting some questions:

Motivation

Firefox wants to continue to support addons that essentially replace the Firefox UX, such as Vimperator, VimFx and Pentadactyl. If they are to be reimplemented these addons require new webextension APIs to be developed. This is one of them.

This API allows callers to listen to keydown events that occur anywhere in the browser, including in the two places that content scripts cannot be injected: the browser chrome and on restricted frames (about:*, addons.mozilla.org). If you don't need that, you'll probably be better served by injecting content scripts or using browser.commands.

Because synchronous interprocess messaging is mostly banned, keydown events cannot be suppressed (stopPropagation(), preventDefault()) in the way that most developers are used to: by the time the API sends you the keydown event, it is too late to cancel it.

Suppression of events is an important feature, so this API offers two methods for suppressing events:

  1. You can suppress or unsuppress all future events with .suppress()
  2. You can declare rules in advance that the API will use to determine whether to suppress each event (this is not implemented yet)

Warning: It is quite possible for two extensions using this API to conflict or interfere with one another. This is considered acceptable: users should not install more than one extension at a time that use this API.

Design

This is subject to change.

Original design was by lydell of vimFx. This turned out to be unworkable because the return value of event listeners cannot be synchronously recovered (Firefox prefers interprocess communication to be asynchronous, and is particularly concerned about the chrome process (where the API lives) making any blocking calls to other processes).

New design is this:

KeyboardEvents are seen, processed and optionally suppressed by this API before Firefox shortcuts, browser.onCommand shortcuts or event listeners defined on DOMWindow objects handle the event.

Suppression rules

I haven't decided how to do this yet, I'm considering a kind of pushdown automata defined by syntax similar to the below.

I'm using a frame script to listen for the events, that will probably mean duplicating the state of the suppression machines, unless I make a synchronous call to the chrome process and let that keep the state, which might be better?

Desired behaviour:

An FSM with transitions on keyevent and attached white/black lists might be good? i in VimFx or <s-esc> in Vimperator could move the FSM into a mostly don't suppress state, and then <s-esc> could move back to normal.

As well as white/black list, will need rules based on target and maybe transitions based on time?

Maybe iptables-like rules, with transitions?

Remember to version the DSL.

Emacs style:

global_key_map = {
  'Ctrl-X': suppress,
  'Ctrl-U': [suppress, undo_key_map],
  '*': incite
};
undo_key_map = {
  'Enter': suppress,
  'Ctrl-G': [suppress, global_key_map],
  '*': suppress
};

Vim style:

normal = {
  target is input: insert_map,
  '<s-esc>': suppress, ignore_map,
  '*': suppress
};
insert_map = {
  'esc': normal_map,
  '*': incite
};
// ...

Concepts

Difficulties:

Current:

Not yet addressed:

Tangential:

Resolved:

Acknowledgements

The denizens of #webextensions, especially zombie, kmag, aswan, The_8472, and rpl.