summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 00:44:14 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 00:44:14 +0000
commit05fcf98bd3e7c462917996fb1c601793dd6345c9 (patch)
tree6e343997968c711f9d7a336e27b133bd14dfaf6b /content
parent0e194cc6261463902915398c3d975d4de64852ff (diff)
downloadchromium_src-05fcf98bd3e7c462917996fb1c601793dd6345c9.zip
chromium_src-05fcf98bd3e7c462917996fb1c601793dd6345c9.tar.gz
chromium_src-05fcf98bd3e7c462917996fb1c601793dd6345c9.tar.bz2
Move BrowserRenderProcessHost to content. It should have been moved earlier.
Review URL: http://codereview.chromium.org/6877019 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82037 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/content_browser_client.cc3
-rw-r--r--content/browser/content_browser_client.h4
-rw-r--r--content/browser/renderer_host/DEPS4
-rw-r--r--content/browser/renderer_host/browser_render_process_host.cc1318
-rw-r--r--content/browser/renderer_host/browser_render_process_host.h226
-rw-r--r--content/browser/renderer_host/pepper_file_message_filter.cc2
-rw-r--r--content/browser/renderer_host/pepper_message_filter.cc2
-rw-r--r--content/browser/renderer_host/render_message_filter.cc2
-rw-r--r--content/browser/renderer_host/render_process_host.h2
-rw-r--r--content/browser/site_instance.cc2
-rw-r--r--content/browser/site_instance_unittest.cc2
-rw-r--r--content/content_browser.gypi2
12 files changed, 1564 insertions, 5 deletions
diff --git a/content/browser/content_browser_client.cc b/content/browser/content_browser_client.cc
index 57392a1..c02c95c 100644
--- a/content/browser/content_browser_client.cc
+++ b/content/browser/content_browser_client.cc
@@ -19,6 +19,9 @@ void ContentBrowserClient::PreCreateRenderView(RenderViewHost* render_view_host,
const GURL& url) {
}
+void ContentBrowserClient::BrowserRenderProcessHostCreated(
+ BrowserRenderProcessHost* host) {
+}
WebUIFactory* ContentBrowserClient::GetWebUIFactory() {
// Return an empty factory so callsites don't have to check for NULL.
return EmptyWebUIFactory::Get();
diff --git a/content/browser/content_browser_client.h b/content/browser/content_browser_client.h
index 1f3c7ca..bcb2d15 100644
--- a/content/browser/content_browser_client.h
+++ b/content/browser/content_browser_client.h
@@ -8,6 +8,7 @@
#include "content/common/content_client.h"
+class BrowserRenderProcessHost;
class GURL;
class Profile;
class RenderViewHost;
@@ -27,6 +28,9 @@ class ContentBrowserClient {
Profile* profile,
const GURL& url);
+ // Notifies that a BrowserRenderProcessHost has been created.
+ virtual void BrowserRenderProcessHostCreated(BrowserRenderProcessHost* host);
+
// Gets the WebUIFactory which will be responsible for generating WebUIs.
virtual WebUIFactory* GetWebUIFactory();
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS
new file mode 100644
index 0000000..8e154f7
--- /dev/null
+++ b/content/browser/renderer_host/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+content/renderer", # For single-process mode.
+ "+chrome/browser/extensions", # temporarily, for BrowserRenderProcessHost
+]
diff --git a/content/browser/renderer_host/browser_render_process_host.cc b/content/browser/renderer_host/browser_render_process_host.cc
new file mode 100644
index 0000000..b10ce64
--- /dev/null
+++ b/content/browser/renderer_host/browser_render_process_host.cc
@@ -0,0 +1,1318 @@
+// Copyright (c) 2011 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/browser_render_process_host.h"
+
+#include <algorithm>
+#include <limits>
+#include <vector>
+
+#if defined(OS_POSIX)
+#include <utility> // for pair<>
+#endif
+
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
+#include "base/path_service.h"
+#include "base/platform_file.h"
+#include "base/stl_util-inl.h"
+#include "base/string_util.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_event_router.h"
+#include "chrome/browser/extensions/extension_function_dispatcher.h"
+#include "chrome/browser/extensions/extension_message_service.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/user_script_master.h"
+#include "chrome/browser/gpu_data_manager.h"
+#include "chrome/browser/history/history.h"
+#include "chrome/browser/io_thread.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/net/resolve_proxy_msg_helper.h"
+#include "chrome/browser/platform_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/renderer_host/web_cache_manager.h"
+#include "chrome/browser/safe_browsing/client_side_detection_service.h"
+#include "chrome/browser/spellcheck_host.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/visitedlink/visitedlink_master.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_icon_set.h"
+#include "chrome/common/extensions/extension_messages.h"
+#include "chrome/common/logging_chrome.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/safe_browsing/safebrowsing_messages.h"
+#include "chrome/common/spellcheck_messages.h"
+#include "content/browser/appcache/appcache_dispatcher_host.h"
+#include "content/browser/browser_child_process_host.h"
+#include "content/browser/child_process_security_policy.h"
+#include "content/browser/content_browser_client.h"
+#include "content/browser/device_orientation/message_filter.h"
+#include "content/browser/geolocation/geolocation_dispatcher_host.h"
+#include "content/browser/gpu_process_host.h"
+#include "content/browser/in_process_webkit/dom_storage_message_filter.h"
+#include "content/browser/in_process_webkit/indexed_db_dispatcher_host.h"
+#include "content/browser/file_system/file_system_dispatcher_host.h"
+#include "content/browser/mime_registry_message_filter.h"
+#include "content/browser/plugin_service.h"
+#include "content/browser/renderer_host/audio_input_renderer_host.h"
+#include "content/browser/renderer_host/audio_renderer_host.h"
+#include "content/browser/renderer_host/blob_message_filter.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/gpu_message_filter.h"
+#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
+#include "content/browser/renderer_host/pepper_file_message_filter.h"
+#include "content/browser/renderer_host/pepper_message_filter.h"
+#include "content/browser/renderer_host/quota_dispatcher_host.h"
+#include "content/browser/renderer_host/render_message_filter.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_helper.h"
+#include "content/browser/renderer_host/render_widget_host.h"
+#include "content/browser/renderer_host/resource_message_filter.h"
+#include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
+#include "content/browser/speech/speech_input_dispatcher_host.h"
+#include "content/browser/trace_message_filter.h"
+#include "content/browser/worker_host/worker_message_filter.h"
+#include "content/common/child_process_info.h"
+#include "content/common/child_process_messages.h"
+#include "content/common/gpu_messages.h"
+#include "content/common/notification_service.h"
+#include "content/common/process_watcher.h"
+#include "content/common/resource_messages.h"
+#include "content/common/result_codes.h"
+#include "content/common/view_messages.h"
+#include "content/renderer/render_process_impl.h"
+#include "content/renderer/render_thread.h"
+#include "ipc/ipc_logging.h"
+#include "ipc/ipc_platform_file.h"
+#include "ipc/ipc_switches.h"
+#include "media/base/media_switches.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/gfx/gl/gl_switches.h"
+#include "webkit/fileapi/file_system_path_manager.h"
+#include "webkit/fileapi/sandbox_mount_point_provider.h"
+#include "webkit/glue/resource_type.h"
+#include "webkit/plugins/plugin_switches.h"
+
+#if defined(OS_WIN)
+#include <objbase.h>
+#include "content/common/section_util_win.h"
+#endif
+
+using WebKit::WebCache;
+
+#include "third_party/skia/include/core/SkBitmap.h"
+
+// TODO(mpcomplete): Remove this after fixing
+// http://code.google.com/p/chromium/issues/detail?id=53991
+bool g_log_bug53991 = false;
+
+// This class creates the IO thread for the renderer when running in
+// single-process mode. It's not used in multi-process mode.
+class RendererMainThread : public base::Thread {
+ public:
+ explicit RendererMainThread(const std::string& channel_id)
+ : base::Thread("Chrome_InProcRendererThread"),
+ channel_id_(channel_id),
+ render_process_(NULL) {
+ }
+
+ ~RendererMainThread() {
+ Stop();
+ }
+
+ protected:
+ virtual void Init() {
+#if defined(OS_WIN)
+ CoInitialize(NULL);
+#endif
+
+ render_process_ = new RenderProcessImpl();
+ render_process_->set_main_thread(new RenderThread(channel_id_));
+ // It's a little lame to manually set this flag. But the single process
+ // RendererThread will receive the WM_QUIT. We don't need to assert on
+ // this thread, so just force the flag manually.
+ // If we want to avoid this, we could create the InProcRendererThread
+ // directly with _beginthreadex() rather than using the Thread class.
+ base::Thread::SetThreadWasQuitProperly(true);
+ }
+
+ virtual void CleanUp() {
+ delete render_process_;
+
+#if defined(OS_WIN)
+ CoUninitialize();
+#endif
+ }
+
+ private:
+ std::string channel_id_;
+ // Deleted in CleanUp() on the renderer thread, so don't use a smart pointer.
+ RenderProcess* render_process_;
+};
+
+
+// Size of the buffer after which individual link updates deemed not warranted
+// and the overall update should be used instead.
+static const unsigned kVisitedLinkBufferThreshold = 50;
+
+// This class manages buffering and sending visited link hashes (fingerprints)
+// to renderer based on widget visibility.
+// As opposed to the VisitedLinkEventListener in profile.cc, which coalesces to
+// reduce the rate of messages being sent to render processes, this class
+// ensures that the updates occur only when explicitly requested. This is
+// used by BrowserRenderProcessHost to only send Add/Reset link events to the
+// renderers when their tabs are visible and the corresponding RenderViews are
+// created.
+class VisitedLinkUpdater {
+ public:
+ VisitedLinkUpdater() : reset_needed_(false), has_receiver_(false) {}
+
+ // Buffers |links| to update, but doesn't actually relay them.
+ void AddLinks(const VisitedLinkCommon::Fingerprints& links) {
+ if (reset_needed_)
+ return;
+
+ if (pending_.size() + links.size() > kVisitedLinkBufferThreshold) {
+ // Once the threshold is reached, there's no need to store pending visited
+ // link updates -- we opt for resetting the state for all links.
+ AddReset();
+ return;
+ }
+
+ pending_.insert(pending_.end(), links.begin(), links.end());
+ }
+
+ // Tells the updater that sending individual link updates is no longer
+ // necessary and the visited state for all links should be reset.
+ void AddReset() {
+ reset_needed_ = true;
+ pending_.clear();
+ }
+
+ // Sends visited link update messages: a list of links whose visited state
+ // changed or reset of visited state for all links.
+ void Update(IPC::Channel::Sender* sender) {
+ DCHECK(sender);
+
+ if (!has_receiver_)
+ return;
+
+ if (reset_needed_) {
+ sender->Send(new ViewMsg_VisitedLink_Reset());
+ reset_needed_ = false;
+ return;
+ }
+
+ if (pending_.empty())
+ return;
+
+ sender->Send(new ViewMsg_VisitedLink_Add(pending_));
+
+ pending_.clear();
+ }
+
+ // Notifies the updater that it is now safe to send visited state updates.
+ void ReceiverReady(IPC::Channel::Sender* sender) {
+ has_receiver_ = true;
+ // Go ahead and send whatever we already have buffered up.
+ Update(sender);
+ }
+
+ private:
+ bool reset_needed_;
+ bool has_receiver_;
+ VisitedLinkCommon::Fingerprints pending_;
+};
+
+namespace {
+
+// Helper class that we pass to ResourceMessageFilter so that it can find the
+// right net::URLRequestContext for a request.
+class RendererURLRequestContextSelector
+ : public ResourceMessageFilter::URLRequestContextSelector {
+ public:
+ RendererURLRequestContextSelector(Profile* profile,
+ const Extension* installed_app)
+ : request_context_(profile->GetRequestContextForPossibleApp(
+ installed_app)),
+ media_request_context_(profile->GetRequestContextForMedia()) {
+ }
+
+ virtual net::URLRequestContext* GetRequestContext(
+ ResourceType::Type resource_type) {
+ net::URLRequestContextGetter* request_context = request_context_;
+ // If the request has resource type of ResourceType::MEDIA, we use a request
+ // context specific to media for handling it because these resources have
+ // specific needs for caching.
+ if (resource_type == ResourceType::MEDIA)
+ request_context = media_request_context_;
+ return request_context->GetURLRequestContext();
+ }
+
+ private:
+ virtual ~RendererURLRequestContextSelector() {}
+
+ scoped_refptr<net::URLRequestContextGetter> request_context_;
+ scoped_refptr<net::URLRequestContextGetter> media_request_context_;
+};
+
+} // namespace
+
+BrowserRenderProcessHost::BrowserRenderProcessHost(Profile* profile)
+ : RenderProcessHost(profile),
+ visible_widgets_(0),
+ backgrounded_(true),
+ ALLOW_THIS_IN_INITIALIZER_LIST(cached_dibs_cleaner_(
+ base::TimeDelta::FromSeconds(5),
+ this, &BrowserRenderProcessHost::ClearTransportDIBCache)),
+ accessibility_enabled_(false),
+ extension_process_(false),
+ callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ widget_helper_ = new RenderWidgetHelper();
+
+ registrar_.Add(this, NotificationType::USER_SCRIPTS_UPDATED,
+ Source<Profile>(profile->GetOriginalProfile()));
+ registrar_.Add(this, NotificationType::EXTENSION_LOADED,
+ Source<Profile>(profile->GetOriginalProfile()));
+ registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
+ Source<Profile>(profile->GetOriginalProfile()));
+ registrar_.Add(this, NotificationType::SPELLCHECK_HOST_REINITIALIZED,
+ NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::SPELLCHECK_WORD_ADDED,
+ NotificationService::AllSources());
+ registrar_.Add(this, NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED,
+ NotificationService::AllSources());
+
+ visited_link_updater_.reset(new VisitedLinkUpdater());
+
+ WebCacheManager::GetInstance()->Add(id());
+ ChildProcessSecurityPolicy::GetInstance()->Add(id());
+
+ // Grant most file permissions to this renderer.
+ // PLATFORM_FILE_TEMPORARY, PLATFORM_FILE_HIDDEN and
+ // PLATFORM_FILE_DELETE_ON_CLOSE are not granted, because no existing API
+ // requests them.
+ ChildProcessSecurityPolicy::GetInstance()->GrantPermissionsForFile(
+ id(), profile->GetPath().Append(
+ fileapi::SandboxMountPointProvider::kFileSystemDirectory),
+ base::PLATFORM_FILE_OPEN |
+ base::PLATFORM_FILE_CREATE |
+ base::PLATFORM_FILE_OPEN_ALWAYS |
+ base::PLATFORM_FILE_CREATE_ALWAYS |
+ base::PLATFORM_FILE_READ |
+ base::PLATFORM_FILE_WRITE |
+ base::PLATFORM_FILE_EXCLUSIVE_READ |
+ base::PLATFORM_FILE_EXCLUSIVE_WRITE |
+ base::PLATFORM_FILE_ASYNC |
+ base::PLATFORM_FILE_TRUNCATE |
+ base::PLATFORM_FILE_WRITE_ATTRIBUTES);
+
+ // Note: When we create the BrowserRenderProcessHost, 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.
+}
+
+BrowserRenderProcessHost::~BrowserRenderProcessHost() {
+ VLOG_IF(1, g_log_bug53991) << "~BrowserRenderProcessHost: " << this;
+
+ WebCacheManager::GetInstance()->Remove(id());
+ ChildProcessSecurityPolicy::GetInstance()->Remove(id());
+
+ // 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();
+ }
+
+ ClearTransportDIBCache();
+}
+
+bool BrowserRenderProcessHost::Init(
+ bool is_accessibility_enabled, bool is_extensions_process) {
+ // 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_.get())
+ return true;
+
+ accessibility_enabled_ = is_accessibility_enabled;
+
+ // It is possible for an extension process to be reused for non-extension
+ // content, e.g. if an extension calls window.open.
+ extension_process_ = extension_process_ || is_extensions_process;
+
+ // run the IPC channel on the shared IO thread.
+ base::Thread* io_thread = g_browser_process->io_thread();
+
+ CommandLine::StringType renderer_prefix;
+#if defined(OS_POSIX)
+ // A command prefix is something prepended to the command line of the spawned
+ // process. It is supported only on POSIX systems.
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ renderer_prefix =
+ browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
+#endif // defined(OS_POSIX)
+
+ // Find the renderer before creating the channel so if this fails early we
+ // return without creating the channel.
+ FilePath renderer_path =
+ ChildProcessHost::GetChildPath(renderer_prefix.empty());
+ if (renderer_path.empty())
+ return false;
+
+ // Setup the IPC channel.
+ const std::string channel_id =
+ ChildProcessInfo::GenerateRandomChannelID(this);
+ channel_.reset(
+ new IPC::SyncChannel(channel_id, IPC::Channel::MODE_SERVER, this,
+ io_thread->message_loop(), true,
+ g_browser_process->shutdown_event()));
+ // As a preventive mesure, we DCHECK if someone sends a synchronous message
+ // with no time-out, which in the context of the browser process we should not
+ // be doing.
+ channel_->set_sync_messages_with_no_timeout_allowed(false);
+
+ CreateMessageFilters();
+
+ content::GetContentClient()->browser()->BrowserRenderProcessHostCreated(this);
+
+ if (run_renderer_in_process()) {
+ // 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(new RendererMainThread(channel_id));
+
+ base::Thread::Options options;
+#if !defined(TOOLKIT_USES_GTK)
+ // In-process plugins require this to be a UI message loop.
+ options.message_loop_type = MessageLoop::TYPE_UI;
+#else
+ // We can't have multiple UI loops on GTK, so we don't support
+ // in-process plugins.
+ options.message_loop_type = MessageLoop::TYPE_DEFAULT;
+#endif
+ in_process_renderer_->StartWithOptions(options);
+
+ OnProcessLaunched(); // Fake a callback that the process is ready.
+ } else {
+ // Build command line for renderer. We call AppendRendererCommandLine()
+ // first so the process type argument will appear first.
+ CommandLine* cmd_line = new 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_.reset(new ChildProcessLauncher(
+#if defined(OS_WIN)
+ FilePath(),
+#elif defined(OS_POSIX)
+ renderer_prefix.empty(),
+ base::environment_vector(),
+ channel_->GetClientFileDescriptor(),
+#endif
+ cmd_line,
+ this));
+
+ fast_shutdown_started_ = false;
+ }
+
+ return true;
+}
+
+void BrowserRenderProcessHost::CreateMessageFilters() {
+ scoped_refptr<RenderMessageFilter> render_message_filter(
+ new RenderMessageFilter(id(),
+ PluginService::GetInstance(),
+ profile(),
+ profile()->GetRequestContextForPossibleApp(
+ installed_app_),
+ widget_helper_));
+ channel_->AddFilter(render_message_filter);
+
+ ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
+ id(), ChildProcessInfo::RENDER_PROCESS,
+ &profile()->GetResourceContext(),
+ new RendererURLRequestContextSelector(profile(), installed_app_),
+ g_browser_process->resource_dispatcher_host());
+
+ channel_->AddFilter(resource_message_filter);
+ channel_->AddFilter(new AudioInputRendererHost());
+ channel_->AddFilter(new AudioRendererHost());
+ channel_->AddFilter(
+ new AppCacheDispatcherHost(profile()->GetRequestContext(), id()));
+ channel_->AddFilter(new ClipboardMessageFilter());
+ channel_->AddFilter(
+ new DOMStorageMessageFilter(id(), profile()->GetWebKitContext(),
+ profile()->GetHostContentSettingsMap()));
+ channel_->AddFilter(
+ new IndexedDBDispatcherHost(id(), profile()->GetWebKitContext(),
+ profile()->GetHostContentSettingsMap()));
+ channel_->AddFilter(
+ GeolocationDispatcherHost::New(
+ id(), profile()->GetGeolocationPermissionContext()));
+ channel_->AddFilter(new GpuMessageFilter(id()));
+ channel_->AddFilter(new PepperFileMessageFilter(id(), profile()));
+ channel_->AddFilter(new PepperMessageFilter(profile()));
+ channel_->AddFilter(new speech_input::SpeechInputDispatcherHost(id()));
+ channel_->AddFilter(new FileSystemDispatcherHost(profile()));
+ channel_->AddFilter(new device_orientation::MessageFilter());
+ channel_->AddFilter(
+ new BlobMessageFilter(id(), profile()->GetBlobStorageContext()));
+ channel_->AddFilter(new FileUtilitiesMessageFilter(id()));
+ channel_->AddFilter(new MimeRegistryMessageFilter());
+ channel_->AddFilter(new DatabaseMessageFilter(
+ profile()->GetDatabaseTracker(), profile()->GetHostContentSettingsMap()));
+
+ SocketStreamDispatcherHost* socket_stream_dispatcher_host =
+ new SocketStreamDispatcherHost(
+ new RendererURLRequestContextSelector(profile(), installed_app_));
+ channel_->AddFilter(socket_stream_dispatcher_host);
+
+ channel_->AddFilter(
+ new WorkerMessageFilter(
+ id(),
+ profile()->GetRequestContext(),
+ &profile()->GetResourceContext(),
+ g_browser_process->resource_dispatcher_host(),
+ NewCallbackWithReturnValue(
+ widget_helper_.get(), &RenderWidgetHelper::GetNextRoutingID)));
+
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableP2PApi))
+ channel_->AddFilter(new P2PSocketDispatcherHost());
+
+ channel_->AddFilter(new TraceMessageFilter());
+ channel_->AddFilter(new ResolveProxyMsgHelper(NULL));
+ channel_->AddFilter(new QuotaDispatcherHost());
+}
+
+int BrowserRenderProcessHost::GetNextRoutingID() {
+ return widget_helper_->GetNextRoutingID();
+}
+
+void BrowserRenderProcessHost::CancelResourceRequests(int render_widget_id) {
+ widget_helper_->CancelResourceRequests(render_widget_id);
+}
+
+void BrowserRenderProcessHost::CrossSiteClosePageACK(
+ const ViewMsg_ClosePage_Params& params) {
+ widget_helper_->CrossSiteClosePageACK(params);
+}
+
+bool BrowserRenderProcessHost::WaitForUpdateMsg(
+ int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
+ // The post task to this thread with the process id could be in queue, and we
+ // don't want to dispatch a message before then since it will need the handle.
+ if (child_process_.get() && child_process_->IsStarting())
+ return false;
+
+ return widget_helper_->WaitForUpdateMsg(render_widget_id, max_delay, msg);
+}
+
+void BrowserRenderProcessHost::ReceivedBadMessage() {
+ if (run_renderer_in_process()) {
+ // In single process mode it is better if we don't suicide but just
+ // crash.
+ CHECK(false);
+ }
+ NOTREACHED();
+ base::KillProcess(GetHandle(), ResultCodes::KILLED_BAD_MESSAGE, false);
+}
+
+void BrowserRenderProcessHost::ViewCreated() {
+ visited_link_updater_->ReceiverReady(this);
+}
+
+void BrowserRenderProcessHost::WidgetRestored() {
+ // Verify we were properly backgrounded.
+ DCHECK_EQ(backgrounded_, (visible_widgets_ == 0));
+ visible_widgets_++;
+ visited_link_updater_->Update(this);
+ SetBackgrounded(false);
+}
+
+void BrowserRenderProcessHost::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);
+ }
+}
+
+void BrowserRenderProcessHost::SendVisitedLinkTable(
+ base::SharedMemory* table_memory) {
+ // Check if the process is still starting and we don't have a handle for it
+ // yet, in which case this will happen later when InitVisitedLinks is called.
+ if (!run_renderer_in_process() &&
+ (!child_process_.get() || child_process_->IsStarting())) {
+ return;
+ }
+
+ base::SharedMemoryHandle handle_for_process;
+ table_memory->ShareToProcess(GetHandle(), &handle_for_process);
+ if (base::SharedMemory::IsHandleValid(handle_for_process))
+ Send(new ViewMsg_VisitedLink_NewTable(handle_for_process));
+}
+
+void BrowserRenderProcessHost::AddVisitedLinks(
+ const VisitedLinkCommon::Fingerprints& links) {
+ visited_link_updater_->AddLinks(links);
+ if (visible_widgets_ == 0)
+ return;
+
+ visited_link_updater_->Update(this);
+}
+
+void BrowserRenderProcessHost::ResetVisitedLinks() {
+ visited_link_updater_->AddReset();
+ if (visible_widgets_ == 0)
+ return;
+
+ visited_link_updater_->Update(this);
+}
+
+void BrowserRenderProcessHost::AppendRendererCommandLine(
+ CommandLine* command_line) const {
+ // Pass the process type first, so it shows first in process listings.
+ // Extensions use a special pseudo-process type to make them distinguishable,
+ // even though they're just renderers.
+ command_line->AppendSwitchASCII(switches::kProcessType,
+ extension_process_ ? switches::kExtensionProcess :
+ switches::kRendererProcess);
+
+ if (logging::DialogsAreSuppressed())
+ command_line->AppendSwitch(switches::kNoErrorDialogs);
+
+ if (accessibility_enabled_)
+ command_line->AppendSwitch(switches::kEnableAccessibility);
+
+ // Now send any options from our own command line we want to propagate.
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ PropagateBrowserCommandLineToRenderer(browser_command_line, command_line);
+
+ // Pass on the browser locale.
+ const std::string locale = g_browser_process->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::StatesToString(&field_trial_states);
+ if (!field_trial_states.empty()) {
+ command_line->AppendSwitchASCII(switches::kForceFieldTestNameAndValue,
+ field_trial_states);
+ }
+
+ BrowserChildProcessHost::SetCrashReporterCommandLine(command_line);
+
+ FilePath user_data_dir =
+ browser_command_line.GetSwitchValuePath(switches::kUserDataDir);
+ if (!user_data_dir.empty())
+ command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
+#if defined(OS_CHROMEOS)
+ const std::string& login_profile =
+ browser_command_line.GetSwitchValueASCII(switches::kLoginProfile);
+ if (!login_profile.empty())
+ command_line->AppendSwitchASCII(switches::kLoginProfile, login_profile);
+#endif
+
+ PrefService* prefs = profile()->GetPrefs();
+ // Currently this pref is only registered if applied via a policy.
+ if (prefs->HasPrefPath(prefs::kDisable3DAPIs) &&
+ prefs->GetBoolean(prefs::kDisable3DAPIs)) {
+ // Turn this policy into a command line switch.
+ command_line->AppendSwitch(switches::kDisable3DAPIs);
+ }
+
+ // Appending disable-gpu-feature switches due to software rendering list.
+ GpuDataManager* gpu_data_manager = GpuDataManager::GetInstance();
+ DCHECK(gpu_data_manager);
+ gpu_data_manager->AppendRendererCommandLine(command_line);
+}
+
+void BrowserRenderProcessHost::PropagateBrowserCommandLineToRenderer(
+ const CommandLine& browser_cmd,
+ 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::kAllowHTTPBackgroundPage,
+ switches::kAllowScriptingGallery,
+ switches::kAlwaysAuthorizePlugins,
+ switches::kAppsCheckoutURL,
+ switches::kAppsGalleryURL,
+ // We propagate the Chrome Frame command line here as well in case the
+ // renderer is not run in the sandbox.
+ switches::kChromeFrame,
+ switches::kDebugPrint,
+ switches::kDisable3DAPIs,
+ switches::kDisableAcceleratedCompositing,
+ switches::kDisableApplicationCache,
+ switches::kDisableAudio,
+ switches::kDisableBreakpad,
+ switches::kDisableDataTransferItems,
+ switches::kDisableDatabases,
+ switches::kDisableDesktopNotifications,
+ switches::kDisableDeviceOrientation,
+ switches::kDisableFileSystem,
+ switches::kDisableGeolocation,
+ switches::kDisableGLMultisampling,
+ switches::kDisableGLSLTranslator,
+ switches::kDisableIndexedDatabase,
+ switches::kDisableJavaScriptI18NAPI,
+ switches::kDisableLocalStorage,
+ switches::kDisableLogging,
+ switches::kDisableSeccompSandbox,
+ switches::kDisableSessionStorage,
+ switches::kDisableSharedWorkers,
+ switches::kDisableSpeechInput,
+ switches::kDisableWebSockets,
+ switches::kDomAutomationController,
+ switches::kDumpHistogramsOnExit,
+ switches::kEnableAcceleratedDecoding,
+ switches::kEnableAdaptive,
+ switches::kEnableBenchmarking,
+ switches::kEnableClickToPlay,
+ switches::kEnableCrxlessWebApps,
+ switches::kEnableDCHECK,
+ switches::kEnableExperimentalExtensionApis,
+ switches::kEnableInBrowserThumbnailing,
+ switches::kEnableLogging,
+ switches::kEnableNaCl,
+ switches::kEnableOpenMax,
+ switches::kEnableP2PApi,
+ switches::kEnablePepperTesting,
+ switches::kEnablePrintPreview,
+ switches::kEnableRemoting,
+ switches::kEnableResourceContentSettings,
+#if defined(OS_MACOSX)
+ // Allow this to be set when invoking the browser and relayed along.
+ switches::kEnableSandboxLogging,
+#endif
+ switches::kEnableSearchProviderApiV2,
+ switches::kEnableSeccompSandbox,
+ switches::kEnableStatsTable,
+ switches::kEnableVideoFullscreen,
+ switches::kEnableVideoLogging,
+ switches::kEnableWatchdog,
+ switches::kEnableWebAudio,
+ switches::kExperimentalSpellcheckerFeatures,
+ switches::kFullMemoryCrashReport,
+#if !defined (GOOGLE_CHROME_BUILD)
+ // These are unsupported and not fully tested modes, so don't enable them
+ // for official Google Chrome builds.
+ switches::kInProcessPlugins,
+#endif // GOOGLE_CHROME_BUILD
+ switches::kInProcessWebGL,
+ switches::kJavaScriptFlags,
+ switches::kLoggingLevel,
+ switches::kMemoryProfiling,
+ switches::kMessageLoopHistogrammer,
+ switches::kNoJsRandomness,
+ switches::kNoReferrers,
+ switches::kNoSandbox,
+ switches::kPlaybackMode,
+ switches::kPpapiFlashInProcess,
+ switches::kPpapiFlashPath,
+ switches::kPpapiFlashVersion,
+ switches::kPpapiOutOfProcess,
+ switches::kProfilingAtStart,
+ switches::kProfilingFile,
+ switches::kProfilingFlush,
+ switches::kRecordMode,
+ switches::kRegisterPepperPlugins,
+ switches::kRemoteShellPort,
+ switches::kRendererAssertTest,
+#if !defined(OFFICIAL_BUILD)
+ switches::kRendererCheckFalseTest,
+#endif // !defined(OFFICIAL_BUILD)
+ switches::kRendererCrashTest,
+ switches::kRendererStartupDialog,
+ switches::kShowPaintRects,
+ switches::kSilentDumpOnDCHECK,
+ switches::kSimpleDataSource,
+ switches::kTestSandbox,
+ // This flag needs to be propagated to the renderer process for
+ // --in-process-webgl.
+ switches::kUseGL,
+ switches::kUserAgent,
+ switches::kV,
+ switches::kVideoThreads,
+ switches::kVModule,
+ switches::kWebCoreLogChannels,
+ };
+ renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
+ arraysize(kSwitchNames));
+
+ // Disable databases in incognito mode.
+ if (profile()->IsOffTheRecord() &&
+ !browser_cmd.HasSwitch(switches::kDisableDatabases)) {
+ renderer_cmd->AppendSwitch(switches::kDisableDatabases);
+ }
+
+ // Disable client-side phishing detection in the renderer if it is disabled
+ // in the browser process.
+ if (!g_browser_process->safe_browsing_detection_service()) {
+ renderer_cmd->AppendSwitch(switches::kDisableClientSidePhishingDetection);
+ }
+}
+
+base::ProcessHandle BrowserRenderProcessHost::GetHandle() {
+ // child_process_ is null either because we're in single process mode, we have
+ // done fast termination, or the process has crashed.
+ if (run_renderer_in_process() || !child_process_.get())
+ return base::Process::Current().handle();
+
+ if (child_process_->IsStarting())
+ return base::kNullProcessHandle;
+
+ return child_process_->GetHandle();
+}
+
+void BrowserRenderProcessHost::InitVisitedLinks() {
+ VisitedLinkMaster* visitedlink_master = profile()->GetVisitedLinkMaster();
+ if (!visitedlink_master)
+ return;
+
+ SendVisitedLinkTable(visitedlink_master->shared_memory());
+}
+
+void BrowserRenderProcessHost::InitUserScripts() {
+ UserScriptMaster* user_script_master = profile()->GetUserScriptMaster();
+
+ // Incognito profiles won't have user scripts.
+ if (!user_script_master)
+ return;
+
+ if (!user_script_master->ScriptsReady()) {
+ // No scripts ready. :(
+ return;
+ }
+
+ // Update the renderer process with the current scripts.
+ SendUserScriptsUpdate(user_script_master->GetSharedMemory());
+}
+
+void BrowserRenderProcessHost::InitExtensions() {
+ // Valid extension function names, used to setup bindings in renderer.
+ std::vector<std::string> function_names;
+ ExtensionFunctionDispatcher::GetAllFunctionNames(&function_names);
+ Send(new ExtensionMsg_SetFunctionNames(function_names));
+
+ // Scripting whitelist. This is modified by tests and must be communicated to
+ // renderers.
+ Send(new ExtensionMsg_SetScriptingWhitelist(
+ *Extension::GetScriptingWhitelist()));
+
+ // Loaded extensions.
+ ExtensionService* service = profile()->GetExtensionService();
+ if (service) {
+ for (size_t i = 0; i < service->extensions()->size(); ++i) {
+ Send(new ExtensionMsg_Loaded(
+ ExtensionMsg_Loaded_Params(service->extensions()->at(i))));
+ }
+ }
+}
+
+void BrowserRenderProcessHost::SendUserScriptsUpdate(
+ base::SharedMemory *shared_memory) {
+ // Process is being started asynchronously. We'll end up calling
+ // InitUserScripts when it's created which will call this again.
+ if (child_process_.get() && child_process_->IsStarting())
+ return;
+
+ base::SharedMemoryHandle handle_for_process;
+ if (!shared_memory->ShareToProcess(GetHandle(), &handle_for_process)) {
+ // This can legitimately fail if the renderer asserts at startup.
+ return;
+ }
+
+ if (base::SharedMemory::IsHandleValid(handle_for_process)) {
+ Send(new ExtensionMsg_UpdateUserScripts(handle_for_process));
+ }
+}
+
+bool BrowserRenderProcessHost::FastShutdownIfPossible() {
+ if (run_renderer_in_process())
+ return false; // Single process mode can't do fast shutdown.
+
+ if (!child_process_.get() || child_process_->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 (!sudden_termination_allowed())
+ return false;
+
+ // Check for any external tab containers, since they may still be running even
+ // though this window closed.
+ listeners_iterator iter(ListenersIterator());
+ while (!iter.IsAtEnd()) {
+ // NOTE: This is a bit dangerous. We know that for now, listeners are
+ // always RenderWidgetHosts. But in theory, they don't have to be.
+ const RenderWidgetHost* widget =
+ static_cast<const RenderWidgetHost*>(iter.GetCurrentValue());
+ DCHECK(widget);
+ if (widget && widget->IsRenderView()) {
+ const RenderViewHost* rvh = static_cast<const RenderViewHost*>(widget);
+ if (rvh->delegate()->IsExternalTabContainer())
+ return false;
+ }
+
+ iter.Advance();
+ }
+
+ child_process_.reset();
+ fast_shutdown_started_ = true;
+ return true;
+}
+
+bool BrowserRenderProcessHost::SendWithTimeout(IPC::Message* msg,
+ int timeout_ms) {
+ if (!channel_.get()) {
+ delete msg;
+ return false;
+ }
+ return channel_->SendWithTimeout(msg, timeout_ms);
+}
+
+// This is a platform specific function for mapping a transport DIB given its id
+TransportDIB* BrowserRenderProcessHost::MapTransportDIB(
+ TransportDIB::Id dib_id) {
+#if defined(OS_WIN)
+ // On Windows we need to duplicate the handle from the remote process
+ HANDLE section = chrome::GetSectionFromProcess(
+ dib_id.handle, GetHandle(), false /* read write */);
+ return TransportDIB::Map(section);
+#elif defined(OS_MACOSX)
+ // On OSX, the browser allocates all DIBs and keeps a file descriptor around
+ // for each.
+ return widget_helper_->MapTransportDIB(dib_id);
+#elif defined(OS_POSIX)
+ return TransportDIB::Map(dib_id.shmkey);
+#endif // defined(OS_POSIX)
+}
+
+TransportDIB* BrowserRenderProcessHost::GetTransportDIB(
+ TransportDIB::Id dib_id) {
+ if (!TransportDIB::is_valid_id(dib_id))
+ return NULL;
+
+ const std::map<TransportDIB::Id, TransportDIB*>::iterator
+ i = cached_dibs_.find(dib_id);
+ if (i != cached_dibs_.end()) {
+ cached_dibs_cleaner_.Reset();
+ return i->second;
+ }
+
+ TransportDIB* dib = MapTransportDIB(dib_id);
+ if (!dib)
+ return NULL;
+
+ if (cached_dibs_.size() >= MAX_MAPPED_TRANSPORT_DIBS) {
+ // Clean a single entry from the cache
+ std::map<TransportDIB::Id, TransportDIB*>::iterator smallest_iterator;
+ size_t smallest_size = std::numeric_limits<size_t>::max();
+
+ for (std::map<TransportDIB::Id, TransportDIB*>::iterator
+ i = cached_dibs_.begin(); i != cached_dibs_.end(); ++i) {
+ if (i->second->size() <= smallest_size) {
+ smallest_iterator = i;
+ smallest_size = i->second->size();
+ }
+ }
+
+ delete smallest_iterator->second;
+ cached_dibs_.erase(smallest_iterator);
+ }
+
+ cached_dibs_[dib_id] = dib;
+ cached_dibs_cleaner_.Reset();
+ return dib;
+}
+
+void BrowserRenderProcessHost::ClearTransportDIBCache() {
+ STLDeleteContainerPairSecondPointers(
+ cached_dibs_.begin(), cached_dibs_.end());
+ cached_dibs_.clear();
+}
+
+bool BrowserRenderProcessHost::Send(IPC::Message* msg) {
+ if (!channel_.get()) {
+ delete msg;
+ return false;
+ }
+
+ if (child_process_.get() && child_process_->IsStarting()) {
+ queued_messages_.push(msg);
+ return true;
+ }
+
+ return channel_->Send(msg);
+}
+
+bool BrowserRenderProcessHost::OnMessageReceived(const IPC::Message& msg) {
+ // If we're about to be deleted, we can no longer trust that our profile is
+ // valid, so we ignore incoming messages.
+ if (deleting_soon_)
+ return false;
+
+ mark_child_process_activity_time();
+ if (msg.routing_id() == MSG_ROUTING_CONTROL) {
+ // Dispatch control messages.
+ bool msg_is_ok = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(BrowserRenderProcessHost, msg, msg_is_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UpdatedCacheStats,
+ OnUpdatedCacheStats)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_SuddenTerminationChanged,
+ SuddenTerminationChanged);
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddListener, OnExtensionAddListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener,
+ OnExtensionRemoveListener)
+ IPC_MESSAGE_HANDLER(ExtensionHostMsg_CloseChannel,
+ OnExtensionCloseChannel)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UserMetricsRecordAction,
+ OnUserMetricsRecordAction)
+ IPC_MESSAGE_HANDLER(SpellCheckHostMsg_RequestDictionary,
+ OnSpellCheckerRequestDictionary)
+ IPC_MESSAGE_UNHANDLED_ERROR()
+ IPC_END_MESSAGE_MAP_EX()
+
+ if (!msg_is_ok) {
+ // The message had a handler, but its de-serialization failed.
+ // We consider this a capital crime. Kill the renderer if we have one.
+ LOG(ERROR) << "bad message " << msg.type() << " terminating renderer.";
+ UserMetrics::RecordAction(UserMetricsAction("BadMessageTerminate_BRPH"));
+ ReceivedBadMessage();
+ }
+ return true;
+ }
+
+ // Dispatch incoming messages to the appropriate RenderView/WidgetHost.
+ IPC::Channel::Listener* listener = GetListenerByID(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 BrowserRenderProcessHost::OnChannelConnected(int32 peer_pid) {
+#if defined(IPC_MESSAGE_LOG_ENABLED)
+ Send(new ChildProcessMsg_SetIPCLoggingEnabled(
+ IPC::Logging::GetInstance()->Enabled()));
+#endif
+}
+
+void BrowserRenderProcessHost::OnChannelError() {
+ // 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.
+ if (!channel_.get())
+ return;
+
+ // child_process_ can be NULL in single process mode or if fast
+ // termination happened.
+ int exit_code = 0;
+ base::TerminationStatus status =
+ child_process_.get() ?
+ child_process_->GetChildTerminationStatus(&exit_code) :
+ base::TERMINATION_STATUS_NORMAL_TERMINATION;
+
+ if (status == base::TERMINATION_STATUS_PROCESS_CRASHED ||
+ status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
+ UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildCrashes",
+ extension_process_ ? 2 : 1);
+ }
+
+ if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+ UMA_HISTOGRAM_PERCENTAGE("BrowserRenderProcessHost.ChildKills",
+ extension_process_ ? 2 : 1);
+ }
+
+ RendererClosedDetails details(status, exit_code, extension_process_);
+ NotificationService::current()->Notify(
+ NotificationType::RENDERER_PROCESS_CLOSED,
+ Source<RenderProcessHost>(this),
+ Details<RendererClosedDetails>(&details));
+
+ WebCacheManager::GetInstance()->Remove(id());
+ child_process_.reset();
+ channel_.reset();
+
+ IDMap<IPC::Channel::Listener>::iterator iter(&listeners_);
+ while (!iter.IsAtEnd()) {
+ iter.GetCurrentValue()->OnMessageReceived(
+ ViewHostMsg_RenderViewGone(iter.GetCurrentKey(),
+ static_cast<int>(status),
+ exit_code));
+ iter.Advance();
+ }
+
+ ClearTransportDIBCache();
+
+ // this object is not deleted at this point and may be reused later.
+ // TODO(darin): clean this up
+}
+
+void BrowserRenderProcessHost::OnUpdatedCacheStats(
+ const WebCache::UsageStats& stats) {
+ WebCacheManager::GetInstance()->ObserveStats(id(), stats);
+}
+
+void BrowserRenderProcessHost::SuddenTerminationChanged(bool enabled) {
+ set_sudden_termination_allowed(enabled);
+}
+
+void BrowserRenderProcessHost::SetBackgrounded(bool 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_.get() || child_process_->IsStarting())
+ 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
+
+ child_process_->SetProcessBackgrounded(backgrounded);
+}
+
+void BrowserRenderProcessHost::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type.value) {
+ case NotificationType::USER_SCRIPTS_UPDATED: {
+ base::SharedMemory* shared_memory =
+ Details<base::SharedMemory>(details).ptr();
+ if (shared_memory) {
+ SendUserScriptsUpdate(shared_memory);
+ }
+ break;
+ }
+ case NotificationType::EXTENSION_LOADED: {
+ Send(new ExtensionMsg_Loaded(
+ ExtensionMsg_Loaded_Params(Details<const Extension>(details).ptr())));
+ break;
+ }
+ case NotificationType::EXTENSION_UNLOADED: {
+ Send(new ExtensionMsg_Unloaded(
+ Details<UnloadedExtensionInfo>(details).ptr()->extension->id()));
+ break;
+ }
+ case NotificationType::SPELLCHECK_HOST_REINITIALIZED: {
+ InitSpellChecker();
+ break;
+ }
+ case NotificationType::SPELLCHECK_WORD_ADDED: {
+ AddSpellCheckWord(
+ reinterpret_cast<const Source<SpellCheckHost>*>(&source)->
+ ptr()->GetLastAddedFile());
+ break;
+ }
+ case NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED: {
+ PrefService* prefs = profile()->GetPrefs();
+ EnableAutoSpellCorrect(
+ prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
+ break;
+ }
+ default: {
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+void BrowserRenderProcessHost::OnProcessLaunched() {
+ if (child_process_.get())
+ child_process_->SetProcessBackgrounded(backgrounded_);
+
+ Send(new ViewMsg_SetIsIncognitoProcess(profile()->IsOffTheRecord()));
+
+ InitVisitedLinks();
+ InitUserScripts();
+ InitExtensions();
+
+ // We don't want to initialize the spellchecker unless SpellCheckHost has been
+ // created. In InitSpellChecker(), we know if GetSpellCheckHost() is NULL
+ // then the spellchecker has been turned off, but here, we don't know if
+ // it's been turned off or just not loaded yet.
+ if (profile()->GetSpellCheckHost())
+ InitSpellChecker();
+
+ InitClientSidePhishingDetection();
+
+ if (max_page_id_ != -1)
+ Send(new ViewMsg_SetNextPageID(max_page_id_ + 1));
+
+ while (!queued_messages_.empty()) {
+ Send(queued_messages_.front());
+ queued_messages_.pop();
+ }
+
+ NotificationService::current()->Notify(
+ NotificationType::RENDERER_PROCESS_CREATED,
+ Source<RenderProcessHost>(this), NotificationService::NoDetails());
+}
+
+void BrowserRenderProcessHost::OnExtensionAddListener(
+ const std::string& extension_id,
+ const std::string& event_name) {
+ if (profile()->GetExtensionEventRouter()) {
+ profile()->GetExtensionEventRouter()->AddEventListener(
+ event_name, this, extension_id);
+ }
+}
+
+void BrowserRenderProcessHost::OnExtensionRemoveListener(
+ const std::string& extension_id,
+ const std::string& event_name) {
+ if (profile()->GetExtensionEventRouter()) {
+ profile()->GetExtensionEventRouter()->RemoveEventListener(
+ event_name, this, extension_id);
+ }
+}
+
+void BrowserRenderProcessHost::OnExtensionCloseChannel(int port_id) {
+ if (profile()->GetExtensionMessageService()) {
+ profile()->GetExtensionMessageService()->CloseChannel(port_id);
+ }
+}
+
+void BrowserRenderProcessHost::OnUserMetricsRecordAction(
+ const std::string& action) {
+ UserMetrics::RecordComputedAction(action, profile());
+}
+
+void BrowserRenderProcessHost::OnSpellCheckerRequestDictionary() {
+ if (profile()->GetSpellCheckHost()) {
+ // The spellchecker initialization already started and finished; just send
+ // it to the renderer.
+ InitSpellChecker();
+ } else {
+ // We may have gotten multiple requests from different renderers. We don't
+ // want to initialize multiple times in this case, so we set |force| to
+ // false.
+ profile()->ReinitializeSpellCheckHost(false);
+ }
+}
+
+void BrowserRenderProcessHost::AddSpellCheckWord(const std::string& word) {
+ Send(new SpellCheckMsg_WordAdded(word));
+}
+
+void BrowserRenderProcessHost::InitSpellChecker() {
+ SpellCheckHost* spellcheck_host = profile()->GetSpellCheckHost();
+ if (spellcheck_host) {
+ PrefService* prefs = profile()->GetPrefs();
+ IPC::PlatformFileForTransit file;
+
+ if (spellcheck_host->GetDictionaryFile() !=
+ base::kInvalidPlatformFileValue) {
+#if defined(OS_POSIX)
+ file = base::FileDescriptor(spellcheck_host->GetDictionaryFile(), false);
+#elif defined(OS_WIN)
+ ::DuplicateHandle(::GetCurrentProcess(),
+ spellcheck_host->GetDictionaryFile(),
+ GetHandle(),
+ &file,
+ 0,
+ false,
+ DUPLICATE_SAME_ACCESS);
+#endif
+ }
+
+ Send(new SpellCheckMsg_Init(
+ file,
+ spellcheck_host->GetCustomWords(),
+ spellcheck_host->GetLanguage(),
+ prefs->GetBoolean(prefs::kEnableAutoSpellCorrect)));
+ } else {
+ Send(new SpellCheckMsg_Init(
+ IPC::InvalidPlatformFileForTransit(),
+ std::vector<std::string>(),
+ std::string(),
+ false));
+ }
+}
+
+void BrowserRenderProcessHost::EnableAutoSpellCorrect(bool enable) {
+ Send(new SpellCheckMsg_EnableAutoSpellCorrect(enable));
+}
+
+void BrowserRenderProcessHost::InitClientSidePhishingDetection() {
+ if (g_browser_process->safe_browsing_detection_service()) {
+ // The BrowserRenderProcessHost object might get deleted before the
+ // safe browsing client-side detection service class is done with opening
+ // the model file. To avoid crashing we use the callback factory which will
+ // cancel the callback if |this| is destroyed.
+ g_browser_process->safe_browsing_detection_service()->GetModelFile(
+ callback_factory_.NewCallback(
+ &BrowserRenderProcessHost::OpenPhishingModelDone));
+ }
+}
+
+void BrowserRenderProcessHost::OpenPhishingModelDone(
+ base::PlatformFile model_file) {
+ if (model_file != base::kInvalidPlatformFileValue) {
+ IPC::PlatformFileForTransit file;
+#if defined(OS_POSIX)
+ file = base::FileDescriptor(model_file, false);
+#elif defined(OS_WIN)
+ ::DuplicateHandle(::GetCurrentProcess(), model_file, GetHandle(), &file, 0,
+ false, DUPLICATE_SAME_ACCESS);
+#endif
+ Send(new SafeBrowsingMsg_SetPhishingModel(file));
+ }
+}
diff --git a/content/browser/renderer_host/browser_render_process_host.h b/content/browser/renderer_host/browser_render_process_host.h
new file mode 100644
index 0000000..70cdf00
--- /dev/null
+++ b/content/browser/renderer_host/browser_render_process_host.h
@@ -0,0 +1,226 @@
+// Copyright (c) 2011 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.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_H_
+#pragma once
+
+#include <map>
+#include <queue>
+#include <string>
+
+#include "base/memory/scoped_callback_factory.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/platform_file.h"
+#include "base/process.h"
+#include "base/timer.h"
+#include "chrome/common/extensions/extension.h"
+#include "content/browser/child_process_launcher.h"
+#include "content/browser/renderer_host/render_process_host.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_registrar.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"
+#include "ui/gfx/surface/transport_dib.h"
+
+class CommandLine;
+class RendererMainThread;
+class RenderWidgetHelper;
+class VisitedLinkUpdater;
+
+namespace base {
+class SharedMemory;
+}
+
+// Implements a concrete RenderProcessHost for the browser process for talking
+// to actual renderer processes (as opposed to mocks).
+//
+// Represents the browser side of the browser <--> renderer communication
+// channel. There will be one RenderProcessHost per renderer process.
+//
+// This object is refcounted so that it can release its resources when all
+// hosts using it go away.
+//
+// This object communicates back and forth with the RenderProcess object
+// running in the renderer process. Each RenderProcessHost and RenderProcess
+// keeps a list of RenderView (renderer) and TabContents (browser) which
+// are correlated with IDs. This way, the Views and the corresponding ViewHosts
+// communicate through the two process objects.
+class BrowserRenderProcessHost : public RenderProcessHost,
+ public NotificationObserver,
+ public ChildProcessLauncher::Client {
+ public:
+ explicit BrowserRenderProcessHost(Profile* profile);
+ ~BrowserRenderProcessHost();
+
+ // Whether this process is associated with an installed app.
+ const Extension* installed_app() const { return installed_app_; }
+ void set_installed_app(const Extension* installed_app) {
+ installed_app_ = installed_app;
+ }
+
+ // RenderProcessHost implementation (public portion).
+ virtual bool Init(bool is_accessibility_enabled, bool is_extensions_process);
+ virtual int GetNextRoutingID();
+ virtual void CancelResourceRequests(int render_widget_id);
+ virtual void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
+ virtual bool WaitForUpdateMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
+ virtual void ReceivedBadMessage();
+ virtual void WidgetRestored();
+ virtual void WidgetHidden();
+ virtual void ViewCreated();
+ virtual void SendVisitedLinkTable(base::SharedMemory* table_memory);
+ virtual void AddVisitedLinks(const VisitedLinkCommon::Fingerprints& links);
+ virtual void ResetVisitedLinks();
+ virtual bool FastShutdownIfPossible();
+ virtual bool SendWithTimeout(IPC::Message* msg, int timeout_ms);
+ virtual base::ProcessHandle GetHandle();
+ virtual TransportDIB* GetTransportDIB(TransportDIB::Id dib_id);
+
+ // IPC::Channel::Sender via RenderProcessHost.
+ virtual bool Send(IPC::Message* msg);
+
+ // IPC::Channel::Listener via RenderProcessHost.
+ virtual bool OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // ChildProcessLauncher::Client implementation.
+ virtual void OnProcessLaunched();
+
+ private:
+ friend class VisitRelayingRenderProcessHost;
+
+ // Creates and adds the IO thread message filters.
+ void CreateMessageFilters();
+
+ // Control message handlers.
+ void OnUpdatedCacheStats(const WebKit::WebCache::UsageStats& stats);
+ void SuddenTerminationChanged(bool enabled);
+ void OnExtensionAddListener(const std::string& extension_id,
+ const std::string& event_name);
+ void OnExtensionRemoveListener(const std::string& extension_id,
+ const std::string& event_name);
+ void OnExtensionCloseChannel(int port_id);
+ void OnUserMetricsRecordAction(const std::string& action);
+
+ // Initialize support for visited links. Send the renderer process its initial
+ // set of visited links.
+ void InitVisitedLinks();
+
+ // Initialize support for user scripts. Send the renderer process its initial
+ // set of scripts and listen for updates to scripts.
+ void InitUserScripts();
+
+ // Initialize support for extension APIs. Send the list of registered API
+ // functions to thre renderer process.
+ void InitExtensions();
+
+ // Sends the renderer process a new set of user scripts.
+ void SendUserScriptsUpdate(base::SharedMemory* shared_memory);
+
+ // Generates a command line to be used to spawn a renderer and appends the
+ // results to |*command_line|.
+ void AppendRendererCommandLine(CommandLine* command_line) const;
+
+ // Copies applicable command line switches from the given |browser_cmd| line
+ // flags to the output |renderer_cmd| line flags. Not all switches will be
+ // copied over.
+ void PropagateBrowserCommandLineToRenderer(const CommandLine& browser_cmd,
+ CommandLine* renderer_cmd) const;
+
+ // Callers can reduce the RenderProcess' priority.
+ void SetBackgrounded(bool backgrounded);
+
+ // The renderer has requested that we initialize its spellchecker. This should
+ // generally only be called once per session, as after the first call, all
+ // future renderers will be passed the initialization information on startup
+ // (or when the dictionary changes in some way).
+ void OnSpellCheckerRequestDictionary();
+
+ // Tell the renderer of a new word that has been added to the custom
+ // dictionary.
+ void AddSpellCheckWord(const std::string& word);
+
+ // Pass the renderer some basic intialization information. Note that the
+ // renderer will not load Hunspell until it needs to.
+ void InitSpellChecker();
+
+ // Tell the renderer that auto spell correction has been enabled/disabled.
+ void EnableAutoSpellCorrect(bool enable);
+
+ // Initializes client-side phishing detection. Starts reading the phishing
+ // model from the client-side detection service class. Once the model is read
+ // OpenPhishingModelDone() is invoked.
+ void InitClientSidePhishingDetection();
+
+ // Called once the client-side detection service class is done with opening
+ // the model file.
+ void OpenPhishingModelDone(base::PlatformFile model_file);
+
+ NotificationRegistrar registrar_;
+
+ // The count of currently visible widgets. Since the host can be a container
+ // for multiple widgets, it uses this count to determine when it should be
+ // backgrounded.
+ int32 visible_widgets_;
+
+ // Does this process have backgrounded priority.
+ bool backgrounded_;
+
+ // Used to allow a RenderWidgetHost to intercept various messages on the
+ // IO thread.
+ scoped_refptr<RenderWidgetHelper> widget_helper_;
+
+ // A map of transport DIB ids to cached TransportDIBs
+ std::map<TransportDIB::Id, TransportDIB*> cached_dibs_;
+ enum {
+ // This is the maximum size of |cached_dibs_|
+ MAX_MAPPED_TRANSPORT_DIBS = 3,
+ };
+
+ // Map a transport DIB from its Id and return it. Returns NULL on error.
+ TransportDIB* MapTransportDIB(TransportDIB::Id dib_id);
+
+ void ClearTransportDIBCache();
+ // This is used to clear our cache five seconds after the last use.
+ base::DelayTimer<BrowserRenderProcessHost> cached_dibs_cleaner_;
+
+ // Used in single-process mode.
+ scoped_ptr<RendererMainThread> in_process_renderer_;
+
+ // Buffer visited links and send them to to renderer.
+ scoped_ptr<VisitedLinkUpdater> visited_link_updater_;
+
+ // True if this prcoess should have accessibility enabled;
+ bool accessibility_enabled_;
+
+ // True iff this process is being used as an extension process. Not valid
+ // when running in single-process mode.
+ bool extension_process_;
+
+ // The Extension for the hosted or packaged app if any, NULL otherwise.
+ scoped_refptr<const Extension> installed_app_;
+
+ // Used to launch and terminate the process without blocking the UI thread.
+ scoped_ptr<ChildProcessLauncher> child_process_;
+
+ // Messages we queue while waiting for the process handle. We queue them here
+ // instead of in the channel so that we ensure they're sent after init related
+ // messages that are sent once the process handle is available. This is
+ // because the queued messages may have dependencies on the init messages.
+ std::queue<IPC::Message*> queued_messages_;
+
+ base::ScopedCallbackFactory<BrowserRenderProcessHost> callback_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserRenderProcessHost);
+};
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_H_
diff --git a/content/browser/renderer_host/pepper_file_message_filter.cc b/content/browser/renderer_host/pepper_file_message_filter.cc
index a4f1535..8cc4d5e 100644
--- a/content/browser/renderer_host/pepper_file_message_filter.cc
+++ b/content/browser/renderer_host/pepper_file_message_filter.cc
@@ -10,9 +10,9 @@
#include "base/platform_file.h"
#include "base/process_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/browser_thread.h"
#include "content/browser/child_process_security_policy.h"
+#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/common/pepper_file_messages.h"
#include "ipc/ipc_platform_file.h"
#include "webkit/plugins/ppapi/file_path.h"
diff --git a/content/browser/renderer_host/pepper_message_filter.cc b/content/browser/renderer_host/pepper_message_filter.cc
index ef6a37f..1c79a90 100644
--- a/content/browser/renderer_host/pepper_message_filter.cc
+++ b/content/browser/renderer_host/pepper_message_filter.cc
@@ -9,8 +9,8 @@
#include "base/threading/worker_pool.h"
#include "chrome/browser/net/chrome_url_request_context.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/browser_thread.h"
+#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/common/pepper_messages.h"
#include "net/base/address_list.h"
#include "net/base/host_port_pair.h"
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 8f664d0..ad28245 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -24,7 +24,6 @@
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
@@ -35,6 +34,7 @@
#include "content/browser/plugin_service.h"
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/browser/ppapi_broker_process_host.h"
+#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_notification_task.h"
#include "content/browser/renderer_host/render_widget_helper.h"
diff --git a/content/browser/renderer_host/render_process_host.h b/content/browser/renderer_host/render_process_host.h
index a954d02..cc37a8c 100644
--- a/content/browser/renderer_host/render_process_host.h
+++ b/content/browser/renderer_host/render_process_host.h
@@ -114,6 +114,8 @@ class RenderProcessHost : public IPC::Channel::Sender,
return listeners_.Lookup(routing_id);
}
+ IPC::SyncChannel* channel() { return channel_.get(); }
+
// Called to inform the render process host of a new "max page id" for a
// render view host. The render process host computes the largest page id
// across all render view hosts and uses the value when it needs to
diff --git a/content/browser/site_instance.cc b/content/browser/site_instance.cc
index 3503eac..a121109 100644
--- a/content/browser/site_instance.cc
+++ b/content/browser/site_instance.cc
@@ -4,10 +4,10 @@
#include "content/browser/site_instance.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/common/url_constants.h"
#include "content/browser/browsing_instance.h"
#include "content/browser/content_browser_client.h"
+#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/webui/web_ui_factory.h"
#include "content/common/notification_service.h"
#include "content/common/content_client.h"
diff --git a/content/browser/site_instance_unittest.cc b/content/browser/site_instance_unittest.cc
index 24b7cd3..b2cb51ca 100644
--- a/content/browser/site_instance_unittest.cc
+++ b/content/browser/site_instance_unittest.cc
@@ -4,7 +4,6 @@
#include "base/stl_util-inl.h"
#include "base/string16.h"
-#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
@@ -13,6 +12,7 @@
#include "content/browser/browsing_instance.h"
#include "content/browser/child_process_security_policy.h"
#include "content/browser/content_browser_client.h"
+#include "content/browser/renderer_host/browser_render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/test_render_view_host.h"
#include "content/browser/site_instance.h"
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index d416b51..789f3d3 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -201,6 +201,8 @@
'browser/renderer_host/backing_store_x.h',
'browser/renderer_host/blob_message_filter.cc',
'browser/renderer_host/blob_message_filter.h',
+ 'browser/renderer_host/browser_render_process_host.cc',
+ 'browser/renderer_host/browser_render_process_host.h',
'browser/renderer_host/buffered_resource_handler.cc',
'browser/renderer_host/buffered_resource_handler.h',
'browser/renderer_host/clipboard_message_filter.cc',