Merge inbound to mozilla-central a=merge
authorCoroiu Cristina <ccoroiu@mozilla.com>
Tue, 24 Jul 2018 00:43:44 +0300
changeset 482935 fe48e26ca88c
parent 482900 07414f000aa1 (current diff)
parent 482934 b82a9d1bfaf8 (diff)
child 482943 c47bdc24522f
child 483007 cb74f2db6d82
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone63.0a1
first release with
nightly linux32
fe48e26ca88c / 63.0a1 / 20180723220051 / files
nightly linux64
fe48e26ca88c / 63.0a1 / 20180723220051 / files
nightly mac
fe48e26ca88c / 63.0a1 / 20180723220051 / files
nightly win32
fe48e26ca88c / 63.0a1 / 20180723220051 / files
nightly win64
fe48e26ca88c / 63.0a1 / 20180723220051 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central a=merge
browser/modules/LightweightThemeChildListener.jsm
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^
testing/web-platform/meta/clipboard-apis/async-navigator-clipboard-basics.https.html.ini
--- 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;
 }