Example #1
0
def _chromium_version():
    """Get the Chromium version for QtWebEngine."""
    if QWebEngineProfile is None:
        # This should never happen
        return 'unavailable'
    profile = QWebEngineProfile()
    ua = profile.httpUserAgent()
    match = re.search(r' Chrome/([^ ]*) ', ua)
    if not match:
        log.misc.error("Could not get Chromium version from: {}".format(ua))
        return 'unknown'
    return match.group(1)
Example #2
0
 def getProfile(self):
     profile=QWebEngineProfile("myProfile")
     profile.cachePath="/home/yyk/Desktop/cache"
     jsFile = constants.QTWEBCHANNELJS_FILE
     with open(jsFile, encoding="UTF-8") as file:
         js = file.read()
     script = QWebEngineScript();
     script.setSourceCode(js)
     script.setName('qwebchannel.js')
     script.setInjectionPoint(QWebEngineScript.DocumentCreation)
     script.setWorldId(QWebEngineScript.MainWorld)
     script.setRunsOnSubFrames(False)
     profile.scripts().insert(script)
     return profile
Example #3
0
def _init_profiles():
    """Init the two used QWebEngineProfiles."""
    global default_profile, private_profile
    default_profile = QWebEngineProfile.defaultProfile()
    default_profile.setCachePath(
        os.path.join(standarddir.cache(), 'webengine'))
    default_profile.setPersistentStoragePath(
        os.path.join(standarddir.data(), 'webengine'))
    _init_stylesheet(default_profile)
    _set_user_agent(default_profile)

    private_profile = QWebEngineProfile()
    assert private_profile.isOffTheRecord()
    _init_stylesheet(private_profile)
    _set_user_agent(private_profile)
Example #4
0
def _chromium_version():
    """Get the Chromium version for QtWebEngine.

    This can also be checked by looking at this file with the right Qt tag:
    http://code.qt.io/cgit/qt/qtwebengine.git/tree/tools/scripts/version_resolver.py#n41

    Quick reference:

    Qt 5.7:  Chromium 49
             49.0.2623.111 (2016-03-31)
             5.7.1: Security fixes up to 54.0.2840.87 (2016-11-01)

    Qt 5.8:  Chromium 53
             53.0.2785.148 (2016-08-31)
             5.8.0: Security fixes up to 55.0.2883.75 (2016-12-01)

    Qt 5.9:  Chromium 56
    (LTS)    56.0.2924.122 (2017-01-25)
             5.9.7: Security fixes up to 69.0.3497.113 (2018-09-27)

    Qt 5.10: Chromium 61
             61.0.3163.140 (2017-09-05)
             5.10.1: Security fixes up to 64.0.3282.140 (2018-02-01)

    Qt 5.11: Chromium 65
             65.0.3325.151 (.1: .230) (2018-03-06)
             5.11.3: Security fixes up to 70.0.3538.102 (2018-11-09)

    Qt 5.12: Chromium 69
    (LTS)    69.0.3497.113 (2018-09-27)
             5.12.1: Security fixes up to 71.0.3578.94 (2018-12-14)
             5.12.2: Security fixes up to 72.0.3626.96 (2019-02-06)

    Qt 5.13: (in development) Chromium 71 merged, 73 in review.

    Also see https://www.chromium.org/developers/calendar
    and https://chromereleases.googleblog.com/
    """
    if QWebEngineProfile is None:
        # This should never happen
        return 'unavailable'
    profile = QWebEngineProfile()
    ua = profile.httpUserAgent()
    match = re.search(r' Chrome/([^ ]*) ', ua)
    if not match:
        log.misc.error("Could not get Chromium version from: {}".format(ua))
        return 'unknown'
    return match.group(1)
Example #5
0
 def _set(self, value, settings=None):
     utils.unused(settings)
     setter = getattr(QWebEngineProfile.defaultProfile(), self._setter)
     setter(
         QWebEngineProfile.AllowPersistentCookies if value else
         QWebEngineProfile.NoPersistentCookies
     )
Example #6
0
def init():
    """Initialize QtWebEngine-specific modules."""
    log.init.debug("Initializing request interceptor...")
    host_blocker = objreg.get('host-blocker')
    req_interceptor = interceptor.RequestInterceptor(
        host_blocker, parent=QApplication.instance())
    req_interceptor.install(QWebEngineProfile.defaultProfile())
def _init_profiles():
    """Init the two used QWebEngineProfiles."""
    global default_profile, private_profile

    default_profile = QWebEngineProfile.defaultProfile()
    default_profile.setter = ProfileSetter(default_profile)
    default_profile.setCachePath(
        os.path.join(standarddir.cache(), 'webengine'))
    default_profile.setPersistentStoragePath(
        os.path.join(standarddir.data(), 'webengine'))
    default_profile.setter.init_profile()
    default_profile.setter.set_persistent_cookie_policy()

    private_profile = QWebEngineProfile()
    private_profile.setter = ProfileSetter(private_profile)
    assert private_profile.isOffTheRecord()
    private_profile.setter.init_profile()
Example #8
0
 def _set(self, value, settings=None):
     if settings is not None:
         raise ValueError("'settings' may not be set with "
                          "PersistentCookiePolicy!")
     setter = getattr(QWebEngineProfile.defaultProfile(), self._setter)
     setter(
         QWebEngineProfile.AllowPersistentCookies if value else
         QWebEngineProfile.NoPersistentCookies
     )
Example #9
0
def _init_profiles():
    """Init the two used QWebEngineProfiles."""
    global default_profile, private_profile
    default_profile = QWebEngineProfile.defaultProfile()
    default_profile.setCachePath(
        os.path.join(standarddir.cache(), 'webengine'))
    default_profile.setPersistentStoragePath(
        os.path.join(standarddir.data(), 'webengine'))
    _init_stylesheet(default_profile)
    _set_http_headers(default_profile)

    private_profile = QWebEngineProfile()
    assert private_profile.isOffTheRecord()
    _init_stylesheet(private_profile)
    _set_http_headers(private_profile)

    if qtutils.version_check('5.8'):
        default_profile.setSpellCheckEnabled(True)
        private_profile.setSpellCheckEnabled(True)
def init(args):
    """Initialize the global QWebSettings."""
    if args.enable_webengine_inspector:
        os.environ['QTWEBENGINE_REMOTE_DEBUGGING'] = str(utils.random_port())

    profile = QWebEngineProfile.defaultProfile()
    profile.setCachePath(os.path.join(standarddir.cache(), 'webengine'))
    profile.setPersistentStoragePath(
        os.path.join(standarddir.data(), 'webengine'))
    _init_stylesheet(profile)

    websettings.init_mappings(MAPPINGS)
    objreg.get('config').changed.connect(update_settings)
Example #11
0
def _chromium_version():
    """Get the Chromium version for QtWebEngine.

    This can also be checked by looking at this file with the right Qt tag:
    https://github.com/qt/qtwebengine/blob/dev/tools/scripts/version_resolver.py#L41

    Quick reference:
    Qt 5.7:  Chromium 49
    Qt 5.8:  Chromium 53
    Qt 5.9:  Chromium 56
    Qt 5.10: Chromium 61
    Qt 5.11: Chromium 63
    Qt 5.12: Chromium 65 (?)
    """
    if QWebEngineProfile is None:
        # This should never happen
        return 'unavailable'
    profile = QWebEngineProfile()
    ua = profile.httpUserAgent()
    match = re.search(r' Chrome/([^ ]*) ', ua)
    if not match:
        log.misc.error("Could not get Chromium version from: {}".format(ua))
        return 'unknown'
    return match.group(1)
Example #12
0
def init():
    """Initialize QtWebEngine-specific modules."""
    # For some reason we need to keep a reference, otherwise the scheme handler
    # won't work...
    # https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html
    global _qute_scheme_handler
    app = QApplication.instance()
    profile = QWebEngineProfile.defaultProfile()

    log.init.debug("Initializing qute:* handler...")
    _qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
    _qute_scheme_handler.install(profile)

    log.init.debug("Initializing request interceptor...")
    host_blocker = objreg.get('host-blocker')
    req_interceptor = interceptor.RequestInterceptor(
        host_blocker, parent=app)
    req_interceptor.install(profile)
Example #13
0
def testdata_scheme(qapp):
    try:
        global _qute_scheme_handler
        from qutebrowser.browser.webengine import webenginequtescheme
        from PyQt5.QtWebEngineWidgets import QWebEngineProfile
        _qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(
            parent=qapp)
        _qute_scheme_handler.install(QWebEngineProfile.defaultProfile())
    except ImportError:
        pass

    @qutescheme.add_handler('testdata')
    def handler(url):  # pylint: disable=unused-variable
        file_abs = os.path.abspath(os.path.dirname(__file__))
        filename = os.path.join(file_abs, os.pardir, 'end2end',
                                url.path().lstrip('/'))
        with open(filename, 'rb') as f:
            data = f.read()

        mimetype, _encoding = mimetypes.guess_type(filename)
        return mimetype, data
Example #14
0
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
Example #15
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.DomainCookies = {}

        self.setWindowTitle('微信读书助手')  # 设置窗口标题
        self.resize(900, 600)  # 设置窗口大小
        self.setWindowFlags(Qt.WindowMinimizeButtonHint)  # 禁止最大化按钮
        self.setFixedSize(self.width(), self.height())  # 禁止调整窗口大小

        url = 'https://weread.qq.com/#login'  # 目标地址
        self.browser = QWebEngineView()  # 实例化浏览器对象

        self.profile = QWebEngineProfile.defaultProfile()
        self.profile.cookieStore().deleteAllCookies()  # 初次运行软件时删除所有cookies
        self.profile.cookieStore().cookieAdded.connect(
            self.onCookieAdd)  # cookies增加时触发self.onCookieAdd()函数

        self.browser.loadFinished.connect(
            self.onLoadFinished)  # 网页加载完毕时触发self.onLoadFinished()函数

        self.browser.load(QUrl(url))  # 加载网页
        self.setCentralWidget(self.browser)  # 设置中心窗口
Example #16
0
    def __init__(self, uri: str, required_cookies: List[str], parent=None):
        """
        此工具类用于 QtWebEngine 自动化 Cookie 登录过程
        Example: QtWebEngine('https://y.qq.com', ['qqmusic_key'])

        :param uri: 初始化登录地址 获取到的 Cookie 也会按照此地址筛选
        :rtype uri: str
        :param required_cookies: 必需包含的 Cookie key 当全部获取到将发送 succeed 信号并自动关闭
        :type required_cookies: List[str]
        :param parent:
        """
        super().__init__(parent)
        self.set_pos()
        self.init_uri = uri
        profile = QWebEngineProfile.defaultProfile()
        cookie_store: QWebEngineCookieStore = profile.cookieStore()
        cookie_store.deleteAllCookies()
        cookie_store.cookieAdded.connect(self.cookie_added)
        cookie_store.cookieRemoved.connect(self.cookie_removed)
        self.saved_cookies = dict()
        self.required_cookies = required_cookies
        self.setPage(NoOutputWebPage(self))
        self.load(QUrl(uri))
Example #17
0
def init():
    """Initialize QtWebEngine-specific modules."""
    # For some reason we need to keep a reference, otherwise the scheme handler
    # won't work...
    # https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html
    global _qute_scheme_handler
    app = QApplication.instance()
    profile = QWebEngineProfile.defaultProfile()

    log.init.debug("Initializing qute:* handler...")
    _qute_scheme_handler = webenginequtescheme.QuteSchemeHandler(parent=app)
    _qute_scheme_handler.install(profile)

    log.init.debug("Initializing request interceptor...")
    host_blocker = objreg.get('host-blocker')
    req_interceptor = interceptor.RequestInterceptor(
        host_blocker, parent=app)
    req_interceptor.install(profile)

    log.init.debug("Initializing QtWebEngine downloads...")
    download_manager = webenginedownloads.DownloadManager(parent=app)
    download_manager.install(profile)
    objreg.register('webengine-download-manager', download_manager)
