/
browser_window.py
154 lines (124 loc) · 5.07 KB
/
browser_window.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import logging
from typing import TYPE_CHECKING
from PySide2.QtCore import Qt, Slot, QRect, QObject, QUrl
from PySide2.QtGui import QIcon, QDesktopServices
from PySide2.QtWebEngineWidgets import QWebEngineView, QWebEnginePage
from PySide2.QtWidgets import QMainWindow
from runekit.browser import Alt1WebChannel
from runekit.ui.windowframe import WindowFrame
if TYPE_CHECKING:
from runekit.app.app import App
class PageClass(QWebEnginePage):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__)
def javaScriptConsoleMessage(
self,
level: QWebEnginePage.JavaScriptConsoleMessageLevel,
message: str,
line_no: int,
src_id: str,
):
logger = self.logger.getChild(self.url().toString())
log = logger.debug
if level == QWebEnginePage.InfoMessageLevel:
log = logger.debug
elif level == QWebEnginePage.WarningMessageLevel:
log = logger.warning
elif level == QWebEnginePage.ErrorMessageLevel:
log = logger.error
log("%s", message)
def acceptNavigationRequest(
self, url: QUrl, type_: QWebEnginePage.NavigationType, is_main_frame: bool
) -> bool:
if not is_main_frame:
return super().acceptNavigationRequest(url, type_, is_main_frame)
if (
type_ != QWebEnginePage.NavigationTypeTyped
and url.authority() != self.url().authority()
):
# The web is only allowed pages on the same origin
# Cross origin pages would open in browser
if url.scheme() in ("http", "https"):
QDesktopServices.openUrl(url)
return False
return super().acceptNavigationRequest(url, type_, is_main_frame)
class BrowserWindow(QMainWindow):
app: "App"
browser: QWebEngineView
page_class = PageClass
framed = False
def __init__(self, app: "App", **kwargs):
super().__init__(**kwargs)
self.app = app
if self.framed:
self.frame = WindowFrame(parent=self)
self.frame.on_exit.connect(self.close)
self.setCentralWidget(self.frame)
self._setup_browser()
self.setWindowTitle(self.app.manifest["appName"])
self.setAttribute(Qt.WA_DeleteOnClose)
def _setup_browser(self):
self.browser = BrowserView(self)
if hasattr(self, "frame"):
self.frame.set_content(self.browser)
else:
self.setCentralWidget(self.browser)
self.browser.setPage(self.get_page())
def get_page(self) -> QWebEnginePage:
page = self.page_class(self.app.get_web_profile(), self.browser)
page.setWebChannel(Alt1WebChannel(app=self.app, parent=self.browser))
page.geometryChangeRequested.connect(self.on_geometry_change)
page.iconChanged.connect(self.on_icon_changed)
page.windowCloseRequested.connect(self.on_window_close)
page.featurePermissionRequested.connect(self.on_permission_request)
return page
@Slot(QRect)
def on_geometry_change(self, size: QRect):
self.resize(size.size())
@Slot(QIcon)
def on_icon_changed(self, icon: QIcon):
self.setWindowIcon(icon)
@Slot()
def on_window_close(self):
self.close()
@Slot(QUrl, QWebEnginePage.Feature)
def on_permission_request(self, origin: QUrl, feature: QWebEnginePage.Feature):
if feature == QWebEnginePage.Notifications and self.app.has_permission(
"overlay"
):
# FIXME: This doesn't really work - PySide2 doesn't have QWebEngineNotification
self.browser.page().setFeaturePermission(
origin, feature, QWebEnginePage.PermissionGrantedByUser
)
elif (
feature in (QWebEnginePage.DesktopVideoCapture, QWebEnginePage.DesktopAudioVideoCapture)
and self.app.has_permission('pixel')
):
self.browser.page().setFeaturePermission(
origin, feature, QWebEnginePage.PermissionGrantedByUser
)
else:
self.browser.page().setFeaturePermission(
origin, feature, QWebEnginePage.PermissionDeniedByUser
)
class BrowserView(QWebEngineView):
def createWindow(self, type_: QWebEnginePage.WebWindowType) -> QWebEngineView:
from runekit.app.view.popup_window import PopupWindow
app_window = self.browser_window()
popup = PopupWindow(app=app_window.app, parent=app_window)
popup.setWindowIcon(app_window.windowIcon())
def show(ok: bool):
popup.browser.loadFinished.disconnect(show)
if ok:
popup.show()
else:
popup.close()
popup.browser.loadFinished.connect(show)
return popup.browser
def browser_window(self) -> BrowserWindow:
parent: QObject = self.parent()
while parent is not None:
if isinstance(parent, BrowserWindow):
return parent
parent = parent.parent()