• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2013 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 compiled_file_system import Unicode
6from extensions_paths import (
7    API_FEATURES, JSON_TEMPLATES, MANIFEST_FEATURES, PERMISSION_FEATURES)
8import features_utility
9from future import Gettable, Future
10from third_party.json_schema_compiler.json_parse import Parse
11
12
13def _AddPlatformsFromDependencies(feature,
14                                  api_features,
15                                  manifest_features,
16                                  permission_features):
17  features_map = {
18    'api': api_features,
19    'manifest': manifest_features,
20    'permission': permission_features,
21  }
22  dependencies = feature.get('dependencies')
23  if dependencies is None:
24    return ['apps', 'extensions']
25  platforms = set()
26  for dependency in dependencies:
27    dep_type, dep_name = dependency.split(':')
28    dependency_features = features_map[dep_type]
29    dependency_feature = dependency_features.get(dep_name)
30    # If the dependency can't be resolved, it is inaccessible and therefore
31    # so is this feature.
32    if dependency_feature is None:
33      return []
34    platforms = platforms.union(dependency_feature['platforms'])
35  feature['platforms'] = list(platforms)
36
37
38class _FeaturesCache(object):
39  def __init__(self, file_system, compiled_fs_factory, *json_paths):
40    self._cache = compiled_fs_factory.Create(
41        file_system, self._CreateCache, type(self))
42    self._text_cache = compiled_fs_factory.ForUnicode(file_system)
43    self._json_path = json_paths[0]
44    self._extra_paths = json_paths[1:]
45
46  @Unicode
47  def _CreateCache(self, _, features_json):
48    extra_path_futures = [self._text_cache.GetFromFile(path)
49                          for path in self._extra_paths]
50    features = features_utility.Parse(Parse(features_json))
51    for path_future in extra_path_futures:
52      extra_json = path_future.Get()
53      features = features_utility.MergedWith(
54          features_utility.Parse(Parse(extra_json)), features)
55    return features
56
57  def GetFeatures(self):
58    if self._json_path is None:
59      return Future(value={})
60    return self._cache.GetFromFile(self._json_path)
61
62
63class FeaturesBundle(object):
64  '''Provides access to properties of API, Manifest, and Permission features.
65  '''
66  def __init__(self, file_system, compiled_fs_factory, object_store_creator):
67    self._api_cache = _FeaturesCache(
68        file_system,
69        compiled_fs_factory,
70        API_FEATURES)
71    self._manifest_cache = _FeaturesCache(
72        file_system,
73        compiled_fs_factory,
74        MANIFEST_FEATURES,
75        '%s/manifest.json' % JSON_TEMPLATES)
76    self._permission_cache = _FeaturesCache(
77        file_system,
78        compiled_fs_factory,
79        PERMISSION_FEATURES,
80        '%s/permissions.json' % JSON_TEMPLATES)
81    self._object_store = object_store_creator.Create(_FeaturesCache, 'features')
82
83  def GetPermissionFeatures(self):
84    return self._permission_cache.GetFeatures()
85
86  def GetManifestFeatures(self):
87    return self._manifest_cache.GetFeatures()
88
89  def GetAPIFeatures(self):
90    api_features = self._object_store.Get('api_features').Get()
91    if api_features is not None:
92      return Future(value=api_features)
93
94    api_features_future = self._api_cache.GetFeatures()
95    manifest_features_future = self._manifest_cache.GetFeatures()
96    permission_features_future = self._permission_cache.GetFeatures()
97    def resolve():
98      api_features = api_features_future.Get()
99      manifest_features = manifest_features_future.Get()
100      permission_features = permission_features_future.Get()
101      # TODO(rockot): Handle inter-API dependencies more gracefully.
102      # Not yet a problem because there is only one such case (windows -> tabs).
103      # If we don't store this value before annotating platforms, inter-API
104      # dependencies will lead to infinite recursion.
105      for feature in api_features.itervalues():
106        _AddPlatformsFromDependencies(
107            feature, api_features, manifest_features, permission_features)
108      self._object_store.Set('api_features', api_features)
109      return api_features
110    return Future(delegate=Gettable(resolve))
111