Xilium CefGlue 关于浏览器开发,注册JavaScript文件,并解决中文乱码
技术要求:需要对基于cef3浏览器开发有一定了解,了解浏览器运行过程中,对各模块的调用过程。
应用场景:自定义浏览器,添加自己的js函数库。本文由群友“汪博”编写,非常感谢!
转载注明“吾乐吧软件站”,原文链接:https://www.wuleba.com/?p=24795
感兴趣的,可以加入:WebKit/Blink 内核浏览器开发 QQ交流群:244840771
开发语言为:.NET/C++ 方向
实现过程:
1、 准备js文件,js文件中的函数可以先用chrome浏览器测试。本例中创建test.js的脚本文件,文件中脚本内容如下。
1
2 3 4 5 6 7 |
function MyExtFunctions(){ }
if (!MyExtFunctions)MyExtFunctions = {}; (function(){ MyExtFunctions.getinfo = function() { alert('中文行不行test.js fileload哈哈呵呵'); }; })(); |
2、 添加继承于CefRenderProcessHandler的类,这里叫MyCefRenderProcessHandler,重写OnWebKitInitialized方法,在OnWebKitInitialized方法中添加注册js脚本文件的代码,示例如下。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
protected override void OnWebKitInitialized()
{ string dir = "MyJSFilePath"; string path =System.IO.Path.GetDirectoryName(newUri(System.Reflection.Assembly.GetEntryAssembly().CodeBase).LocalPath); string fullpath = path +"\\" + dir; if (Directory.Exists(fullpath)) { string[] files =Directory.GetFiles(fullpath); foreach (string item in files) { FileInfo fi = newFileInfo(item); StreamReader objReader =new StreamReader(fi.OpenRead(), Encoding.UTF8); string javascriptCode =objReader.ReadToEnd(); objReader.Close(); CefRuntime.RegisterExtension(fi.Name, javascriptCode, null);} } else { MessageBox.Show("JS文件路径不存在"); } base.OnWebKitInitialized(); } |
3、 这样浏览器启动的时候,就会自动加载js文件,我们可以在html文件这样调用。
1
2 3 |
functionButton2_onclick() {
MyExtFunctions.getinfo(); } |
4、 打开浏览器调用到这个自定义函数后,弹出提示框,会发现中文变成了乱码,于是尝试改变读取文件的编码格式,以及js脚本文件本身保存的编码格式。
StreamReader(fi.OpenRead(), Encoding.UTF8);这里尝试各种编码都无效。
5、 结果反向跟着CefRuntime.RegisterExtension方法,查看源代码,发现varn_javascriptCode = new cef_string_t(javascriptCode_str, javascriptCode.Length);这里会将文件读取的js脚本转换成cef_string_t,然后继续跟踪,发现cef_string_t重写的tostring方法中,returnnew string((char*)obj->_str, 0, (int)obj->_length);这个还原的过程出了问题,发现对中文的解析,出现了问题,utf8中一个中文三个字节,指针中的char类型是单字节的,而c#中却不是,输出转换结果会发现,char*转成c#中的char值时不对的,有时候是负数,所以使用c#提供的默认转换机制是有问题的,这里就需要我们自己来写代码转换,如下。
1
2 3 4 5 |
Listlist = new List();
int len =(int)obj->_length; list.Add(*((byte*)(obj->_str+ i))); string ret = System.Text.Encoding.UTF8.GetString(list.ToArray()); return ret; |
6、 这回我们在浏览器中调用MyExtFunctions.getinfo();函数时就能正常显示中文了。到目前为止看似正常了,但是还有一个隐患。
7、 如果我们再浏览器中还需要做一些扩展,需要一个js函数MyExtFunctions.getinfo(obj);这个函数实现也是通过CefRuntime.RegisterExtension来注册,代码如下。
1
2 3 4 5 6 7 8 9 |
conststring MyWindowJavascriptCode = @"function MyExtFunction() {}
if (!MyExtFunction) MyExtFunction ={}; (function() { MyExtFunction.browserFunction =function(mes) { alert(mes); }; })();"; CefRuntime.RegisterExtension( "MyWindowExtensionJS",MyWindowJavascriptCode, null); |
8、 然后,我们可以在html文件这样调用。
1
2 3 |
functionButton3_onclick() {
MyExtFunction.browserFunction ('test 中文title'); } |
9、 这回居然又是乱码,原来这里的js代码被v8获取到后,也是要通过cef_string_t类中的tostring方法输出,但是这里得到char*是C#中的char类型,不是单字节,通过对(char*)obj->_str中的char逐个输出,得到结果,这里的中文都是用一个char存储,所以这里就会得出,这里的obj->_str有两个来源,一个是从js文件中载入,一个是浏览器运行后,从浏览器段传入。而且编码格式不同,需要进行识别。
10、这里我采取的办法是,同时用两种方式输出tostring的结果,然后判断其中是否含有中文的char字符,代码如下。
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
Listlist = new List();
Listlistc = newList(); int len = (int) obj - > _length; bool bret = false; for (int i = 0; i < len; i++) { list.Add (* ( (byte *) (obj - > _str + i) ) ); listc.Add (* ( (char *) (obj - > _str + i) ) ); if (Convert.ToInt32(listc[i])>= 0x4e00 && Convert.ToInt32(listc[i]) <= 0x9fff) { bret = true; } } string ret = System.Text.Encoding.UTF8.GetString (list.ToArray() ); string ret2 = newstring (listc.ToArray() ); if (bret) { return ret2; } else { return ret; } |
以上是整个解决过程,采取的办法也是应急的办法,没有继续深入去挖源代码,不过还是解决了问题,如果有更好的方式,欢迎分享交流。
下载说明:① 请不要相信网站的任何广告;② 当你使用手机访问网盘时,网盘会诱导你下载他们的APP,大家不要去下载,直接把浏览器改成“电脑模式/PC模式”访问,然后免费普通下载即可;③ 123云盘限制,必须登录后才能下载,且限制每人每天下载流量1GB,下载 123云盘免流量破解工具
版权声明:
小编:吾乐吧软件站
链接:https://wuleba.com/8077.html
来源:吾乐吧软件站
本站资源仅供个人学习交流,请于下载后 24 小时内删除,不允许用于商业用途,否则法律问题自行承担。


Malloc
lz你好,看了你的文章深受启发,但目前还是卡在一个问题上没有头绪,就是如何为CefGlue开发扩展,或者说chrome的扩展(crx后缀的文件)是否可以直接被CefGlue使用,求lz指点?
吾乐吧软件站@Malloc
首先明确告诉你,直接把crx拿来是肯定不能用的。我也想知道怎样开发他的扩展,目前没找到答案。。。。。但是我之前跟进之后发现的基本方向就是:通过注册JS,然后实现所谓的插件(简单的是可以实现的)。至于正确的做法是否如此?暂不清楚
匿名登陆
大牛,求解释一下这一句代码(最后一段代码的12行)
if (Convert.ToInt32 (listc[i]) > = 0x4e00 & amp; & Convert.ToInt32 (listc[i])