Repository: electron/electron
Pull request: fix: initialze featurelist before parsing features

#### Description of Change

`base::FeatureList` needs to be initialized before any features are parsed so that appropriate field trials are setup. Today we call `InitializeFeatureList` from `Electron::PreBrowserMain` and `Electron::PostEarlyInitialization` however the feature list is initialized somewhere in between via `Electron::PreEarlyInitialization`. This results in the following crash when launching the application with a feature param `--enable-features="NetAdapterMaxBufSizeFeature:NetAdapterMaxBufSize/8192"`.

```
[56990:0929/130502.801852:FATAL:base/feature_list.cc:905] DCHECK failed: trial. trial='StudyNetAdapterMaxBufSizeFeature' does not exist
```

This PR addresses by moving the feature list initialization before any feature parsing happens. The instance leaked is on purpose aligning with upstream https://source.chromium.org/chromium/chromium/src/+/main:content/app/content_main_runner_impl.cc;l=1150-1155

#### Release Notes

Notes: fix crash when passing feature param from commandline `--enable-features=Feature:ParamA/Value`

Changed files:
filename: shell/app/electron_main_delegate.cc
patch: @@ -13,10 +13,12 @@
 #include "base/apple/bundle_locations.h"
 #include "base/base_switches.h"
 #include "base/command_line.h"
+#include "base/debug/leak_annotations.h"
 #include "base/debug/stack_trace.h"
 #include "base/environment.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/metrics/field_trial.h"
 #include "base/path_service.h"
 #include "base/strings/cstring_view.h"
 #include "base/strings/string_number_conversions.cc"
@@ -419,6 +421,11 @@ std::optional<int> ElectronMainDelegate::PreBrowserMain() {
   // This is initialized early because the service manager reads some feature
   // flags and we need to make sure the feature list is initialized before the
   // service manager reads the features.
+  if (!base::FieldTrialList::GetInstance()) {
+    base::FieldTrialList* leaked_field_trial_list = new base::FieldTrialList();
+    ANNOTATE_LEAKING_OBJECT_PTR(leaked_field_trial_list);
+    std::ignore = leaked_field_trial_list;
+  }
   InitializeFeatureList();
   // Initialize mojo core as soon as we have a valid feature list
   content::InitializeMojoCore();

filename: shell/browser/electron_browser_main_parts.cc
patch: @@ -14,7 +14,6 @@
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/i18n/rtl.h"
-#include "base/metrics/field_trial.h"
 #include "base/nix/xdg_util.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
@@ -206,7 +205,6 @@ int ElectronBrowserMainParts::GetExitCode() const {
 }
 
 int ElectronBrowserMainParts::PreEarlyInitialization() {
-  field_trial_list_ = std::make_unique<base::FieldTrialList>();
 #if BUILDFLAG(IS_POSIX)
   HandleSIGCHLD();
 #endif

filename: shell/browser/electron_browser_main_parts.h
patch: @@ -19,10 +19,6 @@
 class BrowserProcessImpl;
 class IconManager;
 
-namespace base {
-class FieldTrialList;
-}
-
 namespace display {
 class Screen;
 class ScopedNativeScreen;
@@ -171,7 +167,6 @@ class ElectronBrowserMainParts : public content::BrowserMainParts {
   std::unique_ptr<Browser> browser_;
 
   std::unique_ptr<IconManager> icon_manager_;
-  std::unique_ptr<base::FieldTrialList> field_trial_list_;
 
 #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
   std::unique_ptr<ElectronExtensionsClient> extensions_client_;