Use text affinity to return correct accessible line boundaries.

Our calculations of line boundaries for accessibility were wrong
in certain cases where the character offset is ambiguous. It's
possible for there to be a line break immediately between two
characters, such that one character is on the previous line and
one is on the next line. If the character index is between those
two characters, previously we had no way of knowing if the cursor
was on the first line or second line.

Fix this by passing through the text affinity of the selection
focus and anchor from Blink all the way into Chrome's accessibility
tree. If the affinity is upstream, it means the cursor is on the
previous line, and downstream means the next line.

I added a LayoutTest for Blink and a unit test for Chrome. I also
manually verified this fixes at least one broken case with VoiceOver,
see the bug for a very specific repro.

BUG=632450

Review-Url: https://codereview.chromium.org/2191833003
Cr-Commit-Position: refs/heads/master@{#408989}
diff --git a/ui/accessibility/ax_text_utils_unittest.cc b/ui/accessibility/ax_text_utils_unittest.cc
index 2c7f491..0f1ad1d 100644
--- a/ui/accessibility/ax_text_utils_unittest.cc
+++ b/ui/accessibility/ax_text_utils_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_enums.h"
 #include "ui/accessibility/ax_text_utils.h"
 
 namespace ui {
@@ -19,37 +20,48 @@
   size_t result;
 
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      0, FORWARDS_DIRECTION);
+                                      0, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(6UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      5, BACKWARDS_DIRECTION);
+                                      5, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(0UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      6, FORWARDS_DIRECTION);
+                                      6, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(12UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      11, BACKWARDS_DIRECTION);
+                                      11, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(6UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      12, BACKWARDS_DIRECTION);
+                                      12, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(12UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      15, FORWARDS_DIRECTION);
+                                      15, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(17UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      15, BACKWARDS_DIRECTION);
+                                      15, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(12UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      16, FORWARDS_DIRECTION);
+                                      16, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(17UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      17, FORWARDS_DIRECTION);
+                                      17, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(20UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      20, FORWARDS_DIRECTION);
+                                      20, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(text_length, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, WORD_BOUNDARY,
-                                      text_length, BACKWARDS_DIRECTION);
+                                      text_length, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(20UL, result);
 }
 
@@ -63,48 +75,57 @@
 
   // Basic cases.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                      5, FORWARDS_DIRECTION);
+                                      5, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(8UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                       9, BACKWARDS_DIRECTION);
+                                      9, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(8UL, result);
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                       10, FORWARDS_DIRECTION);
+                                      10, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(15UL, result);
 
   // Edge cases.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                      text_length, BACKWARDS_DIRECTION);
+                                      text_length, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(15UL, result);
 
   // When the start_offset is at the start of the next line and we are searching
   // backwards, it should not move.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                       15, BACKWARDS_DIRECTION);
+                                      15, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(15UL, result);
 
   // When the start_offset is at a hard line break and we are searching
   // backwards, it should return the start of the previous line.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                       14, BACKWARDS_DIRECTION);
+                                      14, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(8UL, result);
 
   // When the start_offset is at the start of a line and we are searching
   // forwards, it should return the start of the next line.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                      8, FORWARDS_DIRECTION);
+                                      8, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(15UL, result);
 
   // When there is no previous line break and we are searching backwards,
   // it should return 0.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                      4, BACKWARDS_DIRECTION);
+                                      4, BACKWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(0UL, result);
 
   // When we are at the start of the last line and we are searching forwards.
   // it should return the text length.
   result = FindAccessibleTextBoundary(text, line_start_offsets, LINE_BOUNDARY,
-                                      15, FORWARDS_DIRECTION);
+                                      15, FORWARDS_DIRECTION,
+                                      AX_TEXT_AFFINITY_DOWNSTREAM);
   EXPECT_EQ(text_length, result);
 }