blob: e1724accbb406d8eb5a17fb56aec6e4f4f9a87bc [file] [log] [blame]
import os
import traceback
from urllib.parse import urljoin
from .base import get_pages
from .executorwebdriver import WebDriverProtocol, WebDriverRefTestExecutor, WebDriverRun
from .protocol import PrintProtocolPart
here = os.path.dirname(__file__)
class ChromeDriverPrintProtocolPart(PrintProtocolPart):
def setup(self):
self.webdriver = self.parent.webdriver
self.runner_handle = None
def load_runner(self):
url = urljoin(self.parent.executor.server_url("http"), "/print_reftest_runner.html")
self.logger.debug("Loading %s" % url)
try:
self.webdriver.url = url
except Exception as e:
self.logger.critical(
"Loading initial page %s failed. Ensure that the "
"there are no other programs bound to this port and "
"that your firewall rules or network setup does not "
"prevent access.\n%s" % (url, traceback.format_exc(e)))
raise
self.runner_handle = self.webdriver.window_handle
def render_as_pdf(self, width, height):
margin = 0.5
body = {
"cmd": "Page.printToPDF",
"params": {
# Chrome accepts dimensions in inches; we are using cm
"paperWidth": width / 2.54,
"paperHeight": height / 2.54,
"marginLeft": margin,
"marginRight": margin,
"marginTop": margin,
"marginBottom": margin,
"shrinkToFit": False,
"printBackground": True,
}
}
return self.webdriver.send_session_command("POST", "goog/cdp/execute", body=body)["data"]
def pdf_to_png(self, pdf_base64, ranges):
handle = self.webdriver.window_handle
self.webdriver.window_handle = self.runner_handle
try:
rv = self.webdriver.execute_async_script("""
let callback = arguments[arguments.length - 1];
render('%s').then(result => callback(result))""" % pdf_base64)
page_numbers = get_pages(ranges, len(rv))
rv = [item for i, item in enumerate(rv) if i + 1 in page_numbers]
return rv
finally:
self.webdriver.window_handle = handle
class ChromeDriverProtocol(WebDriverProtocol):
implements = WebDriverProtocol.implements + [ChromeDriverPrintProtocolPart]
class ChromeDriverPrintRefTestExecutor(WebDriverRefTestExecutor):
protocol_cls = ChromeDriverProtocol
def setup(self, runner):
super().setup(runner)
self.protocol.pdf_print.load_runner()
self.has_window = False
with open(os.path.join(here, "reftest.js")) as f:
self.script = f.read()
def screenshot(self, test, viewport_size, dpi, page_ranges):
# https://github.com/web-platform-tests/wpt/issues/7140
assert dpi is None
if not self.has_window:
self.protocol.base.execute_script(self.script)
self.protocol.base.set_window(self.protocol.webdriver.handles[-1])
self.has_window = True
self.viewport_size = viewport_size
self.page_ranges = page_ranges.get(test.url)
timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
test_url = self.test_url(test)
return WebDriverRun(self.logger,
self._render,
self.protocol,
test_url,
timeout,
self.extra_timeout).run()
def _render(self, protocol, url, timeout):
protocol.webdriver.url = url
protocol.base.execute_script(self.wait_script, asynchronous=True)
pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
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
if screenshot.startswith("data:image/png;base64,"):
screenshots[i] = screenshot.split(",", 1)[1]
return screenshots