历史项管理依据标准定义,由Page管理一个Joint Session History, 包括了各个子Frame的历史项。逻辑上相应例如以下的关系:

从上面看三个层次: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

最新文章

  1. 关于opencv中人脸识别主函数的部分注释详解。
  2. DSP using Matlab 示例Example2.2
  3. 算法(第4版)-1.3.1 API
  4. ecshop利用.htaccess实现301重定向的方法
  5. 2016年11月4日 星期五 --出埃及记 Exodus 19:20
  6. 标准IO操作
  7. DPDK内存管理-----(三)rte_malloc内存管理
  8. hdu4421-Bit Magic(2-SAT)
  9. delphi中使用webbrowser提交表单
  10. Spring Mvc 笔记二之异常和文件上传
  11. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
  12. sql语句判断两个时间段是否有交集
  13. linux 端口占用
  14. Autohotkey window 下宏键盘、宏命令开发入门
  15. BZOJ 2434 阿狸的打字机 | AC自动机
  16. ng之自定义指令
  17. phpwind部署问题
  18. (转).net平台下垃圾回收机制
  19. pthread_join与pthread_detach细节问题
  20. kibana对logstash监控获取不到数据

热门文章

  1. web版扫雷小游戏(三)
  2. js 高级函数 之示例
  3. WPF学习(二)布局与菜单、工具栏
  4. 不为人知的Locked
  5. php开源项目学习二次开发的计划
  6. Tomcat 架构 (一)
  7. HTML和CSS特殊属性
  8. vs2010编译curl为static库及测试
  9. BZOJ1609: [Usaco2008 Feb]Eating Together麻烦的聚餐
  10. (转载)mysql中limit用法