chrome-devtools-frontend 1.0.1681498 → 1.0.1682249
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/eslint.config.mjs +8 -3
- package/front_end/core/sdk/ConsoleModel.ts +1 -1
- package/front_end/core/sdk/PreloadingModel.ts +44 -22
- package/front_end/core/sdk/RemoteObject.ts +4 -1
- package/front_end/core/sdk/RuntimeModel.ts +5 -5
- package/front_end/core/sdk/sdk.ts +2 -0
- package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +1 -1
- package/front_end/entrypoints/inspector_main/InspectorMain.ts +3 -1
- package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +1 -5
- package/front_end/entrypoints/main/MainImpl.ts +9 -10
- package/front_end/entrypoints/shell/shell.ts +0 -2
- package/front_end/entrypoints/trace_app/trace_app.ts +0 -2
- package/front_end/generated/InspectorBackendCommands.ts +2 -0
- package/front_end/generated/protocol-mapping.d.ts +16 -0
- package/front_end/generated/protocol-proxy-api.d.ts +12 -0
- package/front_end/generated/protocol.ts +12 -0
- package/front_end/models/ai_assistance/ExtensionScope.ts +11 -12
- package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -1
- package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +2 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +1 -1
- package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +2 -1
- package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +2 -1
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +8 -8
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +8 -8
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +1 -0
- package/front_end/models/formatter/ScriptFormatter.ts +1 -0
- package/front_end/models/javascript_metadata/NativeFunctions.js +5 -1
- package/front_end/models/live-metrics/web-vitals-injected/spec/spec.ts +4 -4
- package/front_end/models/logs/NetworkLog.ts +8 -1
- package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +4 -2
- package/front_end/models/stack_trace/StackTraceImpl.ts +1 -0
- package/front_end/models/trace/Name.ts +5 -5
- package/front_end/models/trace/Styles.ts +115 -115
- package/front_end/models/trace/extras/TraceTree.ts +2 -1
- package/front_end/models/trace/helpers/Network.ts +4 -1
- package/front_end/models/trace/insights/CLSCulprits.ts +4 -2
- package/front_end/models/trace/insights/CharacterSet.ts +3 -3
- package/front_end/models/trace/insights/DOMSize.ts +1 -1
- package/front_end/models/trace/insights/DuplicatedJavaScript.ts +6 -2
- package/front_end/models/trace/insights/FontDisplay.ts +9 -3
- package/front_end/models/trace/insights/ForcedReflow.ts +4 -4
- package/front_end/models/trace/insights/INPBreakdown.ts +3 -4
- package/front_end/models/trace/insights/ImageDelivery.ts +2 -2
- package/front_end/models/trace/insights/LCPBreakdown.ts +1 -1
- package/front_end/models/trace/insights/LCPDiscovery.ts +5 -5
- package/front_end/models/trace/insights/LegacyJavaScript.ts +7 -3
- package/front_end/models/trace/insights/ModernHTTP.ts +3 -3
- package/front_end/models/trace/insights/NetworkDependencyTree.ts +13 -9
- package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
- package/front_end/models/trace/insights/SlowCSSSelector.ts +29 -25
- package/front_end/models/trace/insights/ThirdParties.ts +13 -5
- package/front_end/models/trace/insights/Viewport.ts +4 -2
- package/front_end/models/workspace/IgnoreListManager.ts +53 -17
- package/front_end/panels/accessibility/ARIAAttributesView.ts +11 -2
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +67 -53
- package/front_end/panels/ai_assistance/components/ChatView.ts +2 -2
- package/front_end/panels/ai_assistance/components/StylingAgentMarkdownRenderer.ts +2 -2
- package/front_end/panels/ai_assistance/components/WalkthroughView.ts +5 -5
- package/front_end/panels/animation/AnimationTimeline.ts +2 -0
- package/front_end/panels/application/preloading/PreloadingView.ts +9 -3
- package/front_end/panels/application/preloading/components/components.ts +2 -0
- package/front_end/panels/browser_debugger/ObjectEventListenersSidebarPane.ts +10 -11
- package/front_end/panels/changes/CombinedDiffView.ts +1 -1
- package/front_end/panels/common/ExtensionServer.ts +9 -10
- package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +9 -4
- package/front_end/panels/elements/ElementStatePaneWidget.ts +3 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +7 -1
- package/front_end/panels/elements/EventListenersWidget.ts +10 -11
- package/front_end/panels/issues/IssueView.ts +5 -6
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryViewer.ts +1 -1
- package/front_end/panels/media/PlayerPropertiesView.ts +309 -416
- package/front_end/panels/media/playerPropertiesView.css +1 -1
- package/front_end/panels/network/NetworkPanel.ts +2 -1
- package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -2
- package/front_end/panels/network/network-meta.ts +6 -0
- package/front_end/panels/performance_monitor/PerformanceMonitor.ts +2 -1
- package/front_end/panels/recorder/RecordingView.ts +89 -73
- package/front_end/panels/recorder/ReplaySection.ts +59 -40
- package/front_end/panels/recorder/injected/injected.ts +4 -0
- package/front_end/panels/security/SecurityPanel.ts +5 -6
- package/front_end/panels/security/SecurityPanelSidebar.ts +244 -204
- package/front_end/panels/security/security.ts +0 -4
- package/front_end/panels/settings/EditFileSystemView.ts +8 -7
- package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +20 -14
- package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +10 -11
- package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +3 -3
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +5 -5
- package/front_end/panels/timeline/components/CWVMetrics.ts +1 -2
- package/front_end/panels/timeline/components/IgnoreListSetting.ts +5 -5
- package/front_end/panels/timeline/components/LayoutShiftDetails.ts +2 -3
- package/front_end/panels/timeline/components/LiveMetricsView.ts +2 -2
- package/front_end/panels/timeline/components/Sidebar.ts +3 -3
- package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -2
- package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +3 -1
- package/front_end/panels/timeline/components/insights/CLSCulprits.ts +1 -2
- package/front_end/panels/timeline/components/insights/Cache.ts +1 -2
- package/front_end/panels/timeline/components/insights/CharacterSet.ts +1 -2
- package/front_end/panels/timeline/components/insights/DOMSize.ts +1 -2
- package/front_end/panels/timeline/components/insights/DocumentLatency.ts +2 -2
- package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +2 -2
- package/front_end/panels/timeline/components/insights/FontDisplay.ts +1 -2
- package/front_end/panels/timeline/components/insights/ForcedReflow.ts +1 -2
- package/front_end/panels/timeline/components/insights/INPBreakdown.ts +1 -2
- package/front_end/panels/timeline/components/insights/ImageDelivery.ts +1 -2
- package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +13 -13
- package/front_end/panels/timeline/components/insights/LCPDiscovery.ts +1 -2
- package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +4 -4
- package/front_end/panels/timeline/components/insights/ModernHTTP.ts +1 -2
- package/front_end/panels/timeline/components/insights/NetworkDependencyTree.ts +10 -8
- package/front_end/panels/timeline/components/insights/RenderBlocking.ts +2 -2
- package/front_end/panels/timeline/components/insights/SidebarInsight.ts +3 -1
- package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +2 -2
- package/front_end/panels/timeline/components/insights/ThirdParties.ts +1 -2
- package/front_end/panels/timeline/components/insights/Viewport.ts +1 -2
- package/front_end/panels/timeline/overlays/OverlaysImpl.ts +1 -2
- package/front_end/panels/timeline/timeline.ts +0 -2
- package/front_end/panels/web_audio/WebAudioView.ts +7 -7
- package/front_end/panels/webauthn/WebauthnPane.ts +9 -9
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/diff_view/DiffView.ts +2 -1
- package/front_end/ui/components/report_view/ReportView.docs.ts +2 -2
- package/front_end/ui/components/text_editor/javascript.ts +12 -13
- package/front_end/ui/legacy/GlassPane.ts +38 -14
- package/front_end/ui/legacy/Treeoutline.ts +14 -3
- package/front_end/ui/legacy/components/object_ui/CustomPreviewComponent.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/JavaScriptREPL.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +1 -1
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +21 -30
- package/front_end/ui/legacy/components/object_ui/RemoteObjectPreviewFormatter.ts +3 -8
- package/front_end/ui/legacy/components/utils/ImagePreview.ts +15 -16
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +4 -4
- package/front_end/ui/legacy/components/utils/Linkifier.ts +8 -10
- package/front_end/ui/settings/InspectorMainSettings.ts +12 -0
- package/front_end/ui/settings/settings.ts +2 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +21 -0
- package/mcp/mcp.ts +0 -6
- package/package.json +1 -1
- package/front_end/models/logs/logs-meta.ts +0 -24
- package/front_end/models/workspace/workspace-meta.ts +0 -40
- package/front_end/panels/security/OriginTreeElement.ts +0 -60
- package/front_end/panels/security/SecurityPanelSidebarTreeElement.ts +0 -30
|
@@ -1,38 +1,36 @@
|
|
|
1
1
|
// Copyright 2019 The Chromium Authors
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
// found in the LICENSE file.
|
|
4
|
-
/* eslint-disable @devtools/no-imperative-dom-api */
|
|
5
4
|
|
|
6
5
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
7
6
|
import * as Platform from '../../core/platform/platform.js';
|
|
8
7
|
import type * as Protocol from '../../generated/protocol.js';
|
|
9
8
|
import * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';
|
|
10
9
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
10
|
+
import {Directives, html, type LitTemplate, nothing, render} from '../../ui/lit/lit.js';
|
|
11
11
|
import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
12
12
|
|
|
13
13
|
import playerPropertiesViewStyles from './playerPropertiesView.css.js';
|
|
14
14
|
|
|
15
15
|
const UIStrings = {
|
|
16
|
-
/**
|
|
17
|
-
* @description The type of media, for example - video, audio, or text. Capitalized.
|
|
18
|
-
*/
|
|
19
|
-
video: 'Video',
|
|
20
|
-
/**
|
|
21
|
-
* @description The type of media, for example - video, audio, or text. Capitalized.
|
|
22
|
-
*/
|
|
23
|
-
audio: 'Audio',
|
|
24
16
|
/**
|
|
25
17
|
* @description A video or audio stream - but capitalized.
|
|
26
18
|
*/
|
|
27
19
|
track: 'Track',
|
|
28
20
|
/**
|
|
29
|
-
* @description
|
|
21
|
+
* @description Title of the video decoder tab in the media player properties view.
|
|
30
22
|
*/
|
|
31
|
-
|
|
23
|
+
videoDecoderProperties: 'Video Decoder Properties',
|
|
32
24
|
/**
|
|
33
|
-
* @description Title of the
|
|
25
|
+
* @description Title of the audio decoder tab in the media player properties view.
|
|
34
26
|
*/
|
|
35
|
-
|
|
27
|
+
audioDecoderProperties: 'Audio Decoder Properties',
|
|
28
|
+
/**
|
|
29
|
+
* @description Menu label for media tracks, it is followed by a number, like 'Track #1'.
|
|
30
|
+
* @example {Track} PH1
|
|
31
|
+
* @example {1} PH2
|
|
32
|
+
*/
|
|
33
|
+
trackNumber: '{PH1} #{PH2}',
|
|
36
34
|
/**
|
|
37
35
|
* @description Menu label for text tracks, it is followed by a number, like 'Text track #1'.
|
|
38
36
|
*/
|
|
@@ -139,7 +137,6 @@ const UIStrings = {
|
|
|
139
137
|
|
|
140
138
|
const str_ = i18n.i18n.registerUIStrings('panels/media/PlayerPropertiesView.ts', UIStrings);
|
|
141
139
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
142
|
-
const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);
|
|
143
140
|
|
|
144
141
|
type TabData = Record<string, string|object>;
|
|
145
142
|
|
|
@@ -150,7 +147,8 @@ export const enum PlayerPropertyKeys {
|
|
|
150
147
|
BITRATE = 'kBitrate',
|
|
151
148
|
MAX_DURATION = 'kMaxDuration',
|
|
152
149
|
START_TIME = 'kStartTime',
|
|
153
|
-
|
|
150
|
+
// Not observed
|
|
151
|
+
// IS_CDM_ATTACHED = 'kIsCdmAttached',
|
|
154
152
|
IS_STREAMING = 'kIsStreaming',
|
|
155
153
|
FRAME_URL = 'kFrameUrl',
|
|
156
154
|
FRAME_TITLE = 'kFrameTitle',
|
|
@@ -174,479 +172,374 @@ export const enum PlayerPropertyKeys {
|
|
|
174
172
|
HLS_BUFFERED_RANGES = 'kHlsBufferedRanges',
|
|
175
173
|
}
|
|
176
174
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
private pseudoColorProtectionElement: HTMLDivElement|null;
|
|
181
|
-
|
|
182
|
-
constructor(title: Platform.UIString.LocalizedString) {
|
|
183
|
-
super();
|
|
184
|
-
this.contentElement.classList.add('media-property-renderer');
|
|
185
|
-
const titleElement = this.contentElement.createChild('span', 'media-property-renderer-title');
|
|
186
|
-
this.contents = this.contentElement.createChild('div', 'media-property-renderer-contents');
|
|
187
|
-
UI.UIUtils.createTextChild(titleElement, title);
|
|
188
|
-
this.value = null;
|
|
189
|
-
this.pseudoColorProtectionElement = null;
|
|
190
|
-
this.contentElement.classList.add('media-property-renderer-hidden');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
updateData(propvalue: string): void {
|
|
194
|
-
// convert all empty possibilities into nulls for easier handling.
|
|
195
|
-
if (propvalue === '' || propvalue === null) {
|
|
196
|
-
this.changeContents(null);
|
|
197
|
-
} else if (this.value === propvalue) {
|
|
198
|
-
return; // Don't rebuild element!
|
|
199
|
-
} else {
|
|
200
|
-
this.value = propvalue;
|
|
201
|
-
this.updateDataInternal(propvalue);
|
|
202
|
-
}
|
|
175
|
+
class Property {
|
|
176
|
+
protected dataInternal: string|null = null;
|
|
177
|
+
constructor(readonly type: PlayerPropertyKeys) {
|
|
203
178
|
}
|
|
204
179
|
|
|
205
|
-
|
|
180
|
+
protected parse<T>(val: string): T {
|
|
206
181
|
try {
|
|
207
|
-
|
|
208
|
-
this.changeContents(parsed);
|
|
182
|
+
return JSON.parse(val) as T;
|
|
209
183
|
} catch {
|
|
210
|
-
|
|
211
|
-
this.changeContents(propvalue);
|
|
184
|
+
return val as T;
|
|
212
185
|
}
|
|
213
186
|
}
|
|
214
187
|
|
|
215
|
-
|
|
216
|
-
this.
|
|
217
|
-
if (this.pseudoColorProtectionElement === null) {
|
|
218
|
-
this.pseudoColorProtectionElement = document.createElement('div');
|
|
219
|
-
this.pseudoColorProtectionElement.classList.add('media-property-renderer');
|
|
220
|
-
this.pseudoColorProtectionElement.classList.add('media-property-renderer-hidden');
|
|
221
|
-
(this.contentElement.parentNode as HTMLElement)
|
|
222
|
-
.insertBefore(this.pseudoColorProtectionElement, this.contentElement);
|
|
223
|
-
}
|
|
188
|
+
get data(): string|null {
|
|
189
|
+
return this.dataInternal;
|
|
224
190
|
}
|
|
225
191
|
|
|
226
|
-
|
|
227
|
-
if (
|
|
228
|
-
this.
|
|
229
|
-
|
|
230
|
-
if (this.pseudoColorProtectionElement !== null) {
|
|
231
|
-
this.pseudoColorProtectionElement.remove();
|
|
232
|
-
this.pseudoColorProtectionElement = null;
|
|
233
|
-
}
|
|
234
|
-
this.contentElement.classList.remove('media-property-renderer-hidden');
|
|
235
|
-
this.contents.removeChildren();
|
|
236
|
-
const jsonWrapperElement =
|
|
237
|
-
new SourceFrame.JSONView.JSONView(new SourceFrame.JSONView.ParsedJSON(value, '', ''), true);
|
|
238
|
-
jsonWrapperElement.show(this.contents);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
changeContents(value: string|null): void {
|
|
243
|
-
if (value === null) {
|
|
244
|
-
this.unsetNestedContents();
|
|
245
|
-
} else {
|
|
246
|
-
if (this.pseudoColorProtectionElement !== null) {
|
|
247
|
-
this.pseudoColorProtectionElement.remove();
|
|
248
|
-
this.pseudoColorProtectionElement = null;
|
|
249
|
-
}
|
|
250
|
-
this.contentElement.classList.remove('media-property-renderer-hidden');
|
|
251
|
-
this.contents.removeChildren();
|
|
252
|
-
const spanElement = document.createElement('span');
|
|
253
|
-
spanElement.textContent = value;
|
|
254
|
-
this.contents.appendChild(spanElement);
|
|
192
|
+
set data(val: string|null) {
|
|
193
|
+
if (!val) {
|
|
194
|
+
this.dataInternal = null;
|
|
195
|
+
return;
|
|
255
196
|
}
|
|
197
|
+
// Some properties are just raw strings.
|
|
198
|
+
this.dataInternal = String(this.parse<string>(val));
|
|
256
199
|
}
|
|
257
200
|
}
|
|
258
201
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
super(title);
|
|
263
|
-
this.formatfunction = formatfunction;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
override updateDataInternal(propvalue: string): void {
|
|
267
|
-
try {
|
|
268
|
-
const parsed: DataType = JSON.parse(propvalue) as DataType;
|
|
269
|
-
this.changeContents(this.formatfunction(parsed));
|
|
270
|
-
} catch {
|
|
271
|
-
const unparsed = propvalue as DataType;
|
|
272
|
-
this.changeContents(this.formatfunction(unparsed));
|
|
273
|
-
}
|
|
202
|
+
class TotalBytesProperty extends Property {
|
|
203
|
+
constructor() {
|
|
204
|
+
super(PlayerPropertyKeys.TOTAL_BYTES);
|
|
274
205
|
}
|
|
275
|
-
}
|
|
276
206
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
super(title);
|
|
280
|
-
this.changeContents(defaultText);
|
|
207
|
+
override get data(): string|null {
|
|
208
|
+
return this.dataInternal;
|
|
281
209
|
}
|
|
282
|
-
}
|
|
283
210
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
super(title);
|
|
287
|
-
this.changeNestedContents(content);
|
|
211
|
+
override set data(val: string|null) {
|
|
212
|
+
this.dataInternal = val === null ? null : TotalBytesProperty.formatFileSize(this.parse<string|number>(val));
|
|
288
213
|
}
|
|
289
|
-
}
|
|
290
214
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
constructor(elements: UI.Widget.Widget[]) {
|
|
295
|
-
super();
|
|
296
|
-
this.contentHash = 0;
|
|
297
|
-
this.contentElement.classList.add('media-attributes-view');
|
|
298
|
-
for (const element of elements) {
|
|
299
|
-
element.show(this.contentElement);
|
|
300
|
-
// We just need a really simple way to compare the topical equality
|
|
301
|
-
// of the attributes views in order to avoid deleting and recreating
|
|
302
|
-
// a node containing exactly the same data.
|
|
303
|
-
const content = this.contentElement.textContent;
|
|
304
|
-
if (content !== null) {
|
|
305
|
-
this.contentHash += Platform.StringUtilities.hashCode(content);
|
|
306
|
-
}
|
|
215
|
+
static formatFileSize(bytes: string|number): string {
|
|
216
|
+
if (bytes === '') {
|
|
217
|
+
return '0 bytes';
|
|
307
218
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
219
|
+
const actualBytes = Number(bytes);
|
|
220
|
+
if (actualBytes < 1000) {
|
|
221
|
+
return `${bytes} bytes`;
|
|
222
|
+
}
|
|
223
|
+
const power = Math.floor(Math.log10(actualBytes) / 3);
|
|
224
|
+
const suffix = ['bytes', 'kB', 'MB', 'GB', 'TB'][power];
|
|
225
|
+
const bytesDecimal = (actualBytes / Math.pow(1000, power)).toFixed(2);
|
|
226
|
+
return `${bytesDecimal} ${suffix}`;
|
|
312
227
|
}
|
|
313
228
|
}
|
|
314
229
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
constructor(propertiesView: PlayerPropertiesView, type: string) {
|
|
320
|
-
this.type = type;
|
|
321
|
-
this.view = propertiesView;
|
|
230
|
+
class BitRateProperty extends Property {
|
|
231
|
+
constructor() {
|
|
232
|
+
super(PlayerPropertyKeys.BITRATE);
|
|
322
233
|
}
|
|
323
234
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
const newTabs = JSON.parse(value) as TabData[];
|
|
328
|
-
let enumerate = 1;
|
|
329
|
-
for (const tabData of newTabs) {
|
|
330
|
-
this.addNewTab(tabs, tabData, enumerate);
|
|
331
|
-
enumerate++;
|
|
332
|
-
}
|
|
235
|
+
override get data(): string|null {
|
|
236
|
+
return this.dataInternal;
|
|
333
237
|
}
|
|
334
238
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
for (const [name, data] of Object.entries(tabData)) {
|
|
338
|
-
if (typeof data === 'object') {
|
|
339
|
-
tabElements.push(new NestedPropertyRenderer(i18n.i18n.lockedString(name), data));
|
|
340
|
-
} else {
|
|
341
|
-
tabElements.push(new DefaultPropertyRenderer(i18n.i18n.lockedString(name), data));
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
const newTab = new AttributesView(tabElements);
|
|
345
|
-
|
|
346
|
-
tabs.addNewTab(tabNumber, newTab);
|
|
239
|
+
override set data(val: string|null) {
|
|
240
|
+
this.dataInternal = val === null ? null : BitRateProperty.formatKbps(this.parse<string|number>(val));
|
|
347
241
|
}
|
|
348
|
-
}
|
|
349
242
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
243
|
+
static formatKbps(bitsPerSecond: string|number): string {
|
|
244
|
+
if (bitsPerSecond === '') {
|
|
245
|
+
return '0 kbps';
|
|
246
|
+
}
|
|
247
|
+
const kbps = Math.floor(Number(bitsPerSecond) / 1000);
|
|
248
|
+
return `${kbps} kbps`;
|
|
353
249
|
}
|
|
354
250
|
}
|
|
355
251
|
|
|
356
|
-
|
|
357
|
-
constructor(
|
|
358
|
-
super(
|
|
252
|
+
class MaxDurationProperty extends Property {
|
|
253
|
+
constructor() {
|
|
254
|
+
super(PlayerPropertyKeys.MAX_DURATION);
|
|
359
255
|
}
|
|
360
|
-
}
|
|
361
256
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
super(propertiesView, 'audio');
|
|
257
|
+
override get data(): string|null {
|
|
258
|
+
return this.dataInternal;
|
|
365
259
|
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
const TrackTypeLocalized = {
|
|
369
|
-
Video: i18nLazyString(UIStrings.video),
|
|
370
|
-
Audio: i18nLazyString(UIStrings.audio),
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
class GenericTrackMenu extends UI.TabbedPane.TabbedPane {
|
|
374
|
-
private readonly decoderName: string;
|
|
375
|
-
private readonly trackName: string;
|
|
376
260
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
this.decoderName = decoderName;
|
|
380
|
-
this.trackName = trackName;
|
|
261
|
+
override set data(val: string|null) {
|
|
262
|
+
this.dataInternal = val === null ? null : MaxDurationProperty.formatTime(this.parse<string|number>(val));
|
|
381
263
|
}
|
|
382
264
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if (this.hasTab(tabId)) {
|
|
387
|
-
const tabElement = this.tabView(tabId);
|
|
388
|
-
if (tabElement === null) {
|
|
389
|
-
return;
|
|
390
|
-
}
|
|
391
|
-
if ((tabElement as AttributesView).getContentHash() === element.getContentHash()) {
|
|
392
|
-
return;
|
|
393
|
-
}
|
|
394
|
-
this.closeTab(tabId, /* userGesture=*/ false);
|
|
265
|
+
static formatTime(seconds: string|number): string {
|
|
266
|
+
if (seconds === '') {
|
|
267
|
+
return '0:00';
|
|
395
268
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
269
|
+
const date = new Date(0);
|
|
270
|
+
date.setSeconds(Number(seconds));
|
|
271
|
+
return date.toISOString().substring(11, 19);
|
|
399
272
|
}
|
|
400
273
|
}
|
|
401
274
|
|
|
402
|
-
class
|
|
403
|
-
constructor(
|
|
404
|
-
super(
|
|
405
|
-
|
|
406
|
-
const decoderLocalized = i18nString(UIStrings.decoder);
|
|
407
|
-
const title = `${decoderName} ${decoderLocalized}`;
|
|
408
|
-
const propertiesLocalized = i18nString(UIStrings.properties);
|
|
409
|
-
const hoverText = `${title} ${propertiesLocalized}`;
|
|
410
|
-
this.appendTab('decoder-properties', title, informationalElement, hoverText);
|
|
275
|
+
class HlsBufferedRangesProperty extends Property {
|
|
276
|
+
constructor() {
|
|
277
|
+
super(PlayerPropertyKeys.HLS_BUFFERED_RANGES);
|
|
411
278
|
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
class NoTracksPlaceholderMenu extends UI.Widget.VBox {
|
|
415
|
-
private isPlaceholder: boolean;
|
|
416
|
-
private readonly wrapping: GenericTrackMenu;
|
|
417
279
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
this.isPlaceholder = true;
|
|
421
|
-
this.wrapping = wrapping;
|
|
422
|
-
this.wrapping.appendTab('_placeholder', placeholderText, new UI.Widget.VBox(), placeholderText);
|
|
423
|
-
this.wrapping.show(this.contentElement);
|
|
280
|
+
override get data(): string|null {
|
|
281
|
+
return this.dataInternal;
|
|
424
282
|
}
|
|
425
283
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
this.isPlaceholder = false;
|
|
430
|
-
}
|
|
431
|
-
this.wrapping.addNewTab(trackNumber, element);
|
|
284
|
+
override set data(val: string|null) {
|
|
285
|
+
this.dataInternal =
|
|
286
|
+
val === null ? null : HlsBufferedRangesProperty.formatBufferedRanges(this.parse<Array<[number, number]>>(val));
|
|
432
287
|
}
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
export class PlayerPropertiesView extends UI.Widget.VBox {
|
|
436
|
-
private readonly mediaElements: PropertyRenderer[];
|
|
437
|
-
private readonly videoDecoderElements: PropertyRenderer[];
|
|
438
|
-
private readonly audioDecoderElements: PropertyRenderer[];
|
|
439
|
-
private readonly attributeMap: Map<string, PropertyRenderer|TrackManager>;
|
|
440
|
-
private readonly videoProperties: AttributesView;
|
|
441
|
-
private readonly videoDecoderProperties: AttributesView;
|
|
442
|
-
private readonly audioDecoderProperties: AttributesView;
|
|
443
|
-
private readonly videoDecoderTabs: DecoderTrackMenu;
|
|
444
|
-
private readonly audioDecoderTabs: DecoderTrackMenu;
|
|
445
|
-
private textTracksTabs: GenericTrackMenu|NoTracksPlaceholderMenu|null;
|
|
446
|
-
|
|
447
|
-
constructor() {
|
|
448
|
-
super({jslog: `${VisualLogging.pane('properties')}`});
|
|
449
|
-
this.registerRequiredCSS(playerPropertiesViewStyles);
|
|
450
|
-
|
|
451
|
-
this.contentElement.classList.add('media-properties-frame');
|
|
452
|
-
|
|
453
|
-
this.mediaElements = [];
|
|
454
|
-
this.videoDecoderElements = [];
|
|
455
|
-
this.audioDecoderElements = [];
|
|
456
|
-
this.attributeMap = new Map();
|
|
457
|
-
|
|
458
|
-
this.populateAttributesAndElements();
|
|
459
|
-
this.videoProperties = new AttributesView(this.mediaElements);
|
|
460
|
-
this.videoDecoderProperties = new AttributesView(this.videoDecoderElements);
|
|
461
|
-
this.audioDecoderProperties = new AttributesView(this.audioDecoderElements);
|
|
462
|
-
|
|
463
|
-
this.videoProperties.show(this.contentElement);
|
|
464
|
-
this.videoDecoderTabs = new DecoderTrackMenu(TrackTypeLocalized.Video(), this.videoDecoderProperties);
|
|
465
|
-
this.videoDecoderTabs.show(this.contentElement);
|
|
466
|
-
this.audioDecoderTabs = new DecoderTrackMenu(TrackTypeLocalized.Audio(), this.audioDecoderProperties);
|
|
467
|
-
this.audioDecoderTabs.show(this.contentElement);
|
|
468
288
|
|
|
469
|
-
|
|
289
|
+
static formatBufferedRanges(ranges: Array<[number, number]>): string {
|
|
290
|
+
// ranges is an array of `Range`, where a `Range` is a tuple-array of start/end floating point numbers.
|
|
291
|
+
return ranges
|
|
292
|
+
.map(range => {
|
|
293
|
+
return '[' + range[0] + ' → ' + range[1] + ']';
|
|
294
|
+
})
|
|
295
|
+
.join(', ');
|
|
470
296
|
}
|
|
297
|
+
}
|
|
471
298
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
textTracksTabs.show(this.contentElement);
|
|
478
|
-
this.textTracksTabs = textTracksTabs;
|
|
479
|
-
}
|
|
480
|
-
return textTracksTabs;
|
|
299
|
+
class TrackProperty extends Property {
|
|
300
|
+
#entries: TabData[]|null = null;
|
|
301
|
+
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
302
|
+
constructor(type: PlayerPropertyKeys.VIDEO_TRACKS|PlayerPropertyKeys.AUDIO_TRACKS|PlayerPropertyKeys.TEXT_TRACKS) {
|
|
303
|
+
super(type);
|
|
481
304
|
}
|
|
482
305
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
return this.audioDecoderTabs;
|
|
486
|
-
}
|
|
487
|
-
if (type === 'video') {
|
|
488
|
-
return this.videoDecoderTabs;
|
|
489
|
-
}
|
|
490
|
-
if (type === 'text') {
|
|
491
|
-
return this.lazyCreateTrackTabs();
|
|
492
|
-
}
|
|
493
|
-
// There should be no other type allowed.
|
|
494
|
-
throw new Error('Unreachable');
|
|
306
|
+
get entries(): TabData[]|null {
|
|
307
|
+
return this.#entries;
|
|
495
308
|
}
|
|
496
309
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
if (!renderer) {
|
|
500
|
-
throw new Error(`Player property "${property.name}" not supported.`);
|
|
501
|
-
}
|
|
502
|
-
renderer.updateData(property.value);
|
|
310
|
+
override get data(): never {
|
|
311
|
+
throw new Error('Cannot access raw data');
|
|
503
312
|
}
|
|
504
313
|
|
|
505
|
-
|
|
506
|
-
if (
|
|
507
|
-
|
|
314
|
+
override set data(val: string|null) {
|
|
315
|
+
if (val === null) {
|
|
316
|
+
this.#entries = null;
|
|
317
|
+
return;
|
|
508
318
|
}
|
|
509
|
-
const
|
|
510
|
-
|
|
319
|
+
const parsed = this.parse<TabData[]>(val);
|
|
320
|
+
this.#entries = Array.isArray(parsed) ? parsed : [];
|
|
511
321
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
322
|
+
}
|
|
323
|
+
const {classMap} = Directives;
|
|
324
|
+
const {widget} = UI.Widget;
|
|
325
|
+
interface ViewInput {
|
|
326
|
+
properties: Record<PlayerPropertyKeys, Property>;
|
|
327
|
+
}
|
|
328
|
+
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
329
|
+
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
330
|
+
function propertyTitle(type: PlayerPropertyKeys): Platform.UIString.LocalizedString {
|
|
331
|
+
switch (type) {
|
|
332
|
+
case PlayerPropertyKeys.RESOLUTION:
|
|
333
|
+
return i18nString(UIStrings.resolution);
|
|
334
|
+
case PlayerPropertyKeys.TOTAL_BYTES:
|
|
335
|
+
return i18nString(UIStrings.fileSize);
|
|
336
|
+
case PlayerPropertyKeys.BITRATE:
|
|
337
|
+
return i18nString(UIStrings.bitrate);
|
|
338
|
+
case PlayerPropertyKeys.MAX_DURATION:
|
|
339
|
+
return i18nString(UIStrings.duration);
|
|
340
|
+
case PlayerPropertyKeys.START_TIME:
|
|
341
|
+
return i18nString(UIStrings.startTime);
|
|
342
|
+
case PlayerPropertyKeys.IS_STREAMING:
|
|
343
|
+
return i18nString(UIStrings.streaming);
|
|
344
|
+
case PlayerPropertyKeys.FRAME_URL:
|
|
345
|
+
return i18nString(UIStrings.playbackFrameUrl);
|
|
346
|
+
case PlayerPropertyKeys.FRAME_TITLE:
|
|
347
|
+
return i18nString(UIStrings.playbackFrameTitle);
|
|
348
|
+
case PlayerPropertyKeys.IS_SINGLE_ORIGIN:
|
|
349
|
+
return i18nString(UIStrings.singleoriginPlayback);
|
|
350
|
+
case PlayerPropertyKeys.IS_RANGE_HEADER_SUPPORTED:
|
|
351
|
+
return i18nString(UIStrings.rangeHeaderSupport);
|
|
352
|
+
case PlayerPropertyKeys.FRAMERATE:
|
|
353
|
+
return i18nString(UIStrings.frameRate);
|
|
354
|
+
case PlayerPropertyKeys.VIDEO_PLAYBACK_ROUGHNESS:
|
|
355
|
+
return i18nString(UIStrings.videoPlaybackRoughness);
|
|
356
|
+
case PlayerPropertyKeys.VIDEO_PLAYBACK_FREEZING:
|
|
357
|
+
return i18nString(UIStrings.videoFreezingScore);
|
|
358
|
+
case PlayerPropertyKeys.RENDERER_NAME:
|
|
359
|
+
return i18nString(UIStrings.rendererName);
|
|
360
|
+
case PlayerPropertyKeys.HLS_BUFFERED_RANGES:
|
|
361
|
+
return i18nString(UIStrings.hlsBufferedRanges);
|
|
362
|
+
case PlayerPropertyKeys.VIDEO_DECODER_NAME:
|
|
363
|
+
return i18nString(UIStrings.decoderName);
|
|
364
|
+
case PlayerPropertyKeys.IS_PLATFORM_VIDEO_DECODER:
|
|
365
|
+
return i18nString(UIStrings.hardwareDecoder);
|
|
366
|
+
case PlayerPropertyKeys.VIDEO_ENCODER_NAME:
|
|
367
|
+
return i18nString(UIStrings.encoderName);
|
|
368
|
+
case PlayerPropertyKeys.IS_PLATFORM_VIDEO_ENCODER:
|
|
369
|
+
return i18nString(UIStrings.hardwareEncoder);
|
|
370
|
+
case PlayerPropertyKeys.IS_VIDEO_DECRYPTION_DEMUXER_STREAM:
|
|
371
|
+
return i18nString(UIStrings.decryptingDemuxer);
|
|
372
|
+
case PlayerPropertyKeys.AUDIO_DECODER_NAME:
|
|
373
|
+
return i18nString(UIStrings.decoderName);
|
|
374
|
+
case PlayerPropertyKeys.IS_PLATFORM_AUDIO_DECODER:
|
|
375
|
+
return i18nString(UIStrings.hardwareDecoder);
|
|
376
|
+
case PlayerPropertyKeys.IS_AUDIO_DECRYPTING_DEMUXER_STREAM:
|
|
377
|
+
return i18nString(UIStrings.decryptingDemuxer);
|
|
378
|
+
default:
|
|
379
|
+
return Platform.UIString.LocalizedEmptyString;
|
|
516
380
|
}
|
|
517
|
-
const date = new Date();
|
|
518
|
-
date.setSeconds(Number(seconds));
|
|
519
|
-
return date.toISOString().substr(11, 8);
|
|
520
381
|
}
|
|
521
382
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
383
|
+
const renderAttribute = (data: string|null|LitTemplate, title: string): LitTemplate => {
|
|
384
|
+
return html`<div class=${classMap({
|
|
385
|
+
widget: true,
|
|
386
|
+
vbox: true,
|
|
387
|
+
'media-property-renderer': true,
|
|
388
|
+
'media-property-renderer-hidden': data === null,
|
|
389
|
+
})}>
|
|
390
|
+
<span class=media-property-renderer-title>${title}</span>
|
|
391
|
+
<div class=media-property-renderer-contents>${data}</div>
|
|
392
|
+
</div>`;
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const renderProperty = (property: Property): LitTemplate => {
|
|
396
|
+
let fallback: string|null = null;
|
|
397
|
+
if (property.type === PlayerPropertyKeys.VIDEO_DECODER_NAME ||
|
|
398
|
+
property.type === PlayerPropertyKeys.AUDIO_DECODER_NAME) {
|
|
399
|
+
fallback = i18nString(UIStrings.noDecoder);
|
|
400
|
+
} else if (property.type === PlayerPropertyKeys.VIDEO_ENCODER_NAME) {
|
|
401
|
+
fallback = i18nString(UIStrings.noEncoder);
|
|
525
402
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
403
|
+
return renderAttribute(property.data ?? fallback, propertyTitle(property.type));
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
const renderTracks =
|
|
407
|
+
(property: Property, trackName: Platform.UIString.LocalizedString, idPrefix: string): LitTemplate[] =>
|
|
408
|
+
property instanceof TrackProperty && property.entries !== null ?
|
|
409
|
+
property.entries.map(
|
|
410
|
+
// clang-format off
|
|
411
|
+
(track, i) => html`
|
|
412
|
+
<div id=track-${idPrefix}-${i} title=${i18nString(UIStrings.trackNumber, {PH1: trackName, PH2: i + 1})}>
|
|
413
|
+
<div class="widget vbox media-attributes-view">
|
|
414
|
+
${Object.entries(track).map(([name, data]) => renderAttribute(typeof data === 'object' ? html`${
|
|
415
|
+
widget(e => new SourceFrame.JSONView.JSONView(
|
|
416
|
+
new SourceFrame.JSONView.ParsedJSON(data, '', ''), true, e))}` :
|
|
417
|
+
String(data),
|
|
418
|
+
name))}
|
|
419
|
+
</div>
|
|
420
|
+
</div>`)
|
|
421
|
+
: [nothing];
|
|
422
|
+
// clang-format on
|
|
423
|
+
|
|
424
|
+
render(
|
|
425
|
+
// clang-format off
|
|
426
|
+
html`
|
|
427
|
+
<style>${playerPropertiesViewStyles}</style>
|
|
428
|
+
<div class="widget vbox media-attributes-view">
|
|
429
|
+
${renderProperty(input.properties[PlayerPropertyKeys.RESOLUTION])}
|
|
430
|
+
${renderProperty(input.properties[PlayerPropertyKeys.TOTAL_BYTES])}
|
|
431
|
+
${renderProperty(input.properties[PlayerPropertyKeys.BITRATE])}
|
|
432
|
+
${renderProperty(input.properties[PlayerPropertyKeys.MAX_DURATION])}
|
|
433
|
+
${renderProperty(input.properties[PlayerPropertyKeys.START_TIME])}
|
|
434
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_STREAMING])}
|
|
435
|
+
${renderProperty(input.properties[PlayerPropertyKeys.FRAME_URL])}
|
|
436
|
+
${renderProperty(input.properties[PlayerPropertyKeys.FRAME_TITLE])}
|
|
437
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_SINGLE_ORIGIN])}
|
|
438
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_RANGE_HEADER_SUPPORTED])}
|
|
439
|
+
${renderProperty(input.properties[PlayerPropertyKeys.FRAMERATE])}
|
|
440
|
+
${renderProperty(input.properties[PlayerPropertyKeys.VIDEO_PLAYBACK_ROUGHNESS])}
|
|
441
|
+
${renderProperty(input.properties[PlayerPropertyKeys.VIDEO_PLAYBACK_FREEZING])}
|
|
442
|
+
${renderProperty(input.properties[PlayerPropertyKeys.RENDERER_NAME])}
|
|
443
|
+
${renderProperty(input.properties[PlayerPropertyKeys.HLS_BUFFERED_RANGES])}
|
|
444
|
+
</div>
|
|
445
|
+
<devtools-tabbed-pane>
|
|
446
|
+
<div id=decoder-properties title=${i18nString(UIStrings.videoDecoderProperties)}>
|
|
447
|
+
<div class="widget vbox media-attributes-view">
|
|
448
|
+
${renderProperty(input.properties[PlayerPropertyKeys.VIDEO_DECODER_NAME])}
|
|
449
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_PLATFORM_VIDEO_DECODER])}
|
|
450
|
+
${renderProperty(input.properties[PlayerPropertyKeys.VIDEO_ENCODER_NAME])}
|
|
451
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_PLATFORM_VIDEO_ENCODER])}
|
|
452
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_VIDEO_DECRYPTION_DEMUXER_STREAM])}
|
|
453
|
+
</div>
|
|
454
|
+
</div>
|
|
455
|
+
${renderTracks(input.properties[PlayerPropertyKeys.VIDEO_TRACKS], i18nString(UIStrings.track), 'video')}
|
|
456
|
+
</devtools-tabbed-pane>
|
|
457
|
+
<devtools-tabbed-pane>
|
|
458
|
+
<div id=decoder-properties title=${i18nString(UIStrings.audioDecoderProperties)}>
|
|
459
|
+
<div class="widget vbox media-attributes-view">
|
|
460
|
+
${renderProperty(input.properties[PlayerPropertyKeys.AUDIO_DECODER_NAME])}
|
|
461
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_PLATFORM_AUDIO_DECODER])}
|
|
462
|
+
${renderProperty(input.properties[PlayerPropertyKeys.IS_AUDIO_DECRYPTING_DEMUXER_STREAM])}
|
|
463
|
+
</div>
|
|
464
|
+
</div>
|
|
465
|
+
${renderTracks(input.properties[PlayerPropertyKeys.AUDIO_TRACKS], i18nString(UIStrings.track), 'audio')}
|
|
466
|
+
</devtools-tabbed-pane>
|
|
467
|
+
${input.properties[PlayerPropertyKeys.TEXT_TRACKS] instanceof TrackProperty &&
|
|
468
|
+
input.properties[PlayerPropertyKeys.TEXT_TRACKS].entries !== null ? html`
|
|
469
|
+
<devtools-tabbed-pane>
|
|
470
|
+
${input.properties[PlayerPropertyKeys.TEXT_TRACKS].entries.length === 0 ?
|
|
471
|
+
html`<div id=_placeholder title=${i18nString(UIStrings.noTextTracks)}></div>` :
|
|
472
|
+
renderTracks(input.properties[PlayerPropertyKeys.TEXT_TRACKS], i18nString(UIStrings.textTrack), 'text')}
|
|
473
|
+
</devtools-tabbed-pane>`
|
|
474
|
+
: nothing}
|
|
475
|
+
`,
|
|
476
|
+
// clang-format on
|
|
477
|
+
target,
|
|
478
|
+
{container: {attributes: {jslog: `${VisualLogging.pane('properties')}`}, classes: ['media-properties-frame']}});
|
|
479
|
+
};
|
|
535
480
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
return ranges
|
|
539
|
-
.map(range => {
|
|
540
|
-
return '[' + range[0] + ' → ' + range[1] + ']';
|
|
541
|
-
})
|
|
542
|
-
.join(', ');
|
|
543
|
-
}
|
|
481
|
+
export class PlayerPropertiesView extends UI.Widget.VBox {
|
|
482
|
+
readonly #view: View;
|
|
544
483
|
|
|
545
|
-
|
|
484
|
+
#properties: Record<PlayerPropertyKeys, Property> = {
|
|
546
485
|
/* Media properties */
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const startTime = new PropertyRenderer(i18nString(UIStrings.startTime));
|
|
564
|
-
this.mediaElements.push(startTime);
|
|
565
|
-
this.attributeMap.set(PlayerPropertyKeys.START_TIME, startTime);
|
|
566
|
-
|
|
567
|
-
const streaming = new PropertyRenderer(i18nString(UIStrings.streaming));
|
|
568
|
-
this.mediaElements.push(streaming);
|
|
569
|
-
this.attributeMap.set(PlayerPropertyKeys.IS_STREAMING, streaming);
|
|
570
|
-
|
|
571
|
-
const frameUrl = new PropertyRenderer(i18nString(UIStrings.playbackFrameUrl));
|
|
572
|
-
this.mediaElements.push(frameUrl);
|
|
573
|
-
this.attributeMap.set(PlayerPropertyKeys.FRAME_URL, frameUrl);
|
|
574
|
-
|
|
575
|
-
const frameTitle = new PropertyRenderer(i18nString(UIStrings.playbackFrameTitle));
|
|
576
|
-
this.mediaElements.push(frameTitle);
|
|
577
|
-
this.attributeMap.set(PlayerPropertyKeys.FRAME_TITLE, frameTitle);
|
|
578
|
-
|
|
579
|
-
const singleOrigin = new PropertyRenderer(i18nString(UIStrings.singleoriginPlayback));
|
|
580
|
-
this.mediaElements.push(singleOrigin);
|
|
581
|
-
this.attributeMap.set(PlayerPropertyKeys.IS_SINGLE_ORIGIN, singleOrigin);
|
|
582
|
-
|
|
583
|
-
const rangeHeaders = new PropertyRenderer(i18nString(UIStrings.rangeHeaderSupport));
|
|
584
|
-
this.mediaElements.push(rangeHeaders);
|
|
585
|
-
this.attributeMap.set(PlayerPropertyKeys.IS_RANGE_HEADER_SUPPORTED, rangeHeaders);
|
|
586
|
-
|
|
587
|
-
const frameRate = new PropertyRenderer(i18nString(UIStrings.frameRate));
|
|
588
|
-
this.mediaElements.push(frameRate);
|
|
589
|
-
this.attributeMap.set(PlayerPropertyKeys.FRAMERATE, frameRate);
|
|
590
|
-
|
|
591
|
-
const roughness = new PropertyRenderer(i18nString(UIStrings.videoPlaybackRoughness));
|
|
592
|
-
this.mediaElements.push(roughness);
|
|
593
|
-
this.attributeMap.set(PlayerPropertyKeys.VIDEO_PLAYBACK_ROUGHNESS, roughness);
|
|
594
|
-
|
|
595
|
-
const freezingScore = new PropertyRenderer(i18nString(UIStrings.videoFreezingScore));
|
|
596
|
-
this.mediaElements.push(freezingScore);
|
|
597
|
-
this.attributeMap.set(PlayerPropertyKeys.VIDEO_PLAYBACK_FREEZING, freezingScore);
|
|
598
|
-
|
|
599
|
-
const rendererName = new PropertyRenderer(i18nString(UIStrings.rendererName));
|
|
600
|
-
this.mediaElements.push(rendererName);
|
|
601
|
-
this.attributeMap.set(PlayerPropertyKeys.RENDERER_NAME, rendererName);
|
|
602
|
-
|
|
603
|
-
const hlsBufferedRanges =
|
|
604
|
-
new FormattedPropertyRenderer(i18nString(UIStrings.hlsBufferedRanges), this.formatBufferedRanges);
|
|
605
|
-
this.mediaElements.push(hlsBufferedRanges);
|
|
606
|
-
this.attributeMap.set(PlayerPropertyKeys.HLS_BUFFERED_RANGES, hlsBufferedRanges);
|
|
486
|
+
[PlayerPropertyKeys.RESOLUTION]: new Property(PlayerPropertyKeys.RESOLUTION),
|
|
487
|
+
[PlayerPropertyKeys.TOTAL_BYTES]: new TotalBytesProperty(),
|
|
488
|
+
[PlayerPropertyKeys.BITRATE]: new BitRateProperty(),
|
|
489
|
+
[PlayerPropertyKeys.MAX_DURATION]: new MaxDurationProperty(),
|
|
490
|
+
[PlayerPropertyKeys.START_TIME]: new Property(PlayerPropertyKeys.START_TIME),
|
|
491
|
+
[PlayerPropertyKeys.IS_STREAMING]: new Property(PlayerPropertyKeys.IS_STREAMING),
|
|
492
|
+
[PlayerPropertyKeys.FRAME_URL]: new Property(PlayerPropertyKeys.FRAME_URL),
|
|
493
|
+
[PlayerPropertyKeys.FRAME_TITLE]: new Property(PlayerPropertyKeys.FRAME_TITLE),
|
|
494
|
+
[PlayerPropertyKeys.IS_SINGLE_ORIGIN]: new Property(PlayerPropertyKeys.IS_SINGLE_ORIGIN),
|
|
495
|
+
[PlayerPropertyKeys.IS_RANGE_HEADER_SUPPORTED]: new Property(PlayerPropertyKeys.IS_RANGE_HEADER_SUPPORTED),
|
|
496
|
+
[PlayerPropertyKeys.FRAMERATE]: new Property(PlayerPropertyKeys.FRAMERATE),
|
|
497
|
+
[PlayerPropertyKeys.VIDEO_PLAYBACK_ROUGHNESS]: new Property(PlayerPropertyKeys.VIDEO_PLAYBACK_ROUGHNESS),
|
|
498
|
+
[PlayerPropertyKeys.VIDEO_PLAYBACK_FREEZING]: new Property(PlayerPropertyKeys.VIDEO_PLAYBACK_FREEZING),
|
|
499
|
+
[PlayerPropertyKeys.RENDERER_NAME]: new Property(PlayerPropertyKeys.RENDERER_NAME),
|
|
500
|
+
[PlayerPropertyKeys.HLS_BUFFERED_RANGES]: new HlsBufferedRangesProperty(),
|
|
607
501
|
|
|
608
502
|
/* Video Decoder Properties */
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
const encoderName = new DefaultPropertyRenderer(i18nString(UIStrings.encoderName), i18nString(UIStrings.noEncoder));
|
|
618
|
-
this.videoDecoderElements.push(encoderName);
|
|
619
|
-
this.attributeMap.set(PlayerPropertyKeys.VIDEO_ENCODER_NAME, encoderName);
|
|
620
|
-
|
|
621
|
-
const videoPlatformEncoder = new PropertyRenderer(i18nString(UIStrings.hardwareEncoder));
|
|
622
|
-
this.videoDecoderElements.push(videoPlatformEncoder);
|
|
623
|
-
this.attributeMap.set(PlayerPropertyKeys.IS_PLATFORM_VIDEO_ENCODER, videoPlatformEncoder);
|
|
624
|
-
|
|
625
|
-
const videoDDS = new PropertyRenderer(i18nString(UIStrings.decryptingDemuxer));
|
|
626
|
-
this.videoDecoderElements.push(videoDDS);
|
|
627
|
-
this.attributeMap.set(PlayerPropertyKeys.IS_VIDEO_DECRYPTION_DEMUXER_STREAM, videoDDS);
|
|
628
|
-
|
|
629
|
-
const videoTrackManager = new VideoTrackManager(this);
|
|
630
|
-
this.attributeMap.set(PlayerPropertyKeys.VIDEO_TRACKS, videoTrackManager);
|
|
503
|
+
[PlayerPropertyKeys.VIDEO_DECODER_NAME]: new Property(PlayerPropertyKeys.VIDEO_DECODER_NAME),
|
|
504
|
+
[PlayerPropertyKeys.IS_PLATFORM_VIDEO_DECODER]: new Property(PlayerPropertyKeys.IS_PLATFORM_VIDEO_DECODER),
|
|
505
|
+
[PlayerPropertyKeys.VIDEO_ENCODER_NAME]: new Property(PlayerPropertyKeys.VIDEO_ENCODER_NAME),
|
|
506
|
+
[PlayerPropertyKeys.IS_PLATFORM_VIDEO_ENCODER]: new Property(PlayerPropertyKeys.IS_PLATFORM_VIDEO_ENCODER),
|
|
507
|
+
[PlayerPropertyKeys.IS_VIDEO_DECRYPTION_DEMUXER_STREAM]:
|
|
508
|
+
new Property(PlayerPropertyKeys.IS_VIDEO_DECRYPTION_DEMUXER_STREAM),
|
|
509
|
+
[PlayerPropertyKeys.VIDEO_TRACKS]: new TrackProperty(PlayerPropertyKeys.VIDEO_TRACKS),
|
|
631
510
|
|
|
632
511
|
/* Audio Decoder Properties */
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
512
|
+
[PlayerPropertyKeys.AUDIO_DECODER_NAME]: new Property(PlayerPropertyKeys.AUDIO_DECODER_NAME),
|
|
513
|
+
[PlayerPropertyKeys.IS_PLATFORM_AUDIO_DECODER]: new Property(PlayerPropertyKeys.IS_PLATFORM_AUDIO_DECODER),
|
|
514
|
+
[PlayerPropertyKeys.IS_AUDIO_DECRYPTING_DEMUXER_STREAM]:
|
|
515
|
+
new Property(PlayerPropertyKeys.IS_AUDIO_DECRYPTING_DEMUXER_STREAM),
|
|
516
|
+
[PlayerPropertyKeys.AUDIO_TRACKS]: new TrackProperty(PlayerPropertyKeys.AUDIO_TRACKS),
|
|
517
|
+
[PlayerPropertyKeys.TEXT_TRACKS]: new TrackProperty(PlayerPropertyKeys.TEXT_TRACKS),
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
constructor(target?: HTMLElement, view = DEFAULT_VIEW) {
|
|
521
|
+
super(target);
|
|
522
|
+
this.#view = view;
|
|
523
|
+
}
|
|
637
524
|
|
|
638
|
-
|
|
639
|
-
this
|
|
640
|
-
|
|
525
|
+
get properties(): Record<PlayerPropertyKeys, Property> {
|
|
526
|
+
return this.#properties;
|
|
527
|
+
}
|
|
641
528
|
|
|
642
|
-
|
|
643
|
-
this
|
|
644
|
-
|
|
529
|
+
onProperty(property: Protocol.Media.PlayerProperty): void {
|
|
530
|
+
if (!(property.name in this.#properties)) {
|
|
531
|
+
throw new Error(`Player property '${property.name}' not supported.`);
|
|
532
|
+
}
|
|
533
|
+
this.#properties[property.name as PlayerPropertyKeys].data = property.value;
|
|
534
|
+
this.requestUpdate();
|
|
535
|
+
}
|
|
645
536
|
|
|
646
|
-
|
|
647
|
-
|
|
537
|
+
override wasShown(): void {
|
|
538
|
+
super.wasShown();
|
|
539
|
+
this.requestUpdate();
|
|
540
|
+
}
|
|
648
541
|
|
|
649
|
-
|
|
650
|
-
this
|
|
542
|
+
override performUpdate(): void {
|
|
543
|
+
this.#view(this, {}, this.contentElement);
|
|
651
544
|
}
|
|
652
545
|
}
|