[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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值