chrome-devtools-frontend 1.0.1650232 → 1.0.1651641

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/.agents/skills/version-control/SKILL.md +5 -1
  2. package/config/typescript/tsconfig.base.json +1 -0
  3. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  4. package/front_end/core/host/UserMetrics.ts +0 -11
  5. package/front_end/core/sdk/CSSMatchedStyles.ts +20 -4
  6. package/front_end/devtools_compatibility.js +1 -2
  7. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +94 -0
  8. package/front_end/foundation/Universe.ts +7 -0
  9. package/front_end/generated/InspectorBackendCommands.ts +4 -1
  10. package/front_end/generated/SupportedCSSProperties.js +284 -0
  11. package/front_end/generated/protocol-mapping.d.ts +7 -0
  12. package/front_end/generated/protocol-proxy-api.d.ts +5 -0
  13. package/front_end/generated/protocol.ts +60 -0
  14. package/front_end/models/ai_assistance/AiAgent2.ts +11 -1
  15. package/front_end/models/ai_assistance/README.md +4 -0
  16. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +2 -0
  17. package/front_end/models/ai_assistance/agents/AiAgent.ts +3 -0
  18. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +2 -0
  19. package/front_end/models/ai_assistance/ai_assistance.ts +4 -0
  20. package/front_end/models/ai_assistance/skills/Skill.ts +1 -1
  21. package/front_end/models/ai_assistance/skills/SkillRegistry.ts +2 -0
  22. package/front_end/models/ai_assistance/skills/accessibility.md +13 -0
  23. package/front_end/models/ai_assistance/tools/GetLighthouseAudits.ts +54 -0
  24. package/front_end/models/ai_assistance/tools/ResolveLighthousePath.ts +124 -0
  25. package/front_end/models/ai_assistance/tools/Tool.ts +12 -2
  26. package/front_end/models/ai_assistance/tools/ToolRegistry.ts +4 -0
  27. package/front_end/models/heap_snapshot/HeapSnapshotModel.ts +14 -0
  28. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +4 -0
  29. package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
  30. package/front_end/models/persistence/NetworkPersistenceManager.ts +9 -1
  31. package/front_end/panels/ai_assistance/components/ChatMessage.ts +3 -11
  32. package/front_end/panels/common/ExtensionServer.ts +70 -50
  33. package/front_end/panels/elements/CSSSpecificityBreakdown.ts +106 -0
  34. package/front_end/panels/elements/ElementsPanel.ts +1 -1
  35. package/front_end/panels/elements/StylePropertiesSection.ts +40 -13
  36. package/front_end/panels/elements/StylePropertyTreeElement.ts +6 -5
  37. package/front_end/panels/elements/components/CSSQuery.ts +119 -4
  38. package/front_end/panels/elements/elements.ts +3 -0
  39. package/front_end/panels/elements/stylesSidebarPane.css +34 -0
  40. package/front_end/panels/js_timeline/js_timeline-meta.ts +1 -2
  41. package/front_end/panels/layer_viewer/PaintProfilerView.ts +0 -3
  42. package/front_end/panels/network/RequestHeadersView.ts +2 -2
  43. package/front_end/panels/network/components/RequestHeadersView.css +1 -0
  44. package/front_end/panels/network/components/ResponseHeaderSection.css +5 -1
  45. package/front_end/panels/recorder/testing/RecorderHelpers.ts +2 -0
  46. package/front_end/panels/timeline/timeline-meta.ts +1 -1
  47. package/front_end/third_party/chromium/README.chromium +1 -1
  48. package/front_end/third_party/puppeteer/README.chromium +2 -2
  49. package/front_end/third_party/puppeteer/package/README.md +14 -0
  50. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +60 -24
  51. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +271 -164
  52. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +2 -6
  53. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
  54. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js +2 -2
  55. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
  56. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +2 -2
  57. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
  58. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js +11 -7
  59. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPRequest.js.map +1 -1
  60. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.d.ts.map +1 -1
  61. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js +3 -10
  62. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/JSHandle.js.map +1 -1
  63. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts +9 -4
  64. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.d.ts.map +1 -1
  65. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js +4 -4
  66. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Page.js.map +1 -1
  67. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.d.ts +13 -0
  68. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.d.ts.map +1 -1
  69. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.js +14 -0
  70. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/WebWorker.js.map +1 -1
  71. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js +5 -5
  72. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
  73. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js +2 -2
  74. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BidiOverCdp.js.map +1 -1
  75. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js +3 -3
  76. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Browser.js.map +1 -1
  77. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserConnector.js +5 -3
  78. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserConnector.js.map +1 -1
  79. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserContext.js +6 -6
  80. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/BrowserContext.js.map +1 -1
  81. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts +1 -1
  82. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.d.ts.map +1 -1
  83. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js +3 -3
  84. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Connection.js.map +1 -1
  85. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Deserializer.js +2 -2
  86. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Deserializer.js.map +1 -1
  87. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/ExposedFunction.js +6 -6
  88. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/ExposedFunction.js.map +1 -1
  89. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Frame.js +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Frame.js.map +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts +1 -0
  92. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.d.ts.map +1 -1
  93. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js +3 -0
  94. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Page.js.map +1 -1
  95. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Realm.js +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/Realm.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.d.ts +1 -0
  98. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.d.ts.map +1 -1
  99. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.js +11 -0
  100. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/BrowsingContext.js.map +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.d.ts.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js +4 -4
  103. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Accessibility.js.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Binding.js +3 -3
  105. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Binding.js.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +13 -2
  108. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
  109. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/BrowserConnector.js +2 -2
  110. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/BrowserConnector.js.map +1 -1
  111. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js +2 -2
  112. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Connection.js.map +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Coverage.js +2 -2
  114. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Coverage.js.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ElementHandle.js +1 -1
  116. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ElementHandle.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts +1 -0
  118. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.d.ts.map +1 -1
  119. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js +25 -4
  120. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/EmulationManager.js.map +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ExecutionContext.js +3 -3
  122. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/ExecutionContext.js.map +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Extension.d.ts.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Extension.js +9 -11
  125. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Extension.js.map +1 -1
  126. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +3 -3
  127. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.d.ts.map +1 -1
  129. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js +7 -7
  130. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js.map +1 -1
  131. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPRequest.js.map +1 -1
  133. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/JSHandle.js +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/JSHandle.js.map +1 -1
  135. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts +3 -1
  136. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  137. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js +18 -10
  138. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/NetworkManager.js.map +1 -1
  139. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts +1 -0
  140. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.d.ts.map +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js +17 -11
  142. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Page.js.map +1 -1
  143. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js +3 -3
  144. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
  145. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.d.ts.map +1 -1
  146. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js +28 -10
  147. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/TargetManager.js.map +1 -1
  148. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  149. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js +10 -6
  150. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js.map +1 -1
  151. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.d.ts +3 -0
  152. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.d.ts.map +1 -1
  153. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.js +20 -5
  154. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebWorker.js.map +1 -1
  155. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.d.ts.map +1 -1
  156. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js +11 -0
  157. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserConnector.js.map +1 -1
  158. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js +2 -2
  159. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/BrowserWebSocketTransport.js.map +1 -1
  160. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/CallbackRegistry.js +2 -2
  161. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/CallbackRegistry.js.map +1 -1
  162. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Configuration.d.ts +4 -2
  163. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Configuration.d.ts.map +1 -1
  164. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts +26 -13
  165. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  166. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts +1 -6
  167. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.d.ts.map +1 -1
  168. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js +24 -33
  169. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/Debug.js.map +1 -1
  170. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js +2 -2
  171. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/EventEmitter.js.map +1 -1
  172. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts +8 -1
  173. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.d.ts.map +1 -1
  174. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js +8 -1
  175. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/util.js.map +1 -1
  176. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.d.ts +2 -0
  177. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.d.ts.map +1 -1
  178. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.js +4 -2
  179. package/front_end/third_party/puppeteer/package/lib/puppeteer/environment.js.map +1 -1
  180. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts +1 -1
  181. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.d.ts.map +1 -1
  182. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js +1 -1
  183. package/front_end/third_party/puppeteer/package/lib/puppeteer/generated/injected.js.map +1 -1
  184. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/TextContent.d.ts.map +1 -1
  185. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/TextContent.js +15 -5
  186. package/front_end/third_party/puppeteer/package/lib/puppeteer/injected/TextContent.js.map +1 -1
  187. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts +5 -1
  188. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  189. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +17 -16
  190. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
  191. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.d.ts.map +1 -1
  192. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js +14 -9
  193. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ChromeLauncher.js.map +1 -1
  194. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/FirefoxLauncher.js +2 -2
  195. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/FirefoxLauncher.js.map +1 -1
  196. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js +2 -2
  197. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/NodeWebSocketTransport.js.map +1 -1
  198. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/PipeTransport.js +3 -3
  199. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/PipeTransport.js.map +1 -1
  200. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts +20 -0
  201. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.d.ts.map +1 -1
  202. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js +38 -9
  203. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/ScreenRecorder.js.map +1 -1
  204. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.d.ts +7 -0
  205. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.d.ts.map +1 -0
  206. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js +16 -0
  207. package/front_end/third_party/puppeteer/package/lib/puppeteer/node-env-setup.js.map +1 -0
  208. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.d.ts +1 -0
  209. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.d.ts.map +1 -1
  210. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.js +3 -8
  211. package/front_end/third_party/puppeteer/package/lib/puppeteer/puppeteer-core.js.map +1 -1
  212. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +3 -3
  213. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +3 -3
  214. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js.map +1 -1
  215. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  216. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  217. package/front_end/third_party/puppeteer/package/lib/types.d.ts +60 -24
  218. package/front_end/third_party/puppeteer/package/package.json +4 -4
  219. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +4 -8
  220. package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +2 -2
  221. package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +10 -10
  222. package/front_end/third_party/puppeteer/package/src/api/JSHandle.ts +3 -10
  223. package/front_end/third_party/puppeteer/package/src/api/Page.ts +14 -8
  224. package/front_end/third_party/puppeteer/package/src/api/WebWorker.ts +30 -0
  225. package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +5 -5
  226. package/front_end/third_party/puppeteer/package/src/bidi/BidiOverCdp.ts +2 -2
  227. package/front_end/third_party/puppeteer/package/src/bidi/Browser.ts +3 -3
  228. package/front_end/third_party/puppeteer/package/src/bidi/BrowserConnector.ts +5 -3
  229. package/front_end/third_party/puppeteer/package/src/bidi/BrowserContext.ts +6 -6
  230. package/front_end/third_party/puppeteer/package/src/bidi/Connection.ts +4 -4
  231. package/front_end/third_party/puppeteer/package/src/bidi/Deserializer.ts +2 -2
  232. package/front_end/third_party/puppeteer/package/src/bidi/ExposedFunction.ts +6 -6
  233. package/front_end/third_party/puppeteer/package/src/bidi/Frame.ts +1 -1
  234. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +4 -0
  235. package/front_end/third_party/puppeteer/package/src/bidi/Realm.ts +1 -1
  236. package/front_end/third_party/puppeteer/package/src/bidi/core/BrowsingContext.ts +11 -0
  237. package/front_end/third_party/puppeteer/package/src/cdp/Accessibility.ts +6 -4
  238. package/front_end/third_party/puppeteer/package/src/cdp/Binding.ts +3 -3
  239. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +14 -2
  240. package/front_end/third_party/puppeteer/package/src/cdp/BrowserConnector.ts +2 -2
  241. package/front_end/third_party/puppeteer/package/src/cdp/Connection.ts +2 -2
  242. package/front_end/third_party/puppeteer/package/src/cdp/Coverage.ts +2 -2
  243. package/front_end/third_party/puppeteer/package/src/cdp/ElementHandle.ts +1 -1
  244. package/front_end/third_party/puppeteer/package/src/cdp/EmulationManager.ts +36 -4
  245. package/front_end/third_party/puppeteer/package/src/cdp/ExecutionContext.ts +3 -3
  246. package/front_end/third_party/puppeteer/package/src/cdp/Extension.ts +16 -17
  247. package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +3 -3
  248. package/front_end/third_party/puppeteer/package/src/cdp/FrameManager.ts +12 -7
  249. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +1 -1
  250. package/front_end/third_party/puppeteer/package/src/cdp/JSHandle.ts +1 -1
  251. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +22 -11
  252. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +18 -10
  253. package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +3 -3
  254. package/front_end/third_party/puppeteer/package/src/cdp/TargetManager.ts +37 -12
  255. package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +11 -9
  256. package/front_end/third_party/puppeteer/package/src/cdp/WebWorker.ts +33 -5
  257. package/front_end/third_party/puppeteer/package/src/common/BrowserConnector.ts +11 -0
  258. package/front_end/third_party/puppeteer/package/src/common/BrowserWebSocketTransport.ts +2 -2
  259. package/front_end/third_party/puppeteer/package/src/common/CallbackRegistry.ts +2 -2
  260. package/front_end/third_party/puppeteer/package/src/common/Configuration.ts +4 -2
  261. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +26 -13
  262. package/front_end/third_party/puppeteer/package/src/common/Debug.ts +30 -40
  263. package/front_end/third_party/puppeteer/package/src/common/EventEmitter.ts +2 -2
  264. package/front_end/third_party/puppeteer/package/src/common/util.ts +9 -1
  265. package/front_end/third_party/puppeteer/package/src/environment.ts +7 -3
  266. package/front_end/third_party/puppeteer/package/src/generated/injected.ts +1 -1
  267. package/front_end/third_party/puppeteer/package/src/injected/TextContent.ts +15 -5
  268. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +23 -23
  269. package/front_end/third_party/puppeteer/package/src/node/ChromeLauncher.ts +19 -13
  270. package/front_end/third_party/puppeteer/package/src/node/FirefoxLauncher.ts +2 -2
  271. package/front_end/third_party/puppeteer/package/src/node/NodeWebSocketTransport.ts +2 -2
  272. package/front_end/third_party/puppeteer/package/src/node/PipeTransport.ts +3 -3
  273. package/front_end/third_party/puppeteer/package/src/node/ScreenRecorder.ts +44 -9
  274. package/front_end/third_party/puppeteer/package/src/node-env-setup.ts +18 -0
  275. package/front_end/third_party/puppeteer/package/src/puppeteer-core.ts +5 -9
  276. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  277. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  278. package/front_end/third_party/puppeteer/puppeteer-tsconfig.json +1 -0
  279. package/front_end/tsconfig.json +1 -2
  280. package/inspector_overlay/tsconfig.json +3 -10
  281. package/mcp/tsconfig.json +1 -5
  282. package/package.json +1 -2
