WebKit历史项管理的实现

历史项管理根据标准定义,由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)中。以下是其时序图:

以下是页面跳转时,向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

时间: 2024-10-07 05:59:55

WebKit历史项管理的实现的相关文章

WebKit的历史项管理

标准定义 关于历史的管理,和HTML页面加载一样,都有其相应的标准.地址如下: WhatWG: https://html.spec.whatwg.org/multipage/browsers.html#history 其中关于历史项的要点如下: 1. 在onload之前,非用户操作引起的导航操作不建立历史项. 非用户操作比如页面中指定的Timer修改location或iframe的src引发的导航操作.而用户点击发起的Timer,则在timer中记录下在发起timer时标记手势来源.但有一个例外

ASP.NET 5 中的依赖项管理

ASP.NET 5 中的依赖项管理? 提示 本文链接: http://cnblogs.com/qin-nz/p/5034398.html 或 http://blog.qin.nz/aspnet5/aspnet5-dependency-management.html 做过实际开发的都知道,我们需要引用各种各样的类库来帮助我们完成项目的开发. 本文将从服务器端和浏览器端两个方面介绍ASP.NET 5 中的依赖项管理. 服务器端代码使用 Nuget 作为包管理器? 对于已经习惯使用 Visual St

RDIFramework.NET ━ 9.7 操作权限项管理 ━ Web部分

RDIFramework.NET ━ .NET快速信息化系统开发框架 9.7 操作权限项管理 -Web部分 随着经济全球化趋势的发展和企业间竞争的加剧,企业对管理要求不断变化.提高,越来越多的信息都表明权限管理必须向更细.更深的方向发展,其目的就是为了更好的发挥监督职能,对不相容的资源进行分离与牵制,对重要的事项进行监督与制约,重点突出精细化管理的要求.操作权限管理模块是框架权限控制的核心,贯穿于整个框架应用之中.这里的操作权限不能简单理解为一些常用的增.删.改.查,应进行更深入的分析与挖掘.比

第一周--Centos7中的 at 使用技巧及其历史命令管理和用法

**Centos 7 中的at 使用技巧及其历史命令管理和用法** 我将在本文讲述如下内容: 关于Linux的发行版及不同发行版间的联系和区别 实现晚上20:30自动关机,并提示用户 总结历史命令管理以及用法 总结Linux帮助用法 * ----------------------------- 大片如下 ------------------------------------------------------------------------------------------ 第一章:关

科略教育:《三项管理技能企业CEO不得不修炼》

身为企业CEO,有三项管理技能不得不修炼,标准化.流程化.栅格化,任何一个企业的管理都离不开这三项,越是能把这三项发挥到极致的管理,企业运营状况就愈良好.愈规范,那标准化.流程化.栅格化管理究竟是什么样呢,在企业管理中该如何执行呢? 第一.做管理就是做标准.凡事做标准,凡事有标准.福特汽车第一条自动生产流水线源自于各部位的标准化:风行全球的ISO质量体系,其本质就是由标准展开:最时髦的ERP无非信息.程序标准化的集成:PC作为产业在全球经济领域里迅速崛起,靠的就是标准化激活整个产业链:国际化公司

History API与浏览器历史堆栈管理

阅读目录 History API回顾 History API与业务实践 回顾 移动端开发在某些场景中有着特殊需求,如为了提高用户体验和加快响应速度,常常在部分工程采用SPA架构.传统的单页应用基于url的hash值进行路由,这种实现不存在兼容性问题,但是缺点也有--针对不支持onhashchange属性的IE6-7需要设置定时器不断检查hash值改变,性能上并不是很友好. 而如今,在移动端开发中HTML5规范给我们提供了一个History接口,使用该接口可以自由操纵历史记录.本文并不详细介绍Hi

Linux历史命令管理以及用法

history命令管理及用法总结  命令历史:shell进程会在其会话中保存此前用户提交执行过的命令,可以用它来重复执行命令   ~]# history     包括关机前的命令:     定制history的功能,可通过环境变量实现:       HISTSIZE:shell进程可保留的命令历史的条数:       HISTFILE:持久保存命令历史的文件:       HISTFILESIZE:命令历史文件的大小:       HISTTIMEFORMAT="%F %T ":显示时

Linux命令:history命令历史的管理及用

bash可以保存的过去曾经执行过的命令.当某个用户登录到shell中,会读取该用户家目录中的~/.bash_history文件,并将历史命令列表保存到内存中.当用户退出当前shell时,会将内存中的历史命令列表覆盖至~/.bash_history文件. 我们可以通过# histroy 来查看历史命令.history是bash的内部命令.通过# help history获取帮助. 一.history的常见选项 # history ... # 省略前面 994 man poweroff 995 po

从历史看管理

我们要发掘中国古人的管理智慧,不仅要古为今用,还要推陈出新.以历史的角度反思现代企业管理本质,每个企业都借鉴历史方案,找到分权与制衡的方法. (一)中国古代政府的管理精粹 管理没有新问题,只是问题的表现形式不同而已.从两千多年来王朝的覆灭兴衰的过程中可以找到解决下面三个问题的绝佳答案. 如何在战略层次上处理好总部与分部的关系 如何实现上层对下层的控制和监督 如何平衡管理层级 (二)现代企业应该鉴戒的四种王朝管理模式 封建制度:在这种模式制度下,分部本地化,与总部不再具有共同意志,越来越远,与土著