1# Copyright (c) 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 telemetry.core import util
6
7DEFAULT_WEB_CONTENTS_TIMEOUT = 90
8
9# TODO(achuith, dtu, nduca): Add unit tests specifically for WebContents,
10# independent of Tab.
11class WebContents(object):
12  """Represents web contents in the browser"""
13  def __init__(self, inspector_backend):
14    self._inspector_backend = inspector_backend
15
16  def __del__(self):
17    self.Disconnect()
18
19  def Disconnect(self):
20    self._inspector_backend.Disconnect()
21
22  def Close(self):
23    """Closes this page.
24
25    Not all browsers or browser versions support this method.
26    Be sure to check browser.supports_tab_control."""
27    self._inspector_backend.Close()
28
29  def WaitForDocumentReadyStateToBeComplete(self,
30      timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
31    self.WaitForJavaScriptExpression(
32        'document.readyState == "complete"', timeout)
33
34  def WaitForDocumentReadyStateToBeInteractiveOrBetter(self,
35      timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
36    self.WaitForJavaScriptExpression(
37        'document.readyState == "interactive" || '
38        'document.readyState == "complete"', timeout)
39
40  def WaitForJavaScriptExpression(self, expr, timeout):
41    """Waits for the given JavaScript expression to be True.
42
43    This method is robust against any given Evaluation timing out.
44    """
45    def IsTrue():
46      try:
47        return bool(self.EvaluateJavaScript(expr))
48      except util.TimeoutException:
49        # If the main thread is busy for longer than Evaluate's timeout, we
50        # may time out here early. Instead, we want to wait for the full
51        # timeout of this method.
52        return False
53    util.WaitFor(IsTrue, timeout)
54
55  def ExecuteJavaScript(self, expr, timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
56    """Executes expr in JavaScript. Does not return the result.
57
58    If the expression failed to evaluate, EvaluateException will be raised.
59    """
60    self._inspector_backend.ExecuteJavaScript(expr, timeout)
61
62  def EvaluateJavaScript(self, expr, timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
63    """Evalutes expr in JavaScript and returns the JSONized result.
64
65    Consider using ExecuteJavaScript for cases where the result of the
66    expression is not needed.
67
68    If evaluation throws in JavaScript, a Python EvaluateException will
69    be raised.
70
71    If the result of the evaluation cannot be JSONized, then an
72    EvaluationException will be raised.
73    """
74    return self._inspector_backend.EvaluateJavaScript(expr, timeout)
75
76  @property
77  def message_output_stream(self):
78    return self._inspector_backend.message_output_stream
79
80  @message_output_stream.setter
81  def message_output_stream(self, stream):
82    self._inspector_backend.message_output_stream = stream
83
84  @property
85  def timeline_model(self):
86    return self._inspector_backend.timeline_model
87
88  def StartTimelineRecording(self):
89    self._inspector_backend.StartTimelineRecording()
90
91  def StopTimelineRecording(self):
92    self._inspector_backend.StopTimelineRecording()
93
94  def TakeJSHeapSnapshot(self, timeout=120):
95    return self._inspector_backend.TakeJSHeapSnapshot(timeout)
96