Example #18
0
    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)
Example #19
0
    def __init__(self, *args, **kwargs):
        # Strip out arguments we handle that are different from QMainWindow:
        if 'width' in kwargs:
            self.width = kwargs['width']
            del kwargs['width']
        else:
            self.width = 1024
        if 'height' in kwargs:
            self.height = kwargs['height']
            del kwargs['height']
        else:
            # Short enough to fit in XGA, 768 height:
            self.height = 735

        # Then run the default constructor.
        super(BrowserWindow, self).__init__(*args, **kwargs)

        self.browserviews = []

        self.profile = QWebEngineProfile()
        # print("Profile initially off the record?",
        #       self.profile.isOffTheRecord())

        self.init_tab_name_len = 40

        self.init_chrome()

        # Resize to fit on an XGA screen, allowing for window chrome.
        # XXX Should check the screen size and see if it can be bigger.
        self.resize(self.width, self.height)

        # Set up the listener for remote commands, the filename
        # and the buffer where we'll store those commands:
        self.cmdsockname = None
        self.cmdread = b''
        self.set_up_listener()
def _init_default_profile():
    """Init the default QWebEngineProfile."""
    global default_profile

    default_profile = QWebEngineProfile.defaultProfile()

    assert parsed_user_agent is None  # avoid earlier profile initialization
    non_ua_version = version.qtwebengine_versions(avoid_init=True)

    init_user_agent()
    ua_version = version.qtwebengine_versions()
    if ua_version.webengine != non_ua_version.webengine:
        log.init.warning(
            "QtWebEngine version mismatch - unexpected behavior might occur, "
            "please open a bug about this.\n"
            f"  Early version: {non_ua_version}\n"
            f"  Real version:  {ua_version}")

    default_profile.setCachePath(
        os.path.join(standarddir.cache(), 'webengine'))
    default_profile.setPersistentStoragePath(
        os.path.join(standarddir.data(), 'webengine'))

    _init_profile(default_profile)
Example #21
0
def _init_profiles():
    """Init the two used QWebEngineProfiles."""
    global default_profile, private_profile
    default_profile = QWebEngineProfile.defaultProfile()
    default_profile.setCachePath(os.path.join(standarddir.cache(),
                                              'webengine'))
    default_profile.setPersistentStoragePath(
        os.path.join(standarddir.data(), 'webengine'))
    _init_stylesheet(default_profile)
    _set_http_headers(default_profile)

    private_profile = QWebEngineProfile()
    assert private_profile.isOffTheRecord()
    _init_stylesheet(private_profile)
    _set_http_headers(private_profile)

    if qtutils.version_check('5.8'):
        default_profile.setSpellCheckEnabled(True)
        private_profile.setSpellCheckEnabled(True)
Example #22
0
def create_profile():
    ans = getattr(create_profile, 'ans', None)
    if ans is None:
        ans = QWebEngineProfile(QApplication.instance())
        osname = 'windows' if iswindows else ('macos' if isosx 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)
        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
