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.
7 from telemetry.core import util
9 DEFAULT_WEB_CONTENTS_TIMEOUT = 90
11 # TODO(achuith, dtu, nduca): Add unit tests specifically for WebContents,
13 class WebContents(object):
14 """Represents web contents in the browser"""
15 def __init__(self, inspector_backend, backend_list):
16 self._inspector_backend = inspector_backend
17 self._backend_list = backend_list
19 with open(os.path.join(os.path.dirname(__file__),
20 'network_quiescence.js')) as f:
21 self._quiescence_js = f.read()
23 def WaitForDocumentReadyStateToBeComplete(self,
24 timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
25 self.WaitForJavaScriptExpression(
26 'document.readyState == "complete"', timeout)
28 def WaitForDocumentReadyStateToBeInteractiveOrBetter(self,
29 timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
30 self.WaitForJavaScriptExpression(
31 'document.readyState == "interactive" || '
32 'document.readyState == "complete"', timeout)
34 def WaitForJavaScriptExpression(self, expr, timeout):
35 """Waits for the given JavaScript expression to be True.
37 This method is robust against any given Evaluation timing out.
39 def IsJavaScriptExpressionTrue():
41 return bool(self.EvaluateJavaScript(expr))
42 except util.TimeoutException:
43 # If the main thread is busy for longer than Evaluate's timeout, we
44 # may time out here early. Instead, we want to wait for the full
45 # timeout of this method.
47 util.WaitFor(IsJavaScriptExpressionTrue, timeout)
49 def HasReachedQuiescence(self):
50 """Determine whether the page has reached quiescence after loading.
53 True if 2 seconds have passed since last resource received, false
56 # Inclusion of the script that provides
57 # window.__telemetry_testHasReachedNetworkQuiescence()
58 # is idempotent, it's run on every call because WebContents doesn't track
59 # page loads and we need to execute anew for every newly loaded page.
60 has_reached_quiescence = (
61 self.EvaluateJavaScript(self._quiescence_js +
62 "window.__telemetry_testHasReachedNetworkQuiescence()"))
63 return has_reached_quiescence
65 def ExecuteJavaScript(self, expr, timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
66 """Executes expr in JavaScript. Does not return the result.
68 If the expression failed to evaluate, EvaluateException will be raised.
70 return self.ExecuteJavaScriptInContext(
71 expr, context_id=None, timeout=timeout)
73 def EvaluateJavaScript(self, expr, timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
74 """Evalutes expr in JavaScript and returns the JSONized result.
76 Consider using ExecuteJavaScript for cases where the result of the
77 expression is not needed.
79 If evaluation throws in JavaScript, a Python EvaluateException will
82 If the result of the evaluation cannot be JSONized, then an
83 EvaluationException will be raised.
85 return self.EvaluateJavaScriptInContext(
86 expr, context_id=None, timeout=timeout)
88 def ExecuteJavaScriptInContext(self, expr, context_id,
89 timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
90 """Similar to ExecuteJavaScript, except context_id can refer to an iframe.
91 The main page has context_id=1, the first iframe context_id=2, etc.
93 return self._inspector_backend.ExecuteJavaScript(
94 expr, context_id=context_id, timeout=timeout)
96 def EvaluateJavaScriptInContext(self, expr, context_id,
97 timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
98 """Similar to ExecuteJavaScript, except context_id can refer to an iframe.
99 The main page has context_id=1, the first iframe context_id=2, etc.
101 return self._inspector_backend.EvaluateJavaScript(
102 expr, context_id=context_id, timeout=timeout)
105 def message_output_stream(self):
106 return self._inspector_backend.message_output_stream
108 @message_output_stream.setter
109 def message_output_stream(self, stream):
110 self._inspector_backend.message_output_stream = stream
113 def timeline_model(self):
114 return self._inspector_backend.timeline_model
116 def StartTimelineRecording(self, options=None):
117 self._inspector_backend.StartTimelineRecording(options)
120 def is_timeline_recording_running(self):
121 return self._inspector_backend.is_timeline_recording_running
123 def StopTimelineRecording(self):
124 self._inspector_backend.StopTimelineRecording()
126 def TakeJSHeapSnapshot(self, timeout=120):
127 return self._inspector_backend.TakeJSHeapSnapshot(timeout)