def _init_stylesheet(profile):
    """Initialize custom stylesheets.

    Mostly inspired by QupZilla:
    https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101
    https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/tools/scripts.cpp#L119-L132

    FIXME:qtwebengine Use QWebEngineStyleSheet once that's available
    https://codereview.qt-project.org/#/c/148671/
    """
    old_script = profile.scripts().findScript('_qute_stylesheet')
    if not old_script.isNull():
        profile.scripts().remove(old_script)

    css = shared.get_user_stylesheet()
    source = """
        (function() {{
            var css = document.createElement('style');
            css.setAttribute('type', 'text/css');
            css.appendChild(document.createTextNode('{}'));
            document.getElementsByTagName('head')[0].appendChild(css);
        }})()
    """.format(javascript.string_escape(css))

    script = QWebEngineScript()
    script.setName('_qute_stylesheet')
    script.setInjectionPoint(QWebEngineScript.DocumentReady)
    script.setWorldId(QWebEngineScript.ApplicationWorld)
    script.setRunsOnSubFrames(True)
    script.setSourceCode(source)
    profile.scripts().insert(script)
Exemple #2
0
    def code(self):
        """Return the processed JavaScript code of this script.

        Adorns the source code with GM_* methods for Greasemonkey
        compatibility and wraps it in an IIFE to hide it within a
        lexical scope. Note that this means line numbers in your
        browser's debugger/inspector will not match up to the line
        numbers in the source script directly.
        """
        template = jinja.js_environment.get_template('greasemonkey_wrapper.js')
        return template.render(scriptName=javascript.string_escape("/".join(
            [self.namespace or '', self.name])),
                               scriptInfo=self._meta_json(),
                               scriptMeta=javascript.string_escape(
                                   self.script_meta),
                               scriptSource=self._code)
 def check_set(self, value, css_style="background-color",
               document_element="document.body"):
     """Check whether the css in ELEMENT is set to VALUE."""
     self.js.run("window.getComputedStyle({}, null)"
                 ".getPropertyValue('{}');"
                 .format(document_element,
                         javascript.string_escape(css_style)), value)
Exemple #4
0
def _generate_pdfjs_script(filename):
    """Generate the script that shows the pdf with pdf.js.

    Args:
        filename: The name of the file to open.
    """
    url = QUrl('qute://pdfjs/file')
    url_query = QUrlQuery()
    url_query.addQueryItem('filename', filename)
    url.setQuery(url_query)

    return jinja.js_environment.from_string("""
        document.addEventListener("DOMContentLoaded", function() {
          {% if disable_create_object_url %}
          PDFJS.disableCreateObjectURL = true;
          {% endif %}
          PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;

          const viewer = window.PDFView || window.PDFViewerApplication;
          viewer.open("{{ url }}");
        });
    """).render(
        url=javascript.string_escape(url.toString(QUrl.FullyEncoded)),
        # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-70420
        disable_create_object_url=(
            not qtutils.version_check('5.12')
            and not qtutils.version_check('5.7.1', exact=True, compiled=False)
            and objects.backend == usertypes.Backend.QtWebEngine))
def _init_stylesheet(profile):
    """Initialize custom stylesheets.

    Mostly inspired by QupZilla:
    https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/app/mainapplication.cpp#L1063-L1101
    https://github.com/QupZilla/qupzilla/blob/v2.0/src/lib/tools/scripts.cpp#L119-L132

    FIXME:qtwebengine Use QWebEngineStyleSheet once that's available
    https://codereview.qt-project.org/#/c/148671/
    """
    old_script = profile.scripts().findScript('_qute_stylesheet')
    if not old_script.isNull():
        profile.scripts().remove(old_script)

    css = shared.get_user_stylesheet()
    source = """
        (function() {{
            var css = document.createElement('style');
            css.setAttribute('type', 'text/css');
            css.appendChild(document.createTextNode('{}'));
            document.getElementsByTagName('head')[0].appendChild(css);
        }})()
    """.format(javascript.string_escape(css))

    script = QWebEngineScript()
    script.setName('_qute_stylesheet')
    script.setInjectionPoint(QWebEngineScript.DocumentReady)
    script.setWorldId(QWebEngineScript.ApplicationWorld)
    script.setRunsOnSubFrames(True)
    script.setSourceCode(source)
    profile.scripts().insert(script)
