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 py_trace_event import trace_event 6 7from telemetry import decorators 8from telemetry.util import js_template 9 10 11GESTURE_SOURCE_DEFAULT = 'DEFAULT' 12GESTURE_SOURCE_MOUSE = 'MOUSE' 13GESTURE_SOURCE_TOUCH = 'TOUCH' 14SUPPORTED_GESTURE_SOURCES = (GESTURE_SOURCE_DEFAULT, 15 GESTURE_SOURCE_MOUSE, 16 GESTURE_SOURCE_TOUCH) 17 18class PageActionNotSupported(Exception): 19 pass 20 21class PageActionFailed(Exception): 22 pass 23 24 25class PageAction(object): 26 """Represents an action that a user might try to perform to a page.""" 27 28 __metaclass__ = trace_event.TracedMetaClass 29 30 def WillRunAction(self, tab): 31 """Override to do action-specific setup before 32 Test.WillRunAction is called.""" 33 pass 34 35 def RunAction(self, tab): 36 raise NotImplementedError() 37 38 def CleanUp(self, tab): 39 pass 40 41def EvaluateCallbackWithElement( 42 tab, callback_js, selector=None, text=None, element_function=None, 43 wait=False, timeout_in_seconds=60): 44 """Evaluates the JavaScript callback with the given element. 45 46 The element may be selected via selector, text, or element_function. 47 Only one of these arguments must be specified. 48 49 Returns: 50 The callback's return value, if any. The return value must be 51 convertible to JSON. 52 53 Args: 54 tab: A telemetry.core.Tab object. 55 callback_js: The JavaScript callback to call (as string). 56 The callback receive 2 parameters: the element, and information 57 string about what method was used to retrieve the element. 58 Example: ''' 59 function(element, info) { 60 if (!element) { 61 throw Error('Can not find element: ' + info); 62 } 63 element.click() 64 }''' 65 selector: A CSS selector describing the element. 66 text: The element must contains this exact text. 67 element_function: A JavaScript function (as string) that is used 68 to retrieve the element. For example: 69 '(function() { return foo.element; })()'. 70 wait: Whether to wait for the return value to be true. 71 timeout_in_seconds: The timeout for wait (if waiting). 72 """ 73 count = 0 74 info_msg = '' 75 if element_function is not None: 76 count = count + 1 77 info_msg = js_template.Render( 78 'using element_function: {{ @code }}', code=element_function) 79 if selector is not None: 80 count = count + 1 81 info_msg = js_template.Render( 82 'using selector {{ selector }}', selector=selector) 83 element_function = js_template.Render( 84 'document.querySelector({{ selector }})', selector=selector) 85 if text is not None: 86 count = count + 1 87 info_msg = js_template.Render( 88 'using exact text match {{ text }}', text=text) 89 element_function = js_template.Render(''' 90 (function() { 91 function _findElement(element, text) { 92 if (element.innerHTML == text) { 93 return element; 94 } 95 96 var childNodes = element.childNodes; 97 for (var i = 0, len = childNodes.length; i < len; ++i) { 98 var found = _findElement(childNodes[i], text); 99 if (found) { 100 return found; 101 } 102 } 103 return null; 104 } 105 return _findElement(document, {{ text }}); 106 })()''', 107 text=text) 108 109 if count != 1: 110 raise PageActionFailed( 111 'Must specify 1 way to retrieve element, but %s was specified.' % count) 112 113 code = js_template.Render(''' 114 (function() { 115 var element = {{ @element_function }}; 116 var callback = {{ @callback_js }}; 117 return callback(element, {{ info_msg }}); 118 })()''', 119 element_function=element_function, 120 callback_js=callback_js, 121 info_msg=info_msg) 122 123 if wait: 124 tab.WaitForJavaScriptCondition(code, timeout=timeout_in_seconds) 125 return True 126 else: 127 return tab.EvaluateJavaScript(code) 128 129 130@decorators.Cache 131def IsGestureSourceTypeSupported(tab, gesture_source_type): 132 # TODO(dominikg): remove once support for 133 # 'chrome.gpuBenchmarking.gestureSourceTypeSupported' has 134 # been rolled into reference build. 135 if tab.EvaluateJavaScript(""" 136 typeof chrome.gpuBenchmarking.gestureSourceTypeSupported === 137 'undefined'"""): 138 return (tab.browser.platform.GetOSName() != 'mac' or 139 gesture_source_type.lower() != 'touch') 140 141 return tab.EvaluateJavaScript(""" 142 chrome.gpuBenchmarking.gestureSourceTypeSupported( 143 chrome.gpuBenchmarking.{{ @gesture_source_type }}_INPUT)""", 144 gesture_source_type=gesture_source_type.upper()) 145