Bug 921169 - Implement secure DOM localization. r=gandalf

The initial discussion took place in the mailing list:

    https://groups.google.com/d/msg/mozilla.tools.l10n/9JvxgTUwIrk/70ja-BE55kQJ

Goals
-----

    1. Make it possible to localize content in HTML elements and
       attributes without forcing developers to split strings into pre-
       and post- parts (definitely a bad practice).  For instance, it
       should be possible for an <a> element to be a part of the
       translation.

    2. Make it possible for localizers to apply text-level semantics to
       the translations and make use of HTML entities.  For instance,
       it should be possible for a localizer to use an <sup> element in
       "M<sup>me</me>" (an abbreviation of French "Madame").

Constraints
-----------

    1. Make the whole system secure and don't trust translations by
       default allowing a safe set of attributes on HTML elements.  For
       instance, the localizer should not be able to add an onclick
       handler or overwrite the target of href or src without the
       developer or the localization engineer knowingly allowing it.

    2. Don't break the Web;  in particular, until we get more feedback
       and gather more data, we should not break any two-way bindings
       the third-party libraries might have set up on existing DOM
       nodes.

Examples
--------

A safe subset of HTML elements (e.g. em, sup), attributes (e.g. title) and
entities can be used in translations. In addition to the pre-defined
whitelists, any element found in the original source HTML is allowed in the
translation as well. Consider the following source HTML:

    <p data-l10n-id="save">
      <input type="submit">
      <a href="/main" class="btn-cancel"></a>
    </p>

Assume the following malicious translation:

    <save """
      <input value="Save" type="text"> or
      <a href="http://myevilwebsite.com"
         onclick="alert('pwnd!')"
         title="Back to the homepage">cancel</a>.
    """>

The result will be:

    <p data-l10n-id="back">
      <input value="Save" type="submit"> or
      <a href="/main" class="btn-cancel"
         title="Back to the homepage">cancel</a>.
    </p>

The input element is not on the default whitelist but since it's present in the
source HTML, it is also allowed in the translation. The value attribute is
allowed on input elements, but type is not. Similarly, href and onclick
attributes are not allowed in translations and they are not inserted in the
final DOM. However, the title attribute is safe.

It is important to note that applying translations doesn't replace DOM
elements, but only modifies their text nodes and their attributes. The
limitation of the current implementation is that it is yet not possible to
reorder elements in the translation (things may break if you try). See bug
922576.

Specification
-------------

Based on the section of the HTML5 WD on text-level semantics:

    http://www.w3.org/html/wg/drafts/html/master/text-level-semantics.html#text-level-semantics

Elements which are always allowed in translations:

    a, em, strong, small, s, cite, q, dfn, abbr, data, time, code, var,
    samp, kbd, sub, sup, i, b, u, mark, ruby, rt, rp, bdi, bdo, span,
    br, wbr

Except for global attributes, attributes are context-sensitive.  Based on the
list available in the section of the HTML5 WD on the "translate" attribute.

    http://www.w3.org/html/wg/drafts/html/master/dom.html#attr-translate

Global attributes:

    title
    aria-label

a, area

    download

input (only if type is one of button, submit, reset)

    value

menuitem, menu, optgroup, option, track

    label

area, img, input

    alt

input, textarea

    placeholder

th

    abbr