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 logging | 6 import logging |
7 import os | 7 import os |
8 import posixpath | 8 import posixpath |
9 | 9 |
10 from environment import IsPreviewServer | 10 from environment import IsPreviewServer |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 | 62 |
63 class _JSCModel(object): | 63 class _JSCModel(object): |
64 '''Uses a Model from the JSON Schema Compiler and generates a dict that | 64 '''Uses a Model from the JSON Schema Compiler and generates a dict that |
65 a Handlebar template can use for a data source. | 65 a Handlebar template can use for a data source. |
66 ''' | 66 ''' |
67 | 67 |
68 def __init__(self, | 68 def __init__(self, |
69 api_name, | 69 api_name, |
70 api_models, | 70 api_models, |
71 ref_resolver, | |
72 disable_refs, | 71 disable_refs, |
73 availability_finder, | 72 availability_finder, |
74 json_cache, | 73 json_cache, |
75 template_cache, | 74 template_cache, |
76 features_bundle, | 75 features_bundle, |
77 event_byname_function): | 76 event_byname_function): |
78 self._ref_resolver = ref_resolver | |
79 self._disable_refs = disable_refs | 77 self._disable_refs = disable_refs |
80 self._availability_finder = availability_finder | 78 self._availability_finder = availability_finder |
81 self._api_availabilities = json_cache.GetFromFile( | 79 self._api_availabilities = json_cache.GetFromFile( |
82 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) | 80 posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) |
83 self._intro_tables = json_cache.GetFromFile( | 81 self._intro_tables = json_cache.GetFromFile( |
84 posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) | 82 posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) |
85 self._api_features = features_bundle.GetAPIFeatures() | 83 self._api_features = features_bundle.GetAPIFeatures() |
86 self._template_cache = template_cache | 84 self._template_cache = template_cache |
87 self._event_byname_function = event_byname_function | 85 self._event_byname_function = event_byname_function |
88 self._namespace = api_models.GetModel(api_name).Get() | 86 self._namespace = api_models.GetModel(api_name).Get() |
89 | 87 |
90 def _FormatDescription(self, description): | |
91 if self._disable_refs: | |
92 return description | |
93 return self._ref_resolver.ResolveAllLinks(description, | |
94 namespace=self._namespace.name) | |
95 | |
96 def _GetLink(self, link): | 88 def _GetLink(self, link): |
97 if self._disable_refs: | 89 ref = link if '.' in link else (self._namespace.name + '.' + link) |
98 type_name = link.split('.', 1)[-1] | 90 return { 'ref': ref, 'text': link, 'name': link } |
99 return { 'href': '#type-%s' % type_name, 'text': link, 'name': link } | |
100 return self._ref_resolver.SafeGetLink(link, namespace=self._namespace.name) | |
101 | 91 |
102 def ToDict(self): | 92 def ToDict(self): |
103 if self._namespace is None: | 93 if self._namespace is None: |
104 return {} | 94 return {} |
105 chrome_dot_name = 'chrome.%s' % self._namespace.name | 95 chrome_dot_name = 'chrome.%s' % self._namespace.name |
106 as_dict = { | 96 as_dict = { |
107 'name': self._namespace.name, | 97 'name': self._namespace.name, |
108 'namespace': self._namespace.documentation_options.get('namespace', | 98 'namespace': self._namespace.documentation_options.get('namespace', |
109 chrome_dot_name), | 99 chrome_dot_name), |
110 'title': self._namespace.documentation_options.get('title', | 100 'title': self._namespace.documentation_options.get('title', |
(...skipping 27 matching lines...) Expand all Loading... |
138 | 128 |
139 def _IsExperimental(self): | 129 def _IsExperimental(self): |
140 return self._namespace.name.startswith('experimental') | 130 return self._namespace.name.startswith('experimental') |
141 | 131 |
142 def _GenerateTypes(self, types): | 132 def _GenerateTypes(self, types): |
143 return [self._GenerateType(t) for t in types] | 133 return [self._GenerateType(t) for t in types] |
144 | 134 |
145 def _GenerateType(self, type_): | 135 def _GenerateType(self, type_): |
146 type_dict = { | 136 type_dict = { |
147 'name': type_.simple_name, | 137 'name': type_.simple_name, |
148 'description': self._FormatDescription(type_.description), | 138 'description': type_.description, |
149 'properties': self._GenerateProperties(type_.properties), | 139 'properties': self._GenerateProperties(type_.properties), |
150 'functions': self._GenerateFunctions(type_.functions), | 140 'functions': self._GenerateFunctions(type_.functions), |
151 'events': self._GenerateEvents(type_.events), | 141 'events': self._GenerateEvents(type_.events), |
152 'id': _CreateId(type_, 'type') | 142 'id': _CreateId(type_, 'type') |
153 } | 143 } |
154 self._RenderTypeInformation(type_, type_dict) | 144 self._RenderTypeInformation(type_, type_dict) |
155 return type_dict | 145 return type_dict |
156 | 146 |
157 def _GenerateFunctions(self, functions): | 147 def _GenerateFunctions(self, functions): |
158 return [self._GenerateFunction(f) for f in functions.values()] | 148 return [self._GenerateFunction(f) for f in functions.values()] |
159 | 149 |
160 def _GenerateFunction(self, function): | 150 def _GenerateFunction(self, function): |
161 function_dict = { | 151 function_dict = { |
162 'name': function.simple_name, | 152 'name': function.simple_name, |
163 'description': self._FormatDescription(function.description), | 153 'description': function.description, |
164 'callback': self._GenerateCallback(function.callback), | 154 'callback': self._GenerateCallback(function.callback), |
165 'parameters': [], | 155 'parameters': [], |
166 'returns': None, | 156 'returns': None, |
167 'id': _CreateId(function, 'method') | 157 'id': _CreateId(function, 'method') |
168 } | 158 } |
169 self._AddCommonProperties(function_dict, function) | 159 self._AddCommonProperties(function_dict, function) |
170 if function.returns: | 160 if function.returns: |
171 function_dict['returns'] = self._GenerateType(function.returns) | 161 function_dict['returns'] = self._GenerateType(function.returns) |
172 for param in function.params: | 162 for param in function.params: |
173 function_dict['parameters'].append(self._GenerateProperty(param)) | 163 function_dict['parameters'].append(self._GenerateProperty(param)) |
174 if function.callback is not None: | 164 if function.callback is not None: |
175 # Show the callback as an extra parameter. | 165 # Show the callback as an extra parameter. |
176 function_dict['parameters'].append( | 166 function_dict['parameters'].append( |
177 self._GenerateCallbackProperty(function.callback)) | 167 self._GenerateCallbackProperty(function.callback)) |
178 if len(function_dict['parameters']) > 0: | 168 if len(function_dict['parameters']) > 0: |
179 function_dict['parameters'][-1]['last'] = True | 169 function_dict['parameters'][-1]['last'] = True |
180 return function_dict | 170 return function_dict |
181 | 171 |
182 def _GenerateEvents(self, events): | 172 def _GenerateEvents(self, events): |
183 return [self._GenerateEvent(e) for e in events.values() | 173 return [self._GenerateEvent(e) for e in events.values() |
184 if not e.supports_dom] | 174 if not e.supports_dom] |
185 | 175 |
186 def _GenerateDomEvents(self, events): | 176 def _GenerateDomEvents(self, events): |
187 return [self._GenerateEvent(e) for e in events.values() | 177 return [self._GenerateEvent(e) for e in events.values() |
188 if e.supports_dom] | 178 if e.supports_dom] |
189 | 179 |
190 def _GenerateEvent(self, event): | 180 def _GenerateEvent(self, event): |
191 event_dict = { | 181 event_dict = { |
192 'name': event.simple_name, | 182 'name': event.simple_name, |
193 'description': self._FormatDescription(event.description), | 183 'description': event.description, |
194 'filters': [self._GenerateProperty(f) for f in event.filters], | 184 'filters': [self._GenerateProperty(f) for f in event.filters], |
195 'conditions': [self._GetLink(condition) | 185 'conditions': [self._GetLink(condition) |
196 for condition in event.conditions], | 186 for condition in event.conditions], |
197 'actions': [self._GetLink(action) for action in event.actions], | 187 'actions': [self._GetLink(action) for action in event.actions], |
198 'supportsRules': event.supports_rules, | 188 'supportsRules': event.supports_rules, |
199 'supportsListeners': event.supports_listeners, | 189 'supportsListeners': event.supports_listeners, |
200 'properties': [], | 190 'properties': [], |
201 'id': _CreateId(event, 'event'), | 191 'id': _CreateId(event, 'event'), |
202 'byName': {}, | 192 'byName': {}, |
203 } | 193 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 # Make sure we generate property info for arrays, too. | 250 # Make sure we generate property info for arrays, too. |
261 # TODO(kalman): what about choices? | 251 # TODO(kalman): what about choices? |
262 if type_.property_type == model.PropertyType.ARRAY: | 252 if type_.property_type == model.PropertyType.ARRAY: |
263 properties = type_.item_type.properties | 253 properties = type_.item_type.properties |
264 else: | 254 else: |
265 properties = type_.properties | 255 properties = type_.properties |
266 | 256 |
267 property_dict = { | 257 property_dict = { |
268 'name': property_.simple_name, | 258 'name': property_.simple_name, |
269 'optional': property_.optional, | 259 'optional': property_.optional, |
270 'description': self._FormatDescription(property_.description), | 260 'description': property_.description, |
271 'properties': self._GenerateProperties(type_.properties), | 261 'properties': self._GenerateProperties(type_.properties), |
272 'functions': self._GenerateFunctions(type_.functions), | 262 'functions': self._GenerateFunctions(type_.functions), |
273 'parameters': [], | 263 'parameters': [], |
274 'returns': None, | 264 'returns': None, |
275 'id': _CreateId(property_, 'property') | 265 'id': _CreateId(property_, 'property') |
276 } | 266 } |
277 self._AddCommonProperties(property_dict, property_) | 267 self._AddCommonProperties(property_dict, property_) |
278 | 268 |
279 if type_.property_type == model.PropertyType.FUNCTION: | 269 if type_.property_type == model.PropertyType.FUNCTION: |
280 function = type_.function | 270 function = type_.function |
281 for param in function.params: | 271 for param in function.params: |
282 property_dict['parameters'].append(self._GenerateProperty(param)) | 272 property_dict['parameters'].append(self._GenerateProperty(param)) |
283 if function.returns: | 273 if function.returns: |
284 property_dict['returns'] = self._GenerateType(function.returns) | 274 property_dict['returns'] = self._GenerateType(function.returns) |
285 | 275 |
286 value = property_.value | 276 value = property_.value |
287 if value is not None: | 277 if value is not None: |
288 if isinstance(value, int): | 278 if isinstance(value, int): |
289 property_dict['value'] = _FormatValue(value) | 279 property_dict['value'] = _FormatValue(value) |
290 else: | 280 else: |
291 property_dict['value'] = value | 281 property_dict['value'] = value |
292 else: | 282 else: |
293 self._RenderTypeInformation(type_, property_dict) | 283 self._RenderTypeInformation(type_, property_dict) |
294 | 284 |
295 return property_dict | 285 return property_dict |
296 | 286 |
297 def _GenerateCallbackProperty(self, callback): | 287 def _GenerateCallbackProperty(self, callback): |
298 property_dict = { | 288 property_dict = { |
299 'name': callback.simple_name, | 289 'name': callback.simple_name, |
300 'description': self._FormatDescription(callback.description), | 290 'description': callback.description, |
301 'optional': callback.optional, | 291 'optional': callback.optional, |
302 'is_callback': True, | 292 'is_callback': True, |
303 'id': _CreateId(callback, 'property'), | 293 'id': _CreateId(callback, 'property'), |
304 'simple_type': 'function', | 294 'simple_type': 'function', |
305 } | 295 } |
306 if (callback.parent is not None and | 296 if (callback.parent is not None and |
307 not isinstance(callback.parent, model.Namespace)): | 297 not isinstance(callback.parent, model.Namespace)): |
308 property_dict['parentName'] = callback.parent.simple_name | 298 property_dict['parentName'] = callback.parent.simple_name |
309 return property_dict | 299 return property_dict |
310 | 300 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 intro_rows.append(misc_row) | 340 intro_rows.append(misc_row) |
351 | 341 |
352 return intro_rows | 342 return intro_rows |
353 | 343 |
354 def _GetIntroDescriptionRow(self): | 344 def _GetIntroDescriptionRow(self): |
355 ''' Generates the 'Description' row data for an API intro table. | 345 ''' Generates the 'Description' row data for an API intro table. |
356 ''' | 346 ''' |
357 return { | 347 return { |
358 'title': 'Description', | 348 'title': 'Description', |
359 'content': [ | 349 'content': [ |
360 { 'text': self._FormatDescription(self._namespace.description) } | 350 { 'text': self._namespace.description } |
361 ] | 351 ] |
362 } | 352 } |
363 | 353 |
364 def _GetIntroAvailabilityRow(self): | 354 def _GetIntroAvailabilityRow(self): |
365 ''' Generates the 'Availability' row data for an API intro table. | 355 ''' Generates the 'Availability' row data for an API intro table. |
366 ''' | 356 ''' |
367 if self._IsExperimental(): | 357 if self._IsExperimental(): |
368 status = 'experimental' | 358 status = 'experimental' |
369 version = None | 359 version = None |
370 else: | 360 else: |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 # If there is a 'partial' argument and it hasn't already been | 438 # If there is a 'partial' argument and it hasn't already been |
449 # converted to a Handlebar object, transform it to a template. | 439 # converted to a Handlebar object, transform it to a template. |
450 if 'partial' in node: | 440 if 'partial' in node: |
451 node['partial'] = self._template_cache.GetFromFile( | 441 node['partial'] = self._template_cache.GetFromFile( |
452 posixpath.join(PRIVATE_TEMPLATES, node['partial'])).Get() | 442 posixpath.join(PRIVATE_TEMPLATES, node['partial'])).Get() |
453 misc_rows.append({ 'title': category, 'content': content }) | 443 misc_rows.append({ 'title': category, 'content': content }) |
454 return misc_rows | 444 return misc_rows |
455 | 445 |
456 def _AddCommonProperties(self, target, src): | 446 def _AddCommonProperties(self, target, src): |
457 if src.deprecated is not None: | 447 if src.deprecated is not None: |
458 target['deprecated'] = self._FormatDescription( | 448 target['deprecated'] = src.deprecated |
459 src.deprecated) | |
460 if (src.parent is not None and | 449 if (src.parent is not None and |
461 not isinstance(src.parent, model.Namespace)): | 450 not isinstance(src.parent, model.Namespace)): |
462 target['parentName'] = src.parent.simple_name | 451 target['parentName'] = src.parent.simple_name |
463 | 452 |
464 | 453 |
465 class _LazySamplesGetter(object): | 454 class _LazySamplesGetter(object): |
466 '''This class is needed so that an extensions API page does not have to fetch | 455 '''This class is needed so that an extensions API page does not have to fetch |
467 the apps samples page and vice versa. | 456 the apps samples page and vice versa. |
468 ''' | 457 ''' |
469 | 458 |
(...skipping 22 matching lines...) Expand all Loading... |
492 self._template_cache = compiled_fs_factory.ForTemplates(file_system) | 481 self._template_cache = compiled_fs_factory.ForTemplates(file_system) |
493 self._availability_finder = availability_finder | 482 self._availability_finder = availability_finder |
494 self._api_models = api_models | 483 self._api_models = api_models |
495 self._features_bundle = features_bundle | 484 self._features_bundle = features_bundle |
496 self._model_cache_refs = object_store_creator.Create( | 485 self._model_cache_refs = object_store_creator.Create( |
497 APIDataSource, 'model-cache-refs') | 486 APIDataSource, 'model-cache-refs') |
498 self._model_cache_no_refs = object_store_creator.Create( | 487 self._model_cache_no_refs = object_store_creator.Create( |
499 APIDataSource, 'model-cache-no-refs') | 488 APIDataSource, 'model-cache-no-refs') |
500 | 489 |
501 # These must be set later via the SetFooDataSourceFactory methods. | 490 # These must be set later via the SetFooDataSourceFactory methods. |
502 self._ref_resolver_factory = None | |
503 self._samples_data_source_factory = None | 491 self._samples_data_source_factory = None |
504 | 492 |
505 # This caches the result of _LoadEventByName. | 493 # This caches the result of _LoadEventByName. |
506 self._event_byname = None | 494 self._event_byname = None |
507 | 495 |
508 def SetSamplesDataSourceFactory(self, samples_data_source_factory): | 496 def SetSamplesDataSourceFactory(self, samples_data_source_factory): |
509 self._samples_data_source_factory = samples_data_source_factory | 497 self._samples_data_source_factory = samples_data_source_factory |
510 | 498 |
511 def SetReferenceResolverFactory(self, ref_resolver_factory): | |
512 self._ref_resolver_factory = ref_resolver_factory | |
513 | |
514 def Create(self, request): | 499 def Create(self, request): |
515 '''Creates an APIDataSource. | 500 '''Creates an APIDataSource. |
516 ''' | 501 ''' |
517 if self._samples_data_source_factory is None: | 502 if self._samples_data_source_factory is None: |
518 # Only error if there is a request, which means this APIDataSource is | 503 # Only error if there is a request, which means this APIDataSource is |
519 # actually being used to render a page. | 504 # actually being used to render a page. |
520 if request is not None: | 505 if request is not None: |
521 logging.error('SamplesDataSource.Factory was never set in ' | 506 logging.error('SamplesDataSource.Factory was never set in ' |
522 'APIDataSource.Factory.') | 507 'APIDataSource.Factory.') |
523 samples = None | 508 samples = None |
(...skipping 16 matching lines...) Expand all Loading... |
540 return self._model_cache_refs | 525 return self._model_cache_refs |
541 | 526 |
542 def _GetSchemaModel(self, api_name, disable_refs): | 527 def _GetSchemaModel(self, api_name, disable_refs): |
543 jsc_model = self._GetModelCache(disable_refs).Get(api_name).Get() | 528 jsc_model = self._GetModelCache(disable_refs).Get(api_name).Get() |
544 if jsc_model is not None: | 529 if jsc_model is not None: |
545 return jsc_model | 530 return jsc_model |
546 | 531 |
547 jsc_model = _JSCModel( | 532 jsc_model = _JSCModel( |
548 api_name, | 533 api_name, |
549 self._api_models, | 534 self._api_models, |
550 self._ref_resolver_factory.Create() if not disable_refs else None, | |
551 disable_refs, | 535 disable_refs, |
552 self._availability_finder, | 536 self._availability_finder, |
553 self._json_cache, | 537 self._json_cache, |
554 self._template_cache, | 538 self._template_cache, |
555 self._features_bundle, | 539 self._features_bundle, |
556 self._LoadEventByName).ToDict() | 540 self._LoadEventByName).ToDict() |
557 | 541 |
558 self._GetModelCache(disable_refs).Set(api_name, jsc_model) | 542 self._GetModelCache(disable_refs).Set(api_name, jsc_model) |
559 return jsc_model | 543 return jsc_model |
560 | 544 |
561 def __init__(self, get_schema_model, samples): | 545 def __init__(self, get_schema_model, samples): |
562 self._get_schema_model = get_schema_model | 546 self._get_schema_model = get_schema_model |
563 self._samples = samples | 547 self._samples = samples |
564 | 548 |
565 def _GenerateHandlebarContext(self, handlebar_dict): | 549 def _GenerateHandlebarContext(self, handlebar_dict): |
566 # Parsing samples on the preview server takes seconds and doesn't add | 550 # Parsing samples on the preview server takes seconds and doesn't add |
567 # anything. Don't do it. | 551 # anything. Don't do it. |
568 if not IsPreviewServer(): | 552 if not IsPreviewServer(): |
569 handlebar_dict['samples'] = _LazySamplesGetter( | 553 handlebar_dict['samples'] = _LazySamplesGetter( |
570 handlebar_dict['name'], | 554 handlebar_dict['name'], |
571 self._samples) | 555 self._samples) |
572 return handlebar_dict | 556 return handlebar_dict |
573 | 557 |
574 def get(self, api_name, disable_refs=False): | 558 def get(self, api_name, disable_refs=False): |
575 return self._GenerateHandlebarContext( | 559 return self._GenerateHandlebarContext( |
576 self._get_schema_model(api_name, disable_refs)) | 560 self._get_schema_model(api_name, disable_refs)) |
OLD | NEW |