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. 4import os 5 6from telemetry.internal.actions import page_action 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 for js_file in ['gesture_common.js', 'scroll_bounce.js']: 45 with open(os.path.join(os.path.dirname(__file__), js_file)) as f: 46 js = f.read() 47 tab.ExecuteJavaScript(js) 48 49 # Fail if browser doesn't support synthetic scroll bounce gestures. 50 if not tab.EvaluateJavaScript( 51 'window.__ScrollBounceAction_SupportedByBrowser()'): 52 raise page_action.PageActionNotSupported( 53 'Synthetic scroll bounce not supported for this browser') 54 55 # Fail if we can't send touch events (bouncing is really only 56 # interesting for touch) 57 if not page_action.IsGestureSourceTypeSupported(tab, 'touch'): 58 raise page_action.PageActionNotSupported( 59 'Touch scroll not supported for this browser') 60 61 if (self._synthetic_gesture_source == 62 'chrome.gpuBenchmarking.MOUSE_INPUT'): 63 raise page_action.PageActionNotSupported( 64 'ScrollBounce page action does not support mouse input') 65 66 done_callback = 'function() { window.__scrollBounceActionDone = true; }' 67 tab.ExecuteJavaScript(""" 68 window.__scrollBounceActionDone = false; 69 window.__scrollBounceAction = new __ScrollBounceAction(%s);""" 70 % (done_callback)) 71 72 def RunAction(self, tab): 73 code = ''' 74 function(element, info) { 75 if (!element) { 76 throw Error('Cannot find element: ' + info); 77 } 78 window.__scrollBounceAction.start({ 79 element: element, 80 left_start_ratio: %s, 81 top_start_ratio: %s, 82 direction: '%s', 83 distance: %s, 84 overscroll: %s, 85 repeat_count: %s, 86 speed: %s 87 }); 88 }''' % (self._left_start_ratio, 89 self._top_start_ratio, 90 self._direction, 91 self._distance, 92 self._overscroll, 93 self._repeat_count, 94 self._speed) 95 page_action.EvaluateCallbackWithElement( 96 tab, code, selector=self._selector, text=self._text, 97 element_function=self._element_function) 98 tab.WaitForJavaScriptExpression('window.__scrollBounceActionDone', 60) 99