render_process_host_impl.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
105bc091336fa31dd0fe62058ae273900d9f8c8ecChris Lattner// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// Use of this source code is governed by a BSD-style license that can be 3cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// found in the LICENSE file. 4cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 5cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// Represents the browser side of the browser <--> renderer communication 6cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// channel. There will be one RenderProcessHost per renderer process. 7cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 8cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/render_process_host_impl.h" 9cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 10cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include <algorithm> 11cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include <limits> 12cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include <vector> 13cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 14cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#if defined(OS_POSIX) 15cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include <utility> // for pair<> 16674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#endif 17674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak 18cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/base_switches.h" 19dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "base/bind.h" 20cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/bind_helpers.h" 21255f89faee13dc491cb64fbeae3c763e7e2ea4e6Chandler Carruth#include "base/callback.h" 22cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/command_line.h" 2336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "base/debug/trace_event.h" 24cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/lazy_instance.h" 25cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/logging.h" 26cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/metrics/field_trial.h" 27cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/metrics/histogram.h" 28cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/path_service.h" 29cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/platform_file.h" 30cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/process_util.h" 31cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/rand_util.h" 32cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/stl_util.h" 33cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/string_util.h" 34cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/supports_user_data.h" 35cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/sys_info.h" 36cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/threading/thread.h" 37cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/threading/thread_restrictions.h" 38cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/tracked_objects.h" 39cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "cc/switches.h" 40cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/appcache/appcache_dispatcher_host.h" 41cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/appcache/chrome_appcache_service.h" 42cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/browser_main.h" 43cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/browser_main_loop.h" 44cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/child_process_security_policy_impl.h" 45cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/device_orientation/orientation_message_filter.h" 46cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/dom_storage/dom_storage_context_impl.h" 47cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/dom_storage/dom_storage_message_filter.h" 48cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/download/mhtml_generation_manager.h" 49cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/fileapi/chrome_blob_storage_context.h" 50cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/fileapi/fileapi_message_filter.h" 51cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/geolocation/geolocation_dispatcher_host.h" 52cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/gpu/gpu_data_manager_impl.h" 53cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/gpu/gpu_process_host.h" 54cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/histogram_message_filter.h" 55cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/hyphenator/hyphenator_message_filter.h" 56cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/in_process_webkit/indexed_db_context_impl.h" 57cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h" 58cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/mime_registry_message_filter.h" 59cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/plugin_service_impl.h" 60cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/profiler_message_filter.h" 61cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/clipboard_message_filter.h" 62cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/database_message_filter.h" 63cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/file_utilities_message_filter.h" 64cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/gamepad_browser_message_filter.h" 65cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/gpu_message_filter.h" 66cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/media/audio_input_renderer_host.h" 67cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/media/audio_renderer_host.h" 68cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h" 69cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/media/video_capture_host.h" 70cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h" 71cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/pepper/pepper_file_message_filter.h" 72cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/pepper/pepper_message_filter.h" 73cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/quota_dispatcher_host.h" 74cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/render_message_filter.h" 75cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/render_view_host_delegate.h" 76cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/render_view_host_impl.h" 77cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/render_widget_helper.h" 78cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/resource_message_filter.h" 79cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/socket_stream_dispatcher_host.h" 80cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/renderer_host/text_input_client_message_filter.h" 81cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/resolve_proxy_msg_helper.h" 82cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/storage_partition_impl.h" 83cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/speech/input_tag_speech_dispatcher_host.h" 84cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/speech/speech_recognition_dispatcher_host.h" 85cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/trace_message_filter.h" 86cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/worker_host/worker_storage_partition.h" 87cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/browser/worker_host/worker_message_filter.h" 88cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/common/child_process_host_impl.h" 89cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/common/child_process_messages.h" 90cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/common/gpu/gpu_messages.h" 91cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/common/resource_messages.h" 92cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/common/view_messages.h" 93cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/browser_context.h" 94cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/content_browser_client.h" 95cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/notification_service.h" 96cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/render_process_host_factory.h" 97cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/resource_context.h" 98cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/user_metrics.h" 99cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/browser/web_ui_controller_factory.h" 100cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/common/content_constants.h" 101cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/common/content_switches.h" 102cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/common/process_type.h" 103cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/common/result_codes.h" 104cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/public/common/url_constants.h" 105cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/renderer/render_process_impl.h" 106cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/renderer/render_thread_impl.h" 107cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ipc/ipc_channel.h" 108cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ipc/ipc_logging.h" 109cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ipc/ipc_platform_file.h" 110cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ipc/ipc_switches.h" 111cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ipc/ipc_sync_channel.h" 112cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "media/base/media_switches.h" 113cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "net/url_request/url_request_context_getter.h" 114cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ppapi/shared_impl/ppapi_switches.h" 115cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ui/base/ui_base_switches.h" 116cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "ui/gl/gl_switches.h" 117cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "webkit/fileapi/sandbox_mount_point_provider.h" 118cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "webkit/glue/resource_type.h" 119cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "webkit/plugins/plugin_switches.h" 120cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 121cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#if defined(OS_WIN) 122cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "base/win/scoped_com_initializer.h" 123cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "content/common/font_cache_dispatcher_win.h" 124cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#endif 125cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 126cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem#include "third_party/skia/include/core/SkBitmap.h" 127cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 128cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotemextern bool g_exited_main_message_loop; 129cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 130cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotemstatic const char* kSiteProcessMapKeyName = "content_site_process_map"; 131cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 132cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotemnamespace content { 133cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 134cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// This class creates the IO thread for the renderer when running in 135cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// single-process mode. It's not used in multi-process mode. 136cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotemclass RendererMainThread : public base::Thread { 137cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem public: 138cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem explicit RendererMainThread(const std::string& channel_id) 139cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem : Thread("Chrome_InProcRendererThread"), 140cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem channel_id_(channel_id) { 141135fe6ac5f5b80ef68c19b3ec7bb0063e28f2babBenjamin Kramer } 142cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 143cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem virtual ~RendererMainThread() { 144cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem Stop(); 145cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem } 146cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 147cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem protected: 148cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem virtual void Init() OVERRIDE { 149cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem render_process_.reset(new RenderProcessImpl()); 150cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem new RenderThreadImpl(channel_id_); 151cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem } 152cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 153cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem virtual void CleanUp() { 154cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem render_process_.reset(); 155cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 156cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // It's a little lame to manually set this flag. But the single process 157cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // RendererThread will receive the WM_QUIT. We don't need to assert on 158cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // this thread, so just force the flag manually. 159cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // If we want to avoid this, we could create the InProcRendererThread 160cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // directly with _beginthreadex() rather than using the Thread class. 161cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // We used to set this flag in the Init function above. However there 162cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // other threads like WebThread which are created by this thread 163cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // which resets this flag. Please see Thread::StartWithOptions. Setting 164cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // this flag to true in Cleanup works around these problems. 165cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem SetThreadWasQuitProperly(true); 166cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem } 167cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 168cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem private: 169cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem std::string channel_id_; 170cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem scoped_ptr<RenderProcess> render_process_; 171cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 172cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem DISALLOW_COPY_AND_ASSIGN(RendererMainThread); 173cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem}; 174cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 175cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotemnamespace { 176cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 177cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// Helper class that we pass to ResourceMessageFilter so that it can find the 178cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem// right net::URLRequestContext for a request. 179cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotemclass RendererURLRequestContextSelector 180cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem : public ResourceMessageFilter::URLRequestContextSelector { 181cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem public: 182cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem RendererURLRequestContextSelector(BrowserContext* browser_context, 183cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem int render_child_id) 184cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem : request_context_(browser_context->GetRequestContextForRenderProcess( 185cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem render_child_id)), 186cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem media_request_context_( 187cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem browser_context->GetMediaRequestContextForRenderProcess( 188cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem render_child_id)) { 189cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem } 190cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem 191cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem virtual net::URLRequestContext* GetRequestContext( 192cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem ResourceType::Type resource_type) { 193cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem net::URLRequestContextGetter* request_context = request_context_; 194cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // If the request has resource type of ResourceType::MEDIA, we use a request 195cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem // context specific to media for handling it because these resources have 196dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // specific needs for caching. 197dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines if (resource_type == ResourceType::MEDIA) 198dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines request_context = media_request_context_; 199dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return request_context->GetURLRequestContext(); 200dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 201dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines private: 203dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines virtual ~RendererURLRequestContextSelector() {} 204dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines scoped_refptr<net::URLRequestContextGetter> request_context_; 20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines scoped_refptr<net::URLRequestContextGetter> media_request_context_; 20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines}; 20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// the global list of all renderer processes 21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbase::LazyInstance<IDMap<RenderProcessHost> >::Leaky 21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines g_all_hosts = LAZY_INSTANCE_INITIALIZER; 21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 21336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Map of site to process, to ensure we only have one RenderProcessHost per 21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// site in process-per-site mode. Each map is specific to a BrowserContext. 21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesclass SiteProcessMap : public base::SupportsUserData::Data { 21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines public: 21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines typedef base::hash_map<std::string, RenderProcessHost*> SiteToProcessMap; 21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SiteProcessMap() {} 21936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 22036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines void RegisterProcess(const std::string& site, RenderProcessHost* process) { 22136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines map_[site] = process; 22236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines } 22336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 22436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines RenderProcessHost* FindProcess(const std::string& site) { 22536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines SiteToProcessMap::iterator i = map_.find(site); 22636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines if (i != map_.end()) 227dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return i->second; 228dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines return NULL; 229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines } 230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines 231dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines void RemoveProcess(RenderProcessHost* host) { 23236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // Find all instances of this process in the map, then separately remove 23336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines // them. 23436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines std::set<std::string> sites; 235cbd9a19b5d6ff93efa82c467508ede78b8af3bacNadav Rotem for (SiteToProcessMap::const_iterator i = map_.begin(); 236 i != map_.end(); 237 i++) { 238 if (i->second == host) 239 sites.insert(i->first); 240 } 241 for (std::set<std::string>::iterator i = sites.begin(); 242 i != sites.end(); 243 i++) { 244 SiteToProcessMap::iterator iter = map_.find(*i); 245 if (iter != map_.end()) { 246 DCHECK_EQ(iter->second, host); 247 map_.erase(iter); 248 } 249 } 250 } 251 252 private: 253 SiteToProcessMap map_; 254}; 255 256// Find the SiteProcessMap specific to the given context. 257SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) { 258 DCHECK(context); 259 SiteProcessMap* map = static_cast<SiteProcessMap*>( 260 context->GetUserData(kSiteProcessMapKeyName)); 261 if (!map) { 262 map = new SiteProcessMap(); 263 context->SetUserData(kSiteProcessMapKeyName, map); 264 } 265 return map; 266} 267 268} // namespace 269 270// Stores the maximum number of renderer processes the content module can 271// create. 272static size_t g_max_renderer_count_override = 0; 273 274// static 275size_t RenderProcessHost::GetMaxRendererProcessCount() { 276 if (g_max_renderer_count_override) 277 return g_max_renderer_count_override; 278 279 // Defines the maximum number of renderer processes according to the 280 // amount of installed memory as reported by the OS. The calculation 281 // assumes that you want the renderers to use half of the installed 282 // RAM and assuming that each WebContents uses ~40MB. 283 // If you modify this assumption, you need to adjust the 284 // ThirtyFourTabs test to match the expected number of processes. 285 // 286 // With the given amounts of installed memory below on a 32-bit CPU, 287 // the maximum renderer count will roughly be as follows: 288 // 289 // 128 MB -> 3 290 // 512 MB -> 6 291 // 1024 MB -> 12 292 // 4096 MB -> 51 293 // 16384 MB -> 82 (kMaxRendererProcessCount) 294 295 static size_t max_count = 0; 296 if (!max_count) { 297 const size_t kEstimatedWebContentsMemoryUsage = 298#if defined(ARCH_CPU_64_BITS) 299 60; // In MB 300#else 301 40; // In MB 302#endif 303 max_count = base::SysInfo::AmountOfPhysicalMemoryMB() / 2; 304 max_count /= kEstimatedWebContentsMemoryUsage; 305 306 const size_t kMinRendererProcessCount = 3; 307 max_count = std::max(max_count, kMinRendererProcessCount); 308 max_count = std::min(max_count, kMaxRendererProcessCount); 309 } 310 return max_count; 311} 312 313// static 314bool g_run_renderer_in_process_ = false; 315 316// static 317void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { 318 g_max_renderer_count_override = count; 319} 320 321RenderProcessHostImpl::RenderProcessHostImpl( 322 BrowserContext* browser_context, 323 StoragePartitionImpl* storage_partition_impl, 324 bool is_guest) 325 : fast_shutdown_started_(false), 326 deleting_soon_(false), 327 pending_views_(0), 328 visible_widgets_(0), 329 backgrounded_(true), 330 ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_( 331 FROM_HERE, base::TimeDelta::FromSeconds(5), 332 this, &RenderProcessHostImpl::ClearTransportDIBCache)), 333 is_initialized_(false), 334 id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), 335 browser_context_(browser_context), 336 storage_partition_impl_(storage_partition_impl), 337 sudden_termination_allowed_(true), 338 ignore_input_events_(false), 339#if defined(OS_ANDROID) 340 dummy_shutdown_event_(false, false), 341#endif 342 is_guest_(is_guest) { 343 widget_helper_ = new RenderWidgetHelper(); 344 345 ChildProcessSecurityPolicyImpl::GetInstance()->Add(GetID()); 346 347 // Grant most file permissions to this renderer. 348 // PLATFORM_FILE_TEMPORARY, PLATFORM_FILE_HIDDEN and 349 // PLATFORM_FILE_DELETE_ON_CLOSE are not granted, because no existing API 350 // requests them. 351 // This is for the filesystem sandbox. 352 ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile( 353 GetID(), storage_partition_impl->GetPath().Append( 354 fileapi::SandboxMountPointProvider::kNewFileSystemDirectory), 355 base::PLATFORM_FILE_OPEN | 356 base::PLATFORM_FILE_CREATE | 357 base::PLATFORM_FILE_OPEN_ALWAYS | 358 base::PLATFORM_FILE_CREATE_ALWAYS | 359 base::PLATFORM_FILE_OPEN_TRUNCATED | 360 base::PLATFORM_FILE_READ | 361 base::PLATFORM_FILE_WRITE | 362 base::PLATFORM_FILE_EXCLUSIVE_READ | 363 base::PLATFORM_FILE_EXCLUSIVE_WRITE | 364 base::PLATFORM_FILE_ASYNC | 365 base::PLATFORM_FILE_WRITE_ATTRIBUTES | 366 base::PLATFORM_FILE_ENUMERATE); 367 // This is so that we can read and move stuff out of the old filesystem 368 // sandbox. 369 ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile( 370 GetID(), storage_partition_impl_->GetPath().Append( 371 fileapi::SandboxMountPointProvider::kOldFileSystemDirectory), 372 base::PLATFORM_FILE_READ | base::PLATFORM_FILE_WRITE | 373 base::PLATFORM_FILE_WRITE_ATTRIBUTES | base::PLATFORM_FILE_ENUMERATE); 374 // This is so that we can rename the old sandbox out of the way so that we 375 // know we've taken care of it. 376 ChildProcessSecurityPolicyImpl::GetInstance()->GrantPermissionsForFile( 377 GetID(), storage_partition_impl_->GetPath().Append( 378 fileapi::SandboxMountPointProvider::kRenamedOldFileSystemDirectory), 379 base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_CREATE_ALWAYS | 380 base::PLATFORM_FILE_WRITE); 381 382 CHECK(!g_exited_main_message_loop); 383 RegisterHost(GetID(), this); 384 g_all_hosts.Get().set_check_on_null_data(true); 385 // Initialize |child_process_activity_time_| to a reasonable value. 386 mark_child_process_activity_time(); 387 // Note: When we create the RenderProcessHostImpl, it's technically 388 // backgrounded, because it has no visible listeners. But the process 389 // doesn't actually exist yet, so we'll Background it later, after 390 // creation. 391} 392 393RenderProcessHostImpl::~RenderProcessHostImpl() { 394 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(GetID()); 395 396 // We may have some unsent messages at this point, but that's OK. 397 channel_.reset(); 398 while (!queued_messages_.empty()) { 399 delete queued_messages_.front(); 400 queued_messages_.pop(); 401 } 402 403 if (run_renderer_in_process()) { 404 // In single process mode, need to set IO allowed in browser main thread 405 // before joining the renderer thread 406 base::ThreadRestrictions::ScopedAllowIO allow_io; 407 in_process_renderer_.reset(); 408 } 409 410 ClearTransportDIBCache(); 411 UnregisterHost(GetID()); 412} 413 414void RenderProcessHostImpl::EnableSendQueue() { 415 is_initialized_ = false; 416} 417 418bool RenderProcessHostImpl::Init() { 419 // calling Init() more than once does nothing, this makes it more convenient 420 // for the view host which may not be sure in some cases 421 if (channel_.get()) 422 return true; 423 424 CommandLine::StringType renderer_prefix; 425#if defined(OS_POSIX) 426 // A command prefix is something prepended to the command line of the spawned 427 // process. It is supported only on POSIX systems. 428 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 429 renderer_prefix = 430 browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix); 431#endif // defined(OS_POSIX) 432 433#if defined(OS_LINUX) 434 int flags = renderer_prefix.empty() ? ChildProcessHost::CHILD_ALLOW_SELF : 435 ChildProcessHost::CHILD_NORMAL; 436#else 437 int flags = ChildProcessHost::CHILD_NORMAL; 438#endif 439 440 // Find the renderer before creating the channel so if this fails early we 441 // return without creating the channel. 442 FilePath renderer_path = ChildProcessHost::GetChildPath(flags); 443 if (renderer_path.empty()) 444 return false; 445 446 // Setup the IPC channel. 447 const std::string channel_id = 448 IPC::Channel::GenerateVerifiedChannelID(std::string()); 449 channel_.reset( 450#if defined(OS_ANDROID) 451 // Android WebView needs to be able to wait from the UI thread to support 452 // the synchronous legacy APIs. 453 browser_command_line.HasSwitch(switches::kEnableWebViewSynchronousAPIs) ? 454 new IPC::SyncChannel( 455 channel_id, IPC::Channel::MODE_SERVER, this, 456 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), 457 true, &dummy_shutdown_event_) : 458#endif 459 new IPC::ChannelProxy( 460 channel_id, IPC::Channel::MODE_SERVER, this, 461 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); 462 463 // Call the embedder first so that their IPC filters have priority. 464 GetContentClient()->browser()->RenderProcessHostCreated(this); 465 466 CreateMessageFilters(); 467 468 if (run_renderer_in_process()) { 469 // Crank up a thread and run the initialization there. With the way that 470 // messages flow between the browser and renderer, this thread is required 471 // to prevent a deadlock in single-process mode. Since the primordial 472 // thread in the renderer process runs the WebKit code and can sometimes 473 // make blocking calls to the UI thread (i.e. this thread), they need to run 474 // on separate threads. 475 in_process_renderer_.reset(new RendererMainThread(channel_id)); 476 477 base::Thread::Options options; 478#if !defined(TOOLKIT_GTK) && !defined(OS_ANDROID) 479 // In-process plugins require this to be a UI message loop. 480 options.message_loop_type = MessageLoop::TYPE_UI; 481#else 482 // We can't have multiple UI loops on GTK and Android, so we don't support 483 // in-process plugins. 484 options.message_loop_type = MessageLoop::TYPE_DEFAULT; 485#endif 486 in_process_renderer_->StartWithOptions(options); 487 488 OnProcessLaunched(); // Fake a callback that the process is ready. 489 } else { 490 // Build command line for renderer. We call AppendRendererCommandLine() 491 // first so the process type argument will appear first. 492 CommandLine* cmd_line = new CommandLine(renderer_path); 493 if (!renderer_prefix.empty()) 494 cmd_line->PrependWrapper(renderer_prefix); 495 AppendRendererCommandLine(cmd_line); 496 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id); 497 498 // Spawn the child process asynchronously to avoid blocking the UI thread. 499 // As long as there's no renderer prefix, we can use the zygote process 500 // at this stage. 501 child_process_launcher_.reset(new ChildProcessLauncher( 502#if defined(OS_WIN) 503 FilePath(), 504#elif defined(OS_POSIX) 505 renderer_prefix.empty(), 506 base::EnvironmentVector(), 507 channel_->TakeClientFileDescriptor(), 508#endif 509 cmd_line, 510 GetID(), 511 this)); 512 513 fast_shutdown_started_ = false; 514 } 515 516 is_initialized_ = true; 517 return true; 518} 519 520void RenderProcessHostImpl::CreateMessageFilters() { 521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 522 MediaObserver* media_observer = 523 GetContentClient()->browser()->GetMediaObserver(); 524 scoped_refptr<RenderMessageFilter> render_message_filter( 525 new RenderMessageFilter( 526 GetID(), 527 PluginServiceImpl::GetInstance(), 528 GetBrowserContext(), 529 GetBrowserContext()->GetRequestContextForRenderProcess(GetID()), 530 widget_helper_, 531 media_observer, 532 storage_partition_impl_->GetDOMStorageContext())); 533 channel_->AddFilter(render_message_filter); 534 BrowserContext* browser_context = GetBrowserContext(); 535 ResourceContext* resource_context = browser_context->GetResourceContext(); 536 537 ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter( 538 GetID(), PROCESS_TYPE_RENDERER, resource_context, 539 storage_partition_impl_->GetAppCacheService(), 540 ChromeBlobStorageContext::GetFor(browser_context), 541 new RendererURLRequestContextSelector(browser_context, GetID())); 542 543 channel_->AddFilter(resource_message_filter); 544 media::AudioManager* audio_manager = BrowserMainLoop::GetAudioManager(); 545 MediaStreamManager* media_stream_manager = 546 BrowserMainLoop::GetMediaStreamManager(); 547 channel_->AddFilter(new AudioInputRendererHost(audio_manager, 548 media_stream_manager)); 549 channel_->AddFilter(new AudioRendererHost(audio_manager, media_observer)); 550 channel_->AddFilter(new VideoCaptureHost()); 551 channel_->AddFilter(new AppCacheDispatcherHost( 552 storage_partition_impl_->GetAppCacheService(), 553 GetID())); 554 channel_->AddFilter(new ClipboardMessageFilter()); 555 channel_->AddFilter( 556 new DOMStorageMessageFilter( 557 GetID(), 558 storage_partition_impl_->GetDOMStorageContext())); 559 channel_->AddFilter( 560 new IndexedDBDispatcherHost( 561 GetID(), 562 storage_partition_impl_->GetIndexedDBContext())); 563 channel_->AddFilter(GeolocationDispatcherHost::New( 564 GetID(), browser_context->GetGeolocationPermissionContext())); 565 gpu_message_filter_ = new GpuMessageFilter(GetID(), widget_helper_.get()); 566 channel_->AddFilter(gpu_message_filter_); 567#if defined(ENABLE_WEBRTC) 568 channel_->AddFilter(new MediaStreamDispatcherHost(GetID())); 569#endif 570 channel_->AddFilter( 571 GetContentClient()->browser()->AllowPepperPrivateFileAPI() ? 572 new PepperUnsafeFileMessageFilter( 573 GetID(), 574 storage_partition_impl_->GetPath()) : 575 new PepperFileMessageFilter(GetID())); 576 channel_->AddFilter(new PepperMessageFilter(PepperMessageFilter::RENDERER, 577 GetID(), browser_context)); 578#if defined(ENABLE_INPUT_SPEECH) 579 channel_->AddFilter(new InputTagSpeechDispatcherHost( 580 GetID(), storage_partition_impl_->GetURLRequestContext(), 581 browser_context->GetSpeechRecognitionPreferences())); 582 channel_->AddFilter(new SpeechRecognitionDispatcherHost( 583 GetID(), storage_partition_impl_->GetURLRequestContext(), 584 browser_context->GetSpeechRecognitionPreferences())); 585#endif 586 channel_->AddFilter(new FileAPIMessageFilter( 587 GetID(), 588 storage_partition_impl_->GetURLRequestContext(), 589 storage_partition_impl_->GetFileSystemContext(), 590 ChromeBlobStorageContext::GetFor(browser_context))); 591 channel_->AddFilter(new OrientationMessageFilter()); 592 channel_->AddFilter(new FileUtilitiesMessageFilter(GetID())); 593 channel_->AddFilter(new MimeRegistryMessageFilter()); 594 channel_->AddFilter(new DatabaseMessageFilter( 595 storage_partition_impl_->GetDatabaseTracker())); 596#if defined(OS_MACOSX) 597 channel_->AddFilter(new TextInputClientMessageFilter(GetID())); 598#elif defined(OS_WIN) 599 channel_->AddFilter(new FontCacheDispatcher()); 600#endif 601 602 SocketStreamDispatcherHost* socket_stream_dispatcher_host = 603 new SocketStreamDispatcherHost(GetID(), 604 new RendererURLRequestContextSelector(browser_context, GetID()), 605 resource_context); 606 channel_->AddFilter(socket_stream_dispatcher_host); 607 608 channel_->AddFilter( 609 new WorkerMessageFilter( 610 GetID(), 611 resource_context, 612 WorkerStoragePartition( 613 storage_partition_impl_->GetURLRequestContext(), 614 storage_partition_impl_->GetMediaURLRequestContext(), 615 storage_partition_impl_->GetAppCacheService(), 616 storage_partition_impl_->GetFileSystemContext(), 617 storage_partition_impl_->GetDatabaseTracker(), 618 storage_partition_impl_->GetIndexedDBContext()), 619 base::Bind(&RenderWidgetHelper::GetNextRoutingID, 620 base::Unretained(widget_helper_.get())))); 621 622#if defined(ENABLE_WEBRTC) 623 channel_->AddFilter(new P2PSocketDispatcherHost(resource_context)); 624#endif 625 626 channel_->AddFilter(new TraceMessageFilter()); 627 channel_->AddFilter(new ResolveProxyMsgHelper( 628 browser_context->GetRequestContextForRenderProcess(GetID()))); 629 channel_->AddFilter(new QuotaDispatcherHost( 630 GetID(), 631 storage_partition_impl_->GetQuotaManager(), 632 GetContentClient()->browser()->CreateQuotaPermissionContext())); 633 channel_->AddFilter(new GamepadBrowserMessageFilter()); 634 channel_->AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER)); 635 channel_->AddFilter(new HistogramMessageFilter()); 636 channel_->AddFilter(new HyphenatorMessageFilter(this)); 637} 638 639int RenderProcessHostImpl::GetNextRoutingID() { 640 return widget_helper_->GetNextRoutingID(); 641} 642 643void RenderProcessHostImpl::CancelResourceRequests(int render_widget_id) { 644 widget_helper_->CancelResourceRequests(render_widget_id); 645} 646 647void RenderProcessHostImpl::SimulateSwapOutACK( 648 const ViewMsg_SwapOut_Params& params) { 649 widget_helper_->SimulateSwapOutACK(params); 650} 651 652bool RenderProcessHostImpl::WaitForBackingStoreMsg( 653 int render_widget_id, 654 const base::TimeDelta& max_delay, 655 IPC::Message* msg) { 656 // The post task to this thread with the process id could be in queue, and we 657 // don't want to dispatch a message before then since it will need the handle. 658 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) 659 return false; 660 661 return widget_helper_->WaitForBackingStoreMsg(render_widget_id, 662 max_delay, msg); 663} 664 665void RenderProcessHostImpl::ReceivedBadMessage() { 666 if (run_renderer_in_process()) { 667 // In single process mode it is better if we don't suicide but just 668 // crash. 669 CHECK(false); 670 } 671 NOTREACHED(); 672 base::KillProcess(GetHandle(), RESULT_CODE_KILLED_BAD_MESSAGE, 673 false); 674} 675 676void RenderProcessHostImpl::WidgetRestored() { 677 // Verify we were properly backgrounded. 678 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); 679 visible_widgets_++; 680 SetBackgrounded(false); 681} 682 683void RenderProcessHostImpl::WidgetHidden() { 684 // On startup, the browser will call Hide 685 if (backgrounded_) 686 return; 687 688 DCHECK_EQ(backgrounded_, (visible_widgets_ == 0)); 689 visible_widgets_--; 690 DCHECK_GE(visible_widgets_, 0); 691 if (visible_widgets_ == 0) { 692 DCHECK(!backgrounded_); 693 SetBackgrounded(true); 694 } 695} 696 697int RenderProcessHostImpl::VisibleWidgetCount() const { 698 return visible_widgets_; 699} 700 701bool RenderProcessHostImpl::IsGuest() const { 702 return is_guest_; 703} 704 705StoragePartition* RenderProcessHostImpl::GetStoragePartition() const { 706 return storage_partition_impl_; 707} 708 709void RenderProcessHostImpl::AppendRendererCommandLine( 710 CommandLine* command_line) const { 711 // Pass the process type first, so it shows first in process listings. 712 command_line->AppendSwitchASCII(switches::kProcessType, 713 switches::kRendererProcess); 714 if (is_guest_) 715 command_line->AppendSwitch(switches::kGuestRenderer); 716 717 // Now send any options from our own command line we want to propagate. 718 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 719 PropagateBrowserCommandLineToRenderer(browser_command_line, command_line); 720 721 // Pass on the browser locale. 722 const std::string locale = 723 GetContentClient()->browser()->GetApplicationLocale(); 724 command_line->AppendSwitchASCII(switches::kLang, locale); 725 726 // If we run base::FieldTrials, we want to pass to their state to the 727 // renderer so that it can act in accordance with each state, or record 728 // histograms relating to the base::FieldTrial states. 729 std::string field_trial_states; 730 base::FieldTrialList::StatesToString(&field_trial_states); 731 if (!field_trial_states.empty()) { 732 command_line->AppendSwitchASCII(switches::kForceFieldTrials, 733 field_trial_states); 734 } 735 736 GetContentClient()->browser()->AppendExtraCommandLineSwitches( 737 command_line, GetID()); 738 739 // Appending disable-gpu-feature switches due to software rendering list. 740 GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance(); 741 DCHECK(gpu_data_manager); 742 gpu_data_manager->AppendRendererCommandLine(command_line); 743} 744 745void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer( 746 const CommandLine& browser_cmd, 747 CommandLine* renderer_cmd) const { 748 // Propagate the following switches to the renderer command line (along 749 // with any associated values) if present in the browser command line. 750 static const char* const kSwitchNames[] = { 751 // We propagate the Chrome Frame command line here as well in case the 752 // renderer is not run in the sandbox. 753 switches::kAuditAllHandles, 754 switches::kAuditHandles, 755 switches::kChromeFrame, 756 switches::kDisable3DAPIs, 757 switches::kDisableAcceleratedCompositing, 758 switches::kDisableAcceleratedVideoDecode, 759 switches::kDisableApplicationCache, 760 switches::kDisableAudio, 761 switches::kDisableAudioOutputResampler, 762 switches::kDisableBreakpad, 763#if defined(OS_MACOSX) 764 switches::kDisableCompositedCoreAnimationPlugins, 765#endif 766 switches::kDisableDataTransferItems, 767 switches::kDisableDatabases, 768 switches::kDisableDesktopNotifications, 769 switches::kDisableDeviceOrientation, 770 switches::kDisableFileSystem, 771 switches::kDisableGeolocation, 772 switches::kDisableGLMultisampling, 773 switches::kDisableGpuVsync, 774 switches::kDisableJavaScriptI18NAPI, 775 switches::kDisableLocalStorage, 776 switches::kDisableLogging, 777 switches::kDisableSeccompFilterSandbox, 778 switches::kDisableSeccompSandbox, 779 switches::kDisableSessionStorage, 780 switches::kDisableSharedWorkers, 781 switches::kDisableSpeechInput, 782 switches::kEnableScriptedSpeech, 783#if defined(OS_ANDROID) 784 switches::kEnableWebAudio, 785#else 786 switches::kDisableWebAudio, 787#endif 788 switches::kEnableWebAudioInput, 789 switches::kDisableWebSockets, 790 switches::kDomAutomationController, 791 switches::kEnableAccessibilityLogging, 792 switches::kEnableBrowserPluginForAllViewTypes, 793 switches::kEnableDCHECK, 794 switches::kEnableEncryptedMedia, 795 switches::kEnableExperimentalWebKitFeatures, 796 switches::kEnableFixedLayout, 797 switches::kEnableDeferredImageDecoding, 798 switches::kEnableGPUServiceLogging, 799 switches::kEnableGPUClientLogging, 800 switches::kEnableGpuBenchmarking, 801 switches::kEnableLogging, 802 switches::kDisableMediaSource, 803 switches::kDisableWebMediaPlayerMS, 804#if defined(OS_WIN) || defined(OS_MAC) 805 switches::kDisableRendererSideMixing, 806#else 807 switches::kEnableRendererSideMixing, 808#endif 809 switches::kEnableStrictSiteIsolation, 810 switches::kDisableFullScreen, 811 switches::kEnablePepperTesting, 812 switches::kEnablePreparsedJsCaching, 813 switches::kEnablePruneGpuCommandBuffers, 814 switches::kEnablePinch, 815#if defined(OS_MACOSX) 816 // Allow this to be set when invoking the browser and relayed along. 817 switches::kEnableSandboxLogging, 818#endif 819 switches::kEnableSeccompSandbox, 820 switches::kEnableSoftwareCompositingGLAdapter, 821 switches::kEnableStatsTable, 822 switches::kEnableThreadedCompositing, 823 switches::kDisableThreadedCompositing, 824 switches::kEnableTouchEvents, 825 switches::kEnableViewport, 826 switches::kForceDeviceScaleFactor, 827 switches::kFullMemoryCrashReport, 828#if !defined (GOOGLE_CHROME_BUILD) 829 // These are unsupported and not fully tested modes, so don't enable them 830 // for official Google Chrome builds. 831 switches::kInProcessPlugins, 832#endif // GOOGLE_CHROME_BUILD 833 switches::kInProcessWebGL, 834 switches::kJavaScriptFlags, 835 switches::kLoggingLevel, 836#if defined(OS_ANDROID) 837 switches::kMediaPlayerInRenderProcess, 838 switches::kNetworkCountryIso, 839#endif 840 switches::kNoReferrers, 841 switches::kNoSandbox, 842 switches::kOldCheckboxStyle, 843 switches::kPpapiOutOfProcess, 844 switches::kRegisterPepperPlugins, 845 switches::kRendererAssertTest, 846#if defined(OS_POSIX) 847 switches::kChildCleanExit, 848#endif 849 switches::kRendererStartupDialog, 850 switches::kShowPaintRects, 851 switches::kTestSandbox, 852 switches::kTraceStartup, 853 // This flag needs to be propagated to the renderer process for 854 // --in-process-webgl. 855 switches::kUseGL, 856 switches::kUseMobileUserAgent, 857 switches::kUserAgent, 858 switches::kV, 859 switches::kVideoThreads, 860 switches::kVModule, 861 switches::kWebCoreLogChannels, 862 cc::switches::kBackgroundColorInsteadOfCheckerboard, 863 cc::switches::kDisableThreadedAnimation, 864 cc::switches::kEnablePartialSwap, 865 cc::switches::kEnablePerTilePainting, 866 cc::switches::kEnablePinchInCompositor, 867 cc::switches::kJankInsteadOfCheckerboard, 868 }; 869 renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames, 870 arraysize(kSwitchNames)); 871 872 // Disable databases in incognito mode. 873 if (GetBrowserContext()->IsOffTheRecord() && 874 !browser_cmd.HasSwitch(switches::kDisableDatabases)) { 875 renderer_cmd->AppendSwitch(switches::kDisableDatabases); 876#if defined(OS_ANDROID) 877 renderer_cmd->AppendSwitch(switches::kDisableMediaHistoryLogging); 878#endif 879 } 880} 881 882base::ProcessHandle RenderProcessHostImpl::GetHandle() { 883 if (run_renderer_in_process()) 884 return base::Process::Current().handle(); 885 886 if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) 887 return base::kNullProcessHandle; 888 889 return child_process_launcher_->GetHandle(); 890} 891 892bool RenderProcessHostImpl::FastShutdownIfPossible() { 893 if (run_renderer_in_process()) 894 return false; // Single process mode can't do fast shutdown. 895 896 if (!GetContentClient()->browser()->IsFastShutdownPossible()) 897 return false; 898 899 if (!child_process_launcher_.get() || 900 child_process_launcher_->IsStarting() || 901 !GetHandle()) 902 return false; // Render process hasn't started or is probably crashed. 903 904 // Test if there's an unload listener. 905 // NOTE: It's possible that an onunload listener may be installed 906 // while we're shutting down, so there's a small race here. Given that 907 // the window is small, it's unlikely that the web page has much 908 // state that will be lost by not calling its unload handlers properly. 909 if (!SuddenTerminationAllowed()) 910 return false; 911 912 ProcessDied(); 913 fast_shutdown_started_ = true; 914 return true; 915} 916 917void RenderProcessHostImpl::DumpHandles() { 918#if defined(OS_WIN) 919 Send(new ChildProcessMsg_DumpHandles()); 920 return; 921#endif 922 923 NOTIMPLEMENTED(); 924} 925 926// This is a platform specific function for mapping a transport DIB given its id 927TransportDIB* RenderProcessHostImpl::MapTransportDIB( 928 TransportDIB::Id dib_id) { 929#if defined(OS_WIN) 930 // On Windows we need to duplicate the handle from the remote process 931 HANDLE section; 932 DuplicateHandle(GetHandle(), dib_id.handle, GetCurrentProcess(), §ion, 933 STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE, 934 FALSE, 0); 935 return TransportDIB::Map(section); 936#elif defined(OS_MACOSX) 937 // On OSX, the browser allocates all DIBs and keeps a file descriptor around 938 // for each. 939 return widget_helper_->MapTransportDIB(dib_id); 940#elif defined(OS_ANDROID) 941 return TransportDIB::Map(dib_id); 942#elif defined(OS_POSIX) 943 return TransportDIB::Map(dib_id.shmkey); 944#endif // defined(OS_POSIX) 945} 946 947TransportDIB* RenderProcessHostImpl::GetTransportDIB( 948 TransportDIB::Id dib_id) { 949 if (!TransportDIB::is_valid_id(dib_id)) 950 return NULL; 951 952 const std::map<TransportDIB::Id, TransportDIB*>::iterator 953 i = cached_dibs_.find(dib_id); 954 if (i != cached_dibs_.end()) { 955 cached_dibs_cleaner_.Reset(); 956 return i->second; 957 } 958 959 TransportDIB* dib = MapTransportDIB(dib_id); 960 if (!dib) 961 return NULL; 962 963 if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) { 964 // Clean a single entry from the cache 965 std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator; 966 size_t smallest_size = std::numeric_limits<size_t>::max(); 967 968 for (std::map<TransportDIB::Id, TransportDIB*>::iterator 969 i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) { 970 if (i->second->size() <= smallest_size) { 971 smallest_iterator = i; 972 smallest_size = i->second->size(); 973 } 974 } 975 976#if defined(USE_X11) 977 smallest_iterator->second->Detach(); 978#else 979 delete smallest_iterator->second; 980#endif 981 cached_dibs_.erase(smallest_iterator); 982 } 983 984 cached_dibs_[dib_id] = dib; 985 cached_dibs_cleaner_.Reset(); 986 return dib; 987} 988 989void RenderProcessHostImpl::ClearTransportDIBCache() { 990#if defined(USE_X11) 991 std::map<TransportDIB::Id, TransportDIB*>::const_iterator dib = 992 cached_dibs_.begin(); 993 for (; dib != cached_dibs_.end(); ++dib) 994 dib->second->Detach(); 995#else 996 STLDeleteContainerPairSecondPointers( 997 cached_dibs_.begin(), cached_dibs_.end()); 998#endif 999 cached_dibs_.clear(); 1000} 1001 1002bool RenderProcessHostImpl::Send(IPC::Message* msg) { 1003 if (!channel_.get()) { 1004 if (!is_initialized_) { 1005 queued_messages_.push(msg); 1006 return true; 1007 } else { 1008 delete msg; 1009 return false; 1010 } 1011 } 1012 1013 if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) { 1014 queued_messages_.push(msg); 1015 return true; 1016 } 1017 1018 return channel_->Send(msg); 1019} 1020 1021bool RenderProcessHostImpl::OnMessageReceived(const IPC::Message& msg) { 1022 // If we're about to be deleted, or have initiated the fast shutdown sequence, 1023 // we ignore incoming messages. 1024 1025 if (deleting_soon_ || fast_shutdown_started_) 1026 return false; 1027 1028 mark_child_process_activity_time(); 1029 if (msg.routing_id() == MSG_ROUTING_CONTROL) { 1030 // Dispatch control messages. 1031 bool msg_is_ok = true; 1032 IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok) 1033 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_ShutdownRequest, 1034 OnShutdownRequest) 1035 IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DumpHandlesDone, 1036 OnDumpHandlesDone) 1037 IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged, 1038 SuddenTerminationChanged) 1039 IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction, 1040 OnUserMetricsRecordAction) 1041 IPC_MESSAGE_HANDLER(ViewHostMsg_SavedPageAsMHTML, OnSavedPageAsMHTML) 1042 // Adding single handlers for your service here is fine, but once your 1043 // service needs more than one handler, please extract them into a new 1044 // message filter and add that filter to CreateMessageFilters(). 1045 IPC_MESSAGE_UNHANDLED_ERROR() 1046 IPC_END_MESSAGE_MAP_EX() 1047 1048 if (!msg_is_ok) { 1049 // The message had a handler, but its de-serialization failed. 1050 // We consider this a capital crime. Kill the renderer if we have one. 1051 LOG(ERROR) << "bad message " << msg.type() << " terminating renderer."; 1052 RecordAction(UserMetricsAction("BadMessageTerminate_BRPH")); 1053 ReceivedBadMessage(); 1054 } 1055 return true; 1056 } 1057 1058 // Dispatch incoming messages to the appropriate RenderView/WidgetHost. 1059 RenderWidgetHost* rwh = render_widget_hosts_.Lookup(msg.routing_id()); 1060 if (!rwh) { 1061 if (msg.is_sync()) { 1062 // The listener has gone away, so we must respond or else the caller will 1063 // hang waiting for a reply. 1064 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg); 1065 reply->set_reply_error(); 1066 Send(reply); 1067 } 1068 1069 // If this is a SwapBuffers, we need to ack it if we're not going to handle 1070 // it so that the GPU process doesn't get stuck in unscheduled state. 1071 bool msg_is_ok = true; 1072 IPC_BEGIN_MESSAGE_MAP_EX(RenderProcessHostImpl, msg, msg_is_ok) 1073 IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped, 1074 OnCompositorSurfaceBuffersSwappedNoHost) 1075 IPC_END_MESSAGE_MAP_EX() 1076 return true; 1077 } 1078 return RenderWidgetHostImpl::From(rwh)->OnMessageReceived(msg); 1079} 1080 1081void RenderProcessHostImpl::OnChannelConnected(int32 peer_pid) { 1082#if defined(IPC_MESSAGE_LOG_ENABLED) 1083 Send(new ChildProcessMsg_SetIPCLoggingEnabled( 1084 IPC::Logging::GetInstance()->Enabled())); 1085#endif 1086 1087 tracked_objects::ThreadData::Status status = 1088 tracked_objects::ThreadData::status(); 1089 Send(new ChildProcessMsg_SetProfilerStatus(status)); 1090} 1091 1092void RenderProcessHostImpl::OnChannelError() { 1093 ProcessDied(); 1094} 1095 1096BrowserContext* RenderProcessHostImpl::GetBrowserContext() const { 1097 return browser_context_; 1098} 1099 1100bool RenderProcessHostImpl::InSameStoragePartition( 1101 StoragePartition* partition) const { 1102 return storage_partition_impl_ == partition; 1103} 1104 1105int RenderProcessHostImpl::GetID() const { 1106 return id_; 1107} 1108 1109bool RenderProcessHostImpl::HasConnection() const { 1110 return channel_.get() != NULL; 1111} 1112 1113RenderWidgetHost* RenderProcessHostImpl::GetRenderWidgetHostByID( 1114 int routing_id) { 1115 return render_widget_hosts_.Lookup(routing_id); 1116} 1117 1118void RenderProcessHostImpl::SetIgnoreInputEvents(bool ignore_input_events) { 1119 ignore_input_events_ = ignore_input_events; 1120} 1121 1122bool RenderProcessHostImpl::IgnoreInputEvents() const { 1123 return ignore_input_events_; 1124} 1125 1126void RenderProcessHostImpl::Attach(RenderWidgetHost* host, 1127 int routing_id) { 1128 render_widget_hosts_.AddWithID(host, routing_id); 1129} 1130 1131void RenderProcessHostImpl::Release(int routing_id) { 1132 DCHECK(render_widget_hosts_.Lookup(routing_id) != NULL); 1133 render_widget_hosts_.Remove(routing_id); 1134 1135 // Make sure that all associated resource requests are stopped. 1136 CancelResourceRequests(routing_id); 1137 1138#if defined(OS_WIN) 1139 // Dump the handle table if handle auditing is enabled. 1140 const CommandLine& browser_command_line = 1141 *CommandLine::ForCurrentProcess(); 1142 if (browser_command_line.HasSwitch(switches::kAuditHandles) || 1143 browser_command_line.HasSwitch(switches::kAuditAllHandles)) { 1144 DumpHandles(); 1145 1146 // We wait to close the channels until the child process has finished 1147 // dumping handles and sends us ChildProcessHostMsg_DumpHandlesDone. 1148 return; 1149 } 1150#endif 1151 Cleanup(); 1152} 1153 1154void RenderProcessHostImpl::Cleanup() { 1155 // When no other owners of this object, we can delete ourselves 1156 if (render_widget_hosts_.IsEmpty()) { 1157 DCHECK_EQ(0, pending_views_); 1158 NotificationService::current()->Notify( 1159 NOTIFICATION_RENDERER_PROCESS_TERMINATED, 1160 Source<RenderProcessHost>(this), 1161 NotificationService::NoDetails()); 1162 MessageLoop::current()->DeleteSoon(FROM_HERE, this); 1163 deleting_soon_ = true; 1164 // It's important not to wait for the DeleteTask to delete the channel 1165 // proxy. Kill it off now. That way, in case the profile is going away, the 1166 // rest of the objects attached to this RenderProcessHost start going 1167 // away first, since deleting the channel proxy will post a 1168 // OnChannelClosed() to IPC::ChannelProxy::Context on the IO thread. 1169 channel_.reset(); 1170 gpu_message_filter_ = NULL; 1171 1172 // Remove ourself from the list of renderer processes so that we can't be 1173 // reused in between now and when the Delete task runs. 1174 UnregisterHost(GetID()); 1175 } 1176} 1177 1178void RenderProcessHostImpl::AddPendingView() { 1179 pending_views_++; 1180} 1181 1182void RenderProcessHostImpl::RemovePendingView() { 1183 DCHECK(pending_views_); 1184 pending_views_--; 1185} 1186 1187void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) { 1188 sudden_termination_allowed_ = enabled; 1189} 1190 1191bool RenderProcessHostImpl::SuddenTerminationAllowed() const { 1192 return sudden_termination_allowed_; 1193} 1194 1195base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const { 1196 return base::TimeTicks::Now() - child_process_activity_time_; 1197} 1198 1199void RenderProcessHostImpl::SurfaceUpdated(int32 surface_id) { 1200 if (!gpu_message_filter_) 1201 return; 1202 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( 1203 &GpuMessageFilter::SurfaceUpdated, 1204 gpu_message_filter_, 1205 surface_id)); 1206} 1207 1208void RenderProcessHostImpl::ResumeRequestsForView(int route_id) { 1209 widget_helper_->ResumeRequestsForView(route_id); 1210} 1211 1212IPC::ChannelProxy* RenderProcessHostImpl::GetChannel() { 1213 return channel_.get(); 1214} 1215 1216RenderProcessHost::RenderWidgetHostsIterator 1217 RenderProcessHostImpl::GetRenderWidgetHostsIterator() { 1218 return RenderWidgetHostsIterator(&render_widget_hosts_); 1219} 1220 1221bool RenderProcessHostImpl::FastShutdownForPageCount(size_t count) { 1222 if (render_widget_hosts_.size() == count) 1223 return FastShutdownIfPossible(); 1224 return false; 1225} 1226 1227bool RenderProcessHostImpl::FastShutdownStarted() const { 1228 return fast_shutdown_started_; 1229} 1230 1231// static 1232void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) { 1233 g_all_hosts.Get().AddWithID(host, host_id); 1234} 1235 1236// static 1237void RenderProcessHostImpl::UnregisterHost(int host_id) { 1238 RenderProcessHost* host = g_all_hosts.Get().Lookup(host_id); 1239 if (!host) 1240 return; 1241 1242 g_all_hosts.Get().Remove(host_id); 1243 1244 // Look up the map of site to process for the given browser_context, 1245 // in case we need to remove this process from it. It will be registered 1246 // under any sites it rendered that use process-per-site mode. 1247 SiteProcessMap* map = 1248 GetSiteProcessMapForBrowserContext(host->GetBrowserContext()); 1249 map->RemoveProcess(host); 1250} 1251 1252// static 1253bool RenderProcessHostImpl::IsSuitableHost( 1254 RenderProcessHost* host, 1255 BrowserContext* browser_context, 1256 const GURL& site_url) { 1257 if (run_renderer_in_process()) 1258 return true; 1259 1260 if (host->GetBrowserContext() != browser_context) 1261 return false; 1262 1263 // Check whether the given host and the intended site_url will be using the 1264 // same StoragePartition, since a RenderProcessHost can only support a single 1265 // StoragePartition. This is relevant for packaged apps, browser tags, and 1266 // isolated sites. 1267 StoragePartition* dest_partition = 1268 BrowserContext::GetStoragePartitionForSite(browser_context, site_url); 1269 if (!host->InSameStoragePartition(dest_partition)) 1270 return false; 1271 1272 // All URLs are suitable if this is associated with a guest renderer process. 1273 // TODO(fsamuel, creis): Further validation is needed to ensure that only 1274 // normal web URLs are permitted in guest processes. We need to investigate 1275 // where this validation should happen. 1276 if (host->IsGuest()) 1277 return true; 1278 1279 if (!host->IsGuest() && site_url.SchemeIs(chrome::kGuestScheme)) 1280 return false; 1281 1282 WebUIControllerFactory* factory = 1283 GetContentClient()->browser()->GetWebUIControllerFactory(); 1284 if (factory && 1285 ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 1286 host->GetID()) != 1287 factory->UseWebUIBindingsForURL(browser_context, site_url)) { 1288 return false; 1289 } 1290 1291 return GetContentClient()->browser()->IsSuitableHost(host, site_url); 1292} 1293 1294// static 1295bool RenderProcessHost::run_renderer_in_process() { 1296 return g_run_renderer_in_process_; 1297} 1298 1299// static 1300void RenderProcessHost::SetRunRendererInProcess(bool value) { 1301 g_run_renderer_in_process_ = value; 1302 1303 CommandLine* command_line = CommandLine::ForCurrentProcess(); 1304 if (value && !command_line->HasSwitch(switches::kLang)) { 1305 // Modify the current process' command line to include the browser locale, 1306 // as the renderer expects this flag to be set. 1307 const std::string locale = 1308 GetContentClient()->browser()->GetApplicationLocale(); 1309 command_line->AppendSwitchASCII(switches::kLang, locale); 1310 } 1311} 1312 1313RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() { 1314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1315 return iterator(g_all_hosts.Pointer()); 1316} 1317 1318// static 1319RenderProcessHost* RenderProcessHost::FromID(int render_process_id) { 1320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1321 return g_all_hosts.Get().Lookup(render_process_id); 1322} 1323 1324// static 1325bool RenderProcessHost::ShouldTryToUseExistingProcessHost( 1326 BrowserContext* browser_context, const GURL& url) { 1327 1328 if (run_renderer_in_process()) 1329 return true; 1330 1331 // NOTE: Sometimes it's necessary to create more render processes than 1332 // GetMaxRendererProcessCount(), for instance when we want to create 1333 // a renderer process for a browser context that has no existing 1334 // renderers. This is OK in moderation, since the 1335 // GetMaxRendererProcessCount() is conservative. 1336 if (g_all_hosts.Get().size() >= GetMaxRendererProcessCount()) 1337 return true; 1338 1339 return GetContentClient()->browser()-> 1340 ShouldTryToUseExistingProcessHost(browser_context, url); 1341} 1342 1343// static 1344RenderProcessHost* RenderProcessHost::GetExistingProcessHost( 1345 BrowserContext* browser_context, 1346 const GURL& site_url) { 1347 // First figure out which existing renderers we can use. 1348 std::vector<RenderProcessHost*> suitable_renderers; 1349 suitable_renderers.reserve(g_all_hosts.Get().size()); 1350 1351 iterator iter(AllHostsIterator()); 1352 while (!iter.IsAtEnd()) { 1353 if (RenderProcessHostImpl::IsSuitableHost( 1354 iter.GetCurrentValue(), 1355 browser_context, site_url)) 1356 suitable_renderers.push_back(iter.GetCurrentValue()); 1357 1358 iter.Advance(); 1359 } 1360 1361 // Now pick a random suitable renderer, if we have any. 1362 if (!suitable_renderers.empty()) { 1363 int suitable_count = static_cast<int>(suitable_renderers.size()); 1364 int random_index = base::RandInt(0, suitable_count - 1); 1365 return suitable_renderers[random_index]; 1366 } 1367 1368 return NULL; 1369} 1370 1371// static 1372bool RenderProcessHostImpl::ShouldUseProcessPerSite( 1373 BrowserContext* browser_context, 1374 const GURL& url) { 1375 // Returns true if we should use the process-per-site model. This will be 1376 // the case if the --process-per-site switch is specified, or in 1377 // process-per-site-instance for particular sites (e.g., WebUI). 1378 1379 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1380 if (command_line.HasSwitch(switches::kProcessPerSite)) 1381 return true; 1382 1383 // We want to consolidate particular sites like WebUI when we are using 1384 // process-per-tab or process-per-site-instance models. 1385 // Note that --single-process is handled in ShouldTryToUseExistingProcessHost. 1386 1387 if (GetContentClient()->browser()-> 1388 ShouldUseProcessPerSite(browser_context, url)) { 1389 return true; 1390 } 1391 1392 // DevTools pages have WebUI type but should not reuse the same host. 1393 WebUIControllerFactory* factory = 1394 GetContentClient()->browser()->GetWebUIControllerFactory(); 1395 if (factory && 1396 factory->UseWebUIForURL(browser_context, url) && 1397 !url.SchemeIs(chrome::kChromeDevToolsScheme)) { 1398 return true; 1399 } 1400 1401 // In all other cases, don't use process-per-site logic. 1402 return false; 1403} 1404 1405// static 1406RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSite( 1407 BrowserContext* browser_context, 1408 const GURL& url) { 1409 // Look up the map of site to process for the given browser_context. 1410 SiteProcessMap* map = 1411 GetSiteProcessMapForBrowserContext(browser_context); 1412 1413 // See if we have an existing process for this site. If not, the caller 1414 // should create a new process and register it. 1415 std::string site = SiteInstanceImpl::GetSiteForURL(browser_context, url) 1416 .possibly_invalid_spec(); 1417 return map->FindProcess(site); 1418} 1419 1420void RenderProcessHostImpl::RegisterProcessHostForSite( 1421 BrowserContext* browser_context, 1422 RenderProcessHost* process, 1423 const GURL& url) { 1424 // Look up the map of site to process for the given browser_context. 1425 SiteProcessMap* map = 1426 GetSiteProcessMapForBrowserContext(browser_context); 1427 1428 // TODO(creis): Determine if it's better to allow registration of 1429 // empty sites or not. For now, group anything from which we can't parse 1430 // a site into the same process, when using --process-per-site. 1431 std::string site = SiteInstanceImpl::GetSiteForURL(browser_context, url) 1432 .possibly_invalid_spec(); 1433 map->RegisterProcess(site, process); 1434} 1435 1436void RenderProcessHostImpl::ProcessDied() { 1437 // Our child process has died. If we didn't expect it, it's a crash. 1438 // In any case, we need to let everyone know it's gone. 1439 // The OnChannelError notification can fire multiple times due to nested sync 1440 // calls to a renderer. If we don't have a valid channel here it means we 1441 // already handled the error. 1442 1443 // child_process_launcher_ can be NULL in single process mode or if fast 1444 // termination happened. 1445 int exit_code = 0; 1446 base::TerminationStatus status = 1447 child_process_launcher_.get() ? 1448 child_process_launcher_->GetChildTerminationStatus(&exit_code) : 1449 base::TERMINATION_STATUS_NORMAL_TERMINATION; 1450 1451 RendererClosedDetails details(GetHandle(), status, exit_code); 1452 NotificationService::current()->Notify( 1453 NOTIFICATION_RENDERER_PROCESS_CLOSED, 1454 Source<RenderProcessHost>(this), 1455 Details<RendererClosedDetails>(&details)); 1456 1457 child_process_launcher_.reset(); 1458 channel_.reset(); 1459 gpu_message_filter_ = NULL; 1460 1461 IDMap<RenderWidgetHost>::iterator iter(&render_widget_hosts_); 1462 while (!iter.IsAtEnd()) { 1463 RenderWidgetHostImpl::From(iter.GetCurrentValue())->OnMessageReceived( 1464 ViewHostMsg_RenderViewGone(iter.GetCurrentKey(), 1465 static_cast<int>(status), 1466 exit_code)); 1467 iter.Advance(); 1468 } 1469 1470 ClearTransportDIBCache(); 1471 1472 // this object is not deleted at this point and may be reused later. 1473 // TODO(darin): clean this up 1474} 1475 1476int RenderProcessHostImpl::GetActiveViewCount() { 1477 int num_active_views = 0; 1478 for (RenderWidgetHostsIterator iter = GetRenderWidgetHostsIterator(); 1479 !iter.IsAtEnd(); 1480 iter.Advance()) { 1481 const RenderWidgetHost* widget = iter.GetCurrentValue(); 1482 DCHECK(widget); 1483 if (!widget) 1484 continue; 1485 1486 // All RenderWidgetHosts are swapped in. 1487 if (!widget->IsRenderView()) { 1488 num_active_views++; 1489 continue; 1490 } 1491 1492 // Don't count swapped out views. 1493 RenderViewHost* rvh = 1494 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); 1495 if (!static_cast<RenderViewHostImpl*>(rvh)->is_swapped_out()) 1496 num_active_views++; 1497 } 1498 return num_active_views; 1499} 1500 1501void RenderProcessHostImpl::OnShutdownRequest() { 1502 // Don't shut down if there are more active RenderViews than the one asking 1503 // to close, or if there are pending RenderViews being swapped back in. 1504 int num_active_views = GetActiveViewCount(); 1505 if (pending_views_ || num_active_views > 1) 1506 return; 1507 1508 // Notify any contents that might have swapped out renderers from this 1509 // process. They should not attempt to swap them back in. 1510 NotificationService::current()->Notify( 1511 NOTIFICATION_RENDERER_PROCESS_CLOSING, 1512 Source<RenderProcessHost>(this), 1513 NotificationService::NoDetails()); 1514 1515 Send(new ChildProcessMsg_Shutdown()); 1516} 1517 1518void RenderProcessHostImpl::SuddenTerminationChanged(bool enabled) { 1519 SetSuddenTerminationAllowed(enabled); 1520} 1521 1522void RenderProcessHostImpl::OnDumpHandlesDone() { 1523 Cleanup(); 1524} 1525 1526void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) { 1527 // Note: we always set the backgrounded_ value. If the process is NULL 1528 // (and hence hasn't been created yet), we will set the process priority 1529 // later when we create the process. 1530 backgrounded_ = backgrounded; 1531 if (!child_process_launcher_.get() || child_process_launcher_->IsStarting()) 1532 return; 1533 1534#if defined(OS_WIN) 1535 // The cbstext.dll loads as a global GetMessage hook in the browser process 1536 // and intercepts/unintercepts the kernel32 API SetPriorityClass in a 1537 // background thread. If the UI thread invokes this API just when it is 1538 // intercepted the stack is messed up on return from the interceptor 1539 // which causes random crashes in the browser process. Our hack for now 1540 // is to not invoke the SetPriorityClass API if the dll is loaded. 1541 if (GetModuleHandle(L"cbstext.dll")) 1542 return; 1543#endif // OS_WIN 1544 1545 child_process_launcher_->SetProcessBackgrounded(backgrounded); 1546} 1547 1548void RenderProcessHostImpl::OnProcessLaunched() { 1549 // No point doing anything, since this object will be destructed soon. We 1550 // especially don't want to send the RENDERER_PROCESS_CREATED notification, 1551 // since some clients might expect a RENDERER_PROCESS_TERMINATED afterwards to 1552 // properly cleanup. 1553 if (deleting_soon_) 1554 return; 1555 1556 if (child_process_launcher_.get()) { 1557 if (!child_process_launcher_->GetHandle()) { 1558 OnChannelError(); 1559 return; 1560 } 1561 1562 child_process_launcher_->SetProcessBackgrounded(backgrounded_); 1563 } 1564 1565 // NOTE: This needs to be before sending queued messages because 1566 // ExtensionService uses this notification to initialize the renderer process 1567 // with state that must be there before any JavaScript executes. 1568 // 1569 // The queued messages contain such things as "navigate". If this notification 1570 // was after, we can end up executing JavaScript before the initialization 1571 // happens. 1572 NotificationService::current()->Notify( 1573 NOTIFICATION_RENDERER_PROCESS_CREATED, 1574 Source<RenderProcessHost>(this), 1575 NotificationService::NoDetails()); 1576 1577 while (!queued_messages_.empty()) { 1578 Send(queued_messages_.front()); 1579 queued_messages_.pop(); 1580 } 1581} 1582 1583void RenderProcessHostImpl::OnUserMetricsRecordAction( 1584 const std::string& action) { 1585 RecordComputedAction(action); 1586} 1587 1588void RenderProcessHostImpl::OnSavedPageAsMHTML(int job_id, int64 data_size) { 1589 MHTMLGenerationManager::GetInstance()->MHTMLGenerated(job_id, data_size); 1590} 1591 1592void RenderProcessHostImpl::OnCompositorSurfaceBuffersSwappedNoHost( 1593 int32 surface_id, 1594 uint64 surface_handle, 1595 int32 route_id, 1596 const gfx::Size& size, 1597 int32 gpu_process_host_id) { 1598 TRACE_EVENT0("renderer_host", 1599 "RenderWidgetHostImpl::OnCompositorSurfaceBuffersSwappedNoHost"); 1600 RenderWidgetHostImpl::AcknowledgeBufferPresent(route_id, 1601 gpu_process_host_id, 1602 false, 1603 0); 1604} 1605 1606} // namespace content 1607