cef3js交互,cef js交互

发布时间:2022-11-22

本文目录一览:

  1. 能不能用c写程序,然后里面嵌入一个网页,网页需要支持Js,并且也可以用c获取这个网页的一切
  2. [如何在CEF JS与browser进程间异步通信](#如何在CEF JS与browser进程间异步通信)
  3. Xilium.CefGlue怎么使用Js调用C#方法
  4. 如何利用CEF3创建一个简单的应用程序
  5. wpf写的前端改成用js写可以吗?

能不能用c写程序,然后里面嵌入一个网页,网页需要支持Js,并且也可以用c获取这个网页的一切

你可以把chromium的开源工程拿来,这个工程你来改造,就可以办到。 不过难度相对不低,你说的对,类似于自己完成浏览器。 chromium的cef3 API可以帮助你完成这些事情。

如何在CEF JS与browser进程间异步通信

基于CEF开发时经常需要在JS和C代码间通信,我们在CEF中JavaScript与C交互中讨论了常见的交互方式,不过都是在Renderer进程中,这次来看看如何在JS和Browser进程间通信,基本介绍可以看这里: 具体做法,上面给出的链接里有大概说明,另外在cef_message_router.h中有详细说明,它分了9步,有需要的可以去查看。我试验了下可行。按照我的实验,从三个方面来说说:

  • browser进程
  • renderer进程
  • html中的js foruok原创,转载请关注微信订阅号“程序视界”联系foruok。

browser进程

  1. 配置browser进程这一侧的Message Router 使用CefMessageRouterConfig来定义可以在html中使用的方法名字。代码片段可能如下:
    ...
    CefMessageRouterConfig g_messageRouterConfig;
    int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                           _In_opt_ HINSTANCE hPrevInstance,
                           _In_ LPTSTR lpCmdLine,
                           _In_ int nCmdShow)
    {
        UNREFERENCED_PARAMETER(hPrevInstance);
        UNREFERENCED_PARAMETER(lpCmdLine);
        // Enable High-DPI support on Windows 7 or newer.
        CefEnableHighDPISupport();
        g_messageRouterConfig.js_query_function = "cefQuery";
        g_messageRouterConfig.js_cancel_function = "cefQueryCancel";
        CefMainArgs main_args(hInstance);
        ...
    }
    
    注意我在main函数之外定义了一个CefMessageRouterConfig的实例,然后在main函数中设置了query和cancel这两个函数。它们定义了可以在html的js代码里使用的方法,比如根据上面代码,你可以用window.cefQuery({...})
  2. 创建CefMessageRouterBrowserSide的实例 browser进程这边需要一个CefMessageRouterBrowserSide的实例来处理renderer进程发过来的消息。建议把这个实例作为成员变量放在CefClient的派生类中,因为它CefMessageRouterBrowserSide定义了一些方法,需要在指定的地方调用。 声明和初始化的代码片段:
    CefRefPtr<CefMessageRouterBrowserSide> m_browser_side_router;
    ...
    extern CefMessageRouterConfig g_messageRouterConfig;
    m_browser_side_router = CefMessageRouterBrowserSide::Create(g_messageRouterConfig);
    ...
    
  3. 调用预定义方法 CefMessageRouterBrowserSide预定义了下列接口,需要在指定地方调用:
    • bool OnProcessMessageReceived(...) // call from CefClient::OnProcessMessageReceived
    • void OnBeforeClose(CefRefPtr<CefBrowser> browser) // call from CefLifeSpanHandler::OnBeforeClose()
    • void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser) // call from CefRequestHandler::OnRenderProcessTerminated()
    • void OnBeforeBrowse(...) // call from CefRequestHandler::OnBeforeBrowse() 所以,我们的这个ClientHandler类,声明如下:
    class ClientHandler : public CefClient,
                          public CefDisplayHandler,
                          public CefLifeSpanHandler,
                          public CefLoadHandler,
                          public CefRequestHandler
    {
        ...
    };
    
    ClientHandler要实现CefClientOnProcessMessageReceivedCefLifeSpanHandlerOnBeforeCloseCefRequestHandlerOnRenderProcessTerminatedOnBeforeBrowse方法,在这些方法里调用CefMessageRouterBrowserSide的同名方法即可。代码片段如下:
    void ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser)
    {
        CEF_REQUIRE_UI_THREAD();
        m_browser_side_router->OnBeforeClose(browser);
        ...
    }
    bool ClientHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                                 CefProcessId source_process,
                                                 CefRefPtr<CefProcessMessage> message)
    {
        if (m_browser_side_router->OnProcessMessageReceived(browser, source_process, message)) return true;
        return false;
    }
    bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request, bool is_redirect)
    {
        m_browser_side_router->OnBeforeBrowse(browser, frame);
        return false;
    }
    void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser, TerminationStatus status)
    {
        m_browser_side_router->OnRenderProcessTerminated(browser);
    }
    
  4. 在browser进程里实现处理JS查询的handler CefMessageRouterBrowserSide定义了一个内部类Handler,继承它:
    class BrowserSideJSHandler : public CefMessageRouterBrowserSide::Handler
    {
    public:
        BrowserSideJSHandler();
        virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
                             int64 query_id,
                             const CefString& request,
                             bool persistent,
                             CefRefPtr<CefValue> callback);
        virtual void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
                                     CefRefPtr<CefFrame> frame,
                                     int64 query_id);
    };
    
    实现 OnQueryOnQueryCanceled两个方法:
    bool BrowserSideJSHandler(CefRefPtr<CefBrowser> browser,
                              CefRefPtr<CefFrame> frame, int64 query_id,
                              const CefString& request, bool persistent, CefRefPtr<CefValue> callback)
    {
        if (request == "HelloCefQuery")
        {
            callback->Success("HelloCefQuery Ok");
            return true;
        }
        else if (request == "GiveMeMoney")
        {
            callback->Failure(404, "There are none thus query!");
            return true;
        }
        return false; // give other handler chance
    }
    void BrowserSideJSHandler::OnQueryCanceled(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int64 query_id)
    {
        //cancel our async query task...
    }
    
  5. CefMessageRouterBrowserSide的实例添加handler 我在ClientHandler类中定义了一个BrowserSideJSHandler的实例,类似下面:
    class ClientHandler : public CefClient,
                          public CefDisplayHandler,
                          public CefLifeSpanHandler,
                          public CefLoadHandler,
                          public CefRequestHandler
    {
        ...
        CefRefPtr<CefMessageRouterBrowserSide> m_browser_side_router;
        BrowserSideJSHandler m_jsHandler;
        ...
    };
    
    然后在ClientHandler构造函数中加入了下列代码:
    m_browser_side_router->AddHandler(m_jsHandler, true);
    
    上面的代码把BrowserSideJSHandler加入到browser进程里的消息路由器中。 好了,到这里browser进程配置完成。接下来看renderer进程。

