webkit会维护已经访问过到链接,最直观的表现是已经访问过到链接会变色。再比如CSS中提供了visited伪类,前端开发者可以据此指定已访问链接的表现形式。
该功能是在PageGroup类中维护的,有PageGroup::addVisitedLink,PageGroup::isLinkVisited两个接口。从这两个函数中可以看到,webkit是通过HASH表的方式来存储已访问的链接。addVisitedLink实现将HASH值存入表中,isLinkVisited来判断指定HASH值是否在表中。大家可能发现了,还缺少一个关键的计算HASH值的函数,这个函数在LinkHash.h中的visitedLinkHash声明。这些HASH相关的函数在不同平台有着不同的实现,一个常规的实现在LinkHash.cpp中。而在chromium平台下,会通过LinkHashChromium.cpp将接口porting出去,由content部分来提供真正实现。
下面我们再来看看这几个接口的调用时机。先看addVisitedLink接口,在每次打开一个链接时,都需要将url加入到已访问链接HASH表。调用堆栈如下:
#0 WebCore::PageGroup::addVisitedLink
#1 WebCore::HistoryController::updateForStandardLoad
#2 WebCore::FrameLoader::transitionToCommitted
#3 WebCore::FrameLoader::commitProvisionalLoad
#4 WebCore::DocumentLoader::commitLoad
可以看出,在接收到网络数据后就会调用该接口。但该接口的调用还受到两个条件的限制,只有2个条件都满足才会维护已访问的链接。
条件一:PageGroup的shouldTrackVisitedLinks标识位,由PageGroup::setShouldTrackVisitedLinks设置,只有该值为true,才会维护已访问链接
条件二:settings->privateBrowsingEnabled(),只有该值为false,才会维护已访问链接。该值标识是否是匿名浏览,在匿名浏览的情况下,用户并不希望自己访问过到链接被记录。
isLinkVisited接口则在打开一个网页包含链接时调用,它与CSS的某些判断相关。
#0 WebCore::PageGroup::isLinkVisited
#1 WebCore::SelectorChecker::determineLinkStateSlowCase
#2 determineLinkState
#3 WebCore::StyleResolver::initElement
#4 WebCore::StyleResolver::styleForElement
#5 WebCore::Element::styleForRenderer
#6 WebCore::NodeRendererFactory::createRendererIfNeeded
#7 WebCore::Node::createRendererIfNeeded
#8 WebCore::Element::attach