轉載自:http://www.chromium.org/developers/webuijavascript
Chrome的WebUI是那種,在Chrome中輸入 "chrome://xxxx"就能打開一個URL頁面的對象。css
建立一個Chrome WebUI接口很是的簡單,只須要改動數個文件。html
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" />
+ 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>
下面咱們增長一個新的類來處理新的資源。一般狀況下,它是ChromeWebUI的一個子類(WebUI對話框則從HtmlDialogUI繼承)
#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文件中
'sources': [ ... + 'browser/ui/webui/hello_world_ui.cc', + 'browser/ui/webui/hello_world_ui.h',
WebUI的工廠負責響應並建立你的請求
+ #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引擎的兩個整數相加(由於咱們知道,它內部是使用浮點數的)。咱們能夠增長回調句柄來處理咱們的整數運算。
#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 Dialog。你必須從HtmlDialogUI繼承,並建立一個HtmlDialogUIDelegate類。
1. 替換ChromeWebUI爲HtmlDialogUIDelegate
- #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
#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。
你可能猜到HtmlDialogUIDelegate::GetDialogArgs()函數是用來傳遞參數給對話框頁的。例如,若是咱們但願顯示一個自定義的消息給用戶,這個自定義消息是在建立對話框時傳遞給它,並由GetDialogArgs返回,並在javascript中經過chrome.dialogArguments來返回。例子以下:
- 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)得到這個參數。
例子待序.....