• CEF(Chromium Embedded Framework和JavaScript交互相互调用函数和设置数据


    3.1     CEF和JavaScript交互

    3.1.1     在CEF执行JavaScript脚本

    3.1.2     窗口绑定方式实现CEF设置JavaScript的变量

    3.1.3     扩展方式(Extension)实现CEF设置JavaScript的变量

    3.1.4     窗口绑定方式实现CEF给JavaScript提供函数

    3.1.5     Extension方式实现CEF给JavaScript提供函数

    3.1  CEF和JavaScript交互

    https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md

    CEF使用的V8 JavaScript 引擎用于内部JavaScript实现,每一个frame都有JS上下文(context),为JS代码执行提供范围和安全。CEF暴露了很多JS特性可以和客户端程序进行交互。

    3.1.1         在CEF执行JavaScript脚本

    应用场景是需要在CEF中拦截一个URL请求,并把它重定向到另外一个URL,可以调用pFrame->ExecuteJavaScript来执行一个JavaScript脚本,实现跳转。当然也可以实现其他应用功能。

    CefRefPtr<CefFrame> pFrame = browser->GetMainFrame();

            std::string strurl = pFrame->GetURL().ToString();

            std::string strname = pFrame->GetName().ToString();

    pFrame->GetName().ToString().c_str());

            if (pFrame->GetURL() == "https://10.19.141.75/portal/")

            {

                             pFrame->ExecuteJavaScript("var param= { url:'https://10.19.141.75/ishelf-web/personalCenter' };

                             window.goToApp(param);

                         var paramEx = { isExtend:true };

                         window.extendScreen(paramEx);

                     ", pFrame->GetURL(), 0);

            }

    3.1.2         窗口绑定方式实现CEF设置JavaScript的变量

    在CEF程序中,创建一个CefV8Value对象,获取上下文的窗口对象,注入窗口对象一个变量值,网页中就可以使用JavaScript获取这个变量值。窗口绑定在CefRenderProcessHandler::OnContextCreated()函数中。是上下文创建响应函数,窗口绑定方式在每次frame重新加载(context创建)时都会加载一遍,CEF程序可以在OnContextCreated()给每一个frame设置不同的变量值。

        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 in the frame can then interact with the window bindings.

    <script language="JavaScript">

    alert(window.myval); // Shows an alert box with "My Value!"

    </script>

    3.1.3         扩展方式(Extension)实现CEF设置JavaScript的变量

    Extension方式和窗口绑定方式类似,但是Extension方式是为每一个frame加载到上下文context,一旦加载变不能在修改,没有加载之前,DOM是不存在的,尝试范围这个值的DOM会出现崩溃。Extension方式是在CefRenderProcessHandler::OnWebKitInitialized()函数中用CefRegisterExtension() 函数注册的,是在初始化函数中实现的,所以对于每一个frame都是一样的。

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

    }

    JS中调用变量值

    <script language="JavaScript">

    alert(test.myval); // Shows an alert box with "My Value!"

    </script>

    3.1.4         窗口绑定方式实现CEF给JavaScript提供函数

    (1)   自定义类实现CefV8Handler类,实现Execute接口,JavaScript执行函数后,会将函数名称、参数和返回值引用传递给Execute函数,Execute函数根据函数名去调用函数,函数的具体实现在Execute中,然后执行返回返回值。

    class MyV8Handler : public CefV8Handler {

    public:

      MyV8Handler() {}

      virtual bool Execute(const CefString& name,

                           CefRefPtr<CefV8Value> object,

                           const CefV8ValueList& arguments,

                           CefRefPtr<CefV8Value>& retval,

                           CefString& exception) OVERRIDE {

        if (name == "myfunc") {

          // Return my string value.

          retval = CefV8Value::CreateString("My Value!");

          return true;

        }

        // Function does not exist.

        return false;

      }

      // Provide the reference counting implementation for this class.

      IMPLEMENT_REFCOUNTING(MyV8Handler);

    };

    (2)将函数名称设置到窗口对象,提供接受调用的handle

    void MyRenderProcessHandler::OnContextCreated(

        CefRefPtr<CefBrowser> browser,

        CefRefPtr<CefFrame> frame,

        CefRefPtr<CefV8Context> context) {

      // Retrieve the context's window object.

      CefRefPtr<CefV8Value> object = context->GetGlobal();

      // Create an instance of my CefV8Handler object.

      CefRefPtr<CefV8Handler> handler = new MyV8Handler();

      // Create the "myfunc" function.

      CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);

      // Add the "myfunc" function to the "window" object.

      object->SetValue("myfunc", func, V8_PROPERTY_ATTRIBUTE_NONE);

    }

    (3)JavaScript执行函数调用,就会进入Execute函数,返回返回值,alert会以弹窗形式展示结果。

    <script language="JavaScript">
    alert(window.myfunc()); // Shows an alert box with "My Value!"
    </script>

    3.1.5         Extension方式实现CEF给JavaScript提供函数

    JavaScript调用CEF中的函数步骤:

    (1)实现app类,继承与CefApp,重写OnWebKitInitialized,在OnWebKitInitialized函数内部使用字符串定义函数。CEF调用CefRegisterExtension函数向JavaScript注册函数,并提供处理调用的handler。

    //CefClientApp.h

    class CCefClientApp : public CefApp, public CefBrowserProcessHandler, CefRenderProcessHandler

    {

    public:

        CCefClientApp();

        ~CCefClientApp();

     

     

        //所有的CEF接口 都需要重载GetXXXHandler,并且return this,才会有效

        virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }

     

        //===========CefRenderProcessHandler

        virtual void OnWebKitInitialized() override;

     

    private:

        CefRefPtr<CCEFV8HandlerEx> v8Handler_;

        // Include the default reference counting implementation.

        IMPLEMENT_REFCOUNTING(CCefClientApp);

     

    private:

     

    };

     

    //CefClientApp.cpp

     

    void CCefClientApp::OnWebKitInitialized()

    {

        //MessageBox(NULL,L"OnWebKitInitialized ",0,0);

        std::string app_code =

            //-----------------------------------

            //声明JavaScript里要调用的Cpp方法

            "var app;"

            "if (!app)"

            "  app = {};"

            "(function() {"

     

            //  jsInvokeCPlusPlus 实例函数

            "  app.jsInvokeCPlusPlus = function(v1, v2) {"

            "    native function jsInvokeCPlusPlus();"

            "    return jsInvokeCPlusPlus(v1, v2);"

            "  };"

     

            //函数

            "  app.jsTransform = function(v1) {"

            "    native function jsTransform();"

            "    return jsTransform(v1);"

            "  };"

     

            "})();";

     

     

        // Register app extension module

     

        // JavaScript里调用app.jsInvokeCPlusPlus时,就会去通过CefRegisterExtension注册的CefV8Handler列表里查找

        // 找到"v8/app"对应的CCEFV8HandlerEx,就调用它的Execute方法

        // 假设v8Handler_是CCefClientApp的一个成员变量

        //v8Handler_ = new CCEFV8HandlerEx();

     

        CefRegisterExtension("v8/app", app_code, v8Handler_);

     

    }

    (2)JavaScript调用函数

    <html>

    <script>

    app.jsInvokeCPlusPlus("123","xyz");

    app.jsTransform("hello world");

    </script>

    </html>

    (3)    handler的Execute函数接收调用响应,根据函数名称判断是调用哪个函数,获取参数调用函数。

    //CEFV8HandlerEx.h
     
    class CCEFV8HandlerEx : public CefV8Handler {
    public:
        CCEFV8HandlerEx();
        ~CCEFV8HandlerEx();
    public:
        virtual bool Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception) override;
    private:
        // Map of message callbacks.
        typedef std::map<std::pair<std::string, int>, std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value> > >CallbackMap;
        CallbackMap callback_map_;
     
     
    public:
        IMPLEMENT_REFCOUNTING(CCEFV8HandlerEx);
    };
     
    //CEFV8HandlerEx.cpp
     
    //JS调用C++函数的回调
    bool CCEFV8HandlerEx::Execute(const CefString& name  /*JavaScript调用的C++方法名字*/, CefRefPtr<CefV8Value> object /*JavaScript调用者对象*/, const CefV8ValueList& arguments /*JavaScript传递的参数*/, CefRefPtr<CefV8Value>& retval /*返回给JS的值设置给这个对象*/, CefString& exception/*通知异常信息给JavaScript*/)
    {
        if (name == _T("jsInvokeCPlusPlus"))
        {
            if (arguments.size() == 2)
            {
                CefString strParam1 = arguments.at(0)->GetStringValue();
                CefString strParam2 = arguments.at(1)->GetStringValue();
     
                TCHAR szBuffer[512];
                StringCbPrintf(szBuffer, sizeof(szBuffer), _T("jsInvokeCPlusPlus(%s,%s)"), strParam1.c_str(), strParam2.c_str());
                ::MessageBox(GetForegroundWindow(), szBuffer, _T("jsInvokeCPlusPlus"), MB_OK);
                retval = CefV8Value::CreateInt(0);
            }
            else
            {
                retval = CefV8Value::CreateInt(2);
            }
     
            return true;
     
        }
     
        if (name == L"jsTransform") {
            CefString strParam1 = arguments.at(0)->GetStringValue();
            TCHAR szBuffer[512];
            StringCbPrintf(szBuffer, sizeof(szBuffer), _T("jsTransform(%s)"), strParam1.c_str());
            ::MessageBox(GetForegroundWindow(), szBuffer, _T("jsTransform"), MB_OK);
        }
        return false;
    }

    自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:

    https://www.cnblogs.com/bclshuai/p/11380657.html

  • 相关阅读:
    timeouts _ golang
    select.go
    channel directions _ golang
    channel synchronization _ golang
    channel _ buffering
    servlet:共享资源造成的线程冲突
    java:多线程的 共享资源冲突问题
    jsp:通过过滤器进行网页的资源管理
    jsp:通过Session控制登陆时间和内部页面的访问
    java:数据结构
  • 原文地址:https://www.cnblogs.com/bclshuai/p/12738925.html
Copyright © 2020-2023  润新知