Example #23
0
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
class BrowserBuffer(Buffer):

    close_page = QtCore.pyqtSignal(str)
    get_focus_text = QtCore.pyqtSignal(str, str)
    open_dev_tools_tab = QtCore.pyqtSignal(object)

    def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict,
                 module_path, fit_to_view):
        Buffer.__init__(self, buffer_id, url, arguments, emacs_var_dict,
                        module_path, fit_to_view)

        self.add_widget(BrowserView(config_dir))

        self.config_dir = config_dir

        self.history_list = []
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true":
            self.history_log_file_path = os.path.join(self.config_dir,
                                                      "browser", "history",
                                                      "log.txt")

            self.history_pattern = re.compile("^(.+)ᛝ(.+)ᛡ(.+)$")
            self.noprefix_url_pattern = re.compile("^(https?|file)://(.+)")
            self.nopostfix_url_pattern = re.compile("^[^#\?]*")
            self.history_close_file_path = os.path.join(
                self.config_dir, "browser", "history", "close.txt")
            touch(self.history_log_file_path)
            with open(self.history_log_file_path, "r") as f:
                raw_list = f.readlines()
                for raw_his in raw_list:
                    his_line = re.match(self.history_pattern, raw_his)
                    if his_line is None:  # Obsolete Old history format
                        old_his = re.match("(.*)\s((https?|file):[^\s]+)$",
                                           raw_his)
                        if old_his is not None:
                            self.history_list.append(
                                HistoryPage(old_his.group(1), old_his.group(2),
                                            1))
                    else:
                        self.history_list.append(
                            HistoryPage(his_line.group(1), his_line.group(2),
                                        his_line.group(3)))

        # Set User Agent with Firefox's one to make EAF browser can login in Google account.
        self.pc_user_agent = "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/72.0"
        self.phone_user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1"
        self.profile = QWebEngineProfile(self.buffer_widget)
        self.profile.defaultProfile().setHttpUserAgent(self.pc_user_agent)

        self.draw_progressbar = False
        self.eval_dark_js = False
        self.progressbar_progress = 0
        self.progressbar_color = QColor(233, 129, 35, 255)
        self.progressbar_height = 2
        self.light_mode_mask_color = QColor("#FFFFFF")
        self.dark_mode_mask_color = QColor("#242525")

        self.current_url = ""
        self.request_url = ""
        self.no_need_draw_background = False

        self.init_background_color()

        self.buffer_widget.loadStarted.connect(self.start_progress)
        self.buffer_widget.loadProgress.connect(self.update_progress)
        self.buffer_widget.urlChanged.connect(self.record_url)
        self.buffer_widget.web_page.windowCloseRequested.connect(
            self.close_buffer)
        self.buffer_widget.web_page.fullScreenRequested.connect(
            self.handle_fullscreen_request)
        self.buffer_widget.web_page.pdfPrintingFinished.connect(
            self.notify_print_message)
        self.profile.defaultProfile().downloadRequested.connect(
            self.handle_download_request)

        settings = QWebEngineSettings.globalSettings()
        try:
            settings.setAttribute(
                QWebEngineSettings.PluginsEnabled,
                self.emacs_var_dict["eaf-browser-enable-plugin"] == "true")
            settings.setAttribute(
                QWebEngineSettings.JavascriptEnabled,
                self.emacs_var_dict["eaf-browser-enable-javascript"] == "true")
            settings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled,
                                  True)
            settings.setAttribute(
                QWebEngineSettings.PlaybackRequiresUserGesture, False)
            settings.setAttribute(QWebEngineSettings.DnsPrefetchEnabled, True)
        except Exception:
            pass

        for method_name in [
                "search_text_forward", "search_text_backward", "zoom_out",
                "zoom_in", "zoom_reset", "scroll_left", "scroll_right",
                "scroll_up", "scroll_down", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "refresh_page", "undo_action", "redo_action", "get_url",
                "exit_fullscreen", "set_focus_text", "clear_focus",
                "dark_mode", "view_source"
        ]:
            self.build_widget_method(method_name)

        self.build_widget_method("history_backward", "back")
        self.build_widget_method("history_forward", "forward")
        self.build_widget_method("action_quit", "search_quit")
        self.build_widget_method("yank_text", "yank_text", "Yank text.")
        self.build_widget_method("kill_text", "kill_text", "Kill text.")

        for method_name in [
                "recover_prev_close_page", "scroll_up", "scroll_down",
                "scroll_left", "scroll_right", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "open_link", "open_link_new_buffer",
                "open_link_background_buffer", "copy_link", "history_backward",
                "history_forward", "new_blank_page",
                "open_download_manage_page", "refresh_page", "zoom_in",
                "zoom_out", "zoom_reset", "save_as_bookmark", "edit_url",
                "download_youtube_video", "download_youtube_audio",
                "toggle_device", "close_buffer", "save_as_pdf", "view_source",
                "save_as_single_file", "select_left_tab", "select_right_tab",
                "copy_code"
        ]:
            self.build_insert_or_do(method_name)

    def notify_print_message(self, file_path, success):
        if success:
            # Try to rename pdf file with title.
            # Use host name if title include invalid file char.
            title_path = os.path.join(
                os.path.expanduser(
                    self.emacs_var_dict["eaf-browser-download-path"]),
                "{}.pdf".format(self.title))
            try:
                os.rename(file_path, title_path)
                self.message_to_emacs.emit(
                    "Successfully saved current webpage as '{}'.".format(
                        title_path))
            except Exception:
                self.message_to_emacs.emit(
                    "Successfully saved current webpage as '{}'.".format(
                        file_path))
        else:
            self.message_to_emacs.emit(
                "Failed to save current webpage as '{}'.".format(file_path))

    def notify_monolith_message(self, download_path, file_path, title,
                                retcode):
        if retcode == 0:
            title_path = os.path.join(os.path.expanduser(download_path),
                                      "{}.html".format(title))
            try:
                os.rename(file_path, title_path)
                self.message_to_emacs.emit(
                    "Successfully saved current webpage as '{}'.".format(
                        title_path))
            except Exception:
                self.message_to_emacs.emit(
                    "Successfully saved current webpage as '{}'.".format(
                        file_path))
        else:
            self.message_to_emacs.emit(
                "Failed to save current page as single file.")

    def record_url(self, url):
        self.request_url = url.toString()

        # Emacs-china forum thread don't need draw background that avoid flash.
        if self.dark_mode_is_enable():
            current_urls = self.current_url.rsplit("/", 1)
            request_urls = self.request_url.rsplit("/", 1)

            if self.request_url == "https://emacs-china.org/":
                self.no_need_draw_background = False
            if self.current_url.startswith("https://emacs-china.org/t/"
                                           ) and self.request_url.startswith(
                                               "https://emacs-china.org/t/"):
                self.no_need_draw_background = current_urls[0] == request_urls[
                    0] or self.request_url == current_urls[0]
            elif self.current_url.startswith(
                    "https://livebook.manning.com/book/"
            ) and self.request_url.startswith(
                    "https://livebook.manning.com/book/"):
                self.no_need_draw_background = current_urls[0] == request_urls[
                    0]
            elif self.current_url.startswith("https://web.telegram.org"
                                             ) and self.request_url.startswith(
                                                 "https://web.telegram.org"):
                self.no_need_draw_background = True

    def dark_mode_is_enable(self):
        module_name = self.module_path.split(".")[1]
        return (self.emacs_var_dict["eaf-browser-dark-mode"] == "true" or \
                (self.emacs_var_dict["eaf-browser-dark-mode"] == "" and self.emacs_var_dict["eaf-emacs-theme-mode"] == "dark")) \
                and module_name in ["browser", "terminal", "mindmap", "js-video-player"] \
                and self.url != "devtools://devtools/bundled/devtools_app.html"

    def init_background_color(self):
        if self.dark_mode_is_enable():
            self.buffer_widget.web_page.setBackgroundColor(
                self.dark_mode_mask_color)
        else:
            self.buffer_widget.web_page.setBackgroundColor(
                self.light_mode_mask_color)

    def drawForeground(self, painter, rect):
        if self.draw_progressbar:
            # Draw foreground over web page avoid white flash when eval dark_mode_js
            if self.dark_mode_is_enable() and not self.no_need_draw_background:
                painter.setBrush(self.dark_mode_mask_color)
                painter.drawRect(0, 0, rect.width(), rect.height())

            # Init progress bar brush.
            painter.setBrush(self.progressbar_color)

            if self.eval_dark_js:
                # Draw 100% when after eval dark_mode_js, avoid flash progressbar.
                painter.drawRect(0, 0, rect.width(), self.progressbar_height)
            else:
                # Draw progress bar.
                painter.drawRect(
                    0, 0,
                    rect.width() * self.progressbar_progress * 1.0 / 100,
                    self.progressbar_height)

    @QtCore.pyqtSlot()
    def start_progress(self):
        self.progressbar_progress = 0
        self.draw_progressbar = True
        self.update()

    @QtCore.pyqtSlot()
    def hide_progress(self):
        self.current_url = self.url
        self.no_need_draw_background = False

        self.draw_progressbar = False
        self.eval_dark_js = False
        self.update()

    @QtCore.pyqtSlot(int)
    def update_progress(self, progress):
        if progress < 100:
            # Update progres.
            self.progressbar_progress = progress
            self.update()
        elif progress == 100 and self.draw_progressbar:
            if self.dark_mode_is_enable():
                if not self.eval_dark_js:
                    self.dark_mode()
                    self.eval_dark_js = True

                    # We need show page some delay, avoid white flash when eval dark_mode_js
                    QtCore.QTimer.singleShot(1000, self.hide_progress)
            else:
                # Hide progress bar immediately if not dark mode.
                self.hide_progress()

    def handle_fullscreen_request(self, request):
        if request.toggleOn():
            self.enter_fullscreen_request.emit()
        else:
            self.exit_fullscreen_request.emit()

        request.accept()

    def handle_download_request(self, download_item):
        download_data = download_item.url().toString()

        if download_data.startswith("data:image/"):
            image_path = os.path.join(
                os.path.expanduser(
                    self.emacs_var_dict["eaf-browser-download-path"]),
                "image.png")
            touch(image_path)
            with open(image_path, "wb") as f:
                f.write(
                    base64.decodestring(
                        download_data.split(",")[1].encode("utf-8")))

            self.message_to_emacs.emit("Save image: " + image_path)
        else:
            self.try_start_aria2_daemon()

            from core.pyaria2 import Jsonrpc

            download_url = download_item.url().toString()
            jsonrpc = Jsonrpc('localhost', 6800)
            resp = jsonrpc.addUris(download_url)

            self.message_to_emacs.emit("Downloading: " + download_url)

    def save_as_pdf(self):
        self.send_input_message("Save current webpage as PDF?", "save_as_pdf",
                                "yes-or-no")

    def save_as_single_file(self):
        import shutil
        if shutil.which("monolith") is None:
            self.message_to_emacs.emit("Executable monolith not in PATH")
        else:
            self.send_input_message(
                "Save current webpage as single html file?",
                "save_as_single_file", "yes-or-no")

    def destroy_buffer(self):
        # Record close page.
        self.close_page.emit(self.buffer_widget.url().toString())

        # Load blank page to stop video playing, such as youtube.com.
        self.buffer_widget.open_url("about:blank")

        if self.buffer_widget is not None:
            # NOTE: We need delete QWebEnginePage manual, otherwise QtWebEngineProcess won't quit.
            self.buffer_widget.web_page.deleteLater()
            self.buffer_widget.deleteLater()

    def get_key_event_widgets(self):
        # We need send key event to QWebEngineView's focusProxy widget, not QWebEngineView.
        return [self.buffer_widget.focusProxy()]

    def scroll(self, scroll_direction, scroll_type):
        if scroll_type == "page":
            if scroll_direction == "up":
                self.scroll_up_page()
            else:
                self.scroll_down_page()
        else:
            if scroll_direction == "up":
                self.scroll_up()
            else:
                self.scroll_down()

    def handle_input_message(self, result_tag, result_content):
        if result_tag == "search_text_forward":
            self.buffer_widget._search_text(str(result_content))
        elif result_tag == "search_text_backward":
            self.buffer_widget._search_text(str(result_content), True)
        elif result_tag == "jump_link":
            self.buffer_widget.jump_to_link(str(result_content).strip())
        elif result_tag == "jump_link_new_buffer":
            self.buffer_widget.jump_to_link_new_buffer(
                str(result_content).strip())
        elif result_tag == "jump_link_background_buffer":
            self.buffer_widget.jump_to_link_background_buffer(
                str(result_content).strip())
        elif result_tag == "copy_link":
            self.buffer_widget.copy_link(str(result_content).strip())
        elif result_tag == "eval_js_file":
            self.buffer_widget.eval_js_file(str(result_content))
        elif result_tag == "eval_js":
            self.buffer_widget.eval_js(str(result_content))
        elif result_tag == "save_as_pdf":
            parsed = urlparse(self.url)
            qd = parse_qs(parsed.query, keep_blank_values=True)
            pdf_path = os.path.join(
                os.path.expanduser(
                    self.emacs_var_dict["eaf-browser-download-path"]),
                "{}.pdf".format(parsed.netloc))
            self.message_to_emacs.emit("Saving as pdf...")
            self.buffer_widget.web_page.printToPdf(pdf_path)
        elif result_tag == "save_as_single_file":
            parsed = urlparse(self.url)
            qd = parse_qs(parsed.query, keep_blank_values=True)
            file_path = os.path.join(
                os.path.expanduser(
                    self.emacs_var_dict["eaf-browser-download-path"]),
                "{}.html".format(parsed.netloc))
            self.message_to_emacs.emit("Saving as single file...")
            args = ["monolith", self.url, "-o", file_path]
            handler = partial(self.notify_monolith_message,
                              self.emacs_var_dict["eaf-browser-download-path"],
                              file_path, self.title)
            call_and_check_code(args, handler)
        elif result_tag == "edit_url":
            self.buffer_widget.open_url(str(result_content))
        elif result_tag == "copy_code":
            self.buffer_widget.copy_code_content(str(result_content).strip())

    def cancel_input_message(self, result_tag):
        if result_tag == "jump_link" or \
           result_tag == "jump_link_new_buffer" or \
           result_tag == "jump_link_background_buffer" or \
           result_tag == "copy_link" or \
           result_tag == "edit_url":
            self.buffer_widget.cleanup_links()

    def clear_all_cookies(self):
        self.buffer_widget.clear_cookies()
        self.message_to_emacs.emit("Cleared all cookies.")

    def try_start_aria2_daemon(self):
        if not is_port_in_use(6800):
            with open(os.devnull, "w") as null_file:
                aria2_args = ["aria2c"]

                aria2_args.append("-d")  # daemon
                aria2_args.append("-c")  # continue download
                aria2_args.append(
                    "--auto-file-renaming=false")  # not auto rename file
                aria2_args.append("-d {}".format(
                    os.path.expanduser(
                        str(self.emacs_var_dict["eaf-browser-download-path"])))
                                  )

                aria2_proxy_host = str(
                    self.emacs_var_dict["eaf-browser-aria2-proxy-host"])
                aria2_proxy_port = str(
                    self.emacs_var_dict["eaf-browser-aria2-proxy-port"])

                if aria2_proxy_host != "" and aria2_proxy_port != "":
                    aria2_args.append("--all-proxy")
                    aria2_args.append("http://{0}:{1}".format(
                        aria2_proxy_host, aria2_proxy_port))

                aria2_args.append("--enable-rpc")
                aria2_args.append("--rpc-listen-all")

                subprocess.Popen(aria2_args, stdout=null_file)

    def open_download_manage_page(self):
        self.try_start_aria2_daemon()
        self.buffer_widget.open_download_manage_page()

    def copy_text(self):
        self.buffer_widget.copy_text()
        self.message_to_emacs.emit("Copy selected text.")

    def copy_code(self):
        self.buffer_widget.get_code_markers()
        self.send_input_message("Copy code: ", "copy_code")

    def open_link(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Open Link: ", "jump_link")

    def open_link_new_buffer(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Open Link in New Buffer: ",
                                "jump_link_new_buffer")

    def open_link_background_buffer(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Open Link in Background Buffer: ",
                                "jump_link_background_buffer")

    def copy_link(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Copy link: ", "copy_link")

    def edit_url(self):
        self.send_input_message("Edit link: ", "edit_url", "string", self.url)

    def reset_default_zoom(self):
        if hasattr(self, "buffer_widget"):
            self.buffer_widget.setZoomFactor(
                float(self.emacs_var_dict["eaf-browser-default-zoom"]))

    def edit_focus_text(self):
        text = self.buffer_widget.get_focus_text()
        if text != None:
            self.get_focus_text.emit(self.buffer_id, text)
        else:
            self.message_to_emacs.emit("No active input element.")

    def is_focus(self):
        return self.buffer_widget.get_focus_text(
        ) != None or self.url == "devtools://devtools/bundled/devtools_app.html"

    def record_history(self, new_title):
        new_url = self.buffer_widget.filter_url(
            self.buffer_widget.url().toString())
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true" and self.buffer_widget.filter_title(new_title) != "" and \
           self.arguments != "temp_html_file" and new_title != "about:blank" and new_url != "about:blank":
            # Throw traceback info if algorithm has bug and protection of historical record is not erased.
            try:
                noprefix_new_url_match = re.match(self.noprefix_url_pattern,
                                                  new_url)
                if noprefix_new_url_match is not None:
                    found = False
                    for history in self.history_list:
                        noprefix_url_match = re.match(
                            self.noprefix_url_pattern, history.url)
                        if noprefix_url_match is not None:
                            noprefix_url = noprefix_url_match.group(2)
                            noprefix_new_url = noprefix_new_url_match.group(2)
                            nopostfix_new_url_match = re.match(
                                self.nopostfix_url_pattern, noprefix_new_url)

                            if noprefix_url == noprefix_new_url:  # found unique url
                                history.title = new_title
                                history.url = new_url
                                history.hit += 0.5
                                found = True
                            elif nopostfix_new_url_match is not None and noprefix_url == nopostfix_new_url_match.group(
                            ):
                                # also increment parent
                                history.hit += 0.25

                    if not found:
                        self.history_list.append(
                            HistoryPage(new_title, new_url, 1))

                self.history_list.sort(key=lambda x: x.hit, reverse=True)

                with open(self.history_log_file_path, "w") as f:
                    f.writelines(
                        map(
                            lambda history: history.title + "ᛝ" + history.url +
                            "ᛡ" + str(history.hit) + "\n", self.history_list))
            except Exception:
                import traceback
                self.message_to_emacs.emit("Error in record_history: " +
                                           str(traceback.print_exc()))

    def new_blank_page(self):
        self.eval_in_emacs.emit(
            '''(eaf-open \"{0}\" \"browser\" \"\" t)'''
            ''.format(self.emacs_var_dict["eaf-browser-blank-page-url"]))

    def clear_history(self):
        if os.path.exists(self.history_log_file_path):
            os.remove(self.history_log_file_path)
            self.message_to_emacs.emit("Cleared browsing history.")
        else:
            self.message_to_emacs.emit("There is no browsing history.")

    def record_close_page(self, url):
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true":
            touch(self.history_close_file_path)
            with open(self.history_close_file_path, "a") as f:
                f.write("{0}\n".format(url))

    def recover_prev_close_page(self):
        if os.path.exists(self.history_close_file_path):
            with open(self.history_close_file_path, "r") as f:
                close_urls = f.readlines()

                if len(close_urls) > 0:
                    # We need use rstrip remove \n char from url record.
                    prev_close_url = close_urls.pop().rstrip()

                    self.open_url_in_new_tab.emit(prev_close_url)
                    open(self.history_close_file_path,
                         "w").writelines(close_urls)

                    self.message_to_emacs.emit(
                        "Recovery {0}".format(prev_close_url))
                else:
                    self.message_to_emacs.emit("No page need recovery.")
        else:
            self.message_to_emacs.emit("No page need recovery.")

    def insert_or_do(func):
        def _do(self, *args, **kwargs):
            if self.is_focus():
                self.fake_key_event(self.current_event_string)
            else:
                func(self, *args, **kwargs)

        return _do

    def build_insert_or_do(self, method_name):
        def _do():
            if self.is_focus():
                self.fake_key_event(self.current_event_string)
            else:
                getattr(self, method_name)()

        setattr(self, "insert_or_{}".format(method_name), _do)

    @insert_or_do
    def insert_or_open_url(self):
        self.eval_in_emacs.emit(
            '''(call-interactively 'eaf-open-browser-with-history)''')

    def select_all_or_input_text(self):
        if self.is_focus():
            self.buffer_widget.select_input_text()
        else:
            self.buffer_widget.select_all()

    def eval_js_file(self):
        self.send_input_message("Eval JS file: ", "eval_js_file", "file")

    def eval_js(self):
        self.send_input_message("Eval JS: ", "eval_js")

    def open_dev_tool_page(self):
        self.open_dev_tools_tab.emit(self.buffer_widget.web_page)

    def toggle_device(self):
        user_agent = self.profile.defaultProfile().httpUserAgent()
        if user_agent == self.pc_user_agent:
            self.profile.defaultProfile().setHttpUserAgent(
                self.phone_user_agent)
            self.set_aspect_ratio(2.0 / 3)
        else:
            self.profile.defaultProfile().setHttpUserAgent(self.pc_user_agent)
            self.set_aspect_ratio(0)

        self.refresh_page()

    def download_youtube_video(self):
        self.download_youtube_file()

    def download_youtube_audio(self):
        self.download_youtube_file(True)

    def download_youtube_file(self, only_audio=False):
        url = self.buffer_widget.url().toString()
        if url.startswith("https://www.youtube.com"):
            import shutil

            if shutil.which("youtube-dl"):
                download_path = "{}/%(title)s-%(id)s.%(ext)s".format(
                    os.path.expanduser(
                        str(self.emacs_var_dict["eaf-browser-download-path"])))

                youtube_dl_args = ["youtube-dl"]
                youtube_dl_args.append("--proxy")
                youtube_dl_args.append(self.proxy_string)
                youtube_dl_args.append(url)
                youtube_dl_args.append("-o")
                youtube_dl_args.append(download_path)

                file_type = "video"
                if only_audio:
                    youtube_dl_args.append("-x")
                    file_type = "audio"

                with open(os.devnull, "w") as null_file:
                    popen_and_call(
                        youtube_dl_args, lambda: self.message_to_emacs.emit(
                            "Downloaded: {0}".format(url)), null_file)

                self.message_to_emacs.emit("Downloading {0}: {1}".format(
                    file_type, url))
            else:
                self.message_to_emacs.emit(
                    "Please install youtube-dl to use this feature.")
        else:
            self.message_to_emacs.emit(
                "Only videos from YouTube can be downloaded for now.")
Example #25
0
class ViewQt5WebEngine(View, QObject):
    _emit_js_signal = pyqtSignal(str, QVariant);

    def __init__(self, name="MyLensApp", width=640, height=480, inspector=False, start_maximized=False, *args, **kwargs):
        View.__init__(self, name=name, width=width,height=height, *args, **kwargs)
        QObject.__init__(self)

        self._app = QApplication([])

        # prepare Qt DBus mainloop
        try:
            DBusQtMainLoop(set_as_default=True)

        except NameError:
            # TODO: validate DBus failed to import (windows)
            pass

        self._app_loaded = False

        self._manager = ThreadManagerQt5(app=self._app)

        self._inspector = inspector
        self._start_maximized = start_maximized
        self._build_app()


    def _build_app(self):
        if self._inspector:
            os.environ.setdefault('QTWEBENGINE_REMOTE_DEBUGGING', '8001')

        # build webengine container
        self._lensview = lv = _QWebView(inspector=self._inspector)
        self._page = p = _QWebPage()
        lv.setPage(self._page)

        # connect to Qt signals
        lv.loadFinished.connect(self._loaded_cb)
        self._app.lastWindowClosed.connect(self._last_window_closed_cb)

        # build webchannel script and inject
        qwebchannel_js = QFile(':/qtwebchannel/qwebchannel.js')

        if not qwebchannel_js.open(QIODevice.ReadOnly):
            raise SystemExit('Failed to load qwebchannel.js with error: %s' % qwebchannel_js.errorString())

        qwebchannel_js = bytes(qwebchannel_js.readAll()).decode('utf-8')

        script = QWebEngineScript()
        script.setSourceCode(qwebchannel_js + '''
                window.lens = window.lens || {};
                window.lens._channel = new QWebChannel(qt.webChannelTransport, function(channel) {
                    window.lens.emit = function() {
                        var args = Array.prototype.slice.call(arguments);
                        if (args.length > 0) {
                            channel.objects.bridge._from_bridge(args);
                        }
                    };

                    channel.objects.bridge._emit_js_signal.connect(function(name, args) {
                        window.lens.__broadcast(name, args);
                    });
                });
            ''')
        script.setName('lens-bridge')
        script.setWorldId(QWebEngineScript.MainWorld)
        script.setInjectionPoint(QWebEngineScript.DocumentCreation)
        script.setRunsOnSubFrames(True)

        p.profile().scripts().insert(script)

        self._channel = QWebChannel(p)
        p.setWebChannel(self._channel)
        self._channel.registerObject('bridge', self)

        # set up scheme handlers for app:// and lens://
        self._app_scheme_handler = AppSchemeHandler()
        self._lens_scheme_handler = LensSchemeHandler()

        self._interceptor = RequestInterceptor()

        self._profile = QWebEngineProfile().defaultProfile()
        self._profile.installUrlSchemeHandler('app'.encode(), self._app_scheme_handler)
        self._profile.installUrlSchemeHandler('lens'.encode(), self._lens_scheme_handler)

        self._profile.setRequestInterceptor(self._interceptor)

        # connect to Lens signals
        self.on('__close_app', self._close_cb)

        # center on screen
        _frame_geometry = lv.frameGeometry()
        _active_screen = self._app.desktop().screenNumber(self._app.desktop().cursor().pos())
        _center = self._app.desktop().screenGeometry(_active_screen).center()
        _frame_geometry.moveCenter(_center)
        lv.move(_frame_geometry.topLeft())

        self.set_title(self._app_name)
        self.set_size(self._app_width, self._app_height)

    def _close_cb(self):
        self.emit('app.close')
        self._app.exit()

    @pyqtSlot(QVariant)
    def _from_bridge(self, name_args):
        # emit our python/js bridge signal
        self.emit(name_args[0], *name_args[1:])

    def _last_window_closed_cb(self, *args):
        self.emit('__close_app', *args)

    def _loaded_cb(self, success):
        # show window once some page has loaded
        self._lensview.show()
        if self._start_maximized:
            self.toggle_window_maximize()

        if not self._app_loaded:
            self._app_loaded = True
            self.emit('app.loaded')

    def _run(self):
        signal.signal(signal.SIGINT, signal.SIG_DFL)
        self._app.exec_()

    def emit_js(self, name, *args):
        self._emit_js_signal.emit(name, list(args))

    def load_string(self, data):
        index_uri = pathlib.Path(self._app_scheme_handler._uri_app_base).as_uri()
        self._lensview.setHtml(data, QUrl(index_uri))

    def load_uri(self, uri):
        uri_base = os.path.dirname(uri) + '/'
        self.set_uri_app_base(uri_base)
        path = uri_base + 'app.html'

        stream = QFile(path)
        if stream.open(QFile.ReadOnly):
            data = str(stream.readAll(), 'utf-8')
            index_uri = pathlib.Path(uri_base).as_uri() + os.sep
            logger.debug('Using {0} as index URI'.format(index_uri))
            self._lensview.setHtml(data, QUrl(index_uri))

    def set_inspector(self, state):
        self._lensview.set_inspector(state)

    def set_size(self, width, height):
        logger.debug('Setting app size: {0}x{1}'.format(width, height))
        self._lensview.setMinimumSize(width, height)
        self._lensview.resize(width, height)

    def set_title(self, title):
        self._lensview.setWindowTitle(QString(title))

    def set_uri_app_base(self, uri):
        self._app_scheme_handler._uri_app_base = pathlib.Path(uri).as_uri() + "/"

    def set_uri_lens_base(self, uri):
        self._lens_scheme_handler._uri_lens_base = pathlib.Path(uri).as_uri() + "/"

    def timer(self, interval, callback, once=False):
        q = QTimer(parent=self._lensview)

        q.timeout.connect(callback)
        q.start(interval)

        return q.timerId

    def toggle_window_maximize(self):
        if self._lensview.windowState() & Qt.WindowMaximized:
            self._lensview.setWindowState(self._lensview.windowState() ^ Qt.WindowMaximized)
            self.emit_js('window-unmaximized')
        else:
            self._lensview.setWindowState(self._lensview.windowState() | Qt.WindowMaximized)
            self.emit_js('window-maximized')

    def toggle_window_fullscreen(self):
        if self._lensview.windowState() & Qt.WindowFullScreen:
            self._lensview.setWindowState(self._lensview.windowState() ^ Qt.WindowFullScreen)
            self.emit_js('window-unfullscreen')
        else:
            self._lensview.setWindowState(self._lensview.windowState() | Qt.WindowFullScreen)
            self.emit_js('window-fullscreen')
    def __init__(self, config):
        self.config = config
        super(JWebView, self).__init__()
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.profile = QWebEngineProfile.defaultProfile()
        self.webpage = JWebPage(self.profile, self, config)
        self.setPage(self.webpage)
        if config["inject_JavaScript"]["JavaScript"]:
            from JAK.Utils import JavaScript
            JavaScript.inject(self.page(), config["inject_JavaScript"])
        self.interceptor = Interceptor(config)

        if config["user_agent"]:
            # Set user agent
            self.profile.setHttpUserAgent(config["user_agent"])

        if config["debug"]:
            self.settings().setAttribute(QWebEngineSettings.XSSAuditingEnabled,
                                         True)
        else:
            self.setContextMenuPolicy(Qt.PreventContextMenu)

        if config["transparent"]:
            # Activates background transparency
            self.setAttribute(Qt.WA_TranslucentBackground)
            self.page().setBackgroundColor(Qt.transparent)
            self.setStyleSheet("background:transparent;")
            print(
                "Transparency detected, make sure you set [ body {background:transparent;} ]"
            )

        # * Set Engine options
        if self.config["JavascriptCanPaste"]:
            self.settings().setAttribute(QWebEngineSettings.JavascriptCanPaste,
                                         True)
        else:
            self.settings().setAttribute(QWebEngineSettings.JavascriptCanPaste,
                                         False)
        if self.config["PlaybackRequiresUserGesture"]:
            self.settings().setAttribute(
                QWebEngineSettings.PlaybackRequiresUserGesture, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.PlaybackRequiresUserGesture, False)
        if self.config["FullScreenSupportEnabled"]:
            self.settings().setAttribute(
                QWebEngineSettings.FullScreenSupportEnabled, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.FullScreenSupportEnabled, False)
        if self.config["AllowWindowActivationFromJavaScript"]:
            self.settings().setAttribute(
                QWebEngineSettings.AllowWindowActivationFromJavaScript, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.AllowWindowActivationFromJavaScript, False)
        if self.config["LocalContentCanAccessRemoteUrls"]:
            self.settings().setAttribute(
                QWebEngineSettings.LocalContentCanAccessRemoteUrls, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.LocalContentCanAccessRemoteUrls, False)
        if self.config["JavascriptCanAccessClipboard"]:
            self.settings().setAttribute(
                QWebEngineSettings.JavascriptCanAccessClipboard, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.JavascriptCanAccessClipboard, False)
        if self.config["SpatialNavigationEnabled"]:
            self.settings().setAttribute(
                QWebEngineSettings.SpatialNavigationEnabled, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.SpatialNavigationEnabled, False)
        if self.config["TouchIconsEnabled"]:
            self.settings().setAttribute(QWebEngineSettings.TouchIconsEnabled,
                                         True)
        else:
            self.settings().setAttribute(QWebEngineSettings.TouchIconsEnabled,
                                         False)
        if self.config["FocusOnNavigationEnabled"]:
            self.settings().setAttribute(
                QWebEngineSettings.FocusOnNavigationEnabled, True)
        else:
            self.settings().setAttribute(
                QWebEngineSettings.FocusOnNavigationEnabled, False)

        if config["online"]:
            self.settings().setAttribute(QWebEngineSettings.DnsPrefetchEnabled,
                                         True)
            print("Engine online (IPC) Disabled")
            self.page().profile().downloadRequested.connect(
                self._download_requested)

            # Set persistent cookies
            self.profile.setPersistentCookiesPolicy(
                QWebEngineProfile.ForcePersistentCookies)

            # set cookies on user folder
            if config["cookies_path"]:
                # allow specific path per application.
                _cookies_path = f"{os.getenv('HOME')}/.jak/{config['cookies_path']}"
            else:
                # use separate cookies database per application
                title = config["title"].lower().replace(" ", "-")
                _cookies_path = f"{os.getenv('HOME')}/.jak/{title}"

            self.profile.setPersistentStoragePath(_cookies_path)
            print(f"Cookies PATH:{_cookies_path}")
        else:
            self.settings().setAttribute(QWebEngineSettings.ShowScrollBars,
                                         False)
            print("Engine interprocess communication (IPC) up and running:")
            self._ipc_scheme_handler = IpcSchemeHandler()
            self.profile.installUrlSchemeHandler('ipc'.encode(),
                                                 self._ipc_scheme_handler)
            if config["webChannel"]["active"]:
                from JAK.Utils import JavaScript
                if bindings() == "PyQt5":
                    from PyQt5.QtCore import QFile, QIODevice
                    from PyQt5.QtWebChannel import QWebChannel

                webchannel_js = QFile(':/qtwebchannel/qwebchannel.js')
                webchannel_js.open(QIODevice.ReadOnly)
                webchannel_js = bytes(webchannel_js.readAll()).decode('utf-8')
                webchannel_js += """ var JAK;
                                      new QWebChannel(qt.webChannelTransport, function (channel) {
                                      JAK = channel.objects.Bridge;
                                      });"""

                JavaScript.inject(self.page(), {
                    "JavaScript": webchannel_js,
                    "name": "QWebChannel API"
                })
                self.channel = QWebChannel(self.page())
                if config["webChannel"]["shared_obj"]:
                    self.bridge_obj = config["webChannel"]["shared_obj"]
                else:
                    raise NotImplementedError("QWebChannel shared QObject")

                self.channel.registerObject("Bridge", self.bridge_obj)
                self.page().setWebChannel(self.channel)
                print("QWebChannel bridge active")

        self.profile.setRequestInterceptor(self.interceptor)
        print(self.profile.httpUserAgent())
        validate_url(self, config["web_contents"])
def init_user_agent():
    _init_user_agent_str(QWebEngineProfile.defaultProfile().httpUserAgent())
Example #28
0
 def __init__(self, *args, **kwargs):
     super(Window, self).__init__(*args, **kwargs)
     self.resize(800, 600)
     QWebEngineProfile.defaultProfile().setRequestInterceptor(RequestInterceptor(self))
Example #29
0
 def __init__(self, *args, **kwargs):
     super(MyWebEngineView, self).__init__(*args, **kwargs)
     # 绑定cookie被添加的信号槽
     QWebEngineProfile.defaultProfile().cookieStore().cookieAdded.connect(
         self.onCookieAdd)
     self.cookies = {}  # 存放cookie字典
Example #30
0
    def _build_app(self):
        if self._inspector:
            os.environ.setdefault('QTWEBENGINE_REMOTE_DEBUGGING', '8001')

        # build webengine container
        self._lensview = lv = _QWebView(inspector=self._inspector)
        self._page = p = _QWebPage()
        lv.setPage(self._page)

        # connect to Qt signals
        lv.loadFinished.connect(self._loaded_cb)
        self._app.lastWindowClosed.connect(self._last_window_closed_cb)

        # build webchannel script and inject
        qwebchannel_js = QFile(':/qtwebchannel/qwebchannel.js')

        if not qwebchannel_js.open(QIODevice.ReadOnly):
            raise SystemExit('Failed to load qwebchannel.js with error: %s' % qwebchannel_js.errorString())

        qwebchannel_js = bytes(qwebchannel_js.readAll()).decode('utf-8')

        script = QWebEngineScript()
        script.setSourceCode(qwebchannel_js + '''
                window.lens = window.lens || {};
                window.lens._channel = new QWebChannel(qt.webChannelTransport, function(channel) {
                    window.lens.emit = function() {
                        var args = Array.prototype.slice.call(arguments);
                        if (args.length > 0) {
                            channel.objects.bridge._from_bridge(args);
                        }
                    };

                    channel.objects.bridge._emit_js_signal.connect(function(name, args) {
                        window.lens.__broadcast(name, args);
                    });
                });
            ''')
        script.setName('lens-bridge')
        script.setWorldId(QWebEngineScript.MainWorld)
        script.setInjectionPoint(QWebEngineScript.DocumentCreation)
        script.setRunsOnSubFrames(True)

        p.profile().scripts().insert(script)

        self._channel = QWebChannel(p)
        p.setWebChannel(self._channel)
        self._channel.registerObject('bridge', self)

        # set up scheme handlers for app:// and lens://
        self._app_scheme_handler = AppSchemeHandler()
        self._lens_scheme_handler = LensSchemeHandler()

        self._interceptor = RequestInterceptor()

        self._profile = QWebEngineProfile().defaultProfile()
        self._profile.installUrlSchemeHandler('app'.encode(), self._app_scheme_handler)
        self._profile.installUrlSchemeHandler('lens'.encode(), self._lens_scheme_handler)

        self._profile.setRequestInterceptor(self._interceptor)

        # connect to Lens signals
        self.on('__close_app', self._close_cb)

        # center on screen
        _frame_geometry = lv.frameGeometry()
        _active_screen = self._app.desktop().screenNumber(self._app.desktop().cursor().pos())
        _center = self._app.desktop().screenGeometry(_active_screen).center()
        _frame_geometry.moveCenter(_center)
        lv.move(_frame_geometry.topLeft())

        self.set_title(self._app_name)
        self.set_size(self._app_width, self._app_height)
Example #31
0
    def __init__(self, config):
        self.config = config
        super(JWebView, self).__init__()
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.profile = QWebEngineProfile.defaultProfile()
        self.webpage = JWebPage(self.profile, self, config)
        self.setPage(self.webpage)
        if config['webview']["injectJavaScript"]["JavaScript"]:
            self._inject_script(config['webview']["injectJavaScript"])
        self.interceptor = Interceptor(config)

        if config['webview']["userAgent"]:
            # Set user agent
            self.profile.setHttpUserAgent(config['webview']["userAgent"])

        if config["debug"]:
            self.settings().setAttribute(QWebEngineSettings.XSSAuditingEnabled,
                                         True)
        else:
            self.setContextMenuPolicy(Qt.PreventContextMenu)

        if config['window']["transparent"]:
            # Activates background transparency
            self.setAttribute(Qt.WA_TranslucentBackground)
            self.page().setBackgroundColor(Qt.transparent)
            print("Transparency detected")

        # * Set Engine options
        self.settings().setAttribute(
            self.config['webview']['disabledSettings'], False)
        for setting in self.config['webview']['enabledSettings']:
            self.settings().setAttribute(setting, True)

        if config['webview']["online"]:
            self.settings().setAttribute(QWebEngineSettings.DnsPrefetchEnabled,
                                         True)
            print("Engine online IPC and Bridge Disabled")
            self.page().profile().downloadRequested.connect(
                self._download_requested)

            # Set persistent cookies
            self.profile.setPersistentCookiesPolicy(
                QWebEngineProfile.ForcePersistentCookies)

            # set cookies on user folder
            if config['webview']["cookiesPath"]:
                # allow specific path per application.
                _cookies_path = f"{os.getenv('HOME')}/.jak/{config['webview']['cookiesPath']}"
            else:
                # use separate cookies database per application
                title = config['window']["title"].lower().replace(" ", "-")
                _cookies_path = f"{os.getenv('HOME')}/.jak/{title}"

            self.profile.setPersistentStoragePath(_cookies_path)
            print(f"Cookies PATH:{_cookies_path}")
        else:
            self.settings().setAttribute(QWebEngineSettings.ShowScrollBars,
                                         False)
            application_script = "const JAK = {};"

            if config['webview']["IPC"]:
                print("IPC Active:")
                self._ipc_scheme_handler = IpcSchemeHandler()
                self.profile.installUrlSchemeHandler('ipc'.encode(),
                                                     self._ipc_scheme_handler)
                application_script += """JAK.IPC = function(backendFunction) {
                            window.location.href = "ipc:" + backendFunction;
                        };"""

            if config['webview']["webChannel"]["active"]:
                if bindings() == "PyQt5":
                    from PyQt5.QtCore import QFile, QIODevice
                    from PyQt5.QtWebChannel import QWebChannel

                webchannel_js = QFile(':/qtwebchannel/qwebchannel.js')
                webchannel_js.open(QIODevice.ReadOnly)
                webchannel_js = bytes(webchannel_js.readAll()).decode('utf-8')
                webchannel_js += """new QWebChannel(qt.webChannelTransport, function (channel) {
                                        JAK.Bridge = channel.objects.Bridge;
                                    });"""

                application_script += webchannel_js
                self._inject_script({
                    "JavaScript": application_script,
                    "name": "JAK"
                })
                channel = QWebChannel(self.page())
                if config['webview']["webChannel"]["sharedOBJ"]:
                    bridge_obj = config['webview']["webChannel"]["sharedOBJ"]
                else:
                    raise NotImplementedError("QWebChannel shared QObject")

                channel.registerObject("Bridge", bridge_obj)
                self.page().setWebChannel(channel)
                print("WebChannel Active:")
            else:
                self._inject_script({
                    "JavaScript": application_script,
                    "name": "JAK"
                })

        self.profile.setRequestInterceptor(self.interceptor)
        print(self.profile.httpUserAgent())
        validate_url(self, config['webview']["webContents"])
Example #32
0
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(
            QWebEngineSettings.WebAttribute.FullScreenSupportEnabled, False)
        s.setAttribute(
            QWebEngineSettings.WebAttribute.LinksIncludedInFocusChain, False)
        create_profile.ans = ans
    return ans
Example #33
0
    def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict,
                 fit_to_view, background_color):
        Buffer.__init__(self, buffer_id, url, arguments, emacs_var_dict,
                        fit_to_view, background_color)

        self.add_widget(BrowserView(config_dir))

        self.config_dir = config_dir

        self.history_list = []
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true":
            self.history_log_file_path = os.path.join(self.config_dir,
                                                      "browser", "history",
                                                      "log.txt")

            self.history_pattern = re.compile("^(.+)ᛝ(.+)ᛡ(.+)$")
            self.noprefix_url_pattern = re.compile("^(https?|file)://(.+)")
            self.nopostfix_url_pattern = re.compile("^[^#\?]*")
            self.history_close_file_path = os.path.join(
                self.config_dir, "browser", "history", "close.txt")
            touch(self.history_log_file_path)
            with open(self.history_log_file_path, "r") as f:
                raw_list = f.readlines()
                for raw_his in raw_list:
                    his_line = re.match(self.history_pattern, raw_his)
                    if his_line is None:  # Obsolete Old history format
                        old_his = re.match("(.*)\s((https?|file):[^\s]+)$",
                                           raw_his)
                        if old_his is not None:
                            self.history_list.append(
                                HistoryPage(old_his.group(1), old_his.group(2),
                                            1))
                    else:
                        self.history_list.append(
                            HistoryPage(his_line.group(1), his_line.group(2),
                                        his_line.group(3)))

        # Set User Agent with Firefox's one to make EAF browser can login in Google account.
        self.profile = QWebEngineProfile(self.buffer_widget)
        self.profile.defaultProfile().setHttpUserAgent(
            "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/72.0"
        )

        self.buffer_widget.loadStarted.connect(self.start_progress)
        self.buffer_widget.loadProgress.connect(self.update_progress)
        self.buffer_widget.loadFinished.connect(self.stop_progress)
        self.buffer_widget.web_page.windowCloseRequested.connect(
            self.request_close_buffer)
        self.buffer_widget.web_page.fullScreenRequested.connect(
            self.handle_fullscreen_request)

        self.profile.defaultProfile().downloadRequested.connect(
            self.handle_download_request)

        settings = QWebEngineSettings.globalSettings()
        try:
            settings.setAttribute(
                QWebEngineSettings.PluginsEnabled,
                self.emacs_var_dict["eaf-browser-enable-plugin"] == "true")
            settings.setAttribute(
                QWebEngineSettings.JavascriptEnabled,
                self.emacs_var_dict["eaf-browser-enable-javascript"] == "true")
            settings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled,
                                  True)
        except Exception:
            pass

        for method_name in [
                "search_text_forward", "search_text_backward", "zoom_out",
                "zoom_in", "zoom_reset", "scroll_left", "scroll_right",
                "scroll_up", "scroll_down", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "refresh_page", "undo_action", "redo_action", "get_url",
                "exit_fullscreen", "set_focus_text", "clear_focus", "dark_mode"
        ]:
            self.build_widget_method(method_name)

        self.build_widget_method("history_backward", "back")
        self.build_widget_method("history_forward", "forward")
        self.build_widget_method("action_quit", "search_quit")
        self.build_widget_method("yank_text", "yank_text", "Yank text.")
        self.build_widget_method("kill_text", "kill_text", "Kill text.")

        for method_name in [
                "recover_prev_close_page", "scroll_up", "scroll_down",
                "scroll_left", "scroll_right", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "open_link", "open_link_new_buffer",
                "open_link_background_buffer", "history_backward",
                "history_forward", "new_blank_page",
                "open_download_manage_page", "refresh_page", "zoom_in",
                "zoom_out", "zoom_reset", "save_as_bookmark"
        ]:
            self.build_insert_or_do(method_name)
