Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / tvcm / resource_loader.py
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 """ResourceFinder is a helper class for finding resources given their name."""
5
6 import os
7 from tvcm import module
8 from tvcm import style_sheet as style_sheet_module
9 from tvcm import resource as resource_module
10 from tvcm import html_module
11 from tvcm import strip_js_comments
12
13 class ResourceLoader(object):
14   """Manges loading modules and their dependencies from files.
15
16   Modules handle parsing and the construction of their individual dependency
17   pointers. The loader deals with bookkeeping of what has been loaded, and
18   mapping names to file resources.
19
20   """
21   def __init__(self, project):
22     self.project = project
23     self.stripped_js_by_filename = {}
24     self.loaded_modules = {}
25     self.loaded_raw_scripts = {}
26     self.loaded_style_sheets = {}
27     self.loaded_images = {}
28
29   @property
30   def source_paths(self):
31     """A list of base directories to search for modules under."""
32     return self.project.source_paths
33
34   def FindResource(self, some_path):
35     """Finds a Resource for the given path.
36
37     Args:
38       some_path: A relative or absolute path to a file.
39
40     Returns:
41       A Resource or None.
42     """
43     if os.path.isabs(some_path):
44       return self.FindResourceGivenAbsolutePath(some_path)
45     else:
46       return self.FindResourceGivenRelativePath(some_path)
47
48   def FindResourceGivenAbsolutePath(self, absolute_path):
49     """Returns a Resource for the given absolute path."""
50     candidate_paths = []
51     for source_path in self.source_paths:
52       if absolute_path.startswith(source_path):
53         candidate_paths.append(source_path)
54     if len(candidate_paths) == 0:
55       return None
56
57     # Sort by length. Longest match wins.
58     candidate_paths.sort(lambda x, y: len(x) - len(y))
59     longest_candidate = candidate_paths[-1]
60     return resource_module.Resource(longest_candidate, absolute_path)
61
62   def FindResourceGivenRelativePath(self, relative_path):
63     """Returns a Resource for the given relative path."""
64     absolute_path = None
65     for script_path in self.source_paths:
66       absolute_path = os.path.join(script_path, relative_path)
67       if os.path.exists(absolute_path):
68         return resource_module.Resource(script_path, absolute_path)
69     return None
70
71
72   def _FindResourceGivenNameAndSuffix(self, requested_name, extension, return_resource=False):
73     """Searches for a file and reads its contents.
74
75     Args:
76       requested_name: The name of the resource that was requested.
77       extension: The extension for this requested resource.
78
79     Returns:
80       A (path, contents) pair.
81     """
82     pathy_name = requested_name.replace('.', os.sep)
83     filename = pathy_name + extension
84
85     resource = self.FindResourceGivenRelativePath(filename)
86     if return_resource:
87       return resource
88     if not resource:
89       return None, None
90     return _read_file(resource.absolute_path)
91
92   def FindModuleResource(self, requested_module_name):
93     """Finds a module javascript file and returns a Resource, or none."""
94     js_resource = self._FindResourceGivenNameAndSuffix(requested_module_name, '.js', return_resource=True)
95     html_resource = self._FindResourceGivenNameAndSuffix(requested_module_name, '.html', return_resource=True)
96     if js_resource and html_resource:
97       if html_module.IsHTMLResourceTheModuleGivenConflictingResourceNames(js_resource, html_resource):
98         return html_resource
99       return js_resource
100     elif js_resource:
101       return js_resource
102     return html_resource
103
104   def LoadModule(self, module_name=None, module_filename=None):
105     assert bool(module_name) ^ bool(module_filename), 'Must provide module_name or module_filename.'
106     if module_filename:
107       resource = self.FindResource(module_filename)
108       if not resource:
109         raise Exception('Could not find %s in %s' % (
110             module_filename, repr(self.source_paths)))
111       module_name = resource.name
112     else:
113       resource = None # Will be set if we end up needing to load.
114
115     if module_name in self.loaded_modules:
116       assert self.loaded_modules[module_name].contents
117       return self.loaded_modules[module_name]
118
119     if not resource: # happens when module_name was given
120       resource = self.FindModuleResource(module_name)
121       if not resource:
122         raise module.DepsException('No resource for module "%s"' % module_name)
123
124     m = html_module.HTMLModule(self, module_name, resource)
125     self.loaded_modules[module_name] = m
126
127     # Fake it, this is probably either polymer.js or platform.js which are
128     # actually .js files....
129     if resource.absolute_path.endswith('.js'):
130       return m
131
132     m.Parse()
133     m.Load()
134     return m
135
136   def LoadRawScript(self, relative_raw_script_path):
137     resource = None
138     for source_path in self.source_paths:
139       possible_absolute_path = os.path.join(source_path, relative_raw_script_path)
140       if os.path.exists(possible_absolute_path):
141         resource = resource_module.Resource(source_path, possible_absolute_path)
142         break
143     if not resource:
144       raise module.DepsException('Could not find a file for raw script %s in %s' % (
145         relative_raw_script_path, self.source_paths))
146     assert relative_raw_script_path == resource.unix_style_relative_path, \
147         'Expected %s == %s' % (relative_raw_script_path, resource.unix_style_relative_path)
148
149     if resource.absolute_path in self.loaded_raw_scripts:
150       return self.loaded_raw_scripts[resource.absolute_path]
151
152     raw_script = module.RawScript(resource)
153     self.loaded_raw_scripts[resource.absolute_path] = raw_script
154     return raw_script
155
156   def LoadStyleSheet(self, name):
157     if name in self.loaded_style_sheets:
158       return self.loaded_style_sheets[name]
159
160     resource = self._FindResourceGivenNameAndSuffix(name, '.css', return_resource=True)
161     if not resource:
162       raise module.DepsException('Could not find a file for stylesheet %s' % name)
163
164     style_sheet = style_sheet_module.StyleSheet(self, name, resource)
165     style_sheet.load()
166     self.loaded_style_sheets[name] = style_sheet
167     return style_sheet
168
169   def LoadImage(self, abs_path):
170     if abs_path in self.loaded_images:
171       return self.loaded_images[abs_path]
172
173     if not os.path.exists(abs_path):
174       raise module.DepsException(
175         """url('%s') did not exist""" % abs_path)
176
177     res =  self.FindResourceGivenAbsolutePath(abs_path)
178     if res == None:
179       raise module.DepsException(
180           """url('%s') was not in search path""" % abs_path)
181
182     image = style_sheet_module.Image(res)
183     self.loaded_images[abs_path] = image
184     return image
185
186   def GetStrippedJSForFilename(self, filename, early_out_if_no_tvcm):
187     if filename in self.stripped_js_by_filename:
188       return self.stripped_js_by_filename[filename]
189
190     with open(filename, 'r') as f:
191       contents = f.read(4096)
192     if early_out_if_no_tvcm and ('tvcm' not in contents):
193       return None
194
195     s = strip_js_comments.StripJSComments(contents)
196     self.stripped_js_by_filename[filename] = s
197     return s
198
199
200 def _read_file(absolute_path):
201   """Reads a file and returns a (path, contents) pair.
202
203   Args:
204     absolute_path: Absolute path to a file.
205
206   Raises:
207     Exception: The given file doesn't exist.
208     IOError: There was a problem opening or reading the file.
209   """
210   if not os.path.exists(absolute_path):
211     raise Exception('%s not found.' % absolute_path)
212   f = open(absolute_path, 'r')
213   contents = f.read()
214   f.close()
215   return absolute_path, contents