背景
看了:http://blog.csdn.net/doon/article/details/9252327,做了一个WebUI的页面,但是过程中遇到很多问题(类名称的改变,函数名的改变等),针对我的Chromium版本修改了一下(对于最新的版本还是需要做一些改动,因为Chromium的代码更新太快了……)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
创建WebUI(Chromium25.0.1364.99)
-
什么是WebUI
WebUI就是Chrome的chrome://about/中列出来的页面。它根本上是一个html页面,但是他的数据可以从浏览器内部的C++代码获取,它可以使用js向浏览器发送消息,还可以接收浏览器发送的消息。
-
为什么要用WebUI
因为html+js与平台无关,这些页面本来需要使用平台特定的UI库来实现,而其本身又没有太多的功能要实现,只是一些简单的数据显示和存储,使用html页面就很方便,而且js在WebUI的支持下也能满足所有需求。
-
WebUI都包含哪些内容
-
一个基本的html页面,页面中包含基本的元素,由后台为其填充数据
-
js脚本文件,也可以嵌入到html页面中,与后台C++代码的通信都由js完成,后台传递过来数据后也需要js进行显示
-
一个继承自content::WebUIController的类,该类负责html页面的数据填充和消息传递
-
-
简单登录页面创建过程
-
WebUI的资源文件都位于src/chrome/browser/resources目录下,编译时会集中打到资源包文件中。首先创建一个html文件:
<!DOCTYPEHTML>
<htmli18n-values="dir:textdirection">
<head>
<metacharset="utf-8">
<titlei18n-content="helloWorldTitle"></title>
<scriptsrc="chrome://resources/js/cr.js"></script>
<scriptsrc="chrome://resources/js/load_time_data.js"></script>
<scriptsrc="chrome://resources/js/util.js"></script>
<scriptsrc="strings.js"></script>
<scriptsrc="mxlogin.js"></script>
</head>
<body
i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
<h1i18n-content="helloWorldTitle"></h1>
<pid="welcome-message"></p>
<form>
<table>
<tr>
<td>UserName:</td>
<td><inputid="username"required="required"></td>
</tr>
<tr>
<td>Password:</td>
<td><inputid="psw"required="required"></td>
</tr>
<tr>
<td></td>
<td>
<buttonid='lg'>Login</button>
</td>
</tr>
</table>
</form>
<scriptsrc="chrome://resources/js/i18n_template2.js"></script>
</body>
</html>
这里面值得注意的元素是:<h1i18n-content="helloWorldTitle"></h1>,带有i18n-content属性的元素内容可以由C++代码直接填充。
-
新建一个js脚本文件:src/chrome/browser/resources/mxlogin.js
cr.define('mxlogin',function(){
'usestrict';
functioninitialize() {
$('welcome-message').textContent= loadTimeData
.getString('welcomeMessage')
+","+ loadTimeData.getString('userName');
$('lg').onclick=function(){
if($('username').value.length==
0||$('psw').value.length== 0) {
return;
}
chrome.send('login',
[$('username').value,$('psw').value]);
}
}
functionResult(rst) {
varrst_json = JSON.parse(rst);
alert(rst_json.message);
}
//Return an object with all of the exports.
return{
initialize: initialize,
Result: Result
};
});
document.addEventListener('DOMContentLoaded',mxlogin.initialize);
这里值得注意的有cr.define和loadTimeData还有chrome.send。cr.define会在当前js环境下定义一个mxlogin对象,它具有两个属性initialize和Result,不再mxlogin对象中的函数也可以和C++通信。loadTimeData可以获取C++在WebUI中设置的值,chrome.send用来向C++传递消息和参数,这个过程是异步的,我们必须等待C++处理完成后调用js函数通知。
-
将添加的文件添加到src/chrome/browser/browser_resources.grd文件中,这样编译时才能识别到新增的文件:
<includes>
……
<includename="IDR_MX_LOGIN_HTML" file="resources\mxlogin.html"type="BINDATA" />
<includename="IDR_MX_LOGIN_JS" file="resources\mxlogin.js"type="BINDATA" />
……
</includes>
-
在chrome中所有的URL常量都声明于文件src/chrome/common/url_constants.h中,并在src/chrome/common/url_constants.cc中定义:
//url_constants.h:
namespacechrome {
……
extern constchar kMxLoginURL[];
extern constchar kMxLoginHost[];
……
//url_constants.cc
namespacechrome{
……
const charkMxLoginURL[] = "chrome://mx-login/";
const charkMxLoginHost[] = "mx-login";
……
-
添加一个处理chrome://mx-login/请求的类:
src/chrome/browser/ui/webui/mx_login_ui.h:
#ifndefCHROME_BROWSER_UI_WEBUI_MX_LOGIN_UI_H_
#defineCHROME_BROWSER_UI_WEBUI_MX_LOGIN_UI_H_
#pragma once
#include"content/public/browser/web_ui_controller.h"
namespacebase {
classListValue;
} //namespace base
classMxLoginUI : public content::WebUIController {
public:
explicitMxLoginUI(content::WebUI* web_ui);
virtual~MxLoginUI() {}
private:
content::WebUI*_web_ui;
content::WebUI*webui(){return _web_ui;}
voidLogin(const base::ListValue* args);
DISALLOW_COPY_AND_ASSIGN(MxLoginUI);
};
#endif
src/chrome/browser/ui/webui/mx_login_ui.cc:
#include"chrome/browser/ui/webui/mx_login_ui.h"
#include<iostream>
#include"chrome/browser/profiles/profile.h"
#include"base/values.h"
#include"base/bind.h"
#include"content/public/browser/web_ui.h"
#include"chrome/common/url_constants.h"
#include"chrome/browser/ui/webui/chrome_url_data_manager.h"
#include"chrome/browser/ui/webui/chrome_web_ui_data_source.h"
#include"grit/browser_resources.h"
#include"grit/generated_resources.h"
#include<string>
usingstd::string;
MxLoginUI::MxLoginUI(content::WebUI*web_ui)
:content::WebUIController(web_ui),_web_ui(web_ui) {
// Set upthe chrome://mx-login/ source.
ChromeWebUIDataSource*html_source =
newChromeWebUIDataSource(chrome::kMxLoginHost);
html_source->set_use_json_js_format_v2();
webui()->RegisterMessageCallback("login",
base::Bind(&MxLoginUI::Login,
base::Unretained(this)));
// As ademonstration of passing a variable for JS to use we pass in thename "Bob".
html_source->AddString("userName","Bob");
html_source->AddString("helloWorldTitle","MaxthonLogin");
html_source->AddString("welcomeMessage","Welcometo Maxthon");
html_source->set_json_path("strings.js");
// Addrequired resources.
html_source->add_resource_path("mxlogin.js",IDR_MX_LOGIN_JS);
html_source->set_default_resource(IDR_MX_LOGIN_HTML);
Profile*profile = Profile::FromWebUI(web_ui);
ChromeURLDataManager::AddDataSource(profile,html_source);
}
voidMxLoginUI::Login(const base::ListValue* args){
stringusername,psw;
if(args->GetString(0,&username)&&args->GetString(1,&psw))
{
MxSocketClientmxsc("user-api.user.maxthon.cn",80);
stringrst;
mxsc.SignIn(username.c_str(),psw.c_str(),rst);
base::StringValueresult(rst);
webui()->CallJavascriptFunction("mxlogin.Result",result);
webui()->CallJavascriptFunction("undefinedfunc");
}
}
这里的html_source->AddString("helloWorldTitle","MaxthonLogin");就是直接给页面中带有i18n-content=”helloWorldTitle”属性的元素填充内容,如果页面中没有对应的元素,比如html_source->AddString("userName","Bob");,则由js通过loadTimeData.GetString(“userName”)获取。
webui()->RegisterMessageCallback("login",base::Bind(&MxLoginUI::Login,base::Unretained(this)));将js传来的“login”消息交由MxLoginUI::Login函数处理,js可以通过chrome对象传递消息:chrome.send(“login”,...);
webui()->CallJavascriptFunction("mxlogin.Result",result);调用了html中定义的mxlogin.Result,并传递了一个result参数。
-
新增的代码文件需要添加到gyp文件中,在src/chrome/chrome_browser.gypi中添加:
'sources': [
……
'browser/ui/webui/mx_login_ui.h',
'browser/ui/webui/mx_login_ui.cc',
……
这样编译时就会识别到新增的两个文件。
-
在chromewebUI factory中添加请求处理程序:
src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc:
WebUIFactoryFunctionGetWebUIFactoryFunction(WebUI* web_ui,
Profile*profile,const GURL& url) {
……
if(url.host()== chrome::kMxLoginHost){
return&NewWebUI<MxLoginUI>;
}
……
-
编译代码之前需要重新处理gyp文件,因为我们在工程中新增了文件:
$ build/gyp_chromium -Dwerror= $ make chrome -j8
如果编译时因为警告而停止,而且你确定这些警告不会影响程序,可以加上参数-Dwerror
如果你的CPU支持8线程,可以在make后加上-j8
-
打开chrome://mx-login/就可以看到新增的WebUI页面
-
-
参考地址:http://www.chromium.org/developers/webui
(访问可能有障碍,GoAgent)