Repository: qutebrowser/qutebrowser

Issue:
Crash when running greasemonkey with jinja <2.9
Debian stable packages a jinja 2.8, which crashes when trying to run any greasemonkey userscript.

```
Traceback (most recent call last):
  File "/home/jay/.local/lib/python3.5/site-packages/qutebrowser/browser/webengine/webview.py", line 355, in _inject_userjs
    _add_script(script, QWebEngineScript.DocumentReady)
  File "/home/jay/.local/lib/python3.5/site-packages/qutebrowser/browser/webengine/webview.py", line 343, in _add_script
    new_script.setSourceCode(script.code())
  File "/home/jay/.local/lib/python3.5/site-packages/qutebrowser/browser/greasemonkey.py", line 107, in code
    template = jinja.js_environment.get_template('greasemonkey_wrapper.js')
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 812, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 786, in _load_template
    template = self.loader.load(self, name, globals)
  File "/usr/lib/python3/dist-packages/jinja2/loaders.py", line 125, in load
    code = environment.compile(source, name, filename)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 565, in compile
    self.handle_exception(exc_info, source_hint=source_hint)
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 754, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/lib/python3/dist-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "javascript/greasemonkey_wrapper.js", line 2, in template
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 515, in _generate
    return generate(source, self, name, filename, defer_init=defer_init)
  File "/usr/lib/python3/dist-packages/jinja2/compiler.py", line 62, in generate
    generator.visit(node)
  File "/usr/lib/python3/dist-packages/jinja2/visitor.py", line 38, in visit
    return f(node, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/jinja2/compiler.py", line 816, in visit_Template
    self.blockvisit(node.body, frame)
  File "/usr/lib/python3/dist-packages/jinja2/compiler.py", line 492, in blockvisit
    self.visit(node, frame)
  File "/usr/lib/python3/dist-packages/jinja2/visitor.py", line 38, in visit
    return f(node, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/jinja2/compiler.py", line 1353, in visit_Output
    self.visit(argument, frame)
  File "/usr/lib/python3/dist-packages/jinja2/visitor.py", line 38, in visit
    return f(node, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/jinja2/compiler.py", line 1565, in visit_Filter
    self.fail('no filter named %r' % node.name, node.lineno)
  File "/usr/lib/python3/dist-packages/jinja2/compiler.py", line 427, in fail
    raise TemplateAssertionError(msg, lineno, self.name, self.filename)
jinja2.exceptions.TemplateAssertionError: no filter named 'tojson'
```

This is because the tojson filter was added in 2.9. 

I'm going to give this a quick stab, but I haven't used jinja before so we'll see how that goes.
[cc: @toofar]


Discussion:

Resolving patch:
diff --git a/qutebrowser/browser/greasemonkey.py b/qutebrowser/browser/greasemonkey.py
--- a/qutebrowser/browser/greasemonkey.py
+++ b/qutebrowser/browser/greasemonkey.py
@@ -30,7 +30,8 @@
 import attr
 from PyQt5.QtCore import pyqtSignal, QObject, QUrl
 
-from qutebrowser.utils import log, standarddir, jinja, objreg, utils
+from qutebrowser.utils import (log, standarddir, jinja, objreg, utils,
+                               javascript)
 from qutebrowser.commands import cmdutils
 from qutebrowser.browser import downloads
 
@@ -106,9 +107,10 @@ def code(self):
         """
         template = jinja.js_environment.get_template('greasemonkey_wrapper.js')
         return template.render(
-            scriptName="/".join([self.namespace or '', self.name]),
+            scriptName=javascript.string_escape(
+                "/".join([self.namespace or '', self.name])),
             scriptInfo=self._meta_json(),
-            scriptMeta=self.script_meta,
+            scriptMeta=javascript.string_escape(self.script_meta),
             scriptSource=self._code)
 
     def _meta_json(self):


Test patch: