Title: [229080] trunk
Revision
229080
Author
[email protected]
Date
2018-02-27 14:57:14 -0800 (Tue, 27 Feb 2018)

Log Message

AX: Spell check and style attributes should be optional when fetching attributed string
https://bugs.webkit.org/show_bug.cgi?id=160744

Patch by Doug Russell <[email protected]> on 2018-02-27
Reviewed by Chris Fleizach.

The overhead of fetching a spell checked attributed string via AX API is substantial.
In some cases on the order of 7/8 of the total time spent fetching the string.

This change introduces the new attribute AXAttributedStringForTextMarkerRangeWithOptions which accepts an NSDictionary as it's parameter with keys "AXTextMarkerRange" (AXTextMarkerRangeRef) and "AXSpellCheck" (NSNumber(BOOL)).

AXAttributedStringForTextMarkerRange will remain unchanged.

Source/WebCore:

Tests: accessibility/mac/attributed-string/attributed-string-for-range-with-options.html
       accessibility/mac/attributed-string/attributed-string-for-range.html

* accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
(AXAttributedStringAppendText):
(-[WebAccessibilityObjectWrapper doAXAttributedStringForTextMarkerRange:spellCheck:]):
(-[WebAccessibilityObjectWrapper accessibilityParameterizedAttributeNames]):
(-[WebAccessibilityObjectWrapper doAXAttributedStringForRange:]):
(-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
(-[WebAccessibilityObjectWrapper doAXAttributedStringForTextMarkerRange:]): Deleted.

Tools:

* DumpRenderTree/AccessibilityUIElement.cpp:
(attributedStringForTextMarkerRangeCallback):
(attributedStringForTextMarkerRangeWithOptionsCallback):
(AccessibilityUIElement::attributedStringForTextMarkerRange):
(AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
(AccessibilityUIElement::getJSClass):
* DumpRenderTree/AccessibilityUIElement.h:
* DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
(AccessibilityUIElement::attributedStringForTextMarkerRange):
(AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
* DumpRenderTree/mac/AccessibilityUIElementMac.mm:
(createJSStringRef):
(AccessibilityUIElement::attributedStringForTextMarkerRange):
(AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
* WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
* WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
* WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp:
(WTR::AccessibilityUIElement::attributedStringForTextMarkerRange):
(WTR::AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
* WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
(WTR::AccessibilityUIElement::attributedStringForTextMarkerRange):
(WTR::AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
* WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
(WTR::createJSStringRef):
(WTR::AccessibilityUIElement::attributedStringForTextMarkerRange):
(WTR::AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):

LayoutTests:

* accessibility/mac/attributed-string: Added.
* accessibility/mac/attributed-string/attributed-string-for-range-expected.txt: Added.
* accessibility/mac/attributed-string/attributed-string-for-range-with-options-expected.txt: Added.
* accessibility/mac/attributed-string/attributed-string-for-range-with-options.html: Added.
* accessibility/mac/attributed-string/attributed-string-for-range.html: Added.
* accessibility/mac/bounds-for-range-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (229079 => 229080)


--- trunk/LayoutTests/ChangeLog	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/LayoutTests/ChangeLog	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1,3 +1,24 @@
+2018-02-27  Doug Russell  <[email protected]>
+
+        AX: Spell check and style attributes should be optional when fetching attributed string
+        https://bugs.webkit.org/show_bug.cgi?id=160744
+
+        Reviewed by Chris Fleizach.
+
+        The overhead of fetching a spell checked attributed string via AX API is substantial. 
+        In some cases on the order of 7/8 of the total time spent fetching the string.
+
+        This change introduces the new attribute AXAttributedStringForTextMarkerRangeWithOptions which accepts an NSDictionary as it's parameter with keys "AXTextMarkerRange" (AXTextMarkerRangeRef) and "AXSpellCheck" (NSNumber(BOOL)).
+
+        AXAttributedStringForTextMarkerRange will remain unchanged.
+
+        * accessibility/mac/attributed-string: Added.
+        * accessibility/mac/attributed-string/attributed-string-for-range-expected.txt: Added.
+        * accessibility/mac/attributed-string/attributed-string-for-range-with-options-expected.txt: Added.
+        * accessibility/mac/attributed-string/attributed-string-for-range-with-options.html: Added.
+        * accessibility/mac/attributed-string/attributed-string-for-range.html: Added.
+        * accessibility/mac/bounds-for-range-expected.txt:
+
 2018-02-27  Antoine Quint  <[email protected]>
 
         Unreviewed, marking a number of Web Animations WPT tests non-flaky.

Added: trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-expected.txt (0 => 229080)


--- trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-expected.txt	2018-02-27 22:57:14 UTC (rev 229080)
@@ -0,0 +1,11 @@
+word mispelled word
+This test ensures that attributed string for text marker range works and does include misspelled attribute.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS text is expected
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-with-options-expected.txt (0 => 229080)


--- trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-with-options-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-with-options-expected.txt	2018-02-27 22:57:14 UTC (rev 229080)
@@ -0,0 +1,12 @@
+word mispelled word
+This test ensures that attributed string for text marker range works and only includes misspelled attribute when requested.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS text is expectedOne
+PASS text is expectedTwo
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-with-options.html (0 => 229080)


--- trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-with-options.html	                        (rev 0)
+++ trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range-with-options.html	2018-02-27 22:57:14 UTC (rev 229080)
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+    <head>
+        <script>
+            var successfullyParsed = false;
+        </script>
+        <script src=""
+    </head>
+    <body id="body">
+
+        <div id="content">
+            word mispelled word
+        </div>
+
+        <p id="description"></p>
+        <div id="console"></div>
+
+        <script>
+
+            description("This test ensures that attributed string for text marker range works and only includes misspelled attribute when requested.");
+
+            var text = 0;
+            var expectedOne = "AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, word mispelled word";
+            var expectedTwo = "AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, Misspelled, AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, word mispelled word";
+
+            if (window.accessibilityController) {
+
+                var obj = accessibilityController.accessibleElementById("content");
+                var range = obj.textMarkerRangeForElement(obj)
+                text = obj.attributedStringForTextMarkerRangeWithOptions(range, false);
+                shouldBe("text", "expectedOne");
+                text = obj.attributedStringForTextMarkerRangeWithOptions(range, true);
+                shouldBe("text", "expectedTwo");
+            }
+
+            successfullyParsed = true;
+        </script>
+        <script src=""
+    </body>
+</html>
+

Added: trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range.html (0 => 229080)


--- trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range.html	                        (rev 0)
+++ trunk/LayoutTests/accessibility/mac/attributed-string/attributed-string-for-range.html	2018-02-27 22:57:14 UTC (rev 229080)
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+    <head>
+        <script>
+            var successfullyParsed = false;
+        </script>
+        <script src=""
+    </head>
+    <body id="body">
+
+        <div id="content">
+            word mispelled word
+        </div>
+
+        <p id="description"></p>
+        <div id="console"></div>
+
+        <script>
+
+            description("This test ensures that attributed string for text marker range works and does include misspelled attribute.");
+            
+            var text = 0;
+            var expected = "AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, Misspelled, AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, AXFont - {\n    AXFontFamily = Times;\n    AXFontName = \"Times-Roman\";\n    AXFontSize = 16;\n    AXVisibleName = \"Times Roman\";\n}, word mispelled word";
+
+            if (window.accessibilityController) {
+
+                var obj = accessibilityController.accessibleElementById("content");
+                var range = obj.textMarkerRangeForElement(obj)
+                text = obj.attributedStringForTextMarkerRange(range);
+                shouldBe("text", "expected");
+            }
+
+            successfullyParsed = true;
+        </script>
+        <script src=""
+    </body>
+</html>
+

Modified: trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt (229079 => 229080)


--- trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/LayoutTests/accessibility/mac/bounds-for-range-expected.txt	2018-02-27 22:57:14 UTC (rev 229080)
@@ -37,6 +37,7 @@
 AXTextMarkerForPosition
 AXBoundsForTextMarkerRange
 AXAttributedStringForTextMarkerRange
+AXAttributedStringForTextMarkerRangeWithOptions
 AXTextMarkerRangeForUnorderedTextMarkers
 AXNextTextMarkerForTextMarker
 AXPreviousTextMarkerForTextMarker

Modified: trunk/Source/WebCore/ChangeLog (229079 => 229080)


--- trunk/Source/WebCore/ChangeLog	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Source/WebCore/ChangeLog	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1,3 +1,28 @@
+2018-02-27  Doug Russell  <[email protected]>
+
+        AX: Spell check and style attributes should be optional when fetching attributed string
+        https://bugs.webkit.org/show_bug.cgi?id=160744
+
+        Reviewed by Chris Fleizach.
+
+        The overhead of fetching a spell checked attributed string via AX API is substantial. 
+        In some cases on the order of 7/8 of the total time spent fetching the string.
+
+        This change introduces the new attribute AXAttributedStringForTextMarkerRangeWithOptions which accepts an NSDictionary as it's parameter with keys "AXTextMarkerRange" (AXTextMarkerRangeRef) and "AXSpellCheck" (NSNumber(BOOL)).
+
+        AXAttributedStringForTextMarkerRange will remain unchanged.
+
+        Tests: accessibility/mac/attributed-string/attributed-string-for-range-with-options.html
+               accessibility/mac/attributed-string/attributed-string-for-range.html
+
+        * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+        (AXAttributedStringAppendText):
+        (-[WebAccessibilityObjectWrapper doAXAttributedStringForTextMarkerRange:spellCheck:]):
+        (-[WebAccessibilityObjectWrapper accessibilityParameterizedAttributeNames]):
+        (-[WebAccessibilityObjectWrapper doAXAttributedStringForRange:]):
+        (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:forParameter:]):
+        (-[WebAccessibilityObjectWrapper doAXAttributedStringForTextMarkerRange:]): Deleted.
+
 2018-02-27  Daniel Bates  <[email protected]>
 
         Standardize terminology for marked text

Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (229079 => 229080)


--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1018,7 +1018,7 @@
         [attrString removeAttribute:attribute range:range];
 }
 
-static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text)
+static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text, bool spellCheck)
 {
     // skip invisible text
     RenderObject* renderer = node->renderer();
@@ -1038,10 +1038,12 @@
     
     // remove inherited attachment from prior AXAttributedStringAppendReplaced
     [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
+    if (spellCheck) {
 #if PLATFORM(MAC)
-    [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
+        [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
 #endif
-    [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
+        [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
+    }
     
     // set new attributes
     AXAttributeStringSetStyle(attrString, renderer, attrStringRange);
@@ -1051,7 +1053,8 @@
     AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
     
     // do spelling last because it tends to break up the range
-    AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
+    if (spellCheck)
+        AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
 }
 
 static NSString* nsStringForReplacedNode(Node* replacedNode)
@@ -1073,7 +1076,7 @@
     return [NSString stringWithCharacters:&attachmentChar length:1];
 }
 
-- (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
+- (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange spellCheck:(BOOL)spellCheck
 {
     if (!m_object)
         return nil;
@@ -1092,8 +1095,8 @@
             // Add the text of the list marker item if necessary.
             String listMarkerText = m_object->listMarkerTextForNodeAndPosition(&node, VisiblePosition(it.range()->startPosition()));
             if (!listMarkerText.isEmpty())
-                AXAttributedStringAppendText(attrString, &node, listMarkerText);
-            AXAttributedStringAppendText(attrString, &node, it.text());
+                AXAttributedStringAppendText(attrString, &node, listMarkerText, spellCheck);
+            AXAttributedStringAppendText(attrString, &node, it.text(), spellCheck);
         } else {
             Node* replacedNode = node.traverseToChildAt(offset);
             NSString *attachmentString = nsStringForReplacedNode(replacedNode);
@@ -1113,7 +1116,7 @@
         }
         it.advance();
     }
-    
+
     return [attrString autorelease];
 }
 
@@ -3380,42 +3383,43 @@
     static NSArray* webAreaParamAttrs = nil;
     if (paramAttrs == nil) {
         paramAttrs = [[NSArray alloc] initWithObjects:
-                      @"AXUIElementForTextMarker",
-                      @"AXTextMarkerRangeForUIElement",
-                      @"AXLineForTextMarker",
-                      @"AXTextMarkerRangeForLine",
-                      @"AXStringForTextMarkerRange",
-                      @"AXTextMarkerForPosition",
-                      @"AXBoundsForTextMarkerRange",
-                      @"AXAttributedStringForTextMarkerRange",
-                      @"AXTextMarkerRangeForUnorderedTextMarkers",
-                      @"AXNextTextMarkerForTextMarker",
-                      @"AXPreviousTextMarkerForTextMarker",
-                      @"AXLeftWordTextMarkerRangeForTextMarker",
-                      @"AXRightWordTextMarkerRangeForTextMarker",
-                      @"AXLeftLineTextMarkerRangeForTextMarker",
-                      @"AXRightLineTextMarkerRangeForTextMarker",
-                      @"AXSentenceTextMarkerRangeForTextMarker",
-                      @"AXParagraphTextMarkerRangeForTextMarker",
-                      @"AXNextWordEndTextMarkerForTextMarker",
-                      @"AXPreviousWordStartTextMarkerForTextMarker",
-                      @"AXNextLineEndTextMarkerForTextMarker",
-                      @"AXPreviousLineStartTextMarkerForTextMarker",
-                      @"AXNextSentenceEndTextMarkerForTextMarker",
-                      @"AXPreviousSentenceStartTextMarkerForTextMarker",
-                      @"AXNextParagraphEndTextMarkerForTextMarker",
-                      @"AXPreviousParagraphStartTextMarkerForTextMarker",
-                      @"AXStyleTextMarkerRangeForTextMarker",
-                      @"AXLengthForTextMarkerRange",
-                      NSAccessibilityBoundsForRangeParameterizedAttribute,
-                      NSAccessibilityStringForRangeParameterizedAttribute,
-                      NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute,
-                      NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
-                      NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute,
-                      NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
-                      NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
-                      NSAccessibilitySelectTextWithCriteriaParameterizedAttribute,
-                      nil];
+            @"AXUIElementForTextMarker",
+            @"AXTextMarkerRangeForUIElement",
+            @"AXLineForTextMarker",
+            @"AXTextMarkerRangeForLine",
+            @"AXStringForTextMarkerRange",
+            @"AXTextMarkerForPosition",
+            @"AXBoundsForTextMarkerRange",
+            @"AXAttributedStringForTextMarkerRange",
+            @"AXAttributedStringForTextMarkerRangeWithOptions",
+            @"AXTextMarkerRangeForUnorderedTextMarkers",
+            @"AXNextTextMarkerForTextMarker",
+            @"AXPreviousTextMarkerForTextMarker",
+            @"AXLeftWordTextMarkerRangeForTextMarker",
+            @"AXRightWordTextMarkerRangeForTextMarker",
+            @"AXLeftLineTextMarkerRangeForTextMarker",
+            @"AXRightLineTextMarkerRangeForTextMarker",
+            @"AXSentenceTextMarkerRangeForTextMarker",
+            @"AXParagraphTextMarkerRangeForTextMarker",
+            @"AXNextWordEndTextMarkerForTextMarker",
+            @"AXPreviousWordStartTextMarkerForTextMarker",
+            @"AXNextLineEndTextMarkerForTextMarker",
+            @"AXPreviousLineStartTextMarkerForTextMarker",
+            @"AXNextSentenceEndTextMarkerForTextMarker",
+            @"AXPreviousSentenceStartTextMarkerForTextMarker",
+            @"AXNextParagraphEndTextMarkerForTextMarker",
+            @"AXPreviousParagraphStartTextMarkerForTextMarker",
+            @"AXStyleTextMarkerRangeForTextMarker",
+            @"AXLengthForTextMarkerRange",
+            NSAccessibilityBoundsForRangeParameterizedAttribute,
+            NSAccessibilityStringForRangeParameterizedAttribute,
+            NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute,
+            NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
+            NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute,
+            NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
+            NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
+            NSAccessibilitySelectTextWithCriteriaParameterizedAttribute,
+            nil];
     }
     
     if (textParamAttrs == nil) {
@@ -3749,7 +3753,7 @@
 {
     PlainTextRange textRange = PlainTextRange(range.location, range.length);
     RefPtr<Range> webRange = m_object->rangeForPlainTextRange(textRange);
-    return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromRange:webRange]];
+    return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromRange:webRange] spellCheck:YES];
 }
 
 - (NSRange)_convertToNSRange:(Range*)range
@@ -4038,10 +4042,27 @@
         RefPtr<Range> range = cache->rangeForUnorderedCharacterOffsets(start, end);
         return m_object->stringForRange(range);
     }
-    
+
     if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
-        return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];
-    
+        return [self doAXAttributedStringForTextMarkerRange:textMarkerRange spellCheck:YES];
+
+    if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRangeWithOptions"]) {
+        if (textMarkerRange)
+            return [self doAXAttributedStringForTextMarkerRange:textMarkerRange spellCheck:NO];
+        if (dictionary) {
+            id textMarkerRange = nil;
+            id parameter = [dictionary objectForKey:@"AXTextMarkerRange"];
+            if (AXObjectIsTextMarkerRange(parameter))
+                textMarkerRange = parameter;
+            BOOL spellCheck = NO;
+            parameter = [dictionary objectForKey:@"AXSpellCheck"];
+            if ([parameter isKindOfClass:[NSNumber class]])
+                spellCheck = [parameter boolValue];
+            return [self doAXAttributedStringForTextMarkerRange:textMarkerRange spellCheck:spellCheck];
+        }
+        return nil;
+    }
+
     if ([attribute isEqualToString:@"AXTextMarkerRangeForUnorderedTextMarkers"]) {
         if ([array count] < 2)
             return nil;

Modified: trunk/Tools/ChangeLog (229079 => 229080)


--- trunk/Tools/ChangeLog	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/ChangeLog	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1,3 +1,44 @@
+2018-02-27  Doug Russell  <[email protected]>
+
+        AX: Spell check and style attributes should be optional when fetching attributed string
+        https://bugs.webkit.org/show_bug.cgi?id=160744
+
+        Reviewed by Chris Fleizach.
+
+        The overhead of fetching a spell checked attributed string via AX API is substantial. 
+        In some cases on the order of 7/8 of the total time spent fetching the string.
+
+        This change introduces the new attribute AXAttributedStringForTextMarkerRangeWithOptions which accepts an NSDictionary as it's parameter with keys "AXTextMarkerRange" (AXTextMarkerRangeRef) and "AXSpellCheck" (NSNumber(BOOL)).
+
+        AXAttributedStringForTextMarkerRange will remain unchanged.
+
+        * DumpRenderTree/AccessibilityUIElement.cpp:
+        (attributedStringForTextMarkerRangeCallback):
+        (attributedStringForTextMarkerRangeWithOptionsCallback):
+        (AccessibilityUIElement::attributedStringForTextMarkerRange):
+        (AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
+        (AccessibilityUIElement::getJSClass):
+        * DumpRenderTree/AccessibilityUIElement.h:
+        * DumpRenderTree/ios/AccessibilityUIElementIOS.mm:
+        (AccessibilityUIElement::attributedStringForTextMarkerRange):
+        (AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
+        * DumpRenderTree/mac/AccessibilityUIElementMac.mm:
+        (createJSStringRef):
+        (AccessibilityUIElement::attributedStringForTextMarkerRange):
+        (AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
+        * WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h:
+        * WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl:
+        * WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp:
+        (WTR::AccessibilityUIElement::attributedStringForTextMarkerRange):
+        (WTR::AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
+        * WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm:
+        (WTR::AccessibilityUIElement::attributedStringForTextMarkerRange):
+        (WTR::AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
+        * WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm:
+        (WTR::createJSStringRef):
+        (WTR::AccessibilityUIElement::attributedStringForTextMarkerRange):
+        (WTR::AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions):
+
 2018-02-27  Daniel Bates  <[email protected]>
 
         Standardize terminology for marked text

Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp (229079 => 229080)


--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.cpp	2018-02-27 22:57:14 UTC (rev 229080)
@@ -881,6 +881,29 @@
     return JSValueMakeString(context, markerRangeString.get());    
 }
 
+static JSValueRef attributedStringForTextMarkerRangeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    AccessibilityTextMarkerRange* markerRange = 0;
+    if (argumentCount == 1)
+        markerRange = toTextMarkerRange(JSValueToObject(context, arguments[0], exception));
+
+    JSRetainPtr<JSStringRef> markerRangeString(Adopt, toAXElement(thisObject)->attributedStringForTextMarkerRange(markerRange));
+    return JSValueMakeString(context, markerRangeString.get());
+}
+
+static JSValueRef attributedStringForTextMarkerRangeWithOptionsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    AccessibilityTextMarkerRange* markerRange = nullptr;
+    bool includeSpellCheck = false;
+    if (argumentCount == 2) {
+        markerRange = toTextMarkerRange(JSValueToObject(context, arguments[0], exception));
+        includeSpellCheck = JSValueToBoolean(context, arguments[1]);
+    }
+
+    JSRetainPtr<JSStringRef> markerRangeString(Adopt, toAXElement(thisObject)->attributedStringForTextMarkerRangeWithOptions(markerRange, includeSpellCheck));
+    return JSValueMakeString(context, markerRangeString.get());
+}
+
 static JSValueRef endTextMarkerForBoundsCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
     int x = 0;
@@ -957,7 +980,7 @@
 
 static JSValueRef accessibilityElementForTextMarkerCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
 {
-    AccessibilityTextMarker* marker = 0;
+    AccessibilityTextMarker* marker = nullptr;
     if (argumentCount == 1)
         marker = toTextMarker(JSValueToObject(context, arguments[0], exception));
     
@@ -1636,6 +1659,16 @@
     return 0;
 }
 
+JSStringRef AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange*)
+{
+    return nullptr;
+}
+
+JSStringRef AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange*, bool includeSpellCheck)
+{
+    return nullptr;
+}
+
 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*)
 {
     return false;
@@ -1908,6 +1941,8 @@
         { "nextTextMarker", nextTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "previousTextMarker", previousTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "stringForTextMarkerRange", stringForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "attributedStringForTextMarkerRange", attributedStringForTextMarkerRangeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "attributedStringForTextMarkerRangeWithOptions", attributedStringForTextMarkerRangeWithOptionsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "leftWordTextMarkerRangeForTextMarker", leftWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "rightWordTextMarkerRangeForTextMarker", rightWordTextMarkerRangeForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "previousWordStartTextMarkerForTextMarker", previousWordStartTextMarkerForTextMarkerCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },

Modified: trunk/Tools/DumpRenderTree/AccessibilityUIElement.h (229079 => 229080)


--- trunk/Tools/DumpRenderTree/AccessibilityUIElement.h	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/DumpRenderTree/AccessibilityUIElement.h	2018-02-27 22:57:14 UTC (rev 229080)
@@ -278,6 +278,8 @@
     bool setSelectedVisibleTextRange(AccessibilityTextMarkerRange*);
     
     JSStringRef stringForTextMarkerRange(AccessibilityTextMarkerRange*);
+    JSStringRef attributedStringForTextMarkerRange(AccessibilityTextMarkerRange*);
+    JSStringRef attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange*, bool includeSpellCheck);
     int textMarkerRangeLength(AccessibilityTextMarkerRange*);
     bool attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*);
     int indexForTextMarker(AccessibilityTextMarker*);

