Merge mozilla-central to autoland a=merge on a CLOSED TREE
authorCoroiu Cristina <ccoroiu@mozilla.com>
Tue, 24 Jul 2018 00:45:40 +0300
changeset 427938 c47bdc24522ff63a7142d98f6db7949613efe3d4
parent 427937 a6b572004dcb6fd66aa27062fe77539de26f0302 (current diff)
parent 427881 fe48e26ca88c7919f0c075dc01d5f9fdccdb1260 (diff)
child 427939 8e9f2c8a1bd8f0abe9ff1c6d1692669d1c7b8c76
push id105593
push userrgurzau@mozilla.com
push dateTue, 24 Jul 2018 09:55:14 +0000
treeherdermozilla-inbound@f636b99a8091 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland a=merge on a CLOSED TREE
dom/security/test/csp/file_child_worker.js
dom/security/test/csp/file_child_worker.js^headers^
dom/security/test/csp/file_main_worker.js
dom/security/test/csp/file_main_worker.js^headers^
modules/libpref/init/all.js
--- a/accessible/aom/AccessibleNode.cpp
+++ b/accessible/aom/AccessibleNode.cpp
@@ -38,16 +38,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(AccessibleNode)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(AccessibleNode)
 
 AccessibleNode::AccessibleNode(nsINode* aNode) :
+    mDoubleProperties(3),
+    mIntProperties(3),
+    mUIntProperties(6),
     mBooleanProperties(0),
     mDOMNode(aNode)
 {
   nsAccessibilityService* accService = GetOrCreateAccService();
   if (!accService) {
     return;
   }
 
--- a/accessible/aom/AccessibleNode.h
+++ b/accessible/aom/AccessibleNode.h
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef A11Y_AOM_ACCESSIBLENODE_H
 #define A11Y_AOM_ACCESSIBLENODE_H
 
+#include "nsDataHashtable.h"
 #include "nsWrapperCache.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Nullable.h"
 
 class nsINode;
 
 namespace mozilla {
@@ -40,16 +41,38 @@ struct ParentObject;
   }                                                         \
 
 #define ANODE_PROPS(typeName, type, ...)                     \
   enum class AOM##typeName##Property {                       \
     MOZ_FOR_EACH(ANODE_ENUM, (), (__VA_ARGS__))              \
   };                                                         \
   MOZ_FOR_EACH(ANODE_FUNC, (typeName, type,), (__VA_ARGS__)) \
 
+#define ANODE_ACCESSOR_MUTATOR(typeName, type, defVal)                          \
+  nsDataHashtable<nsUint32HashKey, type> m##typeName##Properties;               \
+                                                                                \
+  dom::Nullable<type> GetProperty(AOM##typeName##Property aProperty)            \
+  {                                                                             \
+    type value = defVal;                                                        \
+    if (m##typeName##Properties.Get(static_cast<int>(aProperty), &value)) {     \
+      return dom::Nullable<type>(value);                                        \
+    }                                                                           \
+    return dom::Nullable<type>();                                               \
+  }                                                                             \
+                                                                                \
+  void SetProperty(AOM##typeName##Property aProperty,                           \
+                   const dom::Nullable<type>& aValue)                           \
+  {                                                                             \
+    if (aValue.IsNull()) {                                                      \
+      m##typeName##Properties.Remove(static_cast<int>(aProperty));              \
+    } else {                                                                    \
+      m##typeName##Properties.Put(static_cast<int>(aProperty), aValue.Value()); \
+    }                                                                           \
+  }                                                                             \
+
 class AccessibleNode : public nsISupports,
                        public nsWrapperCache
 {
 public:
   explicit AccessibleNode(nsINode* aNode);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS;
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AccessibleNode);
@@ -79,16 +102,37 @@ public:
     Modal,
     Multiline,
     Multiselectable,
     ReadOnly,
     Required,
     Selected
   )
 
+  ANODE_PROPS(UInt, uint32_t,
+    ColIndex,
+    ColSpan,
+    Level,
+    PosInSet,
+    RowIndex,
+    RowSpan
+  )
+
+  ANODE_PROPS(Int, int32_t,
+    ColCount,
+    RowCount,
+    SetSize
+  )
+
+  ANODE_PROPS(Double, double,
+    ValueMax,
+    ValueMin,
+    ValueNow
+  )
+
 protected:
   AccessibleNode(const AccessibleNode& aCopy) = delete;
   AccessibleNode& operator=(const AccessibleNode& aCopy) = delete;
   virtual ~AccessibleNode();
 
   dom::Nullable<bool> GetProperty(AOMBooleanProperty aProperty)
   {
     int num = static_cast<int>(aProperty);
@@ -107,16 +151,20 @@ protected:
       mBooleanProperties &= ~(1U << (2 * num));
     } else {
       mBooleanProperties |= (1U << (2 * num));
       mBooleanProperties = (aValue.Value() ? mBooleanProperties | (1U << (2 * num + 1))
                                            : mBooleanProperties & ~(1U << (2 * num + 1)));
     }
   }
 
+  ANODE_ACCESSOR_MUTATOR(Double, double, 0.0)
+  ANODE_ACCESSOR_MUTATOR(Int, int32_t, 0)
+  ANODE_ACCESSOR_MUTATOR(UInt, uint32_t, 0)
+
   // The 2k'th bit indicates whether the k'th boolean property is used(1) or not(0)
   // and 2k+1'th bit contains the property's value(1:true, 0:false)
   uint32_t mBooleanProperties;
 
   RefPtr<a11y::Accessible> mIntl;
   RefPtr<nsINode> mDOMNode;
   RefPtr<dom::DOMStringList> mStates;
 };
--- a/accessible/jsat/AccessFu.jsm
+++ b/accessible/jsat/AccessFu.jsm
@@ -403,22 +403,19 @@ var Input = {
     mm.sendAsyncMessage("AccessFu:SetSelection", aDetails);
   },
 
   clipboard: function clipboard(aDetails) {
     const mm = Utils.getMessageManager();
     mm.sendAsyncMessage("AccessFu:Clipboard", aDetails);
   },
 
