diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 00000000000..7e28631131d
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+qutebrowser/3rdparty/pdfjs/*
diff --git a/MANIFEST.in b/MANIFEST.in
index 07726eca7a8..e2dd15509e8 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -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
diff --git a/README.asciidoc b/README.asciidoc
index ff903ce99cb..7902360f1c8 100644
--- a/README.asciidoc
+++ b/README.asciidoc
@@ -272,3 +272,13 @@ 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 .
+
+pdf.js
+------
+
+qutebrowser uses https://github.com/mozilla/pdf.js/[pdf.js] to display
+PDF files in the browser.
+
+pdf.js is distributed under the terms of the Apache License. You can
+find a copy of the license in `qutebrowser/pdfjs/LICENSE` or online
+http://www.apache.org/licenses/LICENSE-2.0.html[here].
diff --git a/qutebrowser/browser/network/qutescheme.py b/qutebrowser/browser/network/qutescheme.py
index e74bdd2bca6..876d85e1fcb 100644
--- a/qutebrowser/browser/network/qutescheme.py
+++ b/qutebrowser/browser/network/qutescheme.py
@@ -31,11 +31,13 @@
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 @@ def createRequest(self, _op, request, _outgoing_data):
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)
diff --git a/qutebrowser/browser/pdfjs.py b/qutebrowser/browser/pdfjs.py
new file mode 100644
index 00000000000..83b89330ccb
--- /dev/null
+++ b/qutebrowser/browser/pdfjs.py
@@ -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 .
+
+"""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(
+ '