Exemple #6
0
    def _test_escape(self, text, web_tab, qtbot):
        """Test conversion by running JS in a tab."""
        escaped = javascript.string_escape(text)

        with qtbot.waitCallback() as cb:
            web_tab.run_js_async('"{}";'.format(escaped), cb)

        cb.assert_called_with(text)
Exemple #7
0
 def set_text(self, text, *, use_js=False):
     self._check_vanished()
     if self.is_content_editable() or not use_js:
         log.webelem.debug("Filling {!r} via set_text.".format(self))
         self._elem.setPlainText(text)
     else:
         log.webelem.debug("Filling {!r} via javascript.".format(self))
         text = javascript.string_escape(text)
         self._elem.evaluateJavaScript("this.value='{}'".format(text))
Exemple #8
0
 def set_text(self, text, *, use_js=False):
     self._check_vanished()
     if self.is_content_editable() or not use_js:
         log.webelem.debug("Filling {!r} via set_text.".format(self))
         self._elem.setPlainText(text)
     else:
         log.webelem.debug("Filling {!r} via javascript.".format(self))
         text = javascript.string_escape(text)
         self._elem.evaluateJavaScript("this.value='{}'".format(text))
 def set_value(self, value):
     self._check_vanished()
     if self.is_content_editable():
         log.webelem.debug("Filling {!r} via set_text.".format(self))
         self._elem.setPlainText(value)
     else:
         log.webelem.debug("Filling {!r} via javascript.".format(self))
         value = javascript.string_escape(value)
         self._elem.evaluateJavaScript("this.value='{}'".format(value))
Exemple #10
0
 def set_value(self, value):
     self._check_vanished()
     if self.is_content_editable():
         log.webelem.debug("Filling {!r} via set_text.".format(self))
         self._elem.setPlainText(value)
     else:
         log.webelem.debug("Filling {!r} via javascript.".format(self))
         value = javascript.string_escape(value)
         self._elem.evaluateJavaScript("this.value='{}'".format(value))
Exemple #11
0
 def check_set(self,
               value,
               css_style="background-color",
               document_element="document.body"):
     """Check whether the css in ELEMENT is set to VALUE."""
     self.js.run(
         "window.getComputedStyle({}, null)"
         ".getPropertyValue('{}');".format(
             document_element, javascript.string_escape(css_style)), value)
Exemple #12
0
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=javascript.string_escape(url.toString(QUrl.FullyEncoded)))
Exemple #13
0
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=javascript.string_escape(url.toString(QUrl.FullyEncoded))
    )
Exemple #14
0
 def set_value(self, value):
     self._check_vanished()
     if self._tab.is_deleted():
         raise webelem.OrphanedError("Tab containing element vanished")
     if self.is_content_editable():
         log.webelem.debug("Filling {!r} via set_text.".format(self))
         self._elem.setPlainText(value)
     else:
         log.webelem.debug("Filling {!r} via javascript.".format(self))
         value = javascript.string_escape(value)
         self._elem.evaluateJavaScript("this.value='{}'".format(value))
Exemple #15
0
    def code(self):
        """Return the processed JavaScript code of this script.

        Adorns the source code with GM_* methods for Greasemonkey
        compatibility and wraps it in an IIFE to hide it within a
        lexical scope. Note that this means line numbers in your
        browser's debugger/inspector will not match up to the line
        numbers in the source script directly.
        """
        # Don't use Proxy on this webkit version, the support isn't there.
        use_proxy = not (objects.backend == usertypes.Backend.QtWebKit
                         and version.qWebKitVersion() == '602.1')
        template = jinja.js_environment.get_template('greasemonkey_wrapper.js')
        return template.render(scriptName=javascript.string_escape("/".join(
            [self.namespace or '', self.name])),
                               scriptInfo=self._meta_json(),
                               scriptMeta=javascript.string_escape(
                                   self.script_meta or ''),
                               scriptSource=self._code,
                               use_proxy=use_proxy)
