一、介紹
谷歌瀏覽器和CEF使用V8JavaScript Engine作為內容的JavaScript實現。在瀏覽器中的每個窗口都有它自己在的JS上下文提供作用域和在窗口中安全的執行JS代碼。CEF暴露大量JS功能集成在客戶端應用程序。
CEF3的Webkit和JS在單獨的渲染進程中運行。在渲染進程的主線程中使用TID_RENDERER 作為唯一標識。所有V8的執行必須放置在這個線程中。
與JS執行相關的回調函數被暴露是通過CefRenderProcessHandler接口實現。當一個新的渲染進程被初始化時通過CefApp::GetRenderProcessHandler()函數獲取這個接口。
二、執行JavaScript
在客戶端應用程序中簡單的方式執行JS使用CefFrame::ExecuteJavaScript()函數,這個函數在瀏覽進程一和渲染進程中都可用。在一個JS上下文外可安全使用。
CefRefPtr<CefBrowser> browser = ...;
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
frame->ExecuteJavaScript("alert('ExecuteJavaScript works!');", frame->GetURL(), 0);
上面的引起alert('ExecuteJavaScript works!')在瀏覽器的主窗口中執行。
在窗口的JS上下文中ExecuteJavaScript函數可用於函數和變量交互。是為了從JS到客戶端應用程序返回值使用窗口綁定和擴展。
三、窗口綁定
窗口綁定允許客戶端應用程序系上一個值到窗口的window對象上,窗口綁定的實現使用CefRenderProcessHandler::OnContextCreated()函數。
如:
void MyRenderProcessHandler::OnContextCreated( CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) { // Retrieve the context's window object. CefRefPtr<CefV8Value> object = context->GetGlobal(); // Create a new V8 string value. See the "Basic JS Types" section below. CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!"); // Add the string to the window object as "window.myval". See the "JS Objects" section below. object->SetValue("myval", str, V8_PROPERTY_ATTRIBUTE_NONE); } |
---|
JavaScript框架可以與之交互的窗口綁定。
<script language="JavaScript"> alert(window.myval); // Shows an alert box with "My Value!" </script> |
---|
窗口綁定是每次重新加載一個框架加載給客戶端應用程序在必要時更改綁定的機會。例如,不同的框架通過修改綁定框架的窗口對象值可以訪問不同的特性。
四、擴展
擴展像window綁定一樣除了為每個框架 加載到上下文之外,一旦加載就不能修改,當一個擴展已經加載並試圖在擴展加載中訪問DOM就會出現DOM不存在的crash。擴展應該在CefRenderProcessHandler::OnWebKitInitialized()函數中使用CefRegisterExtension函數注冊。
void MyRenderProcessHandler::OnWebKitInitialized() { // Define the extension contents. std::string extensionCode = "var test;" "if (!test)" " test = {};" "(function() {" " test.myval = 'My Value!';" "})();"; // Register the extension. CefRegisterExtension("v8/test", extensionCode, NULL); } |
---|
通過extensionCode描述的字符串可以是任何有效的代碼,JS框架可以和擴展代碼進行交互
<script language="JavaScript"> alert(test.myval); // Shows an alert box with "My Value!" </script> |
---|
五、基本JS類型
CEF支持基本數據類型的創建,包括:undefined, null, bool, int, double, date 和 string.這些基本數據類型使用CefV8Value::Create*()系列靜態函數創建。如創建一個JS字符串:CefRefPtr<CefV8Value> str = CefV8Value::CreateString("My Value!");
基本數據類型可在任何地方創建和在所關聯的上下文中不用初始化。如:
CefRefPtr<CefV8Value> val = ...;
if (val.IsString())
{ // The value is a string. }
使用Get*Value()系列函數獲取值:CefString strVal = val.GetStringValue();
六、JS數組
使用CefV8Value::CreateArray()靜態函數並傳遞一個長度作為參數創建數組。數組只能在上下文內部創建並使用。如:
CefRefPtr<CefV8Value> arr = CefV8Value::CreateArray(2);
值賦給一個數組使用SetValue()方法的變體,以一個索引作為第一個參數。
arr->SetValue(0, CefV8Value::CreateString("My First String!"));
arr->SetValue(1, CefV8Value::CreateString("My Second String!"));
IsArray()函數測試CefV8Value是否為數組,GetArrayLength()函數獲取數據的長度,從數組中獲取一個值使用GetValue()變體函數。
七、JS對象
使用CefV8Value::CreateObject靜態函數可帶一個可選的CefV8Accessor參數創建JS對象。對象也只能在js上下文中創建並使用。
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
使用SetValue()變體函數並以字符串key作為第一參數給對象分配值。
八、對象的訪問者
JS對象可選擇使用一個與之關聯的CefV8Accessor以提供一個源生的getting和setting值的實現。
CefRefPtr<CefV8Accessor> accessor = …;
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
CefV8Accessor接口的一個實現,必須由客戶端應用程序提供。
class MyV8Accessor : public CefV8Accessor { public: MyV8Accessor() {} virtual bool Get(const CefString& name, const CefRefPtr<CefV8Value> object, CefRefPtr<CefV8Value>& retval, CefString& exception) OVERRIDE { if (name == "myval") { // Return the value. retval = CefV8Value::CreateString(myval_); return true; } // Value does not exist. return false; } virtual bool Set(const CefString& name, const CefRefPtr<CefV8Value> object, const CefRefPtr<CefV8Value> value, CefString& exception) OVERRIDE { if (name == "myval") { if (value.IsString()) { // Store the value. myval_ = value.GetStringValue(); } else { // Throw an exception. exception = "Invalid value type"; } return true; } // Value does not exist. return false; } // Variable used for storing the value. CefString myval_; // Provide the reference counting implementation for this class. IMPLEMENT_REFCOUNTING(MyV8Accessor); }; |
---|
為了將值傳遞給訪問者必須使用SetValue()變體函數設置,接受AccessControl和PropertyAttribute參數
九、JS函數
CEF支持JS函數創建和本地實現,