Merge mozilla-central to mozilla-inbound. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Mon, 14 Jan 2019 12:46:01 +0200
changeset 453710 c879dc493add8fc475fc27f697460d77d213c6a8
parent 453709 d23f6e4d9ba23840b511babbf651e37b297e863d (current diff)
parent 453683 3dc7d345da5282969b71079d483ff8c30558819d (diff)
child 453711 1cebf4f5c850ad22500a360c2742de3c9dd78c81
push id35371
push userncsoregi@mozilla.com
push dateMon, 14 Jan 2019 17:23:11 +0000
treeherdermozilla-central@b8f96f4d584a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound. CLOSED TREE
--- a/accessible/tests/mochitest/focus/a11y.ini
+++ b/accessible/tests/mochitest/focus/a11y.ini
@@ -1,8 +1,9 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/mochitest/*.js
 
+[test_focus_radio.xul]
 [test_focusedChild.html]
 skip-if = (os == 'win' && os_version != '6.1') # bug 845134
 [test_takeFocus.html]
 [test_takeFocus.xul]
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/focus/test_focus_radio.xul
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Tests for Accessible TakeFocus on Radio Elements">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
+          src="../states.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    async function doTests() {
+      let radio1 = getAccessible("radio1");
+      let focused = waitForEventPromise(EVENT_FOCUS, radio1);
+      radio1.takeFocus();
+      await focused;
+      // radio1 wasn't selected. Ensure that takeFocus didn't change that.
+      testStates(radio1, STATE_FOCUSED, 0, STATE_CHECKED);
+
+      // Test focusing another radio in the group while the group is still
+      // focused.
+      let radio2 = getAccessible("radio2");
+      focused = waitForEventPromise(EVENT_FOCUS, radio2);
+      radio2.takeFocus();
+      await focused;
+      testStates(radio2, STATE_FOCUSED | STATE_CHECKED);
+
+      let groupEl = document.getElementById("radiogroup");
+      // Selecting an item also focuses it.
+      focused = waitForEventPromise(EVENT_FOCUS, radio1);
+      groupEl.value = "1";
+      testStates(radio1, STATE_FOCUSED | STATE_CHECKED);
+
+      // If an item is already selected but not focused, selecting it again
+      // focuses it.
+      focused = waitForEventPromise(EVENT_FOCUS, radio2);
+      radio2.takeFocus();
+      await focused;
+      testStates(radio2, STATE_FOCUSED, 0, STATE_CHECKED);
+      // radio1 is selected but not focused.
+      // Select radio1 again, which should focus it.
+      focused = waitForEventPromise(EVENT_FOCUS, radio1);
+      groupEl.value = "1";
+      await focused;
+      testStates(radio1, STATE_FOCUSED | STATE_CHECKED);
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <p id="display"></p>
+      <div id="content" style="display: none"></div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <radiogroup id="radiogroup" value="2">
+        <radio id="radio1" value="1"/>
+        <radio id="radio2" value="2"/>
+      </radiogroup>
+
+      <vbox id="eventdump"/>
+    </vbox>
+  </hbox>
+</window>
--- a/accessible/xul/XULFormControlAccessible.cpp
+++ b/accessible/xul/XULFormControlAccessible.cpp
@@ -13,16 +13,17 @@
 #include "Relation.h"
 #include "Role.h"
 #include "States.h"
 #include "TreeWalker.h"
 #include "XULMenuAccessible.h"
 
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULMenuListElement.h"
+#include "nsIDOMXULRadioGroupElement.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsITextControlFrame.h"
 #include "nsMenuPopupFrame.h"
 #include "nsNameSpaceManager.h"
 #include "mozilla/dom/Element.h"
 
@@ -301,16 +302,51 @@ uint64_t XULRadioGroupAccessible::Native
 bool XULRadioGroupAccessible::IsWidget() const { return true; }
 
 bool XULRadioGroupAccessible::IsActiveWidget() const {
   return FocusMgr()->HasDOMFocus(mContent);
 }
 
 bool XULRadioGroupAccessible::AreItemsOperable() const { return true; }
 
+Accessible* XULRadioGroupAccessible::CurrentItem() const {
+  if (!mSelectControl) {
+    return nullptr;
+  }
+
+  RefPtr<Element> currentItemElm;
+  nsCOMPtr<nsIDOMXULRadioGroupElement> group =
+      mSelectControl->AsXULRadioGroup();
+  if (group) {
+    group->GetFocusedItem(getter_AddRefs(currentItemElm));
+  }
+
+  if (currentItemElm) {
+    DocAccessible* document = Document();
+    if (document) {
+      return document->GetAccessible(currentItemElm);
+    }
+  }
+
+  return nullptr;
+}
+
+void XULRadioGroupAccessible::SetCurrentItem(const Accessible* aItem) {
+  if (!mSelectControl) {
+    return;
+  }
+
+  nsCOMPtr<Element> itemElm = aItem->Elm();
+  nsCOMPtr<nsIDOMXULRadioGroupElement> group =
+      mSelectControl->AsXULRadioGroup();
+  if (group) {
+    group->SetFocusedItem(itemElm);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // XULStatusBarAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 XULStatusBarAccessible::XULStatusBarAccessible(nsIContent* aContent,
                                                DocAccessible* aDoc)
     : AccessibleWrap(aContent, aDoc) {}
 
--- a/accessible/xul/XULFormControlAccessible.h
+++ b/accessible/xul/XULFormControlAccessible.h
@@ -115,16 +115,18 @@ class XULRadioGroupAccessible : public X
   // Accessible
   virtual mozilla::a11y::role NativeRole() const override;
   virtual uint64_t NativeInteractiveState() const override;
 
   // Widgets
   virtual bool IsWidget() const override;
   virtual bool IsActiveWidget() const override;
   virtual bool AreItemsOperable() const override;
+  virtual Accessible* CurrentItem() const override;
+  virtual void SetCurrentItem(const Accessible* aItem) override;
 };
 
 /**
  * Used for XUL statusbar element.
  */
 class XULStatusBarAccessible : public AccessibleWrap {
  public:
   XULStatusBarAccessible(nsIContent* aContent, DocAccessible* aDoc);
--- a/devtools/client/inspector/rules/views/text-property-editor.js
+++ b/devtools/client/inspector/rules/views/text-property-editor.js
@@ -390,17 +390,17 @@ TextPropertyEditor.prototype = {
       bezierSwatchClass: SHARED_SWATCH_CLASS + " " + BEZIER_SWATCH_CLASS,
       colorClass: "ruleview-color",
       colorSwatchClass: SHARED_SWATCH_CLASS + " " + COLOR_SWATCH_CLASS,
       filterClass: "ruleview-filter",
       filterSwatchClass: SHARED_SWATCH_CLASS + " " + FILTER_SWATCH_CLASS,
       flexClass: "ruleview-flex",
       gridClass: "ruleview-grid",
       shapeClass: "ruleview-shape",
-      shapeSwatchClass: SHARED_SWATCH_CLASS + " " + SHAPE_SWATCH_CLASS,
+      shapeSwatchClass: SHAPE_SWATCH_CLASS,
       // Only ask the parser to convert colors to the default color type specified by the
       // user if the property hasn't been changed yet.
       defaultColorType: !propDirty,
       urlClass: "theme-link",
       fontFamilyClass: FONT_FAMILY_CLASS,
       baseURI: this.sheetHref,
       unmatchedVariableClass: "ruleview-unmatched-variable",
       matchedVariableClass: "ruleview-variable",
--- a/devtools/client/responsive.html/index.css
+++ b/devtools/client/responsive.html/index.css
@@ -141,21 +141,25 @@ body,
 #settings-button::before {
   background-image: url("chrome://devtools/skin/images/settings.svg");
 }
 
 #exit-button::before {
   background-image: url("chrome://devtools/skin/images/close.svg");
 }
 
