• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2012 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from telemetry.internal.actions import page_action
6from telemetry.internal.actions import utils
7from telemetry.util import js_template
8
9
10class ScrollAction(page_action.PageAction):
11  # TODO(chrishenry): Ignore attributes, to be deleted when usage in
12  # other repo is cleaned up.
13  def __init__(self, selector=None, text=None, element_function=None,
14               left_start_ratio=0.5, top_start_ratio=0.5, direction='down',
15               distance=None, distance_expr=None,
16               speed_in_pixels_per_second=800, use_touch=False,
17               synthetic_gesture_source=page_action.GESTURE_SOURCE_DEFAULT):
18    super(ScrollAction, self).__init__()
19    if direction not in ('down', 'up', 'left', 'right',
20                         'downleft', 'downright',
21                         'upleft', 'upright'):
22      raise page_action.PageActionNotSupported(
23          'Invalid scroll direction: %s' % self.direction)
24    self._selector = selector
25    self._text = text
26    self._element_function = element_function
27    self._left_start_ratio = left_start_ratio
28    self._top_start_ratio = top_start_ratio
29    self._direction = direction
30    self._speed = speed_in_pixels_per_second
31    self._use_touch = use_touch
32    self._synthetic_gesture_source = ('chrome.gpuBenchmarking.%s_INPUT' %
33                                      synthetic_gesture_source)
34
35    self._distance_func = js_template.RenderValue(None)
36    if distance:
37      assert not distance_expr
38      distance_expr = str(distance)
39    if distance_expr:
40      self._distance_func = js_template.Render(
41          'function() { return 0 + {{ @expr }}; }', expr=distance_expr)
42
43  def WillRunAction(self, tab):
44    if self._direction in ('downleft', 'downright', 'upleft', 'upright'):
45      # Diagonal scrolling support was added in Chrome branch number 2332.
46      branch_num = (
47          tab.browser._browser_backend.devtools_client.GetChromeBranchNumber())
48      if branch_num < 2332:
49        raise ValueError('Diagonal scrolling requires Chrome branch number'
50                         ' 2332 or later. Found branch number %d' %
51                         branch_num)
52    utils.InjectJavaScript(tab, 'gesture_common.js')
53    utils.InjectJavaScript(tab, 'scroll.js')
54
55    # Fail if browser doesn't support synthetic scroll gestures.
56    if not tab.EvaluateJavaScript(
57        'window.__ScrollAction_SupportedByBrowser()'):
58      raise page_action.PageActionNotSupported(
59          'Synthetic scroll not supported for this browser')
60
61    # Fail if this action requires touch and we can't send touch events.
62    if self._use_touch:
63      if not page_action.IsGestureSourceTypeSupported(tab, 'touch'):
64        raise page_action.PageActionNotSupported(
65            'Touch scroll not supported for this browser')
66
67      if (self._synthetic_gesture_source ==
68          'chrome.gpuBenchmarking.MOUSE_INPUT'):
69        raise page_action.PageActionNotSupported(
70            'Scroll requires touch on this page but mouse input was requested')
71
72    tab.ExecuteJavaScript("""
73        window.__scrollActionDone = false;
74        window.__scrollAction = new __ScrollAction(
75            {{ @callback }}, {{ @distance }});""",
76        callback='function() { window.__scrollActionDone = true; }',
77        distance=self._distance_func)
78
79  def RunAction(self, tab):
80    if (self._selector is None and self._text is None and
81        self._element_function is None):
82      self._element_function = '(document.scrollingElement || document.body)'
83
84    gesture_source_type = self._synthetic_gesture_source
85    if self._use_touch:
86      gesture_source_type = 'chrome.gpuBenchmarking.TOUCH_INPUT'
87
88    code = js_template.Render('''
89        function(element, info) {
90          if (!element) {
91            throw Error('Cannot find element: ' + info);
92          }
93          window.__scrollAction.start({
94            element: element,
95            left_start_ratio: {{ left_start_ratio }},
96            top_start_ratio: {{ top_start_ratio }},
97            direction: {{ direction }},
98            speed: {{ speed }},
99            gesture_source_type: {{ @gesture_source_type }}
100          });
101        }''',
102        left_start_ratio=self._left_start_ratio,
103        top_start_ratio=self._top_start_ratio,
104        direction=self._direction,
105        speed=self._speed,
106        gesture_source_type=gesture_source_type)
107    page_action.EvaluateCallbackWithElement(
108        tab, code, selector=self._selector, text=self._text,
109        element_function=self._element_function)
110    tab.WaitForJavaScriptCondition('window.__scrollActionDone', timeout=60)
111