Xilium.CefGlue怎么使用Js调用C#方法

  • 第1篇:.NET多种WebKit内核/Blink内核浏览器初步测评报告
  • 第2篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:导航篇
  • 第3篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:官方原生方法分析
  • 第4篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:委托回调方法分析
  • 第5篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+委托回调方法分析
  • 第6篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:自动注册JS脚本+自动反射方法分析
  • 第7篇:Xilium CefGlue 关于 CLR Object 与 JS 交互类库封装报告:全自动注册与反射方法分析

如何利用CEF3创建一个简单的应用程序

开始

首先,根据自身所使用的开发平台,可以去 这里 下载对应的发布版本。针对这个教程,我们需要下载1750或者更新的版本。当前支持的平台有Windows, Linux和Mac OS X。每一个版本都包含了当在特定平台上编译特定版本CEF3时所需要的所有文件和资源。您可以通过包含在里边的 README.txt 文件或者在Wiki上GeneralUsage 中的 Getting Started,了解每个发布版本的具体内容和细节。

编译发布版本中的项目

以CEF发布版本为基础开发的应用程序可以使用标准的平台编译工具进行编译执行。包括 Windows 平台下的 Visual Studio, Mac OS X 平台下的 Xcode, 以及 Linux 平台下的 gcc/make。针对平台的不同,项目的编译过程也有些许的不同和要求。

Windows

Windows 平台下编译 Cefsimple 步骤:

  1. 用对应的 Visual Studio 版本打开项目解决方案。举个例子,如果你安装的是 Visual Studio 2010, 那么,打开的就是 cesimple2010.sln
  2. 如果你下载的是 x64版本,请确保你选择的是 x64的开发平台。
  3. 开始编译。
  4. 如果编译通过,那么,在当前解决方案的目录下,将出现“out/Debug”(或者 “out/Release”)文件夹。
  5. 执行文件夹下 cefsimple.exe,确保能正确运行。

加载一个自定义URL

cefsimple项目中默认加载的URL是 google.com,当然,你也可以用自定义的 URL 去替代它,最方便的就是通过命令行搞定。