Exemple #16
0
 def insert_text(self, text):
     self._check_vanished()
     if not self.is_editable(strict=True):
         raise webelem.Error("Element is not editable!")
     log.webelem.debug("Inserting text into element {!r}".format(self))
     self._elem.evaluateJavaScript("""
         var text = "{}";
         var event = document.createEvent("TextEvent");
         event.initTextEvent("textInput", true, true, null, text);
         this.dispatchEvent(event);
     """.format(javascript.string_escape(text)))
Exemple #17
0
 def set_value(self, value):
     self._check_vanished()
     if self._tab.is_deleted():
         raise webelem.OrphanedError("Tab containing element vanished")
     if self.is_content_editable():
         log.webelem.debug("Filling {!r} via set_text.".format(self))
         self._elem.setPlainText(value)
     else:
         log.webelem.debug("Filling {!r} via javascript.".format(self))
         value = javascript.string_escape(value)
         self._elem.evaluateJavaScript("this.value='{}'".format(value))
 def insert_text(self, text):
     self._check_vanished()
     if not self.is_editable(strict=True):
         raise webelem.Error("Element is not editable!")
     log.webelem.debug("Inserting text into element {!r}".format(self))
     self._elem.evaluateJavaScript("""
         var text = "{}";
         var event = document.createEvent("TextEvent");
         event.initTextEvent("textInput", true, true, null, text);
         this.dispatchEvent(event);
     """.format(javascript.string_escape(text)))
Exemple #19
0
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 (
        'document.addEventListener("DOMContentLoaded", function() {{\n'
        '  PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
        '  (window.PDFView || window.PDFViewerApplication).open("{url}");\n'
        '}});\n'
    ).format(url=javascript.string_escape(url.toString(QUrl.FullyEncoded)))
Exemple #20
0
    def code(self):
        """Return the processed JavaScript code of this script.

        Adorns the source code with GM_* methods for Greasemonkey
        compatibility and wraps it in an IIFE to hide it within a
        lexical scope. Note that this means line numbers in your
        browser's debugger/inspector will not match up to the line
        numbers in the source script directly.
        """
        # Don't use Proxy on this webkit version, the support isn't there.
        use_proxy = not (
            objects.backend == usertypes.Backend.QtWebKit and
            version.qWebKitVersion() == '602.1')
        template = jinja.js_environment.get_template('greasemonkey_wrapper.js')
        return template.render(
            scriptName=javascript.string_escape(
                "/".join([self.namespace or '', self.name])),
            scriptInfo=self._meta_json(),
            scriptMeta=javascript.string_escape(self.script_meta or ''),
            scriptSource=self._code,
            use_proxy=use_proxy)
Exemple #21
0
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 (
        'document.addEventListener("DOMContentLoaded", function() {{\n'
        '  PDFJS.verbosity = PDFJS.VERBOSITY_LEVELS.info;\n'
        '  (window.PDFView || window.PDFViewerApplication).open("{url}");\n'
        '}});\n').format(
            url=javascript.string_escape(url.toString(QUrl.FullyEncoded)))
Exemple #22
0
 def click_element(self, text):
     """Click the element with the given text."""
     # Use Javascript and XPath to find the right element, use console.log
     # to return an error (no element found, ambiguous element)
     script = (
         "var _es = document.evaluate('//*[text()={text}]', document, "
         "null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);"
         'if (_es.snapshotLength == 0) {{ console.log("qute:no elems"); }} '
         'else if (_es.snapshotLength > 1) {{ console.log("qute:ambiguous '
         'elems") }} '
         'else {{ console.log("qute:okay"); _es.snapshotItem(0).click() }}'
     ).format(text=javascript.string_escape(_xpath_escape(text)))
     self.send_cmd(":jseval " + script, escape=False)
     message = self.wait_for_js("qute:*").message
     if message.endswith("qute:no elems"):
         raise ValueError("No element with {!r} found".format(text))
     elif message.endswith("qute:ambiguous elems"):
         raise ValueError("Element with {!r} is not unique".format(text))
     elif not message.endswith("qute:okay"):
         raise ValueError("Invalid response from qutebrowser: {}".format(message))
