Greasemonkey: webkit: injected all scripts on loadFinished.

The signal we were using to inject greasemonkey scripts registered to
run at document-start (javaScriptWindowObjectCleared) was unreliable to
non-existant. The initialLayoutCompleted signal is a bit of an odd duck
too I suppose. Anyway, we don't anticipate any scripts would break from
being injected when the page is finished loaded that wouldn't already
have been flaky due to the complexities of the modern web. If there is
an issue hopefully someone raises an issue and we can look into it.
This commit is contained in:
Jimmy 2017-11-08 21:03:58 +13:00
parent 8a5b42ffbd
commit df624944f9

View File

@ -86,33 +86,18 @@ class BrowserPage(QWebPage):
self.on_save_frame_state_requested) self.on_save_frame_state_requested)
self.restoreFrameStateRequested.connect( self.restoreFrameStateRequested.connect(
self.on_restore_frame_state_requested) self.on_restore_frame_state_requested)
self.connect_userjs_signals(None) self.connect_userjs_signals(self.mainFrame())
self.frameCreated.connect(self.connect_userjs_signals) self.frameCreated.connect(self.connect_userjs_signals)
@pyqtSlot('QWebFrame*') @pyqtSlot('QWebFrame*')
def connect_userjs_signals(self, frame_arg): def connect_userjs_signals(self, frame):
""" """Connect userjs related signals to `frame`.
Connect the signals used as triggers for injecting user
javascripts into `frame_arg`.
"""
# If we pass whatever self.mainFrame() or self.currentFrame() returns
# at init time into the partial functions which the signals
# below call then the signals don't seem to be called at all for
# the main frame of the first tab. I have no idea why I am
# seeing this behavior. Replace the None in the call to this
# function in __init__ with self.mainFrame() and try for
# yourself.
if frame_arg:
frame = frame_arg
else:
frame = self.mainFrame()
frame.javaScriptWindowObjectCleared.connect( Connect the signals used as triggers for injecting user
functools.partial(self.inject_userjs, frame_arg, load='start')) javascripts into the passed QWebFrame.
frame.initialLayoutCompleted.connect( """
functools.partial(self.inject_userjs, frame_arg, load='end'))
frame.loadFinished.connect( frame.loadFinished.connect(
functools.partial(self.inject_userjs, frame_arg, load='idle')) functools.partial(self.inject_userjs, frame))
def javaScriptPrompt(self, frame, js_msg, default): def javaScriptPrompt(self, frame, js_msg, default):
"""Override javaScriptPrompt to use qutebrowser prompts.""" """Override javaScriptPrompt to use qutebrowser prompts."""
@ -311,32 +296,22 @@ class BrowserPage(QWebPage):
self.error_occurred = False self.error_occurred = False
@pyqtSlot() @pyqtSlot()
def inject_userjs(self, frame, load): def inject_userjs(self, frame):
"""Inject user javascripts into the page. """Inject user javascripts into the page.
Args: Args:
frame: The QWebFrame to inject the user scripts into, or frame: The QWebFrame to inject the user scripts into.
None for the main frame.
load: The page load stage to inject the corresponding
scripts for. Support values are "start", "end" and
"idle", corresponding to the allowed values of the
`@run-at` directive in the greasemonkey metadata spec.
""" """
if not frame:
frame = self.mainFrame()
url = frame.url() url = frame.url()
if url.isEmpty(): if url.isEmpty():
url = frame.requestedUrl() url = frame.requestedUrl()
greasemonkey = objreg.get('greasemonkey') greasemonkey = objreg.get('greasemonkey')
scripts = greasemonkey.scripts_for(url) scripts = greasemonkey.scripts_for(url)
# QtWebKit has trouble providing us with signals representing
if load == "start": # page load progress at reasonable times, so we just load all
toload = scripts.start # scripts on the same event.
elif load == "end": toload = scripts.start + scripts.end + scripts.idle
toload = scripts.end
elif load == "idle":
toload = scripts.idle
if url.isEmpty(): if url.isEmpty():
# This happens during normal usage like with view source but may # This happens during normal usage like with view source but may