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 future import Future
7from operator import itemgetter
8from platform_util import GetPlatforms
9
10from docs_server_utils import MarkFirstAndLast, MarkLast
11
12class APIListDataSource(DataSource):
13  """ This class creates a list of chrome.* APIs and chrome.experimental.* APIs
14  for extensions and apps that are used in the api_index.html,
15  experimental.html, and private_apis.html pages.
16
17  An API is considered listable if it is listed in _api_features.json,
18  it has a corresponding HTML file in the public template path, and one of
19  the following conditions is met:
20    - It has no "dependencies" or "extension_types" properties in _api_features
21    - It has an "extension_types" property in _api_features with either/both
22      "extension"/"platform_app" values present.
23    - It has a dependency in _{api,manifest,permission}_features with an
24      "extension_types" property where either/both "extension"/"platform_app"
25      values are present.
26  """
27  def __init__(self, server_instance, _):
28    self._platform_bundle = server_instance.platform_bundle
29    self._object_store = server_instance.object_store_creator.Create(
30        # Update the model when the API or Features model updates.
31        APIListDataSource, category=self._platform_bundle.GetIdentity())
32
33  def _GenerateAPIDict(self):
34    def make_list_for_content_scripts():
35      def convert_to_list(content_script_apis):
36        content_script_apis_list = [csa.__dict__ for api_name, csa
37                                    in content_script_apis.iteritems()
38                                    if self._platform_bundle.GetAPICategorizer(
39                                        'extensions').IsDocumented(api_name)]
40        content_script_apis_list.sort(key=itemgetter('name'))
41        for csa in content_script_apis_list:
42          restricted_nodes = csa['restrictedTo']
43          if restricted_nodes:
44            restricted_nodes.sort(key=itemgetter('node'))
45            MarkFirstAndLast(restricted_nodes)
46          else:
47            del csa['restrictedTo']
48        return content_script_apis_list
49
50      return (self._platform_bundle.GetAPIModels('extensions')
51              .GetContentScriptAPIs()
52              .Then(convert_to_list))
53
54    def make_dict_for_platform(platform):
55      platform_dict = {
56        'chrome': {'stable': [], 'beta': [], 'dev': [], 'master': []},
57      }
58      private_apis = []
59      experimental_apis = []
60      all_apis = []
61      for api_name, api_model in self._platform_bundle.GetAPIModels(
62          platform).IterModels():
63        if not self._platform_bundle.GetAPICategorizer(platform).IsDocumented(
64            api_name):
65          continue
66        api = {
67          'name': api_name,
68          'description': api_model.description,
69        }
70        category = self._platform_bundle.GetAPICategorizer(
71            platform).GetCategory(api_name)
72        if category == 'chrome':
73          channel_info = self._platform_bundle.GetAvailabilityFinder(
74              platform).GetAPIAvailability(api_name).channel_info
75          channel = channel_info.channel
76          if channel == 'stable':
77            version = channel_info.version
78            api['version'] = version
79          platform_dict[category][channel].append(api)
80          all_apis.append(api)
81        elif category == 'experimental':
82          experimental_apis.append(api)
83          all_apis.append(api)
84        elif category == 'private':
85          private_apis.append(api)
86
87      for channel, apis_by_channel in platform_dict['chrome'].iteritems():
88        apis_by_channel.sort(key=itemgetter('name'))
89        MarkLast(apis_by_channel)
90        platform_dict['chrome'][channel] = apis_by_channel
91
92      for key, apis in (('all', all_apis),
93                        ('private', private_apis),
94                        ('experimental', experimental_apis)):
95        apis.sort(key=itemgetter('name'))
96        MarkLast(apis)
97        platform_dict[key] = apis
98
99      return platform_dict
100
101    def make_api_dict(content_script_apis):
102      api_dict = dict((platform, make_dict_for_platform(platform))
103                       for platform in GetPlatforms())
104      api_dict['contentScripts'] = content_script_apis
105      return api_dict
106
107    return make_list_for_content_scripts().Then(make_api_dict)
108
109  def _GetCachedAPIData(self):
110    def persist_and_return(data):
111      self._object_store.Set('api_data', data)
112      return data
113    def return_or_generate(data):
114      if data is None:
115        return self._GenerateAPIDict().Then(persist_and_return)
116      return data
117    return self._object_store.Get('api_data').Then(return_or_generate)
118
119  def get(self, key):
120    return self._GetCachedAPIData().Get().get(key)
121
122  def Refresh(self, path):
123    return self._GetCachedAPIData()
124