chrome-devtools-frontend 1.0.1007307 → 1.0.1008562
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.
- package/config/gni/devtools_grd_files.gni +3 -0
- package/extension-api/ExtensionAPI.d.ts +10 -0
- package/front_end/core/common/ParsedURL.ts +9 -1
- package/front_end/core/i18n/locales/en-US.json +14 -5
- package/front_end/core/i18n/locales/en-XL.json +14 -5
- package/front_end/core/sdk/CSSFontFace.ts +8 -0
- package/front_end/entrypoints/lighthouse_worker/LighthouseWorkerService.ts +1 -4
- package/front_end/generated/InspectorBackendCommands.js +2 -2
- package/front_end/generated/protocol.ts +2 -1
- package/front_end/legacy_test_runner/lighthouse_test_runner/lighthouse_test_runner.js +16 -0
- package/front_end/models/extensions/ExtensionAPI.ts +95 -12
- package/front_end/models/extensions/ExtensionEndpoint.ts +69 -0
- package/front_end/models/extensions/ExtensionServer.ts +21 -0
- package/front_end/models/extensions/LanguageExtensionEndpoint.ts +46 -78
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +43 -0
- package/front_end/models/extensions/RecorderPluginManager.ts +30 -0
- package/front_end/models/extensions/extensions.ts +2 -0
- package/front_end/models/issues_manager/DeprecationIssue.ts +0 -14
- package/front_end/panels/application/AppManifestView.ts +2 -1
- package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +15 -1
- package/front_end/panels/lighthouse/LighthouseController.ts +25 -10
- package/front_end/panels/lighthouse/LighthouseStartView.ts +25 -1
- package/front_end/panels/lighthouse/LighthouseStartViewFR.ts +1 -1
- package/front_end/panels/network/components/RequestHeadersView.css +5 -0
- package/front_end/panels/network/components/RequestHeadersView.ts +56 -6
- package/front_end/ui/components/tree_outline/TreeOutline.ts +4 -0
- package/front_end/ui/components/tree_outline/treeOutline.css +6 -1
- package/package.json +1 -1
@@ -714,11 +714,14 @@ grd_files_debug_sources = [
|
|
714
714
|
"front_end/models/emulation/DeviceModeModel.js",
|
715
715
|
"front_end/models/emulation/EmulatedDevices.js",
|
716
716
|
"front_end/models/extensions/ExtensionAPI.js",
|
717
|
+
"front_end/models/extensions/ExtensionEndpoint.js",
|
717
718
|
"front_end/models/extensions/ExtensionPanel.js",
|
718
719
|
"front_end/models/extensions/ExtensionServer.js",
|
719
720
|
"front_end/models/extensions/ExtensionTraceProvider.js",
|
720
721
|
"front_end/models/extensions/ExtensionView.js",
|
721
722
|
"front_end/models/extensions/LanguageExtensionEndpoint.js",
|
723
|
+
"front_end/models/extensions/RecorderExtensionEndpoint.js",
|
724
|
+
"front_end/models/extensions/RecorderPluginManager.js",
|
722
725
|
"front_end/models/formatter/FormatterWorkerPool.js",
|
723
726
|
"front_end/models/formatter/ScriptFormatter.js",
|
724
727
|
"front_end/models/formatter/SourceFormatter.js",
|
@@ -94,6 +94,7 @@ export namespace Chrome {
|
|
94
94
|
panels: Panels;
|
95
95
|
inspectedWindow: InspectedWindow;
|
96
96
|
languageServices: LanguageExtensions;
|
97
|
+
recorder: RecorderExtensions;
|
97
98
|
}
|
98
99
|
|
99
100
|
export interface ExperimentalDevToolsAPI {
|
@@ -170,6 +171,10 @@ export namespace Chrome {
|
|
170
171
|
payload: unknown;
|
171
172
|
}
|
172
173
|
|
174
|
+
export interface RecorderExtensionPlugin {
|
175
|
+
stringify(obj: Record<string, any>): Promise<string>;
|
176
|
+
}
|
177
|
+
|
173
178
|
export interface LanguageExtensionPlugin {
|
174
179
|
/**
|
175
180
|
* A new raw module has been loaded. If the raw wasm module references an external debug info module, its URL will be
|
@@ -272,6 +277,11 @@ export namespace Chrome {
|
|
272
277
|
unregisterLanguageExtensionPlugin(plugin: LanguageExtensionPlugin): Promise<void>;
|
273
278
|
}
|
274
279
|
|
280
|
+
export interface RecorderExtensions {
|
281
|
+
registerRecorderExtensionPlugin(plugin: RecorderExtensionPlugin, pluginName: string): Promise<void>;
|
282
|
+
unregisterRecorderExtensionPlugin(plugin: RecorderExtensionPlugin): Promise<void>;
|
283
|
+
}
|
284
|
+
|
275
285
|
export interface Chrome {
|
276
286
|
devtools: DevToolsAPI;
|
277
287
|
experimental: {devtools: ExperimentalDevToolsAPI};
|
@@ -470,8 +470,16 @@ export class ParsedURL {
|
|
470
470
|
return ParsedURL.substring(url as Platform.DevToolsPath.UrlString, 0, wasmFunctionIndex);
|
471
471
|
}
|
472
472
|
|
473
|
+
private static beginsWithWindowsDriveLetter(url: string): boolean {
|
474
|
+
return /^[A-Za-z]:/.test(url);
|
475
|
+
}
|
476
|
+
|
477
|
+
private static beginsWithScheme(url: string): boolean {
|
478
|
+
return /^[A-Za-z][A-Za-z0-9+.-]*:/.test(url);
|
479
|
+
}
|
480
|
+
|
473
481
|
static isRelativeURL(url: string): boolean {
|
474
|
-
return !(
|
482
|
+
return !this.beginsWithScheme(url) || this.beginsWithWindowsDriveLetter(url);
|
475
483
|
}
|
476
484
|
|
477
485
|
get displayName(): string {
|
@@ -1469,9 +1469,6 @@
|
|
1469
1469
|
"models/issues_manager/DeprecationIssue.ts | rtcpMuxPolicyNegotiate": {
|
1470
1470
|
"message": "The rtcpMuxPolicy option is deprecated and will be removed."
|
1471
1471
|
},
|
1472
|
-
"models/issues_manager/DeprecationIssue.ts | rtpDataChannel": {
|
1473
|
-
"message": "RTP data channels are no longer supported. The RtpDataChannels constraint is currently ignored, and may cause an error at a later date."
|
1474
|
-
},
|
1475
1472
|
"models/issues_manager/DeprecationIssue.ts | sharedArrayBufferConstructedWithoutIsolation": {
|
1476
1473
|
"message": "SharedArrayBuffer will require cross-origin isolation. See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details."
|
1477
1474
|
},
|
@@ -3803,6 +3800,9 @@
|
|
3803
3800
|
"panels/browser_debugger/DOMBreakpointsSidebarPane.ts | sS": {
|
3804
3801
|
"message": "{PH1}: {PH2}"
|
3805
3802
|
},
|
3803
|
+
"panels/browser_debugger/DOMBreakpointsSidebarPane.ts | sSS": {
|
3804
|
+
"message": "{PH1}: {PH2}, {PH3}"
|
3805
|
+
},
|
3806
3806
|
"panels/browser_debugger/DOMBreakpointsSidebarPane.ts | subtreeModified": {
|
3807
3807
|
"message": "Subtree modified"
|
3808
3808
|
},
|
@@ -5951,6 +5951,9 @@
|
|
5951
5951
|
"panels/lighthouse/LighthouseController.ts | desktop": {
|
5952
5952
|
"message": "Desktop"
|
5953
5953
|
},
|
5954
|
+
"panels/lighthouse/LighthouseController.ts | devtoolsThrottling": {
|
5955
|
+
"message": "DevTools throttling (advanced)"
|
5956
|
+
},
|
5954
5957
|
"panels/lighthouse/LighthouseController.ts | doesThisPageFollowBestPractices": {
|
5955
5958
|
"message": "Does this page follow best practices for modern web development"
|
5956
5959
|
},
|
@@ -6015,10 +6018,10 @@
|
|
6015
6018
|
"message": "SEO"
|
6016
6019
|
},
|
6017
6020
|
"panels/lighthouse/LighthouseController.ts | simulateASlowerPageLoadBasedOn": {
|
6018
|
-
"message": "
|
6021
|
+
"message": "Simulated throttling simulates a slower page load based on data from an initial unthrottled load. DevTools throttling actually slows down the page."
|
6019
6022
|
},
|
6020
6023
|
"panels/lighthouse/LighthouseController.ts | simulatedThrottling": {
|
6021
|
-
"message": "Simulated throttling"
|
6024
|
+
"message": "Simulated throttling (default)"
|
6022
6025
|
},
|
6023
6026
|
"panels/lighthouse/LighthouseController.ts | snapshot": {
|
6024
6027
|
"message": "Snapshot"
|
@@ -6032,6 +6035,9 @@
|
|
6032
6035
|
"panels/lighthouse/LighthouseController.ts | thereMayBeStoredDataAffectingSingular": {
|
6033
6036
|
"message": "There may be stored data affecting loading performance in this location: {PH1}. Audit this page in an incognito window to prevent those resources from affecting your scores."
|
6034
6037
|
},
|
6038
|
+
"panels/lighthouse/LighthouseController.ts | throttlingMethod": {
|
6039
|
+
"message": "Throttling method"
|
6040
|
+
},
|
6035
6041
|
"panels/lighthouse/LighthouseController.ts | timespan": {
|
6036
6042
|
"message": "Timespan"
|
6037
6043
|
},
|
@@ -6653,6 +6659,9 @@
|
|
6653
6659
|
"panels/network/components/RequestHeadersView.ts | responseHeaders": {
|
6654
6660
|
"message": "Response Headers"
|
6655
6661
|
},
|
6662
|
+
"panels/network/components/RequestHeadersView.ts | showMore": {
|
6663
|
+
"message": "Show more"
|
6664
|
+
},
|
6656
6665
|
"panels/network/components/RequestHeadersView.ts | statusCode": {
|
6657
6666
|
"message": "Status Code"
|
6658
6667
|
},
|
@@ -1469,9 +1469,6 @@
|
|
1469
1469
|
"models/issues_manager/DeprecationIssue.ts | rtcpMuxPolicyNegotiate": {
|
1470
1470
|
"message": "T̂h́ê rtcpMuxPolicy óp̂t́îón̂ íŝ d́êṕr̂éĉát̂éd̂ án̂d́ ŵíl̂ĺ b̂é r̂ém̂óv̂éd̂."
|
1471
1471
|
},
|
1472
|
-
"models/issues_manager/DeprecationIssue.ts | rtpDataChannel": {
|
1473
|
-
"message": "RTP data channels âŕê ńô ĺôńĝér̂ śûṕp̂ór̂t́êd́. T̂h́ê RtpDataChannels ćôńŝt́r̂áîńt̂ íŝ ćûŕr̂én̂t́l̂ý îǵn̂ór̂éd̂, án̂d́ m̂áŷ ćâúŝé âń êŕr̂ór̂ át̂ á l̂át̂ér̂ d́ât́ê."
|
1474
|
-
},
|
1475
1472
|
"models/issues_manager/DeprecationIssue.ts | sharedArrayBufferConstructedWithoutIsolation": {
|
1476
1473
|
"message": "SharedArrayBuffer ŵíl̂ĺ r̂éq̂úîŕê ćr̂óŝś-ôŕîǵîń îśôĺât́îón̂. Śêé ĥt́t̂ṕŝ://d́êv́êĺôṕêŕ.ĉh́r̂óm̂é.ĉóm̂/b́l̂óĝ/én̂áb̂ĺîńĝ-śĥár̂éd̂-ár̂ŕâý-b̂úf̂f́êŕ/ f̂ór̂ ḿôŕê d́êt́âíl̂ś."
|
1477
1474
|
},
|
@@ -3803,6 +3800,9 @@
|
|
3803
3800
|
"panels/browser_debugger/DOMBreakpointsSidebarPane.ts | sS": {
|
3804
3801
|
"message": "{PH1}: {PH2}"
|
3805
3802
|
},
|
3803
|
+
"panels/browser_debugger/DOMBreakpointsSidebarPane.ts | sSS": {
|
3804
|
+
"message": "{PH1}: {PH2}, {PH3}"
|
3805
|
+
},
|
3806
3806
|
"panels/browser_debugger/DOMBreakpointsSidebarPane.ts | subtreeModified": {
|
3807
3807
|
"message": "Ŝúb̂t́r̂éê ḿôd́îf́îéd̂"
|
3808
3808
|
},
|
@@ -5951,6 +5951,9 @@
|
|
5951
5951
|
"panels/lighthouse/LighthouseController.ts | desktop": {
|
5952
5952
|
"message": "D̂éŝḱt̂óp̂"
|
5953
5953
|
},
|
5954
|
+
"panels/lighthouse/LighthouseController.ts | devtoolsThrottling": {
|
5955
|
+
"message": "D̂év̂T́ôól̂ś t̂h́r̂ót̂t́l̂ín̂ǵ (âd́v̂án̂ćêd́)"
|
5956
|
+
},
|
5954
5957
|
"panels/lighthouse/LighthouseController.ts | doesThisPageFollowBestPractices": {
|
5955
5958
|
"message": "D̂óêś t̂h́îś p̂áĝé f̂ól̂ĺôẃ b̂éŝt́ p̂ŕâćt̂íĉéŝ f́ôŕ m̂ód̂ér̂ń ŵéb̂ d́êv́êĺôṕm̂én̂t́"
|
5956
5959
|
},
|
@@ -6015,10 +6018,10 @@
|
|
6015
6018
|
"message": "ŜÉÔ"
|
6016
6019
|
},
|
6017
6020
|
"panels/lighthouse/LighthouseController.ts | simulateASlowerPageLoadBasedOn": {
|
6018
|
-
"message": "Ŝím̂úl̂át̂é â śl̂óŵér̂ ṕâǵê ĺôád
|
6021
|
+
"message": "Ŝím̂úl̂át̂éd̂ t́ĥŕôt́t̂ĺîńĝ śîḿûĺât́êś â śl̂óŵér̂ ṕâǵê ĺôád̂ b́âśêd́ ôń d̂át̂á f̂ŕôḿ âń îńît́îál̂ ún̂t́ĥŕôt́t̂ĺêd́ l̂óâd́. D̂év̂T́ôól̂ś t̂h́r̂ót̂t́l̂ín̂ǵ âćt̂úâĺl̂ý ŝĺôẃŝ d́ôẃn̂ t́ĥé p̂áĝé."
|
6019
6022
|
},
|
6020
6023
|
"panels/lighthouse/LighthouseController.ts | simulatedThrottling": {
|
6021
|
-
"message": "Ŝím̂úl̂át̂éd̂ t́ĥŕôt́t̂ĺîńĝ"
|
6024
|
+
"message": "Ŝím̂úl̂át̂éd̂ t́ĥŕôt́t̂ĺîńĝ (d́êf́âúl̂t́)"
|
6022
6025
|
},
|
6023
6026
|
"panels/lighthouse/LighthouseController.ts | snapshot": {
|
6024
6027
|
"message": "Ŝńâṕŝh́ôt́"
|
@@ -6032,6 +6035,9 @@
|
|
6032
6035
|
"panels/lighthouse/LighthouseController.ts | thereMayBeStoredDataAffectingSingular": {
|
6033
6036
|
"message": "T̂h́êŕê ḿâý b̂é ŝt́ôŕêd́ d̂át̂á âf́f̂éĉt́îńĝ ĺôád̂ín̂ǵ p̂ér̂f́ôŕm̂án̂ćê ín̂ t́ĥíŝ ĺôćât́îón̂: {PH1}. Áûd́ît́ t̂h́îś p̂áĝé îń âń îńĉóĝńît́ô ẃîńd̂óŵ t́ô ṕr̂év̂én̂t́ t̂h́ôśê ŕêśôúr̂ćêś f̂ŕôḿ âf́f̂éĉt́îńĝ ýôúr̂ śĉór̂éŝ."
|
6034
6037
|
},
|
6038
|
+
"panels/lighthouse/LighthouseController.ts | throttlingMethod": {
|
6039
|
+
"message": "T̂h́r̂ót̂t́l̂ín̂ǵ m̂ét̂h́ôd́"
|
6040
|
+
},
|
6035
6041
|
"panels/lighthouse/LighthouseController.ts | timespan": {
|
6036
6042
|
"message": "T̂ím̂éŝṕâń"
|
6037
6043
|
},
|
@@ -6653,6 +6659,9 @@
|
|
6653
6659
|
"panels/network/components/RequestHeadersView.ts | responseHeaders": {
|
6654
6660
|
"message": "R̂éŝṕôńŝé Ĥéâd́êŕŝ"
|
6655
6661
|
},
|
6662
|
+
"panels/network/components/RequestHeadersView.ts | showMore": {
|
6663
|
+
"message": "Ŝh́ôẃ m̂ór̂é"
|
6664
|
+
},
|
6656
6665
|
"panels/network/components/RequestHeadersView.ts | statusCode": {
|
6657
6666
|
"message": "Ŝt́ât́ûś Ĉód̂é"
|
6658
6667
|
},
|
@@ -3,15 +3,19 @@
|
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
5
|
import type * as Protocol from '../../generated/protocol.js';
|
6
|
+
import type * as Platform from '../platform/platform.js';
|
6
7
|
|
7
8
|
export class CSSFontFace {
|
8
9
|
readonly #fontFamily: string;
|
9
10
|
readonly #fontVariationAxes: Protocol.CSS.FontVariationAxis[];
|
10
11
|
readonly #fontVariationAxesByTag: Map<string, Protocol.CSS.FontVariationAxis>;
|
12
|
+
readonly #src: Platform.DevToolsPath.UrlString;
|
13
|
+
|
11
14
|
constructor(payload: Protocol.CSS.FontFace) {
|
12
15
|
this.#fontFamily = payload.fontFamily;
|
13
16
|
this.#fontVariationAxes = payload.fontVariationAxes || [];
|
14
17
|
this.#fontVariationAxesByTag = new Map();
|
18
|
+
this.#src = payload.src as Platform.DevToolsPath.UrlString;
|
15
19
|
for (const axis of this.#fontVariationAxes) {
|
16
20
|
this.#fontVariationAxesByTag.set(axis.tag, axis);
|
17
21
|
}
|
@@ -21,6 +25,10 @@ export class CSSFontFace {
|
|
21
25
|
return this.#fontFamily;
|
22
26
|
}
|
23
27
|
|
28
|
+
getSrc(): Platform.DevToolsPath.UrlString {
|
29
|
+
return this.#src;
|
30
|
+
}
|
31
|
+
|
24
32
|
getVariationAxisByTag(tag: string): Protocol.CSS.FontVariationAxis|undefined {
|
25
33
|
return this.#fontVariationAxesByTag.get(tag);
|
26
34
|
}
|
@@ -143,10 +143,7 @@ async function invokeLH(action: string, args: any): Promise<unknown> {
|
|
143
143
|
const {page} = puppeteerConnection;
|
144
144
|
const configContext = {
|
145
145
|
logLevel: flags.logLevel,
|
146
|
-
settingsOverrides:
|
147
|
-
channel: flags.channel,
|
148
|
-
locale: flags.locale,
|
149
|
-
},
|
146
|
+
settingsOverrides: flags,
|
150
147
|
};
|
151
148
|
|
152
149
|
if (action === 'snapshot') {
|
@@ -315,7 +315,6 @@ export function registerCommands(inspectorBackend) {
|
|
315
315
|
'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
|
316
316
|
RTCPeerConnectionSdpSemanticsPlanB: 'RTCPeerConnectionSdpSemanticsPlanB',
|
317
317
|
RtcpMuxPolicyNegotiate: 'RtcpMuxPolicyNegotiate',
|
318
|
-
RTPDataChannel: 'RTPDataChannel',
|
319
318
|
SharedArrayBufferConstructedWithoutIsolation: 'SharedArrayBufferConstructedWithoutIsolation',
|
320
319
|
TextToSpeech_DisallowedByAutoplay: 'TextToSpeech_DisallowedByAutoplay',
|
321
320
|
V8SharedArrayBufferConstructedInExtensionWithoutIsolation:
|
@@ -2380,7 +2379,8 @@ export function registerCommands(inspectorBackend) {
|
|
2380
2379
|
inspectorBackend.registerEnum(
|
2381
2380
|
'Page.FileChooserOpenedEventMode', {SelectSingle: 'selectSingle', SelectMultiple: 'selectMultiple'});
|
2382
2381
|
inspectorBackend.registerEvent('Page.fileChooserOpened', ['frameId', 'backendNodeId', 'mode']);
|
2383
|
-
inspectorBackend.registerEvent(
|
2382
|
+
inspectorBackend.registerEvent(
|
2383
|
+
'Page.frameAttached', ['frameId', 'parentFrameId', 'stack', 'adScriptId', 'debuggerId']);
|
2384
2384
|
inspectorBackend.registerEvent('Page.frameClearedScheduledNavigation', ['frameId']);
|
2385
2385
|
inspectorBackend.registerEnum('Page.FrameDetachedEventReason', {Remove: 'remove', Swap: 'swap'});
|
2386
2386
|
inspectorBackend.registerEvent('Page.frameDetached', ['frameId', 'reason']);
|
@@ -1062,7 +1062,6 @@ export namespace Audits {
|
|
1062
1062
|
'RTCPeerConnectionComplexPlanBSdpUsingDefaultSdpSemantics',
|
1063
1063
|
RTCPeerConnectionSdpSemanticsPlanB = 'RTCPeerConnectionSdpSemanticsPlanB',
|
1064
1064
|
RtcpMuxPolicyNegotiate = 'RtcpMuxPolicyNegotiate',
|
1065
|
-
RTPDataChannel = 'RTPDataChannel',
|
1066
1065
|
SharedArrayBufferConstructedWithoutIsolation = 'SharedArrayBufferConstructedWithoutIsolation',
|
1067
1066
|
TextToSpeech_DisallowedByAutoplay = 'TextToSpeech_DisallowedByAutoplay',
|
1068
1067
|
V8SharedArrayBufferConstructedInExtensionWithoutIsolation =
|
@@ -11765,6 +11764,8 @@ export namespace Page {
|
|
11765
11764
|
* JavaScript stack trace of when frame was attached, only set if frame initiated from script.
|
11766
11765
|
*/
|
11767
11766
|
stack?: Runtime.StackTrace;
|
11767
|
+
adScriptId?: Runtime.ScriptId;
|
11768
|
+
debuggerId?: Runtime.UniqueDebuggerId;
|
11768
11769
|
}
|
11769
11770
|
|
11770
11771
|
/**
|
@@ -100,6 +100,18 @@ LighthouseTestRunner._checkboxStateLabel = function(checkboxContainer) {
|
|
100
100
|
return `[${checkedLabel}] ${label}`;
|
101
101
|
};
|
102
102
|
|
103
|
+
/**
|
104
|
+
* @param {?Element} combobox
|
105
|
+
* @return {string}
|
106
|
+
*/
|
107
|
+
LighthouseTestRunner._comboboxStateLabel = function(combobox) {
|
108
|
+
if (!combobox) {
|
109
|
+
return 'missing';
|
110
|
+
}
|
111
|
+
|
112
|
+
return `${combobox.ariaLabel}: ${combobox.value}`;
|
113
|
+
};
|
114
|
+
|
103
115
|
/**
|
104
116
|
* @param {?Element} button
|
105
117
|
* @return {string}
|
@@ -130,6 +142,10 @@ LighthouseTestRunner.dumpStartAuditState = function() {
|
|
130
142
|
TestRunner.addResult(LighthouseTestRunner._checkboxStateLabel(element));
|
131
143
|
});
|
132
144
|
|
145
|
+
for (const combobox of toolbarShadowRoot.querySelectorAll('select')) {
|
146
|
+
TestRunner.addResult(LighthouseTestRunner._comboboxStateLabel(combobox));
|
147
|
+
}
|
148
|
+
|
133
149
|
const helpText = containerElement.querySelector('.lighthouse-help-text');
|
134
150
|
if (!helpText.classList.contains('hidden')) {
|
135
151
|
TestRunner.addResult(`Help text: ${helpText.textContent}`);
|
@@ -86,6 +86,7 @@ export namespace PrivateAPI {
|
|
86
86
|
Unsubscribe = 'unsubscribe',
|
87
87
|
UpdateButton = 'updateButton',
|
88
88
|
RegisterLanguageExtensionPlugin = 'registerLanguageExtensionPlugin',
|
89
|
+
RegisterRecorderExtensionPlugin = 'registerRecorderExtensionPlugin',
|
89
90
|
}
|
90
91
|
|
91
92
|
export const enum LanguageExtensionPluginCommands {
|
@@ -108,6 +109,14 @@ export namespace PrivateAPI {
|
|
108
109
|
UnregisteredLanguageExtensionPlugin = 'unregisteredLanguageExtensionPlugin',
|
109
110
|
}
|
110
111
|
|
112
|
+
export const enum RecorderExtensionPluginCommands {
|
113
|
+
Stringify = 'stringify',
|
114
|
+
}
|
115
|
+
|
116
|
+
export const enum RecorderExtensionPluginEvents {
|
117
|
+
UnregisteredRecorderExtensionPlugin = 'unregisteredRecorderExtensionPlugin',
|
118
|
+
}
|
119
|
+
|
111
120
|
export interface EvaluateOptions {
|
112
121
|
frameURL?: string;
|
113
122
|
useContentScriptContext?: boolean;
|
@@ -120,6 +129,11 @@ export namespace PrivateAPI {
|
|
120
129
|
port: MessagePort,
|
121
130
|
supportedScriptTypes: PublicAPI.Chrome.DevTools.SupportedScriptTypes,
|
122
131
|
};
|
132
|
+
type RegisterRecorderExtensionPluginRequest = {
|
133
|
+
command: Commands.RegisterRecorderExtensionPlugin,
|
134
|
+
pluginName: string,
|
135
|
+
port: MessagePort,
|
136
|
+
};
|
123
137
|
type SubscribeRequest = {command: Commands.Subscribe, type: string};
|
124
138
|
type UnsubscribeRequest = {command: Commands.Unsubscribe, type: string};
|
125
139
|
type AddRequestHeadersRequest = {
|
@@ -182,13 +196,13 @@ export namespace PrivateAPI {
|
|
182
196
|
type GetHARRequest = {command: Commands.GetHAR};
|
183
197
|
type GetPageResourcesRequest = {command: Commands.GetPageResources};
|
184
198
|
|
185
|
-
export type ServerRequests = RegisterLanguageExtensionPluginRequest|
|
186
|
-
AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|
|
187
|
-
UpdateButtonRequest|CompleteTraceSessionRequest|
|
188
|
-
SetSidebarContentRequest|SetSidebarPageRequest|
|
189
|
-
SetThemeChangeHandlerRequest|ReloadRequest|
|
190
|
-
GetResourceContentRequest|SetResourceContentRequest|
|
191
|
-
GetHARRequest|GetPageResourcesRequest;
|
199
|
+
export type ServerRequests = RegisterRecorderExtensionPluginRequest|RegisterLanguageExtensionPluginRequest|
|
200
|
+
SubscribeRequest|UnsubscribeRequest|AddRequestHeadersRequest|ApplyStyleSheetRequest|CreatePanelRequest|
|
201
|
+
ShowPanelRequest|CreateToolbarButtonRequest|UpdateButtonRequest|CompleteTraceSessionRequest|
|
202
|
+
CreateSidebarPaneRequest|SetSidebarHeightRequest|SetSidebarContentRequest|SetSidebarPageRequest|
|
203
|
+
OpenResourceRequest|SetOpenResourceHandlerRequest|SetThemeChangeHandlerRequest|ReloadRequest|
|
204
|
+
EvaluateOnInspectedPageRequest|GetRequestContentRequest|GetResourceContentRequest|SetResourceContentRequest|
|
205
|
+
AddTraceProviderRequest|ForwardKeyboardEventRequest|GetHARRequest|GetPageResourcesRequest;
|
192
206
|
export type ExtensionServerRequestMessage = PrivateAPI.ServerRequests&{requestId?: number};
|
193
207
|
|
194
208
|
type AddRawModuleRequest = {
|
@@ -256,6 +270,13 @@ export namespace PrivateAPI {
|
|
256
270
|
RawLocationToSourceLocationRequest|GetScopeInfoRequest|ListVariablesInScopeRequest|RemoveRawModuleRequest|
|
257
271
|
GetTypeInfoRequest|GetFormatterRequest|GetInspectableAddressRequest|GetFunctionInfoRequest|
|
258
272
|
GetInlinedFunctionRangesRequest|GetInlinedCalleesRangesRequest|GetMappedLinesRequest;
|
273
|
+
|
274
|
+
type StringifyRequest = {
|
275
|
+
method: RecorderExtensionPluginCommands.Stringify,
|
276
|
+
parameters: {recording: Record<string, unknown>},
|
277
|
+
};
|
278
|
+
|
279
|
+
export type RecorderExtensionRequests = StringifyRequest;
|
259
280
|
}
|
260
281
|
|
261
282
|
declare global {
|
@@ -264,7 +285,7 @@ declare global {
|
|
264
285
|
(extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
|
265
286
|
testHook:
|
266
287
|
(extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
|
267
|
-
injectedScriptId: number) => void;
|
288
|
+
injectedScriptId: number, targetWindow?: Window) => void;
|
268
289
|
buildExtensionAPIInjectedScript(
|
269
290
|
extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
|
270
291
|
testHook: undefined|((extensionServer: unknown, extensionAPI: unknown) => unknown)): string;
|
@@ -283,6 +304,7 @@ export type ExtensionDescriptor = {
|
|
283
304
|
namespace APIImpl {
|
284
305
|
export interface InspectorExtensionAPI {
|
285
306
|
languageServices: PublicAPI.Chrome.DevTools.LanguageExtensions;
|
307
|
+
recorder: PublicAPI.Chrome.DevTools.RecorderExtensions;
|
286
308
|
timeline: Timeline;
|
287
309
|
network: PublicAPI.Chrome.DevTools.Network;
|
288
310
|
panels: PublicAPI.Chrome.DevTools.Panels;
|
@@ -357,6 +379,10 @@ namespace APIImpl {
|
|
357
379
|
_plugins: Map<PublicAPI.Chrome.DevTools.LanguageExtensionPlugin, MessagePort>;
|
358
380
|
}
|
359
381
|
|
382
|
+
export interface RecorderExtensions extends PublicAPI.Chrome.DevTools.RecorderExtensions {
|
383
|
+
_plugins: Map<PublicAPI.Chrome.DevTools.RecorderExtensionPlugin, MessagePort>;
|
384
|
+
}
|
385
|
+
|
360
386
|
export interface ExtensionPanel extends ExtensionView, PublicAPI.Chrome.DevTools.ExtensionPanel {
|
361
387
|
show(): void;
|
362
388
|
}
|
@@ -392,7 +418,7 @@ namespace APIImpl {
|
|
392
418
|
self.injectedExtensionAPI = function(
|
393
419
|
extensionInfo: ExtensionDescriptor, inspectedTabId: string, themeName: string, keysToForward: number[],
|
394
420
|
testHook: (extensionServer: APIImpl.ExtensionServerClient, extensionAPI: APIImpl.InspectorExtensionAPI) => unknown,
|
395
|
-
injectedScriptId: number): void {
|
421
|
+
injectedScriptId: number, targetWindowForTest?: Window): void {
|
396
422
|
const keysToForwardSet = new Set<number>(keysToForward);
|
397
423
|
const chrome = window.chrome || {};
|
398
424
|
|
@@ -473,6 +499,7 @@ self.injectedExtensionAPI = function(
|
|
473
499
|
this.network = new (Constructor(Network))();
|
474
500
|
this.timeline = new (Constructor(Timeline))();
|
475
501
|
this.languageServices = new (Constructor(LanguageServicesAPI))();
|
502
|
+
this.recorder = new (Constructor(RecorderServicesAPI))();
|
476
503
|
defineDeprecatedProperty(this, 'webInspector', 'resources', 'network');
|
477
504
|
}
|
478
505
|
|
@@ -671,6 +698,60 @@ self.injectedExtensionAPI = function(
|
|
671
698
|
__proto__: ExtensionViewImpl.prototype,
|
672
699
|
};
|
673
700
|
|
701
|
+
function RecorderServicesAPIImpl(this: APIImpl.RecorderExtensions): void {
|
702
|
+
this._plugins = new Map();
|
703
|
+
}
|
704
|
+
|
705
|
+
(RecorderServicesAPIImpl.prototype as
|
706
|
+
Pick<APIImpl.RecorderExtensions, 'registerRecorderExtensionPlugin'|'unregisterRecorderExtensionPlugin'>) = {
|
707
|
+
registerRecorderExtensionPlugin: async function(
|
708
|
+
this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin,
|
709
|
+
pluginName: string): Promise<void> {
|
710
|
+
if (this._plugins.has(plugin)) {
|
711
|
+
throw new Error(`Tried to register plugin '${pluginName}' twice`);
|
712
|
+
}
|
713
|
+
const channel = new MessageChannel();
|
714
|
+
const port = channel.port1;
|
715
|
+
this._plugins.set(plugin, port);
|
716
|
+
port.onmessage = ({data}: MessageEvent<{requestId: number}&PrivateAPI.RecorderExtensionRequests>): void => {
|
717
|
+
const {requestId} = data;
|
718
|
+
dispatchMethodCall(data)
|
719
|
+
.then(result => port.postMessage({requestId, result}))
|
720
|
+
.catch(error => port.postMessage({requestId, error: {message: error.message}}));
|
721
|
+
};
|
722
|
+
|
723
|
+
function dispatchMethodCall(request: PrivateAPI.RecorderExtensionRequests): Promise<unknown> {
|
724
|
+
switch (request.method) {
|
725
|
+
case PrivateAPI.RecorderExtensionPluginCommands.Stringify:
|
726
|
+
return plugin.stringify(request.parameters.recording);
|
727
|
+
default:
|
728
|
+
throw new Error(`'${request.method}' is not recognized`);
|
729
|
+
}
|
730
|
+
}
|
731
|
+
|
732
|
+
await new Promise<void>(resolve => {
|
733
|
+
extensionServer.sendRequest(
|
734
|
+
{
|
735
|
+
command: PrivateAPI.Commands.RegisterRecorderExtensionPlugin,
|
736
|
+
pluginName,
|
737
|
+
port: channel.port2,
|
738
|
+
},
|
739
|
+
() => resolve(), [channel.port2]);
|
740
|
+
});
|
741
|
+
},
|
742
|
+
|
743
|
+
unregisterRecorderExtensionPlugin: async function(
|
744
|
+
this: APIImpl.RecorderExtensions, plugin: PublicAPI.Chrome.DevTools.RecorderExtensionPlugin): Promise<void> {
|
745
|
+
const port = this._plugins.get(plugin);
|
746
|
+
if (!port) {
|
747
|
+
throw new Error('Tried to unregister a plugin that was not previously registered');
|
748
|
+
}
|
749
|
+
this._plugins.delete(plugin);
|
750
|
+
port.postMessage({event: PrivateAPI.RecorderExtensionPluginEvents.UnregisteredRecorderExtensionPlugin});
|
751
|
+
port.close();
|
752
|
+
},
|
753
|
+
};
|
754
|
+
|
674
755
|
function LanguageServicesAPIImpl(this: APIImpl.LanguageExtensions): void {
|
675
756
|
this._plugins = new Map();
|
676
757
|
}
|
@@ -787,6 +868,7 @@ self.injectedExtensionAPI = function(
|
|
787
868
|
}
|
788
869
|
|
789
870
|
const LanguageServicesAPI = declareInterfaceClass(LanguageServicesAPIImpl);
|
871
|
+
const RecorderServicesAPI = declareInterfaceClass(RecorderServicesAPIImpl);
|
790
872
|
const Button = declareInterfaceClass(ButtonImpl);
|
791
873
|
const EventSink = declareInterfaceClass(EventSinkImpl);
|
792
874
|
const ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
|
@@ -1128,7 +1210,7 @@ self.injectedExtensionAPI = function(
|
|
1128
1210
|
|
1129
1211
|
document.addEventListener('keydown', forwardKeyboardEvent, false);
|
1130
1212
|
|
1131
|
-
function ExtensionServerClient(this: APIImpl.ExtensionServerClient): void {
|
1213
|
+
function ExtensionServerClient(this: APIImpl.ExtensionServerClient, targetWindow: Window): void {
|
1132
1214
|
this._callbacks = {};
|
1133
1215
|
this._handlers = {};
|
1134
1216
|
this._lastRequestId = 0;
|
@@ -1141,7 +1223,7 @@ self.injectedExtensionAPI = function(
|
|
1141
1223
|
this._port.addEventListener('message', this._onMessage.bind(this), false);
|
1142
1224
|
this._port.start();
|
1143
1225
|
|
1144
|
-
|
1226
|
+
targetWindow.postMessage('registerExtension', '*', [channel.port2]);
|
1145
1227
|
}
|
1146
1228
|
|
1147
1229
|
(ExtensionServerClient.prototype as Pick<
|
@@ -1225,7 +1307,7 @@ self.injectedExtensionAPI = function(
|
|
1225
1307
|
}
|
1226
1308
|
}
|
1227
1309
|
|
1228
|
-
const extensionServer = new (Constructor(ExtensionServerClient))();
|
1310
|
+
const extensionServer = new (Constructor(ExtensionServerClient))(targetWindowForTest || window.parent);
|
1229
1311
|
|
1230
1312
|
const coreAPI = new (Constructor(InspectorExtensionAPI))();
|
1231
1313
|
|
@@ -1241,6 +1323,7 @@ self.injectedExtensionAPI = function(
|
|
1241
1323
|
chrome.devtools!.panels = coreAPI.panels;
|
1242
1324
|
chrome.devtools!.panels.themeName = themeName;
|
1243
1325
|
chrome.devtools!.languageServices = coreAPI.languageServices;
|
1326
|
+
chrome.devtools!.recorder = coreAPI.recorder;
|
1244
1327
|
|
1245
1328
|
// default to expose experimental APIs for now.
|
1246
1329
|
if (extensionInfo.exposeExperimentalAPIs !== false) {
|
@@ -0,0 +1,69 @@
|
|
1
|
+
// Copyright 2022 The Chromium Authors. All rights reserved.
|
2
|
+
// Use of this source code is governed by a BSD-style license that can be
|
3
|
+
// found in the LICENSE file.
|
4
|
+
|
5
|
+
type Response = {
|
6
|
+
requestId: number,
|
7
|
+
result: unknown,
|
8
|
+
error: Error|null,
|
9
|
+
};
|
10
|
+
|
11
|
+
type Event = {
|
12
|
+
event: string,
|
13
|
+
};
|
14
|
+
|
15
|
+
type Message = MessageEvent<Response|Event>;
|
16
|
+
|
17
|
+
export class ExtensionEndpoint {
|
18
|
+
private readonly port: MessagePort;
|
19
|
+
private nextRequestId: number = 0;
|
20
|
+
private pendingRequests: Map<number, {
|
21
|
+
resolve: (arg: unknown) => void,
|
22
|
+
reject: (error: Error) => void,
|
23
|
+
}>;
|
24
|
+
|
25
|
+
constructor(port: MessagePort) {
|
26
|
+
this.port = port;
|
27
|
+
this.port.onmessage = this.onResponse.bind(this);
|
28
|
+
this.pendingRequests = new Map();
|
29
|
+
}
|
30
|
+
|
31
|
+
sendRequest<ReturnType>(method: string, parameters: unknown): Promise<ReturnType> {
|
32
|
+
return new Promise((resolve, reject) => {
|
33
|
+
const requestId = this.nextRequestId++;
|
34
|
+
this.pendingRequests.set(requestId, {resolve: resolve as (arg: unknown) => void, reject});
|
35
|
+
this.port.postMessage({requestId, method, parameters});
|
36
|
+
});
|
37
|
+
}
|
38
|
+
|
39
|
+
protected disconnect(): void {
|
40
|
+
for (const {reject} of this.pendingRequests.values()) {
|
41
|
+
reject(new Error('Extension endpoint disconnected'));
|
42
|
+
}
|
43
|
+
this.pendingRequests.clear();
|
44
|
+
this.port.close();
|
45
|
+
}
|
46
|
+
|
47
|
+
private onResponse({data}: Message): void {
|
48
|
+
if ('event' in data) {
|
49
|
+
this.handleEvent(data);
|
50
|
+
return;
|
51
|
+
}
|
52
|
+
const {requestId, result, error} = data;
|
53
|
+
const pendingRequest = this.pendingRequests.get(requestId);
|
54
|
+
if (!pendingRequest) {
|
55
|
+
console.error(`No pending request ${requestId}`);
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
this.pendingRequests.delete(requestId);
|
59
|
+
if (error) {
|
60
|
+
pendingRequest.reject(new Error(error.message));
|
61
|
+
} else {
|
62
|
+
pendingRequest.resolve(result);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
protected handleEvent(_event: Event): void {
|
67
|
+
throw new Error('handleEvent is not implemented');
|
68
|
+
}
|
69
|
+
}
|
@@ -52,7 +52,9 @@ import {ExtensionButton, ExtensionPanel, ExtensionSidebarPane} from './Extension
|
|
52
52
|
import type {TracingSession} from './ExtensionTraceProvider.js';
|
53
53
|
import {ExtensionTraceProvider} from './ExtensionTraceProvider.js';
|
54
54
|
import {LanguageExtensionEndpoint} from './LanguageExtensionEndpoint.js';
|
55
|
+
import {RecorderExtensionEndpoint} from './RecorderExtensionEndpoint.js';
|
55
56
|
import {PrivateAPI} from './ExtensionAPI.js';
|
57
|
+
import {RecorderPluginManager} from './RecorderPluginManager.js';
|
56
58
|
|
57
59
|
const extensionOrigins: WeakMap<MessagePort, Platform.DevToolsPath.UrlString> = new WeakMap();
|
58
60
|
|
@@ -138,6 +140,8 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
138
140
|
this.registerHandler(PrivateAPI.Commands.UpdateButton, this.onUpdateButton.bind(this));
|
139
141
|
this.registerHandler(
|
140
142
|
PrivateAPI.Commands.RegisterLanguageExtensionPlugin, this.registerLanguageExtensionEndpoint.bind(this));
|
143
|
+
this.registerHandler(
|
144
|
+
PrivateAPI.Commands.RegisterRecorderExtensionPlugin, this.registerRecorderExtensionEndpoint.bind(this));
|
141
145
|
window.addEventListener('message', this.onWindowMessage.bind(this), false); // Only for main window.
|
142
146
|
|
143
147
|
const existingTabId =
|
@@ -215,6 +219,16 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
215
219
|
return this.status.OK();
|
216
220
|
}
|
217
221
|
|
222
|
+
private registerRecorderExtensionEndpoint(
|
223
|
+
message: PrivateAPI.ExtensionServerRequestMessage, _shared_port: MessagePort): Record {
|
224
|
+
if (message.command !== PrivateAPI.Commands.RegisterRecorderExtensionPlugin) {
|
225
|
+
return this.status.E_BADARG('command', `expected ${PrivateAPI.Commands.Subscribe}`);
|
226
|
+
}
|
227
|
+
const {pluginName, port} = message;
|
228
|
+
RecorderPluginManager.instance().addPlugin(new RecorderExtensionEndpoint(pluginName, port));
|
229
|
+
return this.status.OK();
|
230
|
+
}
|
231
|
+
|
218
232
|
private inspectedURLChanged(event: Common.EventTarget.EventTargetEvent<SDK.Target.Target>): void {
|
219
233
|
if (!this.canInspectURL(event.data.inspectedURL())) {
|
220
234
|
this.disableExtensions();
|
@@ -856,6 +870,13 @@ export class ExtensionServer extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
856
870
|
}
|
857
871
|
}
|
858
872
|
|
873
|
+
addExtensionForTest(extensionInfo: Host.InspectorFrontendHostAPI.ExtensionDescriptor, origin: string): boolean
|
874
|
+
|undefined {
|
875
|
+
const name = extensionInfo.name || `Extension ${origin}`;
|
876
|
+
this.registeredExtensions.set(origin, {name});
|
877
|
+
return true;
|
878
|
+
}
|
879
|
+
|
859
880
|
private addExtension(extensionInfo: Host.InspectorFrontendHostAPI.ExtensionDescriptor): boolean|undefined {
|
860
881
|
const startPage = extensionInfo.startPage;
|
861
882
|
|