diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-27 20:02:46 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-27 20:02:46 +0000 |
commit | 206ebea228b75fd6aa0f7d2867736799f4cadc56 (patch) | |
tree | 25bc16b76c739a6e8da5ff24d4c2468ab0b240ec | |
parent | 957cd5a210873c03233236dc038277a83a6069f9 (diff) | |
download | chromium_src-206ebea228b75fd6aa0f7d2867736799f4cadc56.zip chromium_src-206ebea228b75fd6aa0f7d2867736799f4cadc56.tar.gz chromium_src-206ebea228b75fd6aa0f7d2867736799f4cadc56.tar.bz2 |
Docs: Use the FeaturesBundle for all things features rather than
re-implementing similar logic in several places. This fixes a bug with the
commands API too (and desktopCapture, apparently).
BUG=357192
R=rockot@chromium.org
NOTRY=true
Review URL: https://codereview.chromium.org/212623015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@259958 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 94 insertions, 91 deletions
diff --git a/chrome/common/extensions/docs/server2/api_data_source.py b/chrome/common/extensions/docs/server2/api_data_source.py index b4d7358..ebb0c24 100644 --- a/chrome/common/extensions/docs/server2/api_data_source.py +++ b/chrome/common/extensions/docs/server2/api_data_source.py @@ -8,8 +8,7 @@ import os import posixpath from environment import IsPreviewServer -from extensions_paths import ( - API_FEATURES, JSON_TEMPLATES, PRIVATE_TEMPLATES) +from extensions_paths import JSON_TEMPLATES, PRIVATE_TEMPLATES import third_party.json_schema_compiler.json_parse as json_parse import third_party.json_schema_compiler.model as model from environment import IsPreviewServer @@ -74,6 +73,7 @@ class _JSCModel(object): availability_finder, json_cache, template_cache, + features_bundle, event_byname_function): self._ref_resolver = ref_resolver self._disable_refs = disable_refs @@ -82,7 +82,7 @@ class _JSCModel(object): posixpath.join(JSON_TEMPLATES, 'api_availabilities.json')) self._intro_tables = json_cache.GetFromFile( posixpath.join(JSON_TEMPLATES, 'intro_tables.json')) - self._api_features = json_cache.GetFromFile(API_FEATURES) + self._api_features = features_bundle.GetAPIFeatures() self._template_cache = template_cache self._event_byname_function = event_byname_function self._namespace = api_models.GetModel(api_name).Get() @@ -386,28 +386,20 @@ class _JSCModel(object): # Devtools aren't in _api_features. If we're dealing with devtools, bail. if 'devtools' in self._namespace.name: return [] - feature = self._api_features.Get().get(self._namespace.name) - assert feature, ('"%s" not found in _api_features.json.' - % self._namespace.name) - - # TODO(tbarzic, kalman): Move this logic into features_utility. - if isinstance(feature, list): - dependencies_set = set() - for subfeature in feature: - dependencies_set.update(subfeature.get('dependencies', ())) - dependencies = list(dependencies_set) - else: - dependencies = feature.get('dependencies') - if dependencies is None: - return [] - def make_code_node(text): - return { 'class': 'code', 'text': text } + api_feature = self._api_features.Get().get(self._namespace.name) + if not api_feature: + logging.error('"%s" not found in _api_features.json' % + self._namespace.name) + return [] permissions_content = [] manifest_content = [] def categorize_dependency(dependency): + def make_code_node(text): + return { 'class': 'code', 'text': text } + context, name = dependency.split(':', 1) if context == 'permission': permissions_content.append(make_code_node('"%s"' % name)) @@ -419,10 +411,10 @@ class _JSCModel(object): for transitive_dependency in transitive_dependencies: categorize_dependency(transitive_dependency) else: - raise ValueError('Unrecognized dependency for %s: %s' % ( - self._namespace.name, context)) + logging.error('Unrecognized dependency for %s: %s' % + (self._namespace.name, context)) - for dependency in dependencies: + for dependency in api_feature.get('dependencies', ()): categorize_dependency(dependency) dependency_rows = [] @@ -494,11 +486,13 @@ class APIDataSource(object): file_system, availability_finder, api_models, + features_bundle, object_store_creator): self._json_cache = compiled_fs_factory.ForJson(file_system) self._template_cache = compiled_fs_factory.ForTemplates(file_system) self._availability_finder = availability_finder self._api_models = api_models + self._features_bundle = features_bundle self._model_cache_refs = object_store_creator.Create( APIDataSource, 'model-cache-refs') self._model_cache_no_refs = object_store_creator.Create( @@ -558,6 +552,7 @@ class APIDataSource(object): self._availability_finder, self._json_cache, self._template_cache, + self._features_bundle, self._LoadEventByName).ToDict() self._GetModelCache(disable_refs).Set(api_name, jsc_model) diff --git a/chrome/common/extensions/docs/server2/api_data_source_test.py b/chrome/common/extensions/docs/server2/api_data_source_test.py index 47c4992b..e842576 100755 --- a/chrome/common/extensions/docs/server2/api_data_source_test.py +++ b/chrome/common/extensions/docs/server2/api_data_source_test.py @@ -13,6 +13,8 @@ from api_data_source import (_JSCModel, _GetEventByNameFromEvents) from branch_utility import ChannelInfo from extensions_paths import CHROME_EXTENSIONS +from fake_host_file_system_provider import FakeHostFileSystemProvider +from features_bundle import FeaturesBundle from file_system import FileNotFoundError from future import Future from object_store_creator import ObjectStoreCreator @@ -41,19 +43,6 @@ class _FakeAvailabilityFinder(object): return ChannelInfo('stable', '396', 5) -class _FakeHostFileSystemProvider(object): - - def __init__(self, file_system_data): - self._file_system_data = file_system_data - - def GetTrunk(self): - return self.GetBranch('trunk') - - @memoize - def GetBranch(self, branch): - return TestFileSystem(self._file_system_data[str(branch)]) - - class _FakeSamplesDataSource(object): def Create(self, request): @@ -97,13 +86,16 @@ class APIDataSourceTest(unittest.TestCase): server_instance = ServerInstance.ForTest( TestFileSystem(CANNED_TRUNK_FS_DATA, relative_to=CHROME_EXTENSIONS)) - self._json_cache = server_instance.compiled_fs_factory.ForJson( - server_instance.host_file_system_provider.GetTrunk()) + file_system = server_instance.host_file_system_provider.GetTrunk() + self._json_cache = server_instance.compiled_fs_factory.ForJson(file_system) + self._features_bundle = FeaturesBundle(file_system, + server_instance.compiled_fs_factory, + server_instance.object_store_creator) self._api_models = server_instance.api_models # Used for testGetApiAvailability() so that valid-ish data is processed. server_instance = ServerInstance.ForTest( - file_system_provider=_FakeHostFileSystemProvider( + file_system_provider=FakeHostFileSystemProvider( CANNED_API_FILE_SYSTEM_DATA)) self._avail_api_models = server_instance.api_models self._avail_json_cache = server_instance.compiled_fs_factory.ForJson( @@ -131,6 +123,7 @@ class APIDataSourceTest(unittest.TestCase): _FakeAvailabilityFinder(), self._json_cache, _FakeTemplateCache(), + self._features_bundle, None).ToDict() self.assertEquals('type-TypeA', dict_['types'][0]['id']) self.assertEquals('property-TypeA-b', @@ -148,6 +141,7 @@ class APIDataSourceTest(unittest.TestCase): _FakeAvailabilityFinder(), self._json_cache, _FakeTemplateCache(), + self._features_bundle, None).ToDict() self.assertEquals(expected_json, dict_) @@ -164,6 +158,7 @@ class APIDataSourceTest(unittest.TestCase): _FakeAvailabilityFinder(), self._json_cache, _FakeTemplateCache(), + self._features_bundle, None).ToDict() self.assertEquals(_MakeLink('ref_test.html#type-type2', 'type2'), _GetType(dict_, 'type1')['description']) @@ -194,6 +189,7 @@ class APIDataSourceTest(unittest.TestCase): self._avail_finder, self._avail_json_cache, _FakeTemplateCache(), + self._features_bundle, None) self.assertEquals(availability, model._GetApiAvailability()) @@ -205,6 +201,7 @@ class APIDataSourceTest(unittest.TestCase): _FakeAvailabilityFinder(), self._json_cache, _FakeTemplateCache(), + self._features_bundle, None) expected_list = [ { 'title': 'Description', @@ -277,6 +274,7 @@ class APIDataSourceTest(unittest.TestCase): _FakeAvailabilityFinder(), self._json_cache, _FakeTemplateCache(), + self._features_bundle, self._FakeLoadAddRulesSchema).ToDict() # Check that the first event has the addRulesFunction defined. diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml index 324f88c5..325d09d 100644 --- a/chrome/common/extensions/docs/server2/app.yaml +++ b/chrome/common/extensions/docs/server2/app.yaml @@ -1,5 +1,5 @@ application: chrome-apps-doc -version: 3-14-5 +version: 3-15-0 runtime: python27 api_version: 1 threadsafe: false diff --git a/chrome/common/extensions/docs/server2/availability_finder.py b/chrome/common/extensions/docs/server2/availability_finder.py index 138fe8a..a5bba8e 100644 --- a/chrome/common/extensions/docs/server2/availability_finder.py +++ b/chrome/common/extensions/docs/server2/availability_finder.py @@ -7,9 +7,9 @@ import posixpath from api_schema_graph import APISchemaGraph from branch_utility import BranchUtility -from extensions_paths import ( - API, CHROME_API, JSON_TEMPLATES, API_FEATURES, MANIFEST_FEATURES, - PERMISSION_FEATURES) +from extensions_paths import API, CHROME_API, JSON_TEMPLATES +from features_bundle import FeaturesBundle +import features_utility from file_system import FileNotFoundError from third_party.json_schema_compiler.model import UnixName @@ -27,34 +27,12 @@ _EXTENSION_API_MAX_VERSION = 17 _SVN_MIN_VERSION = 5 -def _GetChannelFromFeatures(api_name, json_fs, filename): - '''Finds API channel information from the features |filename| within the the - given |json_fs|. Returns None if channel information for the API cannot be - located. +def _GetChannelFromFeatures(api_name, features): + '''Finds API channel information for |api_name| from |features|. + Returns None if channel information for the API cannot be located. ''' - feature = json_fs.GetFromFile(filename).Get().get(api_name) - if feature is None: - return None - if isinstance(feature, Mapping): - # The channel information exists as a solitary dict. - return feature.get('channel') - # The channel information dict is nested within a list for whitelisting - # purposes. Take the newest channel out of all of the entries. - return BranchUtility.NewestChannel(entry.get('channel') for entry in feature) - - -def _GetChannelFromApiFeatures(api_name, json_fs): - return _GetChannelFromFeatures(api_name, json_fs, API_FEATURES) - - -def _GetChannelFromManifestFeatures(api_name, json_fs): - # _manifest_features.json uses unix_style API names. - api_name = UnixName(api_name) - return _GetChannelFromFeatures(api_name, json_fs, MANIFEST_FEATURES) - - -def _GetChannelFromPermissionFeatures(api_name, json_fs): - return _GetChannelFromFeatures(api_name, json_fs, PERMISSION_FEATURES) + feature = features.Get().get(api_name) + return feature.get('channel') if feature else None class AvailabilityFinder(object): @@ -154,19 +132,21 @@ class AvailabilityFinder(object): if version < _SVN_MIN_VERSION: # SVN data isn't available below this version. return False + features_bundle = self._CreateFeaturesBundle(file_system) available_channel = None - json_fs = self._compiled_fs_factory.ForJson(file_system) if version >= _API_FEATURES_MIN_VERSION: # The _api_features.json file first appears in version 28 and should be # the most reliable for finding API availability. - available_channel = _GetChannelFromApiFeatures(api_name, json_fs) + available_channel = self._GetChannelFromApiFeatures(api_name, + features_bundle) if version >= _ORIGINAL_FEATURES_MIN_VERSION: # The _permission_features.json and _manifest_features.json files are # present in Chrome 20 and onwards. Use these if no information could be # found using _api_features.json. - available_channel = available_channel or ( - _GetChannelFromPermissionFeatures(api_name, json_fs) - or _GetChannelFromManifestFeatures(api_name, json_fs)) + available_channel = ( + available_channel or + self._GetChannelFromPermissionFeatures(api_name, features_bundle) or + self._GetChannelFromManifestFeatures(api_name, features_bundle)) if available_channel is not None: return available_channel == 'stable' if version >= _SVN_MIN_VERSION: @@ -180,10 +160,11 @@ class AvailabilityFinder(object): back to checking the file system for API schema existence, to determine whether or not an API is available on the given channel, |channel_info|. ''' - json_fs = self._compiled_fs_factory.ForJson(file_system) - available_channel = (_GetChannelFromApiFeatures(api_name, json_fs) - or _GetChannelFromPermissionFeatures(api_name, json_fs) - or _GetChannelFromManifestFeatures(api_name, json_fs)) + features_bundle = self._CreateFeaturesBundle(file_system) + available_channel = ( + self._GetChannelFromApiFeatures(api_name, features_bundle) or + self._GetChannelFromPermissionFeatures(api_name, features_bundle) or + self._GetChannelFromManifestFeatures(api_name, features_bundle)) if (available_channel is None and self._HasApiSchema(api_name, file_system, channel_info.version)): # If an API is not represented in any of the _features files, but exists @@ -196,6 +177,24 @@ class AvailabilityFinder(object): channel_info.channel)) return available_channel is not None and newest == channel_info.channel + def _CreateFeaturesBundle(self, file_system): + return FeaturesBundle(file_system, + self._compiled_fs_factory, + self._object_store_creator) + + def _GetChannelFromApiFeatures(self, api_name, features_bundle): + return _GetChannelFromFeatures(api_name, features_bundle.GetAPIFeatures()) + + def _GetChannelFromManifestFeatures(self, api_name, features_bundle): + # _manifest_features.json uses unix_style API names. + api_name = UnixName(api_name) + return _GetChannelFromFeatures(api_name, + features_bundle.GetManifestFeatures()) + + def _GetChannelFromPermissionFeatures(self, api_name, features_bundle): + return _GetChannelFromFeatures(api_name, + features_bundle.GetPermissionFeatures()) + def _CheckApiAvailability(self, api_name, file_system, channel_info): '''Determines the availability for an API at a certain version of Chrome. Two branches of logic are used depending on whether or not the API is diff --git a/chrome/common/extensions/docs/server2/cron.yaml b/chrome/common/extensions/docs/server2/cron.yaml index aff29da..a8feaa7 100644 --- a/chrome/common/extensions/docs/server2/cron.yaml +++ b/chrome/common/extensions/docs/server2/cron.yaml @@ -2,4 +2,4 @@ cron: - description: Repopulates all cached data. url: /_cron schedule: every 5 minutes - target: 3-14-5 + target: 3-15-0 diff --git a/chrome/common/extensions/docs/server2/features_bundle.py b/chrome/common/extensions/docs/server2/features_bundle.py index 5d76cfe..b98bdff 100644 --- a/chrome/common/extensions/docs/server2/features_bundle.py +++ b/chrome/common/extensions/docs/server2/features_bundle.py @@ -8,6 +8,7 @@ from compiled_file_system import Unicode from extensions_paths import ( API_FEATURES, JSON_TEMPLATES, MANIFEST_FEATURES, PERMISSION_FEATURES) import features_utility +from file_system import FileNotFoundError from future import Future from third_party.json_schema_compiler.json_parse import Parse @@ -51,7 +52,11 @@ class _FeaturesCache(object): for path in self._extra_paths] features = features_utility.Parse(Parse(features_json)) for path_future in extra_path_futures: - extra_json = path_future.Get() + try: + extra_json = path_future.Get() + except FileNotFoundError: + # Not all file system configurations have the extra files. + continue features = features_utility.MergedWith( features_utility.Parse(Parse(extra_json)), features) return features @@ -80,7 +85,11 @@ class FeaturesBundle(object): compiled_fs_factory, PERMISSION_FEATURES, posixpath.join(JSON_TEMPLATES, 'permissions.json')) - self._object_store = object_store_creator.Create(_FeaturesCache, 'features') + # Namespace the object store by the file system ID because this class is + # used by the availability finder cross-channel. + # TODO(kalman): Configure this at the ObjectStore level. + self._object_store = object_store_creator.Create( + _FeaturesCache, category=file_system.GetIdentity()) def GetPermissionFeatures(self): return self._permission_cache.GetFeatures() diff --git a/chrome/common/extensions/docs/server2/server_instance.py b/chrome/common/extensions/docs/server2/server_instance.py index 13f4f20..7894f77 100644 --- a/chrome/common/extensions/docs/server2/server_instance.py +++ b/chrome/common/extensions/docs/server2/server_instance.py @@ -98,6 +98,7 @@ class ServerInstance(object): host_fs_at_trunk, self.availability_finder, self.api_models, + self.features_bundle, self.object_store_creator) self.ref_resolver_factory = ReferenceResolver.Factory( diff --git a/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py b/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py index e47e927..27d45f5 100644 --- a/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py +++ b/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py @@ -182,7 +182,9 @@ CANNED_TRUNK_FS_DATA = { } ] } - }) + }), + 'manifest.json': '{}', + 'permissions.json': '{}' }, 'private': { 'intro_tables': { diff --git a/chrome/common/extensions/docs/server2/test_data/canned_data.py b/chrome/common/extensions/docs/server2/test_data/canned_data.py index 143da00..fabbf99 100644 --- a/chrome/common/extensions/docs/server2/test_data/canned_data.py +++ b/chrome/common/extensions/docs/server2/test_data/canned_data.py @@ -205,9 +205,9 @@ CANNED_API_FILE_SYSTEM_DATA = MoveAllTo(CHROME_EXTENSIONS, { { 'channel': 'beta', 'extension_types': ['extension'] }, - # whitelist { 'channel': 'stable', - 'extension_types': ['extension'] + 'extension_types': ['extension'], + 'whitelist': ['aaa'] }, ], 'falseBetaAPI': { @@ -370,8 +370,7 @@ CANNED_API_FILE_SYSTEM_DATA = MoveAllTo(CHROME_EXTENSIONS, { }, 'declarativeWebRequest': [ { 'channel': 'beta' }, - # whitelist - { 'channel': 'stable'} + { 'channel': 'stable', 'whitelist': ['aaa'] } ], 'downloads': { 'channel': 'beta' @@ -500,8 +499,7 @@ CANNED_API_FILE_SYSTEM_DATA = MoveAllTo(CHROME_EXTENSIONS, { }, 'declarativeWebRequest': [ { 'channel': 'beta' }, - # whitelist - { 'channel': 'stable'} + { 'channel': 'stable', 'whitelist': ['aaa'] } ], 'downloads': { 'channel': 'dev' @@ -614,8 +612,7 @@ CANNED_API_FILE_SYSTEM_DATA = MoveAllTo(CHROME_EXTENSIONS, { }, 'declarativeWebRequest': [ { 'channel': 'beta' }, - # whitelist - { 'channel': 'stable'} + { 'channel': 'stable', 'whitelist': ['aaa'] } ], 'systemInfo.display': { 'channel': 'stable' diff --git a/chrome/common/extensions/docs/templates/intros/commands.html b/chrome/common/extensions/docs/templates/intros/commands.html index 0416a57..6d9503b 100644 --- a/chrome/common/extensions/docs/templates/intros/commands.html +++ b/chrome/common/extensions/docs/templates/intros/commands.html @@ -1,8 +1,10 @@ <h2 id="manifest">Manifest</h2> <p> -You must set manifest_version to (at least) 2 to use this API. +You must have a <code>"manifest_version"</code> of at least <code>2</code> to use this API. </p> +{{?is_apps +partials.warning_dev /}} + <h2 id="usage">Usage</h2> <p>The commands API allows you to define specific commands, and bind them to a default key combination. Each command your extension accepts must be listed in |