Example #34
0
    # QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.DnsPrefetchEnabled, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.JavascriptEnabled, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.OfflineStorageDatabaseEnabled, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.AutoLoadImages, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.LocalStorageEnabled, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.PrivateBrowsingEnabled, True)
    # QWebSettings.globalSettings().setAttribute(QWebSettings.DeveloperExtrasEnabled, True)
    # serverThred = Thread(start_http_server, (8067, 'localhost', HttpServerHandler))

    # serverThred.start()

    app = QApplication(sys.argv)

    interceptor = WebEngineUrlRequestInterceptor()
    QWebEngineProfile.defaultProfile().setRequestInterceptor(interceptor)
    window = Page()
    # window.loadUrl("https://jira.orange.ro/browse/MCC-3353")

    # server_handler = HttpServerHandler
    # server_handler.set_page(window)
    # start_http_server(serverHandler=server_handler)
    # _thread.start_new_thread(start_http_server, (8067, 'localhost', HttpServerHandler))

    window.showMaximized()

    window.loadUrl("https://www.youtube.com/watch?v=raTMa8MneTY")
    # view = Browser()
    # view.show()
    # # view.showMaximized()
    # print('show maximized')
Example #35
0
class QTWSWebView(QWebEngineView):
    def __init__(self, config: QTWSConfig, window, profile_name: str = None):
        super().__init__()
        self.config = config
        self.window = window

        if profile_name is None or profile_name.lower() == 'default':
            self.profile = QWebEngineProfile.defaultProfile()
        else:
            self.profile = QWebEngineProfile(profile_name)

        maxCache = self.config.cache_mb * 1024 * 1024
        self.profile.setHttpCacheMaximumSize(maxCache)

        self.profile.downloadRequested.connect(
            lambda item: self.__download(item))

        QTWSPluginManager.instance().each(
            lambda plugin: plugin.web_profile_setup(self.profile))

        self.webPage = QTWSWebPage(self.config, self.profile)
        self.setPage(self.webPage)
        self.permission_manager = QTWSPermissionManager(self.webPage)

        QTWSPluginManager.instance().each(
            lambda plugin: plugin.web_engine_setup(self))

        if self.config.menu_disabled:
            self.setContextMenuPolicy(Qt.NoContextMenu)
        else:
            self.setContextMenuPolicy(Qt.CustomContextMenu)
            self.customContextMenuRequested.connect(self.__show_menu)

        self.__create_actions()

        self.urlChanged.connect(self.__url_changed)

        self.settings().setAttribute(
            QWebEngineSettings.FullScreenSupportEnabled, True)
        self.settings().setAttribute(
            QWebEngineSettings.JavascriptCanOpenWindows, True)
        self.settings().setAttribute(QWebEngineSettings.ScrollAnimatorEnabled,
                                     True)
        self.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True)

        self.download_windows = []

    def grant_permission(self, permission):
        self.permission_manager.grant_permission(permission)

    def __create_actions(self):
        self.__actionBack = QAction(QIcon.fromTheme("back"), "Back")
        self.__actionBack.triggered.connect(lambda: self.back())

        self.__actionReload = QAction(QIcon.fromTheme("reload"), "Reload")
        self.__actionReload.triggered.connect(lambda: self.reload())

        self.__actionHome = QAction(QIcon.fromTheme("go-home"), "Home")
        self.__actionHome.triggered.connect(
            lambda: self.setUrl(self.config.home))

        self.__actionShare = QAction(QIcon.fromTheme("emblem-shared"), "Share")
        self.__actionShare.triggered.connect(self.__share)

        self.__actionOpenBrowser = QAction(
            QIcon.fromTheme("internet-web-browser"), "Open in the browser")
        self.__actionOpenBrowser.triggered.connect(self.__open_in_browser)

        self.__actionQuit = QAction(QIcon.fromTheme("application-exit"),
                                    "Quit")
        self.__actionQuit.triggered.connect(self.__quit)

        self.__customActions = list()
        for menu_item in self.config.menu:
            if menu_item.icon:
                action = QAction(QIcon.fromTheme(menu_item.icon),
                                 menu_item.title)
            else:
                action = QAction(menu_item.title)

            action.setData(menu_item.action)

            if menu_item.separator:
                self.__customActions.append("-")

            self.__customActions.append(action)

    def __show_menu(self, position: QPoint):
        self.menu = QMenu()

        if not self.page().history().canGoBack():
            self.__actionBack.setEnabled(False)
        self.menu.addAction(self.__actionBack)
        self.menu.addAction(self.__actionReload)
        self.menu.addAction(self.__actionHome)
        self.menu.addAction(self.__actionShare)
        self.menu.addAction(self.__actionOpenBrowser)

        if len(self.__customActions) > 0:
            self.menu.addSeparator()

        for action in self.__customActions:
            if action == '-':
                self.menu.addSeparator()
            else:
                self.menu.addAction(action)

        self.menu.addSeparator()

        for plugin in QTWSPluginManager.instance().plugins:
            plugin.add_menu_items(self.menu)
            self.menu.addSeparator()

        self.menu.addAction(self.__actionQuit)

        # Handles all the custom actions using the
        # URL stored in the action's data field
        self.menu.triggered.connect(self.__menu_click)
        self.menu.popup(self.mapToGlobal(position))

    def __download(self, item):
        default_path = QDir(item.downloadDirectory()).filePath(
            item.downloadFileName())

        path, _ = QFileDialog.getSaveFileName(self, "Save as", default_path)

        if path is None or len(path) == 0:
            item.cancel()
            return

        info = QFileInfo(path)
        item.setDownloadDirectory(info.dir().path())
        item.setDownloadFileName(info.fileName())
        item.accept()
        self.download_windows.append(
            DownloadProgressWindow(item,
                                   info.dir().path() + "/" + info.fileName()))

    def __share(self):
        QApplication.instance().clipboard().setText(self.url().toString())
        QMessageBox().information(self, 'Shared', 'Copied to the clipboard',
                                  QMessageBox.Ok)

    def __open_in_browser(self):
        external_browser.open(self.url().toString())

    def __quit(self):
        self.window.quit()

    def __menu_click(self, action: QAction):
        if action.data():
            self.setUrl(action.data())

    def __url_changed(self, status):
        QTWSPluginManager.instance().each(
            lambda plugin: plugin.on_page_loaded(self.url()))
    def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict,
                 module_path, fit_to_view):
        Buffer.__init__(self, buffer_id, url, arguments, emacs_var_dict,
                        module_path, fit_to_view)

        self.add_widget(BrowserView(config_dir))

        self.config_dir = config_dir

        self.history_list = []
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true":
            self.history_log_file_path = os.path.join(self.config_dir,
                                                      "browser", "history",
                                                      "log.txt")

            self.history_pattern = re.compile("^(.+)ᛝ(.+)ᛡ(.+)$")
            self.noprefix_url_pattern = re.compile("^(https?|file)://(.+)")
            self.nopostfix_url_pattern = re.compile("^[^#\?]*")
            self.history_close_file_path = os.path.join(
                self.config_dir, "browser", "history", "close.txt")
            touch(self.history_log_file_path)
            with open(self.history_log_file_path, "r") as f:
                raw_list = f.readlines()
                for raw_his in raw_list:
                    his_line = re.match(self.history_pattern, raw_his)
                    if his_line is None:  # Obsolete Old history format
                        old_his = re.match("(.*)\s((https?|file):[^\s]+)$",
                                           raw_his)
                        if old_his is not None:
                            self.history_list.append(
                                HistoryPage(old_his.group(1), old_his.group(2),
                                            1))
                    else:
                        self.history_list.append(
                            HistoryPage(his_line.group(1), his_line.group(2),
                                        his_line.group(3)))

        # Set User Agent with Firefox's one to make EAF browser can login in Google account.
        self.pc_user_agent = "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/72.0"
        self.phone_user_agent = "Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A5370a Safari/604.1"
        self.profile = QWebEngineProfile(self.buffer_widget)
        self.profile.defaultProfile().setHttpUserAgent(self.pc_user_agent)

        self.draw_progressbar = False
        self.eval_dark_js = False
        self.progressbar_progress = 0
        self.progressbar_color = QColor(233, 129, 35, 255)
        self.progressbar_height = 2
        self.light_mode_mask_color = QColor("#FFFFFF")
        self.dark_mode_mask_color = QColor("#242525")

        self.current_url = ""
        self.request_url = ""
        self.no_need_draw_background = False

        self.init_background_color()

        self.buffer_widget.loadStarted.connect(self.start_progress)
        self.buffer_widget.loadProgress.connect(self.update_progress)
        self.buffer_widget.urlChanged.connect(self.record_url)
        self.buffer_widget.web_page.windowCloseRequested.connect(
            self.close_buffer)
        self.buffer_widget.web_page.fullScreenRequested.connect(
            self.handle_fullscreen_request)
        self.buffer_widget.web_page.pdfPrintingFinished.connect(
            self.notify_print_message)
        self.profile.defaultProfile().downloadRequested.connect(
            self.handle_download_request)

        settings = QWebEngineSettings.globalSettings()
        try:
            settings.setAttribute(
                QWebEngineSettings.PluginsEnabled,
                self.emacs_var_dict["eaf-browser-enable-plugin"] == "true")
            settings.setAttribute(
                QWebEngineSettings.JavascriptEnabled,
                self.emacs_var_dict["eaf-browser-enable-javascript"] == "true")
            settings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled,
                                  True)
            settings.setAttribute(
                QWebEngineSettings.PlaybackRequiresUserGesture, False)
            settings.setAttribute(QWebEngineSettings.DnsPrefetchEnabled, True)
        except Exception:
            pass

        for method_name in [
                "search_text_forward", "search_text_backward", "zoom_out",
                "zoom_in", "zoom_reset", "scroll_left", "scroll_right",
                "scroll_up", "scroll_down", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "refresh_page", "undo_action", "redo_action", "get_url",
                "exit_fullscreen", "set_focus_text", "clear_focus",
                "dark_mode", "view_source"
        ]:
            self.build_widget_method(method_name)

        self.build_widget_method("history_backward", "back")
        self.build_widget_method("history_forward", "forward")
        self.build_widget_method("action_quit", "search_quit")
        self.build_widget_method("yank_text", "yank_text", "Yank text.")
        self.build_widget_method("kill_text", "kill_text", "Kill text.")

        for method_name in [
                "recover_prev_close_page", "scroll_up", "scroll_down",
                "scroll_left", "scroll_right", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "open_link", "open_link_new_buffer",
                "open_link_background_buffer", "copy_link", "history_backward",
                "history_forward", "new_blank_page",
                "open_download_manage_page", "refresh_page", "zoom_in",
                "zoom_out", "zoom_reset", "save_as_bookmark", "edit_url",
                "download_youtube_video", "download_youtube_audio",
                "toggle_device", "close_buffer", "save_as_pdf", "view_source",
                "save_as_single_file", "select_left_tab", "select_right_tab",
                "copy_code"
        ]:
            self.build_insert_or_do(method_name)