Exemple #23
0
 def click_element_by_text(self, text):
     """Click the element with the given text."""
     # Use Javascript and XPath to find the right element, use console.log
     # to return an error (no element found, ambiguous element)
     script = (
         'var _es = document.evaluate(\'//*[text()={text}]\', document, '
         'null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);'
         'if (_es.snapshotLength == 0) {{ console.log("qute:no elems"); }} '
         'else if (_es.snapshotLength > 1) {{ console.log("qute:ambiguous '
         'elems") }} '
         'else {{ console.log("qute:okay"); _es.snapshotItem(0).click() }}'
     ).format(text=javascript.string_escape(_xpath_escape(text)))
     self.send_cmd(':jseval ' + script, escape=False)
     message = self.wait_for_js('qute:*').message
     if message.endswith('qute:no elems'):
         raise ValueError('No element with {!r} found'.format(text))
     elif message.endswith('qute:ambiguous elems'):
         raise ValueError('Element with {!r} is not unique'.format(text))
     elif not message.endswith('qute:okay'):
         raise ValueError('Invalid response from qutebrowser: {}'
                          .format(message))
    def _test_escape_hexlified(self, text, qtbot, webframe):
        """Test conversion by hexlifying in javascript.

        Since the conversion of QStrings to Python strings is broken in some
        older PyQt versions in some corner cases, we load an HTML file which
        generates an MD5 of the escaped text and use that for comparisons.
        """
        escaped = javascript.string_escape(text)
        path = os.path.join(os.path.dirname(__file__),
                            'test_javascript_string_escape.html')
        with open(path, encoding='utf-8') as f:
            html_source = f.read().replace('%INPUT%', escaped)

        with qtbot.waitSignal(webframe.loadFinished) as blocker:
            webframe.setHtml(html_source)
        assert blocker.args == [True]

        result = webframe.evaluateJavaScript('window.qute_test_result')
        assert result is not None
        assert '|' in result
        result_md5, result_text = result.split('|', maxsplit=1)
        text_md5 = binascii.hexlify(text.encode('utf-8')).decode('ascii')
        assert result_md5 == text_md5, result_text
Exemple #25
0
    def _test_escape_hexlified(self, text, qtbot, webframe):
        """Test conversion by hexlifying in javascript.

        Since the conversion of QStrings to Python strings is broken in some
        older PyQt versions in some corner cases, we load an HTML file which
        generates an MD5 of the escaped text and use that for comparisons.
        """
        escaped = javascript.string_escape(text)
        path = os.path.join(os.path.dirname(__file__),
                            'test_javascript_string_escape.html')
        with open(path, encoding='utf-8') as f:
            html_source = f.read().replace('%INPUT%', escaped)

        with qtbot.waitSignal(webframe.loadFinished) as blocker:
            webframe.setHtml(html_source)
        assert blocker.args == [True]

        result = webframe.evaluateJavaScript('window.qute_test_result')
        assert result is not None
        assert '|' in result
        result_md5, result_text = result.split('|', maxsplit=1)
        text_md5 = binascii.hexlify(text.encode('utf-8')).decode('ascii')
        assert result_md5 == text_md5, result_text
Exemple #26
0
 def test_fake_escape(self, before, after):
     """Test javascript escaping with some expected outcomes."""
     assert javascript.string_escape(before) == after
 def _test_escape(self, text, webframe):
     """Test conversion by using evaluateJavaScript."""
     escaped = javascript.string_escape(text)
     result = webframe.evaluateJavaScript('"{}";'.format(escaped))
     assert result == text
 def test_fake_escape(self, before, after):
     """Test javascript escaping with some expected outcomes."""
     assert javascript.string_escape(before) == after
Exemple #29
0
 def _test_escape_simple(self, text, webframe):
     """Test conversion by using evaluateJavaScript."""
     escaped = javascript.string_escape(text)
     result = webframe.evaluateJavaScript('"{}";'.format(escaped))
     assert result == text