+/* Briefly animate screenshot button when clicked */
 #screenshot-button:disabled {
-  filter: var(--theme-icon-checked-filter);
   opacity: 1 !important;
 }
 
+#screenshot-button:disabled::before {
+  fill: var(--theme-toolbar-checked-color);
+}
+
 #device-selector {
   margin-inline-start: 4px;
 }
 
 #viewports-container {
   display: flex;
   overflow: auto;
   height: 100%;
--- a/devtools/client/themes/common.css
+++ b/devtools/client/themes/common.css
@@ -290,28 +290,32 @@ checkbox:-moz-focusring {
 }
 
 .devtools-toolbarbutton:not([label]) > .toolbarbutton-icon,
 .devtools-button:empty::before {
   width: 16px;
   height: 16px;
   margin: 0 3px;
   transition: opacity 0.05s ease-in-out;
+  -moz-context-properties: fill;
+  fill: currentColor;
   color: var(--theme-toolbar-icon-color);
   direction: ltr;
   font-size: 11px;
 }
 
 .devtools-button:empty::before {
   content: "";
   display: inline-block;
   background-repeat: no-repeat;
   vertical-align: middle;
 }
 
+.devtools-toolbarbutton:not([label])[checked=true] > .toolbarbutton-icon,
+.devtools-toolbarbutton:not([label])[open=true] > .toolbarbutton-icon,
 .devtools-button.checked:empty::before {
   color: var(--theme-toolbar-checked-color);
 }
 
 /* Standalone buttons */
 .devtools-button[standalone],
 .devtools-button[data-standalone],
 .devtools-toolbarbutton[standalone],
