blob: 434f9e212d63749ffc2f7feaaf57bfff9250fce6 [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]2c62b562009-01-27 19:04:505#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:296#include <windows.h>
[email protected]2c62b562009-01-27 19:04:507#endif
initial.commit09911bf2008-07-26 23:55:298#include <algorithm>
9
10#include "chrome/renderer/render_thread.h"
11
12#include "base/shared_memory.h"
[email protected]a9f4d902008-09-15 23:43:4213#include "chrome/common/chrome_plugin_lib.h"
initial.commit09911bf2008-07-26 23:55:2914#include "chrome/common/ipc_logging.h"
[email protected]e09ba552009-02-05 03:26:2915#include "chrome/common/render_messages.h"
[email protected]173de1b2008-08-15 18:36:4616#include "chrome/common/notification_service.h"
[email protected]2c62b562009-01-27 19:04:5017// TODO(port)
18#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2919#include "chrome/plugin/plugin_channel.h"
[email protected]2c62b562009-01-27 19:04:5020#else
21#include <vector>
22#include "base/scoped_handle.h"
23#include "chrome/plugin/plugin_channel_base.h"
24#include "webkit/glue/weburlrequest.h"
25#endif
initial.commit09911bf2008-07-26 23:55:2926#include "chrome/renderer/net/render_dns_master.h"
27#include "chrome/renderer/render_process.h"
28#include "chrome/renderer/render_view.h"
[email protected]0938d3c2009-01-09 20:37:3529#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2930#include "chrome/renderer/visitedlink_slave.h"
31#include "webkit/glue/cache_manager.h"
32
[email protected]2c62b562009-01-27 19:04:5033
[email protected]1d97d2e2008-12-18 23:39:0234RenderThread* g_render_thread;
35
initial.commit09911bf2008-07-26 23:55:2936static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */;
37
38// V8 needs a 1MB stack size.
39static const size_t kStackSize = 1024 * 1024;
40
initial.commit09911bf2008-07-26 23:55:2941//-----------------------------------------------------------------------------
42// Methods below are only called on the owner's thread:
43
44RenderThread::RenderThread(const std::wstring& channel_name)
45 : Thread("Chrome_RenderThread"),
initial.commit09911bf2008-07-26 23:55:2946 owner_loop_(MessageLoop::current()),
[email protected]2c62b562009-01-27 19:04:5047 channel_name_(channel_name),
initial.commit09911bf2008-07-26 23:55:2948 visited_link_slave_(NULL),
[email protected]0938d3c2009-01-09 20:37:3549 user_script_slave_(NULL),
initial.commit09911bf2008-07-26 23:55:2950 render_dns_master_(NULL),
51 in_send_(0) {
52 DCHECK(owner_loop_);
[email protected]ab820df2008-08-26 05:55:1053 base::Thread::Options options;
54 options.stack_size = kStackSize;
55 // When we run plugins in process, we actually run them on the render thread,
56 // which means that we need to make the render thread pump UI events.
57 if (RenderProcess::ShouldLoadPluginsInProcess())
58 options.message_loop_type = MessageLoop::TYPE_UI;
59 StartWithOptions(options);
initial.commit09911bf2008-07-26 23:55:2960}
61
62RenderThread::~RenderThread() {
63 Stop();
64}
65
66void RenderThread::OnChannelError() {
[email protected]295039bd2008-08-15 04:32:5767 owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
initial.commit09911bf2008-07-26 23:55:2968}
69
70bool RenderThread::Send(IPC::Message* msg) {
71 in_send_++;
72 bool rv = channel_->Send(msg);
73 in_send_--;
74 return rv;
75}
76
77void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
78 channel_->AddFilter(filter);
79}
80
81void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) {
82 channel_->RemoveFilter(filter);
83}
84
85void RenderThread::Resolve(const char* name, size_t length) {
[email protected]2c62b562009-01-27 19:04:5086// TODO(port)
87#if defined(OS_WIN)
[email protected]81a34412009-01-05 19:17:2488 return render_dns_master_->Resolve(name, length);
[email protected]2c62b562009-01-27 19:04:5089#else
90 NOTIMPLEMENTED();
91#endif
[email protected]81a34412009-01-05 19:17:2492}
initial.commit09911bf2008-07-26 23:55:2993
94void RenderThread::AddRoute(int32 routing_id,
95 IPC::Channel::Listener* listener) {
96 DCHECK(MessageLoop::current() == message_loop());
97
98 // This corresponds to the AddRoute call done in CreateView.
99 router_.AddRoute(routing_id, listener);
100}
101
102void RenderThread::RemoveRoute(int32 routing_id) {
103 DCHECK(MessageLoop::current() == message_loop());
104
105 router_.RemoveRoute(routing_id);
106}
107
108void RenderThread::Init() {
[email protected]1d97d2e2008-12-18 23:39:02109 DCHECK(!g_render_thread);
110 g_render_thread = this;
initial.commit09911bf2008-07-26 23:55:29111
[email protected]173de1b2008-08-15 18:36:46112 notification_service_.reset(new NotificationService);
113
initial.commit09911bf2008-07-26 23:55:29114 cache_stats_factory_.reset(
115 new ScopedRunnableMethodFactory<RenderThread>(this));
116
117 channel_.reset(new IPC::SyncChannel(channel_name_,
[email protected]d65cab7a2008-08-12 01:25:41118 IPC::Channel::MODE_CLIENT, this, NULL, owner_loop_, true,
119 RenderProcess::GetShutDownEvent()));
initial.commit09911bf2008-07-26 23:55:29120
[email protected]2c62b562009-01-27 19:04:50121#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29122 // The renderer thread should wind-up COM.
123 CoInitialize(0);
[email protected]2c62b562009-01-27 19:04:50124#endif
initial.commit09911bf2008-07-26 23:55:29125
initial.commit09911bf2008-07-26 23:55:29126 visited_link_slave_ = new VisitedLinkSlave();
[email protected]0938d3c2009-01-09 20:37:35127 user_script_slave_ = new UserScriptSlave();
initial.commit09911bf2008-07-26 23:55:29128 render_dns_master_.reset(new RenderDnsMaster());
initial.commit09911bf2008-07-26 23:55:29129
130#ifdef IPC_MESSAGE_LOG_ENABLED
131 IPC::Logging::current()->SetIPCSender(this);
132#endif
133}
134
135void RenderThread::CleanUp() {
[email protected]1d97d2e2008-12-18 23:39:02136 DCHECK(g_render_thread == this);
137 g_render_thread = NULL;
initial.commit09911bf2008-07-26 23:55:29138
[email protected]8fd8de92008-08-12 23:50:30139 // Need to destruct the SyncChannel to the browser before we go away because
140 // it caches a pointer to this thread.
141 channel_.reset();
142
[email protected]2c62b562009-01-27 19:04:50143// TODO(port)
144#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29145 // Clean up plugin channels before this thread goes away.
146 PluginChannelBase::CleanupChannels();
[email protected]2c62b562009-01-27 19:04:50147#endif
initial.commit09911bf2008-07-26 23:55:29148
149#ifdef IPC_MESSAGE_LOG_ENABLED
150 IPC::Logging::current()->SetIPCSender(NULL);
151#endif
152
[email protected]173de1b2008-08-15 18:36:46153 notification_service_.reset();
154
initial.commit09911bf2008-07-26 23:55:29155 delete visited_link_slave_;
156 visited_link_slave_ = NULL;
157
[email protected]0938d3c2009-01-09 20:37:35158 delete user_script_slave_;
159 user_script_slave_ = NULL;
[email protected]1e0f70402008-10-16 23:57:47160
[email protected]2c62b562009-01-27 19:04:50161#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29162 CoUninitialize();
[email protected]2c62b562009-01-27 19:04:50163#endif
initial.commit09911bf2008-07-26 23:55:29164}
165
[email protected]176aa482008-11-14 03:25:15166void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) {
initial.commit09911bf2008-07-26 23:55:29167 DCHECK(table) << "Bad table handle";
168 visited_link_slave_->Init(table);
169}
170
[email protected]0938d3c2009-01-09 20:37:35171void RenderThread::OnUpdateUserScripts(
[email protected]176aa482008-11-14 03:25:15172 base::SharedMemoryHandle scripts) {
[email protected]1e0f70402008-10-16 23:57:47173 DCHECK(scripts) << "Bad scripts handle";
[email protected]0938d3c2009-01-09 20:37:35174 user_script_slave_->UpdateScripts(scripts);
[email protected]1e0f70402008-10-16 23:57:47175}
176
initial.commit09911bf2008-07-26 23:55:29177void RenderThread::OnMessageReceived(const IPC::Message& msg) {
178 // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but
179 // it seems simpler to just process any control messages that we care about
180 // up-front and then send the rest of the messages onto router_.
181
182 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
183 IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)
184 IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)
185 IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)
[email protected]2c62b562009-01-27 19:04:50186 // TODO(port): removed from render_messages_internal.h;
187 // is there a new non-windows message I should add here?
188#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29189 IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
[email protected]2c62b562009-01-27 19:04:50190#endif
initial.commit09911bf2008-07-26 23:55:29191 IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)
192 IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,
193 OnGetCacheResourceStats)
[email protected]a9f4d902008-09-15 23:43:42194 IPC_MESSAGE_HANDLER(ViewMsg_PluginMessage, OnPluginMessage)
[email protected]0938d3c2009-01-09 20:37:35195 IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_NewScripts,
196 OnUpdateUserScripts)
initial.commit09911bf2008-07-26 23:55:29197 // send the rest to the router
198 IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))
199 IPC_END_MESSAGE_MAP()
200 } else {
201 router_.OnMessageReceived(msg);
202 }
203}
204
[email protected]690a99c2009-01-06 16:48:45205void RenderThread::OnPluginMessage(const FilePath& plugin_path,
[email protected]a9f4d902008-09-15 23:43:42206 const std::vector<uint8>& data) {
[email protected]3daa8452009-01-16 18:33:47207 if (!ChromePluginLib::IsInitialized()) {
208 return;
209 }
[email protected]a9f4d902008-09-15 23:43:42210 CHECK(ChromePluginLib::IsPluginThread());
[email protected]690a99c2009-01-06 16:48:45211 ChromePluginLib *chrome_plugin = ChromePluginLib::Find(plugin_path);
[email protected]a9f4d902008-09-15 23:43:42212 if (chrome_plugin) {
213 void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0]));
214 uint32 data_len = static_cast<uint32>(data.size());
215 chrome_plugin->functions().on_message(data_ptr, data_len);
216 }
217}
218
initial.commit09911bf2008-07-26 23:55:29219void RenderThread::OnSetNextPageID(int32 next_page_id) {
220 // This should only be called at process initialization time, so we shouldn't
221 // have to worry about thread-safety.
[email protected]2c62b562009-01-27 19:04:50222 // TODO(port)
223#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29224 RenderView::SetNextPageID(next_page_id);
[email protected]2c62b562009-01-27 19:04:50225#endif
initial.commit09911bf2008-07-26 23:55:29226}
227
[email protected]4274e582009-01-27 22:09:56228#if defined(OS_WIN)
229
[email protected]18bcc3c2009-01-27 21:39:15230void RenderThread::OnCreateNewView(gfx::NativeViewId parent_hwnd,
231 ModalDialogEvent modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29232 const WebPreferences& webkit_prefs,
233 int32 view_id) {
[email protected]18bcc3c2009-01-27 21:39:15234 base::WaitableEvent* waitable_event = new base::WaitableEvent(
235#if defined(OS_WIN)
236 modal_dialog_event.event);
237#else
238 true, false);
239#endif
240
initial.commit09911bf2008-07-26 23:55:29241 // TODO(darin): once we have a RenderThread per RenderView, this will need to
242 // change to assert that we are not creating more than one view.
initial.commit09911bf2008-07-26 23:55:29243 RenderView::Create(
[email protected]1c4947f2009-01-15 22:25:11244 this, parent_hwnd, waitable_event, MSG_ROUTING_NONE, webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08245 new SharedRenderViewCounter(0), view_id);
initial.commit09911bf2008-07-26 23:55:29246}
initial.commit09911bf2008-07-26 23:55:29247
[email protected]4274e582009-01-27 22:09:56248#endif
249
initial.commit09911bf2008-07-26 23:55:29250void RenderThread::OnSetCacheCapacities(size_t min_dead_capacity,
251 size_t max_dead_capacity,
252 size_t capacity) {
[email protected]2c62b562009-01-27 19:04:50253#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29254 CacheManager::SetCapacities(min_dead_capacity, max_dead_capacity, capacity);
[email protected]2c62b562009-01-27 19:04:50255#else
256 // TODO(port)
257 NOTIMPLEMENTED();
258#endif
initial.commit09911bf2008-07-26 23:55:29259}
260
261void RenderThread::OnGetCacheResourceStats() {
[email protected]2c62b562009-01-27 19:04:50262#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29263 CacheManager::ResourceTypeStats stats;
264 CacheManager::GetResourceTypeStats(&stats);
265 Send(new ViewHostMsg_ResourceTypeStats(stats));
[email protected]2c62b562009-01-27 19:04:50266#else
267 // TODO(port)
268 NOTIMPLEMENTED();
269#endif
initial.commit09911bf2008-07-26 23:55:29270}
271
272void RenderThread::InformHostOfCacheStats() {
[email protected]2c62b562009-01-27 19:04:50273#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29274 CacheManager::UsageStats stats;
275 CacheManager::GetUsageStats(&stats);
276 Send(new ViewHostMsg_UpdatedCacheStats(stats));
[email protected]2c62b562009-01-27 19:04:50277#else
278 // TODO(port)
279 NOTIMPLEMENTED();
280#endif
initial.commit09911bf2008-07-26 23:55:29281}
282
283void RenderThread::InformHostOfCacheStatsLater() {
284 // Rate limit informing the host of our cache stats.
285 if (!cache_stats_factory_->empty())
286 return;
287
288 MessageLoop::current()->PostDelayedTask(FROM_HERE,
289 cache_stats_factory_->NewRunnableMethod(
290 &RenderThread::InformHostOfCacheStats),
291 kCacheStatsDelayMS);
292}