WebCore在载入并且显示一张页面时,会创建许多的对象与页面中的各个元素相互对应。这些对象之间的关系,以及由谁来创建并且管理的呢?对于不同的MIME类型的页面(比如HTML,XHTML,XML)又是如何区分的呢?Javascript脚本中是如何访问这些HTML元素的呢?CSS属性又是如何影响到各个元素的绘制的呢?带着这些问题,对WebKit引擎进行Hacking。
当GTKLauncher启动后,创建的第一个WebCore对象是WebCore::Page对象,该对象从负责的功能上并不等同于一张载入的Web页面,而是可以将该对象看成是一次浏览会话。WebCore::Page包含了Chrome对象(例如:JS可以通过该对象使浏览器弹出提示框),浏览器设置(Settings),RenderTheme对象、History对象,以及Frame对象。这些对象在一次浏览会话过程中只会创建一次,也就是说不管在一次会话中发生多少次页面跳转,对象是不会被销毁的,只有当浏览器退出时才会销毁这些对象。
Frame对象与页面载和显示有关,他主要管理资源的载入(由FrameLoader负责),以及内容呈现(由FrameView负责)。Frame对象中保存了两个比较重要的对象Document(描述DOM树)和DOMWindow。DOMWindow可以看成是页面显示的窗口,Javascript中可以通过JSDOMWindow来访问该对象。因为DOMWindow中保存了创建它的Frame的引用,因此JSDOMWindow可以通过该对象找到当前Frame所拥有的Document对象。
Document对象是DOM树的根节点,所有的子节点都可以从其遍历到。并且,当用户点击页面中的某个连接,或者当鼠标滑过某个有焦点响应函数的元素时,Document对象第一个接收到该事件,然后通过起泡算法找到目标对象并响应,然后从目标对象开始反向调用父元素的处理函数。
在webCore中定义了9个主要的文档对象,用来处理不同的文档类型。比如”text/hml”类型的文档是通过HTMLDocument对象描述的,”image/svg+xml”则是由SVGDocument对象描述的,”application/xhtml+xml”则由Document描述。Document对象,根据接收到的不同的MIME类型数据,创建不同的文档对象,并且由各自的文档对象创建其文档解析器。这里以”text/html”类型的文档为例说明其关系。
当用户访问指定URL时,FrameLoader会调用DocumentLoader加载资源(网络或者本地),当页面第一次被载入时,会通知FrameLoader,并且调用其begin方法。该方法会根据接收数据的MIME类型创建不同的文档对象,在这里会创建HTMLDocument对象。并且由HTMLDocument对象创建一个HTMLParser用来继续下面的文档解析工作。当FrameLoader再次接受到页面数据时,对象的addData方法会被调用,该方法会访问Document的parser对象,并且将获得的数据通过Parser解析。HTMLParser碰到一个元素Tag时,会通过HTMLElementFactory创建响应的HTML*元素,来描述该元素。
通过阅读源码可以知道,所有的HTML*元素都是继承于HTMLElement,而HTMLElement并不是直接继承与Node对象的,相反它是StyledElement类的子类,因此CSSParser在解析CSS元素时,可以直接访问和设置HTML*元素的属性。而StyleedElement则是继承与Element类。我们知道,所有的Element元素都是EventTarget的子类,因此HTML*元素都可以接收到DOM事件。
WebKit运行时主要对象关系图