@@ -338,22 +342,16 @@ checkbox:-moz-focusring {
   opacity: 1;
 }
 
 .devtools-button:disabled,
 .devtools-toolbarbutton[disabled] {
   opacity: 0.5 !important;
 }
 
-.devtools-button.checked::before,
-.devtools-toolbarbutton:not([label])[checked=true] > image,
-.devtools-toolbarbutton:not([label])[open=true] > image {
-  fill: var(--theme-toolbar-checked-color);
-}
-
 /* Button states */
 .devtools-toolbarbutton[label],
 .devtools-toolbarbutton[standalone],
 .devtools-button[data-standalone],
 .devtools-button:not(:empty) {
   background: var(--toolbarbutton-background);
   padding: 0 5px;
 }
--- a/devtools/client/themes/images/filters.svg
+++ b/devtools/client/themes/images/filters.svg
@@ -1,30 +1,13 @@
 <!-- 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/. -->
 
 <svg height="0" xmlns="http://www.w3.org/2000/svg">
-  <!-- DevTools icon filter: Photon Blue 60 (light theme checked) -->
-  <filter id="icon-checked-light">
-    <feColorMatrix in="SourceGraphic" type="matrix"
-      values="0 0 0 0 0
-              0 0 0 0 0.122
-              0 0 0 0 0.74
-              0 0 0 1 0"/>
-  </filter>
-  <!-- DevTools icon filter: syntax blue #75BFFF (dark theme checked) -->
-  <filter id="icon-checked-dark">
-    <feColorMatrix in="SourceGraphic" type="matrix"
-      values="0 0 0 0.18 0
-              0 0 0 0.52 0
-              0 0 0 1 0
-              0 0 0 1 0"/>
-  </filter>
-
   <!-- Web Audio Gradients -->
   <linearGradient id="bypass-light" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat">
     <stop offset="0%" stop-color="#dde1e4a0"/> <!-- theme-splitter-color (0.5 opacity) -->
     <stop offset="50%" stop-color="transparent"/>
   </linearGradient>
 
   <linearGradient id="bypass-dark" x1="8%" y1="10%" x2="16%" y2="16%" spreadMethod="repeat">
     <stop offset="0%" stop-color="#454d5d"/> <!-- theme-splitter-color -->
--- a/devtools/client/themes/images/flexbox-swatch.svg
+++ b/devtools/client/themes/images/flexbox-swatch.svg
@@ -1,11 +1,8 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 11">
-  <g fill="none" stroke="context-stroke #0c0c0d" stroke-width="1" stroke-linejoin="round">
-    <rect x="0.5" y="0.5" width="12" height="10"
-      stroke-dasharray="1 1" stroke-dashoffset="0.5" />
-    <rect x="2.5" y="3.5" width="8" height="4"/>
-    <line x1="6.5" x2="6.5" y1="3" y2="8"/>
-  </g>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 13 11" fill="none" stroke="context-stroke" stroke-width="1" stroke-linejoin="round">
+  <rect x="0.5" y="0.5" width="12" height="10" stroke-dasharray="1 1" stroke-dashoffset="0.5"/>
+  <rect x="2.5" y="3.5" width="8" height="4"/>
+  <line x1="6.5" x2="6.5" y1="3" y2="8"/>
 </svg>
--- a/devtools/client/themes/images/grid.svg
+++ b/devtools/client/themes/images/grid.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" stroke="#696969">
+<svg width="12" height="12" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" stroke="context-stroke">
   <path fill="none" d="M1 2.5h9m-9 3h9m-9 3h9M2.5 1v9m3-9v9m3-9v9"/>
 </svg>
