Bug 1442931: Part 1 - Forbid web-visible interfaces outside of WebIDL root. r=mystor

Web-visible WebIDL interfaces require DOM peer review with every change, which
is enforced by a commit hook. ChromeOnly interfaces are not exposed to the
web, and therefore don't require the same strictures.

The current commit hook enforces the review requirement for changes to any
(non-Servo) WebIDL file, and is not smart enough to determine if the change is
web-visible. In order to loosen that restriction, we need the build system to
enforce the requirement that only WebIDL files in certain locations may
contain web-visible interfaces, so that the commit hook can restrict itself to
checking only those directories.

This change restricts the location of web-visible WebIDL interfaces to the
dom/webidl/ and dom/bindings/ roots (along with the corresponding objdir root
for generated interfaces). A follow-up will change the commit hook to only
enforce review requirements on these directories.

MozReview-Commit-ID: CiDxXxN4oO4

--HG--
extra : rebase_source : f61b33ae4c973b1c9ec1423bb9baca59725e44b1
This commit is contained in:
Kris Maglione 2018-03-05 14:21:38 -08:00
Родитель 9f7ee3a7b0
Коммит d047164a17
2 изменённых файлов: 42 добавлений и 3 удалений

Просмотреть файл

@ -18,12 +18,16 @@ class DescriptorProvider:
pass pass
def isChildPath(path, basePath):
return os.path.commonprefix((path, basePath)) == basePath
class Configuration(DescriptorProvider): class Configuration(DescriptorProvider):
""" """
Represents global configuration state based on IDL parse data and Represents global configuration state based on IDL parse data and
the configuration file. the configuration file.
""" """
def __init__(self, filename, parseData, generatedEvents=[]): def __init__(self, filename, webRoots, parseData, generatedEvents=[]):
DescriptorProvider.__init__(self) DescriptorProvider.__init__(self)
# Read the configuration file. # Read the configuration file.
@ -31,6 +35,9 @@ class Configuration(DescriptorProvider):
execfile(filename, glbl) execfile(filename, glbl)
config = glbl['DOMInterfaces'] 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. # Build descriptors for all the interfaces we have in the parse data.
# This allows callers to specify a subset of interfaces by filtering # This allows callers to specify a subset of interfaces by filtering
# |parseData|. # |parseData|.
@ -94,6 +101,17 @@ class Configuration(DescriptorProvider):
"%s\n" "%s\n"
"%s" % "%s" %
(partialIface.location, iface.location)) (partialIface.location, iface.location))
if not (iface.getExtendedAttribute("ChromeOnly") or
not (iface.hasInterfaceObject() or
iface.isNavigatorProperty()) or
isInWebIDLRoot(iface.filename())):
raise TypeError(
"Interfaces which are exposed to the web may only be "
"defined in a DOM WebIDL root %r. Consider marking "
"the interface [ChromeOnly] if you do not want it "
"exposed to the web.\n"
"%s" %
(webRoots, iface.location))
self.interfaces[iface.identifier.name] = iface self.interfaces[iface.identifier.name] = iface
if iface.identifier.name not in config: if iface.identifier.name not in config:
# Completely skip consequential interfaces with no descriptor # Completely skip consequential interfaces with no descriptor

Просмотреть файл

@ -150,7 +150,7 @@ class WebIDLCodegenManager(LoggingMixin):
'PrototypeList.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, codegen_dir, state_path, cache_dir=None, make_deps_path=None,
make_deps_target=None): make_deps_target=None):
"""Create an instance that manages WebIDLs in the build system. """Create an instance that manages WebIDLs in the build system.
@ -176,6 +176,7 @@ class WebIDLCodegenManager(LoggingMixin):
input_paths, exported_stems, generated_events_stems, example_interfaces = inputs input_paths, exported_stems, generated_events_stems, example_interfaces = inputs
self._config_path = config_path self._config_path = config_path
self._webidl_root = webidl_root
self._input_paths = set(input_paths) self._input_paths = set(input_paths)
self._exported_stems = set(exported_stems) self._exported_stems = set(exported_stems)
self._generated_events_stems = set(generated_events_stems) self._generated_events_stems = set(generated_events_stems)
@ -332,8 +333,26 @@ class WebIDLCodegenManager(LoggingMixin):
hashes[path] = hashlib.sha1(data).hexdigest() hashes[path] = hashlib.sha1(data).hexdigest()
parser.parse(data, path) 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._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._generated_events_stems_as_array)
self._input_hashes = hashes self._input_hashes = hashes
@ -546,6 +565,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir):
"""Create a WebIDLCodegenManager for use by the build system.""" """Create a WebIDLCodegenManager for use by the build system."""
src_dir = os.path.join(topsrcdir, 'dom', 'bindings') src_dir = os.path.join(topsrcdir, 'dom', 'bindings')
obj_dir = os.path.join(topobjdir, 'dom', 'bindings') obj_dir = os.path.join(topobjdir, 'dom', 'bindings')
webidl_root = os.path.join(topsrcdir, 'dom', 'webidl')
with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh: with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh:
files = json.load(fh) files = json.load(fh)
@ -562,6 +582,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir):
return WebIDLCodegenManager( return WebIDLCodegenManager(
os.path.join(src_dir, 'Bindings.conf'), os.path.join(src_dir, 'Bindings.conf'),
webidl_root,
inputs, inputs,
os.path.join(dist_dir, 'include', 'mozilla', 'dom'), os.path.join(dist_dir, 'include', 'mozilla', 'dom'),
obj_dir, obj_dir,