lizeb | 36937af | 2016-01-18 17:41:36 | [diff] [blame] | 1 | # Copyright 2016 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 | import devtools_monitor |
| 6 | |
| 7 | |
| 8 | class PageTrack(devtools_monitor.Track): |
| 9 | """Records the events from the page track.""" |
| 10 | _METHODS = ('Page.frameStartedLoading', 'Page.frameStoppedLoading', |
| 11 | 'Page.frameAttached') |
lizeb | c8aa169 | 2016-02-02 17:29:20 | [diff] [blame] | 12 | FRAME_STARTED_LOADING = 'Page.frameStartedLoading' |
lizeb | 36937af | 2016-01-18 17:41:36 | [diff] [blame] | 13 | def __init__(self, connection): |
| 14 | super(PageTrack, self).__init__(connection) |
| 15 | self._connection = connection |
| 16 | self._events = [] |
| 17 | self._pending_frames = set() |
| 18 | self._known_frames = set() |
| 19 | self._main_frame_id = None |
| 20 | if self._connection: |
| 21 | for method in PageTrack._METHODS: |
| 22 | self._connection.RegisterListener(method, self) |
| 23 | |
| 24 | def Handle(self, method, msg): |
| 25 | assert method in PageTrack._METHODS |
| 26 | params = msg['params'] |
| 27 | frame_id = params['frameId'] |
| 28 | should_stop = False |
| 29 | event = {'method': method, 'frame_id': frame_id} |
lizeb | c8aa169 | 2016-02-02 17:29:20 | [diff] [blame] | 30 | if method == self.FRAME_STARTED_LOADING: |
lizeb | 36937af | 2016-01-18 17:41:36 | [diff] [blame] | 31 | if self._main_frame_id is None: |
| 32 | self._main_frame_id = params['frameId'] |
| 33 | self._pending_frames.add(frame_id) |
| 34 | self._known_frames.add(frame_id) |
| 35 | elif method == 'Page.frameStoppedLoading': |
| 36 | assert frame_id in self._pending_frames |
| 37 | self._pending_frames.remove(frame_id) |
| 38 | if frame_id == self._main_frame_id: |
| 39 | should_stop = True |
| 40 | elif method == 'Page.frameAttached': |
| 41 | self._known_frames.add(frame_id) |
| 42 | parent_frame = params['parentFrameId'] |
| 43 | assert parent_frame in self._known_frames |
| 44 | event['parent_frame_id'] = parent_frame |
| 45 | self._events.append(event) |
| 46 | if should_stop and self._connection: |
| 47 | self._connection.StopMonitoring() |
| 48 | |
| 49 | def GetEvents(self): |
| 50 | #TODO(lizeb): Add more checks here (child frame stops loading before parent, |
| 51 | #for instance). |
| 52 | return self._events |
| 53 | |
| 54 | def ToJsonDict(self): |
| 55 | return {'events': [event for event in self._events]} |
| 56 | |
lizeb | c8aa169 | 2016-02-02 17:29:20 | [diff] [blame] | 57 | def GetMainFrameId(self): |
| 58 | """Returns the Id (str) of the main frame, or raises a ValueError.""" |
| 59 | for event in self._events: |
| 60 | if event['method'] == self.FRAME_STARTED_LOADING: |
| 61 | return event['frame_id'] |
| 62 | else: |
| 63 | raise ValueError('No frame loads in the track.') |
| 64 | |
lizeb | 36937af | 2016-01-18 17:41:36 | [diff] [blame] | 65 | @classmethod |
| 66 | def FromJsonDict(cls, json_dict): |
| 67 | assert 'events' in json_dict |
| 68 | result = PageTrack(None) |
| 69 | events = [event for event in json_dict['events']] |
| 70 | result._events = events |
| 71 | return result |