zoukankan      html  css  js  c++  java
  • 利用InjectedBundle定制自己的Webkit(一)

    Webkit是一个多进程构架,内核WebCore和JS引擎JavaScriptCore都处在WebProcess进程中,而用户界面相关的处理则处在UIProcess进程中。(详见Webkit客户端进程解析

    Webkit提供了大量的API供客户程序调用,但是这些API都是在客户进程中调用的,我们无法访问到内核部分的数据结构并处理,如DOM树、Render树、加载的Web资源等等。为了解决这一问题,Webkit提供了一个运行在内核进程的InjectedBundle来提供对内核数据的操作。

    InjectedBundle类似于一个插件,单独编译成一个动态库,在内核进程运行到特定情况时会调用InjectedBundle中注册的对应函数来实现自定义操作。每个WebProcess只能加载一个InjectedBundle,用户可以在创建WebProcess的时候指定使用哪个InjectedBundle。

    接下来我们就动手制作一个自己的InjectedBundle然后用Webkit加载它。

     

    1. 准备工作

    我采用的编译环境是VC2005

    (1)首先需要下载并编译Webkit(详见Windows平台编译Webkit

    (2)然后创建一个空项目,修改项目属性

      a. 配置类型:动态库(.dll)  

      b. 添加附加包含目录:Webkit生成文件路径\inlude 和 Webkit生成文件路径\include\include(一定要加两个,第二个是windows平台缺少的第三方库头文件)

      c. 添加附加库目录:Webkit生成文件路径\lib

    好,项目配置完毕!接下来实现Webkit所需的接口

     

    2. 编写InjectedBundle

    先上代码

    #include <WebKit2/WKBundleInitialize.h>

    #pragma comment(lib, "WebKit.lib"

    extern "C" __declspec(dllexport)

    void WKBundleInitialize(WKBundleRef bundle, WKTypeRef initializationUserData)

      // 初始化代码

    }

    InjectedBundle只需要实现这一个函数即可(是不是很简单),其中参数bundle是Webkit给你的InjectedBundle分配的标志(identifier),可以用它来调用一些InjectedBundle的API,所以存下来为妙;参数initializationUserData是用户利用Webkit加载该InjectedBundle时传入的一些数据(我们可以用它来传启动参数)。

     

    接下来我们要做的就是在该初始化函数中注册我们需要的回调函数

      在Webkit中以Client结尾的结构体都是一个回调函数组,比如WKBundlePageLoaderClient就是一组处理页面加载的回调函数,每个Client都有一个版本号和clientInfo,clientInfo是用来在回调函数中传递用户参数。利用对应的WKBundleSetXXXClient就能够注册某一个回调函数组。

      我们需要注册的第一组回调函数是WKBundleClient,内容如下

    struct WKBundleClient {

      int version;                              // 版本号

      const void * clientInfo;                        // 用户参数

      WKBundleDidCreatePageCallback didCreatePage;           // page创建完毕

      WKBundleWillDestroyPageCallback willDestroyPage;           // page将要销毁

      WKBundleDidInitializePageGroupCallback didInitializePageGroup;   // page组初始化完毕

      WKBundleDidReceiveMessageCallback didReceiveMessage;       // 收到用户消息

    };

      前两个已经说过了,这里主要讲didCreatePage和didReceiveMessage

     

    (1)didCreatePage

      该函数是在创建一个Page对象之后被调用的,原型是

    typedef void (*WKBundleDidCreatePageCallback)(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo);

      在回调里我们能获得所创建Page的引用page,利用这个引用可以调用一些和page相关的API。其中比较重要的是WKBundlePageSetXXXClient,利用这一组函数可以设置该页面的一些回调,比如之前说过的WKBundlePageLoaderClient,包含了didReceiveTitleForFrame(当收到Frame的标题后调用),didFinishLoadForFrame(当一个Frame对象加载完毕后被调用)等回调函数。利用这些回调函数就能在不同阶段实现我们想要的功能了。

     

    (2)didReceiveMessage

      该函数是在收到客户进程的消息后调用的。Webkit设计了一个消息队列机制使得两个进程之间能够通信,客户进程通过调用WKContextSetInjectedBundleClient给InjectedBundle发消息,InjectedBundle通过WKBundlePostMessage向客户进程发消息。我们利用这个方法就能在两个进程间交换数据。例如把InjectedBundle处理的结果传给客户进程,或者客户进程向InjectedBundle发指令。

    消息的格式是messageName + messageBody

    messageName是WKStringRef,即一个字符串

    messageBody是任意的WKType,如:WKDictionaryRef, WKDataRef, WKArrayRef等等。

     

    在InjectedBundle写完之后编译生成一个.dll文件就可以拿来使用了。

    下一篇中将介绍怎样在Webkit中加载InjectedBundle,待续...

  • 相关阅读:
    Centos7 禁止firewalld并使用iptables 作默认防火墙
    在Kibana上格式化字段,更好的在dashboard上展示
    利用 ELK系统分析Nginx日志并对数据进行可视化展示
    Nginx 服务器开启status页面检测服务状态
    Linux 上通过binlog文件 恢复mysql 数据库详细步骤
    Linux 为FTP 服务器添加iptables规则--案例分析
    NUMA架构的CPU -- 你真的用好了么?
    Linux 上利用Nginx代理uWSGI处理Flask web应用
    Linux 之不同运维人员共用root 账户权限审计
    Strategy
  • 原文地址:https://www.cnblogs.com/Jiajun/p/2798540.html
Copyright © 2011-2022 走看看