146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)# Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)# found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import re 65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfrom telemetry import decorators 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PageActionNotSupported(Exception): 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pass 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PageActionFailed(Exception): 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pass 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PageAction(object): 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Represents an action that a user might try to perform to a page.""" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def WillRunAction(self, tab): 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) """Override to do action-specific setup before 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Test.WillRunAction is called.""" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pass 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def RunAction(self, tab): 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) raise NotImplementedError() 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def CleanUp(self, tab): 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pass 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def EvaluateCallbackWithElement( 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tab, callback_js, selector=None, text=None, element_function=None, 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch wait=False, timeout_in_seconds=60): 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) """Evaluates the JavaScript callback with the given element. 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) The element may be selected via selector, text, or element_function. 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Only one of these arguments must be specified. 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Returns: 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) The callback's return value, if any. The return value must be 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) convertible to JSON. 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Args: 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) tab: A telemetry.core.Tab object. 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) callback_js: The JavaScript callback to call (as string). 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) The callback receive 2 parameters: the element, and information 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) string about what method was used to retrieve the element. 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Example: ''' 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function(element, info) { 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!element) { 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) throw Error('Can not find element: ' + info); 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) element.click() 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }''' 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) selector: A CSS selector describing the element. 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) text: The element must contains this exact text. 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) element_function: A JavaScript function (as string) that is used 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) to retrieve the element. For example: 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) '(function() { return foo.element; })()'. 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) wait: Whether to wait for the return value to be true. 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch timeout_in_seconds: The timeout for wait (if waiting). 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) """ 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) count = 0 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) info_msg = '' 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if element_function is not None: 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) count = count + 1 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) info_msg = 'using element_function "%s"' % re.escape(element_function) 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if selector is not None: 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) count = count + 1 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) info_msg = 'using selector "%s"' % _EscapeSelector(selector) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) element_function = 'document.querySelector(\'%s\')' % _EscapeSelector( 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) selector) 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if text is not None: 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) count = count + 1 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) info_msg = 'using exact text match "%s"' % re.escape(text) 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) element_function = ''' 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (function() { 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) function _findElement(element, text) { 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (element.innerHTML == text) { 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return element; 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var childNodes = element.childNodes; 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for (var i = 0, len = childNodes.length; i < len; ++i) { 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var found = _findElement(childNodes[i], text); 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (found) { 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return found; 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return null; 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return _findElement(document, '%s'); 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) })()''' % text 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if count != 1: 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) raise PageActionFailed( 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'Must specify 1 way to retrieve element, but %s was specified.' % count) 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) code = ''' 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (function() { 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var element = %s; 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) var callback = %s; 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return callback(element, '%s'); 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) })()''' % (element_function, callback_js, info_msg) 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if wait: 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tab.WaitForJavaScriptExpression(code, timeout_in_seconds) 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return True 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) else: 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return tab.EvaluateJavaScript(code) 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def _EscapeSelector(selector): 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return selector.replace('\'', '\\\'') 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdochdef GetGestureSourceTypeFromOptions(tab): 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gesture_source_type = tab.browser.synthetic_gesture_source_type 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 'chrome.gpuBenchmarking.' + gesture_source_type.upper() + '_INPUT' 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch@decorators.Cache 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdochdef IsGestureSourceTypeSupported(tab, gesture_source_type): 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # TODO(dominikg): remove once support for 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # 'chrome.gpuBenchmarking.gestureSourceTypeSupported' has 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch # been rolled into reference build. 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if tab.EvaluateJavaScript(""" 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch typeof chrome.gpuBenchmarking.gestureSourceTypeSupported === 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 'undefined'"""): 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (tab.browser.platform.GetOSName() != 'mac' or 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gesture_source_type.lower() != 'touch') 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return tab.EvaluateJavaScript(""" 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chrome.gpuBenchmarking.gestureSourceTypeSupported( 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chrome.gpuBenchmarking.%s_INPUT)""" 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch % (gesture_source_type.upper())) 134