1# Copyright 2014 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 7 8 9class ScrollBounceAction(page_action.PageAction): 10 def __init__(self, selector=None, text=None, element_function=None, 11 left_start_ratio=0.5, top_start_ratio=0.5, 12 direction='down', distance=100, 13 overscroll=10, repeat_count=10, 14 speed_in_pixels_per_second=400, 15 synthetic_gesture_source=page_action.GESTURE_SOURCE_DEFAULT): 16 super(ScrollBounceAction, self).__init__() 17 if direction not in ['down', 'up', 'left', 'right']: 18 raise page_action.PageActionNotSupported( 19 'Invalid scroll direction: %s' % self.direction) 20 self._selector = selector 21 self._text = text 22 self._element_function = element_function 23 self._left_start_ratio = left_start_ratio 24 self._top_start_ratio = top_start_ratio 25 # Should be big enough to do more than just hide the URL bar. 26 self._distance = distance 27 self._direction = direction 28 # This needs to be < height / repeat_count so we don't walk off the screen. 29 # We also probably don't want to spend more than a couple frames in 30 # overscroll since it may mask any synthetic delays. 31 self._overscroll = overscroll 32 # It's the transitions we really want to stress, make this big. 33 self._repeat_count = repeat_count 34 # 7 pixels per frame should be plenty of frames. 35 self._speed = speed_in_pixels_per_second 36 self._synthetic_gesture_source = ('chrome.gpuBenchmarking.%s_INPUT' % 37 synthetic_gesture_source) 38 39 if (self._selector is None and self._text is None and 40 self._element_function is None): 41 self._element_function = '(document.scrollingElement || document.body)' 42 43 def WillRunAction(self, tab): 44 utils.InjectJavaScript(tab, 'gesture_common.js') 45 utils.InjectJavaScript(tab, 'scroll_bounce.js') 46 47 # Fail if browser doesn't support synthetic scroll bounce gestures. 48 if not tab.EvaluateJavaScript( 49 'window.__ScrollBounceAction_SupportedByBrowser()'): 50 raise page_action.PageActionNotSupported( 51 'Synthetic scroll bounce not supported for this browser') 52 53 # Fail if we can't send touch events (bouncing is really only 54 # interesting for touch) 55 if not page_action.IsGestureSourceTypeSupported(tab, 'touch'): 56 raise page_action.PageActionNotSupported( 57 'Touch scroll not supported for this browser') 58 59 if (self._synthetic_gesture_source == 60 'chrome.gpuBenchmarking.MOUSE_INPUT'): 61 raise page_action.PageActionNotSupported( 62 'ScrollBounce page action does not support mouse input') 63 64 done_callback = 'function() { window.__scrollBounceActionDone = true; }' 65 tab.ExecuteJavaScript(""" 66 window.__scrollBounceActionDone = false; 67 window.__scrollBounceAction = new __ScrollBounceAction(%s);""" 68 % (done_callback)) 69 70 def RunAction(self, tab): 71 code = ''' 72 function(element, info) { 73 if (!element) { 74 throw Error('Cannot find element: ' + info); 75 } 76 window.__scrollBounceAction.start({ 77 element: element, 78 left_start_ratio: %s, 79 top_start_ratio: %s, 80 direction: '%s', 81 distance: %s, 82 overscroll: %s, 83 repeat_count: %s, 84 speed: %s 85 }); 86 }''' % (self._left_start_ratio, 87 self._top_start_ratio, 88 self._direction, 89 self._distance, 90 self._overscroll, 91 self._repeat_count, 92 self._speed) 93 page_action.EvaluateCallbackWithElement( 94 tab, code, selector=self._selector, text=self._text, 95 element_function=self._element_function) 96 tab.WaitForJavaScriptExpression('window.__scrollBounceActionDone', 60) 97