Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / backends / chrome / inspector_timeline.py
1 # Copyright 2013 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 from telemetry.core.backends.chrome import timeline_recorder
6 from telemetry.timeline import inspector_timeline_data
7
8
9 class TabBackendException(Exception):
10   """An exception which indicates an error response from devtools inspector."""
11   pass
12
13
14 class InspectorTimeline(timeline_recorder.TimelineRecorder):
15   """Implementation of dev tools timeline."""
16
17   class Recorder(object):
18     """Utility class to Start and Stop recording timeline.
19
20     Example usage:
21
22         with inspector_timeline.InspectorTimeline.Recorder(tab):
23           # Something to run while the timeline is recording.
24
25     This is an alternative to directly calling the Start and Stop methods below.
26     """
27     def __init__(self, tab):
28       self._tab = tab
29
30     def __enter__(self):
31       self._tab.StartTimelineRecording()
32
33     def __exit__(self, *args):
34       self._tab.StopTimelineRecording()
35
36   def __init__(self, inspector_backend):
37     super(InspectorTimeline, self).__init__()
38     self._inspector_backend = inspector_backend
39     self._is_recording = False
40     self._raw_events = None
41
42   @property
43   def is_timeline_recording_running(self):
44     return self._is_recording
45
46   def Start(self):
47     """Starts recording."""
48     assert not self._is_recording, 'Start should only be called once.'
49     self._raw_events = None
50     self._is_recording = True
51     self._inspector_backend.RegisterDomain(
52         'Timeline', self._OnNotification, self._OnClose)
53     # The 'bufferEvents' parameter below means that events should not be sent
54     # individually as messages, but instead all at once when a Timeline.stop
55     # request is sent.
56     request = {
57         'method': 'Timeline.start',
58         'params': {'bufferEvents': True},
59     }
60     self._SendSyncRequest(request)
61
62   def Stop(self):
63     """Stops recording and returns timeline event data."""
64     if not self._is_recording:
65       return None
66     request = {'method': 'Timeline.stop'}
67     result = self._SendSyncRequest(request)
68     self._inspector_backend.UnregisterDomain('Timeline')
69     self._is_recording = False
70
71     # TODO: Backward compatibility. Needs to be removed when
72     # M38 becomes stable.
73     if 'events' in result:
74       raw_events = result['events']
75     else:  # In M38 events will arrive via Timeline.stopped event.
76       raw_events = self._raw_events
77       self._raw_events = None
78     return inspector_timeline_data.InspectorTimelineData(raw_events)
79
80   def _SendSyncRequest(self, request, timeout=60):
81     """Sends a devtools remote debugging protocol request.
82
83     The types of request that are valid is determined by protocol.json:
84     https://src.chromium.org/viewvc/blink/trunk/Source/devtools/protocol.json
85
86     Args:
87       request: Request dict, may contain the keys 'method' and 'params'.
88       timeout: Number of seconds to wait for a response.
89
90     Returns:
91       The result given in the response message.
92
93     Raises:
94       TabBackendException: The response indicates an error occurred.
95     """
96     response = self._inspector_backend.SyncRequest(request, timeout)
97     if 'error' in response:
98       raise TabBackendException(response['error']['message'])
99     return response['result']
100
101   def _OnNotification(self, msg):
102     """Handler called when a message is received."""
103     # Since 'Timeline.start' was invoked with the 'bufferEvents' parameter,
104     # the events will arrive in Timeline.stopped event.
105     if msg['method'] == 'Timeline.stopped' and 'events' in msg['params']:
106       self._raw_events = msg['params']['events']
107
108   def _OnClose(self):
109     """Handler called when a domain is unregistered."""
110     pass