--- a/devtools/client/themes/images/shape-swatch.svg
+++ b/devtools/client/themes/images/shape-swatch.svg
@@ -1,4 +1,10 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke="context-stroke #0b0b0b"><defs><style>.cls-1{fill:none;}</style></defs><path class="cls-1" d="M2.5,5.55V9L2.12,9A1.5,1.5,0,1,0,4,10.88L4,10.5H11l.1.38a1.5,1.5,0,1,0,.89-1.77l-.42.17-2-3.8.36-.25A1.5,1.5,0,1,0,7.55,3.62L7.45,4H4L4,3.62A1.5,1.5,0,1,0,2.12,5.45Z"/><circle class="cls-1" cx="12.5" cy="10.5" r="1.5"/><circle class="cls-1" cx="2.5" cy="10.5" r="1.5"/><circle class="cls-1" cx="9" cy="4" r="1.5"/><circle class="cls-1" cx="2.5" cy="4" r="1.5"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="none" stroke="context-stroke">
+  <path d="M2.5,5.55V9L2.12,9A1.5,1.5,0,1,0,4,10.88L4,10.5H11l.1.38a1.5,1.5,0,1,0,.89-1.77l-.42.17-2-3.8.36-.25A1.5,1.5,0,1,0,7.55,3.62L7.45,4H4L4,3.62A1.5,1.5,0,1,0,2.12,5.45Z"/>
+  <circle cx="12.5" cy="10.5" r="1.5"/>
+  <circle cx="2.5" cy="10.5" r="1.5"/>
+  <circle cx="9" cy="4" r="1.5"/>
+  <circle cx="2.5" cy="4" r="1.5"/>
+</svg>
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -2,29 +2,25 @@
  * 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/. */
 
 /* CSS Variables specific to this panel that aren't defined by the themes */
 :root {
   --rule-highlight-background-color: var(--theme-highlight-yellow);
   --rule-overridden-item-border-color: var(--theme-content-color3);
   --rule-header-background-color: var(--theme-toolbar-background);
-  --rule-flex-toggle-color: var(--grey-90);
-  --rule-shape-toggle-color: var(--grey-90);
   --rule-target-button-color: var(--grey-40);
   --rule-target-button-hover-color: var(--grey-50);
   --rule-target-button-active-color: var(--blue-50);
 }
 
 :root.theme-dark {
   --rule-highlight-background-color: #521C76;
   --rule-overridden-item-border-color: var(--theme-content-color1);
   --rule-header-background-color: #222225;
-  --rule-flex-toggle-color: var(--grey-10);
-  --rule-shape-toggle-color: var(--grey-10);
   --rule-target-button-color: var(--grey-45);
   --rule-target-button-hover-color: var(--grey-30);
   --rule-target-button-active-color: var(--blue-30);
 }
 
 /* Rule View Tabpanel */
 
 #sidebar-panel-ruleview {
@@ -411,56 +407,84 @@
 .ruleview-overridden-item:last-child:after {
   display: none;
 }
 
 .ruleview-overridden-item .ruleview-namecontainer {
   margin-left: 0;
 }
 
+/* All swatches */
+
 .ruleview-flex,
 .ruleview-grid,
+.ruleview-shapeswatch,
 .ruleview-swatch {
   cursor: pointer;
-  border-radius: 50%;
   width: 1em;
   height: 1em;
   vertical-align: middle;
   /* align the swatch with its value */
   margin-top: -1px;
   margin-inline-end: 5px;
   display: inline-block;
   position: relative;
 }
 
+/* Icon swatches not using the .ruleview-swatch class (flex, grid, shape) */
+
+.ruleview-flex,
+.ruleview-grid,
+.ruleview-shapeswatch {
+  -moz-context-properties: stroke;
+  stroke: var(--theme-toolbar-icon-color);
+}
+
+.ruleview-flex.active,
+.ruleview-grid.active,
+.ruleview-shapeswatch.active {
+  stroke: var(--theme-toolbar-checked-color);
+  filter: brightness(0.9);
+}
+
 .ruleview-flex {
   background-image: url("chrome://devtools/skin/images/flexbox-swatch.svg");
   background-size: 13px 11px;
-  -moz-context-properties: stroke;
-  stroke: var(--rule-flex-toggle-color);
   width: 13px;
   height: 11px;
-  border-radius: 0;
 }
 
 .ruleview-grid {
-  background: url("chrome://devtools/skin/images/grid.svg");
-  border-radius: 0;
+  background-image: url("chrome://devtools/skin/images/grid.svg");
 }
 
 .ruleview-grid[disabled] {
   cursor: default;
   opacity: 0.5;
 }
 
+.ruleview-shapeswatch {
+  background-image: url("chrome://devtools/skin/images/shape-swatch.svg");
+  background-size: 110%;
+  width: 1.45em;
+  height: 1.45em;
+}
+
 .ruleview-shape-point.active,
 .ruleview-shapeswatch.active + .ruleview-shape > .ruleview-shape-point:hover {
   background-color: var(--rule-highlight-background-color);
 }
 
+/* Round swatches using the .ruleview-swatch class (color, bezier, filter and angle) */
+
+.ruleview-swatch {
+  background-size: 1em;
+  border-radius: 50%;
+}
+
 .ruleview-colorswatch::before {
   content: '';
   background-color: #eee;
   background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc),
                     linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc);
   background-size: 12px 12px;
   background-position: 0 0, 6px 6px;
   position: absolute;
