--- a/dom/bindings/Configuration.py
+++ b/dom/bindings/Configuration.py
@@ -13,29 +13,36 @@ class DescriptorProvider:
"""
A way of getting descriptors for interface names. Subclasses must
have a getDescriptor method callable with the interface name only.
"""
def __init__(self):
pass
+def isChildPath(path, basePath):
+ return os.path.commonprefix((path, basePath)) == basePath
+
+
class Configuration(DescriptorProvider):
"""
Represents global configuration state based on IDL parse data and
the configuration file.
"""
- def __init__(self, filename, parseData, generatedEvents=[]):
+ def __init__(self, filename, webRoots, parseData, generatedEvents=[]):
DescriptorProvider.__init__(self)
# Read the configuration file.
glbl = {}
execfile(filename, glbl)
config = glbl['DOMInterfaces']
+ def isInWebIDLRoot(path):
+ return any(isChildPath(path, root) for root in webRoots)
+
# Build descriptors for all the interfaces we have in the parse data.
# This allows callers to specify a subset of interfaces by filtering
# |parseData|.
self.descriptors = []
self.interfaces = {}
self.descriptorsByName = {}
self.optimizedOutDescriptorNames = set()
self.generatedEvents = generatedEvents
@@ -89,16 +96,23 @@ class Configuration(DescriptorProvider):
raise TypeError(
"The binding build system doesn't really support "
"partial interfaces which don't appear in the "
"file in which the interface they are extending is "
"defined. Don't do this.\n"
"%s\n"
"%s" %
(partialIface.location, iface.location))
+ if not (iface.getExtendedAttribute("ChromeOnly") or
+ isInWebIDLRoot(iface.filename())):
+ raise TypeError(
+ "Interfaces which are exposed to the web may only be "
+ "defined in a DOM WebIDL root %r\n"
+ "%s" %
+ (webRoots, iface.location))
self.interfaces[iface.identifier.name] = iface
if iface.identifier.name not in config:
# Completely skip consequential interfaces with no descriptor
# if they have no interface object because chances are we
# don't need to do anything interesting with them.
if iface.isConsequential() and not iface.hasInterfaceObject():
self.optimizedOutDescriptorNames.add(iface.identifier.name)
continue
--- a/dom/bindings/mozwebidlcodegen/__init__.py
+++ b/dom/bindings/mozwebidlcodegen/__init__.py
@@ -145,17 +145,17 @@ class WebIDLCodegenManager(LoggingMixin)
'RegisterWorkerBindings.cpp',
'RegisterWorkerDebuggerBindings.cpp',
'RegisterWorkletBindings.cpp',
'ResolveSystemBinding.cpp',
'UnionTypes.cpp',
'PrototypeList.cpp',
}
- def __init__(self, config_path, inputs, exported_header_dir,
+ def __init__(self, config_path, webidl_root, inputs, exported_header_dir,
codegen_dir, state_path, cache_dir=None, make_deps_path=None,
make_deps_target=None):
"""Create an instance that manages WebIDLs in the build system.
config_path refers to a WebIDL config file (e.g. Bindings.conf).
inputs is a 4-tuple describing the input .webidl files and how to
process them. Members are:
(set(.webidl files), set(basenames of exported files),
@@ -171,16 +171,17 @@ class WebIDLCodegenManager(LoggingMixin)
make_deps_target is the target that receives the make dependencies. It
must be defined if using make_deps_path.
"""
self.populate_logger()
input_paths, exported_stems, generated_events_stems, example_interfaces = inputs
self._config_path = config_path
+ self._webidl_root = webidl_root
self._input_paths = set(input_paths)
self._exported_stems = set(exported_stems)
self._generated_events_stems = set(generated_events_stems)
self._generated_events_stems_as_array = generated_events_stems
self._example_interfaces = set(example_interfaces)
self._exported_header_dir = exported_header_dir
self._codegen_dir = codegen_dir
self._state_path = state_path
@@ -327,18 +328,36 @@ class WebIDLCodegenManager(LoggingMixin)
parser = WebIDL.Parser(self._cache_dir)
for path in sorted(self._input_paths):
with open(path, 'rb') as fh:
data = fh.read()
hashes[path] = hashlib.sha1(data).hexdigest()
parser.parse(data, path)
+ # Only these directories may contain WebIDL files with interfaces
+ # which are exposed to the web. WebIDL files in these roots may not
+ # be changed without DOM peer review.
+ #
+ # Other directories may contain WebIDL files as long as they only
+ # contain ChromeOnly interfaces. These are not subject to mandatory
+ # DOM peer review.
+ web_roots = (
+ # The main WebIDL root.
+ self._webidl_root,
+ # The binding config root, which contains some test-only
+ # interfaces.
+ os.path.dirname(self._config_path),
+ # The objdir sub-directory which contains generated WebIDL files.
+ self._codegen_dir,
+ )
+
self._parser_results = parser.finish()
- self._config = Configuration(self._config_path, self._parser_results,
+ self._config = Configuration(self._config_path, web_roots,
+ self._parser_results,
self._generated_events_stems_as_array)
self._input_hashes = hashes
def _write_global_derived(self):
from Codegen import GlobalGenRoots
things = [('declare', f) for f in self.GLOBAL_DECLARE_FILES]
things.extend(('define', f) for f in self.GLOBAL_DEFINE_FILES)
@@ -541,32 +560,34 @@ class WebIDLCodegenManager(LoggingMixin)
else:
result[2].add(path)
def create_build_system_manager(topsrcdir, topobjdir, dist_dir):
"""Create a WebIDLCodegenManager for use by the build system."""
src_dir = os.path.join(topsrcdir, 'dom', 'bindings')
obj_dir = os.path.join(topobjdir, 'dom', 'bindings')
+ web_dir = os.path.join(topsrcdir, 'dom', 'webidl')
with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh:
files = json.load(fh)
inputs = (files['webidls'], files['exported_stems'],
files['generated_events_stems'], files['example_interfaces'])
cache_dir = os.path.join(obj_dir, '_cache')
try:
os.makedirs(cache_dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
return WebIDLCodegenManager(
os.path.join(src_dir, 'Bindings.conf'),
+ web_dir,
inputs,
os.path.join(dist_dir, 'include', 'mozilla', 'dom'),
obj_dir,
os.path.join(obj_dir, 'codegen.json'),
cache_dir=cache_dir,
# The make rules include a codegen.pp file containing dependencies.
make_deps_path=os.path.join(obj_dir, 'codegen.pp'),
make_deps_target='codegen.pp',