chrome-devtools-frontend 1.0.1674545 → 1.0.1675430
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/.agents/skills/devtools-ux-writing-refactor/SKILL.md +26 -9
- package/front_end/core/common/ParsedURL.ts +5 -1
- package/front_end/core/common/SettingRegistration.ts +29 -8
- package/front_end/core/common/Settings.ts +0 -11
- package/front_end/core/root/Runtime.ts +4 -0
- package/front_end/core/sdk/TargetManager.ts +18 -0
- package/front_end/entrypoints/main/MainImpl.ts +1 -0
- package/front_end/foundation/Universe.ts +44 -29
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +15 -5
- package/front_end/models/emulation/DeviceModeModel.ts +60 -71
- package/front_end/models/emulation/EmulatedDevices.ts +18 -66
- package/front_end/models/persistence/AutomaticFileSystemManager.ts +2 -2
- package/front_end/models/persistence/IsolatedFileSystemManager.ts +20 -29
- package/front_end/models/workspace/FileManager.ts +13 -6
- package/front_end/panels/application/WebMCPView.ts +13 -5
- package/front_end/panels/application/components/AdsView.ts +24 -1
- package/front_end/panels/application/components/adsView.css +27 -21
- package/front_end/panels/autofill/AutofillView.ts +12 -12
- package/front_end/panels/autofill/autofill-meta.ts +2 -2
- package/front_end/panels/elements/ElementsTreeElement.ts +550 -327
- package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
- package/front_end/panels/js_timeline/js_timeline-meta.ts +8 -8
- package/front_end/panels/layer_viewer/LayerDetailsView.ts +30 -30
- package/front_end/panels/layer_viewer/LayerTreeOutline.ts +6 -6
- package/front_end/panels/layer_viewer/LayerViewHost.ts +1 -1
- package/front_end/panels/layer_viewer/Layers3DView.ts +11 -11
- package/front_end/panels/layer_viewer/PaintProfilerView.ts +8 -8
- package/front_end/panels/layer_viewer/TransformController.ts +3 -3
- package/front_end/panels/layer_viewer/layer_viewer-meta.ts +11 -11
- package/front_end/panels/mobile_throttling/ThrottlingManager.ts +1 -58
- package/front_end/panels/mobile_throttling/mobile_throttling.ts +0 -10
- package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +7 -0
- package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +1 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/comments/CommentAnchorResolver.ts +132 -0
- package/front_end/ui/comments/comments.ts +9 -0
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +40 -0
- package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -0
- package/front_end/ui/settings/SettingUIRegistration.ts +4 -0
- package/front_end/ui/visual_logging/Debugging.ts +1 -5
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/front_end/ui/visual_logging/LoggingConfig.ts +21 -0
- package/front_end/ui/visual_logging/visual_logging.ts +9 -0
- package/package.json +1 -1
- package/front_end/panels/mobile_throttling/MobileThrottlingSelector.ts +0 -92
|
@@ -124,21 +124,23 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
124
124
|
#touchMobile: boolean;
|
|
125
125
|
#emulationModel: SDK.EmulationModel.EmulationModel|null;
|
|
126
126
|
#onModelAvailable: (() => void)|null;
|
|
127
|
-
#outlineRect?: Rect;
|
|
128
127
|
#screenOrientationLocked: boolean;
|
|
129
128
|
readonly #targetManager: SDK.TargetManager.TargetManager;
|
|
130
129
|
readonly #settings: Common.Settings.Settings;
|
|
131
130
|
readonly #multitargetNetworkManager: SDK.NetworkManager.MultitargetNetworkManager;
|
|
131
|
+
readonly #fileManager: Workspace.FileManager.FileManager;
|
|
132
132
|
|
|
133
133
|
constructor(
|
|
134
134
|
targetManager: SDK.TargetManager.TargetManager,
|
|
135
135
|
settings: Common.Settings.Settings,
|
|
136
136
|
multitargetNetworkManager: SDK.NetworkManager.MultitargetNetworkManager,
|
|
137
|
+
fileManager: Workspace.FileManager.FileManager,
|
|
137
138
|
) {
|
|
138
139
|
super();
|
|
139
140
|
this.#targetManager = targetManager;
|
|
140
141
|
this.#settings = settings;
|
|
141
142
|
this.#multitargetNetworkManager = multitargetNetworkManager;
|
|
143
|
+
this.#fileManager = fileManager;
|
|
142
144
|
this.#screenRect = new Rect(0, 0, 1, 1);
|
|
143
145
|
this.#visiblePageRect = new Rect(0, 0, 1, 1);
|
|
144
146
|
this.#availableSize = new Geometry.Size(1, 1);
|
|
@@ -207,6 +209,8 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
207
209
|
Common.Settings.Settings.instance(),
|
|
208
210
|
// eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
|
|
209
211
|
SDK.NetworkManager.MultitargetNetworkManager.instance(),
|
|
212
|
+
// eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
|
|
213
|
+
Workspace.FileManager.FileManager.instance(),
|
|
210
214
|
));
|
|
211
215
|
}
|
|
212
216
|
|
|
@@ -313,8 +317,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
313
317
|
#updateFitScale(): void {
|
|
314
318
|
if (this.#type === Type.Device && this.#device && this.#mode) {
|
|
315
319
|
const orientation = this.#device.orientationByName(this.#mode.orientation);
|
|
316
|
-
this.#scaleSetting.set(
|
|
317
|
-
this.calculateFitScale(orientation.width, orientation.height, this.currentOutline(), this.currentInsets()));
|
|
320
|
+
this.#scaleSetting.set(this.calculateFitScale(orientation.width, orientation.height, this.currentInsets()));
|
|
318
321
|
}
|
|
319
322
|
}
|
|
320
323
|
|
|
@@ -401,18 +404,6 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
401
404
|
return this.#type;
|
|
402
405
|
}
|
|
403
406
|
|
|
404
|
-
screenImage(): string {
|
|
405
|
-
return (this.#device && this.#mode) ? this.#device.modeImage(this.#mode) : '';
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
canShowDeviceFrame(): boolean {
|
|
409
|
-
return Boolean(this.#device && this.#mode && this.#device.outlineImage(this.#mode));
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
outlineRect(): Rect|null {
|
|
413
|
-
return this.#outlineRect || null;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
407
|
screenRect(): Rect {
|
|
417
408
|
return this.#screenRect;
|
|
418
409
|
}
|
|
@@ -604,10 +595,6 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
604
595
|
return Math.floor(this.#preferredSize.height / (this.#scaleSetting.get() || 1));
|
|
605
596
|
}
|
|
606
597
|
|
|
607
|
-
private currentOutline(): Insets {
|
|
608
|
-
return new Insets(0, 0, 0, 0);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
598
|
private currentInsets(): Insets {
|
|
612
599
|
if (this.#type !== Type.Device || !this.#mode) {
|
|
613
600
|
return new Insets(0, 0, 0, 0);
|
|
@@ -660,25 +647,22 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
660
647
|
}
|
|
661
648
|
if (this.#type === Type.Device && this.#device && this.#mode) {
|
|
662
649
|
const orientation = this.#device.orientationByName(this.#mode.orientation);
|
|
663
|
-
const outline = this.currentOutline();
|
|
664
650
|
const insets = this.currentInsets();
|
|
665
|
-
this.#fitScale = this.calculateFitScale(orientation.width, orientation.height,
|
|
651
|
+
this.#fitScale = this.calculateFitScale(orientation.width, orientation.height, insets);
|
|
666
652
|
if (mobile) {
|
|
667
653
|
this.#appliedUserAgentType = this.#device.touch() ? UA.MOBILE : UA.MOBILE_NO_TOUCH;
|
|
668
654
|
} else {
|
|
669
655
|
this.#appliedUserAgentType = this.#device.touch() ? UA.DESKTOP_TOUCH : UA.DESKTOP;
|
|
670
656
|
}
|
|
671
|
-
this.applyDeviceMetrics(
|
|
672
|
-
|
|
673
|
-
|
|
657
|
+
this.applyDeviceMetrics(new Geometry.Size(orientation.width, orientation.height), insets,
|
|
658
|
+
this.#scaleSetting.get(), this.#device.deviceScaleFactor, mobile,
|
|
659
|
+
this.getScreenOrientationType(), resetPageScaleFactor);
|
|
674
660
|
this.applyUserAgent(this.#device.userAgent, this.#device.userAgentMetadata);
|
|
675
661
|
this.applyTouch(this.#device.touch(), mobile);
|
|
676
662
|
} else if (this.#type === Type.None) {
|
|
677
663
|
this.#fitScale = this.calculateFitScale(this.#availableSize.width, this.#availableSize.height);
|
|
678
664
|
this.#appliedUserAgentType = UA.DESKTOP;
|
|
679
|
-
this.applyDeviceMetrics(
|
|
680
|
-
this.#availableSize, new Insets(0, 0, 0, 0), new Insets(0, 0, 0, 0), 1, 0, mobile, null,
|
|
681
|
-
resetPageScaleFactor);
|
|
665
|
+
this.applyDeviceMetrics(this.#availableSize, new Insets(0, 0, 0, 0), 1, 0, mobile, null, resetPageScaleFactor);
|
|
682
666
|
this.applyUserAgent('', null);
|
|
683
667
|
this.applyTouch(false, false);
|
|
684
668
|
} else if (this.#type === Type.Responsive) {
|
|
@@ -693,12 +677,12 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
693
677
|
const defaultDeviceScaleFactor = mobile ? defaultMobileScaleFactor : 0;
|
|
694
678
|
this.#fitScale = this.calculateFitScale(this.#widthSetting.get(), this.#heightSetting.get());
|
|
695
679
|
this.#appliedUserAgentType = this.#uaSetting.get();
|
|
696
|
-
this.applyDeviceMetrics(
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
680
|
+
this.applyDeviceMetrics(new Geometry.Size(screenWidth, screenHeight), new Insets(0, 0, 0, 0),
|
|
681
|
+
this.#scaleSetting.get(),
|
|
682
|
+
this.#deviceScaleFactorSetting.get() || defaultDeviceScaleFactor, mobile,
|
|
683
|
+
screenHeight >= screenWidth ? Protocol.Emulation.ScreenOrientationType.PortraitPrimary :
|
|
684
|
+
Protocol.Emulation.ScreenOrientationType.LandscapePrimary,
|
|
685
|
+
resetPageScaleFactor);
|
|
702
686
|
this.applyUserAgent(
|
|
703
687
|
mobile ? DeviceModeModel.defaultMobileUserAgent() : '',
|
|
704
688
|
mobile ? DeviceModeModel.defaultMobileUserAgentMetadata() : null);
|
|
@@ -714,14 +698,11 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
714
698
|
this.dispatchEventToListeners(Events.UPDATED);
|
|
715
699
|
}
|
|
716
700
|
|
|
717
|
-
private calculateFitScale(screenWidth: number, screenHeight: number,
|
|
718
|
-
const outlineWidth = outline ? outline.left + outline.right : 0;
|
|
719
|
-
const outlineHeight = outline ? outline.top + outline.bottom : 0;
|
|
701
|
+
private calculateFitScale(screenWidth: number, screenHeight: number, insets?: Insets): number {
|
|
720
702
|
const insetsWidth = insets ? insets.left + insets.right : 0;
|
|
721
703
|
const insetsHeight = insets ? insets.top + insets.bottom : 0;
|
|
722
|
-
let scale = Math.min(
|
|
723
|
-
|
|
724
|
-
screenHeight ? this.#preferredSize.height / (screenHeight + outlineHeight) : 1);
|
|
704
|
+
let scale = Math.min(screenWidth ? this.#preferredSize.width / screenWidth : 1,
|
|
705
|
+
screenHeight ? this.#preferredSize.height / screenHeight : 1);
|
|
725
706
|
scale = Math.min(Math.floor(scale * 100), 100);
|
|
726
707
|
|
|
727
708
|
let sharpScale = scale;
|
|
@@ -754,10 +735,9 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
754
735
|
this.#multitargetNetworkManager.setUserAgentOverride(userAgent, userAgent ? userAgentMetadata : null);
|
|
755
736
|
}
|
|
756
737
|
|
|
757
|
-
private applyDeviceMetrics(
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
resetPageScaleFactor: boolean): void {
|
|
738
|
+
private applyDeviceMetrics(screenSize: Geometry.Size, insets: Insets, scale: number, deviceScaleFactor: number,
|
|
739
|
+
mobile: boolean, screenOrientation: Protocol.Emulation.ScreenOrientationType|null,
|
|
740
|
+
resetPageScaleFactor: boolean): void {
|
|
761
741
|
screenSize.width = Math.max(1, Math.floor(screenSize.width));
|
|
762
742
|
screenSize.height = Math.max(1, Math.floor(screenSize.height));
|
|
763
743
|
|
|
@@ -771,12 +751,8 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
771
751
|
|
|
772
752
|
this.#appliedDeviceSize = screenSize;
|
|
773
753
|
this.#appliedDeviceScaleFactor = deviceScaleFactor || window.devicePixelRatio;
|
|
774
|
-
this.#screenRect = new Rect(
|
|
775
|
-
|
|
776
|
-
screenSize.width * scale, screenSize.height * scale);
|
|
777
|
-
this.#outlineRect = new Rect(
|
|
778
|
-
this.#screenRect.left - outline.left * scale, 0, (outline.left + screenSize.width + outline.right) * scale,
|
|
779
|
-
(outline.top + screenSize.height + outline.bottom) * scale);
|
|
754
|
+
this.#screenRect = new Rect(Math.max(0, (this.#availableSize.width - screenSize.width * scale) / 2), 0,
|
|
755
|
+
screenSize.width * scale, screenSize.height * scale);
|
|
780
756
|
this.#visiblePageRect = new Rect(
|
|
781
757
|
positionX * scale, positionY * scale,
|
|
782
758
|
Math.min(pageWidth * scale, this.#availableSize.width - this.#screenRect.left - positionX * scale),
|
|
@@ -898,29 +874,21 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
898
874
|
pageImage.src = 'data:image/png;base64,' + screenshot;
|
|
899
875
|
pageImage.onload = async () => {
|
|
900
876
|
const scale = pageImage.naturalWidth / this.screenRect().width;
|
|
901
|
-
const outlineRectFromModel = this.outlineRect();
|
|
902
|
-
if (!outlineRectFromModel) {
|
|
903
|
-
throw new Error('Unable to take screenshot: no outlineRect available.');
|
|
904
|
-
}
|
|
905
|
-
const outlineRect = outlineRectFromModel.scale(scale);
|
|
906
877
|
const screenRect = this.screenRect().scale(scale);
|
|
907
878
|
const visiblePageRect = this.visiblePageRect().scale(scale);
|
|
908
|
-
const contentLeft =
|
|
909
|
-
const contentTop =
|
|
879
|
+
const contentLeft = visiblePageRect.left;
|
|
880
|
+
const contentTop = visiblePageRect.top;
|
|
910
881
|
|
|
911
|
-
const canvas = new OffscreenCanvas(Math.floor(
|
|
882
|
+
const canvas = new OffscreenCanvas(Math.floor(screenRect.width),
|
|
912
883
|
// Cap the height to not hit the GPU limit.
|
|
913
884
|
// https://crbug.com/1260828
|
|
914
|
-
Math.min((1 << 14), Math.floor(
|
|
885
|
+
Math.min((1 << 14), Math.floor(screenRect.height)));
|
|
915
886
|
const ctx = canvas.getContext('2d', {willReadFrequently: true});
|
|
916
887
|
if (!ctx) {
|
|
917
888
|
throw new Error('Could not get 2d context from canvas.');
|
|
918
889
|
}
|
|
919
890
|
ctx.imageSmoothingEnabled = false;
|
|
920
891
|
|
|
921
|
-
if (this.screenImage()) {
|
|
922
|
-
await this.paintImage(ctx, this.screenImage(), screenRect.relativeTo(outlineRect));
|
|
923
|
-
}
|
|
924
892
|
ctx.drawImage(pageImage, Math.floor(contentLeft), Math.floor(contentTop));
|
|
925
893
|
void this.saveScreenshot(canvas);
|
|
926
894
|
};
|
|
@@ -976,17 +944,41 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
976
944
|
|
|
977
945
|
private async saveScreenshot(canvas: OffscreenCanvas): Promise<void> {
|
|
978
946
|
const url = this.inspectedURL();
|
|
979
|
-
let
|
|
947
|
+
let baseName = '';
|
|
980
948
|
if (url) {
|
|
981
|
-
const
|
|
982
|
-
|
|
949
|
+
const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);
|
|
950
|
+
if (parsedURL) {
|
|
951
|
+
const host = parsedURL.host;
|
|
952
|
+
const path = parsedURL.path.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
953
|
+
baseName = host;
|
|
954
|
+
if (path) {
|
|
955
|
+
baseName += '-' + path.replaceAll('/', '-');
|
|
956
|
+
}
|
|
957
|
+
baseName = baseName.replace(/[^a-z0-9._-]/gi, '_');
|
|
958
|
+
}
|
|
983
959
|
}
|
|
984
960
|
|
|
961
|
+
if (!baseName) {
|
|
962
|
+
baseName = 'screenshot';
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
let suffix = '';
|
|
985
966
|
const device = this.device();
|
|
986
967
|
if (device && this.type() === Type.Device) {
|
|
987
|
-
|
|
968
|
+
suffix += `(${device.title})`;
|
|
969
|
+
}
|
|
970
|
+
suffix += '.png';
|
|
971
|
+
|
|
972
|
+
// The Windows save dialog / Chrome wrapper limits the suggested filename
|
|
973
|
+
// to 63 characters (due to a 64-byte null-terminated buffer).
|
|
974
|
+
// Capping the total filename length at 63 avoids truncation of the extension.
|
|
975
|
+
const maxBaseNameLength = Math.max(0, 63 - suffix.length);
|
|
976
|
+
baseName = Platform.StringUtilities.truncateToCodeUnitLength(baseName, maxBaseNameLength);
|
|
977
|
+
|
|
978
|
+
let fileName = baseName + suffix;
|
|
979
|
+
if (fileName.length > 63) {
|
|
980
|
+
fileName = Platform.StringUtilities.truncateToCodeUnitLength(fileName, 59) + '.png';
|
|
988
981
|
}
|
|
989
|
-
fileName += '.png';
|
|
990
982
|
const blob = await canvas.convertToBlob({type: 'image/png'});
|
|
991
983
|
const dataUrl = await new Promise<string>((resolve, reject) => {
|
|
992
984
|
const reader = new FileReader();
|
|
@@ -996,11 +988,8 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
996
988
|
});
|
|
997
989
|
const base64 = dataUrl.slice(dataUrl.indexOf(',') + 1);
|
|
998
990
|
const contentData = new TextUtils.ContentData.ContentData(base64, /* isBase64=*/ true, 'image/png');
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
contentData, /* forceSaveAs=*/ true);
|
|
1002
|
-
// eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
|
|
1003
|
-
Workspace.FileManager.FileManager.instance().close(fileName as Platform.DevToolsPath.RawPathString);
|
|
991
|
+
await this.#fileManager.save(fileName as Platform.DevToolsPath.RawPathString, contentData, /* forceSaveAs=*/ true);
|
|
992
|
+
this.#fileManager.close(fileName as Platform.DevToolsPath.RawPathString);
|
|
1004
993
|
}
|
|
1005
994
|
|
|
1006
995
|
private applyTouch(touchEnabled: boolean, mobile: boolean): void {
|
|
@@ -48,12 +48,6 @@ const str_ = i18n.i18n.registerUIStrings('models/emulation/EmulatedDevices.ts',
|
|
|
48
48
|
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
|
49
49
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
50
50
|
|
|
51
|
-
export function computeRelativeImageURL(cssURLValue: string): string {
|
|
52
|
-
return cssURLValue.replace(/@url\(([^\)]*?)\)/g, (_match: string, url: string) => {
|
|
53
|
-
return new URL(`../../emulated_devices/${url}`, import.meta.url).toString();
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
51
|
export class EmulatedDevice {
|
|
58
52
|
title: string;
|
|
59
53
|
type: Type;
|
|
@@ -75,8 +69,8 @@ export class EmulatedDevice {
|
|
|
75
69
|
constructor() {
|
|
76
70
|
this.title = '';
|
|
77
71
|
this.type = Type.Unknown;
|
|
78
|
-
this.vertical = {width: 0, height: 0,
|
|
79
|
-
this.horizontal = {width: 0, height: 0,
|
|
72
|
+
this.vertical = {width: 0, height: 0, hinge: null};
|
|
73
|
+
this.horizontal = {width: 0, height: 0, hinge: null};
|
|
80
74
|
this.deviceScaleFactor = 1;
|
|
81
75
|
this.capabilities = [Capability.TOUCH, Capability.MOBILE];
|
|
82
76
|
this.userAgent = '';
|
|
@@ -85,8 +79,8 @@ export class EmulatedDevice {
|
|
|
85
79
|
|
|
86
80
|
this.isDualScreen = false;
|
|
87
81
|
this.isFoldableScreen = false;
|
|
88
|
-
this.verticalSpanned = {width: 0, height: 0,
|
|
89
|
-
this.horizontalSpanned = {width: 0, height: 0,
|
|
82
|
+
this.verticalSpanned = {width: 0, height: 0, hinge: null};
|
|
83
|
+
this.horizontalSpanned = {width: 0, height: 0, hinge: null};
|
|
90
84
|
|
|
91
85
|
this.#show = Show.Default;
|
|
92
86
|
this.#showByDefault = true;
|
|
@@ -202,15 +196,6 @@ export class EmulatedDevice {
|
|
|
202
196
|
throw new Error('Emulated device has wrong height: ' + result.height);
|
|
203
197
|
}
|
|
204
198
|
|
|
205
|
-
const outlineInsets = parseValue(json['outline'], 'insets', 'object', null);
|
|
206
|
-
if (outlineInsets) {
|
|
207
|
-
result.outlineInsets = parseInsets(outlineInsets);
|
|
208
|
-
if (result.outlineInsets.left < 0 || result.outlineInsets.top < 0) {
|
|
209
|
-
throw new Error('Emulated device has wrong outline insets');
|
|
210
|
-
}
|
|
211
|
-
result.outlineImage = (parseValue(json['outline'], 'image', 'string') as string);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
199
|
if (json['hinge']) {
|
|
215
200
|
result.hinge = parseHinge(parseValue(json, 'hinge', 'object', undefined));
|
|
216
201
|
}
|
|
@@ -282,9 +267,10 @@ export class EmulatedDevice {
|
|
|
282
267
|
if (mode.insets.top < 0 || mode.insets.left < 0 || mode.insets.right < 0 || mode.insets.bottom < 0 ||
|
|
283
268
|
mode.insets.top + mode.insets.bottom > orientation.height ||
|
|
284
269
|
mode.insets.left + mode.insets.right > orientation.width) {
|
|
285
|
-
throw new Error(
|
|
270
|
+
throw new Error(
|
|
271
|
+
'Emulated device mode \'' + mode.title + '\'has wrong mode insets',
|
|
272
|
+
);
|
|
286
273
|
}
|
|
287
|
-
mode.image = (parseValue(modes[i], 'image', 'string', null) as string);
|
|
288
274
|
const safeAreaInsets = parseValue(modes[i], 'safe-area-insets', 'object', null);
|
|
289
275
|
if (safeAreaInsets) {
|
|
290
276
|
mode.safeAreaInsets = parseInsets(safeAreaInsets);
|
|
@@ -419,7 +405,6 @@ export class EmulatedDevice {
|
|
|
419
405
|
right: this.modes[i].insets.right,
|
|
420
406
|
bottom: this.modes[i].insets.bottom,
|
|
421
407
|
},
|
|
422
|
-
image: this.modes[i].image || undefined,
|
|
423
408
|
};
|
|
424
409
|
const safeAreaInsets = this.modes[i].safeAreaInsets;
|
|
425
410
|
if (safeAreaInsets) {
|
|
@@ -469,17 +454,7 @@ export class EmulatedDevice {
|
|
|
469
454
|
const json = {} as any;
|
|
470
455
|
json['width'] = orientation.width;
|
|
471
456
|
json['height'] = orientation.height;
|
|
472
|
-
|
|
473
|
-
json.outline = {
|
|
474
|
-
insets: {
|
|
475
|
-
left: orientation.outlineInsets.left,
|
|
476
|
-
top: orientation.outlineInsets.top,
|
|
477
|
-
right: orientation.outlineInsets.right,
|
|
478
|
-
bottom: orientation.outlineInsets.bottom,
|
|
479
|
-
},
|
|
480
|
-
image: orientation.outlineImage,
|
|
481
|
-
} as {image: string | null, insets: {left: number, right: number, top: number, bottom: number}};
|
|
482
|
-
}
|
|
457
|
+
|
|
483
458
|
if (orientation.hinge) {
|
|
484
459
|
json.hinge = {
|
|
485
460
|
width: orientation.hinge.width,
|
|
@@ -515,21 +490,6 @@ export class EmulatedDevice {
|
|
|
515
490
|
return json;
|
|
516
491
|
}
|
|
517
492
|
|
|
518
|
-
modeImage(mode: Mode): string {
|
|
519
|
-
if (!mode.image) {
|
|
520
|
-
return '';
|
|
521
|
-
}
|
|
522
|
-
return computeRelativeImageURL(mode.image);
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
outlineImage(mode: Mode): string {
|
|
526
|
-
const orientation = this.orientationByName(mode.orientation);
|
|
527
|
-
if (!orientation.outlineImage) {
|
|
528
|
-
return '';
|
|
529
|
-
}
|
|
530
|
-
return computeRelativeImageURL(orientation.outlineImage);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
493
|
orientationByName(name: string): Orientation {
|
|
534
494
|
switch (name) {
|
|
535
495
|
case VerticalSpanned:
|
|
@@ -688,8 +648,16 @@ export class EmulatedDevicesList extends Common.ObjectWrapper.ObjectWrapper<Even
|
|
|
688
648
|
if (device) {
|
|
689
649
|
result.add(device);
|
|
690
650
|
if (!device.modes.length) {
|
|
691
|
-
device.modes.push({
|
|
692
|
-
|
|
651
|
+
device.modes.push({
|
|
652
|
+
title: '',
|
|
653
|
+
orientation: Horizontal,
|
|
654
|
+
insets: new Insets(0, 0, 0, 0),
|
|
655
|
+
});
|
|
656
|
+
device.modes.push({
|
|
657
|
+
title: '',
|
|
658
|
+
orientation: Vertical,
|
|
659
|
+
insets: new Insets(0, 0, 0, 0),
|
|
660
|
+
});
|
|
693
661
|
}
|
|
694
662
|
} else {
|
|
695
663
|
success = false;
|
|
@@ -769,7 +737,6 @@ export interface Mode {
|
|
|
769
737
|
title: string;
|
|
770
738
|
orientation: string;
|
|
771
739
|
insets: Insets;
|
|
772
|
-
image: string|null;
|
|
773
740
|
safeAreaInsets?: Insets;
|
|
774
741
|
cutout?: Cutout;
|
|
775
742
|
}
|
|
@@ -791,14 +758,11 @@ export type Cutout = BaseCutout&({shape: CutoutShape.RECTANGLE}|{shape: CutoutSh
|
|
|
791
758
|
export interface Orientation {
|
|
792
759
|
width: number;
|
|
793
760
|
height: number;
|
|
794
|
-
outlineInsets: Insets|null;
|
|
795
|
-
outlineImage: string|null;
|
|
796
761
|
hinge: SDK.OverlayModel.Hinge|null;
|
|
797
762
|
}
|
|
798
763
|
export interface JSONMode {
|
|
799
764
|
title: string;
|
|
800
765
|
orientation: string;
|
|
801
|
-
image?: string;
|
|
802
766
|
insets: {
|
|
803
767
|
left: number,
|
|
804
768
|
right: number,
|
|
@@ -2136,10 +2100,6 @@ const emulatedDevices = [
|
|
|
2136
2100
|
'title': 'Nest Hub Max',
|
|
2137
2101
|
'screen': {
|
|
2138
2102
|
'horizontal': {
|
|
2139
|
-
'outline': {
|
|
2140
|
-
'image': '@url(optimized/google-nest-hub-max-horizontal.avif)',
|
|
2141
|
-
'insets': {'left': 92, 'top': 96, 'right': 91, 'bottom': 248},
|
|
2142
|
-
},
|
|
2143
2103
|
'width': 1280,
|
|
2144
2104
|
'height': 800,
|
|
2145
2105
|
},
|
|
@@ -2249,19 +2209,11 @@ const emulatedDevices = [
|
|
|
2249
2209
|
'title': 'Moto G4',
|
|
2250
2210
|
'screen': {
|
|
2251
2211
|
'horizontal': {
|
|
2252
|
-
'outline': {
|
|
2253
|
-
'image': '@url(optimized/MotoG4-landscape.avif)',
|
|
2254
|
-
'insets': {'left': 91, 'top': 30, 'right': 74, 'bottom': 30},
|
|
2255
|
-
},
|
|
2256
2212
|
'width': 640,
|
|
2257
2213
|
'height': 360,
|
|
2258
2214
|
},
|
|
2259
2215
|
'device-pixel-ratio': 3,
|
|
2260
2216
|
'vertical': {
|
|
2261
|
-
'outline': {
|
|
2262
|
-
'image': '@url(optimized/MotoG4-portrait.avif)',
|
|
2263
|
-
'insets': {'left': 30, 'top': 91, 'right': 30, 'bottom': 74},
|
|
2264
|
-
},
|
|
2265
2217
|
'width': 360,
|
|
2266
2218
|
'height': 640,
|
|
2267
2219
|
},
|
|
@@ -113,12 +113,12 @@ export class AutomaticFileSystemManager extends Common.ObjectWrapper.ObjectWrapp
|
|
|
113
113
|
*/
|
|
114
114
|
static removeInstance(): void {
|
|
115
115
|
if (Root.DevToolsContext.globalInstance().has(AutomaticFileSystemManager)) {
|
|
116
|
-
Root.DevToolsContext.globalInstance().get(AutomaticFileSystemManager)
|
|
116
|
+
Root.DevToolsContext.globalInstance().get(AutomaticFileSystemManager).dispose();
|
|
117
117
|
Root.DevToolsContext.globalInstance().delete(AutomaticFileSystemManager);
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
dispose(): void {
|
|
122
122
|
this.#inspectorFrontendHost.events.removeEventListener(
|
|
123
123
|
Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this.#fileSystemRemoved, this);
|
|
124
124
|
this.#projectSettingsModel.removeEventListener(
|
|
@@ -35,6 +35,7 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
|
|
|
35
35
|
private readonly fileSystemsLoadedPromise: Promise<IsolatedFileSystem[]>;
|
|
36
36
|
readonly #settings: Common.Settings.Settings;
|
|
37
37
|
readonly #console: Common.Console.Console;
|
|
38
|
+
readonly #eventDescriptors: Common.EventTarget.EventDescriptor[];
|
|
38
39
|
constructor(settings: Common.Settings.Settings, console: Common.Console.Console) {
|
|
39
40
|
super();
|
|
40
41
|
this.#settings = settings;
|
|
@@ -44,20 +45,22 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
|
|
|
44
45
|
this.callbacks = new Map();
|
|
45
46
|
this.progresses = new Map();
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
48
|
+
this.#eventDescriptors = [
|
|
49
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
50
|
+
Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this.onFileSystemRemoved, this),
|
|
51
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
52
|
+
Host.InspectorFrontendHostAPI.Events.FileSystemAdded, this.onFileSystemAdded, this),
|
|
53
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
54
|
+
Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, this.onFileSystemFilesChanged, this),
|
|
55
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
56
|
+
Host.InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this.onIndexingTotalWorkCalculated, this),
|
|
57
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
58
|
+
Host.InspectorFrontendHostAPI.Events.IndexingWorked, this.onIndexingWorked, this),
|
|
59
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
60
|
+
Host.InspectorFrontendHostAPI.Events.IndexingDone, this.onIndexingDone, this),
|
|
61
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
62
|
+
Host.InspectorFrontendHostAPI.Events.SearchCompleted, this.onSearchCompleted, this),
|
|
63
|
+
];
|
|
61
64
|
|
|
62
65
|
// Initialize exclude pattern settings
|
|
63
66
|
const defaultCommonExcludedFolders = [
|
|
@@ -101,20 +104,7 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
|
|
|
101
104
|
|
|
102
105
|
// TODO(crbug.com/542394587): Should be `Symbol.dispsoe`
|
|
103
106
|
dispose(): void {
|
|
104
|
-
|
|
105
|
-
Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this.onFileSystemRemoved, this);
|
|
106
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.removeEventListener(
|
|
107
|
-
Host.InspectorFrontendHostAPI.Events.FileSystemAdded, this.onFileSystemAdded, this);
|
|
108
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.removeEventListener(
|
|
109
|
-
Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, this.onFileSystemFilesChanged, this);
|
|
110
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.removeEventListener(
|
|
111
|
-
Host.InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this.onIndexingTotalWorkCalculated, this);
|
|
112
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.removeEventListener(
|
|
113
|
-
Host.InspectorFrontendHostAPI.Events.IndexingWorked, this.onIndexingWorked, this);
|
|
114
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.removeEventListener(
|
|
115
|
-
Host.InspectorFrontendHostAPI.Events.IndexingDone, this.onIndexingDone, this);
|
|
116
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.removeEventListener(
|
|
117
|
-
Host.InspectorFrontendHostAPI.Events.SearchCompleted, this.onSearchCompleted, this);
|
|
107
|
+
Common.EventTarget.removeEventListeners(this.#eventDescriptors);
|
|
118
108
|
}
|
|
119
109
|
|
|
120
110
|
static instance(opts: {
|
|
@@ -141,8 +131,9 @@ export class IsolatedFileSystemManager extends Common.ObjectWrapper.ObjectWrappe
|
|
|
141
131
|
|
|
142
132
|
private requestFileSystems(): Promise<IsolatedFileSystem[]> {
|
|
143
133
|
const {resolve, promise} = Promise.withResolvers<IsolatedFileSystem[]>();
|
|
144
|
-
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
134
|
+
const descriptor = Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
145
135
|
Host.InspectorFrontendHostAPI.Events.FileSystemsLoaded, onFileSystemsLoaded, this);
|
|
136
|
+
this.#eventDescriptors.push(descriptor);
|
|
146
137
|
Host.InspectorFrontendHost.InspectorFrontendHostInstance.requestFileSystems();
|
|
147
138
|
return promise;
|
|
148
139
|
|
|
@@ -15,14 +15,21 @@ export interface SaveCallbackParam {
|
|
|
15
15
|
export class FileManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
|
|
16
16
|
readonly #saveCallbacks = new Map<
|
|
17
17
|
Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, (arg0: SaveCallbackParam|null) => void>();
|
|
18
|
+
readonly #eventDescriptors: Common.EventTarget.EventDescriptor[];
|
|
18
19
|
constructor() {
|
|
19
20
|
super();
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
this.#eventDescriptors = [
|
|
22
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
23
|
+
Host.InspectorFrontendHostAPI.Events.SavedURL, this.savedURL, this),
|
|
24
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
25
|
+
Host.InspectorFrontendHostAPI.Events.CanceledSaveURL, this.#canceledSavedURL, this),
|
|
26
|
+
Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
|
|
27
|
+
Host.InspectorFrontendHostAPI.Events.AppendedToURL, this.appendedToURL, this),
|
|
28
|
+
];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
dispose(): void {
|
|
32
|
+
Common.EventTarget.removeEventListeners(this.#eventDescriptors);
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
static instance(opts: {forceNew: boolean|null} = {forceNew: null}): FileManager {
|
|
@@ -198,6 +198,14 @@ const UIStrings = {
|
|
|
198
198
|
* @description Label for a list of tool flags or attributes
|
|
199
199
|
*/
|
|
200
200
|
flags: 'Flags',
|
|
201
|
+
/**
|
|
202
|
+
* @description Text for the label of the tool description
|
|
203
|
+
*/
|
|
204
|
+
description: 'Description',
|
|
205
|
+
/**
|
|
206
|
+
* @description Text for the label of the tool origin
|
|
207
|
+
*/
|
|
208
|
+
origin: 'Origin',
|
|
201
209
|
} as const;
|
|
202
210
|
const str_ = i18n.i18n.registerUIStrings('panels/application/WebMCPView.ts', UIStrings);
|
|
203
211
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -714,7 +722,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
714
722
|
} as ProtocolMonitor.JSONEditor.Command,
|
|
715
723
|
});
|
|
716
724
|
}
|
|
717
|
-
}}
|
|
725
|
+
}}>${i18nString(UIStrings.runTool)}</devtools-button>
|
|
718
726
|
` : nothing}
|
|
719
727
|
</div>
|
|
720
728
|
</devtools-split-view>
|
|
@@ -1124,9 +1132,9 @@ const TOOL_DETAILS_VIEW = (input: ToolDetailsViewInput, output: undefined, targe
|
|
|
1124
1132
|
render(html`
|
|
1125
1133
|
<style>${webMCPViewStyles}</style>
|
|
1126
1134
|
<div class="tool-details-grid">
|
|
1127
|
-
<div class="label"
|
|
1135
|
+
<div class="label">${i18nString(UIStrings.name)}</div>
|
|
1128
1136
|
<div class="value source-code">${tool.name}</div>
|
|
1129
|
-
<div class="label"
|
|
1137
|
+
<div class="label">${i18nString(UIStrings.description)}</div>
|
|
1130
1138
|
<div class="value">${tool.description}</div>
|
|
1131
1139
|
${flags.length > 0 ? html`
|
|
1132
1140
|
<div class="label">${i18nString(UIStrings.flags)}</div>
|
|
@@ -1137,7 +1145,7 @@ const TOOL_DETAILS_VIEW = (input: ToolDetailsViewInput, output: undefined, targe
|
|
|
1137
1145
|
<div class="value">${Components.Linkifier.Linkifier.linkifyRevealable(tool.frame, tool.frame.displayName())}</div>
|
|
1138
1146
|
` : nothing}
|
|
1139
1147
|
${origin instanceof SDK.DOMModel.DOMNode ? html`
|
|
1140
|
-
<div class="label"
|
|
1148
|
+
<div class="label">${i18nString(UIStrings.origin)}</div>
|
|
1141
1149
|
<div class="value tool-origin-container">
|
|
1142
1150
|
<span
|
|
1143
1151
|
class="node-text-container source-code tool-origin-node"
|
|
@@ -1161,7 +1169,7 @@ const TOOL_DETAILS_VIEW = (input: ToolDetailsViewInput, output: undefined, targe
|
|
|
1161
1169
|
@click=${() => input.revealNode(origin)}
|
|
1162
1170
|
></devtools-button>
|
|
1163
1171
|
</div>` : origin ? html`
|
|
1164
|
-
<div class="label"
|
|
1172
|
+
<div class="label">${i18nString(UIStrings.origin)}</div>
|
|
1165
1173
|
<div class="value stack-trace">
|
|
1166
1174
|
${widget(Components.JSPresentationUtils.StackTracePreviewContent,
|
|
1167
1175
|
{stackTrace: origin, options: { expandable: true}})}
|