@@ -468,52 +492,39 @@
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   z-index: -1;
 }
 
 .ruleview-bezierswatch {
-  background: url("chrome://devtools/skin/images/cubic-bezier-swatch.svg");
-  background-size: 1em;
+  background-image: url("chrome://devtools/skin/images/cubic-bezier-swatch.svg");
 }
 
 .ruleview-filterswatch {
-  background: url("chrome://devtools/skin/images/filter-swatch.svg");
-  background-size: 1em;
+  background-image: url("chrome://devtools/skin/images/filter-swatch.svg");
 }
 
 .ruleview-angleswatch {
-  background: url("chrome://devtools/skin/images/angle-swatch.svg");
-  background-size: 1em;
-}
-
-.ruleview-shapeswatch {
-  background: url("chrome://devtools/skin/images/shape-swatch.svg");
-  -moz-context-properties: stroke;
-  stroke: var(--rule-shape-toggle-color);
-  border-radius: 0;
-  background-size: 110% 110%;
-  box-shadow: none;
-  width: 1.45em;
-  height: 1.45em;
+  background-image: url("chrome://devtools/skin/images/angle-swatch.svg");
 }
 
 .ruleview-overridden {
   text-decoration: line-through;
 }
 
 /**
  * Hide swatches (tool icons) from properties that are overwritten by higher specificity * rules.
  * .ruleview-swatch is a base class for many tool swatches (shapes, color, bezier curves)
  * .ruleview-flex and .ruleview-grid are custom
  */
 .ruleview-overridden .ruleview-flex,
 .ruleview-overridden .ruleview-grid,
+.ruleview-overridden .ruleview-shapeswatch,
 .ruleview-overridden .ruleview-swatch {
   display: none;
 }
 
 .theme-light .ruleview-overridden {
   text-decoration-color: var(--theme-content-color3);
 }
 
@@ -600,22 +611,16 @@
   fill: var(--rule-target-button-hover-color);
 }
 
 .ruleview-selectorhighlighter:active,
 .ruleview-selectorhighlighter.highlighted {
   fill: var(--rule-target-button-active-color);
 }
 
-.ruleview-flex.active,
-.ruleview-grid.active,
-.ruleview-shapeswatch.active {
-  filter: var(--theme-icon-checked-filter) brightness(0.9);
-}
-
 #ruleview-add-rule-button::before {
   background-image: url("chrome://devtools/skin/images/add.svg");
 }
 
 #pseudo-class-panel-toggle::before {
   background-image: url("chrome://devtools/skin/images/pseudo-class.svg");
 }
 
--- a/devtools/client/themes/toolbars.css
+++ b/devtools/client/themes/toolbars.css
@@ -176,23 +176,17 @@
 .devtools-sidebar-tabs tabs > tab[selected]:hover:active {
   color: var(--theme-selection-color);
   background: var(--theme-selection-background);
 }
 
 /*
  * Apply the default fill color to toolbar icons
  */
-.devtools-toolbarbutton > image,
-.devtools-button::before,
-.scrollbutton-up > .toolbarbutton-icon,
-.scrollbutton-down > .toolbarbutton-icon,
-#black-boxed-message-button .button-icon,
 #canvas-debugging-empty-notice-button .button-icon,
-#toggle-breakpoints[checked] > image,
 .event-tooltip-debugger-icon {
   -moz-context-properties: fill;
   fill: var(--theme-toolbar-icon-color);
 }
 
 .hidden-labels-box:not(.visible) > label,
 .hidden-labels-box.visible ~ .hidden-labels-box > label:last-child {
   display: none;
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -82,19 +82,16 @@
   --theme-graphs-purple: #b693eb;
   --theme-graphs-yellow: #efc052;
   --theme-graphs-orange: #d97e00;
   --theme-graphs-red: #e57180;
   --theme-graphs-grey: #cccccc;
   --theme-graphs-full-red: #f00;
   --theme-graphs-full-blue: #00f;
 
-  /* Icon filters */
-  --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-light);
-
   /* Common popup styles(used by HTMLTooltip and autocomplete) */
   --theme-popup-background: -moz-field;
   --theme-popup-color: -moz-fieldText;
   --theme-popup-border-color: ThreeDShadow;
   --theme-popup-dimmed: hsla(0,0%,80%,.3);
 }
 
 /*
@@ -175,19 +172,16 @@
   --theme-graphs-purple: #df80ff;
   --theme-graphs-yellow: #d99b28;
   --theme-graphs-orange: #d96629;
   --theme-graphs-red: #eb5368;
   --theme-graphs-grey: #757873;
   --theme-graphs-full-red: #f00;
   --theme-graphs-full-blue: #00f;
 
-  /* Icon filters */
-  --theme-icon-checked-filter: url(chrome://devtools/skin/images/filters.svg#icon-checked-dark);
-
   /* Common popup styles(used by HTMLTooltip and autocomplete) */
   --theme-popup-background: var(--grey-60);
   --theme-popup-color: rgb(249,249,250);
   --theme-popup-border-color: #27272b;
   --theme-popup-dimmed: rgba(249,249,250,.1);
 }
 
 :root {
--- a/devtools/client/themes/widgets.css
+++ b/devtools/client/themes/widgets.css
@@ -474,23 +474,24 @@
   background-repeat: no-repeat;
   -moz-context-properties: fill;
   fill: #d7d7d7;
 }
 
 .variables-view-delete:hover,
 .variables-view-edit:hover,
 .variables-view-open-inspector:hover {
-  filter: var(--theme-icon-checked-filter);
+  fill: var(--theme-toolbar-checked-color);
 }
 
 .variables-view-delete:active,
 .variables-view-edit:active,
 .variables-view-open-inspector:active {
-  filter: var(--theme-icon-checked-filter) brightness(0.9);
+  fill: var(--theme-toolbar-checked-color);
+  filter: brightness(0.9);
 }
 
 .variable-or-property:focus > .title > .variables-view-delete,
 .variable-or-property:focus > .title > .variables-view-edit,
 .variable-or-property:focus > .title > .variables-view-open-inspector {
   filter: none;
 }
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -148,16 +148,17 @@
 #include "nsDOMStringMap.h"
 #include "DOMIntersectionObserver.h"
 
 #include "nsIDOMXULButtonElement.h"
 #include "nsIDOMXULContainerElement.h"
 #include "nsIDOMXULControlElement.h"
 #include "nsIDOMXULMenuListElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
