blob: e161438ec96d6648c0455b61d0a1006271a84868 [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
initial.commit09911bf2008-07-26 23:55:295#include "chrome/renderer/render_thread.h"
6
[email protected]da00a2882009-03-09 17:51:197#include <algorithm>
8#include <vector>
9
[email protected]06533c0b2009-03-05 21:39:1110#include "base/command_line.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/shared_memory.h"
[email protected]da00a2882009-03-09 17:51:1912#include "base/stats_table.h"
[email protected]06533c0b2009-03-05 21:39:1113#include "chrome/common/chrome_switches.h"
[email protected]e09ba552009-02-05 03:26:2914#include "chrome/common/render_messages.h"
[email protected]173de1b2008-08-15 18:36:4615#include "chrome/common/notification_service.h"
[email protected]90a3fbb12009-02-28 01:13:4716#include "chrome/common/url_constants.h"
[email protected]8930d472009-02-21 08:05:2817#include "chrome/plugin/npobject_util.h"
[email protected]2c62b562009-01-27 19:04:5018// TODO(port)
19#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2920#include "chrome/plugin/plugin_channel.h"
[email protected]2c62b562009-01-27 19:04:5021#else
[email protected]2c62b562009-01-27 19:04:5022#include "base/scoped_handle.h"
23#include "chrome/plugin/plugin_channel_base.h"
24#include "webkit/glue/weburlrequest.h"
25#endif
[email protected]309d7a282009-03-24 09:18:2726#include "chrome/renderer/extensions/extension_process_bindings.h"
[email protected]0aa477bd2009-03-23 22:21:4327#include "chrome/renderer/extensions/renderer_extension_bindings.h"
initial.commit09911bf2008-07-26 23:55:2928#include "chrome/renderer/net/render_dns_master.h"
29#include "chrome/renderer/render_process.h"
30#include "chrome/renderer/render_view.h"
[email protected]8d86fce2009-02-26 23:37:5531#include "chrome/renderer/renderer_webkitclient_impl.h"
[email protected]0938d3c2009-01-09 20:37:3532#include "chrome/renderer/user_script_slave.h"
initial.commit09911bf2008-07-26 23:55:2933#include "chrome/renderer/visitedlink_slave.h"
[email protected]2c434b32009-03-19 06:27:4734#include "third_party/WebKit/WebKit/chromium/public/WebCache.h"
35#include "third_party/WebKit/WebKit/chromium/public/WebKit.h"
36#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
[email protected]06533c0b2009-03-05 21:39:1137#include "webkit/extensions/v8/gears_extension.h"
38#include "webkit/extensions/v8/interval_extension.h"
39#include "webkit/extensions/v8/playback_extension.h"
[email protected]2c62b562009-01-27 19:04:5040
[email protected]da00a2882009-03-09 17:51:1941#if defined(OS_WIN)
42#include <windows.h>
43#include <objbase.h>
44#endif
45
[email protected]2c434b32009-03-19 06:27:4746using WebKit::WebCache;
47using WebKit::WebString;
initial.commit09911bf2008-07-26 23:55:2948
[email protected]2c434b32009-03-19 06:27:4749static const unsigned int kCacheStatsDelayMS = 2000 /* milliseconds */;
initial.commit09911bf2008-07-26 23:55:2950
initial.commit09911bf2008-07-26 23:55:2951//-----------------------------------------------------------------------------
52// Methods below are only called on the owner's thread:
53
[email protected]8930d472009-02-21 08:05:2854// 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.
56RenderThread::RenderThread()
57 : ChildThread(
58 base::Thread::Options(RenderProcess::InProcessPlugins() ?
[email protected]eb47a132009-03-04 00:39:5659 MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)) {
[email protected]8930d472009-02-21 08:05:2860}
61
62RenderThread::RenderThread(const std::wstring& channel_name)
63 : ChildThread(
64 base::Thread::Options(RenderProcess::InProcessPlugins() ?
[email protected]eb47a132009-03-04 00:39:5665 MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT, kV8StackSize)) {
[email protected]8930d472009-02-21 08:05:2866 SetChannelName(channel_name);
initial.commit09911bf2008-07-26 23:55:2967}
68
69RenderThread::~RenderThread() {
initial.commit09911bf2008-07-26 23:55:2970}
71
[email protected]8930d472009-02-21 08:05:2872RenderThread* RenderThread::current() {
73 DCHECK(!IsPluginProcess());
74 return static_cast<RenderThread*>(ChildThread::current());
initial.commit09911bf2008-07-26 23:55:2975}
76
77void RenderThread::AddFilter(IPC::ChannelProxy::MessageFilter* filter) {
[email protected]8930d472009-02-21 08:05:2878 channel()->AddFilter(filter);
initial.commit09911bf2008-07-26 23:55:2979}
80
81void RenderThread::RemoveFilter(IPC::ChannelProxy::MessageFilter* filter) {
[email protected]8930d472009-02-21 08:05:2882 channel()->RemoveFilter(filter);
initial.commit09911bf2008-07-26 23:55:2983}
84
85void RenderThread::Resolve(const char* name, size_t length) {
[email protected]8d86fce2009-02-26 23:37:5586 return dns_master_->Resolve(name, length);
[email protected]81a34412009-01-05 19:17:2487}
initial.commit09911bf2008-07-26 23:55:2988
[email protected]55e57d42009-02-25 06:10:1789void RenderThread::SendHistograms() {
[email protected]8d86fce2009-02-26 23:37:5590 return histogram_snapshots_->SendHistograms();
[email protected]55e57d42009-02-25 06:10:1791}
92
initial.commit09911bf2008-07-26 23:55:2993void RenderThread::Init() {
[email protected]8d86fce2009-02-26 23:37:5594 // TODO(darin): Why do we need COM here? This is probably bogus.
[email protected]2c62b562009-01-27 19:04:5095#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2996 // The renderer thread should wind-up COM.
97 CoInitialize(0);
[email protected]2c62b562009-01-27 19:04:5098#endif
initial.commit09911bf2008-07-26 23:55:2999
[email protected]8d86fce2009-02-26 23:37:55100 ChildThread::Init();
101 notification_service_.reset(new NotificationService);
102 cache_stats_factory_.reset(
103 new ScopedRunnableMethodFactory<RenderThread>(this));
104
[email protected]8d86fce2009-02-26 23:37:55105 visited_link_slave_.reset(new VisitedLinkSlave());
106 user_script_slave_.reset(new UserScriptSlave());
107 dns_master_.reset(new RenderDnsMaster());
108 histogram_snapshots_.reset(new RendererHistogramSnapshots());
initial.commit09911bf2008-07-26 23:55:29109}
110
111void RenderThread::CleanUp() {
[email protected]8d86fce2009-02-26 23:37:55112 // Shutdown in reverse of the initialization order.
113
114 histogram_snapshots_.reset();
115 dns_master_.reset();
116 user_script_slave_.reset();
117 visited_link_slave_.reset();
118
[email protected]90a3fbb12009-02-28 01:13:47119 if (webkit_client_.get()) {
120 WebKit::shutdown();
121 webkit_client_.reset();
122 }
[email protected]8d86fce2009-02-26 23:37:55123
124 notification_service_.reset();
125
[email protected]8930d472009-02-21 08:05:28126 ChildThread::CleanUp();
[email protected]8fd8de92008-08-12 23:50:30127
[email protected]8d86fce2009-02-26 23:37:55128 // TODO(port)
[email protected]2c62b562009-01-27 19:04:50129#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29130 // Clean up plugin channels before this thread goes away.
131 PluginChannelBase::CleanupChannels();
[email protected]2c62b562009-01-27 19:04:50132#endif
initial.commit09911bf2008-07-26 23:55:29133
[email protected]2c62b562009-01-27 19:04:50134#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29135 CoUninitialize();
[email protected]2c62b562009-01-27 19:04:50136#endif
initial.commit09911bf2008-07-26 23:55:29137}
138
[email protected]176aa482008-11-14 03:25:15139void RenderThread::OnUpdateVisitedLinks(base::SharedMemoryHandle table) {
[email protected]5fe733de2009-02-11 18:59:20140 DCHECK(base::SharedMemory::IsHandleValid(table)) << "Bad table handle";
initial.commit09911bf2008-07-26 23:55:29141 visited_link_slave_->Init(table);
142}
143
[email protected]0938d3c2009-01-09 20:37:35144void RenderThread::OnUpdateUserScripts(
[email protected]176aa482008-11-14 03:25:15145 base::SharedMemoryHandle scripts) {
[email protected]5fe733de2009-02-11 18:59:20146 DCHECK(base::SharedMemory::IsHandleValid(scripts)) << "Bad scripts handle";
[email protected]0938d3c2009-01-09 20:37:35147 user_script_slave_->UpdateScripts(scripts);
[email protected]1e0f70402008-10-16 23:57:47148}
149
[email protected]703e807a2009-03-28 19:56:51150void RenderThread::OnSetExtensionFunctionNames(
151 const std::vector<std::string>& names) {
152 extensions_v8::ExtensionProcessBindings::SetFunctionNames(names);
153}
154
[email protected]8930d472009-02-21 08:05:28155void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
156 IPC_BEGIN_MESSAGE_MAP(RenderThread, msg)
157 IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)
158 IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID)
159 // TODO(port): removed from render_messages_internal.h;
160 // is there a new non-windows message I should add here?
161 IPC_MESSAGE_HANDLER(ViewMsg_New, OnCreateNewView)
162 IPC_MESSAGE_HANDLER(ViewMsg_SetCacheCapacities, OnSetCacheCapacities)
[email protected]55e57d42009-02-25 06:10:17163 IPC_MESSAGE_HANDLER(ViewMsg_GetRendererHistograms,
164 OnGetRendererHistograms)
[email protected]8930d472009-02-21 08:05:28165 IPC_MESSAGE_HANDLER(ViewMsg_GetCacheResourceStats,
166 OnGetCacheResourceStats)
[email protected]8930d472009-02-21 08:05:28167 IPC_MESSAGE_HANDLER(ViewMsg_UserScripts_NewScripts,
168 OnUpdateUserScripts)
[email protected]75e5a872009-04-02 23:56:11169 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionHandleConnect,
170 OnExtensionHandleConnect)
171 IPC_MESSAGE_HANDLER(ViewMsg_ExtensionHandleMessage,
172 OnExtensionHandleMessage)
[email protected]703e807a2009-03-28 19:56:51173 IPC_MESSAGE_HANDLER(ViewMsg_Extension_SetFunctionNames,
174 OnSetExtensionFunctionNames)
[email protected]8930d472009-02-21 08:05:28175 IPC_END_MESSAGE_MAP()
initial.commit09911bf2008-07-26 23:55:29176}
177
178void RenderThread::OnSetNextPageID(int32 next_page_id) {
179 // This should only be called at process initialization time, so we shouldn't
180 // have to worry about thread-safety.
181 RenderView::SetNextPageID(next_page_id);
182}
183
[email protected]18bcc3c2009-01-27 21:39:15184void RenderThread::OnCreateNewView(gfx::NativeViewId parent_hwnd,
185 ModalDialogEvent modal_dialog_event,
initial.commit09911bf2008-07-26 23:55:29186 const WebPreferences& webkit_prefs,
187 int32 view_id) {
[email protected]90a3fbb12009-02-28 01:13:47188 EnsureWebKitInitialized();
189
[email protected]be645db2009-02-06 20:36:33190 // When bringing in render_view, also bring in webkit's glue and jsbindings.
[email protected]18bcc3c2009-01-27 21:39:15191 base::WaitableEvent* waitable_event = new base::WaitableEvent(
192#if defined(OS_WIN)
193 modal_dialog_event.event);
194#else
195 true, false);
196#endif
197
initial.commit09911bf2008-07-26 23:55:29198 // TODO(darin): once we have a RenderThread per RenderView, this will need to
199 // change to assert that we are not creating more than one view.
initial.commit09911bf2008-07-26 23:55:29200 RenderView::Create(
[email protected]1c4947f2009-01-15 22:25:11201 this, parent_hwnd, waitable_event, MSG_ROUTING_NONE, webkit_prefs,
[email protected]0aa55312008-10-17 21:53:08202 new SharedRenderViewCounter(0), view_id);
[email protected]7f874dec2009-02-06 01:48:27203}
[email protected]4274e582009-01-27 22:09:56204
initial.commit09911bf2008-07-26 23:55:29205void RenderThread::OnSetCacheCapacities(size_t min_dead_capacity,
206 size_t max_dead_capacity,
207 size_t capacity) {
[email protected]90a3fbb12009-02-28 01:13:47208 EnsureWebKitInitialized();
[email protected]2c434b32009-03-19 06:27:47209 WebCache::setCapacities(
210 min_dead_capacity, max_dead_capacity, capacity);
initial.commit09911bf2008-07-26 23:55:29211}
212
213void RenderThread::OnGetCacheResourceStats() {
[email protected]90a3fbb12009-02-28 01:13:47214 EnsureWebKitInitialized();
[email protected]2c434b32009-03-19 06:27:47215 WebCache::ResourceTypeStats stats;
216 WebCache::getResourceTypeStats(&stats);
initial.commit09911bf2008-07-26 23:55:29217 Send(new ViewHostMsg_ResourceTypeStats(stats));
218}
219
[email protected]55e57d42009-02-25 06:10:17220void RenderThread::OnGetRendererHistograms() {
221 SendHistograms();
222}
223
initial.commit09911bf2008-07-26 23:55:29224void RenderThread::InformHostOfCacheStats() {
[email protected]90a3fbb12009-02-28 01:13:47225 EnsureWebKitInitialized();
[email protected]2c434b32009-03-19 06:27:47226 WebCache::UsageStats stats;
227 WebCache::getUsageStats(&stats);
initial.commit09911bf2008-07-26 23:55:29228 Send(new ViewHostMsg_UpdatedCacheStats(stats));
229}
230
231void RenderThread::InformHostOfCacheStatsLater() {
232 // Rate limit informing the host of our cache stats.
233 if (!cache_stats_factory_->empty())
234 return;
235
236 MessageLoop::current()->PostDelayedTask(FROM_HERE,
237 cache_stats_factory_->NewRunnableMethod(
238 &RenderThread::InformHostOfCacheStats),
239 kCacheStatsDelayMS);
240}
[email protected]90a3fbb12009-02-28 01:13:47241
[email protected]3df0c202009-03-31 23:51:26242static void* CreateHistogram(
243 const char *name, int min, int max, size_t buckets) {
244 return new Histogram(name, min, max, buckets);
245}
246
247static void AddHistogramSample(void* hist, int sample) {
248 Histogram* histogram = static_cast<Histogram *>(hist);
249 histogram->Add(sample);
250}
251
[email protected]90a3fbb12009-02-28 01:13:47252void RenderThread::EnsureWebKitInitialized() {
253 if (webkit_client_.get())
254 return;
[email protected]da00a2882009-03-09 17:51:19255
256 v8::V8::SetCounterFunction(StatsTable::FindLocation);
[email protected]3df0c202009-03-31 23:51:26257 v8::V8::SetCreateHistogramFunction(CreateHistogram);
258 v8::V8::SetAddHistogramSampleFunction(AddHistogramSample);
[email protected]da00a2882009-03-09 17:51:19259
[email protected]90a3fbb12009-02-28 01:13:47260 webkit_client_.reset(new RendererWebKitClientImpl);
261 WebKit::initialize(webkit_client_.get());
[email protected]8881eca82009-03-12 18:20:44262
263 // chrome-ui pages should not be accessible by normal content, and should
264 // also be unable to script anything but themselves (to help limit the damage
265 // that a corrupt chrome-ui page could cause).
[email protected]2c434b32009-03-19 06:27:47266 WebString chrome_ui_scheme(ASCIIToUTF16(chrome::kChromeUIScheme));
[email protected]8881eca82009-03-12 18:20:44267 WebKit::registerURLSchemeAsLocal(chrome_ui_scheme);
268 WebKit::registerURLSchemeAsNoAccess(chrome_ui_scheme);
[email protected]da00a2882009-03-09 17:51:19269
[email protected]06533c0b2009-03-05 21:39:11270 WebKit::registerExtension(extensions_v8::GearsExtension::Get());
271 WebKit::registerExtension(extensions_v8::IntervalExtension::Get());
[email protected]75e5a872009-04-02 23:56:11272 WebKit::registerExtension(
273 extensions_v8::RendererExtensionBindings::Get(this));
[email protected]06533c0b2009-03-05 21:39:11274
[email protected]309d7a282009-03-24 09:18:27275 WebKit::registerExtension(extensions_v8::ExtensionProcessBindings::Get(),
276 WebKit::WebString::fromUTF8(chrome::kExtensionScheme));
277
[email protected]06533c0b2009-03-05 21:39:11278 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
279 if (command_line.HasSwitch(switches::kPlaybackMode) ||
280 command_line.HasSwitch(switches::kRecordMode)) {
281 WebKit::registerExtension(extensions_v8::PlaybackExtension::Get());
282 }
[email protected]2cb82332009-03-18 17:24:55283
284 if (command_line.HasSwitch(switches::kEnableWebWorkers)) {
[email protected]0b9a1cc92009-03-19 00:55:53285 WebKit::enableWebWorkers();
[email protected]2cb82332009-03-18 17:24:55286 }
[email protected]90a3fbb12009-02-28 01:13:47287}
[email protected]75e5a872009-04-02 23:56:11288
289void RenderThread::OnExtensionHandleConnect(int port_id) {
290 extensions_v8::RendererExtensionBindings::HandleConnect(port_id);
291}
292
293void RenderThread::OnExtensionHandleMessage(const std::string& message,
294 int port_id) {
295 extensions_v8::RendererExtensionBindings::HandleMessage(message, port_id);
296}