Diff
Modified: trunk/LayoutTests/ChangeLog (240308 => 240309)
--- trunk/LayoutTests/ChangeLog 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/LayoutTests/ChangeLog 2019-01-23 00:32:59 UTC (rev 240309)
@@ -1,3 +1,14 @@
+2019-01-22 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: Audit: provide a way to get related Accessibility properties for a given node
+ https://bugs.webkit.org/show_bug.cgi?id=193227
+ <rdar://problem/46787862>
+
+ Reviewed by Joseph Pecoraro.
+
+ * inspector/audit/run-accessibility.html:
+ * inspector/audit/run-accessibility-expected.txt:
+
2019-01-22 Simon Fraser <simon.fra...@apple.com>
Remove an iOS quirk where iframe renderers are identified as "RenderPartObject" in layout test results
Modified: trunk/LayoutTests/inspector/audit/run-accessibility-expected.txt (240308 => 240309)
--- trunk/LayoutTests/inspector/audit/run-accessibility-expected.txt 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/LayoutTests/inspector/audit/run-accessibility-expected.txt 2019-01-23 00:32:59 UTC (rev 240309)
@@ -63,6 +63,46 @@
Result: []
Audit teardown...
+-- Running test case: Audit.run.Accessibility.getComputedProperties.parent
+Audit setup...
+Audit run `WebInspectorAudit.Accessibility.getComputedProperties(document.querySelector("#parent"))`...
+Result: {
+ "busy": false,
+ "currentState": "false",
+ "disabled": false,
+ "headingLevel": 0,
+ "hidden": false,
+ "hierarchicalLevel": 0,
+ "ignored": false,
+ "ignoredByDefault": false,
+ "invalidStatus": "false",
+ "isPopUpButton": false,
+ "pressed": false,
+ "role": "tree",
+ "selected": false
+}
+Audit teardown...
+
+-- Running test case: Audit.run.Accessibility.getComputedProperties.child
+Audit setup...
+Audit run `WebInspectorAudit.Accessibility.getComputedProperties(document.querySelector("#child"))`...
+Result: {
+ "busy": false,
+ "currentState": "false",
+ "disabled": false,
+ "headingLevel": 0,
+ "hidden": false,
+ "hierarchicalLevel": 1,
+ "ignored": false,
+ "ignoredByDefault": false,
+ "invalidStatus": "false",
+ "isPopUpButton": false,
+ "pressed": false,
+ "role": "treeitem",
+ "selected": true
+}
+Audit teardown...
+
-- Running test case: Audit.run.Accessibility.getControlledNodes.parent
Audit setup...
Audit run `WebInspectorAudit.Accessibility.getControlledNodes(document.querySelector("#parent"))`...
@@ -114,7 +154,7 @@
-- Running test case: Audit.run.Accessibility.getParentNode.parent
Audit setup...
Audit run `WebInspectorAudit.Accessibility.getParentNode(document.querySelector("#parent"))`...
-Result: undefined
+Result: <document>
Audit teardown...
-- Running test case: Audit.run.Accessibility.getParentNode.child
@@ -148,6 +188,9 @@
Testing copied getChildNodes...
PASS: Should produce an exception.
Error: NotAllowedError: Cannot be called outside of a Web Inspector Audit
+Testing copied getComputedProperties...
+PASS: Should produce an exception.
+Error: NotAllowedError: Cannot be called outside of a Web Inspector Audit
Testing copied getControlledNodes...
PASS: Should produce an exception.
Error: NotAllowedError: Cannot be called outside of a Web Inspector Audit
Modified: trunk/LayoutTests/inspector/audit/run-accessibility.html (240308 => 240309)
--- trunk/LayoutTests/inspector/audit/run-accessibility.html 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/LayoutTests/inspector/audit/run-accessibility.html 2019-01-23 00:32:59 UTC (rev 240309)
@@ -6,12 +6,20 @@
<script>
function stringify(result) {
+ if (result === null || result === undefined || typeof result === "boolean" || typeof result === "string" || typeof result === "number")
+ return result;
if (result instanceof Element)
return "#" + result.id;
+ if (result instanceof HTMLDocument)
+ return "<document>";
if (Array.isArray(result))
return JSON.stringify(result.map(stringify));
- if (result === null || result === undefined);
- return result;
+ if (typeof result === "object" && result.constructor === Object) {
+ let mapped = {};
+ for (let key in result)
+ mapped[key] = stringify(result[key]);
+ return JSON.stringify(mapped, null, 4);
+ }
return "UNEXPECTED " + result;
}
@@ -44,6 +52,9 @@
{ func: "getChildNodes", target: "parent" },
{ func: "getChildNodes", target: "child" },
+ { func: "getComputedProperties", target: "parent" },
+ { func: "getComputedProperties", target: "child" },
+
{ func: "getControlledNodes", target: "parent" },
{ func: "getControlledNodes", target: "child" },
Modified: trunk/Source/WebCore/ChangeLog (240308 => 240309)
--- trunk/Source/WebCore/ChangeLog 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/Source/WebCore/ChangeLog 2019-01-23 00:32:59 UTC (rev 240309)
@@ -1,3 +1,18 @@
+2019-01-22 Devin Rousso <drou...@apple.com>
+
+ Web Inspector: Audit: provide a way to get related Accessibility properties for a given node
+ https://bugs.webkit.org/show_bug.cgi?id=193227
+ <rdar://problem/46787862>
+
+ Reviewed by Joseph Pecoraro.
+
+ Test: inspector/audit/run-accessibility.html
+
+ * inspector/InspectorAuditAccessibilityObject.idl:
+ * inspector/InspectorAuditAccessibilityObject.h:
+ * inspector/InspectorAuditAccessibilityObject.cpp:
+ (WebCore::InspectorAuditAccessibilityObject::getComputedProperties): Added.
+
2019-01-22 Simon Fraser <simon.fra...@apple.com>
Remove an iOS quirk where iframe renderers are identified as "RenderPartObject" in layout test results
Modified: trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.cpp (240308 => 240309)
--- trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.cpp 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.cpp 2019-01-23 00:32:59 UTC (rev 240309)
@@ -36,7 +36,9 @@
#include "ElementDescendantIterator.h"
#include "HTMLNames.h"
#include "Node.h"
+#include "SpaceSplitString.h"
#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
@@ -115,7 +117,130 @@
return result;
}
+ExceptionOr<Optional<InspectorAuditAccessibilityObject::ComputedProperties>> InspectorAuditAccessibilityObject::getComputedProperties(Node& node)
+{
+ ERROR_IF_NO_ACTIVE_AUDIT();
+ Optional<InspectorAuditAccessibilityObject::ComputedProperties> result;
+
+ if (AccessibilityObject* axObject = accessiblityObjectForNode(node)) {
+ ComputedProperties computedProperties;
+
+ AccessibilityObject* current = axObject;
+ while (current && (!computedProperties.busy || !computedProperties.busy.value())) {
+ computedProperties.busy = current->isBusy();
+ current = current->parentObject();
+ }
+
+ if (axObject->supportsChecked()) {
+ AccessibilityButtonState checkValue = axObject->checkboxOrRadioValue();
+ if (checkValue == AccessibilityButtonState::On)
+ computedProperties.checked = "true"_s;
+ else if (checkValue == AccessibilityButtonState::Mixed)
+ computedProperties.checked = "mixed"_s;
+ else if (axObject->isChecked())
+ computedProperties.checked = "true"_s;
+ else
+ computedProperties.checked = "false"_s;
+ }
+
+ switch (axObject->currentState()) {
+ case AccessibilityCurrentState::False:
+ computedProperties.currentState = "false"_s;
+ break;
+ case AccessibilityCurrentState::True:
+ computedProperties.currentState = "true"_s;
+ break;
+ case AccessibilityCurrentState::Page:
+ computedProperties.currentState = "page"_s;
+ break;
+ case AccessibilityCurrentState::Step:
+ computedProperties.currentState = "step"_s;
+ break;
+ case AccessibilityCurrentState::Location:
+ computedProperties.currentState = "location"_s;
+ break;
+ case AccessibilityCurrentState::Date:
+ computedProperties.currentState = "date"_s;
+ break;
+ case AccessibilityCurrentState::Time:
+ computedProperties.currentState = "time"_s;
+ break;
+ }
+
+ computedProperties.disabled = !axObject->isEnabled();
+
+ if (axObject->supportsExpanded())
+ computedProperties.expanded = axObject->isExpanded();
+
+ if (is<Element>(node) && axObject->canSetFocusAttribute())
+ computedProperties.focused = axObject->isFocused();
+
+ computedProperties.headingLevel = axObject->headingLevel();
+ computedProperties.hidden = axObject->isAXHidden() || axObject->isDOMHidden();
+ computedProperties.hierarchicalLevel = axObject->hierarchicalLevel();
+ computedProperties.ignored = axObject->accessibilityIsIgnored();
+ computedProperties.ignoredByDefault = axObject->accessibilityIsIgnoredByDefault();
+
+ String invalidValue = axObject->invalidStatus();
+ if (invalidValue == "false")
+ computedProperties.invalidStatus = "false"_s;
+ else if (invalidValue == "grammar")
+ computedProperties.invalidStatus = "grammar"_s;
+ else if (invalidValue == "spelling")
+ computedProperties.invalidStatus = "spelling"_s;
+ else
+ computedProperties.invalidStatus = "true"_s;
+
+ computedProperties.isPopUpButton = axObject->isPopUpButton() || axObject->hasPopup();
+ computedProperties.label = axObject->computedLabel();
+
+ if (axObject->supportsLiveRegion()) {
+ computedProperties.liveRegionAtomic = axObject->liveRegionAtomic();
+
+ String ariaRelevantAttrValue = axObject->liveRegionRelevant();
+ if (!ariaRelevantAttrValue.isEmpty()) {
+ Vector<String> liveRegionRelevant;
+ String ariaRelevantAdditions = "additions";
+ String ariaRelevantRemovals = "removals";
+ String ariaRelevantText = "text";
+
+ const auto& values = SpaceSplitString(ariaRelevantAttrValue, true);
+ if (values.contains("all")) {
+ liveRegionRelevant.append(ariaRelevantAdditions);
+ liveRegionRelevant.append(ariaRelevantRemovals);
+ liveRegionRelevant.append(ariaRelevantText);
+ } else {
+ if (values.contains(ariaRelevantAdditions))
+ liveRegionRelevant.append(ariaRelevantAdditions);
+ if (values.contains(ariaRelevantRemovals))
+ liveRegionRelevant.append(ariaRelevantRemovals);
+ if (values.contains(ariaRelevantText))
+ liveRegionRelevant.append(ariaRelevantText);
+ }
+ computedProperties.liveRegionRelevant = liveRegionRelevant;
+ }
+
+ computedProperties.liveRegionStatus = axObject->liveRegionStatus();
+ }
+
+ computedProperties.pressed = axObject->pressedIsPresent() && axObject->isPressed();
+
+ if (axObject->isTextControl())
+ computedProperties.readonly = !axObject->canSetValueAttribute();
+
+ if (axObject->supportsRequiredAttribute())
+ computedProperties.required = axObject->isRequired();
+
+ computedProperties.role = axObject->computedRoleString();
+ computedProperties.selected = axObject->isSelected();
+
+ result = computedProperties;
+ }
+
+ return result;
+}
+
ExceptionOr<Optional<Vector<RefPtr<Node>>>> InspectorAuditAccessibilityObject::getControlledNodes(Node& node)
{
ERROR_IF_NO_ACTIVE_AUDIT();
Modified: trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.h (240308 => 240309)
--- trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.h 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.h 2019-01-23 00:32:59 UTC (rev 240309)
@@ -46,8 +46,34 @@
ExceptionOr<Vector<Ref<Node>>> getElementsByComputedRole(Document&, const String& role, Node* container);
+ struct ComputedProperties {
+ Optional<bool> busy;
+ String checked;
+ String currentState;
+ Optional<bool> disabled;
+ Optional<bool> expanded;
+ Optional<bool> focused;
+ Optional<int> headingLevel;
+ Optional<bool> hidden;
+ Optional<int> hierarchicalLevel;
+ Optional<bool> ignored;
+ Optional<bool> ignoredByDefault;
+ String invalidStatus;
+ Optional<bool> isPopUpButton;
+ String label;
+ Optional<bool> liveRegionAtomic;
+ Optional<Vector<String>> liveRegionRelevant;
+ String liveRegionStatus;
+ Optional<bool> pressed;
+ Optional<bool> readonly;
+ Optional<bool> required;
+ String role;
+ Optional<bool> selected;
+ };
+
ExceptionOr<RefPtr<Node>> getActiveDescendant(Node&);
ExceptionOr<Optional<Vector<RefPtr<Node>>>> getChildNodes(Node&);
+ ExceptionOr<Optional<ComputedProperties>> getComputedProperties(Node&);
ExceptionOr<Optional<Vector<RefPtr<Node>>>> getControlledNodes(Node&);
ExceptionOr<Optional<Vector<RefPtr<Node>>>> getFlowedNodes(Node&);
ExceptionOr<RefPtr<Node>> getMouseEventNode(Node&);
Modified: trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.idl (240308 => 240309)
--- trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.idl 2019-01-23 00:32:24 UTC (rev 240308)
+++ trunk/Source/WebCore/inspector/InspectorAuditAccessibilityObject.idl 2019-01-23 00:32:59 UTC (rev 240309)
@@ -32,6 +32,7 @@
[MayThrowException] Node? getActiveDescendant(Node node);
[MayThrowException] sequence<Node>? getChildNodes(Node node);
+ [MayThrowException] ComputedProperties? getComputedProperties(Node node);
[MayThrowException] sequence<Node>? getControlledNodes(Node node);
[MayThrowException] sequence<Node>? getFlowedNodes(Node node);
[MayThrowException] Node? getMouseEventNode(Node node);
@@ -39,3 +40,30 @@
[MayThrowException] Node? getParentNode(Node node);
[MayThrowException] sequence<Node>? getSelectedChildNodes(Node node);
};
+
+[
+ JSGenerateToJSObject,
+] dictionary ComputedProperties {
+ boolean? busy;
+ DOMString? checked;
+ DOMString? currentState;
+ boolean? disabled;
+ boolean? expanded;
+ boolean? focused;
+ long? headingLevel;
+ boolean? hidden;
+ long? hierarchicalLevel;
+ boolean? ignored;
+ boolean? ignoredByDefault;
+ DOMString? invalidStatus;
+ boolean? isPopUpButton;
+ DOMString? label;
+ boolean? liveRegionAtomic;
+ sequence<DOMString>? liveRegionRelevant;
+ DOMString? liveRegionStatus;
+ boolean? pressed;
+ boolean? readonly;
+ boolean? required;
+ DOMString? role;
+ boolean? selected;
+};
\ No newline at end of file