# Load the local file “c:\example\example.html”
cefsimple.exe --url=file:///c:/example/example.html

除了命令行的方法,也可以通过直接修改在 cefsimple/simple.cpp 文件中的代码,达到你的目的。

...
if (url.empty())
    url = "file:///c:/example/example.html";

应用程序组成

所有的 CEF 应用程序都有一下主要组成部分:

  1. CEF 的动态链接库 。(在 Windows 平台下就是 libcef.dll)
  2. 支持库。(ICU, FFMPEG等)
  3. 资源。(html/js/css, strings等)
  4. 客户端执行文件。(本教程中就是 cefsimple.exe.)

要点(必看)

  1. CEF 使用的是多进程。应用程序主进程是浏览器进程,而其他子进程是由 renderer, plugins, GPU等创建。
  2. 在 Windows 和 Linux 平台下的执行文件可以被主进程和子进程使用。
  3. CEF 中所有进程都可以是多线程的。CEF提供了许多功能和接口在不同的线程中传递任务。
  4. 一些回调方法和函数只能在特定的进程或者线程中使用。在你第一次使用新的回调方法或者函数之前,请确保你已经阅读了 API 头文件中源码,看使用要求。

流程分析

cefsimple 应用程序首先初始化CEF,然后创建了一个简单的弹出浏览器窗口。当关闭了所有的浏览器窗口,应用程序就会结束。程序执行流程如下:

  1. 系统执行入口点函数(main or wWinMain),并创建浏览器进程。
  2. 入口点函数:
    1. 创建能够处理进程级别的回调方法的 SimpleApp 实例。
    2. 初始化 CEF,进入 CEF 消息循环。
  3. 初始化 CEF 之后,调用 SimpleApp::OnContextInitialized() 。这个方法中:
    1. 创建单例的 SimpleHandler
    2. CefBrowserHost::CreateBrowserSync() 方法创建一个浏览器窗口。
  4. 所有的浏览器共享 SimpleHandler 实例, 此实例能定制浏览器行为、处理浏览器相关回调方法(life span, loading state, title display等)。
  5. 当一个浏览器窗口关闭的时候,调用 SimpleHandler::OnBeforeClose() 。当所有的浏览器窗口全部关闭时,OnBeforeClose() 函数就会执行跳出 CEF 消息循环的行为,退出应用程序。

入口点函数

程序的运行开始于浏览器进程中的入口点函数。这个函数会初始化 CEF 以及所有跟操作系统有关的对象。

Windows

#include <windows.h>
#include "cefsimple/simple_app.h"
#include "include/cef_sandbox_win.h"
// Set to 0 to disable sandbox support.
#define CEF_ENABLE_SANDBOX 1
#if CEF_ENABLE_SANDBOX
// The cef_sandbox.lib static library is currently built with VS2010. It may not
// link successfully with other VS versions.
#pragma comment(lib, "cef_sandbox.lib")
#endif
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR lpCmdLine,
                      int nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    void* sandbox_info = NULL;
#if CEF_ENABLE_SANDBOX
    // Manage the life span of the sandbox information object. This is necessary
    // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
    CefScopedSandboxInfo scoped_sandbox;
    sandbox_info = scoped_sandbox.sandbox_info();
#endif
    // Provide CEF with command-line arguments.
    CefMainArgs main_args(hInstance);
    // SimpleApp implements application-level callbacks. It will create the first
    // browser instance in OnContextInitialized() after CEF has initialized.
    CefRefPtr<SimpleApp> app(new SimpleApp);
    // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
    // that share the same executable. This function checks the command-line and,
    // if this is a sub-process, executes the appropriate logic.
    int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
    if (exit_code >= 0) {
        // The sub-process has completed so return here.
        return exit_code;
    }
    // Specify CEF global settings here.
    CefSettings settings;
#if !CEF_ENABLE_SANDBOX
    settings.no_sandbox = true;
#endif
    // Initialize CEF.
    CefInitialize(main_args, settings, app.get(), sandbox_info);
    // Run the CEF message loop. This will block until CefQuitMessageLoop() is
    // called.
    CefRunMessageLoop();
    // Shut down CEF.
    CefShutdown();
    return 0;
}

SimpleApp