Modified: trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm (229079 => 229080)


--- trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/DumpRenderTree/ios/AccessibilityUIElementIOS.mm	2018-02-27 22:57:14 UTC (rev 229080)
@@ -542,6 +542,16 @@
     return [[m_element stringForTextMarkers:textMarkers] createJSStringRef];
 }
 
+JSStringRef AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange*)
+{
+    return nullptr;
+}
+
+JSStringRef AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange*, bool)
+{
+    return nullptr;
+}
+
 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*)
 {
     return false;

Modified: trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm (229079 => 229080)


--- trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/DumpRenderTree/mac/AccessibilityUIElementMac.mm	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1711,6 +1711,44 @@
     return nullptr;
 }
 
+static JSStringRef createJSStringRef(id string)
+{
+    if (!string)
+        return nullptr;
+    id mutableString = [[[NSMutableString alloc] init] autorelease];
+    id attributes = [string attributesAtIndex:0 effectiveRange:nil];
+    id attributeEnumerationBlock = ^(NSDictionary<NSString *, id> *attrs, NSRange range, BOOL *stop) {
+        BOOL misspelled = [[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue];
+        if (misspelled)
+            misspelled = [[attrs objectForKey:NSAccessibilityMarkedMisspelledTextAttribute] boolValue];
+        if (misspelled)
+            [mutableString appendString:@"Misspelled, "];
+        id font = [attributes objectForKey:(id)kAXFontTextAttribute];
+        if (font)
+            [mutableString appendFormat:@"%@ - %@, ", (id)kAXFontTextAttribute, font];
+    };
+    [string enumerateAttributesInRange:NSMakeRange(0, [string length]) options:(NSAttributedStringEnumerationOptions)0 usingBlock:attributeEnumerationBlock];
+    [mutableString appendString:[string string]];
+    return [mutableString createJSStringRef];
+}
+
+JSStringRef AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
+{
+    id string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
+    return createJSStringRef(string);
+}
+
+JSStringRef AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange* markerRange, bool includeSpellCheck)
+{
+    id parameter = nil;
+    if (includeSpellCheck)
+        parameter = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:includeSpellCheck], @"AXSpellCheck", (id)markerRange->platformTextMarkerRange(), @"AXTextMarkerRange", nil];
+    else
+        parameter = (id)markerRange->platformTextMarkerRange();
+    id string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRangeWithOptions" forParameter:parameter];
+    return createJSStringRef(string);
+}
+
 AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
 {
     BEGIN_AX_OBJC_EXCEPTIONS

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h (229079 => 229080)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/AccessibilityUIElement.h	2018-02-27 22:57:14 UTC (rev 229080)
@@ -280,6 +280,8 @@
     RefPtr<AccessibilityTextMarker> nextTextMarker(AccessibilityTextMarker*);
     RefPtr<AccessibilityUIElement> accessibilityElementForTextMarker(AccessibilityTextMarker*);
     JSRetainPtr<JSStringRef> stringForTextMarkerRange(AccessibilityTextMarkerRange*);
+    JSRetainPtr<JSStringRef> attributedStringForTextMarkerRange(AccessibilityTextMarkerRange*);
+    JSRetainPtr<JSStringRef> attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange*, bool);
     int textMarkerRangeLength(AccessibilityTextMarkerRange*);
     bool attributedStringForTextMarkerRangeContainsAttribute(JSStringRef, AccessibilityTextMarkerRange*);
     int indexForTextMarker(AccessibilityTextMarker*);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl (229079 => 229080)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/AccessibilityUIElement.idl	2018-02-27 22:57:14 UTC (rev 229080)
