⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 244561 in webkit


Ignore:
Timestamp:
Apr 23, 2019, 1:31:51 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Accessibility text search and selection API enhancements.
https://bugs.webkit.org/show_bug.cgi?id=197095
<rdar://problem/48181791>

Patch by Andres Gonzalez <Andres Gonzalez> on 2019-04-23
Reviewed by Chris Fleizach.

Source/WebCore:

  • 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.

Tools:

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.

LayoutTests:

  • 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.
Location:
trunk
Files:
3 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r244557 r244561  
     12019-04-23  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Accessibility text search and selection API enhancements.
     4        https://bugs.webkit.org/show_bug.cgi?id=197095
     5        <rdar://problem/48181791>
     6
     7        Reviewed by Chris Fleizach.
     8
     9        - Added new test for AccessibilitySearchTextWithCriteria API.
     10        - Updated bounds-for-range expected file that includes a list of available APIs.
     11
     12        * accessibility/mac/bounds-for-range-expected.txt:
     13        * accessibility/mac/search-text/search-text-expected.txt: Added.
     14        * accessibility/mac/search-text/search-text.html: Added.
     15
    1162019-04-23  Guy Lewin  <guy@lewin.co.il>
    217
  • trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt

    r229080 r244561  
    6666AXLineTextMarkerRangeForTextMarker
    6767AXSelectTextWithCriteria
     68AXSearchTextWithCriteria
     69AXTextOperation
    6870
    6971----------------------
  • trunk/Source/WebCore/ChangeLog

    r244557 r244561  
     12019-04-23  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Accessibility text search and selection API enhancements.
     4        https://bugs.webkit.org/show_bug.cgi?id=197095
     5        <rdar://problem/48181791>
     6
     7        Reviewed by Chris Fleizach.
     8
     9        - Split the existing SelectTextWithCriteria API into two: search text API (SearchTextWithCriteria) and a text operation API (TextOperation: select, replace, capitalize...).
     10        - This allows for more flexibility and extensibility.
     11        - Added the ability to retrieve text markers for multiple search hits.
     12        - Various code clean up and consolidation.
     13        - Added LayoutTest for search API.
     14        - Previous API is marked with "To be deprecated", and is implemented with new implementation. May be removed in a future change.
     15
     16        Test: accessibility/mac/search-text/search-text.html
     17
     18        * accessibility/AccessibilityObject.cpp:
     19        (WebCore::rangeClosestToRange):
     20        (WebCore::AccessibilityObject::rangeOfStringClosestToRangeInDirection const):
     21        (WebCore::AccessibilityObject::findTextRange const):
     22        (WebCore::AccessibilityObject::findTextRanges const):
     23        (WebCore::AccessibilityObject::performTextOperation):
     24        (WebCore::AccessibilityObject::frame const):
     25        (WebCore::AccessibilityObject::selectText): Deleted.
     26        * accessibility/AccessibilityObject.h:
     27        (WebCore::AccessibilitySearchTextCriteria::AccessibilitySearchTextCriteria):
     28        (WebCore::AccessibilityTextOperation::AccessibilityTextOperation):
     29        (WebCore::AccessibilitySelectTextCriteria::AccessibilitySelectTextCriteria): Deleted.
     30        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
     31        (accessibilityTextCriteriaForParameterizedAttribute):
     32        (accessibilitySearchTextCriteriaForParameterizedAttribute):
     33        (accessibilityTextOperationForParameterizedAttribute):
     34        (-[WebAccessibilityObjectWrapper IGNORE_WARNINGS_END]):
     35        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
     36        (accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute): Deleted.
     37
    1382019-04-23  Guy Lewin  <guy@lewin.co.il>
    239
  • trunk/Source/WebCore/accessibility/AccessibilityObject.cpp

    r244538 r244561  
    758758// NOTE: The after range is expected to ACTUALLY be after the reference range and the before
    759759// range is expected to ACTUALLY be before. These are not checked for performance reasons.
    760 static RefPtr<Range> rangeClosestToRange(Range* referenceRange, RefPtr<Range>&& afterRange, RefPtr<Range>&& beforeRange)
     760static RefPtr<Range> rangeClosestToRange(RefPtr<Range> const& referenceRange, RefPtr<Range>&& afterRange, RefPtr<Range>&& beforeRange)
    761761{
    762762    if (!referenceRange)
    763763        return nullptr;
    764    
     764
    765765    // The treeScope for shadow nodes may not be the same scope as another element in a document.
    766766    // Comparisons may fail in that case, which are expected behavior and should not assert.
    767767    if (afterRange && (referenceRange->endPosition().isNull() || ((afterRange->startPosition().anchorNode()->compareDocumentPosition(*referenceRange->endPosition().anchorNode()) & Node::DOCUMENT_POSITION_DISCONNECTED) == Node::DOCUMENT_POSITION_DISCONNECTED)))
    768768        return nullptr;
    769     ASSERT(!afterRange || afterRange->startPosition() >= referenceRange->endPosition());
    770    
     769    ASSERT(!afterRange || afterRange->compareBoundaryPoints(Range::START_TO_START, *referenceRange).releaseReturnValue() >= 0);
     770
    771771    if (beforeRange && (referenceRange->startPosition().isNull() || ((beforeRange->endPosition().anchorNode()->compareDocumentPosition(*referenceRange->startPosition().anchorNode()) & Node::DOCUMENT_POSITION_DISCONNECTED) == Node::DOCUMENT_POSITION_DISCONNECTED)))
    772772        return nullptr;
    773     ASSERT(!beforeRange || beforeRange->endPosition() <= referenceRange->startPosition());
    774    
     773    ASSERT(!beforeRange || beforeRange->compareBoundaryPoints(Range::START_TO_START, *referenceRange).releaseReturnValue() <= 0);
     774
    775775    if (!afterRange && !beforeRange)
    776776        return nullptr;
     
    786786}
    787787
    788 RefPtr<Range> AccessibilityObject::rangeOfStringClosestToRangeInDirection(Range* referenceRange, AccessibilitySearchDirection searchDirection, Vector<String>& searchStrings) const
     788RefPtr<Range> AccessibilityObject::rangeOfStringClosestToRangeInDirection(Range* referenceRange, AccessibilitySearchDirection searchDirection, Vector<String> const& searchStrings) const
    789789{
    790790    Frame* frame = this->frame();
     
    798798    FindOptions findOptions { AtWordStarts, AtWordEnds, CaseInsensitive, StartInSelection };
    799799    if (isBackwardSearch)
    800         findOptions.add(Backwards);
     800        findOptions.add(FindOptionFlag::Backwards);
    801801   
    802802    RefPtr<Range> closestStringRange = nullptr;
     
    844844}
    845845
    846 String AccessibilityObject::selectText(AccessibilitySelectTextCriteria* criteria)
    847 {
    848     ASSERT(criteria);
    849    
    850     if (!criteria)
    851         return String();
    852    
     846RefPtr<Range> AccessibilityObject::findTextRange(Vector<String> const& searchStrings, RefPtr<Range> const& start, AccessibilitySearchTextDirection direction) const
     847{
     848    RefPtr<Range> found;
     849    if (direction == AccessibilitySearchTextDirection::Forward)
     850        found = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Next, searchStrings);
     851    else if (direction == AccessibilitySearchTextDirection::Backward)
     852        found = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Previous, searchStrings);
     853    else if (direction == AccessibilitySearchTextDirection::Closest) {
     854        auto foundAfter = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Next, searchStrings);
     855        auto foundBefore = rangeOfStringClosestToRangeInDirection(start.get(), AccessibilitySearchDirection::Previous, searchStrings);
     856        found = rangeClosestToRange(start.get(), WTFMove(foundAfter), WTFMove(foundBefore));
     857    }
     858
     859    if (found) {
     860        // If the search started within a text control, ensure that the result is inside that element.
     861        if (element() && element()->isTextField()) {
     862            if (!found->startContainer().isDescendantOrShadowDescendantOf(element())
     863                || !found->endContainer().isDescendantOrShadowDescendantOf(element()))
     864                return nullptr;
     865        }
     866    }
     867    return found;
     868}
     869
     870Vector<RefPtr<Range>> AccessibilityObject::findTextRanges(AccessibilitySearchTextCriteria const& criteria) const
     871{
     872    Vector<RefPtr<Range>> result;
     873
     874    // Determine start range.
     875    RefPtr<Range> startRange;
     876    if (criteria.start == AccessibilitySearchTextStartFrom::Selection)
     877        startRange = selectionRange();
     878    else
     879        startRange = elementRange();
     880
     881    if (startRange) {
     882        // Collapse the range to the start unless searching from the end of the doc or searching backwards.
     883        if (criteria.start == AccessibilitySearchTextStartFrom::Begin)
     884            startRange->collapse(true);
     885        else if (criteria.start == AccessibilitySearchTextStartFrom::End)
     886            startRange->collapse(false);
     887        else
     888            startRange->collapse(criteria.direction != AccessibilitySearchTextDirection::Backward);
     889    } else
     890        return result;
     891
     892    RefPtr<Range> found;
     893    switch (criteria.direction) {
     894    case AccessibilitySearchTextDirection::Forward:
     895    case AccessibilitySearchTextDirection::Backward:
     896    case AccessibilitySearchTextDirection::Closest:
     897        found = findTextRange(criteria.searchStrings, startRange, criteria.direction);
     898        if (found)
     899            result.append(found);
     900        break;
     901    case AccessibilitySearchTextDirection::All: {
     902        auto findAll = [&](AccessibilitySearchTextDirection dir) {
     903            found = findTextRange(criteria.searchStrings, startRange, dir);
     904            while (found) {
     905                result.append(found);
     906                found = findTextRange(criteria.searchStrings, found, dir);
     907            }
     908        };
     909        findAll(AccessibilitySearchTextDirection::Forward);
     910        findAll(AccessibilitySearchTextDirection::Backward);
     911        break;
     912    }
     913    }
     914
     915    return result;
     916}
     917
     918Vector<String> AccessibilityObject::performTextOperation(AccessibilityTextOperation const& operation)
     919{
     920    Vector<String> result;
     921
     922    if (operation.textRanges.isEmpty())
     923        return result;
     924
    853925    Frame* frame = this->frame();
    854926    if (!frame)
    855         return String();
    856    
    857     AccessibilitySelectTextActivity& activity = criteria->activity;
    858     AccessibilitySelectTextAmbiguityResolution& ambiguityResolution = criteria->ambiguityResolution;
    859     String& replacementString = criteria->replacementString;
    860     Vector<String>& searchStrings = criteria->searchStrings;
    861    
    862     RefPtr<Range> selectedStringRange = selectionRange();
    863     // When starting our search again, make this a zero length range so that search forwards will find this selected range if its appropriate.
    864     selectedStringRange->setEnd(selectedStringRange->startContainer(), selectedStringRange->startOffset());
    865    
    866     RefPtr<Range> closestAfterStringRange = nullptr;
    867     RefPtr<Range> closestBeforeStringRange = nullptr;
    868     // Search forward if necessary.
    869     if (ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestAfter || ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestTo)
    870         closestAfterStringRange = rangeOfStringClosestToRangeInDirection(selectedStringRange.get(), AccessibilitySearchDirection::Next, searchStrings);
    871     // Search backward if necessary.
    872     if (ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestBefore || ambiguityResolution == AccessibilitySelectTextAmbiguityResolution::ClosestTo)
    873         closestBeforeStringRange = rangeOfStringClosestToRangeInDirection(selectedStringRange.get(), AccessibilitySearchDirection::Previous, searchStrings);
    874    
    875     // Determine which candidate is closest to the selection and perform the activity.
    876     if (RefPtr<Range> closestStringRange = rangeClosestToRange(selectedStringRange.get(), WTFMove(closestAfterStringRange), WTFMove(closestBeforeStringRange))) {
    877         // If the search started within a text control, ensure that the result is inside that element.
    878         if (element() && element()->isTextField()) {
    879             if (!closestStringRange->startContainer().isDescendantOrShadowDescendantOf(element()) || !closestStringRange->endContainer().isDescendantOrShadowDescendantOf(element()))
    880                 return String();
     927        return result;
     928
     929    for (auto textRange : operation.textRanges) {
     930        if (!frame->selection().setSelectedRange(textRange.get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes))
     931            continue;
     932
     933        String text = textRange->text();
     934        String replacementString = operation.replacementText;
     935        bool replaceSelection = false;
     936        switch (operation.type) {
     937        case AccessibilityTextOperationType::Capitalize:
     938            replacementString = capitalize(text, ' '); // FIXME: Needs to take locale into account to work correctly.
     939            replaceSelection = true;
     940            break;
     941        case AccessibilityTextOperationType::Uppercase:
     942            replacementString = text.convertToUppercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
     943            replaceSelection = true;
     944            break;
     945        case AccessibilityTextOperationType::Lowercase:
     946            replacementString = text.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
     947            replaceSelection = true;
     948            break;
     949        case AccessibilityTextOperationType::Replace: {
     950            replaceSelection = true;
     951            // When applying find and replace activities, we want to match the capitalization of the replaced text,
     952            // (unless we're replacing with an abbreviation.)
     953            if (text.length() > 0
     954                && replacementString.length() > 2
     955                && replacementString != replacementString.convertToUppercaseWithoutLocale()) {
     956                if (text[0] == u_toupper(text[0]))
     957                    replacementString = capitalize(replacementString, ' '); // FIXME: Needs to take locale into account to work correctly.
     958                else
     959                    replacementString = replacementString.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
     960            }
     961            break;
    881962        }
    882        
    883         String closestString = closestStringRange->text();
    884         bool replaceSelection = false;
    885         if (frame->selection().setSelectedRange(closestStringRange.get(), DOWNSTREAM, FrameSelection::ShouldCloseTyping::Yes)) {
    886             switch (activity) {
    887             case AccessibilitySelectTextActivity::FindAndCapitalize:
    888                 replacementString = capitalize(closestString, ' '); // FIXME: Needs to take locale into account to work correctly.
    889                 replaceSelection = true;
    890                 break;
    891             case AccessibilitySelectTextActivity::FindAndUppercase:
    892                 replacementString = closestString.convertToUppercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
    893                 replaceSelection = true;
    894                 break;
    895             case AccessibilitySelectTextActivity::FindAndLowercase:
    896                 replacementString = closestString.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
    897                 replaceSelection = true;
    898                 break;
    899             case AccessibilitySelectTextActivity::FindAndReplace: {
    900                 replaceSelection = true;
    901                 // When applying find and replace activities, we want to match the capitalization of the replaced text,
    902                 // (unless we're replacing with an abbreviation.)
    903                 if (closestString.length() > 0 && replacementString.length() > 2 && replacementString != replacementString.convertToUppercaseWithoutLocale()) {
    904                     if (closestString[0] == u_toupper(closestString[0]))
    905                         replacementString = capitalize(replacementString, ' '); // FIXME: Needs to take locale into account to work correctly.
    906                     else
    907                         replacementString = replacementString.convertToLowercaseWithoutLocale(); // FIXME: Needs locale to work correctly.
    908                 }
    909                 break;
    910             }
    911             case AccessibilitySelectTextActivity::FindAndSelect:
    912                 break;
    913             }
    914            
    915             // A bit obvious, but worth noting the API contract for this method is that we should
    916             // return the replacement string when replacing, but the selected string if not.
    917             if (replaceSelection) {
    918                 frame->editor().replaceSelectionWithText(replacementString, Editor::SelectReplacement::Yes, Editor::SmartReplace::Yes);
    919                 return replacementString;
    920             }
    921            
    922             return closestString;
     963        case AccessibilityTextOperationType::Select:
     964            break;
    923965        }
    924     }
    925    
    926     return String();
     966
     967        // A bit obvious, but worth noting the API contract for this method is that we should
     968        // return the replacement string when replacing, but the selected string if not.
     969        if (replaceSelection) {
     970            frame->editor().replaceSelectionWithText(replacementString, Editor::SelectReplacement::Yes, Editor::SmartReplace::Yes);
     971            result.append(replacementString);
     972        } else
     973            result.append(text);
     974    }
     975
     976    return result;
    927977}
    928978
     
    10771127{
    10781128    Node* node = this->node();
    1079     if (!node)
    1080         return nullptr;
    1081    
    1082     return node->document().frame();
     1129    return node ? node->document().frame() : nullptr;
    10831130}
    10841131
  • trunk/Source/WebCore/accessibility/AccessibilityObject.h

    r244538 r244561  
    306306};
    307307
    308 enum class AccessibilitySelectTextActivity {
    309     FindAndReplace,
    310     FindAndSelect,
    311     FindAndCapitalize,
    312     FindAndLowercase,
    313     FindAndUppercase
    314 };
    315 
    316 enum class AccessibilitySelectTextAmbiguityResolution {
    317     ClosestAfter,
    318     ClosestBefore,
    319     ClosestTo
    320 };
    321 
    322 struct AccessibilitySelectTextCriteria {
    323     AccessibilitySelectTextActivity activity;
    324     AccessibilitySelectTextAmbiguityResolution ambiguityResolution;
    325     String replacementString;
    326     Vector<String> searchStrings;
    327    
    328     AccessibilitySelectTextCriteria(AccessibilitySelectTextActivity activity, AccessibilitySelectTextAmbiguityResolution ambiguityResolution, const String& replacementString)
    329         : activity(activity)
    330         , ambiguityResolution(ambiguityResolution)
    331         , replacementString(replacementString)
     308enum class AccessibilitySearchTextStartFrom {
     309    Begin, // Search from the beginning of the element.
     310    Selection, // Search from the position of the current selection.
     311    End // Search from the end of the element.
     312};
     313
     314enum class AccessibilitySearchTextDirection {
     315    Forward, // Occurrence after the starting range.
     316    Backward, // Occurrence before the starting range.
     317    Closest, // Closest occurrence to the starting range, whether after or before.
     318    All // All occurrences
     319};
     320
     321struct AccessibilitySearchTextCriteria {
     322    Vector<String> searchStrings; // Text strings to search for.
     323    AccessibilitySearchTextStartFrom start;
     324    AccessibilitySearchTextDirection direction;
     325
     326    AccessibilitySearchTextCriteria()
     327        : start(AccessibilitySearchTextStartFrom::Selection)
     328        , direction(AccessibilitySearchTextDirection::Forward)
     329    { }
     330};
     331
     332enum class AccessibilityTextOperationType {
     333    Select,
     334    Replace,
     335    Capitalize,
     336    Lowercase,
     337    Uppercase
     338};
     339
     340struct AccessibilityTextOperation {
     341    Vector<RefPtr<Range>> textRanges; // text on which perform the operation.
     342    AccessibilityTextOperationType type;
     343    String replacementText; // For type = replace.
     344
     345    AccessibilityTextOperation()
     346        : type(AccessibilityTextOperationType::Select)
    332347    { }
    333348};
     
    608623
    609624    bool isDescendantOfRole(AccessibilityRole) const;
    610    
     625
    611626    // Text selection
    612     RefPtr<Range> rangeOfStringClosestToRangeInDirection(Range*, AccessibilitySearchDirection, Vector<String>&) const;
     627private:
     628    RefPtr<Range> rangeOfStringClosestToRangeInDirection(Range*, AccessibilitySearchDirection, Vector<String> const&) const;
    613629    RefPtr<Range> selectionRange() const;
    614     String selectText(AccessibilitySelectTextCriteria*);
    615    
     630    RefPtr<Range> findTextRange(Vector<String> const& searchStrings, RefPtr<Range> const& start, AccessibilitySearchTextDirection) const;
     631public:
     632    Vector<RefPtr<Range>> findTextRanges(AccessibilitySearchTextCriteria const&) const;
     633    Vector<String> performTextOperation(AccessibilityTextOperation const&);
     634
    616635    virtual AccessibilityObject* observableObject() const { return nullptr; }
    617636    virtual void linkedUIElements(AccessibilityChildrenVector&) const { }
  • trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm

    r244059 r244561  
    373373#endif
    374374
     375// Text search
     376
     377#ifndef NSAccessibilitySearchTextWithCriteriaParameterizedAttribute
     378/* Performs a text search with the given parameters.
     379 Returns an NSArray of text marker ranges of the search hits.
     380 */
     381#define NSAccessibilitySearchTextWithCriteriaParameterizedAttribute @"AXSearchTextWithCriteria"
     382#endif
     383
     384#ifndef NSAccessibilitySearchTextSearchStrings
     385// NSArray of strings to search for.
     386#define NSAccessibilitySearchTextSearchStrings @"AXSearchTextSearchStrings"
     387#endif
     388
     389#ifndef NSAccessibilitySearchTextStartFrom
     390// NSString specifying the start point of the search: selection, begin or end.
     391#define NSAccessibilitySearchTextStartFrom @"AXSearchTextStartFrom"
     392#endif
     393
     394#ifndef NSAccessibilitySearchTextStartFromBegin
     395// Value for SearchTextStartFrom.
     396#define NSAccessibilitySearchTextStartFromBegin @"AXSearchTextStartFromBegin"
     397#endif
     398
     399#ifndef NSAccessibilitySearchTextStartFromSelection
     400// Value for SearchTextStartFrom.
     401#define NSAccessibilitySearchTextStartFromSelection @"AXSearchTextStartFromSelection"
     402#endif
     403
     404#ifndef NSAccessibilitySearchTextStartFromEnd
     405// Value for SearchTextStartFrom.
     406#define NSAccessibilitySearchTextStartFromEnd @"AXSearchTextStartFromEnd"
     407#endif
     408
     409#ifndef NSAccessibilitySearchTextDirection
     410// NSString specifying the direction of the search: forward, backward, closest, all.
     411#define NSAccessibilitySearchTextDirection @"AXSearchTextDirection"
     412#endif
     413
     414#ifndef NSAccessibilitySearchTextDirectionForward
     415// Value for SearchTextDirection.
     416#define NSAccessibilitySearchTextDirectionForward @"AXSearchTextDirectionForward"
     417#endif
     418
     419#ifndef NSAccessibilitySearchTextDirectionBackward
     420// Value for SearchTextDirection.
     421#define NSAccessibilitySearchTextDirectionBackward @"AXSearchTextDirectionBackward"
     422#endif
     423
     424#ifndef NSAccessibilitySearchTextDirectionClosest
     425// Value for SearchTextDirection.
     426#define NSAccessibilitySearchTextDirectionClosest @"AXSearchTextDirectionClosest"
     427#endif
     428
     429#ifndef NSAccessibilitySearchTextDirectionAll
     430// Value for SearchTextDirection.
     431#define NSAccessibilitySearchTextDirectionAll @"AXSearchTextDirectionAll"
     432#endif
     433
     434// Text operations
     435
     436#ifndef NSAccessibilityTextOperationParameterizedAttribute
     437// Performs an operation on the given text.
     438#define NSAccessibilityTextOperationParameterizedAttribute @"AXTextOperation"
     439#endif
     440
     441#ifndef NSAccessibilityTextOperationMarkerRanges
     442// Text on which to perform operation.
     443#define NSAccessibilityTextOperationMarkerRanges @"AXTextOperationMarkerRanges"
     444#endif
     445
     446#ifndef NSAccessibilityTextOperationType
     447// The type of operation to be performed: select, replace, capitalize....
     448#define NSAccessibilityTextOperationType @"AXTextOperationType"
     449#endif
     450
     451#ifndef NSAccessibilityTextOperationSelect
     452// Value for TextOperationType.
     453#define NSAccessibilityTextOperationSelect @"TextOperationSelect"
     454#endif
     455
     456#ifndef NSAccessibilityTextOperationReplace
     457// Value for TextOperationType.
     458#define NSAccessibilityTextOperationReplace @"TextOperationReplace"
     459#endif
     460
     461#ifndef NSAccessibilityTextOperationCapitalize
     462// Value for TextOperationType.
     463#define NSAccessibilityTextOperationCapitalize @"Capitalize"
     464#endif
     465
     466#ifndef NSAccessibilityTextOperationLowercase
     467// Value for TextOperationType.
     468#define NSAccessibilityTextOperationLowercase @"Lowercase"
     469#endif
     470
     471#ifndef NSAccessibilityTextOperationUppercase
     472// Value for TextOperationType.
     473#define NSAccessibilityTextOperationUppercase @"Uppercase"
     474#endif
     475
     476#ifndef NSAccessibilityTextOperationReplacementString
     477// Replacement text for operation replace.
     478#define NSAccessibilityTextOperationReplacementString @"AXTextOperationReplacementString"
     479#endif
     480
    375481// Math attributes
    376482#define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
     
    505611#pragma mark Select text helpers
    506612
    507 static AccessibilitySelectTextCriteria accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(const NSDictionary *parameterizedAttribute)
    508 {
     613// To be deprecated.
     614static std::pair<AccessibilitySearchTextCriteria, AccessibilityTextOperation> accessibilityTextCriteriaForParameterizedAttribute(const NSDictionary *parameterizedAttribute)
     615{
     616    AccessibilitySearchTextCriteria criteria;
     617    AccessibilityTextOperation operation;
     618
    509619    NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
    510620    NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
    511621    NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
    512622    NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
    513    
    514     AccessibilitySelectTextActivity activity = AccessibilitySelectTextActivity::FindAndSelect;
     623
    515624    if ([activityParameter isKindOfClass:[NSString class]]) {
    516625        if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
    517             activity = AccessibilitySelectTextActivity::FindAndReplace;
     626            operation.type = AccessibilityTextOperationType::Replace;
    518627        else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
    519             activity = AccessibilitySelectTextActivity::FindAndCapitalize;
     628            operation.type = AccessibilityTextOperationType::Capitalize;
    520629        else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
    521             activity = AccessibilitySelectTextActivity::FindAndLowercase;
     630            operation.type = AccessibilityTextOperationType::Lowercase;
    522631        else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
    523             activity = AccessibilitySelectTextActivity::FindAndUppercase;
    524     }
    525    
    526     AccessibilitySelectTextAmbiguityResolution ambiguityResolution = AccessibilitySelectTextAmbiguityResolution::ClosestTo;
     632            operation.type = AccessibilityTextOperationType::Uppercase;
     633    }
     634
     635    criteria.direction = AccessibilitySearchTextDirection::Closest;
    527636    if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
    528637        if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
    529             ambiguityResolution = AccessibilitySelectTextAmbiguityResolution::ClosestAfter;
     638            criteria.direction = AccessibilitySearchTextDirection::Forward;
    530639        else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
    531             ambiguityResolution = AccessibilitySelectTextAmbiguityResolution::ClosestBefore;
    532     }
    533    
    534     String replacementString;
     640            criteria.direction = AccessibilitySearchTextDirection::Backward;
     641    }
     642
    535643    if ([replacementStringParameter isKindOfClass:[NSString class]])
    536         replacementString = replacementStringParameter;
    537    
    538     AccessibilitySelectTextCriteria criteria(activity, ambiguityResolution, replacementString);
    539    
     644        operation.replacementText = replacementStringParameter;
     645
    540646    if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
    541647        size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
     
    546652        }
    547653    }
    548    
     654
     655    return std::make_pair(criteria, operation);
     656}
     657
     658static AccessibilitySearchTextCriteria accessibilitySearchTextCriteriaForParameterizedAttribute(const NSDictionary *params)
     659{
     660    AccessibilitySearchTextCriteria criteria;
     661
     662    NSArray *searchStrings = [params objectForKey:NSAccessibilitySearchTextSearchStrings];
     663    NSString *start = [params objectForKey:NSAccessibilitySearchTextStartFrom];
     664    NSString *direction = [params objectForKey:NSAccessibilitySearchTextDirection];
     665
     666    if ([searchStrings isKindOfClass:[NSArray class]]) {
     667        size_t searchStringsCount = static_cast<size_t>([searchStrings count]);
     668        criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
     669        for (NSString *searchString in searchStrings) {
     670            if ([searchString isKindOfClass:[NSString class]])
     671                criteria.searchStrings.uncheckedAppend(searchString);
     672        }
     673    }
     674
     675    if ([start isKindOfClass:[NSString class]]) {
     676        if ([start isEqualToString:NSAccessibilitySearchTextStartFromBegin])
     677            criteria.start = AccessibilitySearchTextStartFrom::Begin;
     678        else if ([start isEqualToString:NSAccessibilitySearchTextStartFromEnd])
     679            criteria.start = AccessibilitySearchTextStartFrom::End;
     680    }
     681
     682    if ([direction isKindOfClass:[NSString class]]) {
     683        if ([direction isEqualToString:NSAccessibilitySearchTextDirectionBackward])
     684            criteria.direction = AccessibilitySearchTextDirection::Backward;
     685        else if ([direction isEqualToString:NSAccessibilitySearchTextDirectionClosest])
     686            criteria.direction = AccessibilitySearchTextDirection::Closest;
     687        else if ([direction isEqualToString:NSAccessibilitySearchTextDirectionAll])
     688            criteria.direction = AccessibilitySearchTextDirection::All;
     689    }
     690
    549691    return criteria;
     692}
     693
     694static AccessibilityTextOperation accessibilityTextOperationForParameterizedAttribute(WebAccessibilityObjectWrapper *obj, const NSDictionary *parameterizedAttribute)
     695{
     696    AccessibilityTextOperation operation;
     697
     698    NSArray *markerRanges = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationMarkerRanges];
     699    NSString *operationType = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationType];
     700    NSString *replacementString = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationReplacementString];
     701
     702    if ([markerRanges isKindOfClass:[NSArray class]]) {
     703        size_t count = static_cast<size_t>(markerRanges.count);
     704        operation.textRanges.reserveInitialCapacity(count);
     705        for (id markerRange : markerRanges)
     706            operation.textRanges.append([obj rangeForTextMarkerRange:markerRange]);
     707    }
     708
     709    if ([operationType isKindOfClass:[NSString class]]) {
     710        if ([operationType isEqualToString:NSAccessibilityTextOperationReplace])
     711            operation.type = AccessibilityTextOperationType::Replace;
     712        else if ([operationType isEqualToString:NSAccessibilityTextOperationCapitalize])
     713            operation.type = AccessibilityTextOperationType::Capitalize;
     714        else if ([operationType isEqualToString:NSAccessibilityTextOperationLowercase])
     715            operation.type = AccessibilityTextOperationType::Lowercase;
     716        else if ([operationType isEqualToString:NSAccessibilityTextOperationUppercase])
     717            operation.type = AccessibilityTextOperationType::Uppercase;
     718    }
     719
     720    if ([replacementString isKindOfClass:[NSString class]])
     721        operation.replacementText = replacementString;
     722
     723    return operation;
    550724}
    551725
     
    34403614            NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
    34413615            NSAccessibilitySelectTextWithCriteriaParameterizedAttribute,
     3616            NSAccessibilitySearchTextWithCriteriaParameterizedAttribute,
     3617            NSAccessibilityTextOperationParameterizedAttribute,
    34423618            nil];
    34433619    }
     
    39914167    // dispatch
    39924168    if ([attribute isEqualToString:NSAccessibilitySelectTextWithCriteriaParameterizedAttribute]) {
    3993         AccessibilitySelectTextCriteria criteria = accessibilitySelectTextCriteriaForCriteriaParameterizedAttribute(dictionary);
    3994         return m_object->selectText(&criteria);
    3995     }
    3996    
     4169        // To be deprecated.
     4170        auto criteria = accessibilityTextCriteriaForParameterizedAttribute(dictionary);
     4171        criteria.second.textRanges = m_object->findTextRanges(criteria.first);
     4172        ASSERT(criteria.second.textRanges.size() <= 1);
     4173        Vector<String> result = m_object->performTextOperation(criteria.second);
     4174        ASSERT(result.size() <= 1);
     4175        if (result.size() > 0)
     4176            return result[0];
     4177        return String();
     4178    }
     4179
     4180    if ([attribute isEqualToString:NSAccessibilitySearchTextWithCriteriaParameterizedAttribute]) {
     4181        auto criteria = accessibilitySearchTextCriteriaForParameterizedAttribute(dictionary);
     4182        auto ranges = m_object->findTextRanges(criteria);
     4183        if (ranges.isEmpty())
     4184            return nil;
     4185        NSMutableArray *markers = [NSMutableArray arrayWithCapacity:ranges.size()];
     4186        for (auto range : ranges) {
     4187            if (id marker = [self textMarkerRangeFromRange:range])
     4188                [markers addObject:marker];
     4189        }
     4190        return markers;
     4191    }
     4192
     4193    if ([attribute isEqualToString:NSAccessibilityTextOperationParameterizedAttribute]) {
     4194        auto textOperation = accessibilityTextOperationForParameterizedAttribute(self, dictionary);
     4195        auto operationResult = m_object->performTextOperation(textOperation);
     4196        if (operationResult.isEmpty())
     4197            return nil;
     4198        NSMutableArray *result = [NSMutableArray arrayWithCapacity:operationResult.size()];
     4199        for (auto str : operationResult)
     4200            [result addObject:str];
     4201        return result;
     4202    }
     4203
    39974204    if ([attribute isEqualToString:NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute]) {
    39984205        AccessibilitySearchCriteria criteria = accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(dictionary);
  • trunk/Tools/ChangeLog

    r244557 r244561  
     12019-04-23  Andres Gonzalez  <andresg_22@apple.com>
     2
     3        Accessibility text search and selection API enhancements.
     4        https://bugs.webkit.org/show_bug.cgi?id=197095
     5        <rdar://problem/48181791>
     6
     7        Reviewed by Chris Fleizach.
     8
     9        Added new API JS binding code for searchTextWithCriteria to both WTR and DRT.
     10
     11        * DumpRenderTree/AccessibilityTextMarker.h:
     12        * DumpRenderTree/AccessibilityUIElement.cpp:
     13        (searchTextWithCriteriaCallback):
     14        (AccessibilityUIElement::getJSClass):
     15        * DumpRenderTree/AccessibilityUIElement.h:
     16        * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
     17        (convertVectorToObjectArray):
     18        (convertNSArrayToVector):
     19        (searchTextParameterizedAttributeForCriteria):
     20        (AccessibilityUIElement::getLinkedUIElements):
     21        (AccessibilityUIElement::getDocumentLinks):
     22        (AccessibilityUIElement::getChildren):
     23        (AccessibilityUIElement::getChildrenWithRange):
     24        (AccessibilityUIElement::rowHeaders const):
     25        (AccessibilityUIElement::columnHeaders const):
     26        (AccessibilityUIElement::uiElementArrayAttributeValue const):
     27        (AccessibilityUIElement::searchTextWithCriteria):
     28        (AccessibilityUIElement::attributesOfColumnHeaders):
     29        (AccessibilityUIElement::attributesOfRowHeaders):
     30        (AccessibilityUIElement::attributesOfColumns):
     31        (AccessibilityUIElement::attributesOfRows):
     32        (AccessibilityUIElement::attributesOfVisibleCells):
     33        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
     34        * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
     35        * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
     36        (WTR::convertVectorToObjectArray):
     37        (WTR::convertNSArrayToVector):
     38        (WTR::searchTextParameterizedAttributeForCriteria):
     39        (WTR::AccessibilityUIElement::getLinkedUIElements):
     40        (WTR::AccessibilityUIElement::getDocumentLinks):
     41        (WTR::AccessibilityUIElement::getUIElementsWithAttribute const):
     42        (WTR::AccessibilityUIElement::getChildren):
     43        (WTR::AccessibilityUIElement::getChildrenWithRange):
     44        (WTR::AccessibilityUIElement::rowHeaders const):
     45        (WTR::AccessibilityUIElement::columnHeaders const):
     46        (WTR::AccessibilityUIElement::uiElementArrayAttributeValue const):
     47        (WTR::AccessibilityUIElement::searchTextWithCriteria):
     48        (WTR::AccessibilityUIElement::attributesOfColumnHeaders):
     49        (WTR::AccessibilityUIElement::attributesOfRowHeaders):
     50        (WTR::AccessibilityUIElement::attributesOfColumns):
     51        (WTR::AccessibilityUIElement::attributesOfRows):
     52        (WTR::AccessibilityUIElement::attributesOfVisibleCells):
     53        (WTR::convertElementsToObjectArray): Deleted.
     54
    1552019-04-23  Guy Lewin  <guy@lewin.co.il>
    256
  • trunk/Tools/DumpRenderTree/AccessibilityTextMarker.h

    r237266 r244561  
    7676    static JSObjectRef makeJSAccessibilityTextMarkerRange(JSContextRef, const AccessibilityTextMarkerRange&);
    7777    bool isEqual(AccessibilityTextMarkerRange*);
    78    
     78
     79    static JSClassRef getJSClass();
     80
    7981private:
    80     static JSClassRef getJSClass();
    8182#if SUPPORTS_AX_TEXTMARKERS && PLATFORM(MAC)
    8283    RetainPtr<PlatformTextMarkerRange> m_textMarkerRange;
  • trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp

    r244062 r244561  
    279279    return JSValueMakeString(context, result.get());
    280280}
     281
     282#if PLATFORM(MAC)
     283static JSValueRef searchTextWithCriteriaCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     284{
     285    if (argumentCount < 1)
     286        return JSValueMakeUndefined(context);
     287
     288    JSValueRef searchStrings = arguments[0];
     289    JSRetainPtr<JSStringRef> startFrom;
     290    if (argumentCount > 1)
     291        startFrom = adopt(JSValueToStringCopy(context, arguments[1], exception));
     292    JSRetainPtr<JSStringRef> direction;
     293    if (argumentCount > 2)
     294        direction = adopt(JSValueToStringCopy(context, arguments[2], exception));
     295
     296    return toAXElement(thisObject)->searchTextWithCriteria(context, searchStrings, startFrom.get(), direction.get());
     297}
     298#endif
    281299
    282300static JSValueRef indexOfChildCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     
    18971915        { "uiElementForSearchPredicate", uiElementForSearchPredicateCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    18981916        { "selectTextWithCriteria", selectTextWithCriteriaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
     1917#if PLATFORM(MAC)
     1918        { "searchTextWithCriteria", searchTextWithCriteriaCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
     1919#endif
    18991920        { "childAtIndex", childAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
    19001921        { "linkedUIElementAtIndex", linkedUIElementAtIndexCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
  • trunk/Tools/DumpRenderTree/AccessibilityUIElement.h

    r244059 r244561  
    219219    AccessibilityUIElement uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
    220220    JSRetainPtr<JSStringRef> selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity);
     221#if PLATFORM(MAC)
     222    JSValueRef searchTextWithCriteria(JSContextRef, JSValueRef searchStrings, JSStringRef StartFrom, JSStringRef direction);
     223#endif
     224
    221225#if PLATFORM(IOS_FAMILY)
    222226    void elementsForRange(unsigned location, unsigned length, Vector<AccessibilityUIElement>& elements);
  • trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm

    r244059 r244561  
    179179}
    180180
     181template<typename T>
     182static JSValueRef convertVectorToObjectArray(JSContextRef context, Vector<T> const& elements)
     183{
     184    JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
     185    JSObjectRef arrayObj = JSValueToObject(context, arrayResult, 0);
     186    size_t elementCount = elements.size();
     187    for (size_t i = 0; i < elementCount; ++i)
     188        JSObjectSetPropertyAtIndex(context, arrayObj, i, JSObjectMake(context, elements[i].getJSClass(), new T(elements[i])), 0);
     189
     190    return arrayResult;
     191}
     192
    181193static JSRetainPtr<JSStringRef> concatenateAttributeAndValue(NSString *attribute, NSString *value)
    182194{
     
    193205}
    194206
    195 static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
    196 {
    197     NSUInteger count = [array count];
     207template<typename T>
     208static Vector<T> convertNSArrayToVector(NSArray *array)
     209{
     210    Vector<T> v;
     211    NSUInteger count = array.count;
     212    v.reserveInitialCapacity(count);
    198213    for (NSUInteger i = 0; i < count; ++i)
    199         elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
     214        v.append([array objectAtIndex:i]);
     215    return v;
    200216}
    201217
     
    256272}
    257273
     274#if PLATFORM(MAC)
     275static NSDictionary *searchTextParameterizedAttributeForCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
     276{
     277    NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
     278
     279    if (searchStrings) {
     280        NSMutableArray *searchStringsParameter = [NSMutableArray array];
     281        if (JSValueIsString(context, searchStrings)) {
     282            auto searchStringsString = adopt(JSValueToStringCopy(context, searchStrings, nullptr));
     283            if (searchStringsString)
     284                [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
     285        } else if (JSValueIsObject(context, searchStrings)) {
     286            JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
     287            unsigned searchStringsArrayLength = 0;
     288
     289            auto lengthPropertyString = adopt(JSStringCreateWithUTF8CString("length"));
     290            JSValueRef searchStringsArrayLengthValue = JSObjectGetProperty(context, searchStringsArray, lengthPropertyString.get(), nullptr);
     291            if (searchStringsArrayLengthValue && JSValueIsNumber(context, searchStringsArrayLengthValue))
     292                searchStringsArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchStringsArrayLengthValue, nullptr));
     293
     294            for (unsigned i = 0; i < searchStringsArrayLength; ++i) {
     295                auto searchStringsString = adopt(JSValueToStringCopy(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr), nullptr));
     296                if (searchStringsString)
     297                    [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
     298            }
     299        }
     300        [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSearchTextSearchStrings"];
     301    }
     302
     303    if (startFrom)
     304        [parameterizedAttribute setObject:[NSString stringWithJSStringRef:startFrom] forKey:@"AXSearchTextStartFrom"];
     305
     306    if (direction)
     307        [parameterizedAttribute setObject:[NSString stringWithJSStringRef:direction] forKey:@"AXSearchTextDirection"];
     308
     309    return parameterizedAttribute;
     310}
     311#endif
     312
    258313void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
    259314{
    260315    BEGIN_AX_OBJC_EXCEPTIONS
    261316    NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
    262     convertNSArrayToVector(linkedElements, elementVector);
     317    elementVector = convertNSArrayToVector<AccessibilityUIElement>(linkedElements);
    263318    END_AX_OBJC_EXCEPTIONS
    264319}
     
    268323    BEGIN_AX_OBJC_EXCEPTIONS
    269324    NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
    270     convertNSArrayToVector(linkElements, elementVector);
     325    elementVector = convertNSArrayToVector<AccessibilityUIElement>(linkElements);
    271326    END_AX_OBJC_EXCEPTIONS
    272327}
     
    276331    BEGIN_AX_OBJC_EXCEPTIONS
    277332    NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
    278     convertNSArrayToVector(children, elementVector);
     333    elementVector = convertNSArrayToVector<AccessibilityUIElement>(children);
    279334    END_AX_OBJC_EXCEPTIONS
    280335}
     
    284339    BEGIN_AX_OBJC_EXCEPTIONS
    285340    NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
    286     convertNSArrayToVector(children, elementVector);
     341    elementVector = convertNSArrayToVector<AccessibilityUIElement>(children);
    287342    END_AX_OBJC_EXCEPTIONS
    288343}
     
    493548    id value = [m_element accessibilityAttributeValue:NSAccessibilityRowHeaderUIElementsAttribute];
    494549    if ([value isKindOfClass:[NSArray class]])
    495         convertNSArrayToVector(value, elements);
     550        elements = convertNSArrayToVector<AccessibilityUIElement>(value);
    496551    END_AX_OBJC_EXCEPTIONS
    497552}
     
    502557    id value = [m_element accessibilityAttributeValue:NSAccessibilityColumnHeaderUIElementsAttribute];
    503558    if ([value isKindOfClass:[NSArray class]])
    504         convertNSArrayToVector(value, elements);
     559        elements = convertNSArrayToVector<AccessibilityUIElement>(value);
    505560    END_AX_OBJC_EXCEPTIONS
    506561}
     
    511566    id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
    512567    if ([value isKindOfClass:[NSArray class]])
    513         convertNSArrayToVector(value, elements);
     568        elements = convertNSArrayToVector<AccessibilityUIElement>(value);
    514569    END_AX_OBJC_EXCEPTIONS
    515570}
     
    11041159}
    11051160
     1161#if PLATFORM(MAC)
     1162JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
     1163{
     1164    BEGIN_AX_OBJC_EXCEPTIONS
     1165    NSDictionary *parameterizedAttribute = searchTextParameterizedAttributeForCriteria(context, searchStrings, startFrom, direction);
     1166    id result = [m_element accessibilityAttributeValue:@"AXSearchTextWithCriteria" forParameter:parameterizedAttribute];
     1167    if ([result isKindOfClass:[NSArray class]])
     1168        return convertVectorToObjectArray<AccessibilityTextMarkerRange>(context, convertNSArrayToVector<AccessibilityTextMarkerRange>(result));
     1169    END_AX_OBJC_EXCEPTIONS
     1170    return nullptr;
     1171}
     1172#endif
     1173
    11061174JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
    11071175{
     
    11091177    BEGIN_AX_OBJC_EXCEPTIONS
    11101178    NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
    1111     Vector<AccessibilityUIElement> columnHeadersVector;
    1112     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
     1179    auto columnHeadersVector = convertNSArrayToVector<AccessibilityUIElement>(columnHeadersArray);
    11131180    return descriptionOfElements(columnHeadersVector);
    11141181    END_AX_OBJC_EXCEPTIONS
     
    11211188    BEGIN_AX_OBJC_EXCEPTIONS
    11221189    NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
    1123     Vector<AccessibilityUIElement> rowHeadersVector;
    1124     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
     1190    auto rowHeadersVector = convertNSArrayToVector<AccessibilityUIElement>(rowHeadersArray);
    11251191    return descriptionOfElements(rowHeadersVector);
    11261192    END_AX_OBJC_EXCEPTIONS
     
    11331199    BEGIN_AX_OBJC_EXCEPTIONS
    11341200    NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
    1135     Vector<AccessibilityUIElement> columnsVector;
    1136     convertNSArrayToVector(columnsArray, columnsVector);
     1201    auto columnsVector = convertNSArrayToVector<AccessibilityUIElement>(columnsArray);
    11371202    return descriptionOfElements(columnsVector);
    11381203    END_AX_OBJC_EXCEPTIONS
     
    11451210    BEGIN_AX_OBJC_EXCEPTIONS
    11461211    NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
    1147     Vector<AccessibilityUIElement> rowsVector;
    1148     convertNSArrayToVector(rowsArray, rowsVector);
     1212    auto rowsVector = convertNSArrayToVector<AccessibilityUIElement>(rowsArray);
    11491213    return descriptionOfElements(rowsVector);
    11501214    END_AX_OBJC_EXCEPTIONS
     
    11571221    BEGIN_AX_OBJC_EXCEPTIONS
    11581222    NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
    1159     Vector<AccessibilityUIElement> cellsVector;
    1160     convertNSArrayToVector(cellsArray, cellsVector);
     1223    auto cellsVector = convertNSArrayToVector<AccessibilityUIElement>(cellsArray);
    11611224    return descriptionOfElements(cellsVector);
    11621225    END_AX_OBJC_EXCEPTIONS
  • trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.cpp

    r238098 r244561  
    9292void AccessibilityUIElement::setBoolAttributeValue(JSStringRef, bool) { }
    9393void AccessibilityUIElement::setValue(JSStringRef) { }
     94JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef, JSValueRef, JSStringRef, JSStringRef) { return nullptr; }
    9495#endif
    9596
  • trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h

    r244059 r244561  
    256256    RefPtr<AccessibilityUIElement> uiElementForSearchPredicate(JSContextRef, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly);
    257257    JSRetainPtr<JSStringRef> selectTextWithCriteria(JSContextRef, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString, JSStringRef activity);
     258    JSValueRef searchTextWithCriteria(JSContextRef, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction);
    258259
    259260    // Text-specific
  • trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl

    r244059 r244561  
    184184    [PassContext] AccessibilityUIElement uiElementForSearchPredicate(AccessibilityUIElement startElement, boolean isDirectionNext, object searchKey, DOMString searchText, boolean visibleOnly, boolean immediateDescendantsOnly);
    185185    [PassContext] DOMString selectTextWithCriteria(DOMString ambiguityResolution, object searchStrings, DOMString replacementString, DOMString activity);
     186    [PassContext] object searchTextWithCriteria(object searchStrings, DOMString startFrom, DOMString direction);
    186187    boolean setSelectedTextRange(unsigned long location, unsigned long length);
    187188
  • trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm

    r244059 r244561  
    193193}
    194194
    195 static JSValueRef convertElementsToObjectArray(JSContextRef context, Vector<RefPtr<AccessibilityUIElement>>& elements)
     195template<typename T>
     196static JSValueRef convertVectorToObjectArray(JSContextRef context, Vector<T> const& elements)
    196197{
    197198    JSValueRef arrayResult = JSObjectMakeArray(context, 0, 0, 0);
     
    200201    for (size_t i = 0; i < elementCount; ++i)
    201202        JSObjectSetPropertyAtIndex(context, arrayObj, i, JSObjectMake(context, elements[i]->wrapperClass(), elements[i].get()), 0);
    202    
     203
    203204    return arrayResult;
    204205}
     
    218219}
    219220
    220 static void convertNSArrayToVector(NSArray* array, Vector<RefPtr<AccessibilityUIElement> >& elementVector)
    221 {
    222     NSUInteger count = [array count];
     221template<typename T>
     222static Vector<T> convertNSArrayToVector(NSArray *array)
     223{
     224    Vector<T> v;
     225    NSUInteger count = array.count;
     226    v.reserveInitialCapacity(count);
    223227    for (NSUInteger i = 0; i < count; ++i)
    224         elementVector.append(AccessibilityUIElement::create([array objectAtIndex:i]));
     228        v.append(T::ValueType::create([array objectAtIndex:i]));
     229    return v;
    225230}
    226231
     
    282287}
    283288
     289static NSDictionary *searchTextParameterizedAttributeForCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
     290{
     291    NSMutableDictionary *parameterizedAttribute = [NSMutableDictionary dictionary];
     292
     293    if (searchStrings) {
     294        NSMutableArray *searchStringsParameter = [NSMutableArray array];
     295        if (JSValueIsString(context, searchStrings)) {
     296            auto searchStringsString = adopt(JSValueToStringCopy(context, searchStrings, nullptr));
     297            if (searchStringsString)
     298                [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
     299        } else if (JSValueIsObject(context, searchStrings)) {
     300            JSObjectRef searchStringsArray = JSValueToObject(context, searchStrings, nullptr);
     301            unsigned searchStringsArrayLength = 0;
     302
     303            auto lengthPropertyString = adopt(JSStringCreateWithUTF8CString("length"));
     304            JSValueRef searchStringsArrayLengthValue = JSObjectGetProperty(context, searchStringsArray, lengthPropertyString.get(), nullptr);
     305            if (searchStringsArrayLengthValue && JSValueIsNumber(context, searchStringsArrayLengthValue))
     306                searchStringsArrayLength = static_cast<unsigned>(JSValueToNumber(context, searchStringsArrayLengthValue, nullptr));
     307
     308            for (unsigned i = 0; i < searchStringsArrayLength; ++i) {
     309                auto searchStringsString = adopt(JSValueToStringCopy(context, JSObjectGetPropertyAtIndex(context, searchStringsArray, i, nullptr), nullptr));
     310                if (searchStringsString)
     311                    [searchStringsParameter addObject:[NSString stringWithJSStringRef:searchStringsString.get()]];
     312            }
     313        }
     314        [parameterizedAttribute setObject:searchStringsParameter forKey:@"AXSearchTextSearchStrings"];
     315    }
     316
     317    if (startFrom)
     318        [parameterizedAttribute setObject:[NSString stringWithJSStringRef:startFrom] forKey:@"AXSearchTextStartFrom"];
     319
     320    if (direction)
     321        [parameterizedAttribute setObject:[NSString stringWithJSStringRef:direction] forKey:@"AXSearchTextDirection"];
     322
     323    return parameterizedAttribute;
     324}
     325
    284326void AccessibilityUIElement::getLinkedUIElements(Vector<RefPtr<AccessibilityUIElement> >& elementVector)
    285327{
    286328    BEGIN_AX_OBJC_EXCEPTIONS
    287329    NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
    288     convertNSArrayToVector(linkedElements, elementVector);
     330    elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(linkedElements);
    289331    END_AX_OBJC_EXCEPTIONS
    290332}
     
    294336    BEGIN_AX_OBJC_EXCEPTIONS
    295337    NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
    296     convertNSArrayToVector(linkElements, elementVector);
     338    elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(linkElements);
    297339    END_AX_OBJC_EXCEPTIONS
    298340}
     
    303345    id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
    304346    if ([value isKindOfClass:[NSArray class]])
    305         convertNSArrayToVector(value, elements);
     347        elements = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(value);
    306348    END_AX_OBJC_EXCEPTIONS
    307349}
     
    311353    BEGIN_AX_OBJC_EXCEPTIONS
    312354    NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
    313     convertNSArrayToVector(children, elementVector);
     355    elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(children);
    314356    END_AX_OBJC_EXCEPTIONS
    315357}
     
    319361    BEGIN_AX_OBJC_EXCEPTIONS
    320362    NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
    321     convertNSArrayToVector(children, elementVector);
     363    elementVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(children);
    322364    END_AX_OBJC_EXCEPTIONS
    323365}
     
    332374    id value = [m_element accessibilityAttributeValue:NSAccessibilityRowHeaderUIElementsAttribute];
    333375    if ([value isKindOfClass:[NSArray class]])
    334         convertNSArrayToVector(value, elements);
    335     return convertElementsToObjectArray(context, elements);
     376        elements = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(value);
     377    return convertVectorToObjectArray<RefPtr<AccessibilityUIElement>>(context, elements);
    336378    END_AX_OBJC_EXCEPTIONS
    337379}
     
    346388    id value = [m_element accessibilityAttributeValue:NSAccessibilityColumnHeaderUIElementsAttribute];
    347389    if ([value isKindOfClass:[NSArray class]])
    348         convertNSArrayToVector(value, elements);
    349     return convertElementsToObjectArray(context, elements);
     390        elements = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(value);
     391    return convertVectorToObjectArray<RefPtr<AccessibilityUIElement>>(context, elements);
    350392    END_AX_OBJC_EXCEPTIONS
    351393}
     
    597639    Vector<RefPtr<AccessibilityUIElement>> elements;
    598640    getUIElementsWithAttribute(attribute, elements);
    599     return convertElementsToObjectArray(context, elements);
     641    return convertVectorToObjectArray<RefPtr<AccessibilityUIElement>>(context, elements);
    600642}
    601643
     
    12001242}
    12011243
     1244#if PLATFORM(MAC)
     1245JSValueRef AccessibilityUIElement::searchTextWithCriteria(JSContextRef context, JSValueRef searchStrings, JSStringRef startFrom, JSStringRef direction)
     1246{
     1247    BEGIN_AX_OBJC_EXCEPTIONS
     1248    NSDictionary *parameterizedAttribute = searchTextParameterizedAttributeForCriteria(context, searchStrings, startFrom, direction);
     1249    id result = [m_element accessibilityAttributeValue:@"AXSearchTextWithCriteria" forParameter:parameterizedAttribute];
     1250    if ([result isKindOfClass:[NSArray class]])
     1251        return convertVectorToObjectArray<RefPtr<AccessibilityTextMarkerRange>>(context, convertNSArrayToVector<RefPtr<AccessibilityTextMarkerRange>>(result));
     1252    END_AX_OBJC_EXCEPTIONS
     1253
     1254    return nullptr;
     1255}
     1256#endif
     1257
    12021258JSRetainPtr<JSStringRef> AccessibilityUIElement::attributesOfColumnHeaders()
    12031259{
     
    12051261    BEGIN_AX_OBJC_EXCEPTIONS
    12061262    NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
    1207     Vector<RefPtr<AccessibilityUIElement> > columnHeadersVector;
    1208     convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
     1263    auto columnHeadersVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(columnHeadersArray);
    12091264    return descriptionOfElements(columnHeadersVector);
    12101265    END_AX_OBJC_EXCEPTIONS
     
    12171272    BEGIN_AX_OBJC_EXCEPTIONS
    12181273    NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
    1219     Vector<RefPtr<AccessibilityUIElement> > rowHeadersVector;
    1220     convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
     1274    auto rowHeadersVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(rowHeadersArray);
    12211275    return descriptionOfElements(rowHeadersVector);
    12221276    END_AX_OBJC_EXCEPTIONS
     
    12291283    BEGIN_AX_OBJC_EXCEPTIONS
    12301284    NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
    1231     Vector<RefPtr<AccessibilityUIElement> > columnsVector;
    1232     convertNSArrayToVector(columnsArray, columnsVector);
     1285    auto columnsVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(columnsArray);
    12331286    return descriptionOfElements(columnsVector);
    12341287    END_AX_OBJC_EXCEPTIONS
     
    12411294    BEGIN_AX_OBJC_EXCEPTIONS
    12421295    NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
    1243     Vector<RefPtr<AccessibilityUIElement> > rowsVector;
    1244     convertNSArrayToVector(rowsArray, rowsVector);
     1296    auto rowsVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(rowsArray);
    12451297    return descriptionOfElements(rowsVector);
    12461298    END_AX_OBJC_EXCEPTIONS
     
    12531305    BEGIN_AX_OBJC_EXCEPTIONS
    12541306    NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
    1255     Vector<RefPtr<AccessibilityUIElement> > cellsVector;
    1256     convertNSArrayToVector(cellsArray, cellsVector);
     1307    auto cellsVector = convertNSArrayToVector<RefPtr<AccessibilityUIElement>>(cellsArray);
    12571308    return descriptionOfElements(cellsVector);
    12581309    END_AX_OBJC_EXCEPTIONS
Note: See TracChangeset for help on using the changeset viewer.