diff --git a/tools/manifest/item.py b/tools/manifest/item.py
index 99df09d1320dc9..7bd857dbce98e0 100644
--- a/tools/manifest/item.py
+++ b/tools/manifest/item.py
@@ -293,10 +293,16 @@ class PrintRefTest(RefTest):
def page_ranges(self) -> PageRanges:
return cast(PageRanges, self._extras.get("page_ranges", {}))
+ @property
+ def safe_printable_inset(self) -> Optional[float]:
+ return self._extras.get("safe_printable_inset")
+
def to_json(self): # type: ignore
rv = super().to_json()
if self.page_ranges:
rv[-1]["page_ranges"] = self.page_ranges
+ if self.safe_printable_inset:
+ rv[-1]["safe_printable_inset"] = self.safe_printable_inset
return rv
diff --git a/tools/manifest/sourcefile.py b/tools/manifest/sourcefile.py
index 9e8d8302f6a568..efca597a4fc2f6 100644
--- a/tools/manifest/sourcefile.py
+++ b/tools/manifest/sourcefile.py
@@ -675,6 +675,18 @@ def page_ranges(self) -> Dict[Text, List[List[Optional[int]]]]:
rv[key].append(range_parts)
return rv
+ @cached_property
+ def safe_printable_inset(self) -> Optional[float]:
+ """The safe printable inset to simulate (in centimeters)"""
+ assert self.root is not None
+ for entry in self.root.findall(".//{http://www.w3.org/1999/xhtml}meta[@name='safe-printable-inset']"):
+ key_data, value = self.parse_ref_keyed_meta(entry)
+ result = float(value)
+ if result < 0:
+ raise ValueError("Negative value")
+ return result
+ return None
+
@cached_property
def testharness_nodes(self) -> List[ElementTree.Element]:
"""List of ElementTree Elements corresponding to nodes representing a
@@ -1023,6 +1035,7 @@ def manifest_items(self) -> Tuple[Text, List[ManifestItem]]:
viewport_size=self.viewport_size,
fuzzy=self.fuzzy,
page_ranges=self.page_ranges,
+ safe_printable_inset=self.safe_printable_inset,
testdriver=self.has_testdriver,
)]
diff --git a/tools/manifest/tests/test_sourcefile.py b/tools/manifest/tests/test_sourcefile.py
index e77f09e2a79f99..bc120bae9f9bde 100644
--- a/tools/manifest/tests/test_sourcefile.py
+++ b/tools/manifest/tests/test_sourcefile.py
@@ -973,6 +973,32 @@ def test_page_ranges_invalid(page_ranges):
s.page_ranges
+@pytest.mark.parametrize("safe_printable_inset, expected", [
+ (b"0", 0),
+ (b"0.5", 0.5),
+ (b"2.54", 2.54),
+ (b"100", 100)])
+def test_safe_printable_inset(safe_printable_inset, expected):
+ content = b"""
+
+""" % safe_printable_inset
+
+ s = create("foo/test-print.html", content)
+
+ assert s.safe_printable_inset == expected
+
+
+@pytest.mark.parametrize("safe_printable_inset", [b"ananas", b"auto", b"-1", b"0,0"])
+def test_safe_printable_inset_invalid(safe_printable_inset):
+ content = b"""
+
+""" % safe_printable_inset
+
+ s = create("foo/test-print.html", content)
+ with pytest.raises(ValueError):
+ s.safe_printable_inset
+
+
def test_hash():
s = SourceFile("/", "foo", "/", contents=b"Hello, World!")
assert "b45ef6fec89518d314f546fd6c3025367b721684" == s.hash
diff --git a/tools/webdriver/webdriver/client.py b/tools/webdriver/webdriver/client.py
index 8fcb663398dde1..28c10d98ffb36e 100644
--- a/tools/webdriver/webdriver/client.py
+++ b/tools/webdriver/webdriver/client.py
@@ -791,6 +791,7 @@ def print(
orientation=None,
page=None,
page_ranges=None,
+ safe_printable_inset=None,
scale=None,
shrink_to_fit=None,
):
@@ -801,6 +802,7 @@ def print(
"orientation": orientation,
"page": page,
"pageRanges": page_ranges,
+ "safePrintableInset": safe_printable_inset,
"scale": scale,
"shrinkToFit": shrink_to_fit,
}.items():
diff --git a/tools/wptrunner/wptrunner/executors/base.py b/tools/wptrunner/wptrunner/executors/base.py
index dd10aca589c72f..595fe6c39e68fc 100644
--- a/tools/wptrunner/wptrunner/executors/base.py
+++ b/tools/wptrunner/wptrunner/executors/base.py
@@ -418,11 +418,11 @@ def teardown(self):
def logger(self):
return self.executor.logger
- def get_hash(self, test, viewport_size, dpi, page_ranges):
- key = (test.url, viewport_size, dpi)
+ def get_hash(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
+ key = (test.url, viewport_size, dpi, safe_printable_inset)
if key not in self.screenshot_cache:
- success, data = self.get_screenshot_list(test, viewport_size, dpi, page_ranges)
+ success, data = self.get_screenshot_list(test, viewport_size, dpi, page_ranges, safe_printable_inset)
if not success:
return False, data
@@ -524,9 +524,9 @@ def run_test(self, test):
viewport_size = test.viewport_size
dpi = test.dpi
page_ranges = test.page_ranges
+ safe_printable_inset = test.safe_printable_inset
self.message = []
-
# Depth-first search of reference tree, with the goal
# of reachings a leaf node with only pass results
@@ -541,7 +541,7 @@ def run_test(self, test):
fuzzy = self.get_fuzzy(test, nodes, relation)
for i, node in enumerate(nodes):
- success, data = self.get_hash(node, viewport_size, dpi, page_ranges)
+ success, data = self.get_hash(node, viewport_size, dpi, page_ranges, safe_printable_inset)
if success is False:
return {"status": data[0], "message": data[1]}
@@ -575,7 +575,7 @@ def run_test(self, test):
for i, (node, screenshot) in enumerate(zip(nodes, screenshots)):
if screenshot is None:
- success, screenshot = self.retake_screenshot(node, viewport_size, dpi, page_ranges)
+ success, screenshot = self.retake_screenshot(node, viewport_size, dpi, page_ranges, safe_printable_inset)
if success:
screenshots[i] = screenshot
@@ -606,11 +606,12 @@ def get_fuzzy(self, root_test, test_nodes, relation):
break
return value
- def retake_screenshot(self, node, viewport_size, dpi, page_ranges):
+ def retake_screenshot(self, node, viewport_size, dpi, page_ranges, safe_printable_inset):
success, data = self.get_screenshot_list(node,
viewport_size,
dpi,
- page_ranges)
+ page_ranges,
+ safe_printable_inset)
if not success:
return False, data
@@ -641,8 +642,8 @@ def get_png_dimensions(
return struct.unpack(">LL", image_data[16:24])
- def get_screenshot_list(self, node, viewport_size, dpi, page_ranges):
- success, data = self.executor.screenshot(node, viewport_size, dpi, page_ranges)
+ def get_screenshot_list(self, node, viewport_size, dpi, page_ranges, safe_printable_inset):
+ success, data = self.executor.screenshot(node, viewport_size, dpi, page_ranges, safe_printable_inset)
viewport_size = (800, 600) if viewport_size is None else viewport_size
dpi = 96 if dpi is None else dpi
dpcm = dpi / 2.54
diff --git a/tools/wptrunner/wptrunner/executors/executoredge.py b/tools/wptrunner/wptrunner/executors/executoredge.py
index 2ddfdb3ad8f47a..3b1e3a28c6ba24 100644
--- a/tools/wptrunner/wptrunner/executors/executoredge.py
+++ b/tools/wptrunner/wptrunner/executors/executoredge.py
@@ -35,7 +35,7 @@ def setup(self, runner, protocol=None):
with open(os.path.join(here, "reftest.js")) as f:
self.script = f.read()
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
# https://github.com/web-platform-tests/wpt/issues/7140
assert dpi is None
@@ -62,7 +62,7 @@ def _render(self, protocol, url, timeout):
protocol.base.execute_script(self.wait_script, asynchronous=True)
- pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
+ pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size, self.safe_printable_inset)
screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
for i, screenshot in enumerate(screenshots):
# strip off the data:img/png, part of the url
diff --git a/tools/wptrunner/wptrunner/executors/executormarionette.py b/tools/wptrunner/wptrunner/executors/executormarionette.py
index ce9462f0523317..fb916bcf4b0095 100644
--- a/tools/wptrunner/wptrunner/executors/executormarionette.py
+++ b/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -683,7 +683,7 @@ def load_runner(self):
raise
self.runner_handle = self.marionette.current_window_handle
- def render_as_pdf(self, width, height):
+ def render_as_pdf(self, width, height, safe_printable_inset):
margin = 0.5 * 2.54
body = {
"page": {
@@ -701,7 +701,7 @@ def render_as_pdf(self, width, height):
}
return self.marionette._send_message("WebDriver:Print", body, key="value")
- def pdf_to_png(self, pdf_base64, page_ranges):
+ def pdf_to_png(self, pdf_base64, page_ranges, safe_printable_inset):
handle = self.marionette.current_window_handle
_switch_to_window(self.marionette, self.runner_handle)
try:
@@ -1227,7 +1227,7 @@ def do_test(self, test):
return self.convert_result(test, result)
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
# https://github.com/web-platform-tests/wpt/issues/7135
assert viewport_size is None
assert dpi is None
@@ -1431,7 +1431,7 @@ def setup(self, runner, protocol=None):
if not isinstance(self.implementation, InternalRefTestImplementation):
self.protocol.pdf_print.load_runner()
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
# https://github.com/web-platform-tests/wpt/issues/7140
assert dpi is None
@@ -1453,7 +1453,7 @@ def _render(self, protocol, url, timeout):
protocol.base.execute_script(self.wait_script, asynchronous=True)
- pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
+ pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size, self.safe_printable_inset)
screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
for i, screenshot in enumerate(screenshots):
# strip off the data:img/png, part of the url
diff --git a/tools/wptrunner/wptrunner/executors/executorselenium.py b/tools/wptrunner/wptrunner/executors/executorselenium.py
index 0080367f6ed194..73f041e15bc069 100644
--- a/tools/wptrunner/wptrunner/executors/executorselenium.py
+++ b/tools/wptrunner/wptrunner/executors/executorselenium.py
@@ -442,7 +442,7 @@ def do_test(self, test):
return self.convert_result(test, result)
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
# https://github.com/web-platform-tests/wpt/issues/7135
assert viewport_size is None
assert dpi is None
diff --git a/tools/wptrunner/wptrunner/executors/executorservolegacy.py b/tools/wptrunner/wptrunner/executors/executorservolegacy.py
index a03c2d4ee6fff5..8118845b96d7da 100644
--- a/tools/wptrunner/wptrunner/executors/executorservolegacy.py
+++ b/tools/wptrunner/wptrunner/executors/executorservolegacy.py
@@ -244,7 +244,7 @@ def teardown(self):
os.rmdir(self.tempdir)
super().teardown()
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
with TempFilename(self.tempdir) as output_path:
extra_args = ["--exit",
"--output=%s" % output_path,
diff --git a/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/tools/wptrunner/wptrunner/executors/executorwebdriver.py
index 808d96f61d00e7..47d7343a44dd17 100644
--- a/tools/wptrunner/wptrunner/executors/executorwebdriver.py
+++ b/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -519,7 +519,7 @@ def load_runner(self):
raise
self.runner_handle = self.webdriver.window_handle
- def render_as_pdf(self, width, height):
+ def render_as_pdf(self, width, height, safe_printable_inset_param):
# All units passed to `print()` are in cm. See [0] for testing specifications.
#
# [0]: https://web-platform-tests.org/writing-tests/print-reftests.html
@@ -527,6 +527,7 @@ def render_as_pdf(self, width, height):
pdf_base64 = self.webdriver.print(page={"width": width, "height": height},
margin={"top": margin, "right": margin, "bottom": margin,
"left": margin},
+ safe_printable_inset=safe_printable_inset_param,
background=True,
shrink_to_fit=False)
return pdf_base64
@@ -1383,7 +1384,7 @@ def do_test(self, test):
return self.convert_result(test, result)
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
# https://github.com/web-platform-tests/wpt/issues/7135
assert viewport_size is None
assert dpi is None
@@ -1423,7 +1424,7 @@ def setup(self, runner, protocol=None):
with open(os.path.join(here, "reftest.js")) as f:
self.script = f.read()
- def screenshot(self, test, viewport_size, dpi, page_ranges):
+ def screenshot(self, test, viewport_size, dpi, page_ranges, safe_printable_inset):
# https://github.com/web-platform-tests/wpt/issues/7140
assert dpi is None
@@ -1434,6 +1435,7 @@ def screenshot(self, test, viewport_size, dpi, page_ranges):
self.viewport_size = viewport_size
self.page_ranges = page_ranges.get(test.url)
+ self.safe_printable_inset = safe_printable_inset
timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
test_url = self.test_url(test)
@@ -1449,7 +1451,7 @@ def _render(self, protocol, url, timeout):
# return value.
protocol.testdriver.run(url, self.wait_script)
- pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
+ pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size, self.safe_printable_inset)
screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
for i, screenshot in enumerate(screenshots):
# strip off the data:img/png, part of the url
diff --git a/tools/wptrunner/wptrunner/executors/protocol.py b/tools/wptrunner/wptrunner/executors/protocol.py
index b7dfac9de960dc..53744970b0983d 100644
--- a/tools/wptrunner/wptrunner/executors/protocol.py
+++ b/tools/wptrunner/wptrunner/executors/protocol.py
@@ -1134,7 +1134,7 @@ class PrintProtocolPart(ProtocolPart):
name = "pdf_print"
@abstractmethod
- def render_as_pdf(self, width, height):
+ def render_as_pdf(self, width, height, safe_printable_inset):
"""Output document as PDF"""
pass
diff --git a/tools/wptrunner/wptrunner/wpttest.py b/tools/wptrunner/wptrunner/wpttest.py
index 9616f9c429f309..0ba61e5803801d 100644
--- a/tools/wptrunner/wptrunner/wpttest.py
+++ b/tools/wptrunner/wptrunner/wpttest.py
@@ -699,22 +699,28 @@ def fuzzy_override(self):
def page_ranges(self):
return {}
+ @property
+ def safe_printable_inset(self):
+ return 0
class PrintReftestTest(ReftestTest):
test_type = "print-reftest"
def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, references,
timeout=None, path=None, viewport_size=None, dpi=None, fuzzy=None,
- page_ranges=None, protocol="http", subdomain=False, testdriver=False):
+ page_ranges=None, safe_printable_inset=None, protocol="http", subdomain=False,
+ testdriver=False):
super().__init__(url_base, tests_root, url, inherit_metadata, test_metadata,
references, timeout, path, viewport_size, dpi,
fuzzy, protocol, subdomain=subdomain, testdriver=testdriver)
self._page_ranges = page_ranges
+ self._safe_printable_inset = safe_printable_inset
@classmethod
def cls_kwargs(cls, manifest_test):
rv = super().cls_kwargs(manifest_test)
rv["page_ranges"] = manifest_test.page_ranges
+ rv["safe_printable_inset"] = manifest_test.safe_printable_inset
return rv
def get_viewport_size(self, override):
@@ -725,6 +731,9 @@ def get_viewport_size(self, override):
def page_ranges(self):
return self._page_ranges
+ @property
+ def safe_printable_inset(self):
+ return self._safe_printable_inset
class WdspecTest(Test):
result_cls = WdspecResult