Example #37
0
 def __init__(self):
     super().__init__()
     self.cookies = {}
     # 绑定cookie被添加的信号槽
     QWebEngineProfile.defaultProfile().cookieStore().cookieAdded.connect(self.onCookieAdd)
Example #38
0
    def __init__(self):
        super(Browser, self).__init__()
        self.dbConnection = DBConnection("data.db")
        self.dbConnection.createdb()

        self.centralWidget = QWidget(self)
        self.grid = QGridLayout(self.centralWidget)

        self.urlInput = UrlInput(self)
        self.back = PushButton("", QIcon("Icons/NavigationBar/back.png"))
        self.forward = PushButton("", QIcon("Icons/NavigationBar/forward.png"))
        self.reload = PushButton("", QIcon("Icons/NavigationBar/reload.png"))
        self.bookmark = PushButton("", QIcon("Icons/NavigationBar/noFav.png"))
        self.home = PushButton("", QIcon("Icons/NavigationBar/home.png"))
        self.parameter = PushButton("", QIcon("Icons/NavigationBar/param.png"))
        self.tabWidget = TabWidget(self)

        self.tabWidget.requestsaddtab()
        self.back.setFlat(True)
        self.forward.setFlat(True)
        self.reload.setFlat(True)
        self.bookmark.setFlat(True)
        self.home.setFlat(True)
        self.parameter.setFlat(True)

        self.reload.clicked.connect(self.browserWidget.reload)
        self.back.clicked.connect(self.browserWidget.back)
        self.forward.clicked.connect(self.browserWidget.forward)
        self.bookmark.clicked.connect(self.fav)
        self.home.clicked.connect(lambda: self.urlInput.enterurlgiven(
            self.dbConnection.executewithreturn("""SELECT home FROM parameters""")[0][0]))
        self.parameter.clicked.connect(self.openparameter)

        self.grid.addWidget(self.back, 0, 0)
        self.grid.addWidget(self.reload, 0, 1)
        self.grid.addWidget(self.forward, 0, 2)
        self.grid.addWidget(self.urlInput, 0, 3)
        self.grid.addWidget(self.bookmark, 0, 4)
        self.grid.addWidget(self.home, 0, 5)
        self.grid.addWidget(self.parameter, 0, 6)
        self.grid.addWidget(self.tabWidget, 1, 0, 1, 7)

        self.grid.setContentsMargins(0, 0, 0, 0)
        self.grid.setSpacing(0)
        self.setCentralWidget(self.centralWidget)
        self.showMaximized()
        self.setWindowTitle('Browthon')

        QWebEngineSettings.globalSettings().setAttribute(QWebEngineSettings.FullScreenSupportEnabled, True)
        if self.dbConnection.executewithreturn("""SELECT js FROM parameters""")[0][0] == "Activé":
            QWebEngineSettings.globalSettings().setAttribute(QWebEngineSettings.JavascriptEnabled, True)
        else:
            QWebEngineSettings.globalSettings().setAttribute(QWebEngineSettings.JavascriptEnabled, False)
        self.parameterWindow = ParameterWindow(self)
        QWebEngineProfile.defaultProfile().\
            downloadRequested.connect(self.parameterWindow.downloadPage.downloadrequested)

        theme = self.dbConnection.executewithreturn("""SELECT theme FROM parameters""")[0][0]
        if theme == "":
            self.applytheme("")
        else:
            if os.path.exists("Themes/"+theme+"/theme.json"):
                self.applytheme("Themes/"+theme)
            else:
                print("Le theme "+theme+" n'existe pas/plus.")
                self.applytheme("")

        self.show()
