Skip to content

Commit fea57fa

Browse files
committed
Add initial feature/UI customisations for profiling builds
1 parent 6b80704 commit fea57fa

File tree

8 files changed

+133
-6
lines changed

8 files changed

+133
-6
lines changed

config/gni/devtools_grd_files.gni

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,7 @@ grd_files_debug_sources = [
842842
"front_end/entrypoints/node_app/NodeConnectionsPanel.js",
843843
"front_end/entrypoints/node_app/NodeMain.js",
844844
"front_end/entrypoints/node_app/nodeConnectionsPanel.css.js",
845+
"front_end/entrypoints/rn_fusebox/FuseboxProfilingBuildObserver.js",
845846
"front_end/entrypoints/shell/browser_compatibility_guard.js",
846847
"front_end/entrypoints/wasmparser_worker/WasmParserWorker.js",
847848
"front_end/entrypoints/worker_app/WorkerMain.js",

front_end/entrypoints/rn_fusebox/BUILD.gn

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,25 @@
22
# Copyright 2021 The Chromium Authors. All rights reserved.
33
# Use of this source code is governed by a BSD-style license that can be
44
# found in the LICENSE file.
5+
56
import("../../../scripts/build/ninja/devtools_entrypoint.gni")
7+
import("../../../scripts/build/ninja/devtools_module.gni")
68
import("../visibility.gni")
79

10+
devtools_module("rn_fusebox") {
11+
sources = [
12+
"FuseboxProfilingBuildObserver.ts",
13+
]
14+
15+
deps = [
16+
"../../core/common:bundle",
17+
"../../core/i18n:bundle",
18+
"../../core/root:bundle",
19+
"../../core/sdk:bundle",
20+
"../../ui/legacy:bundle",
21+
]
22+
}
23+
824
devtools_entrypoint("entrypoint") {
925
entrypoint = "rn_fusebox.ts"
1026

@@ -39,6 +55,7 @@ devtools_entrypoint("entrypoint") {
3955
"../../panels/webauthn:meta",
4056
"../main:bundle",
4157
"../shell",
58+
":rn_fusebox",
4259
]
4360

4461
visibility = [ "../../:*" ]
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) Meta Platforms, Inc. and affiliates.
2+
// Copyright 2024 The Chromium Authors. All rights reserved.
3+
// Use of this source code is governed by a BSD-style license that can be
4+
// found in the LICENSE file.
5+
6+
import * as Common from '../../core/common/common.js';
7+
import * as Protocol from '../../generated/protocol.js';
8+
import * as Root from '../../core/root/root.js';
9+
import * as SDK from '../../core/sdk/sdk.js';
10+
import * as UI from '../../ui/legacy/legacy.js';
11+
import * as i18n from '../../core/i18n/i18n.js';
12+
13+
const UIStrings = {
14+
/**
15+
* @description Message for the "settings changed" banner shown when a reload is required.
16+
*/
17+
reloadRequiredMessage: '[Profiling build first run] One or more settings have changed. Please reload to access the Performance panel.',
18+
};
19+
20+
const str_ = i18n.i18n.registerUIStrings('entrypoints/rn_fusebox/FuseboxProfilingBuildModeObserver.ts', UIStrings);
21+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
22+
23+
/**
24+
* [Experimental] Model observer which configures available DevTools features
25+
* when a profiling build is identified.
26+
*/
27+
export default class FuseboxProfilingBuildObserver implements
28+
SDK.TargetManager.SDKModelObserver<SDK.ReactNativeApplicationModel.ReactNativeApplicationModel> {
29+
constructor(targetManager: SDK.TargetManager.TargetManager) {
30+
targetManager.observeModels(SDK.ReactNativeApplicationModel.ReactNativeApplicationModel, this);
31+
}
32+
33+
modelAdded(model: SDK.ReactNativeApplicationModel.ReactNativeApplicationModel): void {
34+
model.ensureEnabled();
35+
model.addEventListener(SDK.ReactNativeApplicationModel.Events.MetadataUpdated, this.#handleMetadataUpdated, this);
36+
}
37+
38+
modelRemoved(model: SDK.ReactNativeApplicationModel.ReactNativeApplicationModel): void {
39+
model.removeEventListener(
40+
SDK.ReactNativeApplicationModel.Events.MetadataUpdated, this.#handleMetadataUpdated, this);
41+
}
42+
43+
#handleMetadataUpdated(
44+
event: Common.EventTarget.EventTargetEvent<Protocol.ReactNativeApplication.MetadataUpdatedEvent>): void {
45+
const {unstable_isProfilingBuild} = event.data;
46+
47+
if (unstable_isProfilingBuild) {
48+
this.#hideUnsupportedFeatures();
49+
this.#ensurePerformancePanelEnabled();
50+
}
51+
}
52+
53+
#hideUnsupportedFeatures(): void {
54+
UI.ViewManager.ViewManager.instance()
55+
.resolveLocation(UI.ViewManager.ViewLocationValues.PANEL)
56+
.then(location => {
57+
UI.ViewManager.getRegisteredViewExtensions().forEach(view => {
58+
switch (view.viewId()) {
59+
case 'sources':
60+
case 'network':
61+
case 'react-devtools-components':
62+
case 'react-devtools-profiler':
63+
location?.removeView(view);
64+
break;
65+
}
66+
});
67+
});
68+
}
69+
70+
#ensurePerformancePanelEnabled(): void {
71+
if (
72+
!Root.Runtime.experiments.isEnabled(
73+
Root.Runtime.ExperimentName.ENABLE_PERFORMANCE_PANEL,
74+
)
75+
) {
76+
Root.Runtime.experiments.setEnabled(
77+
Root.Runtime.ExperimentName.ENABLE_PERFORMANCE_PANEL,
78+
true,
79+
);
80+
81+
const inspectorView = UI.InspectorView?.InspectorView?.instance();
82+
if (inspectorView) {
83+
inspectorView.displayReloadRequiredWarning(
84+
i18nString(UIStrings.reloadRequiredMessage),
85+
);
86+
}
87+
}
88+
}
89+
}

