chrome-devtools-frontend 1.0.1654411 → 1.0.1656897

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 (204) hide show
  1. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +116 -0
  2. package/.agents/skills/ui-eng-vision-logic-consolidator/SKILL.md +82 -0
  3. package/.agents/skills/ui-eng-vision-orchestrator/SKILL.md +123 -0
  4. package/.agents/skills/ui-eng-vision-test-scaffolder/SKILL.md +125 -0
  5. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +75 -0
  6. package/AUTHORS +1 -0
  7. package/config/owner/COMMON_OWNERS +0 -4
  8. package/docs/playbook.md +1 -1
  9. package/front_end/Tests.js +1 -0
  10. package/front_end/core/common/Settings.ts +47 -30
  11. package/front_end/core/sdk/CPUThrottlingManager.ts +10 -159
  12. package/front_end/core/sdk/ConsoleModel.ts +13 -11
  13. package/front_end/core/sdk/DOMDebuggerModel.ts +11 -5
  14. package/front_end/core/sdk/DOMModel.ts +7 -5
  15. package/front_end/core/sdk/EventBreakpointsModel.ts +9 -5
  16. package/front_end/core/sdk/IsolateManager.ts +6 -6
  17. package/front_end/core/sdk/ResourceTreeModel.ts +5 -3
  18. package/front_end/core/sdk/SourceMapCache.ts +2 -4
  19. package/front_end/core/sdk/SourceMapManager.ts +8 -7
  20. package/front_end/core/sdk/TargetManager.ts +17 -0
  21. package/front_end/entrypoints/devtools_app/devtools_app.ts +0 -1
  22. package/front_end/entrypoints/main/MainImpl.ts +12 -36
  23. package/front_end/entrypoints/main/SimpleApp.ts +0 -13
  24. package/front_end/entrypoints/main/main-meta.ts +1 -1
  25. package/front_end/foundation/Universe.ts +110 -3
  26. package/front_end/generated/InspectorBackendCommands.ts +5 -1
  27. package/front_end/generated/SupportedCSSProperties.js +2 -6
  28. package/front_end/generated/protocol-mapping.d.ts +8 -0
  29. package/front_end/generated/protocol-proxy-api.d.ts +15 -0
  30. package/front_end/generated/protocol.ts +36 -1
  31. package/front_end/models/ai_assistance/AiConversation.ts +0 -6
  32. package/front_end/models/ai_assistance/agents/NetworkAgent.snapshot.txt +1 -1
  33. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +2 -156
  34. package/front_end/models/ai_assistance/agents/StylingAgent.snapshot.txt +0 -24
  35. package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -358
  36. package/front_end/models/ai_assistance/ai_assistance.ts +0 -6
  37. package/front_end/models/ai_assistance/contexts/RequestContext.snapshot.txt +0 -1
  38. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +0 -2
  39. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +1 -14
  40. package/front_end/models/autofill_manager/AutofillManager.ts +1 -2
  41. package/front_end/models/crux-manager/CrUXManager.ts +16 -11
  42. package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
  43. package/front_end/models/persistence/AutomaticFileSystemManager.ts +14 -13
  44. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +12 -9
  45. package/front_end/models/persistence/IsolatedFileSystemManager.ts +18 -9
  46. package/front_end/models/project_settings/ProjectSettingsModel.ts +12 -11
  47. package/front_end/models/trace/handlers/ScreenshotsHandler.ts +14 -59
  48. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +3 -29
  49. package/front_end/panels/application/DeviceBoundSessionsView.ts +15 -3
  50. package/front_end/panels/application/FrameDetailsView.ts +2 -1
  51. package/front_end/panels/application/ServiceWorkersView.ts +193 -161
  52. package/front_end/panels/application/serviceWorkersView.css +8 -0
  53. package/front_end/panels/common/CPUThrottlingOption.ts +142 -0
  54. package/front_end/panels/common/ThrottlingUtils.ts +9 -4
  55. package/front_end/panels/common/common.ts +1 -1
  56. package/front_end/panels/console/ConsoleViewMessage.ts +45 -0
  57. package/front_end/panels/elements/ElementsPanel.ts +35 -102
  58. package/front_end/panels/elements/ElementsTreeOutline.ts +0 -4
  59. package/front_end/panels/elements/elements-meta.ts +3 -2
  60. package/front_end/panels/emulation/DeviceModeToolbar.ts +46 -45
  61. package/front_end/panels/mobile_throttling/CalibrationController.ts +6 -5
  62. package/front_end/panels/mobile_throttling/MobileThrottlingSelector.ts +1 -1
  63. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +40 -13
  64. package/front_end/panels/mobile_throttling/ThrottlingPresets.ts +13 -17
  65. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +15 -13
  66. package/front_end/panels/network/NetworkLogView.ts +0 -9
  67. package/front_end/panels/network/NetworkPanel.ts +1 -63
  68. package/front_end/panels/network/RequestInitiatorView.ts +29 -4
  69. package/front_end/panels/network/components/HeaderSectionRow.css +9 -7
  70. package/front_end/panels/network/components/HeaderSectionRow.ts +20 -1
  71. package/front_end/panels/network/components/RequestHeaderSection.css +5 -3
  72. package/front_end/panels/network/components/RequestHeaderSection.ts +1 -2
  73. package/front_end/panels/network/components/RequestHeadersView.css +1 -1
  74. package/front_end/panels/security/SecurityPanel.ts +36 -23
  75. package/front_end/panels/settings/SettingsScreen.ts +18 -103
  76. package/front_end/panels/settings/settings-meta.ts +0 -24
  77. package/front_end/panels/timeline/TimelineController.ts +3 -2
  78. package/front_end/panels/timeline/TimelinePanel.ts +20 -3
  79. package/front_end/panels/timeline/components/CPUThrottlingSelector.ts +15 -14
  80. package/front_end/panels/timeline/timelineFlamechartPopover.css +2 -0
  81. package/front_end/panels/utils/utils.ts +25 -24
  82. package/front_end/third_party/chromium/README.chromium +1 -1
  83. package/front_end/third_party/puppeteer/README.chromium +2 -2
  84. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +34 -55
  85. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +96 -83
  86. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts +10 -1
  87. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.d.ts.map +1 -1
  88. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Browser.js.map +1 -1
  89. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.d.ts.map +1 -1
  90. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js +1 -1
  91. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/BrowserContext.js.map +1 -1
  92. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/CDPSession.d.ts.map +1 -1
  93. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/CDPSession.js.map +1 -1
  94. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.d.ts +3 -2
  95. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.d.ts.map +1 -1
  96. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/HTTPResponse.js.map +1 -1
  97. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.d.ts.map +1 -1
  98. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Realm.js.map +1 -1
  99. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Target.d.ts +1 -1
  100. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/Target.js +1 -1
  101. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.d.ts.map +1 -1
  102. package/front_end/third_party/puppeteer/package/lib/puppeteer/api/locators/locators.js.map +1 -1
  103. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.d.ts.map +1 -1
  104. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js +2 -1
  105. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/HTTPResponse.js.map +1 -1
  106. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Realm.d.ts.map +1 -1
  107. package/front_end/third_party/puppeteer/package/lib/puppeteer/bidi/core/Realm.js.map +1 -1
  108. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts +2 -2
  109. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.d.ts.map +1 -1
  110. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js +5 -2
  111. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Browser.js.map +1 -1
  112. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js +1 -1
  113. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Frame.js.map +1 -1
  114. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.d.ts.map +1 -1
  115. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js +23 -13
  116. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/FrameManager.js.map +1 -1
  117. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.d.ts.map +1 -1
  118. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.js +4 -1
  119. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/HTTPResponse.js.map +1 -1
  120. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Input.js +1 -1
  121. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/LifecycleWatcher.d.ts.map +1 -1
  122. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/LifecycleWatcher.js.map +1 -1
  123. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.d.ts.map +1 -1
  124. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/Target.js.map +1 -1
  125. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts +3 -41
  126. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.d.ts.map +1 -1
  127. package/front_end/third_party/puppeteer/package/lib/puppeteer/cdp/WebMCP.js.map +1 -1
  128. package/front_end/third_party/puppeteer/package/lib/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  129. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  130. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js +4 -2
  131. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/BrowserLauncher.js.map +1 -1
  132. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/LaunchOptions.d.ts +5 -0
  133. package/front_end/third_party/puppeteer/package/lib/puppeteer/node/LaunchOptions.d.ts.map +1 -1
  134. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.d.ts +1 -1
  135. package/front_end/third_party/puppeteer/package/lib/puppeteer/revisions.js +1 -1
  136. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.d.ts +1 -1
  137. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.d.ts.map +1 -1
  138. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.js +5 -5
  139. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/httpUtils.js.map +1 -1
  140. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.d.ts +1 -1
  141. package/front_end/third_party/puppeteer/package/lib/puppeteer/util/version.js +1 -1
  142. package/front_end/third_party/puppeteer/package/lib/types.d.ts +34 -55
  143. package/front_end/third_party/puppeteer/package/package.json +4 -4
  144. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +13 -1
  145. package/front_end/third_party/puppeteer/package/src/api/BrowserContext.ts +2 -3
  146. package/front_end/third_party/puppeteer/package/src/api/CDPSession.ts +3 -1
  147. package/front_end/third_party/puppeteer/package/src/api/HTTPResponse.ts +3 -2
  148. package/front_end/third_party/puppeteer/package/src/api/Realm.ts +1 -2
  149. package/front_end/third_party/puppeteer/package/src/api/Target.ts +1 -1
  150. package/front_end/third_party/puppeteer/package/src/api/locators/locators.ts +1 -2
  151. package/front_end/third_party/puppeteer/package/src/bidi/HTTPResponse.ts +3 -1
  152. package/front_end/third_party/puppeteer/package/src/bidi/core/Realm.ts +1 -3
  153. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +13 -3
  154. package/front_end/third_party/puppeteer/package/src/cdp/Frame.ts +1 -1
  155. package/front_end/third_party/puppeteer/package/src/cdp/FrameManager.ts +24 -13
  156. package/front_end/third_party/puppeteer/package/src/cdp/HTTPResponse.ts +4 -1
  157. package/front_end/third_party/puppeteer/package/src/cdp/Input.ts +1 -1
  158. package/front_end/third_party/puppeteer/package/src/cdp/LifecycleWatcher.ts +1 -4
  159. package/front_end/third_party/puppeteer/package/src/cdp/Target.ts +2 -4
  160. package/front_end/third_party/puppeteer/package/src/cdp/WebMCP.ts +7 -76
  161. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +1 -4
  162. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +4 -1
  163. package/front_end/third_party/puppeteer/package/src/node/LaunchOptions.ts +5 -0
  164. package/front_end/third_party/puppeteer/package/src/revisions.ts +1 -1
  165. package/front_end/third_party/puppeteer/package/src/util/httpUtils.ts +5 -5
  166. package/front_end/third_party/puppeteer/package/src/util/version.ts +1 -1
  167. package/front_end/third_party/puppeteer/third_party/parsel/README.chromium +1 -1
  168. package/front_end/ui/components/dialogs/Dialog.ts +3 -0
  169. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +0 -7
  170. package/front_end/ui/helpers/OpenInNewTab.ts +15 -7
  171. package/front_end/ui/legacy/TabbedPane.ts +1 -108
  172. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +9 -0
  173. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +172 -123
  174. package/front_end/ui/legacy/components/data_grid/DataGridExporter.ts +89 -0
  175. package/front_end/ui/legacy/components/data_grid/dataGrid.css +10 -0
  176. package/front_end/ui/legacy/components/data_grid/data_grid.ts +3 -1
  177. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +89 -40
  178. package/front_end/ui/visual_logging/KnownContextValues.ts +2 -0
  179. package/package.json +1 -1
  180. package/front_end/Images/navigationControls.png +0 -0
  181. package/front_end/Images/navigationControls_2x.png +0 -0
  182. package/front_end/Images/popoverArrows.png +0 -0
  183. package/front_end/entrypoints/greendev_floaty/FloatyEntrypoint.ts +0 -746
  184. package/front_end/entrypoints/greendev_floaty/floaty.css +0 -301
  185. package/front_end/entrypoints/greendev_floaty/floaty.html +0 -38
  186. package/front_end/entrypoints/greendev_floaty/greendev_floaty.ts +0 -415
  187. package/front_end/models/ai_assistance/agents/GreenDevAgent.ts +0 -834
  188. package/front_end/models/ai_assistance/agents/GreenDevAgentAntigravityCliSocketClient.ts +0 -53
  189. package/front_end/models/ai_assistance/agents/GreenDevAgentGeminiCliSocketClient.ts +0 -117
  190. package/front_end/models/annotations/AnnotationRepository.ts +0 -238
  191. package/front_end/models/annotations/AnnotationType.ts +0 -10
  192. package/front_end/models/annotations/README.md +0 -7
  193. package/front_end/models/annotations/annotations.ts +0 -6
  194. package/front_end/models/greendev/Prototypes.ts +0 -68
  195. package/front_end/models/greendev/README.md +0 -5
  196. package/front_end/models/greendev/greendev.ts +0 -5
  197. package/front_end/panels/common/Annotation.ts +0 -184
  198. package/front_end/panels/common/AnnotationManager.ts +0 -208
  199. package/front_end/panels/common/annotation.css +0 -40
  200. package/front_end/panels/greendev/GreenDevPanel.css +0 -282
  201. package/front_end/panels/greendev/GreenDevPanel.ts +0 -364
  202. package/front_end/panels/greendev/GreenDevShared.ts +0 -13
  203. package/front_end/panels/greendev/greendev-meta.ts +0 -52
  204. package/front_end/panels/greendev/greendev.ts +0 -9
