change setHtml() to serve content via media server
- fixes https://forums.ankiweb.net/t/deck-list-is-blank/2241/2 - fixes the security warnings on Qt 6, by ensuring our pages and resources are coming from the same origin
This commit is contained in:
parent
4b5004c472
commit
d33c66e195
@ -78,6 +78,8 @@ class MediaServer(threading.Thread):
|
||||
def __init__(self, mw: aqt.main.AnkiQt) -> None:
|
||||
super().__init__()
|
||||
self.is_shutdown = False
|
||||
# map of webview ids to pages
|
||||
self._page_html: dict[int, str] = {}
|
||||
|
||||
def run(self) -> None:
|
||||
try:
|
||||
@ -119,6 +121,18 @@ class MediaServer(threading.Thread):
|
||||
self._ready.wait()
|
||||
return int(self.server.effective_port) # type: ignore
|
||||
|
||||
def set_page_html(self, id: int, html: str) -> None:
|
||||
self._page_html[id] = html
|
||||
|
||||
def get_page_html(self, id: int) -> str | None:
|
||||
return self._page_html.get(id)
|
||||
|
||||
def clear_page_html(self, id: int) -> None:
|
||||
try:
|
||||
del self._page_html[id]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
def _handle_local_file_request(request: LocalFileRequest) -> Response:
|
||||
directory = request.root
|
||||
@ -220,6 +234,8 @@ def _extract_internal_request(
|
||||
if dirname == "_anki":
|
||||
if flask.request.method == "POST":
|
||||
return _extract_collection_post_request(filename)
|
||||
elif get_handler := _extract_dynamic_get_request(filename):
|
||||
return get_handler
|
||||
# remap legacy top-level references
|
||||
base, ext = os.path.splitext(filename)
|
||||
if ext == ".css":
|
||||
@ -395,6 +411,7 @@ def complete_tag() -> bytes:
|
||||
return aqt.mw.col.tags.complete_tag(request.data)
|
||||
|
||||
|
||||
# these require a collection
|
||||
post_handlers = {
|
||||
"graphData": graph_data,
|
||||
"graphPreferences": graph_preferences,
|
||||
@ -435,3 +452,20 @@ def _handle_dynamic_request(request: DynamicRequest) -> Response:
|
||||
return request()
|
||||
except Exception as e:
|
||||
return flask.make_response(str(e), HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
def legacy_page_data() -> Response:
|
||||
id = int(request.args["id"])
|
||||
if html := aqt.mw.mediaServer.get_page_html(id):
|
||||
return Response(html, mimetype="text/html")
|
||||
else:
|
||||
return flask.make_response("page not found", HTTPStatus.NOT_FOUND)
|
||||
|
||||
|
||||
# this currently only handles a single method; in the future, idempotent
|
||||
# requests like i18nResources should probably be moved here
|
||||
def _extract_dynamic_get_request(path: str) -> DynamicRequest | None:
|
||||
if path == "legacyPageData":
|
||||
return legacy_page_data
|
||||
else:
|
||||
return None
|
||||
|
@ -120,7 +120,11 @@ class AnkiWebPage(QWebEnginePage):
|
||||
def acceptNavigationRequest(
|
||||
self, url: QUrl, navType: Any, isMainFrame: bool
|
||||
) -> bool:
|
||||
if not self.open_links_externally or "_anki/pages" in url.path():
|
||||
if (
|
||||
not self.open_links_externally
|
||||
or "_anki/pages" in url.path()
|
||||
or url.path() == "/_anki/legacyPageData"
|
||||
):
|
||||
return super().acceptNavigationRequest(url, navType, isMainFrame)
|
||||
|
||||
if not isMainFrame:
|
||||
@ -315,12 +319,23 @@ class AnkiWebView(QWebEngineView):
|
||||
self.show()
|
||||
|
||||
def _setHtml(self, html: str) -> None:
|
||||
"""Send page data to media server, then surf to it.
|
||||
|
||||
This function used to be implemented by QWebEngine's
|
||||
.setHtml() call. It is no longer used, as it has a
|
||||
maximum size limit, and due to security changes, it
|
||||
will stop working in the future."""
|
||||
from aqt import mw
|
||||
|
||||
oldFocus = mw.app.focusWidget()
|
||||
self._domDone = False
|
||||
self._page.setHtml(html)
|
||||
|
||||
webview_id = id(self)
|
||||
mw.mediaServer.set_page_html(webview_id, html)
|
||||
self.load_url(QUrl(f"{mw.serverURL()}_anki/legacyPageData?id={webview_id}"))
|
||||
|
||||
# work around webengine stealing focus on setHtml()
|
||||
# fixme: check which if any qt versions this is still required on
|
||||
if oldFocus:
|
||||
oldFocus.setFocus()
|
||||
|
||||
@ -646,4 +661,9 @@ document.head.appendChild(style);
|
||||
Must be done on Windows prior to changing current working directory."""
|
||||
self.requiresCol = False
|
||||
self._domReady = False
|
||||
self._page.setContent(bytes("", "ascii"))
|
||||
self._page.setContent(cast(QByteArray, bytes("", "ascii")))
|
||||
|
||||
def __del__(self) -> None:
|
||||
from aqt import mw
|
||||
|
||||
mw.mediaServer.clear_page_html(id(self))
|
||||
|
Loading…
Reference in New Issue
Block a user