现在的位置: 首页 > 综合 > 正文

创建Chrome WebUI接口(Chrome内部页面)

2013年10月21日 ⁄ 综合 ⁄ 共 6515字 ⁄ 字号 评论关闭

背景

看了:http://blog.csdn.net/doon/article/details/9252327,做了一个WebUI的页面,但是过程中遇到很多问题(类名称的改变,函数名的改变等),针对我的Chromium版本修改了一下(对于最新的版本还是需要做一些改动,因为Chromium的代码更新太快了……)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

创建WebUIChromium25.0.1364.99)

  1. 什么是WebUI

    WebUI就是Chromechrome://about/中列出来的页面。它根本上是一个html页面,但是他的数据可以从浏览器内部的C++代码获取,它可以使用js向浏览器发送消息,还可以接收浏览器发送的消息。

  2. 为什么要用WebUI

    因为html+js与平台无关,这些页面本来需要使用平台特定的UI库来实现,而其本身又没有太多的功能要实现,只是一些简单的数据显示和存储,使用html页面就很方便,而且jsWebUI的支持下也能满足所有需求。

  3. WebUI都包含哪些内容

    1. 一个基本的html页面,页面中包含基本的元素,由后台为其填充数据

    2. js脚本文件,也可以嵌入到html页面中,与后台C++代码的通信都由js完成,后台传递过来数据后也需要js进行显示

    3. 一个继承自content::WebUIController的类,该类负责html页面的数据填充和消息传递

  4. 简单登录页面创建过程

    1. 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++代码直接填充。

    2. 新建一个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.defineloadTimeData还有chrome.sendcr.define会在当前js环境下定义一个mxlogin对象,它具有两个属性initializeResult,不再mxlogin对象中的函数也可以和C++通信。loadTimeData可以获取C++WebUI中设置的值,chrome.send用来向C++传递消息和参数,这个过程是异步的,我们必须等待C++处理完成后调用js函数通知。

    3. 将添加的文件添加到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>

    4. 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";

      ……

    5. 添加一个处理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参数。

    6. 新增的代码文件需要添加到gyp文件中,在src/chrome/chrome_browser.gypi中添加:

      'sources': [

      ……

      'browser/ui/webui/mx_login_ui.h',

      'browser/ui/webui/mx_login_ui.cc',

      ……

      这样编译时就会识别到新增的两个文件。

    7. 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>;

      }

      ……

    8. 编译代码之前需要重新处理gyp文件,因为我们在工程中新增了文件:

      $ build/gyp_chromium -Dwerror=
      $ make chrome -j8

      如果编译时因为警告而停止,而且你确定这些警告不会影响程序,可以加上参数-Dwerror

      如果你的CPU支持8线程,可以在make后加上-j8

    9. 打开chrome://mx-login/就可以看到新增的WebUI页面

  5. 参考地址:http://www.chromium.org/developers/webui 
    (访问可能有障碍,GoAgent)

抱歉!评论已关闭.