#include "content/browser/renderer_host/render_process_host_impl.h"
#include <algorithm>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <set>
#include <utility>
#include <vector>
#include "base/base_switches.h"
#include "base/clang_profiling_buildflags.h"
#include "base/command_line.h"
#include "base/containers/adapters.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/memory/writable_shared_memory_region.h"
#include "base/message_loop/message_pump_type.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/persistent_histogram_allocator.h"
#include "base/metrics/persistent_memory_allocator.h"
#include "base/metrics/statistics_recorder.h"
#include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"
#include "base/supports_user_data.h"
#include "base/system/sys_info.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/typed_macros.h"
#include "base/tracing/protos/chrome_track_event.pbzero.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "cc/base/switches.h"
#include "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom.h"
#include "components/discardable_memory/service/discardable_shared_memory_manager.h"
#include "components/metrics/single_sample_metrics.h"
#include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h"
#include "components/services/storage/public/cpp/buckets/bucket_id.h"
#include "components/services/storage/public/cpp/buckets/bucket_info.h"
#include "components/services/storage/public/cpp/buckets/constants.h"
#include "components/services/storage/public/cpp/quota_error_or.h"
#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
#include "components/tracing/common/tracing_switches.h"
#include "components/viz/common/switches.h"
#include "components/viz/host/gpu_client.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/bad_message.h"
#include "content/browser/blob_storage/blob_registry_wrapper.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_context_impl.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/buckets/bucket_manager.h"
#include "content/browser/child_process_host_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/field_trial_recorder.h"
#include "content/browser/field_trial_synchronizer.h"
#include "content/browser/file_system/file_system_manager_impl.h"
#include "content/browser/file_system_access/file_system_access_manager_impl.h"
#include "content/browser/gpu/browser_gpu_client_delegate.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_disk_cache_factory.h"
#include "content/browser/locks/lock_manager.h"
#include "content/browser/media/frameless_media_interface_proxy.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/metrics/histogram_controller.h"
#include "content/browser/mime_registry_impl.h"
#include "content/browser/network_service_instance_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/process_lock.h"
#include "content/browser/push_messaging/push_messaging_manager.h"
#include "content/browser/quota/quota_context.h"
#include "content/browser/renderer_host/embedded_frame_sink_provider_impl.h"
#include "content/browser/renderer_host/indexed_db_client_state_checker_factory.h"
#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
#include "content/browser/renderer_host/recently_destroyed_hosts.h"
#include "content/browser/renderer_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_message_filter.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/renderer_sandboxed_process_launcher_delegate.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/site_info.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/theme_helper.h"
#include "content/browser/tracing/background_tracing_manager_impl.h"
#include "content/browser/web_database/web_database_host_impl.h"
#include "content/browser/websockets/websocket_connector_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/child_process.mojom.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_switches_internal.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/pseudonymization_salt.h"
#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_or_resource_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host_creation_observer.h"
#include "content/public/browser/render_process_host_factory.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/render_process_host_priority_client.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_iterator.h"
#include "content/public/browser/resource_coordinator_service.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/weak_document_ptr.h"
#include "content/public/browser/webrtc_log.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/zygote/zygote_buildflags.h"
#include "google_apis/gaia/gaia_config.h"
#include "google_apis/gaia/gaia_switches.h"
#include "gpu/command_buffer/client/gpu_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_switches.h"
#include "ipc/ipc_channel_mojo.h"
#include "ipc/trace_ipc_message.h"
#include "media/base/media_switches.h"
#include "media/capture/capture_switches.h"
#include "media/media_buildflags.h"
#include "media/mojo/services/video_decode_perf_history.h"
#include "media/mojo/services/webrtc_video_perf_history.h"
#include "media/webrtc/webrtc_features.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/scoped_message_error_crash_key.h"
#include "net/cookies/cookie_setting_override.h"
#include "sandbox/policy/switches.h"
#include "services/device/public/mojom/power_monitor.mojom.h"
#include "services/device/public/mojom/screen_orientation.mojom.h"
#include "services/device/public/mojom/time_zone_monitor.mojom.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/mojom/ukm_interface.mojom.h"
#include "services/metrics/ukm_recorder_factory_impl.h"
#include "services/network/public/mojom/attribution.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/quota/quota_manager.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/mojom/disk_allocator.mojom.h"
#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom.h"
#include "third_party/blink/public/public_buildflags.h"
#include "ui/accessibility/accessibility_switches.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_switches.h"
#include "url/gurl.h"
#include "url/origin.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/child_process_binding_types.h"
#include "content/browser/android/java_interfaces_impl.h"
#include "content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h"
#include "content/public/browser/android/java_interfaces.h"
#include "media/audio/android/audio_manager_android.h"
#include "third_party/blink/public/mojom/android_font_lookup/android_font_lookup.mojom.h"
#endif
#if BUILDFLAG(IS_OHOS)
#include "res_sched_client_adapter.h"
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include <sys/resource.h>
#include "components/services/font/public/mojom/font_service.mojom.h"
#include "content/browser/font_service.h"
#include "third_party/blink/public/mojom/memory_usage_monitor_linux.mojom.h"
#include "content/browser/media/video_encode_accelerator_provider_launcher.h"
#include "content/public/browser/stable_video_decoder_factory.h"
#include "media/mojo/mojom/video_encode_accelerator.mojom.h"
#endif
#if BUILDFLAG(IS_APPLE)
#include "content/browser/child_process_task_port_provider_mac.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "content/browser/sandbox_support_mac_impl.h"
#include "content/common/sandbox_support_mac.mojom.h"
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
#include "services/tracing/public/cpp/system_tracing_service.h"
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
#include "content/browser/v8_snapshot_files.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/scoped_com_initializer.h"
#include "base/win/windows_version.h"
#include "content/browser/renderer_host/dwrite_font_proxy_impl_win.h"
#include "content/public/common/font_cache_dispatcher_win.h"
#include "content/public/common/font_cache_win.mojom.h"
#include "ui/display/win/dpi.h"
#endif
#if BUILDFLAG(ENABLE_LIBRARY_CDMS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS)
#include "content/browser/media/key_system_support_impl.h"
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/browser/renderer_host/plugin_registry_impl.h"
#endif
#if BUILDFLAG(ENABLE_PPAPI)
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#endif
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
#include "ipc/ipc_logging.h"
#endif
#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
#include "content/browser/hyphenation/hyphenation_impl.h"
#endif
#if BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/ozone_switches.h"
#endif
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
#include "content/public/common/profiling_utils.h"
#endif
#if defined(OHOS_WPT)
#include "content/browser/font_unique_name_lookup/font_unique_name_lookup_service.h"
#include "third_party/blink/public/mojom/android_font_lookup/android_font_lookup.mojom.h"
#endif
#ifdef OHOS_INCOGNITO_MODE
#include "base/ohos/sys_info_utils.h"
#endif
#ifdef OHOS_THEME_FONT
#include "base/files/file.h"
#include "base/json/json_reader.h"
#endif
#ifdef OHOS_LOGGER_REPORT
#include "content/public/common/content_switches.h"
#include "base/ohos/logger.h"
#endif
#if BUILDFLAG(IS_FUCHSIA)
#define MAYBEVLOG VLOG
#else
#define MAYBEVLOG DVLOG
#endif
namespace content {
namespace {
using perfetto::protos::pbzero::ChromeTrackEvent;
size_t g_max_renderer_count_override = 0;
bool g_run_renderer_in_process = false;
#ifdef OHOS_RENDER_PROCESS_MODE
RenderProcessMode g_render_process_mode =
RenderProcessMode::DEFAULT_MODE;
#endif
RendererMainThreadFactoryFunction g_renderer_main_thread_factory = nullptr;
base::Thread* g_in_process_thread = nullptr;
RenderProcessHostFactory* g_render_process_host_factory_ = nullptr;
const char kSiteProcessMapKeyName[] = "content_site_process_map";
RenderProcessHost::AnalyzeHungRendererFunction g_analyze_hung_renderer =
nullptr;
base::IDMap<RenderProcessHost*>& GetAllHosts() {
static base::NoDestructor<base::IDMap<RenderProcessHost*>> s_all_hosts;
return *s_all_hosts;
}
std::list<RenderProcessHostCreationObserver*>& GetAllCreationObservers() {
static base::NoDestructor<std::list<RenderProcessHostCreationObserver*>>
s_all_creation_observers;
return *s_all_creation_observers;
}
#if defined(OHOS_RENDER_PROCESS_SHARE)
SharedProcessTokenToProcessMap& GetAllSharedProcessHosts() {
static base::NoDestructor<SharedProcessTokenToProcessMap>
s_all_shared_process_hosts;
return *s_all_shared_process_hosts;
}
#endif
std::string GetRendererPidAsString(RenderProcessHost* host) {
if (host->GetProcess().IsValid()) {
return base::NumberToString(host->GetProcess().Pid());
}
return "no-process";
}
std::ostream& operator<<(std::ostream& o,
const SiteInstanceProcessAssignment& assignment) {
switch (assignment) {
case SiteInstanceProcessAssignment::UNKNOWN:
return o << "No renderer process has been assigned to the SiteInstance "
"yet.";
case SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS:
return o << "Reused some pre-existing process.";
case SiteInstanceProcessAssignment::USED_SPARE_PROCESS:
return o << "Used an existing spare process.";
case SiteInstanceProcessAssignment::CREATED_NEW_PROCESS:
return o << "No renderer could be reused, so a new one was created for "
"the SiteInstance.";
}
}
class SiteProcessMap : public base::SupportsUserData::Data {
public:
typedef std::map<SiteInfo, RenderProcessHost*> SiteToProcessMap;
SiteProcessMap() = default;
void RegisterProcess(const SiteInfo& site_info, RenderProcessHost* process) {
auto i = map_.find(site_info);
if (i == map_.end())
map_[site_info] = process;
}
RenderProcessHost* FindProcess(const SiteInfo& site_info) {
auto i = map_.find(site_info);
if (i != map_.end())
return i->second;
return nullptr;
}
void RemoveProcess(RenderProcessHost* host) {
std::set<SiteInfo> site_info_set;
for (SiteToProcessMap::const_iterator i = map_.begin(); i != map_.end();
++i) {
if (i->second == host)
site_info_set.insert(i->first);
}
for (const auto& i : site_info_set) {
auto iter = map_.find(i);
if (iter != map_.end()) {
DCHECK_EQ(iter->second, host);
map_.erase(iter);
}
}
}
private:
SiteToProcessMap map_;
};
SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
DCHECK(context);
SiteProcessMap* existing_map = static_cast<SiteProcessMap*>(
context->GetUserData(kSiteProcessMapKeyName));
if (existing_map)
return existing_map;
auto new_map = std::make_unique<SiteProcessMap>();
auto* new_map_ptr = new_map.get();
context->SetUserData(kSiteProcessMapKeyName, std::move(new_map));
return new_map_ptr;
}
class SpareRenderProcessHostManager : public RenderProcessHostObserver {
public:
SpareRenderProcessHostManager() = default;
SpareRenderProcessHostManager(const SpareRenderProcessHostManager& other) =
delete;
SpareRenderProcessHostManager& operator=(
const SpareRenderProcessHostManager& other) = delete;
static SpareRenderProcessHostManager& GetInstance() {
static base::NoDestructor<SpareRenderProcessHostManager> s_instance;
return *s_instance;
}
void WarmupSpareRenderProcessHost(BrowserContext* browser_context) {
if (spare_render_process_host_ &&
spare_render_process_host_->GetBrowserContext() == browser_context) {
DCHECK_EQ(browser_context->GetDefaultStoragePartition(),
spare_render_process_host_->GetStoragePartition());
return;
}
CleanupSpareRenderProcessHost();
if (browser_context->ShutdownStarted()) {
base::debug::DumpWithoutCrashing();
return;
}
if (RenderProcessHost::run_renderer_in_process() ||
RenderProcessHostImpl::GetProcessCountForLimit() >=
RenderProcessHostImpl::GetMaxRendererProcessCount())
return;
auto* memory_monitor = base::MemoryPressureMonitor::Get();
if (memory_monitor &&
memory_monitor->GetCurrentPressureLevel() >=
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)
return;
spare_render_process_host_ = RenderProcessHostImpl::CreateRenderProcessHost(
browser_context, nullptr );
spare_render_process_host_->AddObserver(this);
spare_render_process_host_->Init();
}
RenderProcessHost* MaybeTakeSpareRenderProcessHost(
BrowserContext* browser_context,
SiteInstanceImpl* site_instance) {
bool embedder_allows_spare_usage =
GetContentClient()->browser()->ShouldUseSpareRenderProcessHost(
browser_context, site_instance->GetSiteInfo().site_url());
if (GetContentClient()->browser()->IsJitDisabledForSite(
browser_context, site_instance->GetSiteInfo().process_lock_url()))
embedder_allows_spare_usage = false;
bool site_instance_allows_spare_usage =
!site_instance->HasProcess() &&
site_instance->CanAssociateWithSpareProcess();
bool hosts_pdf_content = site_instance->GetSiteInfo().is_pdf();
StoragePartition* site_storage =
browser_context->GetStoragePartition(site_instance);
using SpareProcessMaybeTakeAction =
RenderProcessHostImpl::SpareProcessMaybeTakeAction;
SpareProcessMaybeTakeAction action =
SpareProcessMaybeTakeAction::kNoSparePresent;
if (!spare_render_process_host_)
action = SpareProcessMaybeTakeAction::kNoSparePresent;
else if (browser_context != spare_render_process_host_->GetBrowserContext())
action = SpareProcessMaybeTakeAction::kMismatchedBrowserContext;
else if (!spare_render_process_host_->InSameStoragePartition(site_storage))
action = SpareProcessMaybeTakeAction::kMismatchedStoragePartition;
else if (!embedder_allows_spare_usage)
action = SpareProcessMaybeTakeAction::kRefusedByEmbedder;
else if (!site_instance_allows_spare_usage)
action = SpareProcessMaybeTakeAction::kRefusedBySiteInstance;
else if (hosts_pdf_content)
action = SpareProcessMaybeTakeAction::kRefusedForPdfContent;
else
action = SpareProcessMaybeTakeAction::kSpareTaken;
UMA_HISTOGRAM_ENUMERATION(
"BrowserRenderProcessHost.SpareProcessMaybeTakeAction", action);
RenderProcessHost* returned_process = nullptr;
if (spare_render_process_host_ &&
browser_context == spare_render_process_host_->GetBrowserContext() &&
spare_render_process_host_->InSameStoragePartition(site_storage) &&
!site_instance->IsGuest() && embedder_allows_spare_usage &&
site_instance_allows_spare_usage && !hosts_pdf_content) {
CHECK(spare_render_process_host_->HostHasNotBeenUsed());
CHECK(spare_render_process_host_->IsInitializedAndNotDead());
DCHECK_EQ(SpareProcessMaybeTakeAction::kSpareTaken, action);
returned_process = spare_render_process_host_;
ReleaseSpareRenderProcessHost(spare_render_process_host_);
} else if (!RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
CleanupSpareRenderProcessHost();
} else if (RenderProcessHostImpl::GetProcessCountForLimit() >=
RenderProcessHostImpl::GetMaxRendererProcessCount()) {
CleanupSpareRenderProcessHost();
}
return returned_process;
}
void PrepareForFutureRequests(BrowserContext* browser_context) {
if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
WarmupSpareRenderProcessHost(browser_context);
} else {
CleanupSpareRenderProcessHost();
}
}
void CleanupSpareRenderProcessHost() {
if (spare_render_process_host_) {
spare_render_process_host_->RemoveObserver(this);
if (!spare_render_process_host_->AreRefCountsDisabled())
spare_render_process_host_->Cleanup();
spare_render_process_host_ = nullptr;
spare_render_process_host_changed_callback_list_.Notify(nullptr);
}
}
RenderProcessHost* spare_render_process_host() {
return spare_render_process_host_;
}
base::CallbackListSubscription RegisterSpareRenderProcessHostChangedCallback(
const base::RepeatingCallback<void(RenderProcessHost*)>& cb) {
cb.Run(spare_render_process_host_.get());
return spare_render_process_host_changed_callback_list_.Add(cb);
}
private:
void ReleaseSpareRenderProcessHost(RenderProcessHost* host) {
if (spare_render_process_host_ && spare_render_process_host_ == host) {
spare_render_process_host_->RemoveObserver(this);
spare_render_process_host_ = nullptr;
spare_render_process_host_changed_callback_list_.Notify(nullptr);
}
}
void RenderProcessReady(RenderProcessHost* host) override {
if (host == spare_render_process_host_) {
spare_render_process_host_changed_callback_list_.Notify(
spare_render_process_host_);
}
}
void RenderProcessExited(RenderProcessHost* host,
const ChildProcessTerminationInfo& info) override {
if (host == spare_render_process_host_)
CleanupSpareRenderProcessHost();
}
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
ReleaseSpareRenderProcessHost(host);
}
base::RepeatingCallbackList<void(RenderProcessHost*)>
spare_render_process_host_changed_callback_list_;
raw_ptr<RenderProcessHost> spare_render_process_host_ = nullptr;
};
class RenderProcessHostIsReadyObserver : public RenderProcessHostObserver {
public:
RenderProcessHostIsReadyObserver(RenderProcessHost* render_process_host,
base::OnceClosure task)
: render_process_host_(render_process_host), task_(std::move(task)) {
render_process_host_->AddObserver(this);
if (render_process_host_->IsReady())
PostTask();
}
~RenderProcessHostIsReadyObserver() override {
render_process_host_->RemoveObserver(this);
}
RenderProcessHostIsReadyObserver(
const RenderProcessHostIsReadyObserver& other) = delete;
RenderProcessHostIsReadyObserver& operator=(
const RenderProcessHostIsReadyObserver& other) = delete;
void RenderProcessReady(RenderProcessHost* host) override { PostTask(); }
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
delete this;
}
private:
void PostTask() {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&RenderProcessHostIsReadyObserver::CallTask,
weak_factory_.GetWeakPtr()));
}
void CallTask() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (render_process_host_->IsReady())
std::move(task_).Run();
delete this;
}
raw_ptr<RenderProcessHost> render_process_host_;
base::OnceClosure task_;
base::WeakPtrFactory<RenderProcessHostIsReadyObserver> weak_factory_{this};
};
const void* const kCommittedSiteProcessCountTrackerKey =
"CommittedSiteProcessCountTrackerKey";
const void* const kPendingSiteProcessCountTrackerKey =
"PendingSiteProcessCountTrackerKey";
const void* const kDelayedShutdownSiteProcessCountTrackerKey =
"DelayedShutdownSiteProcessCountTrackerKey";
class SiteProcessCountTracker : public base::SupportsUserData::Data,
public RenderProcessHostObserver {
public:
SiteProcessCountTracker() = default;
~SiteProcessCountTracker() override { DCHECK(map_.empty()); }
static SiteProcessCountTracker* GetInstance(BrowserContext* browser_context,
const void* const tracker_key) {
SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(tracker_key));
if (!tracker) {
tracker = new SiteProcessCountTracker();
browser_context->SetUserData(tracker_key, base::WrapUnique(tracker));
}
return tracker;
}
void IncrementSiteProcessCount(const SiteInfo& site_info,
int render_process_host_id) {
std::map<ProcessID, Count>& counts_per_process = map_[site_info];
++counts_per_process[render_process_host_id];
#ifndef NDEBUG
RenderProcessHost* host = RenderProcessHost::FromID(render_process_host_id);
if (!HasProcess(host))
host->AddObserver(this);
#endif
}
void DecrementSiteProcessCount(const SiteInfo& site_info,
int render_process_host_id) {
auto result = map_.find(site_info);
DCHECK(result != map_.end());
std::map<ProcessID, Count>& counts_per_process = result->second;
--counts_per_process[render_process_host_id];
DCHECK_GE(counts_per_process[render_process_host_id], 0);
if (counts_per_process[render_process_host_id] == 0)
counts_per_process.erase(render_process_host_id);
if (counts_per_process.empty())
map_.erase(site_info);
}
void FindRenderProcessesForSiteInstance(
SiteInstanceImpl* site_instance,
absl::optional<size_t> main_frame_threshold,
std::set<RenderProcessHost*>* foreground_processes,
std::set<RenderProcessHost*>* background_processes) {
auto result = map_.find(site_instance->GetSiteInfo());
if (result == map_.end())
return;
std::map<ProcessID, Count>& counts_per_process = result->second;
for (auto iter : counts_per_process) {
RenderProcessHost* host = RenderProcessHost::FromID(iter.first);
if (!host) {
NOTREACHED();
continue;
}
if (!RenderProcessHostImpl::MayReuseAndIsSuitable(host, site_instance))
continue;
if (main_frame_threshold) {
size_t main_frame_count = 0;
host->ForEachRenderFrameHost(base::BindRepeating(
[](size_t& main_frame_count, RenderFrameHost* render_frame_host) {
if (static_cast<RenderFrameHostImpl*>(render_frame_host)
->IsOutermostMainFrame()) {
++main_frame_count;
}
},
std::ref(main_frame_count)));
if (main_frame_count >= *main_frame_threshold) {
continue;
}
}
if (host->VisibleClientCount())
foreground_processes->insert(host);
else
background_processes->insert(host);
}
}
bool ContainsNonReusableSiteForHost(RenderProcessHost* host) {
for (auto iter : map_) {
if (!SiteInstance::ShouldAssignSiteForURL(iter.first.site_url()) &&
!iter.first.site_url().IsAboutBlank() &&
base::Contains(iter.second, host->GetID())) {
return true;
}
}
return false;
}
void ClearProcessForAllSites(int render_process_host_id) {
for (auto iter = map_.begin(); iter != map_.end();) {
std::map<ProcessID, Count>& counts_per_process = iter->second;
counts_per_process.erase(render_process_host_id);
iter = counts_per_process.empty() ? map_.erase(iter) : ++iter;
}
}
std::string GetDebugString() const {
HostIdToSiteMap rph_to_sites_map = GetHostIdToSiteMapForDebugging();
std::string output;
for (auto host_info : rph_to_sites_map) {
RenderProcessHost* host = GetAllHosts().Lookup(host_info.first);
DCHECK(host);
bool is_locked_to_site = host->GetProcessLock().is_locked_to_site();
output += base::StringPrintf("\tProcess Host ID %d (PID %s, %s):\n",
host_info.first,
GetRendererPidAsString(host).c_str(),
is_locked_to_site ? "locked" : "not locked");
for (auto site_string : host_info.second) {
output += base::StringPrintf("\t\t%s\n", site_string.c_str());
}
}
return output;
}
bool Contains(const SiteInfo& site_info, int render_process_host_id) {
auto site_info_found = map_.find(site_info);
if (site_info_found == map_.end())
return false;
auto counts_per_process = site_info_found->second;
return counts_per_process.find(render_process_host_id) !=
counts_per_process.end();
}
bool ContainsHost(int render_process_host_id) {
for (auto iter : map_) {
auto counts_per_process = iter.second;
if (counts_per_process.find(render_process_host_id) !=
counts_per_process.end()) {
return true;
}
}
return false;
}
private:
using ProcessID = int;
using Count = int;
using HostIdToSiteMap = base::flat_map<ProcessID, std::vector<std::string>>;
HostIdToSiteMap GetHostIdToSiteMapForDebugging() const {
HostIdToSiteMap rph_to_sites_map;
rph_to_sites_map.reserve(RenderProcessHostImpl::GetProcessCount());
for (auto iter(RenderProcessHost::AllHostsIterator()); !iter.IsAtEnd();
iter.Advance()) {
rph_to_sites_map[iter.GetCurrentValue()->GetID()];
}
for (auto iter : map_) {
std::string site = iter.first.GetDebugString();
std::map<ProcessID, Count>& counts_per_process = iter.second;
for (auto iter_process : counts_per_process) {
ProcessID id = iter_process.first;
Count count = iter_process.second;
rph_to_sites_map[id].push_back(
base::StringPrintf("%s -- count: %d", site.c_str(), count));
}
}
return rph_to_sites_map;
}
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
#ifndef NDEBUG
host->RemoveObserver(this);
DCHECK(!HasProcess(host));
#endif
}
#ifndef NDEBUG
bool HasProcess(RenderProcessHost* process) {
for (auto iter : map_) {
std::map<ProcessID, Count>& counts_per_process = iter.second;
for (auto iter_process : counts_per_process) {
if (iter_process.first == process->GetID())
return true;
}
}
return false;
}
#endif
using CountPerProcessPerSiteMap =
std::map<SiteInfo, std::map<ProcessID, Count>>;
CountPerProcessPerSiteMap map_;
};
bool ShouldTrackProcessForSite(const SiteInfo& site_info) {
return !site_info.site_url().is_empty();
}
bool ShouldFindReusableProcessHostForSite(const SiteInfo& site_info) {
return !site_info.site_url().is_empty();
}
std::string GetCurrentHostMapDebugString(
const SiteProcessCountTracker* tracker) {
std::string output =
base::StringPrintf("There are now %zu RenderProcessHosts.",
RenderProcessHostImpl::GetProcessCount());
if (tracker) {
output += base::StringPrintf("\nThe mappings are:\n%s",
tracker->GetDebugString().c_str());
}
return output;
}
const void* const kUnmatchedServiceWorkerProcessTrackerKey =
"UnmatchedServiceWorkerProcessTrackerKey";
class UnmatchedServiceWorkerProcessTracker
: public base::SupportsUserData::Data,
public RenderProcessHostObserver {
public:
static void Register(RenderProcessHost* render_process_host,
SiteInstanceImpl* site_instance) {
BrowserContext* browser_context = site_instance->GetBrowserContext();
DCHECK(!site_instance->GetSiteInfo().site_url().is_empty());
if (!ShouldTrackProcessForSite(site_instance->GetSiteInfo()))
return;
UnmatchedServiceWorkerProcessTracker* tracker =
static_cast<UnmatchedServiceWorkerProcessTracker*>(
browser_context->GetUserData(
kUnmatchedServiceWorkerProcessTrackerKey));
if (!tracker) {
tracker = new UnmatchedServiceWorkerProcessTracker();
browser_context->SetUserData(kUnmatchedServiceWorkerProcessTrackerKey,
base::WrapUnique(tracker));
}
tracker->RegisterProcessForSite(render_process_host, site_instance);
}
static RenderProcessHost* MatchWithSite(SiteInstanceImpl* site_instance) {
BrowserContext* browser_context = site_instance->GetBrowserContext();
if (!ShouldFindReusableProcessHostForSite(site_instance->GetSiteInfo()))
return nullptr;
UnmatchedServiceWorkerProcessTracker* tracker =
static_cast<UnmatchedServiceWorkerProcessTracker*>(
browser_context->GetUserData(
kUnmatchedServiceWorkerProcessTrackerKey));
if (!tracker)
return nullptr;
return tracker->TakeFreshestProcessForSite(site_instance);
}
UnmatchedServiceWorkerProcessTracker() = default;
~UnmatchedServiceWorkerProcessTracker() override {
DCHECK(site_process_set_.empty());
}
void RenderProcessHostDestroyed(RenderProcessHost* host) override {
DCHECK(HasProcess(host));
int process_id = host->GetID();
for (auto it = site_process_set_.begin(); it != site_process_set_.end();) {
if (it->second == process_id) {
it = site_process_set_.erase(it);
} else {
++it;
}
}
host->RemoveObserver(this);
}
private:
using ProcessID = int;
using SiteProcessIDPair = std::pair<SiteInfo, ProcessID>;
using SiteProcessIDPairSet = std::set<SiteProcessIDPair>;
void RegisterProcessForSite(RenderProcessHost* host,
SiteInstanceImpl* site_instance) {
if (!HasProcess(host))
host->AddObserver(this);
site_process_set_.insert(
SiteProcessIDPair(site_instance->GetSiteInfo(), host->GetID()));
}
RenderProcessHost* TakeFreshestProcessForSite(
SiteInstanceImpl* site_instance) {
absl::optional<SiteProcessIDPair> site_process_pair =
FindFreshestProcessForSite(site_instance);
if (!site_process_pair)
return nullptr;
RenderProcessHost* host =
RenderProcessHost::FromID(site_process_pair->second);
if (!host)
return nullptr;
if (!RenderProcessHostImpl::MayReuseAndIsSuitable(host, site_instance))
return nullptr;
site_process_set_.erase(site_process_pair.value());
if (!HasProcess(host))
host->RemoveObserver(this);
return host;
}
absl::optional<SiteProcessIDPair> FindFreshestProcessForSite(
SiteInstanceImpl* site_instance) const {
const auto reversed_site_process_set = base::Reversed(site_process_set_);
if (site_instance->IsDefaultSiteInstance()) {
for (const auto& site_process_pair : reversed_site_process_set) {
if (site_instance->IsSiteInDefaultSiteInstance(
site_process_pair.first.site_url()))
return site_process_pair;
}
} else {
for (const auto& site_process_pair : reversed_site_process_set) {
if (site_process_pair.first == site_instance->GetSiteInfo())
return site_process_pair;
}
}
return absl::nullopt;
}
bool HasProcess(RenderProcessHost* host) const {
int process_id = host->GetID();
for (const auto& site_process_id : site_process_set_) {
if (site_process_id.second == process_id)
return true;
}
return false;
}
SiteProcessIDPairSet site_process_set_;
};
void CopyFeatureSwitch(const base::CommandLine& src,
base::CommandLine* dest,
const char* switch_name) {
std::vector<std::string> features = FeaturesFromSwitch(src, switch_name);
std::set<std::string> dedup(features.begin(), features.end());
features.assign(dedup.begin(), dedup.end());
if (!features.empty())
dest->AppendSwitchASCII(switch_name, base::JoinString(features, ","));
}
RenderProcessHostImpl::DomStorageBinder& GetDomStorageBinder() {
static base::NoDestructor<RenderProcessHostImpl::DomStorageBinder> binder;
return *binder;
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
static constexpr size_t kUnknownPlatformProcessLimit = 0;
size_t GetPlatformProcessLimit() {
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
struct rlimit limit;
if (getrlimit(RLIMIT_NPROC, &limit) != 0)
return kUnknownPlatformProcessLimit;
if (limit.rlim_cur == RLIM_INFINITY)
return std::numeric_limits<size_t>::max();
return base::saturated_cast<size_t>(limit.rlim_cur);
#else
return kUnknownPlatformProcessLimit;
#endif
}
#endif
RenderProcessHost::BindHostReceiverInterceptor&
GetBindHostReceiverInterceptor() {
static base::NoDestructor<RenderProcessHost::BindHostReceiverInterceptor>
interceptor;
return *interceptor;
}
RenderProcessHostImpl::CreateNetworkFactoryCallback&
GetCreateNetworkFactoryCallback() {
static base::NoDestructor<RenderProcessHostImpl::CreateNetworkFactoryCallback>
s_callback;
return *s_callback;
}
RenderProcessHostImpl::BadMojoMessageCallbackForTesting&
GetBadMojoMessageCallbackForTesting() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
static base::NoDestructor<
RenderProcessHostImpl::BadMojoMessageCallbackForTesting>
s_callback;
return *s_callback;
}
void InvokeBadMojoMessageCallbackForTesting(int render_process_id,
const std::string& error) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&InvokeBadMojoMessageCallbackForTesting,
render_process_id, error));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHostImpl::BadMojoMessageCallbackForTesting& callback =
GetBadMojoMessageCallbackForTesting();
if (!callback.is_null())
callback.Run(render_process_id, error);
}
BASE_FEATURE(kCheckNoNewRefCountsWhenRphDeletingSoon,
"CheckNoNewRefCountsWhenRphDeletingSoon",
base::FEATURE_ENABLED_BY_DEFAULT);
#ifdef OHOS_RENDER_PROCESS_MODE
static constexpr char kExtensionScheme[] = "chrome-extension";
static constexpr char kArkwebExtensionScheme[] = "arkweb-extension";
constexpr int kSingleRenderProcessCount = 1;
#endif
}
class RenderProcessHostImpl::IOThreadHostImpl : public mojom::ChildProcessHost {
public:
IOThreadHostImpl(int render_process_id,
base::WeakPtr<RenderProcessHostImpl> weak_host,
std::unique_ptr<service_manager::BinderRegistry> binders,
mojo::PendingReceiver<mojom::ChildProcessHost> host_receiver)
: render_process_id_(render_process_id),
weak_host_(std::move(weak_host)),
binders_(std::move(binders)),
receiver_(this, std::move(host_receiver)) {}
~IOThreadHostImpl() override = default;
IOThreadHostImpl(const IOThreadHostImpl& other) = delete;
IOThreadHostImpl& operator=(const IOThreadHostImpl& other) = delete;
private:
void Ping(PingCallback callback) override { std::move(callback).Run(); }
void BindHostReceiver(mojo::GenericPendingReceiver receiver) override {
const auto& interceptor = GetBindHostReceiverInterceptor();
if (interceptor) {
interceptor.Run(render_process_id_, &receiver);
if (!receiver)
return;
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (auto font_receiver = receiver.As<font_service::mojom::FontService>()) {
ConnectToFontService(std::move(font_receiver));
return;
}
if (base::FeatureList::IsEnabled(media::kUseOutOfProcessVideoEncoding)) {
if (auto r =
receiver.As<media::mojom::VideoEncodeAcceleratorProvider>()) {
if (!video_encode_accelerator_factory_remote_.is_bound()) {
LaunchVideoEncodeAcceleratorProviderFactory(
video_encode_accelerator_factory_remote_
.BindNewPipeAndPassReceiver());
video_encode_accelerator_factory_remote_.reset_on_disconnect();
}
if (!video_encode_accelerator_factory_remote_.is_bound())
return;
video_encode_accelerator_factory_remote_
->CreateVideoEncodeAcceleratorProvider(std::move(r));
return;
}
}
#endif
#if BUILDFLAG(IS_WIN)
if (auto r = receiver.As<mojom::FontCacheWin>()) {
FontCacheDispatcher::Create(std::move(r));
return;
}
#endif
#if BUILDFLAG(IS_MAC)
if (auto r = receiver.As<mojom::SandboxSupportMac>()) {
static base::NoDestructor<SandboxSupportMacImpl> sandbox_support;
sandbox_support->BindReceiver(std::move(r));
return;
}
#endif
if (auto r = receiver.As<
discardable_memory::mojom::DiscardableSharedMemoryManager>()) {
discardable_memory::DiscardableSharedMemoryManager::Get()->Bind(
std::move(r));
return;
}
if (auto r = receiver.As<ukm::mojom::UkmRecorderFactory>()) {
metrics::UkmRecorderFactoryImpl::Create(ukm::UkmRecorder::Get(),
std::move(r));
return;
}
#if BUILDFLAG(IS_ANDROID)
if (auto r = receiver.As<blink::mojom::AndroidFontLookup>()) {
GetGlobalJavaInterfacesOnIOThread()->GetInterface(std::move(r));
return;
}
#endif
std::string interface_name = *receiver.interface_name();
mojo::ScopedMessagePipeHandle pipe = receiver.PassPipe();
if (binders_->TryBindInterface(interface_name, &pipe))
return;
receiver = mojo::GenericPendingReceiver(interface_name, std::move(pipe));
if (!receiver)
return;
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&IOThreadHostImpl::BindHostReceiverOnUIThread,
weak_host_, std::move(receiver)));
}
#if BUILDFLAG(IS_OHOS)
void ReportKeyThread(int32_t status, int32_t process_id, int32_t thread_id, int32_t role) override {
using namespace OHOS::NWeb;
ResSchedClientAdapter::ReportKeyThread(
static_cast<ResSchedStatusAdapter>(status), process_id, thread_id, static_cast<ResSchedRoleAdapter>(role));
}
void ReportKeyThreadIds(int32_t status, int32_t process_id,
const std::vector<int32_t>& thread_ids, int32_t role) override {
using namespace OHOS::NWeb;
for (auto thread_id : thread_ids) {
ResSchedClientAdapter::ReportKeyThread(
static_cast<ResSchedStatusAdapter>(status), process_id, thread_id, static_cast<ResSchedRoleAdapter>(role));
}
}
#endif
static void BindHostReceiverOnUIThread(
base::WeakPtr<RenderProcessHostImpl> weak_host,
mojo::GenericPendingReceiver receiver) {
if (weak_host)
weak_host->OnBindHostReceiver(std::move(receiver));
}
const int render_process_id_;
const base::WeakPtr<RenderProcessHostImpl> weak_host_;
std::unique_ptr<service_manager::BinderRegistry> binders_;
mojo::Receiver<mojom::ChildProcessHost> receiver_{this};
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
mojo::Remote<media::mojom::VideoEncodeAcceleratorProviderFactory>
video_encode_accelerator_factory_remote_;
#endif
};
scoped_refptr<base::SingleThreadTaskRunner>
RenderProcessHostImpl::GetInProcessRendererThreadTaskRunnerForTesting() {
return g_in_process_thread->task_runner();
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
size_t RenderProcessHostImpl::GetPlatformMaxRendererProcessCount() {
size_t limit = GetPlatformProcessLimit() / 2;
if (limit == kUnknownPlatformProcessLimit) {
static constexpr size_t kMaxRendererProcessCount = 82;
limit = kMaxRendererProcessCount;
}
return limit;
}
#endif
size_t RenderProcessHost::GetMaxRendererProcessCount() {
#ifdef OHOS_RENDER_PROCESS_MODE
if (render_process_mode() == RenderProcessMode::SINGLE_MODE) {
return kSingleRenderProcessCount;
}
#endif
if (g_max_renderer_count_override)
#ifdef OHOS_RENDER_PROCESS_MODE
return g_max_renderer_count_override * 0.9;
#else
return g_max_renderer_count_override;
#endif
size_t client_override =
GetContentClient()->browser()->GetMaxRendererProcessCountOverride();
if (client_override)
#ifdef OHOS_RENDER_PROCESS_MODE
return client_override * 0.9;
#else
return client_override;
#endif
#if BUILDFLAG(IS_ANDROID)
return std::numeric_limits<size_t>::max();
#elif BUILDFLAG(IS_CHROMEOS_ASH)
return 100;
#else
static size_t max_count = 0;
if (!max_count) {
static constexpr size_t kEstimatedWebContentsMemoryUsage =
#if defined(ARCH_CPU_64_BITS)
85;
#else
60;
#endif
max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2;
max_count /= kEstimatedWebContentsMemoryUsage;
static constexpr size_t kMinRendererProcessCount = 3;
static const size_t kMaxRendererProcessCount =
RenderProcessHostImpl::GetPlatformMaxRendererProcessCount();
DCHECK_LE(kMinRendererProcessCount, kMaxRendererProcessCount);
max_count = std::clamp(max_count, kMinRendererProcessCount,
kMaxRendererProcessCount);
MAYBEVLOG(1) << __func__ << ": Calculated max " << max_count;
}
#ifdef OHOS_RENDER_PROCESS_MODE
return max_count * 0.9;
#else
return max_count;
#endif
#endif
}
void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
MAYBEVLOG(1) << __func__ << ": Max override set to " << count;
g_max_renderer_count_override = count;
if (RenderProcessHostImpl::GetProcessCount() > count) {
SpareRenderProcessHostManager::GetInstance()
.CleanupSpareRenderProcessHost();
}
}
int RenderProcessHost::GetCurrentRenderProcessCountForTesting() {
RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
int count = 0;
while (!it.IsAtEnd()) {
RenderProcessHost* host = it.GetCurrentValue();
if (host->IsInitializedAndNotDead() &&
host != RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()) {
count++;
}
it.Advance();
}
return count;
}
#if defined(OHOS_INCOGNITO_MODE)
size_t RenderProcessHost::GetOffTheRecordRenderProcessCount() {
RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
size_t count = 0;
while (!it.IsAtEnd()) {
RenderProcessHost* host = it.GetCurrentValue();
if (host->GetBrowserContext()->IsOffTheRecord() &&
!static_cast<RenderProcessHostImpl*>(host)->is_dead()) {
count++;
}
it.Advance();
}
return count;
}
#endif
RenderProcessHost* RenderProcessHostImpl::CreateRenderProcessHost(
BrowserContext* browser_context,
SiteInstanceImpl* site_instance) {
if (g_render_process_host_factory_) {
return g_render_process_host_factory_->CreateRenderProcessHost(
browser_context, site_instance);
}
StoragePartitionImpl* storage_partition_impl =
static_cast<StoragePartitionImpl*>(
browser_context->GetStoragePartition(site_instance));
int flags = RenderProcessFlags::kNone;
if (site_instance && site_instance->IsGuest()) {
flags |= RenderProcessFlags::kForGuestsOnly;
storage_partition_impl->set_is_guest();
}
if (site_instance) {
if (site_instance->IsJitDisabled()) {
flags |= RenderProcessFlags::kJitDisabled;
}
if (site_instance->IsPdf()) {
flags |= RenderProcessFlags::kPdf;
}
}
return new RenderProcessHostImpl(browser_context, storage_partition_impl,
flags);
}
const unsigned int RenderProcessHostImpl::kMaxFrameDepthForPriority =
std::numeric_limits<unsigned int>::max();
const base::TimeDelta RenderProcessHostImpl::kKeepAliveHandleFactoryTimeout =
base::Milliseconds(kKeepAliveHandleFactoryTimeoutInMSec);
#if BUILDFLAG(IS_OHOS)
void RenderProcessHostImpl::Refresh() {
RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
if (it.IsAtEnd()) {
return;
}
do {
RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
it.GetCurrentValue());
if (!host) {
return;
}
auto temp_set = host->render_frame_host_id_set_;
for (auto rfh_id : temp_set) {
auto rfh = RenderFrameHostImpl::FromID(rfh_id);
if (rfh && rfh->IsActive()) {
rfh->Reload();
}
}
} while (0);
}
#endif
RenderProcessHostImpl::RenderProcessHostImpl(
BrowserContext* browser_context,
StoragePartitionImpl* storage_partition_impl,
int flags)
: priority_(!blink::kLaunchingProcessIsBackgrounded,
false ,
false ,
frame_depth_,
false ,
true
#if BUILDFLAG(IS_ANDROID)
,
ChildProcessImportance::NORMAL
#endif
#ifdef OHOS_RENDER_PROCESS_MODE
,
base::TimeTicks::Now()
#endif
),
id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()),
browser_context_(browser_context),
storage_partition_impl_(storage_partition_impl->GetWeakPtr()),
sudden_termination_allowed_(true),
is_blocked_(false),
flags_(flags),
is_unused_(true),
delayed_cleanup_needed_(false),
within_process_died_observer_(false),
channel_connected_(false),
sent_render_process_ready_(false),
shutdown_exit_code_(-1) {
CHECK(!browser_context->ShutdownStarted());
TRACE_EVENT("shutdown", "RenderProcessHostImpl",
ChromeTrackEvent::kRenderProcessHost, *this);
TRACE_EVENT_BEGIN("shutdown", "Browser.RenderProcessHostImpl",
perfetto::Track::FromPointer(this),
ChromeTrackEvent::kRenderProcessHost, *this);
widget_helper_ = new RenderWidgetHelper();
ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID(), browser_context);
CHECK(!BrowserMainRunner::ExitedMainMessageLoop());
RegisterHost(GetID(), this);
GetAllHosts().set_check_on_null_data(true);
mark_child_process_activity_time();
push_messaging_manager_ = std::make_unique<PushMessagingManager>(
*this,
ChildProcessHost::kInvalidUniqueID,
base::WrapRefCounted(storage_partition_impl_->GetServiceWorkerContext()));
InitializeChannelProxy();
const int id = GetID();
const uint64_t tracing_id =
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(id);
gpu_client_.reset(
new viz::GpuClient(std::make_unique<BrowserGpuClientDelegate>(), id,
tracing_id, GetUIThreadTaskRunner({})));
}
void RenderProcessHostImpl::ShutDownInProcessRenderer() {
DCHECK(g_run_renderer_in_process);
switch (RenderProcessHostImpl::GetProcessCount()) {
case 0:
return;
case 1: {
RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
AllHostsIterator().GetCurrentValue());
for (auto& observer : host->observers_)
observer.RenderProcessHostDestroyed(host);
#ifndef NDEBUG
host->is_self_deleted_ = true;
#endif
delete host;
return;
}
default:
NOTREACHED() << "There should be only one RenderProcessHost when running "
<< "in-process.";
}
}
void RenderProcessHostImpl::RegisterRendererMainThreadFactory(
RendererMainThreadFactoryFunction create) {
g_renderer_main_thread_factory = create;
}
void RenderProcessHostImpl::SetDomStorageBinderForTesting(
DomStorageBinder binder) {
GetDomStorageBinder() = std::move(binder);
}
bool RenderProcessHostImpl::HasDomStorageBinderForTesting() {
return !GetDomStorageBinder().is_null();
}
void RenderProcessHostImpl::SetBadMojoMessageCallbackForTesting(
BadMojoMessageCallbackForTesting callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_NE(callback.is_null(),
GetBadMojoMessageCallbackForTesting().is_null());
GetBadMojoMessageCallbackForTesting() = callback;
}
void RenderProcessHostImpl::SetForGuestsOnlyForTesting() {
flags_ |= RenderProcessFlags::kForGuestsOnly;
}
RenderProcessHostImpl::~RenderProcessHostImpl() {
TRACE_EVENT("shutdown", "~RenderProcessHostImpl",
ChromeTrackEvent::kRenderProcessHost, *this);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#ifndef NDEBUG
DCHECK(is_self_deleted_)
<< "RenderProcessHostImpl is destroyed by something other than itself";
#endif
in_process_renderer_.reset();
g_in_process_thread = nullptr;
ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID());
is_dead_ = true;
UnregisterHost(GetID());
if (GetGpuDiskCacheFactorySingleton()) {
gpu_client_->RemoveDiskCacheHandles();
}
TRACE_EVENT_END("shutdown", perfetto::Track::FromPointer(this),
ChromeTrackEvent::kRenderProcessHost, *this);
TRACE_EVENT_END("shutdown", perfetto::Track::FromPointer(this),
ChromeTrackEvent::kRenderProcessHost, *this);
}
bool RenderProcessHostImpl::Init() {
if (IsInitializedAndNotDead())
return true;
base::CommandLine::StringType renderer_prefix;
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
renderer_prefix =
browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF
: ChildProcessHost::CHILD_NORMAL;
#elif BUILDFLAG(IS_MAC)
int flags = ChildProcessHost::CHILD_RENDERER;
#else
int flags = ChildProcessHost::CHILD_NORMAL;
#endif
base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags);
if (renderer_path.empty())
return false;
is_initialized_ = true;
is_dead_ = false;
sent_render_process_ready_ = false;
gpu_client_->PreEstablishGpuChannel();
if (!GetBrowserContext()->IsOffTheRecord() &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuShaderDiskCache)) {
if (auto* cache_factory = GetGpuDiskCacheFactorySingleton()) {
for (const gpu::GpuDiskCacheType type : gpu::kGpuDiskCacheTypes) {
auto handle = cache_factory->GetCacheHandle(
type, storage_partition_impl_->GetPath().Append(
gpu::GetGpuDiskCacheSubdir(type)));
gpu_client_->SetDiskCacheHandle(handle);
}
}
}
if (!channel_)
InitializeChannelProxy();
channel_->Unpause(false );
GetContentClient()->browser()->RenderProcessWillLaunch(this);
FieldTrialSynchronizer::UpdateRendererVariationsHeader(this);
#if BUILDFLAG(IS_ANDROID)
static_cast<media::AudioManagerAndroid*>(media::AudioManager::Get())
->InitializeIfNeeded();
#endif
CreateMessageFilters();
RegisterMojoInterfaces();
GetRendererInterface()->InitializeRenderer(
GetContentClient()->browser()->GetUserAgentBasedOnPolicy(
browser_context_),
GetContentClient()->browser()->GetFullUserAgent(),
GetContentClient()->browser()->GetReducedUserAgent(),
GetContentClient()->browser()->GetUserAgentMetadata(),
storage_partition_impl_->cors_exempt_header_list(),
AttributionManager::GetSupport());
if (run_renderer_in_process()) {
DCHECK(g_renderer_main_thread_factory);
in_process_renderer_.reset(g_renderer_main_thread_factory(
InProcessChildThreadParams(GetIOThreadTaskRunner({}),
&mojo_invitation_),
base::checked_cast<int32_t>(id_)));
base::Thread::Options options;
#if BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC)
options.message_pump_type = base::MessagePumpType::UI;
#else
options.message_pump_type = base::MessagePumpType::DEFAULT;
#endif
OnProcessLaunched();
in_process_renderer_->StartWithOptions(std::move(options));
g_in_process_thread = in_process_renderer_.get();
channel_->Flush();
} else {
std::unique_ptr<base::CommandLine> cmd_line =
std::make_unique<base::CommandLine>(renderer_path);
if (!renderer_prefix.empty())
cmd_line->PrependWrapper(renderer_prefix);
AppendRendererCommandLine(cmd_line.get());
#if BUILDFLAG(IS_WIN)
std::unique_ptr<SandboxedProcessLauncherDelegate> sandbox_delegate =
std::make_unique<RendererSandboxedProcessLauncherDelegateWin>(
*cmd_line, IsPdf(), IsJitDisabled());
#else
std::unique_ptr<SandboxedProcessLauncherDelegate> sandbox_delegate =
std::make_unique<RendererSandboxedProcessLauncherDelegate>();
#endif
auto file_data = std::make_unique<ChildProcessLauncherFileData>();
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
file_data->files_to_preload = GetV8SnapshotFilesToPreload();
#endif
child_process_launcher_ = std::make_unique<ChildProcessLauncher>(
std::move(sandbox_delegate), std::move(cmd_line), GetID(), this,
std::move(mojo_invitation_),
base::BindRepeating(&RenderProcessHostImpl::OnMojoError, id_),
std::move(file_data));
channel_->Pause();
BackgroundTracingManagerImpl::ActivateForProcess(GetID(),
child_process_.get());
fast_shutdown_started_ = false;
shutdown_requested_ = false;
}
last_init_time_ = base::TimeTicks::Now();
return true;
}
void RenderProcessHostImpl::EnableSendQueue() {
if (!channel_)
InitializeChannelProxy();
}
void RenderProcessHostImpl::InitializeChannelProxy() {
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
GetIOThreadTaskRunner({});
mojo_invitation_ = {};
child_process_.reset();
mojo::PendingRemote<mojom::ChildProcess> child_pending_remote(
mojo_invitation_.AttachMessagePipe(kChildProcessReceiverAttachmentName),
0);
child_process_.Bind(std::move(child_pending_remote));
child_host_pending_receiver_ = mojo::PendingReceiver<mojom::ChildProcessHost>(
mojo_invitation_.AttachMessagePipe(
kChildProcessHostRemoteAttachmentName));
mojo::ScopedMessagePipeHandle bootstrap =
mojo_invitation_.AttachMessagePipe(kLegacyIpcBootstrapAttachmentName);
std::unique_ptr<IPC::ChannelFactory> channel_factory =
IPC::ChannelMojo::CreateServerFactory(
std::move(bootstrap), io_task_runner,
base::SingleThreadTaskRunner::GetCurrentDefault());
ResetChannelProxy();
DCHECK(!channel_);
channel_ = IPC::ChannelProxy::Create(
std::move(channel_factory), this,
io_task_runner.get(),
base::SingleThreadTaskRunner::GetCurrentDefault());
renderer_interface_.reset();
channel_->GetRemoteAssociatedInterface(&renderer_interface_);
channel_->Pause();
}
void RenderProcessHostImpl::ResetChannelProxy() {
if (!channel_)
return;
channel_.reset();
channel_connected_ = false;
}
void RenderProcessHostImpl::CreateMessageFilters() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
MediaInternals* media_internals = MediaInternals::GetInstance();
scoped_refptr<RenderMessageFilter> render_message_filter =
base::MakeRefCounted<RenderMessageFilter>(
GetID(), GetBrowserContext(), widget_helper_.get(), media_internals);
AddFilter(render_message_filter.get());
#if BUILDFLAG(ENABLE_PPAPI)
pepper_renderer_connection_ = base::MakeRefCounted<PepperRendererConnection>(
GetID(), PluginServiceImpl::GetInstance(), GetBrowserContext(),
GetStoragePartition());
AddFilter(pepper_renderer_connection_.get());
#endif
p2p_socket_dispatcher_host_ =
std::make_unique<P2PSocketDispatcherHost>(GetID());
}
void RenderProcessHostImpl::BindCacheStorage(
const network::CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
coep_reporter_remote,
const storage::BucketLocator& bucket_locator,
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->GetCacheStorageControl()->AddReceiver(
cross_origin_embedder_policy, std::move(coep_reporter_remote),
bucket_locator, storage::mojom::CacheStorageOwner::kCacheAPI,
std::move(receiver));
}
void RenderProcessHostImpl::BindIndexedDB(
const blink::StorageKey& storage_key,
const GlobalRenderFrameHostId& rfh_id,
mojo::PendingReceiver<blink::mojom::IDBFactory> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (storage_key.origin().opaque()) {
return;
}
storage_partition_impl_->GetIndexedDBControl().BindIndexedDB(
storage_key,
IndexedDBClientStateCheckerFactory::InitializePendingAssociatedRemote(
rfh_id),
std::move(receiver));
}
void RenderProcessHostImpl::BindBucketManagerHost(
base::WeakPtr<BucketContext> bucket_context,
mojo::PendingReceiver<blink::mojom::BucketManagerHost> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->GetBucketManager()->BindReceiver(
std::move(bucket_context), std::move(receiver),
mojo::GetBadMessageCallback());
}
void RenderProcessHostImpl::ForceCrash() {
child_process_->CrashHungProcess();
}
void RenderProcessHostImpl::BindFileSystemManager(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&FileSystemManagerImpl::BindReceiver,
base::Unretained(file_system_manager_impl_.get()),
storage_key, std::move(receiver)));
}
void RenderProcessHostImpl::BindFileSystemAccessManager(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* manager = storage_partition_impl_->GetFileSystemAccessManager();
manager->BindReceiver(
FileSystemAccessManagerImpl::BindingContext(
storage_key,
storage_key.origin().GetURL(), GetID()),
std::move(receiver));
}
void RenderProcessHostImpl::GetSandboxedFileSystemForBucket(
const storage::BucketLocator& bucket,
blink::mojom::FileSystemAccessManager::GetSandboxedFileSystemCallback
callback) {
auto* manager = storage_partition_impl_->GetFileSystemAccessManager();
manager->GetSandboxedFileSystem(
FileSystemAccessManagerImpl::BindingContext(
bucket.storage_key,
bucket.storage_key.origin().GetURL(), GetID()),
bucket, std::move(callback));
}
void RenderProcessHostImpl::BindRestrictedCookieManagerForServiceWorker(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->CreateRestrictedCookieManager(
network::mojom::RestrictedCookieManagerRole::SCRIPT, storage_key.origin(),
net::IsolationInfo::Create(
net::IsolationInfo::RequestType::kOther,
url::Origin::Create(storage_key.top_level_site().GetURL()),
storage_key.origin(), storage_key.ToNetSiteForCookies(),
absl::nullopt, storage_key.nonce()),
true, GetID(), MSG_ROUTING_NONE,
net::CookieSettingOverrides(), std::move(receiver),
storage_partition_impl_->CreateCookieAccessObserverForServiceWorker());
}
void RenderProcessHostImpl::BindVideoDecodePerfHistory(
mojo::PendingReceiver<media::mojom::VideoDecodePerfHistory> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetBrowserContext()->GetVideoDecodePerfHistory()->BindReceiver(
std::move(receiver));
}
void RenderProcessHostImpl::BindWebrtcVideoPerfHistory(
mojo::PendingReceiver<media::mojom::WebrtcVideoPerfHistory> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserContextImpl::From(GetBrowserContext())
->GetWebrtcVideoPerfHistory()
->BindReceiver(std::move(receiver));
}
void RenderProcessHostImpl::BindQuotaManagerHost(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::QuotaManagerHost> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->GetQuotaContext()->BindQuotaManagerHost(
storage_key, std::move(receiver));
}
void RenderProcessHostImpl::CreateLockManager(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->GetQuotaManager()->proxy()->UpdateOrCreateBucket(
storage::BucketInitParams::ForDefaultBucket(storage_key),
GetUIThreadTaskRunner({}),
base::BindOnce(&RenderProcessHostImpl::CreateLockManagerWithBucketInfo,
instance_weak_factory_.GetWeakPtr(), std::move(receiver)));
}
void RenderProcessHostImpl::CreateLockManagerWithBucketInfo(
mojo::PendingReceiver<blink::mojom::LockManager> receiver,
storage::QuotaErrorOr<storage::BucketInfo> bucket) {
storage_partition_impl_->GetLockManager()->BindReceiver(
bucket.has_value() ? bucket->id : storage::BucketId(),
std::move(receiver));
}
void RenderProcessHostImpl::CreatePermissionService(
const url::Origin& origin,
mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!permission_service_context_) {
permission_service_context_ =
std::make_unique<PermissionServiceContext>(this);
}
permission_service_context_->CreateServiceForWorker(origin,
std::move(receiver));
}
void RenderProcessHostImpl::CreatePaymentManagerForOrigin(
const url::Origin& origin,
mojo::PendingReceiver<payments::mojom::PaymentManager> receiver) {
storage_partition_impl_->GetPaymentAppContext()
->CreatePaymentManagerForOrigin(origin, std::move(receiver));
}
void RenderProcessHostImpl::CreateNotificationService(
GlobalRenderFrameHostId rfh_id,
const RenderProcessHost::NotificationServiceCreatorType creator_type,
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::NotificationService> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHost* rfh = RenderFrameHost::FromID(rfh_id);
WeakDocumentPtr weak_document_ptr =
rfh ? rfh->GetWeakDocumentPtr() : WeakDocumentPtr();
switch (creator_type) {
case RenderProcessHost::NotificationServiceCreatorType::kServiceWorker:
case RenderProcessHost::NotificationServiceCreatorType::kSharedWorker:
case RenderProcessHost::NotificationServiceCreatorType::kDedicatedWorker: {
storage_partition_impl_->GetPlatformNotificationContext()->CreateService(
this, storage_key, GURL(), weak_document_ptr,
creator_type, std::move(receiver));
break;
}
case RenderProcessHost::NotificationServiceCreatorType::kDocument: {
CHECK(rfh);
storage_partition_impl_->GetPlatformNotificationContext()->CreateService(
this, storage_key, rfh->GetLastCommittedURL(), weak_document_ptr,
creator_type, std::move(receiver));
break;
}
}
}
void RenderProcessHostImpl::CreateWebSocketConnector(
const blink::StorageKey& storage_key,
mojo::PendingReceiver<blink::mojom::WebSocketConnector> receiver) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<WebSocketConnectorImpl>(
GetID(), MSG_ROUTING_NONE, storage_key.origin(),
net::IsolationInfo::Create(
net::IsolationInfo::RequestType::kOther,
url::Origin::Create(storage_key.top_level_site().GetURL()),
storage_key.origin(), storage_key.ToNetSiteForCookies(),
absl::nullopt, storage_key.nonce())),
std::move(receiver));
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
void RenderProcessHostImpl::ReinitializeLogging(
uint32_t logging_dest,
base::ScopedFD log_file_descriptor) {
auto logging_settings = mojom::LoggingSettings::New();
logging_settings->logging_dest = logging_dest;
logging_settings->log_file_descriptor =
mojo::PlatformHandle(std::move(log_file_descriptor));
child_process_->ReinitializeLogging(std::move(logging_settings));
}
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void RenderProcessHostImpl::CreateStableVideoDecoder(
mojo::PendingReceiver<media::stable::mojom::StableVideoDecoder> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!stable_video_decoder_factory_remote_.is_bound()) {
LaunchStableVideoDecoderFactory(
stable_video_decoder_factory_remote_.BindNewPipeAndPassReceiver());
stable_video_decoder_factory_remote_.reset_on_disconnect();
}
if (!stable_video_decoder_factory_remote_.is_bound())
return;
stable_video_decoder_factory_remote_->CreateStableVideoDecoder(
std::move(receiver));
}
#endif
void RenderProcessHostImpl::DelayProcessShutdown(
const base::TimeDelta& subframe_shutdown_timeout,
const base::TimeDelta& unload_handler_timeout,
const SiteInfo& site_info) {
if (AreRefCountsDisabled() || deleting_soon_ || fast_shutdown_started_) {
return;
}
shutdown_delay_ref_count_++;
if (base::FeatureList::IsEnabled(features::kSubframeShutdownDelay) &&
ShouldTrackProcessForSite(site_info)) {
SiteProcessCountTracker* delayed_shutdown_tracker =
SiteProcessCountTracker::GetInstance(
GetBrowserContext(),
content::kDelayedShutdownSiteProcessCountTrackerKey);
delayed_shutdown_tracker->IncrementSiteProcessCount(site_info, GetID());
}
GetUIThreadTaskRunner({})->PostDelayedTask(
FROM_HERE,
base::BindOnce(&RenderProcessHostImpl::CancelProcessShutdownDelay,
instance_weak_factory_.GetWeakPtr(), site_info),
std::min(subframe_shutdown_timeout + unload_handler_timeout,
kKeepAliveHandleFactoryTimeout));
time_spent_running_unload_handlers_ = unload_handler_timeout;
}
bool RenderProcessHostImpl::IsProcessShutdownDelayedForTesting() {
SiteProcessCountTracker* delayed_shutdown_tracker =
SiteProcessCountTracker::GetInstance(
GetBrowserContext(),
content::kDelayedShutdownSiteProcessCountTrackerKey);
return delayed_shutdown_tracker->ContainsHost(GetID());
}
std::string
RenderProcessHostImpl::GetInfoForBrowserContextDestructionCrashReporting() {
std::string ret = " pl='" + GetProcessLock().ToString() + "'";
if (HostHasNotBeenUsed())
ret += " hnbu";
if (IsSpareProcessForCrashReporting(this))
ret += " spr";
if (delayed_cleanup_needed_)
ret += " dcn";
if (keep_alive_ref_count_ != 0) {
CHECK(!base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration));
ret += " karc=" + base::NumberToString(keep_alive_ref_count_);
}
if (shutdown_delay_ref_count_ != 0)
ret += " sdrc=" + base::NumberToString(shutdown_delay_ref_count_);
if (worker_ref_count_ != 0)
ret += " wrc=" + base::NumberToString(worker_ref_count_);
if (pending_reuse_ref_count_ != 0) {
ret += " prrc=" + base::NumberToString(pending_reuse_ref_count_);
}
if (!listeners_.IsEmpty()) {
ret += " lsn=" + base::NumberToString(listeners_.size());
base::IDMap<IPC::Listener*>::Iterator<IPC::Listener> it(&listeners_);
IPC::Listener* example_listener = it.GetCurrentValue();
ret += "[" + example_listener->ToDebugString() + "]";
}
if (deleting_soon_)
ret += " ds";
return ret;
}
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
void RenderProcessHostImpl::DumpProfilingData(base::OnceClosure callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetRendererInterface()->WriteClangProfilingProfile(std::move(callback));
}
#endif
void RenderProcessHostImpl::WriteIntoTrace(
perfetto::TracedProto<perfetto::protos::pbzero::RenderProcessHost> proto)
const {
proto->set_id(GetID());
proto->set_process_lock(GetProcessLock().ToString());
proto.Set(TraceProto::kBrowserContext, browser_context_);
if (child_process_launcher_ && !child_process_launcher_->IsStarting()) {
const base::Process& process = child_process_launcher_->GetProcess();
if (process.IsValid())
proto->set_child_process_id(process.Pid());
}
perfetto::TracedDictionary dict = std::move(proto).AddDebugAnnotations();
if (ChildProcessSecurityPolicyImpl::GetInstance())
dict.Add("process_lock", GetProcessLock().ToString());
}
void RenderProcessHostImpl::RegisterMojoInterfaces() {
auto registry = std::make_unique<service_manager::BinderRegistry>();
AddUIThreadInterface(
registry.get(),
base::BindRepeating(
[](mojo::PendingReceiver<device::mojom::TimeZoneMonitor> receiver) {
GetDeviceService().BindTimeZoneMonitor(std::move(receiver));
}));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(
[](mojo::PendingReceiver<device::mojom::PowerMonitor> receiver) {
GetDeviceService().BindPowerMonitor(std::move(receiver));
}));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(
[](mojo::PendingReceiver<device::mojom::ScreenOrientationListener>
receiver) {
GetDeviceService().BindScreenOrientationListener(
std::move(receiver));
}));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(
&RenderProcessHostImpl::CreateEmbeddedFrameSinkProvider,
instance_weak_factory_.GetWeakPtr()));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::BindCompositingModeReporter,
instance_weak_factory_.GetWeakPtr()));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::CreateDomStorageProvider,
instance_weak_factory_.GetWeakPtr()));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::BindWebDatabaseHostImpl,
instance_weak_factory_.GetWeakPtr()));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(
[](base::WeakPtr<RenderProcessHostImpl> host,
mojo::PendingReceiver<
memory_instrumentation::mojom::CoordinatorConnector>
receiver) {
if (!host)
return;
host->coordinator_connector_receiver_.reset();
host->coordinator_connector_receiver_.Bind(std::move(receiver));
if (!host->GetProcess().IsValid()) {
host->coordinator_connector_receiver_.Pause();
}
},
instance_weak_factory_.GetWeakPtr()));
registry->AddInterface(
base::BindRepeating(&MimeRegistryImpl::Create),
base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
base::TaskPriority::USER_BLOCKING}));
#if BUILDFLAG(USE_MINIKIN_HYPHENATION)
#if !BUILDFLAG(IS_ANDROID)
hyphenation::HyphenationImpl::RegisterGetDictionary();
#endif
registry->AddInterface(
base::BindRepeating(&hyphenation::HyphenationImpl::Create),
hyphenation::HyphenationImpl::GetTaskRunner());
#endif
#if BUILDFLAG(IS_ANDROID) || (BUILDFLAG(IS_OHOS) && defined(OHOS_WPT))
if (base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)) {
registry->AddInterface(
base::BindRepeating(&FontUniqueNameLookupService::Create),
FontUniqueNameLookupService::GetTaskRunner());
}
#endif
#if BUILDFLAG(IS_WIN)
registry->AddInterface(
base::BindRepeating(&DWriteFontProxyImpl::Create),
base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_BLOCKING, base::MayBlock()}));
#endif
file_system_manager_impl_.reset(new FileSystemManagerImpl(
GetID(), storage_partition_impl_->GetFileSystemContext(),
ChromeBlobStorageContext::GetFor(GetBrowserContext())));
AddUIThreadInterface(
registry.get(), base::BindRepeating(&viz::GpuClient::Add,
base::Unretained(gpu_client_.get())));
registry->AddInterface(
base::BindRepeating(&GpuDataManagerImpl::BindReceiver));
media_stream_track_metrics_host_.reset(new MediaStreamTrackMetricsHost());
registry->AddInterface(base::BindRepeating(
&MediaStreamTrackMetricsHost::BindReceiver,
base::Unretained(media_stream_track_metrics_host_.get())));
registry->AddInterface(
base::BindRepeating(&metrics::CreateSingleSampleMetricsProvider));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::CreateMediaLogRecordHost,
instance_weak_factory_.GetWeakPtr()));
AddUIThreadInterface(registry.get(),
base::BindRepeating(&FieldTrialRecorder::Create));
associated_interfaces_ =
std::make_unique<blink::AssociatedInterfaceRegistry>();
blink::AssociatedInterfaceRegistry* associated_registry =
associated_interfaces_.get();
associated_registry->AddInterface<mojom::RendererHost>(base::BindRepeating(
&RenderProcessHostImpl::CreateRendererHost, base::Unretained(this)));
registry->AddInterface(
base::BindRepeating(&BlobRegistryWrapper::Bind,
storage_partition_impl_->GetBlobRegistry(), GetID()));
#if BUILDFLAG(ENABLE_PLUGINS)
if (!plugin_registry_) {
plugin_registry_ = std::make_unique<PluginRegistryImpl>(GetID());
}
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::BindPluginRegistry,
instance_weak_factory_.GetWeakPtr()));
#else
registry->AddInterface(base::BindRepeating(
[](mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver) {}));
#endif
#if BUILDFLAG(ENABLE_LIBRARY_CDMS) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS)
AddUIThreadInterface(
registry.get(), base::BindRepeating(&KeySystemSupportImpl::BindReceiver));
#endif
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::BindMediaInterfaceProxy,
instance_weak_factory_.GetWeakPtr()));
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::BindAecDumpManager,
instance_weak_factory_.GetWeakPtr()));
#if BUILDFLAG(IS_FUCHSIA)
AddUIThreadInterface(
registry.get(),
base::BindRepeating(&RenderProcessHostImpl::BindMediaCodecProvider,
instance_weak_factory_.GetWeakPtr()));
#endif
GetContentClient()->browser()->ExposeInterfacesToRenderer(
registry.get(), associated_interfaces_.get(), this);
DCHECK(child_host_pending_receiver_);
io_thread_host_impl_.emplace(
GetIOThreadTaskRunner({}), GetID(), instance_weak_factory_.GetWeakPtr(),
std::move(registry), std::move(child_host_pending_receiver_));
}
void RenderProcessHostImpl::CreateEmbeddedFrameSinkProvider(
mojo::PendingReceiver<blink::mojom::EmbeddedFrameSinkProvider> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!embedded_frame_sink_provider_) {
uint32_t renderer_client_id = base::checked_cast<uint32_t>(id_);
embedded_frame_sink_provider_ =
std::make_unique<EmbeddedFrameSinkProviderImpl>(
GetHostFrameSinkManager(), renderer_client_id);
}
embedded_frame_sink_provider_->Add(std::move(receiver));
}
void RenderProcessHostImpl::BindCompositingModeReporter(
mojo::PendingReceiver<viz::mojom::CompositingModeReporter> receiver) {
BrowserMainLoop::GetInstance()->GetCompositingModeReporter(
std::move(receiver));
}
void RenderProcessHostImpl::CreateDomStorageProvider(
mojo::PendingReceiver<blink::mojom::DomStorageProvider> receiver) {
DCHECK(!dom_storage_provider_receiver_.is_bound());
dom_storage_provider_receiver_.Bind(std::move(receiver));
}
void RenderProcessHostImpl::BindMediaInterfaceProxy(
mojo::PendingReceiver<media::mojom::InterfaceFactory> receiver) {
if (!media_interface_proxy_)
media_interface_proxy_ =
std::make_unique<FramelessMediaInterfaceProxy>(this);
media_interface_proxy_->Add(std::move(receiver));
}
void RenderProcessHostImpl::BindWebDatabaseHostImpl(
mojo::PendingReceiver<blink::mojom::WebDatabaseHost> receiver) {
storage::DatabaseTracker* db_tracker =
storage_partition_impl_->GetDatabaseTracker();
db_tracker->task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&WebDatabaseHostImpl::Create, GetID(),
base::WrapRefCounted(db_tracker), std::move(receiver)));
}
void RenderProcessHostImpl::BindAecDumpManager(
mojo::PendingReceiver<blink::mojom::AecDumpManager> receiver) {
aec_dump_manager_.AddReceiver(std::move(receiver));
}
void RenderProcessHostImpl::CreateOneShotSyncService(
const url::Origin& origin,
mojo::PendingReceiver<blink::mojom::OneShotBackgroundSyncService>
receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->GetBackgroundSyncContext()->CreateOneShotSyncService(
origin, this, std::move(receiver));
}
void RenderProcessHostImpl::CreatePeriodicSyncService(
const url::Origin& origin,
mojo::PendingReceiver<blink::mojom::PeriodicBackgroundSyncService>
receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
storage_partition_impl_->GetBackgroundSyncContext()
->CreatePeriodicSyncService(origin, this, std::move(receiver));
}
void RenderProcessHostImpl::BindPushMessaging(
mojo::PendingReceiver<blink::mojom::PushMessaging> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
push_messaging_manager_->AddPushMessagingReceiver(std::move(receiver));
}
void RenderProcessHostImpl::BindP2PSocketManager(
net::NetworkAnonymizationKey anonymization_key,
mojo::PendingReceiver<network::mojom::P2PSocketManager> receiver,
GlobalRenderFrameHostId render_frame_host_id) {
p2p_socket_dispatcher_host_->BindReceiver(
*this, std::move(receiver), anonymization_key, render_frame_host_id);
}
void RenderProcessHostImpl::CreateMediaLogRecordHost(
mojo::PendingReceiver<content::mojom::MediaInternalLogRecords> receiver) {
content::MediaInternals::CreateMediaLogRecords(GetID(), std::move(receiver));
}
#if BUILDFLAG(ENABLE_PLUGINS)
void RenderProcessHostImpl::BindPluginRegistry(
mojo::PendingReceiver<blink::mojom::PluginRegistry> receiver) {
plugin_registry_->Bind(std::move(receiver));
}
#endif
#if BUILDFLAG(IS_FUCHSIA)
void RenderProcessHostImpl::BindMediaCodecProvider(
mojo::PendingReceiver<media::mojom::FuchsiaMediaCodecProvider> receiver) {
if (!media_codec_provider_)
media_codec_provider_ = std::make_unique<FuchsiaMediaCodecProviderImpl>();
media_codec_provider_->AddReceiver(std::move(receiver));
}
#endif
void RenderProcessHostImpl::BindDomStorage(
mojo::PendingReceiver<blink::mojom::DomStorage> receiver,
mojo::PendingRemote<blink::mojom::DomStorageClient> client) {
const DomStorageBinder& binder = GetDomStorageBinder();
if (binder) {
binder.Run(this, std::move(receiver));
return;
}
dom_storage_receiver_ids_.insert(storage_partition_impl_->BindDomStorage(
id_, std::move(receiver), std::move(client)));
dom_storage_provider_receiver_.reset();
}
void RenderProcessHostImpl::RegisterCoordinatorClient(
mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
client_process) {
receiver.reset();
if (!GetProcess().IsValid()) {
return;
}
base::trace_event::MemoryDumpManager::GetInstance()
->GetDumpThreadTaskRunner()
->PostTask(
FROM_HERE,
base::BindOnce(
[](mojo::PendingReceiver<
memory_instrumentation::mojom::Coordinator> receiver,
mojo::PendingRemote<
memory_instrumentation::mojom::ClientProcess>
client_process,
base::ProcessId pid) {
GetMemoryInstrumentationRegistry()->RegisterClientProcess(
std::move(receiver), std::move(client_process),
memory_instrumentation::mojom::ProcessType::RENDERER, pid,
absl::nullopt);
},
std::move(receiver), std::move(client_process),
GetProcess().Pid()));
coordinator_connector_receiver_.reset();
}
void RenderProcessHostImpl::CreateRendererHost(
mojo::PendingAssociatedReceiver<mojom::RendererHost> receiver) {
renderer_host_receiver_.Bind(std::move(receiver));
}
int RenderProcessHostImpl::GetNextRoutingID() {
return widget_helper_->GetNextRoutingID();
}
void RenderProcessHostImpl::BindReceiver(
mojo::GenericPendingReceiver receiver) {
child_process_->BindReceiver(std::move(receiver));
}
std::unique_ptr<base::PersistentMemoryAllocator>
RenderProcessHostImpl::TakeMetricsAllocator() {
return std::move(metrics_allocator_);
}
const base::TimeTicks& RenderProcessHostImpl::GetLastInitTime() {
return last_init_time_;
}
bool RenderProcessHostImpl::IsProcessBackgrounded() {
return priority_.is_background();
}
#ifdef OHOS_RENDER_PROCESS_MODE
const base::TimeTicks& RenderProcessHostImpl::ProcessBackgroundTime() {
return priority_.background_time;
}
#endif
void RenderProcessHostImpl::IncrementKeepAliveRefCount(uint64_t handle_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!are_ref_counts_disabled_);
if (base::FeatureList::IsEnabled(kCheckNoNewRefCountsWhenRphDeletingSoon)) {
CHECK(!deleting_soon_);
}
CHECK(!base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration));
++keep_alive_ref_count_;
DCHECK(!keep_alive_start_times_.contains(handle_id));
keep_alive_start_times_[handle_id] = base::Time::Now();
}
bool RenderProcessHostImpl::AreAllRefCountsZero() {
if (base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration)) {
CHECK_EQ(keep_alive_ref_count_, 0);
}
return keep_alive_ref_count_ == 0 && worker_ref_count_ == 0 &&
shutdown_delay_ref_count_ == 0 && pending_reuse_ref_count_ == 0;
}
void RenderProcessHostImpl::DecrementKeepAliveRefCount(uint64_t handle_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!are_ref_counts_disabled_);
CHECK(!base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration));
CHECK_GT(keep_alive_ref_count_, 0);
--keep_alive_ref_count_;
DCHECK(keep_alive_start_times_.contains(handle_id));
keep_alive_start_times_.erase(handle_id);
if (AreAllRefCountsZero())
Cleanup();
}
void RenderProcessHostImpl::IncrementPendingReuseRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!are_ref_counts_disabled_);
if (base::FeatureList::IsEnabled(kCheckNoNewRefCountsWhenRphDeletingSoon)) {
CHECK(!deleting_soon_);
}
++pending_reuse_ref_count_;
}
void RenderProcessHostImpl::DecrementPendingReuseRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!are_ref_counts_disabled_);
CHECK_GT(pending_reuse_ref_count_, 0);
--pending_reuse_ref_count_;
if (AreAllRefCountsZero()) {
Cleanup();
}
}
std::string RenderProcessHostImpl::GetKeepAliveDurations() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
std::stringstream result;
base::Time now = base::Time::Now();
result << keep_alive_start_times_.size() << " uid/time-deltas:";
for (auto entry : keep_alive_start_times_)
result << " " << entry.first << "/" << (now - entry.second);
result << ".";
return result.str();
}
size_t RenderProcessHostImpl::GetShutdownDelayRefCount() const {
return shutdown_delay_ref_count_;
}
int RenderProcessHostImpl::GetRenderFrameHostCount() const {
return render_frame_host_id_set_.size();
}
void RenderProcessHostImpl::ForEachRenderFrameHost(
base::RepeatingCallback<void(RenderFrameHost*)> on_render_frame_host) {
for (auto rfh_id : render_frame_host_id_set_) {
RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(rfh_id);
if (!rfh)
continue;
if (rfh->lifecycle_state() ==
RenderFrameHostImpl::LifecycleStateImpl::kSpeculative) {
continue;
}
on_render_frame_host.Run(rfh);
}
}
void RenderProcessHostImpl::RegisterRenderFrameHost(
const GlobalRenderFrameHostId& render_frame_host_id) {
DCHECK(!base::Contains(render_frame_host_id_set_, render_frame_host_id));
render_frame_host_id_set_.insert(render_frame_host_id);
}
void RenderProcessHostImpl::UnregisterRenderFrameHost(
const GlobalRenderFrameHostId& render_frame_host_id) {
DCHECK(base::Contains(render_frame_host_id_set_, render_frame_host_id));
render_frame_host_id_set_.erase(render_frame_host_id);
}
void RenderProcessHostImpl::IncrementWorkerRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!are_ref_counts_disabled_);
if (base::FeatureList::IsEnabled(kCheckNoNewRefCountsWhenRphDeletingSoon)) {
CHECK(!deleting_soon_);
}
++worker_ref_count_;
}
void RenderProcessHostImpl::DecrementWorkerRefCount() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(!are_ref_counts_disabled_);
CHECK_GT(worker_ref_count_, 0);
--worker_ref_count_;
if (AreAllRefCountsZero())
Cleanup();
}
void RenderProcessHostImpl::DisableRefCounts() {
TRACE_EVENT("shutdown", "RenderProcessHostImpl::DisableRefCounts",
ChromeTrackEvent::kRenderProcessHost, *this);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (are_ref_counts_disabled_)
return;
are_ref_counts_disabled_ = true;
keep_alive_ref_count_ = 0;
worker_ref_count_ = 0;
shutdown_delay_ref_count_ = 0;
pending_reuse_ref_count_ = 0;
Cleanup();
}
bool RenderProcessHostImpl::AreRefCountsDisabled() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return are_ref_counts_disabled_;
}
mojom::Renderer* RenderProcessHostImpl::GetRendererInterface() {
return renderer_interface_.get();
}
ProcessLock RenderProcessHostImpl::GetProcessLock() const {
return ChildProcessSecurityPolicyImpl::GetInstance()->GetProcessLock(GetID());
}
void RenderProcessHostImpl::SetNetworkFactoryForTesting(
const CreateNetworkFactoryCallback& create_network_factory_callback) {
DCHECK(!BrowserThread::IsThreadInitialized(BrowserThread::UI) ||
BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(create_network_factory_callback.is_null() ||
GetCreateNetworkFactoryCallback().is_null())
<< "It is not expected that this is called with non-null callback when "
<< "another overriding callback is already set.";
GetCreateNetworkFactoryCallback() = create_network_factory_callback;
}
void RenderProcessHostImpl::CreateURLLoaderFactory(
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
network::mojom::URLLoaderFactoryParamsPtr params) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(params);
DCHECK_EQ(GetID(), static_cast<int>(params->process_id));
if (GetCreateNetworkFactoryCallback().is_null()) {
storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
std::move(receiver), std::move(params));
} else {
mojo::PendingRemote<network::mojom::URLLoaderFactory> original_factory;
storage_partition_impl_->GetNetworkContext()->CreateURLLoaderFactory(
original_factory.InitWithNewPipeAndPassReceiver(), std::move(params));
GetCreateNetworkFactoryCallback().Run(std::move(receiver), GetID(),
std::move(original_factory));
}
}
bool RenderProcessHostImpl::MayReuseHost() {
#if BUILDFLAG(IS_OHOS)
if (is_dead_) {
LOG(ERROR) << "RenderProcessHostImpl is dead";
return false;
}
#endif
return GetContentClient()->browser()->MayReuseHost(this);
}
bool RenderProcessHostImpl::IsUnused() {
return is_unused_;
}
void RenderProcessHostImpl::SetIsUsed() {
is_unused_ = false;
}
void RenderProcessHostImpl::AddRoute(int32_t routing_id,
IPC::Listener* listener) {
TRACE_EVENT("shutdown", "RenderProcessHostImpl::AddRoute",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto = ctx.event<ChromeTrackEvent>()
->set_render_process_host_listener_changed();
proto->set_routing_id(routing_id);
});
if (base::FeatureList::IsEnabled(kCheckNoNewRefCountsWhenRphDeletingSoon)) {
CHECK(!deleting_soon_);
}
CHECK(!listeners_.Lookup(routing_id))
<< "Found Routing ID Conflict: " << routing_id;
listeners_.AddWithID(listener, routing_id);
}
void RenderProcessHostImpl::RemoveRoute(int32_t routing_id) {
TRACE_EVENT("shutdown", "RenderProcessHostImpl::RemoveRoute",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto = ctx.event<ChromeTrackEvent>()
->set_render_process_host_listener_changed();
proto->set_routing_id(routing_id);
});
DCHECK(listeners_.Lookup(routing_id) != nullptr);
listeners_.Remove(routing_id);
Cleanup();
}
bool RenderProcessHostImpl::TakeFrameTokensForFrameRoutingID(
int32_t new_routing_id,
blink::LocalFrameToken& frame_token,
base::UnguessableToken& devtools_frame_token,
blink::DocumentToken& document_token) {
return widget_helper_->TakeFrameTokensForFrameRoutingID(
new_routing_id, frame_token, devtools_frame_token, document_token);
}
void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) {
observers_.AddObserver(observer);
}
void RenderProcessHostImpl::RemoveObserver(
RenderProcessHostObserver* observer) {
observers_.RemoveObserver(observer);
}
void RenderProcessHostImpl::AddInternalObserver(
RenderProcessHostInternalObserver* observer) {
internal_observers_.AddObserver(observer);
}
void RenderProcessHostImpl::RemoveInternalObserver(
RenderProcessHostInternalObserver* observer) {
internal_observers_.RemoveObserver(observer);
}
void RenderProcessHostImpl::ShutdownForBadMessage(
CrashReportMode crash_report_mode) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC))
return;
if (run_renderer_in_process()) {
CHECK(false);
}
Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE);
if (crash_report_mode == CrashReportMode::GENERATE_CRASH_DUMP) {
ChildProcessSecurityPolicyImpl::GetInstance()->LogKilledProcessOriginLock(
GetID());
std::string site_isolation_mode;
if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
site_isolation_mode += "spp ";
if (SiteIsolationPolicy::AreIsolatedOriginsEnabled())
site_isolation_mode += "io ";
if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled())
site_isolation_mode += "soi ";
if (site_isolation_mode.empty())
site_isolation_mode = "(none)";
SCOPED_CRASH_KEY_STRING32("RPH.BadMessageKill", "isolation_mode",
site_isolation_mode);
ChildProcessSecurityPolicyImpl::GetInstance()->LogKilledProcessOriginLock(
GetID());
base::debug::DumpWithoutCrashing();
}
}
void RenderProcessHostImpl::UpdateClientPriority(
RenderProcessHostPriorityClient* client) {
DCHECK(client);
DCHECK_EQ(1u, priority_clients_.count(client));
UpdateProcessPriorityInputs();
}
int RenderProcessHostImpl::VisibleClientCount() {
return visible_clients_;
}
unsigned int RenderProcessHostImpl::GetFrameDepth() {
return frame_depth_;
}
bool RenderProcessHostImpl::GetIntersectsViewport() {
return intersects_viewport_;
}
#if BUILDFLAG(IS_ANDROID)
ChildProcessImportance RenderProcessHostImpl::GetEffectiveImportance() {
return effective_importance_;
}
base::android::ChildBindingState
RenderProcessHostImpl::GetEffectiveChildBindingState() {
if (child_process_launcher_) {
return child_process_launcher_->GetEffectiveChildBindingState();
}
return base::android::ChildBindingState::UNBOUND;
}
void RenderProcessHostImpl::DumpProcessStack() {
if (child_process_launcher_)
child_process_launcher_->DumpProcessStack();
}
#endif
void RenderProcessHostImpl::OnMediaStreamAdded() {
++media_stream_count_;
UpdateProcessPriority();
}
void RenderProcessHostImpl::OnMediaStreamRemoved() {
DCHECK_GT(media_stream_count_, 0);
--media_stream_count_;
UpdateProcessPriority();
}
void RenderProcessHostImpl::OnForegroundServiceWorkerAdded() {
foreground_service_worker_count_ += 1;
UpdateProcessPriority();
}
void RenderProcessHostImpl::OnForegroundServiceWorkerRemoved() {
DCHECK_GT(foreground_service_worker_count_, 0);
foreground_service_worker_count_ -= 1;
UpdateProcessPriority();
}
void RenderProcessHostImpl::set_render_process_host_factory_for_testing(
RenderProcessHostFactory* rph_factory) {
g_render_process_host_factory_ = rph_factory;
}
RenderProcessHostFactory*
RenderProcessHostImpl::get_render_process_host_factory_for_testing() {
return g_render_process_host_factory_;
}
void RenderProcessHostImpl::AddFrameWithSite(
BrowserContext* browser_context,
RenderProcessHost* render_process_host,
const SiteInfo& site_info) {
if (!ShouldTrackProcessForSite(site_info))
return;
SiteProcessCountTracker* tracker = SiteProcessCountTracker::GetInstance(
browser_context, kCommittedSiteProcessCountTrackerKey);
tracker->IncrementSiteProcessCount(site_info, render_process_host->GetID());
MAYBEVLOG(2) << __func__ << "(" << site_info
<< "): Site added to process host "
<< render_process_host->GetID() << "." << std::endl
<< GetCurrentHostMapDebugString(tracker);
}
void RenderProcessHostImpl::RemoveFrameWithSite(
BrowserContext* browser_context,
RenderProcessHost* render_process_host,
const SiteInfo& site_info) {
if (!ShouldTrackProcessForSite(site_info))
return;
SiteProcessCountTracker* tracker = SiteProcessCountTracker::GetInstance(
browser_context, kCommittedSiteProcessCountTrackerKey);
tracker->DecrementSiteProcessCount(site_info, render_process_host->GetID());
}
void RenderProcessHostImpl::AddExpectedNavigationToSite(
BrowserContext* browser_context,
RenderProcessHost* render_process_host,
const SiteInfo& site_info) {
if (!ShouldTrackProcessForSite(site_info))
return;
SiteProcessCountTracker* tracker = SiteProcessCountTracker::GetInstance(
browser_context, kPendingSiteProcessCountTrackerKey);
tracker->IncrementSiteProcessCount(site_info, render_process_host->GetID());
}
void RenderProcessHostImpl::RemoveExpectedNavigationToSite(
BrowserContext* browser_context,
RenderProcessHost* render_process_host,
const SiteInfo& site_info) {
if (!ShouldTrackProcessForSite(site_info))
return;
SiteProcessCountTracker* tracker = SiteProcessCountTracker::GetInstance(
browser_context, kPendingSiteProcessCountTrackerKey);
tracker->DecrementSiteProcessCount(site_info, render_process_host->GetID());
}
void RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
BrowserContext* browser_context) {
SpareRenderProcessHostManager::GetInstance().PrepareForFutureRequests(
browser_context);
}
RenderProcessHost* RenderProcessHost::GetSpareRenderProcessHostForTesting() {
return SpareRenderProcessHostManager::GetInstance()
.spare_render_process_host();
}
base::CallbackListSubscription
RenderProcessHost::RegisterSpareRenderProcessHostChangedCallback(
const base::RepeatingCallback<void(RenderProcessHost*)>& cb) {
return SpareRenderProcessHostManager::GetInstance()
.RegisterSpareRenderProcessHostChangedCallback(cb);
}
void RenderProcessHostImpl::DiscardSpareRenderProcessHostForTesting() {
SpareRenderProcessHostManager::GetInstance().CleanupSpareRenderProcessHost();
}
bool RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes() {
if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
return false;
if (!base::FeatureList::IsEnabled(features::kSpareRendererForSitePerProcess))
return false;
if (base::SysInfo::AmountOfPhysicalMemoryMB() <= 1077)
return false;
return true;
}
bool RenderProcessHostImpl::IsSpareProcessForCrashReporting(
RenderProcessHost* render_process_host) {
return render_process_host == SpareRenderProcessHostManager::GetInstance()
.spare_render_process_host();
}
bool RenderProcessHostImpl::HostHasNotBeenUsed() {
return IsUnused() && listeners_.IsEmpty() && AreAllRefCountsZero() &&
pending_views_ == 0;
}
void RenderProcessHostImpl::SetProcessLock(
const IsolationContext& isolation_context,
const ProcessLock& process_lock) {
ChildProcessSecurityPolicyImpl::GetInstance()->LockProcess(
isolation_context, GetID(), !IsUnused(), process_lock);
NotifyRendererOfLockedStateUpdate();
}
bool RenderProcessHostImpl::IsProcessLockedToSiteForTesting() {
return GetProcessLock().is_locked_to_site();
}
void RenderProcessHostImpl::NotifyRendererOfLockedStateUpdate() {
ProcessLock process_lock = GetProcessLock();
if (process_lock.is_invalid())
return;
GetRendererInterface()->SetIsCrossOriginIsolated(
process_lock.GetWebExposedIsolationInfo().is_isolated());
bool is_isolated_context_allowed_by_embedder =
GetContentClient()->browser()->IsIsolatedContextAllowedForUrl(
GetBrowserContext(), process_lock.lock_url());
GetRendererInterface()->SetIsIsolatedContext(
process_lock.GetWebExposedIsolationInfo().is_isolated_application() ||
is_isolated_context_allowed_by_embedder);
if (!process_lock.IsASiteOrOrigin())
return;
CHECK(process_lock.is_locked_to_site());
GetRendererInterface()->SetIsLockedToSite();
}
bool RenderProcessHostImpl::IsForGuestsOnly() {
return !!(flags_ & RenderProcessFlags::kForGuestsOnly);
}
bool RenderProcessHostImpl::IsJitDisabled() {
return !!(flags_ & RenderProcessFlags::kJitDisabled);
}
bool RenderProcessHostImpl::IsPdf() {
return !!(flags_ & RenderProcessFlags::kPdf);
}
StoragePartitionImpl* RenderProcessHostImpl::GetStoragePartition() {
CHECK(!!storage_partition_impl_);
return storage_partition_impl_.get();
}
static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
command_line->AppendSwitchASCII(
cc::switches::kNumRasterThreads,
base::NumberToString(NumberOfRendererRasterThreads()));
int msaa_sample_count = GpuRasterizationMSAASampleCount();
if (msaa_sample_count >= 0) {
command_line->AppendSwitchASCII(
blink::switches::kGpuRasterizationMSAASampleCount,
base::NumberToString(msaa_sample_count));
}
if (IsZeroCopyUploadEnabled())
command_line->AppendSwitch(blink::switches::kEnableZeroCopy);
if (!IsPartialRasterEnabled())
command_line->AppendSwitch(blink::switches::kDisablePartialRaster);
if (IsGpuMemoryBufferCompositorResourcesEnabled()) {
command_line->AppendSwitch(
blink::switches::kEnableGpuMemoryBufferCompositorResources);
}
if (IsMainFrameBeforeActivationEnabled())
command_line->AppendSwitch(cc::switches::kEnableMainFrameBeforeActivation);
}
void RenderProcessHostImpl::AppendRendererCommandLine(
base::CommandLine* command_line) {
command_line->AppendSwitchASCII(switches::kProcessType,
switches::kRendererProcess);
GetContentClient()->browser()->AppendExtraCommandLineSwitches(command_line,
GetID());
static bool first_renderer_process = true;
if (first_renderer_process) {
command_line->AppendSwitch(kFirstRendererProcess);
first_renderer_process = false;
}
if (IsPdf())
command_line->AppendSwitch(switches::kPdfRenderer);
#if BUILDFLAG(IS_WIN)
command_line->AppendArg(switches::kPrefetchArgumentRenderer);
#endif
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
const std::string locale =
GetContentClient()->browser()->GetApplicationLocale();
command_line->AppendSwitchASCII(switches::kLang, locale);
if (!base::CommandLine::ForCurrentProcess()
->GetSwitchValueNative(switches::kRendererCmdPrefix)
.empty()) {
command_line->AppendSwitch(switches::kNoZygote);
}
if (IsJitDisabled())
command_line->AppendSwitchASCII(blink::switches::kJavaScriptFlags,
"--jitless");
#if BUILDFLAG(IS_CHROMEOS)
if (features::IsTouchTextEditingRedesignEnabled()) {
command_line->AppendSwitchASCII(
blink::switches::kTouchTextSelectionStrategy,
blink::switches::kTouchTextSelectionStrategy_Direction);
}
#endif
#if BUILDFLAG(IS_WIN)
command_line->AppendSwitchASCII(
switches::kDeviceScaleFactor,
base::NumberToString(display::win::GetDPIScale()));
#endif
AppendCompositorCommandLineFlags(command_line);
command_line->AppendSwitchASCII(switches::kRendererClientId,
std::to_string(GetID()));
if (base::TimeTicks::IsConsistentAcrossProcesses()) {
command_line->AppendSwitchASCII(
switches::kTimeTicksAtUnixEpoch,
base::NumberToString(
base::TimeTicks::UnixEpoch().since_origin().InMicroseconds()));
}
}
void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
const base::CommandLine& browser_cmd,
base::CommandLine* renderer_cmd) {
static const char* const kSwitchNames[] = {
switches::kDisableInProcessStackTraces,
sandbox::policy::switches::kDisableSeccompFilterSandbox,
sandbox::policy::switches::kNoSandbox,
#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \
!BUILDFLAG(IS_CHROMEOS_LACROS)
switches::kDisableDevShmUsage,
#endif
#if BUILDFLAG(IS_MAC)
sandbox::policy::switches::kEnableSandboxLogging,
#endif
switches::kAllowLoopbackInPeerConnection,
switches::kAudioBufferSize,
switches::kAutoplayPolicy,
switches::kMojoCoreLibraryPath,
switches::kDisable2dCanvasImageChromium,
switches::kDisableYUVImageDecoding,
switches::kDisableAXMenuList,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableBackForwardCache,
switches::kDisableBackgroundTimerThrottling,
switches::kDisableBestEffortTasks,
switches::kDisableBreakpad,
switches::kDisableDatabases,
switches::kDisableFileSystem,
switches::kDisableFrameRateLimit,
switches::kDisableGpuMemoryBufferVideoFrames,
switches::kDisableHistogramCustomizer,
switches::kDisableLCDText,
switches::kDisableLogging,
switches::kDisableBackgroundMediaSuspend,
switches::kDisableNotifications,
switches::kDisableOriginTrialControlledBlinkFeatures,
switches::kDisablePepper3DImageChromium,
switches::kDisablePermissionsAPI,
switches::kDisablePPAPISharedImagesSwapChain,
switches::kDisablePresentationAPI,
switches::kDisableRTCSmoothnessAlgorithm,
switches::kDisableScrollToTextFragment,
switches::kDisableSharedWorkers,
switches::kDisableSkiaRuntimeOpts,
switches::kDisableSpeechAPI,
switches::kDisableThreadedCompositing,
switches::kDisableTouchDragDrop,
switches::kDisableUseMojoVideoDecoderForPepper,
switches::kDisableV8IdleTasks,
switches::kDisableVideoCaptureUseGpuMemoryBuffer,
switches::kDisableWebGLImageChromium,
switches::kDomAutomationController,
switches::kEnableAutomation,
switches::kEnableBackgroundThreadPool,
switches::kEnableExperimentalAccessibilityLanguageDetection,
switches::kEnableExperimentalAccessibilityLabelsDebugging,
switches::kEnableExperimentalWebPlatformFeatures,
switches::kEnableBlinkTestFeatures,
switches::kEnableGPUClientLogging,
switches::kEnableGpuClientTracing,
switches::kEnableGpuMemoryBufferVideoFrames,
switches::kEnableGPUServiceLogging,
switches::kEnableLCDText,
switches::kEnableLogging,
switches::kEnableNetworkInformationDownlinkMax,
switches::kEnablePluginPlaceholderTesting,
switches::kEnablePreciseMemoryInfo,
switches::kEnableSkiaBenchmarking,
switches::kEnableThreadedCompositing,
switches::kEnableTouchDragDrop,
switches::kEnableUnsafeWebGPU,
switches::kEnableViewport,
switches::kEnableVtune,
switches::kEnableWebGLDeveloperExtensions,
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
switches::kEnableWebGPUDeveloperFeatures,
switches::kFileUrlPathAlias,
switches::kForceDeviceScaleFactor,
switches::kForceDisplayColorProfile,
switches::kForceEnablePepperVideoDecoderDevAPI,
switches::kForceGpuMemAvailableMb,
switches::kForceHighContrast,
switches::kForceRasterColorProfile,
switches::kForceSkiaAnalyticAntialiasing,
switches::kForceVideoOverlays,
switches::kFullMemoryCrashReport,
switches::kGaiaUrl,
switches::kIPCConnectionTimeout,
switches::kLogBestEffortTasks,
switches::kLogFile,
switches::kLoggingLevel,
switches::kMaxActiveWebGLContexts,
switches::kMaxDecodedImageSizeMb,
switches::kMaxWebMediaPlayerCount,
switches::kMSEAudioBufferSizeLimitMb,
switches::kMSEVideoBufferSizeLimitMb,
switches::kNoZygote,
switches::kOverrideLanguageDetection,
switches::kPerfettoDisableInterning,
switches::kPpapiInProcess,
switches::kProfilingAtStart,
switches::kProfilingFile,
switches::kProfilingFlush,
switches::kRegisterPepperPlugins,
switches::kRemoteDebuggingPipe,
switches::kRemoteDebuggingPort,
switches::kRendererStartupDialog,
switches::kReportVp9AsAnUnsupportedMimeType,
switches::kStatsCollectionController,
switches::kSkiaFontCacheLimitMb,
switches::kSkiaResourceCacheLimitMb,
switches::kTestType,
switches::kTimeZoneForTesting,
switches::kTouchEventFeatureDetection,
switches::kTraceToConsole,
switches::kUseFakeCodecForPeerConnection,
switches::kUseFakeUIForMediaStream,
switches::kUseMobileUserAgent,
switches::kV,
switches::kVideoCaptureUseGpuMemoryBuffer,
switches::kVideoThreads,
switches::kVideoUnderflowThresholdMs,
switches::kVModule,
switches::kWaitForDebuggerOnNavigation,
switches::kWebAuthRemoteDesktopSupport,
switches::kWebViewDrawFunctorUsesVulkan,
switches::kWebglAntialiasingMode,
switches::kWebglMSAASampleCount,
blink::switches::kAllowPreCommitInput,
blink::switches::kBlinkSettings,
blink::switches::kDarkModeSettings,
blink::switches::kDefaultTileWidth,
blink::switches::kDefaultTileHeight,
blink::switches::kDisableImageAnimationResync,
blink::switches::kDisableLowResTiling,
blink::switches::kDisableNewBaseUrlInheritanceBehavior,
blink::switches::kDisablePreferCompositingToLCDText,
blink::switches::kDisableRGBA4444Textures,
blink::switches::kDisableThreadedScrolling,
blink::switches::kDisableThrottleNonVisibleCrossOriginIframes,
blink::switches::kEnableLowResTiling,
blink::switches::kEnablePreferCompositingToLCDText,
blink::switches::kEnableRGBA4444Textures,
blink::switches::kEnableRasterSideDarkModeForImages,
blink::switches::kMinHeightForGpuRasterTile,
blink::switches::kMaxUntiledLayerWidth,
blink::switches::kMaxUntiledLayerHeight,
blink::switches::kNetworkQuietTimeout,
blink::switches::kShowLayoutShiftRegions,
blink::switches::kShowPaintRects,
blink::switches::kTouchTextSelectionStrategy,
blink::switches::kJavaScriptFlags,
cc::switches::kCCScrollAnimationDurationForTesting,
#if !BUILDFLAG(IS_OHOS)
cc::switches::kCheckDamageEarly,
#endif
cc::switches::kDisableCheckerImaging,
cc::switches::kDisableCompositedAntialiasing,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnableGpuBenchmarking,
cc::switches::kEnableClippedImageScaling,
cc::switches::kHighlightNonLCDTextLayers,
cc::switches::kShowCompositedLayerBorders,
cc::switches::kShowFPSCounter,
cc::switches::kShowLayerAnimationBounds,
cc::switches::kShowPropertyChangedRects,
cc::switches::kShowScreenSpaceRects,
cc::switches::kShowSurfaceDamageRects,
cc::switches::kSlowDownRasterScaleFactor,
cc::switches::kBrowserControlsHideThreshold,
cc::switches::kBrowserControlsShowThreshold,
switches::kRunAllCompositorStagesBeforeDraw,
#if BUILDFLAG(ENABLE_PPAPI)
switches::kEnablePepperTesting,
#endif
switches::kDisableWebRtcHWDecoding,
switches::kDisableWebRtcHWEncoding,
switches::kEnableWebRtcSrtpAesGcm,
switches::kEnableWebRtcSrtpEncryptedHeaders,
switches::kEnforceWebRtcIPPermissionCheck,
switches::kWebRtcMaxCaptureFramerate,
switches::kEnableLowEndDeviceMode,
switches::kDisableLowEndDeviceMode,
switches::kDisallowNonExactResourceReuse,
#if BUILDFLAG(IS_ANDROID)
switches::kDisableMediaSessionAPI,
switches::kEnableReachedCodeProfiler,
switches::kReachedCodeSamplingIntervalUs,
switches::kRendererWaitForJavaDebugger,
#endif
#if BUILDFLAG(IS_WIN)
switches::kDisableHighResTimer,
switches::kTrySupportedChannelLayouts,
switches::kRaiseTimerFrequency,
#endif
#if BUILDFLAG(IS_OZONE)
switches::kOzonePlatform,
#endif
#ifdef OHOS_SCROLLBAR
switches::kPixelRatio,
#endif
#if defined(ENABLE_IPC_FUZZER)
switches::kIpcDumpDirectory,
switches::kIpcFuzzerTestcase,
#endif
#if BUILDFLAG(IS_CHROMEOS)
switches::kSchedulerBoostUrgent,
#endif
#if BUILDFLAG(IS_OHOS)
switches::kForTest,
switches::kBundleInstallationDir,
switches::kOhSchemeHandlerCustomScheme,
switches::kBundleName,
switches::kArkWebInstallPath,
switches::kOhosEnableVulkan,
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
switches::kLacrosEnablePlatformHevc,
switches::kLacrosUseChromeosProtectedMedia,
switches::kLacrosUseChromeosProtectedAv1,
#endif
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
std::size(kSwitchNames));
if (GaiaConfig::GetInstance()) {
GaiaConfig::GetInstance()->SerializeContentsToCommandLineSwitch(
renderer_cmd);
}
BrowserChildProcessHostImpl::CopyTraceStartupFlags(renderer_cmd);
if (GetBrowserContext()->IsOffTheRecord() &&
!browser_cmd.HasSwitch(switches::kDisableDatabases)) {
renderer_cmd->AppendSwitch(switches::kDisableDatabases);
}
#if BUILDFLAG(IS_ANDROID)
if (browser_cmd.HasSwitch(switches::kDisableGpuCompositing)) {
renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing);
}
#elif !BUILDFLAG(IS_CHROMEOS_ASH)
if (GpuDataManagerImpl::GetInstance()->IsGpuCompositingDisabled())
renderer_cmd->AppendSwitch(switches::kDisableGpuCompositing);
#endif
if (browser_cmd.HasSwitch(switches::kWaitForDebuggerChildren)) {
std::string value =
browser_cmd.GetSwitchValueASCII(switches::kWaitForDebuggerChildren);
if (value.empty() || value == switches::kRendererProcess) {
renderer_cmd->AppendSwitch(switches::kWaitForDebugger);
}
}
#if BUILDFLAG(IS_WIN) && !defined(OFFICIAL_BUILD)
if (renderer_cmd->HasSwitch(switches::kRendererStartupDialog) &&
!renderer_cmd->HasSwitch(sandbox::policy::switches::kNoSandbox)) {
renderer_cmd->AppendSwitch(sandbox::policy::switches::kNoSandbox);
}
#endif
CopyFeatureSwitch(browser_cmd, renderer_cmd, switches::kEnableBlinkFeatures);
CopyFeatureSwitch(browser_cmd, renderer_cmd, switches::kDisableBlinkFeatures);
#if BUILDFLAG(IS_WIN)
if (media::IsMediaFoundationD3D11VideoCaptureEnabled()) {
renderer_cmd->AppendSwitch(switches::kVideoCaptureUseGpuMemoryBuffer);
}
#endif
}
const base::Process& RenderProcessHostImpl::GetProcess() {
if (run_renderer_in_process()) {
static const base::NoDestructor<base::Process> self(
base::Process::Current());
return *self;
}
if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) {
static const base::NoDestructor<base::Process> null_process;
return *null_process;
}
return child_process_launcher_->GetProcess();
}
bool RenderProcessHostImpl::IsReady() {
return GetProcess().Handle() && channel_connected_;
}
bool RenderProcessHostImpl::Shutdown(int exit_code) {
if (run_renderer_in_process())
return false;
if (!child_process_launcher_.get())
return false;
shutdown_exit_code_ = exit_code;
shutdown_requested_ = true;
return child_process_launcher_->Terminate(exit_code);
}
bool RenderProcessHostImpl::ShutdownRequested() {
return shutdown_requested_;
}
bool RenderProcessHostImpl::FastShutdownIfPossible(size_t page_count,
bool skip_unload_handlers) {
if (page_count && page_count != (GetActiveViewCount() + pending_views_)) {
LOG(INFO) << "Discard failed; there are active or pending views";
return false;
}
if (run_renderer_in_process()) {
LOG(INFO) << "Discard failed; Single process mode";
return false;
}
if (!child_process_launcher_.get()) {
LOG(INFO) << "Discard failed; Render process hasn't started or is probably crashed";
return false;
}
if (!skip_unload_handlers && !SuddenTerminationAllowed()) {
LOG(INFO) << "Discard failed; there's an unload listener";
return false;
}
if (keep_alive_ref_count_ != 0) {
CHECK(!base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration));
LOG(INFO) << "Discard failed; keep_alive_ref_count_ != 0";
return false;
}
if (worker_ref_count_ != 0) {
LOG(INFO) << "Discard failed; worker_ref_count_ != 0";
return false;
}
if (pending_reuse_ref_count_ != 0) {
LOG(INFO) << "Discard failed; pending_reuse_ref_count_ != 0";
return false;
}
if (shutdown_delay_ref_count_ != 0) {
LOG(INFO) << "Discard failed; shutdown_delay_ref_count_ != 0";
return false;
}
fast_shutdown_started_ = true;
LOG(INFO) << "Rended process: " << GetProcess().Handle() << " died due to fast shutdown versus another cause";
ChildProcessTerminationInfo info;
info.status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED;
info.exit_code = 0;
ProcessDied(info);
return true;
}
bool RenderProcessHostImpl::Send(IPC::Message* msg) {
TRACE_IPC_MESSAGE_SEND("renderer_host", "RenderProcessHostImpl::Send", msg);
std::unique_ptr<IPC::Message> message(msg);
if (!channel_)
return false;
DCHECK(!message->is_sync());
if (ipc_send_watcher_for_testing_)
ipc_send_watcher_for_testing_.Run(*message);
return channel_->Send(message.release());
}
bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) {
if (deleting_soon_ || fast_shutdown_started_)
return false;
mark_child_process_activity_time();
IPC::Listener* listener = listeners_.Lookup(msg.routing_id());
if (!listener) {
if (msg.is_sync()) {
IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
reply->set_reply_error();
Send(reply);
}
return true;
}
return listener->OnMessageReceived(msg);
}
void RenderProcessHostImpl::OnAssociatedInterfaceRequest(
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {
if (associated_interfaces_ &&
!associated_interfaces_->TryBindInterface(interface_name, &handle)) {
LOG(ERROR) << "Request for unknown Channel-associated interface: "
<< interface_name;
}
}
void RenderProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
channel_connected_ = true;
#if BUILDFLAG(IS_MAC)
ChildProcessTaskPortProvider::GetInstance()->OnChildProcessLaunched(
peer_pid, child_process_.get());
#endif
if (IsReady()) {
DCHECK(!sent_render_process_ready_);
sent_render_process_ready_ = true;
for (auto& observer : observers_)
observer.RenderProcessReady(this);
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
ProvideStatusFileForRenderer();
#endif
ProvideSwapFileForRenderer();
}
#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
child_process_->SetIPCLoggingEnabled(IPC::Logging::GetInstance()->Enabled());
#endif
#if BUILDFLAG(CLANG_PROFILING_INSIDE_SANDBOX)
child_process_->SetProfilingFile(OpenProfilingFile());
#endif
child_process_->SetPseudonymizationSalt(GetPseudonymizationSalt());
#ifdef OHOS_THEME_FONT
if (auto* theme_font = EnsureThemeFont()) {
UpdateThemeFontFile(theme_font->font_file.Duplicate());
}
#endif
#ifdef OHOS_LOGGER_REPORT
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableLoggerReport)) {
child_process_->SetStrictLogMode(GetBrowserContext()->IsOffTheRecord());
}
#endif
}
void RenderProcessHostImpl::OnChannelError() {
#if BUILDFLAG(IS_OHOS)
LOG(ERROR) << "RenderProcessHostImpl::OnChannelError";
#endif
ChildProcessTerminationInfo info =
GetChildTerminationInfo(true );
ProcessDied(info);
}
void RenderProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) {
auto type = message.type();
LOG(ERROR) << "bad message " << type << " terminating renderer.";
base::debug::Alias(&type);
bad_message::ReceivedBadMessage(this,
bad_message::RPH_DESERIALIZATION_FAILED);
}
BrowserContext* RenderProcessHostImpl::GetBrowserContext() {
return browser_context_;
}
bool RenderProcessHostImpl::InSameStoragePartition(
StoragePartition* partition) {
return GetStoragePartition() == partition;
}
int RenderProcessHostImpl::GetID() const {
return id_;
}
base::SafeRef<RenderProcessHost> RenderProcessHostImpl::GetSafeRef() const {
return safe_ref_factory_.GetSafeRef();
}
bool RenderProcessHostImpl::IsInitializedAndNotDead() {
return is_initialized_ && !is_dead_;
}
void RenderProcessHostImpl::SetBlocked(bool blocked) {
if (blocked == is_blocked_)
return;
is_blocked_ = blocked;
blocked_state_changed_callback_list_.Notify(blocked);
}
bool RenderProcessHostImpl::IsBlocked() {
return is_blocked_;
}
void RenderProcessHostImpl::PauseSocketManagerForRenderFrameHost(
const GlobalRenderFrameHostId& render_frame_host_id) {
p2p_socket_dispatcher_host_->PauseSocketManagerForRenderFrameHost(
render_frame_host_id);
}
void RenderProcessHostImpl::ResumeSocketManagerForRenderFrameHost(
const GlobalRenderFrameHostId& render_frame_host_id) {
p2p_socket_dispatcher_host_->ResumeSocketManagerForRenderFrameHost(
render_frame_host_id);
}
base::CallbackListSubscription
RenderProcessHostImpl::RegisterBlockStateChangedCallback(
const BlockStateChangedCallback& cb) {
return blocked_state_changed_callback_list_.Add(cb);
}
bool RenderProcessHostImpl::HasOnlyNonLiveRenderFrameHosts() {
if (GetRenderFrameHostCount() == 0)
return false;
int found_rfh_count = 0;
for (auto rfh_id : render_frame_host_id_set_) {
if (RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(rfh_id)) {
found_rfh_count++;
if (rfh->IsRenderFrameLive())
return false;
if (rfh->delegate()->IsInnerWebContentsForGuest())
return false;
}
}
if (found_rfh_count < GetRenderFrameHostCount())
return false;
DCHECK_EQ(GetRenderFrameHostCount(), found_rfh_count);
return true;
}
void RenderProcessHostImpl::Cleanup() {
TRACE_EVENT("shutdown", "RenderProcessHostImpl::Cleanup",
ChromeTrackEvent::kRenderProcessHost, *this);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (run_renderer_in_process())
return;
if (within_process_died_observer_) {
TRACE_EVENT("shutdown",
"RenderProcessHostImpl::Cleanup : within_process_died_observer",
ChromeTrackEvent::kRenderProcessHost, *this);
delayed_cleanup_needed_ = true;
return;
}
delayed_cleanup_needed_ = false;
bool has_only_non_live_rfhs =
GetContentClient()->browser()->ShouldAllowNoLongerUsedProcessToExit() &&
HasOnlyNonLiveRenderFrameHosts();
if (!listeners_.IsEmpty() && !has_only_non_live_rfhs) {
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::Cleanup : Has listeners.",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto =
ctx.event<ChromeTrackEvent>()->set_render_process_host_cleanup();
proto->set_listener_count(listeners_.size());
});
return;
} else if (keep_alive_ref_count_ != 0) {
CHECK(!base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration));
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::Cleanup : Have keep_alive_ref.",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto =
ctx.event<ChromeTrackEvent>()->set_render_process_host_cleanup();
proto->set_keep_alive_ref_count(keep_alive_ref_count_);
});
return;
} else if (shutdown_delay_ref_count_ != 0) {
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::Cleanup : Have shutdown_delay_ref.",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto =
ctx.event<ChromeTrackEvent>()->set_render_process_host_cleanup();
proto->set_shutdown_delay_ref_count(shutdown_delay_ref_count_);
});
return;
} else if (worker_ref_count_ != 0) {
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::Cleanup : Have worker_ref.",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto =
ctx.event<ChromeTrackEvent>()->set_render_process_host_cleanup();
proto->set_worker_ref_count(worker_ref_count_);
});
return;
} else if (pending_reuse_ref_count_ != 0) {
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::Cleanup : Have pending_reuse_ref.",
ChromeTrackEvent::kRenderProcessHost, *this,
[&](perfetto::EventContext ctx) {
auto* proto =
ctx.event<ChromeTrackEvent>()->set_render_process_host_cleanup();
proto->set_pending_reuse_ref_count(pending_reuse_ref_count_);
});
return;
}
if (has_only_non_live_rfhs) {
DCHECK(!listeners_.IsEmpty());
if (!IsInitializedAndNotDead())
return;
TRACE_EVENT("shutdown",
"RenderProcessHostImpl::Cleanup : Exit without full cleanup.",
ChromeTrackEvent::kRenderProcessHost, *this);
ChildProcessTerminationInfo info =
GetChildTerminationInfo(false );
info.status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
info.exit_code = 0;
fast_shutdown_started_ = true;
ProcessDied(info);
return;
}
TRACE_EVENT("shutdown", "RenderProcessHostImpl::Cleanup : Starting cleanup.",
ChromeTrackEvent::kRenderProcessHost, *this);
TRACE_EVENT_BEGIN("shutdown", "Cleanup in progress",
perfetto::Track::FromPointer(this),
ChromeTrackEvent::kRenderProcessHost, *this);
CHECK(!deleting_soon_);
deleting_soon_ = true;
if (is_initialized_) {
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&WebRtcLog::ClearLogMessageCallback, GetID()));
}
DCHECK_EQ(0, pending_views_);
if (IsInitializedAndNotDead()) {
ChildProcessTerminationInfo info = GetChildTerminationInfo(false);
info.status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
info.exit_code = 0;
for (auto& observer : observers_) {
observer.RenderProcessExited(this, info);
}
}
for (auto& observer : observers_)
observer.RenderProcessHostDestroyed(this);
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_TERMINATED, Source<RenderProcessHost>(this),
NotificationService::NoDetails());
RecentlyDestroyedHosts::Add(this, time_spent_running_unload_handlers_,
browser_context_);
StopTrackingProcessForShutdownDelay();
#ifndef NDEBUG
is_self_deleted_ = true;
#endif
base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(FROM_HERE,
this);
ResetIPC();
UnregisterHost(GetID());
browser_context_ = nullptr;
storage_partition_impl_ = nullptr;
}
#if BUILDFLAG(IS_ANDROID)
void RenderProcessHostImpl::PopulateTerminationInfoRendererFields(
ChildProcessTerminationInfo* info) {
info->renderer_has_visible_clients = VisibleClientCount() > 0;
info->renderer_was_subframe = GetFrameDepth() > 0;
}
#endif
void RenderProcessHostImpl::AddPendingView() {
const bool had_pending_views = pending_views_++;
if (!had_pending_views)
UpdateProcessPriority();
}
void RenderProcessHostImpl::RemovePendingView() {
DCHECK(pending_views_);
--pending_views_;
if (!pending_views_)
UpdateProcessPriority();
}
void RenderProcessHostImpl::AddPriorityClient(
RenderProcessHostPriorityClient* priority_client) {
DCHECK(!base::Contains(priority_clients_, priority_client));
priority_clients_.insert(priority_client);
UpdateProcessPriorityInputs();
}
void RenderProcessHostImpl::RemovePriorityClient(
RenderProcessHostPriorityClient* priority_client) {
DCHECK(base::Contains(priority_clients_, priority_client));
priority_clients_.erase(priority_client);
UpdateProcessPriorityInputs();
}
void RenderProcessHostImpl::SetPriorityOverride(bool foregrounded) {
priority_override_ = foregrounded;
UpdateProcessPriority();
}
bool RenderProcessHostImpl::HasPriorityOverride() {
return priority_override_.has_value();
}
void RenderProcessHostImpl::ClearPriorityOverride() {
priority_override_.reset();
UpdateProcessPriority();
}
void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) {
sudden_termination_allowed_ = enabled;
}
bool RenderProcessHostImpl::SuddenTerminationAllowed() {
return sudden_termination_allowed_;
}
base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() {
return base::TimeTicks::Now() - child_process_activity_time_;
}
void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) {
FilterURL(this, empty_allowed, url);
}
void RenderProcessHostImpl::EnableAudioDebugRecordings(
const base::FilePath& file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
aec_dump_manager_.Start(file_path);
}
void RenderProcessHostImpl::DisableAudioDebugRecordings() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
aec_dump_manager_.Stop();
}
RenderProcessHostImpl::WebRtcStopRtpDumpCallback
RenderProcessHostImpl::StartRtpDump(bool incoming,
bool outgoing,
WebRtcRtpPacketCallback packet_callback) {
p2p_socket_dispatcher_host_->StartRtpDump(incoming, outgoing,
std::move(packet_callback));
return base::BindOnce(&P2PSocketDispatcherHost::StopRtpDump,
p2p_socket_dispatcher_host_->GetWeakPtr());
}
IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() {
return channel_.get();
}
void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
filter->RegisterAssociatedInterfaces(channel_.get());
channel_->AddFilter(filter->GetFilter());
}
bool RenderProcessHostImpl::FastShutdownStarted() {
return fast_shutdown_started_;
}
void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::RegisterHost",
[&](perfetto::EventContext ctx) {
ctx.event<ChromeTrackEvent>()->set_render_process_host()->set_id(
host_id);
});
GetAllHosts().AddWithID(host, host_id);
}
void RenderProcessHostImpl::UnregisterHost(int host_id) {
RenderProcessHost* host = GetAllHosts().Lookup(host_id);
if (!host)
return;
TRACE_EVENT(
"shutdown", "RenderProcessHostImpl::UnregisterHost",
[&](perfetto::EventContext ctx) {
ctx.event<ChromeTrackEvent>()->set_render_process_host()->set_id(
host_id);
});
GetAllHosts().Remove(host_id);
#if defined(OHOS_RENDER_PROCESS_SHARE)
RemoveFromSharedRenderProcessMap(host);
#endif
MAYBEVLOG(3) << __func__ << "(" << host_id << ")" << std::endl
<< GetCurrentHostMapDebugString(
static_cast<SiteProcessCountTracker*>(
host->GetBrowserContext()->GetUserData(
kCommittedSiteProcessCountTrackerKey)));
SiteProcessMap* map =
GetSiteProcessMapForBrowserContext(host->GetBrowserContext());
map->RemoveProcess(host);
}
void RenderProcessHostImpl::RegisterCreationObserver(
RenderProcessHostCreationObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetAllCreationObservers().push_back(observer);
}
void RenderProcessHostImpl::UnregisterCreationObserver(
RenderProcessHostCreationObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto iter = base::ranges::find(GetAllCreationObservers(), observer);
DCHECK(iter != GetAllCreationObservers().end());
GetAllCreationObservers().erase(iter);
}
void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph,
bool empty_allowed,
GURL* url) {
if (empty_allowed && url->is_empty())
return;
if (!url->is_valid()) {
TRACE_EVENT1("navigation", "RenderProcessHost::FilterURL - invalid URL",
"process_id", rph->GetID());
*url = GURL(kBlockedURL);
return;
}
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
if (!policy->CanRequestURL(rph->GetID(), *url)) {
TRACE_EVENT2("navigation",
"RenderProcessHost::FilterURL - failed CanRequestURL",
"process_id", rph->GetID(), "url", url->spec());
VLOG(1) << "Blocked URL " << url->spec();
*url = GURL(kBlockedURL);
}
}
bool RenderProcessHostImpl::IsSuitableHost(
RenderProcessHost* host,
const IsolationContext& isolation_context,
const SiteInfo& site_info) {
#ifdef OHOS_RENDER_PROCESS_MODE
if (base::ohos::IsWearableDevice()) {
return true;
}
#endif
BrowserContext* browser_context =
isolation_context.browser_or_resource_context().ToBrowserContext();
DCHECK(browser_context);
if (run_renderer_in_process()) {
DCHECK_EQ(host->GetBrowserContext(), browser_context)
<< " Single-process mode does not support multiple browser contexts.";
return true;
}
if (host->GetBrowserContext() != browser_context)
return false;
if (host->IsForGuestsOnly() != site_info.is_guest())
return false;
if (host->IsJitDisabled() != site_info.is_jit_disabled())
return false;
if (host->IsPdf() != site_info.is_pdf())
return false;
#ifdef OHOS_RENDER_PROCESS_MODE
if (site_info.is_pdf()) {
return host->special_render_numbers_[RenderType::kPdf] > 0;
}
if (site_info.site_url().SchemeIs(kExtensionScheme)
#if defined(OHOS_ARKWEB_EXTENSIONS)
|| site_info.site_url().SchemeIs(kArkwebExtensionScheme)
#endif
) {
return host->special_render_numbers_[RenderType::kExtension] > 0;
}
#endif
StoragePartition* dest_partition = browser_context->GetStoragePartition(
site_info.storage_partition_config());
if (!host->InSameStoragePartition(dest_partition))
return false;
bool host_has_web_ui_bindings =
ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
host->GetID());
ProcessLock process_lock = host->GetProcessLock();
if (host->HostHasNotBeenUsed()) {
CHECK(!host_has_web_ui_bindings);
CHECK(process_lock.is_invalid());
} else {
bool url_is_for_web_ui =
WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, site_info.site_url());
if (host_has_web_ui_bindings && !url_is_for_web_ui)
return false;
if (!host_has_web_ui_bindings && url_is_for_web_ui)
return false;
#ifdef OHOS_RENDER_PROCESS_MODE
if (url_is_for_web_ui) {
return host->special_render_numbers_[RenderType::kWebUI] > 0;
}
#endif
if (process_lock.is_locked_to_site()) {
if (!site_info.ShouldLockProcessToSite(isolation_context))
return false;
if (process_lock != ProcessLock::FromSiteInfo(site_info))
return false;
} else {
if (process_lock.allows_any_site() &&
!process_lock.IsCompatibleWithWebExposedIsolation(site_info)) {
return false;
}
if (!host->IsUnused() &&
site_info.ShouldLockProcessToSite(isolation_context)) {
return false;
}
}
}
if (SiteInstance::ShouldAssignSiteForURL(site_info.site_url()) &&
site_info.RequiresDedicatedProcess(isolation_context)) {
SiteProcessCountTracker* pending_tracker =
static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
if (pending_tracker &&
pending_tracker->ContainsNonReusableSiteForHost(host))
return false;
}
return GetContentClient()->browser()->IsSuitableHost(host,
site_info.site_url());
}
bool RenderProcessHostImpl::MayReuseAndIsSuitable(
RenderProcessHost* host,
const IsolationContext& isolation_context,
const SiteInfo& site_info) {
return host->MayReuseHost() &&
IsSuitableHost(host, isolation_context, site_info);
}
bool RenderProcessHostImpl::MayReuseAndIsSuitable(
RenderProcessHost* host,
SiteInstanceImpl* site_instance) {
return MayReuseAndIsSuitable(host, site_instance->GetIsolationContext(),
site_instance->GetSiteInfo());
}
void RenderProcessHost::WarmupSpareRenderProcessHost(
content::BrowserContext* browser_context) {
SpareRenderProcessHostManager::GetInstance().WarmupSpareRenderProcessHost(
browser_context);
}
bool RenderProcessHost::run_renderer_in_process() {
return g_run_renderer_in_process;
}
void RenderProcessHost::SetRunRendererInProcess(bool value) {
g_run_renderer_in_process = value;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (value) {
if (!command_line->HasSwitch(switches::kLang)) {
const std::string locale =
GetContentClient()->browser()->GetApplicationLocale();
command_line->AppendSwitchASCII(switches::kLang, locale);
}
AppendCompositorCommandLineFlags(command_line);
}
}
void RenderProcessHost::ShutDownInProcessRenderer() {
base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
allow_base_sync_primitives;
RenderProcessHostImpl::ShutDownInProcessRenderer();
}
RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return iterator(&GetAllHosts());
}
RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return GetAllHosts().Lookup(render_process_id);
}
size_t RenderProcessHostImpl::GetProcessCount() {
return GetAllHosts().size();
}
size_t RenderProcessHostImpl::GetProcessCountForLimit() {
size_t process_count_to_ignore =
GetContentClient()->browser()->GetProcessCountToIgnoreForLimit();
CHECK_LE(process_count_to_ignore, RenderProcessHostImpl::GetProcessCount());
RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
size_t count = 0;
while (!it.IsAtEnd()) {
RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>(
it.GetCurrentValue());
if (!host->is_dead()) {
count++;
}
it.Advance();
}
#if BUILDFLAG(IS_OHOS)
LOG(DEBUG) << "RenderProcessHostImpl::GetProcessCount count: " << count;
#endif
return count - process_count_to_ignore;
}
bool RenderProcessHost::ShouldTryToUseExistingProcessHost(
BrowserContext* browser_context,
const GURL& url) {
if (run_renderer_in_process())
return true;
size_t process_count = RenderProcessHostImpl::GetProcessCountForLimit();
if (process_count >= GetMaxRendererProcessCount()) {
MAYBEVLOG(4) << __func__
<< ": process_count >= GetMaxRendererProcessCount() ("
<< process_count << " >= " << GetMaxRendererProcessCount()
<< ") - will try to reuse an existing process";
return true;
}
return GetContentClient()->browser()->ShouldTryToUseExistingProcessHost(
browser_context, url);
}
RenderProcessHost* RenderProcessHostImpl::GetExistingProcessHost(
SiteInstanceImpl* site_instance) {
std::vector<RenderProcessHost*> suitable_renderers;
suitable_renderers.reserve(RenderProcessHostImpl::GetProcessCount());
for (iterator iter(AllHostsIterator()); !iter.IsAtEnd(); iter.Advance()) {
if (iter.GetCurrentValue() == SpareRenderProcessHostManager::GetInstance()
.spare_render_process_host()) {
continue;
}
if (MayReuseAndIsSuitable(iter.GetCurrentValue(), site_instance))
suitable_renderers.push_back(iter.GetCurrentValue());
}
MAYBEVLOG(4) << __func__ << ": Found " << suitable_renderers.size()
<< " suitable process hosts out of "
<< RenderProcessHostImpl::GetProcessCount() << ".";
if (!suitable_renderers.empty()) {
int suitable_count = static_cast<int>(suitable_renderers.size());
int random_index = base::RandInt(0, suitable_count - 1);
return suitable_renderers[random_index];
}
return nullptr;
}
#ifdef OHOS_RENDER_PROCESS_MODE
class DelayedRenderKiller {
public:
static DelayedRenderKiller* GetInstance() {
static DelayedRenderKiller inst_;
return &inst_;
}
~DelayedRenderKiller() = default;
void StartTimer() {
if (!timer_.IsRunning()) {
rep_ = 0;
timer_.Start(FROM_HERE, base::Seconds(3),
base::BindRepeating(&DelayedRenderKiller::TryKillRender, base::Unretained(this)));
}
}
bool NeedDebug() {
return rep_ >= MAX_REP;
}
private:
DelayedRenderKiller() = default;
DelayedRenderKiller(const DelayedRenderKiller& i) = delete;
DelayedRenderKiller& operator= (const DelayedRenderKiller& i) = delete;
void TryKillRender() {
LOG(INFO) << "DelayedRenderKiller shot timer";
rep_++;
if (rep_ > MAX_REP) {
LOG(INFO) << "rep count up to limit, stop timer";
timer_.Stop();
return;
}
size_t count = RenderProcessHostImpl::GetProcessCountForLimit();
if (RenderProcessHost::render_process_mode() !=
RenderProcessMode::SINGLE_MODE &&
(count > RenderProcessHostImpl::GetMaxRendererProcessCount())) {
RenderProcessHostImpl* render_host = static_cast<RenderProcessHostImpl*>(
RenderProcessHostImpl::GetExistingBackgroundProcessHost());
if (render_host) {
render_host->FastShutdownIfPossible(1u, true);
LOG(INFO) << "Successfully tried to fast shutdown idle render process with handle: "
<< render_host->GetProcess().Handle();
}
}
count = RenderProcessHostImpl::GetProcessCountForLimit();
if (count <= RenderProcessHostImpl::GetMaxRendererProcessCount()) {
timer_.Stop();
LOG(INFO) << "DelayedRenderKiller stop timer";
}
}
base::RepeatingTimer timer_;
int32_t rep_ = 0;
const int32_t MAX_REP = 15;
};
RenderProcessHost* RenderProcessHostImpl::GetExistingBackgroundProcessHost() {
RenderProcessHost* longest_background_host;
base::TimeDelta longest_duration;
base::TimeTicks current_time = base::TimeTicks::Now();
for (iterator iter(AllHostsIterator()); !iter.IsAtEnd(); iter.Advance()) {
if (iter.GetCurrentValue() == SpareRenderProcessHostManager::GetInstance()
.spare_render_process_host()) {
continue;
}
if (DelayedRenderKiller::GetInstance()->NeedDebug()) {
LOG(INFO) << "isBackground " << iter.GetCurrentValue()->IsProcessBackgrounded()
<< " AreAllRefCountsZero " << static_cast<RenderProcessHostImpl*>
(iter.GetCurrentValue())->AreAllRefCountsZero()
<< " ActiveView " << iter.GetCurrentValue()->GetActiveViewCount();
}
if (iter.GetCurrentValue()->IsProcessBackgrounded() &&
static_cast<RenderProcessHostImpl*>(iter.GetCurrentValue())
->AreAllRefCountsZero() &&
iter.GetCurrentValue()->GetActiveViewCount() <= 1) {
base::TimeDelta background_duration = current_time -
iter.GetCurrentValue()->ProcessBackgroundTime();
if (background_duration >= longest_duration) {
longest_background_host = iter.GetCurrentValue();
longest_duration = background_duration;
}
}
}
if (longest_background_host) {
LOG(INFO) << ": Found one background render host "
<< longest_background_host->GetProcess().Handle();
return longest_background_host;
}
return nullptr;
}
void RenderProcessHost::SetRenderProcessMode(RenderProcessMode mode) {
g_render_process_mode = mode;
LOG(INFO) << "SetRenderProcessMode g_render_process_mode:"
<< (int)g_render_process_mode;
}
RenderProcessMode RenderProcessHost::render_process_mode() {
if (g_render_process_mode == RenderProcessMode::DEFAULT_MODE) {
return (base::ohos::IsPcDevice() || base::ohos::IsTabletDevice())
? RenderProcessMode::MULTIPLE_MODE
: RenderProcessMode::SINGLE_MODE;
}
return g_render_process_mode;
}
#endif
RenderProcessHost* RenderProcessHostImpl::GetSoleProcessHostForSite(
const IsolationContext& isolation_context,
const SiteInfo& site_info) {
SiteProcessMap* map = GetSiteProcessMapForBrowserContext(
isolation_context.browser_or_resource_context().ToBrowserContext());
RenderProcessHost* host = map->FindProcess(site_info);
if (host && !MayReuseAndIsSuitable(host, isolation_context, site_info)) {
RecordAction(
base::UserMetricsAction("BindingsMismatch_GetProcessHostPerSite"));
map->RemoveProcess(host);
host = nullptr;
}
return host;
}
void RenderProcessHostImpl::RegisterSoleProcessHostForSite(
RenderProcessHost* process,
SiteInstanceImpl* site_instance) {
DCHECK(process);
DCHECK(site_instance);
SiteProcessMap* map =
GetSiteProcessMapForBrowserContext(site_instance->GetBrowserContext());
if (!site_instance->GetSiteInfo().is_empty())
map->RegisterProcess(site_instance->GetSiteInfo(), process);
}
RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
SiteInstanceImpl* site_instance) {
const SiteInfo& site_info = site_instance->GetSiteInfo();
SiteInstanceImpl::ProcessReusePolicy process_reuse_policy =
site_instance->process_reuse_policy();
RenderProcessHost* render_process_host = nullptr;
bool is_unmatched_service_worker = site_instance->is_for_service_worker();
BrowserContext* browser_context = site_instance->GetBrowserContext();
switch (process_reuse_policy) {
case SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE: {
render_process_host = GetSoleProcessHostForSite(
site_instance->GetIsolationContext(), site_info);
break;
}
case SiteInstanceImpl::ProcessReusePolicy::
REUSE_PENDING_OR_COMMITTED_SITE: {
render_process_host =
FindReusableProcessHostForSiteInstance(site_instance);
const base::TimeTicks reusable_host_lookup_time = base::TimeTicks::Now();
UMA_HISTOGRAM_BOOLEAN(
"SiteIsolation.ReusePendingOrCommittedSite.CouldReuse2",
render_process_host != nullptr);
if (render_process_host) {
is_unmatched_service_worker = false;
render_process_host->StopTrackingProcessForShutdownDelay();
} else {
RecentlyDestroyedHosts::RecordMetricIfReusableHostRecentlyDestroyed(
reusable_host_lookup_time,
ProcessLock::FromSiteInfo(site_instance->GetSiteInfo()),
site_instance->GetBrowserContext());
}
break;
}
case SiteInstanceImpl::ProcessReusePolicy::
REUSE_PENDING_OR_COMMITTED_SITE_WITH_MAIN_FRAME_THRESHOLD: {
CHECK(base::FeatureList::IsEnabled(
features::kProcessPerSiteUpToMainFrameThreshold));
size_t main_frame_threshold = base::checked_cast<size_t>(
features::kProcessPerSiteMainFrameThreshold.Get());
render_process_host = FindReusableProcessHostForSiteInstance(
site_instance, main_frame_threshold);
if (render_process_host) {
is_unmatched_service_worker = false;
render_process_host->StopTrackingProcessForShutdownDelay();
}
break;
}
default: {
break;
}
}
if (!render_process_host &&
!(process_reuse_policy == SiteInstanceImpl::ProcessReusePolicy::DEFAULT &&
site_instance->is_for_service_worker())) {
render_process_host =
UnmatchedServiceWorkerProcessTracker::MatchWithSite(site_instance);
}
if (!render_process_host) {
render_process_host =
site_instance->GetSiteInstanceGroupProcessIfAvailable();
}
if (render_process_host) {
site_instance->set_process_assignment(
SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS);
}
auto& spare_process_manager = SpareRenderProcessHostManager::GetInstance();
bool spare_was_taken = false;
if (!render_process_host) {
render_process_host = spare_process_manager.MaybeTakeSpareRenderProcessHost(
browser_context, site_instance);
if (render_process_host) {
site_instance->set_process_assignment(
SiteInstanceProcessAssignment::USED_SPARE_PROCESS);
spare_was_taken = true;
}
}
if (!render_process_host && ShouldTryToUseExistingProcessHost(
browser_context, site_info.site_url())) {
render_process_host = GetExistingProcessHost(site_instance);
if (render_process_host) {
site_instance->set_process_assignment(
SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS);
LOG(INFO) << "Use an existing rendering process, render_process: "
<< render_process_host->GetProcess().Handle();
}
}
if (render_process_host && !RenderProcessHostImpl::MayReuseAndIsSuitable(
render_process_host, site_instance)) {
base::debug::SetCrashKeyString(bad_message::GetRequestedSiteInfoKey(),
site_info.GetDebugString());
ChildProcessSecurityPolicyImpl::GetInstance()->LogKilledProcessOriginLock(
render_process_host->GetID());
CHECK(false) << "Unsuitable process reused for site " << site_info;
}
if (!render_process_host) {
LOG(INFO) << "Request to create a new rendering process, current count: "
<< RenderProcessHostImpl::GetProcessCountForLimit() << " Max: "
<< RenderProcessHostImpl::GetMaxRendererProcessCount();
render_process_host =
CreateRenderProcessHost(browser_context, site_instance);
site_instance->set_process_assignment(
SiteInstanceProcessAssignment::CREATED_NEW_PROCESS);
#ifdef OHOS_RENDER_PROCESS_MODE
if (site_info.site_url().SchemeIs(kExtensionScheme)
#if defined(OHOS_ARKWEB_EXTENSIONS)
|| site_info.site_url().SchemeIs(kArkwebExtensionScheme)
#endif
) {
render_process_host
->special_render_numbers_[RenderType::kExtension]++;
}
if (site_info.is_pdf()) {
render_process_host
->special_render_numbers_[RenderType::kPdf]++;
}
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, site_info.site_url())) {
render_process_host
->special_render_numbers_[RenderType::kWebUI]++;
}
if (RenderProcessHost::render_process_mode() !=
RenderProcessMode::SINGLE_MODE &&
(RenderProcessHostImpl::GetProcessCountForLimit() >
RenderProcessHostImpl::GetMaxRendererProcessCount())) {
RenderProcessHostImpl* render_host =
static_cast<RenderProcessHostImpl*>(
RenderProcessHostImpl::GetExistingBackgroundProcessHost());
if (render_host) {
LOG(INFO) << "Try fast shutdown idle render process: "
<< render_host->GetProcess().Handle() << " in the background.";
render_host->FastShutdownIfPossible(1u, true);
}
if (RenderProcessHostImpl::GetProcessCountForLimit() >
RenderProcessHostImpl::GetMaxRendererProcessCount()) {
DelayedRenderKiller::GetInstance()->StartTimer();
}
}
#endif
}
if (spare_was_taken) {
spare_process_manager.PrepareForFutureRequests(browser_context);
}
if (is_unmatched_service_worker) {
UnmatchedServiceWorkerProcessTracker::Register(render_process_host,
site_instance);
}
#ifdef OHOS_RENDER_PROCESS_MODE
if (!base::ohos::IsWearableDevice()) {
CHECK(render_process_host->InSameStoragePartition(
browser_context->GetStoragePartition(site_instance,
false )));
}
#else
CHECK(render_process_host->InSameStoragePartition(
browser_context->GetStoragePartition(site_instance,
false )));
#endif
MAYBEVLOG(2) << __func__ << "(" << site_info << ") selected process host "
<< render_process_host->GetID() << " using assignment \""
<< site_instance->GetLastProcessAssignmentOutcome() << "\""
<< std::endl
<< GetCurrentHostMapDebugString(
static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(
kCommittedSiteProcessCountTrackerKey)));
return render_process_host;
}
void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
if (!base::GlobalHistogramAllocator::Get()) {
if (is_initialized_) {
HistogramController::GetInstance()->SetHistogramMemory<RenderProcessHost>(
this, base::WritableSharedMemoryRegion());
}
return;
}
base::ProcessHandle destination = GetProcess().Handle();
if (destination == base::kNullProcessHandle)
return;
base::WritableSharedMemoryRegion shm_region =
base::WritableSharedMemoryRegion::Create(2 << 20);
base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
if (!shm_region.IsValid() || !shm_mapping.IsValid())
return;
metrics_allocator_ =
std::make_unique<base::WritableSharedPersistentMemoryAllocator>(
std::move(shm_mapping), GetID(), "RendererMetrics");
HistogramController::GetInstance()->SetHistogramMemory<RenderProcessHost>(
this, std::move(shm_region));
}
ChildProcessTerminationInfo RenderProcessHostImpl::GetChildTerminationInfo(
bool already_dead) {
DCHECK(child_process_launcher_);
ChildProcessTerminationInfo info;
info = child_process_launcher_->GetChildTerminationInfo(already_dead);
if (already_dead && info.status == base::TERMINATION_STATUS_STILL_RUNNING) {
info.status = base::TERMINATION_STATUS_PROCESS_CRASHED;
#if BUILDFLAG(IS_WIN)
if (info.exit_code == WAIT_TIMEOUT && g_analyze_hung_renderer)
g_analyze_hung_renderer(child_process_launcher_->GetProcess());
#endif
}
#if BUILDFLAG(IS_ANDROID)
PopulateTerminationInfoRendererFields(&info);
#endif
return info;
}
void RenderProcessHostImpl::ProcessDied(
const ChildProcessTerminationInfo& termination_info) {
TRACE_EVENT0("content", "RenderProcessHostImpl::ProcessDied");
DCHECK(!within_process_died_observer_);
DCHECK(!deleting_soon_);
#if BUILDFLAG(IS_OHOS)
base::ProcessId process_id = GetProcess().Pid();
OHOS::NWeb::ResSchedClientAdapter::ReportKeyThread(
OHOS::NWeb::ResSchedStatusAdapter::THREAD_DESTROYED, process_id, process_id,
OHOS::NWeb::ResSchedRoleAdapter::IMPORTANT_DISPLAY);
#endif
child_process_launcher_.reset();
is_dead_ = true;
ResetIPC();
UpdateProcessPriority();
ChildProcessTerminationInfo info = termination_info;
if (shutdown_exit_code_ != -1)
info.exit_code = shutdown_exit_code_;
within_process_died_observer_ = true;
for (auto& observer : observers_)
observer.RenderProcessExited(this, info);
NotificationService::current()->Notify(
NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this),
Details<ChildProcessTerminationInfo>(&info));
within_process_died_observer_ = false;
EnableSendQueue();
if (delayed_cleanup_needed_)
Cleanup();
compositing_mode_reporter_.reset();
HistogramController::GetInstance()->NotifyChildDied<RenderProcessHost>(this);
}
void RenderProcessHostImpl::ResetIPC() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
media_interface_proxy_.reset();
renderer_host_receiver_.reset();
io_thread_host_impl_.reset();
associated_interfaces_.reset();
coordinator_connector_receiver_.reset();
tracing_registration_.reset();
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
stable_video_decoder_factory_remote_.reset();
#endif
embedded_frame_sink_provider_.reset();
dom_storage_provider_receiver_.reset();
for (auto receiver_id : dom_storage_receiver_ids_)
storage_partition_impl_->UnbindDomStorage(receiver_id);
instance_weak_factory_.InvalidateWeakPtrs();
ResetChannelProxy();
permission_service_context_.reset();
}
size_t RenderProcessHost::GetActiveViewCount() {
size_t num_active_views = 0;
std::unique_ptr<RenderWidgetHostIterator> widgets(
RenderWidgetHost::GetRenderWidgetHosts());
while (RenderWidgetHost* widget = widgets->GetNextHost()) {
if (widget->GetProcess() && widget->GetProcess()->GetID() == GetID())
num_active_views++;
}
return num_active_views;
}
WebExposedIsolationLevel RenderProcessHost::GetWebExposedIsolationLevel() {
WebExposedIsolationInfo info = GetProcessLock().GetWebExposedIsolationInfo();
if (info.is_isolated_application()) {
return WebExposedIsolationLevel::kMaybeIsolatedApplication;
} else if (info.is_isolated()) {
return WebExposedIsolationLevel::kMaybeIsolated;
}
return WebExposedIsolationLevel::kNotIsolated;
}
void RenderProcessHost::PostTaskWhenProcessIsReady(base::OnceClosure task) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!task.is_null());
new RenderProcessHostIsReadyObserver(this, std::move(task));
}
void RenderProcessHost::SetHungRendererAnalysisFunction(
AnalyzeHungRendererFunction analyze_hung_renderer) {
g_analyze_hung_renderer = analyze_hung_renderer;
}
void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) {
SetSuddenTerminationAllowed(enabled);
}
void RenderProcessHostImpl::RecordUserMetricsAction(const std::string& action) {
base::RecordComputedAction(action);
}
#if BUILDFLAG(IS_ANDROID)
void RenderProcessHostImpl::SetPrivateMemoryFootprint(
uint64_t private_memory_footprint_bytes) {
private_memory_footprint_bytes_ = private_memory_footprint_bytes;
}
#endif
void RenderProcessHostImpl::UpdateProcessPriorityInputs() {
int32_t new_visible_widgets_count = 0;
unsigned int new_frame_depth = kMaxFrameDepthForPriority;
bool new_intersects_viewport = false;
#if BUILDFLAG(IS_ANDROID)
ChildProcessImportance new_effective_importance =
ChildProcessImportance::NORMAL;
#endif
for (auto* client : priority_clients_) {
RenderProcessHostPriorityClient::Priority priority = client->GetPriority();
if (priority.is_hidden) {
if (!new_visible_widgets_count) {
new_frame_depth = std::min(new_frame_depth, priority.frame_depth);
new_intersects_viewport =
new_intersects_viewport || priority.intersects_viewport;
}
} else {
if (new_visible_widgets_count) {
new_frame_depth = std::min(new_frame_depth, priority.frame_depth);
new_intersects_viewport =
new_intersects_viewport || priority.intersects_viewport;
} else {
new_frame_depth = priority.frame_depth;
new_intersects_viewport = priority.intersects_viewport;
}
new_visible_widgets_count++;
}
#if BUILDFLAG(IS_ANDROID)
new_effective_importance =
std::max(new_effective_importance, priority.importance);
#endif
}
bool inputs_changed = new_visible_widgets_count != visible_clients_ ||
frame_depth_ != new_frame_depth ||
intersects_viewport_ != new_intersects_viewport;
visible_clients_ = new_visible_widgets_count;
frame_depth_ = new_frame_depth;
intersects_viewport_ = new_intersects_viewport;
#if BUILDFLAG(IS_ANDROID)
inputs_changed =
inputs_changed || new_effective_importance != effective_importance_;
effective_importance_ = new_effective_importance;
#endif
if (inputs_changed)
UpdateProcessPriority();
}
void RenderProcessHostImpl::UpdateProcessPriority() {
if (!run_renderer_in_process() && (!child_process_launcher_.get() ||
child_process_launcher_->IsStarting())) {
priority_.visible = !blink::kLaunchingProcessIsBackgrounded;
priority_.boost_for_pending_views = true;
return;
}
RenderProcessPriority priority(
visible_clients_ > 0 || base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRendererBackgrounding),
media_stream_count_ > 0, foreground_service_worker_count_ > 0,
frame_depth_, intersects_viewport_,
!!pending_views_
#if BUILDFLAG(IS_ANDROID)
,
GetEffectiveImportance()
#endif
#ifdef OHOS_RENDER_PROCESS_MODE
,
base::TimeTicks::Now()
#endif
);
if (priority_override_.has_value()) {
bool foregrounded = priority_override_.value();
priority = RenderProcessPriority(
foregrounded,
foregrounded,
foregrounded,
0,
foregrounded,
false
#if BUILDFLAG(IS_ANDROID)
,
foregrounded ? ChildProcessImportance::NORMAL
: ChildProcessImportance::MODERATE
#endif
#ifdef OHOS_RENDER_PROCESS_MODE
,
base::TimeTicks::Now()
#endif
);
DCHECK_EQ(!foregrounded, priority.is_background());
}
if (priority_ == priority)
return;
const bool background_state_changed =
priority_.is_background() != priority.is_background();
const bool visibility_state_changed = priority_.visible != priority.visible;
TRACE_EVENT("renderer_host", "RenderProcessHostImpl::UpdateProcessPriority",
ChromeTrackEvent::kRenderProcessHost, *this,
ChromeTrackEvent::kChildProcessLauncherPriority, priority);
priority_ = priority;
if (!run_renderer_in_process()) {
DCHECK(child_process_launcher_.get());
DCHECK(!child_process_launcher_->IsStarting());
#if BUILDFLAG(IS_ANDROID)
child_process_launcher_->SetRenderProcessPriority(priority_);
#elif BUILDFLAG(IS_MAC)
if (base::FeatureList::IsEnabled(
features::kMacAllowBackgroundingRenderProcesses)) {
child_process_launcher_->SetProcessBackgrounded(
priority_.is_background());
}
#else
child_process_launcher_->SetProcessBackgrounded(priority_.is_background());
#endif
}
if ((background_state_changed) || visibility_state_changed) {
SendProcessStateToRenderer();
}
for (auto& observer : internal_observers_)
observer.RenderProcessBackgroundedChanged(this);
if (background_state_changed) {
UpdateControllerServiceWorkerProcessPriority();
}
}
void RenderProcessHostImpl::UpdateControllerServiceWorkerProcessPriority() {
ServiceWorkerContextWrapper* context =
storage_partition_impl_->GetServiceWorkerContext();
if (!context)
return;
for (const auto& kv : context->GetRunningServiceWorkerInfos()) {
ServiceWorkerVersion* version = context->GetLiveVersion(kv.first);
if (version && version->IsControlleeProcessID(GetID())) {
version->UpdateForegroundPriority();
break;
}
}
}
void RenderProcessHostImpl::SendProcessStateToRenderer() {
mojom::RenderProcessBackgroundState background_state =
priority_.is_background()
? mojom::RenderProcessBackgroundState::kBackgrounded
: mojom::RenderProcessBackgroundState::kForegrounded;
mojom::RenderProcessVisibleState visible_state =
priority_.visible ? mojom::RenderProcessVisibleState::kVisible
: mojom::RenderProcessVisibleState::kHidden;
GetRendererInterface()->SetProcessState(background_state, visible_state);
}
void RenderProcessHostImpl::OnProcessLaunched() {
if (deleting_soon_)
return;
if (child_process_launcher_) {
DCHECK(child_process_launcher_->GetProcess().IsValid());
DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, !priority_.visible);
channel_->Unpause(false );
gpu_client_->SetClientPid(GetProcess().Pid());
if (coordinator_connector_receiver_.is_bound())
coordinator_connector_receiver_.Resume();
#if BUILDFLAG(IS_APPLE)
priority_.visible =
!child_process_launcher_->GetProcess().IsProcessBackgrounded(
ChildProcessTaskPortProvider::GetInstance());
#elif BUILDFLAG(IS_ANDROID)
DCHECK_EQ(blink::kLaunchingProcessIsBackgrounded, !priority_.visible);
#else
priority_.visible =
!child_process_launcher_->GetProcess().IsProcessBackgrounded();
#endif
if (priority_.boost_for_pending_views)
UpdateProcessPriority();
CreateSharedRendererHistogramAllocator();
}
NotifyRendererOfLockedStateUpdate();
ThemeHelper::GetInstance()->SendSystemColorInfo(GetRendererInterface());
NotificationService::current()->Notify(NOTIFICATION_RENDERER_PROCESS_CREATED,
Source<RenderProcessHost>(this),
NotificationService::NoDetails());
for (auto* observer : GetAllCreationObservers())
observer->OnRenderProcessHostCreated(this);
if (child_process_launcher_)
channel_->Flush();
if (IsReady()) {
DCHECK(!sent_render_process_ready_);
sent_render_process_ready_ = true;
for (auto& observer : observers_)
observer.RenderProcessReady(this);
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
ProvideStatusFileForRenderer();
#endif
}
aec_dump_manager_.set_pid(GetProcess().Pid());
aec_dump_manager_.AutoStart();
tracing_registration_ = TracingServiceController::Get().RegisterClient(
GetProcess().Pid(),
base::BindRepeating(&RenderProcessHostImpl::BindTracedProcess,
instance_weak_factory_.GetWeakPtr()));
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_ANDROID)
system_tracing_service_ = std::make_unique<tracing::SystemTracingService>();
child_process_->EnableSystemTracingService(
system_tracing_service_->BindAndPassPendingRemote());
#endif
}
void RenderProcessHostImpl::OnProcessLaunchFailed(int error_code) {
if (deleting_soon_)
return;
ChildProcessTerminationInfo info;
info.status = base::TERMINATION_STATUS_LAUNCH_FAILED;
info.exit_code = error_code;
#if BUILDFLAG(IS_ANDROID)
PopulateTerminationInfoRendererFields(&info);
#endif
ProcessDied(info);
}
RenderProcessHost*
RenderProcessHostImpl::FindReusableProcessHostForSiteInstance(
SiteInstanceImpl* site_instance,
absl::optional<size_t> main_frame_threshold) {
BrowserContext* browser_context = site_instance->GetBrowserContext();
if (!ShouldFindReusableProcessHostForSite(site_instance->GetSiteInfo()))
return nullptr;
std::set<RenderProcessHost*> eligible_foreground_hosts;
std::set<RenderProcessHost*> eligible_background_hosts;
SiteProcessCountTracker* pending_tracker =
static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
if (pending_tracker) {
pending_tracker->FindRenderProcessesForSiteInstance(
site_instance, main_frame_threshold, &eligible_foreground_hosts,
&eligible_background_hosts);
}
if (eligible_foreground_hosts.empty()) {
SiteProcessCountTracker* committed_tracker =
static_cast<SiteProcessCountTracker*>(
browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey));
if (committed_tracker) {
committed_tracker->FindRenderProcessesForSiteInstance(
site_instance, main_frame_threshold, &eligible_foreground_hosts,
&eligible_background_hosts);
}
}
if (eligible_foreground_hosts.empty() && eligible_background_hosts.empty() &&
base::FeatureList::IsEnabled(features::kSubframeShutdownDelay)) {
SiteProcessCountTracker* delayed_shutdown_tracker =
static_cast<SiteProcessCountTracker*>(browser_context->GetUserData(
kDelayedShutdownSiteProcessCountTrackerKey));
if (delayed_shutdown_tracker) {
delayed_shutdown_tracker->FindRenderProcessesForSiteInstance(
site_instance, main_frame_threshold, &eligible_foreground_hosts,
&eligible_background_hosts);
}
}
if (!eligible_foreground_hosts.empty()) {
int index = base::RandInt(0, eligible_foreground_hosts.size() - 1);
auto iterator = eligible_foreground_hosts.begin();
for (int i = 0; i < index; ++i)
++iterator;
return *iterator;
}
if (!eligible_background_hosts.empty()) {
int index = base::RandInt(0, eligible_background_hosts.size() - 1);
auto iterator = eligible_background_hosts.begin();
for (int i = 0; i < index; ++i)
++iterator;
return *iterator;
}
return nullptr;
}
void RenderProcessHostImpl::OnMojoError(int render_process_id,
const std::string& error) {
LOG(ERROR) << "Terminating render process for bad Mojo message: " << error;
InvokeBadMojoMessageCallbackForTesting(render_process_id, error);
mojo::debug::ScopedMessageErrorCrashKey error_key_value(error);
bad_message::ReceivedBadMessage(render_process_id,
bad_message::RPH_MOJO_PROCESS_ERROR);
}
void RenderProcessHostImpl::GetBrowserHistogram(
const std::string& name,
BrowserHistogramCallback callback) {
bool using_stats_collection_controller =
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kStatsCollectionController);
if (!using_stats_collection_controller) {
std::move(callback).Run(std::string());
return;
}
base::HistogramBase* histogram =
base::StatisticsRecorder::FindHistogram(name);
std::string histogram_json;
if (!histogram) {
histogram_json = "{}";
} else {
histogram->WriteJSON(&histogram_json, base::JSON_VERBOSITY_LEVEL_FULL);
}
std::move(callback).Run(histogram_json);
}
void RenderProcessHostImpl::CancelProcessShutdownDelay(
const SiteInfo& site_info) {
if (AreRefCountsDisabled())
return;
if (base::FeatureList::IsEnabled(features::kSubframeShutdownDelay) &&
ShouldTrackProcessForSite(site_info)) {
SiteProcessCountTracker* delayed_shutdown_tracker =
SiteProcessCountTracker::GetInstance(
GetBrowserContext(),
content::kDelayedShutdownSiteProcessCountTrackerKey);
if (delayed_shutdown_tracker->Contains(site_info, GetID()))
delayed_shutdown_tracker->DecrementSiteProcessCount(site_info, GetID());
}
CHECK(!are_ref_counts_disabled_);
CHECK_GT(shutdown_delay_ref_count_, 0);
shutdown_delay_ref_count_--;
if (AreAllRefCountsZero())
Cleanup();
}
void RenderProcessHostImpl::StopTrackingProcessForShutdownDelay() {
if (!base::FeatureList::IsEnabled(features::kSubframeShutdownDelay))
return;
SiteProcessCountTracker* delayed_shutdown_tracker =
SiteProcessCountTracker::GetInstance(
GetBrowserContext(),
content::kDelayedShutdownSiteProcessCountTrackerKey);
delayed_shutdown_tracker->ClearProcessForAllSites(GetID());
}
void RenderProcessHostImpl::BindTracedProcess(
mojo::PendingReceiver<tracing::mojom::TracedProcess> receiver) {
BindReceiver(std::move(receiver));
}
void RenderProcessHostImpl::OnBindHostReceiver(
mojo::GenericPendingReceiver receiver) {
#if BUILDFLAG(IS_ANDROID)
if (auto r = receiver.As<blink::mojom::AndroidFontLookup>()) {
content::GetGlobalJavaInterfaces()->GetInterface(std::move(r));
return;
}
#endif
GetContentClient()->browser()->BindHostReceiverForRenderer(
this, std::move(receiver));
}
#if defined(OHOS_LOGGER_REPORT)
void RenderProcessHostImpl::ReportRendererLog(int policy,
const std::string& msg) {
ohos::logger::ReportRendererLog(policy, msg);
}
#endif
void RenderProcessHost::InterceptBindHostReceiverForTesting(
BindHostReceiverInterceptor callback) {
GetBindHostReceiverInterceptor() = std::move(callback);
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void RenderProcessHostImpl::ProvideStatusFileForRenderer() {
base::ScopedAllowBlocking allow_blocking;
base::FilePath proc_pid_dir =
base::FilePath("/proc").Append(base::NumberToString(GetProcess().Pid()));
base::File status_file(
proc_pid_dir.Append("status"),
base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
base::File statm_file(
proc_pid_dir.Append("statm"),
base::File::Flags::FLAG_OPEN | base::File::Flags::FLAG_READ);
if (!status_file.IsValid() || !statm_file.IsValid())
return;
mojo::Remote<blink::mojom::MemoryUsageMonitorLinux> monitor;
BindReceiver(monitor.BindNewPipeAndPassReceiver());
monitor->SetProcFiles(statm_file.Duplicate(), status_file.Duplicate());
}
#endif
void RenderProcessHostImpl::ProvideSwapFileForRenderer() {
if (!blink::features::IsParkableStringsToDiskEnabled())
return;
if (GetBrowserContext()->IsOffTheRecord())
return;
mojo::Remote<blink::mojom::DiskAllocator> allocator;
BindReceiver(allocator.BindNewPipeAndPassReceiver());
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, {base::MayBlock()}, base::BindOnce([]() {
base::FilePath path;
if (!base::CreateTemporaryFile(&path))
return base::File();
int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ |
base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE;
flags = base::File::AddFlagsForPassingToUntrustedProcess(flags);
return base::File(base::FilePath(path), flags);
}),
base::BindOnce(
[](mojo::Remote<blink::mojom::DiskAllocator> allocator,
base::File file) {
if (file.IsValid())
allocator->ProvideTemporaryFile(std::move(file));
},
std::move(allocator)));
}
#if BUILDFLAG(IS_ANDROID)
void RenderProcessHostImpl::NotifyMemoryPressureToRenderer(
base::MemoryPressureListener::MemoryPressureLevel level) {
child_process_->OnMemoryPressure(level);
}
void RenderProcessHostImpl::SetAttributionReportingSupport(
network::mojom::AttributionSupport attribution_support) {
GetRendererInterface()->SetAttributionReportingSupport(attribution_support);
}
#endif
#if defined(OHOS_RENDERER_ANR_DUMP)
void RenderProcessHostImpl::dumpCurrentJavaScriptStackInMainThread(
base::OnceCallback<void(const std::string&)> dump_callback) {
child_process_->dumpCurrentJavaScriptStackInMainThread(base::BindOnce(
[](base::OnceCallback<void(const std::string&)> callback,
const std::string& stack) { std::move(callback).Run(stack); },
std::move(dump_callback)));
}
void RenderProcessHostImpl::InvokeRenderCrashDump() {
child_process_->InvokeRenderCrashDump();
}
#endif
#ifdef OHOS_THEME_FONT
const base::FilePath::CharType kAppThemePathA[] =
FILE_PATH_LITERAL("/data/themes/a/app");
const base::FilePath::CharType kAppThemePathB[] =
FILE_PATH_LITERAL("/data/themes/b/app");
const base::FilePath::CharType kAppThemeFontsDirName[] =
FILE_PATH_LITERAL("fonts");
const base::FilePath::CharType kAppThemeFlagFileName[] =
FILE_PATH_LITERAL("flag");
const base::FilePath::CharType kAppThemeFontsManifest[] =
FILE_PATH_LITERAL("manifest.json");
std::unique_ptr<ThemeFont> RenderProcessHostImpl::g_theme_font_ = nullptr;
bool RenderProcessHostImpl::IsThemeFontValid() {
if (!g_theme_font_ || !base::PathExists(g_theme_font_->flag_path) ||
!base::PathExists(g_theme_font_->manifest_path) ||
!base::PathExists(g_theme_font_->font_path) ||
!g_theme_font_->font_file.IsValid()) {
return false;
}
return true;
}
ThemeFont* RenderProcessHostImpl::EnsureThemeFont() {
if (IsThemeFontValid()) {
return g_theme_font_.get();
}
g_theme_font_.reset();
base::FilePath theme_path(kAppThemePathA);
base::FilePath theme_font_path = theme_path.Append(kAppThemeFontsDirName);
if (!base::PathExists(
base::FilePath(kAppThemePathA).Append(kAppThemeFlagFileName))) {
if (!base::PathExists(
base::FilePath(kAppThemePathB).Append(kAppThemeFlagFileName))) {
LOG(DEBUG) << "[themefont] flag file occurs error";
return nullptr;
}
theme_path = base::FilePath(base::FilePath(kAppThemePathB));
theme_font_path = theme_path.Append(kAppThemeFontsDirName);
}
std::string input_json;
base::FilePath manifest_path(theme_font_path.Append(kAppThemeFontsManifest));
if (!base::PathExists(manifest_path) ||
!base::ReadFileToString(manifest_path, &input_json) ||
input_json.empty()) {
LOG(DEBUG) << "[themefont] manifest file occurs error";
return nullptr;
}
auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(input_json);
if (!parsed_json.has_value() || !parsed_json->is_dict()) {
LOG(ERROR) << "[themefont] manifest file occurs error:"
<< parsed_json.error().message;
return nullptr;
}
const base::Value::Dict& dict = parsed_json->GetDict();
const std::string* origin = dict.FindString("origin");
if (!origin || origin->empty()) {
LOG(ERROR) << "[themefont] manifest file has no origin tag";
return nullptr;
}
if (*origin != std::string("online")) {
LOG(DEBUG) << "[themefont] manifest file's origin tag is not online";
return nullptr;
}
const std::string* absolte_font_path = dict.FindString("ttfFileSrc");
if (!absolte_font_path || absolte_font_path->empty()) {
LOG(ERROR) << "[themefont] manifest file has no ttfFileSrc tag";
return nullptr;
}
base::FilePath font_path =
theme_font_path.Append(base::FilePath(*absolte_font_path).BaseName());
if (!base::PathExists(font_path)) {
LOG(ERROR) << "[themefont] font file not exist:" << font_path.value();
return nullptr;
}
base::File font_file(font_path,
base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!font_file.IsValid()) {
LOG(ERROR) << "[themefont] font file not valid";
return nullptr;
}
base::FilePath flag_path = theme_path.Append(kAppThemeFlagFileName);
g_theme_font_ = std::make_unique<ThemeFont>();
g_theme_font_->flag_path = flag_path;
g_theme_font_->manifest_path = manifest_path;
g_theme_font_->font_path = font_path;
g_theme_font_->font_file = std::move(font_file);
LOG(INFO) << "[themefont] valid font:" << font_path;
return g_theme_font_.get();
}
void RenderProcessHostImpl::OnThemeFontChange() {
if (auto* theme_font = EnsureThemeFont()) {
UpdateThemeFontFile(theme_font->font_file.Duplicate());
} else {
UpdateThemeFontFile(base::File());
}
}
void RenderProcessHostImpl::UpdateThemeFontFile(base::File theme_font_file) {
GetRendererInterface()->UpdateThemeFontFile(std::move(theme_font_file));
}
#endif
#if defined(OHOS_RENDER_PROCESS_SHARE)
RenderProcessHost* RenderProcessHostImpl::GetProcessForSharedToken(
const std::string& shared_render_process_token) {
SharedProcessTokenToProcessMap& processes = GetAllSharedProcessHosts();
auto process = processes.find(shared_render_process_token);
if (process == processes.end())
return nullptr;
return process->second;
}
void RenderProcessHostImpl::RegisteProcessForSharedToken(
const std::string& shared_render_process_token,
RenderProcessHost* renderProcessHost) {
GetAllSharedProcessHosts().emplace(shared_render_process_token,
renderProcessHost);
}
void RenderProcessHostImpl::RemoveFromSharedRenderProcessMap(
RenderProcessHost* renderProcessHost) {
SharedProcessTokenToProcessMap& processes = GetAllSharedProcessHosts();
if (processes.empty())
return;
auto iter = processes.begin();
for (; iter != processes.end(); ++iter) {
if (iter->second == renderProcessHost) {
processes.erase(iter);
break;
}
}
}
#endif
#ifdef OHOS_I18N
void RenderProcessHostImpl::NotifyLocaleChanged(
const std::string& update_locale) {
GetRendererInterface()->NotifyLocaleChanged(update_locale);
}
void RenderProcessHost::OnLocaleChangedToRenderer(
const std::string& update_locale) {
iterator iter(AllHostsIterator());
while (!iter.IsAtEnd()) {
RenderProcessHostImpl* host =
static_cast<RenderProcessHostImpl*>(iter.GetCurrentValue());
if (host && host->IsInitializedAndNotDead()) {
host->NotifyLocaleChanged(update_locale);
}
iter.Advance();
}
}
#endif
}