Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(429)

Side by Side Diff: third_party/WebKit/Source/bindings/scripts/generate_conditional_features.py

Issue 2970003002: Add code generation for ConditionalFeatures bindings code (Closed)
Patch Set: Clean up Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright 2017 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7 # This script reads the global interface data collected by
8 # compute_interfaces_info_overall.py, and writes out the code which adds
9 # bindings for origin-trial-enabled features at runtime.
10
11 # pylint: disable=W0403
12
13 import optparse
14 import os
15 import posixpath
16 import sys
17 from collections import defaultdict
18
19 from code_generator import CodeGeneratorBase
20 from idl_reader import IdlReader
21 from utilities import create_component_info_provider, write_file, read_pickle_fi le
22 from v8_utilities import v8_class_name, v8_class_name_or_partial, uncapitalize
23
24 # Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
25 MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
26
27
28 def get_install_functions(interfaces, feature_names):
29 install_functions = []
30 for interface_info in interfaces:
31 for feature_name in feature_names:
32 install_function = {
33 "condition": 'OriginTrials::%sEnabled' % uncapitalize(feature_na me),
chasej 2017/07/11 20:12:31 I'm wondering if it would be better to have the co
iclelland 2017/07/12 17:23:20 I was definitely thinking about other kinds of con
34 "name": feature_name,
35 "install_method": "install%s" % feature_name,
36 "class": interface_info[1],
37 "class_or_partial": interface_info[2]
38 }
39 install_functions.append(install_function)
40 return install_functions
41
42
43 def get_conditional_feature_names_from_interface(interface):
44 feature_names = set()
45 if 'OriginTrialEnabled' in interface.extended_attributes and interface.is_pa rtial:
46 feature_names.add(interface.extended_attributes['OriginTrialEnabled'])
47 for operation in interface.operations:
48 if 'OriginTrialEnabled' in operation.extended_attributes:
49 feature_names.add(operation.extended_attributes['OriginTrialEnabled' ])
50 for attribute in interface.attributes:
51 if 'OriginTrialEnabled' in attribute.extended_attributes:
52 feature_names.add(attribute.extended_attributes['OriginTrialEnabled' ])
53 return list(feature_names)
54
55
56 class ConditionalFeaturesCodeGenerator(CodeGeneratorBase):
57 def __init__(self, generator_name, info_provider, global_objects, cache_dir, output_dir):
58 super(ConditionalFeaturesCodeGenerator, self).__init__(generator_name, i nfo_provider, cache_dir, output_dir)
59 self.global_objects = global_objects
60
61 def generate_code(self, reader, idl_filenames, header_template, cpp_template , target_component):
62 context = {}
63 context['header_includes'] = []
64
65 includes = set([
66 "core/context_features/ContextFeatureSettings.h",
67 "core/dom/ExecutionContext.h",
68 "core/frame/Frame.h",
69 "core/origin_trials/OriginTrials.h",
70 "platform/bindings/ConditionalFeatures.h",
71 "platform/bindings/ScriptState.h",
72 ])
73 # TODO(iclelland): Remove the need to explicitly include this; it is
74 # here because the ContextFeatureSettings code needs it.
75 includes.add("bindings/core/v8/V8Window.h")
76
77 features_for_type = defaultdict(set)
78 types_for_feature = defaultdict(set)
79
80 for idl_filename in idl_filenames:
81 interfaces_read = reader.read_idl_file(idl_filename).interfaces
82 assert len(interfaces_read) == 1
83 name, interface_read = interfaces_read.items()[0]
84 feature_names = get_conditional_feature_names_from_interface(interfa ce_read)
85 if feature_names:
86 # HACK WARNING: This is here becase the ServiceWorker interface
87 # is actually a complete interface in modules/, but the Origin
88 # Trial declarations end up on
89 # ServiceWorkerGlobalScopeModulesConstructors.idl, which is a
90 # partial interface declaration. TODO: Fix this by correctly
91 # determining whether the interface where the install* methods
92 # are declared is partial or not.
93 if 'ServiceWorkerGlobalScope' in idl_filename:
94 interface_read.is_partial = False
95 # END OF HACK
96 if interface_read.is_partial:
97 includes.add('bindings/core/v8/V8%s.h' % name)
98 includes.add('bindings/%s/v8/V8%sPartial.h' % (target_compon ent, name))
99 else:
100 includes.add('bindings/%s/v8/V8%s.h' % (target_component, na me))
101 interface_info = (name, v8_class_name(interface_read), v8_class_ name_or_partial(interface_read))
102 for feature_name in feature_names:
103 features_for_type[interface_info].add(feature_name)
104 types_for_feature[feature_name].add(interface_info)
105
106 context['installers_by_interface'] = [
107 {"name": interface_info[0],
108 "is_global": interface_info[0] in self.global_objects,
109 "class": interface_info[1],
110 "installers": get_install_functions([interface_info], feature_names )}
111 for interface_info, feature_names in features_for_type.items()]
112 context['installers_by_interface'].sort(key=lambda x: x['name'])
113
114 context['installers_by_feature'] = [
115 {"name": feature_name,
116 "installers": get_install_functions(interfaces, [feature_name])}
117 for feature_name, interfaces in types_for_feature.items()]
118 context['installers_by_feature'].sort(key=lambda x: x['name'])
119
120 context['includes'] = sorted(includes)
121 return self.render_template(
122 [],
123 self.jinja_env.get_template(header_template),
124 self.jinja_env.get_template(cpp_template),
125 context, target_component)
126
127
128 def parse_options():
129 parser = optparse.OptionParser()
130 parser.add_option('--cache-directory',
131 help='cache directory, defaults to output directory')
132 parser.add_option('--output-directory')
133 parser.add_option('--info-dir')
134 parser.add_option('--target-component',
135 type='choice',
136 choices=['Core', 'Modules'],
137 help='target component to generate code')
138 parser.add_option('--idl-files-list')
139 parser.add_option('--global-objects-file')
140
141 options, _ = parser.parse_args()
142 if options.output_directory is None:
143 parser.error('Must specify output directory using --output-directory.')
144 return options
145
146
147 def main():
148 options = parse_options()
149 info_provider = create_component_info_provider(
150 os.path.normpath(options.info_dir), options.target_component.lower())
151
152 idl_filenames = map(str.strip, open(options.idl_files_list))
153 reader = IdlReader(info_provider.interfaces_info, options.cache_directory)
154 cg = ConditionalFeaturesCodeGenerator(MODULE_PYNAME, info_provider,
155 read_pickle_file(options.global_object s_file),
156 options.cache_directory,
157 options.output_directory)
158
159 header_text, cpp_text = cg.generate_code(
160 reader, idl_filenames,
161 "ConditionalFeaturesFor%s.h.tmpl" % options.target_component,
162 "ConditionalFeaturesFor%s.cpp.tmpl" % options.target_component,
163 options.target_component.lower())
164 header_path = posixpath.join(options.output_directory,
165 "ConditionalFeaturesFor%s.h" % options.target_c omponent)
166 cpp_path = posixpath.join(options.output_directory,
167 "ConditionalFeaturesFor%s.cpp" % options.target_co mponent)
168 write_file(header_text, header_path)
169 write_file(cpp_text, cpp_path)
170 return 0
171
172
173 if __name__ == '__main__':
174 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698