chrome-devtools-frontend 1.0.1593518 → 1.0.1593959
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/docs/contributing/settings-experiments-features.md +75 -100
- package/front_end/core/host/UserMetrics.ts +1 -2
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/EmulationModel.ts +41 -1
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/generated/InspectorBackendCommands.ts +6 -4
- package/front_end/generated/protocol-mapping.d.ts +7 -0
- package/front_end/generated/protocol-proxy-api.d.ts +5 -0
- package/front_end/generated/protocol.ts +47 -0
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +1 -0
- package/front_end/models/emulation/DeviceModeModel.ts +47 -0
- package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
- package/front_end/models/issues_manager/IssuesManager.ts +0 -5
- package/front_end/models/issues_manager/issues_manager.ts +0 -4
- package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
- package/front_end/models/lighthouse/lighthouse.ts +9 -0
- package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +3 -0
- package/front_end/panels/common/AiCodeGenerationTeaser.ts +3 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +1 -6
- package/front_end/panels/elements/StylesSidebarPane.ts +79 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +206 -66
- package/front_end/panels/issues/HiddenIssuesRow.ts +1 -1
- package/front_end/panels/issues/IssueKindView.ts +2 -1
- package/front_end/panels/issues/IssueView.ts +2 -4
- package/front_end/panels/issues/IssuesPane.ts +2 -2
- package/front_end/panels/lighthouse/LighthouseController.ts +3 -3
- package/front_end/panels/lighthouse/LighthousePanel.ts +9 -5
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +5 -5
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +6 -7
- package/front_end/panels/lighthouse/LighthouseReportSelector.ts +4 -3
- package/front_end/panels/lighthouse/lighthouse.ts +0 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/deno.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +2 -2
- package/front_end/ui/legacy/SuggestBox.ts +4 -0
- package/front_end/ui/legacy/TextPrompt.ts +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +15 -0
- package/inspector_overlay/highlight_grid_common.ts +11 -8
- package/package.json +1 -1
- package/front_end/models/issues_manager/ContrastCheckTrigger.ts +0 -78
- package/front_end/models/issues_manager/LowTextContrastIssue.ts +0 -63
- package/front_end/panels/issues/AffectedElementsWithLowContrastView.ts +0 -91
- /package/front_end/{panels → models}/lighthouse/LighthouseReporterTypes.ts +0 -0
|
@@ -10,6 +10,7 @@ import * as Host from '../../core/host/host.js';
|
|
|
10
10
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
11
11
|
import * as Platform from '../../core/platform/platform.js';
|
|
12
12
|
import * as EmulationModel from '../../models/emulation/emulation.js';
|
|
13
|
+
import * as uiI18n from '../../ui/i18n/i18n.js';
|
|
13
14
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
14
15
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
15
16
|
import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
|
|
@@ -19,8 +20,14 @@ const UIStrings = {
|
|
|
19
20
|
/**
|
|
20
21
|
* @description Title of the device dimensions selection item in the Device Mode Toolbar.
|
|
21
22
|
* webpage in pixels.
|
|
23
|
+
* @example {Responsive} PH1
|
|
22
24
|
*/
|
|
23
|
-
dimensions: 'Dimensions',
|
|
25
|
+
dimensions: 'Dimensions: {PH1}',
|
|
26
|
+
/**
|
|
27
|
+
* @description Title of the device pixel ratio selection item in the Device Mode Toolbar.
|
|
28
|
+
* @example {2.0} PH1
|
|
29
|
+
*/
|
|
30
|
+
dpr: 'DPR: {PH1}',
|
|
24
31
|
/**
|
|
25
32
|
* @description Title of the width input textbox in the Device Mode Toolbar, for the width of the
|
|
26
33
|
* webpage in pixels.
|
|
@@ -53,12 +60,12 @@ const UIStrings = {
|
|
|
53
60
|
*/
|
|
54
61
|
moreOptions: 'More options',
|
|
55
62
|
/**
|
|
56
|
-
* @description A
|
|
57
|
-
*
|
|
58
|
-
*
|
|
63
|
+
* @description A menu item in the drop-down box that allows the user to select the zoom level.
|
|
64
|
+
* Labels the value which corresponds to the 'fit to window' zoom level, represented by the
|
|
65
|
+
* placeholder, which is a number. In the Device Mode Toolbar.
|
|
59
66
|
* @example {30.0} PH1
|
|
60
67
|
*/
|
|
61
|
-
|
|
68
|
+
fitToWindowPercentage: '{PH1}% (fit to window)',
|
|
62
69
|
/**
|
|
63
70
|
* @description A checkbox setting that appears in the context menu for the zoom level, in the
|
|
64
71
|
* Device Mode Toolbar.
|
|
@@ -70,7 +77,7 @@ const UIStrings = {
|
|
|
70
77
|
* placeholder, which is a number. In the Device Mode Toolbar.
|
|
71
78
|
* @example {4.3} PH1
|
|
72
79
|
*/
|
|
73
|
-
defaultF: '
|
|
80
|
+
defaultF: '{PH1} (default)',
|
|
74
81
|
/**
|
|
75
82
|
* @description Command to hide the frame (like a picture frame) around the mobile device screen.
|
|
76
83
|
*/
|
|
@@ -163,6 +170,11 @@ const UIStrings = {
|
|
|
163
170
|
* @description Tooltip of the rotate/screen orientation button.
|
|
164
171
|
*/
|
|
165
172
|
screenOrientationOptions: 'Screen orientation options',
|
|
173
|
+
/**
|
|
174
|
+
* @description Tooltip shown on the rotate button when screen orientation is locked by the page
|
|
175
|
+
* via screen.orientation.lock().
|
|
176
|
+
*/
|
|
177
|
+
screenOrientationLocked: 'Screen orientation is locked by the page',
|
|
166
178
|
/**
|
|
167
179
|
* @description Tooltip for a button which turns on/off dual-screen mode, which emulates devices
|
|
168
180
|
* like tablets which have two screens.
|
|
@@ -284,6 +296,9 @@ export class DeviceModeToolbar {
|
|
|
284
296
|
new UI.Toolbar.ToolbarMenuButton(this.appendDeviceMenuItems.bind(this), undefined, undefined, 'device');
|
|
285
297
|
this.deviceSelectItem.turnShrinkable();
|
|
286
298
|
this.deviceSelectItem.setDarkText();
|
|
299
|
+
const dimensionsSpan =
|
|
300
|
+
uiI18n.getFormatLocalizedString(str_, UIStrings.dimensions, {PH1: this.deviceSelectItem.element});
|
|
301
|
+
mainToolbar.append(...dimensionsSpan.childNodes);
|
|
287
302
|
mainToolbar.appendToolbarItem(this.deviceSelectItem);
|
|
288
303
|
|
|
289
304
|
this.widthInput.addEventListener('sizechanged', ({size: width}) => {
|
|
@@ -315,6 +330,11 @@ export class DeviceModeToolbar {
|
|
|
315
330
|
this.scaleItem.turnShrinkable();
|
|
316
331
|
this.scaleItem.setDarkText();
|
|
317
332
|
mainToolbar.appendToolbarItem(this.scaleItem);
|
|
333
|
+
|
|
334
|
+
const autoAdjustScaleButton = new UI.Toolbar.ToolbarSettingToggle(
|
|
335
|
+
this.autoAdjustScaleSetting, 'center-focus-weak', i18nString(UIStrings.autoadjustZoom));
|
|
336
|
+
mainToolbar.appendToolbarItem(autoAdjustScaleButton);
|
|
337
|
+
|
|
318
338
|
mainToolbar.appendToolbarItem(new UI.Toolbar.ToolbarItem(this.createEmptyToolbarElement()));
|
|
319
339
|
|
|
320
340
|
this.deviceScaleItem = new UI.Toolbar.ToolbarMenuButton(
|
|
@@ -323,6 +343,8 @@ export class DeviceModeToolbar {
|
|
|
323
343
|
this.deviceScaleItem.setVisible(this.showDeviceScaleFactorSetting.get());
|
|
324
344
|
setTitleForButton(this.deviceScaleItem, i18nString(UIStrings.devicePixelRatio));
|
|
325
345
|
this.deviceScaleItem.setDarkText();
|
|
346
|
+
const deviceScaleSpan = uiI18n.getFormatLocalizedString(str_, UIStrings.dpr, {PH1: this.deviceScaleItem.element});
|
|
347
|
+
mainToolbar.append(...deviceScaleSpan.childNodes);
|
|
326
348
|
mainToolbar.appendToolbarItem(this.deviceScaleItem);
|
|
327
349
|
mainToolbar.appendToolbarItem(new UI.Toolbar.ToolbarItem(this.createEmptyToolbarElement()));
|
|
328
350
|
this.uaItem =
|
|
@@ -374,11 +396,16 @@ export class DeviceModeToolbar {
|
|
|
374
396
|
return optionsToolbar;
|
|
375
397
|
}
|
|
376
398
|
|
|
399
|
+
private getDevicePostureOptions(): Array<{title: string, value: string, selected: boolean}> {
|
|
400
|
+
const currentPosture = this.currentDevicePosture();
|
|
401
|
+
return ['Continuous', 'Folded'].map(title => ({title, value: title, selected: currentPosture === title}));
|
|
402
|
+
}
|
|
403
|
+
|
|
377
404
|
private appendDevicePostureItems(contextMenu: UI.ContextMenu.ContextMenu): void {
|
|
378
|
-
for (const
|
|
405
|
+
for (const option of this.getDevicePostureOptions()) {
|
|
379
406
|
contextMenu.defaultSection().appendCheckboxItem(
|
|
380
|
-
title, this.spanClicked.bind(this),
|
|
381
|
-
{checked:
|
|
407
|
+
option.title, this.spanClicked.bind(this),
|
|
408
|
+
{checked: option.selected, jslogContext: option.title.toLowerCase()});
|
|
382
409
|
}
|
|
383
410
|
}
|
|
384
411
|
|
|
@@ -392,27 +419,43 @@ export class DeviceModeToolbar {
|
|
|
392
419
|
return 'Continuous';
|
|
393
420
|
}
|
|
394
421
|
|
|
395
|
-
private
|
|
422
|
+
private getScaleOptions(): Array<{title: string, value: number, selected: boolean, jslogContext: string}> {
|
|
423
|
+
const values = [0.5, 0.75, 1, 1.25, 1.5, 2];
|
|
424
|
+
let fitValue: number|null = null;
|
|
396
425
|
if (this.model.type() === EmulationModel.DeviceModeModel.Type.Device) {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
426
|
+
fitValue = this.model.fitScale();
|
|
427
|
+
const fitValuePct = (fitValue * 100).toFixed(0);
|
|
428
|
+
let found = false;
|
|
429
|
+
for (let i = 0; i < values.length; ++i) {
|
|
430
|
+
if ((values[i] * 100).toFixed(0) === fitValuePct) {
|
|
431
|
+
found = true;
|
|
432
|
+
values[i] = fitValue;
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (!found) {
|
|
437
|
+
values.push(fitValue);
|
|
438
|
+
values.sort((a, b) => a - b);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
const currentScale = this.model.scaleSetting().get();
|
|
443
|
+
return values.map(value => {
|
|
444
|
+
let title = (value * 100).toFixed(0) + '%';
|
|
445
|
+
let jslogContext = title;
|
|
446
|
+
if (value === fitValue) {
|
|
447
|
+
title = i18nString(UIStrings.fitToWindowPercentage, {PH1: (value * 100).toFixed(0)});
|
|
448
|
+
jslogContext = 'fit-to-window';
|
|
449
|
+
}
|
|
450
|
+
return {title, value, selected: currentScale === value, jslogContext};
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
private appendScaleMenuItems(contextMenu: UI.ContextMenu.ContextMenu): void {
|
|
455
|
+
for (const option of this.getScaleOptions()) {
|
|
413
456
|
contextMenu.defaultSection().appendCheckboxItem(
|
|
414
|
-
title, this.onScaleMenuChanged.bind(this, value),
|
|
415
|
-
{checked:
|
|
457
|
+
option.title, this.onScaleMenuChanged.bind(this, option.value),
|
|
458
|
+
{checked: option.selected, jslogContext: option.jslogContext});
|
|
416
459
|
}
|
|
417
460
|
}
|
|
418
461
|
|
|
@@ -420,41 +463,68 @@ export class DeviceModeToolbar {
|
|
|
420
463
|
this.model.scaleSetting().set(value);
|
|
421
464
|
}
|
|
422
465
|
|
|
423
|
-
private
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
private appendDeviceScaleMenuItems(contextMenu: UI.ContextMenu.ContextMenu): void {
|
|
466
|
+
private getDeviceScaleFactorOptions():
|
|
467
|
+
Array<{title: string, value: number, selected: boolean, jslogContext: string}> {
|
|
428
468
|
const deviceScaleFactorSetting = this.model.deviceScaleFactorSetting();
|
|
429
469
|
const defaultValue = this.model.uaSetting().get() === EmulationModel.DeviceModeModel.UA.MOBILE ||
|
|
430
470
|
this.model.uaSetting().get() === EmulationModel.DeviceModeModel.UA.MOBILE_NO_TOUCH ?
|
|
431
471
|
EmulationModel.DeviceModeModel.defaultMobileScaleFactor :
|
|
432
472
|
window.devicePixelRatio;
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
473
|
+
const values = [1, 2, 3];
|
|
474
|
+
if (!values.includes(defaultValue)) {
|
|
475
|
+
values.push(defaultValue);
|
|
476
|
+
values.sort((a, b) => a - b);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const currentDPR = deviceScaleFactorSetting.get();
|
|
480
|
+
return values.map(value => {
|
|
481
|
+
let title = String(value);
|
|
482
|
+
let jslogContext = `dpr-${value}`;
|
|
483
|
+
if (value === defaultValue) {
|
|
484
|
+
title = i18nString(UIStrings.defaultF, {PH1: value});
|
|
485
|
+
jslogContext = 'dpr-default';
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
title,
|
|
489
|
+
value: value === defaultValue ? 0 : value,
|
|
490
|
+
selected: currentDPR === value || (value === defaultValue && currentDPR === 0),
|
|
491
|
+
jslogContext
|
|
492
|
+
};
|
|
493
|
+
});
|
|
494
|
+
}
|
|
438
495
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
496
|
+
private appendDeviceScaleMenuItems(contextMenu: UI.ContextMenu.ContextMenu): void {
|
|
497
|
+
const deviceScaleFactorSetting = this.model.deviceScaleFactorSetting();
|
|
498
|
+
for (const option of this.getDeviceScaleFactorOptions()) {
|
|
499
|
+
contextMenu.defaultSection().appendCheckboxItem(
|
|
500
|
+
option.title, deviceScaleFactorSetting.set.bind(deviceScaleFactorSetting, option.value),
|
|
501
|
+
{checked: option.selected, jslogContext: option.jslogContext});
|
|
444
502
|
}
|
|
445
503
|
}
|
|
446
504
|
|
|
447
|
-
private
|
|
505
|
+
private getUserAgentOptions():
|
|
506
|
+
Array<{title: string, value: EmulationModel.DeviceModeModel.UA, selected: boolean, jslogContext: string}> {
|
|
448
507
|
const uaSetting = this.model.uaSetting();
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
508
|
+
const currentUserAgent = uaSetting.get();
|
|
509
|
+
return [
|
|
510
|
+
EmulationModel.DeviceModeModel.UA.MOBILE,
|
|
511
|
+
EmulationModel.DeviceModeModel.UA.MOBILE_NO_TOUCH,
|
|
512
|
+
EmulationModel.DeviceModeModel.UA.DESKTOP,
|
|
513
|
+
EmulationModel.DeviceModeModel.UA.DESKTOP_TOUCH,
|
|
514
|
+
].map(value => ({
|
|
515
|
+
title: value,
|
|
516
|
+
value,
|
|
517
|
+
selected: currentUserAgent === value,
|
|
518
|
+
jslogContext: Platform.StringUtilities.toKebabCase(value)
|
|
519
|
+
}));
|
|
520
|
+
}
|
|
453
521
|
|
|
454
|
-
|
|
522
|
+
private appendUserAgentMenuItems(contextMenu: UI.ContextMenu.ContextMenu): void {
|
|
523
|
+
const uaSetting = this.model.uaSetting();
|
|
524
|
+
for (const option of this.getUserAgentOptions()) {
|
|
455
525
|
contextMenu.defaultSection().appendCheckboxItem(
|
|
456
|
-
title, uaSetting.set.bind(uaSetting, value),
|
|
457
|
-
{checked:
|
|
526
|
+
option.title, uaSetting.set.bind(uaSetting, option.value),
|
|
527
|
+
{checked: option.selected, jslogContext: option.jslogContext});
|
|
458
528
|
}
|
|
459
529
|
}
|
|
460
530
|
|
|
@@ -539,25 +609,75 @@ export class DeviceModeToolbar {
|
|
|
539
609
|
return this.standardDevices().concat(this.customDevices());
|
|
540
610
|
}
|
|
541
611
|
|
|
612
|
+
private getDeviceModeOptions(): {
|
|
613
|
+
responsive: {title: string, selected: boolean, jslogContext: string},
|
|
614
|
+
standard: Array<{
|
|
615
|
+
device: EmulationModel.EmulatedDevices.EmulatedDevice,
|
|
616
|
+
title: string,
|
|
617
|
+
selected: boolean,
|
|
618
|
+
jslogContext: string,
|
|
619
|
+
}>,
|
|
620
|
+
custom: Array<{
|
|
621
|
+
device: EmulationModel.EmulatedDevices.EmulatedDevice,
|
|
622
|
+
title: string,
|
|
623
|
+
selected: boolean,
|
|
624
|
+
jslogContext: string,
|
|
625
|
+
}>,
|
|
626
|
+
edit: {title: string, jslogContext: string},
|
|
627
|
+
} {
|
|
628
|
+
return {
|
|
629
|
+
responsive: {
|
|
630
|
+
title: i18nString(UIStrings.responsive),
|
|
631
|
+
selected: this.model.type() === EmulationModel.DeviceModeModel.Type.Responsive,
|
|
632
|
+
jslogContext: 'responsive'
|
|
633
|
+
},
|
|
634
|
+
standard: this.standardDevices().map(device => ({
|
|
635
|
+
device,
|
|
636
|
+
title: device.title,
|
|
637
|
+
selected: this.model.device() === device,
|
|
638
|
+
jslogContext: Platform.StringUtilities.toKebabCase(device.title)
|
|
639
|
+
})),
|
|
640
|
+
custom: this.customDevices().map(device => ({
|
|
641
|
+
device,
|
|
642
|
+
title: device.title,
|
|
643
|
+
selected: this.model.device() === device,
|
|
644
|
+
jslogContext: Platform.StringUtilities.toKebabCase(device.title)
|
|
645
|
+
})),
|
|
646
|
+
edit: {
|
|
647
|
+
title: i18nString(UIStrings.edit),
|
|
648
|
+
jslogContext: 'edit',
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
|
|
542
653
|
private appendDeviceMenuItems(contextMenu: UI.ContextMenu.ContextMenu): void {
|
|
654
|
+
const options = this.getDeviceModeOptions();
|
|
655
|
+
|
|
543
656
|
contextMenu.headerSection().appendCheckboxItem(
|
|
544
|
-
|
|
545
|
-
{checked:
|
|
546
|
-
|
|
547
|
-
appendGroup.call(this,
|
|
548
|
-
|
|
549
|
-
i18nString(UIStrings.edit), this.emulatedDevicesList.revealCustomSetting.bind(this.emulatedDevicesList),
|
|
550
|
-
{jslogContext: 'edit'});
|
|
657
|
+
options.responsive.title, this.switchToResponsive.bind(this),
|
|
658
|
+
{checked: options.responsive.selected, jslogContext: options.responsive.jslogContext});
|
|
659
|
+
|
|
660
|
+
appendGroup.call(this, options.standard);
|
|
661
|
+
appendGroup.call(this, options.custom);
|
|
551
662
|
|
|
552
|
-
|
|
553
|
-
|
|
663
|
+
contextMenu.footerSection().appendItem(
|
|
664
|
+
options.edit.title, this.emulatedDevicesList.revealCustomSetting.bind(this.emulatedDevicesList),
|
|
665
|
+
{jslogContext: options.edit.jslogContext});
|
|
666
|
+
|
|
667
|
+
function appendGroup(this: DeviceModeToolbar, group: Array<{
|
|
668
|
+
device: EmulationModel.EmulatedDevices.EmulatedDevice,
|
|
669
|
+
title: string,
|
|
670
|
+
selected: boolean,
|
|
671
|
+
jslogContext: string,
|
|
672
|
+
}>): void {
|
|
673
|
+
if (!group.length) {
|
|
554
674
|
return;
|
|
555
675
|
}
|
|
556
676
|
const section = contextMenu.section();
|
|
557
|
-
for (const
|
|
558
|
-
section.appendCheckboxItem(
|
|
559
|
-
checked:
|
|
560
|
-
jslogContext:
|
|
677
|
+
for (const item of group) {
|
|
678
|
+
section.appendCheckboxItem(item.title, this.emulateDevice.bind(this, item.device), {
|
|
679
|
+
checked: item.selected,
|
|
680
|
+
jslogContext: item.jslogContext,
|
|
561
681
|
});
|
|
562
682
|
}
|
|
563
683
|
}
|
|
@@ -617,6 +737,9 @@ export class DeviceModeToolbar {
|
|
|
617
737
|
private modeMenuClicked(event: {
|
|
618
738
|
data: Event,
|
|
619
739
|
}): void {
|
|
740
|
+
if (this.model.isScreenOrientationLocked()) {
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
620
743
|
const device = this.model.device();
|
|
621
744
|
const model = this.model;
|
|
622
745
|
const autoAdjustScaleSetting = this.autoAdjustScaleSetting;
|
|
@@ -737,7 +860,7 @@ export class DeviceModeToolbar {
|
|
|
737
860
|
|
|
738
861
|
const deviceScale = this.model.appliedDeviceScaleFactor();
|
|
739
862
|
if (deviceScale !== this.cachedDeviceScale) {
|
|
740
|
-
this.deviceScaleItem.setText(
|
|
863
|
+
this.deviceScaleItem.setText(`${deviceScale.toFixed(1)}`);
|
|
741
864
|
this.cachedDeviceScale = deviceScale;
|
|
742
865
|
}
|
|
743
866
|
|
|
@@ -755,7 +878,7 @@ export class DeviceModeToolbar {
|
|
|
755
878
|
if (this.model.type() === EmulationModel.DeviceModeModel.Type.Device && device) {
|
|
756
879
|
deviceItemTitle = device.title;
|
|
757
880
|
}
|
|
758
|
-
this.deviceSelectItem.setText(
|
|
881
|
+
this.deviceSelectItem.setText(deviceItemTitle);
|
|
759
882
|
|
|
760
883
|
if (this.model.device() !== this.cachedModelDevice) {
|
|
761
884
|
const device = this.model.device();
|
|
@@ -804,6 +927,23 @@ export class DeviceModeToolbar {
|
|
|
804
927
|
}
|
|
805
928
|
this.persistenceSetting.set(value);
|
|
806
929
|
}
|
|
930
|
+
|
|
931
|
+
// When screen orientation is locked by the page (via screen.orientation.lock()),
|
|
932
|
+
// disable the rotate button to prevent user-initiated rotation.
|
|
933
|
+
// When unlocked, restore the button to its normal state.
|
|
934
|
+
if (this.model.isScreenOrientationLocked()) {
|
|
935
|
+
this.modeButton.setEnabled(false);
|
|
936
|
+
setTitleForButton(this.modeButton, i18nString(UIStrings.screenOrientationLocked));
|
|
937
|
+
} else if (this.cachedModelDevice) {
|
|
938
|
+
const modeCount = this.cachedModelDevice.modes.length;
|
|
939
|
+
this.modeButton.setEnabled(modeCount >= 2);
|
|
940
|
+
setTitleForButton(
|
|
941
|
+
this.modeButton,
|
|
942
|
+
modeCount === 2 ? i18nString(UIStrings.rotate) : i18nString(UIStrings.screenOrientationOptions));
|
|
943
|
+
} else if (this.model.type() === EmulationModel.DeviceModeModel.Type.Responsive) {
|
|
944
|
+
this.modeButton.setEnabled(true);
|
|
945
|
+
setTitleForButton(this.modeButton, i18nString(UIStrings.rotate));
|
|
946
|
+
}
|
|
807
947
|
}
|
|
808
948
|
|
|
809
949
|
restore(): void {
|
|
@@ -66,7 +66,7 @@ export class HiddenIssuesRow extends UI.TreeOutline.TreeElement {
|
|
|
66
66
|
#view: View;
|
|
67
67
|
|
|
68
68
|
constructor(view: View = DEFAULT_VIEW) {
|
|
69
|
-
super(undefined, true);
|
|
69
|
+
super(undefined, true, 'hidden-issues');
|
|
70
70
|
this.#view = view;
|
|
71
71
|
this.toggleOnClick = true;
|
|
72
72
|
this.listItemElement.classList.add('issue-category', 'hidden-issues');
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import * as Common from '../../core/common/common.js';
|
|
7
7
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
8
|
+
import * as Platform from '../../core/platform/platform.js';
|
|
8
9
|
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
|
9
10
|
import * as Adorners from '../../ui/components/adorners/adorners.js';
|
|
10
11
|
import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
|
|
@@ -64,7 +65,7 @@ export class IssueKindView extends UI.TreeOutline.TreeElement {
|
|
|
64
65
|
#issueCount: HTMLElement;
|
|
65
66
|
|
|
66
67
|
constructor(kind: IssuesManager.Issue.IssueKind) {
|
|
67
|
-
super(undefined, true);
|
|
68
|
+
super(undefined, true, Platform.StringUtilities.toKebabCase(kind));
|
|
68
69
|
this.#kind = kind;
|
|
69
70
|
this.#issueCount = document.createElement('span');
|
|
70
71
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import * as Common from '../../core/common/common.js';
|
|
7
7
|
import * as Host from '../../core/host/host.js';
|
|
8
8
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
9
|
-
import
|
|
9
|
+
import * as Platform from '../../core/platform/platform.js';
|
|
10
10
|
import * as Protocol from '../../generated/protocol.js';
|
|
11
11
|
import type {AggregatedIssue} from '../../models/issues_manager/IssueAggregator.js';
|
|
12
12
|
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
|
@@ -24,7 +24,6 @@ import {AffectedDescendantsWithinSelectElementView} from './AffectedDescendantsW
|
|
|
24
24
|
import {AffectedDirectivesView} from './AffectedDirectivesView.js';
|
|
25
25
|
import {AffectedDocumentsInQuirksModeView} from './AffectedDocumentsInQuirksModeView.js';
|
|
26
26
|
import {AffectedElementsView} from './AffectedElementsView.js';
|
|
27
|
-
import {AffectedElementsWithLowContrastView} from './AffectedElementsWithLowContrastView.js';
|
|
28
27
|
import {AffectedHeavyAdView} from './AffectedHeavyAdView.js';
|
|
29
28
|
import {AffectedMetadataAllowedSitesView} from './AffectedMetadataAllowedSitesView.js';
|
|
30
29
|
import {AffectedPartitioningBlobURLView} from './AffectedPartitioningBlobURLView.js';
|
|
@@ -230,7 +229,7 @@ export class IssueView extends UI.TreeOutline.TreeElement {
|
|
|
230
229
|
#contentCreated = false;
|
|
231
230
|
|
|
232
231
|
constructor(issue: AggregatedIssue, description: IssuesManager.MarkdownIssueDescription.IssueDescription) {
|
|
233
|
-
super();
|
|
232
|
+
super(undefined, undefined, Platform.StringUtilities.toKebabCase(issue.getCategory()));
|
|
234
233
|
this.#issue = issue;
|
|
235
234
|
this.#description = description;
|
|
236
235
|
this.#throttle = new Common.Throttler.Throttler(250);
|
|
@@ -251,7 +250,6 @@ export class IssueView extends UI.TreeOutline.TreeElement {
|
|
|
251
250
|
new AffectedDirectivesView(this, this.#issue, 'directives-details'),
|
|
252
251
|
new AffectedBlockedByResponseView(this, this.#issue, 'blocked-by-response-details'),
|
|
253
252
|
new AffectedSharedArrayBufferIssueDetailsView(this, this.#issue, 'sab-details'),
|
|
254
|
-
new AffectedElementsWithLowContrastView(this, this.#issue, 'low-contrast-details'),
|
|
255
253
|
new CorsIssueDetailsView(this, this.#issue, 'cors-details'),
|
|
256
254
|
new GenericIssueDetailsView(this, this.#issue, 'generic-details'),
|
|
257
255
|
new AffectedDocumentsInQuirksModeView(this, this.#issue, 'affected-documents'),
|
|
@@ -7,7 +7,7 @@ import '../../ui/legacy/legacy.js';
|
|
|
7
7
|
|
|
8
8
|
import * as Common from '../../core/common/common.js';
|
|
9
9
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
10
|
-
import
|
|
10
|
+
import * as Platform from '../../core/platform/platform.js';
|
|
11
11
|
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
|
|
12
12
|
import * as IssueCounter from '../../ui/components/issue_counter/issue_counter.js';
|
|
13
13
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
@@ -121,7 +121,7 @@ class IssueCategoryView extends UI.TreeOutline.TreeElement {
|
|
|
121
121
|
#category: IssuesManager.Issue.IssueCategory;
|
|
122
122
|
|
|
123
123
|
constructor(category: IssuesManager.Issue.IssueCategory) {
|
|
124
|
-
super();
|
|
124
|
+
super(undefined, undefined, Platform.StringUtilities.toKebabCase(category));
|
|
125
125
|
this.#category = category;
|
|
126
126
|
|
|
127
127
|
this.toggleOnClick = true;
|
|
@@ -9,10 +9,10 @@ import type * as Platform from '../../core/platform/platform.js';
|
|
|
9
9
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
10
10
|
import * as Protocol from '../../generated/protocol.js';
|
|
11
11
|
import * as EmulationModel from '../../models/emulation/emulation.js';
|
|
12
|
+
import type * as LighthouseModel from '../../models/lighthouse/lighthouse.js';
|
|
12
13
|
import * as Emulation from '../emulation/emulation.js';
|
|
13
14
|
|
|
14
15
|
import type {LighthouseRun as LighthouseRunType, ProtocolService} from './LighthouseProtocolService.js';
|
|
15
|
-
import type {RunnerResult} from './LighthouseReporterTypes.js';
|
|
16
16
|
|
|
17
17
|
const UIStrings = {
|
|
18
18
|
/**
|
|
@@ -236,7 +236,7 @@ class LighthouseRun {
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
-
async collect(): Promise<RunnerResult> {
|
|
239
|
+
async collect(): Promise<LighthouseModel.ReporterTypes.RunnerResult> {
|
|
240
240
|
try {
|
|
241
241
|
const lighthouseResponse = await this.protocolService.collectLighthouseResults(
|
|
242
242
|
{inspectedURL: this.inspectedURL, categoryIDs: this.categoryIDs, flags: this.flags});
|
|
@@ -663,7 +663,7 @@ export class LighthouseController extends Common.ObjectWrapper.ObjectWrapper<Eve
|
|
|
663
663
|
return await this.lastAction;
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
async collectLighthouseResults(): Promise<RunnerResult> {
|
|
666
|
+
async collectLighthouseResults(): Promise<LighthouseModel.ReporterTypes.RunnerResult> {
|
|
667
667
|
if (!this.currentLighthouseRun) {
|
|
668
668
|
throw new Error('Lighthouse is not started');
|
|
669
669
|
}
|
|
@@ -7,6 +7,7 @@ import '../../ui/legacy/legacy.js';
|
|
|
7
7
|
|
|
8
8
|
import * as Common from '../../core/common/common.js';
|
|
9
9
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
10
|
+
import type * as LighthouseModel from '../../models/lighthouse/lighthouse.js';
|
|
10
11
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
11
12
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
12
13
|
|
|
@@ -19,7 +20,6 @@ import {
|
|
|
19
20
|
} from './LighthouseController.js';
|
|
20
21
|
import lighthousePanelStyles from './lighthousePanel.css.js';
|
|
21
22
|
import {ProtocolService} from './LighthouseProtocolService.js';
|
|
22
|
-
import type {ReportJSON, RunnerResultArtifacts} from './LighthouseReporterTypes.js';
|
|
23
23
|
import {LighthouseReportRenderer} from './LighthouseReportRenderer.js';
|
|
24
24
|
import {Item, ReportSelector} from './LighthouseReportSelector.js';
|
|
25
25
|
import {StartView} from './LighthouseStartView.js';
|
|
@@ -69,7 +69,7 @@ export class LighthousePanel extends UI.Panel.Panel {
|
|
|
69
69
|
private readonly timespanView: TimespanView;
|
|
70
70
|
private warningText: Nullable<string>;
|
|
71
71
|
private unauditableExplanation: Nullable<string>;
|
|
72
|
-
private readonly cachedRenderedReports: Map<ReportJSON, HTMLElement>;
|
|
72
|
+
private readonly cachedRenderedReports: Map<LighthouseModel.ReporterTypes.ReportJSON, HTMLElement>;
|
|
73
73
|
private readonly dropTarget: UI.DropTarget.DropTarget;
|
|
74
74
|
private readonly auditResultsElement: HTMLElement;
|
|
75
75
|
private clearButton!: UI.Toolbar.ToolbarButton;
|
|
@@ -296,7 +296,9 @@ export class LighthousePanel extends UI.Panel.Panel {
|
|
|
296
296
|
this.statusView.toggleCancelButton(true);
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
private renderReport(
|
|
299
|
+
private renderReport(
|
|
300
|
+
lighthouseResult: LighthouseModel.ReporterTypes.ReportJSON,
|
|
301
|
+
artifacts?: LighthouseModel.ReporterTypes.RunnerResultArtifacts): void {
|
|
300
302
|
this.toggleSettingsDisplay(false);
|
|
301
303
|
this.contentElement.classList.toggle('in-progress', false);
|
|
302
304
|
this.startView.hideWidget();
|
|
@@ -319,7 +321,9 @@ export class LighthousePanel extends UI.Panel.Panel {
|
|
|
319
321
|
this.cachedRenderedReports.set(lighthouseResult, reportContainer);
|
|
320
322
|
}
|
|
321
323
|
|
|
322
|
-
private buildReportUI(
|
|
324
|
+
private buildReportUI(
|
|
325
|
+
lighthouseResult: LighthouseModel.ReporterTypes.ReportJSON,
|
|
326
|
+
artifacts?: LighthouseModel.ReporterTypes.RunnerResultArtifacts): void {
|
|
323
327
|
if (lighthouseResult === null) {
|
|
324
328
|
return;
|
|
325
329
|
}
|
|
@@ -355,7 +359,7 @@ export class LighthousePanel extends UI.Panel.Panel {
|
|
|
355
359
|
if (!data['lighthouseVersion']) {
|
|
356
360
|
return;
|
|
357
361
|
}
|
|
358
|
-
this.buildReportUI(data as ReportJSON);
|
|
362
|
+
this.buildReportUI(data as LighthouseModel.ReporterTypes.ReportJSON);
|
|
359
363
|
}
|
|
360
364
|
|
|
361
365
|
override elementsToRestoreScrollPositionsFor(): Element[] {
|
|
@@ -7,8 +7,7 @@ import type * as Platform from '../../core/platform/platform.js';
|
|
|
7
7
|
import type * as ProtocolClient from '../../core/protocol_client/protocol_client.js';
|
|
8
8
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
9
9
|
import type * as Protocol from '../../generated/protocol.js';
|
|
10
|
-
|
|
11
|
-
import type * as ReportRenderer from './LighthouseReporterTypes.js';
|
|
10
|
+
import type * as LighthouseModel from '../../models/lighthouse/lighthouse.js';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
13
|
* @file
|
|
@@ -149,7 +148,8 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
149
148
|
});
|
|
150
149
|
}
|
|
151
150
|
|
|
152
|
-
async collectLighthouseResults(currentLighthouseRun: LighthouseRun):
|
|
151
|
+
async collectLighthouseResults(currentLighthouseRun: LighthouseRun):
|
|
152
|
+
Promise<LighthouseModel.ReporterTypes.RunnerResult> {
|
|
153
153
|
const {inspectedURL, categoryIDs, flags} = currentLighthouseRun;
|
|
154
154
|
|
|
155
155
|
if (!this.mainSessionId || !this.rootTargetId) {
|
|
@@ -289,10 +289,10 @@ export class ProtocolService implements ProtocolClient.CDPConnection.CDPConnecti
|
|
|
289
289
|
|
|
290
290
|
/** sendWithResponse currently only handles the original startLighthouse request and LHR-filled response. */
|
|
291
291
|
private async sendWithResponse(action: string, args: Record<string, string|string[]|object|undefined> = {}):
|
|
292
|
-
Promise<
|
|
292
|
+
Promise<LighthouseModel.ReporterTypes.RunnerResult> {
|
|
293
293
|
const worker = await this.ensureWorkerExists();
|
|
294
294
|
const messageId = lastId++;
|
|
295
|
-
const messageResult = new Promise<
|
|
295
|
+
const messageResult = new Promise<LighthouseModel.ReporterTypes.RunnerResult>(resolve => {
|
|
296
296
|
const workerListener = (event: MessageEvent): void => {
|
|
297
297
|
const lighthouseMessage = event.data;
|
|
298
298
|
|
|
@@ -6,6 +6,7 @@ import * as Common from '../../core/common/common.js';
|
|
|
6
6
|
import * as Host from '../../core/host/host.js';
|
|
7
7
|
import * as Platform from '../../core/platform/platform.js';
|
|
8
8
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
9
|
+
import type * as LighthouseModel from '../../models/lighthouse/lighthouse.js';
|
|
9
10
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
10
11
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
11
12
|
import * as LighthouseReport from '../../third_party/lighthouse/report/report.js';
|
|
@@ -15,9 +16,6 @@ import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';
|
|
|
15
16
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
16
17
|
import * as PanelsCommon from '../common/common.js';
|
|
17
18
|
|
|
18
|
-
import type {
|
|
19
|
-
NodeDetailsJSON, ReportJSON, RunnerResultArtifacts, SourceLocationDetailsJSON} from './LighthouseReporterTypes.js';
|
|
20
|
-
|
|
21
19
|
const MaxLengthForLinks = 40;
|
|
22
20
|
|
|
23
21
|
interface RenderReportOpts {
|
|
@@ -26,8 +24,9 @@ interface RenderReportOpts {
|
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
export class LighthouseReportRenderer {
|
|
29
|
-
static renderLighthouseReport(
|
|
30
|
-
|
|
27
|
+
static renderLighthouseReport(
|
|
28
|
+
lhr: LighthouseModel.ReporterTypes.ReportJSON, artifacts?: LighthouseModel.ReporterTypes.RunnerResultArtifacts,
|
|
29
|
+
opts?: RenderReportOpts): HTMLElement {
|
|
31
30
|
let onViewTrace: (() => Promise<void>)|undefined = undefined;
|
|
32
31
|
if (artifacts) {
|
|
33
32
|
onViewTrace = async () => {
|
|
@@ -134,7 +133,7 @@ export class LighthouseReportRenderer {
|
|
|
134
133
|
|
|
135
134
|
for (const origElement of el.getElementsByClassName('lh-node')) {
|
|
136
135
|
const origHTMLElement = origElement as HTMLElement;
|
|
137
|
-
const detailsItem = origHTMLElement.dataset as unknown as NodeDetailsJSON;
|
|
136
|
+
const detailsItem = origHTMLElement.dataset as unknown as LighthouseModel.ReporterTypes.NodeDetailsJSON;
|
|
138
137
|
if (!detailsItem.path) {
|
|
139
138
|
continue;
|
|
140
139
|
}
|
|
@@ -165,7 +164,7 @@ export class LighthouseReportRenderer {
|
|
|
165
164
|
static async linkifySourceLocationDetails(el: Element): Promise<void> {
|
|
166
165
|
for (const origElement of el.getElementsByClassName('lh-source-location')) {
|
|
167
166
|
const origHTMLElement = origElement as HTMLElement;
|
|
168
|
-
const detailsItem = origHTMLElement.dataset as SourceLocationDetailsJSON;
|
|
167
|
+
const detailsItem = origHTMLElement.dataset as LighthouseModel.ReporterTypes.SourceLocationDetailsJSON;
|
|
169
168
|
if (!detailsItem.sourceUrl || !detailsItem.sourceLine || !detailsItem.sourceColumn) {
|
|
170
169
|
continue;
|
|
171
170
|
}
|