front_end/entrypoints/rn_fusebox/rn_fusebox.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import * as Protocol from '../../generated/protocol.js';
2828
import type * as Platform from '../../core/platform/platform.js';
2929
import type * as Sources from '../../panels/sources/sources.js';
3030
import * as RNExperiments from '../../core/rn_experiments/rn_experiments.js';
31+
import FuseboxProfilingBuildObserver from './FuseboxProfilingBuildObserver.js';
3132

3233
/*
3334
* To ensure accurate timing measurements,
@@ -275,5 +276,6 @@ class FuseboxReactNativeApplicationObserver implements
275276
}
276277

277278
new FuseboxReactNativeApplicationObserver(SDK.TargetManager.TargetManager.instance());
279+
new FuseboxProfilingBuildObserver(SDK.TargetManager.TargetManager.instance());
278280

279281
Host.rnPerfMetrics.entryPointLoadingFinished('rn_fusebox');

front_end/generated/protocol.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ export namespace ReactNativeApplication {
6060
* The React Native version.
6161
*/
6262
reactNativeVersion?: string;
63+
/**
64+
* Whether the app is a profiling build.
65+
*/
66+
unstable_isProfilingBuild?: boolean;
6367
}
6468
}
6569

front_end/panels/timeline/TimelinePanel.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
261261

262262
let timelinePanelInstance: TimelinePanel;
263263
let isNode: boolean;
264+
let isReactNative: boolean;
264265

265266
export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineModeViewDelegate {
266267
private readonly dropTarget: UI.DropTarget.DropTarget;
@@ -364,7 +365,7 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
364365
this.captureLayersAndPicturesSetting.setTitle(i18nString(UIStrings.enableAdvancedPaint));
365366

366367
this.showScreenshotsSetting =
367-
Common.Settings.Settings.instance().createSetting('timeline-show-screenshots', isNode ? false : true);
368+
Common.Settings.Settings.instance().createSetting('timeline-show-screenshots', isNode || isReactNative ? false : true);
368369
this.showScreenshotsSetting.setTitle(i18nString(UIStrings.screenshots));
369370
this.showScreenshotsSetting.addChangeListener(this.updateOverviewControls, this);
370371

@@ -377,7 +378,7 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
377378
this.panelToolbar = new UI.Toolbar.Toolbar('timeline-main-toolbar', timelineToolbarContainer);
378379
this.panelToolbar.makeWrappable(true);
379380
this.panelRightToolbar = new UI.Toolbar.Toolbar('', timelineToolbarContainer);
380-
if (!isNode) {
381+
if (!isNode && !isReactNative) {
381382
this.createSettingsPane();
382383
this.updateShowSettingsToolbarButton();
383384
}
@@ -454,6 +455,11 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
454455
const {forceNew, isNode: isNodeMode} = opts;
455456
isNode = isNodeMode;
456457

458+
// [RN] Used to scope down available features for React Native targets
459+
isReactNative = Root.Runtime.experiments.isEnabled(
460+
Root.Runtime.ExperimentName.REACT_NATIVE_SPECIFIC_UI,
461+
);
462+
457463
if (!timelinePanelInstance || forceNew) {
458464
timelinePanelInstance = new TimelinePanel();
459465
}
@@ -560,7 +566,7 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
560566

561567
// View
562568
this.panelToolbar.appendSeparator();
563-
if (!isNode) {
569+
if (!isNode && !isReactNative) {
564570
this.showScreenshotsToolbarCheckbox =
565571
this.createSettingCheckbox(this.showScreenshotsSetting, i18nString(UIStrings.captureScreenshots));
566572
this.panelToolbar.appendToolbarItem(this.showScreenshotsToolbarCheckbox);
@@ -581,7 +587,7 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
581587
}
582588

583589
// Settings
584-
if (!isNode) {
590+
if (!isNode && !isReactNative) {
585591
this.panelRightToolbar.appendSeparator();
586592
this.panelRightToolbar.appendToolbarItem(this.showSettingsPaneButton);
587593
}
@@ -801,7 +807,7 @@ export class TimelinePanel extends UI.Panel.Panel implements Client, TimelineMod
801807
}
802808

803809
private updateSettingsPaneVisibility(): void {
804-
if (isNode) {
810+
if (isNode || isReactNative) {
805811
return;
806812
}
807813
if (this.showSettingsPaneSetting.get()) {

third_party/blink/public/devtools_protocol/browser_protocol.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@
6868
"description": "The React Native version.",
6969
"optional": true,
7070
"type": "string"
71+
},
72+
{
73+
"name": "unstable_isProfilingBuild",
74+
"description": "Whether the app is a profiling build.",
75+
"optional": true,
76+
"type": "boolean"
7177
}
7278
]
7379
}
@@ -29262,4 +29268,4 @@
2926229268
]
2926329269
}
2926429270
]
29265-
}
29271+
}

third_party/blink/public/devtools_protocol/react_native_domains.pdl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ experimental domain ReactNativeApplication
3737
optional string platform
3838
# The React Native version.
3939
optional string reactNativeVersion
40+
# Whether the app is a profiling build.
41+
optional boolean unstable_isProfilingBuild

0 commit comments

Comments
 (0)