@@ -1,746 +0,0 @@
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
- /* eslint-disable @devtools/no-imperative-dom-api */
5
-
6
- import '../../core/sdk/sdk-meta.js';
7
- import '../../models/workspace/workspace-meta.js';
8
- import '../../models/logs/logs-meta.js';
9
- import '../../panels/sensors/sensors-meta.js';
10
- import '../../panels/sources/sources-meta.js';
11
- import '../../entrypoints/inspector_main/inspector_main-meta.js';
12
- import '../../entrypoints/main/main-meta.js';
13
- import '../../ui/legacy/components/source_frame/source_frame-meta.js';
14
- import '../../ui/components/markdown_view/markdown_view.js';
15
-
16
- import * as Common from '../../core/common/common.js';
17
- import * as Host from '../../core/host/host.js';
18
- import * as i18n from '../../core/i18n/i18n.js';
19
- import type * as Platform from '../../core/platform/platform.js';
20
- import type * as ExperimentNames from '../../core/root/ExperimentNames.js';
21
- import * as Root from '../../core/root/root.js';
22
- import * as SDK from '../../core/sdk/sdk.js';
23
- import * as Foundation from '../../foundation/foundation.js';
24
- import type * as Protocol from '../../generated/protocol.js';
25
- import * as AiAssistance from '../../models/ai_assistance/ai_assistance.js';
26
- import * as Greendev from '../../models/greendev/greendev.js';
27
- import type {SyncMessage} from '../../panels/greendev/GreenDevShared.js';
28
- import * as Marked from '../../third_party/marked/marked.js';
29
- import * as MarkdownView from '../../ui/components/markdown_view/markdown_view.js';
30
- import * as UI from '../../ui/legacy/legacy.js';
31
- import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
32
-
33
- const {AidaClient} = Host.AidaClient;
34
- const {ResponseType} = AiAssistance.AiAgent;
35
-
36
- let pendingActivationSessionId: number|null = null;
37
-
38
- class GreenDevFloaty {
39
- #chatContainer!: HTMLDivElement;
40
- #textField!: HTMLInputElement;
41
- #playButton!: HTMLButtonElement;
42
- #node?: SDK.DOMModel.DOMNode;
43
- #agent?: AiAssistance.GreenDevAgent.GreenDevAgent|AiAssistance.StylingAgent.StylingAgent;
44
- #nodeContext?: AiAssistance.DOMNodeContext.DOMNodeContext;
45
- #backendNodeId?: Protocol.DOM.BackendNodeId;
46
- #syncChannel: BroadcastChannel;
47
- #isFloatyWindow: boolean;
48
- #socketClient:
49
- AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient|
50
- AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient;
51
-
52
- constructor(document: Document) {
53
- const params = new URLSearchParams(window.location.hash.substring(1));
54
- this.#backendNodeId = parseInt(params.get('backendNodeId') || '0', 10) as Protocol.DOM.BackendNodeId;
55
- this.#isFloatyWindow = !!this.#backendNodeId;
56
-
57
- this.#syncChannel = new BroadcastChannel('green-dev-sync');
58
- this.#syncChannel.onmessage = event => {
59
- this.#onSyncMessage(event.data);
60
- };
61
-
62
- this.#initFloatyMode(document);
63
- if (Greendev.Prototypes.instance().isEnabled('beyondStylingAntigravity')) {
64
- this.#socketClient =
65
- new AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient();
66
- } else {
67
- this.#socketClient = new AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient();
68
- }
69
- }
70
-
71
- #initFloatyMode(doc: Document): void {
72
- this.#chatContainer = doc.getElementById('chat-container') as HTMLDivElement;
73
- this.#textField = doc.querySelector('.green-dev-floaty-dialog-text-field') as HTMLInputElement;
74
- this.#playButton = doc.querySelector('.green-dev-floaty-dialog-play-button') as HTMLButtonElement;
75
-
76
- this.#playButton?.addEventListener('click', () => {
77
- if (this.#node) {
78
- void this.runConversation();
79
- }
80
- });
81
-
82
- const contextText = doc.querySelector('.green-dev-floaty-dialog-context-text') as HTMLSpanElement;
83
- if (contextText) {
84
- contextText.style.cursor = 'pointer';
85
- contextText.title = 'Click to show in DevTools Panel';
86
- contextText.addEventListener('click', () => {
87
- this.#broadcastFullState();
88
- });
89
- }
90
-
91
- const learnMoreLink = doc.querySelector('.learn-more-link');
92
- if (learnMoreLink) {
93
- learnMoreLink.addEventListener('click', event => {
94
- event.preventDefault();
95
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
96
- 'https://developer.chrome.com/docs/devtools/ai-assistance' as Platform.DevToolsPath.UrlString);
97
- });
98
- }
99
-
100
- const nodeDescriptionElement = doc.querySelector('.green-dev-floaty-dialog-node-description') as HTMLDivElement;
101
- nodeDescriptionElement?.addEventListener('mousemove', () => {
102
- if (this.#node) {
103
- this.#node.highlight();
104
- }
105
- });
106
- nodeDescriptionElement?.addEventListener('mouseleave', () => {
107
- if (this.#node && this.#backendNodeId) {
108
- const msg = JSON.stringify({
109
- id: 9999,
110
- method: 'Overlay.setShowInspectedElementAnchor',
111
- params: {inspectedElementAnchorConfig: {backendNodeId: this.#backendNodeId}},
112
- });
113
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.sendMessageToBackend(msg);
114
- }
115
- });
116
-
117
- this.#textField?.addEventListener('keydown', event => {
118
- if (event.key === 'Enter' && this.#node) {
119
- void this.runConversation();
120
- }
121
- });
122
-
123
- this.#textField?.focus();
124
- }
125
-
126
- #broadcastFullState(): void {
127
- const state = {
128
- type: 'full-state',
129
- messages: this.#getMessages(),
130
- sessionId: this.#backendNodeId,
131
- nodeDescription: document.querySelector('.green-dev-floaty-dialog-node-description')?.textContent,
132
- };
133
- this.#syncChannel.postMessage(state);
134
- }
135
-
136
- #onSyncMessage(data: SyncMessage): void {
137
- if (data.type === 'main-window-alive') {
138
- if (pendingActivationSessionId) {
139
- const syncChannel = new BroadcastChannel('green-dev-sync');
140
- syncChannel.postMessage({type: 'activate-panel', sessionId: pendingActivationSessionId});
141
- syncChannel.close();
142
- }
143
- } else if (data.type === 'request-session-state') {
144
- this.#broadcastFullState();
145
-
146
- if (pendingActivationSessionId) {
147
- this.#syncChannel.postMessage({type: 'select-tab', sessionId: pendingActivationSessionId});
148
- pendingActivationSessionId = null;
149
- }
150
- } else if (data.type === 'user-input' && data.sessionId === this.#backendNodeId) {
151
- if (this.#textField) {
152
- this.#textField.value = data.text ?? '';
153
- void this.runConversation();
154
- }
155
- } else if (data.type === 'restore-floaty' && data.sessionId === this.#backendNodeId) {
156
- // The main DevTools window will bring the floaty to the front,
157
- // so the floaty window itself doesn't need to do it.
158
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.bringToFront();
159
- }
160
- }
161
-
162
- static instance(opts: {forceNew: boolean|null, document: Document} = {forceNew: null, document}): GreenDevFloaty {
163
- const {forceNew, document} = opts;
164
- if (!greenDevFloatyInstance || forceNew) {
165
- greenDevFloatyInstance = new GreenDevFloaty(document);
166
- }
167
- return greenDevFloatyInstance;
168
- }
169
-
170
- handlePanelRequest = (event: Common.EventTarget.EventTargetEvent<number>): void => {
171
- pendingActivationSessionId = event.data;
172
- this.#sendActivatePanelMessage(pendingActivationSessionId, 0);
173
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(
174
- 'magic:open-devtools' as Platform.DevToolsPath.UrlString);
175
- };
176
-
177
- readonly #maxActivationRetries = 10;
178
- readonly #activationRetryDelayMs = 200;
179
-
180
- #sendActivatePanelMessage(sessionId: number, retryCount: number): void {
181
- if (retryCount >= this.#maxActivationRetries) {
182
- return;
183
- }
184
-
185
- const syncChannel = new BroadcastChannel('green-dev-sync');
186
- syncChannel.postMessage({type: 'activate-panel', sessionId});
187
- syncChannel.close();
188
-
189
- // To ensure the activate-panel is always received, let's add a small delay and retry.
190
- // This is a pragmatic fix for the prototype given the existing async message flow.
191
- setTimeout(() => {
192
- // Check if pendingActivationSessionId is still set. If it is, it means
193
- // the panel hasn't been activated yet (or the confirmation message
194
- // hasn't arrived), so we retry.
195
- if (pendingActivationSessionId === sessionId) {
196
- this.#sendActivatePanelMessage(sessionId, retryCount + 1);
197
- }
198
- }, this.#activationRetryDelayMs);
199
- }
200
-
201
- handleRestoreEvent(event: Common.EventTarget.EventTargetEvent<number>): void {
202
- const sessionId = event.data;
203
- // Only the main DevTools window (which is NOT a floaty window) should broadcast the restore request.
204
- if (!this.#isFloatyWindow) {
205
- this.#syncChannel.postMessage({type: 'restore-floaty', sessionId});
206
- } else if (this.#backendNodeId === sessionId) {
207
- // If a floaty window receives a restore request for its own session,
208
- // it should bring itself to the front.
209
- console.error('[GreenDev] Calling bringToFront for session ' + sessionId);
210
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.bringToFront();
211
- }
212
- }
213
-
214
- setNode(node: SDK.DOMModel.DOMNode): void {
215
- if (this.#node) {
216
- this.#node.domModel().overlayModel().removeEventListener(
217
- SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, this.handlePanelRequest);
218
- }
219
- if (this.#node === node) {
220
- return;
221
- }
222
- this.#node = node;
223
- this.#node.domModel().overlayModel().addEventListener(
224
- SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, this.handlePanelRequest);
225
- this.#backendNodeId = node.backendNodeId();
226
-
227
- void node.domModel().overlayModel().clearHighlight();
228
- this.#textField?.focus();
229
- this.#agent = undefined;
230
- this.#nodeContext = undefined;
231
-
232
- const nodeDescriptionElement = document.querySelector('.green-dev-floaty-dialog-node-description');
233
- let description = '';
234
- if (nodeDescriptionElement) {
235
- const id = node.getAttribute('id');
236
- if (id) {
237
- description = `#${id}`;
238
- } else {
239
- const classes = node.classNames().join('.');
240
- description = node.nodeName().toLowerCase() + (classes ? `.${classes}` : '');
241
- }
242
- nodeDescriptionElement.textContent = description;
243
- }
244
-
245
- this.#syncChannel.postMessage({type: 'node-changed', sessionId: this.#backendNodeId, nodeDescription: description});
246
-
247
- if (this.#backendNodeId) {
248
- const msg = JSON.stringify({
249
- id: 9999,
250
- method: 'Overlay.setShowInspectedElementAnchor',
251
- params: {inspectedElementAnchorConfig: {backendNodeId: this.#backendNodeId}},
252
- });
253
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.sendMessageToBackend(msg);
254
- }
255
- }
256
-
257
- #getMessages(): Array<{text: string, isUser: boolean}> {
258
- const messages = [];
259
- if (this.#chatContainer) {
260
- const messageElements = this.#chatContainer.querySelectorAll('.message');
261
- for (const el of messageElements) {
262
- const isUser = el.classList.contains('user-message');
263
- const content = el.querySelector('.message-content')?.textContent || '';
264
- messages.push({text: content, isUser});
265
- }
266
- }
267
- return messages;
268
- }
269
-
270
- #formatError(errorMessage: string): string {
271
- return `Error: '${errorMessage}' - Protip: to use AI features you need to be signed in.`;
272
- }
273
-
274
- runConversation = async(): Promise<void> => {
275
- if (!this.#textField || !this.#node) {
276
- return;
277
- }
278
- const query = this.#textField.value || this.#textField.placeholder;
279
- this.#textField.value = '';
280
-
281
- const useAntigravity = Greendev.Prototypes.instance().isEnabled('beyondStylingAntigravity');
282
- const useGemini = Greendev.Prototypes.instance().isEnabled('beyondStylingGemini');
283
- const useGreenDevAgent = useAntigravity || useGemini;
284
- const isAntigravity = useAntigravity;
285
-
286
- if (!this.#agent) {
287
- const aidaClient = new AidaClient();
288
- if (useGreenDevAgent) {
289
- if (isAntigravity) {
290
- this.#socketClient =
291
- new AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient();
292
- } else {
293
- this.#socketClient = new AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient();
294
- }
295
-
296
- this.#agent = new AiAssistance.GreenDevAgent.GreenDevAgent({aidaClient});
297
- this.#agent.addEventListener(
298
- AiAssistance.GreenDevAgent.Events.CLI_PROMPT_REQUESTED,
299
- async (
300
- event: Common.EventTarget.EventTargetEvent<
301
- AiAssistance.GreenDevAgent.EventTypes[AiAssistance.GreenDevAgent.Events.CLI_PROMPT_REQUESTED]>) => {
302
- const {prompt} = event.data;
303
- const remoteName = isAntigravity ? 'Antigravity' : 'Gemini';
304
- const aiContent =
305
- this.#addMessageInternal(`Fix has been submitted to ${remoteName} CLI, please wait...`, false);
306
-
307
- if (isAntigravity) {
308
- let fullResponse = '';
309
- void (
310
- this.#socketClient as
311
- AiAssistance.GreenDevAgentAntigravityCliSocketClient.GreenDevAgentAntigravityCliSocketClient)
312
- .sendPrompt(prompt, (chunk: string) => {
313
- fullResponse += chunk;
314
- const responseText = `Antigravity CLI responds: ${fullResponse}`;
315
- const markdown = new MarkdownView.MarkdownView.MarkdownView();
316
- markdown.data = {
317
- tokens: Marked.Marked.lexer(responseText),
318
- };
319
-
320
- const style = document.createElement('style');
321
- style.textContent =
322
- '.message { font-size: 1.0rem; } .message code { font-size: 1.0rem; font-family: \'Roboto Mono\', ' +
323
- 'monospace; color: green; } .message ul { margin-left: 20px; }';
324
- markdown.shadowRoot?.appendChild(style);
325
-
326
- this.#updateAiMessage(aiContent, markdown, responseText);
327
- });
328
- } else {
329
- const response =
330
- await (this.#socketClient as
331
- AiAssistance.GreenDevAgentGeminiCliSocketClient.GreenDevAgentGeminiCliSocketClient)
332
- .sendPrompt(prompt);
333
-
334
- const responseText = `Gemini CLI responds: ${response}`;
335
- const markdown = new MarkdownView.MarkdownView.MarkdownView();
336
- markdown.data = {
337
- tokens: Marked.Marked.lexer(responseText),
338
- };
339
- this.#updateAiMessage(aiContent, markdown, responseText);
340
- }
341
- });
342
- } else {
343
- this.#agent = new AiAssistance.StylingAgent.StylingAgent({aidaClient});
344
- this.#nodeContext = new AiAssistance.DOMNodeContext.DOMNodeContext(this.#node);
345
- }
346
- }
347
-
348
- this.#addMessageInternal(query, true);
349
- const aiContent = this.#addMessageInternal('Thinking...', false);
350
-
351
- let agentFinished = false;
352
- let steps = 0;
353
- try {
354
- let results;
355
- if (useGreenDevAgent && this.#agent instanceof AiAssistance.GreenDevAgent.GreenDevAgent) {
356
- const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();
357
- if (!target) {
358
- return;
359
- }
360
-
361
- // --- Get the Accessibility Tree ---
362
- const accessibilityModel = target.model(SDK.AccessibilityModel.AccessibilityModel);
363
- let axTree = '';
364
- if (accessibilityModel) {
365
- await accessibilityModel.resumeModel();
366
- const axResponse = await accessibilityModel.agent.invoke_getFullAXTree({});
367
- if (!axResponse.getError()) {
368
- axTree = JSON.stringify(axResponse.nodes);
369
- } else {
370
- console.error('Failed to capture Accessibility Tree:', axResponse.getError());
371
- }
372
- }
373
-
374
- // --- Get the most recent network requests ---
375
- const allNetworkRequests = await AiAssistance.GreenDevAgent.GreenDevAgent.getNetworkContextData(target);
376
- const networkResourcesMax = 50;
377
- const startNetworkIndex = Math.max(0, allNetworkRequests.length - networkResourcesMax);
378
- const lastNetworkRequests = allNetworkRequests.slice(startNetworkIndex);
379
- let formattedNetworkContext = lastNetworkRequests.map(req => req.string).join('\n');
380
-
381
- if (!formattedNetworkContext) {
382
- formattedNetworkContext = 'No network requests found.';
383
- } else {
384
- const footer = allNetworkRequests.length > lastNetworkRequests.length ?
385
- `${
386
- allNetworkRequests.length -
387
- lastNetworkRequests.length} additional requests are available (network requests shown are capped at ${
388
- networkResourcesMax} requests).` :
389
- 'No further network requests are available.';
390
-
391
- formattedNetworkContext = `Showing network requests with indices ${startNetworkIndex}-${
392
- startNetworkIndex + lastNetworkRequests.length - 1}:\n\n${formattedNetworkContext}\n\n${footer}`;
393
- }
394
-
395
- // --- Get the most recent console messages ---
396
- const consoleModel = target.model(SDK.ConsoleModel.ConsoleModel);
397
- const allConsoleMessages = consoleModel ? consoleModel.messages() : [];
398
- const consoleMsgLimit = 50;
399
- const startIndex = Math.max(0, allConsoleMessages.length - consoleMsgLimit);
400
- const lastConsoleMessages = allConsoleMessages.slice(startIndex);
401
- let formattedConsoleMessages =
402
- lastConsoleMessages
403
- .map(
404
- (entry: SDK.ConsoleModel.ConsoleMessage, i: number) =>
405
- AiAssistance.GreenDevAgent.GreenDevAgent.formatConsoleMessage(entry, startIndex + i))
406
- .join('\n');
407
- formattedConsoleMessages = formattedConsoleMessages.trimEnd();
408
-
409
- if (!formattedConsoleMessages) {
410
- formattedConsoleMessages = 'No console messages found.';
411
- } else {
412
- const footer = allConsoleMessages.length > lastConsoleMessages.length ?
413
- `${
414
- allConsoleMessages.length -
415
- lastConsoleMessages.length} additional messages are available (errors shown are capped at ${
416
- consoleMsgLimit} most recent).` :
417
- 'No further console messages are available.';
418
-
419
- formattedConsoleMessages = `Showing console messages with indices ${startIndex}-${
420
- startIndex + lastConsoleMessages.length - 1}:\n\n${formattedConsoleMessages}\n\n${footer}`;
421
- }
422
-
423
- const mainUrl = target.inspectedURL();
424
-
425
- // --- Get the React Props for the selected node (if available) ---
426
- const reactComponentProps = this.#backendNodeId ?
427
- await this.#agent.getReactComponentProps(this.#backendNodeId, false) :
428
- 'Could not get the backendNodeId for the selected element.';
429
-
430
- // --- Get some context information about the selected node ---
431
- const domNodeContext = new AiAssistance.DOMNodeContext.DOMNodeContext(this.#node);
432
- const elementContext = await domNodeContext.describe();
433
-
434
- // Now construct the full context.
435
- const context = `# Page URL
436
-
437
- ${mainUrl}
438
-
439
- # User-selected node
440
-
441
- ${elementContext}
442
-
443
- # React component props:
444
-
445
- ${reactComponentProps}
446
-
447
- # Recent network requests
448
-
449
- ${formattedNetworkContext}
450
-
451
- # Recent console messages
452
-
453
- ${formattedConsoleMessages}
454
-
455
- # Accessibility tree
456
-
457
- ${axTree}`;
458
-
459
- const nodeContext = new AiAssistance.GreenDevAgent.GreenDevContext(context);
460
- results = this.#agent.run(query, {selected: nodeContext});
461
- } else if (this.#agent instanceof AiAssistance.StylingAgent.StylingAgent) {
462
- if (!this.#nodeContext) {
463
- throw new Error('Node context not found.');
464
- }
465
- results = this.#agent.run(query, {selected: this.#nodeContext});
466
- } else {
467
- throw new Error('Agent not initialized correctly');
468
- }
469
-
470
- for await (const result of results) {
471
- switch (result.type) {
472
- case ResponseType.QUERYING:
473
- steps++;
474
- break;
475
- case ResponseType.ANSWER: {
476
- aiContent.textContent = '';
477
- // Add a space in the protocol, which prevents links from being linkified in
478
- // the markup. Why? Because there's an exception thrown if the links don't match the
479
- // allowlist in getMarkdownLink(). Need to figure out later.
480
- let sanitizedText = result.text.replace(/https:\/\//g, 'https: //');
481
- sanitizedText = sanitizedText.replace(/http:\/\//g, 'http: //');
482
- const markdown = new MarkdownView.MarkdownView.MarkdownView();
483
- markdown.data = {
484
- tokens: Marked.Marked.lexer(sanitizedText),
485
- };
486
- this.#updateAiMessage(aiContent, markdown, result.text);
487
-
488
- void new Promise(resolve => setTimeout(resolve, 0)).then(() => {
489
- const style = document.createElement('style');
490
- style.textContent =
491
- '.message { font-size: 1.0rem; } .message code { font-size: 1.0rem; font-family: \'Roboto Mono\', ' +
492
- 'monospace; color: green; } .message ul { margin-left: 20px; }';
493
- markdown.shadowRoot?.appendChild(style);
494
-
495
- const codeBlocks = markdown.shadowRoot?.querySelectorAll('devtools-code-block');
496
- if (codeBlocks) {
497
- for (const codeBlock of codeBlocks) {
498
- const style = document.createElement('style');
499
- style.textContent = `
500
- .heading { color: black; background-color: #f2f6ff; font-family: 'Roboto Mono', monospace; padding: 2px 4px;
501
- border-top-left-radius: 8px; border-top-right-radius: 8px; margin-bottom: 3px; }
502
- .code { background-color: #f8f9fa; font-family: 'Roboto Mono', monospace; padding: 5px;
503
- border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; }
504
- .editor-wrapper { margin-left: 20px; }
505
- `;
506
- codeBlock.shadowRoot?.appendChild(style);
507
- }
508
- }
509
- });
510
- agentFinished = true;
511
- break;
512
- }
513
- case ResponseType.ERROR:
514
- this.#updateAiMessage(
515
- aiContent, document.createTextNode(this.#formatError(result.error)), this.#formatError(result.error));
516
- agentFinished = true;
517
- break;
518
- case ResponseType.SIDE_EFFECT:
519
- result.confirm(true);
520
- break;
521
- default:
522
- break;
523
- }
524
- if (this.#chatContainer) {
525
- this.#chatContainer.scrollTop = this.#chatContainer.scrollHeight;
526
- }
527
- }
528
- } catch (e) {
529
- aiContent.textContent = `Exception: ${e instanceof Error ? e.message : String(e)}`;
530
- agentFinished = true;
531
- }
532
-
533
- const MAX_AGENT_STEPS = AiAssistance.AiAgent.MAX_STEPS;
534
- if (!agentFinished && steps >= MAX_AGENT_STEPS) {
535
- aiContent.textContent = `The agent has reached its internal limit of ${MAX_AGENT_STEPS} steps per turn before
536
- finding an answer. Please try again with a more specific query or say 'continue' (to get ${MAX_AGENT_STEPS}
537
- more steps and continue trying).`;
538
- }
539
- };
540
-
541
- #addMessageInternal(text: string, isUser: boolean): HTMLDivElement {
542
- const messageElement = document.createElement('div');
543
- messageElement.className = `message ${isUser ? 'user-message' : 'ai-message'}`;
544
-
545
- const content = document.createElement('div');
546
- content.className = 'message-content';
547
- content.textContent = text;
548
- messageElement.appendChild(content);
549
-
550
- if (this.#chatContainer) {
551
- this.#chatContainer.appendChild(messageElement);
552
- this.#chatContainer.scrollTop = this.#chatContainer.scrollHeight;
553
- }
554
-
555
- this.#syncChannel.postMessage({
556
- type: 'new-message',
557
- text,
558
- isUser,
559
- sessionId: this.#backendNodeId,
560
- nodeDescription: document.querySelector('.green-dev-floaty-dialog-node-description')?.textContent,
561
- });
562
-
563
- return content;
564
- }
565
-
566
- #updateAiMessage(aiContentElement: HTMLDivElement, newContent: Node, newText: string): void {
567
- aiContentElement.textContent = '';
568
- aiContentElement.append(newContent);
569
- this.#syncChannel.postMessage({type: 'update-last-message', text: newText, sessionId: this.#backendNodeId});
570
- }
571
- }
572
-
573
- let greenDevFloatyInstance: GreenDevFloaty;
574
-
575
- function safeRegisterExperiment(name: string, title: string): void {
576
- try {
577
- Root.Runtime.experiments.register(name as ExperimentNames.ExperimentName, title);
578
- } catch (e) {
579
- console.error('Unable to register experiment ', name, title, e);
580
- }
581
- }
582
-
583
- async function init(): Promise<void> {
584
- try {
585
- Root.Runtime.Runtime.setPlatform(Host.Platform.platform());
586
- const [config, prefs] = await Promise.all([
587
- new Promise<Root.Runtime.HostConfig>(
588
- resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getHostConfig(resolve)),
589
- new Promise<Record<string, string>>(
590
- resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getPreferences(resolve)),
591
- ]);
592
- Object.assign(Root.Runtime.hostConfig, config);
593
-
594
- safeRegisterExperiment(
595
- Root.ExperimentNames.ExperimentName.INSTRUMENTATION_BREAKPOINTS, 'Enable instrumentation breakpoints');
596
- safeRegisterExperiment(Root.ExperimentNames.ExperimentName.PROTOCOL_MONITOR, 'Protocol Monitor');
597
-
598
- const hostUnsyncedStorage: Common.Settings.SettingsBackingStore = {
599
- register: (name: string) =>
600
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.registerPreference(name, {synced: false}),
601
- set: Host.InspectorFrontendHost.InspectorFrontendHostInstance.setPreference,
602
- get: (name: string) =>
603
- new Promise(resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getPreference(name, resolve)),
604
- remove: Host.InspectorFrontendHost.InspectorFrontendHostInstance.removePreference,
605
- clear: Host.InspectorFrontendHost.InspectorFrontendHostInstance.clearPreferences,
606
- };
607
- const syncedStorage = new Common.Settings.SettingsStorage(prefs, hostUnsyncedStorage, '');
608
- const globalStorage = new Common.Settings.SettingsStorage(prefs, hostUnsyncedStorage, '');
609
- const localStorage = new Common.Settings.SettingsStorage(
610
- window.localStorage, {
611
- register(_setting: string): void{},
612
- async get(setting: string): Promise<string> {
613
- return window.localStorage.getItem(setting) as unknown as string;
614
- },
615
- set(setting: string, value: string): void {
616
- window.localStorage.setItem(setting, value);
617
- },
618
- remove(setting: string): void {
619
- window.localStorage.removeItem(setting);
620
- },
621
- clear: () => window.localStorage.clear(),
622
- },
623
- '');
624
-
625
- Common.Settings.Settings.instance({
626
- forceNew: true,
627
- syncedStorage,
628
- globalStorage,
629
- localStorage,
630
- settingRegistrations: Common.SettingRegistration.getRegisteredSettings(),
631
- });
632
-
633
- UI.UIUtils.initializeUIUtils(document);
634
- ThemeSupport.ThemeSupport.instance({
635
- forceNew: true,
636
- setting: Common.Settings.Settings.instance().moduleSetting('ui-theme'),
637
- });
638
- UI.ZoomManager.ZoomManager.instance(
639
- {forceNew: true, win: window, frontendHost: Host.InspectorFrontendHost.InspectorFrontendHostInstance});
640
-
641
- const settingLanguage = Common.Settings.Settings.instance().moduleSetting<string>('language').get();
642
- i18n.DevToolsLocale.DevToolsLocale.instance({
643
- create: true,
644
- data: {
645
- navigatorLanguage: navigator.language,
646
- settingLanguage,
647
- lookupClosestDevToolsLocale: i18n.i18n.lookupClosestSupportedDevToolsLocale,
648
- },
649
- });
650
-
651
- const universe = new Foundation.Universe.Universe({
652
- settingsCreationOptions: {
653
- syncedStorage,
654
- globalStorage,
655
- localStorage,
656
- settingRegistrations: Common.SettingRegistration.getRegisteredSettings(),
657
- }
658
- });
659
- Root.DevToolsContext.setGlobalInstance(universe.context as Root.DevToolsContext.WritableDevToolsContext);
660
-
661
- await i18n.i18n.fetchAndRegisterLocaleData('en-US');
662
- Host.InspectorFrontendHost.InspectorFrontendHostInstance.connectionReady();
663
-
664
- const hash = window.location.hash.substring(1);
665
- const params = new URLSearchParams(hash);
666
- const backendNodeId = parseInt(params.get('backendNodeId') || '0', 10);
667
-
668
- const floaty = GreenDevFloaty.instance({forceNew: null, document});
669
-
670
- if (backendNodeId) {
671
- await SDK.Connections.initMainConnection(async () => {
672
- const targetManager = SDK.TargetManager.TargetManager.instance();
673
- targetManager.createTarget('main', 'Main', SDK.Target.Type.FRAME, null);
674
- const mainTarget = await new Promise<SDK.Target.Target|null>(resolve => {
675
- const t = targetManager.primaryPageTarget();
676
- if (t) {
677
- resolve(t);
678
- return;
679
- }
680
- const observer = {
681
- targetAdded: (target: SDK.Target.Target) => {
682
- if (target === targetManager.primaryPageTarget()) {
683
- targetManager.unobserveTargets(observer);
684
- resolve(target);
685
- }
686
- },
687
- targetRemoved: () => {},
688
- };
689
- targetManager.observeTargets(observer);
690
- });
691
- if (!mainTarget) {
692
- return;
693
- }
694
- const domModel = mainTarget.model(SDK.DOMModel.DOMModel);
695
- if (!domModel) {
696
- return;
697
- }
698
-
699
- // Add listener for floaty restore events
700
- const overlayModel = mainTarget.model(SDK.OverlayModel.OverlayModel);
701
- if (overlayModel) {
702
- overlayModel.addEventListener(
703
- SDK.OverlayModel.Events.INSPECTED_ELEMENT_WINDOW_RESTORED, floaty.handleRestoreEvent, floaty);
704
- }
705
-
706
- const nodesMap =
707
- await domModel.pushNodesByBackendIdsToFrontend(new Set([backendNodeId as Protocol.DOM.BackendNodeId]));
708
- const node = nodesMap?.get(backendNodeId as Protocol.DOM.BackendNodeId) || null;
709
- if (node) {
710
- floaty.setNode(node);
711
- }
712
- }, () => {});
713
- } else {
714
- const targetManager = SDK.TargetManager.TargetManager.instance();
715
- const observer = {
716
- targetAdded: (target: SDK.Target.Target) => {
717
- if (target.type() === SDK.Target.Type.FRAME) {
718
- const overlayModel = target.model(SDK.OverlayModel.OverlayModel);
719
- if (overlayModel) {
720
- overlayModel.addEventListener(
721
- SDK.OverlayModel.Events.INSPECTED_ELEMENT_WINDOW_RESTORED, floaty.handleRestoreEvent, floaty);
722
- overlayModel.addEventListener(
723
- SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, floaty.handlePanelRequest);
724
- }
725
- }
726
- },
727
- targetRemoved: (target: SDK.Target.Target) => {
728
- if (target.type() === SDK.Target.Type.FRAME) {
729
- const overlayModel = target.model(SDK.OverlayModel.OverlayModel);
730
- if (overlayModel) {
731
- overlayModel.removeEventListener(
732
- SDK.OverlayModel.Events.INSPECTED_ELEMENT_WINDOW_RESTORED, floaty.handleRestoreEvent, floaty);
733
- overlayModel.removeEventListener(
734
- SDK.OverlayModel.Events.INSPECT_PANEL_SHOW_REQUESTED, floaty.handlePanelRequest);
735
- }
736
- }
737
- },
738
- };
739
- targetManager.observeTargets(observer);
740
- }
741
- } catch (err) {
742
- console.error('[GreenDev] FATAL ERROR during init():', err);
743
- }
744
- }
745
-
746
- void init();