首页 > 其他分享 >WebKit Inside: CSS 样式表解码字符集

WebKit Inside: CSS 样式表解码字符集

时间:2023-09-30 17:22:53浏览次数:27  
标签:TextResourceDecoder Inside charset 字符集 样式表 WebKit 解码 CSS

CSS 样式表引入有3种方式: 外部样式表、内部样式表、行内样式,不同的引入方式,解码样式表的字符集原理不一样。

外部样式表

外部样式表由 link 标签引入,当 WebKit 解析到 link 标签时就会构造 CachedCSSStyleSheet 对象。这个对象持有 CachedResourceRequest 对象和 TextResourceDecoder 对象。CachedResourceRequest 对象负责发送请求,TextResourceDecoder 对象负责对下载回来的 CSS 数据进行解码。TextResourceDecoder 对象里面的 m_encoding 属性,就是存储着解码 CSS 数据使用的字符编码信息。相关类图如下所示:

 在创建 TextResourceDecoder 对象时,会传入 CachedResourceRequest 使用的字符集信息,代码如下所示:

CachedCSSStyleSheet::CachedCSSStyleSheet(CachedResourceRequest&& request, PAL::SessionID sessionID, const CookieJar* cookieJar)
    : CachedResource(WTFMove(request), Type::CSSStyleSheet, sessionID, cookieJar)
    // 1. 创建 TextResourceDecoder,传入 CachedResourceRqeuest 字符集
    , m_decoder(TextResourceDecoder::create(cssContentTypeAtom(), request.charset()))
{
}

在上面代码注释 1 处,就是 CachedCSSStyleSheet 创建 TextResourceDecoder 对象,并且传入了 CachedResourceReqeust 的字符集用来初始化 TextResourceDecoder 内部的 m_encoding 属性,代码如下:

inline TextResourceDecoder::TextResourceDecoder(const String& mimeType, const PAL::TextEncoding& specifiedDefaultEncoding, bool usesEncodingDetector)
    : m_contentType(determineContentType(mimeType))
    // 1. specifiedDefaultEncoding 就是传入的 CachedResourceRequest 的字符集
    // m_contentType 此时是 CSS
    , m_encoding(defaultEncoding(m_contentType, specifiedDefaultEncoding))
    , m_usesEncodingDetector(usesEncodingDetector)
{
}

在上面代码注释 1 处初始化 TextResourceDecoder 的 m_encoding 属性,m_contentType 此时的值是 CSS,specifiedDefaultEncoding 就是 CachedResourceRequest 的字符集。但是在初始化 m_encoding 时,并不是直接将 m_encoding 直接赋值为 specifiedDefaultEncoding,而是调用了 TextResourceDecoder::defaultEncoding 函数,相关代码如下:

const PAL::TextEncoding& TextResourceDecoder::defaultEncoding(ContentType contentType, const PAL::TextEncoding& specifiedDefaultEncoding)
{
    // Despite 8.5 "Text/xml with Omitted Charset" of RFC 3023, we assume UTF-8 instead of US-ASCII 
    // for text/xml. This matches Firefox.
    // 1. 如果解码的是 XML ,那么无论传入的 specifiedDefaultEncoding 是什么值,都使用 UTF-8 作为默认解码字符集
    if (contentType == XML)
        return PAL::UTF8Encoding();
    // 2. 对于其他资源类型,如果 specifiedDefaultEncoding 使用的字符集名为 null,就默认使用 Latin-1 字符集,
    // 也就是 ISO-8859-1
    if (!specifiedDefaultEncoding.isValid())
        return PAL::Latin1Encoding();

    // 3. 将 specifiedDefaultEncoding 作为 TextResourceDecoder 的默认解码字符集
    return specifiedDefaultEncoding;
}

上面代码注释 1 处可以看出,TextResourceDecoder 不仅用来解码 CSS,还可以用来解码其他资源类型。如果解码的资源类型是 XML,那么默认的解码字符集就是 UTF-8。

从注释 2 处可以看到,如果不是 XML 资源类型,并且 specifiedDefaultEncoding 不合法,也就是 specifiedDefaultEncoding 内部代码字符集名的 m_name 属性为 null,那么就使用 Latin-1(也就是 ISO-8859-1) 作为 TextResourceDecoder 的默认解码字符集。

从注释 3 可以看到,对于非 XML 资源类型,specifiedDefaultEncoding 就会作为 TextResourceDecoder 的默认解码字符集。也就是会说,解码 CSS 的默认字符集和 CacheResourceRequest 使用同一个字符集。

 

那么,CacheResourceRequest 的字符集是如何来的呢?相关代码如下:

void HTMLLinkElement::process()
{   
    ...
    if (m_disabledState != Disabled && treatAsStyleSheet && document().frame() && m_url.isValid()) {
        // 1. 解析 link 标签的 charset 属性值
        String charset = attributeWithoutSynchronization(charsetAttr);
        if (!PAL::TextEncoding { charset }.isValid())
            // 2. 获取文档 Document 使用的字符集
            charset = document().charset();
        ...
        // 3. 设置 CachedResourceRequest 的字符集
        request.setCharset(WTFMove(charset));
        ...
        return;
    }
    ...
}

上面代码注释 1 处首先解析 link 标签的 charset 属性,如果解析到就使用这个字符集作为 CachedResourceRequest 的字符集,如 注释 3所示。如果解析不到,就使用文档 Document 的字符集作为 CachedResourceReqeust 的字符集,如注释 2 所示。文档 Document 的字符集由 <meta> 标签指定,如果没有 <meta> 标签,那么文档 Document 默认使用 Latin-1 字符集(ISO-8859-1)。

 

