Chromium源码由浅入深(三)
接前一篇文章:Chromium源码由浅入深(二)
上一回说到了关键的“钥匙”:browserBridge.gpuInfo,本文就针对其进行深入探究。
先来看前半部分,browserBridge。
在content/browser/resources/gpu/gpu_internals.js中有以下代码:
import './info_view.js';import {BrowserBridge} from './browser_bridge.js';// Injected script from C++ or test environments may reference `browserBridge`
// as a property of the global object.
window.browserBridge = new BrowserBridge();/*** Main entry point. called once the page has loaded.*/
function onLoad() {// Create the views.document.querySelector('info-view').addBrowserBridgeListeners(window.browserBridge);// Because of inherent raciness (between the deprecated DevTools API which// telemtry uses to drive the relevant tests, and the asynchronous loading of// JS modules like this one) it's possible for telemetry tests to inject code// *before* `browserBridge` is set and the DOM is populated. This flag is used// to synchronize script injection by tests to prevent such races.window.gpuPagePopulated = true;
}document.addEventListener('DOMContentLoaded', onLoad);
代码注释说得清楚:从C++或测试环境注入的脚本可能引用“browserBridge”作为全局对象的属性。
BrowserBridge类的定义在Cromium源码中一共有两处,一处在chrome/browser/resources/net_internals/browser_bridge.js中,另一处在content/browser/resources/gpu/browser_bridge.js中。由于上边代码中是“import {BrowserBridge} from './browser_bridge.js';”,也就是引用的是当前路径下的browser_bridge.js,即content/browser/resources/gpu/下的browser_bridge.js,也就是第二处定义。
代码如下:
/*** This class provides a 'bridge' for communicating between javascript and the* browser. When run outside of WebUI, e.g. as a regular webpage, it provides* synthetic data to assist in testing.*/
export class BrowserBridge extends EventTarget {constructor() {super();this.nextRequestId_ = 0;this.pendingCallbacks_ = [];this.logMessages_ = [];// Tell c++ code that we are ready to receive GPU Info.chrome.send('browserBridgeInitialized');this.beginRequestClientInfo_();this.beginRequestLogMessages_();}dispatchEvent_(eventName) {this.dispatchEvent(new CustomEvent(eventName, {bubbles: true, composed: true}));}applySimulatedData_(data) {// set up things according to the simulated datathis.gpuInfo_ = data.gpuInfo;this.clientInfo_ = data.clientInfo;this.logMessages_ = data.logMessages;this.dispatchEvent_('gpuInfoUpdate');this.dispatchEvent_('clientInfoChange');this.dispatchEvent_('logMessagesChange');}/*** Sends a message to the browser with specified args. The* browser will reply asynchronously via the provided callback.*/callAsync(submessage, args, callback) {const requestId = this.nextRequestId_;this.nextRequestId_ += 1;this.pendingCallbacks_[requestId] = callback;if (!args) {chrome.send('callAsync', [requestId.toString(), submessage]);} else {const allArgs = [requestId.toString(), submessage].concat(args);chrome.send('callAsync', allArgs);}}/*** Called by gpu c++ code when client info is ready.*/onCallAsyncReply(requestId, args) {if (this.pendingCallbacks_[requestId] === undefined) {throw new Error('requestId ' + requestId + ' is not pending');}const callback = this.pendingCallbacks_[requestId];callback(args);delete this.pendingCallbacks_[requestId];}/*** Get gpuInfo data.*/get gpuInfo() {return this.gpuInfo_;}/*** Called from gpu c++ code when GPU Info is updated.*/onGpuInfoUpdate(gpuInfo) {this.gpuInfo_ = gpuInfo;this.dispatchEvent_('gpuInfoUpdate');}/*** This function begins a request for the ClientInfo. If it comes back* as undefined, then we will issue the request again in 250ms.*/beginRequestClientInfo_() {this.callAsync('requestClientInfo', undefined,(function(data) {if (data === undefined) { // try again in 250 mswindow.setTimeout(this.beginRequestClientInfo_.bind(this), 250);} else {this.clientInfo_ = data;this.dispatchEvent_('clientInfoChange');}}).bind(this));}/*** Returns information about the currently running Chrome build.*/get clientInfo() {return this.clientInfo_;}/*** This function checks for new GPU_LOG messages.* If any are found, a refresh is triggered.*/beginRequestLogMessages_() {this.callAsync('requestLogMessages', undefined,(function(messages) {if (messages.length !== this.logMessages_.length) {this.logMessages_ = messages;this.dispatchEvent_('logMessagesChange');}// check again in 250 mswindow.setTimeout(this.beginRequestLogMessages_.bind(this), 250);}).bind(this));}/*** Returns an array of log messages issued by the GPU process, if any.*/get logMessages() {return this.logMessages_;}/*** Returns the value of the "Sandboxed" row.*/isSandboxedForTesting() {for (const info of this.gpuInfo_.basicInfo) {if (info.description === 'Sandboxed') {return info.value;}}return false;}
}
再来看后半部分,gpuInfo。
在上边content/browser/resources/gpu/gpu_internals.js的代码中有以下一段:
/*** Main entry point. called once the page has loaded.*/
function onLoad() {// Create the views.document.querySelector('info-view').addBrowserBridgeListeners(window.browserBridge);
addBrowserBridgeListeners函数在content/browser/resources/gpu/info_view.js中,代码如下:
addBrowserBridgeListeners(browserBridge) {browserBridge.addEventListener('gpuInfoUpdate', this.refresh.bind(this, browserBridge));browserBridge.addEventListener('logMessagesChange', this.refresh.bind(this, browserBridge));browserBridge.addEventListener('clientInfoChange', this.refresh.bind(this, browserBridge));this.refresh(browserBridge);}
而'gpuInfoUpdate'这个关键字则有两处相关调用。一处在content/browser/resources/gpu/browser_bridge.js中,代码如下:
applySimulatedData_(data) {// set up things according to the simulated datathis.gpuInfo_ = data.gpuInfo;this.clientInfo_ = data.clientInfo;this.logMessages_ = data.logMessages;this.dispatchEvent_('gpuInfoUpdate');this.dispatchEvent_('clientInfoChange');this.dispatchEvent_('logMessagesChange');}
另一处也是在同文件中,代码如下:
/*** Called from gpu c++ code when GPU Info is updated.*/onGpuInfoUpdate(gpuInfo) {this.gpuInfo_ = gpuInfo;this.dispatchEvent_('gpuInfoUpdate');}
显然后者更为关键和常用。再次查找调用onGpuInfoUpdate函数的地方,只有一处,在content/browser/gpu/gpu_internals_ui.cc中,代码如下:
void GpuMessageHandler::OnGpuInfoUpdate() {// Get GPU Info.const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();const gfx::GpuExtraInfo gpu_extra_info =GpuDataManagerImpl::GetInstance()->GetGpuExtraInfo();base::Value::Dict gpu_info_val = GetGpuInfo();// Add in blocklisting featuresbase::Value::Dict feature_status;feature_status.Set("featureStatus", GetFeatureStatus());feature_status.Set("problems", GetProblems());base::Value::List workarounds;for (const auto& workaround : GetDriverBugWorkarounds())workarounds.Append(workaround);feature_status.Set("workarounds", std::move(workarounds));gpu_info_val.Set("featureStatus", std::move(feature_status));if (!GpuDataManagerImpl::GetInstance()->IsGpuProcessUsingHardwareGpu()) {const gpu::GPUInfo gpu_info_for_hardware_gpu =GpuDataManagerImpl::GetInstance()->GetGPUInfoForHardwareGpu();if (gpu_info_for_hardware_gpu.IsInitialized()) {base::Value::Dict feature_status_for_hardware_gpu;feature_status_for_hardware_gpu.Set("featureStatus",GetFeatureStatusForHardwareGpu());feature_status_for_hardware_gpu.Set("problems",GetProblemsForHardwareGpu());base::Value::List workarounds_for_hardware_gpu;for (const auto& workaround : GetDriverBugWorkaroundsForHardwareGpu())workarounds_for_hardware_gpu.Append(workaround);feature_status_for_hardware_gpu.Set("workarounds", std::move(workarounds_for_hardware_gpu));gpu_info_val.Set("featureStatusForHardwareGpu",std::move(feature_status_for_hardware_gpu));const gpu::GpuFeatureInfo gpu_feature_info_for_hardware_gpu =GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfoForHardwareGpu();base::Value::List gpu_info_for_hardware_gpu_val = GetBasicGpuInfo(gpu_info_for_hardware_gpu, gpu_feature_info_for_hardware_gpu,gfx::GpuExtraInfo{});gpu_info_val.Set("basicInfoForHardwareGpu",std::move(gpu_info_for_hardware_gpu_val));}}gpu_info_val.Set("compositorInfo", CompositorInfo());gpu_info_val.Set("gpuMemoryBufferInfo", GpuMemoryBufferInfo(gpu_extra_info));gpu_info_val.Set("displayInfo", GetDisplayInfo());gpu_info_val.Set("videoAcceleratorsInfo", GetVideoAcceleratorsInfo());gpu_info_val.Set("ANGLEFeatures", GetANGLEFeatures());gpu_info_val.Set("devicePerfInfo", GetDevicePerfInfo());gpu_info_val.Set("dawnInfo", GetDawnInfo());// Send GPU Info to javascript.web_ui()->CallJavascriptFunctionUnsafe("browserBridge.onGpuInfoUpdate",std::move(gpu_info_val));
}
这个函数就是接下来要花大力气探究的核心函数。
欲知后事如何,且看下回分解。
相关文章:

Chromium源码由浅入深(三)
接前一篇文章:Chromium源码由浅入深(二) 上一回说到了关键的“钥匙”:browserBridge.gpuInfo,本文就针对其进行深入探究。 先来看前半部分,browserBridge。 在content/browser/resources/gpu/gpu_interna…...

如何集成验证码短信API到你的应用程序
引言 当你需要为你的应用程序增加安全性和用户验证功能时,集成验证码短信API是一个明智的选择。验证码短信API可以帮助你轻松实现用户验证、密码重置和账户恢复等功能,提高用户体验并增强应用程序的安全性。本文将介绍如何将验证码短信API集成到你的应用…...

Linux- 由映射文件I/O问题引出的SIGBUS 空洞文件(Sparse File)
SIGBUS SIGBUS是一个在Unix-like操作系统中的信号,它通常表示非法访问内存,而这种非法访问的原因与常见的SIGSEGV(段错误)有所不同。以下是可能导致SIGBUS的常见情况: 未对齐的内存访问:某些硬件平台要求数…...

代码随想录图论 第二天 | 695. 岛屿的最大面积 1020. 飞地的数量
代码随想录图论 第二天 | 695. 岛屿的最大面积 1020. 飞地的数量 一、695. 岛屿的最大面积 题目链接:https://leetcode.cn/problems/max-area-of-island/ 思路:典型的遍历模板题,我采用深度优先,每块岛屿递归遍历的时候计数&…...

R语言代码示例
以下是一个使用R语言和httrOAuth库的下载器程序,用于下载的内容。程序使用以下代码。 # 安装和加载必要的库 install.packages("httr") install.packages("httrOAuth") library(httr) library(httrOAuth) # 设置 http_proxy <- "du…...

ESP32网络开发实例-将 ESP32 连接到 EMQX Cloud MQTT Broker
将 ESP32 连接到 EMQX Cloud MQTT Broker 文章目录 将 ESP32 连接到 EMQX Cloud MQTT Broker1、MQTT介绍2、软件准备3、硬件准备4、代码实现5、MQTT测试在本文中,将介绍使用 EMQX Cloud MQTT 服务器。 首先,我们将介绍如何将 ESP32 开发板连接到 EMQX Cloud MQTT 服务器。 我…...

基于Kubesphere容器云平台物联网云平台Devops实践
基于Kubesphere容器云平台物联网云平台Devops实践 项目背景 公司是做工业物联网相关业务的,现业务是云平台,技术栈 后端为 Springboot2.7JDK11 ,前端为 Vue3Ts,需要搭建自动化运维平台以实现业务代码自动部署上线,…...

淘宝商品详情页API接口|tb获取商品主图接口
淘宝的 API 开发接口,我们需要做下面几件事情。 1)开放平台注册开发者账号; 2)然后为每个淘宝应用注册一个应用程序键(App Key) ; 3)下载淘宝 API 的 SDK 并掌握基本的 API 基础知识和调用&a…...

