[WebKit]WebKit2 API解析

这里是对上一篇<<WebKit模块化分析>>的进一步展开。先从API层开始。

API概览

主要类图



WebKit提供了灵活的回调机制用来支持客户端与内核的交互,在API中有一些Set Client类的函数,Client一般就是用于注册针对某一功能的回调函数。

如向WKContext注册history item处理的回调函数,就会使用下面这个结构(WKContext.h):

struct WKContextHistoryClient {

    int                                                                version;

    const void *                                                        clientInfo;

    WKContextDidNavigateWithNavigationDataCallback       didNavigateWithNavigationData;

    WKContextDidPerformClientRedirectCallback                   didPerformClientRedirect;

    WKContextDidPerformServerRedirectCallback                  didPerformServerRedirect;

    WKContextDidUpdateHistoryTitleCallback                        didUpdateHistoryTitle;

    WKContextPopulateVisitedLinksCallback                          populateVisitedLinks;

};

typedef struct WKContextHistoryClient WKContextHistoryClient;

调用WKContextSetHistoryClient就可以完成注册特定的回调函数。

角色与功能

WKView

(浏览视图,浏览功能的主要入口,也是网页显示与系统平台上的视图控件的适配,平台差异比较大。)

主要用于创建一个浏览界面,整合WKContext, WKPageGroup,WKPage的功能, 平台视图基本功能的适配(绘制、事件响应等)。

如在Mac OS下就是要实现对于NSView的适配。


WKPage

(当前浏览的页面, 负责解析执行页面内容)

 -> Frame Loader Client

 -> Page Loader Client

 -> Policy Client

 -> Form Client (表单提交操作的响应)

 -> UI Client (JS提示框、焦点变化、菜单显示状态变化、页面绘制功能等)

 -> Find Client (页面上的搜索)

 -> Context Menu Client(快捷菜单)

 -> 页面基本操作 (加载、刷新、关闭、前进、后退等)

 -> User Agent管理

 -> 页面缩放

 -> 与Injected Bundle交互


WKContext

(浏览内容管理功能)

  -> History Client

  -> Injected Bundle Client

  -> Download Client

  -> Connection Client

  -> Download Request

  -> Cached Mode

  -> Process Model (Web进程的共享模式)

  -> Memory Sampler

通过它的m_supplements成员(一个HashMap)可以提供:

  -> Get Application Cache manager

  -> Get Battery Manager

  -> Get Cookie Manager

  -> Get Database Manager

  -> Get Geolocation Manager

  -> Get Icon Database

  -> Get KeyValue Storage Manager

  -> Get Media Cache Manager

  -> Get Network Info Manager

  -> Get Notification Manager

  -> Get Plugin Site Data Manager

  -> Get Resource Cache Manager

  -> Garbage Collection of JavaScript Objects

*关于进程共享模式,参考这里. 是2010年的资料,ProcessModelSharedSecondaryThread已经不支持了。


WKFrame

(从属于一个WKPage, 表示一个Web Frame)


*完整的API定义文件在Source\WebKit2\UIProcess\API目录下。


交互流程示例




接口函数与内核对象的交互


WebKit2 API提供的C API列表中并没有直接暴露内核中的定义,而是定义了一组空的指针类型用于隐藏一些细节(信息隐藏的设计原则)。通过一个巧妙的方式与WebKit中定义的类型保持了对应关系。


它将暴露给外部应用使用的类型定义为WKXXX, 如WKPageRef, WKContextRef等,这些称为API Type。将其对应的WebKit2中的类型称为Impl Type (实现类型)。


 其定义如下(WKSharedAPICast.h):

   template<typename APIType> struct APITypeInfo { };

   template<typename ImplType> struct ImplTypeInfo { };


WebKit2中使用一个宏来建立两者之前的关联关系, 如下面这个例子(WKAPICast.h):

  WK_ADD_API_MAPPING(WKPageRef, WebPageProxy)


在实际使用时,WebKit2定义了两个函数toImpl()和toAPI()完成它们之间的转换。如

void WKPageLoadURL(WKPageRef pageRef, WKURLRef URLRef)

{

    toImpl(pageRef)->loadURL(toWTFString(URLRef));

}

- (WKPageRef)pageRef

{

    return toAPI(_data->_page.get());

}


对于外部应用能看到的就是WKXXXRef之类的定义,具体的操作由WebKit2的UI Process负责接受处理。




API映射机制的实现


WK_ADD_API_MAPPING宏和两个转换函数都是运用泛型编程来实现的。具体的定义在WKSharedAPICast.h。


首先看一下WK_ADD_API_MAPPING的定义:

#define WK_ADD_API_MAPPING(TheAPIType, TheImplType) \

    template<> struct APITypeInfo<TheAPIType> { typedef TheImplType* ImplType; }; \

    template<> struct ImplTypeInfo<TheImplType*> { typedef TheAPIType APIType; };


看起来就是声明了两个数据结构,并且各嵌套了一个类型定义。这样就可以通过它们完成类型映射了。

举个例子:

在定义过

   WK_ADD_API_MAPPING(WKPageRef, WebPageProxy)

