OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import os | 5 import os |
6 import posixpath | 6 import posixpath |
7 | 7 |
8 from compiled_file_system import SingleFile, Unicode | 8 from compiled_file_system import SingleFile, Unicode |
9 from extensions_paths import API | 9 from extensions_paths import API, CHROME_API |
10 from file_system import FileNotFoundError | 10 from file_system import FileNotFoundError |
11 from future import Gettable, Future | 11 from future import Gettable, Future |
12 from schema_util import ProcessSchema | 12 from schema_util import ProcessSchema |
13 from third_party.json_schema_compiler.model import Namespace, UnixName | 13 from third_party.json_schema_compiler.model import Namespace, UnixName |
14 | 14 |
15 | 15 |
16 @SingleFile | 16 @SingleFile |
17 @Unicode | 17 @Unicode |
18 def _CreateAPIModel(path, data): | 18 def _CreateAPIModel(path, data): |
19 schema = ProcessSchema(path, data)[0] | 19 schema = ProcessSchema(path, data)[0] |
20 if not schema: return None | 20 if not schema: return None |
21 return Namespace(schema, schema['namespace']) | 21 return Namespace(schema, schema['namespace']) |
22 | 22 |
23 | 23 |
24 class APIModels(object): | 24 class APIModels(object): |
25 '''Tracks APIs and their Models. | 25 '''Tracks APIs and their Models. |
26 ''' | 26 ''' |
27 | 27 |
28 def __init__(self, features_bundle, compiled_fs_factory, file_system): | 28 def __init__(self, features_bundle, compiled_fs_factory, file_system): |
29 self._features_bundle = features_bundle | 29 self._features_bundle = features_bundle |
30 self._model_cache = compiled_fs_factory.Create( | 30 self._model_cache = compiled_fs_factory.Create( |
31 file_system, _CreateAPIModel, APIModels) | 31 file_system, _CreateAPIModel, APIModels) |
| 32 self._file_system = file_system |
32 | 33 |
33 def GetNames(self): | 34 def GetNames(self): |
34 # API names appear alongside some of their methods/events/etc in the | 35 # API names appear alongside some of their methods/events/etc in the |
35 # features file. APIs are those which either implicitly or explicitly have | 36 # features file. APIs are those which either implicitly or explicitly have |
36 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are | 37 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are |
37 # APIs; runtime.onConnectNative is not). | 38 # APIs; runtime.onConnectNative is not). |
38 api_features = self._features_bundle.GetAPIFeatures().Get() | 39 api_features = self._features_bundle.GetAPIFeatures().Get() |
39 return [name for name, feature in api_features.iteritems() | 40 return [name for name, feature in api_features.iteritems() |
40 if ('.' not in name or | 41 if ('.' not in name or |
41 name.rsplit('.', 1)[0] not in api_features or | 42 name.rsplit('.', 1)[0] not in api_features or |
42 feature.get('noparent'))] | 43 feature.get('noparent'))] |
43 | 44 |
44 def GetModel(self, api_name): | 45 def GetModel(self, api_name): |
45 # Callers sometimes specify a filename which includes .json or .idl - if | 46 # Callers sometimes specify a filename which includes .json or .idl - if |
46 # so, believe them. They may even include the 'api/' prefix. | 47 # so, believe them. They may even include the 'api/' prefix. |
47 if os.path.splitext(api_name)[1] in ('.json', '.idl'): | 48 if os.path.splitext(api_name)[1] in ('.json', '.idl'): |
48 if not api_name.startswith(API): | 49 if not api_name.startswith((API, CHROME_API)): |
49 api_name = posixpath.join(API, api_name) | 50 api_path = posixpath.join(API, api_name) |
| 51 if self._file_system.Exists(api_path).Get(): |
| 52 return self._model_cache.GetFromFile(api_path) |
| 53 api_name = posixpath.join(CHROME_API, api_name) |
50 return self._model_cache.GetFromFile(api_name) | 54 return self._model_cache.GetFromFile(api_name) |
51 | 55 |
52 assert not api_name.startswith(API) | 56 assert not api_name.startswith((API, CHROME_API)) |
53 | 57 |
54 # API names are given as declarativeContent and app.window but file names | 58 # API names are given as declarativeContent and app.window but file names |
55 # will be declarative_content and app_window. | 59 # will be declarative_content and app_window. |
56 file_name = UnixName(api_name).replace('.', '_') | 60 file_name = UnixName(api_name).replace('.', '_') |
57 # Devtools APIs are in API/devtools/ not API/, and have their | 61 # Devtools APIs are in API/devtools/ not API/, and have their |
58 # "devtools" names removed from the file names. | 62 # "devtools" names removed from the file names. |
59 basename = posixpath.basename(file_name) | 63 basename = posixpath.basename(file_name) |
60 if 'devtools_' in basename: | 64 if 'devtools_' in basename: |
61 file_name = posixpath.join( | 65 file_name = posixpath.join( |
62 'devtools', file_name.replace(basename, | 66 'devtools', file_name.replace(basename, |
63 basename.replace('devtools_' , ''))) | 67 basename.replace('devtools_' , ''))) |
64 | 68 |
65 futures = [self._model_cache.GetFromFile( | 69 futures = [self._model_cache.GetFromFile( |
66 posixpath.join(API, '%s.%s' % (file_name, ext))) | 70 posixpath.join(api_path, '%s.%s' % (file_name, ext))) |
67 for ext in ('json', 'idl')] | 71 for ext in ('json', 'idl') |
| 72 for api_path in (API, CHROME_API)] |
68 def resolve(): | 73 def resolve(): |
69 for future in futures: | 74 for future in futures: |
70 try: | 75 try: |
71 return future.Get() | 76 return future.Get() |
72 except FileNotFoundError: pass | 77 except FileNotFoundError: pass |
73 # Propagate the first FileNotFoundError if neither were found. | 78 # Propagate the first FileNotFoundError if no files were found. |
74 futures[0].Get() | 79 futures[0].Get() |
75 return Future(delegate=Gettable(resolve)) | 80 return Future(delegate=Gettable(resolve)) |
76 | 81 |
77 def IterModels(self): | 82 def IterModels(self): |
78 future_models = [(name, self.GetModel(name)) for name in self.GetNames()] | 83 future_models = [(name, self.GetModel(name)) for name in self.GetNames()] |
79 for name, future_model in future_models: | 84 for name, future_model in future_models: |
80 try: | 85 try: |
81 model = future_model.Get() | 86 model = future_model.Get() |
82 except FileNotFoundError: | 87 except FileNotFoundError: |
83 continue | 88 continue |
84 if model: | 89 if model: |
85 yield name, model | 90 yield name, model |
OLD | NEW |