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