最新版chromium 76如何支持xp

2019-07-11 10:43:14 浏览数 (1)

我知道,当我写下这个标题的时候,肯定一大波人会过来嘲讽:都什么年代了,还XP?

道理我都懂,但据我咨询了腾讯同事一些内部数据,XP在中国依然百之十几个点的占有率。里面最多的就是政企单位。这些电脑配置不好,比较古老了,而且关键是很多配套的软件只有xp版本。让他们升级系统?想法很好,但谁出钱找那些配套工具的厂商呢,更何况很多年久失修的软件的厂商可能早就倒闭不见了,人都找不到。

哈哈,其实我说了这么大堆,只是个借口。真实原因是有不少公司愿意出钱购买chrome支持xp的技术解决方案。我这才有动力研究了一番。

进入正题。要支持xp,要解决几个点:

补上或改掉xp下没有的系统api。 修改部分api调用参数。否则xp下可能出错。 修改部分流程,解决一些例如字体显示问题、声音播放不了等问题。 修改一些编译参数,主要是为了解决TLS问题 整个做下来,如果对chromium非常熟悉,大概1个半月可以搞定。技术难度不算很大,最麻烦的是有很多小坑要去调试找原因,这是最蛋疼的。

先看第一点,这个比较好办。把编译好的文件拿xp下看下就知道缺了哪些api。

目前有三类:

1,读写锁,条件变量相关。

这个是chromium里面用的最多的xp下没有的api。我的解决方案是自己撸了一套山寨版的api,接口和原型完全和windows原版一样。例如AcquireSRWLockExclusive、AcquireSRWLockShared这些。参考了部分ReactOS的代码(但要吐槽一下,那个代码是有bug的。我跑起来后各种断言错误)。过程比较麻烦的一点是一定要多测试,因为涉及到多线程的东西很容易藏隐藏的bug。

另外就是要夸一下windows的新api设计,读写锁和条件变量都是共用了一套机制,调用了内核的NtkeyWaitxxx系列api。而且数据结构设计成只有一个指针大小的变量,利用位运算,小心翼翼的榨干每个位的价值,而且不用event和其他锁就搞定了,十分简洁高效。这点我看其他人实现都是要用event什么的模仿,显得比较笨重了。

2,d2d、d3d系列。

这部分我直接砍掉了。不影响。因为d2d可以用GDI,D3D可以走angle或者swiftshader。这里夸一下谷歌,居然把swiftshader收购了。swiftshader是一个很古老的软件渲染器,以前是给windows或者机顶盒系统做软渲染的。谷歌果然财大气粗,为了能实现全平台全硬件利用起3D加速,真是无所不用其极。给我的感觉就是为了造一部汽车,就先买了一座铁矿。话说回来,chromium的渲染走的是opengl,但这个在windows下驱动支持的各种问题,所以谷歌会用angle把opengl转发给D3D。如果D3D启动有问题(这个很常见,很多垃圾显卡对硬件加速支持的各种bug,为此谷歌做了个显卡黑名单在chromium里,碰到了关闭硬件渲染),就走纯软件渲染,也就是swiftshader。swiftshader和angle编译出来都是libGLESv2.dll接口都一样。哪个可用就用哪个,非常爽。

3,其他杂项类api。

这个很多,有GetIfTable2,有InitPropVariantFromCLSID、RaiseFailFastException、GetUserDefaultLocaleName、SHGetPropertyStoreForWindow等等。这些其实比较好办,就是找到以前版本chromium是用哪个老api,然后替换回去就行。这类api太多了,就不在赘述。

把api全部替换完,只是万里长征第一步。下一步就是修复各种流程上的bug。

下面挑几个点讲下。

首先是字体渲染。操蛋的谷歌把老GDI渲染全部干掉,走DWrite渲染。更操蛋的是干掉就算了,还把代码都删了。其实完全可以判断下版本走哪个分支的。因为据我所知,dw在某些win7可能都还有点小bug。但谷歌是完全不管了。估计认为这些老系统没必要支持吧。所以针对这个问题,需要找到当年的patch,再把gdi渲染补充回来。

然后是声音播放不了。这个也是干掉了老的wavexxxx系列api导致。补充回来即可

再然后是srcbuildconfigwinBUILD.gn里记得加上/Zc:threadSafeInit-

原因是xp的动态tls实现的不完善。需要全部关闭掉vs的动态tls机制。但这会带来一个问题,就是有些地方可能有多线程竞争问题。这就需要一个个的修改。地方比较多,就不说了。

还有个点,就是如果要支持xp sp2,还会碰到个大麻烦,就是vs的xp工具集,编译出来的runtime,是要依赖某个xp sp2没有的api。这个我头痛了几天。最后想到个很简单的办法,就是所有dll都编译成md模式,然后把concrt14.dll做一个IAT HOOK,重定向kernel32.dll到我写的一个转发dll里。里面再实现那个api即可。要支持sp1也可以用这种方式。但sp1实在太少人用了,我估计全国可能都没有一千人,就不折腾sp1了。

此外,还有个大麻烦是沙箱。其实如果你对安全性要求不高,完全可以关闭沙箱。但我比较追求完美(其实是任务要求,蛤蛤),最后还是把沙箱跑起来了。沙箱里面很多地方是根据系统来做hook。有些hook在xp下要去掉。

最后,还有些小问题要修复,例如netcerthttp://cert_verify_proc_win.cc里要去掉ssl error的检查,防止加载不了https网站、http://file_enumerator_win.cc要修改下调用参数等等。这些大家调试一遍就知道了,比较简单。

整个过程基本就是这样,当然还有非常非常多的细节需要拿代码来讲,这里就懒得展开了。如果大家有兴趣也可以私信我交流。

总之,这种事情是个苦力活(尤其是编译和调试chromium,那叫一个慢啊,最后我实在受不了,直接花了几千块加内存加SSD)。不过看在金钱的份上,我忍了……zhic 

0 人点赞