api_data_source.py revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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
3# found in the LICENSE file.
4
5from data_source import DataSource
6from docs_server_utils import StringIdentity
7from environment import IsPreviewServer
8from file_system import FileNotFoundError
9from future import Future, All
10from jsc_view import JSCView, GetEventByNameFromEvents
11from platform_util import GetPlatforms
12
13
14class _LazySamplesGetter(object):
15  '''This class is needed so that an extensions API page does not have to fetch
16  the apps samples page and vice versa.
17  '''
18
19  def __init__(self, api_name, samples):
20    self._api_name = api_name
21    self._samples = samples
22
23  def get(self, key):
24    return self._samples.FilterSamples(key, self._api_name)
25
26
27class APIDataSource(DataSource):
28  '''This class fetches and loads JSON APIs from the FileSystem passed in with
29  |compiled_fs_factory|, so the APIs can be plugged into templates.
30  '''
31  def __init__(self, server_instance, request):
32    file_system = server_instance.host_file_system_provider.GetTrunk()
33    self._json_cache = server_instance.compiled_fs_factory.ForJson(file_system)
34    self._template_cache = server_instance.compiled_fs_factory.ForTemplates(
35        file_system)
36    self._platform_bundle = server_instance.platform_bundle
37    self._view_cache = server_instance.object_store_creator.Create(
38        APIDataSource,
39        # Update the models when any of templates, APIs, or Features change.
40        category=StringIdentity(self._json_cache.GetIdentity(),
41                                self._template_cache.GetIdentity(),
42                                self._platform_bundle.GetIdentity()))
43
44    # This caches the result of _LoadEventByName.
45    self._event_byname_futures = {}
46    self._samples = server_instance.samples_data_source_factory.Create(request)
47
48  def _LoadEventByName(self, platform):
49    '''All events have some members in common. We source their description
50    from Event in events.json.
51    '''
52    if platform not in self._event_byname_futures:
53      future = self._GetSchemaView(platform, 'events')
54      self._event_byname_futures[platform] = Future(
55          callback=lambda: GetEventByNameFromEvents(future.Get()))
56    return self._event_byname_futures[platform]
57
58  def _GetSchemaView(self, platform, api_name):
59    object_store_key = '/'.join((platform, api_name))
60    api_models = self._platform_bundle.GetAPIModels(platform)
61    jsc_view_future = self._view_cache.Get(object_store_key)
62    model_future = api_models.GetModel(api_name)
63    content_script_apis_future = api_models.GetContentScriptAPIs()
64    def resolve():
65      jsc_view = jsc_view_future.Get()
66      if jsc_view is None:
67        jsc_view = JSCView(
68            content_script_apis_future.Get(),
69            model_future.Get(),
70            self._platform_bundle.GetAvailabilityFinder(platform),
71            self._json_cache,
72            self._template_cache,
73            self._platform_bundle.GetFeaturesBundle(platform),
74            self._LoadEventByName(platform),
75            platform).ToDict()
76        self._view_cache.Set(object_store_key, jsc_view)
77      return jsc_view
78    return Future(callback=resolve)
79
80  def _GetImpl(self, platform, api_name):
81    jsc_view_future = self._GetSchemaView(platform, api_name)
82    def resolve():
83      jsc_view = jsc_view_future.Get()
84      # Parsing samples on the preview server takes seconds and doesn't add
85      # anything. Don't do it.
86      if not IsPreviewServer():
87        jsc_view['samples'] = _LazySamplesGetter(
88            jsc_view['name'],
89            self._samples)
90      return jsc_view
91    return Future(callback=resolve)
92
93  def get(self, platform):
94    '''Return a getter object so that templates can perform lookups such
95    as apis.extensions.runtime.
96    '''
97    getter = lambda: 0
98    getter.get = lambda api_name: self._GetImpl(platform, api_name).Get()
99    return getter
100
101  def Cron(self):
102    futures = []
103    for platform in GetPlatforms():
104      futures += [self._GetImpl(platform, name)
105          for name in self._platform_bundle.GetAPIModels(platform).GetNames()]
106    return All(futures, except_pass=FileNotFoundError)
107