WebKit的历史项管理

简介: 标准定义关于历史的管理,和HTML页面加载一样,都有其相应的标准。地址如下: WhatWG: https://html.spec.whatwg.org/multipage/browsers.html#history其中关于历史项的要点如下:1. 在onload之前,非用户操作引起的导航操作不建立历史项。

标准定义

关于历史的管理,和HTML页面加载一样,都有其相应的标准。地址如下:
WhatWG: https://html.spec.whatwg.org/multipage/browsers.html#history

其中关于历史项的要点如下:

1. 在onload之前,非用户操作引起的导航操作不建立历史项。

非用户操作比如页面中指定的Timer修改location或iframe的src引发的导航操作。而用户点击发起的Timer,则在timer中记录下在发起timer时标记手势来源。但有一个例外是由另一个Timer发起的Timer或是重复执行的Timer, 则仅针对第一次执行有效(以nesting level标识)。

2. 子Frame加载完成仍有未加载的上层Frame, 则不创建历史项。

3. 当前Frame只有一个历史项,且为about:blank, 则不创建历史项。

4. 如果页面跳转的间隔小于1s,则不创建历史项。


关于Timer的nesting level可以参考这里:
http://www.w3.org/html/wg/drafts/html/CR/webappapis.html#timer-nesting-level


以上规则对应于以下三个WebKit的函数:

a. LockBackForwardList NavigationScheduler::mustLockBackForwardList(Frame& targetFrame)
LockBackForwardList NavigationScheduler::mustLockBackForwardList(Frame& targetFrame)
{
    // Non-user navigation before the page has finished firing onload should not create a new back/forward item.
    // See https://webkit.org/b/42861 for the original motivation for this.   
    if (!ScriptController::processingUserGesture() && targetFrame.loader().documentLoader() && !targetFrame.loader().documentLoader()->wasOnloadHandled())
        return LockBackForwardList::Yes;
   
    // Navigation of a subframe during loading of an ancestor frame does not create a new back/forward item.
    // The definition of "during load" is any time before all handlers for the load event have been run.
    // See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation for this.
    for (Frame* ancestor = targetFrame.tree().parent(); ancestor; ancestor = ancestor->tree().parent()) {
        Document* document = ancestor->document();
        if (!ancestor->loader().isComplete() || (document && document->processingLoadEvent()))
            return LockBackForwardList::Yes;
    }
    return LockBackForwardList::No;
}


b. HistoryController::currentItemShouldBeReplaced() const
{
    // From the HTML5 spec for location.assign():
    //  "If the browsing context's session history contains only one Document,
    //   and that was the about:blank Document created when the browsing context
    //   was created, then the navigation must be done with replacement enabled."
    return m_currentItem && !m_previousItem && equalIgnoringCase(m_currentItem->urlString(), blankURL());
}


c. void NavigationScheduler::scheduleRedirect(double delay, const URL& url)
{
    if (!shouldScheduleNavigation(url))
        return;
    if (delay < 0 || delay > INT_MAX / 1000)
        return;
    if (url.isEmpty())
        return;
    // We want a new back/forward list item if the refresh timeout is > 1 second.
    if (!m_redirect || delay <= m_redirect->delay()) {
        LockBackForwardList lockBackForwardList = delay <= 1 ? LockBackForwardList::Yes : LockBackForwardList::No;
        schedule(std::make_unique<ScheduledRedirect>(delay, m_frame.document()->securityOrigin(), url, LockHistory::Yes, lockBackForwardList));
    }
}

页面问题分析


1. Timer问题

Timer最大的问题来源于Timer Nesting Level的认定。最初WebKit建一个全局的变量记录, 容易受到不同页面,frame中Timer的影响。

