1 # Copyright 2014 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 from measurements import smooth_gesture_util 5 6 from telemetry.core.backends.chrome import tracing_backend 7 from telemetry.timeline.model import TimelineModel 8 from telemetry.page.actions import action_runner 9 from telemetry.web_perf import timeline_interaction_record as tir_module 10 11 12 RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions' 13 14 15 class TimelineController(object): 16 def __init__(self): 17 super(TimelineController, self).__init__() 18 self.trace_categories = tracing_backend.DEFAULT_TRACE_CATEGORIES 19 self._model = None 20 self._renderer_process = None 21 self._smooth_records = [] 22 self._interaction = None 23 24 def Start(self, page, tab): 25 """Starts gathering timeline data. 26 27 """ 28 # Resets these member variables incase this object is reused. 29 self._model = None 30 self._renderer_process = None 31 if not tab.browser.supports_tracing: 32 raise Exception('Not supported') 33 if self.trace_categories: 34 categories = [self.trace_categories] + \ 35 page.GetSyntheticDelayCategories() 36 else: 37 categories = page.GetSyntheticDelayCategories() 38 tab.browser.StartTracing(','.join(categories)) 39 # Start the smooth marker for all actions. 40 runner = action_runner.ActionRunner(tab) 41 self._interaction = runner.BeginInteraction( 42 RUN_SMOOTH_ACTIONS, is_smooth=True) 43 44 def Stop(self, tab): 45 # End the smooth marker for all actions. 46 self._interaction.End() 47 # Stop tracing. 48 timeline_data = tab.browser.StopTracing() 49 self._model = TimelineModel(timeline_data) 50 self._renderer_process = self._model.GetRendererProcessFromTabId(tab.id) 51 renderer_thread = self.model.GetRendererThreadFromTabId(tab.id) 52 53 run_smooth_actions_record = None 54 self._smooth_records = [] 55 for event in renderer_thread.async_slices: 56 if not tir_module.IsTimelineInteractionRecord(event.name): 57 continue 58 r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event) 59 if r.logical_name == RUN_SMOOTH_ACTIONS: 60 assert run_smooth_actions_record is None, ( 61 'TimelineController cannot issue more than 1 %s record' % 62 RUN_SMOOTH_ACTIONS) 63 run_smooth_actions_record = r 64 elif r.is_smooth: 65 self._smooth_records.append( 66 smooth_gesture_util.GetAdjustedInteractionIfContainGesture( 67 self.model, r)) 68 69 # If there is no other smooth records, we make measurements on time range 70 # marked by timeline_controller itself. 71 # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that 72 # page sets are responsible for issueing the markers themselves. 73 if len(self._smooth_records) == 0 and run_smooth_actions_record: 74 self._smooth_records = [run_smooth_actions_record] 75 76 77 def CleanUp(self, tab): 78 if tab.browser.is_tracing_running: 79 tab.browser.StopTracing() 80 81 @property 82 def model(self): 83 return self._model 84 85 @property 86 def renderer_process(self): 87 return self._renderer_process 88 89 @property 90 def smooth_records(self): 91 return self._smooth_records 92