| 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 posixpath | 5 import posixpath |
| 6 | 6 |
| 7 from compiled_file_system import SingleFile, Unicode | 7 from compiled_file_system import SingleFile, Unicode |
| 8 from extensions_paths import API_PATHS | 8 from extensions_paths import API_PATHS |
| 9 from features_bundle import HasParent, GetParentName | 9 from features_bundle import HasParent, GetParentName |
| 10 from file_system import FileNotFoundError | 10 from file_system import FileNotFoundError |
| 11 from future import All, Future | 11 from future import All, Future, Race |
| 12 from operator import itemgetter | 12 from operator import itemgetter |
| 13 from path_util import Join |
| 13 from platform_util import PlatformToExtensionType | 14 from platform_util import PlatformToExtensionType |
| 14 from schema_util import ProcessSchema | 15 from schema_util import ProcessSchema |
| 15 from third_party.json_schema_compiler.json_schema import DeleteNodes | 16 from third_party.json_schema_compiler.json_schema import DeleteNodes |
| 16 from third_party.json_schema_compiler.model import Namespace, UnixName | 17 from third_party.json_schema_compiler.model import Namespace, UnixName |
| 17 | 18 |
| 18 | 19 |
| 19 def GetNodeCategories(): | 20 def GetNodeCategories(): |
| 20 '''Returns a tuple of the possible categories a node may belong to. | 21 '''Returns a tuple of the possible categories a node may belong to. |
| 21 ''' | 22 ''' |
| 22 return ('types', 'functions', 'events', 'properties') | 23 return ('types', 'functions', 'events', 'properties') |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 | 80 |
| 80 def GetNames(self): | 81 def GetNames(self): |
| 81 # API names appear alongside some of their methods/events/etc in the | 82 # API names appear alongside some of their methods/events/etc in the |
| 82 # features file. APIs are those which either implicitly or explicitly have | 83 # features file. APIs are those which either implicitly or explicitly have |
| 83 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are | 84 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are |
| 84 # APIs; runtime.onConnectNative is not). | 85 # APIs; runtime.onConnectNative is not). |
| 85 api_features = self._features_bundle.GetAPIFeatures().Get() | 86 api_features = self._features_bundle.GetAPIFeatures().Get() |
| 86 return [name for name, feature in api_features.iteritems() | 87 return [name for name, feature in api_features.iteritems() |
| 87 if not HasParent(name, feature, api_features)] | 88 if not HasParent(name, feature, api_features)] |
| 88 | 89 |
| 89 def GetModel(self, api_name): | 90 def _GetPotentialPathsForModel(self, api_name): |
| 91 '''Returns the list of file system paths that the model for |api_name| |
| 92 might be located at. |
| 93 ''' |
| 90 # By default |api_name| is assumed to be given without a path or extension, | 94 # By default |api_name| is assumed to be given without a path or extension, |
| 91 # so combinations of known paths and extension types will be searched. | 95 # so combinations of known paths and extension types will be searched. |
| 92 api_extensions = ('.json', '.idl') | 96 api_extensions = ('.json', '.idl') |
| 93 api_paths = API_PATHS | 97 api_paths = API_PATHS |
| 94 | 98 |
| 95 # Callers sometimes include a file extension and/or prefix path with the | 99 # Callers sometimes include a file extension and/or prefix path with the |
| 96 # |api_name| argument. We believe them and narrow the search space | 100 # |api_name| argument. We believe them and narrow the search space |
| 97 # accordingly. | 101 # accordingly. |
| 98 name, ext = posixpath.splitext(api_name) | 102 name, ext = posixpath.splitext(api_name) |
| 99 if ext in api_extensions: | 103 if ext in api_extensions: |
| 100 api_extensions = (ext,) | 104 api_extensions = (ext,) |
| 101 api_name = name | 105 api_name = name |
| 102 for api_path in api_paths: | 106 for api_path in api_paths: |
| 103 if api_name.startswith(api_path): | 107 if api_name.startswith(api_path): |
| 104 api_name = api_name[len(api_path):] | 108 api_name = api_name[len(api_path):] |
| 105 api_paths = (api_path,) | 109 api_paths = (api_path,) |
| 106 break | 110 break |
| 107 | 111 |
| 108 # API names are given as declarativeContent and app.window but file names | 112 # API names are given as declarativeContent and app.window but file names |
| 109 # will be declarative_content and app_window. | 113 # will be declarative_content and app_window. |
| 110 file_name = UnixName(api_name).replace('.', '_') | 114 file_name = UnixName(api_name).replace('.', '_') |
| 111 # Devtools APIs are in API/devtools/ not API/, and have their | 115 # Devtools APIs are in API/devtools/ not API/, and have their |
| 112 # "devtools" names removed from the file names. | 116 # "devtools" names removed from the file names. |
| 113 basename = posixpath.basename(file_name) | 117 basename = posixpath.basename(file_name) |
| 114 if 'devtools_' in basename: | 118 if 'devtools_' in basename: |
| 115 file_name = posixpath.join( | 119 file_name = posixpath.join( |
| 116 'devtools', file_name.replace(basename, | 120 'devtools', file_name.replace(basename, |
| 117 basename.replace('devtools_' , ''))) | 121 basename.replace('devtools_' , ''))) |
| 118 | 122 |
| 119 futures = [self._model_cache.GetFromFile( | 123 return [Join(path, file_name + ext) for ext in api_extensions |
| 120 posixpath.join(path, '%s%s' % (file_name, ext))) | 124 for path in api_paths] |
| 121 for ext in api_extensions | 125 |
| 122 for path in api_paths] | 126 def GetModel(self, api_name): |
| 123 def resolve(): | 127 futures = [self._model_cache.GetFromFile(path) |
| 124 for future in futures: | 128 for path in self._GetPotentialPathsForModel(api_name)] |
| 125 try: | 129 return Race(futures, except_pass=(FileNotFoundError, ValueError)) |
| 126 return future.Get() | |
| 127 # Either the file wasn't found or there was no schema for the file | |
| 128 except (FileNotFoundError, ValueError): pass | |
| 129 # Propagate the first error if neither were found. | |
| 130 futures[0].Get() | |
| 131 return Future(callback=resolve) | |
| 132 | 130 |
| 133 def GetContentScriptAPIs(self): | 131 def GetContentScriptAPIs(self): |
| 134 '''Creates a dict of APIs and nodes supported by content scripts in | 132 '''Creates a dict of APIs and nodes supported by content scripts in |
| 135 this format: | 133 this format: |
| 136 | 134 |
| 137 { | 135 { |
| 138 'extension': '<ContentScriptAPI name='extension', | 136 'extension': '<ContentScriptAPI name='extension', |
| 139 restrictedTo=[{'node': 'onRequest'}]>', | 137 restrictedTo=[{'node': 'onRequest'}]>', |
| 140 ... | 138 ... |
| 141 } | 139 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 | 173 |
| 176 def IterModels(self): | 174 def IterModels(self): |
| 177 future_models = [(name, self.GetModel(name)) for name in self.GetNames()] | 175 future_models = [(name, self.GetModel(name)) for name in self.GetNames()] |
| 178 for name, future_model in future_models: | 176 for name, future_model in future_models: |
| 179 try: | 177 try: |
| 180 model = future_model.Get() | 178 model = future_model.Get() |
| 181 except FileNotFoundError: | 179 except FileNotFoundError: |
| 182 continue | 180 continue |
| 183 if model: | 181 if model: |
| 184 yield name, model | 182 yield name, model |
| OLD | NEW |