建立Chromium WebUI接口

轉載自:http://www.chromium.org/developers/webuijavascript

Chrome的WebUI是那種,在Chrome中輸入 "chrome://xxxx"就能打開一個URL頁面的對象。css

建立一個Chrome WebUI接口很是的簡單,只須要改動數個文件。html

建立WebUI頁面

webui的資源,放在資源目錄下:src/chrome/browser/resources. 當建立WebUI資源時,參考Web Development Style Guide。例如,咱們建立一個HelloWorld的頁面java

src/chrome/browser/resources/hello_world.htmlweb

<!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:chrome

p {
  white-space: pre-wrap;
}

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

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:app

+ <include name="IDR_HELLO_WORLD_HTML" file="resources\hello_world.html" type="BINDATA" />
+ <include name="IDR_HELLO_WORLD_CSS" file="resources\hello_world.css" type="BINDATA" />
+ <include name="IDR_HELLO_WORLD_JS" file="resources\hello_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:ide

+ <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)得到這個參數。

例子待序.....

相關文章
相關標籤/搜索