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 : source : 6cb20ada1a0aa1f6d621ba3c85ce9946a6f9841f
extra : histedit_source : 1f02888264a936db3e77134c0a7203e911707312%2C6ea38c077b8a7dfaf358bc819d150a20db9bd6b7
This commit is contained in:
Kris Maglione 2018-03-05 14:21:38 -08:00
Родитель 27f4fb5abd
Коммит c8a6abe11d
3 изменённых файлов: 45 добавлений и 3 удалений

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

@ -18,12 +18,17 @@ class DescriptorProvider:
pass
def isChildPath(path, basePath):
path = os.path.normpath(path)
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.
@ -31,6 +36,10 @@ class Configuration(DescriptorProvider):
execfile(filename, glbl)
config = glbl['DOMInterfaces']
webRoots = tuple(map(os.path.normpath, webRoots))
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|.
@ -94,6 +103,17 @@ class Configuration(DescriptorProvider):
"%s\n"
"%s" %
(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
if iface.identifier.name not in config:
# Completely skip consequential interfaces with no descriptor

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

@ -150,7 +150,7 @@ class WebIDLCodegenManager(LoggingMixin):
'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.
@ -176,6 +176,7 @@ class WebIDLCodegenManager(LoggingMixin):
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)
@ -332,8 +333,26 @@ class WebIDLCodegenManager(LoggingMixin):
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
@ -546,6 +565,7 @@ 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')
webidl_root = os.path.join(topsrcdir, 'dom', 'webidl')
with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh:
files = json.load(fh)
@ -562,6 +582,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir):
return WebIDLCodegenManager(
os.path.join(src_dir, 'Bindings.conf'),
webidl_root,
inputs,
os.path.join(dist_dir, 'include', 'mozilla', 'dom'),
obj_dir,

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

@ -71,6 +71,7 @@ class TestWebIDLCodegenManager(unittest.TestCase):
return dict(
config_path=self._config_path,
webidl_root='/',
inputs=inputs,
exported_header_dir=mozpath.join(tmp, 'exports'),
codegen_dir=mozpath.join(tmp, 'codegen'),