JAVA面试笔记
JAVA就业课程 面试整体流程 1.1 简单的自我介绍 我是xxxx,工作xxx年.我先后在xxxx公司、yyyy公司工作。先后做个xxxx项目、yyyy项目。 1.2 你简单介绍一下xxxx项目 为了解决xxxx问题,开发了一套xxxx系统,该系统主要有那些部分组成。简单介绍项目的整体架…...

尚硅谷Flume(仅有基础)
q 1 概述 1.1 定义 Flume 是Cloudera 提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。Flume 基于流式架构,灵活简单。 Flume最主要的作用就是,实时读取服务器本地磁盘的数据,将数据写入到HD…...

JS中this的绑定规则
如果有人问你this指向哪里?但又不给你说调用位置,那他就是在耍流氓。 – 龚港浩 1、默认绑定 首先要介绍的是最常用的函数调用类型:独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。 function foo() {console.log( this…...

酷开科技 | 酷开系统大屏电视,打造精彩家庭场景
在信息资讯不发达的年代,电视机一直都是个人及家庭重要的信息获取渠道和家庭娱乐中心,是每个家庭必不可少的大家电之一!在快节奏的现代生活中,受手机和平板的冲击,电视机这个曾经的客厅“霸主”一度失去了“主角光环”…...

GDPU 数据结构 天码行空6
一、实验目的 1、掌握串的顺序存储结构 2、掌握顺序串的基本操作方法(插入、删除等)。 3、掌握串的链式存储结构。 4、掌握链式串的几种基本操作(插入、删除等)。 5、掌握Brute-Force算法 二、实验内容 1、编写函数BFIndex(Str…...

机器学习实验三:决策树-隐形眼镜分类(判断视力程度)
决策树-隐形眼镜分类(判断视力程度) Title : 使用决策树预测隐形眼镜类型 # Description :隐形眼镜数据是非常著名的数据集 ,它包含很多患者眼部状况的观察条件以及医生推荐的隐形眼镜类型 。 # 隐形眼镜类型包括硬材质 、软材质以及不适合佩…...

广州华锐互动:VR技术应用到工程项目施工安全培训的好处
随着科技的飞速发展,虚拟现实(VR)技术已经深入到各个领域。在建筑施工领域,VR技术的应用为工程项目施工安全培训带来了许多好处。本文将探讨VR技术在这方面的优势和应用。 首先,VR技术能够提供沉浸式的安全培训体验。通过VR设备,学…...

Hadoop3.0大数据处理学习1(Haddop介绍、部署、Hive部署)
Hadoop3.0快速入门 学习步骤: 三大组件的基本理论和实际操作Hadoop3的使用,实际开发流程结合具体问题,提供排查思路 开发技术栈: Linux基础操作、Sehll脚本基础JavaSE、Idea操作MySQL Hadoop简介 Hadoop是一个适合海量数据存…...

C笔记:引用调用,通过指针传递
代码 #include<stdio.h> int max1(int num1,int num2) {if(num1 < num2){num1 num2;}else{num2 num1;} } int max2(int *num1,int *num2) {if(num1 < num2){*num1 *num2; // 把 num2 赋值给 num1 }else{*num2 *num1;} } int main() {int num1 0,num2 -2;int…...

【方法】如何给PDF文件添加“打开密码”?
PDF文件可以在线浏览,但如果想要给文件添加“打开密码”,就需要用到软件工具,下面小编分享两种常用的工具,小伙伴们可以根据需要选择。 工具一:PDF编辑器 PDF阅读器一般是没有设置密码的功能模块,PDF编辑器…...

单源最短路径 -- Dijkstra
Dijkstra算法就适用于解决带权重的有向图上的单源最短路径问题 -- 同时算法要求图中所有边的权重非负(这个很重要) 针对一个带权有向图G , 将所有节点分为两组S和Q , S是已经确定的最短路径的节点集合,在初始时为空&…...

Java--多态及抽象类与接口
1.多态 以不同参数调用父类方法,可以得到不同的处理,子类中无需定义相同功能的方法,避免了重复代码编写,只需要实例化一个继承父类的子类对象,即可调用相应的方法,而只需要维护附父类方法即可。 package c…...

Python手搓C4.5决策树+Azure Adult数据集分析
前言 课上的实验 由于不想被抄袭,所以暂时不放完整代码 Adult数据集可以在Azure官网上找到 Azure 开放数据集中的数据集 - Azure Open Datasets | Microsoft Learn 数据集预处理 删除难以处理的权重属性fnlwgt与意义重复属性educationNum去除重复行与空行删除…...

【tg】6: MediaManager的主要功能
【tg】2:视频采集的输入和输出 的管理者是 media manager‘ media 需要 network的支持:NetworkInterface friend class MediaManager::NetworkInterfaceImpl;NetworkInterfaceImpl 直接持有 MediaManager 的指针即可:发送rtp包、rtcp包、设置socket选项?...

NPM-安装报错connect ETIMEDOUT
报错信息request to https://registry.npm.taobao.org/yarn failed, reason: connect ETIMEDOUT 解决方案: 1、npm set strict-ssl false 2、设置代理 npm config set proxy http://xxx:xxxopenproxy.ali.com:8080npm如何在安装的时候指定源 npm install -g yarn1.…...

机器学习之查准率、查全率与F1
文章目录 查准率(Precision):查全率(Recall):F1分数(F1 Score):实例P-R曲线F1度量python实现 查准率(Precision): 定义: …...

*Django中的Ajax 纯js的书写样式1
搭建项目 建立一个Djano项目,建立一个app,建立路径,视图函数大多为render, Ajax的创建 urls.py path(index/,views.index), path(index2/,views.index2), views.py def index(request):return render(request,01.html) def index2(requ…...

谈谈node架构中的线程进程的应用场景、事件循环及任务队列
本文作者系360奇舞团前端开发工程师 文章标题:谈谈node架构中的线程进程的应用场景、事件循环及任务队列 Node.js是一个基于Chrome V8引擎的JavaScript运行时环境,nodejs是单线程执行的,它基于事件驱动和非阻塞I/O模型进行多任务的执行。在理…...

http代理IP它有哪些应用场景?如何提升访问速度?
随着互联网的快速发展,越来越多的人开始关注网络速度和安全性。其中,代理IP技术作为一种有效的网络加速和安全解决方案,越来越受到人们的关注。那么,http代理IP有哪些应用场景?又如何提升访问速度呢? 一、h…...

Armv8/Armv9的VIPT的别名问题是如何解决的
https://www.cse.unsw.edu.au/~cs9242/02/lectures/03-cache/node8.html https://developer.arm.com/documentation/ddi0406/b/System-Level-Architecture/Virtual-Memory-System-Architecture–VMSA-/Address-mapping-restrictions...

java/javaswing/窗体程序,人脸识别系统,人脸追踪,计算机视觉
源码下载地址 支持:远程部署/安装/调试、讲解、二次开发/修改/定制 源码下载地址...

设计模式(16)迭代器模式
一、介绍: 1、定义:迭代器模式 (Iterator Pattern) 是一种行为型设计模式,它提供一种顺序访问聚合对象(如列表、集合等)中的元素,而无需暴露聚合对象的内部表示。迭代器模式将遍历逻辑封装在一个迭代器对象…...