比如用户点击一条链接就使用一个Timer跳转,如果这个Timer创建时,恰好有另一个repeat timer还在循环执行, 且未加载完成(onload事件没有执行), 那它就无法创建历史项,因为这时全局的nesting level大于1,将不会记录为手势触发的跳转。WebKit提交的( https://bugs.webkit.org/show_bug.cgi?id=136401 [ ^]), 本意用于避免多线程访问的问题,也刚好解决了嵌套层次错误的问题。

现在仍然有一种情况下,这个问题还会存在。见  https://bugs.webkit.org/show_bug.cgi?id=137631。如下面测试页面所示,当在一个document中,有一个repeat timer执行后, 且未加载完成(onload事件没有执行),其它Timer的跳转仍然无法创建历史项。
<html>
  <head>
  </head>
  <body>
  <input type="button" value="Goto next page" onclick="gotoNextPage();">
  <input type="button" value="Start repeating timer" onclick="startRepeatingTimer();">
  <p>
  <div id="Timer">Paused</div>
  </p>
  <script type="text/javascript">

  function gotoNextPage(){
    setTimeout(function(){location.href=" http://www.webkit.org/";},300);
  }

  function startRepeatingTimer(){
    setInterval(function(){document.getElementById("Timer").innerHTML="Running...";},500);
  }
  </script>

  <img src=" http://therecoveringpolitician.com/wp-content/uploads/2013/01/moderate.jpg" width="640" height="480">
  <img src=" http://cullogo.com/full/wallpapers-high-resolution-widescreen-hd-pk.jpg" width="640" height="480">
  <img src=" http://www.highresolutionwallpapers.net/wallpapers/autumn-1680x1050.jpg" width="640" height="480">
  </body>
</html>

2. 加载规则导致多余历史项问题

有点页面(华声论坛)由于页面在iframe的初始化及动态改变时,看起来两个src是相同的,都带有ampersand, 一个由HTML指定,另一个由JavaScript设定。
问题在于JavaScript不会转换ampersand, 这样就相当于iframe加载了两个不同的页面,从而产生了两个历史项。

使用下面的测试页面可以重现这个问题, 注意页面中两处http://m.baidu.com的写法:
<html>
  <head>
  </head>
  <body>
  <p>
  <div id="info">Loading...</div>
  </p>
  <script type="text/javascript">
    setTimeout(function(){ attr("sub_iframe"," http://m.baidu.com/?abc=23&amp;t=20080225");},5000);

    function attr(id,url){
        var obj=document.getElementById(id);
        obj.setAttribute("src", url);
    }
    
    window.onload=function(){
        document.getElementById("info").innerHTML="Loaded.";
    }

  </script>
  <iframe src=" http://m.baidu.com/?abc=23&amp;t=20080225" id="sub_iframe" width="320" height="480"></iframe><br/>
  </body>
</html>



目录
相关文章
|
SQL 安全 算法
阿里云OpenAPI 云安全中心-检查项-检查项详情-子项-通过与未通过判断依据是什么呢?好多都看不出来明显的差别?
阿里云OpenAPI 云安全中心-检查项-检查项详情-子项-通过与未通过判断依据是什么呢?好多都看不出来明显的差别?
80 1
|
7月前
|
数据库 Android开发
Android 通过升级SettingsProvider数据强制覆盖用户的设置项
Android 通过升级SettingsProvider数据强制覆盖用户的设置项 【5月更文挑战第7天】
200 5
|
5月前
|
移动开发 API UED
使用history.pushState管理浏览历史
使用history.pushState管理浏览历史
|
7月前
|
自然语言处理 小程序 API
10月开发者日回顾|订单中心、排查工具、验收工具、搜索BOX全面升级,observers 支持配置化监听
10月开发者日回顾|订单中心、排查工具、验收工具、搜索BOX全面升级,observers 支持配置化监听
188 11
|
7月前
|
小程序 IDE Java
社区每周丨订单中心模板更新及基础API增加音频与动画(5.15-5.19)
社区每周丨订单中心模板更新及基础API增加音频与动画(5.15-5.19)
79 11
|
Java API 数据安全/隐私保护
历史上的今天大事件查询工具推荐 - 历史上的今天 API
历史上的今天大事件查询工具推荐 - 历史上的今天 API
378 0
wincvs2.0—查看文件历史信息图形
wincvs2.0—查看文件历史信息图形
119 0
wincvs2.0—查看文件历史信息图形
|
编解码 自然语言处理 数据可视化
FL Studio 21新版更新全解析!2023年新增80项更新与改进!
FL Studio 21全称Fruity Loops Studio,就是大家熟悉的水果编曲软件,一个全能的音乐制作软件,包括编曲、录音、剪辑和混音等诸多功能,让你的电脑编程一个全能的录音室。FL Studio 21版本发布了,为我们带来了多种新功能,大大提高处理效率,轻松应对各种复杂的编曲任务,小编带来的是FL Studio 21中文版,内置中文补丁,可以切换成中文界面。 今天为大家展示了 FL STUDIO21 新增的插件,今天让我们看一看还有哪些新变化?
265 0
FL Studio 21新版更新全解析!2023年新增80项更新与改进!
|
安全 iOS开发 开发者
ios应用列表调整后排名规则
ios应用列表调整后排名规则

热门文章

最新文章