Example #39
0
    def __init__(self, *args, **kwargs):
        super(WebBrowser, self).__init__(*args, **kwargs)

        QWebEngineProfile.defaultProfile().cookieStore().cookieAdded.connect(
            self.onCookieAdd)
        self.loadFinished.connect(self.onLoadFinished)
Example #40
0
res = requests.get(proxy_provider_url)
ip = res.text.split(":")
port = ip[1]
ip = ip[0]

proxy = QtNetwork.QNetworkProxy()
# Http访问代理
proxy.setType(QtNetwork.QNetworkProxy.HttpProxy)
# 代理ip地址HttpProxy
proxy.setHostName(ip)
# 端口号
proxy.setPort(int(port))
QtNetwork.QNetworkProxy.setApplicationProxy(proxy)

interceptor = TwitchInterceptor()
profile = QWebEngineProfile()
profile.clearHttpCache()
profile.clearAllVisitedLinks()
pCookie = profile.cookieStore()
pCookie.deleteAllCookies()
pCookie.deleteSessionCookies()
profile.setRequestInterceptor(interceptor)

profile.setPersistentCookiesPolicy(QWebEngineProfile.ForcePersistentCookies)

page = QWebEnginePage(profile, view)
page.loadFinished.connect(on_done)
view.setPage(page)
page.setUrl(QUrl(twitch_url))
view.show()
sys.exit(app.exec_())
def update_settings(section, option):
    """Update global settings when qwebsettings changed."""
    websettings.update_mappings(MAPPINGS, section, option)
    profile = QWebEngineProfile.defaultProfile()
    if section == 'ui' and option in ['hide-scrollbar', 'user-stylesheet']:
        _init_stylesheet(profile)
