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