| OLD | NEW | 
|    1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |    1 # Copyright (c) 2012 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 copy |    5 import copy | 
|    6 import json |    6 import json | 
 |    7 import logging | 
|    7 import os |    8 import os | 
|    8  |    9  | 
|    9 from docs_server_utils import GetLinkToRefType |  | 
|   10 import compiled_file_system as compiled_fs |   10 import compiled_file_system as compiled_fs | 
|   11 from file_system import FileNotFoundError |   11 from file_system import FileNotFoundError | 
|   12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater |   12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater | 
|   13 import third_party.json_schema_compiler.model as model |   13 import third_party.json_schema_compiler.model as model | 
|   14 import third_party.json_schema_compiler.idl_schema as idl_schema |   14 import third_party.json_schema_compiler.idl_schema as idl_schema | 
|   15 import third_party.json_schema_compiler.idl_parser as idl_parser |   15 import third_party.json_schema_compiler.idl_parser as idl_parser | 
|   16  |   16  | 
|   17 # Increment this version when there are changes to the data stored in any of |   17 # Increment this version when there are changes to the data stored in any of | 
|   18 # the caches used by APIDataSource. This allows the cache to be invalidated |   18 # the caches used by APIDataSource. This allows the cache to be invalidated | 
|   19 # without having to flush memcache on the production server. |   19 # without having to flush memcache on the production server. | 
|   20 _VERSION = 2 |   20 _VERSION = 3 | 
|   21  |   21  | 
|   22 def _RemoveNoDocs(item): |   22 def _RemoveNoDocs(item): | 
|   23   if type(item) == dict: |   23   if type(item) == dict: | 
|   24     if item.get('nodoc', False): |   24     if item.get('nodoc', False): | 
|   25       return True |   25       return True | 
|   26     to_remove = [] |   26     to_remove = [] | 
|   27     for key, value in item.items(): |   27     for key, value in item.items(): | 
|   28       if _RemoveNoDocs(value): |   28       if _RemoveNoDocs(value): | 
|   29         to_remove.append(key) |   29         to_remove.append(key) | 
|   30     for k in to_remove: |   30     for k in to_remove: | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   42   if node.parent is not None and not isinstance(node.parent, model.Namespace): |   42   if node.parent is not None and not isinstance(node.parent, model.Namespace): | 
|   43     return '-'.join([prefix, node.parent.simple_name, node.simple_name]) |   43     return '-'.join([prefix, node.parent.simple_name, node.simple_name]) | 
|   44   return '-'.join([prefix, node.simple_name]) |   44   return '-'.join([prefix, node.simple_name]) | 
|   45  |   45  | 
|   46 def _FormatValue(value): |   46 def _FormatValue(value): | 
|   47   """Inserts commas every three digits for integer values. It is magic. |   47   """Inserts commas every three digits for integer values. It is magic. | 
|   48   """ |   48   """ | 
|   49   s = str(value) |   49   s = str(value) | 
|   50   return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) |   50   return ','.join([s[max(0, i - 3):i] for i in range(len(s), 0, -3)][::-1]) | 
|   51  |   51  | 
|   52 class _JscModel(object): |   52 class _JSCModel(object): | 
|   53   """Uses a Model from the JSON Schema Compiler and generates a dict that |   53   """Uses a Model from the JSON Schema Compiler and generates a dict that | 
|   54   a Handlebar template can use for a data source. |   54   a Handlebar template can use for a data source. | 
|   55   """ |   55   """ | 
|   56   def __init__(self, json): |   56   def __init__(self, json, ref_resolver, disable_refs): | 
 |   57     self._ref_resolver = ref_resolver | 
 |   58     self._disable_refs = disable_refs | 
|   57     clean_json = copy.deepcopy(json) |   59     clean_json = copy.deepcopy(json) | 
|   58     if _RemoveNoDocs(clean_json): |   60     if _RemoveNoDocs(clean_json): | 
|   59       self._namespace = None |   61       self._namespace = None | 
|   60     else: |   62     else: | 
|   61       self._namespace = model.Namespace(clean_json, clean_json['namespace']) |   63       self._namespace = model.Namespace(clean_json, clean_json['namespace']) | 
|   62  |   64  | 
 |   65   def _GetLink(self, ref): | 
 |   66     if not self._disable_refs: | 
 |   67       ref_data = self._ref_resolver.GetLink(self._namespace.name, ref) | 
 |   68       if ref_data is not None: | 
 |   69         return ref_data | 
 |   70       logging.error('$ref %s could not be resolved.' % ref) | 
 |   71     if '.' in ref: | 
 |   72       type_name = ref.rsplit('.', 1)[-1] | 
 |   73     else: | 
 |   74       type_name = ref | 
 |   75     return { 'href': '#type-%s' % type_name, 'text': ref } | 
 |   76  | 