Example #42
0
 def __init__(self, *args, **kwargs):
     super(WebEngineView, self).__init__(*args, **kwargs)
     # 绑定cookie被添加的信号槽
     QWebEngineProfile.defaultProfile().cookieStore().cookieAdded.connect(
         self.onCookieAdd)
     self.loadFinished.connect(self.onLoadFinished)
Example #43
0
def update_settings(section, option):
    """Update global settings when qwebsettings changed."""
    websettings.update_mappings(MAPPINGS, section, option)
    profile = QWebEngineProfile.defaultProfile()
    if section == 'ui' and option in ['hide-scrollbar', 'user-stylesheet']:
        _init_stylesheet(profile)
Example #44
0
 def __init__(self, getter, setter):
     super().__init__()
     profile = QWebEngineProfile.defaultProfile()
     self._getter = getattr(profile, getter)
     self._setter = getattr(profile, setter)
Example #45
0
class BrowserBuffer(Buffer):

    close_page = QtCore.pyqtSignal(str)
    get_focus_text = QtCore.pyqtSignal(str, str)
    open_dev_tools_tab = QtCore.pyqtSignal(object)
    enter_fullscreen_request = QtCore.pyqtSignal()
    exit_fullscreen_request = QtCore.pyqtSignal()

    def __init__(self, buffer_id, url, config_dir, arguments, emacs_var_dict,
                 fit_to_view, background_color):
        Buffer.__init__(self, buffer_id, url, arguments, emacs_var_dict,
                        fit_to_view, background_color)

        self.add_widget(BrowserView(config_dir))

        self.config_dir = config_dir

        self.history_list = []
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true":
            self.history_log_file_path = os.path.join(self.config_dir,
                                                      "browser", "history",
                                                      "log.txt")

            self.history_pattern = re.compile("^(.+)ᛝ(.+)ᛡ(.+)$")
            self.noprefix_url_pattern = re.compile("^(https?|file)://(.+)")
            self.nopostfix_url_pattern = re.compile("^[^#\?]*")
            self.history_close_file_path = os.path.join(
                self.config_dir, "browser", "history", "close.txt")
            touch(self.history_log_file_path)
            with open(self.history_log_file_path, "r") as f:
                raw_list = f.readlines()
                for raw_his in raw_list:
                    his_line = re.match(self.history_pattern, raw_his)
                    if his_line is None:  # Obsolete Old history format
                        old_his = re.match("(.*)\s((https?|file):[^\s]+)$",
                                           raw_his)
                        if old_his is not None:
                            self.history_list.append(
                                HistoryPage(old_his.group(1), old_his.group(2),
                                            1))
                    else:
                        self.history_list.append(
                            HistoryPage(his_line.group(1), his_line.group(2),
                                        his_line.group(3)))

        # Set User Agent with Firefox's one to make EAF browser can login in Google account.
        self.profile = QWebEngineProfile(self.buffer_widget)
        self.profile.defaultProfile().setHttpUserAgent(
            "Mozilla/5.0 (X11; Linux i586; rv:31.0) Gecko/20100101 Firefox/72.0"
        )

        self.buffer_widget.loadStarted.connect(self.start_progress)
        self.buffer_widget.loadProgress.connect(self.update_progress)
        self.buffer_widget.loadFinished.connect(self.stop_progress)
        self.buffer_widget.web_page.windowCloseRequested.connect(
            self.request_close_buffer)
        self.buffer_widget.web_page.fullScreenRequested.connect(
            self.handle_fullscreen_request)

        self.profile.defaultProfile().downloadRequested.connect(
            self.handle_download_request)

        settings = QWebEngineSettings.globalSettings()
        try:
            settings.setAttribute(
                QWebEngineSettings.PluginsEnabled,
                self.emacs_var_dict["eaf-browser-enable-plugin"] == "true")
            settings.setAttribute(
                QWebEngineSettings.JavascriptEnabled,
                self.emacs_var_dict["eaf-browser-enable-javascript"] == "true")
            settings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled,
                                  True)
        except Exception:
            pass

        for method_name in [
                "search_text_forward", "search_text_backward", "zoom_out",
                "zoom_in", "zoom_reset", "scroll_left", "scroll_right",
                "scroll_up", "scroll_down", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "refresh_page", "undo_action", "redo_action", "get_url",
                "exit_fullscreen", "set_focus_text", "clear_focus", "dark_mode"
        ]:
            self.build_widget_method(method_name)

        self.build_widget_method("history_backward", "back")
        self.build_widget_method("history_forward", "forward")
        self.build_widget_method("action_quit", "search_quit")
        self.build_widget_method("yank_text", "yank_text", "Yank text.")
        self.build_widget_method("kill_text", "kill_text", "Kill text.")

        for method_name in [
                "recover_prev_close_page", "scroll_up", "scroll_down",
                "scroll_left", "scroll_right", "scroll_up_page",
                "scroll_down_page", "scroll_to_begin", "scroll_to_bottom",
                "open_link", "open_link_new_buffer",
                "open_link_background_buffer", "history_backward",
                "history_forward", "new_blank_page",
                "open_download_manage_page", "refresh_page", "zoom_in",
                "zoom_out", "zoom_reset", "save_as_bookmark"
        ]:
            self.build_insert_or_do(method_name)

    def handle_fullscreen_request(self, request):
        if request.toggleOn():
            self.enter_fullscreen_request.emit()
        else:
            self.exit_fullscreen_request.emit()

        request.accept()

    def handle_download_request(self, download_item):
        download_data = download_item.url().toString()

        if download_data.startswith("data:image/"):
            image_path = os.path.join(
                os.path.expanduser(
                    self.emacs_var_dict["eaf-browser-download-path"]),
                "image.png")
            touch(image_path)
            with open(image_path, "wb") as f:
                f.write(
                    base64.decodestring(
                        download_data.split(",")[1].encode("utf-8")))

            self.message_to_emacs.emit("Save image: " + image_path)
        else:
            self.try_start_aria2_daemon()

            download_data = download_item.url().toString()
            with open(os.devnull, "w") as null_file:
                subprocess.Popen(["aria2p", "add", download_data],
                                 stdout=null_file)

            self.message_to_emacs.emit("Start download: " + download_data)

    def destroy_buffer(self):
        # Record close page.
        self.close_page.emit(self.buffer_widget.url().toString())

        # Load blank page to stop video playing, such as youtube.com.
        self.buffer_widget.open_url("about:blank")

        if self.buffer_widget is not None:
            # NOTE: We need delete QWebEnginePage manual, otherwise QtWebEngineProcess won't quit.
            self.buffer_widget.web_page.deleteLater()
            self.buffer_widget.deleteLater()

    def get_key_event_widgets(self):
        # We need send key event to QWebEngineView's focusProxy widget, not QWebEngineView.
        return [self.buffer_widget.focusProxy()]

    def scroll(self, scroll_direction, scroll_type):
        if scroll_type == "page":
            if scroll_direction == "up":
                self.scroll_up_page()
            else:
                self.scroll_down_page()
        else:
            if scroll_direction == "up":
                self.scroll_up()
            else:
                self.scroll_down()

    def handle_input_message(self, result_type, result_content):
        if result_type == "search_text_forward":
            self.buffer_widget._search_text(str(result_content))
        elif result_type == "search_text_backward":
            self.buffer_widget._search_text(str(result_content), True)
        elif result_type == "jump_link":
            self.buffer_widget.jump_to_link(str(result_content).strip())
        elif result_type == "jump_link_new_buffer":
            self.buffer_widget.jump_to_link_new_buffer(
                str(result_content).strip())
        elif result_type == "jump_link_background_buffer":
            self.buffer_widget.jump_to_link_background_buffer(
                str(result_content).strip())
        elif result_type == "eval_js_file":
            self.buffer_widget.eval_js_file(str(result_content))
        elif result_type == "eval_js":
            self.buffer_widget.eval_js(str(result_content))

    def cancel_input_message(self, result_type):
        if result_type == "jump_link" or result_type == "jump_link_new_buffer" or result_type == "jump_link_background_buffer":
            self.buffer_widget.cleanup_links()

    def clear_all_cookies(self):
        self.buffer_widget.clear_cookies()
        self.message_to_emacs.emit("Cleared all cookies.")

    def try_start_aria2_daemon(self):
        if not is_port_in_use(6800):
            with open(os.devnull, "w") as null_file:
                aria2_args = ["aria2c"]

                aria2_args.append("-d")
                aria2_args.append(
                    os.path.expanduser(
                        str(self.emacs_var_dict["eaf-browser-download-path"])))

                aria2_proxy_host = str(
                    self.emacs_var_dict["eaf-browser-aria2-proxy-host"])
                aria2_proxy_port = str(
                    self.emacs_var_dict["eaf-browser-aria2-proxy-port"])

                if aria2_proxy_host != "" and aria2_proxy_port != "":
                    aria2_args.append("--all-proxy")
                    aria2_args.append("http://{0}:{1}".format(
                        aria2_proxy_host, aria2_proxy_port))

                aria2_args.append("--enable-rpc")
                aria2_args.append("--rpc-listen-all")

                subprocess.Popen(aria2_args, stdout=null_file)

    def open_download_manage_page(self):
        self.try_start_aria2_daemon()
        self.buffer_widget.open_download_manage_page()

    def copy_text(self):
        self.buffer_widget.copy_text()
        self.message_to_emacs.emit("Copy '" +
                                   self.buffer_widget.get_selection_text() +
                                   "'")

    def open_link(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Open Link: ", "jump_link")

    def open_link_new_buffer(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Open Link in New Buffer: ",
                                "jump_link_new_buffer")

    def open_link_background_buffer(self):
        self.buffer_widget.get_link_markers()
        self.send_input_message("Open Link in Background Buffer: ",
                                "jump_link_background_buffer")

    def reset_default_zoom(self):
        if hasattr(self, "buffer_widget"):
            self.buffer_widget.setZoomFactor(
                float(self.emacs_var_dict["eaf-browser-default-zoom"]))

    def edit_focus_text(self):
        text = self.buffer_widget.get_focus_text()
        if text != None:
            self.get_focus_text.emit(self.buffer_id, text)
        else:
            self.message_to_emacs.emit("No active input element.")

    def is_focus(self):
        return self.buffer_widget.get_focus_text() != None

    def record_history(self, new_title):
        new_url = self.buffer_widget.filter_url(
            self.buffer_widget.url().toString())
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true" and self.buffer_widget.filter_title(new_title) != "" and \
           self.arguments != "temp_html_file" and new_title != "about:blank" and new_url != "about:blank":
            # Throw traceback info if algorithm has bug and protection of historical record is not erased.
            try:
                noprefix_new_url_match = re.match(self.noprefix_url_pattern,
                                                  new_url)
                if noprefix_new_url_match is not None:
                    found = False
                    for history in self.history_list:
                        noprefix_url_match = re.match(
                            self.noprefix_url_pattern, history.url)
                        if noprefix_url_match is not None:
                            noprefix_url = noprefix_url_match.group(2)
                            noprefix_new_url = noprefix_new_url_match.group(2)
                            nopostfix_new_url_match = re.match(
                                self.nopostfix_url_pattern, noprefix_new_url)

                            if noprefix_url == noprefix_new_url:  # found unique url
                                history.title = new_title
                                history.url = new_url
                                history.hit += 0.5
                                found = True
                            elif nopostfix_new_url_match is not None and noprefix_url == nopostfix_new_url_match.group(
                            ):
                                # also increment parent
                                history.hit += 0.25

                    if not found:
                        self.history_list.append(
                            HistoryPage(new_title, new_url, 1))

                self.history_list.sort(key=lambda x: x.hit, reverse=True)

                with open(self.history_log_file_path, "w") as f:
                    f.writelines(
                        map(
                            lambda history: history.title + "ᛝ" + history.url +
                            "ᛡ" + str(history.hit) + "\n", self.history_list))
            except Exception:
                import traceback
                self.message_to_emacs.emit("Error in record_history: " +
                                           str(traceback.print_exc()))

    def adjust_dark_mode(self):
        try:
            if self.emacs_var_dict["eaf-browser-dark-mode"] == "true":
                self.dark_mode()
        except Exception:
            pass

    def new_blank_page(self):
        self.eval_in_emacs.emit(
            '''(eaf-open \"{0}\" \"browser\" \"\" t)'''
            ''.format(self.emacs_var_dict["eaf-browser-blank-page-url"]))

    def clear_history(self):
        if os.path.exists(self.history_log_file_path):
            os.remove(self.history_log_file_path)
            self.message_to_emacs.emit("Cleared browsing history.")
        else:
            self.message_to_emacs.emit("There is no browsing history.")

    def record_close_page(self, url):
        if self.emacs_var_dict["eaf-browser-remember-history"] == "true":
            touch(self.history_close_file_path)
            with open(self.history_close_file_path, "a") as f:
                f.write("{0}\n".format(url))

    def recover_prev_close_page(self):
        if os.path.exists(self.history_close_file_path):
            with open(self.history_close_file_path, "r") as f:
                close_urls = f.readlines()

                if len(close_urls) > 0:
                    # We need use rstrip remove \n char from url record.
                    prev_close_url = close_urls.pop().rstrip()

                    self.open_url_in_new_tab.emit(prev_close_url)
                    open(self.history_close_file_path,
                         "w").writelines(close_urls)

                    self.message_to_emacs.emit(
                        "Recovery {0}".format(prev_close_url))
                else:
                    self.message_to_emacs.emit("No page need recovery.")
        else:
            self.message_to_emacs.emit("No page need recovery.")

    def insert_or_do(func):
        def _do(self, *args, **kwargs):
            if self.is_focus():
                self.fake_key_event(self.current_event_string)
            else:
                func(self, *args, **kwargs)

        return _do

    def build_insert_or_do(self, method_name):
        def _do():
            if self.is_focus():
                self.fake_key_event(self.current_event_string)
            else:
                getattr(self, method_name)()

        setattr(self, "insert_or_{}".format(method_name), _do)

    @insert_or_do
    def insert_or_close_buffer(self):
        self.request_close_buffer()

    @insert_or_do
    def insert_or_goto_left_tab(self):
        self.goto_left_tab.emit()

    @insert_or_do
    def insert_or_goto_right_tab(self):
        self.goto_right_tab.emit()

    @insert_or_do
    def insert_or_open_url(self):
        self.eval_in_emacs.emit(
            '''(call-interactively 'eaf-open-browser-with-history)''')

    def select_all_or_input_text(self):
        if self.is_focus():
            self.buffer_widget.select_input_text()
        else:
            self.buffer_widget.select_all()

    def eval_js_file(self):
        self.send_input_message("Eval JS file: ", "eval_js_file", "file")

    def eval_js(self):
        self.send_input_message("Eval JS: ", "eval_js")

    def open_dev_tool_page(self):
        self.open_dev_tools_tab.emit(self.buffer_widget.web_page)
Example #46
0
    def __init__(self):
        super(MainWindow, self).__init__()

        self._okToClose = False
        # systray = QSystemTrayIcon(self)
        # systray.setIcon(QIcon(":/icons/icon.png"))
        # systray.show()
        # def systray_activated(reason):
        #    self.setVisible(self.isVisible() ^ True)
        # systray.activated.connect(systray_activated)

        # results
        self._incr_results = None
        self._fts_results = None
        self._found_items = None

        # status
        self._selection_pending = False
        self._loading_pending = False
        self._auto_fts_phrase = None

        # Lazy-loaded objects
        self._lazy = {}

        # Local URL scheme
        for name in _LOCAL_SCHEMES:
            scheme = QWebEngineUrlScheme(name.encode("ascii"))
            scheme.setFlags(
                QWebEngineUrlScheme.SecureScheme
                | QWebEngineUrlScheme.LocalScheme
                | QWebEngineUrlScheme.LocalAccessAllowed
                | QWebEngineUrlScheme.CorsEnabled
            )
            QWebEngineUrlScheme.registerScheme(scheme)

        self._scheme_handler = MyUrlSchemeHandler(self)
        profile = QWebEngineProfile.defaultProfile()
        for name in _LOCAL_SCHEMES:
            profile.installUrlSchemeHandler(name.encode("ascii"), self._scheme_handler)

        # Url request interceptor
        profile.setUrlRequestInterceptor(UrlRequestInterceptor(self))

        # Setup
        self._setup_ui()
        self._restore_from_config()

        # Timers
        def _makeSingleShotTimer(slot):
            timer = QTimer(self)
            timer.setSingleShot(True)
            timer.timeout.connect(slot)
            return timer

        self._timerUpdateIndex = _makeSingleShotTimer(self._updateIndex)
        self._timerAutoFTS = _makeSingleShotTimer(self._onTimerAutoFullSearchTimeout)
        self._timerAutoPron = _makeSingleShotTimer(self._onTimerAutoPronTimeout)
        self._timerSpellCorrection = _makeSingleShotTimer(self._onTimerSpellCorrection)
        self._timerSearchingLabel = _makeSingleShotTimer(self._onTimerSearchingLabel)

        # Clipboard
        clipboard = QApplication.clipboard()
        clipboard.dataChanged.connect(
            partial(self._onClipboardChanged, mode=QClipboard.Clipboard)
        )
        clipboard.selectionChanged.connect(
            partial(self._onClipboardChanged, mode=QClipboard.Selection)
        )

        # Stylesheet for the item list pane
        try:
            self._ui.listWidgetIndex.setStyleSheet(
                _load_static_data("styles/list.css").decode("utf-8", "ignore")
            )
        except EnvironmentError:
            pass

        # Check index
        QTimer.singleShot(0, self._check_index)

        # Show
        self.show()

        # Click the dock icon (macOS)
        if objc:

            def applicationShouldHandleReopen_hasVisibleWindows_(s, a, f):
                self.show()

            objc.classAddMethods(
                Cocoa.NSApplication.sharedApplication().delegate().class__(),
                [applicationShouldHandleReopen_hasVisibleWindows_],
            )