blob: c65e868886a9c9ff5c724ab90ac3d5fc6e0f1bad [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "weblayer/browser/browser_main_parts_impl.h"
#include "base/base_switches.h"
#include "base/bind.h"
#include "base/json/json_reader.h"
#include "base/task/current_thread.h"
#include "base/task/task_traits.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/captive_portal/core/buildflags.h"
#include "components/prefs/pref_service.h"
#include "components/startup_metric_utils/browser/startup_metric_utils.h"
#include "components/subresource_filter/content/browser/ruleset_service.h"
#include "components/translate/core/browser/translate_download_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/page_visibility_state.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "ui/base/resource/resource_bundle.h"
#include "weblayer/browser/browser_process.h"
#include "weblayer/browser/cookie_settings_factory.h"
#include "weblayer/browser/feature_list_creator.h"
#include "weblayer/browser/host_content_settings_map_factory.h"
#include "weblayer/browser/i18n_util.h"
#include "weblayer/browser/no_state_prefetch/prerender_link_manager_factory.h"
#include "weblayer/browser/no_state_prefetch/prerender_manager_factory.h"
#include "weblayer/browser/permissions/weblayer_permissions_client.h"
#include "weblayer/browser/stateful_ssl_host_state_delegate_factory.h"
#include "weblayer/browser/translate_accept_languages_factory.h"
#include "weblayer/browser/translate_ranker_factory.h"
#include "weblayer/browser/webui/web_ui_controller_factory.h"
#include "weblayer/grit/weblayer_resources.h"
#include "weblayer/public/main.h"
#if defined(OS_ANDROID)
#include "base/command_line.h"
#include "components/crash/content/browser/child_exit_observer_android.h"
#include "components/crash/content/browser/child_process_crash_observer_android.h"
#include "components/crash/core/common/crash_key.h"
#include "components/javascript_dialogs/android/app_modal_dialog_view_android.h" // nogncheck
#include "components/javascript_dialogs/app_modal_dialog_manager.h" // nogncheck
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "net/android/network_change_notifier_factory_android.h"
#include "net/base/network_change_notifier.h"
#include "weblayer/browser/android/metrics/uma_utils.h"
#include "weblayer/browser/java/jni/MojoInterfaceRegistrar_jni.h"
#include "weblayer/browser/media/local_presentation_manager_factory.h"
#include "weblayer/browser/media/media_router_factory.h"
#include "weblayer/browser/weblayer_factory_impl_android.h"
#include "weblayer/common/features.h"
#endif
#if defined(USE_AURA) && defined(USE_X11)
#include "ui/base/ui_base_features.h"
#include "ui/events/devices/x11/touch_factory_x11.h" // nogncheck
#endif
#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(OS_LINUX)
#include "ui/base/ime/init/input_method_initializer.h"
#endif
#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
#include "weblayer/browser/captive_portal_service_factory.h"
#endif
namespace weblayer {
namespace {
// Indexes and publishes the subresource filter ruleset data from resources in
// the resource bundle.
void PublishSubresourceFilterRulesetFromResourceBundle() {
// First obtain the version of the ruleset data from the manifest.
std::string ruleset_manifest_string =
ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
IDR_SUBRESOURCE_FILTER_UNINDEXED_RULESET_MANIFEST_JSON);
auto ruleset_manifest = base::JSONReader::Read(ruleset_manifest_string);
DCHECK(ruleset_manifest);
std::string* content_version = ruleset_manifest->FindStringKey("version");
// Instruct the RulesetService to obtain the unindexed ruleset data from the
// ResourceBundle and give it the version of that data.
auto* ruleset_service =
BrowserProcess::GetInstance()->subresource_filter_ruleset_service();
subresource_filter::UnindexedRulesetInfo ruleset_info;
ruleset_info.resource_id = IDR_SUBRESOURCE_FILTER_UNINDEXED_RULESET;
ruleset_info.content_version = *content_version;
ruleset_service->IndexAndStoreAndPublishRulesetIfNeeded(ruleset_info);
}
// Instantiates all weblayer KeyedService factories, which is
// especially important for services that should be created at profile
// creation time as compared to lazily on first access.
void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
CaptivePortalServiceFactory::GetInstance();
#endif
HostContentSettingsMapFactory::GetInstance();
StatefulSSLHostStateDelegateFactory::GetInstance();
CookieSettingsFactory::GetInstance();
TranslateAcceptLanguagesFactory::GetInstance();
TranslateRankerFactory::GetInstance();
PrerenderLinkManagerFactory::GetInstance();
PrerenderManagerFactory::GetInstance();
#if defined(OS_ANDROID)
if (MediaRouterFactory::IsFeatureEnabled()) {
LocalPresentationManagerFactory::GetInstance();
MediaRouterFactory::GetInstance();
}
#endif
}
void StopMessageLoop(base::OnceClosure quit_closure) {
for (auto it = content::RenderProcessHost::AllHostsIterator(); !it.IsAtEnd();
it.Advance()) {
it.GetCurrentValue()->DisableKeepAliveRefCount();
}
std::move(quit_closure).Run();
}
} // namespace
BrowserMainPartsImpl::BrowserMainPartsImpl(
MainParams* params,
const content::MainFunctionParams& main_function_params,
std::unique_ptr<PrefService> local_state)
: params_(params),
main_function_params_(main_function_params),
local_state_(std::move(local_state)) {}
BrowserMainPartsImpl::~BrowserMainPartsImpl() = default;
int BrowserMainPartsImpl::PreCreateThreads() {
// Make sure permissions client has been set.
WebLayerPermissionsClient::GetInstance();
#if defined(OS_ANDROID)
// The ChildExitObserver needs to be created before any child process is
// created because it needs to be notified during process creation.
crash_reporter::ChildExitObserver::Create();
crash_reporter::ChildExitObserver::GetInstance()->RegisterClient(
std::make_unique<crash_reporter::ChildProcessCrashObserver>());
crash_reporter::InitializeCrashKeys();
// MediaSession was implemented in M85, and requires both implementation and
// client libraries to be at least that new. The version check has to be in
// the browser process, but the command line flag is automatically propagated
// to renderers.
if (WebLayerFactoryImplAndroid::GetClientMajorVersion() < 85) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
::switches::kDisableMediaSessionAPI);
}
#endif
return content::RESULT_CODE_NORMAL_EXIT;
}
void BrowserMainPartsImpl::PreMainMessageLoopStart() {
#if defined(USE_AURA) && defined(USE_X11)
if (!features::IsUsingOzonePlatform())
ui::TouchFactory::SetTouchDeviceListFromCommandLine();
#endif
}
int BrowserMainPartsImpl::PreEarlyInitialization() {
browser_process_ = std::make_unique<BrowserProcess>(std::move(local_state_));
#if defined(USE_AURA) && (defined(OS_LINUX) || defined(OS_CHROMEOS))
ui::InitializeInputMethodForTesting();
#endif
#if defined(OS_ANDROID)
net::NetworkChangeNotifier::SetFactory(
new net::NetworkChangeNotifierFactoryAndroid());
#endif
translate::TranslateDownloadManager* download_manager =
translate::TranslateDownloadManager::GetInstance();
download_manager->set_url_loader_factory(
BrowserProcess::GetInstance()->GetSharedURLLoaderFactory());
download_manager->set_application_locale(i18n::GetApplicationLocale());
return content::RESULT_CODE_NORMAL_EXIT;
}
void BrowserMainPartsImpl::PreMainMessageLoopRun() {
FeatureListCreator::GetInstance()->PerformPreMainMessageLoopStartup();
// It's necessary to have a complete dependency graph of
// BrowserContextKeyedServices before calling out to the delegate (which
// will potentially create a profile), so that a profile creation message is
// properly dispatched to the factories that want to create their services
// at profile creation time.
EnsureBrowserContextKeyedServiceFactoriesBuilt();
params_->delegate->PreMainMessageLoopRun();
content::WebUIControllerFactory::RegisterFactory(
WebUIControllerFactory::GetInstance());
BrowserProcess::GetInstance()->PreMainMessageLoopRun();
// Publish the ruleset data. On the vast majority of runs this will
// effectively be a no-op as the version of the data changes at most once per
// release. Nonetheless, post it as a best-effort task to take it off the
// critical path of startup. Note that best-effort tasks are guaranteed to
// execute within a reasonable delay (assuming of course that the app isn't
// shut down first).
content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
->PostTask(
FROM_HERE,
base::BindOnce(&PublishSubresourceFilterRulesetFromResourceBundle));
if (main_function_params_.ui_task) {
std::move(*main_function_params_.ui_task).Run();
delete main_function_params_.ui_task;
run_message_loop_ = false;
}
#if defined(OS_ANDROID)
// On Android, retrieve the application start time from Java and record it. On
// other platforms, the application start time was already recorded in the
// constructor of ContentMainDelegateImpl.
startup_metric_utils::RecordApplicationStartTime(GetApplicationStartTime());
#endif // defined(OS_ANDROID)
// Record the time at which the main message loop starts. Must be recorded
// after application start time (see startup_metric_utils.h).
startup_metric_utils::RecordBrowserMainMessageLoopStart(
base::TimeTicks::Now(), /* is_first_run */ false);
#if defined(OS_ANDROID)
memory_metrics_logger_ = std::make_unique<metrics::MemoryMetricsLogger>();
// Set the global singleton app modal dialog factory.
javascript_dialogs::AppModalDialogManager::GetInstance()
->SetNativeDialogFactory(base::BindRepeating(
[](javascript_dialogs::AppModalDialogController* controller)
-> javascript_dialogs::AppModalDialogView* {
return new javascript_dialogs::AppModalDialogViewAndroid(
base::android::AttachCurrentThread(), controller,
controller->web_contents()->GetTopLevelNativeWindow());
}));
Java_MojoInterfaceRegistrar_registerMojoInterfaces(
base::android::AttachCurrentThread());
#endif
}
bool BrowserMainPartsImpl::MainMessageLoopRun(int* result_code) {
return !run_message_loop_;
}
void BrowserMainPartsImpl::PostMainMessageLoopRun() {
params_->delegate->PostMainMessageLoopRun();
browser_process_->StartTearDown();
}
void BrowserMainPartsImpl::PreDefaultMainMessageLoopRun(
base::OnceClosure quit_closure) {
// Wrap the method that stops the message loop so we can do other shutdown
// cleanup inside content.
params_->delegate->SetMainMessageLoopQuitClosure(
base::BindOnce(StopMessageLoop, std::move(quit_closure)));
}
} // namespace weblayer