后,下面的代码会正常执行:

    APITypeInfo<WKPageRef> sAPIType;

    APITypeInfo<WKPageRef>::ImplType sTemp = NULL;

    WebPageProxy * myClass = newWebPageProxy();

    sTemp = myClass;

这段代码会被正常执行。其中sAPIType的类型是PageRef(类为PageRef是由一个opaque类型定义在WKBase.h中的,运行时会显示为这个类型。), 而sTemp就是WebPageProxy *类型了。


反之,ImplTypeInfo也是类似。


下面就是两个转换函数的定义,现在就很好理解了(WKSharedAPICast.h):

template<typename T>

inline typename APITypeInfo<T>::ImplType toImpl(T t)

{

    // An example of the conversions that take place:

    // const struct OpaqueWKArray* -> const struct OpaqueWKArray -> struct OpaqueWKArray -> struct OpaqueWKArray* -> ImmutableArray*

    

    typedef typename WTF::RemovePointer<T>::Type PotentiallyConstValueType;

    typedef typename WTF::RemoveConst<PotentiallyConstValueType>::Type NonConstValueType;

    

    return reinterpret_cast<typenameAPITypeInfo<T>::ImplType>(const_cast<NonConstValueType*>(t));

}


template<typename T>

inline typename ImplTypeInfo<T>::APIType toAPI(T t)

{

    return reinterpret_cast<typenameImplTypeInfo<T>::APIType>(t);

}


Reference:

  1. 如果对typename的使用有疑问,看这里:
  2. 关于信息隐藏的设计原则
 
转载请注明出处: http://blog.csdn.net/horkychen


  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
miniblink是什么? Miniblink是一个追求极致小巧的浏览器内核项目,全世界第三大流行的浏览器内核控件。 其基于chromium最新版内核,去除了chromium所有多余的部件,只保留最基本的排版引擎blink。 Miniblink保持了10M左右的极简大小,是所有同类产品最小的体积,同时支持windows xp、npapi。 为什么要做miniblink? 市面上作为嵌入的组件的可用的浏览器内核,不外乎这几个:webkit、cef、nwjs、electron。 cef:优点是由于集成的chromium内核,所以对H5支持的很全,同时因为使用的人也多,各种教程、示例,资源很多。但缺点很明显,太大了。最新的cef已经夸张到了100多M,还要带一堆的文件。同时新的cef已经不支持xp了(chromium对应版本是M49)。而且由于是多进程架构,对资源的消耗也很夸张。如果只是想做个小软件,一坨文件需要带上、超大的安装包,显然不能忍受。 nwjs,或者最近大火的electron:和cef内核类似,都是chromium内核。缺点和cef一模一样。优点是由于可以使用nodejs的资源,同时又自带了各种api的绑定,所以可以用的周边资源非常丰富;而基于js的开发方案,使得前端很容易上手。所以最近N多项目都是基于nwjs或electron来实现。例如vscode,atom等等。 原版webkit:现在官网还在更新windows port,但显然漫不在心,而且最新的webkit也很大了,超过20几M。最关键的是,周边资源很少,几乎没人再基于webkit来做开发。同时由于windows版的saferi已经停止开发了,所以用webkit就用不了他的dev tools了。这是个大遗憾。 WKE:这是个很老的webkit内核的裁剪版了。小是小,但bug太多了。 那么关键点来了,使用miniblink有啥好处呢?? 首先,miniblink对大小要求非常严格。原版chromium、blink里对排版渲染没啥大用的如音视频全都被砍了,只专注于网页的排版和渲染。甚至为了裁剪大小,我不惜使用vc6的crt来跑mininblink(见我上篇文章)。这个也算前无古人后无来者了。 其次,miniblink紧跟最新chromium,这意味着chromium相关的资源都可以利用。在未来的规划里,我是打算把electron的接口也加上的,这样可以无缝替换electron。使用miniblink的话,开发调试时用原版electron,发布的时候再替换掉那些dll,直接可以无缝切换,非常方便。 miniblink如何使用? Miniblink导出了electron、WKE的接口,可以直接无缝替换现有的electron、WKE项目。 早期miniblink还导出了CEF接口,不过现在已被废弃。 miniblink有个小demo,从demo里可以看到,brackct这个基于cef的开源编辑器,已经顺利由miniblink跑起来了。现在electron的接口已做好,vscode跑起来了。 更详细的使用文档见本页其他文章。 miniblink如何裁剪到这么小? 这个比较复杂了。主要就是把blink从chromium抽离了出来,同时补上了cc层(硬件渲染层)。现在的blink,已经不是当年的那个webkit了,渲染部分全走cc层,复杂无比。我这大半年都在重写他那个蛋疼又复杂的cc层。 和webkit比,miniblink架构有什么优势 现在的webkit版本,已经比miniblink落后太多了。blink一直在加入各种极富创造力和想象力的功能、组件。例如,blink早就加入多线程解析html token、blink gc回收器、多线程录制回放渲染机制。这些能让blink的解析渲染速度极大提升。下一次,我会先开源出blink gc组件,这东西很有意思,在c++里硬是搞出了一个垃圾回收机制,能让你像写java一样写c++。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值