Suppress tabs permission warning if there is already a browsingHistory warning.
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / api_models.py
blobd7cacc40f2832ff7ccebb03cb6ec0b4237eabf47
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.
5 import posixpath
7 from compiled_file_system import SingleFile, Unicode
8 from extensions_paths import API_PATHS
9 from file_system import FileNotFoundError
10 from future import Future
11 from schema_util import ProcessSchema
12 from third_party.json_schema_compiler.model import Namespace, UnixName
15 @SingleFile
16 @Unicode
17 def _CreateAPIModel(path, data):
18 schema = ProcessSchema(path, data)[0]
19 if not schema: return None
20 return Namespace(schema, schema['namespace'])
23 class APIModels(object):
24 '''Tracks APIs and their Models.
25 '''
27 def __init__(self, features_bundle, compiled_fs_factory, file_system):
28 self._features_bundle = features_bundle
29 self._model_cache = compiled_fs_factory.Create(
30 file_system, _CreateAPIModel, APIModels)
32 def GetNames(self):
33 # API names appear alongside some of their methods/events/etc in the
34 # features file. APIs are those which either implicitly or explicitly have
35 # no parent feature (e.g. app, app.window, and devtools.inspectedWindow are
36 # APIs; runtime.onConnectNative is not).
37 api_features = self._features_bundle.GetAPIFeatures().Get()
38 return [name for name, feature in api_features.iteritems()
39 if ('.' not in name or
40 name.rsplit('.', 1)[0] not in api_features or
41 feature.get('noparent'))]
43 def GetModel(self, api_name):
44 # By default |api_name| is assumed to be given without a path or extension,
45 # so combinations of known paths and extension types will be searched.
46 api_extensions = ('.json', '.idl')
47 api_paths = API_PATHS
49 # Callers sometimes include a file extension and/or prefix path with the
50 # |api_name| argument. We believe them and narrow the search space
51 # accordingly.
52 name, ext = posixpath.splitext(api_name)
53 if ext in api_extensions:
54 api_extensions = (ext,)
55 api_name = name
56 for api_path in api_paths:
57 if api_name.startswith(api_path):
58 api_name = api_name[len(api_path):]
59 api_paths = (api_path,)
60 break
62 # API names are given as declarativeContent and app.window but file names
63 # will be declarative_content and app_window.
64 file_name = UnixName(api_name).replace('.', '_')
65 # Devtools APIs are in API/devtools/ not API/, and have their
66 # "devtools" names removed from the file names.
67 basename = posixpath.basename(file_name)
68 if 'devtools_' in basename:
69 file_name = posixpath.join(
70 'devtools', file_name.replace(basename,
71 basename.replace('devtools_' , '')))
73 futures = [self._model_cache.GetFromFile(
74 posixpath.join(path, '%s%s' % (file_name, ext)))
75 for ext in api_extensions
76 for path in api_paths]
77 def resolve():
78 for future in futures:
79 try:
80 return future.Get()
81 except FileNotFoundError: pass
82 # Propagate the first FileNotFoundError if neither were found.
83 futures[0].Get()
84 return Future(callback=resolve)
86 def IterModels(self):
87 future_models = [(name, self.GetModel(name)) for name in self.GetNames()]
88 for name, future_model in future_models:
89 try:
90 model = future_model.Get()
91 except FileNotFoundError:
92 continue
93 if model:
94 yield name, model