1# Copyright (c) 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
5import sys
6import os
7import re
8
9
10def _AddToPathIfNeeded(path):
11  if path not in sys.path:
12    sys.path.insert(0, path)
13
14
15def UpdateSysPathIfNeeded():
16  for path in GetDependencyPaths():
17    _AddToPathIfNeeded(path)
18
19
20def GetDependencyPaths():
21  # TODO(#3703): Separate the paths that are only used by the dev server into
22  # another call.
23  p = TracingProject()
24  return [
25      p.catapult_path,
26      p.py_vulcanize_path,
27      p.vinn_path,
28      os.path.join(p.catapult_third_party_path, 'WebOb'),
29      os.path.join(p.catapult_third_party_path, 'Paste'),
30      os.path.join(p.catapult_third_party_path, 'six'),
31      os.path.join(p.catapult_third_party_path, 'webapp2'),
32      os.path.join(p.catapult_path, 'common', 'py_utils'),
33      os.path.join(p.tracing_third_party_path, 'symbols')
34  ]
35
36
37def _FindAllFilesRecursive(source_paths):
38  assert isinstance(source_paths, list)
39  all_filenames = set()
40  for source_path in source_paths:
41    for dirpath, _, filenames in os.walk(source_path):
42      for f in filenames:
43        if f.startswith('.'):
44          continue
45        x = os.path.abspath(os.path.join(dirpath, f))
46        all_filenames.add(x)
47  return all_filenames
48
49def _IsFilenameATest(x):
50  if x.endswith('_test.js'):
51    return True
52
53  if x.endswith('_test.html'):
54    return True
55
56  if x.endswith('_unittest.js'):
57    return True
58
59  if x.endswith('_unittest.html'):
60    return True
61
62  # TODO(nduca): Add content test?
63  return False
64
65
66class TracingProject(object):
67  catapult_path = os.path.abspath(
68      os.path.join(os.path.dirname(__file__), os.path.pardir))
69
70  tracing_root_path = os.path.join(catapult_path, 'tracing')
71  trace_processor_root_path = os.path.join(catapult_path, 'trace_processor')
72  common_root_path = os.path.join(catapult_path, 'common')
73  tracing_src_path = os.path.join(tracing_root_path, 'tracing')
74  extras_path = os.path.join(tracing_src_path, 'extras')
75  ui_extras_path = os.path.join(tracing_src_path, 'ui', 'extras')
76
77  catapult_third_party_path = os.path.join(catapult_path, 'third_party')
78  polymer_path = os.path.join(catapult_third_party_path, 'polymer')
79
80  tracing_third_party_path = os.path.join(tracing_root_path, 'third_party')
81  py_vulcanize_path = os.path.join(common_root_path, 'py_vulcanize')
82  vinn_path = os.path.join(catapult_third_party_path, 'vinn')
83
84  jszip_path = os.path.join(tracing_third_party_path, 'jszip')
85  pako_path = os.path.join(tracing_third_party_path, 'pako')
86
87  glmatrix_path = os.path.join(
88      tracing_third_party_path, 'gl-matrix', 'dist')
89
90  mannwhitneyu_path = os.path.join(
91      tracing_third_party_path, 'mannwhitneyu')
92
93  ui_path = os.path.join(tracing_src_path, 'ui')
94  d3_path = os.path.join(tracing_third_party_path, 'd3')
95  chai_path = os.path.join(tracing_third_party_path, 'chai')
96  mocha_path = os.path.join(tracing_third_party_path, 'mocha')
97  oboe_path = os.path.join(tracing_third_party_path, 'oboe')
98
99  mre_path = os.path.join(tracing_src_path, 'mre')
100
101  metrics_path = os.path.join(tracing_src_path, 'metrics')
102  diagnostics_path = os.path.join(tracing_src_path, 'value', 'diagnostics')
103
104  value_ui_path = os.path.join(tracing_src_path, 'value', 'ui')
105  metrics_ui_path = os.path.join(tracing_src_path, 'metrics', 'ui')
106
107  test_data_path = os.path.join(tracing_root_path, 'test_data')
108  skp_data_path = os.path.join(tracing_root_path, 'skp_data')
109
110  rjsmin_path = os.path.join(
111      tracing_third_party_path, 'tvcm', 'third_party', 'rjsmin')
112  rcssmin_path = os.path.join(
113      tracing_third_party_path, 'tvcm', 'third_party', 'rcssmin')
114
115  def __init__(self):
116    self.source_paths = []
117    self.source_paths.append(self.tracing_root_path)
118    self.source_paths.append(self.polymer_path)
119    self.source_paths.append(self.tracing_third_party_path)
120    self.source_paths.append(self.mre_path)
121    self.source_paths.append(self.jszip_path)
122    self.source_paths.append(self.pako_path)
123    self.source_paths.append(self.glmatrix_path)
124    self.source_paths.append(self.mannwhitneyu_path)
125    self.source_paths.append(self.d3_path)
126    self.source_paths.append(self.chai_path)
127    self.source_paths.append(self.mocha_path)
128    self.source_paths.append(self.oboe_path)
129
130  def CreateVulcanizer(self):
131    from py_vulcanize import project as project_module
132    return project_module.Project(self.source_paths)
133
134  def IsD8CompatibleFile(self, filename):
135    if filename.startswith(self.ui_path):
136      return False
137
138    if filename.startswith(self.value_ui_path):
139      return False
140
141    if filename.startswith(self.metrics_ui_path):
142      return False
143
144    return True
145
146  def FindAllTestModuleRelPaths(self, pred=None):
147    if pred is None:
148      pred = lambda x: True
149
150    all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
151    test_module_filenames = [x for x in all_filenames if
152                             _IsFilenameATest(x) and pred(x)]
153    test_module_filenames.sort()
154
155    return [os.path.relpath(x, self.tracing_root_path)
156            for x in test_module_filenames]
157
158  def FindAllMetricsModuleRelPaths(self):
159    all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
160    all_metrics_module_filenames = []
161    for x in all_filenames:
162      if x.startswith(self.metrics_path) and not _IsFilenameATest(x):
163        all_metrics_module_filenames.append(x)
164    all_metrics_module_filenames.sort()
165    return [os.path.relpath(x, self.tracing_root_path)
166            for x in all_metrics_module_filenames]
167
168  def FindAllDiagnosticsModuleRelPaths(self):
169    all_filenames = _FindAllFilesRecursive([self.tracing_src_path])
170    all_diagnostics_module_filenames = []
171    for x in all_filenames:
172      if x.startswith(self.diagnostics_path) and not _IsFilenameATest(x):
173        all_diagnostics_module_filenames.append(x)
174    all_diagnostics_module_filenames.sort()
175    return [os.path.relpath(x, self.tracing_root_path)
176            for x in all_diagnostics_module_filenames]
177
178  def FindAllD8TestModuleRelPaths(self):
179    return self.FindAllTestModuleRelPaths(pred=self.IsD8CompatibleFile)
180
181  def GetConfigNames(self):
182    config_files = [
183        os.path.join(self.ui_extras_path, x)
184        for x in os.listdir(self.ui_extras_path)
185        if x.endswith('_config.html')
186    ]
187
188    config_files = [x for x in config_files if os.path.isfile(x)]
189
190    config_basenames = [os.path.basename(x) for x in config_files]
191    config_names = [re.match('(.+)_config.html$', x).group(1)
192                    for x in config_basenames]
193    return config_names
194
195  def GetDefaultConfigName(self):
196    assert 'full' in self.GetConfigNames()
197    return 'full'
198
199  def AddConfigNameOptionToParser(self, parser):
200    choices = self.GetConfigNames()
201    parser.add_argument(
202        '--config', dest='config_name',
203        choices=choices, default=self.GetDefaultConfigName(),
204        help='Picks a browser config. Valid choices: %s' % ', '.join(choices))
205    return choices
206
207  def GetModuleNameForConfigName(self, config_name):
208    return 'tracing.ui.extras.%s_config' % config_name
209
210