Chromium Code Reviews| Index: content/browser/renderer_host/render_process_host_impl.cc |
| diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc |
| index 8717e3e7d150ab6fcf7a9ed26736cbc1626a0b21..53e30ac10df2b0451c1bb8fa94a9c887670c3a35 100644 |
| --- a/content/browser/renderer_host/render_process_host_impl.cc |
| +++ b/content/browser/renderer_host/render_process_host_impl.cc |
| @@ -1,2570 +1,2516 @@ |
| -// Copyright 2012 The Chromium Authors. All rights reserved. |
| -// Use of this source code is governed by a BSD-style license that can be |
| -// found in the LICENSE file. |
| - |
| -// Represents the browser side of the browser <--> renderer communication |
| -// channel. There will be one RenderProcessHost per renderer process. |
| - |
| -#include "content/browser/renderer_host/render_process_host_impl.h" |
| - |
| -#include <algorithm> |
| -#include <limits> |
| -#include <vector> |
| - |
| -#include "base/base_switches.h" |
| -#include "base/bind.h" |
| -#include "base/bind_helpers.h" |
| -#include "base/callback.h" |
| -#include "base/command_line.h" |
| -#include "base/debug/dump_without_crashing.h" |
| -#include "base/files/file.h" |
| -#include "base/lazy_instance.h" |
| -#include "base/location.h" |
| -#include "base/logging.h" |
| -#include "base/metrics/field_trial.h" |
| -#include "base/metrics/histogram.h" |
| -#include "base/process/process_handle.h" |
| -#include "base/profiler/scoped_tracker.h" |
| -#include "base/rand_util.h" |
| -#include "base/single_thread_task_runner.h" |
| -#include "base/stl_util.h" |
| -#include "base/strings/string_number_conversions.h" |
| -#include "base/strings/string_util.h" |
| -#include "base/supports_user_data.h" |
| -#include "base/sys_info.h" |
| -#include "base/threading/thread.h" |
| -#include "base/threading/thread_restrictions.h" |
| -#include "base/trace_event/trace_event.h" |
| -#include "base/tracked_objects.h" |
| -#include "cc/base/switches.h" |
| -#include "components/tracing/tracing_switches.h" |
| -#include "content/browser/appcache/appcache_dispatcher_host.h" |
| -#include "content/browser/appcache/chrome_appcache_service.h" |
| -#include "content/browser/background_sync/background_sync_service_impl.h" |
| -#include "content/browser/bad_message.h" |
| -#include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| -#include "content/browser/browser_child_process_host_impl.h" |
| -#include "content/browser/browser_main.h" |
| -#include "content/browser/browser_main_loop.h" |
| -#include "content/browser/browser_plugin/browser_plugin_message_filter.h" |
| -#include "content/browser/cache_storage/cache_storage_context_impl.h" |
| -#include "content/browser/cache_storage/cache_storage_dispatcher_host.h" |
| -#include "content/browser/child_process_security_policy_impl.h" |
| -#include "content/browser/device_sensors/device_light_message_filter.h" |
| -#include "content/browser/device_sensors/device_motion_message_filter.h" |
| -#include "content/browser/device_sensors/device_orientation_message_filter.h" |
| -#include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
| -#include "content/browser/dom_storage/dom_storage_message_filter.h" |
| -#include "content/browser/download/mhtml_generation_manager.h" |
| -#include "content/browser/fileapi/chrome_blob_storage_context.h" |
| -#include "content/browser/fileapi/fileapi_message_filter.h" |
| -#include "content/browser/frame_host/render_frame_message_filter.h" |
| -#include "content/browser/geofencing/geofencing_dispatcher_host.h" |
| -#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" |
| -#include "content/browser/gpu/compositor_util.h" |
| -#include "content/browser/gpu/gpu_data_manager_impl.h" |
| -#include "content/browser/gpu/gpu_process_host.h" |
| -#include "content/browser/gpu/shader_disk_cache.h" |
| -#include "content/browser/histogram_message_filter.h" |
| -#include "content/browser/indexed_db/indexed_db_context_impl.h" |
| -#include "content/browser/indexed_db/indexed_db_dispatcher_host.h" |
| -#include "content/browser/loader/resource_message_filter.h" |
| -#include "content/browser/loader/resource_scheduler_filter.h" |
| -#include "content/browser/media/capture/audio_mirroring_manager.h" |
| -#include "content/browser/media/media_internals.h" |
| -#include "content/browser/media/midi_host.h" |
| -#include "content/browser/memory/memory_message_filter.h" |
| -#include "content/browser/message_port_message_filter.h" |
| -#include "content/browser/mime_registry_message_filter.h" |
| -#include "content/browser/mojo/mojo_application_host.h" |
| -#include "content/browser/navigator_connect/service_port_service_impl.h" |
| -#include "content/browser/notifications/notification_message_filter.h" |
| -#include "content/browser/permissions/permission_service_context.h" |
| -#include "content/browser/permissions/permission_service_impl.h" |
| -#include "content/browser/profiler_message_filter.h" |
| -#include "content/browser/push_messaging/push_messaging_message_filter.h" |
| -#include "content/browser/quota_dispatcher_host.h" |
| -#include "content/browser/renderer_host/clipboard_message_filter.h" |
| -#include "content/browser/renderer_host/database_message_filter.h" |
| -#include "content/browser/renderer_host/file_utilities_message_filter.h" |
| -#include "content/browser/renderer_host/gamepad_browser_message_filter.h" |
| -#include "content/browser/renderer_host/gpu_message_filter.h" |
| -#include "content/browser/renderer_host/media/audio_input_renderer_host.h" |
| -#include "content/browser/renderer_host/media/audio_renderer_host.h" |
| -#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" |
| -#include "content/browser/renderer_host/media/peer_connection_tracker_host.h" |
| -#include "content/browser/renderer_host/media/video_capture_host.h" |
| -#include "content/browser/renderer_host/memory_benchmark_message_filter.h" |
| -#include "content/browser/renderer_host/pepper/pepper_message_filter.h" |
| -#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h" |
| -#include "content/browser/renderer_host/render_message_filter.h" |
| -#include "content/browser/renderer_host/render_view_host_delegate.h" |
| -#include "content/browser/renderer_host/render_view_host_impl.h" |
| -#include "content/browser/renderer_host/render_widget_helper.h" |
| -#include "content/browser/renderer_host/render_widget_host_impl.h" |
| -#include "content/browser/renderer_host/text_input_client_message_filter.h" |
| -#include "content/browser/renderer_host/websocket_dispatcher_host.h" |
| -#include "content/browser/resolve_proxy_msg_helper.h" |
| -#include "content/browser/service_worker/service_worker_context_wrapper.h" |
| -#include "content/browser/service_worker/service_worker_dispatcher_host.h" |
| -#include "content/browser/shared_worker/shared_worker_message_filter.h" |
| -#include "content/browser/shared_worker/worker_storage_partition.h" |
| -#include "content/browser/speech/speech_recognition_dispatcher_host.h" |
| -#include "content/browser/storage_partition_impl.h" |
| -#include "content/browser/streams/stream_context.h" |
| -#include "content/browser/tracing/trace_message_filter.h" |
| -#include "content/browser/webui/web_ui_controller_factory_registry.h" |
| -#include "content/common/child_process_host_impl.h" |
| -#include "content/common/child_process_messages.h" |
| -#include "content/common/content_switches_internal.h" |
| -#include "content/common/frame_messages.h" |
| -#include "content/common/gpu/gpu_messages.h" |
| -#include "content/common/in_process_child_thread_params.h" |
| -#include "content/common/mojo/channel_init.h" |
| -#include "content/common/mojo/mojo_messages.h" |
| -#include "content/common/render_process_messages.h" |
| -#include "content/common/resource_messages.h" |
| -#include "content/common/site_isolation_policy.h" |
| -#include "content/common/view_messages.h" |
| -#include "content/public/browser/browser_context.h" |
| -#include "content/public/browser/content_browser_client.h" |
| -#include "content/public/browser/navigator_connect_context.h" |
| -#include "content/public/browser/notification_service.h" |
| -#include "content/public/browser/notification_types.h" |
| -#include "content/public/browser/render_process_host_factory.h" |
| -#include "content/public/browser/render_process_host_observer.h" |
| -#include "content/public/browser/render_widget_host.h" |
| -#include "content/public/browser/render_widget_host_iterator.h" |
| -#include "content/public/browser/render_widget_host_view_frame_subscriber.h" |
| -#include "content/public/browser/resource_context.h" |
| -#include "content/public/browser/user_metrics.h" |
| -#include "content/public/browser/worker_service.h" |
| -#include "content/public/common/child_process_host.h" |
| -#include "content/public/common/content_constants.h" |
| -#include "content/public/common/content_switches.h" |
| -#include "content/public/common/mojo_channel_switches.h" |
| -#include "content/public/common/process_type.h" |
| -#include "content/public/common/resource_type.h" |
| -#include "content/public/common/result_codes.h" |
| -#include "content/public/common/sandboxed_process_launcher_delegate.h" |
| -#include "content/public/common/url_constants.h" |
| -#include "device/battery/battery_monitor_impl.h" |
| -#include "device/vibration/vibration_manager_impl.h" |
| -#include "gpu/GLES2/gl2extchromium.h" |
| -#include "gpu/command_buffer/client/gpu_switches.h" |
| -#include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| -#include "gpu/command_buffer/service/gpu_switches.h" |
| -#include "ipc/ipc_channel.h" |
| -#include "ipc/ipc_logging.h" |
| -#include "ipc/ipc_switches.h" |
| -#include "ipc/mojo/ipc_channel_mojo.h" |
| -#include "media/base/media_switches.h" |
| -#include "net/url_request/url_request_context_getter.h" |
| -#include "ppapi/shared_impl/ppapi_switches.h" |
| -#include "storage/browser/fileapi/sandbox_file_system_backend.h" |
| -#include "third_party/icu/source/common/unicode/unistr.h" |
| -#include "third_party/icu/source/i18n/unicode/timezone.h" |
| -#include "third_party/skia/include/core/SkBitmap.h" |
| -#include "ui/base/ui_base_switches.h" |
| -#include "ui/events/event_switches.h" |
| -#include "ui/gfx/switches.h" |
| -#include "ui/gl/gl_switches.h" |
| -#include "ui/gl/gpu_switching_manager.h" |
| -#include "ui/native_theme/native_theme_switches.h" |
| - |
| -#if defined(OS_ANDROID) |
| -#include "content/browser/android/child_process_launcher_android.h" |
| -#include "content/browser/media/android/browser_demuxer_android.h" |
| -#include "content/browser/mojo/service_registrar_android.h" |
| -#include "content/browser/screen_orientation/screen_orientation_message_filter_android.h" |
| -#endif |
| - |
| -#if defined(OS_WIN) |
| -#include "base/win/scoped_com_initializer.h" |
| -#include "base/win/windows_version.h" |
| -#include "content/common/font_cache_dispatcher_win.h" |
| -#include "content/common/sandbox_win.h" |
| -#include "sandbox/win/src/sandbox_policy.h" |
| -#include "ui/gfx/win/dpi.h" |
| -#endif |
| - |
| -#if defined(OS_MACOSX) && !defined(OS_IOS) |
| -#include "content/browser/bootstrap_sandbox_manager_mac.h" |
| -#include "content/browser/browser_io_surface_manager_mac.h" |
| -#endif |
| - |
| -#if defined(USE_OZONE) |
| -#include "ui/ozone/public/client_native_pixmap_factory.h" |
| -#include "ui/ozone/public/ozone_platform.h" |
| -#include "ui/ozone/public/ozone_switches.h" |
| -#endif |
| - |
| -#if defined(ENABLE_BROWSER_CDMS) |
| -#include "content/browser/media/cdm/browser_cdm_manager.h" |
| -#endif |
| - |
| -#if defined(ENABLE_PLUGINS) |
| -#include "content/browser/plugin_service_impl.h" |
| -#endif |
| - |
| -#if defined(ENABLE_WEBRTC) |
| -#include "content/browser/media/webrtc_internals.h" |
| -#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h" |
| -#include "content/browser/renderer_host/media/webrtc_identity_service_host.h" |
| -#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" |
| -#include "content/common/media/aec_dump_messages.h" |
| -#include "content/common/media/media_stream_messages.h" |
| -#endif |
| - |
| -#if defined(OS_WIN) |
| -#define IntToStringType base::IntToString16 |
| -#else |
| -#define IntToStringType base::IntToString |
| -#endif |
| - |
| -namespace content { |
| -namespace { |
| - |
| -const char kSiteProcessMapKeyName[] = "content_site_process_map"; |
| - |
| -#ifdef ENABLE_WEBRTC |
| -const base::FilePath::CharType kAecDumpFileNameAddition[] = |
| - FILE_PATH_LITERAL("aec_dump"); |
| -#endif |
| - |
| -void CacheShaderInfo(int32 id, base::FilePath path) { |
| - ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path); |
| -} |
| - |
| -void RemoveShaderInfo(int32 id) { |
| - ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id); |
| -} |
| - |
| -net::URLRequestContext* GetRequestContext( |
| - scoped_refptr<net::URLRequestContextGetter> request_context, |
| - scoped_refptr<net::URLRequestContextGetter> media_request_context, |
| - ResourceType resource_type) { |
| - // If the request has resource type of RESOURCE_TYPE_MEDIA, we use a request |
| - // context specific to media for handling it because these resources have |
| - // specific needs for caching. |
| - if (resource_type == RESOURCE_TYPE_MEDIA) |
| - return media_request_context->GetURLRequestContext(); |
| - return request_context->GetURLRequestContext(); |
| -} |
| - |
| -void GetContexts( |
| - ResourceContext* resource_context, |
| - scoped_refptr<net::URLRequestContextGetter> request_context, |
| - scoped_refptr<net::URLRequestContextGetter> media_request_context, |
| - const ResourceHostMsg_Request& request, |
| - ResourceContext** resource_context_out, |
| - net::URLRequestContext** request_context_out) { |
| - *resource_context_out = resource_context; |
| - *request_context_out = |
| - GetRequestContext(request_context, media_request_context, |
| - request.resource_type); |
| -} |
| - |
| -#if defined(ENABLE_WEBRTC) |
| - |
| -// Allow us to only run the trial in the first renderer. |
| -bool has_done_stun_trials = false; |
| - |
| -// Creates a file used for diagnostic echo canceller recordings for handing |
| -// over to the renderer. |
| -IPC::PlatformFileForTransit CreateAecDumpFileForProcess( |
| - base::FilePath file_path, |
| - base::ProcessHandle process) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| - base::File dump_file(file_path, |
| - base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND); |
| - if (!dump_file.IsValid()) { |
| - VLOG(1) << "Could not open AEC dump file, error=" << |
| - dump_file.error_details(); |
| - return IPC::InvalidPlatformFileForTransit(); |
| - } |
| - return IPC::TakeFileHandleForProcess(dump_file.Pass(), process); |
| -} |
| - |
| -// Does nothing. Just to avoid races between enable and disable. |
| -void DisableAecDumpOnFileThread() { |
| - DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| -} |
| -#endif |
| - |
| -// the global list of all renderer processes |
| -base::LazyInstance<IDMap<RenderProcessHost> >::Leaky |
| - g_all_hosts = LAZY_INSTANCE_INITIALIZER; |
| - |
| -// Map of site to process, to ensure we only have one RenderProcessHost per |
| -// site in process-per-site mode. Each map is specific to a BrowserContext. |
| -class SiteProcessMap : public base::SupportsUserData::Data { |
| - public: |
| - typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap; |
| - SiteProcessMap() {} |
| - |
| - void RegisterProcess(const std::string& site, RenderProcessHost* process) { |
| - map_[site] = process; |
| - } |
| - |
| - RenderProcessHost* FindProcess(const std::string& site) { |
| - SiteToProcessMap::iterator i = map_.find(site); |
| - if (i != map_.end()) |
| - return i->second; |
| - return NULL; |
| - } |
| - |
| - void RemoveProcess(RenderProcessHost* host) { |
| - // Find all instances of this process in the map, then separately remove |
| - // them. |
| - std::set<std::string> sites; |
| - for (SiteToProcessMap::const_iterator i = map_.begin(); |
| - i != map_.end(); |
| - i++) { |
| - if (i->second == host) |
| - sites.insert(i->first); |
| - } |
| - for (std::set<std::string>::iterator i = sites.begin(); |
| - i != sites.end(); |
| - i++) { |
| - SiteToProcessMap::iterator iter = map_.find(*i); |
| - if (iter != map_.end()) { |
| - DCHECK_EQ(iter->second, host); |
| - map_.erase(iter); |
| - } |
| - } |
| - } |
| - |
| - private: |
| - SiteToProcessMap map_; |
| -}; |
| - |
| -// Find the SiteProcessMap specific to the given context. |
| -SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) { |
| - DCHECK(context); |
| - SiteProcessMap* map = static_cast<SiteProcessMap*>( |
| - context->GetUserData(kSiteProcessMapKeyName)); |
| - if (!map) { |
| - map = new SiteProcessMap(); |
| - context->SetUserData(kSiteProcessMapKeyName, map); |
| - } |
| - return map; |
| -} |
| - |
| -// NOTE: changes to this class need to be reviewed by the security team. |
| -class RendererSandboxedProcessLauncherDelegate |
| - : public SandboxedProcessLauncherDelegate { |
| - public: |
| - explicit RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel) |
| -#if defined(OS_POSIX) |
| - : ipc_fd_(channel->TakeClientFileDescriptor()) |
| -#endif // OS_POSIX |
| - {} |
| - |
| - ~RendererSandboxedProcessLauncherDelegate() override {} |
| - |
| -#if defined(OS_WIN) |
| - void PreSpawnTarget(sandbox::TargetPolicy* policy, bool* success) override { |
| - AddBaseHandleClosePolicy(policy); |
| - |
| - const base::string16& sid = |
| - GetContentClient()->browser()->GetAppContainerSidForSandboxType( |
| - GetSandboxType()); |
| - if (!sid.empty()) |
| - AddAppContainerPolicy(policy, sid.c_str()); |
| - |
| - GetContentClient()->browser()->PreSpawnRenderer(policy, success); |
| - } |
| - |
| -#elif defined(OS_POSIX) |
| - bool ShouldUseZygote() override { |
| - const base::CommandLine& browser_command_line = |
| - *base::CommandLine::ForCurrentProcess(); |
| - base::CommandLine::StringType renderer_prefix = |
| - browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); |
| - return renderer_prefix.empty(); |
| - } |
| - base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); } |
| -#endif // OS_WIN |
| - |
| - SandboxType GetSandboxType() override { |
| - return SANDBOX_TYPE_RENDERER; |
| - } |
| - |
| - private: |
| -#if defined(OS_POSIX) |
| - base::ScopedFD ipc_fd_; |
| -#endif // OS_POSIX |
| -}; |
| - |
| -const char kSessionStorageHolderKey[] = "kSessionStorageHolderKey"; |
| - |
| -class SessionStorageHolder : public base::SupportsUserData::Data { |
| - public: |
| - SessionStorageHolder() {} |
| - ~SessionStorageHolder() override {} |
| - |
| - void Hold(const SessionStorageNamespaceMap& sessions, int view_route_id) { |
| - session_storage_namespaces_awaiting_close_[view_route_id] = sessions; |
| - } |
| - |
| - void Release(int old_route_id) { |
| - session_storage_namespaces_awaiting_close_.erase(old_route_id); |
| - } |
| - |
| - private: |
| - std::map<int, SessionStorageNamespaceMap > |
| - session_storage_namespaces_awaiting_close_; |
| - DISALLOW_COPY_AND_ASSIGN(SessionStorageHolder); |
| -}; |
| - |
| -std::string UintVectorToString(const std::vector<unsigned>& vector) { |
| - std::string str; |
| - for (auto it : vector) { |
| - if (!str.empty()) |
| - str += ","; |
| - str += base::UintToString(it); |
| - } |
| - return str; |
| -} |
| - |
| -} // namespace |
| - |
| -RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
| - |
| -base::MessageLoop* g_in_process_thread; |
| - |
| -base::MessageLoop* |
| - RenderProcessHostImpl::GetInProcessRendererThreadForTesting() { |
| - return g_in_process_thread; |
| -} |
| - |
| -// Stores the maximum number of renderer processes the content module can |
| -// create. |
| -static size_t g_max_renderer_count_override = 0; |
| - |
| -// static |
| -size_t RenderProcessHost::GetMaxRendererProcessCount() { |
| - if (g_max_renderer_count_override) |
| - return g_max_renderer_count_override; |
| - |
| -#if defined(OS_ANDROID) |
| - // On Android we don't maintain a limit of renderer process hosts - we are |
| - // happy with keeping a lot of these, as long as the number of live renderer |
| - // processes remains reasonable, and on Android the OS takes care of that. |
| - return std::numeric_limits<size_t>::max(); |
| -#endif |
| - |
| - // On other platforms, we calculate the maximum number of renderer process |
| - // hosts according to the amount of installed memory as reported by the OS. |
| - // The calculation assumes that you want the renderers to use half of the |
| - // installed RAM and assuming that each WebContents uses ~40MB. If you modify |
| - // this assumption, you need to adjust the ThirtyFourTabs test to match the |
| - // expected number of processes. |
| - // |
| - // With the given amounts of installed memory below on a 32-bit CPU, the |
| - // maximum renderer count will roughly be as follows: |
| - // |
| - // 128 MB -> 3 |
| - // 512 MB -> 6 |
| - // 1024 MB -> 12 |
| - // 4096 MB -> 51 |
| - // 16384 MB -> 82 (kMaxRendererProcessCount) |
| - |
| - static size_t max_count = 0; |
| - if (!max_count) { |
| - const size_t kEstimatedWebContentsMemoryUsage = |
| -#if defined(ARCH_CPU_64_BITS) |
| - 60; // In MB |
| -#else |
| - 40; // In MB |
| -#endif |
| - max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2; |
| - max_count /= kEstimatedWebContentsMemoryUsage; |
| - |
| - const size_t kMinRendererProcessCount = 3; |
| - max_count = std::max(max_count, kMinRendererProcessCount); |
| - max_count = std::min(max_count, kMaxRendererProcessCount); |
| - } |
| - return max_count; |
| -} |
| - |
| -// static |
| -bool g_run_renderer_in_process_ = false; |
| - |
| -// static |
| -void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { |
| - g_max_renderer_count_override = count; |
| -} |
| - |
| -RenderProcessHostImpl::RenderProcessHostImpl( |
| - BrowserContext* browser_context, |
| - StoragePartitionImpl* storage_partition_impl, |
| - bool is_for_guests_only) |
| - : fast_shutdown_started_(false), |
| - deleting_soon_(false), |
| -#ifndef NDEBUG |
| - is_self_deleted_(false), |
| -#endif |
| - pending_views_(0), |
| - mojo_application_host_(new MojoApplicationHost), |
| - visible_widgets_(0), |
| - backgrounded_(true), |
| - is_initialized_(false), |
| - id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), |
| - browser_context_(browser_context), |
| - storage_partition_impl_(storage_partition_impl), |
| - sudden_termination_allowed_(true), |
| - ignore_input_events_(false), |
| - is_for_guests_only_(is_for_guests_only), |
| - gpu_observer_registered_(false), |
| - delayed_cleanup_needed_(false), |
| - within_process_died_observer_(false), |
| - power_monitor_broadcaster_(this), |
| - worker_ref_count_(0), |
| - max_worker_count_(0), |
| - permission_service_context_(new PermissionServiceContext(this)), |
| - pending_valuebuffer_state_(new gpu::ValueStateMap()), |
| - subscribe_uniform_enabled_(false), |
| - weak_factory_(this) { |
| - widget_helper_ = new RenderWidgetHelper(); |
| - |
| - ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID()); |
| - |
| - CHECK(!BrowserMainRunner::ExitedMainMessageLoop()); |
| - RegisterHost(GetID(), this); |
| - g_all_hosts.Get().set_check_on_null_data(true); |
| - // Initialize |child_process_activity_time_| to a reasonable value. |
| - mark_child_process_activity_time(); |
| - |
| - if (!GetBrowserContext()->IsOffTheRecord() && |
| - !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kDisableGpuShaderDiskCache)) { |
| - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| - base::Bind(&CacheShaderInfo, GetID(), |
| - storage_partition_impl_->GetPath())); |
| - } |
| - subscribe_uniform_enabled_ = |
| - base::CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kEnableSubscribeUniformExtension); |
| - |
| -#if defined(OS_MACOSX) |
| - if (BootstrapSandboxManager::ShouldEnable()) |
|
gab
2015/09/30 13:33:31
Hmm why are we removing this?
sebsg
2015/09/30 18:26:43
Good catch, it's a case of ad merging. Thanks.
|
| - AddObserver(BootstrapSandboxManager::GetInstance()); |
| -#endif |
| - |
| - // Note: When we create the RenderProcessHostImpl, it's technically |
| - // backgrounded, because it has no visible listeners. But the process |
| - // doesn't actually exist yet, so we'll Background it later, after |
| - // creation. |
| -} |
| - |
| -// static |
| -void RenderProcessHostImpl::ShutDownInProcessRenderer() { |
| - DCHECK(g_run_renderer_in_process_); |
| - |
| - switch (g_all_hosts.Pointer()->size()) { |
| - case 0: |
| - return; |
| - case 1: { |
| - RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>( |
| - AllHostsIterator().GetCurrentValue()); |
| - FOR_EACH_OBSERVER(RenderProcessHostObserver, |
| - host->observers_, |
| - 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; |
| -} |
| - |
| -RenderProcessHostImpl::~RenderProcessHostImpl() { |
| -#ifndef NDEBUG |
| - DCHECK(is_self_deleted_) |
| - << "RenderProcessHostImpl is destroyed by something other than itself"; |
| -#endif |
| - |
| - // Make sure to clean up the in-process renderer before the channel, otherwise |
| - // it may still run and have its IPCs fail, causing asserts. |
| - in_process_renderer_.reset(); |
| - |
| - ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID()); |
| - |
| - if (gpu_observer_registered_) { |
| - ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this); |
| - gpu_observer_registered_ = false; |
| - } |
| - |
| - // We may have some unsent messages at this point, but that's OK. |
| - channel_.reset(); |
| - while (!queued_messages_.empty()) { |
| - delete queued_messages_.front(); |
| - queued_messages_.pop(); |
| - } |
| - |
| - UnregisterHost(GetID()); |
| - |
| - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kDisableGpuShaderDiskCache)) { |
| - BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| - base::Bind(&RemoveShaderInfo, GetID())); |
| - } |
| -} |
| - |
| -void RenderProcessHostImpl::EnableSendQueue() { |
| - is_initialized_ = false; |
| -} |
| - |
| -bool RenderProcessHostImpl::Init() { |
| - // calling Init() more than once does nothing, this makes it more convenient |
| - // for the view host which may not be sure in some cases |
| - if (channel_) |
| - return true; |
| - |
| - base::CommandLine::StringType renderer_prefix; |
| - // A command prefix is something prepended to the command line of the spawned |
| - // process. |
| - const base::CommandLine& browser_command_line = |
| - *base::CommandLine::ForCurrentProcess(); |
| - renderer_prefix = |
| - browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); |
| - |
| -#if defined(OS_LINUX) |
| - int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : |
| - ChildProcessHost::CHILD_NORMAL; |
| -#else |
| - int flags = ChildProcessHost::CHILD_NORMAL; |
| -#endif |
| - |
| - // Find the renderer before creating the channel so if this fails early we |
| - // return without creating the channel. |
| - base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags); |
| - if (renderer_path.empty()) |
| - return false; |
| - |
| - // Setup the IPC channel. |
| - const std::string channel_id = |
| - IPC::Channel::GenerateVerifiedChannelID(std::string()); |
| - channel_ = CreateChannelProxy(channel_id); |
| - |
| - // Setup the Mojo channel. |
| - mojo_application_host_->Init(); |
| - |
| - // Call the embedder first so that their IPC filters have priority. |
| - GetContentClient()->browser()->RenderProcessWillLaunch(this); |
| - |
| - CreateMessageFilters(); |
| - RegisterMojoServices(); |
| - |
| - if (run_renderer_in_process()) { |
| - DCHECK(g_renderer_main_thread_factory); |
| - // Crank up a thread and run the initialization there. With the way that |
| - // messages flow between the browser and renderer, this thread is required |
| - // to prevent a deadlock in single-process mode. Since the primordial |
| - // thread in the renderer process runs the WebKit code and can sometimes |
| - // make blocking calls to the UI thread (i.e. this thread), they need to run |
| - // on separate threads. |
| - in_process_renderer_.reset( |
| - g_renderer_main_thread_factory(InProcessChildThreadParams( |
| - channel_id, BrowserThread::UnsafeGetMessageLoopForThread( |
| - BrowserThread::IO)->task_runner()))); |
| - |
| - base::Thread::Options options; |
| -#if defined(OS_WIN) && !defined(OS_MACOSX) |
| - // In-process plugins require this to be a UI message loop. |
| - options.message_loop_type = base::MessageLoop::TYPE_UI; |
| -#else |
| - // We can't have multiple UI loops on Linux and Android, so we don't support |
| - // in-process plugins. |
| - options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; |
| -#endif |
| - |
| - // As for execution sequence, this callback should have no any dependency |
| - // on starting in-process-render-thread. |
| - // So put it here to trigger ChannelMojo initialization earlier to enable |
| - // in-process-render-thread using ChannelMojo there. |
| - OnProcessLaunched(); // Fake a callback that the process is ready. |
| - |
| - in_process_renderer_->StartWithOptions(options); |
| - |
| - g_in_process_thread = in_process_renderer_->message_loop(); |
| - |
| - } else { |
| - // Build command line for renderer. We call AppendRendererCommandLine() |
| - // first so the process type argument will appear first. |
| - base::CommandLine* cmd_line = new base::CommandLine(renderer_path); |
| - if (!renderer_prefix.empty()) |
| - cmd_line->PrependWrapper(renderer_prefix); |
| - AppendRendererCommandLine(cmd_line); |
| - cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
| - |
| - // Spawn the child process asynchronously to avoid blocking the UI thread. |
| - // As long as there's no renderer prefix, we can use the zygote process |
| - // at this stage. |
| - child_process_launcher_.reset(new ChildProcessLauncher( |
| - new RendererSandboxedProcessLauncherDelegate(channel_.get()), |
| - cmd_line, |
| - GetID(), |
| - this)); |
| - |
| - fast_shutdown_started_ = false; |
| - } |
| - |
| - if (!gpu_observer_registered_) { |
| - gpu_observer_registered_ = true; |
| - ui::GpuSwitchingManager::GetInstance()->AddObserver(this); |
| - } |
| - |
| - power_monitor_broadcaster_.Init(); |
| - |
| - is_initialized_ = true; |
| - init_time_ = base::TimeTicks::Now(); |
| - return true; |
| -} |
| - |
| -scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy( |
| - const std::string& channel_id) { |
| - scoped_refptr<base::SingleThreadTaskRunner> runner = |
| - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); |
| - scoped_refptr<base::SequencedTaskRunner> mojo_task_runner = |
| - BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) |
| - ->task_runner(); |
| - if (ShouldUseMojoChannel()) { |
| - VLOG(1) << "Mojo Channel is enabled on host"; |
| - |
| - return IPC::ChannelProxy::Create( |
| - IPC::ChannelMojo::CreateServerFactory(mojo_task_runner, channel_id), |
| - this, runner.get()); |
| - } |
| - |
| - return IPC::ChannelProxy::Create(channel_id, IPC::Channel::MODE_SERVER, this, |
| - runner.get()); |
| -} |
| - |
| -void RenderProcessHostImpl::CreateMessageFilters() { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - const base::CommandLine& browser_command_line = |
| - *base::CommandLine::ForCurrentProcess(); |
| - AddFilter(new ResourceSchedulerFilter(GetID())); |
| - MediaInternals* media_internals = MediaInternals::GetInstance(); |
| - media::AudioManager* audio_manager = |
| - BrowserMainLoop::GetInstance()->audio_manager(); |
| - // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages |
| - // from guests. |
| - scoped_refptr<BrowserPluginMessageFilter> bp_message_filter( |
| - new BrowserPluginMessageFilter(GetID())); |
| - AddFilter(bp_message_filter.get()); |
| - |
| - scoped_refptr<RenderMessageFilter> render_message_filter( |
| - new RenderMessageFilter( |
| - GetID(), |
| - GetBrowserContext(), |
| - GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), |
| - widget_helper_.get(), |
| - audio_manager, |
| - media_internals, |
| - storage_partition_impl_->GetDOMStorageContext())); |
| - AddFilter(render_message_filter.get()); |
| - AddFilter(new RenderFrameMessageFilter( |
| - GetID(), |
| -#if defined(ENABLE_PLUGINS) |
| - PluginServiceImpl::GetInstance(), |
| -#else |
| - nullptr, |
| -#endif |
| - GetBrowserContext(), |
| - GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), |
| - widget_helper_.get())); |
| - BrowserContext* browser_context = GetBrowserContext(); |
| - ResourceContext* resource_context = browser_context->GetResourceContext(); |
| - |
| - scoped_refptr<net::URLRequestContextGetter> request_context( |
| - browser_context->GetRequestContextForRenderProcess(GetID())); |
| - scoped_refptr<net::URLRequestContextGetter> media_request_context( |
| - browser_context->GetMediaRequestContextForRenderProcess(GetID())); |
| - |
| - ResourceMessageFilter::GetContextsCallback get_contexts_callback( |
| - base::Bind(&GetContexts, browser_context->GetResourceContext(), |
| - request_context, media_request_context)); |
| - |
| - ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter( |
| - GetID(), PROCESS_TYPE_RENDERER, |
| - storage_partition_impl_->GetAppCacheService(), |
| - ChromeBlobStorageContext::GetFor(browser_context), |
| - storage_partition_impl_->GetFileSystemContext(), |
| - storage_partition_impl_->GetServiceWorkerContext(), |
| - storage_partition_impl_->GetHostZoomLevelContext(), |
| - get_contexts_callback); |
| - |
| - AddFilter(resource_message_filter); |
| - MediaStreamManager* media_stream_manager = |
| - BrowserMainLoop::GetInstance()->media_stream_manager(); |
| - // The AudioInputRendererHost and AudioRendererHost needs to be available for |
| - // lookup, so it's stashed in a member variable. |
| - audio_input_renderer_host_ = new AudioInputRendererHost( |
| - GetID(), |
| - base::GetProcId(GetHandle()), |
| - audio_manager, |
| - media_stream_manager, |
| - AudioMirroringManager::GetInstance(), |
| - BrowserMainLoop::GetInstance()->user_input_monitor()); |
| - AddFilter(audio_input_renderer_host_.get()); |
| - audio_renderer_host_ = new AudioRendererHost( |
| - GetID(), |
| - audio_manager, |
| - AudioMirroringManager::GetInstance(), |
| - media_internals, |
| - media_stream_manager, |
| - browser_context->GetResourceContext()->GetMediaDeviceIDSalt()); |
| - AddFilter(audio_renderer_host_.get()); |
| - AddFilter( |
| - new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager())); |
| - AddFilter(new VideoCaptureHost(media_stream_manager)); |
| - AddFilter(new AppCacheDispatcherHost( |
| - storage_partition_impl_->GetAppCacheService(), |
| - GetID())); |
| - AddFilter(new ClipboardMessageFilter); |
| - AddFilter(new DOMStorageMessageFilter( |
| - storage_partition_impl_->GetDOMStorageContext())); |
| - AddFilter(new IndexedDBDispatcherHost( |
| - GetID(), |
| - storage_partition_impl_->GetURLRequestContext(), |
| - storage_partition_impl_->GetIndexedDBContext(), |
| - ChromeBlobStorageContext::GetFor(browser_context))); |
| - |
| - gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get()); |
| - AddFilter(gpu_message_filter_); |
| -#if defined(ENABLE_WEBRTC) |
| - AddFilter(new WebRTCIdentityServiceHost( |
| - GetID(), |
| - storage_partition_impl_->GetWebRTCIdentityStore(), |
| - resource_context)); |
| - peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID()); |
| - AddFilter(peer_connection_tracker_host_.get()); |
| - AddFilter(new MediaStreamDispatcherHost( |
| - GetID(), |
| - browser_context->GetResourceContext()->GetMediaDeviceIDSalt(), |
| - media_stream_manager)); |
| - AddFilter(new MediaStreamTrackMetricsHost()); |
| -#endif |
| -#if defined(ENABLE_PLUGINS) |
| - AddFilter(new PepperRendererConnection(GetID())); |
| -#endif |
| - AddFilter(new SpeechRecognitionDispatcherHost( |
| - GetID(), storage_partition_impl_->GetURLRequestContext())); |
| - AddFilter(new FileAPIMessageFilter( |
| - GetID(), |
| - storage_partition_impl_->GetURLRequestContext(), |
| - storage_partition_impl_->GetFileSystemContext(), |
| - ChromeBlobStorageContext::GetFor(browser_context), |
| - StreamContext::GetFor(browser_context))); |
| - AddFilter(new FileUtilitiesMessageFilter(GetID())); |
| - AddFilter(new MimeRegistryMessageFilter()); |
| - AddFilter(new DatabaseMessageFilter( |
| - storage_partition_impl_->GetDatabaseTracker())); |
| -#if defined(OS_MACOSX) |
| - AddFilter(new TextInputClientMessageFilter(GetID())); |
| -#elif defined(OS_WIN) |
| - // The FontCacheDispatcher is required only when we're using GDI rendering. |
| - // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache |
| - // GDI fonts (http://crbug.com/383227), even when using DirectWrite. This |
| - // should eventually be if (!ShouldUseDirectWrite()) guarded. |
| - channel_->AddFilter(new FontCacheDispatcher()); |
| -#elif defined(OS_ANDROID) |
| - browser_demuxer_android_ = new BrowserDemuxerAndroid(); |
| - AddFilter(browser_demuxer_android_.get()); |
| -#endif |
| -#if defined(ENABLE_BROWSER_CDMS) |
| - AddFilter(new BrowserCdmManager(GetID(), NULL)); |
| -#endif |
| - |
| - WebSocketDispatcherHost::GetRequestContextCallback |
| - websocket_request_context_callback( |
| - base::Bind(&GetRequestContext, request_context, |
| - media_request_context, RESOURCE_TYPE_SUB_RESOURCE)); |
| - |
| - AddFilter( |
| - new WebSocketDispatcherHost(GetID(), websocket_request_context_callback)); |
| - |
| - message_port_message_filter_ = new MessagePortMessageFilter( |
| - base::Bind(&RenderWidgetHelper::GetNextRoutingID, |
| - base::Unretained(widget_helper_.get()))); |
| - AddFilter(message_port_message_filter_.get()); |
| - |
| - scoped_refptr<CacheStorageDispatcherHost> cache_storage_filter = |
| - new CacheStorageDispatcherHost(); |
| - cache_storage_filter->Init(storage_partition_impl_->GetCacheStorageContext()); |
| - AddFilter(cache_storage_filter.get()); |
| - |
| - scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter = |
| - new ServiceWorkerDispatcherHost( |
| - GetID(), message_port_message_filter_.get(), resource_context); |
| - service_worker_filter->Init( |
| - storage_partition_impl_->GetServiceWorkerContext()); |
| - AddFilter(service_worker_filter.get()); |
| - |
| - AddFilter(new SharedWorkerMessageFilter( |
| - GetID(), |
| - resource_context, |
| - WorkerStoragePartition( |
| - storage_partition_impl_->GetURLRequestContext(), |
| - storage_partition_impl_->GetMediaURLRequestContext(), |
| - storage_partition_impl_->GetAppCacheService(), |
| - storage_partition_impl_->GetQuotaManager(), |
| - storage_partition_impl_->GetFileSystemContext(), |
| - storage_partition_impl_->GetDatabaseTracker(), |
| - storage_partition_impl_->GetIndexedDBContext(), |
| - storage_partition_impl_->GetServiceWorkerContext()), |
| - message_port_message_filter_.get())); |
| - |
| -#if defined(ENABLE_WEBRTC) |
| - p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost( |
| - resource_context, |
| - browser_context->GetRequestContextForRenderProcess(GetID())); |
| - AddFilter(p2p_socket_dispatcher_host_.get()); |
| -#endif |
| - |
| - AddFilter(new TraceMessageFilter(GetID())); |
| - AddFilter(new ResolveProxyMsgHelper( |
| - browser_context->GetRequestContextForRenderProcess(GetID()))); |
| - AddFilter(new QuotaDispatcherHost( |
| - GetID(), |
| - storage_partition_impl_->GetQuotaManager(), |
| - GetContentClient()->browser()->CreateQuotaPermissionContext())); |
| - |
| - notification_message_filter_ = new NotificationMessageFilter( |
| - GetID(), |
| - storage_partition_impl_->GetPlatformNotificationContext(), |
| - resource_context, |
| - browser_context); |
| - AddFilter(notification_message_filter_.get()); |
| - |
| - AddFilter(new GamepadBrowserMessageFilter()); |
| - AddFilter(new DeviceLightMessageFilter()); |
| - AddFilter(new DeviceMotionMessageFilter()); |
| - AddFilter(new DeviceOrientationMessageFilter()); |
| - AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER)); |
| - AddFilter(new HistogramMessageFilter()); |
| -#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID)) |
| - if (browser_command_line.HasSwitch(switches::kEnableMemoryBenchmarking)) |
| - AddFilter(new MemoryBenchmarkMessageFilter()); |
| -#endif |
| - AddFilter(new MemoryMessageFilter()); |
| - AddFilter(new PushMessagingMessageFilter( |
| - GetID(), storage_partition_impl_->GetServiceWorkerContext())); |
| -#if defined(OS_ANDROID) |
| - AddFilter(new ScreenOrientationMessageFilterAndroid()); |
| -#endif |
| - AddFilter(new GeofencingDispatcherHost( |
| - storage_partition_impl_->GetGeofencingManager())); |
| - if (browser_command_line.HasSwitch(switches::kEnableWebBluetooth)) { |
| - bluetooth_dispatcher_host_ = new BluetoothDispatcherHost(GetID()); |
| - AddFilter(bluetooth_dispatcher_host_.get()); |
| - } |
| -} |
| - |
| -void RenderProcessHostImpl::RegisterMojoServices() { |
| -#if !defined(OS_ANDROID) |
| - mojo_application_host_->service_registry()->AddService( |
| - base::Bind(&device::BatteryMonitorImpl::Create)); |
| - |
| - mojo_application_host_->service_registry()->AddService( |
| - base::Bind(&device::VibrationManagerImpl::Create)); |
| -#endif |
| - |
| - mojo_application_host_->service_registry()->AddService( |
| - base::Bind(&PermissionServiceContext::CreateService, |
| - base::Unretained(permission_service_context_.get()))); |
| - |
| - mojo_application_host_->service_registry()->AddService(base::Bind( |
| - &BackgroundSyncContextImpl::CreateService, |
| - base::Unretained(storage_partition_impl_->GetBackgroundSyncContext()))); |
| - |
| - mojo_application_host_->service_registry()->AddService(base::Bind( |
| - &content::ServicePortServiceImpl::Create, |
| - make_scoped_refptr(storage_partition_impl_->GetNavigatorConnectContext()), |
| - message_port_message_filter_)); |
| - |
| -#if defined(OS_ANDROID) |
| - ServiceRegistrarAndroid::RegisterProcessHostServices( |
| - mojo_application_host_->service_registry_android()); |
| -#endif |
| - |
| - GetContentClient()->browser()->RegisterRenderProcessMojoServices( |
| - mojo_application_host_->service_registry()); |
| -} |
| - |
| -int RenderProcessHostImpl::GetNextRoutingID() { |
| - return widget_helper_->GetNextRoutingID(); |
| -} |
| - |
| -void RenderProcessHostImpl::ResumeDeferredNavigation( |
| - const GlobalRequestID& request_id) { |
| - widget_helper_->ResumeDeferredNavigation(request_id); |
| -} |
| - |
| -void RenderProcessHostImpl::NotifyTimezoneChange(const std::string& zone_id) { |
| - Send(new ViewMsg_TimezoneChange(zone_id)); |
| -} |
| - |
| -ServiceRegistry* RenderProcessHostImpl::GetServiceRegistry() { |
| - DCHECK(mojo_application_host_); |
| - return mojo_application_host_->service_registry(); |
| -} |
| - |
| -const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics() |
| - const { |
| - return init_time_; |
| -} |
| - |
| -bool RenderProcessHostImpl::SubscribeUniformEnabled() const { |
| - return subscribe_uniform_enabled_; |
| -} |
| - |
| -void RenderProcessHostImpl::OnAddSubscription(unsigned int target) { |
| - DCHECK(subscribe_uniform_enabled_); |
| - subscription_set_.insert(target); |
| - const gpu::ValueState* state = pending_valuebuffer_state_->GetState(target); |
| - if (state) { |
| - SendUpdateValueState(target, *state); |
| - } |
| -} |
| - |
| -void RenderProcessHostImpl::OnRemoveSubscription(unsigned int target) { |
| - DCHECK(subscribe_uniform_enabled_); |
| - subscription_set_.erase(target); |
| -} |
| - |
| -void RenderProcessHostImpl::SendUpdateValueState(unsigned int target, |
| - const gpu::ValueState& state) { |
| - DCHECK(subscribe_uniform_enabled_); |
| - if (subscription_set_.find(target) != subscription_set_.end()) { |
| - GpuProcessHost::SendOnIO( |
| - GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
| - CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, |
| - new GpuMsg_UpdateValueState(id_, target, state)); |
| - } else { |
| - // Store the ValueState locally in case a Valuebuffer subscribes to it later |
| - pending_valuebuffer_state_->UpdateState(target, state); |
| - } |
| -} |
| - |
| -#if defined(ENABLE_BROWSER_CDMS) |
| -media::BrowserCdm* RenderProcessHostImpl::GetBrowserCdm(int render_frame_id, |
| - int cdm_id) const { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - BrowserCdmManager* manager = BrowserCdmManager::FromProcess(GetID()); |
| - if (!manager) |
| - return nullptr; |
| - return manager->GetCdm(render_frame_id, cdm_id); |
| -} |
| -#endif |
| - |
| -void RenderProcessHostImpl::AddRoute( |
| - int32 routing_id, |
| - IPC::Listener* listener) { |
| - CHECK(!listeners_.Lookup(routing_id)) |
| - << "Found Routing ID Conflict: " << routing_id; |
| - listeners_.AddWithID(listener, routing_id); |
| -} |
| - |
| -void RenderProcessHostImpl::RemoveRoute(int32 routing_id) { |
| - DCHECK(listeners_.Lookup(routing_id) != NULL); |
| - listeners_.Remove(routing_id); |
| - |
| - // Keep the one renderer thread around forever in single process mode. |
| - if (!run_renderer_in_process()) |
| - Cleanup(); |
| -} |
| - |
| -void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) { |
| - observers_.AddObserver(observer); |
| -} |
| - |
| -void RenderProcessHostImpl::RemoveObserver( |
| - RenderProcessHostObserver* observer) { |
| - observers_.RemoveObserver(observer); |
| -} |
| - |
| -void RenderProcessHostImpl::ShutdownForBadMessage() { |
| - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| - if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) |
| - return; |
| - |
| - if (run_renderer_in_process()) { |
| - // In single process mode it is better if we don't suicide but just |
| - // crash. |
| - CHECK(false); |
| - } |
| - // We kill the renderer but don't include a NOTREACHED, because we want the |
| - // browser to try to survive when it gets illegal messages from the renderer. |
| - Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE, false); |
| -} |
| - |
| -void RenderProcessHostImpl::WidgetRestored() { |
| - // Verify we were properly backgrounded. |
| - DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); |
| - visible_widgets_++; |
| - SetBackgrounded(false); |
| -} |
| - |
| -void RenderProcessHostImpl::WidgetHidden() { |
| - // On startup, the browser will call Hide |
| - if (backgrounded_) |
| - return; |
| - |
| - DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); |
| - visible_widgets_--; |
| - DCHECK_GE(visible_widgets_, 0); |
| - if (visible_widgets_ == 0) { |
| - DCHECK(!backgrounded_); |
| - SetBackgrounded(true); |
| - } |
| -} |
| - |
| -int RenderProcessHostImpl::VisibleWidgetCount() const { |
| - return visible_widgets_; |
| -} |
| - |
| -bool RenderProcessHostImpl::IsForGuestsOnly() const { |
| - return is_for_guests_only_; |
| -} |
| - |
| -StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { |
| - return storage_partition_impl_; |
| -} |
| - |
| -static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { |
| - if (IsPropertyTreeVerificationEnabled()) |
| - command_line->AppendSwitch(cc::switches::kEnablePropertyTreeVerification); |
| - |
| - command_line->AppendSwitchASCII( |
| - switches::kNumRasterThreads, |
| - base::IntToString(NumberOfRendererRasterThreads())); |
| - |
| - if (IsGpuRasterizationEnabled()) |
| - command_line->AppendSwitch(switches::kEnableGpuRasterization); |
| - |
| - int msaa_sample_count = GpuRasterizationMSAASampleCount(); |
| - if (msaa_sample_count >= 0) { |
| - command_line->AppendSwitchASCII( |
| - switches::kGpuRasterizationMSAASampleCount, |
| - base::IntToString(msaa_sample_count)); |
| - } |
| - |
| - if (IsZeroCopyUploadEnabled()) |
| - command_line->AppendSwitch(switches::kEnableZeroCopy); |
| - if (IsPersistentGpuMemoryBufferEnabled()) |
| - command_line->AppendSwitch(switches::kEnablePersistentGpuMemoryBuffer); |
| - |
| - if (IsForceGpuRasterizationEnabled()) |
| - command_line->AppendSwitch(switches::kForceGpuRasterization); |
| - |
| - gfx::BufferUsage buffer_usage = IsPersistentGpuMemoryBufferEnabled() |
| - ? gfx::BufferUsage::PERSISTENT_MAP |
| - : gfx::BufferUsage::MAP; |
| - std::vector<unsigned> image_targets( |
| - static_cast<size_t>(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D); |
| - for (size_t format = 0; |
| - format < static_cast<size_t>(gfx::BufferFormat::LAST) + 1; format++) { |
| - image_targets[format] = |
| - BrowserGpuMemoryBufferManager::GetImageTextureTarget( |
| - static_cast<gfx::BufferFormat>(format), buffer_usage); |
| - } |
| - command_line->AppendSwitchASCII(switches::kContentImageTextureTarget, |
| - UintVectorToString(image_targets)); |
| - |
| - command_line->AppendSwitchASCII( |
| - switches::kVideoImageTextureTarget, |
| - base::UintToString(BrowserGpuMemoryBufferManager::GetImageTextureTarget( |
| - gfx::BufferFormat::R_8, gfx::BufferUsage::MAP))); |
| - |
| - // Appending disable-gpu-feature switches due to software rendering list. |
| - GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); |
| - DCHECK(gpu_data_manager); |
| - gpu_data_manager->AppendRendererCommandLine(command_line); |
| -} |
| - |
| -void RenderProcessHostImpl::AppendRendererCommandLine( |
| - base::CommandLine* command_line) const { |
| - // Pass the process type first, so it shows first in process listings. |
| - command_line->AppendSwitchASCII(switches::kProcessType, |
| - switches::kRendererProcess); |
| - |
| - // Now send any options from our own command line we want to propagate. |
| - const base::CommandLine& browser_command_line = |
| - *base::CommandLine::ForCurrentProcess(); |
| - PropagateBrowserCommandLineToRenderer(browser_command_line, command_line); |
| - |
| - // Pass on the browser locale. |
| - const std::string locale = |
| - GetContentClient()->browser()->GetApplicationLocale(); |
| - command_line->AppendSwitchASCII(switches::kLang, locale); |
| - |
| - // If we run base::FieldTrials, we want to pass to their state to the |
| - // renderer so that it can act in accordance with each state, or record |
| - // histograms relating to the base::FieldTrial states. |
| - std::string field_trial_states; |
| - base::FieldTrialList::AllStatesToString(&field_trial_states); |
| - if (!field_trial_states.empty()) { |
| - command_line->AppendSwitchASCII(switches::kForceFieldTrials, |
| - field_trial_states); |
| - } |
| - |
| - GetContentClient()->browser()->AppendExtraCommandLineSwitches( |
| - command_line, GetID()); |
| - |
| - if (IsPinchToZoomEnabled()) |
| - command_line->AppendSwitch(switches::kEnablePinch); |
| - |
| -#if defined(OS_WIN) |
| - command_line->AppendSwitchASCII(switches::kDeviceScaleFactor, |
| - base::DoubleToString(gfx::GetDPIScale())); |
| -#endif |
| - |
| - AppendCompositorCommandLineFlags(command_line); |
| -} |
| - |
| -void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( |
| - const base::CommandLine& browser_cmd, |
| - base::CommandLine* renderer_cmd) const { |
| - // Propagate the following switches to the renderer command line (along |
| - // with any associated values) if present in the browser command line. |
| - static const char* const kSwitchNames[] = { |
| - switches::kAllowLoopbackInPeerConnection, |
| - switches::kAudioBufferSize, |
| - switches::kBlinkPlatformLogChannels, |
| - switches::kBlinkSettings, |
| - switches::kDefaultTileWidth, |
| - switches::kDefaultTileHeight, |
| - switches::kDisable3DAPIs, |
| - switches::kDisableAcceleratedJpegDecoding, |
| - switches::kDisableAcceleratedVideoDecode, |
| - switches::kDisableBlinkFeatures, |
| - switches::kDisableBreakpad, |
| - switches::kDisablePreferCompositingToLCDText, |
| - switches::kDisableDatabases, |
| - switches::kDisableDelayAgnosticAec, |
| - switches::kDisableDirectNPAPIRequests, |
| - switches::kDisableDisplayList2dCanvas, |
| - switches::kDisableDistanceFieldText, |
| - switches::kDisableEncryptedMedia, |
| - switches::kDisableFeatures, |
| - switches::kDisableFileSystem, |
| - switches::kDisableGpuCompositing, |
| - switches::kDisableGpuMemoryBufferVideoFrames, |
| - switches::kDisableGpuVsync, |
| - switches::kDisableLowResTiling, |
| - switches::kDisableHistogramCustomizer, |
| - switches::kDisableIconNtp, |
| - switches::kDisableLCDText, |
| - switches::kDisableLocalStorage, |
| - switches::kDisableLogging, |
| - switches::kDisableMediaSource, |
| - switches::kDisableMojoChannel, |
| - switches::kDisableNotifications, |
| - switches::kDisableOverlayScrollbar, |
| - switches::kDisablePermissionsAPI, |
| - switches::kDisablePresentationAPI, |
| - switches::kDisablePinch, |
| - switches::kDisableRGBA4444Textures, |
| - switches::kDisableSeccompFilterSandbox, |
| - switches::kDisableSharedWorkers, |
| - switches::kDisableSpeechAPI, |
| - switches::kDisableSVG1DOM, |
| - switches::kDisableThreadedCompositing, |
| - switches::kDisableThreadedScrolling, |
| - switches::kDisableTouchAdjustment, |
| - switches::kDisableTouchDragDrop, |
| - switches::kDisableTouchEditing, |
| - switches::kDisableV8IdleTasks, |
| - switches::kDomAutomationController, |
| - switches::kEnableBleedingEdgeRenderingFastPaths, |
| - switches::kEnableBlinkFeatures, |
| - switches::kEnableBrowserSideNavigation, |
| - switches::kEnableCompositorAnimationTimelines, |
| - switches::kEnableCredentialManagerAPI, |
| - switches::kEnableDisplayList2dCanvas, |
| - switches::kEnableDistanceFieldText, |
| - switches::kEnableExperimentalCanvasFeatures, |
| - switches::kEnableExperimentalWebPlatformFeatures, |
| - switches::kEnableFeatures, |
| - switches::kEnableGPUClientLogging, |
| - switches::kEnableGpuClientTracing, |
| - switches::kEnableGpuMemoryBufferVideoFrames, |
| - switches::kEnableGPUServiceLogging, |
| - switches::kEnableIconNtp, |
| - switches::kEnableLinkDisambiguationPopup, |
| - switches::kEnableLowResTiling, |
| - switches::kEnableInbandTextTracks, |
| - switches::kEnableLCDText, |
| - switches::kEnableLogging, |
| - switches::kEnableMemoryBenchmarking, |
| - switches::kEnableNetworkInformation, |
| - switches::kEnableOverlayScrollbar, |
| - switches::kEnablePinch, |
| - switches::kEnablePluginPlaceholderTesting, |
| - switches::kEnablePreciseMemoryInfo, |
| - switches::kEnablePreferCompositingToLCDText, |
| - switches::kEnablePrefixedEncryptedMedia, |
| - switches::kEnablePushMessagePayload, |
| - switches::kEnableRGBA4444Textures, |
| - switches::kEnableRendererMojoChannel, |
| - switches::kEnableRTCSmoothnessAlgorithm, |
| - switches::kEnableSeccompFilterSandbox, |
| - switches::kEnableSkiaBenchmarking, |
| - switches::kEnableSlimmingPaintV2, |
| - switches::kEnableSmoothScrolling, |
| - switches::kEnableStatsTable, |
| - switches::kEnableThreadedCompositing, |
| - switches::kEnableTouchDragDrop, |
| - switches::kEnableTouchEditing, |
| - switches::kEnableUnsafeES3APIs, |
| - switches::kEnableViewport, |
| - switches::kEnableVtune, |
| - switches::kEnableWebBluetooth, |
| - switches::kEnableWebGLDraftExtensions, |
| - switches::kEnableWebGLImageChromium, |
| - switches::kEnableWebVR, |
| - switches::kExplicitlyAllowedPorts, |
| - switches::kForceDeviceScaleFactor, |
| - switches::kForceDisplayList2dCanvas, |
| - switches::kForceOverlayFullscreenVideo, |
| - switches::kFullMemoryCrashReport, |
| - switches::kInertVisualViewport, |
| - switches::kIPCConnectionTimeout, |
| - switches::kJavaScriptFlags, |
| - switches::kLoggingLevel, |
| - switches::kMainFrameResizesAreOrientationChanges, |
| - switches::kMaxUntiledLayerWidth, |
| - switches::kMaxUntiledLayerHeight, |
| - switches::kMemoryMetrics, |
| - switches::kNoReferrers, |
| - switches::kNoSandbox, |
| - switches::kOverridePluginPowerSaverForTesting, |
| - switches::kPpapiInProcess, |
| - switches::kProfilerTiming, |
| - switches::kReducedReferrerGranularity, |
| - switches::kReduceSecurityForTesting, |
| - switches::kRegisterPepperPlugins, |
| - switches::kRendererStartupDialog, |
| - switches::kRootLayerScrolls, |
| - switches::kShowPaintRects, |
| - switches::kSitePerProcess, |
| - switches::kStatsCollectionController, |
| - switches::kTestType, |
| - switches::kTouchEvents, |
| - switches::kTouchTextSelectionStrategy, |
| - switches::kTraceConfigFile, |
| - switches::kTraceToConsole, |
| - // This flag needs to be propagated to the renderer process for |
| - // --in-process-webgl. |
| - switches::kUseGL, |
| - switches::kUseMobileUserAgent, |
| - switches::kUseNormalPriorityForTileTaskWorkerThreads, |
| - switches::kV, |
| - switches::kVideoThreads, |
| - switches::kVideoUnderflowThresholdMs, |
| - switches::kVModule, |
| - // Please keep these in alphabetical order. Compositor switches here should |
| - // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc. |
| - cc::switches::kDisableCompositedAntialiasing, |
| - cc::switches::kDisableMainFrameBeforeActivation, |
| - cc::switches::kDisableThreadedAnimation, |
| - cc::switches::kEnableBeginFrameScheduling, |
| - cc::switches::kEnableGpuBenchmarking, |
| - cc::switches::kEnableMainFrameBeforeActivation, |
| - cc::switches::kShowCompositedLayerBorders, |
| - cc::switches::kShowFPSCounter, |
| - cc::switches::kShowLayerAnimationBounds, |
| - cc::switches::kShowPropertyChangedRects, |
| - cc::switches::kShowReplicaScreenSpaceRects, |
| - cc::switches::kShowScreenSpaceRects, |
| - cc::switches::kShowSurfaceDamageRects, |
| - cc::switches::kSlowDownRasterScaleFactor, |
| - cc::switches::kStrictLayerPropertyChangeChecking, |
| - cc::switches::kTopControlsHideThreshold, |
| - cc::switches::kTopControlsShowThreshold, |
| - |
| -#if defined(ENABLE_PLUGINS) |
| - switches::kEnablePepperTesting, |
| -#endif |
| -#if defined(ENABLE_WEBRTC) |
| - switches::kDisableWebRtcHWDecoding, |
| - switches::kDisableWebRtcHWEncoding, |
| - switches::kEnableWebRtcDtls12, |
| - switches::kEnableWebRtcHWH264Encoding, |
| - switches::kEnableWebRtcStunOrigin, |
| - switches::kWebRtcMaxCaptureFramerate, |
| -#endif |
| - switches::kEnableLowEndDeviceMode, |
| - switches::kDisableLowEndDeviceMode, |
| -#if defined(OS_ANDROID) |
| - switches::kDisableGestureRequirementForMediaPlayback, |
| - switches::kDisableWebAudio, |
| - switches::kRendererWaitForJavaDebugger, |
| -#endif |
| -#if defined(OS_MACOSX) |
| - // Allow this to be set when invoking the browser and relayed along. |
| - switches::kEnableSandboxLogging, |
| -#endif |
| -#if defined(OS_WIN) |
| - switches::kDisableDirectWrite, |
| - switches::kDisableWin32kRendererLockDown, |
| - switches::kTraceExportEventsToETW, |
| -#endif |
| -#if defined(USE_OZONE) |
| - switches::kOzonePlatform, |
| -#endif |
| -#if defined(OS_CHROMEOS) |
| - switches::kDisableVaapiAcceleratedVideoEncode, |
| -#endif |
| - }; |
| - renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, |
| - arraysize(kSwitchNames)); |
| - |
| - if (browser_cmd.HasSwitch(switches::kTraceStartup) && |
| - BrowserMainLoop::GetInstance()->is_tracing_startup_for_duration()) { |
| - // Pass kTraceStartup switch to renderer only if startup tracing has not |
| - // finished. |
| - renderer_cmd->AppendSwitchASCII( |
| - switches::kTraceStartup, |
| - browser_cmd.GetSwitchValueASCII(switches::kTraceStartup)); |
| - } |
| - |
| -#if defined(ENABLE_WEBRTC) |
| - // Only run the Stun trials in the first renderer. |
| - if (!has_done_stun_trials && |
| - browser_cmd.HasSwitch(switches::kWebRtcStunProbeTrialParameter)) { |
| - has_done_stun_trials = true; |
| - renderer_cmd->AppendSwitchASCII( |
| - switches::kWebRtcStunProbeTrialParameter, |
| - browser_cmd.GetSwitchValueASCII( |
| - switches::kWebRtcStunProbeTrialParameter)); |
| - } |
| -#endif |
| - |
| - // Disable databases in incognito mode. |
| - if (GetBrowserContext()->IsOffTheRecord() && |
| - !browser_cmd.HasSwitch(switches::kDisableDatabases)) { |
| - renderer_cmd->AppendSwitch(switches::kDisableDatabases); |
| - } |
| - |
| - // Add kWaitForDebugger to let renderer process wait for a debugger. |
| - if (browser_cmd.HasSwitch(switches::kWaitForDebuggerChildren)) { |
| - // Look to pass-on the kWaitForDebugger flag. |
| - std::string value = |
| - browser_cmd.GetSwitchValueASCII(switches::kWaitForDebuggerChildren); |
| - if (value.empty() || value == switches::kRendererProcess) { |
| - renderer_cmd->AppendSwitch(switches::kWaitForDebugger); |
| - } |
| - } |
| -} |
| - |
| -base::ProcessHandle RenderProcessHostImpl::GetHandle() const { |
| - if (run_renderer_in_process()) |
| - return base::GetCurrentProcessHandle(); |
| - |
| - if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) |
| - return base::kNullProcessHandle; |
| - |
| - return child_process_launcher_->GetProcess().Handle(); |
| -} |
| - |
| -bool RenderProcessHostImpl::Shutdown(int exit_code, bool wait) { |
| - if (run_renderer_in_process()) |
| - return false; // Single process mode never shuts down the renderer. |
| - |
| -#if defined(OS_ANDROID) |
| - // Android requires a different approach for killing. |
| - StopChildProcess(GetHandle()); |
| - return true; |
| -#else |
| - if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) |
| - return false; |
| - |
| - return child_process_launcher_->GetProcess().Terminate(exit_code, wait); |
| -#endif |
| -} |
| - |
| -bool RenderProcessHostImpl::FastShutdownIfPossible() { |
| - if (run_renderer_in_process()) |
| - return false; // Single process mode never shuts down the renderer. |
| - |
| - if (!GetContentClient()->browser()->IsFastShutdownPossible()) |
| - return false; |
| - |
| - if (!child_process_launcher_.get() || |
| - child_process_launcher_->IsStarting() || |
| - !GetHandle()) |
| - return false; // Render process hasn't started or is probably crashed. |
| - |
| - // Test if there's an unload listener. |
| - // NOTE: It's possible that an onunload listener may be installed |
| - // while we're shutting down, so there's a small race here. Given that |
| - // the window is small, it's unlikely that the web page has much |
| - // state that will be lost by not calling its unload handlers properly. |
| - if (!SuddenTerminationAllowed()) |
| - return false; |
| - |
| - if (worker_ref_count_ != 0) { |
| - if (survive_for_worker_start_time_.is_null()) |
| - survive_for_worker_start_time_ = base::TimeTicks::Now(); |
| - return false; |
| - } |
| - |
| - // Set this before ProcessDied() so observers can tell if the render process |
| - // died due to fast shutdown versus another cause. |
| - fast_shutdown_started_ = true; |
| - |
| - ProcessDied(false /* already_dead */, nullptr); |
| - return true; |
| -} |
| - |
| -bool RenderProcessHostImpl::Send(IPC::Message* msg) { |
| - TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send"); |
| - if (!channel_) { |
| - if (!is_initialized_) { |
| - queued_messages_.push(msg); |
| - return true; |
| - } else { |
| - delete msg; |
| - return false; |
| - } |
| - } |
| - |
| - if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { |
| - queued_messages_.push(msg); |
| - return true; |
| - } |
| - |
| - return channel_->Send(msg); |
| -} |
| - |
| -bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
| - // If we're about to be deleted, or have initiated the fast shutdown sequence, |
| - // we ignore incoming messages. |
| - |
| - if (deleting_soon_ || fast_shutdown_started_) |
| - return false; |
| - |
| - mark_child_process_activity_time(); |
| - if (msg.routing_id() == MSG_ROUTING_CONTROL) { |
| - // Dispatch control messages. |
| - IPC_BEGIN_MESSAGE_MAP(RenderProcessHostImpl, msg) |
| - IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, |
| - OnShutdownRequest) |
| - IPC_MESSAGE_HANDLER(RenderProcessHostMsg_SuddenTerminationChanged, |
| - SuddenTerminationChanged) |
| - IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction, |
| - OnUserMetricsRecordAction) |
| - IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML) |
| - IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK) |
| -#if defined(ENABLE_WEBRTC) |
| - IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer, |
| - OnRegisterAecDumpConsumer) |
| - IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer, |
| - OnUnregisterAecDumpConsumer) |
| -#endif |
| - // Adding single handlers for your service here is fine, but once your |
| - // service needs more than one handler, please extract them into a new |
| - // message filter and add that filter to CreateMessageFilters(). |
| - IPC_END_MESSAGE_MAP() |
| - |
| - return true; |
| - } |
| - |
| - // Dispatch incoming messages to the appropriate IPC::Listener. |
| - IPC::Listener* listener = listeners_.Lookup(msg.routing_id()); |
| - if (!listener) { |
| - if (msg.is_sync()) { |
| - // The listener has gone away, so we must respond or else the caller will |
| - // hang waiting for a reply. |
| - IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg); |
| - reply->set_reply_error(); |
| - Send(reply); |
| - } |
| - return true; |
| - } |
| - return listener->OnMessageReceived(msg); |
| -} |
| - |
| -void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) { |
| -#if defined(IPC_MESSAGE_LOG_ENABLED) |
| - Send(new ChildProcessMsg_SetIPCLoggingEnabled( |
| - IPC::Logging::GetInstance()->Enabled())); |
| -#endif |
| - |
| - tracked_objects::ThreadData::Status status = |
| - tracked_objects::ThreadData::status(); |
| - Send(new ChildProcessMsg_SetProfilerStatus(status)); |
| - |
| -#if defined(OS_MACOSX) && !defined(OS_IOS) |
| - io_surface_manager_token_ = |
| - BrowserIOSurfaceManager::GetInstance()->GenerateChildProcessToken( |
| - GetID()); |
| - Send(new ChildProcessMsg_SetIOSurfaceManagerToken(io_surface_manager_token_)); |
| -#endif |
| - |
| -#if defined(USE_OZONE) |
| - Send(new ChildProcessMsg_InitializeClientNativePixmapFactory( |
| - base::FileDescriptor( |
| - ui::OzonePlatform::GetInstance()->OpenClientNativePixmapDevice()))); |
| -#endif |
| - |
| - // Inform AudioInputRendererHost about the new render process PID. |
| - // AudioInputRendererHost is reference counted, so it's lifetime is |
| - // guarantueed during the lifetime of the closure. |
| - BrowserThread::PostTask( |
| - BrowserThread::IO, FROM_HERE, |
| - base::Bind(&AudioInputRendererHost::set_renderer_pid, |
| - audio_input_renderer_host_, |
| - peer_pid)); |
| -} |
| - |
| -void RenderProcessHostImpl::OnChannelError() { |
| - ProcessDied(true /* already_dead */, nullptr); |
| -} |
| - |
| -void RenderProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) { |
| - // Message de-serialization failed. We consider this a capital crime. Kill the |
| - // renderer if we have one. |
| - auto type = message.type(); |
| - LOG(ERROR) << "bad message " << type << " terminating renderer."; |
| - BrowserChildProcessHostImpl::HistogramBadMessageTerminated( |
| - PROCESS_TYPE_RENDERER); |
| - |
| - // Create a memory dump. This will contain enough stack frames to work out |
| - // what the bad message was. |
| - base::debug::Alias(&type); |
| - base::debug::DumpWithoutCrashing(); |
| - |
| - bad_message::ReceivedBadMessage(this, |
| - bad_message::RPH_DESERIALIZATION_FAILED); |
| -} |
| - |
| -BrowserContext* RenderProcessHostImpl::GetBrowserContext() const { |
| - return browser_context_; |
| -} |
| - |
| -bool RenderProcessHostImpl::InSameStoragePartition( |
| - StoragePartition* partition) const { |
| - return storage_partition_impl_ == partition; |
| -} |
| - |
| -int RenderProcessHostImpl::GetID() const { |
| - return id_; |
| -} |
| - |
| -bool RenderProcessHostImpl::HasConnection() const { |
| - return channel_.get() != NULL; |
| -} |
| - |
| -void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) { |
| - ignore_input_events_ = ignore_input_events; |
| -} |
| - |
| -bool RenderProcessHostImpl::IgnoreInputEvents() const { |
| - return ignore_input_events_; |
| -} |
| - |
| -void RenderProcessHostImpl::Cleanup() { |
| - // If within_process_died_observer_ is true, one of our observers performed an |
| - // action that caused us to die (e.g. http://crbug.com/339504). Therefore, |
| - // delay the destruction until all of the observer callbacks have been made, |
| - // and guarantee that the RenderProcessHostDestroyed observer callback is |
| - // always the last callback fired. |
| - if (within_process_died_observer_) { |
| - delayed_cleanup_needed_ = true; |
| - return; |
| - } |
| - delayed_cleanup_needed_ = false; |
| - |
| - // Records the time when the process starts surviving for workers for UMA. |
| - if (listeners_.IsEmpty() && worker_ref_count_ > 0 && |
| - survive_for_worker_start_time_.is_null()) { |
| - survive_for_worker_start_time_ = base::TimeTicks::Now(); |
| - } |
| - |
| - // When there are no other owners of this object, we can delete ourselves. |
| - if (listeners_.IsEmpty() && worker_ref_count_ == 0) { |
| - if (!survive_for_worker_start_time_.is_null()) { |
| - UMA_HISTOGRAM_LONG_TIMES( |
| - "SharedWorker.RendererSurviveForWorkerTime", |
| - base::TimeTicks::Now() - survive_for_worker_start_time_); |
| - } |
| - |
| - if (max_worker_count_ > 0) { |
| - // Record the max number of workers (SharedWorker or ServiceWorker) |
| - // that are simultaneously hosted in this renderer process. |
| - UMA_HISTOGRAM_COUNTS("Render.Workers.MaxWorkerCountInRendererProcess", |
| - max_worker_count_); |
| - } |
| - |
| - // We cannot clean up twice; if this fails, there is an issue with our |
| - // control flow. |
| - DCHECK(!deleting_soon_); |
| - |
| - DCHECK_EQ(0, pending_views_); |
| - FOR_EACH_OBSERVER(RenderProcessHostObserver, |
| - observers_, |
| - RenderProcessHostDestroyed(this)); |
| - NotificationService::current()->Notify( |
| - NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| - Source<RenderProcessHost>(this), |
| - NotificationService::NoDetails()); |
| - |
| -#ifndef NDEBUG |
| - is_self_deleted_ = true; |
| -#endif |
| - base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| - deleting_soon_ = true; |
| - // It's important not to wait for the DeleteTask to delete the channel |
| - // proxy. Kill it off now. That way, in case the profile is going away, the |
| - // rest of the objects attached to this RenderProcessHost start going |
| - // away first, since deleting the channel proxy will post a |
| - // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. |
| - channel_.reset(); |
| - |
| - // The following members should be cleared in ProcessDied() as well! |
| - gpu_message_filter_ = NULL; |
| - message_port_message_filter_ = NULL; |
| - |
| - RemoveUserData(kSessionStorageHolderKey); |
| - |
| - // Remove ourself from the list of renderer processes so that we can't be |
| - // reused in between now and when the Delete task runs. |
| - UnregisterHost(GetID()); |
| - |
| -#if defined(OS_MACOSX) && !defined(OS_IOS) |
| - if (!io_surface_manager_token_.IsZero()) { |
| - BrowserIOSurfaceManager::GetInstance()->InvalidateChildProcessToken( |
| - io_surface_manager_token_); |
| - io_surface_manager_token_.SetZero(); |
| - } |
| -#endif |
| - } |
| -} |
| - |
| -void RenderProcessHostImpl::AddPendingView() { |
| - pending_views_++; |
| -} |
| - |
| -void RenderProcessHostImpl::RemovePendingView() { |
| - DCHECK(pending_views_); |
| - pending_views_--; |
| -} |
| - |
| -void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) { |
| - sudden_termination_allowed_ = enabled; |
| -} |
| - |
| -bool RenderProcessHostImpl::SuddenTerminationAllowed() const { |
| - return sudden_termination_allowed_; |
| -} |
| - |
| -base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const { |
| - return base::TimeTicks::Now() - child_process_activity_time_; |
| -} |
| - |
| -void RenderProcessHostImpl::ResumeRequestsForView(int route_id) { |
| - widget_helper_->ResumeRequestsForView(route_id); |
| -} |
| - |
| -void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) { |
| - FilterURL(this, empty_allowed, url); |
| -} |
| - |
| -#if defined(ENABLE_WEBRTC) |
| -void RenderProcessHostImpl::EnableAudioDebugRecordings( |
| - const base::FilePath& file) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - |
| - // Enable AEC dump for each registered consumer. |
| - base::FilePath file_with_extensions = |
| - GetAecDumpFilePathWithExtensions(file); |
| - for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); |
| - it != aec_dump_consumers_.end(); ++it) { |
| - EnableAecDumpForId(file_with_extensions, *it); |
| - } |
| - |
| - // Enable mic input recording. AudioInputRendererHost is reference counted, so |
| - // it's lifetime is guarantueed during the lifetime of the closure. |
| - BrowserThread::PostTask( |
| - BrowserThread::IO, FROM_HERE, |
| - base::Bind(&AudioInputRendererHost::EnableDebugRecording, |
| - audio_input_renderer_host_, |
| - file)); |
| -} |
| - |
| -void RenderProcessHostImpl::DisableAudioDebugRecordings() { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - |
| - // Posting on the FILE thread and then replying back on the UI thread is only |
| - // for avoiding races between enable and disable. Nothing is done on the FILE |
| - // thread. |
| - BrowserThread::PostTaskAndReply( |
| - BrowserThread::FILE, FROM_HERE, |
| - base::Bind(&DisableAecDumpOnFileThread), |
| - base::Bind(&RenderProcessHostImpl::SendDisableAecDumpToRenderer, |
| - weak_factory_.GetWeakPtr())); |
| - |
| - // AudioInputRendererHost is reference counted, so it's lifetime is |
| - // guaranteed during the lifetime of the closure. |
| - BrowserThread::PostTask( |
| - BrowserThread::IO, FROM_HERE, |
| - base::Bind( |
| - &AudioInputRendererHost::DisableDebugRecording, |
| - audio_input_renderer_host_)); |
| -} |
| - |
| -void RenderProcessHostImpl::SetWebRtcLogMessageCallback( |
| - base::Callback<void(const std::string&)> callback) { |
| - webrtc_log_message_callback_ = callback; |
| -} |
| - |
| -RenderProcessHostImpl::WebRtcStopRtpDumpCallback |
| -RenderProcessHostImpl::StartRtpDump( |
| - bool incoming, |
| - bool outgoing, |
| - const WebRtcRtpPacketCallback& packet_callback) { |
| - if (!p2p_socket_dispatcher_host_.get()) |
| - return WebRtcStopRtpDumpCallback(); |
| - |
| - BrowserThread::PostTask(BrowserThread::IO, |
| - FROM_HERE, |
| - base::Bind(&P2PSocketDispatcherHost::StartRtpDump, |
| - p2p_socket_dispatcher_host_, |
| - incoming, |
| - outgoing, |
| - packet_callback)); |
| - |
| - if (stop_rtp_dump_callback_.is_null()) { |
| - stop_rtp_dump_callback_ = |
| - base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnUIThread, |
| - p2p_socket_dispatcher_host_); |
| - } |
| - return stop_rtp_dump_callback_; |
| -} |
| -#endif |
| - |
| -IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { |
| - return channel_.get(); |
| -} |
| - |
| -void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { |
| - channel_->AddFilter(filter->GetFilter()); |
| -} |
| - |
| -bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) { |
| - if (GetActiveViewCount() == count) |
| - return FastShutdownIfPossible(); |
| - return false; |
| -} |
| - |
| -bool RenderProcessHostImpl::FastShutdownStarted() const { |
| - return fast_shutdown_started_; |
| -} |
| - |
| -// static |
| -void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { |
| - g_all_hosts.Get().AddWithID(host, host_id); |
| -} |
| - |
| -// static |
| -void RenderProcessHostImpl::UnregisterHost(int host_id) { |
| - RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id); |
| - if (!host) |
| - return; |
| - |
| - g_all_hosts.Get().Remove(host_id); |
| - |
| - // Look up the map of site to process for the given browser_context, |
| - // in case we need to remove this process from it. It will be registered |
| - // under any sites it rendered that use process-per-site mode. |
| - SiteProcessMap* map = |
| - GetSiteProcessMapForBrowserContext(host->GetBrowserContext()); |
| - map->RemoveProcess(host); |
| -} |
| - |
| -// static |
| -void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph, |
| - bool empty_allowed, |
| - GURL* url) { |
| - ChildProcessSecurityPolicyImpl* policy = |
| - ChildProcessSecurityPolicyImpl::GetInstance(); |
| - |
| - if (empty_allowed && url->is_empty()) |
| - return; |
| - |
| - // The browser process should never hear the swappedout:// URL from any |
| - // of the renderer's messages. Check for this in debug builds, but don't |
| - // let it crash a release browser. |
| - DCHECK(GURL(kSwappedOutURL) != *url); |
| - |
| - if (!url->is_valid()) { |
| - // Have to use about:blank for the denied case, instead of an empty GURL. |
| - // This is because the browser treats navigation to an empty GURL as a |
| - // navigation to the home page. This is often a privileged page |
| - // (chrome://newtab/) which is exactly what we don't want. |
| - *url = GURL(url::kAboutBlankURL); |
| - return; |
| - } |
| - |
| - if (url->SchemeIs(url::kAboutScheme)) { |
| - // The renderer treats all URLs in the about: scheme as being about:blank. |
| - // Canonicalize about: URLs to about:blank. |
| - *url = GURL(url::kAboutBlankURL); |
| - } |
| - |
| - // Do not allow browser plugin guests to navigate to non-web URLs, since they |
| - // cannot swap processes or grant bindings. |
| - bool non_web_url_in_guest = rph->IsForGuestsOnly() && |
| - !(url->is_valid() && policy->IsWebSafeScheme(url->scheme())); |
| - |
| - if (non_web_url_in_guest || !policy->CanRequestURL(rph->GetID(), *url)) { |
| - // If this renderer is not permitted to request this URL, we invalidate the |
| - // URL. This prevents us from storing the blocked URL and becoming confused |
| - // later. |
| - VLOG(1) << "Blocked URL " << url->spec(); |
| - *url = GURL(url::kAboutBlankURL); |
| - } |
| -} |
| - |
| -// static |
| -bool RenderProcessHostImpl::IsSuitableHost( |
| - RenderProcessHost* host, |
| - BrowserContext* browser_context, |
| - const GURL& site_url) { |
| - if (run_renderer_in_process()) |
| - return true; |
| - |
| - if (host->GetBrowserContext() != browser_context) |
| - return false; |
| - |
| - // Do not allow sharing of guest hosts. This is to prevent bugs where guest |
| - // and non-guest storage gets mixed. In the future, we might consider enabling |
| - // the sharing of guests, in this case this check should be removed and |
| - // InSameStoragePartition should handle the possible sharing. |
| - if (host->IsForGuestsOnly()) |
| - return false; |
| - |
| - // Check whether the given host and the intended site_url will be using the |
| - // same StoragePartition, since a RenderProcessHost can only support a single |
| - // StoragePartition. This is relevant for packaged apps. |
| - StoragePartition* dest_partition = |
| - BrowserContext::GetStoragePartitionForSite(browser_context, site_url); |
| - if (!host->InSameStoragePartition(dest_partition)) |
| - return false; |
| - |
| - // TODO(nick): Consult the SiteIsolationPolicy here. https://crbug.com/513036 |
| - if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
| - host->GetID()) != |
| - WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL( |
| - browser_context, site_url)) { |
| - return false; |
| - } |
| - |
| - return GetContentClient()->browser()->IsSuitableHost(host, site_url); |
| -} |
| - |
| -// static |
| -bool RenderProcessHost::run_renderer_in_process() { |
| - return g_run_renderer_in_process_; |
| -} |
| - |
| -// static |
| -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)) { |
| - // Modify the current process' command line to include the browser locale, |
| - // as the renderer expects this flag to be set. |
| - const std::string locale = |
| - GetContentClient()->browser()->GetApplicationLocale(); |
| - command_line->AppendSwitchASCII(switches::kLang, locale); |
| - } |
| - // TODO(piman): we should really send configuration through bools rather |
| - // than by parsing strings, i.e. sending an IPC rather than command line |
| - // args. crbug.com/314909 |
| - AppendCompositorCommandLineFlags(command_line); |
| - } |
| -} |
| - |
| -// static |
| -RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - return iterator(g_all_hosts.Pointer()); |
| -} |
| - |
| -// static |
| -RenderProcessHost* RenderProcessHost::FromID(int render_process_id) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - return g_all_hosts.Get().Lookup(render_process_id); |
| -} |
| - |
| -// static |
| -bool RenderProcessHost::ShouldTryToUseExistingProcessHost( |
| - BrowserContext* browser_context, const GURL& url) { |
| - // If --site-per-process is enabled, do not try to reuse renderer processes |
| - // when over the limit. |
| - // TODO(nick): This is overly conservative and isn't launchable. Move this |
| - // logic into IsSuitableHost, and check |url| against the URL the process is |
| - // dedicated to. This will allow pages from the same site to share, and will |
| - // also allow non-isolated sites to share processes. https://crbug.com/513036 |
| - if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) |
| - return false; |
| - |
| - if (run_renderer_in_process()) |
| - return true; |
| - |
| - // NOTE: Sometimes it's necessary to create more render processes than |
| - // GetMaxRendererProcessCount(), for instance when we want to create |
| - // a renderer process for a browser context that has no existing |
| - // renderers. This is OK in moderation, since the |
| - // GetMaxRendererProcessCount() is conservative. |
| - if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount()) |
| - return true; |
| - |
| - return GetContentClient()->browser()-> |
| - ShouldTryToUseExistingProcessHost(browser_context, url); |
| -} |
| - |
| -// static |
| -RenderProcessHost* RenderProcessHost::GetExistingProcessHost( |
| - BrowserContext* browser_context, |
| - const GURL& site_url) { |
| - // First figure out which existing renderers we can use. |
| - std::vector<RenderProcessHost*> suitable_renderers; |
| - suitable_renderers.reserve(g_all_hosts.Get().size()); |
| - |
| - iterator iter(AllHostsIterator()); |
| - while (!iter.IsAtEnd()) { |
| - if (GetContentClient()->browser()->MayReuseHost(iter.GetCurrentValue()) && |
| - RenderProcessHostImpl::IsSuitableHost( |
| - iter.GetCurrentValue(), |
| - browser_context, site_url)) { |
| - suitable_renderers.push_back(iter.GetCurrentValue()); |
| - } |
| - iter.Advance(); |
| - } |
| - |
| - // Now pick a random suitable renderer, if we have any. |
| - 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 NULL; |
| -} |
| - |
| -// static |
| -bool RenderProcessHost::ShouldUseProcessPerSite( |
| - BrowserContext* browser_context, |
| - const GURL& url) { |
| - // Returns true if we should use the process-per-site model. This will be |
| - // the case if the --process-per-site switch is specified, or in |
| - // process-per-site-instance for particular sites (e.g., WebUI). |
| - // Note that --single-process is handled in ShouldTryToUseExistingProcessHost. |
| - const base::CommandLine& command_line = |
| - *base::CommandLine::ForCurrentProcess(); |
| - if (command_line.HasSwitch(switches::kProcessPerSite)) |
| - return true; |
| - |
| - // We want to consolidate particular sites like WebUI even when we are using |
| - // the process-per-tab or process-per-site-instance models. |
| - // Note: DevTools pages have WebUI type but should not reuse the same host. |
| - if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( |
| - browser_context, url) && |
| - !url.SchemeIs(kChromeDevToolsScheme)) { |
| - return true; |
| - } |
| - |
| - // Otherwise let the content client decide, defaulting to false. |
| - return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context, |
| - url); |
| -} |
| - |
| -// static |
| -RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite( |
| - BrowserContext* browser_context, |
| - const GURL& url) { |
| - // Look up the map of site to process for the given browser_context. |
| - SiteProcessMap* map = |
| - GetSiteProcessMapForBrowserContext(browser_context); |
| - |
| - // See if we have an existing process with appropriate bindings for this site. |
| - // If not, the caller should create a new process and register it. |
| - std::string site = SiteInstance::GetSiteForURL(browser_context, url) |
| - .possibly_invalid_spec(); |
| - RenderProcessHost* host = map->FindProcess(site); |
| - if (host && (!GetContentClient()->browser()->MayReuseHost(host) || |
| - !IsSuitableHost(host, browser_context, url))) { |
| - // The registered process does not have an appropriate set of bindings for |
| - // the url. Remove it from the map so we can register a better one. |
| - RecordAction( |
| - base::UserMetricsAction("BindingsMismatch_GetProcessHostPerSite")); |
| - map->RemoveProcess(host); |
| - host = NULL; |
| - } |
| - |
| - return host; |
| -} |
| - |
| -void RenderProcessHostImpl::RegisterProcessHostForSite( |
| - BrowserContext* browser_context, |
| - RenderProcessHost* process, |
| - const GURL& url) { |
| - // Look up the map of site to process for the given browser_context. |
| - SiteProcessMap* map = |
| - GetSiteProcessMapForBrowserContext(browser_context); |
| - |
| - // Only register valid, non-empty sites. Empty or invalid sites will not |
| - // use process-per-site mode. We cannot check whether the process has |
| - // appropriate bindings here, because the bindings have not yet been granted. |
| - std::string site = SiteInstance::GetSiteForURL(browser_context, url) |
| - .possibly_invalid_spec(); |
| - if (!site.empty()) |
| - map->RegisterProcess(site, process); |
| -} |
| - |
| -void RenderProcessHostImpl::ProcessDied(bool already_dead, |
| - RendererClosedDetails* known_details) { |
| - // Our child process has died. If we didn't expect it, it's a crash. |
| - // In any case, we need to let everyone know it's gone. |
| - // The OnChannelError notification can fire multiple times due to nested sync |
| - // calls to a renderer. If we don't have a valid channel here it means we |
| - // already handled the error. |
| - |
| - // It should not be possible for us to be called re-entrantly. |
| - DCHECK(!within_process_died_observer_); |
| - |
| - // It should not be possible for a process death notification to come in while |
| - // we are dying. |
| - DCHECK(!deleting_soon_); |
| - |
| - // child_process_launcher_ can be NULL in single process mode or if fast |
| - // termination happened. |
| - base::TerminationStatus status = base::TERMINATION_STATUS_NORMAL_TERMINATION; |
| - int exit_code = 0; |
| - if (known_details) { |
| - status = known_details->status; |
| - exit_code = known_details->exit_code; |
| - } else if (child_process_launcher_.get()) { |
| - status = child_process_launcher_->GetChildTerminationStatus(already_dead, |
| - &exit_code); |
| - if (already_dead && status == base::TERMINATION_STATUS_STILL_RUNNING) { |
| - // May be in case of IPC error, if it takes long time for renderer |
| - // to exit. Child process will be killed in any case during |
| - // child_process_launcher_.reset(). Make sure we will not broadcast |
| - // FrameHostMsg_RenderProcessGone with status |
| - // TERMINATION_STATUS_STILL_RUNNING, since this will break WebContentsImpl |
| - // logic. |
| - status = base::TERMINATION_STATUS_PROCESS_CRASHED; |
| - } |
| - } |
| - |
| - RendererClosedDetails details(status, exit_code); |
| - mojo_application_host_->WillDestroySoon(); |
| - |
| - child_process_launcher_.reset(); |
| - channel_.reset(); |
| - while (!queued_messages_.empty()) { |
| - delete queued_messages_.front(); |
| - queued_messages_.pop(); |
| - } |
| - |
| - within_process_died_observer_ = true; |
| - NotificationService::current()->Notify( |
| - NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| - Source<RenderProcessHost>(this), |
| - Details<RendererClosedDetails>(&details)); |
| - FOR_EACH_OBSERVER(RenderProcessHostObserver, |
| - observers_, |
| - RenderProcessExited(this, status, exit_code)); |
| - within_process_died_observer_ = false; |
| - |
| - gpu_message_filter_ = NULL; |
| - message_port_message_filter_ = NULL; |
| - RemoveUserData(kSessionStorageHolderKey); |
| - |
| - // RenderProcessGone handlers might navigate or perform other actions that |
| - // require a connection. Ensure that there is one before calling them. |
| - mojo_application_host_.reset(new MojoApplicationHost); |
| - |
| - IDMap<IPC::Listener>::iterator iter(&listeners_); |
| - while (!iter.IsAtEnd()) { |
| - iter.GetCurrentValue()->OnMessageReceived( |
| - FrameHostMsg_RenderProcessGone(iter.GetCurrentKey(), |
| - static_cast<int>(status), |
| - exit_code)); |
| - iter.Advance(); |
| - } |
| - |
| - // It's possible that one of the calls out to the observers might have caused |
| - // this object to be no longer needed. |
| - if (delayed_cleanup_needed_) |
| - Cleanup(); |
| - |
| - // This object is not deleted at this point and might be reused later. |
| - // TODO(darin): clean this up |
| -} |
| - |
| -size_t RenderProcessHost::GetActiveViewCount() { |
| - size_t num_active_views = 0; |
| - scoped_ptr<RenderWidgetHostIterator> widgets( |
| - RenderWidgetHost::GetRenderWidgetHosts()); |
| - while (RenderWidgetHost* widget = widgets->GetNextHost()) { |
| - // Count only RenderWidgetHosts in this process. |
| - if (widget->GetProcess()->GetID() == GetID()) |
| - num_active_views++; |
| - } |
| - return num_active_views; |
| -} |
| - |
| -#if defined(ENABLE_WEBRTC) |
| -void RenderProcessHostImpl::WebRtcLogMessage(const std::string& message) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - if (!webrtc_log_message_callback_.is_null()) |
| - webrtc_log_message_callback_.Run(message); |
| -} |
| -#endif |
| - |
| -void RenderProcessHostImpl::ReleaseOnCloseACK( |
| - RenderProcessHost* host, |
| - const SessionStorageNamespaceMap& sessions, |
| - int view_route_id) { |
| - DCHECK(host); |
| - if (sessions.empty()) |
| - return; |
| - SessionStorageHolder* holder = static_cast<SessionStorageHolder*> |
| - (host->GetUserData(kSessionStorageHolderKey)); |
| - if (!holder) { |
| - holder = new SessionStorageHolder(); |
| - host->SetUserData( |
| - kSessionStorageHolderKey, |
| - holder); |
| - } |
| - holder->Hold(sessions, view_route_id); |
| -} |
| - |
| -void RenderProcessHostImpl::OnShutdownRequest() { |
| - // Don't shut down if there are active RenderViews, or if there are pending |
| - // RenderViews being swapped back in. |
| - // In single process mode, we never shutdown the renderer. |
| - if (pending_views_ || run_renderer_in_process() || GetActiveViewCount() > 0) |
| - return; |
| - |
| - // Notify any contents that might have swapped out renderers from this |
| - // process. They should not attempt to swap them back in. |
| - FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_, |
| - RenderProcessWillExit(this)); |
| - |
| - mojo_application_host_->WillDestroySoon(); |
| - |
| - Send(new ChildProcessMsg_Shutdown()); |
| -} |
| - |
| -void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) { |
| - SetSuddenTerminationAllowed(enabled); |
| -} |
| - |
| -void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) { |
| - TRACE_EVENT1("renderer_host", "RenderProcessHostImpl::SetBackgrounded", |
| - "backgrounded", backgrounded); |
| - // Note: we always set the backgrounded_ value. If the process is NULL |
| - // (and hence hasn't been created yet), we will set the process priority |
| - // later when we create the process. |
| - backgrounded_ = backgrounded; |
| - if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) |
| - return; |
| - |
| - // Don't background processes which have active audio streams. |
| - if (backgrounded_ && audio_renderer_host_->HasActiveAudio()) |
| - return; |
| - |
| - const base::CommandLine* command_line = |
| - base::CommandLine::ForCurrentProcess(); |
| - if (command_line->HasSwitch(switches::kDisableRendererBackgrounding)) |
| - return; |
| - |
| -#if defined(OS_WIN) |
| - // The cbstext.dll loads as a global GetMessage hook in the browser process |
| - // and intercepts/unintercepts the kernel32 API SetPriorityClass in a |
| - // background thread. If the UI thread invokes this API just when it is |
| - // intercepted the stack is messed up on return from the interceptor |
| - // which causes random crashes in the browser process. Our hack for now |
| - // is to not invoke the SetPriorityClass API if the dll is loaded. |
| - if (GetModuleHandle(L"cbstext.dll")) |
| - return; |
| -#endif // OS_WIN |
| - |
| -#if defined(OS_WIN) |
| - // Same as below, but bound to an experiment (http://crbug.com/458594 ). |
| - // Enabled by default in the absence of field trials to get coverage on the |
| - // perf waterfall. |
| - base::FieldTrial* trial = |
| - base::FieldTrialList::Find("BackgroundRendererProcesses"); |
| - if (!trial || !base::StartsWith(trial->group_name(), "Disallow", |
| - base::CompareCase::SENSITIVE)) { |
| - child_process_launcher_->SetProcessBackgrounded(backgrounded); |
| - } |
| -#else |
| - // Control the background state from the browser process, otherwise the task |
| - // telling the renderer to "unbackground" itself may be preempted by other |
| - // tasks executing at lowered priority ahead of it or simply by not being |
| - // swiftly scheduled by the OS per the low process priority |
| - // (http://crbug.com/398103). |
| - child_process_launcher_->SetProcessBackgrounded(backgrounded); |
| -#endif // OS_WIN |
| - |
| - // Notify the child process of background state. |
| - Send(new ChildProcessMsg_SetProcessBackgrounded(backgrounded)); |
| -} |
| - |
| -void RenderProcessHostImpl::OnProcessLaunched() { |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile1( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 RenderProcessHostImpl::OnProcessLaunched::Start")); |
| - // No point doing anything, since this object will be destructed soon. We |
| - // especially don't want to send the RENDERER_PROCESS_CREATED notification, |
| - // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to |
| - // properly cleanup. |
| - if (deleting_soon_) |
| - return; |
| - |
| - if (child_process_launcher_) { |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile2( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 RenderProcessHostImpl::OnProcessLaunched::Backgrounded")); |
| - DCHECK(child_process_launcher_->GetProcess().IsValid()); |
| - SetBackgrounded(backgrounded_); |
| - } |
| - |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile3( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 RenderProcessHostImpl::OnProcessLaunched::Notify")); |
| - // NOTE: This needs to be before sending queued messages because |
| - // ExtensionService uses this notification to initialize the renderer process |
| - // with state that must be there before any JavaScript executes. |
| - // |
| - // The queued messages contain such things as "navigate". If this notification |
| - // was after, we can end up executing JavaScript before the initialization |
| - // happens. |
| - NotificationService::current()->Notify( |
| - NOTIFICATION_RENDERER_PROCESS_CREATED, |
| - Source<RenderProcessHost>(this), |
| - NotificationService::NoDetails()); |
| - |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile4( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 RenderProcessHostImpl::OnProcessLaunched::MojoActivate")); |
| - // Allow Mojo to be setup before the renderer sees any Chrome IPC messages. |
| - // This way, Mojo can be safely used from the renderer in response to any |
| - // Chrome IPC message. |
| - mojo_application_host_->Activate(this, GetHandle()); |
| - |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile5( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 RenderProcessHostImpl::OnProcessLaunched::MojoClientLaunch")); |
| - |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile6( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 " |
| - "RenderProcessHostImpl::OnProcessLaunched::SendQueuedMessages")); |
| - while (!queued_messages_.empty()) { |
| - Send(queued_messages_.front()); |
| - queued_messages_.pop(); |
| - } |
| - |
| -#if defined(ENABLE_WEBRTC) |
| - // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| - // is fixed. |
| - tracked_objects::ScopedTracker tracking_profile7( |
| - FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| - "465841 RenderProcessHostImpl::OnProcessLaunched::EnableAec")); |
| - if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) { |
| - EnableAudioDebugRecordings( |
| - WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath()); |
| - } |
| -#endif |
| -} |
| - |
| -void RenderProcessHostImpl::OnProcessLaunchFailed() { |
| - // If this object will be destructed soon, then observers have already been |
| - // sent a RenderProcessHostDestroyed notification, and we must observe our |
| - // contract that says that will be the last call. |
| - if (deleting_soon_) |
| - return; |
| - |
| - // TODO(wfh): Fill in the real error code here see crbug.com/526198. |
| - RendererClosedDetails details { base::TERMINATION_STATUS_LAUNCH_FAILED, |
| - -1 }; |
| - ProcessDied(true, &details); |
| -} |
| - |
| -scoped_refptr<AudioRendererHost> |
| -RenderProcessHostImpl::audio_renderer_host() const { |
| - return audio_renderer_host_; |
| -} |
| - |
| -void RenderProcessHostImpl::OnUserMetricsRecordAction( |
| - const std::string& action) { |
| - RecordComputedAction(action); |
| -} |
| - |
| -void RenderProcessHostImpl::OnCloseACK(int old_route_id) { |
| - SessionStorageHolder* holder = static_cast<SessionStorageHolder*> |
| - (GetUserData(kSessionStorageHolderKey)); |
| - if (!holder) |
| - return; |
| - holder->Release(old_route_id); |
| -} |
| - |
| -void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) { |
| - MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size); |
| -} |
| - |
| -void RenderProcessHostImpl::OnGpuSwitched() { |
| - // We are updating all widgets including swapped out ones. |
| - scoped_ptr<RenderWidgetHostIterator> widgets( |
| - RenderWidgetHostImpl::GetAllRenderWidgetHosts()); |
| - while (RenderWidgetHost* widget = widgets->GetNextHost()) { |
| - if (!widget->IsRenderView()) |
| - continue; |
| - |
| - // Skip widgets in other processes. |
| - if (widget->GetProcess()->GetID() != GetID()) |
| - continue; |
| - |
| - RenderViewHost* rvh = RenderViewHost::From(widget); |
| - rvh->OnWebkitPreferencesChanged(); |
| - } |
| -} |
| - |
| -#if defined(ENABLE_WEBRTC) |
| -void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { |
| - BrowserThread::PostTask( |
| - BrowserThread::UI, |
| - FROM_HERE, |
| - base::Bind( |
| - &RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, |
| - weak_factory_.GetWeakPtr(), |
| - id)); |
| -} |
| - |
| -void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { |
| - BrowserThread::PostTask( |
| - BrowserThread::UI, |
| - FROM_HERE, |
| - base::Bind( |
| - &RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread, |
| - weak_factory_.GetWeakPtr(), |
| - id)); |
| -} |
| - |
| -void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int id) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - aec_dump_consumers_.push_back(id); |
| - |
| - if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) { |
| - base::FilePath file_with_extensions = GetAecDumpFilePathWithExtensions( |
| - WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath()); |
| - EnableAecDumpForId(file_with_extensions, id); |
| - } |
| -} |
| - |
| -void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); |
| - it != aec_dump_consumers_.end(); ++it) { |
| - if (*it == id) { |
| - aec_dump_consumers_.erase(it); |
| - break; |
| - } |
| - } |
| -} |
| - |
| -void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file, |
| - int id) { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - BrowserThread::PostTaskAndReplyWithResult( |
| - BrowserThread::FILE, FROM_HERE, |
| - base::Bind(&CreateAecDumpFileForProcess, |
| - file.AddExtension(IntToStringType(id)), |
| - GetHandle()), |
| - base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer, |
| - weak_factory_.GetWeakPtr(), |
| - id)); |
| -} |
| - |
| -void RenderProcessHostImpl::SendAecDumpFileToRenderer( |
| - int id, |
| - IPC::PlatformFileForTransit file_for_transit) { |
| - if (file_for_transit == IPC::InvalidPlatformFileForTransit()) |
| - return; |
| - Send(new AecDumpMsg_EnableAecDump(id, file_for_transit)); |
| -} |
| - |
| -void RenderProcessHostImpl::SendDisableAecDumpToRenderer() { |
| - Send(new AecDumpMsg_DisableAecDump()); |
| -} |
| - |
| -base::FilePath RenderProcessHostImpl::GetAecDumpFilePathWithExtensions( |
| - const base::FilePath& file) { |
| - return file.AddExtension(IntToStringType(base::GetProcId(GetHandle()))) |
| - .AddExtension(kAecDumpFileNameAddition); |
| -} |
| -#endif // defined(ENABLE_WEBRTC) |
| - |
| -void RenderProcessHostImpl::IncrementWorkerRefCount() { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - ++worker_ref_count_; |
| - if (worker_ref_count_ > max_worker_count_) |
| - max_worker_count_ = worker_ref_count_; |
| -} |
| - |
| -void RenderProcessHostImpl::DecrementWorkerRefCount() { |
| - DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| - DCHECK_GT(worker_ref_count_, 0); |
| - --worker_ref_count_; |
| - if (worker_ref_count_ == 0) |
| - Cleanup(); |
| -} |
| - |
| -void RenderProcessHostImpl::GetAudioOutputControllers( |
| - const GetAudioOutputControllersCallback& callback) const { |
| - audio_renderer_host()->GetOutputControllers(callback); |
| -} |
| - |
| -BluetoothDispatcherHost* RenderProcessHostImpl::GetBluetoothDispatcherHost() { |
| - return bluetooth_dispatcher_host_.get(); |
| -} |
| - |
| -} // namespace content |
| +// Copyright 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +// Represents the browser side of the browser <--> renderer communication |
| +// channel. There will be one RenderProcessHost per renderer process. |
| + |
| +#include "content/browser/renderer_host/render_process_host_impl.h" |
| + |
| +#include <algorithm> |
| +#include <limits> |
| +#include <vector> |
| + |
| +#include "base/base_switches.h" |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/callback.h" |
| +#include "base/command_line.h" |
| +#include "base/debug/dump_without_crashing.h" |
| +#include "base/files/file.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/location.h" |
| +#include "base/logging.h" |
| +#include "base/metrics/field_trial.h" |
| +#include "base/metrics/histogram.h" |
| +#include "base/process/process_handle.h" |
| +#include "base/profiler/scoped_tracker.h" |
| +#include "base/rand_util.h" |
| +#include "base/single_thread_task_runner.h" |
| +#include "base/stl_util.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/strings/string_util.h" |
| +#include "base/supports_user_data.h" |
| +#include "base/sys_info.h" |
| +#include "base/threading/thread.h" |
| +#include "base/threading/thread_restrictions.h" |
| +#include "base/trace_event/trace_event.h" |
| +#include "base/tracked_objects.h" |
| +#include "cc/base/switches.h" |
| +#include "components/tracing/tracing_switches.h" |
| +#include "content/browser/appcache/appcache_dispatcher_host.h" |
| +#include "content/browser/appcache/chrome_appcache_service.h" |
| +#include "content/browser/background_sync/background_sync_service_impl.h" |
| +#include "content/browser/bad_message.h" |
| +#include "content/browser/bluetooth/bluetooth_dispatcher_host.h" |
| +#include "content/browser/browser_child_process_host_impl.h" |
| +#include "content/browser/browser_main.h" |
| +#include "content/browser/browser_main_loop.h" |
| +#include "content/browser/browser_plugin/browser_plugin_message_filter.h" |
| +#include "content/browser/cache_storage/cache_storage_context_impl.h" |
| +#include "content/browser/cache_storage/cache_storage_dispatcher_host.h" |
| +#include "content/browser/child_process_security_policy_impl.h" |
| +#include "content/browser/device_sensors/device_light_message_filter.h" |
| +#include "content/browser/device_sensors/device_motion_message_filter.h" |
| +#include "content/browser/device_sensors/device_orientation_message_filter.h" |
| +#include "content/browser/dom_storage/dom_storage_context_wrapper.h" |
| +#include "content/browser/dom_storage/dom_storage_message_filter.h" |
| +#include "content/browser/download/mhtml_generation_manager.h" |
| +#include "content/browser/fileapi/chrome_blob_storage_context.h" |
| +#include "content/browser/fileapi/fileapi_message_filter.h" |
| +#include "content/browser/frame_host/render_frame_message_filter.h" |
| +#include "content/browser/geofencing/geofencing_dispatcher_host.h" |
| +#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h" |
| +#include "content/browser/gpu/compositor_util.h" |
| +#include "content/browser/gpu/gpu_data_manager_impl.h" |
| +#include "content/browser/gpu/gpu_process_host.h" |
| +#include "content/browser/gpu/shader_disk_cache.h" |
| +#include "content/browser/histogram_message_filter.h" |
| +#include "content/browser/indexed_db/indexed_db_context_impl.h" |
| +#include "content/browser/indexed_db/indexed_db_dispatcher_host.h" |
| +#include "content/browser/loader/resource_message_filter.h" |
| +#include "content/browser/loader/resource_scheduler_filter.h" |
| +#include "content/browser/media/capture/audio_mirroring_manager.h" |
| +#include "content/browser/media/media_internals.h" |
| +#include "content/browser/media/midi_host.h" |
| +#include "content/browser/memory/memory_message_filter.h" |
| +#include "content/browser/message_port_message_filter.h" |
| +#include "content/browser/mime_registry_message_filter.h" |
| +#include "content/browser/mojo/mojo_application_host.h" |
| +#include "content/browser/navigator_connect/service_port_service_impl.h" |
| +#include "content/browser/notifications/notification_message_filter.h" |
| +#include "content/browser/permissions/permission_service_context.h" |
| +#include "content/browser/permissions/permission_service_impl.h" |
| +#include "content/browser/profiler_message_filter.h" |
| +#include "content/browser/push_messaging/push_messaging_message_filter.h" |
| +#include "content/browser/quota_dispatcher_host.h" |
| +#include "content/browser/renderer_host/clipboard_message_filter.h" |
| +#include "content/browser/renderer_host/database_message_filter.h" |
| +#include "content/browser/renderer_host/file_utilities_message_filter.h" |
| +#include "content/browser/renderer_host/gamepad_browser_message_filter.h" |
| +#include "content/browser/renderer_host/gpu_message_filter.h" |
| +#include "content/browser/renderer_host/media/audio_input_renderer_host.h" |
| +#include "content/browser/renderer_host/media/audio_renderer_host.h" |
| +#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" |
| +#include "content/browser/renderer_host/media/peer_connection_tracker_host.h" |
| +#include "content/browser/renderer_host/media/video_capture_host.h" |
| +#include "content/browser/renderer_host/memory_benchmark_message_filter.h" |
| +#include "content/browser/renderer_host/pepper/pepper_message_filter.h" |
| +#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h" |
| +#include "content/browser/renderer_host/render_message_filter.h" |
| +#include "content/browser/renderer_host/render_view_host_delegate.h" |
| +#include "content/browser/renderer_host/render_view_host_impl.h" |
| +#include "content/browser/renderer_host/render_widget_helper.h" |
| +#include "content/browser/renderer_host/render_widget_host_impl.h" |
| +#include "content/browser/renderer_host/text_input_client_message_filter.h" |
| +#include "content/browser/renderer_host/websocket_dispatcher_host.h" |
| +#include "content/browser/resolve_proxy_msg_helper.h" |
| +#include "content/browser/service_worker/service_worker_context_wrapper.h" |
| +#include "content/browser/service_worker/service_worker_dispatcher_host.h" |
| +#include "content/browser/shared_worker/shared_worker_message_filter.h" |
| +#include "content/browser/shared_worker/worker_storage_partition.h" |
| +#include "content/browser/speech/speech_recognition_dispatcher_host.h" |
| +#include "content/browser/storage_partition_impl.h" |
| +#include "content/browser/streams/stream_context.h" |
| +#include "content/browser/tracing/trace_message_filter.h" |
| +#include "content/browser/webui/web_ui_controller_factory_registry.h" |
| +#include "content/common/child_process_host_impl.h" |
| +#include "content/common/child_process_messages.h" |
| +#include "content/common/content_switches_internal.h" |
| +#include "content/common/frame_messages.h" |
| +#include "content/common/gpu/gpu_messages.h" |
| +#include "content/common/in_process_child_thread_params.h" |
| +#include "content/common/mojo/channel_init.h" |
| +#include "content/common/mojo/mojo_messages.h" |
| +#include "content/common/render_process_messages.h" |
| +#include "content/common/resource_messages.h" |
| +#include "content/common/site_isolation_policy.h" |
| +#include "content/common/view_messages.h" |
| +#include "content/public/browser/browser_context.h" |
| +#include "content/public/browser/content_browser_client.h" |
| +#include "content/public/browser/navigator_connect_context.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/notification_types.h" |
| +#include "content/public/browser/render_process_host_factory.h" |
| +#include "content/public/browser/render_process_host_observer.h" |
| +#include "content/public/browser/render_widget_host.h" |
| +#include "content/public/browser/render_widget_host_iterator.h" |
| +#include "content/public/browser/render_widget_host_view_frame_subscriber.h" |
| +#include "content/public/browser/resource_context.h" |
| +#include "content/public/browser/user_metrics.h" |
| +#include "content/public/browser/worker_service.h" |
| +#include "content/public/common/child_process_host.h" |
| +#include "content/public/common/content_constants.h" |
| +#include "content/public/common/content_switches.h" |
| +#include "content/public/common/mojo_channel_switches.h" |
| +#include "content/public/common/process_type.h" |
| +#include "content/public/common/resource_type.h" |
| +#include "content/public/common/result_codes.h" |
| +#include "content/public/common/sandboxed_process_launcher_delegate.h" |
| +#include "content/public/common/url_constants.h" |
| +#include "device/battery/battery_monitor_impl.h" |
| +#include "device/vibration/vibration_manager_impl.h" |
| +#include "gpu/GLES2/gl2extchromium.h" |
| +#include "gpu/command_buffer/client/gpu_switches.h" |
| +#include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| +#include "gpu/command_buffer/service/gpu_switches.h" |
| +#include "ipc/ipc_channel.h" |
| +#include "ipc/ipc_logging.h" |
| +#include "ipc/ipc_switches.h" |
| +#include "ipc/mojo/ipc_channel_mojo.h" |
| +#include "media/base/media_switches.h" |
| +#include "net/url_request/url_request_context_getter.h" |
| +#include "ppapi/shared_impl/ppapi_switches.h" |
| +#include "storage/browser/fileapi/sandbox_file_system_backend.h" |
| +#include "third_party/icu/source/common/unicode/unistr.h" |
| +#include "third_party/icu/source/i18n/unicode/timezone.h" |
| +#include "third_party/skia/include/core/SkBitmap.h" |
| +#include "ui/base/ui_base_switches.h" |
| +#include "ui/events/event_switches.h" |
| +#include "ui/gfx/switches.h" |
| +#include "ui/gl/gl_switches.h" |
| +#include "ui/gl/gpu_switching_manager.h" |
| +#include "ui/native_theme/native_theme_switches.h" |
| + |
| +#if defined(OS_ANDROID) |
| +#include "content/browser/android/child_process_launcher_android.h" |
| +#include "content/browser/media/android/browser_demuxer_android.h" |
| +#include "content/browser/mojo/service_registrar_android.h" |
| +#include "content/browser/screen_orientation/screen_orientation_message_filter_android.h" |
| +#endif |
| + |
| +#if defined(OS_WIN) |
| +#include "base/win/scoped_com_initializer.h" |
| +#include "base/win/windows_version.h" |
| +#include "content/common/font_cache_dispatcher_win.h" |
| +#include "content/common/sandbox_win.h" |
| +#include "sandbox/win/src/sandbox_policy.h" |
| +#include "ui/gfx/win/dpi.h" |
| +#endif |
| + |
| +#if defined(OS_MACOSX) && !defined(OS_IOS) |
| +#include "content/browser/bootstrap_sandbox_manager_mac.h" |
| +#include "content/browser/browser_io_surface_manager_mac.h" |
| +#include "content/browser/mach_broker_mac.h" |
|
gab
2015/09/30 13:33:31
rm this include
sebsg
2015/09/30 18:26:43
Done.
|
| +#endif |
| + |
| +#if defined(USE_OZONE) |
| +#include "ui/ozone/public/client_native_pixmap_factory.h" |
| +#include "ui/ozone/public/ozone_platform.h" |
| +#include "ui/ozone/public/ozone_switches.h" |
| +#endif |
| + |
| +#if defined(ENABLE_BROWSER_CDMS) |
| +#include "content/browser/media/cdm/browser_cdm_manager.h" |
| +#endif |
| + |
| +#if defined(ENABLE_PLUGINS) |
| +#include "content/browser/plugin_service_impl.h" |
| +#endif |
| + |
| +#if defined(ENABLE_WEBRTC) |
| +#include "content/browser/media/webrtc_internals.h" |
| +#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h" |
| +#include "content/browser/renderer_host/media/webrtc_identity_service_host.h" |
| +#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" |
| +#include "content/common/media/aec_dump_messages.h" |
| +#include "content/common/media/media_stream_messages.h" |
| +#endif |
| + |
| +#if defined(OS_WIN) |
| +#define IntToStringType base::IntToString16 |
| +#else |
| +#define IntToStringType base::IntToString |
| +#endif |
| + |
| +namespace content { |
| +namespace { |
| + |
| +const char kSiteProcessMapKeyName[] = "content_site_process_map"; |
| + |
| +#ifdef ENABLE_WEBRTC |
| +const base::FilePath::CharType kAecDumpFileNameAddition[] = |
| + FILE_PATH_LITERAL("aec_dump"); |
| +#endif |
| + |
| +void CacheShaderInfo(int32 id, base::FilePath path) { |
| + ShaderCacheFactory::GetInstance()->SetCacheInfo(id, path); |
| +} |
| + |
| +void RemoveShaderInfo(int32 id) { |
| + ShaderCacheFactory::GetInstance()->RemoveCacheInfo(id); |
| +} |
| + |
| +net::URLRequestContext* GetRequestContext( |
| + scoped_refptr<net::URLRequestContextGetter> request_context, |
| + scoped_refptr<net::URLRequestContextGetter> media_request_context, |
| + ResourceType resource_type) { |
| + // If the request has resource type of RESOURCE_TYPE_MEDIA, we use a request |
| + // context specific to media for handling it because these resources have |
| + // specific needs for caching. |
| + if (resource_type == RESOURCE_TYPE_MEDIA) |
| + return media_request_context->GetURLRequestContext(); |
| + return request_context->GetURLRequestContext(); |
| +} |
| + |
| +void GetContexts( |
| + ResourceContext* resource_context, |
| + scoped_refptr<net::URLRequestContextGetter> request_context, |
| + scoped_refptr<net::URLRequestContextGetter> media_request_context, |
| + const ResourceHostMsg_Request& request, |
| + ResourceContext** resource_context_out, |
| + net::URLRequestContext** request_context_out) { |
| + *resource_context_out = resource_context; |
| + *request_context_out = GetRequestContext( |
| + request_context, media_request_context, request.resource_type); |
| +} |
| + |
| +#if defined(ENABLE_WEBRTC) |
| + |
| +// Allow us to only run the trial in the first renderer. |
| +bool has_done_stun_trials = false; |
| + |
| +// Creates a file used for diagnostic echo canceller recordings for handing |
| +// over to the renderer. |
| +IPC::PlatformFileForTransit CreateAecDumpFileForProcess( |
| + base::FilePath file_path, |
| + base::ProcessHandle process) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| + base::File dump_file(file_path, |
| + base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND); |
| + if (!dump_file.IsValid()) { |
| + VLOG(1) << "Could not open AEC dump file, error=" |
| + << dump_file.error_details(); |
| + return IPC::InvalidPlatformFileForTransit(); |
| + } |
| + return IPC::TakeFileHandleForProcess(dump_file.Pass(), process); |
| +} |
| + |
| +// Does nothing. Just to avoid races between enable and disable. |
| +void DisableAecDumpOnFileThread() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| +} |
| +#endif |
| + |
| +// the global list of all renderer processes |
| +base::LazyInstance<IDMap<RenderProcessHost>>::Leaky g_all_hosts = |
| + LAZY_INSTANCE_INITIALIZER; |
| + |
| +// Map of site to process, to ensure we only have one RenderProcessHost per |
| +// site in process-per-site mode. Each map is specific to a BrowserContext. |
| +class SiteProcessMap : public base::SupportsUserData::Data { |
| + public: |
| + typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap; |
| + SiteProcessMap() {} |
| + |
| + void RegisterProcess(const std::string& site, RenderProcessHost* process) { |
| + map_[site] = process; |
| + } |
| + |
| + RenderProcessHost* FindProcess(const std::string& site) { |
| + SiteToProcessMap::iterator i = map_.find(site); |
| + if (i != map_.end()) |
| + return i->second; |
| + return NULL; |
| + } |
| + |
| + void RemoveProcess(RenderProcessHost* host) { |
| + // Find all instances of this process in the map, then separately remove |
| + // them. |
| + std::set<std::string> sites; |
| + for (SiteToProcessMap::const_iterator i = map_.begin(); i != map_.end(); |
| + i++) { |
| + if (i->second == host) |
| + sites.insert(i->first); |
| + } |
| + for (std::set<std::string>::iterator i = sites.begin(); i != sites.end(); |
| + i++) { |
| + SiteToProcessMap::iterator iter = map_.find(*i); |
| + if (iter != map_.end()) { |
| + DCHECK_EQ(iter->second, host); |
| + map_.erase(iter); |
| + } |
| + } |
| + } |
| + |
| + private: |
| + SiteToProcessMap map_; |
| +}; |
| + |
| +// Find the SiteProcessMap specific to the given context. |
| +SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) { |
| + DCHECK(context); |
| + SiteProcessMap* map = static_cast<SiteProcessMap*>( |
| + context->GetUserData(kSiteProcessMapKeyName)); |
| + if (!map) { |
| + map = new SiteProcessMap(); |
| + context->SetUserData(kSiteProcessMapKeyName, map); |
| + } |
| + return map; |
| +} |
| + |
| +// NOTE: changes to this class need to be reviewed by the security team. |
| +class RendererSandboxedProcessLauncherDelegate |
| + : public SandboxedProcessLauncherDelegate { |
| + public: |
| + explicit RendererSandboxedProcessLauncherDelegate(IPC::ChannelProxy* channel) |
| +#if defined(OS_POSIX) |
| + : ipc_fd_(channel->TakeClientFileDescriptor()) |
| +#endif // OS_POSIX |
| + { |
| + } |
| + |
| + ~RendererSandboxedProcessLauncherDelegate() override {} |
| + |
| +#if defined(OS_WIN) |
| + void PreSpawnTarget(sandbox::TargetPolicy* policy, bool* success) override { |
| + AddBaseHandleClosePolicy(policy); |
| + |
| + const base::string16& sid = |
| + GetContentClient()->browser()->GetAppContainerSidForSandboxType( |
| + GetSandboxType()); |
| + if (!sid.empty()) |
| + AddAppContainerPolicy(policy, sid.c_str()); |
| + |
| + GetContentClient()->browser()->PreSpawnRenderer(policy, success); |
| + } |
| + |
| +#elif defined(OS_POSIX) |
| + bool ShouldUseZygote() override { |
| + const base::CommandLine& browser_command_line = |
| + *base::CommandLine::ForCurrentProcess(); |
| + base::CommandLine::StringType renderer_prefix = |
| + browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); |
| + return renderer_prefix.empty(); |
| + } |
| + base::ScopedFD TakeIpcFd() override { return ipc_fd_.Pass(); } |
| +#endif // OS_WIN |
| + |
| + SandboxType GetSandboxType() override { return SANDBOX_TYPE_RENDERER; } |
| + |
| + private: |
| +#if defined(OS_POSIX) |
| + base::ScopedFD ipc_fd_; |
| +#endif // OS_POSIX |
| +}; |
| + |
| +const char kSessionStorageHolderKey[] = "kSessionStorageHolderKey"; |
| + |
| +class SessionStorageHolder : public base::SupportsUserData::Data { |
| + public: |
| + SessionStorageHolder() {} |
| + ~SessionStorageHolder() override {} |
| + |
| + void Hold(const SessionStorageNamespaceMap& sessions, int view_route_id) { |
| + session_storage_namespaces_awaiting_close_[view_route_id] = sessions; |
| + } |
| + |
| + void Release(int old_route_id) { |
| + session_storage_namespaces_awaiting_close_.erase(old_route_id); |
| + } |
| + |
| + private: |
| + std::map<int, SessionStorageNamespaceMap> |
| + session_storage_namespaces_awaiting_close_; |
| + DISALLOW_COPY_AND_ASSIGN(SessionStorageHolder); |
| +}; |
| + |
| +std::string UintVectorToString(const std::vector<unsigned>& vector) { |
| + std::string str; |
| + for (auto it : vector) { |
| + if (!str.empty()) |
| + str += ","; |
| + str += base::UintToString(it); |
| + } |
| + return str; |
| +} |
| + |
| +} // namespace |
| + |
| +RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
| + |
| +base::MessageLoop* g_in_process_thread; |
| + |
| +base::MessageLoop* |
| +RenderProcessHostImpl::GetInProcessRendererThreadForTesting() { |
| + return g_in_process_thread; |
| +} |
| + |
| +// Stores the maximum number of renderer processes the content module can |
| +// create. |
| +static size_t g_max_renderer_count_override = 0; |
| + |
| +// static |
| +size_t RenderProcessHost::GetMaxRendererProcessCount() { |
| + if (g_max_renderer_count_override) |
| + return g_max_renderer_count_override; |
| + |
| +#if defined(OS_ANDROID) |
| + // On Android we don't maintain a limit of renderer process hosts - we are |
| + // happy with keeping a lot of these, as long as the number of live renderer |
| + // processes remains reasonable, and on Android the OS takes care of that. |
| + return std::numeric_limits<size_t>::max(); |
| +#endif |
| + |
| + // On other platforms, we calculate the maximum number of renderer process |
| + // hosts according to the amount of installed memory as reported by the OS. |
| + // The calculation assumes that you want the renderers to use half of the |
| + // installed RAM and assuming that each WebContents uses ~40MB. If you modify |
| + // this assumption, you need to adjust the ThirtyFourTabs test to match the |
| + // expected number of processes. |
| + // |
| + // With the given amounts of installed memory below on a 32-bit CPU, the |
| + // maximum renderer count will roughly be as follows: |
| + // |
| + // 128 MB -> 3 |
| + // 512 MB -> 6 |
| + // 1024 MB -> 12 |
| + // 4096 MB -> 51 |
| + // 16384 MB -> 82 (kMaxRendererProcessCount) |
| + |
| + static size_t max_count = 0; |
| + if (!max_count) { |
| + const size_t kEstimatedWebContentsMemoryUsage = |
| +#if defined(ARCH_CPU_64_BITS) |
| + 60; // In MB |
| +#else |
| + 40; // In MB |
| +#endif |
| + max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2; |
| + max_count /= kEstimatedWebContentsMemoryUsage; |
| + |
| + const size_t kMinRendererProcessCount = 3; |
| + max_count = std::max(max_count, kMinRendererProcessCount); |
| + max_count = std::min(max_count, kMaxRendererProcessCount); |
| + } |
| + return max_count; |
| +} |
| + |
| +// static |
| +bool g_run_renderer_in_process_ = false; |
| + |
| +// static |
| +void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { |
| + g_max_renderer_count_override = count; |
| +} |
| + |
| +RenderProcessHostImpl::RenderProcessHostImpl( |
| + BrowserContext* browser_context, |
| + StoragePartitionImpl* storage_partition_impl, |
| + bool is_for_guests_only) |
| + : fast_shutdown_started_(false), |
| + deleting_soon_(false), |
| +#ifndef NDEBUG |
| + is_self_deleted_(false), |
| +#endif |
| + pending_views_(0), |
| + mojo_application_host_(new MojoApplicationHost), |
| + visible_widgets_(0), |
| + is_process_backgrounded_(false), |
| + is_initialized_(false), |
| + id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), |
| + browser_context_(browser_context), |
| + storage_partition_impl_(storage_partition_impl), |
| + sudden_termination_allowed_(true), |
| + ignore_input_events_(false), |
| + is_for_guests_only_(is_for_guests_only), |
| + gpu_observer_registered_(false), |
| + delayed_cleanup_needed_(false), |
| + within_process_died_observer_(false), |
| + power_monitor_broadcaster_(this), |
| + worker_ref_count_(0), |
| + max_worker_count_(0), |
| + permission_service_context_(new PermissionServiceContext(this)), |
| + pending_valuebuffer_state_(new gpu::ValueStateMap()), |
| + subscribe_uniform_enabled_(false), |
| + weak_factory_(this) { |
| + widget_helper_ = new RenderWidgetHelper(); |
| + |
| + ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID()); |
| + |
| + CHECK(!BrowserMainRunner::ExitedMainMessageLoop()); |
| + RegisterHost(GetID(), this); |
| + g_all_hosts.Get().set_check_on_null_data(true); |
| + // Initialize |child_process_activity_time_| to a reasonable value. |
| + mark_child_process_activity_time(); |
| + |
| + if (!GetBrowserContext()->IsOffTheRecord() && |
| + !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kDisableGpuShaderDiskCache)) { |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&CacheShaderInfo, GetID(), |
| + storage_partition_impl_->GetPath())); |
| + } |
| + subscribe_uniform_enabled_ = |
| + base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableSubscribeUniformExtension); |
| +} |
| + |
| +// static |
| +void RenderProcessHostImpl::ShutDownInProcessRenderer() { |
| + DCHECK(g_run_renderer_in_process_); |
| + |
| + switch (g_all_hosts.Pointer()->size()) { |
| + case 0: |
| + return; |
| + case 1: { |
| + RenderProcessHostImpl* host = static_cast<RenderProcessHostImpl*>( |
| + AllHostsIterator().GetCurrentValue()); |
| + FOR_EACH_OBSERVER(RenderProcessHostObserver, host->observers_, |
| + 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; |
| +} |
| + |
| +RenderProcessHostImpl::~RenderProcessHostImpl() { |
| +#ifndef NDEBUG |
| + DCHECK(is_self_deleted_) |
| + << "RenderProcessHostImpl is destroyed by something other than itself"; |
| +#endif |
| + |
| + // Make sure to clean up the in-process renderer before the channel, otherwise |
| + // it may still run and have its IPCs fail, causing asserts. |
| + in_process_renderer_.reset(); |
| + |
| + ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID()); |
| + |
| + if (gpu_observer_registered_) { |
| + ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this); |
| + gpu_observer_registered_ = false; |
| + } |
| + |
| + // We may have some unsent messages at this point, but that's OK. |
| + channel_.reset(); |
| + while (!queued_messages_.empty()) { |
| + delete queued_messages_.front(); |
| + queued_messages_.pop(); |
| + } |
| + |
| + UnregisterHost(GetID()); |
| + |
| + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kDisableGpuShaderDiskCache)) { |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&RemoveShaderInfo, GetID())); |
| + } |
| +} |
| + |
| +void RenderProcessHostImpl::EnableSendQueue() { |
| + is_initialized_ = false; |
| +} |
| + |
| +bool RenderProcessHostImpl::Init() { |
| + // calling Init() more than once does nothing, this makes it more convenient |
| + // for the view host which may not be sure in some cases |
| + if (channel_) |
| + return true; |
| + |
| + base::CommandLine::StringType renderer_prefix; |
| + // A command prefix is something prepended to the command line of the spawned |
| + // process. |
| + const base::CommandLine& browser_command_line = |
| + *base::CommandLine::ForCurrentProcess(); |
| + renderer_prefix = |
| + browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); |
| + |
| +#if defined(OS_LINUX) |
| + int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF |
| + : ChildProcessHost::CHILD_NORMAL; |
| +#else |
| + int flags = ChildProcessHost::CHILD_NORMAL; |
| +#endif |
| + |
| + // Find the renderer before creating the channel so if this fails early we |
| + // return without creating the channel. |
| + base::FilePath renderer_path = ChildProcessHost::GetChildPath(flags); |
| + if (renderer_path.empty()) |
| + return false; |
| + |
| + // Setup the IPC channel. |
| + const std::string channel_id = |
| + IPC::Channel::GenerateVerifiedChannelID(std::string()); |
| + channel_ = CreateChannelProxy(channel_id); |
| + |
| + // Setup the Mojo channel. |
| + mojo_application_host_->Init(); |
| + |
| + // Call the embedder first so that their IPC filters have priority. |
| + GetContentClient()->browser()->RenderProcessWillLaunch(this); |
| + |
| + CreateMessageFilters(); |
| + RegisterMojoServices(); |
| + |
| + if (run_renderer_in_process()) { |
| + DCHECK(g_renderer_main_thread_factory); |
| + // Crank up a thread and run the initialization there. With the way that |
| + // messages flow between the browser and renderer, this thread is required |
| + // to prevent a deadlock in single-process mode. Since the primordial |
| + // thread in the renderer process runs the WebKit code and can sometimes |
| + // make blocking calls to the UI thread (i.e. this thread), they need to run |
| + // on separate threads. |
| + in_process_renderer_.reset( |
| + g_renderer_main_thread_factory(InProcessChildThreadParams( |
| + channel_id, |
| + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) |
| + ->task_runner()))); |
| + |
| + base::Thread::Options options; |
| +#if defined(OS_WIN) && !defined(OS_MACOSX) |
| + // In-process plugins require this to be a UI message loop. |
| + options.message_loop_type = base::MessageLoop::TYPE_UI; |
| +#else |
| + // We can't have multiple UI loops on Linux and Android, so we don't support |
| + // in-process plugins. |
| + options.message_loop_type = base::MessageLoop::TYPE_DEFAULT; |
| +#endif |
| + |
| + // As for execution sequence, this callback should have no any dependency |
| + // on starting in-process-render-thread. |
| + // So put it here to trigger ChannelMojo initialization earlier to enable |
| + // in-process-render-thread using ChannelMojo there. |
| + OnProcessLaunched(); // Fake a callback that the process is ready. |
| + |
| + in_process_renderer_->StartWithOptions(options); |
| + |
| + g_in_process_thread = in_process_renderer_->message_loop(); |
| + |
| + } else { |
| + // Build command line for renderer. We call AppendRendererCommandLine() |
| + // first so the process type argument will appear first. |
| + base::CommandLine* cmd_line = new base::CommandLine(renderer_path); |
| + if (!renderer_prefix.empty()) |
| + cmd_line->PrependWrapper(renderer_prefix); |
| + AppendRendererCommandLine(cmd_line); |
| + cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); |
| + |
| + // Spawn the child process asynchronously to avoid blocking the UI thread. |
| + // As long as there's no renderer prefix, we can use the zygote process |
| + // at this stage. |
| + child_process_launcher_.reset(new ChildProcessLauncher( |
| + new RendererSandboxedProcessLauncherDelegate(channel_.get()), cmd_line, |
| + GetID(), this)); |
| + |
| + fast_shutdown_started_ = false; |
| + } |
| + |
| + if (!gpu_observer_registered_) { |
| + gpu_observer_registered_ = true; |
| + ui::GpuSwitchingManager::GetInstance()->AddObserver(this); |
| + } |
| + |
| + power_monitor_broadcaster_.Init(); |
| + |
| + is_initialized_ = true; |
| + init_time_ = base::TimeTicks::Now(); |
| + return true; |
| +} |
| + |
| +scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy( |
| + const std::string& channel_id) { |
| + scoped_refptr<base::SingleThreadTaskRunner> runner = |
| + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); |
| + scoped_refptr<base::SequencedTaskRunner> mojo_task_runner = |
| + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) |
| + ->task_runner(); |
| + if (ShouldUseMojoChannel()) { |
| + VLOG(1) << "Mojo Channel is enabled on host"; |
| + |
| + return IPC::ChannelProxy::Create( |
| + IPC::ChannelMojo::CreateServerFactory(mojo_task_runner, channel_id), |
| + this, runner.get()); |
| + } |
| + |
| + return IPC::ChannelProxy::Create(channel_id, IPC::Channel::MODE_SERVER, this, |
| + runner.get()); |
| +} |
| + |
| +void RenderProcessHostImpl::CreateMessageFilters() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + const base::CommandLine& browser_command_line = |
| + *base::CommandLine::ForCurrentProcess(); |
| + AddFilter(new ResourceSchedulerFilter(GetID())); |
| + MediaInternals* media_internals = MediaInternals::GetInstance(); |
| + media::AudioManager* audio_manager = |
| + BrowserMainLoop::GetInstance()->audio_manager(); |
| + // Add BrowserPluginMessageFilter to ensure it gets the first stab at messages |
| + // from guests. |
| + scoped_refptr<BrowserPluginMessageFilter> bp_message_filter( |
| + new BrowserPluginMessageFilter(GetID())); |
| + AddFilter(bp_message_filter.get()); |
| + |
| + scoped_refptr<RenderMessageFilter> render_message_filter( |
| + new RenderMessageFilter( |
| + GetID(), GetBrowserContext(), |
| + GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), |
| + widget_helper_.get(), audio_manager, media_internals, |
| + storage_partition_impl_->GetDOMStorageContext())); |
| + AddFilter(render_message_filter.get()); |
| + AddFilter(new RenderFrameMessageFilter( |
| + GetID(), |
| +#if defined(ENABLE_PLUGINS) |
| + PluginServiceImpl::GetInstance(), |
| +#else |
| + nullptr, |
| +#endif |
| + GetBrowserContext(), |
| + GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), |
| + widget_helper_.get())); |
| + BrowserContext* browser_context = GetBrowserContext(); |
| + ResourceContext* resource_context = browser_context->GetResourceContext(); |
| + |
| + scoped_refptr<net::URLRequestContextGetter> request_context( |
| + browser_context->GetRequestContextForRenderProcess(GetID())); |
| + scoped_refptr<net::URLRequestContextGetter> media_request_context( |
| + browser_context->GetMediaRequestContextForRenderProcess(GetID())); |
| + |
| + ResourceMessageFilter::GetContextsCallback get_contexts_callback( |
| + base::Bind(&GetContexts, browser_context->GetResourceContext(), |
| + request_context, media_request_context)); |
| + |
| + ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter( |
| + GetID(), PROCESS_TYPE_RENDERER, |
| + storage_partition_impl_->GetAppCacheService(), |
| + ChromeBlobStorageContext::GetFor(browser_context), |
| + storage_partition_impl_->GetFileSystemContext(), |
| + storage_partition_impl_->GetServiceWorkerContext(), |
| + storage_partition_impl_->GetHostZoomLevelContext(), |
| + get_contexts_callback); |
| + |
| + AddFilter(resource_message_filter); |
| + MediaStreamManager* media_stream_manager = |
| + BrowserMainLoop::GetInstance()->media_stream_manager(); |
| + // The AudioInputRendererHost and AudioRendererHost needs to be available for |
| + // lookup, so it's stashed in a member variable. |
| + audio_input_renderer_host_ = new AudioInputRendererHost( |
| + GetID(), base::GetProcId(GetHandle()), audio_manager, |
| + media_stream_manager, AudioMirroringManager::GetInstance(), |
| + BrowserMainLoop::GetInstance()->user_input_monitor()); |
| + AddFilter(audio_input_renderer_host_.get()); |
| + audio_renderer_host_ = new AudioRendererHost( |
| + GetID(), audio_manager, AudioMirroringManager::GetInstance(), |
| + media_internals, media_stream_manager, |
| + browser_context->GetResourceContext()->GetMediaDeviceIDSalt()); |
| + AddFilter(audio_renderer_host_.get()); |
| + AddFilter( |
| + new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_manager())); |
| + AddFilter(new VideoCaptureHost(media_stream_manager)); |
| + AddFilter(new AppCacheDispatcherHost( |
| + storage_partition_impl_->GetAppCacheService(), GetID())); |
| + AddFilter(new ClipboardMessageFilter); |
| + AddFilter(new DOMStorageMessageFilter( |
| + storage_partition_impl_->GetDOMStorageContext())); |
| + AddFilter(new IndexedDBDispatcherHost( |
| + GetID(), storage_partition_impl_->GetURLRequestContext(), |
| + storage_partition_impl_->GetIndexedDBContext(), |
| + ChromeBlobStorageContext::GetFor(browser_context))); |
| + |
| + gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get()); |
| + AddFilter(gpu_message_filter_); |
| +#if defined(ENABLE_WEBRTC) |
| + AddFilter(new WebRTCIdentityServiceHost( |
| + GetID(), storage_partition_impl_->GetWebRTCIdentityStore(), |
| + resource_context)); |
| + peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID()); |
| + AddFilter(peer_connection_tracker_host_.get()); |
| + AddFilter(new MediaStreamDispatcherHost( |
| + GetID(), browser_context->GetResourceContext()->GetMediaDeviceIDSalt(), |
| + media_stream_manager)); |
| + AddFilter(new MediaStreamTrackMetricsHost()); |
| +#endif |
| +#if defined(ENABLE_PLUGINS) |
| + AddFilter(new PepperRendererConnection(GetID())); |
| +#endif |
| + AddFilter(new SpeechRecognitionDispatcherHost( |
| + GetID(), storage_partition_impl_->GetURLRequestContext())); |
| + AddFilter(new FileAPIMessageFilter( |
| + GetID(), storage_partition_impl_->GetURLRequestContext(), |
| + storage_partition_impl_->GetFileSystemContext(), |
| + ChromeBlobStorageContext::GetFor(browser_context), |
| + StreamContext::GetFor(browser_context))); |
| + AddFilter(new FileUtilitiesMessageFilter(GetID())); |
| + AddFilter(new MimeRegistryMessageFilter()); |
| + AddFilter( |
| + new DatabaseMessageFilter(storage_partition_impl_->GetDatabaseTracker())); |
| +#if defined(OS_MACOSX) |
| + AddFilter(new TextInputClientMessageFilter(GetID())); |
| +#elif defined(OS_WIN) |
| + // The FontCacheDispatcher is required only when we're using GDI rendering. |
| + // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache |
| + // GDI fonts (http://crbug.com/383227), even when using DirectWrite. This |
| + // should eventually be if (!ShouldUseDirectWrite()) guarded. |
| + channel_->AddFilter(new FontCacheDispatcher()); |
| +#elif defined(OS_ANDROID) |
| + browser_demuxer_android_ = new BrowserDemuxerAndroid(); |
| + AddFilter(browser_demuxer_android_.get()); |
| +#endif |
| +#if defined(ENABLE_BROWSER_CDMS) |
| + AddFilter(new BrowserCdmManager(GetID(), NULL)); |
| +#endif |
| + |
| + WebSocketDispatcherHost::GetRequestContextCallback |
| + websocket_request_context_callback( |
| + base::Bind(&GetRequestContext, request_context, media_request_context, |
| + RESOURCE_TYPE_SUB_RESOURCE)); |
| + |
| + AddFilter( |
| + new WebSocketDispatcherHost(GetID(), websocket_request_context_callback)); |
| + |
| + message_port_message_filter_ = new MessagePortMessageFilter( |
| + base::Bind(&RenderWidgetHelper::GetNextRoutingID, |
| + base::Unretained(widget_helper_.get()))); |
| + AddFilter(message_port_message_filter_.get()); |
| + |
| + scoped_refptr<CacheStorageDispatcherHost> cache_storage_filter = |
| + new CacheStorageDispatcherHost(); |
| + cache_storage_filter->Init(storage_partition_impl_->GetCacheStorageContext()); |
| + AddFilter(cache_storage_filter.get()); |
| + |
| + scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter = |
| + new ServiceWorkerDispatcherHost( |
| + GetID(), message_port_message_filter_.get(), resource_context); |
| + service_worker_filter->Init( |
| + storage_partition_impl_->GetServiceWorkerContext()); |
| + AddFilter(service_worker_filter.get()); |
| + |
| + AddFilter(new SharedWorkerMessageFilter( |
| + GetID(), resource_context, |
| + WorkerStoragePartition( |
| + storage_partition_impl_->GetURLRequestContext(), |
| + storage_partition_impl_->GetMediaURLRequestContext(), |
| + storage_partition_impl_->GetAppCacheService(), |
| + storage_partition_impl_->GetQuotaManager(), |
| + storage_partition_impl_->GetFileSystemContext(), |
| + storage_partition_impl_->GetDatabaseTracker(), |
| + storage_partition_impl_->GetIndexedDBContext(), |
| + storage_partition_impl_->GetServiceWorkerContext()), |
| + message_port_message_filter_.get())); |
| + |
| +#if defined(ENABLE_WEBRTC) |
| + p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost( |
| + resource_context, |
| + browser_context->GetRequestContextForRenderProcess(GetID())); |
| + AddFilter(p2p_socket_dispatcher_host_.get()); |
| +#endif |
| + |
| + AddFilter(new TraceMessageFilter(GetID())); |
| + AddFilter(new ResolveProxyMsgHelper( |
| + browser_context->GetRequestContextForRenderProcess(GetID()))); |
| + AddFilter(new QuotaDispatcherHost( |
| + GetID(), storage_partition_impl_->GetQuotaManager(), |
| + GetContentClient()->browser()->CreateQuotaPermissionContext())); |
| + |
| + notification_message_filter_ = new NotificationMessageFilter( |
| + GetID(), storage_partition_impl_->GetPlatformNotificationContext(), |
| + resource_context, browser_context); |
| + AddFilter(notification_message_filter_.get()); |
| + |
| + AddFilter(new GamepadBrowserMessageFilter()); |
| + AddFilter(new DeviceLightMessageFilter()); |
| + AddFilter(new DeviceMotionMessageFilter()); |
| + AddFilter(new DeviceOrientationMessageFilter()); |
| + AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER)); |
| + AddFilter(new HistogramMessageFilter()); |
| +#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID)) |
| + if (browser_command_line.HasSwitch(switches::kEnableMemoryBenchmarking)) |
| + AddFilter(new MemoryBenchmarkMessageFilter()); |
| +#endif |
| + AddFilter(new MemoryMessageFilter()); |
| + AddFilter(new PushMessagingMessageFilter( |
| + GetID(), storage_partition_impl_->GetServiceWorkerContext())); |
| +#if defined(OS_ANDROID) |
| + AddFilter(new ScreenOrientationMessageFilterAndroid()); |
| +#endif |
| + AddFilter(new GeofencingDispatcherHost( |
| + storage_partition_impl_->GetGeofencingManager())); |
| + if (browser_command_line.HasSwitch(switches::kEnableWebBluetooth)) { |
| + bluetooth_dispatcher_host_ = new BluetoothDispatcherHost(GetID()); |
| + AddFilter(bluetooth_dispatcher_host_.get()); |
| + } |
| +} |
| + |
| +void RenderProcessHostImpl::RegisterMojoServices() { |
| +#if !defined(OS_ANDROID) |
| + mojo_application_host_->service_registry()->AddService( |
| + base::Bind(&device::BatteryMonitorImpl::Create)); |
| + |
| + mojo_application_host_->service_registry()->AddService( |
| + base::Bind(&device::VibrationManagerImpl::Create)); |
| +#endif |
| + |
| + mojo_application_host_->service_registry()->AddService( |
| + base::Bind(&PermissionServiceContext::CreateService, |
| + base::Unretained(permission_service_context_.get()))); |
| + |
| + mojo_application_host_->service_registry()->AddService(base::Bind( |
| + &BackgroundSyncContextImpl::CreateService, |
| + base::Unretained(storage_partition_impl_->GetBackgroundSyncContext()))); |
| + |
| + mojo_application_host_->service_registry()->AddService(base::Bind( |
| + &content::ServicePortServiceImpl::Create, |
| + make_scoped_refptr(storage_partition_impl_->GetNavigatorConnectContext()), |
| + message_port_message_filter_)); |
| + |
| +#if defined(OS_ANDROID) |
| + ServiceRegistrarAndroid::RegisterProcessHostServices( |
| + mojo_application_host_->service_registry_android()); |
| +#endif |
| + |
| + GetContentClient()->browser()->RegisterRenderProcessMojoServices( |
| + mojo_application_host_->service_registry()); |
| +} |
| + |
| +int RenderProcessHostImpl::GetNextRoutingID() { |
| + return widget_helper_->GetNextRoutingID(); |
| +} |
| + |
| +void RenderProcessHostImpl::ResumeDeferredNavigation( |
| + const GlobalRequestID& request_id) { |
| + widget_helper_->ResumeDeferredNavigation(request_id); |
| +} |
| + |
| +void RenderProcessHostImpl::NotifyTimezoneChange(const std::string& zone_id) { |
| + Send(new ViewMsg_TimezoneChange(zone_id)); |
| +} |
| + |
| +ServiceRegistry* RenderProcessHostImpl::GetServiceRegistry() { |
| + DCHECK(mojo_application_host_); |
| + return mojo_application_host_->service_registry(); |
| +} |
| + |
| +const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics() |
| + const { |
| + return init_time_; |
| +} |
| + |
| +bool RenderProcessHostImpl::SubscribeUniformEnabled() const { |
| + return subscribe_uniform_enabled_; |
| +} |
| + |
| +void RenderProcessHostImpl::OnAddSubscription(unsigned int target) { |
| + DCHECK(subscribe_uniform_enabled_); |
| + subscription_set_.insert(target); |
| + const gpu::ValueState* state = pending_valuebuffer_state_->GetState(target); |
| + if (state) { |
| + SendUpdateValueState(target, *state); |
| + } |
| +} |
| + |
| +void RenderProcessHostImpl::OnRemoveSubscription(unsigned int target) { |
| + DCHECK(subscribe_uniform_enabled_); |
| + subscription_set_.erase(target); |
| +} |
| + |
| +void RenderProcessHostImpl::SendUpdateValueState(unsigned int target, |
| + const gpu::ValueState& state) { |
| + DCHECK(subscribe_uniform_enabled_); |
| + if (subscription_set_.find(target) != subscription_set_.end()) { |
| + GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED, |
| + CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH, |
| + new GpuMsg_UpdateValueState(id_, target, state)); |
| + } else { |
| + // Store the ValueState locally in case a Valuebuffer subscribes to it later |
| + pending_valuebuffer_state_->UpdateState(target, state); |
| + } |
| +} |
| + |
| +#if defined(ENABLE_BROWSER_CDMS) |
| +media::BrowserCdm* RenderProcessHostImpl::GetBrowserCdm(int render_frame_id, |
| + int cdm_id) const { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + BrowserCdmManager* manager = BrowserCdmManager::FromProcess(GetID()); |
| + if (!manager) |
| + return nullptr; |
| + return manager->GetCdm(render_frame_id, cdm_id); |
| +} |
| +#endif |
| + |
| +void RenderProcessHostImpl::AddRoute(int32 routing_id, |
| + IPC::Listener* listener) { |
| + CHECK(!listeners_.Lookup(routing_id)) << "Found Routing ID Conflict: " |
| + << routing_id; |
| + listeners_.AddWithID(listener, routing_id); |
| +} |
| + |
| +void RenderProcessHostImpl::RemoveRoute(int32 routing_id) { |
| + DCHECK(listeners_.Lookup(routing_id) != NULL); |
| + listeners_.Remove(routing_id); |
| + |
| + // Keep the one renderer thread around forever in single process mode. |
| + if (!run_renderer_in_process()) |
| + Cleanup(); |
| +} |
| + |
| +void RenderProcessHostImpl::AddObserver(RenderProcessHostObserver* observer) { |
| + observers_.AddObserver(observer); |
| +} |
| + |
| +void RenderProcessHostImpl::RemoveObserver( |
| + RenderProcessHostObserver* observer) { |
| + observers_.RemoveObserver(observer); |
| +} |
| + |
| +void RenderProcessHostImpl::ShutdownForBadMessage() { |
| + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| + if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) |
| + return; |
| + |
| + if (run_renderer_in_process()) { |
| + // In single process mode it is better if we don't suicide but just |
| + // crash. |
| + CHECK(false); |
| + } |
| + // We kill the renderer but don't include a NOTREACHED, because we want the |
| + // browser to try to survive when it gets illegal messages from the renderer. |
| + Shutdown(RESULT_CODE_KILLED_BAD_MESSAGE, false); |
| +} |
| + |
| +void RenderProcessHostImpl::WidgetRestored() { |
| + visible_widgets_++; |
| + UpdateProcessPriority(); |
| + DCHECK(!is_process_backgrounded_); |
| +} |
| + |
| +void RenderProcessHostImpl::WidgetHidden() { |
| + // On startup, the browser will call Hide. We ignore this call. |
| + if (visible_widgets_ == 0) |
| + return; |
| + |
| + --visible_widgets_; |
| + if (visible_widgets_ == 0) { |
| + DCHECK(!is_process_backgrounded_); |
| + UpdateProcessPriority(); |
| + } |
| +} |
| + |
| +int RenderProcessHostImpl::VisibleWidgetCount() const { |
| + return visible_widgets_; |
| +} |
| + |
| +void RenderProcessHostImpl::AudioStateChanged() { |
| + UpdateProcessPriority(); |
| +} |
| + |
| +bool RenderProcessHostImpl::IsForGuestsOnly() const { |
| + return is_for_guests_only_; |
| +} |
| + |
| +StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { |
| + return storage_partition_impl_; |
| +} |
| + |
| +static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) { |
| + if (IsPropertyTreeVerificationEnabled()) |
| + command_line->AppendSwitch(cc::switches::kEnablePropertyTreeVerification); |
| + |
| + command_line->AppendSwitchASCII( |
| + switches::kNumRasterThreads, |
| + base::IntToString(NumberOfRendererRasterThreads())); |
| + |
| + if (IsGpuRasterizationEnabled()) |
| + command_line->AppendSwitch(switches::kEnableGpuRasterization); |
| + |
| + int msaa_sample_count = GpuRasterizationMSAASampleCount(); |
| + if (msaa_sample_count >= 0) { |
| + command_line->AppendSwitchASCII(switches::kGpuRasterizationMSAASampleCount, |
| + base::IntToString(msaa_sample_count)); |
| + } |
| + |
| + if (IsZeroCopyUploadEnabled()) |
| + command_line->AppendSwitch(switches::kEnableZeroCopy); |
| + if (IsPersistentGpuMemoryBufferEnabled()) |
| + command_line->AppendSwitch(switches::kEnablePersistentGpuMemoryBuffer); |
| + |
| + if (IsForceGpuRasterizationEnabled()) |
| + command_line->AppendSwitch(switches::kForceGpuRasterization); |
| + |
| + gfx::BufferUsage buffer_usage = IsPersistentGpuMemoryBufferEnabled() |
| + ? gfx::BufferUsage::PERSISTENT_MAP |
| + : gfx::BufferUsage::MAP; |
| + std::vector<unsigned> image_targets( |
| + static_cast<size_t>(gfx::BufferFormat::LAST) + 1, GL_TEXTURE_2D); |
| + for (size_t format = 0; |
| + format < static_cast<size_t>(gfx::BufferFormat::LAST) + 1; format++) { |
| + image_targets[format] = |
| + BrowserGpuMemoryBufferManager::GetImageTextureTarget( |
| + static_cast<gfx::BufferFormat>(format), buffer_usage); |
| + } |
| + command_line->AppendSwitchASCII(switches::kContentImageTextureTarget, |
| + UintVectorToString(image_targets)); |
| + |
| + command_line->AppendSwitchASCII( |
| + switches::kVideoImageTextureTarget, |
| + base::UintToString(BrowserGpuMemoryBufferManager::GetImageTextureTarget( |
| + gfx::BufferFormat::R_8, gfx::BufferUsage::MAP))); |
| + |
| + // Appending disable-gpu-feature switches due to software rendering list. |
| + GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); |
| + DCHECK(gpu_data_manager); |
| + gpu_data_manager->AppendRendererCommandLine(command_line); |
| +} |
| + |
| +void RenderProcessHostImpl::AppendRendererCommandLine( |
| + base::CommandLine* command_line) const { |
| + // Pass the process type first, so it shows first in process listings. |
| + command_line->AppendSwitchASCII(switches::kProcessType, |
| + switches::kRendererProcess); |
| + |
| + // Now send any options from our own command line we want to propagate. |
| + const base::CommandLine& browser_command_line = |
| + *base::CommandLine::ForCurrentProcess(); |
| + PropagateBrowserCommandLineToRenderer(browser_command_line, command_line); |
| + |
| + // Pass on the browser locale. |
| + const std::string locale = |
| + GetContentClient()->browser()->GetApplicationLocale(); |
| + command_line->AppendSwitchASCII(switches::kLang, locale); |
| + |
| + // If we run base::FieldTrials, we want to pass to their state to the |
| + // renderer so that it can act in accordance with each state, or record |
| + // histograms relating to the base::FieldTrial states. |
| + std::string field_trial_states; |
| + base::FieldTrialList::AllStatesToString(&field_trial_states); |
| + if (!field_trial_states.empty()) { |
| + command_line->AppendSwitchASCII(switches::kForceFieldTrials, |
| + field_trial_states); |
| + } |
| + |
| + GetContentClient()->browser()->AppendExtraCommandLineSwitches(command_line, |
| + GetID()); |
| + |
| + if (IsPinchToZoomEnabled()) |
| + command_line->AppendSwitch(switches::kEnablePinch); |
| + |
| +#if defined(OS_WIN) |
| + command_line->AppendSwitchASCII(switches::kDeviceScaleFactor, |
| + base::DoubleToString(gfx::GetDPIScale())); |
| +#endif |
| + |
| + AppendCompositorCommandLineFlags(command_line); |
| +} |
| + |
| +void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( |
| + const base::CommandLine& browser_cmd, |
| + base::CommandLine* renderer_cmd) const { |
| + // Propagate the following switches to the renderer command line (along |
| + // with any associated values) if present in the browser command line. |
| + static const char* const kSwitchNames[] = { |
| + switches::kAllowLoopbackInPeerConnection, |
| + switches::kAudioBufferSize, |
| + switches::kBlinkPlatformLogChannels, |
| + switches::kBlinkSettings, |
| + switches::kDefaultTileWidth, |
| + switches::kDefaultTileHeight, |
| + switches::kDisable3DAPIs, |
| + switches::kDisableAcceleratedJpegDecoding, |
| + switches::kDisableAcceleratedVideoDecode, |
| + switches::kDisableBlinkFeatures, |
| + switches::kDisableBreakpad, |
| + switches::kDisablePreferCompositingToLCDText, |
| + switches::kDisableDatabases, |
| + switches::kDisableDelayAgnosticAec, |
| + switches::kDisableDirectNPAPIRequests, |
| + switches::kDisableDisplayList2dCanvas, |
| + switches::kDisableDistanceFieldText, |
| + switches::kDisableEncryptedMedia, |
| + switches::kDisableFeatures, |
| + switches::kDisableFileSystem, |
| + switches::kDisableGpuCompositing, |
| + switches::kDisableGpuMemoryBufferVideoFrames, |
| + switches::kDisableGpuVsync, |
| + switches::kDisableLowResTiling, |
| + switches::kDisableHistogramCustomizer, |
| + switches::kDisableIconNtp, |
| + switches::kDisableLCDText, |
| + switches::kDisableLocalStorage, |
| + switches::kDisableLogging, |
| + switches::kDisableMediaSource, |
| + switches::kDisableMojoChannel, |
| + switches::kDisableNotifications, |
| + switches::kDisableOverlayScrollbar, |
| + switches::kDisablePermissionsAPI, |
| + switches::kDisablePresentationAPI, |
| + switches::kDisablePinch, |
| + switches::kDisableRGBA4444Textures, |
| + switches::kDisableSeccompFilterSandbox, |
| + switches::kDisableSharedWorkers, |
| + switches::kDisableSpeechAPI, |
| + switches::kDisableSVG1DOM, |
| + switches::kDisableThreadedCompositing, |
| + switches::kDisableThreadedScrolling, |
| + switches::kDisableTouchAdjustment, |
| + switches::kDisableTouchDragDrop, |
| + switches::kDisableTouchEditing, |
| + switches::kDisableV8IdleTasks, |
| + switches::kDomAutomationController, |
| + switches::kEnableBleedingEdgeRenderingFastPaths, |
| + switches::kEnableBlinkFeatures, |
| + switches::kEnableBrowserSideNavigation, |
| + switches::kEnableCompositorAnimationTimelines, |
| + switches::kEnableCredentialManagerAPI, |
| + switches::kEnableDisplayList2dCanvas, |
| + switches::kEnableDistanceFieldText, |
| + switches::kEnableExperimentalCanvasFeatures, |
| + switches::kEnableExperimentalWebPlatformFeatures, |
| + switches::kEnableFeatures, |
| + switches::kEnableGPUClientLogging, |
| + switches::kEnableGpuClientTracing, |
| + switches::kEnableGpuMemoryBufferVideoFrames, |
| + switches::kEnableGPUServiceLogging, |
| + switches::kEnableIconNtp, |
| + switches::kEnableLinkDisambiguationPopup, |
| + switches::kEnableLowResTiling, |
| + switches::kEnableInbandTextTracks, |
| + switches::kEnableLCDText, |
| + switches::kEnableLogging, |
| + switches::kEnableMemoryBenchmarking, |
| + switches::kEnableNetworkInformation, |
| + switches::kEnableOverlayScrollbar, |
| + switches::kEnablePinch, |
| + switches::kEnablePluginPlaceholderTesting, |
| + switches::kEnablePreciseMemoryInfo, |
| + switches::kEnablePreferCompositingToLCDText, |
| + switches::kEnablePrefixedEncryptedMedia, |
| + switches::kEnablePushMessagePayload, |
| + switches::kEnableRGBA4444Textures, |
| + switches::kEnableRendererMojoChannel, |
| + switches::kEnableRTCSmoothnessAlgorithm, |
| + switches::kEnableSeccompFilterSandbox, |
| + switches::kEnableSkiaBenchmarking, |
| + switches::kEnableSlimmingPaintV2, |
| + switches::kEnableSmoothScrolling, |
| + switches::kEnableStatsTable, |
| + switches::kEnableThreadedCompositing, |
| + switches::kEnableTouchDragDrop, |
| + switches::kEnableTouchEditing, |
| + switches::kEnableUnsafeES3APIs, |
| + switches::kEnableViewport, |
| + switches::kEnableVtune, |
| + switches::kEnableWebBluetooth, |
| + switches::kEnableWebGLDraftExtensions, |
| + switches::kEnableWebGLImageChromium, |
| + switches::kEnableWebVR, |
| + switches::kExplicitlyAllowedPorts, |
| + switches::kForceDeviceScaleFactor, |
| + switches::kForceDisplayList2dCanvas, |
| + switches::kForceOverlayFullscreenVideo, |
| + switches::kFullMemoryCrashReport, |
| + switches::kInertVisualViewport, |
| + switches::kIPCConnectionTimeout, |
| + switches::kJavaScriptFlags, |
| + switches::kLoggingLevel, |
| + switches::kMainFrameResizesAreOrientationChanges, |
| + switches::kMaxUntiledLayerWidth, |
| + switches::kMaxUntiledLayerHeight, |
| + switches::kMemoryMetrics, |
| + switches::kNoReferrers, |
| + switches::kNoSandbox, |
| + switches::kOverridePluginPowerSaverForTesting, |
| + switches::kPpapiInProcess, |
| + switches::kProfilerTiming, |
| + switches::kReducedReferrerGranularity, |
| + switches::kReduceSecurityForTesting, |
| + switches::kRegisterPepperPlugins, |
| + switches::kRendererStartupDialog, |
| + switches::kRootLayerScrolls, |
| + switches::kShowPaintRects, |
| + switches::kSitePerProcess, |
| + switches::kStatsCollectionController, |
| + switches::kTestType, |
| + switches::kTouchEvents, |
| + switches::kTouchTextSelectionStrategy, |
| + switches::kTraceConfigFile, |
| + switches::kTraceToConsole, |
| + // This flag needs to be propagated to the renderer process for |
| + // --in-process-webgl. |
| + switches::kUseGL, |
| + switches::kUseMobileUserAgent, |
| + switches::kUseNormalPriorityForTileTaskWorkerThreads, |
| + switches::kV, |
| + switches::kVideoThreads, |
| + switches::kVideoUnderflowThresholdMs, |
| + switches::kVModule, |
| + // Please keep these in alphabetical order. Compositor switches here should |
| + // also be added to chrome/browser/chromeos/login/chrome_restart_request.cc. |
| + cc::switches::kDisableCompositedAntialiasing, |
| + cc::switches::kDisableMainFrameBeforeActivation, |
| + cc::switches::kDisableThreadedAnimation, |
| + cc::switches::kEnableBeginFrameScheduling, |
| + cc::switches::kEnableGpuBenchmarking, |
| + cc::switches::kEnableMainFrameBeforeActivation, |
| + cc::switches::kShowCompositedLayerBorders, |
| + cc::switches::kShowFPSCounter, |
| + cc::switches::kShowLayerAnimationBounds, |
| + cc::switches::kShowPropertyChangedRects, |
| + cc::switches::kShowReplicaScreenSpaceRects, |
| + cc::switches::kShowScreenSpaceRects, |
| + cc::switches::kShowSurfaceDamageRects, |
| + cc::switches::kSlowDownRasterScaleFactor, |
| + cc::switches::kStrictLayerPropertyChangeChecking, |
| + cc::switches::kTopControlsHideThreshold, |
| + cc::switches::kTopControlsShowThreshold, |
| + |
| +#if defined(ENABLE_PLUGINS) |
| + switches::kEnablePepperTesting, |
| +#endif |
| +#if defined(ENABLE_WEBRTC) |
| + switches::kDisableWebRtcHWDecoding, |
| + switches::kDisableWebRtcHWEncoding, |
| + switches::kEnableWebRtcDtls12, |
| + switches::kEnableWebRtcHWH264Encoding, |
| + switches::kEnableWebRtcStunOrigin, |
| + switches::kWebRtcMaxCaptureFramerate, |
| +#endif |
| + switches::kEnableLowEndDeviceMode, |
| + switches::kDisableLowEndDeviceMode, |
| +#if defined(OS_ANDROID) |
| + switches::kDisableGestureRequirementForMediaPlayback, |
| + switches::kDisableWebAudio, |
| + switches::kRendererWaitForJavaDebugger, |
| +#endif |
| +#if defined(OS_MACOSX) |
| + // Allow this to be set when invoking the browser and relayed along. |
| + switches::kEnableSandboxLogging, |
| +#endif |
| +#if defined(OS_WIN) |
| + switches::kDisableDirectWrite, |
| + switches::kDisableWin32kRendererLockDown, |
| + switches::kTraceExportEventsToETW, |
| +#endif |
| +#if defined(USE_OZONE) |
| + switches::kOzonePlatform, |
| +#endif |
| +#if defined(OS_CHROMEOS) |
| + switches::kDisableVaapiAcceleratedVideoEncode, |
| +#endif |
| + }; |
| + renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, |
| + arraysize(kSwitchNames)); |
| + |
| + if (browser_cmd.HasSwitch(switches::kTraceStartup) && |
| + BrowserMainLoop::GetInstance()->is_tracing_startup_for_duration()) { |
| + // Pass kTraceStartup switch to renderer only if startup tracing has not |
| + // finished. |
| + renderer_cmd->AppendSwitchASCII( |
| + switches::kTraceStartup, |
| + browser_cmd.GetSwitchValueASCII(switches::kTraceStartup)); |
| + } |
| + |
| +#if defined(ENABLE_WEBRTC) |
| + // Only run the Stun trials in the first renderer. |
| + if (!has_done_stun_trials && |
| + browser_cmd.HasSwitch(switches::kWebRtcStunProbeTrialParameter)) { |
| + has_done_stun_trials = true; |
| + renderer_cmd->AppendSwitchASCII( |
| + switches::kWebRtcStunProbeTrialParameter, |
| + browser_cmd.GetSwitchValueASCII( |
| + switches::kWebRtcStunProbeTrialParameter)); |
| + } |
| +#endif |
| + |
| + // Disable databases in incognito mode. |
| + if (GetBrowserContext()->IsOffTheRecord() && |
| + !browser_cmd.HasSwitch(switches::kDisableDatabases)) { |
| + renderer_cmd->AppendSwitch(switches::kDisableDatabases); |
| + } |
| + |
| + // Add kWaitForDebugger to let renderer process wait for a debugger. |
| + if (browser_cmd.HasSwitch(switches::kWaitForDebuggerChildren)) { |
| + // Look to pass-on the kWaitForDebugger flag. |
| + std::string value = |
| + browser_cmd.GetSwitchValueASCII(switches::kWaitForDebuggerChildren); |
| + if (value.empty() || value == switches::kRendererProcess) { |
| + renderer_cmd->AppendSwitch(switches::kWaitForDebugger); |
| + } |
| + } |
| +} |
| + |
| +base::ProcessHandle RenderProcessHostImpl::GetHandle() const { |
| + if (run_renderer_in_process()) |
| + return base::GetCurrentProcessHandle(); |
| + |
| + if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) |
| + return base::kNullProcessHandle; |
| + |
| + return child_process_launcher_->GetProcess().Handle(); |
| +} |
| + |
| +bool RenderProcessHostImpl::Shutdown(int exit_code, bool wait) { |
| + if (run_renderer_in_process()) |
| + return false; // Single process mode never shuts down the renderer. |
| + |
| +#if defined(OS_ANDROID) |
| + // Android requires a different approach for killing. |
| + StopChildProcess(GetHandle()); |
| + return true; |
| +#else |
| + if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) |
| + return false; |
| + |
| + return child_process_launcher_->GetProcess().Terminate(exit_code, wait); |
| +#endif |
| +} |
| + |
| +bool RenderProcessHostImpl::FastShutdownIfPossible() { |
| + if (run_renderer_in_process()) |
| + return false; // Single process mode never shuts down the renderer. |
| + |
| + if (!GetContentClient()->browser()->IsFastShutdownPossible()) |
| + return false; |
| + |
| + if (!child_process_launcher_.get() || child_process_launcher_->IsStarting() || |
| + !GetHandle()) |
| + return false; // Render process hasn't started or is probably crashed. |
| + |
| + // Test if there's an unload listener. |
| + // NOTE: It's possible that an onunload listener may be installed |
| + // while we're shutting down, so there's a small race here. Given that |
| + // the window is small, it's unlikely that the web page has much |
| + // state that will be lost by not calling its unload handlers properly. |
| + if (!SuddenTerminationAllowed()) |
| + return false; |
| + |
| + if (worker_ref_count_ != 0) { |
| + if (survive_for_worker_start_time_.is_null()) |
| + survive_for_worker_start_time_ = base::TimeTicks::Now(); |
| + return false; |
| + } |
| + |
| + // Set this before ProcessDied() so observers can tell if the render process |
| + // died due to fast shutdown versus another cause. |
| + fast_shutdown_started_ = true; |
| + |
| + ProcessDied(false /* already_dead */, nullptr); |
| + return true; |
| +} |
| + |
| +bool RenderProcessHostImpl::Send(IPC::Message* msg) { |
| + TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send"); |
| + if (!channel_) { |
| + if (!is_initialized_) { |
| + queued_messages_.push(msg); |
| + return true; |
| + } else { |
| + delete msg; |
| + return false; |
| + } |
| + } |
| + |
| + if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { |
| + queued_messages_.push(msg); |
| + return true; |
| + } |
| + |
| + return channel_->Send(msg); |
| +} |
| + |
| +bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { |
| + // If we're about to be deleted, or have initiated the fast shutdown sequence, |
| + // we ignore incoming messages. |
| + |
| + if (deleting_soon_ || fast_shutdown_started_) |
| + return false; |
| + |
| + mark_child_process_activity_time(); |
| + if (msg.routing_id() == MSG_ROUTING_CONTROL) { |
| + // Dispatch control messages. |
| + IPC_BEGIN_MESSAGE_MAP(RenderProcessHostImpl, msg) |
| + IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, |
| + OnShutdownRequest) |
| + IPC_MESSAGE_HANDLER(RenderProcessHostMsg_SuddenTerminationChanged, |
| + SuddenTerminationChanged) |
| + IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction, |
| + OnUserMetricsRecordAction) |
| + IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML) |
| + IPC_MESSAGE_HANDLER(ViewHostMsg_Close_ACK, OnCloseACK) |
| +#if defined(ENABLE_WEBRTC) |
| + IPC_MESSAGE_HANDLER(AecDumpMsg_RegisterAecDumpConsumer, |
| + OnRegisterAecDumpConsumer) |
| + IPC_MESSAGE_HANDLER(AecDumpMsg_UnregisterAecDumpConsumer, |
| + OnUnregisterAecDumpConsumer) |
| +#endif |
| + // Adding single handlers for your service here is fine, but once your |
| + // service needs more than one handler, please extract them into a new |
| + // message filter and add that filter to CreateMessageFilters(). |
| + IPC_END_MESSAGE_MAP() |
| + |
| + return true; |
| + } |
| + |
| + // Dispatch incoming messages to the appropriate IPC::Listener. |
| + IPC::Listener* listener = listeners_.Lookup(msg.routing_id()); |
| + if (!listener) { |
| + if (msg.is_sync()) { |
| + // The listener has gone away, so we must respond or else the caller will |
| + // hang waiting for a reply. |
| + IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg); |
| + reply->set_reply_error(); |
| + Send(reply); |
| + } |
| + return true; |
| + } |
| + return listener->OnMessageReceived(msg); |
| +} |
| + |
| +void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) { |
| +#if defined(IPC_MESSAGE_LOG_ENABLED) |
| + Send(new ChildProcessMsg_SetIPCLoggingEnabled( |
| + IPC::Logging::GetInstance()->Enabled())); |
| +#endif |
| + |
| + tracked_objects::ThreadData::Status status = |
| + tracked_objects::ThreadData::status(); |
| + Send(new ChildProcessMsg_SetProfilerStatus(status)); |
| + |
| +#if defined(OS_MACOSX) && !defined(OS_IOS) |
| + io_surface_manager_token_ = |
| + BrowserIOSurfaceManager::GetInstance()->GenerateChildProcessToken( |
| + GetID()); |
| + Send(new ChildProcessMsg_SetIOSurfaceManagerToken(io_surface_manager_token_)); |
| +#endif |
| + |
| +#if defined(USE_OZONE) |
| + Send(new ChildProcessMsg_InitializeClientNativePixmapFactory( |
| + base::FileDescriptor( |
| + ui::OzonePlatform::GetInstance()->OpenClientNativePixmapDevice()))); |
| +#endif |
| + |
| + // Inform AudioInputRendererHost about the new render process PID. |
| + // AudioInputRendererHost is reference counted, so it's lifetime is |
| + // guarantueed during the lifetime of the closure. |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&AudioInputRendererHost::set_renderer_pid, |
| + audio_input_renderer_host_, peer_pid)); |
| +} |
| + |
| +void RenderProcessHostImpl::OnChannelError() { |
| + ProcessDied(true /* already_dead */, nullptr); |
| +} |
| + |
| +void RenderProcessHostImpl::OnBadMessageReceived(const IPC::Message& message) { |
| + // Message de-serialization failed. We consider this a capital crime. Kill the |
| + // renderer if we have one. |
| + auto type = message.type(); |
| + LOG(ERROR) << "bad message " << type << " terminating renderer."; |
| + BrowserChildProcessHostImpl::HistogramBadMessageTerminated( |
| + PROCESS_TYPE_RENDERER); |
| + |
| + // Create a memory dump. This will contain enough stack frames to work out |
| + // what the bad message was. |
| + base::debug::Alias(&type); |
| + base::debug::DumpWithoutCrashing(); |
| + |
| + bad_message::ReceivedBadMessage(this, |
| + bad_message::RPH_DESERIALIZATION_FAILED); |
| +} |
| + |
| +BrowserContext* RenderProcessHostImpl::GetBrowserContext() const { |
| + return browser_context_; |
| +} |
| + |
| +bool RenderProcessHostImpl::InSameStoragePartition( |
| + StoragePartition* partition) const { |
| + return storage_partition_impl_ == partition; |
| +} |
| + |
| +int RenderProcessHostImpl::GetID() const { |
| + return id_; |
| +} |
| + |
| +bool RenderProcessHostImpl::HasConnection() const { |
| + return channel_.get() != NULL; |
| +} |
| + |
| +void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) { |
| + ignore_input_events_ = ignore_input_events; |
| +} |
| + |
| +bool RenderProcessHostImpl::IgnoreInputEvents() const { |
| + return ignore_input_events_; |
| +} |
| + |
| +void RenderProcessHostImpl::Cleanup() { |
| + // If within_process_died_observer_ is true, one of our observers performed an |
| + // action that caused us to die (e.g. http://crbug.com/339504). Therefore, |
| + // delay the destruction until all of the observer callbacks have been made, |
| + // and guarantee that the RenderProcessHostDestroyed observer callback is |
| + // always the last callback fired. |
| + if (within_process_died_observer_) { |
| + delayed_cleanup_needed_ = true; |
| + return; |
| + } |
| + delayed_cleanup_needed_ = false; |
| + |
| + // Records the time when the process starts surviving for workers for UMA. |
| + if (listeners_.IsEmpty() && worker_ref_count_ > 0 && |
| + survive_for_worker_start_time_.is_null()) { |
| + survive_for_worker_start_time_ = base::TimeTicks::Now(); |
| + } |
| + |
| + // When there are no other owners of this object, we can delete ourselves. |
| + if (listeners_.IsEmpty() && worker_ref_count_ == 0) { |
| + if (!survive_for_worker_start_time_.is_null()) { |
| + UMA_HISTOGRAM_LONG_TIMES( |
| + "SharedWorker.RendererSurviveForWorkerTime", |
| + base::TimeTicks::Now() - survive_for_worker_start_time_); |
| + } |
| + |
| + if (max_worker_count_ > 0) { |
| + // Record the max number of workers (SharedWorker or ServiceWorker) |
| + // that are simultaneously hosted in this renderer process. |
| + UMA_HISTOGRAM_COUNTS("Render.Workers.MaxWorkerCountInRendererProcess", |
| + max_worker_count_); |
| + } |
| + |
| + // We cannot clean up twice; if this fails, there is an issue with our |
| + // control flow. |
| + DCHECK(!deleting_soon_); |
| + |
| + DCHECK_EQ(0, pending_views_); |
| + FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_, |
| + RenderProcessHostDestroyed(this)); |
| + NotificationService::current()->Notify( |
| + NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| + Source<RenderProcessHost>(this), NotificationService::NoDetails()); |
| + |
| +#ifndef NDEBUG |
| + is_self_deleted_ = true; |
| +#endif |
| + base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| + deleting_soon_ = true; |
| + // It's important not to wait for the DeleteTask to delete the channel |
| + // proxy. Kill it off now. That way, in case the profile is going away, the |
| + // rest of the objects attached to this RenderProcessHost start going |
| + // away first, since deleting the channel proxy will post a |
| + // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. |
| + channel_.reset(); |
| + |
| + // The following members should be cleared in ProcessDied() as well! |
| + gpu_message_filter_ = NULL; |
| + message_port_message_filter_ = NULL; |
| + |
| + RemoveUserData(kSessionStorageHolderKey); |
| + |
| + // Remove ourself from the list of renderer processes so that we can't be |
| + // reused in between now and when the Delete task runs. |
| + UnregisterHost(GetID()); |
| + |
| +#if defined(OS_MACOSX) && !defined(OS_IOS) |
| + if (!io_surface_manager_token_.IsZero()) { |
| + BrowserIOSurfaceManager::GetInstance()->InvalidateChildProcessToken( |
| + io_surface_manager_token_); |
| + io_surface_manager_token_.SetZero(); |
| + } |
| +#endif |
| + } |
| +} |
| + |
| +void RenderProcessHostImpl::AddPendingView() { |
| + pending_views_++; |
| +} |
| + |
| +void RenderProcessHostImpl::RemovePendingView() { |
| + DCHECK(pending_views_); |
| + pending_views_--; |
| +} |
| + |
| +void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) { |
| + sudden_termination_allowed_ = enabled; |
| +} |
| + |
| +bool RenderProcessHostImpl::SuddenTerminationAllowed() const { |
| + return sudden_termination_allowed_; |
| +} |
| + |
| +base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const { |
| + return base::TimeTicks::Now() - child_process_activity_time_; |
| +} |
| + |
| +void RenderProcessHostImpl::ResumeRequestsForView(int route_id) { |
| + widget_helper_->ResumeRequestsForView(route_id); |
| +} |
| + |
| +void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) { |
| + FilterURL(this, empty_allowed, url); |
| +} |
| + |
| +#if defined(ENABLE_WEBRTC) |
| +void RenderProcessHostImpl::EnableAudioDebugRecordings( |
| + const base::FilePath& file) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + // Enable AEC dump for each registered consumer. |
| + base::FilePath file_with_extensions = GetAecDumpFilePathWithExtensions(file); |
| + for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); |
| + it != aec_dump_consumers_.end(); ++it) { |
| + EnableAecDumpForId(file_with_extensions, *it); |
| + } |
| + |
| + // Enable mic input recording. AudioInputRendererHost is reference counted, so |
| + // it's lifetime is guarantueed during the lifetime of the closure. |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&AudioInputRendererHost::EnableDebugRecording, |
| + audio_input_renderer_host_, file)); |
| +} |
| + |
| +void RenderProcessHostImpl::DisableAudioDebugRecordings() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + // Posting on the FILE thread and then replying back on the UI thread is only |
| + // for avoiding races between enable and disable. Nothing is done on the FILE |
| + // thread. |
| + BrowserThread::PostTaskAndReply( |
| + BrowserThread::FILE, FROM_HERE, base::Bind(&DisableAecDumpOnFileThread), |
| + base::Bind(&RenderProcessHostImpl::SendDisableAecDumpToRenderer, |
| + weak_factory_.GetWeakPtr())); |
| + |
| + // AudioInputRendererHost is reference counted, so it's lifetime is |
| + // guaranteed during the lifetime of the closure. |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&AudioInputRendererHost::DisableDebugRecording, |
| + audio_input_renderer_host_)); |
| +} |
| + |
| +void RenderProcessHostImpl::SetWebRtcLogMessageCallback( |
| + base::Callback<void(const std::string&)> callback) { |
| + webrtc_log_message_callback_ = callback; |
| +} |
| + |
| +RenderProcessHostImpl::WebRtcStopRtpDumpCallback |
| +RenderProcessHostImpl::StartRtpDump( |
| + bool incoming, |
| + bool outgoing, |
| + const WebRtcRtpPacketCallback& packet_callback) { |
| + if (!p2p_socket_dispatcher_host_.get()) |
| + return WebRtcStopRtpDumpCallback(); |
| + |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&P2PSocketDispatcherHost::StartRtpDump, |
| + p2p_socket_dispatcher_host_, incoming, |
| + outgoing, packet_callback)); |
| + |
| + if (stop_rtp_dump_callback_.is_null()) { |
| + stop_rtp_dump_callback_ = |
| + base::Bind(&P2PSocketDispatcherHost::StopRtpDumpOnUIThread, |
| + p2p_socket_dispatcher_host_); |
| + } |
| + return stop_rtp_dump_callback_; |
| +} |
| +#endif |
| + |
| +IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { |
| + return channel_.get(); |
| +} |
| + |
| +void RenderProcessHostImpl::AddFilter(BrowserMessageFilter* filter) { |
| + channel_->AddFilter(filter->GetFilter()); |
| +} |
| + |
| +bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) { |
| + if (GetActiveViewCount() == count) |
| + return FastShutdownIfPossible(); |
| + return false; |
| +} |
| + |
| +bool RenderProcessHostImpl::FastShutdownStarted() const { |
| + return fast_shutdown_started_; |
| +} |
| + |
| +// static |
| +void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { |
| + g_all_hosts.Get().AddWithID(host, host_id); |
| +} |
| + |
| +// static |
| +void RenderProcessHostImpl::UnregisterHost(int host_id) { |
| + RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id); |
| + if (!host) |
| + return; |
| + |
| + g_all_hosts.Get().Remove(host_id); |
| + |
| + // Look up the map of site to process for the given browser_context, |
| + // in case we need to remove this process from it. It will be registered |
| + // under any sites it rendered that use process-per-site mode. |
| + SiteProcessMap* map = |
| + GetSiteProcessMapForBrowserContext(host->GetBrowserContext()); |
| + map->RemoveProcess(host); |
| +} |
| + |
| +// static |
| +void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph, |
| + bool empty_allowed, |
| + GURL* url) { |
| + ChildProcessSecurityPolicyImpl* policy = |
| + ChildProcessSecurityPolicyImpl::GetInstance(); |
| + |
| + if (empty_allowed && url->is_empty()) |
| + return; |
| + |
| + // The browser process should never hear the swappedout:// URL from any |
| + // of the renderer's messages. Check for this in debug builds, but don't |
| + // let it crash a release browser. |
| + DCHECK(GURL(kSwappedOutURL) != *url); |
| + |
| + if (!url->is_valid()) { |
| + // Have to use about:blank for the denied case, instead of an empty GURL. |
| + // This is because the browser treats navigation to an empty GURL as a |
| + // navigation to the home page. This is often a privileged page |
| + // (chrome://newtab/) which is exactly what we don't want. |
| + *url = GURL(url::kAboutBlankURL); |
| + return; |
| + } |
| + |
| + if (url->SchemeIs(url::kAboutScheme)) { |
| + // The renderer treats all URLs in the about: scheme as being about:blank. |
| + // Canonicalize about: URLs to about:blank. |
| + *url = GURL(url::kAboutBlankURL); |
| + } |
| + |
| + // Do not allow browser plugin guests to navigate to non-web URLs, since they |
| + // cannot swap processes or grant bindings. |
| + bool non_web_url_in_guest = |
| + rph->IsForGuestsOnly() && |
| + !(url->is_valid() && policy->IsWebSafeScheme(url->scheme())); |
| + |
| + if (non_web_url_in_guest || !policy->CanRequestURL(rph->GetID(), *url)) { |
| + // If this renderer is not permitted to request this URL, we invalidate the |
| + // URL. This prevents us from storing the blocked URL and becoming confused |
| + // later. |
| + VLOG(1) << "Blocked URL " << url->spec(); |
| + *url = GURL(url::kAboutBlankURL); |
| + } |
| +} |
| + |
| +// static |
| +bool RenderProcessHostImpl::IsSuitableHost(RenderProcessHost* host, |
| + BrowserContext* browser_context, |
| + const GURL& site_url) { |
| + if (run_renderer_in_process()) |
| + return true; |
| + |
| + if (host->GetBrowserContext() != browser_context) |
| + return false; |
| + |
| + // Do not allow sharing of guest hosts. This is to prevent bugs where guest |
| + // and non-guest storage gets mixed. In the future, we might consider enabling |
| + // the sharing of guests, in this case this check should be removed and |
| + // InSameStoragePartition should handle the possible sharing. |
| + if (host->IsForGuestsOnly()) |
| + return false; |
| + |
| + // Check whether the given host and the intended site_url will be using the |
| + // same StoragePartition, since a RenderProcessHost can only support a single |
| + // StoragePartition. This is relevant for packaged apps. |
| + StoragePartition* dest_partition = |
| + BrowserContext::GetStoragePartitionForSite(browser_context, site_url); |
| + if (!host->InSameStoragePartition(dest_partition)) |
| + return false; |
| + |
| + // TODO(nick): Consult the SiteIsolationPolicy here. https://crbug.com/513036 |
| + if (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
| + host->GetID()) != |
| + WebUIControllerFactoryRegistry::GetInstance()->UseWebUIBindingsForURL( |
| + browser_context, site_url)) { |
| + return false; |
| + } |
| + |
| + return GetContentClient()->browser()->IsSuitableHost(host, site_url); |
| +} |
| + |
| +// static |
| +bool RenderProcessHost::run_renderer_in_process() { |
| + return g_run_renderer_in_process_; |
| +} |
| + |
| +// static |
| +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)) { |
| + // Modify the current process' command line to include the browser locale, |
| + // as the renderer expects this flag to be set. |
| + const std::string locale = |
| + GetContentClient()->browser()->GetApplicationLocale(); |
| + command_line->AppendSwitchASCII(switches::kLang, locale); |
| + } |
| + // TODO(piman): we should really send configuration through bools rather |
| + // than by parsing strings, i.e. sending an IPC rather than command line |
| + // args. crbug.com/314909 |
| + AppendCompositorCommandLineFlags(command_line); |
| + } |
| +} |
| + |
| +// static |
| +RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + return iterator(g_all_hosts.Pointer()); |
| +} |
| + |
| +// static |
| +RenderProcessHost* RenderProcessHost::FromID(int render_process_id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + return g_all_hosts.Get().Lookup(render_process_id); |
| +} |
| + |
| +// static |
| +bool RenderProcessHost::ShouldTryToUseExistingProcessHost( |
| + BrowserContext* browser_context, |
| + const GURL& url) { |
| + // If --site-per-process is enabled, do not try to reuse renderer processes |
| + // when over the limit. |
| + // TODO(nick): This is overly conservative and isn't launchable. Move this |
| + // logic into IsSuitableHost, and check |url| against the URL the process is |
| + // dedicated to. This will allow pages from the same site to share, and will |
| + // also allow non-isolated sites to share processes. https://crbug.com/513036 |
| + if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) |
| + return false; |
| + |
| + if (run_renderer_in_process()) |
| + return true; |
| + |
| + // NOTE: Sometimes it's necessary to create more render processes than |
| + // GetMaxRendererProcessCount(), for instance when we want to create |
| + // a renderer process for a browser context that has no existing |
| + // renderers. This is OK in moderation, since the |
| + // GetMaxRendererProcessCount() is conservative. |
| + if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount()) |
| + return true; |
| + |
| + return GetContentClient()->browser()->ShouldTryToUseExistingProcessHost( |
| + browser_context, url); |
| +} |
| + |
| +// static |
| +RenderProcessHost* RenderProcessHost::GetExistingProcessHost( |
| + BrowserContext* browser_context, |
| + const GURL& site_url) { |
| + // First figure out which existing renderers we can use. |
| + std::vector<RenderProcessHost*> suitable_renderers; |
| + suitable_renderers.reserve(g_all_hosts.Get().size()); |
| + |
| + iterator iter(AllHostsIterator()); |
| + while (!iter.IsAtEnd()) { |
| + if (GetContentClient()->browser()->MayReuseHost(iter.GetCurrentValue()) && |
| + RenderProcessHostImpl::IsSuitableHost(iter.GetCurrentValue(), |
| + browser_context, site_url)) { |
| + suitable_renderers.push_back(iter.GetCurrentValue()); |
| + } |
| + iter.Advance(); |
| + } |
| + |
| + // Now pick a random suitable renderer, if we have any. |
| + 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 NULL; |
| +} |
| + |
| +// static |
| +bool RenderProcessHost::ShouldUseProcessPerSite(BrowserContext* browser_context, |
| + const GURL& url) { |
| + // Returns true if we should use the process-per-site model. This will be |
| + // the case if the --process-per-site switch is specified, or in |
| + // process-per-site-instance for particular sites (e.g., WebUI). |
| + // Note that --single-process is handled in ShouldTryToUseExistingProcessHost. |
| + const base::CommandLine& command_line = |
| + *base::CommandLine::ForCurrentProcess(); |
| + if (command_line.HasSwitch(switches::kProcessPerSite)) |
| + return true; |
| + |
| + // We want to consolidate particular sites like WebUI even when we are using |
| + // the process-per-tab or process-per-site-instance models. |
| + // Note: DevTools pages have WebUI type but should not reuse the same host. |
| + if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL( |
| + browser_context, url) && |
| + !url.SchemeIs(kChromeDevToolsScheme)) { |
| + return true; |
| + } |
| + |
| + // Otherwise let the content client decide, defaulting to false. |
| + return GetContentClient()->browser()->ShouldUseProcessPerSite(browser_context, |
| + url); |
| +} |
| + |
| +// static |
| +RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite( |
| + BrowserContext* browser_context, |
| + const GURL& url) { |
| + // Look up the map of site to process for the given browser_context. |
| + SiteProcessMap* map = GetSiteProcessMapForBrowserContext(browser_context); |
| + |
| + // See if we have an existing process with appropriate bindings for this site. |
| + // If not, the caller should create a new process and register it. |
| + std::string site = |
| + SiteInstance::GetSiteForURL(browser_context, url).possibly_invalid_spec(); |
| + RenderProcessHost* host = map->FindProcess(site); |
| + if (host && (!GetContentClient()->browser()->MayReuseHost(host) || |
| + !IsSuitableHost(host, browser_context, url))) { |
| + // The registered process does not have an appropriate set of bindings for |
| + // the url. Remove it from the map so we can register a better one. |
| + RecordAction( |
| + base::UserMetricsAction("BindingsMismatch_GetProcessHostPerSite")); |
| + map->RemoveProcess(host); |
| + host = NULL; |
| + } |
| + |
| + return host; |
| +} |
| + |
| +void RenderProcessHostImpl::RegisterProcessHostForSite( |
| + BrowserContext* browser_context, |
| + RenderProcessHost* process, |
| + const GURL& url) { |
| + // Look up the map of site to process for the given browser_context. |
| + SiteProcessMap* map = GetSiteProcessMapForBrowserContext(browser_context); |
| + |
| + // Only register valid, non-empty sites. Empty or invalid sites will not |
| + // use process-per-site mode. We cannot check whether the process has |
| + // appropriate bindings here, because the bindings have not yet been granted. |
| + std::string site = |
| + SiteInstance::GetSiteForURL(browser_context, url).possibly_invalid_spec(); |
| + if (!site.empty()) |
| + map->RegisterProcess(site, process); |
| +} |
| + |
| +void RenderProcessHostImpl::ProcessDied(bool already_dead, |
| + RendererClosedDetails* known_details) { |
| + // Our child process has died. If we didn't expect it, it's a crash. |
| + // In any case, we need to let everyone know it's gone. |
| + // The OnChannelError notification can fire multiple times due to nested sync |
| + // calls to a renderer. If we don't have a valid channel here it means we |
| + // already handled the error. |
| + |
| + // It should not be possible for us to be called re-entrantly. |
| + DCHECK(!within_process_died_observer_); |
| + |
| + // It should not be possible for a process death notification to come in while |
| + // we are dying. |
| + DCHECK(!deleting_soon_); |
| + |
| + // child_process_launcher_ can be NULL in single process mode or if fast |
| + // termination happened. |
| + base::TerminationStatus status = base::TERMINATION_STATUS_NORMAL_TERMINATION; |
| + int exit_code = 0; |
| + if (known_details) { |
| + status = known_details->status; |
| + exit_code = known_details->exit_code; |
| + } else if (child_process_launcher_.get()) { |
| + status = child_process_launcher_->GetChildTerminationStatus(already_dead, |
| + &exit_code); |
| + if (already_dead && status == base::TERMINATION_STATUS_STILL_RUNNING) { |
| + // May be in case of IPC error, if it takes long time for renderer |
| + // to exit. Child process will be killed in any case during |
| + // child_process_launcher_.reset(). Make sure we will not broadcast |
| + // FrameHostMsg_RenderProcessGone with status |
| + // TERMINATION_STATUS_STILL_RUNNING, since this will break WebContentsImpl |
| + // logic. |
| + status = base::TERMINATION_STATUS_PROCESS_CRASHED; |
| + } |
| + } |
| + |
| + RendererClosedDetails details(status, exit_code); |
| + mojo_application_host_->WillDestroySoon(); |
| + |
| + child_process_launcher_.reset(); |
| + channel_.reset(); |
| + while (!queued_messages_.empty()) { |
| + delete queued_messages_.front(); |
| + queued_messages_.pop(); |
| + } |
| + UpdateProcessPriority(); |
| + DCHECK(!is_process_backgrounded_); |
| + |
| + within_process_died_observer_ = true; |
| + NotificationService::current()->Notify( |
| + NOTIFICATION_RENDERER_PROCESS_CLOSED, Source<RenderProcessHost>(this), |
| + Details<RendererClosedDetails>(&details)); |
| + FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_, |
| + RenderProcessExited(this, status, exit_code)); |
| + within_process_died_observer_ = false; |
| + |
| + gpu_message_filter_ = NULL; |
| + message_port_message_filter_ = NULL; |
| + RemoveUserData(kSessionStorageHolderKey); |
| + |
| + // RenderProcessGone handlers might navigate or perform other actions that |
| + // require a connection. Ensure that there is one before calling them. |
| + mojo_application_host_.reset(new MojoApplicationHost); |
| + |
| + IDMap<IPC::Listener>::iterator iter(&listeners_); |
| + while (!iter.IsAtEnd()) { |
| + iter.GetCurrentValue()->OnMessageReceived(FrameHostMsg_RenderProcessGone( |
| + iter.GetCurrentKey(), static_cast<int>(status), exit_code)); |
| + iter.Advance(); |
| + } |
| + |
| + // It's possible that one of the calls out to the observers might have caused |
| + // this object to be no longer needed. |
| + if (delayed_cleanup_needed_) |
| + Cleanup(); |
| + |
| + // This object is not deleted at this point and might be reused later. |
| + // TODO(darin): clean this up |
| +} |
| + |
| +size_t RenderProcessHost::GetActiveViewCount() { |
| + size_t num_active_views = 0; |
| + scoped_ptr<RenderWidgetHostIterator> widgets( |
| + RenderWidgetHost::GetRenderWidgetHosts()); |
| + while (RenderWidgetHost* widget = widgets->GetNextHost()) { |
| + // Count only RenderWidgetHosts in this process. |
| + if (widget->GetProcess()->GetID() == GetID()) |
| + num_active_views++; |
| + } |
| + return num_active_views; |
| +} |
| + |
| +#if defined(ENABLE_WEBRTC) |
| +void RenderProcessHostImpl::WebRtcLogMessage(const std::string& message) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + if (!webrtc_log_message_callback_.is_null()) |
| + webrtc_log_message_callback_.Run(message); |
| +} |
| +#endif |
| + |
| +void RenderProcessHostImpl::ReleaseOnCloseACK( |
| + RenderProcessHost* host, |
| + const SessionStorageNamespaceMap& sessions, |
| + int view_route_id) { |
| + DCHECK(host); |
| + if (sessions.empty()) |
| + return; |
| + SessionStorageHolder* holder = static_cast<SessionStorageHolder*>( |
| + host->GetUserData(kSessionStorageHolderKey)); |
| + if (!holder) { |
| + holder = new SessionStorageHolder(); |
| + host->SetUserData(kSessionStorageHolderKey, holder); |
| + } |
| + holder->Hold(sessions, view_route_id); |
| +} |
| + |
| +void RenderProcessHostImpl::OnShutdownRequest() { |
| + // Don't shut down if there are active RenderViews, or if there are pending |
| + // RenderViews being swapped back in. |
| + // In single process mode, we never shutdown the renderer. |
| + if (pending_views_ || run_renderer_in_process() || GetActiveViewCount() > 0) |
| + return; |
| + |
| + // Notify any contents that might have swapped out renderers from this |
| + // process. They should not attempt to swap them back in. |
| + FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_, |
| + RenderProcessWillExit(this)); |
| + |
| + mojo_application_host_->WillDestroySoon(); |
| + |
| + Send(new ChildProcessMsg_Shutdown()); |
| +} |
| + |
| +void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) { |
| + SetSuddenTerminationAllowed(enabled); |
| +} |
| + |
| +void RenderProcessHostImpl::UpdateProcessPriority() { |
| + if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) { |
| + is_process_backgrounded_ = false; |
| + return; |
| + } |
| + |
| + // We background a process as soon as it hosts no active audio streams and no |
| + // visible widgets -- the callers must call this function whenever we |
| + // transition in/out of those states. |
| + const bool should_background = |
| + visible_widgets_ == 0 && !audio_renderer_host_->HasActiveAudio() && |
| + !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kDisableRendererBackgrounding); |
| + |
| +#if !defined(OS_ANDROID) |
|
gab
2015/09/30 13:33:31
Add a TODO with the bug ID here.
sebsg
2015/09/30 18:26:43
Done.
|
| + if (is_process_backgrounded_ == should_background) |
| + return; |
| +#endif |
| + |
| + TRACE_EVENT1("renderer_host", "RenderProcessHostImpl::UpdateProcessPriority", |
| + "should_background", should_background); |
| + is_process_backgrounded_ = should_background; |
| + |
| +#if defined(OS_WIN) |
| + // The cbstext.dll loads as a global GetMessage hook in the browser process |
| + // and intercepts/unintercepts the kernel32 API SetPriorityClass in a |
| + // background thread. If the UI thread invokes this API just when it is |
| + // intercepted the stack is messed up on return from the interceptor |
| + // which causes random crashes in the browser process. Our hack for now |
| + // is to not invoke the SetPriorityClass API if the dll is loaded. |
| + if (GetModuleHandle(L"cbstext.dll")) |
| + return; |
| +#endif // OS_WIN |
| + |
| +#if defined(OS_WIN) |
| + // Same as below, but bound to an experiment (http://crbug.com/458594 ). |
| + // Enabled by default in the absence of field trials to get coverage on the |
| + // perf waterfall. |
| + base::FieldTrial* trial = |
| + base::FieldTrialList::Find("BackgroundRendererProcesses"); |
| + if (!trial || |
| + !base::StartsWith(trial->group_name(), "Disallow", |
| + base::CompareCase::SENSITIVE)) { |
| + child_process_launcher_->SetProcessBackgrounded(should_background); |
| + } |
| +#else |
| + // Control the background state from the browser process, otherwise the task |
| + // telling the renderer to "unbackground" itself may be preempted by other |
| + // tasks executing at lowered priority ahead of it or simply by not being |
| + // swiftly scheduled by the OS per the low process priority |
| + // (http://crbug.com/398103). |
| + child_process_launcher_->SetProcessBackgrounded(should_background); |
| +#endif // OS_WIN |
| + |
| + // Notify the child process of background state. |
| + Send(new ChildProcessMsg_SetProcessBackgrounded(should_background)); |
| +} |
| + |
| +void RenderProcessHostImpl::OnProcessLaunched() { |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile1( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 RenderProcessHostImpl::OnProcessLaunched::Start")); |
| + // No point doing anything, since this object will be destructed soon. We |
| + // especially don't want to send the RENDERER_PROCESS_CREATED notification, |
| + // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to |
| + // properly cleanup. |
| + if (deleting_soon_) |
| + return; |
| + |
| + if (child_process_launcher_) { |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile2( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 RenderProcessHostImpl::OnProcessLaunched::Backgrounded")); |
| + DCHECK(child_process_launcher_->GetProcess().IsValid()); |
| + DCHECK(!is_process_backgrounded_); |
| + |
| + is_process_backgrounded_ = |
|
gab
2015/09/30 13:33:31
Add a comment like:
// Not all platforms launch p
sebsg
2015/09/30 18:26:43
Done.
|
| + child_process_launcher_->GetProcess().IsProcessBackgrounded(); |
| + |
| + UpdateProcessPriority(); |
| + } |
| + |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile3( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 RenderProcessHostImpl::OnProcessLaunched::Notify")); |
| + // NOTE: This needs to be before sending queued messages because |
| + // ExtensionService uses this notification to initialize the renderer process |
| + // with state that must be there before any JavaScript executes. |
| + // |
| + // The queued messages contain such things as "navigate". If this notification |
| + // was after, we can end up executing JavaScript before the initialization |
| + // happens. |
| + NotificationService::current()->Notify(NOTIFICATION_RENDERER_PROCESS_CREATED, |
| + Source<RenderProcessHost>(this), |
| + NotificationService::NoDetails()); |
| + |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile4( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 RenderProcessHostImpl::OnProcessLaunched::MojoActivate")); |
| + // Allow Mojo to be setup before the renderer sees any Chrome IPC messages. |
| + // This way, Mojo can be safely used from the renderer in response to any |
| + // Chrome IPC message. |
| + mojo_application_host_->Activate(this, GetHandle()); |
| + |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile5( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 RenderProcessHostImpl::OnProcessLaunched::MojoClientLaunch")); |
| + |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile6( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 " |
| + "RenderProcessHostImpl::OnProcessLaunched::SendQueuedMessages")); |
| + while (!queued_messages_.empty()) { |
| + Send(queued_messages_.front()); |
| + queued_messages_.pop(); |
| + } |
| + |
| +#if defined(ENABLE_WEBRTC) |
| + // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/465841 |
| + // is fixed. |
| + tracked_objects::ScopedTracker tracking_profile7( |
| + FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| + "465841 RenderProcessHostImpl::OnProcessLaunched::EnableAec")); |
| + if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) { |
| + EnableAudioDebugRecordings( |
| + WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath()); |
| + } |
| +#endif |
| +} |
| + |
| +void RenderProcessHostImpl::OnProcessLaunchFailed() { |
| + // If this object will be destructed soon, then observers have already been |
| + // sent a RenderProcessHostDestroyed notification, and we must observe our |
| + // contract that says that will be the last call. |
| + if (deleting_soon_) |
| + return; |
| + |
| + // TODO(wfh): Fill in the real error code here see crbug.com/526198. |
| + RendererClosedDetails details{base::TERMINATION_STATUS_LAUNCH_FAILED, -1}; |
| + ProcessDied(true, &details); |
| +} |
| + |
| +scoped_refptr<AudioRendererHost> RenderProcessHostImpl::audio_renderer_host() |
| + const { |
| + return audio_renderer_host_; |
| +} |
| + |
| +void RenderProcessHostImpl::OnUserMetricsRecordAction( |
| + const std::string& action) { |
| + RecordComputedAction(action); |
| +} |
| + |
| +void RenderProcessHostImpl::OnCloseACK(int old_route_id) { |
| + SessionStorageHolder* holder = |
| + static_cast<SessionStorageHolder*>(GetUserData(kSessionStorageHolderKey)); |
| + if (!holder) |
| + return; |
| + holder->Release(old_route_id); |
| +} |
| + |
| +void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) { |
| + MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size); |
| +} |
| + |
| +void RenderProcessHostImpl::OnGpuSwitched() { |
| + // We are updating all widgets including swapped out ones. |
| + scoped_ptr<RenderWidgetHostIterator> widgets( |
| + RenderWidgetHostImpl::GetAllRenderWidgetHosts()); |
| + while (RenderWidgetHost* widget = widgets->GetNextHost()) { |
| + if (!widget->IsRenderView()) |
| + continue; |
| + |
| + // Skip widgets in other processes. |
| + if (widget->GetProcess()->GetID() != GetID()) |
| + continue; |
| + |
| + RenderViewHost* rvh = RenderViewHost::From(widget); |
| + rvh->OnWebkitPreferencesChanged(); |
| + } |
| +} |
| + |
| +#if defined(ENABLE_WEBRTC) |
| +void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread, |
| + weak_factory_.GetWeakPtr(), id)); |
| +} |
| + |
| +void RenderProcessHostImpl::OnUnregisterAecDumpConsumer(int id) { |
| + BrowserThread::PostTask( |
| + BrowserThread::UI, FROM_HERE, |
| + base::Bind(&RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread, |
| + weak_factory_.GetWeakPtr(), id)); |
| +} |
| + |
| +void RenderProcessHostImpl::RegisterAecDumpConsumerOnUIThread(int id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + aec_dump_consumers_.push_back(id); |
| + |
| + if (WebRTCInternals::GetInstance()->IsAudioDebugRecordingsEnabled()) { |
| + base::FilePath file_with_extensions = GetAecDumpFilePathWithExtensions( |
| + WebRTCInternals::GetInstance()->GetAudioDebugRecordingsFilePath()); |
| + EnableAecDumpForId(file_with_extensions, id); |
| + } |
| +} |
| + |
| +void RenderProcessHostImpl::UnregisterAecDumpConsumerOnUIThread(int id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + for (std::vector<int>::iterator it = aec_dump_consumers_.begin(); |
| + it != aec_dump_consumers_.end(); ++it) { |
| + if (*it == id) { |
| + aec_dump_consumers_.erase(it); |
| + break; |
| + } |
| + } |
| +} |
| + |
| +void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file, |
| + int id) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + BrowserThread::PostTaskAndReplyWithResult( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&CreateAecDumpFileForProcess, |
| + file.AddExtension(IntToStringType(id)), GetHandle()), |
| + base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer, |
| + weak_factory_.GetWeakPtr(), id)); |
| +} |
| + |
| +void RenderProcessHostImpl::SendAecDumpFileToRenderer( |
| + int id, |
| + IPC::PlatformFileForTransit file_for_transit) { |
| + if (file_for_transit == IPC::InvalidPlatformFileForTransit()) |
| + return; |
| + Send(new AecDumpMsg_EnableAecDump(id, file_for_transit)); |
| +} |
| + |
| +void RenderProcessHostImpl::SendDisableAecDumpToRenderer() { |
| + Send(new AecDumpMsg_DisableAecDump()); |
| +} |
| + |
| +base::FilePath RenderProcessHostImpl::GetAecDumpFilePathWithExtensions( |
| + const base::FilePath& file) { |
| + return file.AddExtension(IntToStringType(base::GetProcId(GetHandle()))) |
| + .AddExtension(kAecDumpFileNameAddition); |
| +} |
| +#endif // defined(ENABLE_WEBRTC) |
| + |
| +void RenderProcessHostImpl::IncrementWorkerRefCount() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + ++worker_ref_count_; |
| + if (worker_ref_count_ > max_worker_count_) |
| + max_worker_count_ = worker_ref_count_; |
| +} |
| + |
| +void RenderProcessHostImpl::DecrementWorkerRefCount() { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + DCHECK_GT(worker_ref_count_, 0); |
| + --worker_ref_count_; |
| + if (worker_ref_count_ == 0) |
| + Cleanup(); |
| +} |
| + |
| +void RenderProcessHostImpl::GetAudioOutputControllers( |
| + const GetAudioOutputControllersCallback& callback) const { |
| + audio_renderer_host()->GetOutputControllers(callback); |
| +} |
| + |
| +BluetoothDispatcherHost* RenderProcessHostImpl::GetBluetoothDispatcherHost() { |
| + return bluetooth_dispatcher_host_.get(); |
| +} |
| + |
| +} // namespace content |