0

[ios blink] Adjust process initialization

Enable initialization of the feature list before mojo
is initialized. This changes the creation of the
ApplicationContextImpl to happen in a PostEarlyInitialization
callback in the IOSMainDelegate.

Bug: 40261735
Change-Id: If2b76a2fad420fb15551354ecb65a85310777504
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6293264
Reviewed-by: Rohit Rao <rohitrao@chromium.org>
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Justin Cohen <justincohen@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1424792}
This commit is contained in:
Dave Tapuska
2025-02-25 14:01:10 -08:00
committed by Chromium LUCI CQ
parent e58017eab5
commit fde3488573
11 changed files with 147 additions and 49 deletions

@ -457,11 +457,15 @@ ApplicationContextImpl::GetNetworkConnectionTracker() {
BrowserPolicyConnectorIOS* ApplicationContextImpl::GetBrowserPolicyConnector() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!browser_policy_connector_.get()) {
#if !BUILDFLAG(USE_BLINK)
// Ensure that the ResourceBundle has already been initialized. If this
// DCHECK ever fails, a call to
// BrowserPolicyConnector::OnResourceBundleCreated() will need to be added
// later in the startup sequence, after the ResourceBundle is initialized.
// Blink based startup will call OnResourceBundleCreated in
// IOSChromeMainParts::PreCreateThreads.
DCHECK(ui::ResourceBundle::HasSharedInstance());
#endif
version_info::Channel channel = ::GetChannel();
policy::ConfigurationPolicyProvider* test_policy_provider =
tests_hook::GetOverriddenPlatformPolicyProvider();

@ -79,6 +79,8 @@ class BrowserPolicyConnectorIOS : public policy::BrowserPolicyConnector {
// line switch anyway.
bool IsCommandLineSwitchSupported() const override;
void OnResourceBundleCreated();
protected:
// BrowserPolicyConnectorBase.
std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>>

@ -165,3 +165,7 @@ BrowserPolicyConnectorIOS::CreatePlatformProvider() {
return std::make_unique<AsyncPolicyProvider>(GetSchemaRegistry(),
std::move(loader));
}
void BrowserPolicyConnectorIOS::OnResourceBundleCreated() {
BrowserPolicyConnectorBase::OnResourceBundleCreated();
}

@ -27,6 +27,10 @@ class IOSChromeMainParts : public web::WebMainParts {
~IOSChromeMainParts() override;
// Initializes the field trials and feature list. This should be called early
// before features such as mojo are initialized.
void InitializeFieldTrialAndFeatureList();
private:
// web::WebMainParts implementation.
void PreCreateMainMessageLoop() override;
@ -47,6 +51,12 @@ class IOSChromeMainParts : public web::WebMainParts {
// Constructs the metrics service and initializes metrics recording.
void SetupMetrics();
// Create the application context.
void CreateApplicationContext();
// Apply the command line to the feature list.
void ApplyFeatureList();
// Starts recording of metrics. This can only be called after we have a file
// thread.
void StartMetricsRecording();

@ -136,7 +136,9 @@ IOSChromeMainParts::~IOSChromeMainParts() {
}
void IOSChromeMainParts::PreCreateMainMessageLoop() {
#if !BUILDFLAG(USE_BLINK)
l10n_util::OverrideLocaleWithCocoaLocale();
#endif
const std::string loaded_locale =
ui::ResourceBundle::InitSharedInstanceWithLocale(
std::string(), nullptr, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
@ -152,22 +154,15 @@ void IOSChromeMainParts::PreCreateMainMessageLoop() {
resources_pack_path, ui::k100Percent);
}
void IOSChromeMainParts::PreCreateThreads() {
// Create and start the stack sampling profiler if CANARY or DEV. The warning
// below doesn't apply.
const version_info::Channel channel = ::GetChannel();
if (channel == version_info::Channel::CANARY ||
channel == version_info::Channel::DEV) {
sampling_profiler_ = IOSThreadProfiler::CreateAndStartOnMainThread();
IOSThreadProfiler::SetMainThreadTaskRunner(
base::SingleThreadTaskRunner::GetCurrentDefault());
}
// IMPORTANT
// Calls in this function should not post tasks or create threads as
// components used to handle those tasks are not yet available. This work
// should be deferred to PreMainMessageLoopRunImpl.
void IOSChromeMainParts::InitializeFieldTrialAndFeatureList() {
#if BUILDFLAG(USE_BLINK)
l10n_util::OverrideLocaleWithCocoaLocale();
CreateApplicationContext();
ApplyFeatureList();
#endif
}
void IOSChromeMainParts::CreateApplicationContext() {
// The initial read is done synchronously, the TaskPriority is thus only used
// for flushes to disks and BACKGROUND is therefore appropriate. Priority of
// remaining BACKGROUND+BLOCK_SHUTDOWN tasks is bumped by the ThreadPool on
@ -178,36 +173,15 @@ void IOSChromeMainParts::PreCreateThreads() {
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::SingleThreadTaskRunnerThreadMode::DEDICATED);
base::FilePath local_state_path;
CHECK(base::PathService::Get(ios::FILE_LOCAL_STATE, &local_state_path));
application_context_.reset(new ApplicationContextImpl(
local_state_task_runner.get(), *parsed_command_line_,
l10n_util::GetLocaleOverride(),
base::SysNSStringToUTF8(
[[NSLocale currentLocale] objectForKey:NSLocaleCountryCode])));
DCHECK_EQ(application_context_.get(), GetApplicationContext());
}
// Check the first run state early; this must be done before IO is disallowed
// so that later calls can use the cached value.
static crash_reporter::CrashKeyString<4> key("first-run");
if (FirstRun::IsChromeFirstRun()) {
key.Set("yes");
}
// Compute device restore flag before IO is disallowed on UI thread, so the
// value is available from cache synchronously.
static crash_reporter::CrashKeyString<8> device_restore_key("device-restore");
switch (IsFirstSessionAfterDeviceRestore()) {
case signin::Tribool::kTrue:
device_restore_key.Set("yes");
break;
case signin::Tribool::kFalse:
break;
case signin::Tribool::kUnknown:
device_restore_key.Set("unknown");
break;
}
void IOSChromeMainParts::ApplyFeatureList() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
// Convert freeform experimental settings into switches before initializing
@ -245,6 +219,55 @@ void IOSChromeMainParts::PreCreateThreads() {
// emitting profiler metadata since the profiler doesn't run on iOS.
base::features::Init(
base::features::EmitThreadControllerProfilerMetadata::kFeatureDependent);
}
void IOSChromeMainParts::PreCreateThreads() {
// Create and start the stack sampling profiler if CANARY or DEV. The warning
// below doesn't apply.
const version_info::Channel channel = ::GetChannel();
if (channel == version_info::Channel::CANARY ||
channel == version_info::Channel::DEV) {
sampling_profiler_ = IOSThreadProfiler::CreateAndStartOnMainThread();
IOSThreadProfiler::SetMainThreadTaskRunner(
base::SingleThreadTaskRunner::GetCurrentDefault());
}
#if BUILDFLAG(USE_BLINK)
GetApplicationContext()
->GetBrowserPolicyConnector()
->OnResourceBundleCreated();
#else
// IMPORTANT
// Calls in this function should not post tasks or create threads as
// components used to handle those tasks are not yet available. This work
// should be deferred to PreMainMessageLoopRunImpl.
CreateApplicationContext();
#endif
// Check the first run state early; this must be done before IO is disallowed
// so that later calls can use the cached value.
static crash_reporter::CrashKeyString<4> key("first-run");
if (FirstRun::IsChromeFirstRun()) {
key.Set("yes");
}
// Compute device restore flag before IO is disallowed on UI thread, so the
// value is available from cache synchronously.
static crash_reporter::CrashKeyString<8> device_restore_key("device-restore");
switch (IsFirstSessionAfterDeviceRestore()) {
case signin::Tribool::kTrue:
device_restore_key.Set("yes");
break;
case signin::Tribool::kFalse:
break;
case signin::Tribool::kUnknown:
device_restore_key.Set("unknown");
break;
}
#if !BUILDFLAG(USE_BLINK)
ApplyFeatureList();
#endif
// Set metrics upload for stack/heap profiles.
IOSThreadProfiler::SetBrowserProcessReceiverCallback(base::BindRepeating(
@ -278,6 +301,9 @@ void IOSChromeMainParts::PreCreateThreads() {
@"RemoveProtectionFromPrefKey";
if ([NSUserDefaults.standardUserDefaults
boolForKey:kRemoveProtectionFromPrefFileKey]) {
base::FilePath local_state_path;
CHECK(base::PathService::Get(ios::FILE_LOCAL_STATE, &local_state_path));
// Restore default protection level when user is no longer in the
// experimental group.
SetProtectionLevel(local_state_path,
@ -391,9 +417,9 @@ void IOSChromeMainParts::SetUpFieldTrials(
const std::string& command_line_variation_ids) {
base::SetRecordActionTaskRunner(web::GetUIThreadTaskRunner({}));
// FeatureList requires VariationsIdsProvider to be created.
// This will occur inside //content for blink.
#if !BUILDFLAG(USE_BLINK)
// TODO(crbug.com/40261735) Move variations to PostEarlyInitialization.
// FeatureList requires VariationsIdsProvider to be created.
variations::VariationsIdsProvider::Create(
variations::VariationsIdsProvider::Mode::kUseSignedInState);
#endif
@ -416,14 +442,11 @@ void IOSChromeMainParts::SetUpFieldTrials(
application_context_->GetAdditionalFeaturesController();
additional_features_controller->RegisterFeatureList(feature_list.get());
#if !BUILDFLAG(USE_BLINK)
// TODO(crbug.com/40261735) Move variations to PostEarlyInitialization.
application_context_->GetVariationsService()->SetUpFieldTrials(
variation_ids, command_line_variation_ids,
std::vector<base::FeatureList::FeatureOverrideInfo>(),
std::move(feature_list), &ios_field_trials_);
additional_features_controller->FeatureListDidCompleteSetup();
#endif
}
void IOSChromeMainParts::SetupMetrics() {

@ -10,8 +10,11 @@
#include <string_view>
#include <vector>
#include "build/blink_buildflags.h"
#import "ios/web/public/web_client.h"
class IOSChromeMainParts;
// Chrome implementation of WebClient.
class ChromeWebClient : public web::WebClient {
public:
@ -24,6 +27,7 @@ class ChromeWebClient : public web::WebClient {
// WebClient implementation.
std::unique_ptr<web::WebMainParts> CreateWebMainParts() override;
void InitializeFieldTrialAndFeatureList() override;
void PreWebViewCreation() const override;
void AddAdditionalSchemes(Schemes* schemes) const override;
std::string GetApplicationLocale() const override;
@ -71,6 +75,10 @@ class ChromeWebClient : public web::WebClient {
private:
// Reference to a view that is attached to a window.
UIView* windowed_container_ = nil;
#if BUILDFLAG(USE_BLINK)
std::unique_ptr<IOSChromeMainParts> main_parts_;
#endif
};
#endif // IOS_CHROME_BROWSER_WEB_MODEL_CHROME_WEB_CLIENT_H_

@ -254,8 +254,21 @@ ChromeWebClient::ChromeWebClient() {}
ChromeWebClient::~ChromeWebClient() {}
std::unique_ptr<web::WebMainParts> ChromeWebClient::CreateWebMainParts() {
#if BUILDFLAG(USE_BLINK)
CHECK(main_parts_);
return std::move(main_parts_);
#else
return std::make_unique<IOSChromeMainParts>(
*base::CommandLine::ForCurrentProcess());
#endif
}
void ChromeWebClient::InitializeFieldTrialAndFeatureList() {
#if BUILDFLAG(USE_BLINK)
main_parts_ = std::make_unique<IOSChromeMainParts>(
*base::CommandLine::ForCurrentProcess());
main_parts_->InitializeFieldTrialAndFeatureList();
#endif
}
void ChromeWebClient::PreWebViewCreation() const {}

@ -19,8 +19,8 @@ source_set("init") {
"ios_content_browser_client.h",
"ios_content_main_runner.cc",
"ios_content_main_runner.h",
"ios_main_delegate.cc",
"ios_main_delegate.h",
"ios_main_delegate.mm",
"ios_renderer_main_delegate.cc",
"ios_renderer_main_delegate.h",
]

@ -33,6 +33,9 @@ class IOSMainDelegate : public content::ContentMainDelegate {
content::ContentClient* CreateContentClient() override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
content::ContentRendererClient* CreateContentRendererClient() override;
bool ShouldCreateFeatureList(InvokedIn invoked_in) override;
bool ShouldInitializeMojo(InvokedIn invoked_in) override;
std::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
absl::variant<int, content::MainFunctionParams> RunProcess(
const std::string& process_type,

@ -2,18 +2,45 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/web/content/init/ios_main_delegate.h"
#import "ios/web/content/init/ios_main_delegate.h"
#include "content/public/renderer/content_renderer_client.h"
#include "ios/web/content/init/ios_content_browser_client.h"
#include "ios/web/content/init/ios_content_client.h"
#include "ios/web/content/init/ios_content_renderer_client.h"
#import "content/public/app/initialize_mojo_core.h"
#import "content/public/renderer/content_renderer_client.h"
#import "ios/web/content/init/ios_content_browser_client.h"
#import "ios/web/content/init/ios_content_client.h"
#import "ios/web/content/init/ios_content_renderer_client.h"
#import "ios/web/public/web_client.h"
namespace web {
IOSMainDelegate::IOSMainDelegate() {}
IOSMainDelegate::~IOSMainDelegate() {}
bool IOSMainDelegate::ShouldCreateFeatureList(InvokedIn invoked_in) {
// The //content layer is always responsible for creating the FeatureList in
// child processes.
if (absl::holds_alternative<InvokedInChildProcess>(invoked_in)) {
return true;
}
// Otherwise, normally the browser process in Chrome is responsible for
// creating the FeatureList.
return false;
}
bool IOSMainDelegate::ShouldInitializeMojo(InvokedIn invoked_in) {
return ShouldCreateFeatureList(invoked_in);
}
std::optional<int> IOSMainDelegate::PostEarlyInitialization(
InvokedIn invoked_in) {
#if BUILDFLAG(USE_BLINK)
web::GetWebClient()->InitializeFieldTrialAndFeatureList();
content::InitializeMojoCore();
#endif
return std::nullopt;
}
content::ContentClient* IOSMainDelegate::CreateContentClient() {
content_client_ = std::make_unique<IOSContentClient>();
return content_client_.get();

@ -59,6 +59,10 @@ class WebClient {
// browser startup code.
virtual std::unique_ptr<WebMainParts> CreateWebMainParts();
// Allows the embedder to initialize the field trial and features list
// early.
virtual void InitializeFieldTrialAndFeatureList() {}
// Gives the embedder a chance to perform tasks before a web view is created.
virtual void PreWebViewCreation() const {}