-  activateCurrent: function activateCurrent(aData, aActivateIfKey = false) {
+  activateCurrent: function activateCurrent(aData) {
     let mm = Utils.getMessageManager();
-    let offset = 0;
-
-    mm.sendAsyncMessage("AccessFu:Activate",
-                        {offset, activateIfKey: aActivateIfKey});
+    mm.sendAsyncMessage("AccessFu:Activate", { offset: 0 });
   },
 
   // XXX: This is here for backwards compatability with screen reader simulator
   // it should be removed when the extension is updated on amo.
   scroll: function scroll(aPage, aHorizontal) {
     this.sendScrollMessage(aPage, aHorizontal);
   },
 
--- a/accessible/jsat/ContentControl.jsm
+++ b/accessible/jsat/ContentControl.jsm
@@ -181,26 +181,16 @@ this.ContentControl.prototype = {
     this.autoMove(null, aMessage.json);
   },
 
   handleActivate: function cc_handleActivate(aMessage) {
     let activateAccessible = (aAccessible) => {
       Logger.debug(() => {
         return ["activateAccessible", Logger.accessibleToString(aAccessible)];
       });
-      try {
-        if (aMessage.json.activateIfKey &&
-          !Utils.isActivatableOnFingerUp(aAccessible)) {
-          // Only activate keys, don't do anything on other objects.
-          return;
-        }
-      } catch (e) {
-        // accessible is invalid. Silently fail.
-        return;
-      }
 
       if (aAccessible.actionCount > 0) {
         aAccessible.doAction(0);
       } else {
         let control = Utils.getEmbeddedControl(aAccessible);
         if (control && control.actionCount > 0) {
           control.doAction(0);
         }
@@ -224,18 +214,19 @@ this.ContentControl.prototype = {
         for (let eventType of ["mousedown", "mouseup"]) {
           let evt = this.document.createEvent("MouseEvents");
           evt.initMouseEvent(eventType, true, true, this.window,
             x, y, 0, 0, 0, false, false, false, false, 0, null);
           node.dispatchEvent(evt);
         }
       }
 
-      if (!Utils.isActivatableOnFingerUp(aAccessible)) {
-        // Keys will typically have a sound of their own.
+      // Action invoked will be presented on checked/selected state change.
+      if (!Utils.getState(aAccessible).contains(States.CHECKABLE) &&
+          !Utils.getState(aAccessible).contains(States.SELECTABLE)) {
         this._contentScope.get().sendAsyncMessage("AccessFu:Present",
           Presentation.actionInvoked(aAccessible, "click"));
       }
     };
 
     let focusedAcc = Utils.AccService.getAccessibleFor(
       this.document.activeElement);
     if (focusedAcc && this.vc.position === focusedAcc
--- a/accessible/jsat/EventManager.jsm
+++ b/accessible/jsat/EventManager.jsm
@@ -145,48 +145,35 @@ this.EventManager.prototype = {
         const position = event.newAccessible;
 
         // We pass control to the vc in the embedded frame.
         if (position && position.role == Roles.INTERNAL_FRAME) {
           break;
         }
 
         // Blur to document if new position is not explicitly focused.
-        if (!Utils.getState(position).contains(States.FOCUSED)) {
+        if (!position || !Utils.getState(position).contains(States.FOCUSED)) {
           aEvent.accessibleDocument.takeFocus();
         }
 
         this.present(
           Presentation.pivotChanged(position, event.oldAccessible,
                                     event.newStartOffset, event.newEndOffset,
                                     event.reason, event.boundaryType));
 
         break;
       }
       case Events.STATE_CHANGE:
       {
-        let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
-        let state = Utils.getState(event);
+        const event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
+        const state = Utils.getState(event);
         if (state.contains(States.CHECKED)) {
-          if (aEvent.accessible.role === Roles.SWITCH) {
-            this.present(
-              Presentation.
-                actionInvoked(aEvent.accessible,
-                              event.isEnabled ? "on" : "off"));
-          } else {
-            this.present(
-              Presentation.
-                actionInvoked(aEvent.accessible,
-                              event.isEnabled ? "check" : "uncheck"));
-          }
+          this.present(Presentation.checked(aEvent.accessible));
         } else if (state.contains(States.SELECTED)) {
-          this.present(
-            Presentation.
-              actionInvoked(aEvent.accessible,
-                            event.isEnabled ? "select" : "unselect"));
+          this.present(Presentation.selected(aEvent.accessible));
         }
         break;
       }
       case Events.NAME_CHANGE:
       {
         let acc = aEvent.accessible;
         if (acc === this.contentControl.vc.position) {
           this.present(Presentation.nameChanged(acc));
--- a/accessible/jsat/OutputGenerator.jsm
+++ b/accessible/jsat/OutputGenerator.jsm
@@ -765,42 +765,30 @@ var UtteranceGenerator = {  // jshint ig
   _addRole: function _addRole(aOutput, aAccessible, aRoleStr) {
     if (this.mathmlRolesSet.has(aAccessible.role)) {
       this._addMathRoles(aOutput, aAccessible, aRoleStr);
     } else {
       aOutput.push({string: this._getOutputName(aRoleStr)});
     }
   },
 
+  /**
+   * Add localized state information to output data.
+   * Note: We do not expose checked and selected states, we let TalkBack do it for us
+   * there. This is because we expose the checked information on the node info itself.
+   */
   _addState: function _addState(aOutput, aState, aRoleStr) {
-
     if (aState.contains(States.UNAVAILABLE)) {
       aOutput.push({string: "stateUnavailable"});
     }
 
     if (aState.contains(States.READONLY)) {
       aOutput.push({string: "stateReadonly"});
     }
 
-    // Don't utter this in Jelly Bean, we let TalkBack do it for us there.
-    // This is because we expose the checked information on the node itself.
-    // XXX: this means the checked state is always appended to the end,
-    // regardless of the utterance ordering preference.
-    if ((Utils.AndroidSdkVersion < 16 || Utils.MozBuildApp === "browser") &&
-      aState.contains(States.CHECKABLE)) {
-      let checked = aState.contains(States.CHECKED);
-      let statetr;
-      if (aRoleStr === "switch") {
-        statetr = checked ? "stateOn" : "stateOff";
-      } else {
-        statetr = checked ? "stateChecked" : "stateNotChecked";
-      }
-      aOutput.push({string: statetr});
-    }
-
     if (aState.contains(States.PRESSED)) {
       aOutput.push({string: "statePressed"});
     }
 
     if (aState.contains(States.EXPANDABLE)) {
       let statetr = aState.contains(States.EXPANDED) ?
         "stateExpanded" : "stateCollapsed";
       aOutput.push({string: statetr});
@@ -812,20 +800,16 @@ var UtteranceGenerator = {  // jshint ig
 
     if (aState.contains(States.TRAVERSED)) {
       aOutput.push({string: "stateTraversed"});
     }
 
     if (aState.contains(States.HASPOPUP)) {
       aOutput.push({string: "stateHasPopup"});
     }
-
-    if (aState.contains(States.SELECTED)) {
-      aOutput.push({string: "stateSelected"});
-    }
   },
 
   _getListUtterance:
     function _getListUtterance(aAccessible, aRoleStr, aFlags, aItemCount) {
       let utterance = [];
       this._addRole(utterance, aAccessible, aRoleStr);
       utterance.push({
         string: this._getOutputName("listItemsCount"),
--- a/accessible/jsat/Presentation.jsm
+++ b/accessible/jsat/Presentation.jsm
@@ -93,35 +93,48 @@ class AndroidPresentor {
 
   focused(aObject) {
     let info = this._infoFromContext(
       new PivotContext(aObject, null, -1, -1, true, false));
     return [{ eventType: AndroidEvents.VIEW_FOCUSED, ...info }];
   }
 
   /**
+   * An object's check action has been invoked.
+   * Note: Checkable objects use TalkBack's text derived from the event state, so we don't
+   * populate the text here.
+   * @param {nsIAccessible} aAccessible the object that has been invoked.
+   */
+  checked(aAccessible) {
+    return [{
+      eventType: AndroidEvents.VIEW_CLICKED,
+      checked: Utils.getState(aAccessible).contains(States.CHECKED)
+    }];
+  }
+
+  /**
+   * An object's select action has been invoked.
+   * @param {nsIAccessible} aAccessible the object that has been invoked.
+   */
+  selected(aAccessible) {
+    return [{
+      eventType: AndroidEvents.VIEW_CLICKED,
+      selected: Utils.getState(aAccessible).contains(States.SELECTED)
+    }];
+  }
+
+  /**
    * An object's action has been invoked.
-   * @param {nsIAccessible} aObject the object that has been invoked.
+   * @param {nsIAccessible} aAccessible the object that has been invoked.
    * @param {string} aActionName the name of the action.
    */
-  actionInvoked(aObject, aActionName) {
-    let state = Utils.getState(aObject);
-
-    // Checkable objects use TalkBack's text derived from the event state,
-    // so we don't populate the text here.
-    let text = null;
-    if (!state.contains(States.CHECKABLE)) {
-      text = Utils.localize(UtteranceGenerator.genForAction(aObject,
-        aActionName));
-    }
-
+  actionInvoked(aAccessible, aActionName) {
     return [{
       eventType: AndroidEvents.VIEW_CLICKED,
-      text,
-      checked: state.contains(States.CHECKED)
+      text: Utils.localize(UtteranceGenerator.genForAction(aAccessible, aActionName))
     }];
   }
 
   /**
    * Text has changed, either by the user or by the system. TODO.
    */
   textChanged(aAccessible, aIsInserted, aStart, aLength, aText, aModifiedText) {
     let androidEvent = {
@@ -287,16 +300,17 @@ class AndroidPresentor {
     const info = {
       bounds: aContext.bounds,
       focusable: state.contains(States.FOCUSABLE),
       focused: state.contains(States.FOCUSED),
       clickable: aContext.accessible.actionCount > 0,
       checkable: state.contains(States.CHECKABLE),
       checked: state.contains(States.CHECKED),
       editable: state.contains(States.EDITABLE),
+      selected: state.contains(States.SELECTED)
     };
 
     if (EDIT_TEXT_ROLES.has(aContext.accessible.role)) {
       let textAcc = aContext.accessible.QueryInterface(Ci.nsIAccessibleText);
       return {
         ...info,
         className: "android.widget.EditText",
         hint: aContext.accessible.name,
--- a/accessible/jsat/Utils.jsm
+++ b/accessible/jsat/Utils.jsm
@@ -380,24 +380,16 @@ var Utils = { // jshint ignore:line
                                                     aExcludeOrdered) {
     let parent = aStaticText.parent;
     if (aExcludeOrdered && parent.parent.DOMNode.nodeName === "OL") {
       return false;
     }
 
     return parent.role === Roles.LISTITEM && parent.childCount > 1 &&
       aStaticText.indexInParent === 0;
-  },
-
-  isActivatableOnFingerUp: function isActivatableOnFingerUp(aAccessible) {
-    if (aAccessible.role === Roles.KEY) {
-      return true;
-    }
-    let quick_activate = this.getAttributes(aAccessible)["moz-quick-activate"];
-    return quick_activate && JSON.parse(quick_activate);
   }
 };
 
 /**
  * State object used internally to process accessible's states.
  * @param {Number} aBase     Base state.
  * @param {Number} aExtended Extended state.
  */
--- a/accessible/tests/mochitest/aom/test_general.html
+++ b/accessible/tests/mochitest/aom/test_general.html
@@ -46,16 +46,40 @@
     anode[prop] = true;
     is(anode[prop], true, `anode.${prop} was assigned true`);
     anode[prop] = false;
     is(anode[prop], false, `anode.${prop} was assigned false`);
     anode[prop] = null;
     is(anode[prop], null, `anode.${prop} was assigned null`);
   }
 
+  function testDoubleProp(anode, prop) {
+    is(anode[prop], null, `anode.${prop} should be null`);
+    anode[prop] = Number.MAX_VALUE;
+    is(anode[prop], Number.MAX_VALUE, `anode.${prop} was assigned ${Number.MAX_VALUE}`);
+    anode[prop] = null;
+    is(anode[prop], null, `anode.${prop} was assigned null`);
+  }
+
+  function testIntProp(anode, prop) {
+    is(anode[prop], null, `anode.${prop} should be null`);
+    anode[prop] = -1;
+    is(anode[prop], -1, `anode.${prop} was assigned -1`);
+    anode[prop] = null;
+    is(anode[prop], null, `anode.${prop} was assigned null`);
+  }
+
+  function testUIntProp(anode, prop) {
+    is(anode[prop], null, `anode.${prop} should be null`);
+    anode[prop] = 4294967295;
+    is(anode[prop], 4294967295, `anode.${prop} was assigned 4294967295`);
+    anode[prop] = null;
+    is(anode[prop], null, `anode.${prop} was assigned null`);
+  }
+
   // Check that the WebIDL is as expected.
   function checkImplementation(ifrDoc) {
     let anode = ifrDoc.accessibleNode;
     ok(anode, "DOM document has accessible node");
 
     is(anode.role, "document", "correct role of a document accessible node");
     is(anode.DOMNode, ifrDoc, "correct DOM Node of a document accessible node");
 
@@ -113,16 +137,34 @@
 
     const boolProps = ["atomic", "busy", "disabled", "expanded", "hidden", "modal",
                        "multiline", "multiselectable", "readOnly", "required", "selected"];
 
     for (const boolProp of boolProps) {
       testBoolProp(anode, boolProp);
     }
 
+    const doubleProps = ["valueMax", "valueMin", "valueNow"];
+
+    for (const doubleProp of doubleProps) {
+      testDoubleProp(anode, doubleProp);
+    }
+
+    const intProps = ["colCount", "rowCount", "setSize"];
+
+    for (const intProp of intProps) {
+      testIntProp(anode, intProp);
+    }
+
+    const uintProps = ["colIndex", "colSpan", "level", "posInSet", "rowIndex", "rowSpan"];
+
+    for (const uintProp of uintProps) {
+      testUIntProp(anode, uintProp);
+    }
+
     // Check if an AccessibleNode is properly cached.
     let node = ifrDoc.createElement("div");
     anode = node.accessibleNode;
     is(anode, node.accessibleNode, "an AccessibleNode is properly cached");
 
     // Adopting node to another document doesn't change .accessibleNode
     let anotherDoc = document.implementation.createDocument("", "", null);
     let adopted_node = anotherDoc.adoptNode(node);
--- a/accessible/tests/mochitest/jsat/jsatcommon.js
+++ b/accessible/tests/mochitest/jsat/jsatcommon.js
@@ -363,16 +363,23 @@ class AccessFuContentTestRunner {
   }
 
   eventTextMatches(aEvent, aExpected) {
     isDeeply(aEvent.text, aExpected,
       "Event text matches. " +
       `Got ${JSON.stringify(aEvent.text)}, expected ${JSON.stringify(aExpected)}.`);
   }
 
+  eventInfoMatches(aEvent, aExpected) {
+    for (let key in aExpected) {
+      is(aEvent[key], aExpected[key], `Event info matches for ${key}. ` +
+         `Got ${aEvent[key]}, expected ${aExpected[key]}.`);
+    }
+  }
+
   androidScrollForward() {
     this.sendMessage({
       name: "AccessFu:AndroidScroll",
       data: { origin: "top", direction: "forward" }
     });
   }
 
   androidScrollBackward() {
--- a/accessible/tests/mochitest/jsat/test_content_integration.html
+++ b/accessible/tests/mochitest/jsat/test_content_integration.html
@@ -39,22 +39,22 @@
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
       runner.isFocused("iframe");
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["many option", "not checked", "check button", "First item", "list", "1 item"]);
+      runner.eventInfoMatches(evt, { checked: false });
+      runner.eventTextMatches(evt, ["many option", "check button", "First item", "list", "1 item"]);
 
       evt = await runner.activateCurrent(0,
-        AndroidEvents.VIEW_CLICKED,
         AndroidEvents.VIEW_CLICKED);
-      is(evt[1].checked, true, "checkbox is checked");
+      is(evt.checked, true, "checkbox is checked");
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["many option"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["much range", "label"]);
@@ -72,35 +72,35 @@
       runner.eventTextMatches(evt, ["Home", "button"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["apple", "button"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["Light", "off", "switch"]);
+      runner.eventInfoMatches(evt, { checked: false });
+      runner.eventTextMatches(evt, ["Light", "switch"]);
 
       evt = await runner.activateCurrent(0,
-        AndroidEvents.VIEW_CLICKED,
         AndroidEvents.VIEW_CLICKED);
-      is(evt[1].checked, true, "checkbox is checked");
+      is(evt.checked, true, "checkbox is checked");
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["slider", "0", "slider", "live"]);
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["Light", "on", "switch"]);
+      runner.eventInfoMatches(evt, { checked: true });
+      runner.eventTextMatches(evt, ["Light", "switch"]);
 
       evt = await runner.activateCurrent(0,
-        AndroidEvents.VIEW_CLICKED,
         AndroidEvents.VIEW_CLICKED);
-      is(evt[1].checked, false, "checkbox is checked");
+      is(evt.checked, false, "checkbox is checked");
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["apple", "button"]);
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["Home", "button"]);
@@ -122,22 +122,22 @@
       runner.eventTextMatches(evt, ["much range", "label"]);
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["many option", "label", "First item", "list", "1 item"]);
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["many option", "checked", "check button"]);
+      runner.eventInfoMatches(evt, { checked: true });
+      runner.eventTextMatches(evt, ["many option", "check button"]);
 
       evt = await runner.activateCurrent(0,
-        AndroidEvents.VIEW_CLICKED,
         AndroidEvents.VIEW_CLICKED);
-      is(evt[1].checked, false, "checkbox is checked");
+      is(evt.checked, false, "checkbox is checked");
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["wow", "heading level 1"]);
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["Back", "button"]);
@@ -175,29 +175,31 @@
       runner.eventTextMatches(evt, ["Traversal Rule test document", "Phone status bar"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["Back", "button"]);
 
       evt = await runner.moveNext("FormElement",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["such app", "many option", "not checked", "check button", "First item", "list", "1 item"]);
+      runner.eventInfoMatches(evt, { checked: false });
+      runner.eventTextMatches(evt, ["such app", "many option", "check button", "First item", "list", "1 item"]);
 
       evt = await runner.moveNext("FormElement",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["much range", "4", "slider"]);
 
       evt = await runner.movePrevious("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["much range", "label"]);
 
       evt = await runner.movePrevious("FormElement",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["many option", "not checked", "check button", "First item", "list", "1 item"]);
+      runner.eventInfoMatches(evt, { checked: false });
+      runner.eventTextMatches(evt, ["many option", "check button", "First item", "list", "1 item"]);
 
       evt = await runner.movePrevious("FormElement",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["Back", "button"]);
 
       await runner.clearCursor();
 
 
@@ -209,17 +211,18 @@
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["Back", "button"]);
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["such app", "wow", "heading level 1"]);
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["many option", "not checked", "check button", "First item", "list", "1 item"]);
+      runner.eventInfoMatches(evt, { checked: false });
+      runner.eventTextMatches(evt, ["many option", "check button", "First item", "list", "1 item"]);
 
       evt = await runner.moveFirst("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       todo_is(evt.text[0], "Phone status bar");
 
       await runner.clearCursor();
 
       evt = await runner.moveNext("Simple",
@@ -410,17 +413,18 @@
       runner.eventTextMatches(evt, ["Traversal Rule test document", "Home", "button"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["banana", "button"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
-      runner.eventTextMatches(evt, ["Light", "off", "switch"]);
+      runner.eventInfoMatches(evt, { checked: false });
+      runner.eventTextMatches(evt, ["Light", "switch"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       runner.eventTextMatches(evt, ["mover", "medium", "slider", "live"]);
 
       evt = await runner.moveNext("Simple",
         AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
       is(evt.exitView, "moveNext", "Reached end of content");
--- a/accessible/tests/mochitest/jsat/test_output.html
+++ b/accessible/tests/mochitest/jsat/test_output.html
@@ -248,21 +248,20 @@ https://bugzilla.mozilla.org/show_bug.cg
           expectedUtterance: [[{"string": "stateHasPopup"},
             {"string": "buttonmenu"}, "I have a popup"], ["I have a popup",
             {"string": "stateHasPopup"}, {"string": "buttonmenu"}]],
           expectedBraille: [[{"string": "buttonmenuAbbr"}, "I have a popup"],
                             ["I have a popup", {"string": "buttonmenuAbbr"}]]
         }, {
           // Test selected tab
           accOrElmOrID: "tab1",
-          expectedUtterance: [[{"string": "pagetablist"},
-            {"string": "stateSelected"}, {"string": "pagetab"},
+          expectedUtterance: [[{"string": "pagetablist"}, {"string": "pagetab"},
             {"string": "objItemOfN", "args": [1, 2]}, "Account"], ["Account",
-            {"string": "stateSelected"}, {"string": "pagetab"},
-            {"string": "objItemOfN", "args": [1, 2]}, {"string": "pagetablist"}]
+            {"string": "pagetab"}, {"string": "objItemOfN", "args": [1, 2]},
+            {"string": "pagetablist"}]
           ],
           expectedBraille: [[{"string": "pagetabAbbr"},
             {"string": "objItemOfN", "args": [1, 2]}, "Account"], ["Account",
             {"string": "pagetabAbbr"},
             {"string": "objItemOfN", "args": [1, 2]}]]
         }, {
           // Test unselected tab
           accOrElmOrID: "tab2",
@@ -272,60 +271,48 @@ https://bugzilla.mozilla.org/show_bug.cg
             {"string": "pagetablist"}]],
           expectedBraille: [[{"string": "pagetabAbbr"},
             {"string": "objItemOfN", "args": [2, 2]}, "Advanced"], ["Advanced",
             {"string": "pagetabAbbr"},
             {"string": "objItemOfN", "args": [2, 2]}]]
         }, {
           // Landing on this label should mimic landing on the checkbox.
           accOrElmOrID: "label1",
-          expectedUtterance: [[{"string": "stateNotChecked"},
-            {"string": "checkbutton"}, "Orange"], ["Orange",
-            {"string": "stateNotChecked"}, {"string": "checkbutton"}]],
-          expectedBraille: [[{"string": "stateUncheckedAbbr"}, "Orange"],
-                            ["Orange", {"string": "stateUncheckedAbbr"}]]
+          expectedUtterance: [[{"string": "checkbutton"}, "Orange"], ["Orange",
+            {"string": "checkbutton"}]],
+          expectedBraille: [["Orange"], ["Orange"]]
         }, {
           // Here we get a top-level view of the form.
           accOrElmOrID: "form1",
-          expectedUtterance: [[{"string": "label"},
-            {"string": "stateNotChecked"}, {"string": "checkbutton"}, "Orange",
-            "Orange", {"string": "stateNotChecked"}, {"string": "checkbutton"},
-            "Blue", {"string": "label"}, "Blue"], ["Orange",
-            {"string": "stateNotChecked"}, {"string": "checkbutton"}, "Orange",
-            {"string": "label"}, "Blue", {"string": "stateNotChecked"},
+          expectedUtterance: [[{"string": "label"}, {"string": "checkbutton"}, "Orange",
+            "Orange", {"string": "checkbutton"}, "Blue", {"string": "label"}, "Blue"],
+            ["Orange", {"string": "checkbutton"}, "Orange", {"string": "label"}, "Blue",
             {"string": "checkbutton"}, "Blue", {"string": "label"}]],
-          expectedBraille: [[{"string": "labelAbbr"},
-            {"string": "stateUncheckedAbbr"}, "Orange", "Orange",
-            {"string": "stateUncheckedAbbr"}, "Blue", {"string": "labelAbbr"},
-            "Blue"], ["Orange", {"string": "stateUncheckedAbbr"}, "Orange",
-            {"string": "labelAbbr"}, "Blue", {"string": "stateUncheckedAbbr"},
-            "Blue", {"string": "labelAbbr"}]]
+          expectedBraille: [[{"string": "labelAbbr"}, "Orange", "Orange", "Blue",
+            {"string": "labelAbbr"}, "Blue"], ["Orange", "Orange",
+            {"string": "labelAbbr"}, "Blue", "Blue", {"string": "labelAbbr"}]]
         }, {
           // This is a non-nesting label.
           accOrElmOrID: "label2",
           expectedUtterance: [[{"string": "label"}, "Blue"],
                               ["Blue", {"string": "label"}]],
           expectedBraille: [[{"string": "labelAbbr"}, "Blue"],
                             ["Blue", {"string": "labelAbbr"}]]
         }, {
           // This is a distinct control.
           accOrElmOrID: "input2",
-          expectedUtterance: [[{"string": "stateNotChecked"},
-            {"string": "checkbutton"}, "Blue"], ["Blue",
-            {"string": "stateNotChecked"}, {"string": "checkbutton"}]],
-          expectedBraille: [[{"string": "stateUncheckedAbbr"}, "Blue"], ["Blue",
-            {"string": "stateUncheckedAbbr"}]]
+          expectedUtterance: [[ {"string": "checkbutton"}, "Blue"],
+                              ["Blue", {"string": "checkbutton"}]],
+          expectedBraille: [["Blue"], ["Blue"]]
         }, {
           // This is a nested control.
           accOrElmOrID: "input1",
-          expectedUtterance: [[{"string": "stateNotChecked"},
-            {"string": "checkbutton"}, "Orange"], ["Orange",
-            {"string": "stateNotChecked"}, {"string": "checkbutton"}]],
-          expectedBraille: [[{"string": "stateUncheckedAbbr"}, "Orange"],
-            ["Orange", {"string": "stateUncheckedAbbr"}]]
+          expectedUtterance: [[ {"string": "checkbutton"}, "Orange"], ["Orange",
+            {"string": "checkbutton"}]],
+          expectedBraille: [["Orange"], ["Orange"]]
         }, {
           // Landing on this label should mimic landing on the entry.
           accOrElmOrID: "label3",
           expectedUtterance: [[{"string": "entry"}, "Joe", "First name:"],
                              ["First name:", "Joe", {"string": "entry"}]],
           expectedBraille: [[{"string": "entryAbbr"}, "Joe", "First name:"],
                             ["First name:", "Joe", {"string": "entryAbbr"}]]
         }, {
@@ -345,40 +332,30 @@ https://bugzilla.mozilla.org/show_bug.cg
         }, {
           accOrElmOrID: "password",
           expectedUtterance: [[{"string": "passwordtext"}, "Secret Password"],
                               ["Secret Password", {"string": "passwordtext"}]],
           expectedBraille: [[{"string": "passwordtextAbbr"}, "Secret Password"],
                             ["Secret Password", {"string": "passwordtextAbbr"}]]
         }, {
           accOrElmOrID: "input5",
-          expectedUtterance: [[{"string": "stateChecked"},
-            {"string": "checkbutton"}, "Boring label"], ["Boring label",
-            {"string": "stateChecked"}, {"string": "checkbutton"}]],
-          expectedBraille: [[{"string": "stateCheckedAbbr"}, "Boring label"],
-            ["Boring label", {"string": "stateCheckedAbbr"}]]
+          expectedUtterance: [[{"string": "checkbutton"}, "Boring label"],
+                              ["Boring label", {"string": "checkbutton"}]],
+          expectedBraille: [["Boring label"], ["Boring label"]]
         }, {
           accOrElmOrID: "radio_unselected",
-          expectedUtterance: [[{"string": "stateNotChecked"},
-            {"string": "radiobutton"}, "any old radio button"],
-            ["any old radio button", {"string": "stateNotChecked"},
-            {"string": "radiobutton"}]
+          expectedUtterance: [[{"string": "radiobutton"}, "any old radio button"],
+                              ["any old radio button", {"string": "radiobutton"}]
           ],
-          expectedBraille: [
-            [{"string": "stateUncheckedAbbr"}, "any old radio button"],
-            ["any old radio button", {"string": "stateUncheckedAbbr"}]]
+          expectedBraille: [["any old radio button"], ["any old radio button"]]
         }, {
           accOrElmOrID: "radio_selected",
-          expectedUtterance: [[{"string": "stateChecked"},
-            {"string": "radiobutton"}, "a unique radio button"],
-            ["a unique radio button", {"string": "stateChecked"},
-            {"string": "radiobutton"}]],
-          expectedBraille: [
-            [{"string": "stateCheckedAbbr"}, "a unique radio button"],
-            ["a unique radio button", {"string": "stateCheckedAbbr"}]]
+          expectedUtterance: [[{"string": "radiobutton"}, "a unique radio button"],
+                              ["a unique radio button", {"string": "radiobutton"}]],
+          expectedBraille: [["a unique radio button"], ["a unique radio button"]]
         }, {
           accOrElmOrID: "togglebutton_notpressed",
           expectedUtterance: [[{"string": "togglebutton"}, "I am not pressed"],
                               ["I am not pressed", {"string": "togglebutton"}]],
           expectedBraille: [
             [{"string": "stateUnpressedAbbr"}, "I am not pressed"],
             ["I am not pressed", {"string": "stateUnpressedAbbr"}]]
         }, {
@@ -432,33 +409,31 @@ https://bugzilla.mozilla.org/show_bug.cg
         }, {
           accOrElmOrID: "gridcell2",
           oldAccOrElmOrID: "grid",
           expectedUtterance: [["4", "7"], ["4", "7"]],
           expectedBraille: [["4", "7"], ["4", "7"]]
         }, {
           accOrElmOrID: "gridcell3",
           oldAccOrElmOrID: "grid",
-          expectedUtterance: [[{"string": "stateSelected"}, "5"],
-                              ["5", {"string": "stateSelected"}]],
+          expectedUtterance: [["5"], ["5"]],
           expectedBraille: [["5"], ["5"]],
         }, {
           accOrElmOrID: "frequency",
           expectedUtterance: [[{"string": "stateCollapsed"},
             {"string": "stateHasPopup"}, {"string": "combobox"}, "15 min"], [
             "15 min", {"string": "stateCollapsed"}, {"string": "stateHasPopup"},
             {"string": "combobox"}]],
           expectedBraille: [[{"string": "comboboxAbbr"}, "15 min"], ["15 min",
             {"string": "comboboxAbbr"}]]
         }, {
           accOrElmOrID: "selected-combobox-option",
           oldAccOrElmOrID: "frequency",
-          expectedUtterance: [[{"string": "stateSelected"},
-            {"string": "comboboxoption"}, "15 min"], ["15 min",
-            {"string": "stateSelected"}, {"string": "comboboxoption"}]],
+          expectedUtterance: [[{"string": "comboboxoption"}, "15 min"],
+                              ["15 min", {"string": "comboboxoption"}]],
           expectedBraille: [[{"string": "comboboxoptionAbbr"}, "15 min"], [
             "15 min", {"string": "comboboxoptionAbbr"}]]
         }, {
           accOrElmOrID: "combobox-option",
           oldAccOrElmOrID: "frequency",
           expectedUtterance: [[{"string": "comboboxoption"}, "30 min"], [
             "30 min", {"string": "comboboxoption"}]],
           expectedBraille: [[{"string": "comboboxoptionAbbr"}, "30 min"], [
@@ -479,29 +454,24 @@ https://bugzilla.mozilla.org/show_bug.cg
                             ["Last sync:", "2 days ago"]]
         }, {
           accOrElmOrID: "statusbar-2",
           expectedUtterance: [["Last sync: 30min ago"],
                               ["Last sync: 30min ago"]],
           expectedBraille: [["Last sync: 30min ago"], ["Last sync: 30min ago"]]
         }, {
           accOrElmOrID: "switch-1",
-          expectedUtterance: [[{"string": "stateOn"}, {"string": "switch"},
-            "Simple switch"], ["Simple switch", {"string": "stateOn"},
-            {"string": "switch"}]],
-          expectedBraille: [[{"string": "stateCheckedAbbr"}, "Simple switch"],
-            ["Simple switch", {"string": "stateCheckedAbbr"}]]
+          expectedUtterance: [[{"string": "switch"}, "Simple switch"],
+                              ["Simple switch", {"string": "switch"}]],
+          expectedBraille: [["Simple switch"], ["Simple switch"]]
         }, {
           accOrElmOrID: "switch-2",
-          expectedUtterance: [[{"string": "stateOff"},
-            {"string": "switch"}, "Another switch"], ["Another switch",
-            {"string": "stateOff"}, {"string": "switch"}]],
-          expectedBraille: [
-            [{"string": "stateUncheckedAbbr"}, "Another switch"],
-            ["Another switch", {"string": "stateUncheckedAbbr"}]]
+          expectedUtterance: [[{"string": "switch"}, "Another switch"],
+                              ["Another switch", {"string": "switch"}]],
+          expectedBraille: [["Another switch"], ["Another switch"]]
         }];
 
         // Test all possible utterance order preference values.
         function testOutputOrder(aOutputOrder) {
           return function() {
             SpecialPowers.pushPrefEnv({
               "set": [[PREF_UTTERANCE_ORDER, aOutputOrder]]
             }, function() {
--- a/browser/app/winlauncher/LauncherProcessWin.cpp
+++ b/browser/app/winlauncher/LauncherProcessWin.cpp
@@ -76,42 +76,16 @@ ShowError(DWORD aError = ::GetLastError(
   if (!result) {
     return;
   }
 
   ::MessageBoxW(nullptr, rawMsgBuf, L"Firefox", MB_OK | MB_ICONERROR);
   ::LocalFree(rawMsgBuf);
 }
 
-static bool
-SetArgv0ToFullBinaryPath(wchar_t* aArgv[])
-{
-  DWORD bufLen = MAX_PATH;
-  mozilla::UniquePtr<wchar_t[]> buf;
-
-  while (true) {
-    buf = mozilla::MakeUnique<wchar_t[]>(bufLen);
-    DWORD retLen = ::GetModuleFileNameW(nullptr, buf.get(), bufLen);
-    if (!retLen) {
-      return false;
-    }
-
-    if (retLen == bufLen && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-      bufLen *= 2;
-      continue;
-    }
-
-    break;
-  }
-
-  // We intentionally leak buf into argv[0]
-  aArgv[0] = buf.release();
-  return true;
-}
-
 namespace mozilla {
 
 // Eventually we want to be able to set a build config flag such that, when set,
 // this function will always return true.
 bool
 RunAsLauncherProcess(int& argc, wchar_t** argv)
 {
   return CheckArg(argc, argv, L"launcher",
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -127,17 +127,16 @@ var whitelist = [
   {file: "chrome://global/skin/tree/sort-asc-classic.png", platforms: ["linux"]},
   {file: "chrome://global/skin/tree/sort-asc.png", platforms: ["linux"]},
   {file: "chrome://global/skin/tree/sort-dsc-classic.png", platforms: ["linux"]},
   {file: "chrome://global/skin/tree/sort-dsc.png", platforms: ["linux"]},
   // Bug 1344267
   {file: "chrome://marionette/content/test_anonymous_content.xul"},
   {file: "chrome://marionette/content/test_dialog.properties"},
   {file: "chrome://marionette/content/test_dialog.xul"},
-  {file: "chrome://marionette/content/PerTestCoverageUtils.jsm"},
   // Bug 1348533
   {file: "chrome://mozapps/skin/downloads/buttons.png", platforms: ["macosx"]},
   {file: "chrome://mozapps/skin/downloads/downloadButtons.png", platforms: ["linux", "win"]},
   // Bug 1348558
   {file: "chrome://mozapps/skin/update/downloadButtons.png",
    platforms: ["linux"]},
   // Bug 1348559
   {file: "chrome://pippki/content/resetpassword.xul"},
@@ -198,16 +197,20 @@ if (!isDevtools) {
   for (let module of ["addons.js", "bookmarks.js", "forms.js", "history.js",
                       "passwords.js", "prefs.js", "tabs.js",
                       "extension-storage.js"]) {
     whitelist.add("resource://services-sync/engines/" + module);
   }
 
 }
 
+if (AppConstants.MOZ_CODE_COVERAGE) {
+  whitelist.add("chrome://marionette/content/PerTestCoverageUtils.jsm");
+}
+
 const gInterestingCategories = new Set([
   "agent-style-sheets", "addon-provider-module", "webextension-modules",
   "webextension-scripts", "webextension-schemas", "webextension-scripts-addon",
   "webextension-scripts-content", "webextension-scripts-devtools"
 ]);
 
 var gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"]
                  .getService(Ci.nsIChromeRegistry);
--- a/browser/base/content/test/static/browser_parsable_css.js
+++ b/browser/base/content/test/static/browser_parsable_css.js
@@ -62,16 +62,25 @@ let whitelist = [
    errorMessage: /Property contained reference to invalid variable.*background/i,
    isFromDevTools: true},
   {sourceName: /devtools\/skin\/animationinspector\.css$/i,
    intermittent: true,
    errorMessage: /Property contained reference to invalid variable.*color/i,
    isFromDevTools: true},
 ];
 
+if (!Services.prefs.getBoolPref("layout.css.xul-box-display-values.content.enabled")) {
+  // These are UA sheets which use non-content-exposed `display` values.
+  whitelist.push({
+    sourceName: /(skin\/shared\/Heartbeat|((?:res|gre-resources)\/(ua|html)))\.css$/i,
+    errorMessage: /Error in parsing value for .*\bdisplay\b/i,
+    isFromDevTools: false
+  });
+}
+
 if (!Services.prefs.getBoolPref("full-screen-api.unprefix.enabled")) {
   whitelist.push({
     sourceName: /(?:res|gre-resources)\/(ua|html)\.css$/i,
     errorMessage: /Unknown pseudo-class .*\bfullscreen\b/i,
     isFromDevTools: false
   }, {
     // PDFjs is futureproofing its pseudoselectors, and those rules are dropped.
     sourceName: /web\/viewer\.css$/i,
--- a/browser/components/preferences/languages.xul
+++ b/browser/components/preferences/languages.xul
@@ -44,17 +44,17 @@
               onsynctopreference="return gLanguagesDialog.writeSpoofEnglish();"/>
     <grid flex="1">
       <columns>
         <column flex="1"/>
         <column/>
       </columns>
       <rows>
         <row flex="1">
-          <richlistbox id="activeLanguages" flex="1" height="200"
+          <richlistbox id="activeLanguages" flex="1"
                        seltype="multiple"
                        onselect="gLanguagesDialog.onLanguageSelect();"/>
           <vbox>
             <button id="up" class="up" oncommand="gLanguagesDialog.moveUp();" disabled="true"
                     data-l10n-id="languages-customize-moveup"
                     preference="pref.browser.language.disable_button.up"/>
             <button id="down" class="down" oncommand="gLanguagesDialog.moveDown();" disabled="true"
                     data-l10n-id="languages-customize-movedown"
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -204,16 +204,20 @@ button > hbox > label {
   width: 30px;
   margin-inline-start: 5px;
 }
 
 #getStarted {
   font-size: 90%;
 }
 
+#activeLanguages {
+  height: 16em;
+}
+
 #activeLanguages > richlistitem {
   padding: 0.3em;
 }
 
 #downloadFolder {
   margin-inline-start: 0;
   padding-inline-start: 30px;
   background-repeat: no-repeat;
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -657,17 +657,17 @@ public:
 
 private:
   friend class MediaRawData;
   explicit MediaRawDataWriter(MediaRawData* aMediaRawData);
   MOZ_MUST_USE bool EnsureSize(size_t aSize);
   MediaRawData* mTarget;
 };
 
-class MediaRawData : public MediaData
+class MediaRawData final : public MediaData
 {
 public:
   MediaRawData();
   MediaRawData(const uint8_t* aData, size_t aSize);
   MediaRawData(const uint8_t* aData, size_t aSize,
                const uint8_t* aAlphaData, size_t aAlphaSize);
 
   // Pointer to data or null if not-yet allocated
@@ -695,21 +695,21 @@ public:
 
   // Indicate to the audio decoder that mDiscardPadding frames should be
   // trimmed.
   uint32_t mDiscardPadding = 0;
 
   RefPtr<TrackInfoSharedPtr> mTrackInfo;
 
   // Return a deep copy or nullptr if out of memory.
-  virtual already_AddRefed<MediaRawData> Clone() const;
+  already_AddRefed<MediaRawData> Clone() const;
   // Create a MediaRawDataWriter for this MediaRawData. The writer is not
   // thread-safe.
-  virtual UniquePtr<MediaRawDataWriter> CreateWriter();
-  virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
+  UniquePtr<MediaRawDataWriter> CreateWriter();
+  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
 protected:
   ~MediaRawData();
 
 private:
   friend class MediaRawDataWriter;
   AlignedByteBuffer mBuffer;
   AlignedByteBuffer mAlphaBuffer;
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -710,16 +710,22 @@ IsVP9CodecString(const nsAString& aCodec
   uint8_t level = 0;
   uint8_t bitDepth = 0;
   return aCodec.EqualsLiteral("vp9") ||
          aCodec.EqualsLiteral("vp9.0") ||
          (StartsWith(NS_ConvertUTF16toUTF8(aCodec), "vp09") &&
           ExtractVPXCodecDetails(aCodec, profile, level, bitDepth));
 }
 
+bool
+IsAV1CodecString(const nsAString& aCodec)
+{
+  return aCodec.EqualsLiteral("av1"); // AV1
+}
+
 UniquePtr<TrackInfo>
 CreateTrackInfoWithMIMEType(const nsACString& aCodecMIMEType)
 {
   UniquePtr<TrackInfo> trackInfo;
   if (StartsWith(aCodecMIMEType, "audio/")) {
     trackInfo.reset(new AudioInfo());
     trackInfo->mMimeType = aCodecMIMEType;
   } else if (StartsWith(aCodecMIMEType, "video/")) {
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -356,16 +356,19 @@ bool
 IsAACCodecString(const nsAString& aCodec);
 
 bool
 IsVP8CodecString(const nsAString& aCodec);
 
 bool
 IsVP9CodecString(const nsAString& aCodec);
 
+bool
+IsAV1CodecString(const nsAString& aCodec);
+
 // Try and create a TrackInfo with a given codec MIME type.
 UniquePtr<TrackInfo>
 CreateTrackInfoWithMIMEType(const nsACString& aCodecMIMEType);
 
 // Try and create a TrackInfo with a given codec MIME type, and optional extra
 // parameters from a container type (its MIME type and codecs are ignored).
 UniquePtr<TrackInfo>
 CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -1,19 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaSource.h"
 
-#if MOZ_AV1
-#include "AOMDecoder.h"
-#endif
 #include "AsyncEventRunner.h"
 #include "DecoderTraits.h"
 #include "Benchmark.h"
 #include "DecoderDoctorDiagnostics.h"
 #include "MediaContainerType.h"
 #include "MediaResult.h"
 #include "MediaSourceDemuxer.h"
 #include "MediaSourceUtils.h"
@@ -130,19 +127,19 @@ MediaSource::IsTypeSupported(const nsASt
     return NS_OK;
   }
   if (mimeType == MEDIAMIMETYPE("video/webm")) {
     if (!(Preferences::GetBool("media.mediasource.webm.enabled", false) ||
           StaticPrefs::MediaCapabilitiesEnabled() ||
           containerType->ExtendedType().Codecs().Contains(
             NS_LITERAL_STRING("vp8")) ||
 #ifdef MOZ_AV1
-          // FIXME: Temporary comparison with the full codecs attribute.
-          // See bug 1377015.
-          AOMDecoder::IsSupportedCodec(containerType->ExtendedType().Codecs().AsString()) ||
+          (StaticPrefs::MediaAv1Enabled() &&
+           IsAV1CodecString(
+             containerType->ExtendedType().Codecs().AsString())) ||
 #endif
           IsWebMForced(aDiagnostics))) {
       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     }
     return NS_OK;
   }
   if (mimeType == MEDIAMIMETYPE("audio/webm")) {
     if (!(Preferences::GetBool("media.mediasource.webm.enabled", false) ||
--- a/dom/media/platforms/agnostic/AOMDecoder.cpp
+++ b/dom/media/platforms/agnostic/AOMDecoder.cpp
@@ -337,23 +337,16 @@ AOMDecoder::Drain()
 bool
 AOMDecoder::IsAV1(const nsACString& aMimeType)
 {
   return aMimeType.EqualsLiteral("video/av1");
 }
 
 /* static */
 bool
-AOMDecoder::IsSupportedCodec(const nsAString& aCodecType)
-{
-  return aCodecType.EqualsLiteral("av1");
-}
-
-/* static */
-bool
 AOMDecoder::IsKeyframe(Span<const uint8_t> aBuffer) {
   aom_codec_stream_info_t info;
   PodZero(&info);
 
   auto res = aom_codec_peek_stream_info(aom_codec_av1_dx(),
                                         aBuffer.Elements(),
                                         aBuffer.Length(),
                                         &info);
--- a/dom/media/platforms/agnostic/AOMDecoder.h
+++ b/dom/media/platforms/agnostic/AOMDecoder.h
@@ -32,19 +32,16 @@ public:
   {
     return NS_LITERAL_CSTRING("av1 libaom video decoder");
   }
 
   // Return true if aMimeType is a one of the strings used
   // by our demuxers to identify AV1 streams.
   static bool IsAV1(const nsACString& aMimeType);
 
-  // Return true if aCodecType is a supported codec description.
-  static bool IsSupportedCodec(const nsAString& aCodecType);
-
   // Return true if a sample is a keyframe.
   static bool IsKeyframe(Span<const uint8_t> aBuffer);
 
   // Return the frame dimensions for a sample.
   static gfx::IntSize GetFrameSize(Span<const uint8_t> aBuffer);
 
 private:
   ~AOMDecoder();
--- a/dom/media/test/can_play_type_webm.js
+++ b/dom/media/test/can_play_type_webm.js
@@ -1,11 +1,11 @@
-function check_webm(v, enabled) {
+async function check_webm(v, enabled) {
   function check(type, expected) {
-    is(v.canPlayType(type), enabled ? expected : "", type);
+    is(v.canPlayType(type), enabled ? expected : "", type + "='" + expected + "'");
   }
 
   // WebM types
   check("video/webm", "maybe");
   check("audio/webm", "maybe");
 
   var video = ['vp8', 'vp8.0', 'vp9', 'vp9.0'];
   var audio = ['vorbis', 'opus'];
@@ -21,9 +21,36 @@ function check_webm(v, enabled) {
         check("video/webm; codecs=\"" + acodec + ", " + vcodec + "\"", "probably");
     });
   });
 
   // Unsupported WebM codecs
   check("video/webm; codecs=xyz", "");
   check("video/webm; codecs=xyz,vorbis", "");
   check("video/webm; codecs=vorbis,xyz", "");
+
+  function getPref(name) {
+    var pref = false;
+    try {
+      pref = SpecialPowers.getBoolPref(name);
+    } catch(ex) { }
+    return pref;
+  }
+
+  function isWindows32() {
+    return navigator.userAgent.includes("Windows") &&
+           !navigator.userAgent.includes("Win64");
+  }
+
+  function isAndroid() {
+    return navigator.userAgent.includes("Android");
+  }
+
+  const haveAv1 = getPref("media.av1.enabled");
+  check("video/webm; codecs=\"av1\"", haveAv1 ? "probably" : "");
+
+  await SpecialPowers.pushPrefEnv({"set": [["media.av1.enabled", true]]});
+  // AV1 is disabled on Windows 32 bits (bug 1475564) and Android (bug 1368843)
+  check("video/webm; codecs=\"av1\"", (isWindows32() || isAndroid()) ? "" : "probably");
+
+  await SpecialPowers.pushPrefEnv({"set": [["media.av1.enabled", false]]});
+  check("video/webm; codecs=\"av1\"", "");
 }
--- a/dom/media/test/test_can_play_type_mpeg.html
+++ b/dom/media/test/test_can_play_type_mpeg.html
@@ -91,16 +91,19 @@ function check_mp4(v, enabled) {
   [ "video/mp4; codecs=vp9",
     "video/mp4; codecs=\"vp9\"",
     "video/mp4; codecs=\"vp9.0\""
   ].forEach((codec) => {
     // canPlayType should support VP9 in MP4...
     check(codec, "probably");
     ok(MediaSource.isTypeSupported(codec), "VP9 in MP4 should be supported in MSE");
   });
+
+  // AV1 (disabled until bug 1417050 is fixed)
+  check("video/mp4; codecs=\"av1\"", "");
 }
 
 function check_mp3(v, enabled) {
   function check(type, expected) {
     var ex = enabled ? expected : "";
     is(v.canPlayType(type), ex, type + "='" + ex + "'");
   }
 
--- a/dom/media/test/test_can_play_type_webm.html
+++ b/dom/media/test/test_can_play_type_webm.html
@@ -16,14 +16,24 @@ a Bug 566245</a>
 <div id="content" style="display: none">
 </div>
 
 <video id="v"></video>
 
 <pre id="test">
 <script src="can_play_type_webm.js"></script>
 <script>
-check_webm(document.getElementById('v'), true);
-mediaTestCleanup();
+  async function runTest() {
+    try {
+      await check_webm(document.getElementById('v'), true);
+      mediaTestCleanup();
+    } catch (e) {
+      info("Exception " + e.message);
+      ok(false, "Threw exception " + e.message);
+    }
+    SimpleTest.finish();
+  }
+  SimpleTest.waitForExplicitFinish();
+  addLoadEvent(runTest);
 </script>
 </pre>
 </body>
 </html>
--- a/dom/media/webm/WebMDecoder.cpp
+++ b/dom/media/webm/WebMDecoder.cpp
@@ -60,17 +60,17 @@ WebMDecoder::GetTracksInfo(const MediaCo
         if (ExtractVPXCodecDetails(codec, profile, level, bitDepth)) {
           trackInfo->GetAsVideoInfo()->mBitDepth = bitDepth;
         }
         tracks.AppendElement(std::move(trackInfo));
         continue;
       }
     }
 #ifdef MOZ_AV1
-    if (AOMDecoder::IsSupportedCodec(codec)) {
+    if (StaticPrefs::MediaAv1Enabled() && IsAV1CodecString(codec)) {
       tracks.AppendElement(
         CreateTrackInfoWithMIMETypeAndContainerTypeExtraParameters(
           NS_LITERAL_CSTRING("video/av1"), aType));
       continue;
     }
 #endif
     // Unknown codec
     aError =
deleted file mode 100644
--- a/dom/security/test/csp/file_child_worker.js
+++ /dev/null
@@ -1,39 +0,0 @@
-function doXHR(uri) {
-  try {
-    var xhr = new XMLHttpRequest();
-    xhr.open("GET", uri);
-    xhr.send();
-  } catch(ex) {}
-}
-
-var sameBase = "http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=";
-var crossBase = "http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=";
-
-onmessage = (e) => {
-  for (base of [sameBase, crossBase]) {
-    var prefix;
-    var suffix;
-    if (e.data.inherited == "parent") {
-      //Worker inherits CSP from parent worker
-      prefix = base + "worker_child_inherited_parent_";
-      suffix = base == sameBase ? "_good" : "_bad";
-    } else if (e.data.inherited == "document") {
-      //Worker inherits CSP from owner document -> parent worker -> subworker
-      prefix = base + "worker_child_inherited_document_";
-      suffix = base == sameBase ? "_good" : "_bad";
-    } else {
-      // Worker delivers CSP from HTTP header
-      prefix = base + "worker_child_";
-      suffix = base == sameBase ? "_same_bad" : "_cross_bad";
-    }
-
-    doXHR(prefix + "xhr" + suffix);
-    // Fetch is likely failed in subworker
-    // See Bug 1273070 - Failed to fetch in subworker
-    // Enable fetch test after the bug is fixed
-    // fetch(prefix + "xhr" + suffix);
-    try {
-      importScripts(prefix + "script" + suffix);
-    } catch(ex) {}
-  }
-}
deleted file mode 100644
--- a/dom/security/test/csp/file_child_worker.js^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Security-Policy: default-src 'none'
--- a/dom/security/test/csp/file_main.js
+++ b/dom/security/test/csp/file_main.js
@@ -1,51 +1,14 @@
-function doXHR(uri, callback) {
+function doXHR(uri) {
   try {
     var xhr = new XMLHttpRequest();
     xhr.open("GET", uri);
-    xhr.responseType = "blob";
     xhr.send();
-    xhr.onload = function () {
-      if (callback) callback(xhr.response);
-    }
   } catch(ex) {}
 }
 
 doXHR("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_good");
 doXHR("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=xhr_bad");
 fetch("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=fetch_good");
 fetch("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=fetch_bad");
 navigator.sendBeacon("http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=beacon_good");
 navigator.sendBeacon("http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=beacon_bad");
-
-var topWorkerBlob;
-var nestedWorkerBlob;
-
-doXHR("file_main_worker.js", function (topResponse) {
-  topWorkerBlob = URL.createObjectURL(topResponse);
-  doXHR("file_child_worker.js", function (response) {
-    nestedWorkerBlob = URL.createObjectURL(response);
-    runWorker();
-  });
-});
-
-function runWorker() {
-  // Top level worker, no subworker
-  // Worker does not inherit CSP from owner document
-  new Worker("file_main_worker.js").postMessage({inherited : "none"});
-
-  // Top level worker, no subworker
-  // Worker inherits CSP from owner document
-  new Worker(topWorkerBlob).postMessage({inherited : "document"});
-
-  // Subworker
-  // Worker does not inherit CSP from parent worker
-  new Worker("file_main_worker.js").postMessage({inherited : "none", nested : nestedWorkerBlob});
-
-  // Subworker
-  // Worker inherits CSP from parent worker
-  new Worker("file_main_worker.js").postMessage({inherited : "parent", nested : nestedWorkerBlob});
-
-  // Subworker
-  // Worker inherits CSP from owner document -> parent worker -> subworker
-  new Worker(topWorkerBlob).postMessage({inherited : "document", nested : nestedWorkerBlob});
-}
deleted file mode 100644
--- a/dom/security/test/csp/file_main_worker.js
+++ /dev/null
@@ -1,48 +0,0 @@
-function doXHR(uri) {
-  try {
-    var xhr = new XMLHttpRequest();
-    xhr.open("GET", uri);
-    xhr.send();
-  } catch(ex) {}
-}
-
-var sameBase = "http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs?testid=";
-var crossBase = "http://example.com/tests/dom/security/test/csp/file_CSP.sjs?testid=";
-
-onmessage = (e) => {
-  // Tests of nested worker
-  if (e.data.nested) {
-    if (e.data.inherited != "none") {
-      // Worker inherits CSP
-      new Worker(e.data.nested).postMessage({inherited : e.data.inherited});
-    }
-    else {
-      // Worker does not inherit CSP
-      new Worker("file_child_worker.js").postMessage({inherited : e.data.inherited});
-    }
-    return;
-  }
-
-  //Tests of top level worker
-  for (base of [sameBase, crossBase]) {
-    var prefix;
-    var suffix;
-    if (e.data.inherited != "none") {
-      // Top worker inherits CSP from owner document
-      prefix = base + "worker_inherited_";
-      suffix = base == sameBase ? "_good" : "_bad";
-    }
-    else {
-      // Top worker delivers CSP from HTTP header
-      prefix = base + "worker_";
-      suffix = base == sameBase ? "_same_bad" : "_cross_good";
-    }
-
-    doXHR(prefix + "xhr" + suffix);
-    fetch(prefix + "fetch" + suffix);
-    try {
-      if (e.data.inherited == "none") suffix = base == sameBase ? "_same_good" : "_cross_bad";
-      importScripts(prefix + "script" + suffix);
-    } catch(ex) {}
-  }
-}
deleted file mode 100644
--- a/dom/security/test/csp/file_main_worker.js^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Security-Policy: default-src 'self' blob: ; connect-src http://example.com
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/main_csp_worker.html
@@ -0,0 +1,439 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <title>Bug 1475849: Test CSP worker inheritance</title>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script type="application/javascript" src="worker_helper.js"></script>
+
+  </head>
+  <body>
+    <script type="application/javascript">
+      const SJS = "worker.sjs";
+      const SAME_BASE = "http://mochi.test:8888/tests/dom/security/test/csp/file_CSP.sjs";
+      const CROSS_BASE = "http://example.com/tests/dom/security/test/csp/file_CSP.sjs";
+
+      SimpleTest.waitForExplicitFinish();
+      /* test data format :
+        {
+          id: test id, short description of test,
+          base: URL of the request in worker,
+          action: type of request in worker (fetch, xhr, importscript)
+          type: how do we create the worker, from URL or Blob,
+          csp: csp of worker,
+          child: how do we create the child worker, from URL or Blob,
+          childCsp: csp of child worker
+          expectedBlock: result when CSP policy, true or false
+        }
+      */
+
+      // Document's CSP is defined in main_csp_worker.html^headers^
+      // Content-Security-Policy: default-src 'self' blob: 'unsafe-inline'
+      var tests = [
+        // create new Worker(url), worker's csp should be deliveried from header.
+        // csp should be: default-src 'self' blob: ; connect-src CROSS_BASE
+        {
+          id: "worker_url_fetch_same_bad",
+          base: SAME_BASE,
+          action: "fetch",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_importScripts_same_good",
+          base: SAME_BASE,
+          action: "importScripts",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_url_xhr_same_bad",
+          base: SAME_BASE,
+          action: "xhr",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_fetch_cross_good",
+          base: CROSS_BASE,
+          action: "fetch",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_url_importScripts_cross_bad",
+          base: CROSS_BASE,
+          action: "importScripts",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_xhr_cross_good",
+          base: CROSS_BASE,
+          action: "xhr",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: false
+        },
+
+        // create new Worker(blob:), worker's csp should be inherited from
+        // document.
+        // csp should be : default-src 'self' blob: 'unsafe-inline'
+        {
+          id: "worker_blob_fetch_same_good",
+          base: SAME_BASE,
+          action: "fetch",
+          type: "blob",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_blob_xhr_same_good",
+          base: SAME_BASE,
+          action: "xhr",
+          type: "blob",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_blob_importScripts_same_good",
+          base: SAME_BASE,
+          action: "importScripts",
+          type: "blob",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_blob_fetch_cross_bad",
+          base: CROSS_BASE,
+          action: "fetch",
+          type: "blob",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_xhr_cross_bad",
+          base: CROSS_BASE,
+          action: "xhr",
+          type: "blob",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_importScripts_cross_bad",
+          base: CROSS_BASE,
+          action: "importScripts",
+          type: "blob",
+          csp: "default-src 'self' blob: ; connect-src http://example.com",
+          expectBlocked: true
+        },
+
+        // create parent worker from url, child worker from blob,
+        // Parent delivery csp then propagate to child
+        // csp should be: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+        {
+          id: "worker_url_child_blob_fetch_same_good",
+          base: SAME_BASE,
+          action: "fetch",
+          child: "blob",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_url_child_blob_importScripts_same_good",
+          base: SAME_BASE,
+          action: "importScripts",
+          child: "blob",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_url_child_blob_xhr_same_good",
+          base: SAME_BASE,
+          child: "blob",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_url_child_blob_fetch_cross_good",
+          base: CROSS_BASE,
+          action: "fetch",
+          child: "blob",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+          expectBlocked: false
+        },
+        {
+          id: "worker_url_child_blob_importScripts_cross_bad",
+          base: CROSS_BASE,
+          action: "importScripts",
+          child: "blob",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_child_blob_xhr_cross_godd",
+          base: CROSS_BASE,
+          child: "blob",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "url",
+          csp: "default-src 'self' blob: ; connect-src 'self' http://example.com",
+          expectBlocked: false
+        },
+
+
+        // create parent worker from blob, child worker from blob,
+        // Csp: document->parent->child
+        // csp should be : default-src 'self' blob: 'unsafe-inline'
+        {
+          id: "worker_blob_child_blob_fetch_same_good",
+          base: SAME_BASE,
+          child: "blob",
+          childCsp: "default-src 'none'",
+          action: "fetch",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: false
+        },
+        {
+          id: "worker_blob_child_blob_xhr_same_good",
+          base: SAME_BASE,
+          child: "blob",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: false
+        },
+        {
+          id: "worker_blob_child_blob_importScripts_same_good",
+          base: SAME_BASE,
+          action: "importScripts",
+          child: "blob",
+          childCsp: "default-src 'none'",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: false
+        },
+        {
+          id: "worker_blob_child_blob_fetch_cross_bad",
+          base: CROSS_BASE,
+          child: "blob",
+          childCsp: "default-src 'none'",
+          action: "fetch",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_blob_xhr_cross_bad",
+          base: CROSS_BASE,
+          child: "blob",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_blob_importScripts_cross_bad",
+          base: CROSS_BASE,
+          action: "importScripts",
+          child: "blob",
+          childCsp: "default-src 'none'",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+
+        // create parent worker from url, child worker from url,
+        // child delivery csp from header
+        // csp should be : default-src 'none'
+        {
+          id: "worker_url_child_url_fetch_cross_bad",
+          base: CROSS_BASE,
+          action: "fetch",
+          child: "url",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_child_url_xhr_cross_bad",
+          base: CROSS_BASE,
+          child: "url",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "url",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_child_url_importScripts_cross_bad",
+          base: CROSS_BASE,
+          action: "importScripts",
+          child: "url",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_child_url_fetch_same_bad",
+          base: SAME_BASE,
+          action: "fetch",
+          child: "url",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_child_url_xhr_same_bad",
+          base: SAME_BASE,
+          child: "url",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "url",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_url_child_url_importScripts_same_bad",
+          base: SAME_BASE,
+          action: "importScripts",
+          child: "url",
+          childCsp: "default-src 'none'",
+          type: "url",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+
+        // create parent worker from blob, child worker from url,
+        // child delivery csp from header
+        // csp should be : default-src 'none'
+        {
+          id: "worker_blob_child_url_fetch_cross_bad",
+          base: CROSS_BASE,
+          child: "url",
+          childCsp: "default-src 'none'",
+          action: "fetch",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_url_xhr_cross_bad",
+          base: CROSS_BASE,
+          child: "url",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_url_importScripts_cross_bad",
+          base: CROSS_BASE,
+          action: "importScripts",
+          child: "url",
+          childCsp: "default-src 'none'",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_url_fetch_same_bad",
+          base: SAME_BASE,
+          child: "url",
+          childCsp: "default-src 'none'",
+          action: "fetch",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_url_xhr_same_bad",
+          base: SAME_BASE,
+          child: "url",
+          childCsp: "default-src 'none'",
+          action: "xhr",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+        {
+          id: "worker_blob_child_url_importScripts_same_bad",
+          base: SAME_BASE,
+          action: "importScripts",
+          child: "url",
+          childCsp: "default-src 'none'",
+          type: "blob",
+          csp: "default-src 'self' blob:",
+          expectBlocked: true
+        },
+
+
+      ];
+
+      async function runWorkerTest(data) {
+        let src = SJS;
+        src += "?base=" + escape(data.base);
+        src += "&action=" + escape(data.action);
+        src += "&csp=" + escape(data.csp);
+        src += "&id=" + escape(data.id);
+
+        if (data.child) {
+          src += "&child=" + escape(data.child);
+        }
+
+        if (data.childCsp) {
+          src += "&childCsp=" + escape(data.childCsp);
+        }
+
+        switch (data.type) {
+          case "url":
+            new Worker(src);
+            break;
+
+          case "blob":
+            new Worker(URL.createObjectURL(await doXHRGetBlob(src)));
+            break;
+
+          default:
+            throw "Unsupport type";
+        }
+
+        let checkUri = data.base + "?id=" + data.id;
+        await assertCSPBlock(checkUri, data.expectBlocked);
+        runNextTest();
+      };
+
+      tests.forEach(function(test) {
+        addAsyncTest(async function() {
+          runWorkerTest(test);
+        });
+      });
+
+      runNextTest();
+    </script>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/main_csp_worker.html^headers^
@@ -0,0 +1,1 @@
+Content-Security-Policy: default-src 'self' blob: 'unsafe-inline'
--- a/dom/security/test/csp/mochitest.ini
+++ b/dom/security/test/csp/mochitest.ini
@@ -42,20 +42,16 @@ support-files =
   file_inlinestyle_main.html
   file_inlinestyle_main.html^headers^
   file_inlinestyle_main_allowed.html
   file_inlinestyle_main_allowed.html^headers^
   file_invalid_source_expression.html
   file_main.html
   file_main.html^headers^
   file_main.js
-  file_main_worker.js
-  file_main_worker.js^headers^
-  file_child_worker.js
-  file_child_worker.js^headers^
   file_web_manifest.html
   file_web_manifest_remote.html
   file_web_manifest_https.html
   file_web_manifest.json
   file_web_manifest.json^headers^
   file_web_manifest_https.json
   file_web_manifest_mixed_content.html
   file_bug836922_npolicies.html
@@ -358,8 +354,14 @@ support-files =
   file_spawn_service_worker.js
 [test_frame_src.html]
 support-files =
   file_frame_src_frame_governs.html
   file_frame_src_child_governs.html
   file_frame_src.js
   file_frame_src_inner.html
 [test_security_policy_violation_event.html]
+[test_csp_worker_inheritance.html]
+support-files =
+  worker.sjs
+  worker_helper.js
+  main_csp_worker.html
+  main_csp_worker.html^headers^
--- a/dom/security/test/csp/test_CSP.html
+++ b/dom/security/test/csp/test_CSP.html
@@ -24,40 +24,16 @@ window.tests = {
   script_good: -1,
   script_bad: -1,
   xhr_good: -1,
   xhr_bad: -1,
   fetch_good: -1,
   fetch_bad: -1,
   beacon_good: -1,
   beacon_bad: -1,
-  worker_xhr_same_bad: -1,
-  worker_xhr_cross_good: -1,
-  worker_fetch_same_bad: -1,
-  worker_fetch_cross_good: -1,
-  worker_script_same_good: -1,
-  worker_script_cross_bad: -1,
-  worker_inherited_xhr_good: -1,
-  worker_inherited_xhr_bad: -1,
-  worker_inherited_fetch_good: -1,
-  worker_inherited_fetch_bad: -1,
-  worker_inherited_script_good: -1,
-  worker_inherited_script_bad: -1,
-  worker_child_xhr_same_bad: -1,
-  worker_child_xhr_cross_bad: -1,
-  worker_child_script_same_bad: -1,
-  worker_child_script_cross_bad: -1,
-  worker_child_inherited_parent_xhr_bad: -1,
-  worker_child_inherited_parent_xhr_good: -1,
-  worker_child_inherited_parent_script_good: -1,
-  worker_child_inherited_parent_script_bad: -1,
-  worker_child_inherited_document_xhr_good: -1,
-  worker_child_inherited_document_xhr_bad: -1,
-  worker_child_inherited_document_script_good: -1,
-  worker_child_inherited_document_script_bad: -1,
   media_good: -1,
   media_bad: -1,
   font_good: -1,
   font_bad: -1,
   object_good: -1,
   object_bad: -1,
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/test_csp_worker_inheritance.html
@@ -0,0 +1,20 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+<html>
+  <head>
+    <title>Test for Bug 1475849</title>
+  </head>
+  <body>
+    <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <iframe style="width:200px;height:200px;" id='cspframe'></iframe>
+        <script class="testbody" type="text/javascript">
+          document.getElementById('cspframe').src = 'main_csp_worker.html';
+        </script>
+
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/worker.sjs
@@ -0,0 +1,116 @@
+Components.utils.importGlobalProperties(["URLSearchParams"]);
+
+const SJS = "http://mochi.test:8888/tests/dom/security/test/csp/worker.sjs";
+
+function createFetchWorker(url)
+{
+    return `fetch("${url}");`;
+}
+
+function createXHRWorker(url)
+{
+  return `
+    try {
+      var xhr = new XMLHttpRequest();
+      xhr.open("GET", "${url}");
+      xhr.send();
+    } catch(ex) {}
+  `;
+}
+
+function createImportScriptsWorker(url)
+{
+  return `
+    try {
+      importScripts("${url}");
+    } catch(ex) {}
+  `;
+}
+
+function createChildWorkerURL(params)
+{
+  let url = SJS + "?" + params.toString();
+  return `new Worker("${url}");`;
+}
+
+function createChildWorkerBlob(params)
+{
+  let url = SJS + "?" + params.toString();
+  return `
+    try {
+      var xhr = new XMLHttpRequest();
+      xhr.open("GET", "${url}");
+      xhr.responseType = "blob";
+      xhr.send();
+      xhr.onload = () => {
+        new Worker(URL.createObjectURL(xhr.response));};
+    } catch(ex) {}
+  `;
+}
+
+function handleRequest(request, response)
+{
+  let params = new URLSearchParams(request.queryString);
+
+  let id = params.get("id");
+  let base = unescape(params.get("base"));
+  let child = params.has("child") ? params.get("child") : "";
+
+  //avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+  response.setHeader("Content-Type", "application/javascript");
+
+  // Deliver the CSP policy encoded in the URL
+  if(params.has("csp")) {
+    response.setHeader("Content-Security-Policy", unescape(params.get("csp")), false);
+  }
+
+  if (child) {
+    let childCsp = params.has("childCsp") ? params.get("childCsp") : "";
+    params.delete("csp");
+    params.delete("child");
+    params.delete("childCsp");
+    params.append("csp", childCsp);
+
+    switch (child) {
+      case "blob":
+        response.write(createChildWorkerBlob(params));
+        break;
+
+      case "url":
+        response.write(createChildWorkerURL(params));
+        break;
+
+      default:
+        response.setStatusLine(request.httpVersion, 400, "Bad request");
+        break;
+    }
+
+    return;
+  }
+
+  if (params.has("action")) {
+    switch (params.get("action")) {
+      case "fetch":
+        response.write(createFetchWorker(base + "?id=" + id));
+        break;
+
+      case "xhr":
+        response.write(createXHRWorker(base + "?id=" + id));
+        break;
+
+      case "importScripts":
+        response.write(createImportScriptsWorker(base + "?id=" + id));
+        break;
+
+      default:
+        response.setStatusLine(request.httpVersion, 400, "Bad request");
+        break;
+    }
+
+    return;
+  }
+
+  response.write("I don't know action ");
+  return;
+}
new file mode 100644
--- /dev/null
+++ b/dom/security/test/csp/worker_helper.js
@@ -0,0 +1,81 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var _tests = [];
+function addTest(test) {
+  _tests.push(test);
+}
+
+function addAsyncTest(fn) {
+  _tests.push(() => (fn)().catch(ok.bind(null, false)));
+}
+
+function runNextTest() {
+  if (_tests.length == 0) {
+    SimpleTest.finish();
+    return;
+  }
+  const fn = _tests.shift();
+  try {
+    fn();
+  } catch (ex) {
+    info("Test function " + (fn.name ? "'" + fn.name + "' " : "") +
+         "threw an exception: " + ex);
+  }
+}
+
+/**
+ * Helper to perform an XHR then blob response to create worker
+ */
+function doXHRGetBlob(uri) {
+  return new Promise(resolve => {
+    const xhr = new XMLHttpRequest();
+    xhr.open("GET", uri);
+    xhr.responseType = "blob";
+    xhr.addEventListener("load", function() {
+      is(xhr.status, 200, "doXHRGetBlob load uri='" + uri + "' status=" + xhr.status);
+      resolve(xhr.response);
+    });
+    xhr.send();
+  });
+}
+
+function removeObserver(observer) {
+  SpecialPowers.removeObserver(observer, "specialpowers-http-notify-request");
+  SpecialPowers.removeObserver(observer, "csp-on-violate-policy");
+}
+
+/**
+ * Helper to perform an assert to check if the request should be blocked or
+ * allowed by CSP
+ */
+function assertCSPBlock(url, shouldBlock) {
+  return new Promise((resolve, reject) => {
+    let observer = {
+      observe(subject, topic, data) {
+        if (topic === "specialpowers-http-notify-request") {
+          if (data == url) {
+            is(shouldBlock, false, "Should allow request uri='" + url);
+            removeObserver(observer);
+            resolve();
+          }
+        }
+
+        if (topic === "csp-on-violate-policy") {
+          let asciiSpec = SpecialPowers.getPrivilegedProps(
+            SpecialPowers.do_QueryInterface(subject, "nsIURI"), "asciiSpec");
+          if (asciiSpec == url) {
+            is(shouldBlock, true, "Should block request uri='" + url);
+            removeObserver(observer);
+            resolve();
+          }
+        }
+       },
+    };
+
+    SpecialPowers.addObserver(observer, "csp-on-violate-policy");
+    SpecialPowers.addObserver(observer, "specialpowers-http-notify-request");
+  });
+}
--- a/dom/svg/test/mochitest.ini
+++ b/dom/svg/test/mochitest.ini
@@ -40,16 +40,17 @@ support-files =
 [test_bug872812.html]
 [test_getBBox-method.html]
 [test_dataTypes.html]
 [test_dataTypesModEvents.html]
 [test_fragments.html]
 [test_getCTM.html]
 [test_getElementById.xhtml]
 [test_getSubStringLength.xhtml]
+[test_getTotalLength.xhtml]
 [test_lang.xhtml]
 skip-if = true # disabled-for-intermittent-failures--bug-701060
 [test_length.xhtml]
 [test_lengthParsing.html]
 [test_markerOrient.xhtml]
 [test_nonAnimStrings.xhtml]
 [test_non-scaling-stroke.html]
 [test_object-delayed-intrinsic-size.html]
new file mode 100644
--- /dev/null
+++ b/dom/svg/test/test_getTotalLength.xhtml
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1474284
+-->
+<head>
+  <title>Test for Bug 1474284</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1474284">Mozilla Bug 1474284</a>
+<p id="display"></p>
+
+<svg xmlns="http://www.w3.org/2000/svg">
+  <path id="path1" stroke="#000" fill="none"
+        d="M 50,40
+           C 50,40 0,60 30,20"/>
+</svg>
+
+<pre id="test">
+<script class="testbody" type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function expectValue(id, expected)
+{
+  isfuzzy(document.getElementById(id).getTotalLength(),
+          expected, expected * 0.02,
+          `getTotalLength() on element id="${id}" returned the wrong value`);
+}
+
+function run()
+{
+  expectValue("path1", 55.19);
+  SimpleTest.finish();
+}
+
+window.addEventListener("load", run, false);
+</script>
+</pre>
+</body>
+</html>
--- a/dom/webidl/AccessibleNode.webidl
+++ b/dom/webidl/AccessibleNode.webidl
@@ -20,18 +20,34 @@ interface AccessibleNode {
 
   // Accessible properties
   attribute boolean? modal;
   attribute boolean? multiline;
   attribute boolean? multiselectable;
   attribute boolean? readOnly;
   attribute boolean? required;
 
+  // Range values
+  attribute double? valueMax;
+  attribute double? valueMin;
+  attribute double? valueNow;
+
   // Accessible states
   attribute boolean? disabled;
   attribute boolean? expanded;
   attribute boolean? hidden;
   attribute boolean? selected;
 
   // Live regions
   attribute boolean? atomic;
   attribute boolean? busy;
+
+  // Collections.
+  attribute long? colCount;
+  attribute unsigned long? colIndex;
+  attribute unsigned long? colSpan;
+  attribute unsigned long? level;
+  attribute unsigned long? posInSet;
+  attribute long? rowCount;
+  attribute unsigned long? rowIndex;
+  attribute unsigned long? rowSpan;
+  attribute long? setSize;
 };
--- a/gfx/2d/Path.cpp
+++ b/gfx/2d/Path.cpp
@@ -301,16 +301,20 @@ FindInflectionApproximationRange(BezierC
                                  double aTolerance)
 {
     SplitBezier(aControlPoints, nullptr, &aControlPoints, aT);
 
     PointD cp21 = aControlPoints.mCP2 - aControlPoints.mCP1;
     PointD cp41 = aControlPoints.mCP4 - aControlPoints.mCP1;
 
     if (cp21.x == 0. && cp21.y == 0.) {
+      cp21 = aControlPoints.mCP3 - aControlPoints.mCP1;
+    }
+
+    if (cp21.x == 0. && cp21.y == 0.) {
       // In this case s3 becomes lim[n->0] (cp41.x * n) / n - (cp41.y * n) / n = cp41.x - cp41.y.
 
       // Use the absolute value so that Min and Max will correspond with the
       // minimum and maximum of the range.
       *aMin = aT - CubicRoot(std::abs(aTolerance / (cp41.x - cp41.y)));
       *aMax = aT + CubicRoot(std::abs(aTolerance / (cp41.x - cp41.y)));
       return;
     }
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -219,17 +219,17 @@ class BumpChunk : public SingleLinkedLis
     uint8_t* const capacity_;
 
 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     // Magic number used to check against poisoned values.
     const uintptr_t magic_ : 24;
     static constexpr uintptr_t magicNumber = uintptr_t(0x4c6966);
 #endif
 
-#if defined(DEBUG) || defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
+#if defined(DEBUG) || defined(MOZ_ASAN)
 # define LIFO_CHUNK_PROTECT 1
 #endif
 
 #ifdef LIFO_CHUNK_PROTECT
     // Constant used to know if the current chunk should be protected. This is
     // mainly use to prevent dead-lock in the MemoryProtectionExceptionHandler
     // methods.
     const uintptr_t protect_ : 1;
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -647,18 +647,18 @@ load text-overflow-bug713610.html
 load text-overflow-form-elements.html
 load text-overflow-iframe.html
 asserts(1-4) load 1225005.html # bug 682647 and bug 448083
 load 1233191.html
 load 1233607.html
 load 1234701-1.html
 load 1234701-2.html
 load 1271765.html
-asserts(2) asserts-if(Android,1) load 1272983-1.html # bug 586628
-asserts(2) asserts-if(Android,1) load 1272983-2.html # bug 586628
+pref(layout.css.xul-box-display-values.content.enabled,true) asserts(2) asserts-if(Android,1) load 1272983-1.html # bug 586628
+pref(layout.css.xul-box-display-values.content.enabled,true) asserts(2) asserts-if(Android,1) load 1272983-2.html # bug 586628
 load 1275059.html
 load 1278007.html
 load 1278080.html
 load 1279814.html
 skip-if(webrender) load large-border-radius-dashed.html # see bug 1409243, not handled by webrender
 skip-if(webrender) load large-border-radius-dashed2.html # see bug 1409243, not handled by webrender
 skip-if(webrender) load large-border-radius-dotted.html # see bug 1409243, not handled by webrender
 skip-if(webrender) load large-border-radius-dotted2.html # see bug 1409243, not handled by webrender
--- a/layout/reftests/box-ordinal/reftest.list
+++ b/layout/reftests/box-ordinal/reftest.list
@@ -1,7 +1,7 @@
-== box-ordinal-with-out-of-flow-1.html box-ordinal-with-out-of-flow-1-ref.html
+pref(layout.css.xul-box-display-values.content.enabled,true) == box-ordinal-with-out-of-flow-1.html box-ordinal-with-out-of-flow-1-ref.html
 == dynamic-1-remove-to-none-grouped.xul dynamic-1-ref.xul
 == dynamic-1-add-to-one-grouped.xul dynamic-1-ref.xul
 == dynamic-1-remove-to-one-grouped-1.xul dynamic-1-ref.xul
 fails == dynamic-1-remove-to-one-grouped-2.xul dynamic-1-ref.xul # bug 575500
 == dynamic-1-add-to-two-grouped-1.xul dynamic-1-ref.xul
 == dynamic-1-add-to-two-grouped-2.xul dynamic-1-ref.xul
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -412,17 +412,17 @@ fuzzy-if(Android,2,18) == 315920-17.html
 == 320979-1.html 320979-1-ref.html
 != 321402-1.html about:blank
 != 321402-2.html about:blank
 fuzzy-if(webrender&&winWidget,35-35,1-1) == 321402-3.xul 321402-3-ref.xul
 == 321402-4.xul 321402-4-ref.xul
 == 321402-5.xul 321402-5-ref.xul
 == 321402-6.xul 321402-6-ref.xul
 == 321738-1.html 321738-1-ref.html
-== 322436-1.html 322436-1-ref.html
+pref(layout.css.xul-box-display-values.content.enabled,true) == 322436-1.html 322436-1-ref.html
 == 322461-1.xml 322461-1-ref.html
 == 323656-1.html 323656-1-ref.html
 == 323656-2.html 323656-2-ref.html
 == 323656-3.html 323656-3-ref.html
 == 323656-4.html 323656-4-ref.html
 == 323656-5.svg 323656-5-ref.svg
 == 323656-6.html 323656-6-ref.html
 fuzzy-if(Android,2,140) == 325292-1.html 325292-1-ref.html
@@ -951,17 +951,17 @@ fails == 411585-3.html 411585-3-ref.html
 == 411792-1.html 411792-1-ref.html
 == 412093-1.html 412093-1-ref.html
 == 412352-1.html 412352-1-ref.html
 == 412352-2.html 412352-2-ref.html
 == 412607-1a.html 412607-1-ref.html
 == 412607-1b.html 412607-1-ref.html
 random-if(Android) == 412679-1.html 412679-1-ref.html
 fuzzy-if(skiaContent,1,17) == 412679-2.html 412679-2-ref.html
-== 413027-1.html 413027-1-ref.html
+pref(layout.css.xul-box-display-values.content.enabled,true) == 413027-1.html 413027-1-ref.html
 fails == 413027-2.html 413027-2-ref.html
 fails == 413027-3.html 413027-3-ref.html
 == 413286-1a.html 413286-1-ref.html
 == 413286-1b.html 413286-1-ref.html
 == 413286-1c.html 413286-1-ref.html
 == 413286-2a.html 413286-2-ref.html
 == 413286-2b.html 413286-2-ref.html
 == 413286-2c.html 413286-2-ref.html
@@ -1404,17 +1404,17 @@ fuzzy-if(Android,5,2800) == 506481-1.htm
 == 507187-1.html 507187-1-ref.html
 == 507487-1.html 507487-1-ref.html
 == 507487-2.xhtml 507487-2-ref.xhtml
 == 507762-1.html 507762-1-ref.html
 == 507762-2.html 507762-2-ref.html
 == 507762-3.html 507762-1-ref.html
 == 507762-4.html 507762-2-ref.html
 random == 508816-1.xul 508816-1-ref.xul # Bug 1375012
-== 508816-2.html 508816-2-ref.html
+pref(layout.css.xul-box-display-values.content.enabled,true) == 508816-2.html 508816-2-ref.html
 skip-if(isDebugBuild) == 508908-1.xul 508908-1-ref.xul
 == 508919-1.xhtml 508919-1-ref.xhtml
 == 509155-1.xhtml 509155-1-ref.xhtml
 fuzzy-if(Android,5,1656) fuzzy-if(skiaContent,1,1200) == 512410.html 512410-ref.html
 == 512631-1.html 512631-1-ref.html
 == 513153-1a.html 513153-1-ref.html
 == 513153-1b.html 513153-1-ref.html
 == 513153-2a.html 513153-2-ref.html
@@ -1444,17 +1444,17 @@ fuzzy-if(skiaContent,5,50) == 526463-1.h
 == 528038-1b.html 528038-1-ref.html
 == 528038-1c.html 528038-1-ref.html
 == 528038-1d.html 528038-1-ref.html
 == 528038-1e.html 528038-1-ref.html
 == 528038-1f.html 528038-1-ref.html
 == 528038-2.html 528038-2-ref.html
 == 528096-1.html 528096-1-ref.html
 == 530686-1.html 530686-1-ref.html
-== 531098-1.html 531098-1-ref.html
+pref(layout.css.xul-box-display-values.content.enabled,true) == 531098-1.html 531098-1-ref.html
 fuzzy-if(Android,2,48) == 531200-1.html 531200-1-ref.html
 == 531371-1.html 531371-1-ref.html
 == 534526-1a.html 534526-1-ref.html
 == 534526-1b.html 534526-1-ref.html
 == 534804-1.html 534804-1-ref.html
 == 534808-1.html 534808-1-ref.html
 == 534808-2.html 534808-2-ref.html
 == 534919-1.html 534919-1-ref.html
@@ -1559,17 +1559,17 @@ fuzzy-if(Android,1,1) needs-focus == 568
 == 574898-1.html 574898-ref.html
 # 574907 is a windows-only issue, result on other platforms depends on details of font support
 random-if(!winWidget) random-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)) == 574907-1.html 574907-1-ref.html # Bug 1258240
 random-if(!winWidget) random-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)) == 574907-2.html 574907-2-ref.html # Bug 1258240
 # 574907-3 only worked under directwrite, and even there it now depends on the rendering mode; marking as random for now
 random-if(!winWidget) fails-if(winWidget&&!dwrite) random-if(winWidget&&dwrite) != 574907-3.html 574907-3-notref.html
 == 577838-1.html 577838-1-ref.html
 == 577838-2.html 577838-2-ref.html
-== 579323-1.html 579323-1-ref.html
+pref(layout.css.xul-box-display-values.content.enabled,true) == 579323-1.html 579323-1-ref.html
 == 579349-1.html 579349-1-ref.html
 == 579655-1.html 579655-1-ref.html
 skip-if(!haveTestPlugin) fails-if(Android) HTTP == 579808-1.html 579808-1-ref.html
 fails-if(Android) random-if(layersGPUAccelerated) fuzzy-if(skiaContent,1,10000) == 579985-1.html 579985-1-ref.html # this bug was only for a regression in BasicLayers anyway
 skip-if(Android) == 580160-1.html 580160-1-ref.html # bug 920927 for Android; issues without the test-plugin
 fuzzy-if(asyncPan&&!layersGPUAccelerated,255,141) == 580863-1.html 580863-1-ref.html
 fails-if(Android) random-if(layersGPUAccelerated) fuzzy-if(skiaContent,1,6436) == 581317-1.html 581317-1-ref.html
 == 581579-1.html 581579-1-ref.html
--- a/layout/reftests/text-overflow/reftest.list
+++ b/layout/reftests/text-overflow/reftest.list
@@ -17,17 +17,17 @@ fuzzy-if(skiaContent,1,4200) fuzzy-if(we
 fuzzy-if(webrender,5,509) == marker-shadow.html marker-shadow-ref.html
 fuzzy-if(webrender,3,25) == aligned-baseline.html aligned-baseline-ref.html
 skip-if(Android) fuzzy-if(skiaContent,1,5) == clipped-elements.html clipped-elements-ref.html
 == theme-overflow.html theme-overflow-ref.html
 == table-cell.html table-cell-ref.html
 fuzzy-if(gtkWidget,10,32) fuzzy-if(webrender,47,18) == two-value-syntax.html two-value-syntax-ref.html
 == single-value.html single-value-ref.html
 fuzzy-if(gtkWidget,10,2) == atomic-under-marker.html atomic-under-marker-ref.html
-fuzzy(1,2616) skip-if(Android) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) fails-if(gtkWidget) == xulscroll.html xulscroll-ref.html # gtkWidget:bug 1309107, bug 1328771
+pref(layout.css.xul-box-display-values.content.enabled,true) fuzzy(1,2616) skip-if(Android) fuzzy-if(asyncPan&&!layersGPUAccelerated,102,12352) fails-if(gtkWidget) == xulscroll.html xulscroll-ref.html # gtkWidget:bug 1309107, bug 1328771
 == combobox-zoom.html combobox-zoom-ref.html
 == dynamic-change-1.html dynamic-change-1-ref.html
 == float-edges-1.html float-edges-1-ref.html
 
 # The vertical-text pref setting can be removed after bug 1138384 lands
 == vertical-decorations-1.html vertical-decorations-1-ref.html
 == vertical-decorations-2.html vertical-decorations-2-ref.html
 != vertical-decorations-1.html vertical-decorations-1-2-notref.html
--- a/layout/style/test/test_flexbox_child_display_values.xhtml
+++ b/layout/style/test/test_flexbox_child_display_values.xhtml
@@ -134,18 +134,16 @@ function main() {
   testDisplayValue("table");
   testDisplayValue("inline-table", "table");
 
   // These values all compute to "block" in a flex container. Do them in a
   // loop, so that I don't have to type "block" a zillion times.
   var dispValsThatComputeToBlockInAFlexContainer = [
     "inline",
     "inline-block",
-    "-moz-box",
-    "-moz-inline-box",
   ];
 
   dispValsThatComputeToBlockInAFlexContainer.forEach(
     function(aSpecifiedDisplay) {
       testDisplayValue(aSpecifiedDisplay, "block");
   });
 
   // Table-parts are special. When they're a child of a flex container,
--- a/layout/style/test/test_layout_css_xul_display_values_content_enabled.html
+++ b/layout/style/test/test_layout_css_xul_display_values_content_enabled.html
@@ -13,17 +13,20 @@ const VALUES = [
   "-moz-inline-stack",
   "-moz-deck",
   "-moz-popup",
   "-moz-groupbox",
 ];
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPrefEnv(
-  {"set": [["layout.css.xul-display-values.content.enabled", true]]}
+  {"set": [
+    ["layout.css.xul-display-values.content.enabled", true],
+    ["layout.css.xul-box-display-values.content.enabled", true],
+  ]}
 ).then(runTest);
 
 function runTest() {
   const div = document.querySelector("div");
   for (const value of VALUES) {
     div.style.display = value;
     is(div.style.display, value);
     is(getComputedStyle(div).display, value);
--- a/layout/style/test/test_non_content_accessible_values.html
+++ b/layout/style/test/test_non_content_accessible_values.html
@@ -1,19 +1,18 @@
 <!doctype html>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <style id="sheet"></style>
 <div></div>
 <script>
 const NON_CONTENT_ACCESSIBLE_VALUES = {
   "display": [
-    // FIXME(emilio, bug TBD): Remove from content these two too.
-    // "-moz-box",
-    // "-moz-inline-box",
+    "-moz-box",
+    "-moz-inline-box",
     "-moz-grid",
     "-moz-inline-grid",
     "-moz-grid-group",
     "-moz-grid-line",
     "-moz-stack",
     "-moz-inline-stack",
     "-moz-deck",
     "-moz-popup",
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AccessibilityTest.kt
@@ -57,16 +57,17 @@ class AccessibilityTest : BaseSessionTes
             return getVirtualDescendantId(getSourceIdMethod.invoke(event) as Long)
         } catch (ex: Exception) {
             return 0
         }
     }
 
     private interface EventDelegate {
         fun onAccessibilityFocused(event: AccessibilityEvent) { }
+        fun onClicked(event: AccessibilityEvent) { }
         fun onFocused(event: AccessibilityEvent) { }
         fun onTextSelectionChanged(event: AccessibilityEvent) { }
         fun onTextChanged(event: AccessibilityEvent) { }
         fun onTextTraversal(event: AccessibilityEvent) { }
     }
 
     @Before fun setup() {
         // We initialize a view with a parent and grandparent so that the
@@ -82,16 +83,17 @@ class AccessibilityTest : BaseSessionTes
 
         // Set up an external delegate that will intercept accessibility events.
         sessionRule.addExternalDelegateUntilTestEnd(
             EventDelegate::class,
         { newDelegate -> (view.parent as View).setAccessibilityDelegate(object : View.AccessibilityDelegate() {
             override fun onRequestSendAccessibilityEvent(host: ViewGroup, child: View, event: AccessibilityEvent): Boolean {
                 when (event.eventType) {
                     AccessibilityEvent.TYPE_VIEW_FOCUSED -> newDelegate.onFocused(event)
+                    AccessibilityEvent.TYPE_VIEW_CLICKED -> newDelegate.onClicked(event)
                     AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED -> newDelegate.onAccessibilityFocused(event)
                     AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> newDelegate.onTextSelectionChanged(event)
                     AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> newDelegate.onTextChanged(event)
                     AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY -> newDelegate.onTextTraversal(event)
                     else -> {}
                 }
                 return false
             }
@@ -190,16 +192,35 @@ class AccessibilityTest : BaseSessionTes
             @AssertCalled(count = 1)
             override fun onTextTraversal(event: AccessibilityEvent) {
               assertThat("fromIndex matches", event.fromIndex, equalTo(fromIndex))
               assertThat("toIndex matches", event.toIndex, equalTo(toIndex))
             }
         })
     }
 
+    private fun waitUntilClick(checked: Boolean? = null, selected: Boolean? = null) {
+        sessionRule.waitUntilCalled(object : EventDelegate {
+            @AssertCalled(count = 1)
+            override fun onClicked(event: AccessibilityEvent) {
+                var nodeId = getSourceId(event)
+                var node = provider.createAccessibilityNodeInfo(nodeId)
+
+                if (checked != null) {
+                    assertThat("Event's checked state matches", event.isChecked, equalTo(checked))
+                    assertThat("Checkbox node has correct checked state", node.isChecked, equalTo(checked))
+                }
+
+                if (selected != null) {
+                    assertThat("Selectable node has correct selected state", node.isSelected, equalTo(selected))
+                }
+            }
+        })
+    }
+
     private fun setSelectionArguments(start: Int, end: Int): Bundle {
         val arguments = Bundle(2)
         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, start)
         arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, end)
         return arguments
     }
 
     private fun moveByGranularityArguments(granularity: Int, extendSelection: Boolean = false): Bundle {
@@ -353,9 +374,63 @@ class AccessibilityTest : BaseSessionTes
                 moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE))
         waitUntilTextTraversed(18, 28) // "sit amet, "
 
         provider.performAction(nodeId,
                 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
                 moveByGranularityArguments(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE))
         waitUntilTextTraversed(0, 18) // "Lorem ipsum dolor "
     }
+
+    @Test fun testCheckbox() {
+        var nodeId = AccessibilityNodeProvider.HOST_VIEW_ID;
+        sessionRule.session.loadString("<label><input id='checkbox' type='checkbox'>many option</label>", "text/html")
+        sessionRule.waitForPageStop()
+
+        mainSession.evaluateJS("$('#checkbox').focus()")
+        sessionRule.waitUntilCalled(object : EventDelegate {
+            @AssertCalled(count = 1)
+            override fun onAccessibilityFocused(event: AccessibilityEvent) {
+                nodeId = getSourceId(event)
+                var node = provider.createAccessibilityNodeInfo(nodeId)
+                assertThat("Checkbox node is checkable", node.isCheckable, equalTo(true))
+                assertThat("Checkbox node is clickable", node.isClickable, equalTo(true))
+                assertThat("Checkbox node is focusable", node.isFocusable, equalTo(true))
+                assertThat("Checkbox node is not checked", node.isChecked, equalTo(false))
+                assertThat("Checkbox node has correct role", node.text.toString(), equalTo("many option check button"))
+            }
+        })
+
+        provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
+        waitUntilClick(checked = true)
+
+        provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
+        waitUntilClick(checked = false)
+    }
+
+    @Test fun testSelectable() {
+        var nodeId = View.NO_ID
+        sessionRule.session.loadString(
+                """<ul style="list-style-type: none;" role="listbox">
+                        <li id="li" role="option" onclick="this.setAttribute('aria-selected',
+                            this.getAttribute('aria-selected') == 'true' ? 'false' : 'true')">1</li>
+                </ul>""","text/html")
+        sessionRule.waitForPageStop()
+
+        provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null)
+        sessionRule.waitUntilCalled(object : EventDelegate {
+            @AssertCalled(count = 1)
+            override fun onAccessibilityFocused(event: AccessibilityEvent) {
+                nodeId = getSourceId(event)
+                var node = provider.createAccessibilityNodeInfo(nodeId)
+                assertThat("Selectable node is clickable", node.isClickable, equalTo(true))
+                assertThat("Selectable node is not selected", node.isSelected, equalTo(false))
+                assertThat("Selectable node has correct role", node.text.toString(), equalTo("1 option list box"))
+            }
+        })
+
+        provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
+        waitUntilClick(selected = true)
+
+        provider.performAction(nodeId, AccessibilityNodeInfo.ACTION_CLICK, null)
+        waitUntilClick(selected = false)
+    }
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
@@ -374,16 +374,17 @@ public class SessionAccessibility {
 
     private void populateNodeInfoFromJSON(AccessibilityNodeInfo node, final GeckoBundle message) {
         node.setEnabled(message.getBoolean("enabled", true));
         node.setCheckable(message.getBoolean("checkable"));
         node.setChecked(message.getBoolean("checked"));
         node.setPassword(message.getBoolean("password"));
         node.setFocusable(message.getBoolean("focusable"));
         node.setFocused(message.getBoolean("focused"));
+        node.setSelected(message.getBoolean("selected"));
 
         node.setClassName(message.getString("className", "android.view.View"));
 
         final String[] textArray = message.getStringArray("text");
         StringBuilder sb = new StringBuilder();
         if (textArray != null && textArray.length > 0) {
             sb.append(textArray[0] != null ? textArray[0] : "");
             for (int i = 1; i < textArray.length; i++) {
@@ -426,16 +427,25 @@ public class SessionAccessibility {
         final float[] origin = new float[2];
         mSession.getClientToScreenMatrix(matrix);
         matrix.mapPoints(origin);
 
         screenBounds.offset((int) -origin[0], (int) -origin[1]);
         node.setBoundsInParent(screenBounds);
     }
 
+    private void updateState(final AccessibilityNodeInfo node, final GeckoBundle message) {
+        if (message.containsKey("checked")) {
+            node.setChecked(message.getBoolean("checked"));
+        }
+        if (message.containsKey("selected")) {
+            node.setSelected(message.getBoolean("selected"));
+        }
+    }
+
     private void sendAccessibilityEvent(final GeckoBundle message) {
         if (mView == null || !Settings.isEnabled())
             return;
 
         final int eventType = message.getInt("eventType", -1);
         if (eventType < 0) {
             Log.e(LOGTAG, "No accessibility event type provided");
             return;
@@ -467,16 +477,21 @@ public class SessionAccessibility {
             }
             mVirtualContentNode = AccessibilityNodeInfo.obtain(mView, eventSource);
             populateNodeInfoFromJSON(mVirtualContentNode, message);
         }
 
         if (mVirtualContentNode != null) {
             // Bounds for the virtual content can be updated from any event.
             updateBounds(mVirtualContentNode, message);
+
+            // State for the virtual content can be updated when view is clicked.
+            if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED) {
+                updateState(mVirtualContentNode, message);
+            }
         }
 
         final AccessibilityEvent accessibilityEvent = obtainEvent(eventType, eventSource);
         populateEventFromJSON(accessibilityEvent, message);
         ((ViewParent) mView).requestSendAccessibilityEvent(mView, accessibilityEvent);
     }
 
     public boolean onMotionEvent(final MotionEvent event) {
--- a/modules/libpref/init/StaticPrefList.h
+++ b/modules/libpref/init/StaticPrefList.h
@@ -356,16 +356,30 @@ VARCACHE_PREF(
 #undef PREF_VALUE
 
 VARCACHE_PREF(
   "layout.css.xul-display-values.content.enabled",
    layout_css_xul_display_values_content_enabled,
   bool, false
 )
 
+// Pref to control whether display: -moz-box and display: -moz-inline-box are
+// parsed in content pages.
+#ifdef EARLY_BETA_OR_EARLIER
+#define PREF_VALUE false
+#else
+#define PREF_VALUE true
+#endif
+VARCACHE_PREF(
+  "layout.css.xul-box-display-values.content.enabled",
+   layout_css_xul_box_display_values_content_enabled,
+  bool, PREF_VALUE
+)
+#undef PREF_VALUE
+
 // Is support for CSS "grid-template-{columns,rows}: subgrid X" enabled?
 VARCACHE_PREF(
   "layout.css.grid-template-subgrid-value.enabled",
    layout_css_grid_template_subgrid_value_enabled,
   bool, false
 )
 
 // Is support for variation fonts enabled?
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -601,16 +601,20 @@ pref("media.cubeb.logging_level", "");
 pref("media.cubeb.sandbox", true);
 pref("media.audioipc.pool_size", 2);
 // 64 * 4 kB stack per pool thread.
 pref("media.audioipc.stack_size", 262144);
 #else
 pref("media.cubeb.sandbox", false);
 #endif
 
+#ifdef MOZ_AV1
+pref("media.av1.enabled", false);
+#endif
+
 pref("media.webaudio.audiocontextoptions-samplerate.enabled", true);
 
 // setSinkId expected to be unconditionally enabled in 63. Till then the
 // implementation will remain hidden behind this pref (Bug 1152401, Bug 934425).
 pref("media.setsinkid.enabled", false);
 
 // Weather we allow AMD switchable graphics
 pref("layers.amd-switchable-gfx.enabled", true);
--- a/mozglue/tests/interceptor/TestDllInterceptor.cpp
+++ b/mozglue/tests/interceptor/TestDllInterceptor.cpp
@@ -394,17 +394,18 @@ bool ShouldTestTipTsf()
   if (!LoadLibraryW(fullPath)) {
     return false;
   }
 
   // Leak the module so that it's loaded for the interceptor test
   return true;
 }
 
-int main()
+extern "C"
+int wmain(int argc, wchar_t* argv[])
 {
   LARGE_INTEGER start;
   QueryPerformanceCounter(&start);
 
   // We disable this part of the test because the code coverage instrumentation
   // injects code in rotatePayload in a way that WindowsDllInterceptor doesn't
   // understand.
 #ifndef MOZ_CODE_COVERAGE
--- a/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
+++ b/mozglue/tests/interceptor/TestDllInterceptorCrossProcess.cpp
@@ -1,14 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
+#include "mozilla/Attributes.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/CmdLineAndEnvUtils.h"
 #include "nsWindowsDllInterceptor.h"
 #include "nsWindowsHelpers.h"
 
 #include <string>
 
 using std::wstring;
 
 extern "C" __declspec(dllexport) int
@@ -25,43 +28,51 @@ ReturnResultHook()
 {
   if (gOrigReturnResult() != 2) {
     return 3;
   }
 
   return 0;
 }
 
-int ParentMain()
+int ParentMain(int argc, wchar_t* argv[])
 {
+  mozilla::SetArgv0ToFullBinaryPath(argv);
+
   // We'll add the child process to a job so that, in the event of a failure in
   // this parent process, the child process will be automatically terminated.
   nsAutoHandle job(::CreateJobObject(nullptr, nullptr));
   if (!job) {
     printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Job creation failed\n");
     return 1;
   }
 
-  JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo{};
+  JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobInfo = {};
   jobInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
 
   if (!::SetInformationJobObject(job.get(), JobObjectExtendedLimitInformation,
                                  &jobInfo, sizeof(jobInfo))) {
     printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Job config failed\n");
     return 1;
   }
 
-  wstring cmdLine(::GetCommandLineW());
-  cmdLine += L" -child";
+  wchar_t childArgv_1[] = L"-child";
+
+  wchar_t* childArgv[] = {
+    argv[0],
+    childArgv_1
+  };
+
+  mozilla::UniquePtr<wchar_t[]>
+    cmdLine(mozilla::MakeCommandLine(mozilla::ArrayLength(childArgv), childArgv));
 
   STARTUPINFOW si = { sizeof(si) };
   PROCESS_INFORMATION pi;
-  if (!::CreateProcessW(nullptr, const_cast<LPWSTR>(cmdLine.c_str()), nullptr,
-                        nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &si,
-                        &pi)) {
+  if (!::CreateProcessW(argv[0], cmdLine.get(), nullptr, nullptr, FALSE,
+                        CREATE_SUSPENDED, nullptr, nullptr, &si, &pi)) {
     printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Failed to spawn child process\n");
     return 1;
   }
 
   nsAutoHandle childProcess(pi.hProcess);
   nsAutoHandle childMainThread(pi.hThread);
 
   if (!::AssignProcessToJobObject(job.get(), childProcess.get())) {
@@ -109,17 +120,23 @@ int ParentMain()
     printf("TEST-UNEXPECTED-FAIL | DllInterceptorCrossProcess | Child process exit code is %lu instead of 0\n", childExitCode);
     return 1;
   }
 
   printf("TEST-PASS | DllInterceptorCrossProcess | Child process exit code is zero\n");
   return 0;
 }
 
-int main(int argc, char* argv[])
+extern "C"
+int wmain(int argc, wchar_t* argv[])
 {
   if (argc > 1) {
-    return ReturnResult();
+    // clang keeps inlining this call despite every attempt to force it to do
+    // otherwise. We'll use GetProcAddress and call its function pointer instead.
+    auto pReturnResult =
+      reinterpret_cast<decltype(&ReturnResult)>(
+        ::GetProcAddress(::GetModuleHandleW(nullptr), "ReturnResult"));
+    return pReturnResult();
   }
 
-  return ParentMain();
+  return ParentMain(argc, argv);
 }
 
--- a/mozglue/tests/interceptor/moz.build
+++ b/mozglue/tests/interceptor/moz.build
@@ -10,8 +10,14 @@ GeckoCppUnitTests(
       'TestDllInterceptorCrossProcess',
     ],
     linkage=None
 )
 
 OS_LIBS += [
     'ole32',
 ]
+
+if CONFIG['OS_TARGET'] == 'WINNT' and CONFIG['CC_TYPE'] == 'gcc':
+    # This allows us to use wmain as the entry point on mingw
+    LDFLAGS += [
+        '-municode',
+    ]
--- a/nsprpub/TAG-INFO
+++ b/nsprpub/TAG-INFO
@@ -1,1 +1,1 @@
-NSPR_4_19_RTM
+607196c7ef66
--- a/nsprpub/config/prdepend.h
+++ b/nsprpub/config/prdepend.h
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSPR in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/nsprpub/configure
+++ b/nsprpub/configure
@@ -2483,17 +2483,17 @@ case $target_os in *\ *) target_os=`echo
 # The aliases save the names the user supplied, while $host etc.
 # will get canonicalized.
 test -n "$target_alias" &&
   test "$program_prefix$program_suffix$program_transform_name" = \
     NONENONEs,x,x, &&
   program_prefix=${target_alias}-
 
 MOD_MAJOR_VERSION=4
-MOD_MINOR_VERSION=19
+MOD_MINOR_VERSION=20
 MOD_PATCH_VERSION=0
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
 USE_N32=
 USE_X32=
--- a/nsprpub/configure.in
+++ b/nsprpub/configure.in
@@ -10,17 +10,17 @@ AC_CONFIG_SRCDIR([pr/include/nspr.h])
 
 AC_CONFIG_AUX_DIR(${srcdir}/build/autoconf)
 AC_CANONICAL_TARGET
 
 dnl ========================================================
 dnl = Defaults
 dnl ========================================================
 MOD_MAJOR_VERSION=4
-MOD_MINOR_VERSION=19
+MOD_MINOR_VERSION=20
 MOD_PATCH_VERSION=0
 NSPR_MODNAME=nspr20
 _HAVE_PTHREADS=
 USE_PTHREADS=
 USE_USER_PTHREADS=
 USE_NSPR_THREADS=
 USE_N32=
 USE_X32=
--- a/nsprpub/pr/include/md/_linux.cfg
+++ b/nsprpub/pr/include/md/_linux.cfg
@@ -1015,16 +1015,108 @@
 #define PR_ALIGN_OF_FLOAT   4
 #define PR_ALIGN_OF_DOUBLE  4
 #define PR_ALIGN_OF_POINTER 4
 #define PR_ALIGN_OF_WORD    4
 
 #define PR_BYTES_PER_WORD_LOG2   2
 #define PR_BYTES_PER_DWORD_LOG2  3
 
+#elif defined(__riscv) && (__riscv_xlen == 32)
+
+#undef  IS_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#undef  IS_64
+
+#define PR_BYTES_PER_BYTE   1
+#define PR_BYTES_PER_SHORT  2
+#define PR_BYTES_PER_INT    4
+#define PR_BYTES_PER_INT64  8
+#define PR_BYTES_PER_LONG   4
+#define PR_BYTES_PER_FLOAT  4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD   4
+#define PR_BYTES_PER_DWORD  8
+
+#define PR_BITS_PER_BYTE    8
+#define PR_BITS_PER_SHORT   16
+#define PR_BITS_PER_INT     32
+#define PR_BITS_PER_INT64   64
+#define PR_BITS_PER_LONG    32
+#define PR_BITS_PER_FLOAT   32
+#define PR_BITS_PER_DOUBLE  64
+#define PR_BITS_PER_WORD    32
+
+#define PR_BITS_PER_BYTE_LOG2   3
+#define PR_BITS_PER_SHORT_LOG2  4
+#define PR_BITS_PER_INT_LOG2    5
+#define PR_BITS_PER_INT64_LOG2  6
+#define PR_BITS_PER_LONG_LOG2   5
+#define PR_BITS_PER_FLOAT_LOG2  5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2   5
+
+#define PR_ALIGN_OF_SHORT   2
+#define PR_ALIGN_OF_INT     4
+#define PR_ALIGN_OF_LONG    4
+#define PR_ALIGN_OF_INT64   8
+#define PR_ALIGN_OF_FLOAT   4
+#define PR_ALIGN_OF_DOUBLE  8
+#define PR_ALIGN_OF_POINTER 4
+#define PR_ALIGN_OF_WORD    4
+
+#define PR_BYTES_PER_WORD_LOG2  2
+#define PR_BYTES_PER_DWORD_LOG2 3
+
+#elif defined(__riscv) && (__riscv_xlen == 64)
+
+#undef  IS_BIG_ENDIAN
+#define IS_LITTLE_ENDIAN 1
+#define IS_64
+
+#define PR_BYTES_PER_BYTE   1
+#define PR_BYTES_PER_SHORT  2
+#define PR_BYTES_PER_INT    4
+#define PR_BYTES_PER_INT64  8
+#define PR_BYTES_PER_LONG   8
+#define PR_BYTES_PER_FLOAT  4
+#define PR_BYTES_PER_DOUBLE 8
+#define PR_BYTES_PER_WORD   8
+#define PR_BYTES_PER_DWORD  8
+
+#define PR_BITS_PER_BYTE    8
+#define PR_BITS_PER_SHORT   16
+#define PR_BITS_PER_INT     32
+#define PR_BITS_PER_INT64   64
+#define PR_BITS_PER_LONG    64
+#define PR_BITS_PER_FLOAT   32
+#define PR_BITS_PER_DOUBLE  64
+#define PR_BITS_PER_WORD    64
+
+#define PR_BITS_PER_BYTE_LOG2   3
+#define PR_BITS_PER_SHORT_LOG2  4
+#define PR_BITS_PER_INT_LOG2    5
+#define PR_BITS_PER_INT64_LOG2  6
+#define PR_BITS_PER_LONG_LOG2   6
+#define PR_BITS_PER_FLOAT_LOG2  5
+#define PR_BITS_PER_DOUBLE_LOG2 6
+#define PR_BITS_PER_WORD_LOG2   6
+
+#define PR_ALIGN_OF_SHORT   2
+#define PR_ALIGN_OF_INT     4
+#define PR_ALIGN_OF_LONG    8
+#define PR_ALIGN_OF_INT64   8
+#define PR_ALIGN_OF_FLOAT   4
+#define PR_ALIGN_OF_DOUBLE  8
+#define PR_ALIGN_OF_POINTER 8
+#define PR_ALIGN_OF_WORD    8
+
+#define PR_BYTES_PER_WORD_LOG2  3
+#define PR_BYTES_PER_DWORD_LOG2 3
+
 #else
 
 #error "Unknown CPU architecture"
 
 #endif
 
 #ifndef HAVE_LONG_LONG
 #define	HAVE_LONG_LONG
--- a/nsprpub/pr/include/md/_linux.h
+++ b/nsprpub/pr/include/md/_linux.h
@@ -52,16 +52,20 @@
 #elif defined(__sh__)
 #define _PR_SI_ARCHITECTURE "sh"
 #elif defined(__avr32__)
 #define _PR_SI_ARCHITECTURE "avr32"
 #elif defined(__m32r__)
 #define _PR_SI_ARCHITECTURE "m32r"
 #elif defined(__or1k__)
 #define _PR_SI_ARCHITECTURE "or1k"
+#elif defined(__riscv) && (__riscv_xlen == 32)
+#define _PR_SI_ARCHITECTURE "riscv32"
+#elif defined(__riscv) && (__riscv_xlen == 64)
+#define _PR_SI_ARCHITECTURE "riscv64"
 #else
 #error "Unknown CPU architecture"
 #endif
 #define PR_DLL_SUFFIX		".so"
 
 #define _PR_VMBASE              0x30000000
 #define _PR_STACK_VMBASE	0x50000000
 #define _MD_DEFAULT_STACK_SIZE	65536L
--- a/nsprpub/pr/include/prinit.h
+++ b/nsprpub/pr/include/prinit.h
@@ -26,21 +26,21 @@ PR_BEGIN_EXTERN_C
 /*
 ** NSPR's version is used to determine the likelihood that the version you
 ** used to build your component is anywhere close to being compatible with
 ** what is in the underlying library.
 **
 ** The format of the version string is
 **     "<major version>.<minor version>[.<patch level>] [<Beta>]"
 */
-#define PR_VERSION  "4.19"
+#define PR_VERSION  "4.20 Beta"
 #define PR_VMAJOR   4
-#define PR_VMINOR   19
+#define PR_VMINOR   20
 #define PR_VPATCH   0
-#define PR_BETA     PR_FALSE
+#define PR_BETA     PR_TRUE
 
 /*
 ** PRVersionCheck
 **
 ** The basic signature of the function that is called to provide version
 ** checking. The result will be a boolean that indicates the likelihood
 ** that the underling library will perform as the caller expects.
 **
--- a/nsprpub/pr/src/misc/prnetdb.c
+++ b/nsprpub/pr/src/misc/prnetdb.c
@@ -2,16 +2,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "primpl.h"
 
 #include <string.h>
 
+#if defined(LINUX)
+#include <sys/un.h>
+#endif
+
 /*
  * On Unix, the error code for gethostbyname() and gethostbyaddr()
  * is returned in the global variable h_errno, instead of the usual
  * errno.
  */
 #if defined(XP_UNIX)
 #if defined(_PR_NEED_H_ERRNO)
 extern int h_errno;
@@ -1361,17 +1365,27 @@ PRUintn _PR_NetAddrSize(const PRNetAddr*
     else if (PR_AF_INET6 == addr->raw.family)
 #if defined(_PR_INET6)
         addrsize = sizeof(struct sockaddr_in6);
 #else
         addrsize = sizeof(addr->ipv6);
 #endif
 #if defined(XP_UNIX) || defined(XP_OS2)
     else if (AF_UNIX == addr->raw.family)
-        addrsize = sizeof(addr->local);
+    {
+#if defined(LINUX)
+        if (addr->local.path[0] == 0)
+            /* abstract socket address is supported on Linux only */
+            addrsize = strnlen(addr->local.path + 1,
+                               sizeof(addr->local.path)) +
+                       offsetof(struct sockaddr_un, sun_path) + 1;
+        else
+#endif
+            addrsize = sizeof(addr->local);
+    }
 #endif
     else addrsize = 0;
 
     return addrsize;
 }  /* _PR_NetAddrSize */
 
 PR_IMPLEMENT(PRIntn) PR_EnumerateHostEnt(
     PRIntn enumIndex, const PRHostEnt *hostEnt, PRUint16 port, PRNetAddr *address)
--- a/nsprpub/pr/src/pthreads/ptio.c
+++ b/nsprpub/pr/src/pthreads/ptio.c
@@ -1745,17 +1745,22 @@ static PRStatus pt_Bind(PRFileDesc *fd, 
 #endif
 
     if (pt_TestAbort()) return PR_FAILURE;
 
     PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
     if (addr->raw.family == AF_UNIX)
     {
         /* Disallow relative pathnames */
-        if (addr->local.path[0] != '/')
+        if (addr->local.path[0] != '/'
+#if defined(LINUX)
+            /* Linux has abstract socket address support */
+            && addr->local.path[0] != 0
+#endif
+            )
         {
             PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
             return PR_FAILURE;
         }
     }
 
 #ifdef _PR_INET6
     if (addr->raw.family == PR_AF_INET6) {
--- a/nsprpub/pr/src/pthreads/ptsynch.c
+++ b/nsprpub/pr/src/pthreads/ptsynch.c
@@ -906,17 +906,18 @@ PR_IMPLEMENT(PRStatus) PR_DeleteSemaphor
 
 #include <fcntl.h>
 #include <sys/sem.h>
 
 /*
  * From the semctl(2) man page in glibc 2.0
  */
 #if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)) \
-    || defined(FREEBSD) || defined(OPENBSD) || defined(BSDI) \
+    || (defined(FREEBSD) && __FreeBSD_version < 1200059) \
+    || defined(OPENBSD) || defined(BSDI) \
     || defined(DARWIN) || defined(SYMBIAN)
 /* union semun is defined by including <sys/sem.h> */
 #else
 /* according to X/OPEN we have to define it ourselves */
 union semun {
     int val;
     struct semid_ds *buf;
     unsigned short  *array;
--- a/nsprpub/pr/tests/Makefile.in
+++ b/nsprpub/pr/tests/Makefile.in
@@ -13,16 +13,17 @@ VPATH		= @srcdir@
 
 include $(MOD_DEPTH)/config/autoconf.mk
 
 include $(topsrcdir)/config/config.mk
 
 DIRS = dll
 
 CSRCS =             \
+	abstract.c		\
 	accept.c		\
 	acceptread.c	\
 	acceptreademu.c	\
 	addrstr.c		\
 	affinity.c		\
 	alarm.c			\
 	anonfm.c		\
 	append.c		\
new file mode 100755
--- /dev/null
+++ b/nsprpub/pr/tests/abstract.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include <stdio.h>
+
+#if defined(LINUX)
+
+#include <string.h>
+#include "nspr.h"
+
+static const char abstractSocketName[] = "\0testsocket";
+
+static void
+ClientThread(void* aArg)
+{
+  PRFileDesc* socket;
+  PRNetAddr addr;
+  PRUint8 buf[1024];
+  PRInt32 len;
+  PRInt32 total;
+
+  addr.local.family = PR_AF_LOCAL;
+  memcpy(addr.local.path, abstractSocketName, sizeof(abstractSocketName));
+
+  socket = PR_OpenTCPSocket(addr.raw.family);
+  if (!socket) {
+    fprintf(stderr, "PR_OpenTCPSokcet failed\n");
+    exit(1);
+  }
+
+  if (PR_Connect(socket, &addr, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
+    fprintf(stderr, "PR_Connect failed\n");
+    exit(1);
+  }
+
+  total = 0;
+  while (total < sizeof(buf)) {
+    len = PR_Recv(socket, buf + total, sizeof(buf) - total, 0,
+                  PR_INTERVAL_NO_TIMEOUT);
+    if (len < 1) {
+      fprintf(stderr, "PR_Recv failed\n");
+      exit(1);
+    }
+    total += len;
+  }
+
+  total = 0;
+  while (total < sizeof(buf)) {
+    len = PR_Send(socket, buf + total, sizeof(buf) - total, 0,
+                  PR_INTERVAL_NO_TIMEOUT);
+    if (len < 1) {
+      fprintf(stderr, "PR_Send failed\n");
+      exit(1);
+    }
+    total += len;
+  }
+
+  if (PR_Close(socket) == PR_FAILURE) {
+    fprintf(stderr, "PR_Close failed\n");
+    exit(1);
+  }
+}
+
+int
+main()
+{
+  PRFileDesc* socket;
+  PRFileDesc* acceptSocket;
+  PRThread* thread;
+  PRNetAddr addr;
+  PRUint8 buf[1024];
+  PRInt32 len;
+  PRInt32 total;
+
+  addr.local.family = PR_AF_LOCAL;
+  memcpy(addr.local.path, abstractSocketName, sizeof(abstractSocketName));
+
+  socket = PR_OpenTCPSocket(addr.raw.family);
+  if (!socket) {
+    fprintf(stderr, "PR_OpenTCPSocket failed\n");
+    exit(1);
+  }
+  if (PR_Bind(socket, &addr) == PR_FAILURE) {
+    fprintf(stderr, "PR_Bind failed\n");
+    exit(1);
+  }
+
+  if (PR_Listen(socket, 5) == PR_FAILURE) {
+    fprintf(stderr, "PR_Listen failed\n");
+    exit(1);
+  }
+
+  thread = PR_CreateThread(PR_USER_THREAD, ClientThread, 0, PR_PRIORITY_NORMAL,
+                           PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
+  if (!thread) {
+    fprintf(stderr, "PR_CreateThread failed");
+    exit(1);
+  }
+
+  acceptSocket  = PR_Accept(socket, NULL, PR_INTERVAL_NO_TIMEOUT);
+  if (!acceptSocket) {
+    fprintf(stderr, "PR_Accept failed\n");
+    exit(1);
+  }
+
+  memset(buf, 'A', sizeof(buf));
+
+  total = 0;
+  while (total < sizeof(buf)) {
+    len = PR_Send(acceptSocket, buf + total, sizeof(buf) - total, 0,
+                  PR_INTERVAL_NO_TIMEOUT);
+    if (len < 1) {
+      fprintf(stderr, "PR_Send failed\n");
+      exit(1);
+    }
+    total += len;
+  }
+
+  total = 0;
+  while (total < sizeof(buf)) {
+    len = PR_Recv(acceptSocket, buf + total, sizeof(buf) - total, 0,
+                  PR_INTERVAL_NO_TIMEOUT);
+    if (len < 1) {
+      fprintf(stderr, "PR_Recv failed\n");
+      exit(1);
+    }
+    total += len;
+  }
+
+  if (PR_Close(acceptSocket) == PR_FAILURE) {
+    fprintf(stderr, "PR_Close failed\n");
+    exit(1);
+  }
+
+  if (PR_JoinThread(thread) == PR_FAILURE) {
+    fprintf(stderr, "PR_JoinThread failed\n");
+    exit(1);
+  }
+
+  if (PR_Close(socket) == PR_FAILURE) {
+    fprintf(stderr, "PR_Close failed\n");
+    exit(1);
+  }
+  printf("PASS\n");
+  return 0;
+}
+
+#else
+int
+main()
+{
+  prinf("PASS\n");
+  return 0;
+}
+#endif
--- a/nsprpub/pr/tests/runtests.pl
+++ b/nsprpub/pr/tests/runtests.pl
@@ -236,16 +236,17 @@ sub win_test_prog {
     # There is no signal, no core on Windows
     print_end($prog, $status, 0, 0);
 
     return $status
 }
 
 # MAIN ---------------
 @progs = (
+"abstract",
 "accept",
 "acceptread",
 "acceptreademu",
 "affinity",
 "alarm",
 "anonfm",
 "atomic",
 "attach",
--- a/nsprpub/pr/tests/runtests.sh
+++ b/nsprpub/pr/tests/runtests.sh
@@ -66,16 +66,17 @@ fi
 
 LOGFILE=${NSPR_TEST_LOGFILE:-$NULL_DEVICE}
 
 #
 # Tests run on all platforms
 #
 
 TESTS="
+abstract
 accept
 acceptread
 acceptreademu
 affinity
 alarm
 anonfm
 atomic
 attach
--- a/nsprpub/pr/tests/vercheck.c
+++ b/nsprpub/pr/tests/vercheck.c
@@ -35,34 +35,34 @@ static char *compatible_version[] = {
     "4.7.6",
     "4.8", "4.8.1", "4.8.2", "4.8.3", "4.8.4", "4.8.5",
     "4.8.6", "4.8.7", "4.8.8", "4.8.9",
     "4.9", "4.9.1", "4.9.2", "4.9.3", "4.9.4", "4.9.5",
     "4.9.6",
     "4.10", "4.10.1", "4.10.2", "4.10.3", "4.10.4",
     "4.10.5", "4.10.6", "4.10.7", "4.10.8", "4.10.9",
     "4.10.10", "4.11", "4.12", "4.13", "4.14", "4.15",
-    "4.16", "4.17", "4.18",
+    "4.16", "4.17", "4.18", "4.19",
     PR_VERSION
 };
 
 /*
  * This release is not backward compatible with the old
  * NSPR 2.1 and 3.x releases.
  *
  * Any release is incompatible with future releases and
  * patches.
  */
 static char *incompatible_version[] = {
     "2.1 19980529",
     "3.0", "3.0.1",
     "3.1", "3.1.1", "3.1.2", "3.1.3",
     "3.5", "3.5.1",
-    "4.19.1",
-    "4.20", "4.20.1",
+    "4.20.1",
+    "4.21", "4.21.1",
     "10.0", "11.1", "12.14.20"
 };
 
 int main(int argc, char **argv)
 {
     int idx;
     int num_compatible = sizeof(compatible_version) / sizeof(char *);
     int num_incompatible = sizeof(incompatible_version) / sizeof(char *);
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -25,16 +25,27 @@ fn moz_display_values_enabled(context: &
     use stylesheets::Origin;
     context.stylesheet_origin == Origin::UserAgent ||
     context.chrome_rules_enabled() ||
     unsafe {
         structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled
     }
 }
 
+#[cfg(feature = "gecko")]
+fn moz_box_display_values_enabled(context: &ParserContext) -> bool {
+    use gecko_bindings::structs;
+    use stylesheets::Origin;
+    context.stylesheet_origin == Origin::UserAgent ||
+    context.chrome_rules_enabled() ||
+    unsafe {
+        structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled
+    }
+}
+
 #[allow(missing_docs)]
 #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq,
          SpecifiedValueInfo, ToComputedValue, ToCss)]
 #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
 /// Defines an element’s display type, which consists of
 /// the two basic qualities of how an element generates boxes
 /// <https://drafts.csswg.org/css-display/#propdef-display>
 pub enum Display {
@@ -75,18 +86,20 @@ pub enum Display {
     Contents,
     #[cfg(feature = "gecko")]
     FlowRoot,
     #[cfg(feature = "gecko")]
     WebkitBox,
     #[cfg(feature = "gecko")]
     WebkitInlineBox,
     #[cfg(feature = "gecko")]
+    #[parse(condition = "moz_box_display_values_enabled")]
     MozBox,
     #[cfg(feature = "gecko")]
+    #[parse(condition = "moz_box_display_values_enabled")]
     MozInlineBox,
     #[cfg(feature = "gecko")]
     #[parse(condition = "moz_display_values_enabled")]
     MozGrid,
     #[cfg(feature = "gecko")]
     #[parse(condition = "moz_display_values_enabled")]
     MozInlineGrid,
     #[cfg(feature = "gecko")]
--- a/testing/marionette/jar.mn
+++ b/testing/marionette/jar.mn
@@ -41,10 +41,12 @@ marionette.jar:
 #ifdef ENABLE_TESTS
   content/test2.xul (chrome/test2.xul)
   content/test_anonymous_content.xul (chrome/test_anonymous_content.xul)
   content/test_dialog.dtd (chrome/test_dialog.dtd)
   content/test_dialog.properties (chrome/test_dialog.properties)
   content/test_dialog.xul (chrome/test_dialog.xul)
   content/test_nested_iframe.xul (chrome/test_nested_iframe.xul)
   content/test.xul (chrome/test.xul)
+#ifdef MOZ_CODE_COVERAGE
   content/PerTestCoverageUtils.jsm (../../tools/code-coverage/PerTestCoverageUtils.jsm)
 #endif
+#endif
--- a/testing/mozharness/scripts/merge_day/gecko_migration.py
+++ b/testing/mozharness/scripts/merge_day/gecko_migration.py
@@ -42,16 +42,23 @@ class GeckoMigration(MercurialScript, Ba
     config_options = [
         [['--hg-user', ], {
             "action": "store",
             "dest": "hg_user",
             "type": "string",
             "default": "ffxbld <release@mozilla.com>",
             "help": "Specify what user to use to commit to hg.",
         }],
+        [['--ssh-user', ], {
+            "action": "store",
+            "dest": "ssh_user",
+            "type": "string",
+            "default": None,
+            "help": "The user to push to hg.mozilla.org as.",
+        }],
         [['--balrog-api-root', ], {
             "action": "store",
             "dest": "balrog_api_root",
             "type": "string",
             "help": "Specify Balrog API root URL.",
         }],
         [['--balrog-username', ], {
             "action": "store",
@@ -186,17 +193,22 @@ class GeckoMigration(MercurialScript, Ba
                 self.config['migration_behavior'] == 'beta_to_release':
             return ['--new-branch', '-r', '.']
         else:
             return ['-r', '.']
 
     def set_push_to_ssh(self):
         for cwd in self.query_push_dirs():
             repo_url = self.read_repo_hg_rc(cwd).get('paths', 'default')
-            push_dest = repo_url.replace('https://', 'ssh://')
+            username = self.config.get('ssh_user', '')
+            # Add a trailing @ to the username if it exists, otherwise it gets
+            # mushed up with the hostname.
+            if username:
+                username += '@'
+            push_dest = repo_url.replace('https://', 'ssh://' + username)
 
             if not push_dest.startswith('ssh://'):
                 raise Exception('Warning: path "{}" is not supported. Protocol must be ssh')
 
             self.edit_repo_hg_rc(cwd, 'paths', 'default-push', push_dest)
 
     def query_from_revision(self):
         """ Shortcut to get the revision for the from repo
--- a/toolkit/components/prompts/content/selectDialog.xul
+++ b/toolkit/components/prompts/content/selectDialog.xul
@@ -11,12 +11,12 @@
       onload="dialogOnLoad()"
       ondialogaccept="return dialogOK();">
 
   <script type="application/javascript" src="chrome://global/content/selectDialog.js" />
   <keyset id="dialogKeys"/>
   <vbox style="width: 24em;margin: 5px;">
     <label id="info.txt"/>
     <vbox>
-      <richlistbox id="list" class="theme-listbox" height="80"/>
+      <richlistbox id="list" class="theme-listbox" style="height: 8em;"/>
     </vbox>
   </vbox>
 </dialog>
--- a/toolkit/content/widgets.css
+++ b/toolkit/content/widgets.css
@@ -5,18 +5,20 @@
 /* ===== widgets.css =====================================================
    == Styles ported from XBL <resources>, loaded by "global.css".
    ======================================================================= */
 
 @import url("chrome://global/content/autocomplete.css");
 @import url("chrome://global/skin/autocomplete.css");
 @import url("chrome://formautofill-shared/skin/autocomplete-item.css");
 @import url("chrome://formautofill/skin/autocomplete-item.css");
+@import url("chrome://global/skin/dialog.css");
 @import url("chrome://global/skin/dropmarker.css");
 @import url("chrome://global/skin/groupbox.css");
 @import url("chrome://global/skin/menu.css");
 @import url("chrome://global/skin/menulist.css");
 @import url("chrome://global/skin/notification.css");
 @import url("chrome://global/skin/popup.css");
+@import url("chrome://global/skin/progressmeter.css");
 @import url("chrome://global/skin/richlistbox.css");
 @import url("chrome://global/skin/splitter.css");
 @import url("chrome://global/skin/toolbar.css");
 @import url("chrome://global/skin/wizard.css");
--- a/toolkit/content/widgets/dialog.xml
+++ b/toolkit/content/widgets/dialog.xml
@@ -9,19 +9,16 @@
 ]>
 
 <bindings id="dialogBindings"
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="dialog">
-    <resources>
-      <stylesheet src="chrome://global/skin/dialog.css"/>
-    </resources>
     <content>
       <xul:vbox class="box-inherit dialog-content-box" flex="1">
         <children/>
       </xul:vbox>
 
       <xul:hbox class="dialog-button-box" anonid="buttons"
                 xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
 #ifdef XP_UNIX
--- a/toolkit/content/widgets/progressmeter.xml
+++ b/toolkit/content/widgets/progressmeter.xml
@@ -5,20 +5,16 @@
 
 
 <bindings id="progressmeterBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="progressmeter">
-    <resources>
-      <stylesheet src="chrome://global/skin/progressmeter.css"/>
-    </resources>
-
     <content>
       <xul:spacer class="progress-bar" xbl:inherits="mode"/>
       <xul:spacer class="progress-remainder" xbl:inherits="mode"/>
     </content>
 
     <implementation>
       <property name="mode" onset="if (this.mode != val) this.setAttribute('mode', val); return val;"
                             onget="return this.getAttribute('mode');"/>
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -314,9 +314,16 @@ this.AppConstants = Object.freeze({
 #endif
 
   HAVE_SHELL_SERVICE:
 #ifdef HAVE_SHELL_SERVICE
     true,
 #else
     false,
 #endif
+
+  MOZ_CODE_COVERAGE:
+#ifdef MOZ_CODE_COVERAGE
+    true,
+#else
+    false,
+#endif
 });
--- a/toolkit/profile/content/profileSelection.js
+++ b/toolkit/profile/content/profileSelection.js
@@ -132,17 +132,17 @@ function onProfilesKey(aEvent) {
     break;
   case KeyEvent.DOM_VK_F2:
     RenameProfile();
     break;
   }
 }
 
 function onProfilesDblClick(aEvent) {
-  if (aEvent.target.localName == "listitem")
+  if (aEvent.target.closest("richlistitem"))
     document.documentElement.acceptDialog();
 }
 
 // invoke the createProfile Wizard
 function CreateProfileWizard() {
   window.openDialog("chrome://mozapps/content/profile/createProfileWizard.xul",
                     "", "centerscreen,chrome,modal,titlebar", gProfileService);
 }
--- a/toolkit/profile/content/profileSelection.xul
+++ b/toolkit/profile/content/profileSelection.xul
@@ -52,17 +52,17 @@
               accesskey="&renameButton.accesskey;" oncommand="RenameProfile();"/>
       <button id="delbutton" label="&deleteButton.label;"
               accesskey="&deleteButton.accesskey;" oncommand="ConfirmDelete();"/>
     </vbox>
 
     <separator flex="1"/>
 
     <vbox flex="1">
-      <richlistbox id="profiles" class="theme-listbox" height="100" seltype="single"
+      <richlistbox id="profiles" class="theme-listbox" seltype="single"
                    ondblclick="onProfilesDblClick(event)"
                    onkeypress="onProfilesKey(event);">
       </richlistbox>
 
       <!-- Bug 257777 -->
       <checkbox id="offlineState" label="&offlineState.label;" accesskey="&offlineState.accesskey;"/>
 
       <checkbox id="autoSelectLastProfile" label="&useSelected.label;"
--- a/toolkit/themes/osx/mozapps/profile/profileSelection.css
+++ b/toolkit/themes/osx/mozapps/profile/profileSelection.css
@@ -9,8 +9,12 @@
 
 box#managebuttons > button {
   min-width: 8em;
 }
 
 #managebuttons {
   padding-top: 1em;
 }
+
+#profiles {
+  height: 12em;
+}
--- a/toolkit/themes/windows/mozapps/profile/profileSelection.css
+++ b/toolkit/themes/windows/mozapps/profile/profileSelection.css
@@ -9,8 +9,12 @@
 
 box#managebuttons > button {
   min-width: 8em;
 }
 
 #managebuttons {
   padding-top: 1em;
 }
+
+#profiles {
+  height: 12em;
+}
--- a/toolkit/xre/CmdLineAndEnvUtils.h
+++ b/toolkit/xre/CmdLineAndEnvUtils.h
@@ -18,18 +18,20 @@
 #endif
 
 #if defined(XP_WIN)
 #include "mozilla/Move.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Vector.h"
 
 #include <wchar.h>
+#include <windows.h>
 #endif // defined(XP_WIN)
 
+#include "mozilla/MemoryChecking.h"
 #include "mozilla/TypedEnumBits.h"
 
 #include <ctype.h>
 #include <stdint.h>
 
 // Undo X11/X.h's definition of None
 #undef None
 
@@ -342,16 +344,58 @@ MakeCommandLine(int argc, wchar_t **argv
     }
   }
 
   *c = '\0';
 
   return std::move(s);
 }
 
+inline bool
+SetArgv0ToFullBinaryPath(wchar_t* aArgv[])
+{
+  if (!aArgv) {
+    return false;
+  }
+
+  DWORD bufLen = MAX_PATH;
+  mozilla::UniquePtr<wchar_t[]> buf;
+  DWORD retLen;
+
+  while (true) {
+    buf = mozilla::MakeUnique<wchar_t[]>(bufLen);
+    retLen = ::GetModuleFileNameW(nullptr, buf.get(), bufLen);
+    if (!retLen) {
+      return false;
+    }
+
+    if (retLen == bufLen && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+      bufLen *= 2;
+      continue;
+    }
+
+    break;
+  }
+
+  // Upon success, retLen *excludes* the null character
+  ++retLen;
+
+  // Since we're likely to have a bunch of unused space in buf, let's reallocate
+  // a string to the actual size of the file name.
+  auto newArgv_0 = mozilla::MakeUnique<wchar_t[]>(retLen);
+  if (wcscpy_s(newArgv_0.get(), retLen, buf.get())) {
+    return false;
+  }
+
+  // We intentionally leak newArgv_0 into argv[0]
+  aArgv[0] = newArgv_0.release();
+  MOZ_LSAN_INTENTIONALLY_LEAK_OBJECT(aArgv[0]);
+  return true;
+}
+
 #endif // defined(XP_WIN)
 
 // Save literal putenv string to environment variable.
 inline void
 SaveToEnv(const char *aEnvString)
 {
 #if defined(MOZILLA_INTERNAL_API)
   char *expr = strdup(aEnvString);
--- a/xpcom/ds/PLDHashTable.cpp
+++ b/xpcom/ds/PLDHashTable.cpp
@@ -496,21 +496,21 @@ PLDHashTable::ChangeTable(int32_t aDelta
   mEntryStore.Set(newEntryStore, &mGeneration);
   PLDHashMoveEntry moveEntry = mOps->moveEntry;
 
   // Copy only live entries, leaving removed ones behind.
   uint32_t oldCapacity = 1u << oldLog2;
   for (uint32_t i = 0; i < oldCapacity; ++i) {
     PLDHashEntryHdr* oldEntry = (PLDHashEntryHdr*)oldEntryAddr;
     if (EntryIsLive(oldEntry)) {
-      oldEntry->mKeyHash &= ~kCollisionFlag;
-      PLDHashEntryHdr* newEntry = FindFreeEntry(oldEntry->mKeyHash);
+      const PLDHashNumber key = oldEntry->mKeyHash & ~kCollisionFlag;
+      PLDHashEntryHdr* newEntry = FindFreeEntry(key);
       NS_ASSERTION(EntryIsFree(newEntry), "EntryIsFree(newEntry)");
       moveEntry(this, oldEntry, newEntry);
-      newEntry->mKeyHash = oldEntry->mKeyHash;
+      newEntry->mKeyHash = key;
     }
     oldEntryAddr += mEntrySize;
   }
 
   free(oldEntryStore);
   return true;
 }