@@ -85,7 +85,8 @@ export class HostsPolicy {
85
85
  }
86
86
 
87
87
  class RegisteredExtension {
88
- constructor(readonly name: string, readonly hostsPolicy: HostsPolicy, readonly allowFileAccess: boolean) {
88
+ constructor(readonly origin: string, readonly name: string, readonly hostsPolicy: HostsPolicy,
89
+ readonly allowFileAccess: boolean) {
89
90
  }
90
91
 
91
92
  isAllowedOnTarget(inspectedURL?: Platform.DevToolsPath.UrlString): boolean {
@@ -104,6 +105,14 @@ class RegisteredExtension {
104
105
  return false;
105
106
  }
106
107
 
108
+ if (parsedURL.protocol === 'chrome-extension:') {
109
+ if (parsedURL.origin !== this.origin) {
110
+ if (!Root.Runtime.hostConfig.extensionsOnChromeUrls?.enabled) {
111
+ return false;
112
+ }
113
+ }
114
+ }
115
+
107
116
  if (!ExtensionServer.canInspectURL(inspectedURL)) {
108
117
  return false;
109
118
  }
@@ -953,27 +962,45 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
953
962
  */
954
963
  private extensionAllowedOnContentProvider(
955
964
  contentProvider: TextUtils.ContentProvider.ContentProvider, port: MessagePort): boolean {
956
- if (!(contentProvider instanceof Workspace.UISourceCode.UISourceCode)) {
957
- return this.extensionAllowedOnURL(contentProvider.contentURL(), port);
965
+ // 1. Exception for Scripts with sourceURL
966
+ if (contentProvider instanceof Workspace.UISourceCode.UISourceCode &&
967
+ contentProvider.contentType() === Common.ResourceType.resourceTypes.Script) {
968
+ const scripts =
969
+ Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().scriptsForUISourceCode(contentProvider);
970
+ if (scripts.length > 0) {
971
+ const uiSourceCodeTarget =
972
+ Bindings.NetworkProject.NetworkProject.targetForUISourceCode(contentProvider) ?? undefined;
973
+ if (uiSourceCodeTarget && !this.extensionAllowedOnTarget(uiSourceCodeTarget, port)) {
974
+ return false;
975
+ }
976
+ return scripts.every(script => {
977
+ if (script.hasSourceURL) {
978
+ return this.extensionAllowedOnTarget(script.target(), port);
979
+ }
980
+ return this.extensionAllowedOnURL(script.contentURL(), port) &&
981
+ this.extensionAllowedOnTarget(script.target(), port);
982
+ });
983
+ }
958
984
  }
959
985
 
960
- if (contentProvider.contentType() !== Common.ResourceType.resourceTypes.Script) {
961
- // We only check sourceURL magic comments for scripts (excluding ones coming from source maps).
962
- return this.extensionAllowedOnURL(contentProvider.contentURL(), port);
986
+ // 2. Standard Policy: Both URL and Target must be allowed
987
+
988
+ // 2a. Check URL
989
+ if (!this.extensionAllowedOnURL(contentProvider.contentURL(), port)) {
990
+ return false;
963
991
  }
964
992
 
965
- const scripts =
966
- Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().scriptsForUISourceCode(contentProvider);
967
- if (scripts.length === 0) {
968
- return this.extensionAllowedOnURL(contentProvider.contentURL(), port);
993
+ // 2b. Check Target (if one can be identified)
994
+ let target: SDK.Target.Target|undefined;
995
+ if (contentProvider instanceof SDK.NetworkRequest.NetworkRequest) {
996
+ target = SDK.NetworkManager.NetworkManager.forRequest(contentProvider)?.target();
997
+ } else if (contentProvider instanceof SDK.Resource.Resource) {
998
+ target = contentProvider.frame()?.resourceTreeModel().target();
999
+ } else if (contentProvider instanceof Workspace.UISourceCode.UISourceCode) {
1000
+ target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(contentProvider) ?? undefined;
969
1001
  }
970
1002
 
971
- return scripts.every(script => {
972
- if (script.hasSourceURL) {
973
- return this.extensionAllowedOnTarget(script.target(), port);
974
- }
975
- return this.extensionAllowedOnURL(script.contentURL(), port);
976
- });
1003
+ return !target || this.extensionAllowedOnTarget(target, port);
977
1004
  }
978
1005
 
979
1006
  /**
@@ -998,7 +1025,10 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
998
1025
  return {uiSourceCode};
999
1026
  }
1000
1027
 
1001
- private extensionAllowedOnTarget(target: SDK.Target.Target, port: MessagePort): boolean {
1028
+ private extensionAllowedOnTarget(target: SDK.Target.Target|undefined, port: MessagePort): boolean {
1029
+ if (!target) {
1030
+ return false;
1031
+ }
1002
1032
  return this.extensionAllowedOnURL(target.inspectedURL(), port);
1003
1033
  }
1004
1034
 
@@ -1061,7 +1091,7 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1061
1091
  return this.status.E_BADARG('command', `expected ${Extensions.ExtensionAPI.PrivateAPI.Commands.GetHAR}`);
1062
1092
  }
1063
1093
  const requests =
1064
- Logs.NetworkLog.NetworkLog.instance().requests().filter(r => this.extensionAllowedOnURL(r.url(), port));
1094
+ Logs.NetworkLog.NetworkLog.instance().requests().filter(r => this.extensionAllowedOnContentProvider(r, port));
1065
1095
  const harLog = await HAR.Log.Log.build(requests, {sanitize: false});
1066
1096
  for (let i = 0; i < harLog.entries.length; ++i) {
1067
1097
  // @ts-expect-error
@@ -1310,26 +1340,34 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1310
1340
 
1311
1341
  private notifyResourceAdded(event: Common.EventTarget.EventTargetEvent<Workspace.UISourceCode.UISourceCode>): void {
1312
1342
  const uiSourceCode = event.data;
1313
- this.postNotification(
1314
- Extensions.ExtensionAPI.PrivateAPI.Events.ResourceAdded, [this.makeResource(uiSourceCode)],
1315
- extension => extension.isAllowedOnTarget(uiSourceCode.url()));
1343
+ const target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(uiSourceCode);
1344
+ const targetUrl = target?.inspectedURL();
1345
+ this.postNotification(Extensions.ExtensionAPI.PrivateAPI.Events.ResourceAdded, [this.makeResource(uiSourceCode)],
1346
+ extension => extension.isAllowedOnTarget(uiSourceCode.url()) &&
1347
+ (!targetUrl || extension.isAllowedOnTarget(targetUrl)));
1316
1348
  }
1317
1349
 
1318
1350
  private notifyUISourceCodeContentCommitted(
1319
1351
  event: Common.EventTarget.EventTargetEvent<Workspace.Workspace.WorkingCopyCommittedEvent>): void {
1320
1352
  const {uiSourceCode, content} = event.data;
1321
- this.postNotification(
1322
- Extensions.ExtensionAPI.PrivateAPI.Events.ResourceContentCommitted, [this.makeResource(uiSourceCode), content],
1323
- extension => extension.isAllowedOnTarget(uiSourceCode.url()));
1353
+ const target = Bindings.NetworkProject.NetworkProject.targetForUISourceCode(uiSourceCode);
1354
+ const targetUrl = target?.inspectedURL();
1355
+ this.postNotification(Extensions.ExtensionAPI.PrivateAPI.Events.ResourceContentCommitted,
1356
+ [this.makeResource(uiSourceCode), content],
1357
+ extension => extension.isAllowedOnTarget(uiSourceCode.url()) &&
1358
+ (!targetUrl || extension.isAllowedOnTarget(targetUrl)));
1324
1359
  }
1325
1360
 
1326
1361
  private async notifyRequestFinished(event: Common.EventTarget.EventTargetEvent<SDK.NetworkRequest.NetworkRequest>):
1327
1362
  Promise<void> {
1328
1363
  const request = event.data;
1329
1364
  const entry = await HAR.Log.Entry.build(request, {sanitize: false});
1365
+ const networkManager = SDK.NetworkManager.NetworkManager.forRequest(request);
1366
+ const targetUrl = networkManager?.target()?.inspectedURL();
1330
1367
  this.postNotification(
1331
1368
  Extensions.ExtensionAPI.PrivateAPI.Events.NetworkRequestFinished, [this.requestId(request), entry],
1332
- extension => extension.isAllowedOnTarget(entry.request.url));
1369
+ extension => extension.isAllowedOnTarget(entry.request.url as Platform.DevToolsPath.UrlString) &&
1370
+ (!targetUrl || extension.isAllowedOnTarget(targetUrl)));
1333
1371
  }
1334
1372
 
1335
1373
  private notifyElementsSelectionChanged(): void {
@@ -1388,7 +1426,8 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1388
1426
  const startPageURL = new URL((startPage));
1389
1427
  const extensionOrigin = startPageURL.origin;
1390
1428
  const name = extensionInfo.name || `Extension ${extensionOrigin}`;
1391
- const extensionRegistration = new RegisteredExtension(name, hostsPolicy, Boolean(extensionInfo.allowFileAccess));
1429
+ const extensionRegistration =
1430
+ new RegisteredExtension(extensionOrigin, name, hostsPolicy, Boolean(extensionInfo.allowFileAccess));
1392
1431
  if (!extensionRegistration.isAllowedOnTarget(inspectedURL)) {
1393
1432
  this.#pendingExtensions.push(extensionInfo);
1394
1433
  return;
@@ -1494,11 +1533,11 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1494
1533
  private registerAutosubscriptionTargetManagerHandler<Events, T extends keyof Events>(
1495
1534
  eventTopic: string, modelClass: new(arg1: SDK.Target.Target) => SDK.SDKModel.SDKModel<Events>,
1496
1535
  frontendEventType: T, handler: Common.EventTarget.EventListener<Events, T>): void {
1497
- this.registerSubscriptionHandler(
1498
- eventTopic,
1499
- () => SDK.TargetManager.TargetManager.instance().addModelListener(modelClass, frontendEventType, handler, this),
1500
- () => SDK.TargetManager.TargetManager.instance().removeModelListener(
1501
- modelClass, frontendEventType, handler, this));
1536
+ this.registerSubscriptionHandler(eventTopic,
1537
+ () => SDK.TargetManager.TargetManager.instance().addModelListener(
1538
+ modelClass, frontendEventType, handler, this, {scoped: true}),
1539
+ () => SDK.TargetManager.TargetManager.instance().removeModelListener(
1540
+ modelClass, frontendEventType, handler, this));
1502
1541
  }
1503
1542
 
1504
1543
  private registerResourceContentCommittedHandler(
@@ -1609,25 +1648,6 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
1609
1648
  return this.status.E_FAILED('Permission denied');
1610
1649
  }
1611
1650
 
1612
- try {
1613
- const parsedUrl = new URL(frame.url);
1614
- let targetType = Host.UserMetrics.ExtensionEvalTarget.WEB_PAGE;
1615
- if (parsedUrl.protocol === 'chrome-extension:') {
1616
- if (parsedUrl.origin === securityOrigin) {
1617
- targetType = Host.UserMetrics.ExtensionEvalTarget.SAME_EXTENSION;
1618
- } else {
1619
- targetType = Host.UserMetrics.ExtensionEvalTarget.OTHER_EXTENSION;
1620
- if (!Root.Runtime.hostConfig.extensionsOnChromeUrls?.enabled) {
1621
- return this.status.E_FAILED(
1622
- 'Access to extension URLs is restricted; use --extensions-on-chrome-urls to enable.');
1623
- }
1624
- }
1625
- }
1626
- Host.userMetrics.extensionEvalTarget(targetType);
1627
- } catch {
1628
- // Ignore invalid URLs.
1629
- }
1630
-
1631
1651
  void context
1632
1652
  .evaluate(
1633
1653
  {
@@ -0,0 +1,106 @@
1
+ // Copyright 2026 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../core/i18n/i18n.js';
6
+ import type * as Protocol from '../../generated/protocol.js';
7
+
8
+ const UIStrings = {
9
+ /**
10
+ * @description Summary line in a tooltip explaining a CSS selector specificity.
11
+ * @example {1} PH1
12
+ * @example {2} PH2
13
+ * @example {3} PH3
14
+ */
15
+ specificity: 'Specificity: ({PH1},{PH2},{PH3})',
16
+ /**
17
+ * @description Tooltip line listing the selector parts contributing to the ID-like specificity bucket.
18
+ * @example {#main} PH1
19
+ */
20
+ idLikeSpecificity: '(a) ID-like: {PH1}',
21
+ /**
22
+ * @description Tooltip line listing the selector parts contributing to the class-like specificity bucket.
23
+ * @example {.active, :hover} PH1
24
+ */
25
+ classLikeSpecificity: '(b) Class-like: {PH1}',
26
+ /**
27
+ * @description Tooltip line listing the selector parts contributing to the type-like specificity bucket.
28
+ * @example {div} PH1
29
+ */
30
+ typeLikeSpecificity: '(c) Type-like: {PH1}',
31
+ } as const;
32
+ const str_ = i18n.i18n.registerUIStrings('panels/elements/CSSSpecificityBreakdown.ts', UIStrings);
33
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
34
+
35
+ export interface SpecificityBreakdown {
36
+ ids: string[];
37
+ classes: string[];
38
+ types: string[];
39
+ }
40
+
41
+ function formatContribution(text: string, contribution: number): string {
42
+ return contribution > 1 ? `${text} x${contribution}` : text;
43
+ }
44
+
45
+ function formatComponentList(components: string[]): string {
46
+ const formatter = new Intl.ListFormat(i18n.DevToolsLocale.DevToolsLocale.instance().locale, {
47
+ style: 'long',
48
+ type: 'conjunction',
49
+ });
50
+ return formatter.format(components);
51
+ }
52
+
53
+ export function getSpecificityBreakdown(specificity: Protocol.CSS.Specificity): SpecificityBreakdown {
54
+ const ids: string[] = [];
55
+ const classes: string[] = [];
56
+ const types: string[] = [];
57
+
58
+ for (const component of specificity.components ?? []) {
59
+ if (component.a > 0) {
60
+ ids.push(formatContribution(component.text, component.a));
61
+ }
62
+ if (component.b > 0) {
63
+ classes.push(formatContribution(component.text, component.b));
64
+ }
65
+ if (component.c > 0) {
66
+ types.push(formatContribution(component.text, component.c));
67
+ }
68
+ }
69
+
70
+ return {ids, classes, types};
71
+ }
72
+
73
+ /**
74
+ * Formats the specificity breakdown into a human-readable multi-line string
75
+ * suitable for displaying in a tooltip.
76
+ *
77
+ * Example output for selector "div#main .active:hover":
78
+ * Specificity: (1,2,1)
79
+ * (a) ID-like: #main
80
+ * (b) Class-like: .active, :hover
81
+ * (c) Type-like: div
82
+ */
83
+ export function formatSpecificitySummary(specificity: Protocol.CSS.Specificity): string {
84
+ return i18nString(UIStrings.specificity, {PH1: specificity.a, PH2: specificity.b, PH3: specificity.c});
85
+ }
86
+
87
+ export function getSpecificityBreakdownLines(specificity: Protocol.CSS.Specificity): string[] {
88
+ const breakdown = getSpecificityBreakdown(specificity);
89
+ const lines: string[] = [];
90
+
91
+ if (breakdown.ids.length > 0) {
92
+ lines.push(i18nString(UIStrings.idLikeSpecificity, {PH1: formatComponentList(breakdown.ids)}));
93
+ }
94
+ if (breakdown.classes.length > 0) {
95
+ lines.push(i18nString(UIStrings.classLikeSpecificity, {PH1: formatComponentList(breakdown.classes)}));
96
+ }
97
+ if (breakdown.types.length > 0) {
98
+ lines.push(i18nString(UIStrings.typeLikeSpecificity, {PH1: formatComponentList(breakdown.types)}));
99
+ }
100
+
101
+ return lines;
102
+ }
103
+
104
+ export function formatSpecificityTooltip(specificity: Protocol.CSS.Specificity): string {
105
+ return [formatSpecificitySummary(specificity), ...getSpecificityBreakdownLines(specificity)].join('\n');
106
+ }
@@ -1627,7 +1627,7 @@ export class PseudoStateMarkerDecorator implements MarkerDecorator {
1627
1627
  return null;
1628
1628
  }
1629
1629
  return {
1630
- color: '--sys-color-orange-bright',
1630
+ color: 'var(--sys-color-orange-bright)',
1631
1631
  title: i18nString(UIStrings.elementStateS, {PH1: ':' + pseudoState.join(', :')}),
1632
1632
  };
1633
1633
  }
@@ -54,9 +54,15 @@ import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
54
54
  import * as PanelsCommon from '../common/common.js';
55
55
 
56
56
  import * as ElementsComponents from './components/components.js';
57
+ import {formatSpecificitySummary, getSpecificityBreakdownLines} from './CSSSpecificityBreakdown.js';
57
58
  import {ElementsPanel} from './ElementsPanel.js';
58
59
  import stylePropertiesTreeOutlineStyles from './stylePropertiesTreeOutline.css.js';
59
- import {type Context, GhostStylePropertyTreeElement, StylePropertyTreeElement} from './StylePropertyTreeElement.js';
60
+ import {
61
+ type Context,
62
+ GhostStylePropertyTreeElement,
63
+ handleVarDefinitionActivate,
64
+ StylePropertyTreeElement,
65
+ } from './StylePropertyTreeElement.js';
60
66
  import type {StylesContainer} from './StylesContainer.js';
61
67
 
62
68
  const UIStrings = {
@@ -110,11 +116,6 @@ const UIStrings = {
110
116
  * @description Text that is announced by the screen reader when the user focuses on an input field for editing the name of a CSS selector in the Styles panel
111
117
  */
112
118
  cssSelector: '`CSS` selector',
113
- /**
114
- * @description Text displayed in tooltip that shows specificity information.
115
- * @example {(0,0,1)} PH1
116
- */
117
- specificity: 'Specificity: {PH1}',
118
119
  /**
119
120
  * @description Accessibility label for the button that expands a collapsed CSS rule in the Styles pane.
120
121
  */
@@ -898,7 +899,7 @@ export class StylePropertiesSection {
898
899
  ancestorRuleElement = this.createMediaElement(rule.media[mediaIndex++]);
899
900
  break;
900
901
  case Protocol.CSS.CSSRuleType.ContainerRule:
901
- ancestorRuleElement = this.createContainerQueryElement(rule.containerQueries[containerIndex++]);
902
+ ancestorRuleElement = this.createContainerQueryElement(rule.containerQueries[containerIndex++], rule.style);
902
903
  break;
903
904
  case Protocol.CSS.CSSRuleType.ScopeRule:
904
905
  ancestorRuleElement = this.createScopeElement(rule.scopes[scopeIndex++]);
@@ -1019,7 +1020,8 @@ export class StylePropertiesSection {
1019
1020
  return mediaQueryElement;
1020
1021
  }
1021
1022
 
1022
- protected createContainerQueryElement(containerQuery: SDK.CSSContainerQuery.CSSContainerQuery):
1023
+ protected createContainerQueryElement(containerQuery: SDK.CSSContainerQuery.CSSContainerQuery,
1024
+ style?: SDK.CSSStyleDeclaration.CSSStyleDeclaration):
1023
1025
  ElementsComponents.CSSQuery.CSSQuery|undefined {
1024
1026
  let onQueryTextClick;
1025
1027
  if (containerQuery.styleSheetId) {
@@ -1032,10 +1034,22 @@ export class StylePropertiesSection {
1032
1034
  queryName: containerQuery.textIsConditionText ? undefined : containerQuery.name,
1033
1035
  queryText: containerQuery.text,
1034
1036
  onQueryTextClick,
1037
+ onLinkActivate: async(resolvedVariable: string|SDK.CSSMatchedStyles.CSSValueSource): Promise<void> => {
1038
+ handleVarDefinitionActivate(resolvedVariable, this.stylesContainer);
1039
+ },
1040
+ getPopoverContents: (variableName: string, variableValue: string|null):
1041
+ ElementsComponents.CSSVariableValueView.CSSVariableValueView => {
1042
+ return this.stylesContainer.getVariablePopoverContents(this.matchedStyles, variableName, variableValue);
1043
+ },
1035
1044
  jslogContext: 'container-query',
1036
1045
  };
1037
- if (!/^style\(.*\)/.test(containerQuery.text)) {
1038
- // We only add container element for non-style queries.
1046
+ if (style) {
1047
+ const tooltipPrefix = `container-${this.sectionTooltipIdPrefix}-${this.nestingLevel}`;
1048
+ void containerQuery.getContainerForNode(this.matchedStyles.node().id).then(container => {
1049
+ if (container) {
1050
+ containerQueryElement.parseStyleQueries(this.matchedStyles, style, container.containerNode, tooltipPrefix);
1051
+ }
1052
+ });
1039
1053
  void this.addContainerForContainerQuery(containerQuery);
1040
1054
  }
1041
1055
  return containerQueryElement;
@@ -1434,14 +1448,27 @@ export class StylePropertiesSection {
1434
1448
  elementToSelectorIndex.set(span, i);
1435
1449
  span.textContent = selectors[i].text;
1436
1450
  if (specificityTooltipId && selector.specificity) {
1437
- span.setAttribute('aria-describedby', specificityTooltipId);
1438
- const PH1 = `(${selector.specificity.a},${selector.specificity.b},${selector.specificity.c})`;
1451
+ span.setAttribute('aria-details', specificityTooltipId);
1439
1452
  const tooltip = this.#specificityTooltips.appendChild(new Tooltips.Tooltip.Tooltip({
1440
1453
  id: specificityTooltipId,
1441
1454
  anchor: span,
1455
+ variant: 'rich',
1442
1456
  jslogContext: 'elements.css-selector-specificity',
1443
1457
  }));
1444
- tooltip.textContent = i18nString(UIStrings.specificity, {PH1});
1458
+ tooltip.hoverDelay = 500;
1459
+
1460
+ const specificitySummary = formatSpecificitySummary(selector.specificity);
1461
+ const breakdownLines = getSpecificityBreakdownLines(selector.specificity);
1462
+ const tooltipContent = breakdownLines.length > 0 ? html`
1463
+ <details class="selector-specificity-tooltip-disclosure">
1464
+ <summary>${specificitySummary}</summary>
1465
+ <ul class="selector-specificity-tooltip-list">
1466
+ ${breakdownLines.map(line => html`<li>${line}</li>`)}
1467
+ </ul>
1468
+ </details>` :
1469
+ html`
1470
+ <div class="selector-specificity-tooltip-summary">${specificitySummary}</div>`;
1471
+ render(tooltipContent, tooltip, {host: this});
1445
1472
  }
1446
1473
  }
1447
1474
  }
@@ -316,8 +316,8 @@ export class CSSWideKeywordRenderer extends rendererBase(SDK.CSSPropertyParserMa
316
316
  }
317
317
  }
318
318
 
319
- function handleVarDefinitionActivate(variable: string|SDK.CSSMatchedStyles.CSSValueSource,
320
- stylesContainer: StylesContainer): void {
319
+ export function handleVarDefinitionActivate(variable: string|SDK.CSSMatchedStyles.CSSValueSource,
320
+ stylesContainer: StylesContainer): void {
321
321
  Host.userMetrics.actionTaken(Host.UserMetrics.Action.CustomPropertyLinkClicked);
322
322
  Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.VAR_LINK);
323
323
 
@@ -448,16 +448,17 @@ export class VariableNameRenderer extends rendererBase(SDK.CSSPropertyParserMatc
448
448
  this.#matchedStyles = matchedStyles;
449
449
  }
450
450
 
451
- override render(match: SDK.CSSPropertyParserMatchers.VariableNameMatch, context: RenderingContext): Node[] {
451
+ override render(match: SDK.CSSPropertyParserMatchers.VariableNameMatch, _context: RenderingContext): Node[] {
452
+ const varSwatch = document.createElement('span');
452
453
  if (this.#treeElement?.property.ownerStyle.parentRule instanceof SDK.CSSRule.CSSFunctionRule) {
453
- return Renderer.render(ASTUtils.children(match.node), context).nodes;
454
+ render(html`${match.text}`, varSwatch);
455
+ return [varSwatch];
454
456
  }
455
457
 
456
458
  const {declaration, value: variableValue} = match.resolveVariable() ?? {};
457
459
  const isDefined = variableValue !== undefined;
458
460
  const onLinkActivate = (name: string): void =>
459
461
  handleVarDefinitionActivate(declaration ?? name, this.#stylesContainer);
460
- const varSwatch = document.createElement('span');
461
462
 
462
463
  const tooltipContents =
463
464
  this.#stylesContainer.getVariablePopoverContents(this.#matchedStyles, match.text, variableValue ?? null);
@@ -3,11 +3,17 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-lit-render-outside-of-view */
5
5
 
6
+ import '../../../ui/components/tooltips/tooltips.js';
7
+ import '../../../ui/legacy/components/inline_editor/inline_editor.js';
8
+
9
+ import * as SDK from '../../../core/sdk/sdk.js';
10
+ import type * as InlineEditor from '../../../ui/legacy/components/inline_editor/inline_editor.js';
6
11
  import * as UI from '../../../ui/legacy/legacy.js';
7
12
  import * as Lit from '../../../ui/lit/lit.js';
8
13
  import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';
9
14
 
10
15
  import cssQueryStyles from './cssQuery.css.js';
16
+ import type {CSSVariableValueView} from './CSSVariableValueView.js';
11
17
 
12
18
  const {render, html} = Lit;
13
19
 
@@ -16,36 +22,145 @@ export interface CSSQueryData {
16
22
  queryName?: string;
17
23
  queryText: string;
18
24
  onQueryTextClick?: (event: Event) => void;
25
+ onLinkActivate?: (resolvedVariable: string|SDK.CSSMatchedStyles.CSSValueSource) => void;
26
+ getPopoverContents?: (variableName: string, variableValue: string|null) => CSSVariableValueView;
19
27
  jslogContext: string;
20
28
  }
21
29
 
30
+ interface TextSection {
31
+ text: string;
32
+ isVariable: boolean;
33
+ }
34
+
22
35
  export class CSSQuery extends HTMLElement {
23
36
  readonly #shadow = this.attachShadow({mode: 'open'});
24
37
  #queryPrefix = '';
25
38
  #queryName?: string;
26
- #queryText = '';
39
+ #queryText: TextSection[] = [];
27
40
  #onQueryTextClick?: (event: Event) => void;
41
+ #onLinkActivate?: (resolvedVariable: string|SDK.CSSMatchedStyles.CSSValueSource) => void;
42
+ #getPopoverContents?: (variableName: string, variableValue: string|null) => CSSVariableValueView;
28
43
  #jslogContext?: string;
44
+ #matchedStyles?: SDK.CSSMatchedStyles.CSSMatchedStyles;
45
+ #style?: SDK.CSSStyleDeclaration.CSSStyleDeclaration;
46
+ #containerNode?: SDK.DOMModel.DOMNode;
47
+ #tooltipPrefix = '';
29
48
 
30
49
  set data(data: CSSQueryData) {
31
50
  this.#queryPrefix = data.queryPrefix;
32
51
  this.#queryName = data.queryName;
33
- this.#queryText = data.queryText;
52
+ this.#queryText = [{text: data.queryText, isVariable: false}];
34
53
  this.#onQueryTextClick = data.onQueryTextClick;
54
+ this.#onLinkActivate = data.onLinkActivate;
55
+ this.#getPopoverContents = data.getPopoverContents;
35
56
  this.#jslogContext = data.jslogContext;
36
57
  this.#render();
37
58
  }
38
59
 
60
+ parseStyleQueries(
61
+ matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles,
62
+ style: SDK.CSSStyleDeclaration.CSSStyleDeclaration,
63
+ containerNode: SDK.DOMModel.DOMNode,
64
+ tooltipPrefix: string,
65
+ ): void {
66
+ this.#matchedStyles = matchedStyles;
67
+ this.#style = style;
68
+ this.#containerNode = containerNode;
69
+ this.#tooltipPrefix = tooltipPrefix;
70
+
71
+ const queryText = this.#queryText[0]?.text;
72
+ if (!queryText) {
73
+ return;
74
+ }
75
+
76
+ const prefix = 'if(';
77
+ const suffix = ': 1)';
78
+ const ast = SDK.CSSPropertyParser.tokenizeDeclaration('--query', prefix + queryText + suffix);
79
+ if (!ast) {
80
+ return;
81
+ }
82
+
83
+ const matcher = new SDK.CSSPropertyParserMatchers.VariableNameMatcher(matchedStyles, style);
84
+ const matchedResult = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [matcher]);
85
+ const matchedNodes = SDK.CSSPropertyParser.TreeSearch.findAll(ast, node => {
86
+ return matchedResult.getMatch(node) instanceof SDK.CSSPropertyParserMatchers.VariableNameMatch;
87
+ });
88
+
89
+ matchedNodes.sort((a, b) => a.from - b.from);
90
+
91
+ const sections: TextSection[] = [];
92
+ const valueOffset = ast.rule.indexOf(ast.propertyValue) + prefix.length;
93
+ let lastOffset = 0;
94
+
95
+ for (const node of matchedNodes) {
96
+ const start = node.from - valueOffset;
97
+ const end = node.to - valueOffset;
98
+ if (start > lastOffset) {
99
+ sections.push({
100
+ text: queryText.substring(lastOffset, start),
101
+ isVariable: false,
102
+ });
103
+ }
104
+ sections.push({
105
+ text: queryText.substring(start, end),
106
+ isVariable: true,
107
+ });
108
+ lastOffset = end;
109
+ }
110
+
111
+ if (lastOffset < queryText.length) {
112
+ sections.push({
113
+ text: queryText.substring(lastOffset),
114
+ isVariable: false,
115
+ });
116
+ }
117
+
118
+ this.#queryText = sections;
119
+ this.#render();
120
+ }
121
+
39
122
  #render(): void {
40
123
  const queryClasses = Lit.Directives.classMap({
41
124
  query: true,
42
125
  editable: Boolean(this.#onQueryTextClick),
43
126
  });
44
127
 
45
- // Disabled until https://crbug.com/1079231 is fixed.
46
128
  // clang-format off
47
129
  const queryText = html`
48
- <span class="query-text" @click=${this.#onQueryTextClick}>${this.#queryText}</span>
130
+ <span class="query-text" @click=${this.#onQueryTextClick}>${
131
+ this.#queryText.map((section, index) => {
132
+ if (section.isVariable && this.#matchedStyles && this.#style && this.#onLinkActivate) {
133
+ const variableName = section.text;
134
+ const variable = this.#matchedStyles.computeCSSVariable(this.#style, variableName, this.#containerNode);
135
+ const isDefined = variable !== null && variable.value !== undefined;
136
+ const onLinkActivate = (): void => {
137
+ if (this.#onLinkActivate) {
138
+ this.#onLinkActivate(variable ? variable.declaration : variableName);
139
+ }
140
+ };
141
+ const tooltipContents = this.#getPopoverContents?.(variableName, variable?.value ?? null) ?? null;
142
+ const tooltipId = `${this.#tooltipPrefix}-${index}-${variableName}`;
143
+ const tooltip = {tooltipId};
144
+ return html`
145
+ <devtools-link-swatch class="css-var-link" .data=${{
146
+ tooltip,
147
+ text: variableName,
148
+ isDefined,
149
+ onLinkActivate,
150
+ } as InlineEditor.LinkSwatch.LinkSwatchRenderData}>
151
+ </devtools-link-swatch>
152
+ <devtools-tooltip
153
+ id=${tooltipId}
154
+ variant="rich"
155
+ jslogContext="elements.css-var"
156
+ >
157
+ ${tooltipContents}
158
+ </devtools-tooltip>
159
+ `;
160
+ }
161
+ return html`${section.text}`;
162
+ })
163
+ }</span>
49
164
  `;
50
165
 
51
166
  render(html`
@@ -23,6 +23,7 @@ import './StylesAiCodeCompletionProvider.js';
23
23
  import './StylePropertyTreeElement.js';
24
24
  import './ComputedStyleWidget.js';
25
25
  import './CSSRuleValidator.js';
26
+ import './CSSSpecificityBreakdown.js';
26
27
  import './ElementsPanel.js';
27
28
  import './ClassesPaneWidget.js';
28
29
  import './ElementStatePaneWidget.js';
@@ -36,6 +37,7 @@ import * as ClassesPaneWidget from './ClassesPaneWidget.js';
36
37
  import * as ColorSwatchPopoverIcon from './ColorSwatchPopoverIcon.js';
37
38
  import * as ComputedStyleWidget from './ComputedStyleWidget.js';
38
39
  import * as CSSRuleValidator from './CSSRuleValidator.js';
40
+ import * as CSSSpecificityBreakdown from './CSSSpecificityBreakdown.js';
39
41
  import * as CSSValueTraceView from './CSSValueTraceView.js';
40
42
  import * as DOMPath from './DOMPath.js';
41
43
  import * as ElementsPanel from './ElementsPanel.js';
@@ -73,6 +75,7 @@ export {
73
75
  ColorSwatchPopoverIcon,
74
76
  ComputedStyleWidget,
75
77
  CSSRuleValidator,
78
+ CSSSpecificityBreakdown,
76
79
  CSSValueTraceView,
77
80
  DOMPath,
78
81
  ElementsPanel,