《WebKit 技术内幕》学习之十(4): 插件与JavaScript扩展

4 Chromium扩展机制

4.1 原理

        Chromium的扩展(Extension)机制 (1) 原先是Chromium推出的一项技术,该机制能够扩展浏览器的能力,例如笔者使用的一个扩展实例名为“switchy proxy”,它可以帮助用户方便的切换Chromium浏览器代理,但是也仅此而已。本质上,它其实就是浏览器能力的简单扩展,而对于一些本地的功能,如书签、USB、蓝牙、电源管理等,该机制并没有这方面的能力。

         一个Chromium Extension的实例其实就是一个网页加上JavaScript代码和CSS样式代码。当然,在Extension中,开发者也可以使用NPAPI插件和PPAPI及NaCl机制技术来扩展网页能力,所以它同这些技术没有冲突,相反,Chromium Extension机制可能需要这些技术以实现特定功能。

        当然,Chromium Extension机制的目标远不止这么简单,扩展浏览器功能的Extension只是其中一个很小的功能。随着该机制的不断发展,Extension机制已经被用来支持Web应用程序,也就是使用HTML5、JavaScript、CSS等技术来开发应用程序,该应用程序可以使用Chromium浏览器来运行,而用户获得的体验同本地应用程序非常接近,听起来非常吸引人吧。Chromium打造了一个依赖于Web的运行平台,使用扩展机制的网页已经可以简单称之为Web应用。如果读者认为功能还不够,也可以将其理解为初级阶段,但是它实实在在将网页扩展到Web应用的范畴。在Google的Web Store (2) 中,读者可以发现两个类别,包括传统的Extension和Web应用。从用户的角度看,普通扩展和Web应用的区别在于普通插件只是Extension在当前窗口运行(当然也不是绝对的,但是工作机制与Web应用的确不一样),而Web应用是一个独立的窗口。

        图10-15是Chrome浏览器中已经安装的Extensions(Google Docs)和Web应用(Cut the Rope),读者可以通过在地址栏输入“chrome://extensions/”来查看它们。

                   图10-15 Chromium浏览器中已安装的Extensions和Web应用

        在目前的Chromium项目中,对于Web应用,Chromium根据特性将其分成两类,第一种叫做Host App,另外一种叫做Packaged App。前面一种表示将网络上的资源直接变成一个Web应用,所以它需要使用外部的资源才能够工作,而对于后一种,该Web应用所需要的文件和资源都包含在该应用中,而不需要外部的资源,所以对于那些离线应用特别有用,这让使用者感觉更像本地应用。关于W3C和Chromium的Web应用详细情况,我们将在第15章重点讲解,这里只是一个简单的介绍。

        因为目前的网页只是由HTML5、JavaScript和CSS等文件组成,所以还需要其他辅助功能才能形成一个Chromium的扩展实例。Chromium的Extension机制使用一个清单文件(manifest.json)来描述Extensions所需要的文件和资源等,这样使得它看起来更像一个应用程序,因为现在很多应用程序都是使用该种方式,例如Android平台上的AndroidManifest.xml,或者W3C为Web应用定义的Widget方式,示例代码10-9是一个简单的清单文件实例。

        熟悉JavaScript语言的开发者可以发现,它其实是一个JSON格式的文件,里面的属性名也非常的直观,例如Extension的名字、版本号、应用图标等。值得注意的是,它包含了一个属性“permissions”,该属性设置了该Web应用能够访问哪些功能,例如“plugins”表明该Extension能够使用NPAPI插件,“notification”表示可以从该Extension发出通知,这也同移动平台上的本地应用有类似的地方。

示例代码10-9 Chromium Extension的清单文件(manifest.json)

    {
      "name": "An Extension",
      "description": "Just an example",
      "version": "1",
      "app": {
        "launch": {
          "web_url": "http://blog.csdn.net/milado_nju/"
        }
      },
      "icons": {
        "128": "icon_128.png"
      },
      "permissions": [
        "notifications",
        "plugins",
        "management"
      ]

        其实,上面提供的这些权限所使用的功能,有些在HTML5中并没有被定义,例如“management”,但是Chromium的这些Extension实例能够使用它们,原因在于Chromium提供了一些JavaScript接口,这就是著名的“chrome.*”应用程序编程接口。本质上,它们是一系列的JavaScript接口,包括标签、管理、历史记录、USB等,功能还是非常的丰富。当Chromium的Extension实例需要使用这些接口的时候,必须在该清单文件中申明它们,否则Chromiunm会拒绝它们的请求。

        对于Chromium的Extension实例和Web应用,它们会共享一些接口,但是两者还会提供不同的接口,这是由于各自的目的不同。对于传统的Extension实例而言,这里面包含“alarms”、“bookmarks”、“cookies”和“runtime”等。而对于Web应用而言,它们可以使用“app.runtime”、“app.window”、“bluetooth”和“runtime”等。这些接口也是对JavaScript能力的一种扩展,不同于NPAPI和PPAPI使用的扩展机制,“chrome.*”接口使用一种新的机制来处理多进程之间的通信,这依然是消息传递机制。

4.2 基本设施

        针对Chromium的Extension机制,主要是解决两个大方面的问题,第一是Extension实例的管理工作,包括安装、更新、删除等;第二是Extension实例是如何运行的。对于第一个问题,相关的过程比较复杂,这里不便介绍。笔者主要介绍第二个问题,包括Extension运行时需要涉及到的基础设施,它同本章的重点JavaScript扩展密切相关,由于Extension运行时需要调用“chrome.*”接口,我们必须了解这些接口是如何被扩展和实现的。

        从基本过程上来看,简单地讲应该是Chromium的Extension机制在V8引擎中注入一些代码,然后当JavaScript代码调用这些接口的时候,V8引擎调用注入的本地代码,这些代码会将调用接口的请求从Renderer进程发送给Browser进程。在Browser进程中,接收这些请求并派发给相应的实现类,请求完成后按需要返回调用结果。

        首先来看Renderer进程,图10-16是运行Extension实例时所使用的一些主要类,简单介绍如下。

                                图10-16 Renderer进程中Extension运行时所需的类

  • ChromeV8Context :对V8引擎上下文对象的一个简单封装,帮助注入代码和拥有Extension实例的本地实现函数列表。
  • ModuleSystem :管理所有注册的“chrome.*”接口,当然接口的具体实现在Browser进程中(读者考虑一下为什么呢),这里主要是注册回调的函数,这些回调函数会将对接口的调用发送请求给Browser进程的具体实现类。
  • NativeHandler,ObjectBackedNativeHandler,ChromeV8Extension :接口类(继承关系),用于表示每个“chrome.*”的接口,至于为什么有几层继承是因为需求,同时需要注入管理的回调函数。
  • Dispatcher :该类负责同Renderer进程创建过程交互,也就是说它知道什么时候该注入这些回调函数。
  • EventBindings :实现chrome.events接口的辅助类,它会定义一个ChromeV8Extension的子类。

下面是Browser进程的相关类,如图10-17所示,相对比较简单一些。

图10-17 Browser进程中Extension运行时所需的类

  • ExtensionHost :负责处理请求的消息,并回复请求结果。
  • ExtensionFunctionDispatcher :将请求转换成对ExtensionFunction的调用,因为如chrome.boomarks这样的接口,包含多个函数,这里每个函数对应于一个ExtensionFunction对象。
  • ExtensionFunction、AsyncExtensionFunction、BookmarksFunction和Bookmarks-GetFunction :用于表示接口中的函数,而BookmarksGetFunction对应的函数是“chrome.bookmarks.get()”。

下面来看看Chromium是如何进行“chrome.*”的接口初始化工作,主要是Renderer进程的工作的。

        首先当然是网页的解释工作,在创建Document对象的时候,WebKit使用ScriptController类来注入Chromium的Extension机制所需要的代码,这里会调用类Dispatcher,该类此时创建一个ModuleSystem对象,并将各种各样的NativeHandler对象注册,这里的NativeHandler就是各种各样的“chrome.*”的接口。

        然后在注册这个NativeHandler的时候,每个该类的对象表示一个接口,每个类别的接口创建一个ObjectTemplate,该对象包含一个FunctionTemplate对象,当调用该接口的任何函数的时候,就会调用ObjectBackedNativeHandler类的Router函数。

        最后,在注册完之后,完成网页渲染的工作,当执行到JavaScript代码调用“chrome.*”接口的时候,就会调用Router函数,之后就使用消息传递机制将请求传递给Browser进程。

4.3 消息传递机制

        Chromium的扩展机制的一个重要的特性是使用消息传递机制来提供大量JavaScript新的接口,前面已经提到V8引擎会调用Router方法,这里详细解释一个接口中的函数是如何使用消息传递机制来工作的。

        可以结合图10-18和图10-19来理解Extension机制中对“chrome.*”接口的函数调用过程,图中的数字(1、2、3)表示调用顺序,首先是Renderer进程中的“1”过程,其次是Browser进程中的“2”过程,最后是Renderer进程中的“3”过程,其中两个进程都是通过消息传递机制实现,这里消息是将JavaScript函数中的所有调用转成字符串来处理,也就是当调用某个接口的时候,首先在Renderer进程中,V8的引擎将使用接口名来查找NativeHandler,使用字符串来表示调用函数名,并将参数序列化成JSON格式的字符串传递给Browser进程,这些对函数的调用都是借助函数名和JSON字符串,称为Extension机制的消息传递机制,如图10-18所示。

图10-18 V8引擎调用“Chrome.*”接口在Renderer进程中的处理

图10-19 Chromium在Browser进程中的处理Extension的函数调用

        然后是图10-19中的“2”过程,经过一系列的处理之后,最终会调用具体的函数实现类,这里就是BookmarkGetTreeFunction,读取JSON字符串并计算得出结果返回给Renderer进程。

        最后就是图10-18中的“3”过程,得到回复结果之后,最后需要将它们传入V8引擎,这里就是使用ChromeV8Context,它包含一个V8引擎运行上下文,使用该上下文将结果传入V8引擎。

        上面这些过程在实际的实现过程更为复杂,这里省略了中间过程中的一些函数调用,但是并不妨碍读者理解。经过上面这三个过程,就完成了一次对“chrome.*”接口中定义的函数实现的调用过程。

        本章介绍的这些扩展机制在现代浏览器中仍然发挥着重要的作用,因为扩展能力和支持Web应用程序的需要依然存在。相信通过这些介绍,读者可以了解它们内在的机制和展现出来的能力,不妨进行一些实现上的尝试。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/349092.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode—29. 两数相除【中等】

2023每日刷题(九十四) Leetcode—29. 两数相除 叛逆期实现代码 class Solution { public:int divide(int dividend, int divisor) {if(dividend INT_MIN && divisor -1) {return INT_MAX;} return dividend / divisor;} };运行结果 倍增算法…

EG-2121CA (晶体振荡器 低抖动表面声波(SAW)振荡器)

在当今高度数字化的时代,稳定的信号传输显得尤为重要。若要实现信号的稳定传输,晶体振荡器必不可少。EG-2121CA,它是一款低抖动表面声波(SAW)振荡器设计的产品,凭借其出色的频率范围、稳定的电源电压和可靠…

JAVA泛型、泛型通配符、综合练习

作用&#xff1a; 是 jdk5 中引入的特性&#xff0c;可以在编译阶段 约束 操作的数据类型&#xff0c;并进行检查。 格式&#xff1a; <数据类型> 注意泛型只能支持引用数据类型&#xff0c;基本数据类型可转成对应的包装类。 问题&#xff1a; 在没有泛型的时候&…

「JavaSE」抽象类接口3

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;快来卷Java啦 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 抽象类&接口3 &#x1f349;Clonable 接口和深拷贝&#x1f34c;浅拷贝和深拷贝 &#x1f349;Object类&#x1f349;抽象类…

无法获得dpkg前端锁、Linux之E: 无法锁定管理目录(/var/lib/dpkg/),是否有其他进程正占用它?(解决方法)

无法获得dpkg前端锁的解决方法 sudo rm /var/lib/dpkg/lock sudo rm /var/lib/dpkg/lock-frontend sudo rm /var/cache/apt/archives/lock 输入以上三个命令即可解除占用。解除后&#xff0c;继续运行apt命令&#xff0c;已经顺利运行了。解除前端锁后&#xff0c;Linux之E: 无…

.net访问oracle数据库性能问题

问题&#xff1a; 生产环境相同的inser语句在别的非.NET程序相应明显快于.NET程序&#xff0c;执行时间相差比较大&#xff0c;影响正常业务运行&#xff0c;测试环境反而正常。 问题详细诊断过程 问题初步判断诊断过程&#xff1a; 查询插入慢的sql_id 检查对应的执行计划…

20240122面试练习题10

1. Redis为什么执行这么快&#xff1f; 二、Redis为什么这么快&#xff1f; 1、完全基于内存&#xff0c;数据存在内存中&#xff0c;绝大部分请求是纯粹的内存操作&#xff0c;非常快速&#xff0c;跟传统的磁盘文件数据存储相比&#xff0c;避免了通过磁盘IO读取到内存这部分…

配置接口策略路由案例

知识改变命运&#xff0c;技术就是要分享&#xff0c;有问题随时联系&#xff0c;免费答疑&#xff0c;欢迎联系 厦门微思网络​​​​​​ https://www.xmws.cn 华为认证\华为HCIA-Datacom\华为HCIP-Datacom\华为HCIE-Datacom Linux\RHCE\RHCE 9.0\RHCA\ Oracle OCP\CKA\K8S\…

如何使用Jellyfin+cpolar搭建私人影音平台实现无公网ip远程访问

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及&#xff0c;各种各样的使用需求也被开发出来&…

jQuery实现选择方法和保护信息方法

最近呢&#xff01;一直在学习jQuery语法&#xff0c;也没时间发布文章&#xff0c;现在学的差不多了&#xff0c;先跟大家分享下学习感受吧&#xff01;JavaScript学过后&#xff0c;再学习jQuery语法&#xff0c;应该是简单的&#xff0c;但我总是容易把它们搞混&#xff0c;…

Alzet渗透泵工作原理,你清楚么?

由于Alzet渗透泵独特的释放原理&#xff0c;使得许多化学试剂、药剂或者其他物质&#xff0c;可以通过Alzet渗透泵应用到科研试验中。一个小小的胶囊就可以完成持续的动物给药实验&#xff0c;对于科研实验者来说就是一个福音。 那你了解Alzet渗透泵么?让我们一起来简单了解一…

Android HIDL概述与绑定模式的实现

一、前言 Android O(8.0) 版本之后&#xff0c;底层实现有了比较大的变化&#xff0c;最显著的一个方面就是 HIDL 机制的全面实施。本文对于理解系统源码中 Gnss、Usb、Camera 等模块的工作原理有极大帮助。 二、HIDL 设计目的 在 Android O(8.0) 之前系统的升级牵扯多方协作…

循环购:电商新时代的消费革命

随着电商市场的竞争加剧&#xff0c;消费者需求日益多样化&#xff0c;电商企业需要不断创新以满足市场需求。循环购模式作为一种新兴的消费模式&#xff0c;正逐渐受到消费者的青睐&#xff0c;成为电商行业的新热点。本文将深入剖析循环购模式的魅力&#xff0c;探索其在电商…

chromedriver下载地址与安装方法

用到例如selenium时&#xff0c;需要使用谷歌浏览器并配合chromedriver进行模拟浏览等 分享chromedriver的实时更新的下载网址&#xff1a; https://registry.npmmirror.com/binary.html?pathchromedriver/ 。。。 需要找到自己电脑谷歌浏览器版本所对应的chromedriver版本 …

CQ 社区版 2.8.0 | 支持TiDB、StarRocks,新增列过滤算法、导出模式设置等

Hello&#xff0c;CloudQuery 社区版 2.8.0 已发布&#xff0c;本文将带大家详细解析本次更新的功能~&#xff08;完整的讲解视频可点击 &#x1f449;&#x1f3fb; CloudQuery 社区版2.8.0 功能讲解演示 本期亮点更新 新增支持数据源 TiDB、StarRocks数据保护新增列过滤脱敏…

HNSW算法

From&#xff1a; HNSW算法(nsmlib/hnswlib)-CSDN博客HNSW算法的基本原理及使用 - 知乎 HNSW是一种广泛使用的ANN图索引结构&#xff0c;包括DiskANN、DF-GAS、SmartSSD等。本文档主要总结HNSW的结构与工作流程&#xff0c;便于后期研究其工作流程在迁移到CSD中存在的I/O问题…

计算CNN卷积层和全连接层的参数量

计算CNN卷积层和全连接层的参数量 先前阅读 CNN ExplainerA Comprehensive Guide to Convolutional Neural Networks — the ELI5 way 本文主旨意在搞明白2个问题&#xff1a; 第一个问题 一个卷积操作&#xff0c;他的参数&#xff0c;也就是我们要训练的参数&#xff0c;也…

50. Pow(x, n)

分治算法&#xff1a; 从右往左开始递归计算&#xff0c;假设yx^(n/2)&#xff0c;那么当n为偶数时&#xff0c;x^ny*y&#xff0c;当n为奇数时&#xff0c;x^ny*y*x。 另外&#xff0c;注意n有可能是负数。 class Solution {public double myPow(double x, int n) {int N n…

Kettle-Docker部署+Sqlserver数据同步Mysql+Start定时任务

一. 背景介绍 1. ETL是什么 ETL&#xff08;Extract-Transform-Load&#xff09;&#xff0c;即数据抽取、转换、装载的过程。它是一种思想&#xff0c;主要是说&#xff0c;从不同的数据源获取数据&#xff0c;并通过对数据进行处理&#xff08;格式&#xff0c;协议等转换&a…

ChatGPT 全域调教高手:成为人工智能交流专家

随着人工智能的快速发展&#xff0c;ChatGPT作为一种强大的文本生成模型&#xff0c;在各行各业中越来越受到重视和应用。想要利用ChatGPT实现更加智能、自然的交流&#xff0c;成为 ChatGPT 全域调教高手吗&#xff1f;本文将为您介绍如何通过优化ChatGPT的训练方法&#xff0…