• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import re
6
7class PageActionNotSupported(Exception):
8  pass
9
10class PageActionFailed(Exception):
11  pass
12
13
14class PageAction(object):
15  """Represents an action that a user might try to perform to a page."""
16
17  def __init__(self, attributes=None):
18    if attributes:
19      for k, v in attributes.iteritems():
20        setattr(self, k, v)
21
22  def WillRunAction(self, tab):
23    """Override to do action-specific setup before
24    Test.WillRunAction is called."""
25    pass
26
27  def RunAction(self, tab):
28    raise NotImplementedError()
29
30  def CleanUp(self, tab):
31    pass
32
33
34def EvaluateCallbackWithElement(
35    tab, callback_js, selector=None, text=None, element_function=None,
36    wait=False, timeout=60):
37  """Evaluates the JavaScript callback with the given element.
38
39  The element may be selected via selector, text, or element_function.
40  Only one of these arguments must be specified.
41
42  Returns:
43    The callback's return value, if any. The return value must be
44    convertible to JSON.
45
46  Args:
47    tab: A telemetry.core.Tab object.
48    callback_js: The JavaScript callback to call (as string).
49        The callback receive 2 parameters: the element, and information
50        string about what method was used to retrieve the element.
51        Example: '''
52          function(element, info) {
53            if (!element) {
54              throw Error('Can not find element: ' + info);
55            }
56            element.click()
57          }'''
58    selector: A CSS selector describing the element.
59    text: The element must contains this exact text.
60    element_function: A JavaScript function (as string) that is used
61        to retrieve the element. For example:
62        '(function() { return foo.element; })()'.
63    wait: Whether to wait for the return value to be true.
64    timeout: The timeout for wait (if waiting).
65  """
66  count = 0
67  info_msg = ''
68  if element_function is not None:
69    count = count + 1
70    info_msg = 'using element_function "%s"' % re.escape(element_function)
71  if selector is not None:
72    count = count + 1
73    info_msg = 'using selector "%s"' % _EscapeSelector(selector)
74    element_function = 'document.querySelector(\'%s\')' % _EscapeSelector(
75        selector)
76  if text is not None:
77    count = count + 1
78    info_msg = 'using exact text match "%s"' % re.escape(text)
79    element_function = '''
80        (function() {
81          function _findElement(element, text) {
82            if (element.innerHTML == text) {
83              return element;
84            }
85
86            var childNodes = element.childNodes;
87            for (var i = 0, len = childNodes.length; i < len; ++i) {
88              var found = _findElement(childNodes[i], text);
89              if (found) {
90                return found;
91              }
92            }
93            return null;
94          }
95          return _findElement(document, '%s');
96        })()''' % text
97
98  if count != 1:
99    raise PageActionFailed(
100        'Must specify 1 way to retrieve element, but %s was specified.' % count)
101
102  code = '''
103      (function() {
104        var element = %s;
105        var callback = %s;
106        return callback(element, '%s');
107      })()''' % (element_function, callback_js, info_msg)
108
109  if wait:
110    tab.WaitForJavaScriptExpression(code, timeout)
111    return True
112  else:
113    return tab.EvaluateJavaScript(code)
114
115def _EscapeSelector(selector):
116  return selector.replace('\'', '\\\'')
117