但是,解码 CSS 使用的字符集此时还并没有完全确定,因为 CSS 样式表本身支持 @charset at-rule,它可以指定解码 CSS 样式表需要使用什么字符集。因此,当从网络上下载到 CSS 样式表之后,还需要检测 CSS 样式表里面是否有 @charset at-rule,相关代码如下:

String TextResourceDecoder::decode(const char* data, size_t length)
{
    ...
    if (m_contentType == CSS && !m_checkedForCSSCharset)
        // 1. 当下载完 CSS 样式表,这里调用 checkForCSSCharset 函数,检测样式表里是否有 @charset
        if (!checkForCSSCharset(data, length, movedDataToBuffer))
            return emptyString();
    ...
}

上面代码注释 1处,当下载完 CSS 样式表使用 TextResourceDecoder 进行解码时,会调用 TextResourceDecoder::checkForCSSCharset 检测 CSS 样式表里面是否有 @charset at-rule。如果有 @charset at-rule,那么就将 TextResourceDecoder 的 m_encoding 属性值设置为 @charset 指定的字符集。

 

综上所述,对于外部引入的样式表,解码字符集的优先级为:

1 如果样式表有 @charset at-rule,就优先使用 @charset 指定的字符集;

2 否则,就看 link 标签有没有 charset 属性,有的话就优先使用 link 标签 charset 属性指定的字符集;

3 否则,就使用文档 Document 的字符集。

内部样式表与行内样式

由于内部样式表和行内样式本身就在 HTML 文件里面,因此对于它们的解码就使用 HTML 字符集。HTML 解码字符集确认规则如下:

1 如果有 <meta> 标签,就使用 <meta> 标签使用的字符集;

2 否则,就默认使用 Latin-1(ISO-8859-1) 字符集

 

标签:TextResourceDecoder,Inside,charset,字符集,样式表,WebKit,解码,CSS
From: https://www.cnblogs.com/chaoguo1234/p/17737902.html

相关文章

  • Datainside数据分析,基于大数据分析学生成绩综合评价
    Datainside是一种基于大数据分析的学生成绩综合评价方法,通过对海量学生成绩数据进行深度挖掘和分析,为学生的学习表现提供全面、客观的评价。以下是对Datainside数据分析学生成绩综合评价的详细描述:1.数据收集:Datainside首先需要收集大量学生成绩数据,包括不同科目、不同年级、不......
  • 【matplotlib基础】--样式表
    Matplotlib库由于诞生的比较早,所以其默认的显示样式很难符合现在的审美,这也是它经常为人诟病的地方。不过,经过版本更迭之后,现在Matplotlib已经内置了很多样式表,通过使用不同的样式表,可以整体改变绘制图形的风格,不用再调整一个个显示参数。1.样式表的使用1.1.所有内置样式......
  • CSS gradient渐变之webkit核心浏览器下的使用
    [color=red][b]一、关于渐变[/b][/color]渐变是一种应用于平面的视觉效果,可以从一种颜色逐渐地转变成另外一种颜色,故可以创建类似于彩虹的效果渐变可以应用在任何可以使用图片的地方。例如,您可以指定一个这么一个渐变:顶部的颜色是红色,中间的是蓝色,底部为黄色来作为div的背景色。渐......
  • 数据驱动决策,Datainside引领可视化报告新时代
     数据驱动决策已经成为当今社会中的重要趋势,而Datainside作为一家数据可视化报告平台,正引领着可视化报告的新时代。下面是关于Datainside平台的详细描述。数据集成与连接Datainside平台提供强大的数据集成和连接功能。它可以与各类数据源进行无缝连接,包括企业内部的数据仓库......
  • Qt-QWidget对样式表设置边框无效的解决方法
    相关资料:https://www.ngui.cc/el/1647992.html?action=onClick   1、现象在对QWidget使用样式表时无效QWidget#MyWgt{border:1pxsolidgray;}2、原因原因是QWidget只支持background、background-clip和background-origin属性。官方说明3、解决方法3.1使用QFrame代替QW......
  • Android官方资料--Inside OTA Packages
    InsideOTAPackagesINTHISDOCUMENTEdifysyntaxBuilt-infunctionsThesystembuildstheupdaterbinaryfrombootable/recovery/updater andusesitinanOTApackage.Thepackageitselfisa.zipfile(ota_update.zip,incremental_ota_update.zip)that......
  • 解决vue项目build的时候报错Warning: Accessing non-existent property ‘cat‘ of mo
    *正在执行任务:npmrunbuild>[email protected]>nodebuild/build.js-buildingforproduction...(node:8992)Warning:Accessingnon-existentproperty'cat'ofmoduleexportsinsidecirculardependency(Use`node--trace-warnings...`t......
  • Webkit 实现页面滚动条美化
    当页面或者某个容器布局内容超出过后,就会有滚动条,但默认的有点丑,经常需要自己来美化一下,这里做个笔记吧./*美化全局的滚动条*/::-webkit-scrollbar{width:4px;height:6px;}::-webkit-scrollbar-corner{display:block;}::-webkit-scrollbar-thumb{......
  • 样式表文件
    样式表文件用于定义网页的样式和布局,常用的样式表文件类型有CSS(层叠样式表)和Sass(SyntacticallyAwesomeStyleSheets)。CSS样式表文件:CSS是一种用于描述网页样式的语言,通过CSS样式表文件可以集中管理网页的样式。在HTML文件中使用<link>标签引入CSS样式表文件,例如:<linkrel="......
  • webkit webApp 开发技术要点总结
    如果你是一名前端er,又想在移动设备上开发出自己的应用,那怎么实现呢?幸好,webkit内核的浏览器能帮助我们完成这一切。接触webkitwebApp的开发已经有一段时间了,现把一些技巧分享给大家:1.viewport:也就是可视区域。对于桌面浏览器,我们都很清楚viewport是什么,就是出去了所有工具栏、......