Index: tools/telemetry/telemetry/page/actions/page_action.py |
diff --git a/tools/telemetry/telemetry/page/actions/page_action.py b/tools/telemetry/telemetry/page/actions/page_action.py |
index 14f193ec4055d2c41cdcc19e00aecdf2f8bdbd54..ad3b38fe7e998f9fbeaaceb95b6855dd83c68f2c 100644 |
--- a/tools/telemetry/telemetry/page/actions/page_action.py |
+++ b/tools/telemetry/telemetry/page/actions/page_action.py |
@@ -2,6 +2,8 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
+import re |
+ |
class PageActionNotSupported(Exception): |
pass |
@@ -27,3 +29,88 @@ class PageAction(object): |
def CleanUp(self, tab): |
pass |
+ |
+ |
+def EvaluateCallbackWithElement( |
+ tab, callback_js, selector=None, text=None, element_function=None, |
+ wait=False, timeout=60): |
+ """Evaluates the JavaScript callback with the given element. |
+ |
+ The element may be selected via selector, text, or element_function. |
+ Only one of these arguments must be specified. |
+ |
+ Returns: |
+ The callback's return value, if any. The return value must be |
+ convertible to JSON. |
+ |
+ Args: |
+ tab: A telemetry.core.Tab object. |
+ callback_js: The JavaScript callback to call (as string). |
+ The callback receive 2 parameters: the element, and information |
+ string about what method was used to retrieve the element. |
+ Example: ''' |
+ function(element, info) { |
+ if (!element) { |
+ throw Error('Can not find element: ' + info); |
+ } |
+ element.click() |
+ }''' |
+ selector: A CSS selector describing the element. |
+ text: The element must contains this exact text. |
+ element_function: A JavaScript function (as string) that is used |
+ to retrieve the element. For example: |
+ '(function() { return foo.element; })()'. |
nednguyen
2014/06/14 17:12:13
The naming element_function is misleading, I think
chrishenry
2014/06/14 17:30:51
I think you're right. It's not super confusing, bu
|
+ wait: Whether to wait for the return value to be true. |
+ timeout: The timeout for wait (if waiting). |
+ """ |
+ count = 0 |
+ info_msg = '' |
+ if element_function is not None: |
+ count = count + 1 |
+ info_msg = 'using element_function "%s"' % re.escape(element_function) |
+ if selector is not None: |
+ count = count + 1 |
+ info_msg = 'using selector "%s"' % _EscapeSelector(selector) |
+ element_function = 'document.querySelector("%s")' % _EscapeSelector( |
+ selector) |
+ if text is not None: |
+ count = count + 1 |
+ info_msg = 'using exact text match "%s"' % re.escape(text) |
+ element_function = ''' |
+ (function() { |
+ function _findElement(element, text) { |
+ if (element.innerHTML == text) { |
+ return element; |
+ } |
+ |
+ var childNodes = element.childNodes; |
+ for (var i = 0, len = childNodes.length; i < len; ++i) { |
+ var found = _findElement(childNodes[i], text); |
+ if (found) { |
+ return found; |
+ } |
+ } |
+ return null; |
+ } |
+ return _findElement(document, '%s'); |
+ })()''' % text |
+ |
+ if count != 1: |
+ raise PageActionFailed( |
+ 'Must specify 1 way to retrieve element, but %s was specified.' % count) |
+ |
+ code = ''' |
+ (function() { |
+ var element = %s; |
+ var callback = %s; |
+ return callback(element, '%s'); |
+ })()''' % (element_function, callback_js, info_msg) |
+ |
+ if wait: |
+ tab.WaitForJavaScriptExpression(code, timeout) |
+ return True |
+ else: |
+ return tab.EvaluateJavaScript(code) |
+ |
+def _EscapeSelector(selector): |
+ return selector.replace('\'', '\\\'') |