Move private tab API into an own object
This commit is contained in:
parent
d60dff2623
commit
5f5f202098
@ -734,6 +734,67 @@ class AbstractAudio(QObject):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AbstractTabPrivate:
|
||||
|
||||
"""Tab-related methods which are only needed in the core.
|
||||
|
||||
Those methods are not part of the API which is exposed to extensions, and
|
||||
should ideally be removed at some point in the future.
|
||||
"""
|
||||
|
||||
def __init__(self, mode_manager: modeman.ModeManager,
|
||||
tab: 'AbstractTab') -> None:
|
||||
self._widget = None # type: typing.Optional[QWidget]
|
||||
self._tab = tab
|
||||
self._mode_manager = mode_manager
|
||||
|
||||
def event_target(self) -> QWidget:
|
||||
"""Return the widget events should be sent to."""
|
||||
raise NotImplementedError
|
||||
|
||||
def handle_auto_insert_mode(self, ok: bool) -> None:
|
||||
"""Handle `input.insert_mode.auto_load` after loading finished."""
|
||||
if not config.val.input.insert_mode.auto_load or not ok:
|
||||
return
|
||||
|
||||
cur_mode = self._mode_manager.mode
|
||||
if cur_mode == usertypes.KeyMode.insert:
|
||||
return
|
||||
|
||||
def _auto_insert_mode_cb(elem: webelem.AbstractWebElement) -> None:
|
||||
"""Called from JS after finding the focused element."""
|
||||
if elem is None:
|
||||
log.webview.debug("No focused element!")
|
||||
return
|
||||
if elem.is_editable():
|
||||
modeman.enter(self._tab.win_id, usertypes.KeyMode.insert,
|
||||
'load finished', only_if_normal=True)
|
||||
|
||||
self._tab.elements.find_focused(_auto_insert_mode_cb)
|
||||
|
||||
def clear_ssl_errors(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def networkaccessmanager(self) -> typing.Optional[QNetworkAccessManager]:
|
||||
"""Get the QNetworkAccessManager for this tab.
|
||||
|
||||
This is only implemented for QtWebKit.
|
||||
For QtWebEngine, always returns None.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def user_agent(self) -> typing.Optional[str]:
|
||||
"""Get the user agent for this tab.
|
||||
|
||||
This is only implemented for QtWebKit.
|
||||
For QtWebEngine, always returns None.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def shutdown(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AbstractTab(QWidget):
|
||||
|
||||
"""A wrapper over the given widget to hide its API and expose another one.
|
||||
@ -785,10 +846,7 @@ class AbstractTab(QWidget):
|
||||
renderer_process_terminated = pyqtSignal(TerminationStatus, int)
|
||||
predicted_navigation = pyqtSignal(QUrl)
|
||||
|
||||
def __init__(self, *,
|
||||
win_id: int,
|
||||
mode_manager: modeman.ModeManager,
|
||||
private: bool,
|
||||
def __init__(self, *, win_id: int, private: bool,
|
||||
parent: QWidget = None) -> None:
|
||||
self.is_private = private
|
||||
self.win_id = win_id
|
||||
@ -806,7 +864,6 @@ class AbstractTab(QWidget):
|
||||
self._widget = None # type: typing.Optional[QWidget]
|
||||
self._progress = 0
|
||||
self._has_ssl_errors = False
|
||||
self._mode_manager = mode_manager
|
||||
self._load_status = usertypes.LoadStatus.none
|
||||
self._mouse_event_filter = mouse.MouseEventFilter(
|
||||
self, parent=self)
|
||||
@ -833,6 +890,7 @@ class AbstractTab(QWidget):
|
||||
self.action._widget = widget
|
||||
self.elements._widget = widget
|
||||
self.audio._widget = widget
|
||||
self.private_api._widget = widget
|
||||
self.settings._settings = widget.settings()
|
||||
|
||||
self._install_event_filter()
|
||||
@ -849,10 +907,6 @@ class AbstractTab(QWidget):
|
||||
self._load_status = val
|
||||
self.load_status_changed.emit(val.name)
|
||||
|
||||
def event_target(self) -> QWidget:
|
||||
"""Return the widget events should be sent to."""
|
||||
raise NotImplementedError
|
||||
|
||||
def send_event(self, evt: QEvent) -> None:
|
||||
"""Send the given event to the underlying widget.
|
||||
|
||||
@ -865,7 +919,7 @@ class AbstractTab(QWidget):
|
||||
raise utils.Unreachable("Can't re-use an event which was already "
|
||||
"posted!")
|
||||
|
||||
recipient = self.event_target()
|
||||
recipient = self.private_api.event_target()
|
||||
if recipient is None:
|
||||
# https://github.com/qutebrowser/qutebrowser/issues/3888
|
||||
log.webview.warning("Unable to find event target!")
|
||||
@ -925,26 +979,6 @@ class AbstractTab(QWidget):
|
||||
navigation.url.errorString()))
|
||||
navigation.accepted = False
|
||||
|
||||
def handle_auto_insert_mode(self, ok: bool) -> None:
|
||||
"""Handle `input.insert_mode.auto_load` after loading finished."""
|
||||
if not config.val.input.insert_mode.auto_load or not ok:
|
||||
return
|
||||
|
||||
cur_mode = self._mode_manager.mode
|
||||
if cur_mode == usertypes.KeyMode.insert:
|
||||
return
|
||||
|
||||
def _auto_insert_mode_cb(elem: webelem.AbstractWebElement) -> None:
|
||||
"""Called from JS after finding the focused element."""
|
||||
if elem is None:
|
||||
log.webview.debug("No focused element!")
|
||||
return
|
||||
if elem.is_editable():
|
||||
modeman.enter(self.win_id, usertypes.KeyMode.insert,
|
||||
'load finished', only_if_normal=True)
|
||||
|
||||
self.elements.find_focused(_auto_insert_mode_cb)
|
||||
|
||||
@pyqtSlot(bool)
|
||||
def _on_load_finished(self, ok: bool) -> None:
|
||||
assert self._widget is not None
|
||||
@ -1010,9 +1044,6 @@ class AbstractTab(QWidget):
|
||||
def stop(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def clear_ssl_errors(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def key_press(self,
|
||||
key: Qt.Key,
|
||||
modifier: Qt.KeyboardModifier = Qt.NoModifier) -> None:
|
||||
@ -1048,9 +1079,6 @@ class AbstractTab(QWidget):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def shutdown(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def title(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
@ -1060,22 +1088,6 @@ class AbstractTab(QWidget):
|
||||
def set_html(self, html: str, base_url: QUrl = QUrl()) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def networkaccessmanager(self) -> typing.Optional[QNetworkAccessManager]:
|
||||
"""Get the QNetworkAccessManager for this tab.
|
||||
|
||||
This is only implemented for QtWebKit.
|
||||
For QtWebEngine, always returns None.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def user_agent(self) -> typing.Optional[str]:
|
||||
"""Get the user agent for this tab.
|
||||
|
||||
This is only implemented for QtWebKit.
|
||||
For QtWebEngine, always returns None.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def __repr__(self) -> str:
|
||||
try:
|
||||
qurl = self.url()
|
||||
|
@ -1516,7 +1516,7 @@ class CommandDispatcher:
|
||||
else:
|
||||
download_manager.get_mhtml(tab, target)
|
||||
else:
|
||||
qnam = tab.networkaccessmanager()
|
||||
qnam = tab.private_api.networkaccessmanager()
|
||||
|
||||
suggested_fn = downloads.suggested_fn_from_title(
|
||||
self._current_url().path(), tab.title()
|
||||
@ -2165,7 +2165,7 @@ class CommandDispatcher:
|
||||
debug=True, backend=usertypes.Backend.QtWebKit)
|
||||
def debug_clear_ssl_errors(self):
|
||||
"""Clear remembered SSL error answers."""
|
||||
self._current_widget().clear_ssl_errors()
|
||||
self._current_widget().private_api.clear_ssl_errors()
|
||||
|
||||
@cmdutils.register(instance='command-dispatcher', scope='window')
|
||||
def edit_url(self, url=None, bg=False, tab=False, window=False,
|
||||
|
@ -304,7 +304,7 @@ class HintActions:
|
||||
raise HintingError("No suitable link found for this element.")
|
||||
|
||||
prompt = False if context.rapid else None
|
||||
qnam = context.tab.networkaccessmanager()
|
||||
qnam = context.tab.private_api.networkaccessmanager()
|
||||
user_agent = context.tab.user_agent()
|
||||
|
||||
# FIXME:qtwebengine do this with QtWebEngine downloads?
|
||||
|
@ -240,7 +240,7 @@ class MouseEventFilter(QObject):
|
||||
evtype = event.type()
|
||||
if evtype not in self._handlers:
|
||||
return False
|
||||
if obj is not self._tab.event_target():
|
||||
if obj is not self._tab.private_api.event_target():
|
||||
log.mouse.debug("Ignoring {} to {}".format(
|
||||
event.__class__.__name__, obj))
|
||||
return False
|
||||
|
@ -1038,6 +1038,28 @@ class _WebEngineScripts(QObject):
|
||||
page_scripts.insert(new_script)
|
||||
|
||||
|
||||
class WebEngineTabPrivate(browsertab.AbstractTabPrivate):
|
||||
|
||||
"""QtWebEngine-related methods which aren't part of the public API."""
|
||||
|
||||
def networkaccessmanager(self):
|
||||
return None
|
||||
|
||||
def user_agent(self):
|
||||
return None
|
||||
|
||||
def clear_ssl_errors(self):
|
||||
raise browsertab.UnsupportedOperationError
|
||||
|
||||
def event_target(self):
|
||||
return self._widget.render_widget()
|
||||
|
||||
def shutdown(self):
|
||||
self._tab.shutting_down.emit()
|
||||
self._tab.action.exit_fullscreen()
|
||||
self._widget.shutdown()
|
||||
|
||||
|
||||
class WebEngineTab(browsertab.AbstractTab):
|
||||
|
||||
"""A QtWebEngine tab in the browser.
|
||||
@ -1051,8 +1073,7 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
_load_finished_fake = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
super().__init__(win_id=win_id, mode_manager=mode_manager,
|
||||
private=private, parent=parent)
|
||||
super().__init__(win_id=win_id, private=private, parent=parent)
|
||||
widget = webview.WebEngineView(tabdata=self.data, win_id=win_id,
|
||||
private=private)
|
||||
self.history = WebEngineHistory(tab=self)
|
||||
@ -1065,6 +1086,8 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
self.elements = WebEngineElements(tab=self)
|
||||
self.action = WebEngineAction(tab=self)
|
||||
self.audio = WebEngineAudio(tab=self, parent=self)
|
||||
self.private_api = WebEngineTabPrivate(mode_manager=mode_manager,
|
||||
tab=self)
|
||||
self._permissions = _WebEnginePermissions(tab=self, parent=self)
|
||||
self._scripts = _WebEngineScripts(tab=self, parent=self)
|
||||
# We're assigning settings in _set_widget
|
||||
@ -1146,11 +1169,6 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
else:
|
||||
self._widget.page().runJavaScript(code, world_id, callback)
|
||||
|
||||
def shutdown(self):
|
||||
self.shutting_down.emit()
|
||||
self.action.exit_fullscreen()
|
||||
self._widget.shutdown()
|
||||
|
||||
def reload(self, *, force=False):
|
||||
if force:
|
||||
action = QWebEnginePage.ReloadAndBypassCache
|
||||
@ -1175,15 +1193,6 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
# percent encoded content is 2 megabytes minus 30 bytes.
|
||||
self._widget.setHtml(html, base_url)
|
||||
|
||||
def networkaccessmanager(self):
|
||||
return None
|
||||
|
||||
def user_agent(self):
|
||||
return None
|
||||
|
||||
def clear_ssl_errors(self):
|
||||
raise browsertab.UnsupportedOperationError
|
||||
|
||||
def key_press(self, key, modifier=Qt.NoModifier):
|
||||
press_evt = QKeyEvent(QEvent.KeyPress, key, modifier, 0, 0, 0)
|
||||
release_evt = QKeyEvent(QEvent.KeyRelease, key, modifier,
|
||||
@ -1485,6 +1494,3 @@ class WebEngineTab(browsertab.AbstractTab):
|
||||
self.audio._connect_signals()
|
||||
self._permissions.connect_signals()
|
||||
self._scripts.connect_signals()
|
||||
|
||||
def event_target(self):
|
||||
return self._widget.render_widget()
|
||||
|
@ -657,13 +657,33 @@ class WebKitAudio(browsertab.AbstractAudio):
|
||||
return False
|
||||
|
||||
|
||||
class WebKitTabPrivate(browsertab.AbstractTabPrivate):
|
||||
|
||||
"""QtWebKit-related methods which aren't part of the public API."""
|
||||
|
||||
def networkaccessmanager(self):
|
||||
return self._widget.page().networkAccessManager()
|
||||
|
||||
def user_agent(self):
|
||||
page = self._widget.page()
|
||||
return page.userAgentForUrl(self._tab.url())
|
||||
|
||||
def clear_ssl_errors(self):
|
||||
self.networkaccessmanager().clear_all_ssl_errors()
|
||||
|
||||
def event_target(self):
|
||||
return self._widget
|
||||
|
||||
def shutdown(self):
|
||||
self._widget.shutdown()
|
||||
|
||||
|
||||
class WebKitTab(browsertab.AbstractTab):
|
||||
|
||||
"""A QtWebKit tab in the browser."""
|
||||
|
||||
def __init__(self, *, win_id, mode_manager, private, parent=None):
|
||||
super().__init__(win_id=win_id, mode_manager=mode_manager,
|
||||
private=private, parent=parent)
|
||||
super().__init__(win_id=win_id, private=private, parent=parent)
|
||||
widget = webview.WebView(win_id=win_id, tab_id=self.tab_id,
|
||||
private=private, tab=self)
|
||||
if private:
|
||||
@ -678,6 +698,8 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
self.elements = WebKitElements(tab=self)
|
||||
self.action = WebKitAction(tab=self)
|
||||
self.audio = WebKitAudio(tab=self, parent=self)
|
||||
self.private_api = WebKitTabPrivate(mode_manager=mode_manager,
|
||||
tab=self)
|
||||
# We're assigning settings in _set_widget
|
||||
self.settings = webkitsettings.WebKitSettings(settings=None)
|
||||
self._set_widget(widget)
|
||||
@ -720,9 +742,6 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
def icon(self):
|
||||
return self._widget.icon()
|
||||
|
||||
def shutdown(self):
|
||||
self._widget.shutdown()
|
||||
|
||||
def reload(self, *, force=False):
|
||||
if force:
|
||||
action = QWebPage.ReloadAndBypassCache
|
||||
@ -736,9 +755,6 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
def title(self):
|
||||
return self._widget.title()
|
||||
|
||||
def clear_ssl_errors(self):
|
||||
self.networkaccessmanager().clear_all_ssl_errors()
|
||||
|
||||
def key_press(self, key, modifier=Qt.NoModifier):
|
||||
press_evt = QKeyEvent(QEvent.KeyPress, key, modifier, 0, 0, 0)
|
||||
release_evt = QKeyEvent(QEvent.KeyRelease, key, modifier,
|
||||
@ -755,17 +771,11 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
def set_html(self, html, base_url=QUrl()):
|
||||
self._widget.setHtml(html, base_url)
|
||||
|
||||
def networkaccessmanager(self):
|
||||
return self._widget.page().networkAccessManager()
|
||||
|
||||
def user_agent(self):
|
||||
page = self._widget.page()
|
||||
return page.userAgentForUrl(self.url())
|
||||
|
||||
@pyqtSlot()
|
||||
def _on_load_started(self):
|
||||
super()._on_load_started()
|
||||
self.networkaccessmanager().netrc_used = False
|
||||
nam = self._widget.page().networkAccessManager()
|
||||
nam.netrc_used = False
|
||||
# Make sure the icon is cleared when navigating to a page without one.
|
||||
self.icon_changed.emit(QIcon())
|
||||
|
||||
@ -847,6 +857,3 @@ class WebKitTab(browsertab.AbstractTab):
|
||||
frame.contentsSizeChanged.connect(self._on_contents_size_changed)
|
||||
frame.initialLayoutCompleted.connect(self._on_history_trigger)
|
||||
page.navigation_request.connect(self._on_navigation_request)
|
||||
|
||||
def event_target(self):
|
||||
return self._widget
|
||||
|
@ -753,7 +753,7 @@ class TabbedBrowser(QWidget):
|
||||
self.widget.update_tab_title(idx)
|
||||
if idx == self.widget.currentIndex():
|
||||
self._update_window_title()
|
||||
tab.handle_auto_insert_mode(ok)
|
||||
tab.private_api.handle_auto_insert_mode(ok)
|
||||
|
||||
@pyqtSlot()
|
||||
def on_scroll_pos_changed(self):
|
||||
|
@ -241,6 +241,12 @@ class FakeWebTabAudio(browsertab.AbstractAudio):
|
||||
return False
|
||||
|
||||
|
||||
class FakeWebTabPrivate:
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
|
||||
class FakeWebTab(browsertab.AbstractTab):
|
||||
|
||||
"""Fake AbstractTab to use in tests."""
|
||||
@ -258,6 +264,7 @@ class FakeWebTab(browsertab.AbstractTab):
|
||||
can_go_forward=can_go_forward)
|
||||
self.scroller = FakeWebTabScroller(self, scroll_pos_perc)
|
||||
self.audio = FakeWebTabAudio(self)
|
||||
self.private_api = FakeWebTabPrivate()
|
||||
wrapped = QWidget()
|
||||
self._layout.wrap(self, wrapped)
|
||||
|
||||
@ -274,9 +281,6 @@ class FakeWebTab(browsertab.AbstractTab):
|
||||
def load_status(self):
|
||||
return self._load_status
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def icon(self):
|
||||
return QIcon()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user