Diff
Modified: trunk/LayoutTests/ChangeLog (244560 => 244561)
--- trunk/LayoutTests/ChangeLog 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/LayoutTests/ChangeLog 2019-04-23 20:31:51 UTC (rev 244561)
@@ -1,3 +1,18 @@
+2019-04-23 Andres Gonzalez <[email protected]>
+
+ Accessibility text search and selection API enhancements.
+ https://bugs.webkit.org/show_bug.cgi?id=197095
+ <rdar://problem/48181791>
+
+ Reviewed by Chris Fleizach.
+
+ - Added new test for AccessibilitySearchTextWithCriteria API.
+ - Updated bounds-for-range expected file that includes a list of available APIs.
+
+ * accessibility/mac/bounds-for-range-expected.txt:
+ * accessibility/mac/search-text/search-text-expected.txt: Added.
+ * accessibility/mac/search-text/search-text.html: Added.
+
2019-04-23 Guy Lewin <[email protected]>
Multiple File Input Icon Set Regardless of File List
Modified: trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt (244560 => 244561)
--- trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt 2019-04-23 20:31:51 UTC (rev 244561)
@@ -65,6 +65,8 @@
AXStartTextMarkerForBounds
AXLineTextMarkerRangeForTextMarker
AXSelectTextWithCriteria
+AXSearchTextWithCriteria
+AXTextOperation
----------------------
{{-1.000000, -1.000000}, {60.000000, 18.000000}}
Added: trunk/LayoutTests/accessibility/mac/search-text/search-text-expected.txt (0 => 244561)
--- trunk/LayoutTests/accessibility/mac/search-text/search-text-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/mac/search-text/search-text-expected.txt 2019-04-23 20:31:51 UTC (rev 244561)
@@ -0,0 +1,36 @@
+The quick brown fox jumps over the lazy dog.
+
+TEXT2: The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.
+
+This tests the ability to search for text given a starting point and a direction for the search.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'lazy'
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'quick'
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'the'
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'The'
+PASS result.length is 3
+PASS body.stringForTextMarkerRange(result[i]) is 'dog'
+PASS body.stringForTextMarkerRange(result[i]) is 'dog'
+PASS body.stringForTextMarkerRange(result[i]) is 'dog'
+PASS result.length is 3
+PASS body.stringForTextMarkerRange(result[i]) is 'fox'
+PASS body.stringForTextMarkerRange(result[i]) is 'fox'
+PASS body.stringForTextMarkerRange(result[i]) is 'fox'
+PASS typeof result is 'undefined'
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'over'
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'fox'
+PASS result.length is 1
+PASS text.stringForTextMarkerRange(result[0]) is 'fox'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/accessibility/mac/search-text/search-text.html (0 => 244561)
--- trunk/LayoutTests/accessibility/mac/search-text/search-text.html (rev 0)
+++ trunk/LayoutTests/accessibility/mac/search-text/search-text.html 2019-04-23 20:31:51 UTC (rev 244561)
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<title>Search Text 1</title>
+</head>
+<body id="body">
+
+<p contenteditable="true" id="text">The quick brown fox <span id="target">jumps</span> over the lazy dog. </p>
+
+<p contenteditable="true" id="text2">TEXT2: The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog.</p>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+ description("This tests the ability to search for text given a starting point and a direction for the search.");
+
+ function selectElementText(element) {
+ var range = document.createRange();
+ range.selectNodeContents(element);
+
+ var selection = window.getSelection();
+ selection.removeAllRanges();
+ selection.addRange(range);
+ }
+
+ if (window.accessibilityController) {
+ var text = accessibilityController.accessibleElementById("text");
+ var result = 0;
+ var selection = 0;
+ var target = document.getElementById("target");
+
+ // Select target element.
+ selectElementText(target);
+
+ // Search for text after selection (single search string).
+ result = text.searchTextWithCriteria("lazy", "AXSearchTextStartFromSelection", "AXSearchTextDirectionForward");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'lazy'");
+
+ // Search for text before selection (single search string).
+ result = text.searchTextWithCriteria("quick", "AXSearchTextStartFromSelection", "AXSearchTextDirectionBackward");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'quick'");
+
+ // Search for text closest to selection (single search string).
+ result = text.searchTextWithCriteria("the", "AXSearchTextStartFromSelection", "AXSearchTextDirectionClosest");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'the'");
+
+ // Search from the beginning (single search string).
+ result = text.searchTextWithCriteria("the", "AXSearchTextStartFromBegin", "AXSearchTextDirectionClosest");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'The'");
+
+ // Search for all occurrences from the beginning of document (single search string).
+ var body = accessibilityController.rootElement.childAtIndex(0);
+ result = body.searchTextWithCriteria("dog", "AXSearchTextStartFromBegin", "AXSearchTextDirectionAll");
+ shouldBe("result.length", "3");
+ for (var i = 0; i < result.length; i++)
+ shouldBe("body.stringForTextMarkerRange(result[i])", "'dog'");
+
+ // Search for all occurrences from the end of document (single search string).
+ result = body.searchTextWithCriteria("fox", "AXSearchTextStartFromEnd", "AXSearchTextDirectionAll");
+ shouldBe("result.length", "3");
+ for (var i = 0; i < result.length; i++)
+ shouldBe("body.stringForTextMarkerRange(result[i])", "'fox'");
+
+ // Search for a non-present string (single search string).
+ result = body.searchTextWithCriteria("cat", "AXSearchTextStartFromBegin", "AXSearchTextDirectionAll");
+ shouldBe("typeof result", "'undefined'");
+
+ // Search for multiple strings after selection.
+ result = text.searchTextWithCriteria(["lazy", "over"], "AXSearchTextStartFromSelection", "AXSearchTextDirectionForward");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'over'");
+
+ // Search for multiple strings before selection.
+ result = text.searchTextWithCriteria(["quick", "fox"], "AXSearchTextStartFromSelection", "AXSearchTextDirectionBackward");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'fox'");
+
+ // Search for multiple strings closest to selection.
+ result = text.searchTextWithCriteria(["dog", "fox"], "AXSearchTextStartFromSelection", "AXSearchTextDirectionClosest");
+ shouldBe("result.length", "1");
+ shouldBe("text.stringForTextMarkerRange(result[0])", "'fox'");
+ }
+</script>
+
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (244560 => 244561)
--- trunk/Source/WebCore/ChangeLog 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Source/WebCore/ChangeLog 2019-04-23 20:31:51 UTC (rev 244561)
@@ -1,3 +1,40 @@
+2019-04-23 Andres Gonzalez <[email protected]>
+
+ Accessibility text search and selection API enhancements.
+ https://bugs.webkit.org/show_bug.cgi?id=197095
+ <rdar://problem/48181791>
+
+ Reviewed by Chris Fleizach.
+
+ - Split the existing SelectTextWithCriteria API into two: search text API (SearchTextWithCriteria) and a text operation API (TextOperation: select, replace, capitalize...).
+ - This allows for more flexibility and extensibility.
+ - Added the ability to retrieve text markers for multiple search hits.
+ - Various code clean up and consolidation.
+ - Added LayoutTest for search API.
+ - Previous API is marked with "To be deprecated", and is implemented with new implementation. May be removed in a future change.
+
+ Test: accessibility/mac/search-text/search-text.html
+
+ * accessibility/AccessibilityObject.cpp:
+ (WebCore::rangeClosestToRange):
+ (WebCore::AccessibilityObject::rangeOfStringClosestToRangeInDirection const):
+ (WebCore::AccessibilityObject::findTextRange const):
+ (WebCore::AccessibilityObject::findTextRanges const):
+ (WebCore::AccessibilityObject::performTextOperation):
+ (WebCore::AccessibilityObject::frame const):
+ (WebCore::AccessibilityObject::selectText): Deleted.
+ * accessibility/AccessibilityObject.h:
+ (WebCore::AccessibilitySearchTextCriteria::AccessibilitySearchTextCriteria):
+ (WebCore::AccessibilityTextOperation::AccessibilityTextOperation):
+ (WebCore::AccessibilitySelectTextCriteria::AccessibilitySelectTextCriteria): Deleted.
+ * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+ (accessibilityTextCriteriaForParameterizedAttribute):
+ (accessibilitySearchTextCriteriaForParameterizedAttribute):
+ (accessibilityTextOperationForParameterizedAttribute):
+ (-[WebAccessibilityObjectWrapper IGNORE_WARNINGS_END]):
+ (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+ (accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute): Deleted.
+
2019-04-23 Guy Lewin <[email protected]>
Multiple File Input Icon Set Regardless of File List
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (244560 => 244561)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp 2019-04-23 20:31:51 UTC (rev 244561)
@@ -757,21 +757,21 @@
// Returns the range that is fewer positions away from the reference range.
// NOTE: The after range is expected to ACTUALLY be after the reference range and the before
// range is expected to ACTUALLY be before. These are not checked for performance reasons.
-static RefPtr<Range> rangeClosestToRange(Range* referenceRange, RefPtr<Range>&& afterRange, RefPtr<Range>&& beforeRange)
+static RefPtr<Range> rangeClosestToRange(RefPtr<Range> const& referenceRange, RefPtr<Range>&& afterRange, RefPtr<Range>&& beforeRange)
{
if (!referenceRange)
return nullptr;
-
+
// The treeScope for shadow nodes may not be the same scope as another element in a document.
// Comparisons may fail in that case, which are expected behavior and should not assert.
if (afterRange && (referenceRange->endPosition().isNull() || ((afterRange->startPosition().anchorNode()->compareDocumentPosition(*referenceRange->endPosition().anchorNode()) & Node::DOCUMENT_POSITION_DISCONNECTED) == Node::DOCUMENT_POSITION_DISCONNECTED)))
return nullptr;
- ASSERT(!afterRange || afterRange->startPosition() >= referenceRange->endPosition());
-
+ ASSERT(!afterRange || afterRange->compareBoundaryPoints(Range::START_TO_START, *referenceRange).releaseReturnValue() >= 0);
+
if (beforeRange && (referenceRange->startPosition().isNull() || ((beforeRange->endPosition().anchorNode()->compareDocumentPosition(*referenceRange->startPosition().anchorNode()) & Node::DOCUMENT_POSITION_DISCONNECTED) == Node::DOCUMENT_POSITION_DISCONNECTED)))
return nullptr;
- ASSERT(!beforeRange || beforeRange->endPosition() <= referenceRange->startPosition());
-
+ ASSERT(!beforeRange || beforeRange->compareBoundaryPoints(Range::START_TO_START, *referenceRange).releaseReturnValue() <= 0);
+
if (!afterRange && !beforeRange)
return nullptr;
if (afterRange && !beforeRange)
@@ -785,7 +785,7 @@
return positionsToAfterRange < positionsToBeforeRange ? afterRange : beforeRange;
}
-RefPtr<Range> AccessibilityObject::rangeOfStringClosestToRangeInDirection(Range* referenceRange, AccessibilitySearchDirection searchDirection, Vector<String>& searchStrings) const
+RefPtr<Range> AccessibilityObject::rangeOfStringClosestToRangeInDirection(Range* referenceRange, AccessibilitySearchDirection searchDirection, Vector<String> const& searchStrings) const
{
Frame* frame = this->frame();
if (!frame)
@@ -797,7 +797,7 @@
bool isBackwardSearch = searchDirection == AccessibilitySearchDirection::Previous;
FindOptions findOptions { AtWordStarts, AtWordEnds, CaseInsensitive, StartInSelection };
if (isBackwardSearch)
- findOptions.add(Backwards);
+ findOptions.add(FindOptionFlag::Backwards);
RefPtr<Range> closestStringRange = nullptr;
for (const auto& searchString : searchStrings) {
@@ -843,87 +843,137 @@
return AXObjectCache::rangeForNodeContents(node());
}
-String AccessibilityObject::selectText(AccessibilitySelectTextCriteria* criteria)
+RefPtr<Range> AccessibilityObject::findTextRange(Vector<String> const& searchStrings, RefPtr<Range> const& start, AccessibilitySearchTextDirection direction) const
{
- ASSERT(criteria);
-
- if (!criteria)
- return String();
-
- Frame* frame = this->frame();
- if (!frame)
- return String();
-
- AccessibilitySelectTextActivity& activity = criteria->activity;
- AccessibilitySelectTextAmbiguityResolution& ambiguityResolution = criteria->ambiguityResolution;
- String& replacementString = criteria->replacementString;
- Vector<String>& searchStrings = criteria->searchStrings;
-
- RefPtr<Range> selectedStringRange = selectionRange();
- // When starting our search again, make this a zero length range so that search forwards will find this selected range if its appropriate.
- selectedStringRange->setEnd(selectedStringRange->startContainer(), selectedStringRange->startOffset());
-
- RefPtr<Range> closestAfterStringRange = nullptr;
- RefPtr<Range> closestBeforeStringRange = nullptr;
- // Search forward if necessary.
- if (ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestAfter || ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestTo)
- closestAfterStringRange = rangeOfStringClosestToRangeInDirection(selectedStringRange.get(), AccessibilitySearchDirection::Next, searchStrings);
- // Search backward if necessary.
- if (ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestBefore || ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestTo)
- closestBeforeStringRange = rangeOfStringClosestToRangeInDirection(selectedStringRange.get(), AccessibilitySearchDirection::Previous, searchStrings);
-
- // Determine which candidate is closest to the selection and perform the activity.
- if (RefPtr<Range> closestStringRange = rangeClosestToRange(selectedStringRange.get(), WTFMove(closestAfterStringRange), WTFMove(closestBeforeStringRange))) {
+ RefPtr<Range> found;
+ if (direction == AccessibilitySearchTextDirection::Forward)
+ found = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Next, searchStrings);
+ else if (direction == AccessibilitySearchTextDirection::Backward)
+ found = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Previous, searchStrings);
+ else if (direction == AccessibilitySearchTextDirection::Closest) {
+ auto foundAfter = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Next, searchStrings);
+ auto foundBefore = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Previous, searchStrings);
+ found = rangeClosestToRange(start.get(), WTFMove(foundAfter), WTFMove(foundBefore));
+ }
+
+ if (found) {
// If the search started within a text control, ensure that the result is inside that element.
if (element() && element()->isTextField()) {
- if (!closestStringRange->startContainer().isDescendantOrShadowDescendantOf(element()) || !closestStringRange->endContainer().isDescendantOrShadowDescendantOf(element()))
- return String();
+ if (!found->startContainer().isDescendantOrShadowDescendantOf(element())
+ || !found->endContainer().isDescendantOrShadowDescendantOf(element()))
+ return nullptr;
}
-
- String closestString = closestStringRange->text();
+ }
+ return found;
+}
+
+Vector<RefPtr<Range>> AccessibilityObject::findTextRanges(AccessibilitySearchTextCriteria const& criteria) const
+{
+ Vector<RefPtr<Range>> result;
+
+ // Determine start range.
+ RefPtr<Range> startRange;
+ if (criteria.start == AccessibilitySearchTextStartFrom::Selection)
+ startRange = selectionRange();
+ else
+ startRange = elementRange();
+
+ if (startRange) {
+ // Collapse the range to the start unless searching from the end of the doc or searching backwards.
+ if (criteria.start == AccessibilitySearchTextStartFrom::Begin)
+ startRange->collapse(true);
+ else if (criteria.start == AccessibilitySearchTextStartFrom::End)
+ startRange->collapse(false);
+ else
+ startRange->collapse(criteria.direction != AccessibilitySearchTextDirection::Backward);
+ } else
+ return result;
+
+ RefPtr<Range> found;
+ switch (criteria.direction) {
+ case AccessibilitySearchTextDirection::Forward:
+ case AccessibilitySearchTextDirection::Backward:
+ case AccessibilitySearchTextDirection::Closest:
+ found = findTextRange(criteria.searchStrings, startRange, criteria.direction);
+ if (found)
+ result.append(found);
+ break;
+ case AccessibilitySearchTextDirection::All: {
+ auto findAll = [&](AccessibilitySearchTextDirection dir) {
+ found = findTextRange(criteria.searchStrings, startRange, dir);
+ while (found) {
+ result.append(found);
+ found = findTextRange(criteria.searchStrings, found, dir);
+ }
+ };
+ findAll(AccessibilitySearchTextDirection::Forward);
+ findAll(AccessibilitySearchTextDirection::Backward);
+ break;
+ }
+ }
+
+ return result;
+}
+
+Vector<String> AccessibilityObject::performTextOperation(AccessibilityTextOperation const& operation)
+{
+ Vector<String> result;
+
+ if (operation.textRanges.isEmpty())
+ return result;
+
+ Frame* frame = this->frame();
+ if (!frame)
+ return result;
+
+ for (auto textRange : operation.textRanges) {
+ if (!frame->selection().setSelectedRange(textRange.get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes))
+ continue;
+
+ String text = textRange->text();
+ String replacementString = operation.replacementText;
bool replaceSelection = false;
- if (frame->selection().setSelectedRange(closestStringRange.get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes)) {
- switch (activity) {
- case AccessibilitySelectTextActivity::FindAndCapitalize:
- replacementString = capitalize(closestString, ' '); // FIXME: Needs to take locale into account to work correctly.
- replaceSelection = true;
- break;
- case AccessibilitySelectTextActivity::FindAndUppercase:
- replacementString = closestString.convertToUppercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
- replaceSelection = true;
- break;
- case AccessibilitySelectTextActivity::FindAndLowercase:
- replacementString = closestString.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
- replaceSelection = true;
- break;
- case AccessibilitySelectTextActivity::FindAndReplace: {
- replaceSelection = true;
- // When applying find and replace activities, we want to match the capitalization of the replaced text,
- // (unless we're replacing with an abbreviation.)
- if (closestString.length() > 0 && replacementString.length() > 2 && replacementString != replacementString.convertToUppercaseWithoutLocale()) {
- if (closestString[0] == u_toupper(closestString[0]))
- replacementString = capitalize(replacementString, ' '); // FIXME: Needs to take locale into account to work correctly.
- else
- replacementString = replacementString.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
- }
- break;
+ switch (operation.type) {
+ case AccessibilityTextOperationType::Capitalize:
+ replacementString = capitalize(text, ' '); // FIXME: Needs to take locale into account to work correctly.
+ replaceSelection = true;
+ break;
+ case AccessibilityTextOperationType::Uppercase:
+ replacementString = text.convertToUppercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
+ replaceSelection = true;
+ break;
+ case AccessibilityTextOperationType::Lowercase:
+ replacementString = text.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
+ replaceSelection = true;
+ break;
+ case AccessibilityTextOperationType::Replace: {
+ replaceSelection = true;
+ // When applying find and replace activities, we want to match the capitalization of the replaced text,
+ // (unless we're replacing with an abbreviation.)
+ if (text.length() > 0
+ && replacementString.length() > 2
+ && replacementString != replacementString.convertToUppercaseWithoutLocale()) {
+ if (text[0] == u_toupper(text[0]))
+ replacementString = capitalize(replacementString, ' '); // FIXME: Needs to take locale into account to work correctly.
+ else
+ replacementString = replacementString.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
}
- case AccessibilitySelectTextActivity::FindAndSelect:
- break;
- }
-
- // A bit obvious, but worth noting the API contract for this method is that we should
- // return the replacement string when replacing, but the selected string if not.
- if (replaceSelection) {
- frame->editor().replaceSelectionWithText(replacementString, Editor::SelectReplacement::Yes, Editor::SmartReplace::Yes);
- return replacementString;
- }
-
- return closestString;
+ break;
}
+ case AccessibilityTextOperationType::Select:
+ break;
+ }
+
+ // A bit obvious, but worth noting the API contract for this method is that we should
+ // return the replacement string when replacing, but the selected string if not.
+ if (replaceSelection) {
+ frame->editor().replaceSelectionWithText(replacementString, Editor::SelectReplacement::Yes, Editor::SmartReplace::Yes);
+ result.append(replacementString);
+ } else
+ result.append(text);
}
-
- return String();
+
+ return result;
}
bool AccessibilityObject::hasAttributesRequiredForInclusion() const
@@ -1076,10 +1126,7 @@
Frame* AccessibilityObject::frame() const
{
Node* node = this->node();
- if (!node)
- return nullptr;
-
- return node->document().frame();
+ return node ? node->document().frame() : nullptr;
}
Frame* AccessibilityObject::mainFrame() const
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (244560 => 244561)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.h 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h 2019-04-23 20:31:51 UTC (rev 244561)
@@ -305,33 +305,48 @@
bool isNull() const { return !start && !length; }
};
-enum class AccessibilitySelectTextActivity {
- FindAndReplace,
- FindAndSelect,
- FindAndCapitalize,
- FindAndLowercase,
- FindAndUppercase
+enum class AccessibilitySearchTextStartFrom {
+ Begin, // Search from the beginning of the element.
+ Selection, // Search from the position of the current selection.
+ End // Search from the end of the element.
};
-enum class AccessibilitySelectTextAmbiguityResolution {
- ClosestAfter,
- ClosestBefore,
- ClosestTo
+enum class AccessibilitySearchTextDirection {
+ Forward, // Occurrence after the starting range.
+ Backward, // Occurrence before the starting range.
+ Closest, // Closest occurrence to the starting range, whether after or before.
+ All // All occurrences
};
-struct AccessibilitySelectTextCriteria {
- AccessibilitySelectTextActivity activity;
- AccessibilitySelectTextAmbiguityResolution ambiguityResolution;
- String replacementString;
- Vector<String> searchStrings;
-
- AccessibilitySelectTextCriteria(AccessibilitySelectTextActivity activity, AccessibilitySelectTextAmbiguityResolution ambiguityResolution, const String& replacementString)
- : activity(activity)
- , ambiguityResolution(ambiguityResolution)
- , replacementString(replacementString)
+struct AccessibilitySearchTextCriteria {
+ Vector<String> searchStrings; // Text strings to search for.
+ AccessibilitySearchTextStartFrom start;
+ AccessibilitySearchTextDirection direction;
+
+ AccessibilitySearchTextCriteria()
+ : start(AccessibilitySearchTextStartFrom::Selection)
+ , direction(AccessibilitySearchTextDirection::Forward)
{ }
};
+enum class AccessibilityTextOperationType {
+ Select,
+ Replace,
+ Capitalize,
+ Lowercase,
+ Uppercase
+};
+
+struct AccessibilityTextOperation {
+ Vector<RefPtr<Range>> textRanges; // text on which perform the operation.
+ AccessibilityTextOperationType type;
+ String replacementText; // For type = replace.
+
+ AccessibilityTextOperation()
+ : type(AccessibilityTextOperationType::Select)
+ { }
+};
+
enum class AccessibilityMathScriptObjectType { Subscript, Superscript };
enum class AccessibilityMathMultiscriptObjectType { PreSubscript, PreSuperscript, PostSubscript, PostSuperscript };
@@ -607,12 +622,16 @@
virtual bool isDescendantOfBarrenParent() const { return false; }
bool isDescendantOfRole(AccessibilityRole) const;
-
+
// Text selection
- RefPtr<Range> rangeOfStringClosestToRangeInDirection(Range*, AccessibilitySearchDirection, Vector<String>&) const;
+private:
+ RefPtr<Range> rangeOfStringClosestToRangeInDirection(Range*, AccessibilitySearchDirection, Vector<String> const&) const;
RefPtr<Range> selectionRange() const;
- String selectText(AccessibilitySelectTextCriteria*);
-
+ RefPtr<Range> findTextRange(Vector<String> const& searchStrings, RefPtr<Range> const& start, AccessibilitySearchTextDirection) const;
+public:
+ Vector<RefPtr<Range>> findTextRanges(AccessibilitySearchTextCriteria const&) const;
+ Vector<String> performTextOperation(AccessibilityTextOperation const&);
+
virtual AccessibilityObject* observableObject() const { return nullptr; }
virtual void linkedUIElements(AccessibilityChildrenVector&) const { }
virtual AccessibilityObject* titleUIElement() const { return nullptr; }
Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (244560 => 244561)
--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm 2019-04-23 20:31:51 UTC (rev 244561)
@@ -372,6 +372,112 @@
#define NSAccessibilitySelectTextWithCriteriaParameterizedAttribute @"AXSelectTextWithCriteria"
#endif
+// Text search
+
+#ifndef NSAccessibilitySearchTextWithCriteriaParameterizedAttribute
+/* Performs a text search with the given parameters.
+ Returns an NSArray of text marker ranges of the search hits.
+ */
+#define NSAccessibilitySearchTextWithCriteriaParameterizedAttribute @"AXSearchTextWithCriteria"
+#endif
+
+#ifndef NSAccessibilitySearchTextSearchStrings
+// NSArray of strings to search for.
+#define NSAccessibilitySearchTextSearchStrings @"AXSearchTextSearchStrings"
+#endif
+
+#ifndef NSAccessibilitySearchTextStartFrom
+// NSString specifying the start point of the search: selection, begin or end.
+#define NSAccessibilitySearchTextStartFrom @"AXSearchTextStartFrom"
+#endif
+
+#ifndef NSAccessibilitySearchTextStartFromBegin
+// Value for SearchTextStartFrom.
+#define NSAccessibilitySearchTextStartFromBegin @"AXSearchTextStartFromBegin"
+#endif
+
+#ifndef NSAccessibilitySearchTextStartFromSelection
+// Value for SearchTextStartFrom.
+#define NSAccessibilitySearchTextStartFromSelection @"AXSearchTextStartFromSelection"
+#endif
+
+#ifndef NSAccessibilitySearchTextStartFromEnd
+// Value for SearchTextStartFrom.
+#define NSAccessibilitySearchTextStartFromEnd @"AXSearchTextStartFromEnd"
+#endif
+
+#ifndef NSAccessibilitySearchTextDirection
+// NSString specifying the direction of the search: forward, backward, closest, all.
+#define NSAccessibilitySearchTextDirection @"AXSearchTextDirection"
+#endif
+
+#ifndef NSAccessibilitySearchTextDirectionForward
+// Value for SearchTextDirection.
+#define NSAccessibilitySearchTextDirectionForward @"AXSearchTextDirectionForward"
+#endif
+
+#ifndef NSAccessibilitySearchTextDirectionBackward
+// Value for SearchTextDirection.
+#define NSAccessibilitySearchTextDirectionBackward @"AXSearchTextDirectionBackward"
+#endif
+
+#ifndef NSAccessibilitySearchTextDirectionClosest
+// Value for SearchTextDirection.
+#define NSAccessibilitySearchTextDirectionClosest @"AXSearchTextDirectionClosest"
+#endif
+
+#ifndef NSAccessibilitySearchTextDirectionAll
+// Value for SearchTextDirection.
+#define NSAccessibilitySearchTextDirectionAll @"AXSearchTextDirectionAll"
+#endif
+
+// Text operations
+
+#ifndef NSAccessibilityTextOperationParameterizedAttribute
+// Performs an operation on the given text.
+#define NSAccessibilityTextOperationParameterizedAttribute @"AXTextOperation"
+#endif
+
+#ifndef NSAccessibilityTextOperationMarkerRanges
+// Text on which to perform operation.
+#define NSAccessibilityTextOperationMarkerRanges @"AXTextOperationMarkerRanges"
+#endif
+
+#ifndef NSAccessibilityTextOperationType
+// The type of operation to be performed: select, replace, capitalize....
+#define NSAccessibilityTextOperationType @"AXTextOperationType"
+#endif
+
+#ifndef NSAccessibilityTextOperationSelect
+// Value for TextOperationType.
+#define NSAccessibilityTextOperationSelect @"TextOperationSelect"
+#endif
+
+#ifndef NSAccessibilityTextOperationReplace
+// Value for TextOperationType.
+#define NSAccessibilityTextOperationReplace @"TextOperationReplace"
+#endif
+
+#ifndef NSAccessibilityTextOperationCapitalize
+// Value for TextOperationType.
+#define NSAccessibilityTextOperationCapitalize @"Capitalize"
+#endif
+
+#ifndef NSAccessibilityTextOperationLowercase
+// Value for TextOperationType.
+#define NSAccessibilityTextOperationLowercase @"Lowercase"
+#endif
+
+#ifndef NSAccessibilityTextOperationUppercase
+// Value for TextOperationType.
+#define NSAccessibilityTextOperationUppercase @"Uppercase"
+#endif
+
+#ifndef NSAccessibilityTextOperationReplacementString
+// Replacement text for operation replace.
+#define NSAccessibilityTextOperationReplacementString @"AXTextOperationReplacementString"
+#endif
+
// Math attributes
#define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
#define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
@@ -504,39 +610,39 @@
#pragma mark Select text helpers
-static AccessibilitySelectTextCriteria accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(const NSDictionary *parameterizedAttribute)
+// To be deprecated.
+static std::pair<AccessibilitySearchTextCriteria, AccessibilityTextOperation> accessibilityTextCriteriaForParameterizedAttribute(const NSDictionary *parameterizedAttribute)
{
+ AccessibilitySearchTextCriteria criteria;
+ AccessibilityTextOperation operation;
+
NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
-
- AccessibilitySelectTextActivity activity = AccessibilitySelectTextActivity::FindAndSelect;
+
if ([activityParameter isKindOfClass:[NSString class]]) {
if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
- activity = AccessibilitySelectTextActivity::FindAndReplace;
+ operation.type = AccessibilityTextOperationType::Replace;
else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
- activity = AccessibilitySelectTextActivity::FindAndCapitalize;
+ operation.type = AccessibilityTextOperationType::Capitalize;
else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
- activity = AccessibilitySelectTextActivity::FindAndLowercase;
+ operation.type = AccessibilityTextOperationType::Lowercase;
else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
- activity = AccessibilitySelectTextActivity::FindAndUppercase;
+ operation.type = AccessibilityTextOperationType::Uppercase;
}
-
- AccessibilitySelectTextAmbiguityResolution ambiguityResolution = AccessibilitySelectTextAmbiguityResolution::ClosestTo;
+
+ criteria.direction = AccessibilitySearchTextDirection::Closest;
if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
- ambiguityResolution = AccessibilitySelectTextAmbiguityResolution::ClosestAfter;
+ criteria.direction = AccessibilitySearchTextDirection::Forward;
else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
- ambiguityResolution = AccessibilitySelectTextAmbiguityResolution::ClosestBefore;
+ criteria.direction = AccessibilitySearchTextDirection::Backward;
}
-
- String replacementString;
+
if ([replacementStringParameter isKindOfClass:[NSString class]])
- replacementString = replacementStringParameter;
-
- AccessibilitySelectTextCriteria criteria(activity, ambiguityResolution, replacementString);
-
+ operation.replacementText = replacementStringParameter;
+
if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
@@ -545,10 +651,78 @@
criteria.searchStrings.uncheckedAppend(searchString);
}
}
-
+
+ return std::make_pair(criteria, operation);
+}
+
+static AccessibilitySearchTextCriteria accessibilitySearchTextCriteriaForParameterizedAttribute(const NSDictionary *params)
+{
+ AccessibilitySearchTextCriteria criteria;
+
+ NSArray *searchStrings = [params objectForKey:NSAccessibilitySearchTextSearchStrings];
+ NSString *start = [params objectForKey:NSAccessibilitySearchTextStartFrom];
+ NSString *direction = [params objectForKey:NSAccessibilitySearchTextDirection];
+
+ if ([searchStrings isKindOfClass:[NSArray class]]) {
+ size_t searchStringsCount = static_cast<size_t>([searchStrings count]);
+ criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
+ for (NSString *searchString in searchStrings) {
+ if ([searchString isKindOfClass:[NSString class]])
+ criteria.searchStrings.uncheckedAppend(searchString);
+ }
+ }
+
+ if ([start isKindOfClass:[NSString class]]) {
+ if ([start isEqualToString:NSAccessibilitySearchTextStartFromBegin])
+ criteria.start = AccessibilitySearchTextStartFrom::Begin;
+ else if ([start isEqualToString:NSAccessibilitySearchTextStartFromEnd])
+ criteria.start = AccessibilitySearchTextStartFrom::End;
+ }
+
+ if ([direction isKindOfClass:[NSString class]]) {
+ if ([direction isEqualToString:NSAccessibilitySearchTextDirectionBackward])
+ criteria.direction = AccessibilitySearchTextDirection::Backward;
+ else if ([direction isEqualToString:NSAccessibilitySearchTextDirectionClosest])
+ criteria.direction = AccessibilitySearchTextDirection::Closest;
+ else if ([direction isEqualToString:NSAccessibilitySearchTextDirectionAll])
+ criteria.direction = AccessibilitySearchTextDirection::All;
+ }
+
return criteria;
}
+static AccessibilityTextOperation accessibilityTextOperationForParameterizedAttribute(WebAccessibilityObjectWrapper *obj, const NSDictionary *parameterizedAttribute)
+{
+ AccessibilityTextOperation operation;
+
+ NSArray *markerRanges = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationMarkerRanges];
+ NSString *operationType = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationType];
+ NSString *replacementString = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationReplacementString];
+
+ if ([markerRanges isKindOfClass:[NSArray class]]) {
+ size_t count = static_cast<size_t>(markerRanges.count);
+ operation.textRanges.reserveInitialCapacity(count);
+ for (id markerRange : markerRanges)
+ operation.textRanges.append([obj rangeForTextMarkerRange:markerRange]);
+ }
+
+ if ([operationType isKindOfClass:[NSString class]]) {
+ if ([operationType isEqualToString:NSAccessibilityTextOperationReplace])
+ operation.type = AccessibilityTextOperationType::Replace;
+ else if ([operationType isEqualToString:NSAccessibilityTextOperationCapitalize])
+ operation.type = AccessibilityTextOperationType::Capitalize;
+ else if ([operationType isEqualToString:NSAccessibilityTextOperationLowercase])
+ operation.type = AccessibilityTextOperationType::Lowercase;
+ else if ([operationType isEqualToString:NSAccessibilityTextOperationUppercase])
+ operation.type = AccessibilityTextOperationType::Uppercase;
+ }
+
+ if ([replacementString isKindOfClass:[NSString class]])
+ operation.replacementText = replacementString;
+
+ return operation;
+}
+
#pragma mark Text Marker helpers
static BOOL getBytesFromAXTextMarker(CFTypeRef textMarker, void* bytes, size_t length)
@@ -3439,6 +3613,8 @@
NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
NSAccessibilitySelectTextWithCriteriaParameterizedAttribute,
+ NSAccessibilitySearchTextWithCriteriaParameterizedAttribute,
+ NSAccessibilityTextOperationParameterizedAttribute,
nil];
}
@@ -3990,10 +4166,41 @@
// dispatch
if ([attribute isEqualToString:NSAccessibilitySelectTextWithCriteriaParameterizedAttribute]) {
- AccessibilitySelectTextCriteria criteria = accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(dictionary);
- return m_object->selectText(&criteria);
+ // To be deprecated.
+ auto criteria = accessibilityTextCriteriaForParameterizedAttribute(dictionary);
+ criteria.second.textRanges = m_object->findTextRanges(criteria.first);
+ ASSERT(criteria.second.textRanges.size() <= 1);
+ Vector<String> result = m_object->performTextOperation(criteria.second);
+ ASSERT(result.size() <= 1);
+ if (result.size() > 0)
+ return result[0];
+ return String();
}
-
+
+ if ([attribute isEqualToString:NSAccessibilitySearchTextWithCriteriaParameterizedAttribute]) {
+ auto criteria = accessibilitySearchTextCriteriaForParameterizedAttribute(dictionary);
+ auto ranges = m_object->findTextRanges(criteria);
+ if (ranges.isEmpty())
+ return nil;
+ NSMutableArray *markers = [NSMutableArray arrayWithCapacity:ranges.size()];
+ for (auto range : ranges) {
+ if (id marker = [self textMarkerRangeFromRange:range])
+ [markers addObject:marker];
+ }
+ return markers;
+ }
+
+ if ([attribute isEqualToString:NSAccessibilityTextOperationParameterizedAttribute]) {
+ auto textOperation = accessibilityTextOperationForParameterizedAttribute(self, dictionary);
+ auto operationResult = m_object->performTextOperation(textOperation);
+ if (operationResult.isEmpty())
+ return nil;
+ NSMutableArray *result = [NSMutableArray arrayWithCapacity:operationResult.size()];
+ for (auto str : operationResult)
+ [result addObject:str];
+ return result;
+ }
+
if ([attribute isEqualToString:NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute]) {
AccessibilitySearchCriteria criteria = accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(dictionary);
AccessibilityObject::AccessibilityChildrenVector results;
Modified: trunk/Tools/ChangeLog (244560 => 244561)
--- trunk/Tools/ChangeLog 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/ChangeLog 2019-04-23 20:31:51 UTC (rev 244561)
@@ -1,3 +1,57 @@
+2019-04-23 Andres Gonzalez <[email protected]>
+
+ Accessibility text search and selection API enhancements.
+ https://bugs.webkit.org/show_bug.cgi?id=197095
+ <rdar://problem/48181791>
+
+ Reviewed by Chris Fleizach.
+
+ Added new API JS binding code for searchTextWithCriteria to both WTR and DRT.
+
+ * DumpRenderTree/AccessibilityTextMarker.h:
+ * DumpRenderTree/AccessibilityUIElement.cpp:
+ (searchTextWithCriteriaCallback):
+ (AccessibilityUIElement::getJSClass):
+ * DumpRenderTree/AccessibilityUIElement.h:
+ * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
+ (convertVectorToObjectArray):
+ (convertNSArrayToVector):
+ (searchTextParameterizedAttributeForCriteria):
+ (AccessibilityUIElement::getLinkedUIElements):
+ (AccessibilityUIElement::getDocumentLinks):
+ (AccessibilityUIElement::getChildren):
+ (AccessibilityUIElement::getChildrenWithRange):
+ (AccessibilityUIElement::rowHeaders const):
+ (AccessibilityUIElement::columnHeaders const):
+ (AccessibilityUIElement::uiElementArrayAttributeValue const):
+ (AccessibilityUIElement::searchTextWithCriteria):
+ (AccessibilityUIElement::attributesOfColumnHeaders):
+ (AccessibilityUIElement::attributesOfRowHeaders):
+ (AccessibilityUIElement::attributesOfColumns):
+ (AccessibilityUIElement::attributesOfRows):
+ (AccessibilityUIElement::attributesOfVisibleCells):
+ * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+ * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+ * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+ (WTR::convertVectorToObjectArray):
+ (WTR::convertNSArrayToVector):
+ (WTR::searchTextParameterizedAttributeForCriteria):
+ (WTR::AccessibilityUIElement::getLinkedUIElements):
+ (WTR::AccessibilityUIElement::getDocumentLinks):
+ (WTR::AccessibilityUIElement::getUIElementsWithAttribute const):
+ (WTR::AccessibilityUIElement::getChildren):
+ (WTR::AccessibilityUIElement::getChildrenWithRange):
+ (WTR::AccessibilityUIElement::rowHeaders const):
+ (WTR::AccessibilityUIElement::columnHeaders const):
+ (WTR::AccessibilityUIElement::uiElementArrayAttributeValue const):
+ (WTR::AccessibilityUIElement::searchTextWithCriteria):
+ (WTR::AccessibilityUIElement::attributesOfColumnHeaders):
+ (WTR::AccessibilityUIElement::attributesOfRowHeaders):
+ (WTR::AccessibilityUIElement::attributesOfColumns):
+ (WTR::AccessibilityUIElement::attributesOfRows):
+ (WTR::AccessibilityUIElement::attributesOfVisibleCells):
+ (WTR::convertElementsToObjectArray): Deleted.
+
2019-04-23 Guy Lewin <[email protected]>
Multiple File Input Icon Set Regardless of File List
Modified: trunk/Tools/DumpRenderTree/AccessibilityTextMarker.h (244560 => 244561)
--- trunk/Tools/DumpRenderTree/AccessibilityTextMarker.h 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/DumpRenderTree/AccessibilityTextMarker.h 2019-04-23 20:31:51 UTC (rev 244561)
@@ -75,9 +75,10 @@
static JSObjectRef makeJSAccessibilityTextMarkerRange(JSContextRef, const AccessibilityTextMarkerRange&);
bool isEqual(AccessibilityTextMarkerRange*);
-
+
+ static JSClassRef getJSClass();
+
private:
- static JSClassRef getJSClass();
#if SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC)
RetainPtr<PlatformTextMarkerRange> m_textMarkerRange;
#else
Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp (244560 => 244561)
--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp 2019-04-23 20:31:51 UTC (rev 244561)
@@ -279,6 +279,24 @@
return JSValueMakeString(context, result.get());
}
+#if PLATFORM(MAC)
+static JSValueRef searchTextWithCriteriaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+ if (argumentCount < 1)
+ return JSValueMakeUndefined(context);
+
+ JSValueRef searchStrings = arguments[0];
+ JSRetainPtr<JSStringRef> startFrom;
+ if (argumentCount > 1)
+ startFrom = adopt(JSValueToStringCopy(context, arguments[1], exception));
+ JSRetainPtr<JSStringRef> direction;
+ if (argumentCount > 2)
+ direction = adopt(JSValueToStringCopy(context, arguments[2], exception));
+
+ return toAXElement(thisObject)->searchTextWithCriteria(context, searchStrings, startFrom.get(), direction.get());
+}
+#endif
+
static JSValueRef indexOfChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
{
if (argumentCount != 1)
@@ -1896,6 +1914,9 @@
{ "uiElementCountForSearchPredicate", uiElementCountForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "uiElementForSearchPredicate", uiElementForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "selectTextWithCriteria", selectTextWithCriteriaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+#if PLATFORM(MAC)
+ { "searchTextWithCriteria", searchTextWithCriteriaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+#endif
{ "childAtIndex", childAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "linkedUIElementAtIndex", linkedUIElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
{ "indexOfChild", indexOfChildCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.h (244560 => 244561)
--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.h 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.h 2019-04-23 20:31:51 UTC (rev 244561)
@@ -218,6 +218,10 @@
unsigned uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
AccessibilityUIElement uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
JSRetainPtr<JSStringRef> selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity);
+#if PLATFORM(MAC)
+ JSValueRef searchTextWithCriteria(JSContextRef, JSValueRef searchStrings, JSStringRef StartFrom, JSStringRef direction);
+#endif
+
#if PLATFORM(IOS_FAMILY)
void elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements);
JSRetainPtr<JSStringRef> stringForSelection();
Modified: trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm (244560 => 244561)
--- trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm 2019-04-23 20:31:51 UTC (rev 244561)
@@ -178,6 +178,18 @@
return attributesString;
}
+template<typename T>
+static JSValueRef convertVectorToObjectArray(JSContextRef context, Vector<T> const& elements)
+{
+ JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
+ JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
+ size_t elementCount = elements.size();
+ for (size_t i = 0; i < elementCount; ++i)
+ JSObjectSetPropertyAtIndex(context, arrayObj, i, JSObjectMake(context, elements[i].getJSClass(), new T(elements[i])), 0);
+
+ return arrayResult;
+}
+
static JSRetainPtr<JSStringRef> concatenateAttributeAndValue(NSString *attribute, NSString *value)
{
Vector<UniChar> buffer([attribute length]);
@@ -192,11 +204,15 @@
return adopt(JSStringCreateWithCharacters(buffer.data(), buffer.size()));
}
-static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
+template<typename T>
+static Vector<T> convertNSArrayToVector(NSArray *array)
{
- NSUInteger count = [array count];
+ Vector<T> v;
+ NSUInteger count = array.count;
+ v.reserveInitialCapacity(count);
for (NSUInteger i = 0; i < count; ++i)
- elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
+ v.append([array objectAtIndex:i]);
+ return v;
}
static JSRetainPtr<JSStringRef> descriptionOfElements(Vector<AccessibilityUIElement>& elementVector)
@@ -255,11 +271,50 @@
return parameterizedAttribute;
}
+#if PLATFORM(MAC)
+static NSDictionary *searchTextParameterizedAttributeForCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
+{
+ NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
+
+ if (searchStrings) {
+ NSMutableArray *searchStringsParameter = [NSMutableArray array];
+ if (JSValueIsString(context, searchStrings)) {
+ auto searchStringsString = adopt(JSValueToStringCopy(context, searchStrings, nullptr));
+ if (searchStringsString)
+ [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
+ } else if (JSValueIsObject(context, searchStrings)) {
+ JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
+ unsigned searchStringsArrayLength = 0;
+
+ auto lengthPropertyString = adopt(JSStringCreateWithUTF8CString("length"));
+ JSValueRef searchStringsArrayLengthValue = JSObjectGetProperty(context, searchStringsArray, lengthPropertyString.get(), nullptr);
+ if (searchStringsArrayLengthValue && JSValueIsNumber(context, searchStringsArrayLengthValue))
+ searchStringsArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchStringsArrayLengthValue, nullptr));
+
+ for (unsigned i = 0; i < searchStringsArrayLength; ++i) {
+ auto searchStringsString = adopt(JSValueToStringCopy(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr), nullptr));
+ if (searchStringsString)
+ [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
+ }
+ }
+ [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSearchTextSearchStrings"];
+ }
+
+ if (startFrom)
+ [parameterizedAttribute setObject:[NSString stringWithJSStringRef:startFrom] forKey:@"AXSearchTextStartFrom"];
+
+ if (direction)
+ [parameterizedAttribute setObject:[NSString stringWithJSStringRef:direction] forKey:@"AXSearchTextDirection"];
+
+ return parameterizedAttribute;
+}
+#endif
+
void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
- convertNSArrayToVector(linkedElements, elementVector);
+ elementVector = convertNSArrayToVector<AccessibilityUIElement>(linkedElements);
END_AX_OBJC_EXCEPTIONS
}
@@ -267,7 +322,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
- convertNSArrayToVector(linkElements, elementVector);
+ elementVector = convertNSArrayToVector<AccessibilityUIElement>(linkElements);
END_AX_OBJC_EXCEPTIONS
}
@@ -275,7 +330,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
- convertNSArrayToVector(children, elementVector);
+ elementVector = convertNSArrayToVector<AccessibilityUIElement>(children);
END_AX_OBJC_EXCEPTIONS
}
@@ -283,7 +338,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
- convertNSArrayToVector(children, elementVector);
+ elementVector = convertNSArrayToVector<AccessibilityUIElement>(children);
END_AX_OBJC_EXCEPTIONS
}
@@ -492,7 +547,7 @@
BEGIN_AX_OBJC_EXCEPTIONS
id value = [m_element accessibilityAttributeValue:NSAccessibilityRowHeaderUIElementsAttribute];
if ([value isKindOfClass:[NSArray class]])
- convertNSArrayToVector(value, elements);
+ elements = convertNSArrayToVector<AccessibilityUIElement>(value);
END_AX_OBJC_EXCEPTIONS
}
@@ -501,7 +556,7 @@
BEGIN_AX_OBJC_EXCEPTIONS
id value = [m_element accessibilityAttributeValue:NSAccessibilityColumnHeaderUIElementsAttribute];
if ([value isKindOfClass:[NSArray class]])
- convertNSArrayToVector(value, elements);
+ elements = convertNSArrayToVector<AccessibilityUIElement>(value);
END_AX_OBJC_EXCEPTIONS
}
@@ -510,7 +565,7 @@
BEGIN_AX_OBJC_EXCEPTIONS
id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
if ([value isKindOfClass:[NSArray class]])
- convertNSArrayToVector(value, elements);
+ elements = convertNSArrayToVector<AccessibilityUIElement>(value);
END_AX_OBJC_EXCEPTIONS
}
@@ -1103,13 +1158,25 @@
return nullptr;
}
+#if PLATFORM(MAC)
+JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSDictionary *parameterizedAttribute = searchTextParameterizedAttributeForCriteria(context, searchStrings, startFrom, direction);
+ id result = [m_element accessibilityAttributeValue:@"AXSearchTextWithCriteria" forParameter:parameterizedAttribute];
+ if ([result isKindOfClass:[NSArray class]])
+ return convertVectorToObjectArray<AccessibilityTextMarkerRange>(context, convertNSArrayToVector<AccessibilityTextMarkerRange>(result));
+ END_AX_OBJC_EXCEPTIONS
+ return nullptr;
+}
+#endif
+
JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
{
// not yet defined in AppKit... odd
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
- Vector<AccessibilityUIElement> columnHeadersVector;
- convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
+ auto columnHeadersVector = convertNSArrayToVector<AccessibilityUIElement>(columnHeadersArray);
return descriptionOfElements(columnHeadersVector);
END_AX_OBJC_EXCEPTIONS
@@ -1120,8 +1187,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
- Vector<AccessibilityUIElement> rowHeadersVector;
- convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
+ auto rowHeadersVector = convertNSArrayToVector<AccessibilityUIElement>(rowHeadersArray);
return descriptionOfElements(rowHeadersVector);
END_AX_OBJC_EXCEPTIONS
@@ -1132,8 +1198,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
- Vector<AccessibilityUIElement> columnsVector;
- convertNSArrayToVector(columnsArray, columnsVector);
+ auto columnsVector = convertNSArrayToVector<AccessibilityUIElement>(columnsArray);
return descriptionOfElements(columnsVector);
END_AX_OBJC_EXCEPTIONS
@@ -1144,8 +1209,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
- Vector<AccessibilityUIElement> rowsVector;
- convertNSArrayToVector(rowsArray, rowsVector);
+ auto rowsVector = convertNSArrayToVector<AccessibilityUIElement>(rowsArray);
return descriptionOfElements(rowsVector);
END_AX_OBJC_EXCEPTIONS
@@ -1156,8 +1220,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
- Vector<AccessibilityUIElement> cellsVector;
- convertNSArrayToVector(cellsArray, cellsVector);
+ auto cellsVector = convertNSArrayToVector<AccessibilityUIElement>(cellsArray);
return descriptionOfElements(cellsVector);
END_AX_OBJC_EXCEPTIONS
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp (244560 => 244561)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp 2019-04-23 20:31:51 UTC (rev 244561)
@@ -91,6 +91,7 @@
void AccessibilityUIElement::resetSelectedTextMarkerRange() { }
void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { }
void AccessibilityUIElement::setValue(JSStringRef) { }
+JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef, JSValueRef, JSStringRef, JSStringRef) { return nullptr; }
#endif
#if !PLATFORM(COCOA) || !HAVE(ACCESSIBILITY)
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (244560 => 244561)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h 2019-04-23 20:31:51 UTC (rev 244561)
@@ -255,6 +255,7 @@
unsigned uiElementCountForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
RefPtr<AccessibilityUIElement> uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
JSRetainPtr<JSStringRef> selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity);
+ JSValueRef searchTextWithCriteria(JSContextRef, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction);
// Text-specific
JSRetainPtr<JSStringRef> characterAtOffset(int offset);
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl (244560 => 244561)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl 2019-04-23 20:31:51 UTC (rev 244561)
@@ -183,6 +183,7 @@
[PassContext] unsigned long uiElementCountForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly);
[PassContext] AccessibilityUIElement uiElementForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly);
[PassContext] DOMString selectTextWithCriteria(DOMString ambiguityResolution, object searchStrings, DOMString replacementString, DOMString activity);
+ [PassContext] object searchTextWithCriteria(object searchStrings, DOMString startFrom, DOMString direction);
boolean setSelectedTextRange(unsigned long location, unsigned long length);
// Scroll area attributes.
Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm (244560 => 244561)
--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm 2019-04-23 20:31:02 UTC (rev 244560)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm 2019-04-23 20:31:51 UTC (rev 244561)
@@ -192,7 +192,8 @@
return attributesString;
}
-static JSValueRef convertElementsToObjectArray(JSContextRef context, Vector<RefPtr<AccessibilityUIElement>>& elements)
+template<typename T>
+static JSValueRef convertVectorToObjectArray(JSContextRef context, Vector<T> const& elements)
{
JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
@@ -199,7 +200,7 @@
size_t elementCount = elements.size();
for (size_t i = 0; i < elementCount; ++i)
JSObjectSetPropertyAtIndex(context, arrayObj, i, JSObjectMake(context, elements[i]->wrapperClass(), elements[i].get()), 0);
-
+
return arrayResult;
}
@@ -217,11 +218,15 @@
return adopt(JSStringCreateWithCharacters(buffer.data(), buffer.size()));
}
-static void convertNSArrayToVector(NSArray* array, Vector<RefPtr<AccessibilityUIElement> >& elementVector)
+template<typename T>
+static Vector<T> convertNSArrayToVector(NSArray *array)
{
- NSUInteger count = [array count];
+ Vector<T> v;
+ NSUInteger count = array.count;
+ v.reserveInitialCapacity(count);
for (NSUInteger i = 0; i < count; ++i)
- elementVector.append(AccessibilityUIElement::create([array objectAtIndex:i]));
+ v.append(T::ValueType::create([array objectAtIndex:i]));
+ return v;
}
static JSRetainPtr<JSStringRef> descriptionOfElements(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
@@ -281,11 +286,48 @@
return parameterizedAttribute;
}
+static NSDictionary *searchTextParameterizedAttributeForCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
+{
+ NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
+
+ if (searchStrings) {
+ NSMutableArray *searchStringsParameter = [NSMutableArray array];
+ if (JSValueIsString(context, searchStrings)) {
+ auto searchStringsString = adopt(JSValueToStringCopy(context, searchStrings, nullptr));
+ if (searchStringsString)
+ [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
+ } else if (JSValueIsObject(context, searchStrings)) {
+ JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
+ unsigned searchStringsArrayLength = 0;
+
+ auto lengthPropertyString = adopt(JSStringCreateWithUTF8CString("length"));
+ JSValueRef searchStringsArrayLengthValue = JSObjectGetProperty(context, searchStringsArray, lengthPropertyString.get(), nullptr);
+ if (searchStringsArrayLengthValue && JSValueIsNumber(context, searchStringsArrayLengthValue))
+ searchStringsArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchStringsArrayLengthValue, nullptr));
+
+ for (unsigned i = 0; i < searchStringsArrayLength; ++i) {
+ auto searchStringsString = adopt(JSValueToStringCopy(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr), nullptr));
+ if (searchStringsString)
+ [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
+ }
+ }
+ [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSearchTextSearchStrings"];
+ }
+
+ if (startFrom)
+ [parameterizedAttribute setObject:[NSString stringWithJSStringRef:startFrom] forKey:@"AXSearchTextStartFrom"];
+
+ if (direction)
+ [parameterizedAttribute setObject:[NSString stringWithJSStringRef:direction] forKey:@"AXSearchTextDirection"];
+
+ return parameterizedAttribute;
+}
+
void AccessibilityUIElement::getLinkedUIElements(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
- convertNSArrayToVector(linkedElements, elementVector);
+ elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(linkedElements);
END_AX_OBJC_EXCEPTIONS
}
@@ -293,7 +335,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
- convertNSArrayToVector(linkElements, elementVector);
+ elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(linkElements);
END_AX_OBJC_EXCEPTIONS
}
@@ -302,7 +344,7 @@
BEGIN_AX_OBJC_EXCEPTIONS
id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
if ([value isKindOfClass:[NSArray class]])
- convertNSArrayToVector(value, elements);
+ elements = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(value);
END_AX_OBJC_EXCEPTIONS
}
@@ -310,7 +352,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
- convertNSArrayToVector(children, elementVector);
+ elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(children);
END_AX_OBJC_EXCEPTIONS
}
@@ -318,7 +360,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
- convertNSArrayToVector(children, elementVector);
+ elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(children);
END_AX_OBJC_EXCEPTIONS
}
@@ -331,8 +373,8 @@
Vector<RefPtr<AccessibilityUIElement>> elements;
id value = [m_element accessibilityAttributeValue:NSAccessibilityRowHeaderUIElementsAttribute];
if ([value isKindOfClass:[NSArray class]])
- convertNSArrayToVector(value, elements);
- return convertElementsToObjectArray(context, elements);
+ elements = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(value);
+ return convertVectorToObjectArray<RefPtr<AccessibilityUIElement>>(context, elements);
END_AX_OBJC_EXCEPTIONS
}
@@ -345,8 +387,8 @@
Vector<RefPtr<AccessibilityUIElement>> elements;
id value = [m_element accessibilityAttributeValue:NSAccessibilityColumnHeaderUIElementsAttribute];
if ([value isKindOfClass:[NSArray class]])
- convertNSArrayToVector(value, elements);
- return convertElementsToObjectArray(context, elements);
+ elements = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(value);
+ return convertVectorToObjectArray<RefPtr<AccessibilityUIElement>>(context, elements);
END_AX_OBJC_EXCEPTIONS
}
@@ -596,7 +638,7 @@
Vector<RefPtr<AccessibilityUIElement>> elements;
getUIElementsWithAttribute(attribute, elements);
- return convertElementsToObjectArray(context, elements);
+ return convertVectorToObjectArray<RefPtr<AccessibilityUIElement>>(context, elements);
}
RefPtr<AccessibilityUIElement> AccessibilityUIElement::uiElementAttributeValue(JSStringRef attribute) const
@@ -1199,13 +1241,26 @@
return nullptr;
}
+#if PLATFORM(MAC)
+JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
+{
+ BEGIN_AX_OBJC_EXCEPTIONS
+ NSDictionary *parameterizedAttribute = searchTextParameterizedAttributeForCriteria(context, searchStrings, startFrom, direction);
+ id result = [m_element accessibilityAttributeValue:@"AXSearchTextWithCriteria" forParameter:parameterizedAttribute];
+ if ([result isKindOfClass:[NSArray class]])
+ return convertVectorToObjectArray<RefPtr<AccessibilityTextMarkerRange>>(context, convertNSArrayToVector<RefPtr<AccessibilityTextMarkerRange>>(result));
+ END_AX_OBJC_EXCEPTIONS
+
+ return nullptr;
+}
+#endif
+
JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
{
// not yet defined in AppKit... odd
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
- Vector<RefPtr<AccessibilityUIElement> > columnHeadersVector;
- convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
+ auto columnHeadersVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(columnHeadersArray);
return descriptionOfElements(columnHeadersVector);
END_AX_OBJC_EXCEPTIONS
@@ -1216,8 +1271,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
- Vector<RefPtr<AccessibilityUIElement> > rowHeadersVector;
- convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
+ auto rowHeadersVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(rowHeadersArray);
return descriptionOfElements(rowHeadersVector);
END_AX_OBJC_EXCEPTIONS
@@ -1228,8 +1282,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
- Vector<RefPtr<AccessibilityUIElement> > columnsVector;
- convertNSArrayToVector(columnsArray, columnsVector);
+ auto columnsVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(columnsArray);
return descriptionOfElements(columnsVector);
END_AX_OBJC_EXCEPTIONS
@@ -1240,8 +1293,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
- Vector<RefPtr<AccessibilityUIElement> > rowsVector;
- convertNSArrayToVector(rowsArray, rowsVector);
+ auto rowsVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(rowsArray);
return descriptionOfElements(rowsVector);
END_AX_OBJC_EXCEPTIONS
@@ -1252,8 +1304,7 @@
{
BEGIN_AX_OBJC_EXCEPTIONS
NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
- Vector<RefPtr<AccessibilityUIElement> > cellsVector;
- convertNSArrayToVector(cellsArray, cellsVector);
+ auto cellsVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(cellsArray);
return descriptionOfElements(cellsVector);
END_AX_OBJC_EXCEPTIONS