@@ -209,6 +209,8 @@
     AccessibilityTextMarker nextTextMarker(AccessibilityTextMarker marker);
     AccessibilityUIElement accessibilityElementForTextMarker(AccessibilityTextMarker marker);
     DOMString stringForTextMarkerRange(AccessibilityTextMarkerRange range);
+    DOMString attributedStringForTextMarkerRange(AccessibilityTextMarkerRange range);
+    DOMString attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange range, boolean includeSpellCheck);
     long textMarkerRangeLength(AccessibilityTextMarkerRange range);
     boolean attributedStringForTextMarkerRangeContainsAttribute(DOMString attr, AccessibilityTextMarkerRange range);
     long indexForTextMarker(AccessibilityTextMarker marker);

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp (229079 => 229080)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/atk/AccessibilityUIElementAtk.cpp	2018-02-27 22:57:14 UTC (rev 229080)
@@ -2215,6 +2215,16 @@
     return nullptr;
 }
 
+JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange*)
+{
+    return nullptr;
+}
+
+JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange*, bool)
+{
+    return nullptr;
+}
+
 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
 {
     // FIXME: implement

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm (229079 => 229080)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/ios/AccessibilityUIElementIOS.mm	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1123,6 +1123,16 @@
     return nullptr;
 }
 
+JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
+{
+    return nullptr;
+}
+
+JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange* markerRange, bool)
+{
+    return nullptr;
+}
+
 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
 {
     return false;

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm (229079 => 229080)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm	2018-02-27 22:35:47 UTC (rev 229079)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/AccessibilityUIElementMac.mm	2018-02-27 22:57:14 UTC (rev 229080)
@@ -1806,7 +1806,60 @@
     
     return nullptr;
 }
-    
+
+static JSStringRef createJSStringRef(id string)
+{
+    id mutableString = [[[NSMutableString alloc] init] autorelease];
+    id attributes = [string attributesAtIndex:0 effectiveRange:nil];
+    id attributeEnumerationBlock = ^(NSDictionary<NSString *, id> *attrs, NSRange range, BOOL *stop) {
+        BOOL misspelled = [[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue];
+        if (misspelled)
+            misspelled = [[attrs objectForKey:NSAccessibilityMarkedMisspelledTextAttribute] boolValue];
+        if (misspelled)
+            [mutableString appendString:@"Misspelled, "];
+        id font = [attributes objectForKey:(id)kAXFontTextAttribute];
+        if (font)
+            [mutableString appendFormat:@"%@ - %@, ", (id)kAXFontTextAttribute, font];
+    };
+    [string enumerateAttributesInRange:NSMakeRange(0, [string length]) options:(NSAttributedStringEnumerationOptions)0 usingBlock:attributeEnumerationBlock];
+    [mutableString appendString:[string string]];
+    return [mutableString createJSStringRef];
+}
+
+JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRange(AccessibilityTextMarkerRange* markerRange)
+{
+    NSAttributedString* string = nil;
+
+    BEGIN_AX_OBJC_EXCEPTIONS
+    string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRange" forParameter:(id)markerRange->platformTextMarkerRange()];
+    END_AX_OBJC_EXCEPTIONS
+
+    if (![string isKindOfClass:[NSAttributedString class]])
+        return nil;
+
+    return createJSStringRef(string);
+}
+
+JSRetainPtr<JSStringRef> AccessibilityUIElement::attributedStringForTextMarkerRangeWithOptions(AccessibilityTextMarkerRange* markerRange, bool includeSpellCheck)
+{
+    NSAttributedString* string = nil;
+
+    id parameter = nil;
+    if (includeSpellCheck)
+        parameter = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:includeSpellCheck], @"AXSpellCheck", (id)markerRange->platformTextMarkerRange(), @"AXTextMarkerRange", nil];
+    else
+        parameter = (id)markerRange->platformTextMarkerRange();
+
+    BEGIN_AX_OBJC_EXCEPTIONS
+    string = [m_element accessibilityAttributeValue:@"AXAttributedStringForTextMarkerRangeWithOptions" forParameter:parameter];
+    END_AX_OBJC_EXCEPTIONS
+
+    if (![string isKindOfClass:[NSAttributedString class]])
+        return nil;
+
+    return createJSStringRef(string);
+}
+
 bool AccessibilityUIElement::attributedStringForTextMarkerRangeContainsAttribute(JSStringRef attribute, AccessibilityTextMarkerRange* range)
 {
     BEGIN_AX_OBJC_EXCEPTIONS
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to