Allow downloading from PDF.js

When we click the download button in PDF.js, it downloads a blob://qute:...
URL. We can detect that and force a download rather than opening it in PDF.js
again.

Note that what actually happens depends on the Qt version and backend:

QtWebKit (any Qt version):
Downloads always work properly (regardless of Qt version).

QtWebEngine, Qt 5.7.1:
Downloads work.

QtWebEngine, Qt 5.9 - 5.11:
Downloads won't work as we need to tell PDF.js to not use blob: URLs:
https://bugreports.qt.io/browse/QTBUG-70420 - in theory, PDF.js could fall back
to downloading the existing qute:// URL, but it has a whitelist of schemes
which does not include qute://... Since it's not in that whitelist, it just
ends up doing nothing at all.

QtWebEngine, Qt 5.12:
Downloads should hopefully work properly again, as we can register the qute://
scheme with Chromium, which allows us to use blob:// URLs.
This commit is contained in:
Florian Bruhin 2018-09-10 13:15:39 +02:00
parent 02641b86fc
commit d80d9eb26c
4 changed files with 20 additions and 12 deletions

View File

@ -198,9 +198,12 @@ def is_available():
return True
def should_use_pdfjs(mimetype):
return (mimetype in ['application/pdf', 'application/x-pdf'] and
config.val.content.pdfjs)
def should_use_pdfjs(mimetype, url):
# e.g. 'blob:qute%3A///b45250b3-787e-44d1-a8d8-c2c90f81f981'
is_download_url = (url.scheme() == 'blob' and
QUrl(url.path()).scheme() == 'qute')
is_pdf = mimetype in ['application/pdf', 'application/x-pdf']
return is_pdf and not is_download_url and config.val.content.pdfjs
def get_main_url(filename):

View File

@ -221,7 +221,7 @@ class DownloadManager(downloads.AbstractDownloadManager):
download.set_target(self._mhtml_target)
self._mhtml_target = None
return
if pdfjs.should_use_pdfjs(qt_item.mimeType()):
if pdfjs.should_use_pdfjs(qt_item.mimeType(), qt_item.url()):
download.set_target(downloads.PDFJSDownloadTarget())
return

View File

@ -268,7 +268,7 @@ class BrowserPage(QWebPage):
else:
reply.finished.connect(functools.partial(
self.display_content, reply, 'image/jpeg'))
elif pdfjs.should_use_pdfjs(mimetype):
elif pdfjs.should_use_pdfjs(mimetype, reply.url()):
download_manager.fetch(reply,
target=downloads.PDFJSDownloadTarget())
else:

View File

@ -173,15 +173,20 @@ def test_is_available(available, mocker):
assert pdfjs.is_available() == available
@pytest.mark.parametrize('mimetype, enabled, expected', [
('application/pdf', True, True),
('application/x-pdf', True, True),
('application/octet-stream', True, False),
('application/pdf', False, False),
@pytest.mark.parametrize('mimetype, url, enabled, expected', [
# PDF files
('application/pdf', 'http://www.example.com', True, True),
('application/x-pdf', 'http://www.example.com', True, True),
# Not a PDF
('application/octet-stream', 'http://www.example.com', True, False),
# PDF.js disabled
('application/pdf', 'http://www.example.com', False, False),
# Download button in PDF.js
('application/pdf', 'blob:qute%3A///b45250b3', True, False),
])
def test_should_use_pdfjs(mimetype, enabled, expected, config_stub):
def test_should_use_pdfjs(mimetype, url, enabled, expected, config_stub):
config_stub.val.content.pdfjs = enabled
assert pdfjs.should_use_pdfjs(mimetype) == expected
assert pdfjs.should_use_pdfjs(mimetype, QUrl(url)) == expected
def test_get_main_url():