def create_profile(): ans = getattr(create_profile, 'ans', None) if ans is None: ans = QWebEngineProfile(QApplication.instance()) ua = 'calibre-editor-preview ' + __version__ ans.setHttpUserAgent(ua) if is_running_from_develop: from calibre.utils.rapydscript import compile_editor compile_editor() js = P('editor.js', data=True, allow_user_override=False) cparser = P('csscolorparser.js', data=True, allow_user_override=False) insert_scripts( ans, create_script('csscolorparser.js', cparser), create_script('editor.js', js), ) url_handler = UrlSchemeHandler(ans) ans.installUrlSchemeHandler(QByteArray(FAKE_PROTOCOL.encode('ascii')), url_handler) s = ans.settings() s.setDefaultTextEncoding('utf-8') s.setAttribute(s.FullScreenSupportEnabled, False) s.setAttribute(s.LinksIncludedInFocusChain, False) create_profile.ans = ans return ans
def create_profile(): ans = getattr(create_profile, 'ans', None) if ans is None: ans = QWebEngineProfile(QApplication.instance()) osname = 'windows' if iswindows else ('macos' if ismacos else 'linux') # DO NOT change the user agent as it is used to workaround # Qt bugs see workaround_qt_bug() in ajax.pyj ua = 'calibre-viewer {} {}'.format(__version__, osname) ans.setHttpUserAgent(ua) if is_running_from_develop: from calibre.utils.rapydscript import compile_viewer prints('Compiling viewer code...') compile_viewer() js = P('viewer.js', data=True, allow_user_override=False) translations_json = get_translations_data() or b'null' js = js.replace(b'__TRANSLATIONS_DATA__', translations_json, 1) if in_develop_mode: js = js.replace(b'__IN_DEVELOP_MODE__', b'1') insert_scripts(ans, create_script('viewer.js', js)) url_handler = UrlSchemeHandler(ans) ans.installUrlSchemeHandler(QByteArray(FAKE_PROTOCOL.encode('ascii')), url_handler) s = ans.settings() s.setDefaultTextEncoding('utf-8') s.setAttribute(QWebEngineSettings.WebAttribute.LinksIncludedInFocusChain, False) create_profile.ans = ans return ans
def create_profile(): ans = getattr(create_profile, 'ans', None) if ans is None: ans = QWebEngineProfile(QApplication.instance()) ua = 'calibre-editor-preview ' + __version__ ans.setHttpUserAgent(ua) if is_running_from_develop: from calibre.utils.rapydscript import compile_editor compile_editor() js = P('editor.js', data=True, allow_user_override=False) cparser = P('csscolorparser.js', data=True, allow_user_override=False) dark_mode_css = P('dark_mode.css', data=True, allow_user_override=False).decode('utf-8') insert_scripts( ans, create_script('csscolorparser.js', cparser), create_script('editor.js', js), create_script('dark-mode.js', ''' (function() { var settings = JSON.parse(navigator.userAgent.split('|')[1]); var dark_css = CSS; function apply_body_colors(event) { if (document.documentElement) { if (settings.bg) document.documentElement.style.backgroundColor = settings.bg; if (settings.fg) document.documentElement.style.color = settings.fg; } if (document.body) { if (settings.bg) document.body.style.backgroundColor = settings.bg; if (settings.fg) document.body.style.color = settings.fg; } } function apply_css() { var css = ''; if (settings.link) css += 'html > body :link, html > body :link * { color: ' + settings.link + ' !important; }'; if (settings.is_dark_theme) { css += dark_css; } var style = document.createElement('style'); style.textContent = css; document.documentElement.appendChild(style); apply_body_colors(); } apply_body_colors(); document.addEventListener("DOMContentLoaded", apply_css); })(); '''.replace('CSS', json.dumps(dark_mode_css), 1), injection_point=QWebEngineScript.InjectionPoint. DocumentCreation)) url_handler = UrlSchemeHandler(ans) ans.installUrlSchemeHandler(QByteArray(FAKE_PROTOCOL.encode('ascii')), url_handler) s = ans.settings() s.setDefaultTextEncoding('utf-8') s.setAttribute(s.FullScreenSupportEnabled, False) s.setAttribute(s.LinksIncludedInFocusChain, False) create_profile.ans = ans return ans
def create_profile(): ans = getattr(create_profile, 'ans', None) if ans is None: ans = QWebEngineProfile('viewer-lookup', QApplication.instance()) ans.setHttpUserAgent(random_user_agent(allow_ie=False)) ans.setCachePath(os.path.join(cache_dir(), 'ev2vl')) js = P('lookup.js', data=True, allow_user_override=False) insert_scripts(ans, create_script('lookup.js', js)) s = ans.settings() s.setDefaultTextEncoding('utf-8') create_profile.ans = ans return ans
def create_profile(): ans = getattr(create_profile, 'ans', None) if ans is None: ans = QWebEngineProfile(QApplication.instance()) ua = 'calibre-viewer ' + __version__ ans.setHttpUserAgent(ua) if is_running_from_develop: from calibre.utils.rapydscript import compile_viewer print('Compiling viewer code...') compile_viewer() js = P('viewer.js', data=True, allow_user_override=False) translations_json = get_translations_data() or b'null' js = js.replace(b'__TRANSLATIONS_DATA__', translations_json, 1) insert_scripts(ans, create_script('viewer.js', js)) url_handler = UrlSchemeHandler(ans) ans.installUrlSchemeHandler(QByteArray(FAKE_PROTOCOL.encode('ascii')), url_handler) s = ans.settings() s.setDefaultTextEncoding('utf-8') s.setAttribute(s.LinksIncludedInFocusChain, False) create_profile.ans = ans return ans
def __init__(self, opts, log, container_root): QObject.__init__(self) self.interceptor = RequestInterceptor(self) self.has_maths = {} self.interceptor.log = self.log = log self.interceptor.container_root = os.path.normcase(os.path.abspath(container_root)) self.interceptor.resources_root = os.path.normcase(os.path.abspath(os.path.dirname(mathjax_dir()))) ans = QWebEngineProfile(QApplication.instance()) ua = 'calibre-pdf-output ' + __version__ ans.setHttpUserAgent(ua) s = ans.settings() s.setDefaultTextEncoding('utf-8') ans.setUrlRequestInterceptor(self.interceptor) self.profile = ans self.opts = opts self.workers = [] self.max_workers = detect_ncpus() if iswindows: self.original_signal_handlers = {} else: self.original_signal_handlers = setup_unix_signals(self)
class Njaxt(QtWidgets.QMainWindow, njaxt_ui.Ui_MainWindow): def __init__(self): super().__init__() self.setupUi(self) self.fuzzer = None self.stopLoop = False self.fuzz_widget = FuzzerWidget() self.payload_widget = PayloadsWidget() self.init_webview() self.init_sigslot() self.show() def init_webview(self): self.webProfile = QWebEngineProfile(self.webView) self.webProfile.setHttpUserAgent( "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36" ) self.webProfile.setHttpAcceptLanguage("en-US,en;q=0.8") self.webProfile.settings().setAttribute( QWebEngineSettings.LocalStorageEnabled, True) self.set_scripts() self.webPage = QWebEnginePage(self.webProfile, self) self.webView.setPage(self.webPage) self.webView.loadProgress.connect(self.set_progress) self.webView.loadFinished.connect( lambda: self.lineEdit.setText(self.webView.url().toString())) def set_scripts(self): script = QWebEngineScript() script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setWorldId(QWebEngineScript.MainWorld) script.setSourceCode("""(function() { var _old_alert = window.alert; window.alert = function() { document.activeElement.innerHTML += "<br>alerting"; _old_alert.apply(window,arguments); document.activeElement.innerHTML += "<br>done alerting<br>"; }; })(); """) self.webProfile.scripts().insert(script) def init_sigslot(self): self.lineEdit.returnPressed.connect(self.make_fuzzer) self.pushButton.clicked.connect(self.make_fuzzer) self.pushButtonReset.clicked.connect(self.handle_reset) self.actionAdvanced_Fuzzer.triggered.connect(self.show_fuzz) self.fuzz_widget.pushButton.clicked.connect(self.make_fuzzer) self.actionWordlist.triggered.connect(self.show_payloads) def set_progress(self, p): self.progressBar.setValue(p) def show_fuzz(self): self.fuzz_widget.show() def show_payloads(self): self.payload_widget.show() def make_fuzzer(self): if self.fuzz_widget.data: self.fuzzer = fuzzer.Fuzzer(self.fuzz_widget.data) else: self.fuzzer = fuzzer.Fuzzer({"url": self.lineEdit.text()}) self.fuzz() def handle_reset(self): # Reset Fuzz Widget self.fuzz_widget.reset_widget() # Reset Main Form self.fuzzer = fuzzer.Fuzzer({"url": ""}) self.init_webview() self.lineEdit.setText("") self.set_progress(0) self.stopLoop = False def detect_xss(self, source): if "<br>alerting" in source: print(self.lineEdit.text()) self.stopLoop = True def fuzz(self): loop = QEventLoop() for request in self.fuzzer.requests(PAYLOADS): self.webView.loadFinished.connect(loop.quit) self.webView.load(request) loop.exec() self.webView.page().toHtml(self.detect_xss) if self.stopLoop: break
class MainApplication(QtSingleApp): s_testMode = False # type AfterLaunch OpenBlankPage = 0 OpenHomePage = 1 OpenSpeedDial = 2 RestoreSession = 3 SelectSession = 4 def __init__(self, argv): # noqa 901 super(MainApplication, self).__init__(argv) self._isPrivate = False self._isPortable = True self._isClosing = False self._isStartingAfterCrash = False self._history = None # History self._bookmarks = None # Bookmarks self._autoFill = None # AutoFill self._cookieJar = None # CookieJar self._plugins = None # PluginProxy self._browsingLibrary = None # BrowsingLibrary self._networkManager = None self._restoreManager = None self._sessionManager = None self._downloadManager = None self._userAgentManager = None self._searchEnginesManager = None self._closedWindowsManager = None self._protocolHandlerManager = None self._html5PermissionsManager = None self._desktopNotifications = None # DesktopNotificationsFactory self._webProfile = None # QWebEngineProfile self._autoSaver = None self._proxyStyle = None self._wmClass = QByteArray() self._windows = [] self._lastActiveWindow = None self._postLaunchActions = [] self.setAttribute(Qt.AA_UseHighDpiPixmaps) self.setAttribute(Qt.AA_DontCreateNativeWidgetSiblings) self.setApplicationName('demo') self.setOrganizationDomain('org.autowin') self.setWindowIcon(QIcon.fromTheme('demo', QIcon(':/icons/demo.svg'))) self.setDesktopFileName('orig.autowin.demo') self.setApplicationVersion('1.0') # Set fallback icon theme (eg. on Windows/Mac) if QIcon.fromTheme('view-refresh').isNull(): QIcon.setThemeName('breeze-fallback') # QSQLITE database plugin is required if not QSqlDatabase.isDriverAvailable('QSQLITE'): QMessageBox.Critical( None, 'Error', 'Qt SQLite database plugin is not available.' ' Please install it and restart the application.') self._isClosing = True return if const.OS_WIN: # Set default app font (needed for N'ko) fontId = QFontDatabase.addApplicationFont('font.ttf') if fontId != -1: families = QFontDatabase.applicationFontFamilies(fontId) if not families.empty(): self.setFont(QFont(families.at(0))) startUrl = QUrl() startProfile = '' messages = [] noAddons = False newInstance = False if len(argv) > 1: cmd = CommandLineOptions() for pair in cmd.getActions(): action = pair.action text = pair.text if action == const.CL_StartWithoutAddons: noAddons = True elif action == const.CL_StartWithProfile: startProfile = text elif action == const.CL_StartPortable: self._isPortable = True elif action == const.CL_NewTab: messages.append("ACTION:NewTab") self._postLaunchActions.append(self.OpenNewTab) elif action == const.CL_NewWindow: messages.append("ACTION:NewWindow") elif action == const.CL_ToggleFullScreen: messages.append("ACTION:ToggleFullScreen") self._postLaunchActions.append(self.ToggleFullScreen) elif action == const.CL_ShowDownloadManager: messages.append("ACTION:ShowDownloadManager") self._postLaunchActions.append(self.OpenDownloadManager) elif action == const.CL_StartPrivateBrowsing: self._isPrivate = True elif action == const.CL_StartNewInstance: newInstance = True elif action == const.CL_OpenUrlInCurrentTab: startUrl = QUrl.fromUserInput(text) messages.append("ACTION:OpenUrlInCurrentTab" + text) elif action == const.CL_OpenUrlInNewWindow: startUrl = QUrl.fromUserInput(text) messages.append("ACTION:OpenUrlInNewWindow" + text) elif action == const.CL_OpenUrl: startUrl = QUrl.fromUserInput(text) messages.append("URL:" + text) elif action == const.CL_ExitAction: self._isClosing = True return elif action == const.CL_WMClass: self._wmClass = text if not self.isPortable(): appConf = QSettings( pathjoin(self.applicationDirPath(), '%s.conf' % const.APPNAME), QSettings.IniFormat) appConf.value('Config/Portable') if self.isPortable(): print('%s: Running in Portable Mode.' % const.APPNAME) DataPaths.setPortableVersion() # Don't start single application in private browsing if not self.isPrivate(): appId = 'org.autowin.mc' if self.isPortable(): appId += '.Portable' if self.isTestModeEnabled(): appId += '.TestMode' if newInstance: if not startProfile or startProfile == 'default': print( 'New instance cannot be started with default profile!') else: # Generate unique appId so it is possible to start more # separate instances of the same profile. It is dangerous to # run more instance of the same profile, but if the user # wants it, we should allow it. appId += '.' + str(QDateTime.currentMSecsSinceEpoch()) self.setAppId(appId) # If there is nothing to tell other instance, we need to at least weak it if not messages: messages.append(' ') if self.isRunning(): self._isClosing = True for message in messages: self.sendMessage(message) return if const.OS_MACOS: self.setQuitOnLastWindowClosed(False) # TODO: # disable tabbing issue #2261 # extern void disableWindowTabbing(); # self.disableWindowTabbing() else: self.setQuitOnLastWindowClosed(True) QSettings.setDefaultFormat(QSettings.IniFormat) QDesktopServices.setUrlHandler('http', self.addNewTab) QDesktopServices.setUrlHandler('https', self.addNewTab) QDesktopServices.setUrlHandler('ftp', self.addNewTab) profileManager = ProfileManager() profileManager.initConfigDir() profileManager.initCurrentProfile(startProfile) Settings.createSettings( pathjoin(DataPaths.currentProfilePath(), 'settings.ini')) NetworkManager.registerSchemes() if self.isPrivate(): self._webProfile = QWebEngineProfile() else: self._webProfile = QWebEngineProfile.defaultProfile() self._webProfile.downloadRequested.connect(self.downloadRequested) self._networkManager = NetworkManager(self) self.setupUserScripts() if not self.isPrivate() and not self.isTestModeEnabled(): self._sessionManager = SessionManager(self) self._autoSaver = AutoSaver(self) self._autoSaver.save.connect( self._sessionManager.autoSaveLastSession) settings = Settings() settings.beginGroup('SessionRestore') wasRunning = settings.value('isRunning', False) wasRestoring = settings.value('isRestoring', False) settings.setValue('isRunning', True) settings.setValue('isRestoring', wasRunning) settings.endGroup() settings.sync() self._isStartingAfterCrash = bool(wasRunning and wasRestoring) if wasRunning: QTimer.singleShot( 60 * 1000, lambda: Settings().setValue( 'SessionRestore/isRestoring', False)) # we have to ask about startup session before creating main window if self._isStartingAfterCrash and self.afterLaunch( ) == self.SelectSession: self._restoreManager = RestoreManager( self.sessionManager().askSessionFromUser()) self.loadSettings() self._plugins = PluginProxy(self) self._autoFill = AutoFill(self) self.app.protocolHandlerManager() if not noAddons: self._plugins.loadPlugins() window = self.createWindow(const.BW_FirstAppWindow, startUrl) window.startingCompleted.connect(self.restoreOverrideCursor) self.focusChanged.connect(self.onFocusChanged) if not self.isPrivate() and not self.isTestModeEnabled(): # check updates settings = Settings() checkUpdates = settings.value('Web-Browser-Settings/CheckUpdates', True) if checkUpdates: Updater(window) self.sessionManager().backupSavedSessions() if self._isStartingAfterCrash or self.afterLaunch( ) == self.RestoreSession: self._restoreManager = RestoreManager( self.sessionManager().lastActiveSessionPath()) if not self._restoreManager.isValid(): self.destroyRestoreManager() if not self._isStartingAfterCrash and self._restoreManager: self.restoreSession(window, self._restoreManager.restoreData()) QSettings.setPath(QSettings.IniFormat, QSettings.UserScope, DataPaths.currentProfilePath()) self.messageReceived.connect(self.messageReceivedCb) self.aboutToQuit.connect(self.saveSettings) QTimer.singleShot(0, self.postLaunch) def __delete__(self): self._isClosing = True IconProvider.instance().saveIconsToDatabase() # Wait for all QtConcurrent jobs to finish QThreadPool.globalInstance().waitForDone() # Delete all classes that are saving data in destructor self._bookmarks = None self._cookieJar = None Settings.syncSettings() @cached_property def app(self): return MainApplication.instance() def isClosing(self): return self._isClosing def isPrivate(self): return self._isPrivate def isPortable(self): return self._isPortable def isStartingAfterCrash(self): return self._isStartingAfterCrash def windowCount(self): return len(self._windows) def windows(self): ''' @return: QList<BrowserWindow*> ''' return self._windows def getWindow(self): ''' @return: BrowserWindow ''' if self._lastActiveWindow: return self._lastActiveWindow if not self._windows: return None else: return self._windows[0] def createWindow(self, type_, startUrl=QUrl()): ''' @param: type_ const.BrowserWindowType @param: startUrl QUrl ''' window = BrowserWindow(type_, startUrl) def windowDestroyFunc(): self.windowDestroyed(window) window.destroyed.connect(windowDestroyFunc) self._windows.insert(0, window) return window def afterLaunch(self): return Settings().value('Web-URL-Settings/afterLaunch', self.RestoreSession, type=int) def openSession(self, window, restoreData): ''' @param: window BrowserWindow* @param: restoreData RestoreData ''' self.setOverrideCursor(Qt.BusyCursor) if not window: window = self.createWindow(const.BW_OtherRestoredWindow) if window.tabCount() != 0: # This can only happend when recovering crashed session! # Don't restore tabs in current window as user already opened some # new tabs window = self.createWindow(const.BW_OtherRestoredWindow) \ .restoreWindow(restoreData.windows.pop(0)) else: window.restoreWindow(restoreData.windows.pop(0)) # data -> BrowserWindow::SavedWindow for data in restoreData.windows: window = self.createWindow(const.BW_OtherRestoredWindow) window.restoreWindow(data) self._closedWindowsManager.restoreState(restoreData.closedWindows) self.restoreOverrideCursor() def restoreSession(self, window, restoreData): if self._isPrivate or not restoreData.isValid(): return False self.openSession(window, restoreData) self._restoreManager.clearRestoreData() self.destroyRestoreManager() return True def destroyRestoreManager(self): if self._restoreManager and self._restoreManager.isValid(): return True self._restoreManager = None def reloadSettings(self): self.loadSettings() self.settingsReloaded.emit() def styleName(self): if self._proxyStyle: return self._proxyStyle.name() else: return '' def setProxyStyle(self, style): ''' @param: style ProxyStyle ''' self._proxyStyle = style self.setStyle(style) def wmClass(self): return self._wmClass def history(self): if not self._history: self._history = History(self) return self._history def bookmarks(self): if not self._bookmarks: self._bookmarks = Bookmarks(self) return self._bookmarks def autoFill(self): return self._autoFill def cookieJar(self): if not self._cookieJar: self._cookieJar = CookieJar(self) return self._cookieJar def plugins(self): return self._plugins def browsingLibrary(self): if not self._browsingLibrary: self._browsingLibrary = BrowsingLibrary(self.getWindow()) return self._browsingLibrary def networkManager(self): return self._networkManager def restoreManager(self): return self._restoreManager def sessionManager(self): return self._sessionManager def downloadManager(self): if not self._downloadManager: self._downloadManager = DownloadManager() return self._downloadManager def userAgentManager(self): if not self._userAgentManager: self._userAgentManager = UserAgentManager() return self._userAgentManager def searchEnginesManager(self): if not self._searchEnginesManager: self._searchEnginesManager = SearchEnginesManager() return self._searchEnginesManager def closedWindowsManager(self): if not self._closedWindowsManager: self._closedWindowsManager = ClosedWindowsManager() return self._closedWindowsManager def protocolHandlerManager(self): if not self._protocolHandlerManager: self._protocolHandlerManager = ProtocolHandlerManager() return self._protocolHandlerManager def html5PermissionsManager(self): if not self._html5PermissionsManager: self._html5PermissionsManager = HTML5PermissionsManager(self) return self._html5PermissionsManager def desktopNotifications(self): if not self._desktopNotifications: self._desktopNotifications = DesktopNotificationsFactory(self) return self._desktopNotifications def webProfile(self): return self._webProfile def webSettings(self): return self._webProfile.settings() @classmethod def instance(cls): return QCoreApplication.instance() @classmethod def isTestModeEnabled(cls): return cls.s_testMode @classmethod def setTestModeEnabled(cls, enabled): cls.s_testMode = enabled # Q_SLOTS def addNewTab(self, url=QUrl()): window = self.getWindow() if window: window.tabWidget().addView( url, url.isEmpty() and const.NT_SelectedNewEmptyTab or const.NT_SelectedTabAtTheEnd) def startPrivateBrowsing(self, startUrl=QUrl()): url = startUrl act = self.sender() if isinstance(act, QAction): url = QUrl(act.data()) args = [const.MAIN_PATH] args.append('--private-browsing') args.append('--profile=%s' % ProfileManager.currentProfile()) if not url.isEmpty(): args.append(url.toEncoded().data().decode()) if not QProcess.startDetached(self.applicationFilePath(), args): print( 'MainApplication: Cannot start new browser process for private browsing!' ' %s %s' % (self.applicationFilePath(), args), file=stderr) def reloadUserStyleSheet(self): userCssFile = Settings().value('Web-Browser-Settings/userStyleSheet', '') self.setUserStyleSheet(userCssFile) def restoreOverrideCursor(self): super().restoreOverrideCursor() def changeOccurred(self): if self._autoSaver: self._autoSaver.changeOccurred() def quitApplication(self): if self._downloadManager and not self._downloadManager.canClose(): self._downloadManager.show() return for window in self._windows: window.aboutToClose.emit() if self._sessionManager and len(self._windows) > 0: self._sessionManager.autoSaveLastSession() self._isClosing = True for window in self._windows: window.close() # Saving settings in saveSettings() slot called from quit() so # everything gets saved also when quitting application in other # way than clicking Quit action in File menu or closing last window # eg. on Mac (#157) if not self.isPrivate(): self.removeLockFile() self.quit() # Q_SIGNALS settingsReloaded = pyqtSignal() activeWindowChanged = pyqtSignal(BrowserWindow) # private Q_SLOTS def postLaunch(self): if self.OpenDownloadManager in self._postLaunchActions: self.downloadManager().show() if self.OpenNewTab in self._postLaunchActions: self.getWindow().tabWidget().addView(QUrl(), const.NT_SelectedNewEmptyTab) if self.ToggleFullScreen in self._postLaunchActions: self.getWindow().toggleFullScreen() self._createJumpList() self._initPulseSupport() QTimer.singleShot(5000, self.runDeferredPostLaunchActions) def saveState(self): restoreData = RestoreData() for window in self._windows: restoreData.windows.append(BrowserWindow.SavedWindow(window)) if self._restoreManager and self._restoreManager.isValid(): stream = QDataStream(restoreData.crashedSession, QIODevice.WriteOnly) stream.writeQVariant(self._restoreManager.restoreData()) restoreData.closedWindows = self._closedWindowsManager.saveState() data = QByteArray() stream = QDataStream(data, QIODevice.WriteOnly) stream.writeInt(const.sessionVersion) stream.writeBytes(pickle.dumps(restoreData)) return data def saveSettings(self): if self.isPrivate(): return self._isClosing = True settings = Settings() settings.beginGroup('SessionRestore') settings.setValue('isRunning', False) settings.setValue('isRestoring', False) settings.endGroup() settings.beginGroup('Web-Browser-Settings') deleteCache = settings.value('deleteCacheOnClose', False) deleteHistory = settings.value('deleteHistoryOnClose', False) deleteHtml5Storage = settings.value('deleteHTML5StorageOnClose', False) settings.endGroup() settings.beginGroup('Cookies-Settings') deleteCookies = settings.value('deleteCookiesOnClose', False) settings.endGroup() settings.sync() del settings if deleteHistory: self._history.clearHistory() if deleteHtml5Storage: ClearPrivateData.clearLocalStorage() if deleteCookies: self._cookieJar.deleteAllCookies(False) if deleteCache: gVar.appTools.removeRecursively(self.app.webProfile().cachePath()) if self._searchEnginesManager: self._searchEnginesManager.saveSettings() self._plugins.shutdown() self._networkManager.shutdown() gVar.appSettings.saveSettings() webpageIconsPath = pathjoin(DataPaths.currentProfilePath(), 'webpageIcons.db') if pathexists(webpageIconsPath): remove(webpageIconsPath) self.sessionManager().saveSettings() def messageReceivedCb(self, message): ''' @param: message string ''' actWin = self.getWindow() actUrl = QUrl() if message.startswith('URL:'): url = QUrl.fromUserInput(message[4:]) self.addNewTab(url) actWin = self.getWindow() elif message.startswith('ACTION:'): text = message[7:] if text == 'NewTab': self.addNewTab() elif text == 'NewWindow': actWin = self.createWindow(const.BW_NewWindow) elif text == 'ShowDownloadManager': self.downloadManager().show() actWin = self.downloadManager() elif text == 'ToggleFullScreen' and actWin: assert (isinstance(actWin, BrowserWindow)) actWin.toggleFullScreen() elif text.startswith('OpenUrlInCurrentTab'): actUrl = QUrl.fromUserInput(text[:19]) elif text.startswith('OpenUrlInNewTab'): # user attempted to start another instance. let's open a new one self.createWindow(const.BW_NewWindow, QUrl.fromUserInput(text[18:])) return else: actWin = self.createWindow(const.BW_NewWindow) if not actWin: if not self.isClosing(): # It can only occur if download manager window was still opened self.createWindow(const.BW_NewWindow, actUrl) return actWin.setWindowState(actWin.windowState() & Qt.WindowMinimized) actWin.raise_() actWin.activateWindow() actWin.setFocus() win = actWin if isinstance(win, BrowserWindow) and not actWin.isEmpty(): win.loadAddress(actUrl) def windowDestroyed(self, window): ''' @param: message QObject* ''' assert (window) assert (window in self._windows) self._windows.remove(window) def onFocusChanged(self): activeBrowserWindow = self.activeWindow() if isinstance(activeBrowserWindow, BrowserWindow): self._lastActiveWindow = activeBrowserWindow self.activeWindowChanged.emit(self._lastActiveWindow) def runDeferredPostLaunchActions(self): self.checkDefaultWebBrowser() self.checkOptimizeDatabase() def downloadRequested(self, download): ''' @param: download QWebEngineDownloadItem ''' self.downloadManager().download(download) # private # enum PostLaunchAction OpenDownloadManager = 0 OpenNewTab = 1 ToggleFullScreen = 2 def loadSettings(self): settings = Settings() settings.beginGroup('Themes') activeTheme = settings.value('activeTheme', const.DEFAULT_THEME_NAME) settings.endGroup() self.loadTheme(activeTheme) webSettings = self._webProfile.settings() # Web browsing settings settings.beginGroup('Web-Browser-Settings') webSettings.setAttribute(QWebEngineSettings.LocalStorageEnabled, settings.value("HTML5StorageEnabled", True)) webSettings.setAttribute(QWebEngineSettings.PluginsEnabled, settings.value("allowPlugins", True)) webSettings.setAttribute(QWebEngineSettings.JavascriptEnabled, settings.value("allowJavaScript", True)) webSettings.setAttribute( QWebEngineSettings.JavascriptCanOpenWindows, settings.value("allowJavaScriptOpenWindow", False)) webSettings.setAttribute( QWebEngineSettings.JavascriptCanAccessClipboard, settings.value("allowJavaScriptAccessClipboard", True)) webSettings.setAttribute( QWebEngineSettings.LinksIncludedInFocusChain, settings.value("IncludeLinkInFocusChain", False)) webSettings.setAttribute(QWebEngineSettings.XSSAuditingEnabled, settings.value("XSSAuditing", False)) webSettings.setAttribute( QWebEngineSettings.PrintElementBackgrounds, settings.value("PrintElementBackground", True)) webSettings.setAttribute(QWebEngineSettings.SpatialNavigationEnabled, settings.value("SpatialNavigation", False)) webSettings.setAttribute(QWebEngineSettings.ScrollAnimatorEnabled, settings.value("AnimateScrolling", True)) webSettings.setAttribute(QWebEngineSettings.HyperlinkAuditingEnabled, False) webSettings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled, True) webSettings.setAttribute( QWebEngineSettings.LocalContentCanAccessRemoteUrls, True) webSettings.setAttribute(QWebEngineSettings.FocusOnNavigationEnabled, False) webSettings.setAttribute( QWebEngineSettings.AllowWindowActivationFromJavaScript, settings.value("allowJavaScriptActivationWindow", False)) webSettings.setAttribute(QWebEngineSettings.JavascriptCanPaste, settings.value("allowJavaScriptPaste", True)) webSettings.setAttribute( QWebEngineSettings.PlaybackRequiresUserGesture, settings.value("DisableVideoAutoPlay", False)) webSettings.setAttribute(QWebEngineSettings.WebRTCPublicInterfacesOnly, settings.value("WebRTCPublicIpOnly", True)) webSettings.setUnknownUrlSchemePolicy( QWebEngineSettings.AllowAllUnknownUrlSchemes) webSettings.setAttribute(QWebEngineSettings.DnsPrefetchEnabled, settings.value("DNSPrefetch", True)) webSettings.setDefaultTextEncoding( settings.value("DefaultEncoding", webSettings.defaultTextEncoding(), type=str)) scrollLines = settings.value("wheelScrollLines", self.wheelScrollLines()) self.setWheelScrollLines(scrollLines) userCss = settings.value("userStyleSheet", '') settings.endGroup() self.setUserStyleSheet(userCss) settings.beginGroup("Browser-Fonts") webSettings.setFontFamily( QWebEngineSettings.StandardFont, settings.value("StandardFont", webSettings.fontFamily( QWebEngineSettings.StandardFont), type=str)) webSettings.setFontFamily( QWebEngineSettings.CursiveFont, settings.value("CursiveFont", webSettings.fontFamily( QWebEngineSettings.CursiveFont), type=str)) webSettings.setFontFamily( QWebEngineSettings.FantasyFont, settings.value("FantasyFont", webSettings.fontFamily( QWebEngineSettings.FantasyFont), type=str)) webSettings.setFontFamily( QWebEngineSettings.FixedFont, settings.value("FixedFont", webSettings.fontFamily( QWebEngineSettings.FixedFont), type=str)) webSettings.setFontFamily( QWebEngineSettings.SansSerifFont, settings.value("SansSerifFont", webSettings.fontFamily( QWebEngineSettings.SansSerifFont), type=str)) webSettings.setFontFamily( QWebEngineSettings.SerifFont, settings.value("SerifFont", webSettings.fontFamily( QWebEngineSettings.SerifFont), type=str)) webSettings.setFontSize(QWebEngineSettings.DefaultFontSize, settings.value("DefaultFontSize", 15)) webSettings.setFontSize(QWebEngineSettings.DefaultFixedFontSize, settings.value("FixedFontSize", 14)) webSettings.setFontSize(QWebEngineSettings.MinimumFontSize, settings.value("MinimumFontSize", 3)) webSettings.setFontSize(QWebEngineSettings.MinimumLogicalFontSize, settings.value("MinimumLogicalFontSize", 5)) settings.endGroup() profile = QWebEngineProfile.defaultProfile() profile.setPersistentCookiesPolicy( QWebEngineProfile.AllowPersistentCookies) profile.setPersistentStoragePath(DataPaths.currentProfilePath()) defaultPath = DataPaths.path(DataPaths.Cache) if not defaultPath.startswith(DataPaths.currentProfilePath()): defaultPath += '/' + ProfileManager.currentProfile() cachePath = settings.value("Web-Browser-Settings/CachePath", defaultPath, type=str) profile.setCachePath(cachePath) allowCache = settings.value("Web-Browser-Settings/AllowLocalCache", True) profile.setHttpCacheType(allowCache and QWebEngineProfile.DiskHttpCache or QWebEngineProfile.MemoryHttpCache) cacheSize = settings.value("Web-Browser-Settings/LocalCacheSize", 50) * 1000 * 1000 profile.setHttpCacheMaximumSize(cacheSize) settings.beginGroup("SpellCheck") profile.setSpellCheckEnabled(settings.value("Enabled", False)) profile.setSpellCheckLanguages(settings.value("Languages", type=list)) settings.endGroup() if self.isPrivate(): webSettings.setAttribute(QWebEngineSettings.LocalStorageEnabled, False) self.history().setSaving(False) if self._downloadManager: self._downloadManager.loadSettings() gVar.appSettings.loadSettings() self.userAgentManager().loadSettings() self.networkManager().loadSettings() def loadTheme(self, name): activeThemePath = DataPaths.locate(DataPaths.Themes, name) if not activeThemePath: print('Warning: Cannot load theme %s' % name) activeThemePath = '%s/%s' % (DataPaths.path( DataPaths.Themes), const.DEFAULT_THEME_NAME) qss = gVar.appTools.readAllFileContents(activeThemePath + '/main.css') if const.OS_MACOS: qss += gVar.appTools.readAllFileContents(activeThemePath + '/mac.css') elif const.OS_UNIX: qss += gVar.appTools.readAllFileContents(activeThemePath + '/linux.css') elif const.OS_WIN: qss += gVar.appTools.readAllFileContents(activeThemePath + '/windows.css') if self.isRightToLeft(): qss += gVar.appTools.readAllFileContents(activeThemePath + 'rtl.css') if self.isPrivate(): qss += gVar.appTools.readAllFileContents(activeThemePath + 'private.css') qss += gVar.appTools.readAllFileContents(activeThemePath + 'userChrome.css') relativePath = QDir.current().relativeFilePath(activeThemePath) qss = re.sub("url\\s*\\(\\s*([^\\*:\\);]+)\\s*\\)", r'url(' + relativePath + r'/\1)', qss) self.setStyleSheet(qss) def setupUserScripts(self): # WebChannel for SafeJsWorld script = QWebEngineScript() script.setName('_app_webchannel') script.setInjectionPoint(QWebEngineScript.DocumentCreation) script.setWorldId(WebPage.SafeJsWorld) script.setRunsOnSubFrames(True) script.setSourceCode(Scripts.setupWebChannel()) self._webProfile.scripts().insert(script) # app:restore appRestore = QWebEngineScript() appRestore.setWorldId(WebPage.SafeJsWorld) appRestore.setSourceCode( gVar.appTools.readAllFileContents(':html/restore.user.js')) self._webProfile.scripts().insert(appRestore) # app:speeddial appSpeedDial = QWebEngineScript() appSpeedDial.setWorldId(WebPage.SafeJsWorld) appSpeedDial.setSourceCode(Scripts.setupSpeedDial()) self._webProfile.scripts().insert(appSpeedDial) # document.window object addons documentWindowAddons = QWebEngineScript() documentWindowAddons.setName('_app_window_object') documentWindowAddons.setInjectionPoint( QWebEngineScript.DocumentCreation) documentWindowAddons.setWorldId(WebPage.UnsafeJsWorld) documentWindowAddons.setRunsOnSubFrames(True) documentWindowAddons.setSourceCode(Scripts.setupWindowObject()) self._webProfile.scripts().insert(documentWindowAddons) def setUserStyleSheet(self, filePath): userCss = '' if not const.OS_UNIX and not const.OS_MACOS: # Don't grey out selection on losing focus (to prevent graying out # found text) highlightColor = '' highlightedTextColor = '' if const.OS_MACOS: # TODO: ? can not enter this branch highlightColor = '#b6d6fc' highlightedTextColor = '#000' else: pal = self.style().standardPalette() highlightColor = pal.color(QPalette.Highlight).name() highlightedTextColor = pal.color( QPalette.HighlightedText).name() userCss += "::selection {background: %s; color: %s;} " % \ (highlightColor, highlightedTextColor) userCss += gVar.appTools.readAllFileContents(filePath).replace( '\n', '') name = '_app_userstylesheet' oldScript = self._webProfile.scripts().findScript(name) if not oldScript.isNull(): self._webProfile.scripts().remove(oldScript) if not userCss: return script = QWebEngineScript() script.setName(name) script.setInjectionPoint(QWebEngineScript.DocumentReady) script.setWorldId(WebPage.SafeJsWorld) script.setRunsOnSubFrames(True) script.setSourceCode(Scripts.setCss(userCss)) self._webProfile.scripts().insert(script) def checkDefaultWebBrowser(self): pass def checkOptimizeDatabase(self): pass # private: def _createJumpList(self): pass def _initPulseSupport(self): pass environ["PULSE_PROP_OVERRIDE_application.name"] = "App" environ["PULSE_PROP_OVERRIDE_application.icon_name"] = "app" environ["PULSE_PROP_OVERRIDE_media.icon_name"] = "app"