zoukankan      html  css  js  c++  java
  • 创建Chromium WebUI接口

    转载自:http://www.chromium.org/developers/webui

    Chrome的WebUI是那种,在Chrome中输入 "chrome://xxxx"就能打开一个URL页面的对象。

    创建一个Chrome WebUI接口非常的简单,只需要改动数个文件。

    创建WebUI页面

    webui的资源,放在资源目录下:src/chrome/browser/resources. 当创建WebUI资源时,参考Web Development Style Guide。例如,我们创建一个HelloWorld的页面

    src/chrome/browser/resources/hello_world.html

    <!DOCTYPE HTML>
    <html i18n-values="dir:textdirection">
    <head>
     <meta charset="utf-8">
     <title i18n-content="helloWorldTitle"></title>
     <link
     rel="stylesheet" href="hello_world.css">
    <script src="chrome://resources/js/cr.js"></script>
    <script src="chrome://resources/js/load_time_data.js"></script>
    <script src="chrome://resources/js/util.js"></script>
     <script
     src="strings.js"></script>
     <script
     src="hello_world.js"></script>
    </head>
    <body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
      <h1 i18n-content="helloWorldTitle"></h1>
      <p id="welcome-message"></p>
    <script
     src="chrome://resources/js/i18n_template2.js"></script>
    </body>
    </html>

    src/chrome/browser/resources/hello_world.css:

    p {
      white-space: pre-wrap;
    }

    src/chrome/browser/resources/hello_world.js:

    cr.define('hello_world', function() {
      'use strict';
      /**
       * Be polite and insert translated hello world strings for the user on loading.
       */
      function initialize() {
        $('welcome-message').textContent = loadTimeData.getStringF('welcomeMessage',
            loadTimeData.getString('userName'));
      }
    
      // Return an object with all of the exports.
      return {
        initialize: initialize,
      };
    });
    
    document.addEventListener('DOMContentLoaded', hello_world.initialize);

    资源信息应该添加到Chrome使用的src/chrome/browser/browser_resources.grd文件中。
    src/chrome/browser/browser_resources.grd:

    + <include name="IDR_HELLO_WORLD_HTML" file="resourceshello_world.html" type="BINDATA" />
    + <include name="IDR_HELLO_WORLD_CSS" file="resourceshello_world.css" type="BINDATA" />
    + <include name="IDR_HELLO_WORLD_JS" file="resourceshello_world.js" type="BINDATA" /> 

    添加URL标识到新的Chrome URL中

    URL标识被保存在src/chrome/common/url_constants.*文件中。
    src/chrome/common/url_constants.h:
     
    + extern const char kChromeUIHelloWorldURL[];
    ...
    + extern const char kChromeUIHelloWorldHost[];

    src/chrome/common/url_constants.cc:

    + const char kChromeUIHelloWorldURL[] = "chrome://hello-world/";
    ...
    + const char kChromeUIHelloWorldHost[] = "hello-world";


    添加本地字符串

    我们需要为新的资源添加新的本地化字符串。比如一个欢迎信息
    src/chrome/app/generated_resources.grd:

    + <message name="IDS_HELLO_WORLD_TITLE" desc="A happy message saying hello to the world">
    +   Hello World!
    + </message>
    + <message name="IDS_HELLO_WORLD_WELCOME_TEXT" desc="Message welcoming the user to the hello world page">
    +   Welcome to this fancy Hello World page <ph name="WELCOME_NAME">$1<ex>Chromium User</ex></ph>!
    + </message>

     

     

    添加处理chrome://hello-world/请求的WebUI类

     

    下面我们增加一个新的类来处理新的资源。通常情况下,它是ChromeWebUI的一个子类(WebUI对话框则从HtmlDialogUI继承)

    src/chrome/browser/ui/webui/hello_world_ui.h:
    #ifndef CHROME_BROWSER_UI_WEBUI_HELLO_WORLD_UI_H_
    #define CHROME_BROWSER_UI_WEBUI_HELLO_WORLD_UI_H_
    #pragma once
    
    #include "content/public/browser/web_ui_controller.h"
    
    // The WebUI for chrome://hello-world
    class HelloWorldUI : public content::WebUIController {
     public:
      explicit HelloWorldUI(content::WebUI* web_ui);
      virtual ~HelloWorldUI();
     private: 
      DISALLOW_COPY_AND_ASSIGN(HelloWorldUI);
    };
    
    #endif  // CHROME_BROWSER_UI_WEBUI_HELLO_WORLD_UI_H_

    src/chrome/browser/ui/webui/hello_world_ui.cc:

    #include "chrome/browser/ui/webui/hello_world_ui.h"
    
    #include "chrome/browser/profiles/profile.h"
    #include "chrome/common/url_constants.h"
    #include "content/public/browser/web_ui_data_source.h"
    #include "grit/browser_resources.h"
    #include "grit/generated_resources.h"
    
    HelloWorldUI::HelloWorldUI(content::WebUI* web_ui)
        : content::WebUIController(web_ui) {
      // Set up the chrome://hello-world source.
      content::WebUIDataSource* html_source =
          new content::WebUIDataSource(chrome::kChromeUIHelloWorldHost);
      html_source->SetUseJsonJSFormatV2();
    
      // Localized strings.
      html_source->AddLocalizedString("helloWorldTitle", IDS_HELLO_WORLD_TITLE);
      html_source->AddLocalizedString("welcomeMessage", IDS_HELLO_WORLD_WELCOME_TEXT);
    
      // As a demonstration of passing a variable for JS to use we pass in the name "Bob".
      html_source->AddString("userName", "Bob");
      html_source->SetJsonPath("strings.js");
    
      // Add required resources.
      html_source->AddResourcePath("hello_world.css", IDR_HELLO_WORLD_CSS);
      html_source->AddResourcePath("hello_world.js", IDR_HELLO_WORLD_JS);
      html_source->SetDefaultResource(IDR_HELLO_WORLD_HTML);
    
      Profile* profile = Profile::FromWebUI(web_ui);
      content::WebUIDataSource::Add(profile, html_source);
    }
    
    HelloWorldUI::~HelloWorldUI() {
    }

    编译新的类,需要添加到工程的gyp文件中

    src/chrome/chrome_browser_ui.gypi:
    'sources': [
    ...
    +   'browser/ui/webui/hello_world_ui.cc',
    +   'browser/ui/webui/hello_world_ui.h',

    添加WebUI请求到Chrome WebUI工厂

    WebUI的工厂负责响应并创建你的请求

    src/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc:
    + #include "chrome/browser/ui/webui/hello_world_ui.h"
    ...
    + if (url.host() == chrome::kChromeUIHelloWorldHost)
    +   return &NewWebUI<HelloWorldUI>;

    测试

    OK!假定没有错误,你可以编译和运行chrome了。并在地址栏输入 chrome:://hello-world/ 你将看到欢迎信息。

    增加回调处理句柄

    你也许你问新的WebUI页面能够做些什么事情,或者从C++世界获取一些信息。为此,我们使用消息回调句柄。 假设我们不信任JavaScript引擎的两个整数相加(因为我们知道,它内部是使用浮点数的)。我们可以增加回调句柄来处理我们的整数运算。

    src/chrome/browser/ui/webui/hello_world_ui.h:
    #include "chrome/browser/ui/webui/chrome_web_ui.h"
    + namespace base {
    +   class ListValue;
    + }  // namespace base
    // The WebUI for chrome://hello-world
    ...
        // Set up the chrome://hello-world source.
        ChromeWebUIDataSource* html_source =
            new ChromeWebUIDataSource(chrome::kChromeUIHelloWorldHost);
    +   // Register callback handler.
    +   RegisterMessageCallback("addNumbers",
    +       base::Bind(&HelloWorldUI::AddNumbers,
    +                  base::Unretained(this)));
        // Localized strings.
    ...
        virtual ~HelloWorldUI();
    +
    +  private:
    +   // Add two numbers together using integer arithmetic.
    +   void AddNumbers(const base::ListValue* args);
        DISALLOW_COPY_AND_ASSIGN(HelloWorldUI);
      };

    src/chrome/browser/ui/webui/hello_world_ui.cc:

    #include "chrome/browser/ui/webui/hello_world_ui.h"
    +
    + #include "base/values.h"
      #include "chrome/browser/profiles/profile.h"
    ...
      HelloWorldUI::~HelloWorldUI() {
      }
    +
    + void HelloWorldUI::AddNumbers(const base::ListValue* args) {
    +   int term1, term2;
    +   if (!args->GetInteger(0, &term1) || !args->GetInteger(1, &term2))
    +     return;
    +   base::FundamentalValue result(term1 + term2);
    +   CallJavascriptFunction("hello_world.addResult", result);
    + }

    src/chrome/browser/resources/hello_world.js:

        function initialize() {
    +     chrome.send('addNumbers', [2, 2]);
        }
    +
    +   function addResult(result) {
    +     alert('The result of our C++ arithmetic: 2 + 2 = ' + result);
    +   }
        return {
    +     addResult: addResult,
          initialize: initialize,
        };

    请注意调用是异步的。我们必须等待C++端主带调用javascript的函数才能获取到结果。

    创建WebUI对话框

    一旦你按照上面的步骤创建了一个WebUI,你需要修改两个地方来创建一个WebUI Dialog。你必须从HtmlDialogUI继承,并创建一个HtmlDialogUIDelegate类。

    1. 替换ChromeWebUI为HtmlDialogUIDelegate

    src/chrome/browser/ui/webui/hello_world_ui.h:
    - #include "#chrome/browser/ui/webui/chrome_web_ui.h"
    + #include "#chrome/browser/ui/webui/html_dialog_ui.h"
    - class HelloWorldUI : public ChromeWebUI {
    + class HelloWorldUI : public HtmlDialogUI {

    2. 创建一个HtmlDialogUIDelegage

    src/chrome/browser/ui/webui/hello_world.h
    #ifndef CHROME_BROWSER_UI_WEBUI_HELLO_WORLD_H_
    #define CHROME_BROWSER_UI_WEBUI_HELLO_WORLD_H_
    #pragma once
    #include "chrome/browser/ui/webui/html_dialog_ui.h"
    class HelloWorldDialog : private HtmlDialogUIDelegate {
     public:
      // Shows the Hello World dialog.
      static void ShowDialog();
      virtual ~HelloWorldDialog();
     private:
      // Construct a Hello World dialog
      explicit HelloWorldDialog();
      // Overridden from HtmlDialogUI::Delegate:
      virtual bool IsDialogModal() const OVERRIDE;
      virtual string16 GetDialogTitle() const OVERRIDE;
      virtual GURL GetDialogContentURL() const OVERRIDE;
      virtual void GetWebUIMessageHandlers(
          std::vector<WebUIMessageHandler*>* handlers) const OVERRIDE;
      virtual void GetDialogSize(gfx::Size* size) const OVERRIDE;
      virtual std::string GetDialogArgs() const OVERRIDE;
      virtual void OnDialogClosed(const std::string& json_retval) OVERRIDE;
      virtual void OnCloseContents(
          TabContents* source, bool* out_close_dialog) OVERRIDE;
      virtual bool ShouldShowDialogTitle() const OVERRIDE;
    
      DISALLOW_COPY_AND_ASSIGN(HelloWorldDialog);
    };
    #endif  // CHROME_BROWSER_UI_WEBUI_HELLO_WORLD_H_

    src/chrome/browser/ui/webui/hello_world.cc

    #include "base/utf_string_conversions.h"
    #include "chrome/browser/ui/browser.h"
    #include "chrome/browser/ui/browser_list.h"
    #include "chrome/browser/ui/webui/hello_world.h"
    #include "chrome/common/url_constants.h"
    void HelloWorldDialog::ShowDialog() {
      Browser* browser = BrowserList::GetLastActive();
      DCHECK(browser);
      browser->BrowserShowHtmlDialog(new HelloWorldDialog(), NULL);
    }
    HelloWorldDialog::HelloWorldDialog() {
    }
    HelloWorldDialog::~HelloWorldDialog() {
    }
    bool HelloWorldDialog::IsDialogModal() {
      return false;
    }
    string16 HelloWorldDialog::GetDialogTitle() {
      return UTF8ToUTF16("Hello World");
    }
    GURL HelloWorldDialog::GetDialogContentURL() const {
      return GURL(chrome::kChromeUIHelloWorldURL);
    }
    void HelloWorldDialog::GetWebUIMessageHandlers(
        std::vector<WebUIMessageHandler*>* handlers) const {
    }
    void HelloWorldDialog::GetDialogSize(gfx::Size* size) const {
      size->SetSize(600, 400);
    }
    std::string HelloWorldDialog::GetDialogArgs() const {
      return std::string();
    }
    void HelloWorldDialog::OnDialogClosed(const std::string& json_retval) {
      delete this;
    }
    void HelloWorldDialog::OnCloseContents(TabContents* source,
        bool* out_close_dialog) {
      if (out_close_dialog)
        *out_close_dialog = true;
    }
    bool HelloWorldDialog::ShouldShowDialogTitle() const {
      return true;
    }

    你需要通过HelloWroldDialog::ShowDialog来创建一个新的dialog。

    传递参数给WebUI

    你可能猜到HtmlDialogUIDelegate::GetDialogArgs()函数是用来传递参数给对话框页的。例如,如果我们希望显示一个自定义的消息给用户,这个自定义消息是在创建对话框时传递给它,并由GetDialogArgs返回,并在javascript中通过chrome.dialogArguments来返回。例子如下:

    src/chrome/browser/ui/webui/hello_world.h
    -   static void ShowDialog();
    +   static void ShowDialog(std::string message);
    +   // The message to be displayed to the user.
    +   std::string message_;
        DISALLOW_COPY_AND_ASSIGN(HelloWorldDialog);
      };

    src/chrome/browser/ui/webui/hello_world.cc

    - HelloWorldDialog::HelloWorldDialog() {
    + HelloWorldDialog::HelloWorldDialog(std::string message)
    +     : message_(message) {
      }
      std::string HelloWorldDialog::GetDialogArgs() const {
    -   return std::string();
    +   return message_;
      }

    src/chrome/browser/resources/hello_world.js:

     function initialize() {
    +     document.getElementsByTagName('p')[0].textContent = chrome.dialogArguments;
        }

    实际上,你可以传递一个结构体给你的WebUI。你可以通过base::JSONWriter来产生一个JSON字符串,在javascript端通过JSON.parse(chrome.dialogArguments)获得这个参数。

    例子待序.....

  • 相关阅读:
    spring3.0使用annotation完全代替XML(续)
    spring3.0使用annotation完全代替XML
    Hibernate Session中的save(),update(),delete(),saveOrUpdate() 细粒度分析
    SpringMVC介绍之Validation
    Mysql 5.7 使用SSL安全连接
    深入分析Java ClassLoader原理
    Hibernate 动态分页查询
    【翻译自mos文章】Linux的/var/log/messages是空的(0k),messages.0, messages.1也是空的
    <html>
    Android Notification和权限机制探讨
  • 原文地址:https://www.cnblogs.com/yanayana/p/6690228.html
Copyright © 2011-2022 走看看