Bug 1253989 Part 5 - Remove touch caret and selection carets naming. r?mtseng draft
authorTing-Yu Lin <tlin@mozilla.com>
Tue, 08 Mar 2016 22:45:47 +0800
changeset 338121 e690b6a6d4004e29905b46416b9d69c8973b81ee
parent 338120 36a3b753490f5949f0ae382cae429dc80dff0287
child 338122 5db5132dfdcdde5e9da8cbef4e10d7cdf739ae89
push id12434
push usertlin@mozilla.com
push dateTue, 08 Mar 2016 14:46:18 +0000
reviewersmtseng
bugs1253989
milestone48.0a1
Bug 1253989 Part 5 - Remove touch caret and selection carets naming. r?mtseng - To avoid confusion, call the blinking cursor (nsCaret) "cursor" so that AccessibleCaret can be called caret for short. - Add second_caret_location() as a helper function, and use it in selection mode tests. MozReview-Commit-ID: IKN6KuR92HE
layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
testing/marionette/client/marionette_driver/selection.py
--- a/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
+++ b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
@@ -46,82 +46,82 @@ class AccessibleCaretCursorModeTestCase(
     def test_move_cursor_to_the_right_by_one_character(self, el_id):
         self.open_test_html()
         el = self.marionette.find_element(By.ID, el_id)
         sel = SelectionManager(el)
         content_to_add = '!'
         target_content = sel.content
         target_content = target_content[:1] + content_to_add + target_content[1:]
 
-        # Get touch caret (x, y) at position 1 and 2.
+        # Get first caret (x, y) at position 1 and 2.
         el.tap()
-        sel.move_caret_to_front()
-        caret0_x, caret0_y = sel.caret_location()
-        touch_caret0_x, touch_caret0_y = sel.touch_caret_location()
-        sel.move_caret_by_offset(1)
-        touch_caret1_x, touch_caret1_y = sel.touch_caret_location()
+        sel.move_cursor_to_front()
+        cursor0_x, cursor0_y = sel.cursor_location()
+        first_caret0_x, first_caret0_y = sel.first_caret_location()
+        sel.move_cursor_by_offset(1)
+        first_caret1_x, first_caret1_y = sel.first_caret_location()
 
-        # Tap the front of the input to make touch caret appear.
-        el.tap(caret0_x, caret0_y)
+        # Tap the front of the input to make first caret appear.
+        el.tap(cursor0_x, cursor0_y)
 
-        # Move touch caret
-        self.actions.flick(el, touch_caret0_x, touch_caret0_y,
-                           touch_caret1_x, touch_caret1_y).perform()
+        # Move first caret.
+        self.actions.flick(el, first_caret0_x, first_caret0_y,
+                           first_caret1_x, first_caret1_y).perform()
 
         self.actions.key_down(content_to_add).key_up(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_textarea_id, el_id=_textarea_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     def test_move_cursor_to_end_by_dragging_caret_to_bottom_right_corner(self, el_id):
         self.open_test_html()
         el = self.marionette.find_element(By.ID, el_id)
         sel = SelectionManager(el)
         content_to_add = '!'
         target_content = sel.content + content_to_add
 
-        # Tap the front of the input to make touch caret appear.
+        # Tap the front of the input to make first caret appear.
         el.tap()
-        sel.move_caret_to_front()
-        el.tap(*sel.caret_location())
+        sel.move_cursor_to_front()
+        el.tap(*sel.cursor_location())
 
-        # Move touch caret to the bottom-right corner of the element.
-        src_x, src_y = sel.touch_caret_location()
+        # Move first caret to the bottom-right corner of the element.
+        src_x, src_y = sel.first_caret_location()
         dest_x, dest_y = el.size['width'], el.size['height']
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
         self.actions.key_down(content_to_add).key_up(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_textarea_id, el_id=_textarea_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
     def test_move_cursor_to_front_by_dragging_caret_to_front(self, el_id):
         self.open_test_html()
         el = self.marionette.find_element(By.ID, el_id)
         sel = SelectionManager(el)
         content_to_add = '!'
         target_content = content_to_add + sel.content
 
-        # Get touch caret location at the front.
+        # Get first caret location at the front.
         el.tap()
-        sel.move_caret_to_front()
-        dest_x, dest_y = sel.touch_caret_location()
+        sel.move_cursor_to_front()
+        dest_x, dest_y = sel.first_caret_location()
 
-        # Tap to make touch caret appear. Note: it's strange that when the caret
+        # Tap to make first caret appear. Note: it's strange that when the caret
         # is at the end, the rect of the caret in <textarea> cannot be obtained.
         # A bug perhaps.
         el.tap()
-        sel.move_caret_to_end()
-        sel.move_caret_by_offset(1, backward=True)
-        el.tap(*sel.caret_location())
-        src_x, src_y = sel.touch_caret_location()
+        sel.move_cursor_to_end()
+        sel.move_cursor_by_offset(1, backward=True)
+        el.tap(*sel.cursor_location())
+        src_x, src_y = sel.first_caret_location()
 
-        # Move touch caret to the front of the input box.
+        # Move first caret to the front of the input box.
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
         self.actions.key_down(content_to_add).key_up(content_to_add).perform()
         self.assertEqual(target_content, sel.content)
 
     @parameterized(_input_id, el_id=_input_id)
     @parameterized(_textarea_id, el_id=_textarea_id)
     @parameterized(_contenteditable_id, el_id=_contenteditable_id)
@@ -134,51 +134,51 @@ class AccessibleCaretCursorModeTestCase(
 
         # Set caret timeout to be 1 second.
         timeout = 1
         self.marionette.set_pref(self.caret_timeout_ms_pref, timeout * 1000)
 
         # Set a 3x timeout margin to prevent intermittent test failures.
         timeout *= 3
 
-        # Tap to make touch caret appear. Note: it's strange that when the caret
+        # Tap to make first caret appear. Note: it's strange that when the caret
         # is at the end, the rect of the caret in <textarea> cannot be obtained.
         # A bug perhaps.
         el.tap()
-        sel.move_caret_to_end()
-        sel.move_caret_by_offset(1, backward=True)
-        el.tap(*sel.caret_location())
+        sel.move_cursor_to_end()
+        sel.move_cursor_by_offset(1, backward=True)
+        el.tap(*sel.cursor_location())
 
-        # Wait until touch caret disappears, then pretend to move it to the
+        # Wait until first caret disappears, then pretend to move it to the
         # top-left corner of the input box.
-        src_x, src_y = sel.touch_caret_location()
+        src_x, src_y = sel.first_caret_location()
         dest_x, dest_y = 0, 0
         self.actions.wait(timeout).flick(el, src_x, src_y, dest_x, dest_y).perform()
 
         self.actions.key_down(content_to_add).key_up(content_to_add).perform()
         self.assertNotEqual(non_target_content, sel.content)
 
     def test_caret_not_appear_when_typing_in_scrollable_content(self):
         self.open_test_html()
         el = self.marionette.find_element(By.ID, self._input_id)
         sel = SelectionManager(el)
         content_to_add = '!'
         target_content = sel.content + string.ascii_letters + content_to_add
 
         el.tap()
-        sel.move_caret_to_end()
+        sel.move_cursor_to_end()
 
         # Insert a long string to the end of the <input>, which triggers
         # ScrollPositionChanged event.
         el.send_keys(string.ascii_letters)
 
         # The caret should not be visible. If it does appear wrongly due to the
         # ScrollPositionChanged event, we can drag it to the front of the
         # <input> to change the cursor position.
-        src_x, src_y = sel.touch_caret_location()
+        src_x, src_y = sel.first_caret_location()
         dest_x, dest_y = 0, 0
         self.actions.flick(el, src_x, src_y, dest_x, dest_y).perform()
 
         # The content should be inserted at the end of the <input>.
         el.send_keys(content_to_add)
 
         self.assertEqual(target_content, sel.content)
 
@@ -187,16 +187,16 @@ class AccessibleCaretCursorModeTestCase(
         el = self.marionette.find_element(By.ID, self._input_id)
         sel = SelectionManager(el)
         content_to_add = '!'
         non_target_content = sel.content + content_to_add
 
         # Goal: the cursor position does not being changed after dragging the
         # caret down on the Y-axis.
         el.tap()
-        sel.move_caret_to_front()
-        el.tap(*sel.caret_location())
-        x, y = sel.touch_caret_location()
+        sel.move_cursor_to_front()
+        el.tap(*sel.cursor_location())
+        x, y = sel.first_caret_location()
 
         # Drag the caret down by 50px, and insert '!'.
         self.actions.flick(el, x, y, x, y + 50).perform()
         self.actions.key_down(content_to_add).key_up(content_to_add).perform()
         self.assertNotEqual(non_target_content, sel.content)
--- a/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
+++ b/layout/base/tests/marionette/test_accessiblecaret_selection_mode.py
@@ -91,19 +91,19 @@ class AccessibleCaretSelectionModeTestCa
         target element el.
 
         '''
         sel = SelectionManager(el)
         offset = self.word_offset(sel.content, ordinal)
 
         # Move the blinking cursor to the word.
         el.tap()
-        sel.move_caret_to_front()
-        sel.move_caret_by_offset(offset)
-        x, y = sel.caret_location()
+        sel.move_cursor_to_front()
+        sel.move_cursor_by_offset(offset)
+        x, y = sel.cursor_location()
 
         return x, y
 
     def rect_relative_to_window(self, el):
         '''Get element's bounding rectangle.
 
         This function is similar to el.rect, but the coordinate is relative to
         the top left corner of the window instead of the document.
@@ -183,26 +183,26 @@ class AccessibleCaretSelectionModeTestCa
         sel = SelectionManager(el)
         original_content = sel.content
         words = original_content.split()
         self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
 
         # Goal: Select all text after the first word.
         target_content = original_content[len(words[0]):]
 
-        # Get the location of the selection carets at the end of the content for
-        # later use.
+        # Get the location of the carets at the end of the content for later
+        # use.
         el.tap()
         sel.select_all()
-        (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location()
+        end_caret_x, end_caret_y = sel.second_caret_location()
 
         self.long_press_on_word(el, 0)
 
         # Drag the second caret to the end of the content.
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform()
 
         # Drag the first caret to the previous position of the second caret.
         self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform()
 
         self.assertEqual(target_content, sel.selected_content)
 
     @parameterized(_input_id, el_id=_input_id)
@@ -224,39 +224,39 @@ class AccessibleCaretSelectionModeTestCa
         self._test_minimum_select_one_character(el)
 
     def _test_minimum_select_one_character(self, el, x=None, y=None):
         sel = SelectionManager(el)
         original_content = sel.content
         words = original_content.split()
         self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
 
-        # Get the location of the selection carets at the end of the content for
-        # later use.
+        # Get the location of the carets at the end of the content for later
+        # use.
         sel.select_all()
-        (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location()
+        end_caret_x, end_caret_y = sel.second_caret_location()
         el.tap()
 
         # Goal: Select the first character.
         target_content = original_content[0]
 
         if x and y:
             # If we got x and y from the arguments, use it as a hint of the
             # location of the first word
             pass
         else:
             x, y = self.word_location(el, 0)
         self.long_press_on_location(el, x, y)
 
         # Drag the second caret to the end of the content.
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform()
 
         # Drag the second caret to the position of the first caret.
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform()
 
         self.assertEqual(target_content, sel.selected_content)
 
     @parameterized(_input_id + '_to_' + _textarea_id,
                    el1_id=_input_id, el2_id=_textarea_id)
     @parameterized(_input_id + '_to_' + _contenteditable_id,
                    el1_id=_input_id, el2_id=_contenteditable_id)
@@ -338,24 +338,24 @@ class AccessibleCaretSelectionModeTestCa
         self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
 
         # Goal: Select the first word.
         self.long_press_on_word(el, 0)
         target_content = sel.selected_content
 
         # Drag the first caret to the position of the second caret to trigger
         # carets overlapping.
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform()
 
         # We make two hit tests targeting the left edge of the left tilted caret
         # and the right edge of the right tilted caret. If either of the hits is
         # missed, selection would be collapsed and both carets should not be
         # draggable.
-        (caret3_x, caret3_y), (caret4_x, caret4_y) = sel.selection_carets_location()
+        (caret3_x, caret3_y), (caret4_x, caret4_y) = sel.carets_location()
 
         # The following values are from ua.css and all.js
         caret_width = float(self.marionette.get_pref('layout.accessiblecaret.width'))
         caret_margin_left = float(self.marionette.get_pref('layout.accessiblecaret.margin-left'))
         tilt_right_margin_left = 0.41 * caret_width
         tilt_left_margin_left = -0.39 * caret_width
 
         left_caret_left_edge_x = caret3_x + caret_margin_left + tilt_left_margin_left
@@ -366,72 +366,75 @@ class AccessibleCaretSelectionModeTestCa
         el.tap(right_caret_right_edge_x - 2, caret4_y)
 
         # Drag the first caret back to the initial selection, the first word.
         self.actions.flick(el, caret3_x, caret3_y, caret1_x, caret1_y).perform()
 
         self.assertEqual(target_content, sel.selected_content)
 
     def test_drag_caret_over_non_selectable_field(self):
-        '''Testing drag caret over non selectable field.
-        So that the selected content should exclude non selectable field and
-        end selection caret should appear in last range's position.'''
+        '''Test dragging the caret over a non-selectable field.
+
+        The selected content should exclude non-selectable elements and the
+        second caret should appear in last range's position.
+
+        '''
         self.open_test_html_multirange()
         body = self.marionette.find_element(By.ID, 'bd')
         sel3 = self.marionette.find_element(By.ID, 'sel3')
         sel4 = self.marionette.find_element(By.ID, 'sel4')
         sel6 = self.marionette.find_element(By.ID, 'sel6')
 
         # Select target element and get target caret location
         self.long_press_on_word(sel4, 3)
         sel = SelectionManager(body)
-        (_, _), (end_caret_x, end_caret_y) = sel.selection_carets_location()
+        end_caret_x, end_caret_y = sel.second_caret_location()
 
         self.long_press_on_word(sel6, 0)
-        (_, _), (end_caret2_x, end_caret2_y) = sel.selection_carets_location()
+        end_caret2_x, end_caret2_y = sel.second_caret_location()
 
         # Select start element
         self.long_press_on_word(sel3, 3)
 
         # Drag end caret to target location
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(body, caret2_x, caret2_y, end_caret_x, end_caret_y, 1).perform()
         self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
                          'this 3\nuser can select this')
 
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(body, caret2_x, caret2_y, end_caret2_x, end_caret2_y, 1).perform()
         self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
                          'this 3\nuser can select this 4\nuser can select this 5\nuser')
 
         # Drag first caret to target location
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(body, caret1_x, caret1_y, end_caret_x, end_caret_y, 1).perform()
         self.assertEqual(self.to_unix_line_ending(sel.selected_content.strip()),
                          '4\nuser can select this 5\nuser')
 
     def test_drag_caret_to_beginning_of_a_line(self):
         '''Bug 1094056
         Test caret visibility when caret is dragged to beginning of a line
         '''
         self.open_test_html_multirange()
         body = self.marionette.find_element(By.ID, 'bd')
         sel1 = self.marionette.find_element(By.ID, 'sel1')
         sel2 = self.marionette.find_element(By.ID, 'sel2')
 
         # Select the first word in the second line
         self.long_press_on_word(sel2, 0)
         sel = SelectionManager(body)
-        (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.selection_carets_location()
+        (start_caret_x, start_caret_y), (end_caret_x, end_caret_y) = sel.carets_location()
 
         # Select target word in the first line
         self.long_press_on_word(sel1, 2)
 
         # Drag end caret to the beginning of the second line
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(body, caret2_x, caret2_y, start_caret_x, start_caret_y).perform()
 
         # Drag end caret back to the target word
         self.actions.flick(body, start_caret_x, start_caret_y, caret2_x, caret2_y).perform()
 
         self.assertEqual(self.to_unix_line_ending(sel.selected_content), 'select')
 
     @skip_if_not_rotatable
@@ -444,19 +447,19 @@ class AccessibleCaretSelectionModeTestCa
 
         body = self.marionette.find_element(By.ID, 'bd')
         longtext = self.marionette.find_element(By.ID, 'longtext')
 
         # Select word in portrait mode, then change to landscape mode
         self.marionette.set_orientation('portrait')
         self.long_press_on_word(longtext, 12)
         sel = SelectionManager(body)
-        (p_start_caret_x, p_start_caret_y), (p_end_caret_x, p_end_caret_y) = sel.selection_carets_location()
+        (p_start_caret_x, p_start_caret_y), (p_end_caret_x, p_end_caret_y) = sel.carets_location()
         self.marionette.set_orientation('landscape')
-        (l_start_caret_x, l_start_caret_y), (l_end_caret_x, l_end_caret_y) = sel.selection_carets_location()
+        (l_start_caret_x, l_start_caret_y), (l_end_caret_x, l_end_caret_y) = sel.carets_location()
 
         # Drag end caret to the start caret to change the selected content
         self.actions.flick(body, l_end_caret_x, l_end_caret_y,
                            l_start_caret_x, l_start_caret_y).perform()
 
         # Change orientation back to portrait mode to prevent affecting
         # other tests
         self.marionette.set_orientation('portrait')
@@ -534,34 +537,34 @@ class AccessibleCaretSelectionModeTestCa
         self.assertEqual(words[1], sel.selected_content)
 
         self.long_press_on_location(el, word0_x, word0_y)
         self.assertEqual(words[0], sel.selected_content)
 
         # If the second carets is visible, it can be dragged to the position of
         # the first caret. After that, selection will contain only the first
         # character.
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
         self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform()
         self.assertEqual(words[0][0], sel.selected_content)
 
     def test_carets_do_not_jump_when_dragging_to_editable_content_boundary(self):
         self.open_test_html()
         el = self.marionette.find_element(By.ID, self._input_id)
         sel = SelectionManager(el)
         original_content = sel.content
         words = original_content.split()
         self.assertTrue(len(words) >= 3, 'Expect at least three words in the content.')
 
         # Goal: the selection does not being changed after dragging the caret
         # on the Y-axis only.
         target_content = words[1]
 
         self.long_press_on_word(el, 1)
-        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.carets_location()
 
         # Drag the first caret up by 50px.
         self.actions.flick(el, caret1_x, caret1_y, caret1_x, caret1_y - 50).perform()
         self.assertEqual(target_content, sel.selected_content)
 
         # Drag the first caret down by 50px.
         self.actions.flick(el, caret2_x, caret2_y, caret2_x, caret2_y + 50).perform()
         self.assertEqual(target_content, sel.selected_content)
--- a/testing/marionette/client/marionette_driver/selection.py
+++ b/testing/marionette/client/marionette_driver/selection.py
@@ -2,16 +2,19 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 class SelectionManager(object):
     '''Interface for manipulating the selection and carets of the element.
 
+    We call the blinking cursor (nsCaret) as cursor, and call AccessibleCaret as
+    caret for short.
+
     Simple usage example:
 
     ::
 
         element = marionette.find_element('id', 'input')
         sel = SelectionManager(element)
         sel.move_caret_to_front()
 
@@ -36,45 +39,45 @@ class SelectionManager(object):
         '''
         if self._input_or_textarea():
             # We must unwrap sel so that DOMRect could be returned to Python
             # side.
             return '''var sel = arguments[0].editor.selection;'''
         else:
             return '''var sel = window.getSelection();'''
 
-    def move_caret_by_offset(self, offset, backward=False):
-        '''Move caret in the element by character offset.
+    def move_cursor_by_offset(self, offset, backward=False):
+        '''Move cursor in the element by character offset.
 
-        :param offset: Move the caret to the direction by offset characters.
+        :param offset: Move the cursor to the direction by offset characters.
         :param backward: Optional, True to move backward; Default to False to
          move forward.
 
         '''
         cmd = self.js_selection_cmd() + '''
               for (let i = 0; i < %d; ++i) {
                   sel.modify("move", "%s", "character");
               }
               ''' % (offset, 'backward' if backward else 'forward')
 
         self.element.marionette.execute_script(
             cmd, script_args=[self.element], sandbox='system')
 
-    def move_caret_to_front(self):
-        '''Move caret in the element to the front of the content.'''
+    def move_cursor_to_front(self):
+        '''Move cursor in the element to the front of the content.'''
         if self._input_or_textarea():
             cmd = '''arguments[0].setSelectionRange(0, 0);'''
         else:
             cmd = '''var sel = window.getSelection();
                   sel.collapse(arguments[0].firstChild, 0);'''
 
         self.element.marionette.execute_script(cmd, script_args=[self.element])
 
-    def move_caret_to_end(self):
-        '''Move caret in the element to the end of the content.'''
+    def move_cursor_to_end(self):
+        '''Move cursor in the element to the end of the content.'''
         if self._input_or_textarea():
             cmd = '''var len = arguments[0].value.length;
                   arguments[0].setSelectionRange(len, len);'''
         else:
             cmd = '''var sel = window.getSelection();
                   sel.collapse(arguments[0].lastChild, arguments[0].lastChild.length);'''
 
         self.element.marionette.execute_script(cmd, script_args=[self.element])
@@ -148,43 +151,52 @@ class SelectionManager(object):
         Return a tuple containing two pairs of (x, y) coordinates of the start
         and end of the selection. The coordinates are relative to the top
         left-hand corner of the element. Both ltr and rtl direction are
         considered.
 
         '''
         return self._selection_location_helper('center')
 
-    def selection_carets_location(self):
-        '''Return a pair of the two selection carets' location.
+    def carets_location(self):
+        '''Return a pair of the two carets' location.
 
         Return a tuple containing two pairs of (x, y) coordinates of the two
-        selection carets' tip. The coordinates are relative to the top left-hand
-        corner of the element. Both ltr and rtl direction are considered.
+        carets' tip. The coordinates are relative to the top left-hand corner of
+        the element. Both ltr and rtl direction are considered.
 
         '''
         return self._selection_location_helper('caret')
 
-    def caret_location(self):
-        '''Return caret's center location within the element.
+    def cursor_location(self):
+        '''Return the blanking cursor's center location within the element.
 
-        Return (x, y) coordinates of the caret's center relative to the top
+        Return (x, y) coordinates of the cursor's center relative to the top
         left-hand corner of the element.
 
         '''
         return self._selection_location_helper('center')[0]
 
-    def touch_caret_location(self):
-        '''Return touch caret's location (based on current caret location).
+    def first_caret_location(self):
+        '''Return the first caret's location.
 
-        Return (x, y) coordinates of the touch caret's tip relative to the top
+        Return (x, y) coordinates of the first caret's tip relative to the top
         left-hand corner of the element.
 
         '''
-        return self._selection_location_helper('caret')[0]
+        return self.carets_location()[0]
+
+    def second_caret_location(self):
+        '''Return the second caret's location.
+
+        Return (x, y) coordinates of the second caret's tip relative to the top
+        left-hand corner of the element.
+
+        '''
+        return self.carets_location()[1]
 
     def select_all(self):
         '''Select all the content in the element.'''
         if self._input_or_textarea():
             cmd = '''var len = arguments[0].value.length;
                   arguments[0].focus();
                   arguments[0].setSelectionRange(0, len);'''
         else: