Chromium源码阅读:Mojo实战:从浏览器JS API 到blink实现


通过在前面几篇文章,我们粗略梳理了Mojo这套跨进程通信的设计思路和IDL细节。

实际上,Mojo不止是跨进程通信框架,而是跨语言的模块通信自动化系统。

在浏览器暴露的JS API,也是需要通过Mojo这个系统进行桥接,最终到blink的实现上。

我们打开浏览器控制台,可以输入 window.cookieStore.getAll()获取当前默认Frame的Cookie。如下图:
在这里插入图片描述
我们以这个API为例子,看看Chromium是如何实现这个功能的。

确定Web标准

这个API是基于Cookie Store API的Web标准的一部分。首先,我们可以先查找相关的Web标准文档以了解这个API的定义和预期行为。
Cookie Store API

CookieStore 接口的 getAll() 方法返回与传递给它的 name 或 options 匹配的所有 cookie 列表。 语法

getAll(name) getAll(options)

参数 name 可选 记录 cookie 名称的字符串。 或 options 可选 一个包括以下属性的对象:name:记录 cookie
名称的字符串。 url:记录 cookie URL 的字符串。 返回值:一个兑现为与指定的 name 或 options 对象匹配的
cookie 信息对象的 Promise。

寻找IDL 定义

这个API是Web标准API,肯定在blink/render下面,简单一搜就找到了:
在这里插入图片描述
打开third_party\blink\renderer\modules\cookie_store\cookie_store.idl:

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// https://wicg.github.io/cookie-store/explainer.html

[
  Exposed=(ServiceWorker,Window),
  SecureContext
] interface CookieStore : EventTarget {
  // https://wicg.github.io/cookie-store/explainer.html#the-query-api
  [CallWith=ScriptState, Measure, RaisesException] Promise<CookieListItem?> get(
      USVString name);
  [CallWith=ScriptState, Measure, RaisesException] Promise<CookieListItem?> get(
      optional CookieStoreGetOptions options = {});
  [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList> getAll(
      USVString name);
  [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList> getAll(
      optional CookieStoreGetOptions options = {});

  // https://wicg.github.io/cookie-store/explainer.html#the-modifications-api
  [CallWith=ScriptState, Measure, RaisesException] Promise<undefined> set(
      USVString name, USVString value);
  [CallWith=ScriptState, Measure, RaisesException] Promise<undefined> set(
      CookieInit cookieInit);
  [CallWith=ScriptState, ImplementedAs=Delete, Measure, RaisesException]
  Promise<undefined> delete(USVString name);
  [CallWith=ScriptState, ImplementedAs=Delete, Measure, RaisesException]
  Promise<undefined> delete(CookieStoreDeleteOptions options);

  // https://wicg.github.io/cookie-store/explainer.html#the-change-events-api
  [Exposed=Window] attribute EventHandler onchange;
};

这个idl不复杂,我们针对其内容,简单做了注释标注,方便读者理解:

// Cookie Store API的解释器文档链接
// https://wicg.github.io/cookie-store/explainer.html

// 定义一个名为CookieStore的接口,它在ServiceWorker和Window环境中被暴露,
[
  Exposed=(ServiceWorker,Window), // 暴露给ServiceWorker和Window
  SecureContext // 并且仅在安全上下文中可用(如HTTPS)
] interface CookieStore : EventTarget {
  // 查询API部分的解释器文档链接
  // https://wicg.github.io/cookie-store/explainer.html#the-query-api  
  // ...
  [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList> getAll(
      USVString name);
  // 使用选项获取所有匹配的cookies。返回一个包含cookie信息数组的Promise对象。
  [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList> getAll(
      optional CookieStoreGetOptions options = {});
  // ...
};

[CallWith=ScriptState]表示函数在调用时需要当前的脚本状态,[Measure]表示该函数调用会被性能监控工具记录,而[RaisesException]则表明该函数可能会抛出异常。Promise表示该方法操作成功后会返回一个解决为undefined的Promise对象,Promise<CookieListItem?>表示返回的Promise对象会解决为CookieListItem类型或者null。ImplementedAs属性用于指定C++实现中对应的方法名。

查看对应生成的文件:

所有的mojom生成的文件都会放到out\xxx\gen目录下。根据源文件路径,很容易找到对应的生成文件:
在这里插入图片描述
看起来有点多,别紧张,我们依次进行解释:

C++ 绑定和实现文件

  • cookie_store.mojom.h

    • 这是CookieStore接口的主要C++绑定头文件,包含接口定义和相关类型。
  • cookie_store.mojom.cc

    • 这个文件包含CookieStore接口的主要C++实现,通常与.mojom.h头文件相关联。
  • cookie_store.mojom-blink.h

    • 这是为Blink层生成的CookieStore接口的C++绑定头文件。
  • cookie_store.mojom-blink.cc

    • 包含Blink层CookieStore接口的C++实现,与cookie_store.mojom-blink.h头文件相关联。

内部共享定义和辅助文件

  • cookie_store.mojom-shared-internal.h
    • 这个文件包含CookieStore接口的内部共享定义,例如序列化和反序列化逻辑。
  • cookie_store.mojom-shared.cc
    • 包含CookieStore接口共享代码的C++实现,如序列化和反序列化帮助函数。
  • cookie_store.mojom-params-data.h
    • 包含与CookieStore中的方法参数相关的结构体和序列化/反序列化逻辑。
  • cookie_store.mojom-shared-message-ids.h
    • 包含CookieStore接口中所有消息的唯一标识符(ID),用于IPC通信。

导入和前向声明文件

  • cookie_store.mojom-import-headers.h
    • 这个文件导入所有必需的头文件,用于非Blink代码。
  • cookie_store.mojom-forward.h
    • 这个文件包含公共接口的前向声明,用于非Blink代码。
  • cookie_store.mojom-blink-import-headers.h
    • 这个文件负责引入所有与CookieStore接口相关的头文件,用于Blink层。
  • cookie_store.mojom-blink-forward.h
    • 这个文件包含CookieStore接口的前向声明,专用于Blink代码。

特性控制文件

  • cookie_store.mojom-features.h
    • 这个文件定义了与CookieStore接口相关的特性宏,这些宏可以在编译时启用或禁用接口的特定部分。

JavaScript 绑定文件

  • cookie_store.mojom.js
    • 这个文件包含CookieStore接口的JavaScript绑定,允许在Web页面中通过JavaScript调用接口。
  • cookie_store.mojom.m.js
    • 这是CookieStore的ES模块JavaScript绑定文件,它允许在支持JavaScript模块的环境中使用CookieStore接口。
      cookie_store.mojom-module
    • 这个是直接生成了JavaScript的二进制

v8 虚拟机绑定文件(在另一个目录:src\out\x64_debug\gen\third_party\blink\renderer\bindings\modules\v8\)

  • v8_cookie_store.cc&v8_cookie_store.h
    • 这个文件用于将mojo的C++实现注册到V8虚拟机中

大部分生成文件都比较小,主要关注cookie_store.mojom.h、cookie_store-blink.mojom.h、cookie_store.mojom.js即可。之所以生成这么多个文件,是为了分离关注点。分离关注点是软件工程中的一个核心概念,它可以增强代码的可读性、可维护性和可重用性。通过生成不同的文件来处理不同的需求,开发者可以更容易地管理和维护代码。

阅读生成的源文件

cookie_store.mojom.js

// third_party/blink/public/mojom/cookie_store/cookie_store.mojom.js is auto generated by mojom_bindings_generator.py, do not edit
'use strict';

(function() {
  var mojomId = 'third_party/blink/public/mojom/cookie_store/cookie_store.mojom';
  if (mojo.internal.isMojomLoaded(mojomId)) {
    console.warn('The following mojom is loaded multiple times: ' + mojomId);
    return;
  }
  // 省略...
  var CookieStore = {
    name: 'blink.mojom.CookieStore',
    kVersion: 0,
    ptrClass: CookieStorePtr,
    proxyClass: CookieStoreProxy,
    stubClass: CookieStoreStub,
    validateRequest: validateCookieStoreRequest,
    validateResponse: validateCookieStoreResponse,
  };
  CookieStoreStub.prototype.validator = validateCookieStoreRequest;
  CookieStoreProxy.prototype.validator = validateCookieStoreResponse;
  exports.CookieChangeSubscription = CookieChangeSubscription;
  exports.CookieStore = CookieStore;
  exports.CookieStorePtr = CookieStorePtr;
  exports.CookieStoreAssociatedPtr = CookieStoreAssociatedPtr;
})();

上面代码导出了proxyClass、studClass等:

var CookieStore = {
name: ‘blink.mojom.CookieStore’,
kVersion: 0,
ptrClass: CookieStorePtr,
proxyClass: CookieStoreProxy,
stubClass: CookieStoreStub,
validateRequest: validateCookieStoreRequest,
validateResponse: validateCookieStoreResponse,
};

上面代码省略了大量的定义,实际上在这个源文件搜索CookieStore,可以看到一些定义的细节。
在这里插入图片描述
CookieStore通过prototype完成了定义,不在展开。

接下来,看render这边如何收到来自JS的调用

注册到JS 虚拟机

看C++侧代码,打断点是最直接的做法:
找到getAll的注册函数,如下图,下断点(chromium的JS注册是按需注册的,也就是如果在JS里没访问这个对象,那么这里的V8CookieStore::InstallUnconditionalProperties是不会调用的):
在这里插入图片描述
V8怎么知道在需要CookieStore的时候跑过来找V8CookieStore::InstallUnconditionalProperties注册这个对象呢?只需要搜索这个方法,找到注册定义:
在这里插入图片描述
这个定义的对象由V8CookieStore::GetWrapperTypeInfo返回。搜索这个函数的调用,就能找到注册的入口:
在这里插入图片描述
继续往下找这个函数的注册入口:
在这里插入图片描述
终于可以下断点了,在上面截图的地方所在函数( V8Window::Impl::InstallContextDependentProperties)下断点:
在这里插入图片描述
关键注册的流程已经标红,不再冗述。

content.dll!RenderFrameImpl::CommitNavigationWithParams
blink_core.dll!WebLocalFrameImpl::CommitNavigation
blink_modules.dll!V8ContextSnapshotImpl::InstallContextIndependentProps
blink_platform.dll!V8PerContextData::ConstructorForTypeSlowCase
blink_core.dll!V8Window::InstallContextDependentProperties
blink_modules.dll!V8Window::Impl::InstallContextDependentProperties

收到调用

还是通过断点阅读代码:
在这里插入图片描述
JS的调用先到CookieStore::getAll,然后通过成员函数DoRead,把请求转发给HeapMojoRemotenetwork::mojom::blink::RestrictedCookieManager backend_;
在这里插入图片描述
这时,我们要跑去网络进程打断点。根据network::mojom::blink::RestrictedCookieManager的类所在源文件是restricted_cookie_manager.mojom-blink.cc,那么我们去不带blink的源文件对应的函数打上断点:
在这里插入图片描述
核心代码如上图。

总结

从js调用 window.cookieStore.getAll(),总体流程如下图:

编译成
cookie_store.idl
v8_cookie_store.h/cc cookie_store.mojom-blink.h/cc cookie_store.mojom.h/cc等

跨进程`调用
浏览器加载完毕
给V8引起初始化window对象,注册了V8CookieStore的Warper信息
当JS访问V8CookieStore的时候,通过注册信息, 生成CookieStore的JS对象使其可以被调用和访问
JS在访问CookieStore.getAll的时候,转调到对应C++的方法
在getAll方法里,解包JS的参数,转调到实际的网络进程的RestrictedCookieManager去
在getAll方法里,解包JS的参数,转调到实际的网络进程的RestrictedCookieManager去

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

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

相关文章

遥感图像地物覆盖分类,数据集制作-分类模型对比-分类保姆级教程

在遥感影像上人工制作分类数据集 1.新建shp文件 地理坐标系保持和影像一致&#xff0c;面类型 2.打开属性表 3.添加字段 这里分类6类&#xff0c;点击添加值添加 添加完毕 开始人工选地物类型&#xff0c;制作数据集 开始标注&#xff0c;标注的时候可以借助谷歌地图…

记录清除挖矿病毒 solrd 过程

1、发现solrd病毒 端午节期间&#xff0c;kafka 服务器被黑客攻击了&#xff0c;植入了挖矿病毒 solrd&#xff0c;这个病毒很聪明&#xff0c;内存&#xff0c;CPU并没有异常升高&#xff0c;以致于上班第一天完全没有察觉。 上班第一天 正常登录服务器查看 flink ,消费kafka…

Eclipse创建Spring项目

第一步&#xff1a;先用Eclipse创建一个tomcat项目 打开eclipse 配置tomcat 这里点击add去添加tomcat 创建项目 写好项目名字&#xff0c;点击next 将这个Deploy path修改一下 配置一下项目&#xff0c;将项目部署到tomcat上面去 写个html测试一下 <html><h1>Hel…

tensorboard终于不报错了!

之前tensorboard笔记,记录2种使用方法&#xff0c;可以参考&#xff01; 有图这也没有数据啊这也。实际是没点对&#xff0c;干了个大噶。选择上方scalars就能看见图了&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&…

GitHub新手使用基本流程(保姆级教程)

GitHub&#xff0c; 一个聚合了海量开源免费的软件、电子书、视频课等资源的神仙网站&#xff0c;如果你还不会用GitHub&#xff0c;这条保姆级教程&#xff0c;您千万不要错过。 首先打开浏览器搜索GitHub, 点击进入官网 如果遇到无法加载的问题&#xff0c;可以试试这个名叫…

机器视觉:工业相机的主要参数

工业相机是将目标物体的表面特征信息转化为数字信号&#xff08;或者模拟信号&#xff09;的一种采集设备。 一、工业相机的成像原理 工业相机主要由光电传感器和转换电路组成。 光线照射到被检测物体的表面&#xff0c;反射光经过透镜&#xff0c;再进入相机的光电传感器&a…

从报名到领证:软考初级【信息系统运行管理员】报名考试全攻略

本文共计9991字&#xff0c;预计阅读33分钟。包括七个篇章&#xff1a;报名、准考证打印、备考、考试、成绩查询、证书领取及常见问题。 一、报名篇 报名条件要求&#xff1a; 1.凡遵守中华人民共和国宪法和各项法律&#xff0c;恪守职业道德&#xff0c;具有一定计算机技术…

flask基础3-蓝图-cookie-钩函数-flask上下文-异常处理

目录 一&#xff1a;蓝图 1.蓝图介绍 2.使用步骤 3.蓝图中的静态资源和模板 二.cookie和session 1.cookie 2.flask中操作cookie 3.session 4.session操作步骤 三.请求钩子 四.flask上下文 1.介绍 2.请求上下文&#xff1a; 3.应用上下文 3.g对象 五&#xff1a;…

STM32高级控制定时器(STM32F103):TIM1和TIM8介绍

目录 概述 1 认识TIM1和TIM8 2 TIM1和TIM8的特性 3 TIM1和TIM6时基和分频 3.1 时基单元 3.2 预分频 3.3 时基和分频相关寄存器 3.3.1TIMx_CR1 3.3.2 TIMx_PSC 概述 本文主要介绍STM32高级定时器TIM1和TIM8的功能&#xff0c;还介绍了与之相关的寄存器的配置参数。包括…

如何在3天内开发一个鸿蒙app

华为鸿蒙操作系统&#xff08;HarmonyOS&#xff09;自2.0版本正式上线以来&#xff0c;在短时间内就部署超过了2亿台设备&#xff0c;纵观全球操作系统的发展史&#xff0c;也是十分罕见的。与其他手机操作系统不同&#xff0c;HarmonyOS自诞生之日起&#xff0c;就是一款面向…

layui一个页面多个table显示时工具栏被下方的table遮挡

记录&#xff1a;layui一个页面多个table显示时工具栏被下方的table遮挡 css代码&#xff1a; [lay-idcurrentTableId] .layui-table-tool {position: relative;z-index: 9999;width: 100%;min-height: 50px;line-height: 30px;padding: 10px 15px;border-width: 0;border-bot…

c#中上传超过30mb的文件,接口一直报404,小于30mb的却可以上传成功

在一次前端实现上传视频文件时,超过30mb的文件上传,访问接口一直报404,但是在Swagger中直接访问接口确是正常的,且在后端控制器中添加了限制特性,如下 但是却仍然报404,在apifox中请求接口也是报404, 网上说: 在ASP.NET Core中,配置请求过来的文件上传的大小限制通常…

jfif格式怎么转换成jpg?关于将jfif转成jpg的几种方法

jfif格式怎么转换成jpg&#xff1f;JFIF格式是一种常见的图像文件格式&#xff0c;通常用于存储数字照片。然而&#xff0c;在某些情况下&#xff0c;你可能需要将JFIF格式转换为JPG格式。JPG格式是一种广泛使用的图像格式&#xff0c;它被支持和接受的程度比JFIF更高。PNG是一…

C++迈向精通:当我尝试修改虚函数表

尝试修改虚函数表 本期纯整活儿好吧&#xff01;&#xff01;&#xff01;&#xff01; 初衷 有一天我突然开始好奇虚函数表是否真的存在&#xff0c;于是我开始想是否能够从C中查看或者调用虚函数表中的内容。&#xff0c;于是有了下面的操作。 操作过程 起初我并没有思路…

加入牛导研究团队|普通高校老师获得香港理工大学访问学者邀请函

随着国内高校高层次人才引进机制的日益完善&#xff0c;本校教师也倍感竞争压力日趋激烈&#xff0c;而出国访学&#xff0c;加入牛导的科研团队&#xff0c;发表高质量的论文&#xff0c;是提升自己学术水平的有效途径。本案例中的O老师就是借助知识人网的帮助&#xff0c;实现…

docker-compose harbor 2.11

harbor 前言 “Harbor” 是一个用于管理容器镜像的开源仓库项目。由 VMware 开发和维护,Harbor 提供一个企业级的 Docker 镜像仓库,具有丰富的功能,包括: 镜像管理:提供存储和分发 Docker 镜像的能力。安全性:支持镜像签名和漏洞扫描,确保镜像的安全性。身份认证:集成…

SECS/GEM 底层协议解析

SECS是什么&#xff1f; SEMI电子半导体联盟,为实现设备与工厂系统的快速对接数据,状态,配方,程序的标准化协议,SECS具有多个版本,本文主要介绍E5协议 HSMS通信方式,设备端的处理流程(Passive模式)。 SECS关键字 Host 主机一般指向工厂控制系统EQP 单机设备Active 在Tcp通信…

SAP 价格金额信息控制

1)migo / mb51/mb51/mb59 关于价格和金额的显示&#xff0c;需要权限控制&#xff0c;当权限对象F_BKPF_BUK,检查对应【公司代码】 和 ACTVT有03’的权限&#xff0c;如果没有03的权限&#xff0c;对应行的价格和金额显示为空 关于价格和金额的显示&#xff0c;需要权限控制&a…

Java——重载

一、重载&#xff08;Overload&#xff09; 1、重载是什么 方法重载&#xff08;Method Overloading&#xff09;是Java中实现多态的一种方式。它允许在同一个类中定义多个同名的方法&#xff0c;只要这些方法的参数列表不同。这些不同的参数列表可以通过不同的参数类型、参数…

【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版12(附带项目源码)

最终效果 系列导航 文章目录 最终效果系列导航前言UI框架先绘制一些常用UI面板&#xff0c;设置为预制件提示弹窗用户列表菜单输入框弹窗 创建各个面板的脚本控制代码控制菜单界面按钮事件 源码结束语 前言 本节主要实现UI框架调用不同的面板界面 UI框架 不懂UI框架的设计思路…