+#include "nsIDOMXULRadioGroupElement.h"
 #include "nsIDOMXULRelatedElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsIBrowser.h"
 
 #include "nsISpeculativeConnect.h"
 #include "nsIIOService.h"
@@ -4059,16 +4060,22 @@ already_AddRefed<nsIDOMXULMenuListElemen
 
 already_AddRefed<nsIDOMXULMultiSelectControlElement>
 Element::AsXULMultiSelectControl() {
   nsCOMPtr<nsIDOMXULMultiSelectControlElement> value;
   GetCustomInterface(getter_AddRefs(value));
   return value.forget();
 }
 
+already_AddRefed<nsIDOMXULRadioGroupElement> Element::AsXULRadioGroup() {
+  nsCOMPtr<nsIDOMXULRadioGroupElement> value;
+  GetCustomInterface(getter_AddRefs(value));
+  return value.forget();
+}
+
 already_AddRefed<nsIDOMXULRelatedElement> Element::AsXULRelated() {
   nsCOMPtr<nsIDOMXULRelatedElement> value;
   GetCustomInterface(getter_AddRefs(value));
   return value.forget();
 }
 
 already_AddRefed<nsIDOMXULSelectControlElement> Element::AsXULSelectControl() {
   nsCOMPtr<nsIDOMXULSelectControlElement> value;
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -63,16 +63,17 @@ class nsDOMStringMap;
 struct ServoNodeData;
 
 class nsIDOMXULButtonElement;
 class nsIDOMXULContainerElement;
 class nsIDOMXULContainerItemElement;
 class nsIDOMXULControlElement;
 class nsIDOMXULMenuListElement;
 class nsIDOMXULMultiSelectControlElement;
+class nsIDOMXULRadioGroupElement;
 class nsIDOMXULRelatedElement;
 class nsIDOMXULSelectControlElement;
 class nsIDOMXULSelectControlItemElement;
 class nsIBrowser;
 
 namespace mozilla {
 class DeclarationBlock;
 struct MutationClosureData;
@@ -1598,16 +1599,17 @@ class Element : public FragmentOrElement
   // pointer only if the element implements that interface.
   already_AddRefed<nsIDOMXULButtonElement> AsXULButton();
   already_AddRefed<nsIDOMXULContainerElement> AsXULContainer();
   already_AddRefed<nsIDOMXULContainerItemElement> AsXULContainerItem();
   already_AddRefed<nsIDOMXULControlElement> AsXULControl();
   already_AddRefed<nsIDOMXULMenuListElement> AsXULMenuList();
   already_AddRefed<nsIDOMXULMultiSelectControlElement>
   AsXULMultiSelectControl();
+  already_AddRefed<nsIDOMXULRadioGroupElement> AsXULRadioGroup();
   already_AddRefed<nsIDOMXULRelatedElement> AsXULRelated();
   already_AddRefed<nsIDOMXULSelectControlElement> AsXULSelectControl();
   already_AddRefed<nsIDOMXULSelectControlItemElement> AsXULSelectControlItem();
   already_AddRefed<nsIBrowser> AsBrowser();
 
  protected:
   /*
    * Named-bools for use with SetAttrAndNotify to make call sites easier to
--- a/dom/interfaces/xul/moz.build
+++ b/dom/interfaces/xul/moz.build
@@ -9,15 +9,16 @@ with Files("**"):
 
 XPIDL_SOURCES += [
     'nsIDOMXULButtonElement.idl',
     'nsIDOMXULCommandDispatcher.idl',
     'nsIDOMXULContainerElement.idl',
     'nsIDOMXULControlElement.idl',
     'nsIDOMXULMenuListElement.idl',
     'nsIDOMXULMultSelectCntrlEl.idl',
+    'nsIDOMXULRadioGroupElement.idl',
     'nsIDOMXULRelatedElement.idl',
     'nsIDOMXULSelectCntrlEl.idl',
     'nsIDOMXULSelectCntrlItemEl.idl',
 ]
 
 XPIDL_MODULE = 'dom_xul'
 
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/xul/nsIDOMXULRadioGroupElement.idl
@@ -0,0 +1,13 @@
+/* -*- Mode: IDL; tab-width: 2; 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 "nsISupports.idl"
+
+webidl Element;
+
+[scriptable, uuid(2cc1d24b-ec9f-4e18-aa34-a298a9007f23)]
+interface nsIDOMXULRadioGroupElement : nsISupports {
+  attribute Element focusedItem;
+};
--- a/image/decoders/icon/nsIconURI.cpp
+++ b/image/decoders/icon/nsIconURI.cpp
@@ -413,18 +413,21 @@ NS_IMETHODIMP
 nsMozIconURI::EqualsExceptRef(nsIURI* other, bool* result) {
   // GetRef/SetRef not supported by nsMozIconURI, so
   // EqualsExceptRef() is the same as Equals().
   return Equals(other, result);
 }
 
 NS_IMETHODIMP
 nsMozIconURI::SchemeIs(const char* aScheme, bool* aEquals) {
-  MOZ_ASSERT(aScheme);
   MOZ_ASSERT(aEquals, "null pointer");
+  if (!aScheme) {
+    *aEquals = false;
+    return NS_OK;
+  }
 
   *aEquals = PL_strcasecmp("moz-icon", aScheme) ? false : true;
   return NS_OK;
 }
 
 nsresult nsMozIconURI::Clone(nsIURI** result) {
   nsCOMPtr<nsIURL> newIconURL;
   if (mIconURL) {
--- a/modules/libjar/nsJARURI.cpp
+++ b/modules/libjar/nsJARURI.cpp
@@ -470,18 +470,21 @@ nsJARURI::EqualsExceptRef(nsIURI *other,
 
   return refHandlingMode == eHonorRef
              ? mJAREntry->Equals(otherJAR->mJAREntry, result)
              : mJAREntry->EqualsExceptRef(otherJAR->mJAREntry, result);
 }
 
 NS_IMETHODIMP
 nsJARURI::SchemeIs(const char *i_Scheme, bool *o_Equals) {
-  MOZ_ASSERT(i_Scheme);
   MOZ_ASSERT(o_Equals);
+  if (!i_Scheme) {
+    *o_Equals = false;
+    return NS_OK;
+  }
 
   *o_Equals = PL_strcasecmp("jar", i_Scheme) ? false : true;
   return NS_OK;
 }
 
 nsresult nsJARURI::Clone(nsIURI **result) {
   nsresult rv;
 
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -518,18 +518,21 @@ bool nsSimpleURI::EqualsInternal(nsSimpl
               (!mIsRefValid || mRef == otherUri->mRef));
   }
 
   return result;
 }
 
 NS_IMETHODIMP
 nsSimpleURI::SchemeIs(const char *i_Scheme, bool *o_Equals) {
-  MOZ_ASSERT(i_Scheme);
   MOZ_ASSERT(o_Equals, "null pointer");
+  if (!i_Scheme) {
+    *o_Equals = false;
+    return NS_OK;
+  }
 
   const char *this_scheme = mScheme.get();
 
   // mScheme is guaranteed to be lower case.
   if (*i_Scheme == *this_scheme || *i_Scheme == (*this_scheme - ('a' - 'A'))) {
     *o_Equals = PL_strcasecmp(this_scheme, i_Scheme) ? false : true;
   } else {
     *o_Equals = false;
--- a/netwerk/base/nsStandardURL.cpp
+++ b/netwerk/base/nsStandardURL.cpp
@@ -2199,18 +2199,21 @@ nsresult nsStandardURL::EqualsInternal(
   // same file, so they are different.
   *result = false;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsStandardURL::SchemeIs(const char *scheme, bool *result) {
-  MOZ_ASSERT(scheme);
   MOZ_ASSERT(result, "null pointer");
+  if (!scheme) {
+    *result = false;
+    return NS_OK;
+  }
 
   *result = SegmentIs(mScheme, scheme);
   return NS_OK;
 }
 
 /* virtual */ nsStandardURL *nsStandardURL::StartClone() {
   nsStandardURL *clone = new nsStandardURL();
   return clone;
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -605,22 +605,37 @@ function check_space_escaping()
   uri = gIoService.newURI("data:text/plain,hello world#space%20hash");
   Assert.equal(uri.spec, "data:text/plain,hello world#space%20hash");
   uri = gIoService.newURI("data:text/plain,hello world#space hash");
   Assert.equal(uri.spec, "data:text/plain,hello world#space%20hash");
   uri = gIoService.newURI("http://example.com/test path#test path");
   uri = gIoService.newURI("http://example.com/test%20path#test%20path");
 }
 
+function check_schemeIsNull()
+{
+  let uri = gIoService.newURI("data:text/plain,aaa");
+  Assert.ok(!uri.schemeIs(null));
+  uri = gIoService.newURI("http://example.com");
+  Assert.ok(!uri.schemeIs(null));
+  uri = gIoService.newURI("dummyscheme://example.com");
+  Assert.ok(!uri.schemeIs(null));
+  uri = gIoService.newURI("jar:resource://gre/chrome.toolkit.jar!/");
+  Assert.ok(!uri.schemeIs(null));
+  uri = gIoService.newURI("moz-icon://.unknown?size=32");
+  Assert.ok(!uri.schemeIs(null));
+}
+
 // TEST MAIN FUNCTION
 // ------------------
 function run_test()
 {
   check_nested_mutations();
   check_space_escaping();
+  check_schemeIsNull();
 
   // UTF-8 check - From bug 622981
   // ASCII
   let base = gIoService.newURI("http://example.org/xenia?");
   let resolved = gIoService.newURI("?x", null, base);
   let expected = gIoService.newURI("http://example.org/xenia?x");
   do_info("Bug 662981: ACSII - comparing " + resolved.spec + " and " + expected.spec);
   Assert.ok(resolved.equals(expected));
--- a/toolkit/content/widgets/radio.js
+++ b/toolkit/content/widgets/radio.js
@@ -241,46 +241,59 @@ class MozRadiogroup extends MozElements.
         children[i].removeAttribute("focused");
       }
     }
 
     var event = document.createEvent("Events");
     event.initEvent("select", false, true);
     this.dispatchEvent(event);
 
-    if (!alreadySelected && focused) {
-      // Only report if actual change
-      var myEvent;
-      if (val) {
-        myEvent = document.createEvent("Events");
-        myEvent.initEvent("RadioStateChange", true, true);
-        val.dispatchEvent(myEvent);
-      }
+    if (focused) {
+      if (alreadySelected) {
+        // Notify accessibility that this item got focus.
+        event = document.createEvent("Events");
+        event.initEvent("DOMMenuItemActive", true, true);
+        val.dispatchEvent(event);
+      } else {
+        // Only report if actual change
+        if (val) {
+          // Accessibility will fire focus for this.
+          event = document.createEvent("Events");
+          event.initEvent("RadioStateChange", true, true);
+          val.dispatchEvent(event);
+        }
 
-      if (previousItem) {
-        myEvent = document.createEvent("Events");
-        myEvent.initEvent("RadioStateChange", true, true);
-        previousItem.dispatchEvent(myEvent);
+        if (previousItem) {
+          event = document.createEvent("Events");
+          event.initEvent("RadioStateChange", true, true);
+          previousItem.dispatchEvent(event);
+        }
       }
     }
 
     return val;
   }
 
   get selectedItem() {
     var children = this._getRadioChildren();
     for (var i = 0; i < children.length; ++i) {
       if (children[i].selected)
         return children[i];
     }
     return null;
   }
 
   set focusedItem(val) {
-    if (val) val.setAttribute("focused", "true");
+    if (val) {
+      val.setAttribute("focused", "true");
+      // Notify accessibility that this item got focus.
+      let event = document.createEvent("Events");
+      event.initEvent("DOMMenuItemActive", true, true);
+      val.dispatchEvent(event);
+    }
 
     // unfocus all other group nodes
     var children = this._getRadioChildren();
     for (var i = 0; i < children.length; ++i) {
       if (children[i] != val)
         children[i].removeAttribute("focused");
     }
     return val;
@@ -370,13 +383,16 @@ class MozRadiogroup extends MozElements.
     var radio = document.createXULElement("radio");
     radio.setAttribute("label", label);
     radio.setAttribute("value", value);
     this.appendChild(radio);
     return radio;
   }
 }
 
-MozXULElement.implementCustomInterface(MozRadiogroup, [Ci.nsIDOMXULSelectControlElement]);
+MozXULElement.implementCustomInterface(MozRadiogroup, [
+  Ci.nsIDOMXULSelectControlElement,
+  Ci.nsIDOMXULRadioGroupElement,
+]);
 
 customElements.define("radiogroup", MozRadiogroup);
 
 }