Xilium CefGlue 关于浏览器开发,注册JavaScript文件,并解决中文乱码

作者: 时间: 2014-02-23 分类: 技术文章 | 3 评论数 |

技术要求:需要对基于cef3浏览器开发有一定了解,了解浏览器运行过程中,对各模块的调用过程。

应用场景:自定义浏览器,添加自己的js函数库。本文由群友“汪博”编写,非常感谢!

转载注明“吾乐吧软件站”,原文链接:http://www.wuleba.com/?p=24795

感兴趣的,可以加入:WebKit/Blink 内核浏览器开发 QQ交流群:244840771

开发语言为:.NET/C++ 方向

实现过程:

1、 准备js文件,js文件中的函数可以先用chrome浏览器测试。本例中创建test.js的脚本文件,文件中脚本内容如下。

 C# Code By WuleBa.COM
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脚本文件的代码,示例如下。

 C# Code By WuleBa.COM
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文件这样调用。

 C# Code By WuleBa.COM
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#提供的默认转换机制是有问题的,这里就需要我们自己来写代码转换,如下。

 C# Code By WuleBa.COM
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来注册,代码如下。

 C# Code By WuleBa.COM
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文件这样调用。

 C# Code By WuleBa.COM
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字符,代码如下。

 C# Code By WuleBa.COM
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;
}

以上是整个解决过程,采取的办法也是应急的办法,没有继续深入去挖源代码,不过还是解决了问题,如果有更好的方式,欢迎分享交流。

本文采用 CC协议 发布,转载请注明:转载自 吾乐吧软件站

本文链接地址:http://www.wuleba.com/?p=24795

3 条评论 给“Xilium CefGlue 关于浏览器开发,注册JavaScript文件,并解决中文乱码”

  1. 大牛,求解释一下这一句代码(最后一段代码的12行)
    if (Convert.ToInt32 (listc[i]) > = 0x4e00 & amp; & Convert.ToInt32 (listc[i])

  2. lz你好,看了你的文章深受启发,但目前还是卡在一个问题上没有头绪,就是如何为CefGlue开发扩展,或者说chrome的扩展(crx后缀的文件)是否可以直接被CefGlue使用,求lz指点?

    • 首先明确告诉你,直接把crx拿来是肯定不能用的。我也想知道怎样开发他的扩展,目前没找到答案。。。。。但是我之前跟进之后发现的基本方向就是:通过注册JS,然后实现所谓的插件(简单的是可以实现的)。至于正确的做法是否如此?暂不清楚

发表评论


微软MSDN资源免费订阅,MSDN 我告诉你