• Chromium源码由浅入深(三)


    接前一篇文章:Chromium源码由浅入深(二)

    上一回说到了关键的“钥匙”:browserBridge.gpuInfo,本文就针对其进行深入探究。

    先来看前半部分,browserBridge。

    在content/browser/resources/gpu/gpu_internals.js中有以下代码:

    1. import './info_view.js';
    2. import {BrowserBridge} from './browser_bridge.js';
    3. // Injected script from C++ or test environments may reference `browserBridge`
    4. // as a property of the global object.
    5. window.browserBridge = new BrowserBridge();
    6. /**
    7. * Main entry point. called once the page has loaded.
    8. */
    9. function onLoad() {
    10. // Create the views.
    11. document.querySelector('info-view')
    12. .addBrowserBridgeListeners(window.browserBridge);
    13. // Because of inherent raciness (between the deprecated DevTools API which
    14. // telemtry uses to drive the relevant tests, and the asynchronous loading of
    15. // JS modules like this one) it's possible for telemetry tests to inject code
    16. // *before* `browserBridge` is set and the DOM is populated. This flag is used
    17. // to synchronize script injection by tests to prevent such races.
    18. window.gpuPagePopulated = true;
    19. }
    20. 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,也就是第二处定义。

    代码如下:

    1. /**
    2. * This class provides a 'bridge' for communicating between javascript and the
    3. * browser. When run outside of WebUI, e.g. as a regular webpage, it provides
    4. * synthetic data to assist in testing.
    5. */
    6. export class BrowserBridge extends EventTarget {
    7. constructor() {
    8. super();
    9. this.nextRequestId_ = 0;
    10. this.pendingCallbacks_ = [];
    11. this.logMessages_ = [];
    12. // Tell c++ code that we are ready to receive GPU Info.
    13. chrome.send('browserBridgeInitialized');
    14. this.beginRequestClientInfo_();
    15. this.beginRequestLogMessages_();
    16. }
    17. dispatchEvent_(eventName) {
    18. this.dispatchEvent(
    19. new CustomEvent(eventName, {bubbles: true, composed: true}));
    20. }
    21. applySimulatedData_(data) {
    22. // set up things according to the simulated data
    23. this.gpuInfo_ = data.gpuInfo;
    24. this.clientInfo_ = data.clientInfo;
    25. this.logMessages_ = data.logMessages;
    26. this.dispatchEvent_('gpuInfoUpdate');
    27. this.dispatchEvent_('clientInfoChange');
    28. this.dispatchEvent_('logMessagesChange');
    29. }
    30. /**
    31. * Sends a message to the browser with specified args. The
    32. * browser will reply asynchronously via the provided callback.
    33. */
    34. callAsync(submessage, args, callback) {
    35. const requestId = this.nextRequestId_;
    36. this.nextRequestId_ += 1;
    37. this.pendingCallbacks_[requestId] = callback;
    38. if (!args) {
    39. chrome.send('callAsync', [requestId.toString(), submessage]);
    40. } else {
    41. const allArgs = [requestId.toString(), submessage].concat(args);
    42. chrome.send('callAsync', allArgs);
    43. }
    44. }
    45. /**
    46. * Called by gpu c++ code when client info is ready.
    47. */
    48. onCallAsyncReply(requestId, args) {
    49. if (this.pendingCallbacks_[requestId] === undefined) {
    50. throw new Error('requestId ' + requestId + ' is not pending');
    51. }
    52. const callback = this.pendingCallbacks_[requestId];
    53. callback(args);
    54. delete this.pendingCallbacks_[requestId];
    55. }
    56. /**
    57. * Get gpuInfo data.
    58. */
    59. get gpuInfo() {
    60. return this.gpuInfo_;
    61. }
    62. /**
    63. * Called from gpu c++ code when GPU Info is updated.
    64. */
    65. onGpuInfoUpdate(gpuInfo) {
    66. this.gpuInfo_ = gpuInfo;
    67. this.dispatchEvent_('gpuInfoUpdate');
    68. }
    69. /**
    70. * This function begins a request for the ClientInfo. If it comes back
    71. * as undefined, then we will issue the request again in 250ms.
    72. */
    73. beginRequestClientInfo_() {
    74. this.callAsync(
    75. 'requestClientInfo', undefined,
    76. (function(data) {
    77. if (data === undefined) { // try again in 250 ms
    78. window.setTimeout(this.beginRequestClientInfo_.bind(this), 250);
    79. } else {
    80. this.clientInfo_ = data;
    81. this.dispatchEvent_('clientInfoChange');
    82. }
    83. }).bind(this));
    84. }
    85. /**
    86. * Returns information about the currently running Chrome build.
    87. */
    88. get clientInfo() {
    89. return this.clientInfo_;
    90. }
    91. /**
    92. * This function checks for new GPU_LOG messages.
    93. * If any are found, a refresh is triggered.
    94. */
    95. beginRequestLogMessages_() {
    96. this.callAsync(
    97. 'requestLogMessages', undefined,
    98. (function(messages) {
    99. if (messages.length !== this.logMessages_.length) {
    100. this.logMessages_ = messages;
    101. this.dispatchEvent_('logMessagesChange');
    102. }
    103. // check again in 250 ms
    104. window.setTimeout(this.beginRequestLogMessages_.bind(this), 250);
    105. }).bind(this));
    106. }
    107. /**
    108. * Returns an array of log messages issued by the GPU process, if any.
    109. */
    110. get logMessages() {
    111. return this.logMessages_;
    112. }
    113. /**
    114. * Returns the value of the "Sandboxed" row.
    115. */
    116. isSandboxedForTesting() {
    117. for (const info of this.gpuInfo_.basicInfo) {
    118. if (info.description === 'Sandboxed') {
    119. return info.value;
    120. }
    121. }
    122. return false;
    123. }
    124. }

    再来看后半部分,gpuInfo。

    在上边content/browser/resources/gpu/gpu_internals.js的代码中有以下一段:

    1. /**
    2. * Main entry point. called once the page has loaded.
    3. */
    4. function onLoad() {
    5. // Create the views.
    6. document.querySelector('info-view')
    7. .addBrowserBridgeListeners(window.browserBridge);

    addBrowserBridgeListeners函数在content/browser/resources/gpu/info_view.js中,代码如下:

    1. addBrowserBridgeListeners(browserBridge) {
    2. browserBridge.addEventListener(
    3. 'gpuInfoUpdate', this.refresh.bind(this, browserBridge));
    4. browserBridge.addEventListener(
    5. 'logMessagesChange', this.refresh.bind(this, browserBridge));
    6. browserBridge.addEventListener(
    7. 'clientInfoChange', this.refresh.bind(this, browserBridge));
    8. this.refresh(browserBridge);
    9. }

    而'gpuInfoUpdate'这个关键字则有两处相关调用。一处在content/browser/resources/gpu/browser_bridge.js中,代码如下:

    1. applySimulatedData_(data) {
    2. // set up things according to the simulated data
    3. this.gpuInfo_ = data.gpuInfo;
    4. this.clientInfo_ = data.clientInfo;
    5. this.logMessages_ = data.logMessages;
    6. this.dispatchEvent_('gpuInfoUpdate');
    7. this.dispatchEvent_('clientInfoChange');
    8. this.dispatchEvent_('logMessagesChange');
    9. }

    另一处也是在同文件中,代码如下:

    1. /**
    2. * Called from gpu c++ code when GPU Info is updated.
    3. */
    4. onGpuInfoUpdate(gpuInfo) {
    5. this.gpuInfo_ = gpuInfo;
    6. this.dispatchEvent_('gpuInfoUpdate');
    7. }

    显然后者更为关键和常用。再次查找调用onGpuInfoUpdate函数的地方,只有一处,在content/browser/gpu/gpu_internals_ui.cc中,代码如下:

    1. void GpuMessageHandler::OnGpuInfoUpdate() {
    2. // Get GPU Info.
    3. const gpu::GPUInfo gpu_info = GpuDataManagerImpl::GetInstance()->GetGPUInfo();
    4. const gfx::GpuExtraInfo gpu_extra_info =
    5. GpuDataManagerImpl::GetInstance()->GetGpuExtraInfo();
    6. base::Value::Dict gpu_info_val = GetGpuInfo();
    7. // Add in blocklisting features
    8. base::Value::Dict feature_status;
    9. feature_status.Set("featureStatus", GetFeatureStatus());
    10. feature_status.Set("problems", GetProblems());
    11. base::Value::List workarounds;
    12. for (const auto& workaround : GetDriverBugWorkarounds())
    13. workarounds.Append(workaround);
    14. feature_status.Set("workarounds", std::move(workarounds));
    15. gpu_info_val.Set("featureStatus", std::move(feature_status));
    16. if (!GpuDataManagerImpl::GetInstance()->IsGpuProcessUsingHardwareGpu()) {
    17. const gpu::GPUInfo gpu_info_for_hardware_gpu =
    18. GpuDataManagerImpl::GetInstance()->GetGPUInfoForHardwareGpu();
    19. if (gpu_info_for_hardware_gpu.IsInitialized()) {
    20. base::Value::Dict feature_status_for_hardware_gpu;
    21. feature_status_for_hardware_gpu.Set("featureStatus",
    22. GetFeatureStatusForHardwareGpu());
    23. feature_status_for_hardware_gpu.Set("problems",
    24. GetProblemsForHardwareGpu());
    25. base::Value::List workarounds_for_hardware_gpu;
    26. for (const auto& workaround : GetDriverBugWorkaroundsForHardwareGpu())
    27. workarounds_for_hardware_gpu.Append(workaround);
    28. feature_status_for_hardware_gpu.Set(
    29. "workarounds", std::move(workarounds_for_hardware_gpu));
    30. gpu_info_val.Set("featureStatusForHardwareGpu",
    31. std::move(feature_status_for_hardware_gpu));
    32. const gpu::GpuFeatureInfo gpu_feature_info_for_hardware_gpu =
    33. GpuDataManagerImpl::GetInstance()->GetGpuFeatureInfoForHardwareGpu();
    34. base::Value::List gpu_info_for_hardware_gpu_val = GetBasicGpuInfo(
    35. gpu_info_for_hardware_gpu, gpu_feature_info_for_hardware_gpu,
    36. gfx::GpuExtraInfo{});
    37. gpu_info_val.Set("basicInfoForHardwareGpu",
    38. std::move(gpu_info_for_hardware_gpu_val));
    39. }
    40. }
    41. gpu_info_val.Set("compositorInfo", CompositorInfo());
    42. gpu_info_val.Set("gpuMemoryBufferInfo", GpuMemoryBufferInfo(gpu_extra_info));
    43. gpu_info_val.Set("displayInfo", GetDisplayInfo());
    44. gpu_info_val.Set("videoAcceleratorsInfo", GetVideoAcceleratorsInfo());
    45. gpu_info_val.Set("ANGLEFeatures", GetANGLEFeatures());
    46. gpu_info_val.Set("devicePerfInfo", GetDevicePerfInfo());
    47. gpu_info_val.Set("dawnInfo", GetDawnInfo());
    48. // Send GPU Info to javascript.
    49. web_ui()->CallJavascriptFunctionUnsafe("browserBridge.onGpuInfoUpdate",
    50. std::move(gpu_info_val));
    51. }

    这个函数就是接下来要花大力气探究的核心函数。

    欲知后事如何,且看下回分解。

  • 相关阅读:
    net-java-php-python-基于mvc的酒吧系统的设计与实现计算机毕业设计程序
    Swin Transformer目标检测—训练自己数据集
    9月17日计算机视觉基础学习笔记——认识机器学习
    Spring Security 集成 OAuth 2.0 认证(一)
    不动产数据质量提升_电子档案挂接
    19.ROS编程学习:节点关闭与多种日志输出
    【C语言】病人信息管理系统
    原生GO开发的博客系统
    【EI会议征稿】2023计算机网络技术与电子信息工程国际学术会议(CNTEIE 2023)
    服务 700+ 厂商,接入 4000+游戏,数数科技 C+ 轮再融 1 亿元
  • 原文地址:https://blog.csdn.net/phmatthaus/article/details/134038010