blob: d39800f1efceda34f5e32a14a68593c76aa49d52 [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]173de1b2008-08-15 18:36:4615#include "chrome/common/notification_service.h"
[email protected]2c62b562009-01-27 19:04:5016// TODO(port)
17#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2918#include "chrome/plugin/plugin_channel.h"
[email protected]2c62b562009-01-27 19:04:5019#else
20#include <vector>
21#include "base/scoped_handle.h"
22#include "chrome/plugin/plugin_channel_base.h"
23#include "webkit/glue/weburlrequest.h"
24#endif
initial.commit09911bf2008-07-26 23:55:2925#include "chrome/renderer/net/render_dns_master.h"
26#include "chrome/renderer/render_process.h"
27#include "chrome/renderer/render_view.h"
[email protected]0938d3c2009-01-09 20:37:3528#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2929#include "chrome/renderer/visitedlink_slave.h"
30#include "webkit/glue/cache_manager.h"
31
[email protected]2c62b562009-01-27 19:04:5032
[email protected]1d97d2e2008-12-18 23:39:0233RenderThread* g_render_thread;
34
initial.commit09911bf2008-07-26 23:55:2935static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */;
36
37// V8 needs a 1MB stack size.
38static const size_t kStackSize = 1024 * 1024;
39
initial.commit09911bf2008-07-26 23:55:2940//-----------------------------------------------------------------------------
41// Methods below are only called on the owner's thread:
42
43RenderThread::RenderThread(const std::wstring& channel_name)
44 : Thread("Chrome_RenderThread"),
initial.commit09911bf2008-07-26 23:55:2945 owner_loop_(MessageLoop::current()),
[email protected]2c62b562009-01-27 19:04:5046 channel_name_(channel_name),
initial.commit09911bf2008-07-26 23:55:2947 visited_link_slave_(NULL),
[email protected]0938d3c2009-01-09 20:37:3548 user_script_slave_(NULL),
initial.commit09911bf2008-07-26 23:55:2949 render_dns_master_(NULL),
50 in_send_(0) {
51 DCHECK(owner_loop_);
[email protected]ab820df2008-08-26 05:55:1052 base::Thread::Options options;
53 options.stack_size = kStackSize;
54 // When we run plugins in process, we actually run them on the render thread,
55 // which means that we need to make the render thread pump UI events.
56 if (RenderProcess::ShouldLoadPluginsInProcess())
57 options.message_loop_type = MessageLoop::TYPE_UI;
58 StartWithOptions(options);
initial.commit09911bf2008-07-26 23:55:2959}
60
61RenderThread::~RenderThread() {
62 Stop();
63}
64
65void RenderThread::OnChannelError() {
[email protected]295039bd2008-08-15 04:32:5766 owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
initial.commit09911bf2008-07-26 23:55:2967}
68
69bool RenderThread::Send(IPC::Message* msg) {
70 in_send_++;
71 bool rv = channel_->Send(msg);
72 in_send_--;
73 return rv;
74}
75
76void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
77 channel_->AddFilter(filter);
78}
79
80void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) {
81 channel_->RemoveFilter(filter);
82}
83
84void RenderThread::Resolve(const char* name, size_t length) {
[email protected]2c62b562009-01-27 19:04:5085// TODO(port)
86#if defined(OS_WIN)
[email protected]81a34412009-01-05 19:17:2487 return render_dns_master_->Resolve(name, length);
[email protected]2c62b562009-01-27 19:04:5088#else
89 NOTIMPLEMENTED();
90#endif
[email protected]81a34412009-01-05 19:17:2491}
initial.commit09911bf2008-07-26 23:55:2992
93void RenderThread::AddRoute(int32 routing_id,
94 IPC::Channel::Listener* listener) {
95 DCHECK(MessageLoop::current() == message_loop());
96
97 // This corresponds to the AddRoute call done in CreateView.
98 router_.AddRoute(routing_id, listener);
99}
100
101void RenderThread::RemoveRoute(int32 routing_id) {
102 DCHECK(MessageLoop::current() == message_loop());
103
104 router_.RemoveRoute(routing_id);
105}
106
107void RenderThread::Init() {
[email protected]1d97d2e2008-12-18 23:39:02108 DCHECK(!g_render_thread);
109 g_render_thread = this;
initial.commit09911bf2008-07-26 23:55:29110
[email protected]173de1b2008-08-15 18:36:46111 notification_service_.reset(new NotificationService);
112
initial.commit09911bf2008-07-26 23:55:29113 cache_stats_factory_.reset(
114 new ScopedRunnableMethodFactory<RenderThread>(this));
115
116 channel_.reset(new IPC::SyncChannel(channel_name_,
[email protected]d65cab7a2008-08-12 01:25:41117 IPC::Channel::MODE_CLIENT, this, NULL, owner_loop_, true,
118 RenderProcess::GetShutDownEvent()));
initial.commit09911bf2008-07-26 23:55:29119
[email protected]2c62b562009-01-27 19:04:50120#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29121 // The renderer thread should wind-up COM.
122 CoInitialize(0);
[email protected]2c62b562009-01-27 19:04:50123#endif
initial.commit09911bf2008-07-26 23:55:29124
initial.commit09911bf2008-07-26 23:55:29125 visited_link_slave_ = new VisitedLinkSlave();
[email protected]0938d3c2009-01-09 20:37:35126 user_script_slave_ = new UserScriptSlave();
initial.commit09911bf2008-07-26 23:55:29127
[email protected]2c62b562009-01-27 19:04:50128// TODO(port)
129#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29130 render_dns_master_.reset(new RenderDnsMaster());
[email protected]2c62b562009-01-27 19:04:50131#else
132 NOTIMPLEMENTED();
133#endif
initial.commit09911bf2008-07-26 23:55:29134
135#ifdef IPC_MESSAGE_LOG_ENABLED
136 IPC::Logging::current()->SetIPCSender(this);
137#endif
138}
139
140void RenderThread::CleanUp() {
[email protected]1d97d2e2008-12-18 23:39:02141 DCHECK(g_render_thread == this);
142 g_render_thread = NULL;
initial.commit09911bf2008-07-26 23:55:29143
[email protected]8fd8de92008-08-12 23:50:30144 // Need to destruct the SyncChannel to the browser before we go away because
145 // it caches a pointer to this thread.
146 channel_.reset();
147
[email protected]2c62b562009-01-27 19:04:50148// TODO(port)
149#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29150 // Clean up plugin channels before this thread goes away.
151 PluginChannelBase::CleanupChannels();
[email protected]2c62b562009-01-27 19:04:50152#endif
initial.commit09911bf2008-07-26 23:55:29153
154#ifdef IPC_MESSAGE_LOG_ENABLED
155 IPC::Logging::current()->SetIPCSender(NULL);
156#endif
157
[email protected]173de1b2008-08-15 18:36:46158 notification_service_.reset();
159
initial.commit09911bf2008-07-26 23:55:29160 delete visited_link_slave_;
161 visited_link_slave_ = NULL;
162
[email protected]0938d3c2009-01-09 20:37:35163 delete user_script_slave_;
164 user_script_slave_ = NULL;
[email protected]1e0f70402008-10-16 23:57:47165
[email protected]2c62b562009-01-27 19:04:50166#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29167 CoUninitialize();
[email protected]2c62b562009-01-27 19:04:50168#endif
initial.commit09911bf2008-07-26 23:55:29169}
170
[email protected]176aa482008-11-14 03:25:15171void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) {
initial.commit09911bf2008-07-26 23:55:29172 DCHECK(table) << "Bad table handle";
173 visited_link_slave_->Init(table);
174}
175
[email protected]0938d3c2009-01-09 20:37:35176void RenderThread::OnUpdateUserScripts(
[email protected]176aa482008-11-14 03:25:15177 base::SharedMemoryHandle scripts) {
[email protected]1e0f70402008-10-16 23:57:47178 DCHECK(scripts) << "Bad scripts handle";
[email protected]0938d3c2009-01-09 20:37:35179 user_script_slave_->UpdateScripts(scripts);
[email protected]1e0f70402008-10-16 23:57:47180}
181
initial.commit09911bf2008-07-26 23:55:29182void RenderThread::OnMessageReceived(const IPC::Message& msg) {
183 // NOTE: We could subclass router_ to intercept OnControlMessageReceived, but
184 // it seems simpler to just process any control messages that we care about
185 // up-front and then send the rest of the messages onto router_.
186
187 if (msg.routing_id() == MSG_ROUTING_CONTROL) {
188 IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)
189 IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)
190 IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)
[email protected]2c62b562009-01-27 19:04:50191 // TODO(port): removed from render_messages_internal.h;
192 // is there a new non-windows message I should add here?
193#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29194 IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
[email protected]2c62b562009-01-27 19:04:50195#endif
initial.commit09911bf2008-07-26 23:55:29196 IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)
197 IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,
198 OnGetCacheResourceStats)
[email protected]a9f4d902008-09-15 23:43:42199 IPC_MESSAGE_HANDLER(ViewMsg_PluginMessage, OnPluginMessage)
[email protected]0938d3c2009-01-09 20:37:35200 IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_NewScripts,
201 OnUpdateUserScripts)
initial.commit09911bf2008-07-26 23:55:29202 // send the rest to the router
203 IPC_MESSAGE_UNHANDLED(router_.OnMessageReceived(msg))
204 IPC_END_MESSAGE_MAP()
205 } else {
206 router_.OnMessageReceived(msg);
207 }
208}
209
[email protected]690a99c2009-01-06 16:48:45210void RenderThread::OnPluginMessage(const FilePath& plugin_path,
[email protected]a9f4d902008-09-15 23:43:42211 const std::vector<uint8>& data) {
[email protected]3daa8452009-01-16 18:33:47212 if (!ChromePluginLib::IsInitialized()) {
213 return;
214 }
[email protected]a9f4d902008-09-15 23:43:42215 CHECK(ChromePluginLib::IsPluginThread());
[email protected]690a99c2009-01-06 16:48:45216 ChromePluginLib *chrome_plugin = ChromePluginLib::Find(plugin_path);
[email protected]a9f4d902008-09-15 23:43:42217 if (chrome_plugin) {
218 void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0]));
219 uint32 data_len = static_cast<uint32>(data.size());
220 chrome_plugin->functions().on_message(data_ptr, data_len);
221 }
222}
223
initial.commit09911bf2008-07-26 23:55:29224void RenderThread::OnSetNextPageID(int32 next_page_id) {
225 // This should only be called at process initialization time, so we shouldn't
226 // have to worry about thread-safety.
[email protected]2c62b562009-01-27 19:04:50227 // TODO(port)
228#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29229 RenderView::SetNextPageID(next_page_id);
[email protected]2c62b562009-01-27 19:04:50230#endif
initial.commit09911bf2008-07-26 23:55:29231}
232
[email protected]2c62b562009-01-27 19:04:50233// TODO(port)
234#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29235void RenderThread::OnCreateNewView(HWND parent_hwnd,
236 HANDLE modal_dialog_event,
237 const WebPreferences& webkit_prefs,
238 int32 view_id) {
239 // TODO(darin): once we have a RenderThread per RenderView, this will need to
240 // change to assert that we are not creating more than one view.
[email protected]1c4947f2009-01-15 22:25:11241 base::WaitableEvent* waitable_event =
242 new base::WaitableEvent(modal_dialog_event);
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}
[email protected]2c62b562009-01-27 19:04:50247#endif
initial.commit09911bf2008-07-26 23:55:29248
249void RenderThread::OnSetCacheCapacities(size_t min_dead_capacity,
250 size_t max_dead_capacity,
251 size_t capacity) {
[email protected]2c62b562009-01-27 19:04:50252#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29253 CacheManager::SetCapacities(min_dead_capacity, max_dead_capacity, capacity);
[email protected]2c62b562009-01-27 19:04:50254#else
255 // TODO(port)
256 NOTIMPLEMENTED();
257#endif
initial.commit09911bf2008-07-26 23:55:29258}
259
260void RenderThread::OnGetCacheResourceStats() {
[email protected]2c62b562009-01-27 19:04:50261#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29262 CacheManager::ResourceTypeStats stats;
263 CacheManager::GetResourceTypeStats(&stats);
264 Send(new ViewHostMsg_ResourceTypeStats(stats));
[email protected]2c62b562009-01-27 19:04:50265#else
266 // TODO(port)
267 NOTIMPLEMENTED();
268#endif
initial.commit09911bf2008-07-26 23:55:29269}
270
271void RenderThread::InformHostOfCacheStats() {
[email protected]2c62b562009-01-27 19:04:50272#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29273 CacheManager::UsageStats stats;
274 CacheManager::GetUsageStats(&stats);
275 Send(new ViewHostMsg_UpdatedCacheStats(stats));
[email protected]2c62b562009-01-27 19:04:50276#else
277 // TODO(port)
278 NOTIMPLEMENTED();
279#endif
initial.commit09911bf2008-07-26 23:55:29280}
281
282void RenderThread::InformHostOfCacheStatsLater() {
283 // Rate limit informing the host of our cache stats.
284 if (!cache_stats_factory_->empty())
285 return;
286
287 MessageLoop::current()->PostDelayedTask(FROM_HERE,
288 cache_stats_factory_->NewRunnableMethod(
289 &RenderThread::InformHostOfCacheStats),
290 kCacheStatsDelayMS);
291}