|   63   def _FormatDescription(self, description): |   77   def _FormatDescription(self, description): | 
|   64     if description is None or '$ref:' not in description: |   78     if description is None or '$ref:' not in description: | 
|   65       return description |   79       return description | 
|   66     refs = description.split('$ref:') |   80     refs = description.split('$ref:') | 
|   67     formatted_description = [refs[0]] |   81     formatted_description = [refs[0]] | 
|   68     for ref in refs[1:]: |   82     for ref in refs[1:]: | 
|   69       parts = ref.split(' ', 1) |   83       parts = ref.split(' ', 1) | 
|   70       if len(parts) == 1: |   84       if len(parts) == 1: | 
|   71         ref = parts[0] |   85         ref = parts[0] | 
|   72         rest = '' |   86         rest = '' | 
|   73       else: |   87       else: | 
|   74         ref, rest = parts |   88         ref, rest = parts | 
|   75         rest = ' ' + rest |   89         rest = ' ' + rest | 
|   76       if not ref[-1].isalnum(): |   90       if not ref[-1].isalnum(): | 
|   77         rest = ref[-1] + rest |   91         rest = ref[-1] + rest | 
|   78         ref = ref[:-1] |   92         ref = ref[:-1] | 
|   79       ref_dict = GetLinkToRefType(self._namespace.name, ref) |   93       ref_dict = self._GetLink(ref) | 
|   80       formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % |   94       formatted_description.append('<a href="%(href)s">%(text)s</a>%(rest)s' % | 
|   81           { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) |   95           { 'href': ref_dict['href'], 'text': ref_dict['text'], 'rest': rest }) | 
|   82     return ''.join(formatted_description) |   96     return ''.join(formatted_description) | 
|   83  |   97  | 
|   84   def ToDict(self): |   98   def ToDict(self): | 
|   85     if self._namespace is None: |   99     if self._namespace is None: | 
|   86       return {} |  100       return {} | 
|   87     return { |  101     return { | 
|   88       'name': self._namespace.name, |  102       'name': self._namespace.name, | 
|   89       'types':  [self._GenerateType(t) for t in self._namespace.types.values() |  103       'types':  [self._GenerateType(t) for t in self._namespace.types.values() | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  132       function_dict['parameters'][-1]['last'] = True |  146       function_dict['parameters'][-1]['last'] = True | 
|  133     return function_dict |  147     return function_dict | 
|  134  |  148  | 
|  135   def _GenerateEvents(self, events): |  149   def _GenerateEvents(self, events): | 
|  136     return [self._GenerateEvent(e) for e in events.values()] |  150     return [self._GenerateEvent(e) for e in events.values()] | 
|  137  |  151  | 
|  138   def _GenerateEvent(self, event): |  152   def _GenerateEvent(self, event): | 
|  139     event_dict = { |  153     event_dict = { | 
|  140       'name': event.simple_name, |  154       'name': event.simple_name, | 
|  141       'description': self._FormatDescription(event.description), |  155       'description': self._FormatDescription(event.description), | 
|  142       'parameters': map(self._GenerateProperty, event.params), |  156       'parameters': [self._GenerateProperty(p) for p in event.params], | 
|  143       'callback': self._GenerateCallback(event.callback), |  157       'callback': self._GenerateCallback(event.callback), | 
|  144       'conditions': [GetLinkToRefType(self._namespace.name, c) |  158       'filters': [self._GenerateProperty(f) for f in event.filters], | 
|  145                      for c in event.conditions], |  159       'conditions': [self._GetLink(condition) | 
|  146       'actions': [GetLinkToRefType(self._namespace.name, a) |  160                      for condition in event.conditions], | 
|  147                      for a in event.actions], |  161       'actions': [self._GetLink(action) for action in event.actions], | 
|  148       'filters': map(self._GenerateProperty, event.filters), |  | 
|  149       'supportsRules': event.supports_rules, |  162       'supportsRules': event.supports_rules, | 
|  150       'id': _CreateId(event, 'event') |  163       'id': _CreateId(event, 'event') | 
|  151     } |  164     } | 
|  152     if (event.parent is not None and |  165     if (event.parent is not None and | 
|  153         not isinstance(event.parent, model.Namespace)): |  166         not isinstance(event.parent, model.Namespace)): | 
|  154       event_dict['parent_name'] = event.parent.simple_name |  167       event_dict['parent_name'] = event.parent.simple_name | 
|  155     else: |  168     else: | 
|  156       event_dict['parent_name'] = None |  169       event_dict['parent_name'] = None | 
|  157     if event_dict['callback']: |  170     if event_dict['callback']: | 
|  158       event_dict['parameters'].append(event_dict['callback']) |  171       event_dict['parameters'].append(event_dict['callback']) | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  179   def _GenerateProperties(self, properties): |  192   def _GenerateProperties(self, properties): | 
|  180     return [self._GenerateProperty(v) for v in properties.values() |  193     return [self._GenerateProperty(v) for v in properties.values() | 
|  181             if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES] |  194             if v.type_ != model.PropertyType.ADDITIONAL_PROPERTIES] | 
|  182  |  195  | 
|  183   def _GenerateProperty(self, property_): |  196   def _GenerateProperty(self, property_): | 
|  184     property_dict = { |  197     property_dict = { | 
|  185       'name': property_.simple_name, |  198       'name': property_.simple_name, | 
|  186       'optional': property_.optional, |  199       'optional': property_.optional, | 
|  187       'description': self._FormatDescription(property_.description), |  200       'description': self._FormatDescription(property_.description), | 
|  188       'properties': self._GenerateProperties(property_.properties), |  201       'properties': self._GenerateProperties(property_.properties), | 
 |  202       'functions': self._GenerateFunctions(property_.functions), | 
|  189       'parameters': [], |  203       'parameters': [], | 
|  190       'functions': self._GenerateFunctions(property_.functions), |  | 
|  191       'returns': None, |  204       'returns': None, | 
|  192       'id': _CreateId(property_, 'property') |  205       'id': _CreateId(property_, 'property') | 
|  193     } |  206     } | 
|  194     for param in property_.params: |  207     for param in property_.params: | 
|  195       property_dict['parameters'].append(self._GenerateProperty(param)) |  208       property_dict['parameters'].append(self._GenerateProperty(param)) | 
|  196     if property_.returns: |  209     if property_.returns: | 
|  197       property_dict['returns'] = self._GenerateProperty(property_.returns) |  210       property_dict['returns'] = self._GenerateProperty(property_.returns) | 
|  198     if (property_.parent is not None and |  211     if (property_.parent is not None and | 
|  199         not isinstance(property_.parent, model.Namespace)): |  212         not isinstance(property_.parent, model.Namespace)): | 
|  200       property_dict['parent_name'] = property_.parent.simple_name |  213       property_dict['parent_name'] = property_.parent.simple_name | 
|  201     else: |  214     else: | 
|  202       property_dict['parent_name'] = None |  215       property_dict['parent_name'] = None | 
|  203     if property_.has_value: |  216     if property_.has_value: | 
|  204       if isinstance(property_.value, int): |  217       if isinstance(property_.value, int): | 
|  205         property_dict['value'] = _FormatValue(property_.value) |  218         property_dict['value'] = _FormatValue(property_.value) | 
|  206       else: |  219       else: | 
|  207         property_dict['value'] = property_.value |  220         property_dict['value'] = property_.value | 
|  208     else: |  221     else: | 
|  209       self._RenderTypeInformation(property_, property_dict) |  222       self._RenderTypeInformation(property_, property_dict) | 
|  210     return property_dict |  223     return property_dict | 
|  211  |  224  | 
|  212   def _RenderTypeInformation(self, property_, dst_dict): |  225   def _RenderTypeInformation(self, property_, dst_dict): | 
|  213     if property_.type_ == model.PropertyType.CHOICES: |  226     if property_.type_ == model.PropertyType.CHOICES: | 
|  214       dst_dict['choices'] = map(self._GenerateProperty, |  227       dst_dict['choices'] = [self._GenerateProperty(c) | 
|  215                                 property_.choices.values()) |  228                              for c in property_.choices.values()] | 
|  216       # We keep track of which is last for knowing when to add "or" between |  229       # We keep track of which is last for knowing when to add "or" between | 
|  217       # choices in templates. |  230       # choices in templates. | 
|  218       if len(dst_dict['choices']) > 0: |  231       if len(dst_dict['choices']) > 0: | 
|  219         dst_dict['choices'][-1]['last'] = True |  232         dst_dict['choices'][-1]['last'] = True | 
|  220     elif property_.type_ == model.PropertyType.REF: |  233     elif property_.type_ == model.PropertyType.REF: | 
|  221       dst_dict['link'] = GetLinkToRefType(self._namespace.name, |  234       dst_dict['link'] = self._GetLink(property_.ref_type) | 
|  222                                           property_.ref_type) |  | 
|  223     elif property_.type_ == model.PropertyType.ARRAY: |  235     elif property_.type_ == model.PropertyType.ARRAY: | 
|  224       dst_dict['array'] = self._GenerateProperty(property_.item_type) |  236       dst_dict['array'] = self._GenerateProperty(property_.item_type) | 
|  225     elif property_.type_ == model.PropertyType.ENUM: |  237     elif property_.type_ == model.PropertyType.ENUM: | 
|  226       dst_dict['enum_values'] = [] |  238       dst_dict['enum_values'] = [] | 
|  227       for enum_value in property_.enum_values: |  239       for enum_value in property_.enum_values: | 
|  228         dst_dict['enum_values'].append({'name': enum_value}) |  240         dst_dict['enum_values'].append({'name': enum_value}) | 
|  229       if len(dst_dict['enum_values']) > 0: |  241       if len(dst_dict['enum_values']) > 0: | 
|  230         dst_dict['enum_values'][-1]['last'] = True |  242         dst_dict['enum_values'][-1]['last'] = True | 
|  231     elif property_.instance_of is not None: |  243     elif property_.instance_of is not None: | 
|  232       dst_dict['simple_type'] = property_.instance_of.lower() |  244       dst_dict['simple_type'] = property_.instance_of.lower() | 
|  233     else: |  245     else: | 
|  234       dst_dict['simple_type'] = property_.type_.name.lower() |  246       dst_dict['simple_type'] = property_.type_.name.lower() | 
|  235  |  247  | 
|  236 class _LazySamplesGetter(object): |  248 class _LazySamplesGetter(object): | 
|  237   """This class is needed so that an extensions API page does not have to fetch |  249   """This class is needed so that an extensions API page does not have to fetch | 
|  238   the apps samples page and vice versa. |  250   the apps samples page and vice versa. | 
|  239   """ |  251   """ | 
|  240   def __init__(self, api_name, samples): |  252   def __init__(self, api_name, samples): | 
|  241     self._api_name = api_name |  253     self._api_name = api_name | 
|  242     self._samples = samples |  254     self._samples = samples | 
|  243  |  255  | 
|  244   def get(self, key): |  256   def get(self, key): | 
|  245     return self._samples.FilterSamples(key, self._api_name) |  257     return self._samples.FilterSamples(key, self._api_name) | 
|  246  |  258  | 
|  247 class APIDataSource(object): |  259 class APIDataSource(object): | 
|  248   """This class fetches and loads JSON APIs from the FileSystem passed in with |  260   """This class fetches and loads JSON APIs from the FileSystem passed in with | 
|  249   |cache_factory|, so the APIs can be plugged into templates. |  261   |cache_factory|, so the APIs can be plugged into templates. | 
|  250   """ |  262   """ | 
|  251   class Factory(object): |  263   class Factory(object): | 
|  252     def __init__(self, cache_factory, base_path, samples_factory): |  264     def __init__(self, | 
 |  265                  cache_factory, | 
 |  266                  base_path): | 
|  253       self._permissions_cache = cache_factory.Create(self._LoadPermissions, |  267       self._permissions_cache = cache_factory.Create(self._LoadPermissions, | 
|  254                                                      compiled_fs.PERMS, |  268                                                      compiled_fs.PERMS, | 
|  255                                                      version=_VERSION) |  269                                                      version=_VERSION) | 
|  256       self._json_cache = cache_factory.Create(self._LoadJsonAPI, |  270       self._json_cache = cache_factory.Create( | 
|  257                                               compiled_fs.JSON, |  271           lambda api: self._LoadJsonAPI(api, False), | 
|  258                                               version=_VERSION) |  272           compiled_fs.JSON, | 
|  259       self._idl_cache = cache_factory.Create(self._LoadIdlAPI, |  273           version=_VERSION) | 
|  260                                              compiled_fs.IDL, |  274       self._idl_cache = cache_factory.Create( | 
|  261                                              version=_VERSION) |  275           lambda api: self._LoadIdlAPI(api, False), | 
 |  276           compiled_fs.IDL, | 
 |  277           version=_VERSION) | 
 |  278  | 
 |  279       # These caches are used if an APIDataSource does not want to resolve the | 
 |  280       # $refs in an API. This is needed to prevent infinite recursion in | 
 |  281       # ReferenceResolver. | 
 |  282       self._json_cache_no_refs = cache_factory.Create( | 
 |  283           lambda api: self._LoadJsonAPI(api, True), | 
 |  284           compiled_fs.JSON_NO_REFS, | 
 |  285           version=_VERSION) | 
 |  286       self._idl_cache_no_refs = cache_factory.Create( | 
 |  287           lambda api: self._LoadIdlAPI(api, True), | 
 |  288           compiled_fs.IDL_NO_REFS, | 
 |  289           version=_VERSION) | 
|  262       self._idl_names_cache = cache_factory.Create(self._GetIDLNames, |  290       self._idl_names_cache = cache_factory.Create(self._GetIDLNames, | 
|  263                                                    compiled_fs.IDL_NAMES, |  291                                                    compiled_fs.IDL_NAMES, | 
|  264                                                    version=_VERSION) |  292                                                    version=_VERSION) | 
|  265       self._samples_factory = samples_factory |  293       self._names_cache = cache_factory.Create(self._GetAllNames, | 
 |  294                                                compiled_fs.NAMES, | 
 |  295                                                version=_VERSION) | 
|  266       self._base_path = base_path |  296       self._base_path = base_path | 
|  267  |  297  | 
|  268     def Create(self, request): |  298       # These must be set later via the SetFooDataSourceFactory methods. | 
 |  299       self._ref_resolver_factory = None | 
 |  300       self._samples_data_source_factory = None | 
 |  301  | 
 |  302     def SetSamplesDataSourceFactory(self, samples_data_source_factory): | 
 |  303       self._samples_data_source_factory = samples_data_source_factory | 
 |  304  | 
 |  305     def SetReferenceResolverFactory(self, ref_resolver_factory): | 
 |  306       self._ref_resolver_factory = ref_resolver_factory | 
 |  307  | 
 |  308     def Create(self, request, disable_refs=False): | 
 |  309       """Create an APIDataSource. |disable_refs| specifies whether $ref's in | 
 |  310       APIs being processed by the |ToDict| method of _JSCModel follows $ref's | 
 |  311       in the API. This prevents endless recursion in ReferenceResolver. | 
 |  312       """ | 
 |  313       if self._samples_data_source_factory is None: | 
 |  314         # Only error if there is a request, which means this APIDataSource is | 
 |  315         # actually being used to render a page. | 
 |  316         if request is not None: | 
 |  317           logging.error('SamplesDataSource.Factory was never set in ' | 
 |  318                         'APIDataSource.Factory.') | 
 |  319         samples = None | 
 |  320       else: | 
 |  321         samples = self._samples_data_source_factory.Create(request) | 
 |  322       if not disable_refs and self._ref_resolver_factory is None: | 
 |  323         logging.error('ReferenceResolver.Factory was never set in ' | 
 |  324                       'APIDataSource.Factory.') | 
|  269       return APIDataSource(self._permissions_cache, |  325       return APIDataSource(self._permissions_cache, | 
|  270                            self._json_cache, |  326                            self._json_cache, | 
|  271                            self._idl_cache, |  327                            self._idl_cache, | 
 |  328                            self._json_cache_no_refs, | 
 |  329                            self._idl_cache_no_refs, | 
 |  330                            self._names_cache, | 
|  272                            self._idl_names_cache, |  331                            self._idl_names_cache, | 
|  273                            self._base_path, |  332                            self._base_path, | 
|  274                            self._samples_factory.Create(request)) |  333                            samples, | 
 |  334                            disable_refs) | 
|  275  |  335  | 
|  276     def _LoadPermissions(self, json_str): |  336     def _LoadPermissions(self, json_str): | 
|  277       return json.loads(json_comment_eater.Nom(json_str)) |  337       return json.loads(json_comment_eater.Nom(json_str)) | 
|  278  |  338  | 
|  279     def _LoadJsonAPI(self, api): |  339     def _LoadJsonAPI(self, api, disable_refs): | 
|  280       return _JscModel(json.loads(json_comment_eater.Nom(api))[0]) |  340       return _JSCModel( | 
 |  341           json.loads(json_comment_eater.Nom(api))[0], | 
 |  342           self._ref_resolver_factory.Create() if not disable_refs else None, | 
 |  343           disable_refs).ToDict() | 
|  281  |  344  | 
|  282     def _LoadIdlAPI(self, api): |  345     def _LoadIdlAPI(self, api, disable_refs): | 
|  283       idl = idl_parser.IDLParser().ParseData(api) |  346       idl = idl_parser.IDLParser().ParseData(api) | 
|  284       return _JscModel(idl_schema.IDLSchema(idl).process()[0]) |  347       return _JSCModel( | 
 |  348           idl_schema.IDLSchema(idl).process()[0], | 
 |  349           self._ref_resolver_factory.Create() if not disable_refs else None, | 
 |  350           disable_refs).ToDict() | 
|  285  |  351  | 
|  286     def _GetIDLNames(self, apis): |  352     def _GetIDLNames(self, apis): | 
|  287       return [model.UnixName(os.path.splitext(api.split('/')[-1])[0]) |  353       return [ | 
|  288               for api in apis if api.endswith('.idl')] |  354         model.UnixName(os.path.splitext(api[len('%s/' % self._base_path):])[0]) | 
 |  355         for api in apis if api.endswith('.idl') | 
 |  356       ] | 
 |  357  | 
 |  358     def _GetAllNames(self, apis): | 
 |  359       return [ | 
 |  360         model.UnixName(os.path.splitext(api[len('%s/' % self._base_path):])[0]) | 
 |  361         for api in apis | 
 |  362       ] | 
|  289  |  363  | 
|  290   def __init__(self, |  364   def __init__(self, | 
|  291                permissions_cache, |  365                permissions_cache, | 
|  292                json_cache, |  366                json_cache, | 
|  293                idl_cache, |  367                idl_cache, | 
 |  368                json_cache_no_refs, | 
 |  369                idl_cache_no_refs, | 
 |  370                names_cache, | 
|  294                idl_names_cache, |  371                idl_names_cache, | 
|  295                base_path, |  372                base_path, | 
|  296                samples): |  373                samples, | 
 |  374                disable_refs): | 
|  297     self._base_path = base_path |  375     self._base_path = base_path | 
|  298     self._permissions_cache = permissions_cache |  376     self._permissions_cache = permissions_cache | 
|  299     self._json_cache = json_cache |  377     self._json_cache = json_cache | 
|  300     self._idl_cache = idl_cache |  378     self._idl_cache = idl_cache | 
 |  379     self._json_cache_no_refs = json_cache_no_refs | 
 |  380     self._idl_cache_no_refs = idl_cache_no_refs | 
 |  381     self._names_cache = names_cache | 
|  301     self._idl_names_cache = idl_names_cache |  382     self._idl_names_cache = idl_names_cache | 
|  302     self._samples = samples |  383     self._samples = samples | 
 |  384     self._disable_refs = disable_refs | 
|  303  |  385  | 
|  304   def _GetPermsFromFile(self, filename): |  386   def _GetPermsFromFile(self, filename): | 
|  305     try: |  387     try: | 
|  306       perms = self._permissions_cache.GetFromFile('%s/%s' % |  388       perms = self._permissions_cache.GetFromFile('%s/%s' % | 
|  307           (self._base_path, filename)) |  389           (self._base_path, filename)) | 
|  308       return dict((model.UnixName(k), v) for k, v in perms.iteritems()) |  390       return dict((model.UnixName(k), v) for k, v in perms.iteritems()) | 
|  309     except FileNotFoundError: |  391     except FileNotFoundError: | 
|  310       return {} |  392       return {} | 
|  311  |  393  | 
|  312   def _GetFeature(self, path): |  394   def _GetFeature(self, path): | 
|  313     # Remove 'experimental_' from path name to match the keys in |  395     # Remove 'experimental_' from path name to match the keys in | 
|  314     # _permissions_features.json. |  396     # _permissions_features.json. | 
|  315     path = model.UnixName(path.replace('experimental_', '')) |  397     path = model.UnixName(path.replace('experimental_', '')) | 
|  316     for filename in ['_permission_features.json', '_manifest_features.json']: |  398     for filename in ['_permission_features.json', '_manifest_features.json']: | 
|  317       api_perms = self._GetPermsFromFile(filename).get(path, None) |  399       api_perms = self._GetPermsFromFile(filename).get(path, None) | 
|  318       if api_perms is not None: |  400       if api_perms is not None: | 
|  319         break |  401         break | 
|  320     if api_perms and api_perms['channel'] in ('trunk', 'dev', 'beta'): |  402     if api_perms and api_perms['channel'] in ('trunk', 'dev', 'beta'): | 
|  321       api_perms[api_perms['channel']] = True |  403       api_perms[api_perms['channel']] = True | 
|  322     return api_perms |  404     return api_perms | 
|  323  |  405  | 
|  324   def _GenerateHandlebarContext(self, handlebar, path): |  406   def _GenerateHandlebarContext(self, handlebar_dict, path): | 
|  325     return_dict = { |  407     return_dict = { | 
|  326       'permissions': self._GetFeature(path), |  408       'permissions': self._GetFeature(path), | 
|  327       'samples': _LazySamplesGetter(path, self._samples) |  409       'samples': _LazySamplesGetter(path, self._samples) | 
|  328     } |  410     } | 
|  329     return_dict.update(handlebar.ToDict()) |  411     return_dict.update(handlebar_dict) | 
|  330     return return_dict |  412     return return_dict | 
|  331  |  413  | 
|  332   def __getitem__(self, key): |  414   def _GetAsSubdirectory(self, name): | 
|  333     return self.get(key) |  415     if name.startswith('experimental_'): | 
 |  416       parts = name[len('experimental_'):].split('_', 1) | 
 |  417       parts[1] = 'experimental_%s' % parts[1] | 
 |  418       return '/'.join(parts) | 
 |  419     return name.replace('_', '/', 1) | 
|  334  |  420  | 
|  335   def get(self, key): |  421   def get(self, key): | 
|  336     path, ext = os.path.splitext(key) |  422     if key.endswith('.html') or key.endswith('.json') or key.endswith('.idl'): | 
 |  423       path, ext = os.path.splitext(key) | 
 |  424     else: | 
 |  425       path = key | 
|  337     unix_name = model.UnixName(path) |  426     unix_name = model.UnixName(path) | 
|  338     idl_names = self._idl_names_cache.GetFromFileListing(self._base_path) |  427     idl_names = self._idl_names_cache.GetFromFileListing(self._base_path) | 
|  339     cache, ext = ((self._idl_cache, '.idl') if (unix_name in idl_names) else |  428     names = self._names_cache.GetFromFileListing(self._base_path) | 
|  340                   (self._json_cache, '.json')) |  429     if unix_name not in names and self._GetAsSubdirectory(unix_name) in names: | 
 |  430       unix_name = self._GetAsSubdirectory(unix_name) | 
 |  431  | 
 |  432     if self._disable_refs: | 
 |  433       cache, ext = ( | 
 |  434           (self._idl_cache_no_refs, '.idl') if (unix_name in idl_names) else | 
 |  435           (self._json_cache_no_refs, '.json')) | 
 |  436     else: | 
 |  437       cache, ext = ((self._idl_cache, '.idl') if (unix_name in idl_names) else | 
 |  438                     (self._json_cache, '.json')) | 
|  341     return self._GenerateHandlebarContext( |  439     return self._GenerateHandlebarContext( | 
|  342         cache.GetFromFile('%s/%s%s' % (self._base_path, unix_name, ext)), |  440         cache.GetFromFile('%s/%s%s' % (self._base_path, unix_name, ext)), | 
|  343         path) |  441         path) | 
| OLD | NEW |