SimpleApp 负责处理进程级别的回调方法。它会曝露出一些在多进程中共享或者被特定进程使用的接口和方法。CefBrowserProcessHandler 接口,在浏览器进程中调用。还有一个被分离出 CefBrowserProcessHandler 接口(例子项目没有展示)只会在渲染进程中被调用。由于 CefBrowserProcessHandler 不光实现了 CefApp, 同时还有 CefBrowserProcessHandler,所以它的返回值必须是[this]

// simple_app.h
#include "include/cef_app.h"
class SimpleApp : public CefApp,
                 public CefBrowserProcessHandler {
public:
    SimpleApp();
    // CefApp methods:
    virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
        OVERRIDE { return this; }
    // CefBrowserProcessHandler methods:
    virtual void OnContextInitialized() OVERRIDE;
private:
    // Include the default reference counting implementation.
    IMPLEMENT_REFCOUNTING(SimpleApp);
};
// simple_app.cpp
#include "cefsimple/simple_app.h"
#include <string>
#include "cefsimple/simple_handler.h"
#include "cefsimple/util.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
SimpleApp::SimpleApp() {
}
void SimpleApp::OnContextInitialized() {
    REQUIRE_UI_THREAD();
    // Information used when creating the native window.
    CefWindowInfo window_info;
#if defined(OS_WIN)
    // On Windows we need to specify certain flags that will be passed to
    // CreateWindowEx().
    window_info.SetAsPopup(NULL, "cefsimple");
#endif
    // SimpleHandler implements browser-level callbacks.
    CefRefPtr<SimpleHandler> handler(new SimpleHandler());
    // Specify CEF browser settings here.
    CefBrowserSettings browser_settings;
    std::string url;
    // Check if a "--url=" value was provided via the command-line. If so, use
    // that instead of the default URL.
    CefRefPtr<CefCommandLine> command_line =
        CefCommandLine::GetGlobalCommandLine();
    url = command_line->GetSwitchValue("url");
    if (url.empty())
        url = "https://www.google.com";
    // Create the first browser window.
    CefBrowserHost::CreateBrowserSync(window_info, handler.get(), url,
                                      browser_settings, NULL);
}

SimpleHandler

SimpleHandler 负责处理浏览器级别的回调方法。这些回调方法会在浏览器进程中执行。在这个项目中,针对所有的浏览器使用相同的 CefClient 实例,但是如果你愿意,可以在自己的应用程序中使用不同的 CefClient实例的。

// simple_handler.h
#include "include/cef_client.h"
#include <list>
class SimpleHandler : public CefClient,
                      public CefDisplayHandler,
                      public CefLifeSpanHandler,
                      public CefLoadHandler {
public:
    SimpleHandler();
    ~SimpleHandler();
    // Provide access to the single global instance of this object.
    static SimpleHandler* GetInstance();
    // CefClient methods:
    virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
        return this;
    }
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
        return this;
    }
    virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
        return this;
    }
    // CefDisplayHandler methods:
    virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
                               const CefString& title) OVERRIDE;
    // CefLifeSpanHandler methods:
    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
    virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
    // CefLoadHandler methods:
    virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
                             CefRefPtr<CefFrame> frame,
                             ErrorCode errorCode,
                             const CefString& errorText,
                             const CefString& failedUrl) OVERRIDE;
    // Request that all existing browser windows close.
    void CloseAllBrowsers(bool force_close);
private:
    // List of existing browser windows. Only accessed on the CEF UI thread.
    typedef std::list<CefRefPtr<CefBrowser>> BrowserList;
    BrowserList browser_list_;
    // Include the default reference counting implementation.
    IMPLEMENT_REFCOUNTING(SimpleHandler);
};
// simple_handler.cpp
#include "cefsimple/simple_handler.h"
#include <sstream>
#include <string>
#include "cefsimple/util.h"
#include "include/cef_app.h"
#include "include/cef_runnable.h"
namespace {
SimpleHandler* g_instance = NULL;

wpf写的前端改成用js写可以吗?

可以。 通过NuGet获取CefSharp.Wpf组件。xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"加载,需要把项目的cpu设置成x86,Framework4.5。 js全称JavaScript,是运行在浏览器上的脚本语言,连续多年被评为全球最受欢迎的编程语言。js可以使网页具有交互性,例如响应用户点击,给用户提供更好的体验。还可以根据用户的操作,动态的创建页面。主要目的是为了解决服务器终端语言,比如Perl,遗留的速度问题。当时服务端需要对数据进行验证,由于网络速度相当缓慢,只有28.8kbps,验证步骤浪费的时间太多。于是Netscape的浏览器Navigator加入了Javascript,提供了数据验证的基本功能。