WebKit历史项管理的实现
来源:互联网 发布:签名设计软件免费版 编辑:程序博客网 时间:2024/06/10 22:02
历史项管理根据标准定义,由Page管理一个Joint Session History, 包含了各个子Frame的历史项。逻辑上对应如下的关系:
从上面看三个层次:Page,Frame,以及JS Binding的接口。页面加载的核心是由Frame通过FrameLoader来完成的,HistoryController及BackForwardController可以视为页面加载进行历史项操作的接口。 Frame层次中通过HistoryController, Page层次中通过BackForwardController进行历史项操作。
BackForwardClient及HistoryItem则存储着历史项的具体内容。历史项的变化消息则由FrameLoaderClient负责发送(适配到WebKit层)。
Page层次中的主要类关系如下:
从上面看三个层次:Page,Frame,以及JS Binding的接口。页面加载的核心是由Frame通过FrameLoader来完成的,HistoryController及BackForwardController可以视为页面加载进行历史项操作的接口。 Frame层次中通过HistoryController, Page层次中通过BackForwardController进行历史项操作。
BackForwardClient及HistoryItem则存储着历史项的具体内容。历史项的变化消息则由FrameLoaderClient负责发送(适配到WebKit层)。
Page层次中的主要类关系如下:
一个HistoryItem可以理解为标准中定义的state。HistoryItem存储和Joint Session History的关系表现在其存储的成员变量上:
m_target, m_parent存储的都是Frame名称,可以从FrameTree获取到Frame, 分别代表着此HistoryItem对应的Frame, 以及其父Frame。
m_scrollPoint则是当前显示的位置。如果是通过Anchor跳转,这个值就会有所区分。
m_stateObject则是通过HTML5 History API的pushState及replaceState所操作的内容。
JSBinding层则是由History通过Frame向JS提供服务。在Frame的层次上,Frame主要通过FrameLoader进行历史项操作。页面跳转操作则由Frame的NavigatorScheduler来完成。在HTML5 Spec中关于Session History的操作集中在HistoryController里,一部分逻辑分散在NavigationScheduler里,比如NavigationScheduler::mustLockBackForwardList()函数,以及1秒内跳转的处理逻辑。
当页面前进后退时,具体的加载操作还是以FrameLoader为核心的,HistoryController和BackForwardController充其量还主要是存储操作。历史项的变化也还需要由FrameLoaderClient及其在各个平台的实现来派发到WebKit及UI层(上图中WebHistoryDelegate即为Mac OS下WebView接收历史项相关信息的Delegate)。
当页面通过JS执行pushState,在WebCore就会在HistoryController中生成一个含有此State的HistoryItem,然后添加到BackForwardList(BackForwardClient)中。以下是其时序图:
其中在HistoryContrller::pushState()中会通过主Fame的HistoryContoller::createItemTree()来创建新的历史项,保存当前文档的状态。如果本身就是主Frame则不需要指定历史项间的从属关系。
以下是页面跳转时,向JS发送popState消息的时序图:
具体的行为逻辑,通读标准定义是最合适的。附链接如下:
https://html.spec.whatwg.org/multipage/browsers.html
从WebKit对外的适配,具体的实现差异比较大,但都会以历史项变化的消息通知来对应UI上的前进后退操作及状态显示,这样可以保持一致性。
比如在Mac OS下,一个历史项变化时,WebFrameLoaderClient::updateGlobalHistory()会使用如下的方式通知到WebView上:
if ([view historyDelegate]) { WebHistoryDelegateImplementationCache* implementations = WebViewGetHistoryDelegateImplementations(view); if (implementations->navigatedFunc) { WebNavigationData *data = [[WebNavigationData alloc] initWithURLString:loader->url() title:nilOrNSString(loader->title().string()) originalRequest:loader->originalRequestCopy().nsURLRequest(UpdateHTTPBody) response:loader->response().nsURLResponse() hasSubstituteData:loader->substituteData().isValid() clientRedirectSource:loader->clientRedirectSourceForHistory()]; CallHistoryDelegate(implementations->navigatedFunc, view, @selector(webView:didNavigateWithNavigationData:inFrame:), data, m_webFrame.get()); [data release]; } return; }
历史项的创建及通知流程如下:
转载请注明出处: http://blog.csdn.net/horkychen
0 0
- WebKit历史项管理的实现
- WebKit历史项管理的实现
- WebKit的历史项管理
- WebKit的历史项管理
- 任务管理的历史
- webkit的CachedImage管理解析
- 浏览历史的实现
- JavaScriptCore, WebKit的JS实现
- WebKit 中CSS的实现
- JavaScriptCore, WebKit的JS实现(
- 理解WebKit和Chromium: WebKit的CSS实现
- 理解WebKit和Chromium: WebKit的CSS实现
- 理解WebKit和Chromium: WebKit的CSS实现
- Python实现Tab自动补全和历史命令管理的方法
- 工作流管理产生的历史必然性
- 浅谈项目管理的发展历史
- 浅谈项目管理的发展历史
- OS中的内存管理的发展历史
- Hibernate基础二
- Java程序性能优化技巧
- HDOJ 4472 Count(递推)
- 如何破解CentOS的root密码
- 进制间的相互转换
- WebKit历史项管理的实现
- 零基础实测搭建xmpp服务器
- BIRT Frameset 汉化
- OC简单程序框架总结
- [LeetCode]Roman to Integer
- 各个Zend Guard版本与Zend Optimizer各版本的对应关系
- iOS8 - - 一些适配
- nodjs jugglingdb orm框架的使用
- Spring aop学习详解