想给 eaf browser 加个黑白名单代理插件遇到个问题

用了一段时间的eaf browser后,发现自己经常需要访问一些内网服务和google,所以需要频繁切换代理,然后想着给eaf browser实现一个类似pac的黑白名单插件

大概的主体思路就是想在 QNetworkProxyFactoryqueryProxy 判断黑白名单然后来返回不同的ProxyList

但是,调试的时候发现在queryProxyquery.url().toString()取到的 url 总是空的。无法拿来匹配黑白名单的规则

    def queryProxy(self, query=None, *args, **kwargs):
        protocol = str(query.protocolTag())
        url = str(query.url().toString())

        if self.shouldUseDefault(protocol, url):
            return self._defaultProxyList()

        return self._customProxyList()

    def shouldUseDefault(self, protocol, url):
        if not self.proxy:
            return True

        if any(re.match(p, url) if isinstance(p, str) else False for p in self.blacklist):
            return False

        if any(re.match(p, url) if isinstance(p, str) else False for p in self.whitelist):
            return True

        return bool(self.blacklist)

    def _defaultProxyList(self):
        return [QNetworkProxy(QNetworkProxy.NoProxy)]

google 了一番得回来得结论感觉是QtWebEnginebug,无果

不知道有没有大佬有更加了解的或者有其他思路的呢?

目前的code:

https://github.com/emacs-eaf/emacs-application-framework/compare/master...EdmondFrank:feat-proxy-plugin?expand=1

要从操作系统看,看看有啥流量重定向的方法,估计更好弄。

我以前折腾过,qwebengine没法自定义规则,没折腾起。

试一下用 BrowserView 的 get_url() 函数?

嗯,好像这也是一个思路

加油,欢迎发送补丁, 这个功能很实用。

提了个PR,不过感觉实现的方案不是特别好 :joy:

我怎么感觉逻辑不对啊,BlackWhiteQNetworkProxyFactory感觉是一个全局规则,get_emacs_buffer_url是获取当前显示 Buffer 的 url 作为黑白名单对比。

这个 BlackWhiteQNetworkProxyFactory 不应该跟每个浏览器页面的 URL 对比吗?

按照这个PR, 我在网页里面切换一下,代理逻辑就会乱啊。

是的,最好的方式应该是这个帖子上面一开始提到的 QtNetwork.QNetworkProxyFactory.queryProxy[query=QNetworkProxyQuery()]来获取 url,但是感觉 QtWebEngine 有bug,获取到的 url 总是空的;然后,我又尝试了通过调用 eaf-get-path-or-url 来获取每个浏览器页面对应的 url 的,但是性能太差了,python 和 elisp 的 epc 频繁往复调用容易导致超时。然后,最后写下了这个方案,获取当前 buffer 的 url,这个方案存在的问题,就是大大说的,在切换buffer的时候,url 会不一致,但是在目标 buffer 等待页面加载的时候是 work 的。

应该是你用的方法有问题,我看网上说的 QNetworkProxyFactory 应该和 QNetworkAccessManager 配合着用,关键的函数:

  1. QNetworkAccessManager.setProxyFactory
  2. WebPage.setNetworkAccessManager
  3. query.protocolTag()

你看一下这个下面这几个链接,参考一下别人的实现:

https://github.com/yeyanchao/calibre/blob/e4d06dd27cd4d9139f5acaabda6e11804ab4734b/src/calibre/web/jsbrowser/browser.py

感谢大大,我看看

还有个下载器的代码

QNetworkProxyFactory 和 QNetworkAccessManager 配合用

https://wiki.qt.io/QtWebEngine/Porting_from_QtWebKit

看官方文档的描述,Qt WebEngine 似乎并不能配合着 QNetWorkAccessManager 来使用

用webpage,webpage可以用,你看我上面发的两个链接。

webpage是webengineview的属性

QWebEnginePage 应该才是 WebEngineView的属性

是呀,我的意思是,你按照下面的逻辑来做:

  1. WebEngineView 调用 QWebEnginePage
  2. QWebEnginePage 调用 setNetworkAccessManager
  3. QNetworkAccessManager 调用 setProxyFactory
  4. QProxyFactory 调用 queryProxy 设置代理规则

我估计你按照上面的调用顺序来设置, 你最早的 query.url() 的问题就可以解决

嗯,这个你想表达的流程我了解,但是

QWebEnginePage 并不支持 setNetworkAccessManager

https://doc.qt.io/qt-5/qwebenginepage.html

似乎基于chromium 的 QWebEngine并没有太多Proxy的支持,而NetWorkAccessManager 这些都是基于Webkit的QtWebKit

嗯,那我建议直接操作系统底层库入手,针对EAF进程进行URL规则过滤,不用QT的方法

嗯嗯,还是感谢懒猫大大的耐心回复,和大大的讨论交流中不断查阅文档,我也逐渐知道,是chromium 本身限制了,而不是QtWebEngine的实现bug,哈哈哈。

目前来说,可能直接从系统入手,或者代理层入手设置url规则才是最好的方式。不过,上面的类似 get_url的方式对我来说也能work (本来还想给eaf贡献贡献的,不过这种蹩脚的实现还是自己玩玩好了),我看看还没有什么优化思路。 :grimacing:

懒猫大大,我又查了下Qt的文档,在QtWebEngine下 QWebEngineUrlRequestInterceptor有类似 QProxyFactory 的 queryProxy的捕获请求的功能,基于QWebEngineUrlRequestInterceptor 改了下,我又提交了一版代码。

1 个赞

好的,我周末要带小朋友出去玩一下,估计要晚上回家才能 review code 了,耐心等一下哈。