[WebKit]WebKit2 API解析

- 日理万妓 2022-03-30 12:20 377阅读 0赞

这里是对上一篇<>的进一步展开。先从API层开始。

API概览

主要类图

1361200968_9095.png

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

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

struct WKContextHistoryClient {

  1. int version;
  2. const void \* clientInfo;
  3. WKContextDidNavigateWithNavigationDataCallback didNavigateWithNavigationData;
  4. WKContextDidPerformClientRedirectCallback didPerformClientRedirect;
  5. WKContextDidPerformServerRedirectCallback didPerformServerRedirect;
  6. WKContextDidUpdateHistoryTitleCallback didUpdateHistoryTitle;
  7. 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目录下。

交互流程示例

1361201069_3757.png

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

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

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

其定义如下(WKSharedAPICast.h):

template struct APITypeInfo { };

template struct ImplTypeInfo { };

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

WK_ADD_API_MAPPING(WKPageRef, WebPageProxy)

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

void WKPageLoadURL(WKPageRef pageRef, WKURLRef URLRef)

{

  1. **toImpl**(pageRef)->**loadURL**(**toWTFString**(URLRef));

}

- (WKPageRef)pageRef

{

  1. return **toAPI**(\_data->\_page.**get**());

}

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

1361201169_9542.png

API映射机制的实现

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

首先看一下WK_ADD_API_MAPPING的定义:

#define WK_ADD_API_MAPPING(TheAPIType, TheImplType) \

  1. template<> struct APITypeInfo<TheAPIType> \{ typedef TheImplType\* ImplType; \}; \\
  2. template<> struct ImplTypeInfo<TheImplType\*> \{ typedef TheAPIType APIType; \};

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

举个例子:

在定义过

WK_ADD_API_MAPPING(WKPageRef, WebPageProxy)

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

  1. **APITypeInfo**<WKPageRef> sAPIType;
  2. **APITypeInfo**<WKPageRef>::ImplType sTemp = NULL;
  3. WebPageProxy \* myClass = newWebPageProxy();
  4. sTemp = myClass;

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

反之,ImplTypeInfo也是类似。

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

template

inline typename APITypeInfo::ImplType toImpl(T t)

{

  1. *// An example of the conversions that take place:*
  2. *// const struct OpaqueWKArray\* -> const struct OpaqueWKArray -> struct OpaqueWKArray -> struct OpaqueWKArray\* -> ImmutableArray\**
  3. typedef typename WTF::**RemovePointer**<T>::Type PotentiallyConstValueType;
  4. typedef typename WTF::**RemoveConst**<PotentiallyConstValueType>::Type NonConstValueType;
  5. return reinterpret\_cast<typename**APITypeInfo**<T>::ImplType>(const\_cast<NonConstValueType\*>(t));

}

template

inline typename ImplTypeInfo::APIType toAPI(T t)

{

  1. return reinterpret\_cast<typename**ImplTypeInfo**<T>::APIType>(t);

}

Reference:

  1. 如果对typename的使用有疑问,看这里:
  1. [http://dev.yesky.com/13/2221013.shtml][http_dev.yesky.com_13_2221013.shtml]
  1. 关于信息隐藏的设计原则

    a. Hiding Data within OOP

    b. 设计的核心任务之二:信息隐藏

转载请注明出处: http://blog.csdn.net/horkychen

发表评论

表情:
评论列表 (有 0 条评论,377人围观)

还没有评论,来说两句吧...

相关阅读