Merge branch 'Kingdread-pdfjs'

This commit is contained in:
Florian Bruhin 2016-01-05 19:12:57 +01:00
commit 2ccb4342a4
21 changed files with 611 additions and 4 deletions

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
qutebrowser/3rdparty/pdfjs/*

View File

@ -20,6 +20,9 @@ v0.5.0 (unreleased)
Added
~~~~~
- Ability to preview PDFs using pdf.js in the browser if it's installed. This
is disabled by default and can be enabled using the
`content -> pdfjs-enabled` setting.
- New setting `ui -> hide-wayland-decoration` to hide the window decoration
when using wayland.
- New userscripts in `misc/userscripts`:

View File

@ -3,6 +3,7 @@ recursive-include qutebrowser/html *.html
recursive-include qutebrowser/img *.svg *.png
recursive-include qutebrowser/test *.py
recursive-include qutebrowser/javascript *.js
graft qutebrowser/3rdparty
graft icons
graft doc/img
graft misc
@ -27,6 +28,7 @@ exclude qutebrowser.rcc
exclude .coveragerc
exclude .pylintrc
exclude .eslintrc
exclude .eslintignore
exclude doc/help
exclude .appveyor.yml
exclude .travis.yml

View File

@ -272,3 +272,14 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
pdf.js
------
qutebrowser optionally uses https://github.com/mozilla/pdf.js/[pdf.js] to
display PDF files in the browser. Windows releases come with a bundled pdf.js.
pdf.js is distributed under the terms of the Apache License. You can
find a copy of the license in `qutebrowser/3rdparty/pdfjs/LICENSE` (in the
Windows release or after running `scripts/dev/update_3rdparty.py`), or online
http://www.apache.org/licenses/LICENSE-2.0.html[here].

View File

@ -165,6 +165,7 @@
|<<content-host-block-lists,host-block-lists>>|List of URLs of lists which contain hosts to block.
|<<content-host-blocking-enabled,host-blocking-enabled>>|Whether host blocking is enabled.
|<<content-host-blocking-whitelist,host-blocking-whitelist>>|List of domains that should always be loaded, despite being ad-blocked.
|<<content-enable-pdfjs,enable-pdfjs>>|Enable pdf.js to view PDF files in the browser.
|==============
.Quick reference for section ``hints''
@ -1501,6 +1502,19 @@ Local domains are always exempt from hostblocking.
Default: +pass:[piwik.org]+
[[content-enable-pdfjs]]
=== enable-pdfjs
Enable pdf.js to view PDF files in the browser.
Note that the files can still be downloaded by clicking the download button in the pdf.js viewer.
Valid values:
* +true+
* +false+
Default: +pass:[false]+
== hints
Hinting settings.

View File

@ -31,11 +31,13 @@ Module attributes:
import functools
import configparser
import mimetypes
from PyQt5.QtCore import pyqtSlot, QObject
from PyQt5.QtNetwork import QNetworkReply
import qutebrowser
from qutebrowser.browser import pdfjs
from qutebrowser.browser.network import schemehandler, networkreply
from qutebrowser.utils import (version, utils, jinja, log, message, docutils,
objreg)
@ -93,8 +95,11 @@ class QuteSchemeHandler(schemehandler.SchemeHandler):
return networkreply.ErrorNetworkReply(
request, str(e), QNetworkReply.ContentNotFoundError,
self.parent())
mimetype, _encoding = mimetypes.guess_type(request.url().fileName())
if mimetype is None:
mimetype = 'text/html'
return networkreply.FixedDataNetworkReply(
request, data, 'text/html', self.parent())
request, data, mimetype, self.parent())
class JSBridge(QObject):
@ -201,3 +206,10 @@ def qute_settings(win_id, _request):
win_id=win_id, title='settings', config=configdata,
confget=config_getter)
return html.encode('UTF-8', errors='xmlcharrefreplace')
@add_handler('pdfjs')
def qute_pdfjs(_win_id, request):
"""Handler for qute://pdfjs. Return the pdf.js viewer."""
urlpath = request.url().path()
return pdfjs.get_pdfjs_res(urlpath)

View File

@ -0,0 +1,175 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Daniel Schadt
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""pdf.js integration for qutebrowser."""
import os
from PyQt5.QtCore import QUrl
from qutebrowser.browser import webelem
from qutebrowser.utils import utils
class PDFJSNotFound(Exception):
"""Raised when no pdf.js installation is found."""
pass
def generate_pdfjs_page(url):
"""Return the html content of a page that displays url with pdfjs.
Returns a string.
Args:
url: The url of the pdf as QUrl.
"""
viewer = get_pdfjs_res('web/viewer.html').decode('utf-8')
script = _generate_pdfjs_script(url)
html_page = viewer.replace(
'</body>', '</body><script>{}</script>'.format(script)
)
return html_page
def _generate_pdfjs_script(url):
"""Generate the script that shows the pdf with pdf.js.
Args:
url: The url of the pdf page as QUrl.
"""
return (
'PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
'PDFView.open("{url}");\n'
).format(url=webelem.javascript_escape(url.toString(QUrl.FullyEncoded)))
def fix_urls(asset):
"""Take a html page and replace each relative URL wth an absolute.
This is specialized for pdf.js files and not a general purpose function.
Args:
asset: js file or html page as string.
"""
new_urls = {
'viewer.css': 'qute://pdfjs/web/viewer.css',
'compatibility.js': 'qute://pdfjs/web/compatibility.js',
'locale/locale.properties':
'qute://pdfjs/web/locale/locale.properties',
'l10n.js': 'qute://pdfjs/web/l10n.js',
'../build/pdf.js': 'qute://pdfjs/build/pdf.js',
'debugger.js': 'qute://pdfjs/web/debugger.js',
'viewer.js': 'qute://pdfjs/web/viewer.js',
'compressed.tracemonkey-pldi-09.pdf': '',
'./images/': 'qute://pdfjs/web/images/',
'../build/pdf.worker.js': 'qute://pdfjs/build/pdf.worker.js',
'../web/cmaps/': 'qute://pdfjs/web/cmaps/',
}
for original, new in new_urls.items():
asset = asset.replace(original, new)
return asset
SYSTEM_PDFJS_PATHS = [
'/usr/share/pdf.js/', # Debian pdf.js-common
'/usr/share/javascript/pdf/', # Debian libjs-pdf
os.path.expanduser('~/.local/share/qutebrowser/pdfjs/'), # fallback
]
def get_pdfjs_res(path):
"""Get a pdf.js resource in binary format.
Args:
path: The path inside the pdfjs directory.
"""
path = path.lstrip('/')
content = None
# First try a system wide installation
# System installations might strip off the 'build/' or 'web/' prefixes.
# qute expects them, so we need to adjust for it.
names_to_try = [path, _remove_prefix(path)]
for system_path in SYSTEM_PDFJS_PATHS:
content = _read_from_system(system_path, names_to_try)
if content is not None:
break
# Fallback to bundled pdf.js
if content is None:
res_path = '3rdparty/pdfjs/{}'.format(path)
try:
content = utils.read_file(res_path, binary=True)
except FileNotFoundError:
raise PDFJSNotFound
try:
# Might be script/html or might be binary
text_content = content.decode('utf-8')
except UnicodeDecodeError:
return content
text_content = fix_urls(text_content)
return text_content.encode('utf-8')
def _remove_prefix(path):
"""Remove the web/ or build/ prefix of a pdfjs-file-path.
Args:
path: Path as string where the prefix should be stripped off.
"""
prefixes = {'web/', 'build/'}
if any(path.startswith(prefix) for prefix in prefixes):
return path.split('/', maxsplit=1)[1]
# Return the unchanged path if no prefix is found
return path
def _read_from_system(system_path, names):
"""Try to read a file with one of the given names in system_path.
Each file in names is considered equal, the first file that is found
is read and its binary content returned.
Returns None if no file could be found
Args:
system_path: The folder where the file should be searched.
names: List of possible file names.
"""
for name in names:
try:
with open(os.path.join(system_path, name), 'rb') as f:
return f.read()
except OSError:
continue
return None
def is_available():
"""Return true if a pdfjs installation is available."""
try:
get_pdfjs_res('build/pdf.js')
except PDFJSNotFound:
return False
else:
return True

View File

@ -30,7 +30,7 @@ from PyQt5.QtPrintSupport import QPrintDialog
from PyQt5.QtWebKitWidgets import QWebPage
from qutebrowser.config import config
from qutebrowser.browser import http, tabhistory
from qutebrowser.browser import http, tabhistory, pdfjs
from qutebrowser.browser.network import networkmanager
from qutebrowser.utils import (message, usertypes, log, jinja, qtutils, utils,
objreg, debug)
@ -218,6 +218,19 @@ class BrowserPage(QWebPage):
q.deleteLater()
return q.answer
def _show_pdfjs(self, reply):
"""Show the reply with pdfjs."""
try:
page = pdfjs.generate_pdfjs_page(reply.url()).encode('utf-8')
except pdfjs.PDFJSNotFound:
# pylint: disable=no-member
# WORKAROUND for https://bitbucket.org/logilab/pylint/issue/490/
page = (jinja.env.get_template('no_pdfjs.html')
.render(url=reply.url().toDisplayString())
.encode('utf-8'))
self.mainFrame().setContent(page, 'text/html', reply.url())
reply.deleteLater()
def shutdown(self):
"""Prepare the web page for being deleted."""
self._is_shutting_down = True
@ -305,6 +318,10 @@ class BrowserPage(QWebPage):
else:
reply.finished.connect(functools.partial(
self.display_content, reply, 'image/jpeg'))
elif (mimetype in {'application/pdf', 'application/x-pdf'} and
config.get('content', 'enable-pdfjs')):
# Use pdf.js to display the page
self._show_pdfjs(reply)
else:
# Unknown mimetype, so download anyways.
download_manager.fetch(reply,

View File

@ -841,6 +841,11 @@ def data(readonly=False):
"required to exactly match the requested domain.\n\n"
"Local domains are always exempt from hostblocking."),
('enable-pdfjs', SettingValue(typ.Bool(), 'false'),
"Enable pdf.js to view PDF files in the browser.\n\n"
"Note that the files can still be downloaded by clicking"
" the download button in the pdf.js viewer."),
readonly=readonly
)),

View File

@ -0,0 +1,129 @@
{% extends "base.html" %}
{% block style %}
{{ super() }}
* {
margin: 0px 0px;
padding: 0px 0px;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-webkit-text-size-adjust: none;
color: #333333;
background-color: #EEEEEE;
font-size: 1.2em;
}
#error-container {
margin-left: 20px;
margin-right: 20px;
margin-top: 20px;
border: 1px solid #CCCCCC;
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.20);
border-radius: 5px;
background-color: #FFFFFF;
padding: 20px 20px;
}
#header {
border-bottom: 1px solid #CCC;
}
.qutebrowser-broken {
display: block;
width: 100%;
}
span.warning {
text-weigth: bold;
color: red;
}
td {
margin-top: 20px;
color: #555;
}
h1, h2 {
font-weight: normal;
color: #1e89c6;
margin-bottom: 10px;
}
ul {
margin-left: 20px;
margin-top: 20px;
margin-bottom: 20px;
}
li {
margin-top: 10px;
margin-bottom: 10px;
}
{% endblock %}
{% block content %}
<div id="error-container">
<table>
<tr>
<td style="width: 10%; vertical-align: top;">
<img style="width: 100%; display: block; max-width: 256px;" src="{{ resource_url('img/broken_qutebrowser_logo.png') }}" />
</td>
<td style="padding-left: 40px;">
<h1>No pdf.js installation found</h1>
<p>Error while opening {{ url }}: <br>
<p id="error-message-text" style="color: #a31a1a;">qutebrowser can't find a suitable pdf.js installation</p></p>
<p>It looks like you set <code>content -> enable-pdfjs</code>
to <em>true</em> but qutebrowser can't find the required files.</p>
<br>
<h2>Possible fixes</h2>
<ul>
<li>
Disable <code>content -> enable-pdfjs</code> and reload the page.
You will need to download the pdf-file and open it with an external
tool instead.
</li>
<li>
If you have installed a packaged version of qutebrowser, make sure
the required packages for pdf.js are also installed.
</li>
<li>
If you have installed a pdf.js package and qutebrowser still can't
find it, please send us a report with your system and the package
name, so we can add it to the list of supported packages.
</li>
<li>
If you're running a self-built version or the source version, make
sure you have pdf.js in <code>qutebrowser/3rdparty/pdfjs</code>.
You can use the <code>scripts/dev/update_3rdparty.py</code> script
to download the latest version.
</li>
<li>
You can manually download the pdf.js archive
<a href="https://mozilla.github.io/pdf.js/getting_started/#download">here</a>
and extract it to <code>~/.local/share/qutebrowser/pdfjs</code>
<br>
<span class="warning">Warning:</span> Using this method you are
responsible for yourself to keep the installation updated! If a
vulnerability is found in pdf.js, neither qutebrowser nor your
system's package manager will update your pdf.js installation.
Use it at your own risk!
</li>
</ul>
<p>
If none of these fixes work for you, please send us a bug report so
we can fix the issue.
</p>
</td>
</tr>
</table>
</div>
{% endblock %}

View File

@ -19,6 +19,7 @@
"""Utilities to show various version informations."""
import re
import sys
import glob
import os.path
@ -34,6 +35,7 @@ from PyQt5.QtWidgets import QApplication
import qutebrowser
from qutebrowser.utils import log, utils
from qutebrowser.browser import pdfjs
GPL_BOILERPLATE = """
@ -183,6 +185,25 @@ def _os_info():
return lines
def _pdfjs_version():
"""Get the pdf.js version.
Return:
A string with the version number.
"""
try:
pdfjs_file = pdfjs.get_pdfjs_res('build/pdf.js').decode('utf-8')
except pdfjs.PDFJSNotFound:
return 'no'
else:
version_re = re.compile(r"^PDFJS\.version = '([^']+)';$", re.MULTILINE)
match = version_re.search(pdfjs_file)
if not match:
return 'unknown'
else:
return match.group(1)
def version(short=False):
"""Return a string with various version informations.
@ -211,6 +232,7 @@ def version(short=False):
lines += _module_versions()
lines += [
'pdf.js: {}'.format(_pdfjs_version()),
'Webkit: {}'.format(qWebKitVersion()),
'Harfbuzz: {}'.format(os.environ.get('QT_HARFBUZZ', 'system')),
'SSL: {}'.format(QSslSocket.sslLibraryVersionString()),

View File

@ -35,6 +35,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir,
import qutebrowser
from scripts import utils
from scripts.dev import update_3rdparty
def call_script(name, *args, python=sys.executable):
@ -89,6 +90,9 @@ def smoke_test(executable):
def build_windows():
"""Build windows executables/setups."""
utils.print_title("Updating 3rdparty content")
update_3rdparty.main()
utils.print_title("Building Windows binaries")
parts = str(sys.version_info.major), str(sys.version_info.minor)
ver = ''.join(parts)

View File

@ -67,6 +67,11 @@ def get_build_exe_options(skip_html=False):
('qutebrowser/html', 'html'),
]
if os.path.exists(os.path.join('qutebrowser', '3rdparty', 'pdfjs')):
include_files.append(('qutebrowser/3rdparty/pdfjs', '3rdparty/pdfjs'))
else:
print("Warning: excluding pdfjs as it's not present!")
if not skip_html:
include_files += [
('qutebrowser/html/doc', 'html/doc'),

View File

@ -96,12 +96,19 @@ def check_spelling():
'[Ss]tatemachine', '[Mm]etaobject', '[Ll]ogrecord',
'[Ff]iletype'}
# Files which should be ignored, e.g. because they come from another
# package
ignored = [
os.path.join('.', 'scripts', 'dev', 'misc_checks.py'),
os.path.join('.', 'qutebrowser', '3rdparty', 'pdfjs'),
]
seen = collections.defaultdict(list)
try:
ok = True
for fn in _get_files():
with tokenize.open(fn) as f:
if fn == os.path.join('.', 'scripts', 'dev', 'misc_checks.py'):
if any(fn.startswith(i) for i in ignored):
continue
for line in f:
for w in words:

View File

@ -89,6 +89,7 @@ def whitelist_generator():
yield 'qutebrowser.utils.log.VDEBUG'
yield 'qutebrowser.utils.log.QtWarningFilter.filter'
yield 'logging.LogRecord.log_color'
yield 'qutebrowser.browser.pdfjs.is_available'
# vulture doesn't notice the hasattr() and thus thinks netrc_used is unused
# in NetworkManager.on_authentication_required
yield 'PyQt5.QtNetwork.QNetworkReply.netrc_used'

64
scripts/dev/update_3rdparty.py Executable file
View File

@ -0,0 +1,64 @@
#!/usr/bin/env python3
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Daniel Schadt
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Update all third-party-modules."""
import urllib.request
import shutil
import json
import os
def get_latest_pdfjs_url():
"""Get the URL of the latest pdf.js prebuilt package.
Returns a (version, url)-tuple."""
github_api = 'https://api.github.com'
endpoint = 'repos/mozilla/pdf.js/releases/latest'
request_url = '{}/{}'.format(github_api, endpoint)
with urllib.request.urlopen(request_url) as fp:
data = json.loads(fp.read().decode('utf-8'))
download_url = data['assets'][0]['browser_download_url']
version_name = data['name']
return (version_name, download_url)
def update_pdfjs():
"""Download and extract the latest pdf.js version."""
version, url = get_latest_pdfjs_url()
target_path = os.path.join('qutebrowser', '3rdparty', 'pdfjs')
print("=> Downloading pdf.js {}".format(version))
(archive_path, _headers) = urllib.request.urlretrieve(url)
if os.path.isdir(target_path):
print("Removing old version in {}".format(target_path))
shutil.rmtree(target_path)
os.makedirs(target_path)
print("Extracting new version")
with open(archive_path, 'rb') as archive:
shutil.unpack_archive(archive, target_path, 'zip')
urllib.request.urlcleanup()
def main():
update_pdfjs()
if __name__ == '__main__':
main()

Binary file not shown.

View File

@ -245,3 +245,17 @@ Feature: Various utility commands.
When I set general -> startpage to http://localhost:(port)/data/numbers/1.txt,http://localhost:(port)/data/numbers/2.txt
And I run :home
Then data/numbers/1.txt should be loaded
# pdfjs support
Scenario: pdfjs is used for pdf files
Given pdfjs is available
When I set content -> enable-pdfjs to true
And I open data/misc/test.pdf
Then the javascript message "PDF * [*] (PDF.js: *)" should be logged
Scenario: pdfjs is not used when disabled
When I set content -> enable-pdfjs to false
And I set storage -> prompt-download-directory to false
And I open data/misc/test.pdf
Then "Download finished" should be logged

View File

@ -23,10 +23,13 @@ import subprocess
import pytest
import pytest_bdd as bdd
bdd.scenarios('misc.feature')
import qutebrowser
from qutebrowser.utils import docutils
from qutebrowser.browser import pdfjs
bdd.scenarios('misc.feature')
@bdd.when("the documentation is up to date")
@ -51,3 +54,9 @@ def update_documentation():
update_script = os.path.join(script_path, 'asciidoc2html.py')
subprocess.call([sys.executable, update_script])
@bdd.given('pdfjs is available')
def pdfjs_available():
if not pdfjs.is_available():
pytest.skip("No pdfjs installation found.")

View File

@ -0,0 +1,76 @@
# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
# Copyright 2015 Daniel Schadt
#
# This file is part of qutebrowser.
#
# qutebrowser is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# qutebrowser is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
"""Tests for qutebrowser.browser.pdfjs"""
import textwrap
import pytest
from PyQt5.QtCore import QUrl
from qutebrowser.browser import pdfjs
# Note that we got double protection, once because we use QUrl.FullyEncoded and
# because we use qutebrowser.browser.webelem.javascript_escape. Characters
# like " are already replaced by QUrl.
@pytest.mark.parametrize('url, expected', [
('http://foo.bar', "http://foo.bar"),
('http://"', ''),
('\0', '%00'),
('http://foobar/");alert("attack!");',
'http://foobar/%22);alert(%22attack!%22);'),
])
def test_generate_pdfjs_script(url, expected):
expected_code = ('PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
'PDFView.open("{}");\n'.format(expected))
url = QUrl(url)
actual = pdfjs._generate_pdfjs_script(url)
assert actual == expected_code
def test_fix_urls():
page = textwrap.dedent("""
<html>
<script src="viewer.js"></script>
<link href="viewer.css">
<script src="unrelated.js"></script>
</html>
""").strip()
expected = textwrap.dedent("""
<html>
<script src="qute://pdfjs/web/viewer.js"></script>
<link href="qute://pdfjs/web/viewer.css">
<script src="unrelated.js"></script>
</html>
""").strip()
actual = pdfjs.fix_urls(page)
assert actual == expected
@pytest.mark.parametrize('path, expected', [
('web/viewer.js', 'viewer.js'),
('build/locale/foo.bar', 'locale/foo.bar'),
('viewer.js', 'viewer.js'),
('foo/viewer.css', 'foo/viewer.css'),
])
def test_remove_prefix(path, expected):
assert pdfjs._remove_prefix(path) == expected

View File

@ -34,6 +34,7 @@ import pytest
import qutebrowser
from qutebrowser.utils import version
from qutebrowser.browser import pdfjs
class GitStrSubprocessFake:
@ -529,6 +530,39 @@ class TestOsInfo:
version._os_info()
class TestPDFJSVersion:
"""Tests for _pdfjs_version."""
def test_not_found(self, mocker):
mocker.patch('qutebrowser.utils.version.pdfjs.get_pdfjs_res',
side_effect=pdfjs.PDFJSNotFound)
assert version._pdfjs_version() == 'no'
def test_unknown(self, monkeypatch):
monkeypatch.setattr('qutebrowser.utils.version.pdfjs.get_pdfjs_res',
lambda path: b'foobar')
assert version._pdfjs_version() == 'unknown'
def test_known(self, monkeypatch):
pdfjs_code = textwrap.dedent("""
// Initializing PDFJS global object (if still undefined)
if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
PDFJS.version = '1.2.109';
PDFJS.build = '875588d';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
'use strict';
""").strip().encode('utf-8')
monkeypatch.setattr('qutebrowser.utils.version.pdfjs.get_pdfjs_res',
lambda path: pdfjs_code)
assert version._pdfjs_version() == '1.2.109'
class FakeQSslSocket:
"""Fake for the QSslSocket Qt class.
@ -571,6 +605,7 @@ def test_version_output(git_commit, harfbuzz, frozen, short, stubs,
'qVersion': lambda: 'QT RUNTIME VERSION',
'PYQT_VERSION_STR': 'PYQT VERSION',
'_module_versions': lambda: ['MODULE VERSION 1', 'MODULE VERSION 2'],
'_pdfjs_version': lambda: 'PDFJS VERSION',
'qWebKitVersion': lambda: 'WEBKIT VERSION',
'QSslSocket': FakeQSslSocket('SSL VERSION'),
'platform.platform': lambda: 'PLATFORM',
@ -613,6 +648,7 @@ def test_version_output(git_commit, harfbuzz, frozen, short, stubs,
Desktop: DESKTOP
MODULE VERSION 1
MODULE VERSION 2
pdf.js: PDFJS VERSION
Webkit: WEBKIT VERSION
Harfbuzz: {harfbuzz}
SSL: SSL VERSION